···11+import { type DynamicModule, Module, type Type } from "@nestjs/common";
22+import { DiskFileStorage } from "./disk-file-storage";
33+import { FILE_STORAGE } from "./file-storage.interface";
44+import { R2FileStorage, type R2FileStorageConfig } from "./r2-file-storage";
55+66+type DiskConfig = { driver: "disk"; baseDir: string };
77+type R2Config = { driver: "r2" } & R2FileStorageConfig;
88+export type FileStorageModuleConfig = DiskConfig | R2Config;
99+1010+/**
1111+ * Implement this interface to provide FileStorage configuration
1212+ * via NestJS DI. Register it with `FileStorageModule.forRootAsync()`.
1313+ */
1414+export interface FileStorageConfigProvider {
1515+ createFileStorageConfig(): FileStorageModuleConfig;
1616+}
1717+1818+export const FILE_STORAGE_CONFIG_PROVIDER = Symbol("FILE_STORAGE_CONFIG_PROVIDER");
1919+2020+@Module({})
2121+export class FileStorageModule {
2222+ /**
2323+ * Static configuration — pass the config directly.
2424+ */
2525+ static forRoot(config: FileStorageModuleConfig): DynamicModule {
2626+ return {
2727+ module: FileStorageModule,
2828+ providers: [
2929+ {
3030+ provide: FILE_STORAGE,
3131+ useFactory: () => createStorage(config),
3232+ },
3333+ ],
3434+ exports: [FILE_STORAGE],
3535+ global: true,
3636+ };
3737+ }
3838+3939+ /**
4040+ * Async configuration — provide a class that implements
4141+ * `FileStorageConfigProvider`. The class can inject ConfigService
4242+ * or any other NestJS provider.
4343+ */
4444+ static forRootAsync(options: {
4545+ imports?: Type[];
4646+ useClass: Type<FileStorageConfigProvider>;
4747+ }): DynamicModule {
4848+ return {
4949+ module: FileStorageModule,
5050+ imports: options.imports ?? [],
5151+ providers: [
5252+ {
5353+ provide: FILE_STORAGE_CONFIG_PROVIDER,
5454+ useClass: options.useClass,
5555+ },
5656+ {
5757+ provide: FILE_STORAGE,
5858+ useFactory: (provider: FileStorageConfigProvider) =>
5959+ createStorage(provider.createFileStorageConfig()),
6060+ inject: [FILE_STORAGE_CONFIG_PROVIDER],
6161+ },
6262+ ],
6363+ exports: [FILE_STORAGE],
6464+ global: true,
6565+ };
6666+ }
6767+}
6868+6969+const createStorage = (config: FileStorageModuleConfig) =>
7070+ config.driver === "r2"
7171+ ? new R2FileStorage(config)
7272+ : new DiskFileStorage(config.baseDir);
+8
packages/file-storage/src/index.ts
···11+export { FILE_STORAGE, type FileStorage } from "./file-storage.interface";
22+export { DiskFileStorage } from "./disk-file-storage";
33+export { R2FileStorage, type R2FileStorageConfig } from "./r2-file-storage";
44+export {
55+ FileStorageModule,
66+ type FileStorageModuleConfig,
77+ type FileStorageConfigProvider,
88+} from "./file-storage.module";