@nest-boot/file-upload 7.1.2 → 7.1.4
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/dist/file-upload-field.object.d.ts +3 -0
- package/dist/file-upload-field.object.js +1 -0
- package/dist/file-upload-field.object.js.map +1 -1
- package/dist/file-upload-options.interface.d.ts +9 -0
- package/dist/file-upload.module.d.ts +21 -1
- package/dist/file-upload.module.js +23 -0
- package/dist/file-upload.module.js.map +1 -1
- package/dist/file-upload.module.spec.d.ts +1 -0
- package/dist/file-upload.module.spec.js +38 -0
- package/dist/file-upload.module.spec.js.map +1 -0
- package/dist/file-upload.object.d.ts +3 -0
- package/dist/file-upload.object.js +1 -0
- package/dist/file-upload.object.js.map +1 -1
- package/dist/file-upload.object.spec.d.ts +1 -0
- package/dist/file-upload.object.spec.js +36 -0
- package/dist/file-upload.object.spec.js.map +1 -0
- package/dist/file-upload.resolver.spec.d.ts +1 -0
- package/dist/file-upload.resolver.spec.js +46 -0
- package/dist/file-upload.resolver.spec.js.map +1 -0
- package/dist/file-upload.service.d.ts +29 -1
- package/dist/file-upload.service.js +30 -9
- package/dist/file-upload.service.js.map +1 -1
- package/dist/file-upload.service.spec.d.ts +1 -0
- package/dist/file-upload.service.spec.js +304 -0
- package/dist/file-upload.service.spec.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/inputs/file-upload.input.d.ts +4 -0
- package/dist/inputs/file-upload.input.js +1 -0
- package/dist/inputs/file-upload.input.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +23 -14
|
@@ -11,6 +11,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.FileUploadField = void 0;
|
|
13
13
|
const graphql_1 = require("@nest-boot/graphql");
|
|
14
|
+
/** GraphQL object type representing a single form field in a presigned upload. */
|
|
14
15
|
let FileUploadField = class FileUploadField {
|
|
15
16
|
};
|
|
16
17
|
exports.FileUploadField = FileUploadField;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload-field.object.js","sourceRoot":"","sources":["../src/file-upload-field.object.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,gDAAuD;
|
|
1
|
+
{"version":3,"file":"file-upload-field.object.js","sourceRoot":"","sources":["../src/file-upload-field.object.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,gDAAuD;AAEvD,kFAAkF;AAE3E,IAAM,eAAe,GAArB,MAAM,eAAe;CAQ3B,CAAA;AARY,0CAAe;AAG1B;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;;6CACN;AAId;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;;8CACL;0BAPJ,eAAe;IAD3B,IAAA,oBAAU,GAAE;GACA,eAAe,CAQ3B"}
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { S3Client, S3ClientConfig } from "@aws-sdk/client-s3";
|
|
2
|
+
/** Defines file size and MIME type constraints for uploaded files. */
|
|
2
3
|
export interface FileUploadLimit {
|
|
4
|
+
/** Maximum file size in bytes. */
|
|
3
5
|
fileSize: number;
|
|
6
|
+
/** Allowed MIME type patterns (supports glob matching via micromatch). */
|
|
4
7
|
mimeTypes: string[];
|
|
5
8
|
}
|
|
9
|
+
/** Configuration options for the FileUploadModule. */
|
|
6
10
|
export interface FileUploadModuleOptions {
|
|
11
|
+
/** S3 client instance or configuration for creating one. */
|
|
7
12
|
client: S3Client | S3ClientConfig;
|
|
13
|
+
/** Optional custom URL prefix for presigned upload URLs. */
|
|
8
14
|
url?: string;
|
|
15
|
+
/** S3 bucket name for storing uploaded files. */
|
|
9
16
|
bucket: string;
|
|
17
|
+
/** Presigned URL expiration time in seconds (defaults to 3600). */
|
|
10
18
|
expires?: number;
|
|
19
|
+
/** File upload constraints (size and MIME type limits). */
|
|
11
20
|
limits?: FileUploadLimit[];
|
|
12
21
|
}
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type DynamicModule } from "@nestjs/common";
|
|
2
|
+
import { ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, OPTIONS_TYPE } from "./file-upload.module-definition";
|
|
3
|
+
/**
|
|
4
|
+
* File upload module providing upload handling via GraphQL.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Registers the {@link FileUploadService} and GraphQL resolver
|
|
8
|
+
* for handling file upload operations.
|
|
9
|
+
*/
|
|
2
10
|
export declare class FileUploadModule extends ConfigurableModuleClass {
|
|
11
|
+
/**
|
|
12
|
+
* Registers the FileUploadModule with the given options.
|
|
13
|
+
* @param options - Configuration options
|
|
14
|
+
* @returns Dynamic module configuration
|
|
15
|
+
*/
|
|
16
|
+
static register(options: typeof OPTIONS_TYPE): DynamicModule;
|
|
17
|
+
/**
|
|
18
|
+
* Registers the FileUploadModule asynchronously with factory functions.
|
|
19
|
+
* @param options - Async configuration options
|
|
20
|
+
* @returns Dynamic module configuration
|
|
21
|
+
*/
|
|
22
|
+
static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule;
|
|
3
23
|
}
|
|
@@ -11,7 +11,30 @@ const common_1 = require("@nestjs/common");
|
|
|
11
11
|
const file_upload_module_definition_1 = require("./file-upload.module-definition");
|
|
12
12
|
const file_upload_resolver_1 = require("./file-upload.resolver");
|
|
13
13
|
const file_upload_service_1 = require("./file-upload.service");
|
|
14
|
+
/**
|
|
15
|
+
* File upload module providing upload handling via GraphQL.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* Registers the {@link FileUploadService} and GraphQL resolver
|
|
19
|
+
* for handling file upload operations.
|
|
20
|
+
*/
|
|
14
21
|
let FileUploadModule = class FileUploadModule extends file_upload_module_definition_1.ConfigurableModuleClass {
|
|
22
|
+
/**
|
|
23
|
+
* Registers the FileUploadModule with the given options.
|
|
24
|
+
* @param options - Configuration options
|
|
25
|
+
* @returns Dynamic module configuration
|
|
26
|
+
*/
|
|
27
|
+
static register(options) {
|
|
28
|
+
return super.register(options);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Registers the FileUploadModule asynchronously with factory functions.
|
|
32
|
+
* @param options - Async configuration options
|
|
33
|
+
* @returns Dynamic module configuration
|
|
34
|
+
*/
|
|
35
|
+
static registerAsync(options) {
|
|
36
|
+
return super.registerAsync(options);
|
|
37
|
+
}
|
|
15
38
|
};
|
|
16
39
|
exports.FileUploadModule = FileUploadModule;
|
|
17
40
|
exports.FileUploadModule = FileUploadModule = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.module.js","sourceRoot":"","sources":["../src/file-upload.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"file-upload.module.js","sourceRoot":"","sources":["../src/file-upload.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4D;AAE5D,mFAIyC;AACzC,iEAA4D;AAC5D,+DAA0D;AAE1D;;;;;;GAMG;AAKI,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,uDAAuB;IAC3D;;;;OAIG;IACH,MAAM,CAAU,QAAQ,CAAC,OAA4B;QACnD,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAU,aAAa,CAC3B,OAAkC;QAElC,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAA;AApBY,4CAAgB;2BAAhB,gBAAgB;IAJ5B,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,uCAAiB,EAAE,yCAAkB,CAAC;QAClD,OAAO,EAAE,CAAC,uCAAiB,CAAC;KAC7B,CAAC;GACW,gBAAgB,CAoB5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const file_upload_module_1 = require("./file-upload.module");
|
|
4
|
+
const file_upload_module_definition_1 = require("./file-upload.module-definition");
|
|
5
|
+
describe("FileUploadModule", () => {
|
|
6
|
+
const options = {
|
|
7
|
+
bucket: "uploads",
|
|
8
|
+
client: {
|
|
9
|
+
endpoint: "http://s3.local",
|
|
10
|
+
region: "us-east-1",
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
it("should register synchronous options", () => {
|
|
14
|
+
const dynamicModule = file_upload_module_1.FileUploadModule.register(options);
|
|
15
|
+
expect(dynamicModule.module).toBe(file_upload_module_1.FileUploadModule);
|
|
16
|
+
expect(dynamicModule.providers).toEqual(expect.arrayContaining([
|
|
17
|
+
{
|
|
18
|
+
provide: file_upload_module_definition_1.MODULE_OPTIONS_TOKEN,
|
|
19
|
+
useValue: options,
|
|
20
|
+
},
|
|
21
|
+
]));
|
|
22
|
+
});
|
|
23
|
+
it("should register asynchronous options", () => {
|
|
24
|
+
const useFactory = () => options;
|
|
25
|
+
const dynamicModule = file_upload_module_1.FileUploadModule.registerAsync({
|
|
26
|
+
useFactory,
|
|
27
|
+
});
|
|
28
|
+
expect(dynamicModule.module).toBe(file_upload_module_1.FileUploadModule);
|
|
29
|
+
expect(dynamicModule.providers).toEqual(expect.arrayContaining([
|
|
30
|
+
{
|
|
31
|
+
inject: [],
|
|
32
|
+
provide: file_upload_module_definition_1.MODULE_OPTIONS_TOKEN,
|
|
33
|
+
useFactory,
|
|
34
|
+
},
|
|
35
|
+
]));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=file-upload.module.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-upload.module.spec.js","sourceRoot":"","sources":["../src/file-upload.module.spec.ts"],"names":[],"mappings":";;AAAA,6DAAwD;AACxD,mFAAuE;AAEvE,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,MAAM,OAAO,GAAG;QACd,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE;YACN,QAAQ,EAAE,iBAAiB;YAC3B,MAAM,EAAE,WAAW;SACpB;KACF,CAAC;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,aAAa,GAAG,qCAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAEzD,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,qCAAgB,CAAC,CAAC;QACpD,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,OAAO,CACrC,MAAM,CAAC,eAAe,CAAC;YACrB;gBACE,OAAO,EAAE,oDAAoB;gBAC7B,QAAQ,EAAE,OAAO;aAClB;SACF,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;QACjC,MAAM,aAAa,GAAG,qCAAgB,CAAC,aAAa,CAAC;YACnD,UAAU;SACX,CAAC,CAAC;QAEH,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,qCAAgB,CAAC,CAAC;QACpD,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,OAAO,CACrC,MAAM,CAAC,eAAe,CAAC;YACrB;gBACE,MAAM,EAAE,EAAE;gBACV,OAAO,EAAE,oDAAoB;gBAC7B,UAAU;aACX;SACF,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { FileUploadField } from "./file-upload-field.object";
|
|
2
|
+
/** GraphQL object type representing a presigned file upload response. */
|
|
2
3
|
export declare class FileUpload {
|
|
4
|
+
/** Form fields required for the presigned POST upload. */
|
|
3
5
|
fields: FileUploadField[];
|
|
6
|
+
/** The presigned upload URL. */
|
|
4
7
|
url: string;
|
|
5
8
|
}
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.FileUpload = void 0;
|
|
13
13
|
const graphql_1 = require("@nest-boot/graphql");
|
|
14
14
|
const file_upload_field_object_1 = require("./file-upload-field.object");
|
|
15
|
+
/** GraphQL object type representing a presigned file upload response. */
|
|
15
16
|
let FileUpload = class FileUpload {
|
|
16
17
|
};
|
|
17
18
|
exports.FileUpload = FileUpload;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.object.js","sourceRoot":"","sources":["../src/file-upload.object.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,gDAAuD;AAEvD,yEAA6D;
|
|
1
|
+
{"version":3,"file":"file-upload.object.js","sourceRoot":"","sources":["../src/file-upload.object.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,gDAAuD;AAEvD,yEAA6D;AAE7D,yEAAyE;AAElE,IAAM,UAAU,GAAhB,MAAM,UAAU;CAQtB,CAAA;AARY,gCAAU;AAGrB;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,CAAC,0CAAe,CAAC,CAAC;;0CACJ;AAI3B;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;;uCACP;qBAPF,UAAU;IADtB,IAAA,oBAAU,GAAE;GACA,UAAU,CAQtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const file_upload_object_1 = require("./file-upload.object");
|
|
4
|
+
const file_upload_field_object_1 = require("./file-upload-field.object");
|
|
5
|
+
const file_upload_input_1 = require("./inputs/file-upload.input");
|
|
6
|
+
describe("file upload GraphQL models", () => {
|
|
7
|
+
it("should store file upload response fields", () => {
|
|
8
|
+
const field = new file_upload_field_object_1.FileUploadField();
|
|
9
|
+
field.name = "key";
|
|
10
|
+
field.value = "tmp/file.png";
|
|
11
|
+
const upload = new file_upload_object_1.FileUpload();
|
|
12
|
+
upload.fields = [field];
|
|
13
|
+
upload.url = "https://s3.local/tmp/file.png";
|
|
14
|
+
expect(upload).toEqual({
|
|
15
|
+
fields: [
|
|
16
|
+
{
|
|
17
|
+
name: "key",
|
|
18
|
+
value: "tmp/file.png",
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
url: "https://s3.local/tmp/file.png",
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it("should store upload input values", () => {
|
|
25
|
+
const input = new file_upload_input_1.FileUploadInput();
|
|
26
|
+
input.fileSize = 123;
|
|
27
|
+
input.mimeType = "image/png";
|
|
28
|
+
input.name = "file.png";
|
|
29
|
+
expect(input).toEqual({
|
|
30
|
+
fileSize: 123,
|
|
31
|
+
mimeType: "image/png",
|
|
32
|
+
name: "file.png",
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=file-upload.object.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-upload.object.spec.js","sourceRoot":"","sources":["../src/file-upload.object.spec.ts"],"names":[],"mappings":";;AAAA,6DAAkD;AAClD,yEAA6D;AAC7D,kEAA6D;AAE7D,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,KAAK,GAAG,IAAI,0CAAe,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;QACnB,KAAK,CAAC,KAAK,GAAG,cAAc,CAAC;QAE7B,MAAM,MAAM,GAAG,IAAI,+BAAU,EAAE,CAAC;QAChC,MAAM,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,GAAG,+BAA+B,CAAC;QAE7C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,MAAM,EAAE;gBACN;oBACE,IAAI,EAAE,KAAK;oBACX,KAAK,EAAE,cAAc;iBACtB;aACF;YACD,GAAG,EAAE,+BAA+B;SACrC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,KAAK,GAAG,IAAI,mCAAe,EAAE,CAAC;QACpC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC;QACrB,KAAK,CAAC,QAAQ,GAAG,WAAW,CAAC;QAC7B,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC;QAExB,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC;YACpB,QAAQ,EAAE,GAAG;YACb,QAAQ,EAAE,WAAW;YACrB,IAAI,EAAE,UAAU;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const testing_1 = require("@nestjs/testing");
|
|
4
|
+
const file_upload_resolver_1 = require("./file-upload.resolver");
|
|
5
|
+
const file_upload_service_1 = require("./file-upload.service");
|
|
6
|
+
describe("FileUploadResolver", () => {
|
|
7
|
+
it("should delegate file upload creation to the service", async () => {
|
|
8
|
+
const result = [
|
|
9
|
+
{
|
|
10
|
+
fields: [
|
|
11
|
+
{
|
|
12
|
+
name: "key",
|
|
13
|
+
value: "tmp/file.png",
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
url: "https://s3.local/tmp/file.png",
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
const create = jest.fn().mockResolvedValue(result);
|
|
20
|
+
const resolver = await createResolver(create);
|
|
21
|
+
const input = [
|
|
22
|
+
{
|
|
23
|
+
fileSize: 123,
|
|
24
|
+
mimeType: "image/png",
|
|
25
|
+
name: "file.png",
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
await expect(resolver.createFileUploads(input)).resolves.toBe(result);
|
|
29
|
+
expect(create).toHaveBeenCalledWith(input);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
async function createResolver(create) {
|
|
33
|
+
const moduleRef = await testing_1.Test.createTestingModule({
|
|
34
|
+
providers: [
|
|
35
|
+
file_upload_resolver_1.FileUploadResolver,
|
|
36
|
+
{
|
|
37
|
+
provide: file_upload_service_1.FileUploadService,
|
|
38
|
+
useValue: {
|
|
39
|
+
create,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
}).compile();
|
|
44
|
+
return moduleRef.get(file_upload_resolver_1.FileUploadResolver);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=file-upload.resolver.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-upload.resolver.spec.js","sourceRoot":"","sources":["../src/file-upload.resolver.spec.ts"],"names":[],"mappings":";;AAAA,6CAAuC;AAEvC,iEAA4D;AAC5D,+DAA0D;AAE1D,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,MAAM,GAAG;YACb;gBACE,MAAM,EAAE;oBACN;wBACE,IAAI,EAAE,KAAK;wBACX,KAAK,EAAE,cAAc;qBACtB;iBACF;gBACD,GAAG,EAAE,+BAA+B;aACrC;SACF,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG;YACZ;gBACE,QAAQ,EAAE,GAAG;gBACb,QAAQ,EAAE,WAAW;gBACrB,IAAI,EAAE,UAAU;aACjB;SACF,CAAC;QAEF,MAAM,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtE,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,cAAc,CAAC,MAAiB;IAC7C,MAAM,SAAS,GAAG,MAAM,cAAI,CAAC,mBAAmB,CAAC;QAC/C,SAAS,EAAE;YACT,yCAAkB;YAClB;gBACE,OAAO,EAAE,uCAAiB;gBAC1B,QAAQ,EAAE;oBACR,MAAM;iBACP;aACF;SACF;KACF,CAAC,CAAC,OAAO,EAAE,CAAC;IAEb,OAAO,SAAS,CAAC,GAAG,CAAC,yCAAkB,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -2,16 +2,44 @@ import { Readable } from "stream";
|
|
|
2
2
|
import { FileUpload } from "./file-upload.object";
|
|
3
3
|
import { FileUploadModuleOptions } from "./file-upload-options.interface";
|
|
4
4
|
import { FileUploadInput } from "./inputs/file-upload.input";
|
|
5
|
+
/**
|
|
6
|
+
* Service for handling file uploads to S3-compatible storage.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* Supports presigned POST uploads, direct uploads, and
|
|
10
|
+
* moving temporary files to permanent storage paths.
|
|
11
|
+
*/
|
|
5
12
|
export declare class FileUploadService {
|
|
6
13
|
private readonly options;
|
|
7
|
-
private readonly s3Client;
|
|
14
|
+
/** S3 client instance. @internal */ private readonly s3Client;
|
|
15
|
+
/** Creates a new FileUploadService instance.
|
|
16
|
+
* @param options - File upload module configuration options
|
|
17
|
+
*/
|
|
8
18
|
constructor(options: FileUploadModuleOptions);
|
|
19
|
+
/**
|
|
20
|
+
* Creates presigned POST URLs for uploading files.
|
|
21
|
+
* @param input - Array of file upload inputs with name, size, and MIME type
|
|
22
|
+
* @returns An array of presigned POST data (URL and form fields)
|
|
23
|
+
*/
|
|
9
24
|
create(input: FileUploadInput[]): Promise<FileUpload[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Moves a temporary file to permanent storage.
|
|
27
|
+
* @param tmpUrl - The URL of the temporary file
|
|
28
|
+
* @returns The permanent URL of the file
|
|
29
|
+
*/
|
|
10
30
|
persist(tmpUrl: string): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Uploads file data directly to S3.
|
|
33
|
+
* @param data - File content as a Readable stream, Buffer, or string
|
|
34
|
+
* @param metadata - Upload metadata including Content-Type and optional extension
|
|
35
|
+
* @param persist - Whether to move the file to permanent storage immediately
|
|
36
|
+
* @returns The URL of the uploaded file
|
|
37
|
+
*/
|
|
11
38
|
upload(data: Readable | Buffer | string, metadata: {
|
|
12
39
|
"Content-Type": string;
|
|
13
40
|
extension?: string;
|
|
14
41
|
[key: string]: any;
|
|
15
42
|
}, persist?: boolean): Promise<string>;
|
|
43
|
+
/** Constructs the full URL for a file stored in S3. @internal */
|
|
16
44
|
private getFileUrl;
|
|
17
45
|
}
|
|
@@ -25,7 +25,17 @@ const micromatch_1 = __importDefault(require("micromatch"));
|
|
|
25
25
|
const mime_types_1 = __importDefault(require("mime-types"));
|
|
26
26
|
const path_1 = require("path");
|
|
27
27
|
const file_upload_module_definition_1 = require("./file-upload.module-definition");
|
|
28
|
+
/**
|
|
29
|
+
* Service for handling file uploads to S3-compatible storage.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* Supports presigned POST uploads, direct uploads, and
|
|
33
|
+
* moving temporary files to permanent storage paths.
|
|
34
|
+
*/
|
|
28
35
|
let FileUploadService = class FileUploadService {
|
|
36
|
+
/** Creates a new FileUploadService instance.
|
|
37
|
+
* @param options - File upload module configuration options
|
|
38
|
+
*/
|
|
29
39
|
constructor(options) {
|
|
30
40
|
this.options = options;
|
|
31
41
|
this.s3Client =
|
|
@@ -33,13 +43,17 @@ let FileUploadService = class FileUploadService {
|
|
|
33
43
|
? options.client
|
|
34
44
|
: new client_s3_1.S3Client(options.client);
|
|
35
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates presigned POST URLs for uploading files.
|
|
48
|
+
* @param input - Array of file upload inputs with name, size, and MIME type
|
|
49
|
+
* @returns An array of presigned POST data (URL and form fields)
|
|
50
|
+
*/
|
|
36
51
|
async create(input) {
|
|
37
52
|
const results = input.map(async (item) => {
|
|
38
53
|
const key = `tmp/${(0, crypto_1.randomUUID)()}${(0, path_1.extname)(item.name)}`;
|
|
39
54
|
const limit = this.options.limits?.find((v) => item.fileSize <= v.fileSize &&
|
|
40
55
|
micromatch_1.default.isMatch(item.mimeType, v.mimeTypes));
|
|
41
56
|
if (this.options.limits && !limit) {
|
|
42
|
-
// 上传的文件不符合要求
|
|
43
57
|
throw new common_1.BadRequestException("The uploaded file does not meet the requirements");
|
|
44
58
|
}
|
|
45
59
|
const conditions = [
|
|
@@ -64,7 +78,8 @@ let FileUploadService = class FileUploadService {
|
|
|
64
78
|
? (() => {
|
|
65
79
|
const originalUrl = new URL(presignedPost.url);
|
|
66
80
|
const customUrl = new URL(this.options.url);
|
|
67
|
-
|
|
81
|
+
const customPathname = customUrl.pathname.replace(/\/$/, "");
|
|
82
|
+
return `${customUrl.origin}${customPathname}${originalUrl.pathname}${originalUrl.search}`;
|
|
68
83
|
})()
|
|
69
84
|
: presignedPost.url,
|
|
70
85
|
fields: [
|
|
@@ -80,7 +95,11 @@ let FileUploadService = class FileUploadService {
|
|
|
80
95
|
});
|
|
81
96
|
return await Promise.all(results);
|
|
82
97
|
}
|
|
83
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Moves a temporary file to permanent storage.
|
|
100
|
+
* @param tmpUrl - The URL of the temporary file
|
|
101
|
+
* @returns The permanent URL of the file
|
|
102
|
+
*/
|
|
84
103
|
async persist(tmpUrl) {
|
|
85
104
|
const tmpKey = tmpUrl.split("/tmp/")[1];
|
|
86
105
|
const originKey = `tmp/${tmpKey}`;
|
|
@@ -93,6 +112,13 @@ let FileUploadService = class FileUploadService {
|
|
|
93
112
|
await this.s3Client.send(copyCommand);
|
|
94
113
|
return await this.getFileUrl(targetKey);
|
|
95
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Uploads file data directly to S3.
|
|
117
|
+
* @param data - File content as a Readable stream, Buffer, or string
|
|
118
|
+
* @param metadata - Upload metadata including Content-Type and optional extension
|
|
119
|
+
* @param persist - Whether to move the file to permanent storage immediately
|
|
120
|
+
* @returns The URL of the uploaded file
|
|
121
|
+
*/
|
|
96
122
|
async upload(data, metadata, persist = false) {
|
|
97
123
|
const extension = metadata.extension ??
|
|
98
124
|
(mime_types_1.default.extension(metadata["Content-Type"]) || "bin");
|
|
@@ -108,29 +134,24 @@ let FileUploadService = class FileUploadService {
|
|
|
108
134
|
if (!persist) {
|
|
109
135
|
return tmpUrl;
|
|
110
136
|
}
|
|
111
|
-
// 持久化
|
|
112
137
|
return await this.persist(tmpUrl);
|
|
113
138
|
}
|
|
139
|
+
/** Constructs the full URL for a file stored in S3. @internal */
|
|
114
140
|
async getFileUrl(filePath) {
|
|
115
|
-
// 获取 S3Client 的配置
|
|
116
141
|
const config = this.s3Client.config;
|
|
117
142
|
const forcePathStyle = config.forcePathStyle;
|
|
118
143
|
const endpoint = await config.endpoint?.();
|
|
119
144
|
if (!endpoint) {
|
|
120
145
|
throw new Error("Endpoint is not configured");
|
|
121
146
|
}
|
|
122
|
-
// 构造基础 URL
|
|
123
147
|
const protocol = endpoint.protocol;
|
|
124
148
|
const hostname = endpoint.hostname;
|
|
125
149
|
const port = endpoint.port ? `:${String(endpoint.port)}` : "";
|
|
126
150
|
const baseUrl = `${protocol}//${hostname}${port}`;
|
|
127
|
-
// 根据配置生成正确的 URL
|
|
128
151
|
if (forcePathStyle) {
|
|
129
|
-
// Path-style URL: https://endpoint/bucket/key
|
|
130
152
|
return `${baseUrl}/${this.options.bucket}/${filePath}`;
|
|
131
153
|
}
|
|
132
154
|
else {
|
|
133
|
-
// Virtual-hosted-style URL: https://bucket.endpoint/key
|
|
134
155
|
return `${protocol}//${this.options.bucket}.${hostname}${port}/${filePath}`;
|
|
135
156
|
}
|
|
136
157
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.service.js","sourceRoot":"","sources":["../src/file-upload.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,kDAI4B;AAC5B,kEAAiE;AACjE,2CAAyE;AACzE,mCAAoC;AACpC,kDAA0B;AAC1B,4DAAoC;AACpC,4DAAmC;AACnC,+BAA+B;AAG/B,mFAAuE;
|
|
1
|
+
{"version":3,"file":"file-upload.service.js","sourceRoot":"","sources":["../src/file-upload.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|