@russ-b/nestjs-common-tools 1.14.1 → 1.14.3
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/README.md +58 -2
- package/dist/modules/s3/index.d.ts +1 -0
- package/dist/modules/s3/index.js +1 -0
- package/dist/modules/s3/index.js.map +1 -1
- package/dist/modules/s3/s3.interface.d.ts +16 -1
- package/dist/modules/s3/s3.module.js +2 -0
- package/dist/modules/s3/s3.module.js.map +1 -1
- package/dist/modules/s3/s3.service.d.ts +5 -1
- package/dist/modules/s3/s3.service.js +58 -2
- package/dist/modules/s3/s3.service.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -107,7 +107,7 @@ import { S3Module } from '@russ-b/nestjs-common-tools/modules';
|
|
|
107
107
|
inject: [ConfigService],
|
|
108
108
|
useFactory: (config: ConfigService) => ({
|
|
109
109
|
region: config.get<string>('AWS_REGION') ?? 'eu-central-1',
|
|
110
|
-
|
|
110
|
+
defaultBucket: config.get<string>('S3_BUCKET'),
|
|
111
111
|
endpoint: config.get<string>('S3_ENDPOINT'),
|
|
112
112
|
logger: config.get<string>('S3_DEBUG') === 'true',
|
|
113
113
|
}),
|
|
@@ -140,6 +140,8 @@ The AWS SDK reads values from process environment, not directly from a `.env` fi
|
|
|
140
140
|
|
|
141
141
|
`forcePathStyle` defaults to `true` in this module. That is usually convenient for MinIO and LocalStack. If you want standard AWS virtual-hosted URLs, set `forcePathStyle: false`.
|
|
142
142
|
|
|
143
|
+
`defaultBucket` is the module-level fallback bucket. You can still override it per method call with `options.bucket`.
|
|
144
|
+
|
|
143
145
|
### Optional logging
|
|
144
146
|
|
|
145
147
|
By default, the module stays silent and does not write S3 operation logs.
|
|
@@ -149,7 +151,7 @@ If you want extra visibility while testing connectivity with S3 or MinIO, set `l
|
|
|
149
151
|
```typescript
|
|
150
152
|
S3Module.forRootAsync({
|
|
151
153
|
useFactory: () => ({
|
|
152
|
-
|
|
154
|
+
defaultBucket: 'my-app-bucket',
|
|
153
155
|
endpoint: 'http://localhost:9000',
|
|
154
156
|
forcePathStyle: true,
|
|
155
157
|
logger: true,
|
|
@@ -204,6 +206,17 @@ export class FilesService {
|
|
|
204
206
|
async deleteAvatar(key: string) {
|
|
205
207
|
return this.s3Service.deleteObject(key);
|
|
206
208
|
}
|
|
209
|
+
|
|
210
|
+
async duplicateAvatar(sourceKey: string, destinationKey: string) {
|
|
211
|
+
return this.s3Service.copyObject(sourceKey, destinationKey);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async listAvatars() {
|
|
215
|
+
return this.s3Service.listObjects({
|
|
216
|
+
prefix: 'avatars/',
|
|
217
|
+
maxKeys: 50,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
207
220
|
}
|
|
208
221
|
```
|
|
209
222
|
|
|
@@ -243,10 +256,53 @@ When generating a signed `putObject` URL, make sure the client sends the same he
|
|
|
243
256
|
| `upload(key, body, options)` | Managed upload using `@aws-sdk/lib-storage`, useful for larger or streaming payloads |
|
|
244
257
|
| `getObject(key, options)` | Returns the readable stream together with object metadata |
|
|
245
258
|
| `deleteObject(key, options)` | Deletes an object from the configured bucket |
|
|
259
|
+
| `copyObject(sourceKey, destinationKey, options)` | Copies an object, optionally across buckets |
|
|
260
|
+
| `listObjects(options)` | Lists objects with `prefix`, `maxKeys`, `continuationToken`, and `delimiter` support |
|
|
246
261
|
| `getSignedUrl(key, options)` | Creates a presigned URL for `getObject` or `putObject` |
|
|
247
262
|
|
|
248
263
|
`uploadObject` is still available as a compatibility alias, but `putObject` is the preferred method name going forward.
|
|
249
264
|
|
|
265
|
+
### Inject the raw S3 client
|
|
266
|
+
|
|
267
|
+
If you need lower-level S3 commands that are not covered by `S3Service`, you can inject the configured AWS client directly.
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
271
|
+
import {
|
|
272
|
+
DeleteObjectsCommand,
|
|
273
|
+
HeadObjectCommand,
|
|
274
|
+
S3Client,
|
|
275
|
+
} from '@aws-sdk/client-s3';
|
|
276
|
+
import { S3_CLIENT } from '@russ-b/nestjs-common-tools/modules';
|
|
277
|
+
|
|
278
|
+
@Injectable()
|
|
279
|
+
export class CarPhotoService {
|
|
280
|
+
constructor(
|
|
281
|
+
@Inject(S3_CLIENT) private readonly s3Client: S3Client,
|
|
282
|
+
) {}
|
|
283
|
+
|
|
284
|
+
async getPhotoMetadata(key: string) {
|
|
285
|
+
return this.s3Client.send(
|
|
286
|
+
new HeadObjectCommand({
|
|
287
|
+
Bucket: 'car-photos',
|
|
288
|
+
Key: key,
|
|
289
|
+
}),
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async deleteMany(keys: string[]) {
|
|
294
|
+
return this.s3Client.send(
|
|
295
|
+
new DeleteObjectsCommand({
|
|
296
|
+
Bucket: 'car-photos',
|
|
297
|
+
Delete: {
|
|
298
|
+
Objects: keys.map((key) => ({ Key: key })),
|
|
299
|
+
},
|
|
300
|
+
}),
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
250
306
|
## Entity Validator
|
|
251
307
|
|
|
252
308
|
A custom validator for NestJS that validates if an entity exists in the database using TypeORM.
|
package/dist/modules/s3/index.js
CHANGED
|
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./s3.module"), exports);
|
|
18
18
|
__exportStar(require("./s3.service"), exports);
|
|
19
19
|
__exportStar(require("./s3.interface"), exports);
|
|
20
|
+
__exportStar(require("./s3.constants"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/s3/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,+CAA6B;AAC7B,iDAA+B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/s3/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,+CAA6B;AAC7B,iDAA+B;AAC/B,iDAA+B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LoggerService, ModuleMetadata } from '@nestjs/common';
|
|
2
|
-
import type { DeleteObjectCommandOutput, GetObjectCommandOutput, ObjectCannedACL, PutObjectCommandInput, PutObjectCommandOutput } from '@aws-sdk/client-s3';
|
|
2
|
+
import type { CopyObjectCommandInput, CopyObjectCommandOutput, DeleteObjectCommandOutput, GetObjectCommandOutput, ListObjectsV2CommandInput, ListObjectsV2CommandOutput, ObjectCannedACL, PutObjectCommandInput, PutObjectCommandOutput, S3ClientConfig } from '@aws-sdk/client-s3';
|
|
3
3
|
import type { CompleteMultipartUploadCommandOutput } from '@aws-sdk/client-s3';
|
|
4
4
|
import type { Readable } from 'stream';
|
|
5
5
|
export type S3ModuleLogger = Pick<LoggerService, 'log' | 'error'>;
|
|
@@ -7,6 +7,9 @@ export interface S3ModuleOptions {
|
|
|
7
7
|
region?: string;
|
|
8
8
|
endpoint?: string;
|
|
9
9
|
forcePathStyle?: boolean;
|
|
10
|
+
requestChecksumCalculation?: S3ClientConfig['requestChecksumCalculation'];
|
|
11
|
+
responseChecksumValidation?: S3ClientConfig['responseChecksumValidation'];
|
|
12
|
+
defaultBucket?: string;
|
|
10
13
|
bucket?: string;
|
|
11
14
|
logger?: boolean | S3ModuleLogger;
|
|
12
15
|
}
|
|
@@ -28,6 +31,16 @@ export interface S3SignedUrlOptions extends S3UploadOptions {
|
|
|
28
31
|
expiresIn?: number;
|
|
29
32
|
operation?: 'getObject' | 'putObject';
|
|
30
33
|
}
|
|
34
|
+
export interface S3CopyObjectOptions extends S3UploadOptions {
|
|
35
|
+
metadataDirective?: CopyObjectCommandInput['MetadataDirective'];
|
|
36
|
+
sourceBucket?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface S3ListObjectsOptions extends S3ObjectOptions {
|
|
39
|
+
continuationToken?: ListObjectsV2CommandInput['ContinuationToken'];
|
|
40
|
+
delimiter?: ListObjectsV2CommandInput['Delimiter'];
|
|
41
|
+
maxKeys?: ListObjectsV2CommandInput['MaxKeys'];
|
|
42
|
+
prefix?: ListObjectsV2CommandInput['Prefix'];
|
|
43
|
+
}
|
|
31
44
|
export interface S3GetObjectResult {
|
|
32
45
|
body: Readable;
|
|
33
46
|
cacheControl?: GetObjectCommandOutput['CacheControl'];
|
|
@@ -40,5 +53,7 @@ export interface S3GetObjectResult {
|
|
|
40
53
|
export type S3UploadResult = CompleteMultipartUploadCommandOutput;
|
|
41
54
|
export type S3PutObjectResult = PutObjectCommandOutput;
|
|
42
55
|
export type S3DeleteObjectResult = DeleteObjectCommandOutput;
|
|
56
|
+
export type S3CopyObjectResult = CopyObjectCommandOutput;
|
|
57
|
+
export type S3ListObjectsResult = ListObjectsV2CommandOutput;
|
|
43
58
|
export type S3Body = NonNullable<PutObjectCommandInput['Body']>;
|
|
44
59
|
export type UploadParams = S3UploadOptions;
|
|
@@ -32,6 +32,8 @@ let S3Module = S3Module_1 = class S3Module {
|
|
|
32
32
|
region: opts.region || 'us-east-1',
|
|
33
33
|
endpoint: opts.endpoint,
|
|
34
34
|
forcePathStyle: opts.forcePathStyle ?? true,
|
|
35
|
+
requestChecksumCalculation: opts.requestChecksumCalculation,
|
|
36
|
+
responseChecksumValidation: opts.responseChecksumValidation,
|
|
35
37
|
};
|
|
36
38
|
return new client_s3_1.S3Client(clientConfig);
|
|
37
39
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.module.js","sourceRoot":"","sources":["../../../src/modules/s3/s3.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,kDAA8D;AAE9D,iDAA8D;AAC9D,6CAAyC;AAGlC,IAAM,QAAQ,gBAAd,MAAM,QAAQ;IACnB,MAAM,CAAC,YAAY,CAAC,OAA6B;QAC/C,OAAO;YACL,MAAM,EAAE,UAAQ;YAChB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,gCAAiB;oBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;oBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;iBAC7B;gBACD;oBACE,OAAO,EAAE,wBAAS;oBAClB,MAAM,EAAE,CAAC,gCAAiB,CAAC;oBAC3B,UAAU,EAAE,CAAC,IAAqB,EAAE,EAAE;wBACpC,MAAM,YAAY,GAAmB;4BACnC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,WAAW;4BAClC,QAAQ,EAAE,IAAI,CAAC,QAAQ;4BACvB,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"s3.module.js","sourceRoot":"","sources":["../../../src/modules/s3/s3.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,kDAA8D;AAE9D,iDAA8D;AAC9D,6CAAyC;AAGlC,IAAM,QAAQ,gBAAd,MAAM,QAAQ;IACnB,MAAM,CAAC,YAAY,CAAC,OAA6B;QAC/C,OAAO;YACL,MAAM,EAAE,UAAQ;YAChB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,gCAAiB;oBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;oBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;iBAC7B;gBACD;oBACE,OAAO,EAAE,wBAAS;oBAClB,MAAM,EAAE,CAAC,gCAAiB,CAAC;oBAC3B,UAAU,EAAE,CAAC,IAAqB,EAAE,EAAE;wBACpC,MAAM,YAAY,GAAmB;4BACnC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,WAAW;4BAClC,QAAQ,EAAE,IAAI,CAAC,QAAQ;4BACvB,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI;4BAC3C,0BAA0B,EAAE,IAAI,CAAC,0BAA0B;4BAC3D,0BAA0B,EAAE,IAAI,CAAC,0BAA0B;yBAC5D,CAAC;wBAEF,OAAO,IAAI,oBAAQ,CAAC,YAAY,CAAC,CAAC;oBACpC,CAAC;iBACF;gBACD,sBAAS;aACV;YACD,OAAO,EAAE,CAAC,sBAAS,CAAC;SACrB,CAAC;IACJ,CAAC;CACF,CAAA;AAhCY,4BAAQ;mBAAR,QAAQ;IADpB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,QAAQ,CAgCpB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { S3Client } from '@aws-sdk/client-s3';
|
|
2
|
-
import { S3Body, S3DeleteObjectResult, S3GetObjectResult, S3ModuleOptions, S3ObjectOptions, S3PutObjectResult, S3SignedUrlOptions, S3UploadOptions, S3UploadResult } from './s3.interface';
|
|
2
|
+
import { S3Body, S3CopyObjectOptions, S3CopyObjectResult, S3DeleteObjectResult, S3GetObjectResult, S3ListObjectsOptions, S3ListObjectsResult, S3ModuleOptions, S3ObjectOptions, S3PutObjectResult, S3SignedUrlOptions, S3UploadOptions, S3UploadResult } from './s3.interface';
|
|
3
3
|
export declare class S3Service {
|
|
4
4
|
private readonly options;
|
|
5
5
|
private readonly s3Client;
|
|
@@ -9,9 +9,13 @@ export declare class S3Service {
|
|
|
9
9
|
putObject(key: string, body: S3Body, options?: S3UploadOptions): Promise<S3PutObjectResult>;
|
|
10
10
|
uploadObject(key: string, body: S3Body, options?: S3UploadOptions): Promise<S3PutObjectResult>;
|
|
11
11
|
deleteObject(key: string, options?: S3ObjectOptions): Promise<S3DeleteObjectResult>;
|
|
12
|
+
copyObject(sourceKey: string, destinationKey: string, options?: S3CopyObjectOptions): Promise<S3CopyObjectResult>;
|
|
12
13
|
getObject(key: string, options?: S3ObjectOptions): Promise<S3GetObjectResult>;
|
|
14
|
+
listObjects(options?: S3ListObjectsOptions): Promise<S3ListObjectsResult>;
|
|
13
15
|
getSignedUrl(key: string, options?: S3SignedUrlOptions): Promise<string>;
|
|
16
|
+
private createCopyObjectParams;
|
|
14
17
|
private createPutObjectParams;
|
|
18
|
+
private buildCopySource;
|
|
15
19
|
private resolveBucket;
|
|
16
20
|
private log;
|
|
17
21
|
private logError;
|
|
@@ -66,6 +66,18 @@ let S3Service = S3Service_1 = class S3Service {
|
|
|
66
66
|
throw error;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
async copyObject(sourceKey, destinationKey, options) {
|
|
70
|
+
const command = new client_s3_1.CopyObjectCommand(this.createCopyObjectParams(sourceKey, destinationKey, options));
|
|
71
|
+
try {
|
|
72
|
+
const response = await this.s3Client.send(command);
|
|
73
|
+
this.log(`Copied object: ${sourceKey} -> ${destinationKey}`);
|
|
74
|
+
return response;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.logError(`Failed to copy object: ${sourceKey} -> ${destinationKey}`, error);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
69
81
|
async getObject(key, options) {
|
|
70
82
|
const command = new client_s3_1.GetObjectCommand({
|
|
71
83
|
Bucket: this.resolveBucket(options?.bucket),
|
|
@@ -95,6 +107,26 @@ let S3Service = S3Service_1 = class S3Service {
|
|
|
95
107
|
throw error;
|
|
96
108
|
}
|
|
97
109
|
}
|
|
110
|
+
async listObjects(options) {
|
|
111
|
+
const command = new client_s3_1.ListObjectsV2Command({
|
|
112
|
+
Bucket: this.resolveBucket(options?.bucket),
|
|
113
|
+
...(options?.continuationToken
|
|
114
|
+
? { ContinuationToken: options.continuationToken }
|
|
115
|
+
: {}),
|
|
116
|
+
...(options?.delimiter ? { Delimiter: options.delimiter } : {}),
|
|
117
|
+
...(options?.maxKeys ? { MaxKeys: options.maxKeys } : {}),
|
|
118
|
+
...(options?.prefix ? { Prefix: options.prefix } : {}),
|
|
119
|
+
});
|
|
120
|
+
try {
|
|
121
|
+
const response = await this.s3Client.send(command);
|
|
122
|
+
this.log(`Listed objects for bucket: ${command.input.Bucket}`);
|
|
123
|
+
return response;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
this.logError(`Failed to list objects for bucket: ${command.input.Bucket}`, error);
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
98
130
|
async getSignedUrl(key, options) {
|
|
99
131
|
const expiresIn = options?.expiresIn ?? 900;
|
|
100
132
|
const operation = options?.operation ?? 'getObject';
|
|
@@ -106,6 +138,24 @@ let S3Service = S3Service_1 = class S3Service {
|
|
|
106
138
|
});
|
|
107
139
|
return (0, s3_request_presigner_1.getSignedUrl)(this.s3Client, command, { expiresIn });
|
|
108
140
|
}
|
|
141
|
+
createCopyObjectParams(sourceKey, destinationKey, options) {
|
|
142
|
+
const destinationBucket = this.resolveBucket(options?.bucket);
|
|
143
|
+
const sourceBucket = this.resolveBucket(options?.sourceBucket ?? options?.bucket);
|
|
144
|
+
const shouldReplaceMetadata = !!(options?.cacheControl ||
|
|
145
|
+
options?.contentType ||
|
|
146
|
+
options?.metadata);
|
|
147
|
+
const metadataDirective = options?.metadataDirective ?? (shouldReplaceMetadata ? 'REPLACE' : undefined);
|
|
148
|
+
return {
|
|
149
|
+
Bucket: destinationBucket,
|
|
150
|
+
CopySource: this.buildCopySource(sourceBucket, sourceKey),
|
|
151
|
+
Key: destinationKey,
|
|
152
|
+
...(options?.acl ? { ACL: options.acl } : {}),
|
|
153
|
+
...(options?.cacheControl ? { CacheControl: options.cacheControl } : {}),
|
|
154
|
+
...(options?.contentType ? { ContentType: options.contentType } : {}),
|
|
155
|
+
...(metadataDirective ? { MetadataDirective: metadataDirective } : {}),
|
|
156
|
+
...(options?.metadata ? { Metadata: options.metadata } : {}),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
109
159
|
createPutObjectParams(key, body, options, useDefaultContentType = false) {
|
|
110
160
|
const contentType = options?.contentType ??
|
|
111
161
|
(useDefaultContentType ? 'application/octet-stream' : undefined);
|
|
@@ -119,10 +169,16 @@ let S3Service = S3Service_1 = class S3Service {
|
|
|
119
169
|
...(options?.metadata ? { Metadata: options.metadata } : {}),
|
|
120
170
|
};
|
|
121
171
|
}
|
|
172
|
+
buildCopySource(bucket, key) {
|
|
173
|
+
return `${encodeURIComponent(bucket)}/${key
|
|
174
|
+
.split('/')
|
|
175
|
+
.map((part) => encodeURIComponent(part))
|
|
176
|
+
.join('/')}`;
|
|
177
|
+
}
|
|
122
178
|
resolveBucket(bucket) {
|
|
123
|
-
const resolvedBucket = bucket ?? this.options.bucket;
|
|
179
|
+
const resolvedBucket = bucket ?? this.options.defaultBucket ?? this.options.bucket;
|
|
124
180
|
if (!resolvedBucket) {
|
|
125
|
-
throw new Error('S3 bucket is not configured. Pass a bucket to the method call or set S3ModuleOptions.
|
|
181
|
+
throw new Error('S3 bucket is not configured. Pass a bucket to the method call or set S3ModuleOptions.defaultBucket.');
|
|
126
182
|
}
|
|
127
183
|
return resolvedBucket;
|
|
128
184
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.service.js","sourceRoot":"","sources":["../../../src/modules/s3/s3.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAA4D;AAC5D,
|
|
1
|
+
{"version":3,"file":"s3.service.js","sourceRoot":"","sources":["../../../src/modules/s3/s3.service.ts"],"names":[],"mappings":"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"}
|