@ackplus/nest-file-storage 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/{index.ts → index.d.ts} +1 -0
- package/src/index.d.ts.map +1 -0
- package/src/lib/constants.d.ts +2 -0
- package/src/lib/constants.d.ts.map +1 -0
- package/src/lib/file-storage.service.d.ts +8 -0
- package/src/lib/file-storage.service.d.ts.map +1 -0
- package/src/lib/{index.ts → index.d.ts} +1 -0
- package/src/lib/index.d.ts.map +1 -0
- package/src/lib/interceptor/file-storage.interceptor.d.ts +25 -0
- package/src/lib/interceptor/file-storage.interceptor.d.ts.map +1 -0
- package/src/lib/nest-file-storage.module.d.ts +9 -0
- package/src/lib/nest-file-storage.module.d.ts.map +1 -0
- package/src/lib/storage/azure.storage.d.ts +19 -0
- package/src/lib/storage/azure.storage.d.ts.map +1 -0
- package/src/lib/storage/local.storage.d.ts +35 -0
- package/src/lib/storage/local.storage.d.ts.map +1 -0
- package/src/lib/storage/s3.storage.d.ts +20 -0
- package/src/lib/storage/s3.storage.d.ts.map +1 -0
- package/src/lib/storage.factory.d.ts +9 -0
- package/src/lib/storage.factory.d.ts.map +1 -0
- package/src/lib/{types.ts → types.d.ts} +23 -35
- package/src/lib/types.d.ts.map +1 -0
- package/eslint.config.mjs +0 -22
- package/jest.config.ts +0 -10
- package/project.json +0 -38
- package/src/lib/constants.ts +0 -1
- package/src/lib/file-storage.service.ts +0 -36
- package/src/lib/interceptor/file-storage.interceptor.ts +0 -174
- package/src/lib/nest-file-storage.module.ts +0 -78
- package/src/lib/storage/azure.storage.ts +0 -214
- package/src/lib/storage/local.storage.ts +0 -233
- package/src/lib/storage/s3.storage.ts +0 -242
- package/src/lib/storage.factory.ts +0 -58
- package/tsconfig.json +0 -17
- package/tsconfig.lib.json +0 -14
- package/tsconfig.spec.json +0 -15
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/nest-file-storage/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-file-storage/src/lib/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FileStorageEnum, FileStorageModuleOptions } from './types';
|
|
2
|
+
export declare class FileStorageService {
|
|
3
|
+
private static options;
|
|
4
|
+
static setOptions(options: FileStorageModuleOptions): void;
|
|
5
|
+
static getOptions(): FileStorageModuleOptions;
|
|
6
|
+
static getStorage(storageType?: FileStorageEnum): Promise<import("./types").Storage>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=file-storage.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-storage.service.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-file-storage/src/lib/file-storage.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAqD,MAAM,SAAS,CAAC;AAGvH,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,MAAM,CAAC,OAAO,CAA2B;IAEjD,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,wBAAwB;IAInD,MAAM,CAAC,UAAU,IAAI,wBAAwB;WAIhC,UAAU,CAAC,WAAW,CAAC,EAAE,eAAe;CAmBxD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-file-storage/src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,wCAAwC,CAAC;AACvD,cAAc,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { NestInterceptor } from '@nestjs/common';
|
|
2
|
+
import { Request } from 'express';
|
|
3
|
+
import { FileStorageEnum, StorageOptions } from '../types';
|
|
4
|
+
export type FileUploadConfig = {
|
|
5
|
+
type: 'single' | 'array' | 'fields';
|
|
6
|
+
fieldName?: string;
|
|
7
|
+
maxCount?: number;
|
|
8
|
+
fields?: {
|
|
9
|
+
name: string;
|
|
10
|
+
maxCount?: number;
|
|
11
|
+
}[];
|
|
12
|
+
};
|
|
13
|
+
export type FileStorageInterceptorOptions = {
|
|
14
|
+
fileName?: (file: any, req?: Request) => string;
|
|
15
|
+
fileDist?: (file: any, req?: Request) => string;
|
|
16
|
+
prefix?: string;
|
|
17
|
+
storageType?: FileStorageEnum;
|
|
18
|
+
storageOptions?: StorageOptions;
|
|
19
|
+
mapToRequestBody?: (file: any, fieldName: string, req?: Request) => any;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Function-based interceptor that accepts storage options dynamically.
|
|
23
|
+
*/
|
|
24
|
+
export declare function FileStorageInterceptor(fileConfig: FileUploadConfig | string, interceptorOptions?: FileStorageInterceptorOptions): NestInterceptor;
|
|
25
|
+
//# sourceMappingURL=file-storage.interceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-storage.interceptor.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-file-storage/src/lib/interceptor/file-storage.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAiC,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAMlC,OAAO,EAAE,eAAe,EAAE,cAAc,EAA0C,MAAM,UAAU,CAAC;AAGnG,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IACxC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IAChD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,cAAc,CAAC,EAAE,cAAc,CAAC;IAGhC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,GAAG,CAAC;CAC3E,CAAC;AA2DF;;GAEG;AACH,wBAAgB,sBAAsB,CAClC,UAAU,EAAE,gBAAgB,GAAG,MAAM,EACrC,kBAAkB,CAAC,EAAE,6BAA6B,GACnD,eAAe,CAkFjB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { FileStorageAsyncOptions, FileStorageModuleOptions } from './types';
|
|
3
|
+
export declare class NestFileStorageModule {
|
|
4
|
+
static forRoot(options: FileStorageModuleOptions): DynamicModule;
|
|
5
|
+
static forRootAsync(options: FileStorageAsyncOptions): DynamicModule;
|
|
6
|
+
private static createAsyncProviders;
|
|
7
|
+
private static createAsyncOptionsProvider;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=nest-file-storage.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nest-file-storage.module.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-file-storage/src/lib/nest-file-storage.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,aAAa,EAAY,MAAM,gBAAgB,CAAC;AAIjE,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAA6B,MAAM,SAAS,CAAC;AAGvG,qBACa,qBAAqB;IAE9B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,wBAAwB,GAAG,aAAa;IAkBhE,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,uBAAuB,GAAG,aAAa;IAWpE,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAcnC,OAAO,CAAC,MAAM,CAAC,0BAA0B;CAwB5C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BlobSASSignatureValues } from '@azure/storage-blob';
|
|
2
|
+
import { StorageEngine } from 'multer';
|
|
3
|
+
import { AzureStorageOptions, Storage, UploadedFile } from '../types';
|
|
4
|
+
export declare class AzureStorage implements StorageEngine, Storage {
|
|
5
|
+
private options;
|
|
6
|
+
private blobServiceClient;
|
|
7
|
+
private fileNameFunction;
|
|
8
|
+
private fileDistFunction;
|
|
9
|
+
constructor(options: AzureStorageOptions);
|
|
10
|
+
_handleFile(req: any, file: any, cb: (error?: any, info?: any) => void): Promise<void>;
|
|
11
|
+
_removeFile(_req: any, file: any, cb: (error: Error | null) => void): Promise<void>;
|
|
12
|
+
getUrl(key: string): string;
|
|
13
|
+
getSignedUrl(key: string, signatureValues?: Partial<Omit<BlobSASSignatureValues, 'containerName'>>): string;
|
|
14
|
+
getFile(key: string): Promise<Buffer>;
|
|
15
|
+
putFile(buffer: Buffer, key: string): Promise<UploadedFile>;
|
|
16
|
+
deleteFile(key: string): Promise<void>;
|
|
17
|
+
copyFile(oldKey: string, newKey: string): Promise<UploadedFile>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=azure.storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure.storage.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-file-storage/src/lib/storage/azure.storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,sBAAsB,EAKzB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAIvC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGtE,qBAAa,YAAa,YAAW,aAAa,EAAE,OAAO;IAQ3C,OAAO,CAAC,OAAO;IAN3B,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,OAAO,CAAC,gBAAgB,CAAqE;IAC7F,OAAO,CAAC,gBAAgB,CAAqE;gBAGzE,OAAO,EAAE,mBAAmB;IAoB1C,WAAW,CACb,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,GAAG,EACT,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GACtC,OAAO,CAAC,IAAI,CAAC;IA6BV,WAAW,CACb,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GAClC,OAAO,CAAC,IAAI,CAAC;IAahB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAK3B,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,GAAE,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,eAAe,CAAC,CAAM,GAAG,MAAM;IAqCzG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAcrC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAwB3D,UAAU,CAAC,GAAG,EAAE,MAAM;IAYtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CA0BxE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { StorageEngine } from 'multer';
|
|
2
|
+
import { LocalStorageOptions, Storage, UploadedFile } from '../types';
|
|
3
|
+
export declare class LocalStorage implements StorageEngine, Storage {
|
|
4
|
+
private options;
|
|
5
|
+
private rootPath;
|
|
6
|
+
private fileNameFunction;
|
|
7
|
+
private fileDistFunction;
|
|
8
|
+
/**
|
|
9
|
+
* Convert OS-specific file path to URL-friendly key
|
|
10
|
+
* This ensures keys are consistent across all platforms
|
|
11
|
+
* Windows: C:\uploads\2024\01\file.jpg -> 2024/01/file.jpg
|
|
12
|
+
* Unix: /uploads/2024/01/file.jpg -> 2024/01/file.jpg
|
|
13
|
+
*/
|
|
14
|
+
private pathToUrl;
|
|
15
|
+
/**
|
|
16
|
+
* Convert URL-friendly key to OS-specific file path
|
|
17
|
+
* This converts stored keys back to valid file system paths
|
|
18
|
+
* 2024/01/file.jpg -> Windows: 2024\01\file.jpg, Unix: 2024/01/file.jpg
|
|
19
|
+
*/
|
|
20
|
+
private urlToPath;
|
|
21
|
+
/**
|
|
22
|
+
* Get full file system path from URL-friendly key
|
|
23
|
+
*/
|
|
24
|
+
private getFullPath;
|
|
25
|
+
constructor(options: LocalStorageOptions);
|
|
26
|
+
_handleFile(req: any, file: Express.Multer.File, cb: (error?: any, info?: any) => void): Promise<void>;
|
|
27
|
+
_removeFile(_req: any, file: any, cb: (error: Error | null) => void): void;
|
|
28
|
+
getUrl(urlKey: string): string;
|
|
29
|
+
getFile(urlKey: string): Promise<Buffer>;
|
|
30
|
+
deleteFile(urlKey: string): Promise<void>;
|
|
31
|
+
putFile(fileContent: Buffer, urlKey: string): Promise<UploadedFile>;
|
|
32
|
+
path(urlKey: string): string;
|
|
33
|
+
copyFile(oldUrlKey: string, newUrlKey: string): Promise<UploadedFile>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=local.storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.storage.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-file-storage/src/lib/storage/local.storage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAMvC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGtE,qBAAa,YAAa,YAAW,aAAa,EAAE,OAAO;IA8C3C,OAAO,CAAC,OAAO;IA5C3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAqE;IAC7F,OAAO,CAAC,gBAAgB,CAAqE;IAE7F;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAajB;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAQjB;;OAEG;IACH,OAAO,CAAC,WAAW;gBAKC,OAAO,EAAE,mBAAmB;IAmB1C,WAAW,CACb,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EACzB,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI;IAgCzC,WAAW,CACP,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI;IAarC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAgBxB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMxC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,OAAO,CACT,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC;IAiCxB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQtB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAgC9E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { GetObjectCommandInput } from '@aws-sdk/client-s3';
|
|
2
|
+
import { StorageEngine } from 'multer';
|
|
3
|
+
import { S3StorageOptions, Storage, UploadedFile } from '../types';
|
|
4
|
+
export declare class S3Storage implements StorageEngine, Storage {
|
|
5
|
+
private options;
|
|
6
|
+
private s3;
|
|
7
|
+
private fileNameFunction;
|
|
8
|
+
private fileDistFunction;
|
|
9
|
+
constructor(options: S3StorageOptions);
|
|
10
|
+
_handleFile(req: any, file: Express.Multer.File, cb: (error?: any, info?: any) => void): Promise<void>;
|
|
11
|
+
_removeFile(_req: any, file: any, cb: (error: Error | null) => void): void;
|
|
12
|
+
getUrl(key: string): string;
|
|
13
|
+
getSignedUrl(key: string, objectConfig?: Partial<GetObjectCommandInput>): Promise<string>;
|
|
14
|
+
getFile(key: string): Promise<Buffer>;
|
|
15
|
+
putFile(fileContent: Buffer, key: string): Promise<any>;
|
|
16
|
+
deleteFile(key: string): Promise<void>;
|
|
17
|
+
private streamToBuffer;
|
|
18
|
+
copyFile(oldKey: string, newKey: string): Promise<UploadedFile>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=s3.storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.storage.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-file-storage/src/lib/storage/s3.storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,qBAAqB,EAAM,MAAM,oBAAoB,CAAC;AAIlF,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAMvC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGnE,qBAAa,SAAU,YAAW,aAAa,EAAE,OAAO;IAMxC,OAAO,CAAC,OAAO;IAJ3B,OAAO,CAAC,EAAE,CAAK;IACf,OAAO,CAAC,gBAAgB,CAAqE;IAC7F,OAAO,CAAC,gBAAgB,CAAqE;gBAEzE,OAAO,EAAE,gBAAgB;IAmBvC,WAAW,CACb,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EACzB,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GACtC,OAAO,CAAC,IAAI,CAAC;IAkChB,WAAW,CACP,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,GAAG,EACT,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GAClC,IAAI;IAYP,MAAM,CAAC,GAAG,EAAE,MAAM;IAOZ,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAezF,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BrC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IA0CvD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAmB9B,cAAc;IAQtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CA4BxE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FileStorageEnum, StorageOptions } from './types';
|
|
2
|
+
import { StorageEngine } from 'multer';
|
|
3
|
+
import { Storage } from './types';
|
|
4
|
+
export declare class StorageFactory {
|
|
5
|
+
private static storageInstances;
|
|
6
|
+
static createStorage(storageType: FileStorageEnum, options: StorageOptions): Promise<StorageEngine & Storage>;
|
|
7
|
+
static clearCache(): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=storage.factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.factory.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-file-storage/src/lib/storage.factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,eAAe,EAAyC,cAAc,EAAE,MAAM,SAAS,CAAC;AACtH,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAA8C;WAEhE,aAAa,CAAC,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC;IA+CnH,MAAM,CAAC,UAAU;CAGpB"}
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { ModuleMetadata, Type } from '@nestjs/common';
|
|
2
2
|
import { Request } from 'express';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
S3 = 's3',
|
|
8
|
-
AZURE = 'azure',
|
|
3
|
+
export declare enum FileStorageEnum {
|
|
4
|
+
LOCAL = "local",
|
|
5
|
+
S3 = "s3",
|
|
6
|
+
AZURE = "azure"
|
|
9
7
|
}
|
|
10
|
-
|
|
11
8
|
export interface FileStorageOptions {
|
|
12
9
|
prefix?: string;
|
|
13
|
-
fileName?: (file: any, req: Request) => string;
|
|
14
|
-
fileDist?: (file: any, req: Request) => string;
|
|
10
|
+
fileName?: (file: any, req: Request) => string;
|
|
11
|
+
fileDist?: (file: any, req: Request) => string;
|
|
15
12
|
transformUploadedFileObject?: (file: any) => any;
|
|
16
13
|
}
|
|
17
|
-
|
|
18
14
|
export interface S3StorageOptions extends FileStorageOptions {
|
|
19
15
|
accessKeyId: string;
|
|
20
16
|
secretAccessKey: string;
|
|
@@ -23,36 +19,31 @@ export interface S3StorageOptions extends FileStorageOptions {
|
|
|
23
19
|
endpoint?: string;
|
|
24
20
|
cloudFrontUrl?: string;
|
|
25
21
|
}
|
|
26
|
-
|
|
27
22
|
export interface LocalStorageOptions extends FileStorageOptions {
|
|
28
23
|
rootPath: string;
|
|
29
24
|
baseUrl: string;
|
|
30
25
|
}
|
|
31
|
-
|
|
32
26
|
export interface AzureStorageOptions extends FileStorageOptions {
|
|
33
27
|
account: string;
|
|
34
28
|
accountKey: string;
|
|
35
29
|
container: string;
|
|
36
30
|
}
|
|
37
|
-
|
|
38
31
|
export type StorageOptions = S3StorageOptions | AzureStorageOptions | LocalStorageOptions;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
32
|
+
export type FileStorageConfigOptions = {
|
|
33
|
+
storage: FileStorageEnum.LOCAL;
|
|
34
|
+
localConfig: LocalStorageOptions;
|
|
35
|
+
} | {
|
|
36
|
+
storage: FileStorageEnum.S3;
|
|
37
|
+
s3Config: S3StorageOptions;
|
|
38
|
+
} | {
|
|
39
|
+
storage: FileStorageEnum.AZURE;
|
|
40
|
+
azureConfig: AzureStorageOptions;
|
|
41
|
+
};
|
|
47
42
|
export interface FileStorageClassOptions {
|
|
48
43
|
storageFactory: () => Promise<new (...args: any[]) => Storage> | (new (...args: any[]) => Storage);
|
|
49
44
|
options?: any;
|
|
50
45
|
}
|
|
51
|
-
|
|
52
|
-
// Combined module options
|
|
53
46
|
export type FileStorageModuleOptions = FileStorageConfigOptions | FileStorageClassOptions;
|
|
54
|
-
|
|
55
|
-
|
|
56
47
|
export interface FileStorageAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
|
|
57
48
|
/**
|
|
58
49
|
* The `useExisting` syntax allows you to create aliases for existing providers.
|
|
@@ -72,26 +63,22 @@ export interface FileStorageAsyncOptions extends Pick<ModuleMetadata, 'imports'>
|
|
|
72
63
|
*/
|
|
73
64
|
inject?: any[];
|
|
74
65
|
}
|
|
75
|
-
|
|
76
66
|
export interface FileStorageOptionsFactory {
|
|
77
67
|
createFileStorageOptions(): Promise<FileStorageModuleOptions> | FileStorageModuleOptions;
|
|
78
68
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
69
|
export interface UploadedFile {
|
|
82
70
|
fieldName?: string;
|
|
83
71
|
fieldname?: string;
|
|
84
72
|
fileName: string;
|
|
85
|
-
originalName: string;
|
|
86
|
-
size: number;
|
|
73
|
+
originalName: string;
|
|
74
|
+
size: number;
|
|
87
75
|
mimetype?: string;
|
|
88
76
|
buffer?: Buffer;
|
|
89
|
-
key: string;
|
|
90
|
-
url: string;
|
|
91
|
-
fullPath: string;
|
|
77
|
+
key: string;
|
|
78
|
+
url: string;
|
|
79
|
+
fullPath: string;
|
|
92
80
|
encoding?: string;
|
|
93
81
|
}
|
|
94
|
-
|
|
95
82
|
export interface Storage {
|
|
96
83
|
getFile(key: string): Promise<Buffer> | Buffer;
|
|
97
84
|
deleteFile(key: string): Promise<void> | void;
|
|
@@ -99,5 +86,6 @@ export interface Storage {
|
|
|
99
86
|
path?(filePath: string): Promise<string> | string;
|
|
100
87
|
getUrl(key: string): Promise<string> | string;
|
|
101
88
|
getSignedUrl?(key: string, options: any): Promise<string> | string;
|
|
102
|
-
copyFile(oldKey: string, newKey: string): Promise<UploadedFile
|
|
89
|
+
copyFile(oldKey: string, newKey: string): Promise<UploadedFile>;
|
|
103
90
|
}
|
|
91
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-file-storage/src/lib/types.ts"],"names":[],"mappings":"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"}
|
package/eslint.config.mjs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import baseConfig from '../../eslint.base.config';
|
|
2
|
-
|
|
3
|
-
export default [
|
|
4
|
-
...baseConfig,
|
|
5
|
-
{
|
|
6
|
-
files: ['**/*.json'],
|
|
7
|
-
rules: {
|
|
8
|
-
'@nx/dependency-checks': [
|
|
9
|
-
'error',
|
|
10
|
-
{
|
|
11
|
-
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}'],
|
|
12
|
-
},
|
|
13
|
-
],
|
|
14
|
-
},
|
|
15
|
-
languageOptions: {
|
|
16
|
-
parser: await import('jsonc-eslint-parser'),
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
ignores: ['**/out-tsc'],
|
|
21
|
-
},
|
|
22
|
-
];
|
package/jest.config.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
displayName: 'nest-file-storage',
|
|
3
|
-
preset: '../../jest.preset.js',
|
|
4
|
-
testEnvironment: 'node',
|
|
5
|
-
transform: {
|
|
6
|
-
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
|
7
|
-
},
|
|
8
|
-
moduleFileExtensions: ['ts', 'js', 'html'],
|
|
9
|
-
coverageDirectory: '../../coverage/packages/nest-file-storage',
|
|
10
|
-
};
|
package/project.json
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "nest-file-storage",
|
|
3
|
-
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"sourceRoot": "packages/nest-file-storage/src",
|
|
5
|
-
"projectType": "library",
|
|
6
|
-
"release": {
|
|
7
|
-
"version": {
|
|
8
|
-
"manifestRootsToUpdate": [
|
|
9
|
-
"dist/{projectRoot}"
|
|
10
|
-
],
|
|
11
|
-
"currentVersionResolver": "git-tag",
|
|
12
|
-
"fallbackCurrentVersionResolver": "disk"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"tags": [],
|
|
16
|
-
"targets": {
|
|
17
|
-
"build": {
|
|
18
|
-
"executor": "@nx/js:tsc",
|
|
19
|
-
"outputs": [
|
|
20
|
-
"{options.outputPath}"
|
|
21
|
-
],
|
|
22
|
-
"options": {
|
|
23
|
-
"outputPath": "dist/packages/nest-file-storage",
|
|
24
|
-
"tsConfig": "packages/nest-file-storage/tsconfig.lib.json",
|
|
25
|
-
"packageJson": "packages/nest-file-storage/package.json",
|
|
26
|
-
"main": "packages/nest-file-storage/src/index.ts",
|
|
27
|
-
"assets": [
|
|
28
|
-
"packages/nest-file-storage/*.md"
|
|
29
|
-
]
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
"nx-release-publish": {
|
|
33
|
-
"options": {
|
|
34
|
-
"packageRoot": "dist/{projectRoot}"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
package/src/lib/constants.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const FILE_STORAGE_OPTIONS = 'FileStorageOptions';
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { StorageFactory } from './storage.factory';
|
|
2
|
-
import { FileStorageEnum, FileStorageModuleOptions, FileStorageConfigOptions, FileStorageClassOptions } from './types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export class FileStorageService {
|
|
6
|
-
|
|
7
|
-
private static options: FileStorageModuleOptions; // ✅ Static global property
|
|
8
|
-
|
|
9
|
-
static setOptions(options: FileStorageModuleOptions) {
|
|
10
|
-
FileStorageService.options = options;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
static getOptions(): FileStorageModuleOptions {
|
|
14
|
-
return FileStorageService.options;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static async getStorage(storageType?: FileStorageEnum) {
|
|
18
|
-
const options = this.getOptions();
|
|
19
|
-
|
|
20
|
-
// Check if it's a class factory approach
|
|
21
|
-
if ('storageFactory' in options) {
|
|
22
|
-
const classOptions = options as FileStorageClassOptions;
|
|
23
|
-
const StorageClass = await classOptions.storageFactory();
|
|
24
|
-
return new StorageClass(classOptions.options);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Configuration-based approach
|
|
28
|
-
const configOptions = options as FileStorageConfigOptions;
|
|
29
|
-
if (!storageType) {
|
|
30
|
-
storageType = configOptions.storage;
|
|
31
|
-
}
|
|
32
|
-
const config = (configOptions as any)[`Config`];
|
|
33
|
-
return await StorageFactory.createStorage(storageType, config);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
2
|
-
import { Request } from 'express';
|
|
3
|
-
import multer from 'multer';
|
|
4
|
-
import { Observable } from 'rxjs';
|
|
5
|
-
|
|
6
|
-
import { FileStorageService } from '../file-storage.service';
|
|
7
|
-
import { StorageFactory } from '../storage.factory';
|
|
8
|
-
import { FileStorageEnum, StorageOptions, FileStorageConfigOptions, UploadedFile } from '../types';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export type FileUploadConfig = {
|
|
12
|
-
type: 'single' | 'array' | 'fields';
|
|
13
|
-
fieldName?: string;
|
|
14
|
-
maxCount?: number;
|
|
15
|
-
fields?: { name: string; maxCount?: number }[];
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type FileStorageInterceptorOptions = {
|
|
19
|
-
fileName?: (file: any, req?: Request) => string;
|
|
20
|
-
fileDist?: (file: any, req?: Request) => string;
|
|
21
|
-
prefix?: string;
|
|
22
|
-
storageType?: FileStorageEnum;
|
|
23
|
-
storageOptions?: StorageOptions;
|
|
24
|
-
|
|
25
|
-
// File mapping callback - user defines what to return (defaults to file.key)
|
|
26
|
-
mapToRequestBody?: (file: any, fieldName: string, req?: Request) => any;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// Helper function to map file object
|
|
30
|
-
function mapFileObject(file: any) {
|
|
31
|
-
return {
|
|
32
|
-
fieldName: file.fieldname,
|
|
33
|
-
originalName: file.originalname,
|
|
34
|
-
fileName: file.filename,
|
|
35
|
-
mimetype: file.mimetype,
|
|
36
|
-
size: file.size,
|
|
37
|
-
key: (file as any).key,
|
|
38
|
-
path: (file as any).path,
|
|
39
|
-
url: (file as any).url,
|
|
40
|
-
encoding: file.encoding,
|
|
41
|
-
fullPath: (file as any).fullPath
|
|
42
|
-
} as unknown as UploadedFile;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Helper function to apply file mapping with callback
|
|
46
|
-
function applyFileKeyMapping(
|
|
47
|
-
request: Request,
|
|
48
|
-
fileConfig: FileUploadConfig,
|
|
49
|
-
interceptorOptions?: FileStorageInterceptorOptions
|
|
50
|
-
): void {
|
|
51
|
-
// Default callback returns the file key
|
|
52
|
-
const mapCallback = interceptorOptions?.mapToRequestBody || ((file: any) => {
|
|
53
|
-
// For arrays, return array of keys
|
|
54
|
-
if (Array.isArray(file)) {
|
|
55
|
-
return file.map(f => f.key);
|
|
56
|
-
}
|
|
57
|
-
// For single file, return the key
|
|
58
|
-
return file.key;
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
if (fileConfig.type === 'single') {
|
|
62
|
-
const file = request.file;
|
|
63
|
-
if (file) {
|
|
64
|
-
const fieldName = fileConfig.fieldName || 'file';
|
|
65
|
-
const mappedFile = mapFileObject(file);
|
|
66
|
-
request.body[fieldName] = mapCallback(mappedFile, fieldName, request);
|
|
67
|
-
}
|
|
68
|
-
} else if (fileConfig.type === 'array') {
|
|
69
|
-
const files = request.files as Express.Multer.File[];
|
|
70
|
-
if (files && files.length > 0) {
|
|
71
|
-
const fieldName = fileConfig.fieldName || 'files';
|
|
72
|
-
const mappedFiles = files.map(file => mapFileObject(file));
|
|
73
|
-
request.body[fieldName] = mapCallback(mappedFiles, fieldName, request);
|
|
74
|
-
}
|
|
75
|
-
} else if (fileConfig.type === 'fields') {
|
|
76
|
-
const files = request.files as { [fieldname: string]: Express.Multer.File[] };
|
|
77
|
-
if (files) {
|
|
78
|
-
Object.keys(files).forEach(fieldName => {
|
|
79
|
-
const mappedFiles = files[fieldName].map(file => mapFileObject(file));
|
|
80
|
-
request.body[fieldName] = mapCallback(mappedFiles, fieldName, request);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Function-based interceptor that accepts storage options dynamically.
|
|
88
|
-
*/
|
|
89
|
-
export function FileStorageInterceptor(
|
|
90
|
-
fileConfig: FileUploadConfig | string,
|
|
91
|
-
interceptorOptions?: FileStorageInterceptorOptions,
|
|
92
|
-
): NestInterceptor {
|
|
93
|
-
if (typeof fileConfig === 'string') {
|
|
94
|
-
fileConfig = {
|
|
95
|
-
type: 'single',
|
|
96
|
-
fieldName: fileConfig,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return {
|
|
101
|
-
async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
|
|
102
|
-
const options = FileStorageService.getOptions();
|
|
103
|
-
const request = context.switchToHttp().getRequest();
|
|
104
|
-
const response = context.switchToHttp().getResponse();
|
|
105
|
-
|
|
106
|
-
// Determine storage type - handle both config approaches
|
|
107
|
-
let storageType: FileStorageEnum;
|
|
108
|
-
let storageConfig: any;
|
|
109
|
-
|
|
110
|
-
if ('storage' in options) {
|
|
111
|
-
// Configuration-based approach
|
|
112
|
-
const configOptions = options as FileStorageConfigOptions;
|
|
113
|
-
storageType = interceptorOptions?.storageType ?? configOptions.storage;
|
|
114
|
-
storageConfig = (configOptions as any)[`Config`];
|
|
115
|
-
} else {
|
|
116
|
-
// Class factory approach - default to LOCAL
|
|
117
|
-
storageType = interceptorOptions?.storageType ?? FileStorageEnum.LOCAL;
|
|
118
|
-
storageConfig = {};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const storageOptions = {
|
|
122
|
-
...storageConfig,
|
|
123
|
-
...(interceptorOptions?.storageOptions || {}),
|
|
124
|
-
fileName: interceptorOptions?.fileName || storageConfig?.fileName,
|
|
125
|
-
fileDist: (file: any, req: any) => {
|
|
126
|
-
if (interceptorOptions?.fileDist) {
|
|
127
|
-
return interceptorOptions.fileDist(file, req);
|
|
128
|
-
}
|
|
129
|
-
return storageConfig?.fileDist?.(file, req);
|
|
130
|
-
},
|
|
131
|
-
prefix: interceptorOptions?.prefix || storageConfig?.prefix,
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// Create storage instance dynamically
|
|
135
|
-
const storage = await StorageFactory.createStorage(storageType, storageOptions);
|
|
136
|
-
const multerInstance = multer({ storage });
|
|
137
|
-
|
|
138
|
-
// Multer setup based on fileConfig
|
|
139
|
-
let multerMiddleware;
|
|
140
|
-
switch (fileConfig.type) {
|
|
141
|
-
case 'single':
|
|
142
|
-
if (!fileConfig.fieldName) {
|
|
143
|
-
throw new Error('fieldName is required for single file upload.');
|
|
144
|
-
}
|
|
145
|
-
multerMiddleware = multerInstance.single(fileConfig.fieldName);
|
|
146
|
-
break;
|
|
147
|
-
case 'array':
|
|
148
|
-
if (!fileConfig.fieldName) {
|
|
149
|
-
throw new Error('fieldName is required for multiple file upload.');
|
|
150
|
-
}
|
|
151
|
-
multerMiddleware = multerInstance.array(fileConfig.fieldName, fileConfig.maxCount);
|
|
152
|
-
break;
|
|
153
|
-
case 'fields':
|
|
154
|
-
if (!fileConfig.fields || !Array.isArray(fileConfig.fields)) {
|
|
155
|
-
throw new Error('fields array is required for multiple fields file upload.');
|
|
156
|
-
}
|
|
157
|
-
multerMiddleware = multerInstance.fields(fileConfig.fields);
|
|
158
|
-
break;
|
|
159
|
-
default:
|
|
160
|
-
throw new Error('Invalid file upload type. Use "single", "array", or "fields".');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Execute Multer middleware
|
|
164
|
-
await new Promise((resolve, reject) => {
|
|
165
|
-
multerMiddleware(request, response, (err) => (err ? reject(err) : resolve(true)));
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// Apply file key mapping after multer processing
|
|
169
|
-
applyFileKeyMapping(request, fileConfig, interceptorOptions);
|
|
170
|
-
|
|
171
|
-
return next.handle();
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
}
|