feat(web)!: SPA (#5069)

* feat(web): SPA

* chore: remove unnecessary prune

* feat(web): merge with immich-server

* Correct method name

* fix: bugs, docs, workflows, etc.

* chore: keep dockerignore for dev

* chore: remove license

* fix: expose 2283

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Jason Rasmussen
2023-11-17 23:13:36 -05:00
committed by GitHub
parent 5118d261ab
commit adae5dd758
115 changed files with 730 additions and 1446 deletions
+15
View File
@@ -13,6 +13,7 @@ import {
SwaggerDocumentOptions,
SwaggerModule,
} from '@nestjs/swagger';
import { NextFunction, Request, Response } from 'express';
import { writeFileSync } from 'fs';
import path from 'path';
@@ -56,6 +57,12 @@ const patchOpenAPI = (document: OpenAPIObject) => {
document.components.schemas = sortKeys(document.components.schemas);
}
for (const [key, value] of Object.entries(document.paths)) {
const newKey = key.replace('/api/', '/');
delete document.paths[key];
document.paths[newKey] = value;
}
for (const path of Object.values(document.paths)) {
const operations = {
get: path.get,
@@ -94,6 +101,14 @@ const patchOpenAPI = (document: OpenAPIObject) => {
return document;
};
export const indexFallback = (excludePaths: string[]) => (req: Request, res: Response, next: NextFunction) => {
if (req.url.startsWith('/api') || req.method.toLowerCase() !== 'get' || excludePaths.indexOf(req.url) !== -1) {
next();
} else {
res.sendFile('/www/index.html', { root: process.cwd() });
}
};
export const useSwagger = (app: INestApplication, isDev: boolean) => {
const config = new DocumentBuilder()
.setTitle('Immich')
@@ -1,15 +1,34 @@
import { SystemConfigService } from '@app/domain';
import { Controller, HttpCode, HttpStatus, Post } from '@nestjs/common';
import { Controller, Get, Header, HttpCode, HttpStatus, Post } from '@nestjs/common';
import { ApiExcludeEndpoint } from '@nestjs/swagger';
import { PublicRoute } from '../app.guard';
@Controller()
export class AppController {
constructor(private configService: SystemConfigService) {}
constructor(private service: SystemConfigService) {}
@ApiExcludeEndpoint()
@Get('.well-known/immich')
getImmichWellKnown() {
return {
api: {
endpoint: '/api',
},
};
}
@ApiExcludeEndpoint()
@PublicRoute()
@Get('custom.css')
@Header('Content-Type', 'text/css')
getCustomCss() {
return this.service.getCustomCss();
}
@ApiExcludeEndpoint()
@Post('refresh-config')
@HttpCode(HttpStatus.OK)
public reloadConfig() {
return this.configService.refreshConfig();
return this.service.refreshConfig();
}
}
+6 -1
View File
@@ -6,7 +6,7 @@ import { NestExpressApplication } from '@nestjs/platform-express';
import { json } from 'body-parser';
import cookieParser from 'cookie-parser';
import { AppModule } from './app.module';
import { useSwagger } from './app.utils';
import { indexFallback, useSwagger } from './app.utils';
const logger = new Logger('ImmichServer');
const port = Number(process.env.SERVER_PORT) || 3001;
@@ -24,6 +24,11 @@ export async function bootstrap() {
app.useWebSocketAdapter(new RedisIoAdapter(app));
useSwagger(app, isDev);
const excludePaths = ['/.well-known/immich', '/custom.css'];
app.setGlobalPrefix('api', { exclude: excludePaths });
app.useStaticAssets('www');
app.use(indexFallback(excludePaths));
const server = await app.listen(port);
server.requestTimeout = 30 * 60 * 1000;