@russ-b/nestjs-common-tools 1.13.1 → 1.14.1
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 +235 -2
- package/dist/class-transformer/index.d.ts +2 -0
- package/dist/class-transformer/index.js +19 -0
- package/dist/class-transformer/index.js.map +1 -0
- package/dist/class-transformer/to-boolean-from-string.decorator.d.ts +3 -0
- package/dist/class-transformer/to-boolean-from-string.decorator.js +29 -0
- package/dist/class-transformer/to-boolean-from-string.decorator.js.map +1 -0
- package/dist/class-transformer/to-string-array.decorator.d.ts +1 -0
- package/dist/class-transformer/to-string-array.decorator.js +23 -0
- package/dist/class-transformer/to-string-array.decorator.js.map +1 -0
- 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 +31 -6
- package/dist/modules/s3/s3.module.js +5 -8
- package/dist/modules/s3/s3.module.js.map +1 -1
- package/dist/modules/s3/s3.service.d.ts +13 -10
- package/dist/modules/s3/s3.service.js +91 -35
- package/dist/modules/s3/s3.service.js.map +1 -1
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# nestjs-common-tools
|
|
2
|
-
NestJS Common Tools
|
|
3
2
|
|
|
4
3
|
A small toolbox for NestJS with helpers that often come up in day-to-day development.
|
|
5
4
|
|
|
@@ -15,6 +14,239 @@ npm install @russ-b/nestjs-common-tools
|
|
|
15
14
|
|
|
16
15
|
Depending on which features you use, make sure the relevant peer dependencies are also installed in your project.
|
|
17
16
|
|
|
17
|
+
## Public entrypoints
|
|
18
|
+
|
|
19
|
+
This package uses subpath exports for most features.
|
|
20
|
+
|
|
21
|
+
| Import path | What it contains |
|
|
22
|
+
|-------------|------------------|
|
|
23
|
+
| `@russ-b/nestjs-common-tools` | root exports such as `services` |
|
|
24
|
+
| `@russ-b/nestjs-common-tools/class-transformer` | reusable `class-transformer` decorators and helpers |
|
|
25
|
+
| `@russ-b/nestjs-common-tools/modules` | NestJS modules such as `S3Module` |
|
|
26
|
+
| `@russ-b/nestjs-common-tools/validators` | validation decorators and constraints |
|
|
27
|
+
| `@russ-b/nestjs-common-tools/typeorm` | TypeORM filters, helpers, transformers, and types |
|
|
28
|
+
| `@russ-b/nestjs-common-tools/logger` | logger builder and logger-related interfaces/types |
|
|
29
|
+
| `@russ-b/nestjs-common-tools/common/util` | generic utility helpers |
|
|
30
|
+
| `@russ-b/nestjs-common-tools/common/pagination` | pagination DTOs and helpers |
|
|
31
|
+
| `@russ-b/nestjs-common-tools/common/filters` | shared filter exports |
|
|
32
|
+
|
|
33
|
+
## Class Transformer Helpers
|
|
34
|
+
|
|
35
|
+
This package also exposes small reusable decorators for `class-transformer`.
|
|
36
|
+
|
|
37
|
+
### `ToStringArray`
|
|
38
|
+
|
|
39
|
+
`ToStringArray()` is useful for DTO query fields that may arrive as a comma-separated string such as `"cars, bikes, boats"` or as an array.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { ToStringArray } from '@russ-b/nestjs-common-tools/class-transformer';
|
|
43
|
+
|
|
44
|
+
export class SearchDto {
|
|
45
|
+
@ToStringArray()
|
|
46
|
+
tags?: string[];
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
It will:
|
|
51
|
+
|
|
52
|
+
- split string values by comma
|
|
53
|
+
- trim extra spaces around items
|
|
54
|
+
- remove empty values
|
|
55
|
+
- normalize a string like `'cars, bikes, boats'` into `['cars', 'bikes', 'boats']`
|
|
56
|
+
|
|
57
|
+
### `ToBooleanFromString`
|
|
58
|
+
|
|
59
|
+
`ToBooleanFromString()` is useful for DTO fields that may arrive as `'true'` or `'false'` strings and should become real booleans.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { ToBooleanFromString } from '@russ-b/nestjs-common-tools/class-transformer';
|
|
63
|
+
|
|
64
|
+
export class SearchDto {
|
|
65
|
+
@ToBooleanFromString()
|
|
66
|
+
archived?: boolean;
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
It will:
|
|
71
|
+
|
|
72
|
+
- convert `'true'` to `true`
|
|
73
|
+
- convert `'false'` to `false`
|
|
74
|
+
- trim extra spaces and ignore case
|
|
75
|
+
- leave unsupported values unchanged
|
|
76
|
+
|
|
77
|
+
## S3 Module
|
|
78
|
+
|
|
79
|
+
`S3Module` is a small NestJS wrapper around the AWS SDK v3 S3 client. It gives you a reusable `S3Service` with a simple Nest-friendly setup for uploads, downloads, deletes, and signed URLs.
|
|
80
|
+
|
|
81
|
+
### Install S3 peer dependencies
|
|
82
|
+
|
|
83
|
+
If you want to use the S3 module, install the required AWS peer dependencies in your application:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Register the module
|
|
90
|
+
|
|
91
|
+
Import the module from `@russ-b/nestjs-common-tools/modules` and configure it with `forRootAsync`.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
// app.module.ts
|
|
95
|
+
import { Module } from '@nestjs/common';
|
|
96
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
97
|
+
import { S3Module } from '@russ-b/nestjs-common-tools/modules';
|
|
98
|
+
|
|
99
|
+
@Module({
|
|
100
|
+
imports: [
|
|
101
|
+
ConfigModule.forRoot({
|
|
102
|
+
isGlobal: true,
|
|
103
|
+
}),
|
|
104
|
+
S3Module.forRootAsync({
|
|
105
|
+
global: true,
|
|
106
|
+
imports: [ConfigModule],
|
|
107
|
+
inject: [ConfigService],
|
|
108
|
+
useFactory: (config: ConfigService) => ({
|
|
109
|
+
region: config.get<string>('AWS_REGION') ?? 'eu-central-1',
|
|
110
|
+
bucket: config.get<string>('S3_BUCKET'),
|
|
111
|
+
endpoint: config.get<string>('S3_ENDPOINT'),
|
|
112
|
+
logger: config.get<string>('S3_DEBUG') === 'true',
|
|
113
|
+
}),
|
|
114
|
+
}),
|
|
115
|
+
],
|
|
116
|
+
})
|
|
117
|
+
export class AppModule {}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Credentials
|
|
121
|
+
|
|
122
|
+
The module does not accept `accessKeyId` or `secretAccessKey` directly. It relies on the AWS SDK default credential chain instead, which means credentials can come from:
|
|
123
|
+
|
|
124
|
+
- `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
|
|
125
|
+
- local AWS profiles and shared config
|
|
126
|
+
- IAM roles in AWS environments
|
|
127
|
+
|
|
128
|
+
Example environment variables:
|
|
129
|
+
|
|
130
|
+
```env
|
|
131
|
+
AWS_REGION=eu-central-1
|
|
132
|
+
AWS_ACCESS_KEY_ID=your-access-key
|
|
133
|
+
AWS_SECRET_ACCESS_KEY=your-secret-key
|
|
134
|
+
S3_BUCKET=my-app-bucket
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The AWS SDK reads values from process environment, not directly from a `.env` file, so make sure your application loads those variables before creating the client.
|
|
138
|
+
|
|
139
|
+
`endpoint` is optional and is mostly useful for S3-compatible providers such as MinIO or LocalStack.
|
|
140
|
+
|
|
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
|
+
|
|
143
|
+
### Optional logging
|
|
144
|
+
|
|
145
|
+
By default, the module stays silent and does not write S3 operation logs.
|
|
146
|
+
|
|
147
|
+
If you want extra visibility while testing connectivity with S3 or MinIO, set `logger: true` in the module options. That enables the standard Nest logger for this service.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
S3Module.forRootAsync({
|
|
151
|
+
useFactory: () => ({
|
|
152
|
+
bucket: 'my-app-bucket',
|
|
153
|
+
endpoint: 'http://localhost:9000',
|
|
154
|
+
forcePathStyle: true,
|
|
155
|
+
logger: true,
|
|
156
|
+
}),
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
You can also pass your own Nest-compatible logger object if you want to redirect those logs elsewhere.
|
|
161
|
+
|
|
162
|
+
### Inject and use the service
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// files.service.ts
|
|
166
|
+
import { Injectable } from '@nestjs/common';
|
|
167
|
+
import { Readable } from 'stream';
|
|
168
|
+
import { S3Service } from '@russ-b/nestjs-common-tools/modules';
|
|
169
|
+
|
|
170
|
+
@Injectable()
|
|
171
|
+
export class FilesService {
|
|
172
|
+
constructor(private readonly s3Service: S3Service) {}
|
|
173
|
+
|
|
174
|
+
async putAvatar(key: string, file: Buffer) {
|
|
175
|
+
return this.s3Service.putObject(key, file, {
|
|
176
|
+
contentType: 'image/png',
|
|
177
|
+
cacheControl: 'public, max-age=31536000, immutable',
|
|
178
|
+
metadata: {
|
|
179
|
+
source: 'avatar-service',
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async uploadLargeFile(key: string, stream: Readable) {
|
|
185
|
+
return this.s3Service.upload(key, stream, {
|
|
186
|
+
contentType: 'application/pdf',
|
|
187
|
+
metadata: {
|
|
188
|
+
source: 'document-service',
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async getAvatar(key: string) {
|
|
194
|
+
const object = await this.s3Service.getObject(key);
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
stream: object.body,
|
|
198
|
+
contentType: object.contentType,
|
|
199
|
+
cacheControl: object.cacheControl,
|
|
200
|
+
metadata: object.metadata,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async deleteAvatar(key: string) {
|
|
205
|
+
return this.s3Service.deleteObject(key);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Signed URLs
|
|
211
|
+
|
|
212
|
+
Use `getSignedUrl` when the client should upload or download directly from S3.
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// files.service.ts
|
|
216
|
+
async getAvatarUploadUrl(key: string) {
|
|
217
|
+
return this.s3Service.getSignedUrl(key, {
|
|
218
|
+
operation: 'putObject',
|
|
219
|
+
expiresIn: 300,
|
|
220
|
+
contentType: 'image/png',
|
|
221
|
+
cacheControl: 'public, max-age=31536000, immutable',
|
|
222
|
+
metadata: {
|
|
223
|
+
source: 'avatar-upload',
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async getAvatarDownloadUrl(key: string) {
|
|
229
|
+
return this.s3Service.getSignedUrl(key, {
|
|
230
|
+
operation: 'getObject',
|
|
231
|
+
expiresIn: 300,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
When generating a signed `putObject` URL, make sure the client sends the same headers you used during signing, especially `Content-Type` and any custom metadata headers.
|
|
237
|
+
|
|
238
|
+
### Available methods
|
|
239
|
+
|
|
240
|
+
| Method | Description |
|
|
241
|
+
|--------|-------------|
|
|
242
|
+
| `putObject(key, body, options)` | Simple upload using `PutObjectCommand` |
|
|
243
|
+
| `upload(key, body, options)` | Managed upload using `@aws-sdk/lib-storage`, useful for larger or streaming payloads |
|
|
244
|
+
| `getObject(key, options)` | Returns the readable stream together with object metadata |
|
|
245
|
+
| `deleteObject(key, options)` | Deletes an object from the configured bucket |
|
|
246
|
+
| `getSignedUrl(key, options)` | Creates a presigned URL for `getObject` or `putObject` |
|
|
247
|
+
|
|
248
|
+
`uploadObject` is still available as a compatibility alias, but `putObject` is the preferred method name going forward.
|
|
249
|
+
|
|
18
250
|
## Entity Validator
|
|
19
251
|
|
|
20
252
|
A custom validator for NestJS that validates if an entity exists in the database using TypeORM.
|
|
@@ -25,7 +257,9 @@ A custom validator for NestJS that validates if an entity exists in the database
|
|
|
25
257
|
|
|
26
258
|
```typescript
|
|
27
259
|
// main.ts
|
|
260
|
+
import { NestFactory } from '@nestjs/core';
|
|
28
261
|
import { useContainer } from 'class-validator';
|
|
262
|
+
import { AppModule } from './app.module';
|
|
29
263
|
|
|
30
264
|
async function bootstrap() {
|
|
31
265
|
const app = await NestFactory.create(AppModule);
|
|
@@ -43,7 +277,6 @@ async function bootstrap() {
|
|
|
43
277
|
```typescript
|
|
44
278
|
// app.module.ts
|
|
45
279
|
import { Module } from '@nestjs/common';
|
|
46
|
-
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
47
280
|
import { EntityConstraint } from '@russ-b/nestjs-common-tools/validators';
|
|
48
281
|
|
|
49
282
|
@Module({
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./to-string-array.decorator"), exports);
|
|
18
|
+
__exportStar(require("./to-boolean-from-string.decorator"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/class-transformer/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,qEAAmD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseBooleanFromStringTransformer = void 0;
|
|
4
|
+
exports.ToBooleanFromString = ToBooleanFromString;
|
|
5
|
+
const class_transformer_1 = require("class-transformer");
|
|
6
|
+
function ToBooleanFromString() {
|
|
7
|
+
return (0, class_transformer_1.Transform)(exports.parseBooleanFromStringTransformer);
|
|
8
|
+
}
|
|
9
|
+
const parseBooleanFromStringTransformer = ({ value, }) => normalizeBooleanFromString(value);
|
|
10
|
+
exports.parseBooleanFromStringTransformer = parseBooleanFromStringTransformer;
|
|
11
|
+
function normalizeBooleanFromString(value) {
|
|
12
|
+
if (value === undefined) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
if (typeof value === 'boolean') {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === 'string') {
|
|
19
|
+
const normalizedValue = value.trim().toLowerCase();
|
|
20
|
+
if (normalizedValue === 'true') {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (normalizedValue === 'false') {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=to-boolean-from-string.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-boolean-from-string.decorator.js","sourceRoot":"","sources":["../../src/class-transformer/to-boolean-from-string.decorator.ts"],"names":[],"mappings":";;;AAEA,kDAEC;AAJD,yDAAiE;AAEjE,SAAgB,mBAAmB;IACjC,OAAO,IAAA,6BAAS,EAAC,yCAAiC,CAAC,CAAC;AACtD,CAAC;AAEM,MAAM,iCAAiC,GAAG,CAAC,EAChD,KAAK,GACa,EAAW,EAAE,CAAC,0BAA0B,CAAC,KAAK,CAAC,CAAC;AAFvD,QAAA,iCAAiC,qCAEsB;AAEpE,SAAS,0BAA0B,CAAC,KAAc;IAChD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAEnD,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;YAChC,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ToStringArray(): PropertyDecorator;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToStringArray = ToStringArray;
|
|
4
|
+
const class_transformer_1 = require("class-transformer");
|
|
5
|
+
function ToStringArray() {
|
|
6
|
+
return (0, class_transformer_1.Transform)(({ value }) => normalizeToStringArray(value));
|
|
7
|
+
}
|
|
8
|
+
function normalizeToStringArray(value) {
|
|
9
|
+
if (typeof value === 'string') {
|
|
10
|
+
return splitAndTrim(value);
|
|
11
|
+
}
|
|
12
|
+
if (Array.isArray(value)) {
|
|
13
|
+
return value.flatMap((item) => typeof item === 'string' ? splitAndTrim(item) : []);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
function splitAndTrim(value) {
|
|
18
|
+
return value
|
|
19
|
+
.split(',')
|
|
20
|
+
.map((item) => item.trim())
|
|
21
|
+
.filter(Boolean);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=to-string-array.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-string-array.decorator.js","sourceRoot":"","sources":["../../src/class-transformer/to-string-array.decorator.ts"],"names":[],"mappings":";;AAEA,sCAEC;AAJD,yDAAiE;AAEjE,SAAgB,aAAa;IAC3B,OAAO,IAAA,6BAAS,EAAC,CAAC,EAAE,KAAK,EAAqB,EAAE,EAAE,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAC5B,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CACnD,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC"}
|
package/dist/modules/s3/index.js
CHANGED
|
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./s3.module"), exports);
|
|
18
18
|
__exportStar(require("./s3.service"), exports);
|
|
19
|
+
__exportStar(require("./s3.interface"), exports);
|
|
19
20
|
//# 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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/s3/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,+CAA6B;AAC7B,iDAA+B"}
|
|
@@ -1,19 +1,44 @@
|
|
|
1
|
-
import { ModuleMetadata } from '@nestjs/common';
|
|
2
|
-
import { ObjectCannedACL } from '@aws-sdk/client-s3';
|
|
1
|
+
import type { LoggerService, ModuleMetadata } from '@nestjs/common';
|
|
2
|
+
import type { DeleteObjectCommandOutput, GetObjectCommandOutput, ObjectCannedACL, PutObjectCommandInput, PutObjectCommandOutput } from '@aws-sdk/client-s3';
|
|
3
|
+
import type { CompleteMultipartUploadCommandOutput } from '@aws-sdk/client-s3';
|
|
4
|
+
import type { Readable } from 'stream';
|
|
5
|
+
export type S3ModuleLogger = Pick<LoggerService, 'log' | 'error'>;
|
|
3
6
|
export interface S3ModuleOptions {
|
|
4
7
|
region?: string;
|
|
5
|
-
endpoint
|
|
6
|
-
accessKeyId: string;
|
|
7
|
-
secretAccessKey: string;
|
|
8
|
+
endpoint?: string;
|
|
8
9
|
forcePathStyle?: boolean;
|
|
9
10
|
bucket?: string;
|
|
11
|
+
logger?: boolean | S3ModuleLogger;
|
|
10
12
|
}
|
|
11
13
|
export interface S3ModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
|
|
12
14
|
useFactory: (...args: any[]) => Promise<S3ModuleOptions> | S3ModuleOptions;
|
|
13
15
|
global?: boolean;
|
|
14
16
|
inject?: any[];
|
|
15
17
|
}
|
|
16
|
-
export interface
|
|
18
|
+
export interface S3ObjectOptions {
|
|
17
19
|
bucket?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface S3UploadOptions extends S3ObjectOptions {
|
|
18
22
|
acl?: ObjectCannedACL;
|
|
23
|
+
cacheControl?: PutObjectCommandInput['CacheControl'];
|
|
24
|
+
contentType?: NonNullable<PutObjectCommandInput['ContentType']>;
|
|
25
|
+
metadata?: PutObjectCommandInput['Metadata'];
|
|
26
|
+
}
|
|
27
|
+
export interface S3SignedUrlOptions extends S3UploadOptions {
|
|
28
|
+
expiresIn?: number;
|
|
29
|
+
operation?: 'getObject' | 'putObject';
|
|
30
|
+
}
|
|
31
|
+
export interface S3GetObjectResult {
|
|
32
|
+
body: Readable;
|
|
33
|
+
cacheControl?: GetObjectCommandOutput['CacheControl'];
|
|
34
|
+
contentLength?: GetObjectCommandOutput['ContentLength'];
|
|
35
|
+
contentType?: GetObjectCommandOutput['ContentType'];
|
|
36
|
+
eTag?: GetObjectCommandOutput['ETag'];
|
|
37
|
+
lastModified?: GetObjectCommandOutput['LastModified'];
|
|
38
|
+
metadata?: GetObjectCommandOutput['Metadata'];
|
|
19
39
|
}
|
|
40
|
+
export type S3UploadResult = CompleteMultipartUploadCommandOutput;
|
|
41
|
+
export type S3PutObjectResult = PutObjectCommandOutput;
|
|
42
|
+
export type S3DeleteObjectResult = DeleteObjectCommandOutput;
|
|
43
|
+
export type S3Body = NonNullable<PutObjectCommandInput['Body']>;
|
|
44
|
+
export type UploadParams = S3UploadOptions;
|
|
@@ -9,9 +9,9 @@ var S3Module_1;
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.S3Module = void 0;
|
|
11
11
|
const common_1 = require("@nestjs/common");
|
|
12
|
-
const s3_service_1 = require("./s3.service");
|
|
13
|
-
const s3_constants_1 = require("./s3.constants");
|
|
14
12
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
13
|
+
const s3_constants_1 = require("./s3.constants");
|
|
14
|
+
const s3_service_1 = require("./s3.service");
|
|
15
15
|
let S3Module = S3Module_1 = class S3Module {
|
|
16
16
|
static forRootAsync(options) {
|
|
17
17
|
return {
|
|
@@ -28,15 +28,12 @@ let S3Module = S3Module_1 = class S3Module {
|
|
|
28
28
|
provide: s3_constants_1.S3_CLIENT,
|
|
29
29
|
inject: [s3_constants_1.S3_MODULE_OPTIONS],
|
|
30
30
|
useFactory: (opts) => {
|
|
31
|
-
|
|
31
|
+
const clientConfig = {
|
|
32
32
|
region: opts.region || 'us-east-1',
|
|
33
33
|
endpoint: opts.endpoint,
|
|
34
|
-
credentials: {
|
|
35
|
-
accessKeyId: opts.accessKeyId,
|
|
36
|
-
secretAccessKey: opts.secretAccessKey,
|
|
37
|
-
},
|
|
38
34
|
forcePathStyle: opts.forcePathStyle ?? true,
|
|
39
|
-
}
|
|
35
|
+
};
|
|
36
|
+
return new client_s3_1.S3Client(clientConfig);
|
|
40
37
|
},
|
|
41
38
|
},
|
|
42
39
|
s3_service_1.S3Service,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.module.js","sourceRoot":"","sources":["../../../src/modules/s3/s3.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,
|
|
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;yBAC5C,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;AA9BY,4BAAQ;mBAAR,QAAQ;IADpB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,QAAQ,CA8BpB"}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { S3Client } from '@aws-sdk/client-s3';
|
|
2
|
-
import {
|
|
3
|
-
import { StreamingBlobPayloadInputTypes } from '@smithy/types/dist-types/streaming-payload/streaming-blob-payload-input-types';
|
|
4
|
-
import { UploadParams } from './s3.interface';
|
|
2
|
+
import { S3Body, S3DeleteObjectResult, S3GetObjectResult, S3ModuleOptions, S3ObjectOptions, S3PutObjectResult, S3SignedUrlOptions, S3UploadOptions, S3UploadResult } from './s3.interface';
|
|
5
3
|
export declare class S3Service {
|
|
6
4
|
private readonly options;
|
|
7
5
|
private readonly s3Client;
|
|
8
|
-
private readonly logger
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
uploadObject(key: string, body:
|
|
13
|
-
deleteObject(key: string,
|
|
14
|
-
getObject(key: string,
|
|
6
|
+
private readonly logger?;
|
|
7
|
+
constructor(options: S3ModuleOptions, s3Client: S3Client);
|
|
8
|
+
upload(key: string, body: S3Body, options?: S3UploadOptions): Promise<S3UploadResult>;
|
|
9
|
+
putObject(key: string, body: S3Body, options?: S3UploadOptions): Promise<S3PutObjectResult>;
|
|
10
|
+
uploadObject(key: string, body: S3Body, options?: S3UploadOptions): Promise<S3PutObjectResult>;
|
|
11
|
+
deleteObject(key: string, options?: S3ObjectOptions): Promise<S3DeleteObjectResult>;
|
|
12
|
+
getObject(key: string, options?: S3ObjectOptions): Promise<S3GetObjectResult>;
|
|
13
|
+
getSignedUrl(key: string, options?: S3SignedUrlOptions): Promise<string>;
|
|
14
|
+
private createPutObjectParams;
|
|
15
|
+
private resolveBucket;
|
|
16
|
+
private log;
|
|
17
|
+
private logError;
|
|
15
18
|
}
|
|
@@ -11,81 +11,137 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
|
+
var S3Service_1;
|
|
14
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
16
|
exports.S3Service = void 0;
|
|
16
17
|
const common_1 = require("@nestjs/common");
|
|
17
18
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
18
|
-
const
|
|
19
|
+
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
20
|
+
const stream_1 = require("stream");
|
|
19
21
|
const lib_storage_1 = require("@aws-sdk/lib-storage");
|
|
20
|
-
|
|
22
|
+
const s3_constants_1 = require("./s3.constants");
|
|
23
|
+
let S3Service = S3Service_1 = class S3Service {
|
|
21
24
|
constructor(options, s3Client) {
|
|
22
25
|
this.options = options;
|
|
23
26
|
this.s3Client = s3Client;
|
|
24
|
-
this.logger =
|
|
25
|
-
|
|
27
|
+
this.logger =
|
|
28
|
+
options.logger === true ? new common_1.Logger(S3Service_1.name) : options.logger || undefined;
|
|
26
29
|
}
|
|
27
|
-
async upload(key, body,
|
|
30
|
+
async upload(key, body, options) {
|
|
28
31
|
const upload = new lib_storage_1.Upload({
|
|
29
32
|
client: this.s3Client,
|
|
30
|
-
params:
|
|
31
|
-
Bucket: params?.bucket || this.bucket,
|
|
32
|
-
Key: key,
|
|
33
|
-
Body: body,
|
|
34
|
-
ContentType: contentType,
|
|
35
|
-
ACL: params?.acl || 'public-read',
|
|
36
|
-
},
|
|
33
|
+
params: this.createPutObjectParams(key, body, options, true),
|
|
37
34
|
});
|
|
38
|
-
await upload.done();
|
|
35
|
+
const response = await upload.done();
|
|
36
|
+
this.log(`Uploaded object with multipart upload: ${key}`);
|
|
37
|
+
return response;
|
|
39
38
|
}
|
|
40
|
-
async
|
|
41
|
-
const command = new client_s3_1.PutObjectCommand(
|
|
42
|
-
Bucket: params?.bucket || this.bucket,
|
|
43
|
-
Key: key,
|
|
44
|
-
Body: body,
|
|
45
|
-
ContentType: contentType,
|
|
46
|
-
ACL: params?.acl || 'public-read',
|
|
47
|
-
});
|
|
39
|
+
async putObject(key, body, options) {
|
|
40
|
+
const command = new client_s3_1.PutObjectCommand(this.createPutObjectParams(key, body, options, true));
|
|
48
41
|
try {
|
|
49
|
-
await this.s3Client.send(command);
|
|
50
|
-
this.
|
|
42
|
+
const response = await this.s3Client.send(command);
|
|
43
|
+
this.log(`Uploaded object: ${key}`);
|
|
44
|
+
return response;
|
|
51
45
|
}
|
|
52
46
|
catch (error) {
|
|
53
|
-
this.
|
|
47
|
+
this.logError(`Failed to upload object: ${key}`, error);
|
|
54
48
|
throw error;
|
|
55
49
|
}
|
|
56
50
|
}
|
|
57
|
-
async
|
|
51
|
+
async uploadObject(key, body, options) {
|
|
52
|
+
return this.putObject(key, body, options);
|
|
53
|
+
}
|
|
54
|
+
async deleteObject(key, options) {
|
|
58
55
|
const command = new client_s3_1.DeleteObjectCommand({
|
|
59
|
-
Bucket:
|
|
56
|
+
Bucket: this.resolveBucket(options?.bucket),
|
|
60
57
|
Key: key,
|
|
61
58
|
});
|
|
62
59
|
try {
|
|
63
|
-
await this.s3Client.send(command);
|
|
64
|
-
this.
|
|
60
|
+
const response = await this.s3Client.send(command);
|
|
61
|
+
this.log(`Deleted object: ${key}`);
|
|
62
|
+
return response;
|
|
65
63
|
}
|
|
66
64
|
catch (error) {
|
|
67
|
-
this.
|
|
65
|
+
this.logError(`Failed to delete object: ${key}`, error);
|
|
68
66
|
throw error;
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
|
-
async getObject(key,
|
|
69
|
+
async getObject(key, options) {
|
|
72
70
|
const command = new client_s3_1.GetObjectCommand({
|
|
73
|
-
Bucket:
|
|
71
|
+
Bucket: this.resolveBucket(options?.bucket),
|
|
74
72
|
Key: key,
|
|
75
73
|
});
|
|
76
74
|
try {
|
|
77
75
|
const response = await this.s3Client.send(command);
|
|
78
|
-
this.
|
|
79
|
-
|
|
76
|
+
this.log(`Fetched object: ${key}`);
|
|
77
|
+
if (!response.Body) {
|
|
78
|
+
throw new Error(`S3 object "${key}" returned an empty body.`);
|
|
79
|
+
}
|
|
80
|
+
if (!(response.Body instanceof stream_1.Readable)) {
|
|
81
|
+
throw new Error(`S3 object "${key}" did not return a Node.js readable stream.`);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
body: response.Body,
|
|
85
|
+
cacheControl: response.CacheControl,
|
|
86
|
+
contentLength: response.ContentLength,
|
|
87
|
+
contentType: response.ContentType,
|
|
88
|
+
eTag: response.ETag,
|
|
89
|
+
lastModified: response.LastModified,
|
|
90
|
+
metadata: response.Metadata,
|
|
91
|
+
};
|
|
80
92
|
}
|
|
81
93
|
catch (error) {
|
|
82
|
-
this.
|
|
94
|
+
this.logError(`Failed to get object: ${key}`, error);
|
|
83
95
|
throw error;
|
|
84
96
|
}
|
|
85
97
|
}
|
|
98
|
+
async getSignedUrl(key, options) {
|
|
99
|
+
const expiresIn = options?.expiresIn ?? 900;
|
|
100
|
+
const operation = options?.operation ?? 'getObject';
|
|
101
|
+
const command = operation === 'putObject'
|
|
102
|
+
? new client_s3_1.PutObjectCommand(this.createPutObjectParams(key, undefined, options))
|
|
103
|
+
: new client_s3_1.GetObjectCommand({
|
|
104
|
+
Bucket: this.resolveBucket(options?.bucket),
|
|
105
|
+
Key: key,
|
|
106
|
+
});
|
|
107
|
+
return (0, s3_request_presigner_1.getSignedUrl)(this.s3Client, command, { expiresIn });
|
|
108
|
+
}
|
|
109
|
+
createPutObjectParams(key, body, options, useDefaultContentType = false) {
|
|
110
|
+
const contentType = options?.contentType ??
|
|
111
|
+
(useDefaultContentType ? 'application/octet-stream' : undefined);
|
|
112
|
+
return {
|
|
113
|
+
Bucket: this.resolveBucket(options?.bucket),
|
|
114
|
+
Key: key,
|
|
115
|
+
...(body !== undefined ? { Body: body } : {}),
|
|
116
|
+
...(contentType ? { ContentType: contentType } : {}),
|
|
117
|
+
...(options?.acl ? { ACL: options.acl } : {}),
|
|
118
|
+
...(options?.cacheControl ? { CacheControl: options.cacheControl } : {}),
|
|
119
|
+
...(options?.metadata ? { Metadata: options.metadata } : {}),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
resolveBucket(bucket) {
|
|
123
|
+
const resolvedBucket = bucket ?? this.options.bucket;
|
|
124
|
+
if (!resolvedBucket) {
|
|
125
|
+
throw new Error('S3 bucket is not configured. Pass a bucket to the method call or set S3ModuleOptions.bucket.');
|
|
126
|
+
}
|
|
127
|
+
return resolvedBucket;
|
|
128
|
+
}
|
|
129
|
+
log(message) {
|
|
130
|
+
this.logger?.log(message);
|
|
131
|
+
}
|
|
132
|
+
logError(message, error) {
|
|
133
|
+
if (!this.logger) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (error instanceof Error) {
|
|
137
|
+
this.logger.error(message, error.stack ?? error.message);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.logger.error(message, error);
|
|
141
|
+
}
|
|
86
142
|
};
|
|
87
143
|
exports.S3Service = S3Service;
|
|
88
|
-
exports.S3Service = S3Service = __decorate([
|
|
144
|
+
exports.S3Service = S3Service = S3Service_1 = __decorate([
|
|
89
145
|
(0, common_1.Injectable)(),
|
|
90
146
|
__param(0, (0, common_1.Inject)(s3_constants_1.S3_MODULE_OPTIONS)),
|
|
91
147
|
__param(1, (0, common_1.Inject)(s3_constants_1.S3_CLIENT)),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.service.js","sourceRoot":"","sources":["../../../src/modules/s3/s3.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"s3.service.js","sourceRoot":"","sources":["../../../src/modules/s3/s3.service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@russ-b/nestjs-common-tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.1",
|
|
4
4
|
"description": "NestJS utility tools",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -47,6 +47,10 @@
|
|
|
47
47
|
"types": "./dist/common/filters/index.d.ts",
|
|
48
48
|
"default": "./dist/common/filters/index.js"
|
|
49
49
|
},
|
|
50
|
+
"./class-transformer": {
|
|
51
|
+
"types": "./dist/class-transformer/index.d.ts",
|
|
52
|
+
"default": "./dist/class-transformer/index.js"
|
|
53
|
+
},
|
|
50
54
|
"./validators": {
|
|
51
55
|
"types": "./dist/validators/index.d.ts",
|
|
52
56
|
"default": "./dist/validators/index.js"
|
|
@@ -82,6 +86,9 @@
|
|
|
82
86
|
"common/filters": [
|
|
83
87
|
"dist/common/filters/index.d.ts"
|
|
84
88
|
],
|
|
89
|
+
"class-transformer": [
|
|
90
|
+
"dist/class-transformer/index.d.ts"
|
|
91
|
+
],
|
|
85
92
|
"modules": [
|
|
86
93
|
"dist/modules/index.d.ts"
|
|
87
94
|
],
|
|
@@ -99,6 +106,7 @@
|
|
|
99
106
|
"peerDependencies": {
|
|
100
107
|
"@aws-sdk/client-s3": "^3.0.0",
|
|
101
108
|
"@aws-sdk/lib-storage": "^3.0.0",
|
|
109
|
+
"@aws-sdk/s3-request-presigner": "^3.1019.0",
|
|
102
110
|
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
103
111
|
"@nestjs/config": "^3.0.0 || ^4.0.0",
|
|
104
112
|
"nest-winston": "^1.10.2",
|