1
0
mirror of https://github.com/immich-app/immich.git synced 2025-07-07 06:16:05 +02:00
Files
immich/server/src/app.module.ts

140 lines
5.0 KiB
TypeScript
Raw Normal View History

import { BullModule } from '@nestjs/bullmq';
import { Inject, Module, OnModuleDestroy, OnModuleInit, ValidationPipe } from '@nestjs/common';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE, ModuleRef } from '@nestjs/core';
import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule';
import { TypeOrmModule } from '@nestjs/typeorm';
import { PostgresJSDialect } from 'kysely-postgres-js';
import { ClsModule } from 'nestjs-cls';
2025-01-09 11:15:41 -05:00
import { KyselyModule } from 'nestjs-kysely';
import { OpenTelemetryModule } from 'nestjs-otel';
import postgres from 'postgres';
import { commands } from 'src/commands';
import { IWorker } from 'src/constants';
import { controllers } from 'src/controllers';
import { entities } from 'src/entities';
2024-10-04 16:57:34 -04:00
import { ImmichWorker } from 'src/enum';
import { IJobRepository } from 'src/interfaces/job.interface';
2024-03-21 09:08:29 -05:00
import { AuthGuard } from 'src/middleware/auth.guard';
import { ErrorInterceptor } from 'src/middleware/error.interceptor';
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter';
import { LoggingInterceptor } from 'src/middleware/logging.interceptor';
2025-01-15 23:31:26 -05:00
import { providers, repositories } from 'src/repositories';
import { ConfigRepository } from 'src/repositories/config.repository';
2025-02-11 15:12:31 -05:00
import { EventRepository } from 'src/repositories/event.repository';
2025-01-23 08:31:30 -05:00
import { LoggingRepository } from 'src/repositories/logging.repository';
import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository';
import { services } from 'src/services';
2025-02-11 15:12:31 -05:00
import { AuthService } from 'src/services/auth.service';
import { CliService } from 'src/services/cli.service';
import { DatabaseService } from 'src/services/database.service';
2025-01-15 23:31:26 -05:00
const common = [...services, ...providers, ...repositories];
2024-03-21 09:08:29 -05:00
const middleware = [
FileUploadInterceptor,
{ provide: APP_FILTER, useClass: GlobalExceptionFilter },
2024-03-21 09:08:29 -05:00
{ provide: APP_PIPE, useValue: new ValidationPipe({ transform: true, whitelist: true }) },
{ provide: APP_INTERCEPTOR, useClass: LoggingInterceptor },
2024-03-21 09:08:29 -05:00
{ provide: APP_INTERCEPTOR, useClass: ErrorInterceptor },
{ provide: APP_GUARD, useClass: AuthGuard },
];
const configRepository = new ConfigRepository();
2024-10-29 16:41:47 -04:00
const { bull, cls, database, otel } = configRepository.getEnv();
2024-03-21 09:08:29 -05:00
const imports = [
BullModule.forRoot(bull.config),
BullModule.registerQueue(...bull.queues),
2024-10-29 16:41:47 -04:00
ClsModule.forRoot(cls.config),
OpenTelemetryModule.forRoot(otel),
TypeOrmModule.forRootAsync({
inject: [ModuleRef],
useFactory: (moduleRef: ModuleRef) => {
return {
2025-01-09 11:15:41 -05:00
...database.config.typeorm,
poolErrorHandler: (error) => {
moduleRef.get(DatabaseService, { strict: false }).handleConnectionError(error);
},
};
},
}),
TypeOrmModule.forFeature(entities),
KyselyModule.forRoot({
dialect: new PostgresJSDialect({ postgres: postgres(database.config.kysely) }),
log(event) {
if (event.level === 'error') {
console.error('Query failed :', {
durationMs: event.queryDurationMillis,
error: event.error,
sql: event.query.sql,
params: event.query.parameters,
});
}
},
}),
2024-03-21 09:08:29 -05:00
];
class BaseModule implements OnModuleInit, OnModuleDestroy {
constructor(
@Inject(IWorker) private worker: ImmichWorker,
2025-01-23 08:31:30 -05:00
logger: LoggingRepository,
2025-02-11 15:12:31 -05:00
private eventRepository: EventRepository,
@Inject(IJobRepository) private jobRepository: IJobRepository,
private telemetryRepository: TelemetryRepository,
2025-02-11 15:12:31 -05:00
private authService: AuthService,
) {
2024-10-04 16:57:34 -04:00
logger.setAppName(this.worker);
}
2024-03-21 09:08:29 -05:00
2024-10-04 16:57:34 -04:00
async onModuleInit() {
2025-01-15 23:31:26 -05:00
this.telemetryRepository.setup({ repositories: [...providers.map(({ useClass }) => useClass), ...repositories] });
this.jobRepository.setup({ services });
if (this.worker === ImmichWorker.MICROSERVICES) {
this.jobRepository.startWorkers();
}
2025-02-11 15:12:31 -05:00
this.eventRepository.setAuthFn(async (client) =>
this.authService.authenticate({
headers: client.request.headers,
queryParams: {},
metadata: { adminRoute: false, sharedLinkRoute: false, uri: '/api/socket.io' },
}),
);
2024-10-04 16:57:34 -04:00
this.eventRepository.setup({ services });
await this.eventRepository.emit('app.bootstrap');
}
async onModuleDestroy() {
await this.eventRepository.emit('app.shutdown');
await teardownTelemetry();
2024-03-21 09:08:29 -05:00
}
}
@Module({
2024-10-04 16:57:34 -04:00
imports: [...imports, ScheduleModule.forRoot()],
controllers: [...controllers],
providers: [...common, ...middleware, { provide: IWorker, useValue: ImmichWorker.API }],
})
export class ApiModule extends BaseModule {}
2024-10-04 16:57:34 -04:00
@Module({
imports: [...imports],
providers: [...common, { provide: IWorker, useValue: ImmichWorker.MICROSERVICES }, SchedulerRegistry],
2024-10-04 16:57:34 -04:00
})
export class MicroservicesModule extends BaseModule {}
2024-03-21 09:08:29 -05:00
@Module({
imports: [...imports],
providers: [...common, ...commands, SchedulerRegistry],
2024-03-21 09:08:29 -05:00
})
export class ImmichAdminModule implements OnModuleDestroy {
constructor(private service: CliService) {}
async onModuleDestroy() {
await this.service.cleanup();
}
}