Browse Source

Add middleware

pull/2239/head
Thomas 2 years ago
parent
commit
63ecc1cb81
  1. 14
      apps/api/src/app/app.module.ts
  2. 2
      apps/api/src/app/frontend.middleware.ts
  3. 82
      apps/api/src/app/static.middleware.ts
  4. 3
      apps/api/src/main.ts
  5. 3
      apps/client/project.json
  6. 0
      apps/client/src/assets/index.html
  7. 32
      apps/client/src/index.html
  8. 63
      apps/client/src/index.template.html

14
apps/api/src/app/app.module.ts

@ -12,7 +12,9 @@ import {
SUPPORTED_LANGUAGE_CODES SUPPORTED_LANGUAGE_CODES
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common'; import {
/*MiddlewareConsumer,*/ Module /*RequestMethod*/
} from '@nestjs/common';
import { ConfigModule } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config';
import { ScheduleModule } from '@nestjs/schedule'; import { ScheduleModule } from '@nestjs/schedule';
import { ServeStaticModule } from '@nestjs/serve-static'; import { ServeStaticModule } from '@nestjs/serve-static';
@ -28,7 +30,7 @@ import { BenchmarkModule } from './benchmark/benchmark.module';
import { CacheModule } from './cache/cache.module'; import { CacheModule } from './cache/cache.module';
import { ExchangeRateModule } from './exchange-rate/exchange-rate.module'; import { ExchangeRateModule } from './exchange-rate/exchange-rate.module';
import { ExportModule } from './export/export.module'; import { ExportModule } from './export/export.module';
import { FrontendMiddleware } from './frontend.middleware'; // import { FrontendMiddleware } from './frontend.middleware';
import { HealthModule } from './health/health.module'; import { HealthModule } from './health/health.module';
import { ImportModule } from './import/import.module'; import { ImportModule } from './import/import.module';
import { InfoModule } from './info/info.module'; import { InfoModule } from './info/info.module';
@ -75,12 +77,12 @@ import { UserModule } from './user/user.module';
PrismaModule, PrismaModule,
RedisCacheModule, RedisCacheModule,
ScheduleModule.forRoot(), ScheduleModule.forRoot(),
...SUPPORTED_LANGUAGE_CODES.map((languageCode) => { /*...SUPPORTED_LANGUAGE_CODES.map((languageCode) => {
return ServeStaticModule.forRoot({ return ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'client', languageCode), rootPath: join(__dirname, '..', 'client', languageCode),
serveRoot: `/${languageCode}` serveRoot: `/${languageCode}`
}); });
}), }),*/
ServeStaticModule.forRoot({ ServeStaticModule.forRoot({
exclude: ['/api*', '/sitemap.xml'], exclude: ['/api*', '/sitemap.xml'],
rootPath: join(__dirname, '..', 'client'), rootPath: join(__dirname, '..', 'client'),
@ -115,9 +117,9 @@ import { UserModule } from './user/user.module';
providers: [CronService] providers: [CronService]
}) })
export class AppModule { export class AppModule {
configure(consumer: MiddlewareConsumer) { /*configure(consumer: MiddlewareConsumer) {
consumer consumer
.apply(FrontendMiddleware) .apply(FrontendMiddleware)
.forRoutes({ path: '*', method: RequestMethod.ALL }); .forRoutes({ path: '*', method: RequestMethod.ALL });
} }*/
} }

2
apps/api/src/app/frontend.middleware.ts

@ -1,3 +1,5 @@
// TODO: Remove
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';

82
apps/api/src/app/static.middleware.ts

@ -0,0 +1,82 @@
import * as fs from 'fs';
import { NextFunction, Request, Response } from 'express';
import { join } from 'path';
import { DATE_FORMAT, interpolate } from '@ghostfolio/common/helper';
import { environment } from '@ghostfolio/api/environments/environment';
import { SUPPORTED_LANGUAGE_CODES } from '@ghostfolio/common/config';
import { format } from 'date-fns';
const title = 'Ghostfolio – Open Source Wealth Management Software';
// TODO
const descriptions = {
en: 'Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies across multiple platforms.'
};
// TODO
const locales = {
'/en/blog/2022/08/500-stars-on-github': {
featureGraphicPath: 'assets/images/blog/500-stars-on-github.jpg',
title: `500 Stars - ${title}`
}
};
const getPathOfIndexHtmlFile = (aLocale: string) => {
return join(__dirname, '..', 'client', aLocale, 'index.html');
};
const isFileRequest = (filename: string) => {
if (filename === '/assets/LICENSE') {
return true;
} else if (
filename.includes('auth/ey') ||
filename.includes(
'personal-finance-tools/open-source-alternative-to-markets.sh'
)
) {
return false;
}
return filename.split('.').pop() !== filename;
};
export const StaticMiddleware = async (
request: Request,
response: Response,
next: NextFunction
) => {
const path = request.originalUrl.replace(/\/$/, '');
const languageCode = path.substr(1, 2);
const currentDate = format(new Date(), DATE_FORMAT);
const rootUrl = 'https://ghostfol.io';
if (
path.startsWith('/api/') ||
isFileRequest(path) /*||
!environment.production*/
) {
// Skip
next();
} else if (SUPPORTED_LANGUAGE_CODES.includes(languageCode)) {
// TODO: Only load once
const indexHtml = interpolate(
fs.readFileSync(getPathOfIndexHtmlFile(languageCode), 'utf8'),
{
currentDate,
languageCode,
path,
rootUrl,
description: descriptions[languageCode],
featureGraphicPath:
locales[path]?.featureGraphicPath ?? 'assets/cover.png',
title: locales[path]?.title ?? title
}
);
return response.send(indexHtml);
} else {
// TODO
}
};

3
apps/api/src/main.ts

@ -6,6 +6,7 @@ import * as bodyParser from 'body-parser';
import helmet from 'helmet'; import helmet from 'helmet';
import { AppModule } from './app/app.module'; import { AppModule } from './app/app.module';
import { StaticMiddleware } from './app/static.middleware';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
async function bootstrap() { async function bootstrap() {
@ -52,6 +53,8 @@ async function bootstrap() {
); );
} }
app.use(StaticMiddleware);
const BASE_CURRENCY = configService.get<string>('BASE_CURRENCY'); const BASE_CURRENCY = configService.get<string>('BASE_CURRENCY');
const HOST = configService.get<string>('HOST') || '0.0.0.0'; const HOST = configService.get<string>('HOST') || '0.0.0.0';
const PORT = configService.get<number>('PORT') || 3333; const PORT = configService.get<number>('PORT') || 3333;

3
apps/client/project.json

@ -110,9 +110,6 @@
{ {
"command": "cp apps/client/src/assets/favicon.ico dist/apps/client" "command": "cp apps/client/src/assets/favicon.ico dist/apps/client"
}, },
{
"command": "cp apps/client/src/assets/index.html dist/apps/client"
},
{ {
"command": "cp apps/client/src/assets/robots.txt dist/apps/client" "command": "cp apps/client/src/assets/robots.txt dist/apps/client"
}, },

0
apps/client/src/assets/index.html

32
apps/client/src/index.html

@ -1,14 +1,11 @@
<!DOCTYPE html> <!DOCTYPE html>
<html class="h-100 position-relative" lang="en"> <html class="h-100 position-relative" lang="${languageCode}">
<head> <head>
<title>Ghostfolio – Open Source Wealth Management Software</title> <title>${title}</title>
<base href="/" /> <base href="/" />
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta content="yes" name="apple-mobile-web-app-capable" /> <meta content="yes" name="apple-mobile-web-app-capable" />
<meta <meta content="${description}" name="description" />
content="Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies across multiple platforms."
name="description"
/>
<meta <meta
content="app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3" content="app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3"
name="keywords" name="keywords"
@ -19,29 +16,20 @@
content="Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies" content="Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies"
name="twitter:description" name="twitter:description"
/> />
<meta content="https://ghostfol.io/assets/cover.png" name="twitter:image" /> <meta content="${rootUrl}/${featureGraphicPath}" name="twitter:image" />
<meta <meta content="${title}" name="twitter:title" />
content="Ghostfolio – Open Source Wealth Management Software"
name="twitter:title"
/>
<meta <meta
content="initial-scale=1, viewport-fit=cover, width=device-width" content="initial-scale=1, viewport-fit=cover, width=device-width"
name="viewport" name="viewport"
/> />
<meta content="#FFFFFF" name="theme-color" /> <meta content="#FFFFFF" name="theme-color" />
<meta content="" property="og:description" /> <meta content="" property="og:description" />
<meta <meta content="${title}" property="og:title" />
content="Ghostfolio – Open Source Wealth Management Software"
property="og:title"
/>
<meta content="website" property="og:type" /> <meta content="website" property="og:type" />
<meta content="https://ghostfol.io" property="og:url" /> <meta content="${rootUrl}${path}" property="og:url" />
<meta content="https://ghostfol.io/assets/cover.png" property="og:image" /> <meta content="${rootUrl}/${featureGraphicPath}" property="og:image" />
<meta content="2023-08-10T00:00:00+00:00" property="og:updated_time" /> <meta content="${currentDate}T00:00:00+00:00" property="og:updated_time" />
<meta <meta content="${title}" property="og:site_name" />
content="Ghostfolio – Open Source Wealth Management Software"
property="og:site_name"
/>
<link <link
href="../assets/apple-touch-icon.png" href="../assets/apple-touch-icon.png"

63
apps/client/src/index.template.html

@ -1,63 +0,0 @@
<!DOCTYPE html>
<html class="h-100 position-relative" lang="${languageCode}">
<head>
<title>${title}</title>
<base href="/" />
<meta charset="utf-8" />
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta content="${description}" name="description" />
<meta
content="app, asset, cryptocurrency, dashboard, etf, finance, management, performance, portfolio, software, stock, trading, wealth, web3"
name="keywords"
/>
<meta content="yes" name="mobile-web-app-capable" />
<meta content="summary_large_image" name="twitter:card" />
<meta
content="Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies"
name="twitter:description"
/>
<meta content="${rootUrl}/${featureGraphicPath}" name="twitter:image" />
<meta content="${title}" name="twitter:title" />
<meta
content="initial-scale=1, viewport-fit=cover, width=device-width"
name="viewport"
/>
<meta content="#FFFFFF" name="theme-color" />
<meta content="" property="og:description" />
<meta content="${title}" property="og:title" />
<meta content="website" property="og:type" />
<meta content="${rootUrl}${path}" property="og:url" />
<meta content="${rootUrl}/${featureGraphicPath}" property="og:image" />
<meta content="${currentDate}T00:00:00+00:00" property="og:updated_time" />
<meta content="${title}" property="og:site_name" />
<link
href="../assets/apple-touch-icon.png"
rel="apple-touch-icon"
sizes="180x180"
/>
<link
href="../assets/favicon-32x32.png"
rel="icon"
sizes="32x32"
type="image/png"
/>
<link
href="../assets/favicon-16x16.png"
rel="icon"
sizes="16x16"
type="image/png"
/>
<link href="../assets/site.webmanifest" rel="manifest" />
</head>
<body>
<gf-root></gf-root>
<script src="../ionicons/ionicons.esm.js" type="module"></script>
<script nomodule="" src="ionicons.js"></script>
<noscript
>Please enable JavaScript to continue using this application.</noscript
>
</body>
</html>
Loading…
Cancel
Save