import { DynamicModule, Module, Provider } from '@nestjs/common'; import { S3Client } from '@aws-sdk/client-s3'; import { MediaManagerService } from './media-manager.service'; import { LocalStorageAdapter } from './adapters/local.adapter'; import { S3StorageAdapter } from './adapters/s3.adapter'; export interface MediaManagerAwsOptions { region?: string; endpoint?: string; accessKeyId?: string; secretAccessKey?: string; bucket?: string; } export interface MediaManagerModuleOptions { localRoot?: string; aws?: MediaManagerAwsOptions; } export interface MediaManagerModuleAsyncOptions { imports?: any[]; inject?: any[]; useFactory: (...args: any[]) => Promise | MediaManagerModuleOptions; } const S3_CLIENT = 'MEDIA_MANAGER_S3_CLIENT'; const MEDIA_MANAGER_OPTIONS = 'MEDIA_MANAGER_OPTIONS'; @Module({}) export class MediaManagerModule { static register(options?: MediaManagerModuleOptions): DynamicModule { return this.registerAsync({ useFactory: () => options ?? {}, }); } static registerAsync( asyncOptions: MediaManagerModuleAsyncOptions, ): DynamicModule { const providers: Provider[] = this.createProviders(); const optionProvider: Provider = { provide: MEDIA_MANAGER_OPTIONS, useFactory: asyncOptions.useFactory, inject: asyncOptions.inject || [], }; return { module: MediaManagerModule, imports: asyncOptions.imports || [], providers: [optionProvider, ...providers], exports: [MediaManagerService], }; } private static createProviders(): Provider[] { const localStorageProvider: Provider = { provide: LocalStorageAdapter, useFactory: (options: MediaManagerModuleOptions) => new LocalStorageAdapter(options.localRoot), inject: [MEDIA_MANAGER_OPTIONS], }; const s3ClientProvider: Provider = { provide: S3_CLIENT, useFactory: (options: MediaManagerModuleOptions) => new S3Client({ region: options.aws?.region, endpoint: options.aws?.endpoint, credentials: options.aws?.accessKeyId && options.aws?.secretAccessKey ? { accessKeyId: options.aws.accessKeyId, secretAccessKey: options.aws.secretAccessKey, } : undefined, }), inject: [MEDIA_MANAGER_OPTIONS], }; const s3StorageAdapterProvider: Provider = { provide: S3StorageAdapter, useFactory: (client: S3Client, options: MediaManagerModuleOptions) => new S3StorageAdapter(client, options.aws?.bucket ?? ''), inject: [S3_CLIENT, MEDIA_MANAGER_OPTIONS], }; const serviceProvider: Provider = { provide: MediaManagerService, useFactory: ( localAdapter: LocalStorageAdapter, s3Adapter: S3StorageAdapter, ) => new MediaManagerService(localAdapter, s3Adapter), inject: [LocalStorageAdapter, S3StorageAdapter], }; return [ localStorageProvider, s3ClientProvider, s3StorageAdapterProvider, serviceProvider, ]; } }