@rsdk/s3 4.2.0-next.0
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/CHANGELOG.md +10 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +19 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/s3.client.d.ts +89 -0
- package/dist/client/s3.client.js +216 -0
- package/dist/client/s3.client.js.map +1 -0
- package/dist/client/types.d.ts +68 -0
- package/dist/client/types.js +3 -0
- package/dist/client/types.js.map +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/decorators/index.d.ts +1 -0
- package/dist/decorators/index.js +18 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/inject-client.decorator.d.ts +8 -0
- package/dist/decorators/inject-client.decorator.js +19 -0
- package/dist/decorators/inject-client.decorator.js.map +1 -0
- package/dist/decorators/set-client-metadata.fn.d.ts +1 -0
- package/dist/decorators/set-client-metadata.fn.js +12 -0
- package/dist/decorators/set-client-metadata.fn.js.map +1 -0
- package/dist/generate-key.fn.d.ts +5 -0
- package/dist/generate-key.fn.js +13 -0
- package/dist/generate-key.fn.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/module/index.d.ts +2 -0
- package/dist/module/index.js +19 -0
- package/dist/module/index.js.map +1 -0
- package/dist/module/s3-clients.config.d.ts +5 -0
- package/dist/module/s3-clients.config.js +32 -0
- package/dist/module/s3-clients.config.js.map +1 -0
- package/dist/module/s3-clients.indicator.d.ts +13 -0
- package/dist/module/s3-clients.indicator.js +52 -0
- package/dist/module/s3-clients.indicator.js.map +1 -0
- package/dist/module/s3-clients.module.d.ts +6 -0
- package/dist/module/s3-clients.module.js +27 -0
- package/dist/module/s3-clients.module.js.map +1 -0
- package/dist/module/s3-clients.plugin.d.ts +10 -0
- package/dist/module/s3-clients.plugin.js +17 -0
- package/dist/module/s3-clients.plugin.js.map +1 -0
- package/dist/module/s3-clients.service.d.ts +25 -0
- package/dist/module/s3-clients.service.js +101 -0
- package/dist/module/s3-clients.service.js.map +1 -0
- package/dist/module.generator.d.ts +9 -0
- package/dist/module.generator.js +55 -0
- package/dist/module.generator.js.map +1 -0
- package/dist/s3-clients.autodoc.d.ts +6 -0
- package/dist/s3-clients.autodoc.js +19 -0
- package/dist/s3-clients.autodoc.js.map +1 -0
- package/dist/token.factories.d.ts +2 -0
- package/dist/token.factories.js +9 -0
- package/dist/token.factories.js.map +1 -0
- package/package.json +30 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [4.2.0-next.0](https://github.com/R-Vision/rsdk/compare/v4.1.0...v4.2.0-next.0) (2024-02-02)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **s3:** added @rsdk/s3 package ([03bd9ea](https://github.com/R-Vision/rsdk/commit/03bd9ea7e5f78be6c93b1a2547fe7c2639ca0146))
|
|
@@ -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("./s3.client"), exports);
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,0CAAwB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import type { Timespan } from '@rsdk/common';
|
|
4
|
+
import { Readable } from 'node:stream';
|
|
5
|
+
import type { File, ObjectInfo, S3ClientOptions, UploadOptions } from './types';
|
|
6
|
+
/**
|
|
7
|
+
* Object storage client
|
|
8
|
+
*/
|
|
9
|
+
export declare class S3Client {
|
|
10
|
+
readonly storageName: string;
|
|
11
|
+
readonly bucket: string;
|
|
12
|
+
private readonly s3;
|
|
13
|
+
private readonly defaultTTL;
|
|
14
|
+
private readonly logger;
|
|
15
|
+
constructor({ url, defaultTTL, bucket, storageName, logger, }: S3ClientOptions);
|
|
16
|
+
/**
|
|
17
|
+
* Throws error if server is not responding
|
|
18
|
+
* or bucket doesn't exist
|
|
19
|
+
*/
|
|
20
|
+
checkBucket(): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Returns true if bucket is reachable
|
|
23
|
+
* @returns Promise<boolean>
|
|
24
|
+
*/
|
|
25
|
+
isHealthy(): Promise<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Creates temporary download link for object
|
|
28
|
+
* @param key Object key
|
|
29
|
+
* @param ttl Time too live for the presigned url (defaults to 48h)
|
|
30
|
+
* @returns Promise<string>
|
|
31
|
+
*/
|
|
32
|
+
getPresignedUrl(key: string, ttl?: Timespan): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Get object metadata
|
|
35
|
+
* @param key Key to save object to
|
|
36
|
+
* @returns Promise<ObjectInfo>
|
|
37
|
+
*/
|
|
38
|
+
getObjectInfo(key: string): Promise<ObjectInfo>;
|
|
39
|
+
/**
|
|
40
|
+
* Retrieves object from storage
|
|
41
|
+
* @param key string
|
|
42
|
+
* @returns Promise<File>
|
|
43
|
+
*/
|
|
44
|
+
getObject(key: string): Promise<File>;
|
|
45
|
+
/**
|
|
46
|
+
* Get object stream from storage
|
|
47
|
+
* @param key Object key
|
|
48
|
+
* @returns Promise<Readable>
|
|
49
|
+
*/
|
|
50
|
+
getObjectStream(key: string): Promise<Readable>;
|
|
51
|
+
/**
|
|
52
|
+
* Upload object to storage
|
|
53
|
+
* @param key Object key
|
|
54
|
+
* @param content Buffer
|
|
55
|
+
* @param options UploadOptions
|
|
56
|
+
*/
|
|
57
|
+
addObject(key: string, content: Buffer | Readable, options?: UploadOptions): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Removes object by key
|
|
60
|
+
* @param key Object key
|
|
61
|
+
*/
|
|
62
|
+
removeObject(key: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Tries to determine content type by file name
|
|
65
|
+
* @param filename filename
|
|
66
|
+
* @returns string
|
|
67
|
+
*/
|
|
68
|
+
private tryGetContentType;
|
|
69
|
+
/**
|
|
70
|
+
* Parses metadata from S3 response
|
|
71
|
+
* @param key Object key
|
|
72
|
+
* @param response Object storage response
|
|
73
|
+
* @returns
|
|
74
|
+
*/
|
|
75
|
+
private parseMetadata;
|
|
76
|
+
/**
|
|
77
|
+
* S3 storage can reply with different kinds of body
|
|
78
|
+
* @param key Object key
|
|
79
|
+
* @param response Object storage response
|
|
80
|
+
* @returns
|
|
81
|
+
*/
|
|
82
|
+
private parseBody;
|
|
83
|
+
/**
|
|
84
|
+
* Create short hash of object key if there is no filename
|
|
85
|
+
* @param key Object key
|
|
86
|
+
* @returns string
|
|
87
|
+
*/
|
|
88
|
+
private hashKey;
|
|
89
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.S3Client = void 0;
|
|
7
|
+
const common_1 = require("@rsdk/common");
|
|
8
|
+
const common_node_1 = require("@rsdk/common.node");
|
|
9
|
+
const aws_sdk_1 = require("aws-sdk");
|
|
10
|
+
const mime_types_1 = __importDefault(require("mime-types"));
|
|
11
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
12
|
+
const node_crypto_1 = require("node:crypto");
|
|
13
|
+
const node_stream_1 = require("node:stream");
|
|
14
|
+
const DEFAULT_CONTENT_TYPE = 'application/octet-stream';
|
|
15
|
+
/**
|
|
16
|
+
* Object storage client
|
|
17
|
+
*/
|
|
18
|
+
class S3Client {
|
|
19
|
+
storageName;
|
|
20
|
+
bucket;
|
|
21
|
+
s3;
|
|
22
|
+
defaultTTL;
|
|
23
|
+
logger;
|
|
24
|
+
constructor({ url, defaultTTL, bucket, storageName, logger, }) {
|
|
25
|
+
this.s3 = new aws_sdk_1.S3({
|
|
26
|
+
accessKeyId: url.username,
|
|
27
|
+
secretAccessKey: url.password,
|
|
28
|
+
endpoint: `${url.protocol}//${url.host}${url.pathname}`,
|
|
29
|
+
s3ForcePathStyle: true,
|
|
30
|
+
});
|
|
31
|
+
this.bucket = bucket;
|
|
32
|
+
this.defaultTTL = defaultTTL;
|
|
33
|
+
this.storageName = storageName;
|
|
34
|
+
this.logger = logger;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Throws error if server is not responding
|
|
38
|
+
* or bucket doesn't exist
|
|
39
|
+
*/
|
|
40
|
+
async checkBucket() {
|
|
41
|
+
await this.s3.headBucket({ Bucket: this.bucket }).promise();
|
|
42
|
+
/**
|
|
43
|
+
* TODO: Добавить более информативную обработку ошибок.
|
|
44
|
+
* Сейчас в целом терпимо, но может быть лучше.
|
|
45
|
+
*/
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns true if bucket is reachable
|
|
49
|
+
* @returns Promise<boolean>
|
|
50
|
+
*/
|
|
51
|
+
async isHealthy() {
|
|
52
|
+
try {
|
|
53
|
+
await this.checkBucket();
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Creates temporary download link for object
|
|
62
|
+
* @param key Object key
|
|
63
|
+
* @param ttl Time too live for the presigned url (defaults to 48h)
|
|
64
|
+
* @returns Promise<string>
|
|
65
|
+
*/
|
|
66
|
+
async getPresignedUrl(key, ttl = this.defaultTTL) {
|
|
67
|
+
return this.s3.getSignedUrlPromise('getObject', {
|
|
68
|
+
Bucket: this.bucket,
|
|
69
|
+
Key: key,
|
|
70
|
+
Expires: ttl.millis(),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get object metadata
|
|
75
|
+
* @param key Key to save object to
|
|
76
|
+
* @returns Promise<ObjectInfo>
|
|
77
|
+
*/
|
|
78
|
+
async getObjectInfo(key) {
|
|
79
|
+
const response = await this.s3
|
|
80
|
+
.headObject({ Bucket: this.bucket, Key: key })
|
|
81
|
+
.promise();
|
|
82
|
+
return this.parseMetadata(key, response);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Retrieves object from storage
|
|
86
|
+
* @param key string
|
|
87
|
+
* @returns Promise<File>
|
|
88
|
+
*/
|
|
89
|
+
async getObject(key) {
|
|
90
|
+
const response = await this.s3
|
|
91
|
+
.getObject({
|
|
92
|
+
Bucket: this.bucket,
|
|
93
|
+
Key: key,
|
|
94
|
+
})
|
|
95
|
+
.promise();
|
|
96
|
+
return {
|
|
97
|
+
...this.parseMetadata(key, response),
|
|
98
|
+
content: await this.parseBody(key, response),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get object stream from storage
|
|
103
|
+
* @param key Object key
|
|
104
|
+
* @returns Promise<Readable>
|
|
105
|
+
*/
|
|
106
|
+
async getObjectStream(key) {
|
|
107
|
+
const stream = this.s3
|
|
108
|
+
.getObject({
|
|
109
|
+
Bucket: this.bucket,
|
|
110
|
+
Key: key,
|
|
111
|
+
})
|
|
112
|
+
.createReadStream();
|
|
113
|
+
return stream;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Upload object to storage
|
|
117
|
+
* @param key Object key
|
|
118
|
+
* @param content Buffer
|
|
119
|
+
* @param options UploadOptions
|
|
120
|
+
*/
|
|
121
|
+
async addObject(key, content, options) {
|
|
122
|
+
const { filename, contentType, metadata = {}, isAttachment = false, } = options || {};
|
|
123
|
+
const encodedFilenameOrHash = filename
|
|
124
|
+
? encodeURIComponent(filename)
|
|
125
|
+
: this.hashKey(key);
|
|
126
|
+
await this.s3
|
|
127
|
+
.upload({
|
|
128
|
+
Key: key,
|
|
129
|
+
Body: content,
|
|
130
|
+
Bucket: this.bucket,
|
|
131
|
+
ContentType: contentType ||
|
|
132
|
+
this.tryGetContentType(encodedFilenameOrHash) ||
|
|
133
|
+
DEFAULT_CONTENT_TYPE,
|
|
134
|
+
ContentDisposition: `${isAttachment ? 'attachment; ' : ''}filename=${encodedFilenameOrHash}`,
|
|
135
|
+
Metadata: { ...metadata, filename: encodedFilenameOrHash },
|
|
136
|
+
})
|
|
137
|
+
.promise();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Removes object by key
|
|
141
|
+
* @param key Object key
|
|
142
|
+
*/
|
|
143
|
+
async removeObject(key) {
|
|
144
|
+
await this.s3
|
|
145
|
+
.deleteObject({
|
|
146
|
+
Bucket: this.bucket,
|
|
147
|
+
Key: key,
|
|
148
|
+
})
|
|
149
|
+
.promise();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Tries to determine content type by file name
|
|
153
|
+
* @param filename filename
|
|
154
|
+
* @returns string
|
|
155
|
+
*/
|
|
156
|
+
tryGetContentType(filename) {
|
|
157
|
+
const contentType = mime_types_1.default.contentType(filename);
|
|
158
|
+
if (contentType === false) {
|
|
159
|
+
this.logger.warn(`Can not detect content type of file: ${filename}`);
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
return contentType;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Parses metadata from S3 response
|
|
166
|
+
* @param key Object key
|
|
167
|
+
* @param response Object storage response
|
|
168
|
+
* @returns
|
|
169
|
+
*/
|
|
170
|
+
parseMetadata(key, response) {
|
|
171
|
+
const { Metadata, ContentLength, ContentType } = response;
|
|
172
|
+
(0, node_assert_1.default)(Metadata, `Object <${key}> missing Metadata`);
|
|
173
|
+
(0, node_assert_1.default)(ContentLength, `Object <${key}> missing ContentLength`);
|
|
174
|
+
const { filename, ...metadata } = Metadata;
|
|
175
|
+
return {
|
|
176
|
+
size: new common_1.Size(ContentLength, 'b'),
|
|
177
|
+
contentType: ContentType,
|
|
178
|
+
filename: filename ? decodeURIComponent(filename) : this.hashKey(key),
|
|
179
|
+
metadata,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* S3 storage can reply with different kinds of body
|
|
184
|
+
* @param key Object key
|
|
185
|
+
* @param response Object storage response
|
|
186
|
+
* @returns
|
|
187
|
+
*/
|
|
188
|
+
async parseBody(key, response) {
|
|
189
|
+
const { Body } = response;
|
|
190
|
+
if (Buffer.isBuffer(Body)) {
|
|
191
|
+
return Body;
|
|
192
|
+
}
|
|
193
|
+
if (typeof Body === 'string' || Body instanceof Uint8Array) {
|
|
194
|
+
return Buffer.from(Body);
|
|
195
|
+
}
|
|
196
|
+
if (Body instanceof Blob) {
|
|
197
|
+
return Buffer.from(await Body.text());
|
|
198
|
+
}
|
|
199
|
+
if (Body instanceof node_stream_1.Readable) {
|
|
200
|
+
return (0, common_node_1.streamToBuffer)(Body);
|
|
201
|
+
}
|
|
202
|
+
throw new Error(`Object <${key}> missing Body or it is invalid`);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Create short hash of object key if there is no filename
|
|
206
|
+
* @param key Object key
|
|
207
|
+
* @returns string
|
|
208
|
+
*/
|
|
209
|
+
hashKey(key) {
|
|
210
|
+
return (0, node_crypto_1.createHash)('shake256', { outputLength: 4 })
|
|
211
|
+
.update(key)
|
|
212
|
+
.digest('hex');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
exports.S3Client = S3Client;
|
|
216
|
+
//# sourceMappingURL=s3.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.client.js","sourceRoot":"","sources":["../../src/client/s3.client.ts"],"names":[],"mappings":";;;;;;AACA,yCAAoC;AACpC,mDAAmD;AAGnD,qCAA6B;AAE7B,4DAA8B;AAC9B,8DAAiC;AACjC,6CAAyC;AACzC,6CAAuC;AAIvC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAExD;;GAEG;AACH,MAAa,QAAQ;IACV,WAAW,CAAS;IACpB,MAAM,CAAS;IAEP,EAAE,CAAK;IACP,UAAU,CAAW;IACrB,MAAM,CAAU;IAEjC,YAAY,EACV,GAAG,EACH,UAAU,EACV,MAAM,EACN,WAAW,EACX,MAAM,GACU;QAChB,IAAI,CAAC,EAAE,GAAG,IAAI,YAAE,CAAC;YACf,WAAW,EAAE,GAAG,CAAC,QAAQ;YACzB,eAAe,EAAE,GAAG,CAAC,QAAQ;YAC7B,QAAQ,EAAE,GAAG,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE;YACvD,gBAAgB,EAAE,IAAI;SACvB,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;QAE5D;;;WAGG;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS;QACb,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,eAAe,CAC1B,GAAW,EACX,GAAG,GAAG,IAAI,CAAC,UAAU;QAErB,OAAO,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,WAAW,EAAE;YAC9C,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,GAAG;YACR,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;SACtB,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,aAAa,CAAC,GAAW;QACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE;aAC3B,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;aAC7C,OAAO,EAAE,CAAC;QAEb,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,SAAS,CAAC,GAAW;QAChC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE;aAC3B,SAAS,CAAC;YACT,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,GAAG;SACT,CAAC;aACD,OAAO,EAAE,CAAC;QAEb,OAAO;YACL,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC;YACpC,OAAO,EAAE,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC;SAC7C,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,eAAe,CAAC,GAAW;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE;aACnB,SAAS,CAAC;YACT,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,GAAG;SACT,CAAC;aACD,gBAAgB,EAAE,CAAC;QAEtB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CACb,GAAW,EACX,OAA0B,EAC1B,OAAuB;QAEvB,MAAM,EACJ,QAAQ,EACR,WAAW,EACX,QAAQ,GAAG,EAAE,EACb,YAAY,GAAG,KAAK,GACrB,GAAG,OAAO,IAAI,EAAE,CAAC;QAElB,MAAM,qBAAqB,GAAG,QAAQ;YACpC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC;YAC9B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEtB,MAAM,IAAI,CAAC,EAAE;aACV,MAAM,CAAC;YACN,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW,EACT,WAAW;gBACX,IAAI,CAAC,iBAAiB,CAAC,qBAAqB,CAAC;gBAC7C,oBAAoB;YACtB,kBAAkB,EAAE,GAClB,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAClC,YAAY,qBAAqB,EAAE;YACnC,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,qBAAqB,EAAE;SAC3D,CAAC;aACD,OAAO,EAAE,CAAC;IACf,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,GAAW;QAC5B,MAAM,IAAI,CAAC,EAAE;aACV,YAAY,CAAC;YACZ,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,GAAG;SACT,CAAC;aACD,OAAO,EAAE,CAAC;IACf,CAAC;IAED;;;;OAIG;IACK,iBAAiB,CAAC,QAAgB;QACxC,MAAM,WAAW,GAAG,oBAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAE/C,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wCAAwC,QAAQ,EAAE,CAAC,CAAC;YACrE,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACK,aAAa,CACnB,GAAW,EACX,QAAqD;QAErD,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC;QAE1D,IAAA,qBAAM,EAAC,QAAQ,EAAE,WAAW,GAAG,oBAAoB,CAAC,CAAC;QACrD,IAAA,qBAAM,EAAC,aAAa,EAAE,WAAW,GAAG,yBAAyB,CAAC,CAAC;QAE/D,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,GAAG,QAAQ,CAAC;QAE3C,OAAO;YACL,IAAI,EAAE,IAAI,aAAI,CAAC,aAAa,EAAE,GAAG,CAAC;YAClC,WAAW,EAAE,WAAW;YACxB,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;YACrE,QAAQ;SACT,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,SAAS,CACrB,GAAW,EACX,QAAqD;QAErD,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;QAE1B,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,YAAY,UAAU,EAAE,CAAC;YAC3D,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QAED,IAAI,IAAI,YAAY,IAAI,EAAE,CAAC;YACzB,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,IAAI,YAAY,sBAAQ,EAAE,CAAC;YAC7B,OAAO,IAAA,4BAAc,EAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,iCAAiC,CAAC,CAAC;IACnE,CAAC;IAED;;;;OAIG;IACK,OAAO,CAAC,GAAW;QACzB,OAAO,IAAA,wBAAU,EAAC,UAAU,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;aAC/C,MAAM,CAAC,GAAG,CAAC;aACX,MAAM,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;CACF;AA7PD,4BA6PC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { Size, Timespan } from '@rsdk/common';
|
|
3
|
+
import type { ILogger } from '@rsdk/logging';
|
|
4
|
+
export interface UploadOptions {
|
|
5
|
+
/**
|
|
6
|
+
* File name that will be added to object metadata.
|
|
7
|
+
* If not provided, filename will be calculated from
|
|
8
|
+
* object key
|
|
9
|
+
*/
|
|
10
|
+
filename?: string;
|
|
11
|
+
/**
|
|
12
|
+
* File attachment flag that will be added to object metadata.
|
|
13
|
+
* If provided, the browser will interpret the file as downloadable
|
|
14
|
+
* object key
|
|
15
|
+
*/
|
|
16
|
+
isAttachment?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Mime type of the object. If not provided, client
|
|
19
|
+
* will try to determine content type from filename.
|
|
20
|
+
* Default: application/octet-stream
|
|
21
|
+
*/
|
|
22
|
+
contentType?: string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Key/value data that will be attached to object
|
|
25
|
+
* and returned as headers
|
|
26
|
+
*
|
|
27
|
+
* NOTE: All keys will be lowercase'ed. So use
|
|
28
|
+
* snake_case or kebab-case for keys
|
|
29
|
+
*/
|
|
30
|
+
metadata?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
export interface S3ClientOptions {
|
|
33
|
+
storageName: string;
|
|
34
|
+
url: URL;
|
|
35
|
+
bucket: string;
|
|
36
|
+
defaultTTL: Timespan;
|
|
37
|
+
logger: ILogger;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Object metadata
|
|
41
|
+
*/
|
|
42
|
+
export interface ObjectInfo {
|
|
43
|
+
/**
|
|
44
|
+
* File name of object
|
|
45
|
+
*/
|
|
46
|
+
filename: string;
|
|
47
|
+
/**
|
|
48
|
+
* Content type of object
|
|
49
|
+
*/
|
|
50
|
+
contentType: string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Size of object
|
|
53
|
+
*/
|
|
54
|
+
size: Size;
|
|
55
|
+
/**
|
|
56
|
+
* Key/value data attached to object
|
|
57
|
+
*/
|
|
58
|
+
metadata: Record<string, string>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Object metadata with the object itself
|
|
62
|
+
*/
|
|
63
|
+
export interface File extends ObjectInfo {
|
|
64
|
+
/**
|
|
65
|
+
* Blob
|
|
66
|
+
*/
|
|
67
|
+
content: Buffer;
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const S3_CLIENTS_RSDK_METADATA_SCOPE = "s3-clients";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,8BAA8B,GAAG,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './inject-client.decorator';
|
|
@@ -0,0 +1,18 @@
|
|
|
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("./inject-client.decorator"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4DAA0C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InjectBucket = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const token_factories_1 = require("../token.factories");
|
|
6
|
+
const set_client_metadata_fn_1 = require("./set-client-metadata.fn");
|
|
7
|
+
/**
|
|
8
|
+
* @returns ParameterDecorator
|
|
9
|
+
* @param connectionName
|
|
10
|
+
*/
|
|
11
|
+
const InjectBucket = (bucketName, options) => {
|
|
12
|
+
return (target, propertyKey, parameterIndex) => {
|
|
13
|
+
const storageName = options?.storageName ?? 'default';
|
|
14
|
+
(0, common_1.Inject)((0, token_factories_1.getClientToken)(storageName, bucketName))(target, propertyKey, parameterIndex);
|
|
15
|
+
(0, set_client_metadata_fn_1.setClientMetadata)(target, storageName, bucketName);
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
exports.InjectBucket = InjectBucket;
|
|
19
|
+
//# sourceMappingURL=inject-client.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-client.decorator.js","sourceRoot":"","sources":["../../src/decorators/inject-client.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AAExC,wDAAoD;AAEpD,qEAA6D;AAM7D;;;GAGG;AACI,MAAM,YAAY,GAAG,CAC1B,UAAkB,EAClB,OAA6B,EACT,EAAE;IACtB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,EAAE;QAC7C,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,SAAS,CAAC;QAEtD,IAAA,eAAM,EAAC,IAAA,gCAAc,EAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAC7C,MAAM,EACN,WAAW,EACX,cAAc,CACf,CAAC;QACF,IAAA,0CAAiB,EAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC,CAAC;AAdW,QAAA,YAAY,gBAcvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const setClientMetadata: (target: object, storageName: string, bucketName: string) => void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setClientMetadata = void 0;
|
|
4
|
+
const metadata_1 = require("@rsdk/metadata");
|
|
5
|
+
const module_generator_1 = require("../module.generator");
|
|
6
|
+
const setClientMetadata = (target, storageName, bucketName) => {
|
|
7
|
+
const key = `s3:${storageName}:${bucketName}`;
|
|
8
|
+
const moduleDefinition = module_generator_1.ModuleGenerator.createClientModuleDefinition(target, storageName, bucketName);
|
|
9
|
+
metadata_1.RsdkMetadata.setWithScope(target, metadata_1.PLATFORM_RAW_GLOBAL_METADATA_SCOPE, key, moduleDefinition, true);
|
|
10
|
+
};
|
|
11
|
+
exports.setClientMetadata = setClientMetadata;
|
|
12
|
+
//# sourceMappingURL=set-client-metadata.fn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-client-metadata.fn.js","sourceRoot":"","sources":["../../src/decorators/set-client-metadata.fn.ts"],"names":[],"mappings":";;;AAAA,6CAGwB;AAExB,0DAAsD;AAE/C,MAAM,iBAAiB,GAAG,CAC/B,MAAc,EACd,WAAmB,EACnB,UAAkB,EACZ,EAAE;IACR,MAAM,GAAG,GAAG,MAAM,WAAW,IAAI,UAAU,EAAE,CAAC;IAC9C,MAAM,gBAAgB,GAAG,kCAAe,CAAC,4BAA4B,CACnE,MAAM,EACN,WAAW,EACX,UAAU,CACX,CAAC;IAEF,uBAAY,CAAC,YAAY,CACvB,MAAM,EACN,6CAAkC,EAClC,GAAG,EACH,gBAAgB,EAChB,IAAI,CACL,CAAC;AACJ,CAAC,CAAC;AAnBW,QAAA,iBAAiB,qBAmB5B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateKey = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
/**
|
|
6
|
+
* Генерирует ключ для S3 из текущей даты и случайного UUID
|
|
7
|
+
* @returns string
|
|
8
|
+
*/
|
|
9
|
+
const generateKey = () => {
|
|
10
|
+
return `${Date.now()}/${(0, node_crypto_1.randomUUID)()}`;
|
|
11
|
+
};
|
|
12
|
+
exports.generateKey = generateKey;
|
|
13
|
+
//# sourceMappingURL=generate-key.fn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-key.fn.js","sourceRoot":"","sources":["../src/generate-key.fn.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAEzC;;;GAGG;AACI,MAAM,WAAW,GAAG,GAAW,EAAE;IACtC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,IAAA,wBAAU,GAAE,EAAE,CAAC;AACzC,CAAC,CAAC;AAFW,QAAA,WAAW,eAEtB"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
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("./decorators"), exports);
|
|
18
|
+
__exportStar(require("./module"), exports);
|
|
19
|
+
__exportStar(require("./client"), exports);
|
|
20
|
+
__exportStar(require("./generate-key.fn"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,2CAAyB;AACzB,2CAAyB;AACzB,oDAAkC"}
|
|
@@ -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("./s3-clients.plugin"), exports);
|
|
18
|
+
__exportStar(require("./s3-clients.service"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/module/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,sDAAoC;AACpC,uDAAqC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.S3ClientsConfig = void 0;
|
|
13
|
+
const common_1 = require("@rsdk/common");
|
|
14
|
+
const core_1 = require("@rsdk/core");
|
|
15
|
+
let S3ClientsConfig = class S3ClientsConfig extends core_1.Config {
|
|
16
|
+
defaultTTL;
|
|
17
|
+
};
|
|
18
|
+
exports.S3ClientsConfig = S3ClientsConfig;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, core_1.Property)('S3_PRESIGNED_URL_DEFAULT_TTL', new core_1.TimespanParser(), {
|
|
21
|
+
description: (0, common_1.text) `
|
|
22
|
+
Время валидности подписанных ссылок по умолчанию. Может быть
|
|
23
|
+
переопределено при создании отдельных ссылок.
|
|
24
|
+
`,
|
|
25
|
+
defaultValue: new common_1.Timespan(48, 'h'),
|
|
26
|
+
}),
|
|
27
|
+
__metadata("design:type", common_1.Timespan)
|
|
28
|
+
], S3ClientsConfig.prototype, "defaultTTL", void 0);
|
|
29
|
+
exports.S3ClientsConfig = S3ClientsConfig = __decorate([
|
|
30
|
+
(0, core_1.ConfigSection)()
|
|
31
|
+
], S3ClientsConfig);
|
|
32
|
+
//# sourceMappingURL=s3-clients.config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-clients.config.js","sourceRoot":"","sources":["../../src/module/s3-clients.config.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yCAA8C;AAC9C,qCAA6E;AAGtE,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,aAAM;IAQhC,UAAU,CAAY;CAChC,CAAA;AATY,0CAAe;AAQjB;IAPR,IAAA,eAAQ,EAAC,8BAA8B,EAAE,IAAI,qBAAc,EAAE,EAAE;QAC9D,WAAW,EAAE,IAAA,aAAI,EAAA;;;KAGhB;QACD,YAAY,EAAE,IAAI,iBAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;KACpC,CAAC;8BACoB,iBAAQ;mDAAC;0BARpB,eAAe;IAD3B,IAAA,oBAAa,GAAE;GACH,eAAe,CAS3B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { OnApplicationBootstrap } from '@nestjs/common';
|
|
2
|
+
import type { HealthIndicator } from '@rsdk/core';
|
|
3
|
+
import { CheckResult } from '@rsdk/core';
|
|
4
|
+
import { ILogger } from '@rsdk/logging';
|
|
5
|
+
import { S3ClientsService } from './s3-clients.service';
|
|
6
|
+
export declare class S3HealthIndicator implements HealthIndicator, OnApplicationBootstrap {
|
|
7
|
+
private readonly logger;
|
|
8
|
+
private readonly service;
|
|
9
|
+
private clients;
|
|
10
|
+
constructor(logger: ILogger, service: S3ClientsService);
|
|
11
|
+
onApplicationBootstrap(): void;
|
|
12
|
+
check(): Promise<CheckResult>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.S3HealthIndicator = void 0;
|
|
16
|
+
const core_1 = require("@rsdk/core");
|
|
17
|
+
const s3_clients_service_1 = require("./s3-clients.service");
|
|
18
|
+
let S3HealthIndicator = class S3HealthIndicator {
|
|
19
|
+
logger;
|
|
20
|
+
service;
|
|
21
|
+
clients;
|
|
22
|
+
constructor(logger, service) {
|
|
23
|
+
this.logger = logger;
|
|
24
|
+
this.service = service;
|
|
25
|
+
}
|
|
26
|
+
onApplicationBootstrap() {
|
|
27
|
+
this.clients = this.service.clients();
|
|
28
|
+
}
|
|
29
|
+
async check() {
|
|
30
|
+
if (!this.clients) {
|
|
31
|
+
throw new core_1.InternalException('S3 healthchecks are not ready!');
|
|
32
|
+
}
|
|
33
|
+
this.logger.trace('Checking S3 clients health...');
|
|
34
|
+
this.logger.trace(`Found ${this.clients.length} clients.`);
|
|
35
|
+
const results = await Promise.all([...this.clients].map(async (client) => ({
|
|
36
|
+
client: `${client.storageName}`,
|
|
37
|
+
isHealty: await client.isHealthy(),
|
|
38
|
+
})));
|
|
39
|
+
const isHealthy = results.every((r) => r.isHealty);
|
|
40
|
+
this.logger.trace(`Is up: ${isHealthy}`);
|
|
41
|
+
return isHealthy
|
|
42
|
+
? core_1.CheckResult.up({ results })
|
|
43
|
+
: core_1.CheckResult.down({ results });
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
exports.S3HealthIndicator = S3HealthIndicator;
|
|
47
|
+
exports.S3HealthIndicator = S3HealthIndicator = __decorate([
|
|
48
|
+
(0, core_1.Indicator)('s3'),
|
|
49
|
+
__param(0, (0, core_1.InjectLogger)(S3HealthIndicator)),
|
|
50
|
+
__metadata("design:paramtypes", [Object, s3_clients_service_1.S3ClientsService])
|
|
51
|
+
], S3HealthIndicator);
|
|
52
|
+
//# sourceMappingURL=s3-clients.indicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-clients.indicator.js","sourceRoot":"","sources":["../../src/module/s3-clients.indicator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAEA,qCAKoB;AAKpB,6DAAwD;AAGjD,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAMwB;IACjC;IAJX,OAAO,CAA6C;IAE5D,YACoD,MAAe,EAChD,OAAyB;QADQ,WAAM,GAAN,MAAM,CAAS;QAChD,YAAO,GAAP,OAAO,CAAkB;IACzC,CAAC;IAEJ,sBAAsB;QACpB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,wBAAiB,CAAC,gCAAgC,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,WAAW,CAAC,CAAC;QAE3D,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;YACvC,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,EAAE;YAC/B,QAAQ,EAAE,MAAM,MAAM,CAAC,SAAS,EAAE;SACnC,CAAC,CAAC,CACJ,CAAC;QAEF,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAEnD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;QAEzC,OAAO,SAAS;YACd,CAAC,CAAC,kBAAW,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;YAC7B,CAAC,CAAC,kBAAW,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACpC,CAAC;CACF,CAAA;AArCY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,gBAAS,EAAC,IAAI,CAAC;IAOX,WAAA,IAAA,mBAAY,EAAC,iBAAiB,CAAC,CAAA;6CACN,qCAAgB;GAPjC,iBAAiB,CAqC7B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.S3ClientsModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const s3_clients_indicator_1 = require("./s3-clients.indicator");
|
|
12
|
+
const s3_clients_service_1 = require("./s3-clients.service");
|
|
13
|
+
/**
|
|
14
|
+
* Вынесено в отдельный модуль для того чтобы не было дублирования внутри DI
|
|
15
|
+
* Но при этом чтобы не надо было делать `forRoot` в корне приложения
|
|
16
|
+
*/
|
|
17
|
+
let S3ClientsModule = class S3ClientsModule {
|
|
18
|
+
};
|
|
19
|
+
exports.S3ClientsModule = S3ClientsModule;
|
|
20
|
+
exports.S3ClientsModule = S3ClientsModule = __decorate([
|
|
21
|
+
(0, common_1.Global)(),
|
|
22
|
+
(0, common_1.Module)({
|
|
23
|
+
providers: [s3_clients_service_1.S3ClientsService, s3_clients_indicator_1.S3HealthIndicator],
|
|
24
|
+
exports: [s3_clients_service_1.S3ClientsService],
|
|
25
|
+
})
|
|
26
|
+
], S3ClientsModule);
|
|
27
|
+
//# sourceMappingURL=s3-clients.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-clients.module.js","sourceRoot":"","sources":["../../src/module/s3-clients.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAEhD,iEAA2D;AAC3D,6DAAwD;AAExD;;;GAGG;AAMI,IAAM,eAAe,GAArB,MAAM,eAAe;CAAG,CAAA;AAAlB,0CAAe;0BAAf,eAAe;IAL3B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,qCAAgB,EAAE,wCAAiB,CAAC;QAChD,OAAO,EAAE,CAAC,qCAAgB,CAAC;KAC5B,CAAC;GACW,eAAe,CAAG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import type { Constructor } from '@rsdk/common';
|
|
3
|
+
import type { AppropriateTransports, PlatformAppPlugin } from '@rsdk/core';
|
|
4
|
+
/**
|
|
5
|
+
* На данный момент требуется только для работы хелсчеков
|
|
6
|
+
*/
|
|
7
|
+
export declare class S3Plugin implements PlatformAppPlugin {
|
|
8
|
+
forTransports(): AppropriateTransports;
|
|
9
|
+
modules?(): (DynamicModule | Constructor)[];
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S3Plugin = void 0;
|
|
4
|
+
const s3_clients_module_1 = require("./s3-clients.module");
|
|
5
|
+
/**
|
|
6
|
+
* На данный момент требуется только для работы хелсчеков
|
|
7
|
+
*/
|
|
8
|
+
class S3Plugin {
|
|
9
|
+
forTransports() {
|
|
10
|
+
return 'any';
|
|
11
|
+
}
|
|
12
|
+
modules() {
|
|
13
|
+
return [s3_clients_module_1.S3ClientsModule];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.S3Plugin = S3Plugin;
|
|
17
|
+
//# sourceMappingURL=s3-clients.plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-clients.plugin.js","sourceRoot":"","sources":["../../src/module/s3-clients.plugin.ts"],"names":[],"mappings":";;;AAIA,2DAAsD;AAEtD;;GAEG;AACH,MAAa,QAAQ;IACnB,aAAa;QACX,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO;QACL,OAAO,CAAC,mCAAe,CAAC,CAAC;IAC3B,CAAC;CACF;AARD,4BAQC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { OnApplicationBootstrap } from '@nestjs/common';
|
|
2
|
+
import { ILogger } from '@rsdk/logging';
|
|
3
|
+
import { S3Client } from '../client/s3.client';
|
|
4
|
+
import { S3ClientsConfig } from './s3-clients.config';
|
|
5
|
+
/**
|
|
6
|
+
* Простое кеш хранилище внутри DI для кеширования на замену статике
|
|
7
|
+
*/
|
|
8
|
+
export declare class S3ClientsService implements OnApplicationBootstrap {
|
|
9
|
+
private readonly config;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
private readonly cache;
|
|
12
|
+
constructor(config: S3ClientsConfig, logger: ILogger);
|
|
13
|
+
/**
|
|
14
|
+
* Blocking application start if one of storages is unreachable.
|
|
15
|
+
*
|
|
16
|
+
* NOTE: Not sure that this is correct. Maybe it's better to
|
|
17
|
+
* print errors if exist and start app.
|
|
18
|
+
*/
|
|
19
|
+
onApplicationBootstrap(): Promise<void>;
|
|
20
|
+
clients(): Readonly<Readonly<S3Client>[]>;
|
|
21
|
+
resolveClient(storageUrl: URL, storageName: string, bucket: string): S3Client;
|
|
22
|
+
getClient(storageName: string, bucket: string): S3Client | undefined;
|
|
23
|
+
private getExisting;
|
|
24
|
+
private setCache;
|
|
25
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.S3ClientsService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const common_2 = require("@rsdk/common");
|
|
18
|
+
const core_1 = require("@rsdk/core");
|
|
19
|
+
const logging_1 = require("@rsdk/logging");
|
|
20
|
+
const s3_client_1 = require("../client/s3.client");
|
|
21
|
+
const s3_clients_config_1 = require("./s3-clients.config");
|
|
22
|
+
/**
|
|
23
|
+
* Простое кеш хранилище внутри DI для кеширования на замену статике
|
|
24
|
+
*/
|
|
25
|
+
let S3ClientsService = class S3ClientsService {
|
|
26
|
+
config;
|
|
27
|
+
logger;
|
|
28
|
+
cache = new Map();
|
|
29
|
+
constructor(config, logger) {
|
|
30
|
+
this.config = config;
|
|
31
|
+
this.logger = logger;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Blocking application start if one of storages is unreachable.
|
|
35
|
+
*
|
|
36
|
+
* NOTE: Not sure that this is correct. Maybe it's better to
|
|
37
|
+
* print errors if exist and start app.
|
|
38
|
+
*/
|
|
39
|
+
async onApplicationBootstrap() {
|
|
40
|
+
const clients = this.clients();
|
|
41
|
+
const interval = new common_2.Timespan(1, 's');
|
|
42
|
+
this.logger.debug(`Checking connections to ${clients.length} S3 buckets.`);
|
|
43
|
+
for (const client of clients) {
|
|
44
|
+
const metadata = {
|
|
45
|
+
storage: client.storageName,
|
|
46
|
+
bucket: client.bucket,
|
|
47
|
+
};
|
|
48
|
+
while (true) {
|
|
49
|
+
try {
|
|
50
|
+
this.logger.debug('Checking connection to bucket...', metadata);
|
|
51
|
+
await client.checkBucket();
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
common_2.Assert.isError(error);
|
|
56
|
+
this.logger.fatal(`Connection check failed. Retry in ${interval.millis()}ms`, error);
|
|
57
|
+
}
|
|
58
|
+
await (0, common_2.delay)(interval);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
clients() {
|
|
63
|
+
const clients = [];
|
|
64
|
+
for (const buckets of this.cache.values()) {
|
|
65
|
+
for (const client of buckets.values()) {
|
|
66
|
+
clients.push(client);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return clients;
|
|
70
|
+
}
|
|
71
|
+
resolveClient(storageUrl, storageName, bucket) {
|
|
72
|
+
const client = this.getExisting(storageName, bucket) ??
|
|
73
|
+
new s3_client_1.S3Client({
|
|
74
|
+
storageName,
|
|
75
|
+
bucket,
|
|
76
|
+
url: storageUrl,
|
|
77
|
+
defaultTTL: this.config.defaultTTL,
|
|
78
|
+
logger: logging_1.LoggerFactory.create(`s3/${storageName}/${bucket}`),
|
|
79
|
+
});
|
|
80
|
+
this.setCache(storageName, bucket, client);
|
|
81
|
+
return client;
|
|
82
|
+
}
|
|
83
|
+
getClient(storageName, bucket) {
|
|
84
|
+
return this.getExisting(storageName, bucket);
|
|
85
|
+
}
|
|
86
|
+
getExisting(storageName, bucket) {
|
|
87
|
+
return this.cache.get(storageName)?.get(bucket);
|
|
88
|
+
}
|
|
89
|
+
setCache(storageName, bucket, client) {
|
|
90
|
+
const existing = this.cache.get(storageName);
|
|
91
|
+
const updated = (existing || new Map())?.set(bucket, client);
|
|
92
|
+
this.cache.set(storageName, updated);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
exports.S3ClientsService = S3ClientsService;
|
|
96
|
+
exports.S3ClientsService = S3ClientsService = __decorate([
|
|
97
|
+
(0, common_1.Injectable)(),
|
|
98
|
+
__param(1, (0, core_1.InjectLogger)(S3ClientsService)),
|
|
99
|
+
__metadata("design:paramtypes", [s3_clients_config_1.S3ClientsConfig, Object])
|
|
100
|
+
], S3ClientsService);
|
|
101
|
+
//# sourceMappingURL=s3-clients.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-clients.service.js","sourceRoot":"","sources":["../../src/module/s3-clients.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DynamicModule } from '@nestjs/common';
|
|
2
|
+
export type S3ClientMetadataValue = {
|
|
3
|
+
storageName: string;
|
|
4
|
+
bucketName: string;
|
|
5
|
+
};
|
|
6
|
+
export declare class ModuleGenerator {
|
|
7
|
+
static createClientModuleDefinition(target: object, storageName: string, bucketName: string): DynamicModule;
|
|
8
|
+
private static createClientProvider;
|
|
9
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ModuleGenerator = void 0;
|
|
4
|
+
const common_1 = require("@rsdk/common");
|
|
5
|
+
const core_1 = require("@rsdk/core");
|
|
6
|
+
const metadata_1 = require("@rsdk/metadata");
|
|
7
|
+
const s3_clients_module_1 = require("./module/s3-clients.module");
|
|
8
|
+
const s3_clients_service_1 = require("./module/s3-clients.service");
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
const token_factories_1 = require("./token.factories");
|
|
11
|
+
class ModuleGenerator {
|
|
12
|
+
static createClientModuleDefinition(target, storageName, bucketName) {
|
|
13
|
+
const CONFIG_PROPERTY_ALIAS = (0, token_factories_1.getPropertyKey)(storageName);
|
|
14
|
+
const propertyToken = (0, core_1.getPropertyToken)(CONFIG_PROPERTY_ALIAS);
|
|
15
|
+
const provider = ModuleGenerator.createClientProvider(storageName, bucketName, propertyToken);
|
|
16
|
+
const moduleDefinition = {
|
|
17
|
+
global: true,
|
|
18
|
+
imports: [
|
|
19
|
+
core_1.PlatformConfigModule.forProperty(CONFIG_PROPERTY_ALIAS),
|
|
20
|
+
s3_clients_module_1.S3ClientsModule,
|
|
21
|
+
],
|
|
22
|
+
module: ModuleGenerator,
|
|
23
|
+
providers: [provider],
|
|
24
|
+
exports: [provider],
|
|
25
|
+
};
|
|
26
|
+
const key = (0, token_factories_1.getPropertyKey)(storageName);
|
|
27
|
+
core_1.ConfigMetadataRegistry.registerProperty(target, key, {
|
|
28
|
+
key: key,
|
|
29
|
+
parser: new core_1.UrlParser(),
|
|
30
|
+
description: (0, common_1.text) `
|
|
31
|
+
URL S3-совместимого хранилища (${storageName}),
|
|
32
|
+
включая access key и secret key (в username и password соответственно).
|
|
33
|
+
Например: https://{ACCESS_KEY}:{SECRET_KEY}@s3.domain.cloud
|
|
34
|
+
`,
|
|
35
|
+
expectedInEnv: false,
|
|
36
|
+
});
|
|
37
|
+
metadata_1.RsdkMetadata.add(target, { storageName, bucketName }, constants_1.S3_CLIENTS_RSDK_METADATA_SCOPE);
|
|
38
|
+
// AutodocMetadata.defineResolver(
|
|
39
|
+
// moduleDefinition,
|
|
40
|
+
// REDIS_CLIENTS_RSDK_METADATA_SCOPE,
|
|
41
|
+
// new RedisClientsAutodocResolver(),
|
|
42
|
+
// );
|
|
43
|
+
return moduleDefinition;
|
|
44
|
+
}
|
|
45
|
+
static createClientProvider(storageName, bucketName, propertyToken) {
|
|
46
|
+
const clientToken = (0, token_factories_1.getClientToken)(storageName, bucketName);
|
|
47
|
+
return {
|
|
48
|
+
provide: clientToken,
|
|
49
|
+
inject: [propertyToken, s3_clients_service_1.S3ClientsService, core_1.APP_SCOPE],
|
|
50
|
+
useFactory: (url, clients, appScope) => clients.resolveClient(url, storageName, `${appScope.toLowerCase()}.${bucketName}`),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.ModuleGenerator = ModuleGenerator;
|
|
55
|
+
//# sourceMappingURL=module.generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.generator.js","sourceRoot":"","sources":["../src/module.generator.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,qCAMoB;AACpB,6CAA8C;AAG9C,kEAA6D;AAC7D,oEAA+D;AAC/D,2CAA6D;AAC7D,uDAAmE;AAOnE,MAAa,eAAe;IAC1B,MAAM,CAAC,4BAA4B,CACjC,MAAc,EACd,WAAmB,EACnB,UAAkB;QAElB,MAAM,qBAAqB,GAAG,IAAA,gCAAc,EAAC,WAAW,CAAC,CAAC;QAC1D,MAAM,aAAa,GAAG,IAAA,uBAAgB,EAAC,qBAAqB,CAAC,CAAC;QAE9D,MAAM,QAAQ,GAAG,eAAe,CAAC,oBAAoB,CACnD,WAAW,EACX,UAAU,EACV,aAAa,CACd,CAAC;QAEF,MAAM,gBAAgB,GAAkB;YACtC,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,2BAAoB,CAAC,WAAW,CAAC,qBAAqB,CAAC;gBACvD,mCAAe;aAChB;YACD,MAAM,EAAE,eAAe;YACvB,SAAS,EAAE,CAAC,QAAQ,CAAC;YACrB,OAAO,EAAE,CAAC,QAAQ,CAAC;SACpB,CAAC;QAEF,MAAM,GAAG,GAAG,IAAA,gCAAc,EAAC,WAAW,CAAC,CAAC;QAExC,6BAAsB,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YACnD,GAAG,EAAE,GAAG;YACR,MAAM,EAAE,IAAI,gBAAS,EAAE;YACvB,WAAW,EAAE,IAAA,aAAI,EAAA;yCACkB,WAAW;;;OAG7C;YACD,aAAa,EAAE,KAAK;SACrB,CAAC,CAAC;QAEH,uBAAY,CAAC,GAAG,CACd,MAAM,EACN,EAAE,WAAW,EAAE,UAAU,EAAE,EAC3B,0CAA8B,CAC/B,CAAC;QAEF,kCAAkC;QAClC,sBAAsB;QACtB,uCAAuC;QACvC,uCAAuC;QACvC,KAAK;QAEL,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAEO,MAAM,CAAC,oBAAoB,CACjC,WAAmB,EACnB,UAAkB,EAClB,aAAqD;QAErD,MAAM,WAAW,GAAG,IAAA,gCAAc,EAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAE5D,OAAO;YACL,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,CAAC,aAAa,EAAE,qCAAgB,EAAE,gBAAS,CAAC;YACpD,UAAU,EAAE,CACV,GAAQ,EACR,OAAyB,EACzB,QAAgB,EACN,EAAE,CACZ,OAAO,CAAC,aAAa,CACnB,GAAG,EACH,WAAW,EACX,GAAG,QAAQ,CAAC,WAAW,EAAE,IAAI,UAAU,EAAE,CAC1C;SACJ,CAAC;IACJ,CAAC;CACF;AA5ED,0CA4EC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DocumentNode, DocumentResolver } from '@rsdk/autodoc.protocol';
|
|
2
|
+
import type { RsdkMetadataProvider } from '@rsdk/metadata';
|
|
3
|
+
import type { Promisable } from 'type-fest';
|
|
4
|
+
export declare class S3ClientsAutodocResolver implements DocumentResolver {
|
|
5
|
+
getNode(rsdkMetadata: RsdkMetadataProvider): Promisable<DocumentNode | null>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S3ClientsAutodocResolver = void 0;
|
|
4
|
+
const autodoc_protocol_1 = require("@rsdk/autodoc.protocol");
|
|
5
|
+
const constants_1 = require("./constants");
|
|
6
|
+
class S3ClientsAutodocResolver {
|
|
7
|
+
getNode(rsdkMetadata) {
|
|
8
|
+
const resources = rsdkMetadata.get(constants_1.S3_CLIENTS_RSDK_METADATA_SCOPE);
|
|
9
|
+
if (!resources) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return new autodoc_protocol_1.Composite(new autodoc_protocol_1.Table(resources.map(({ value: { storageName, bucketName } }) => ({
|
|
13
|
+
storageName,
|
|
14
|
+
bucketName,
|
|
15
|
+
}))), 'S3 clients');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.S3ClientsAutodocResolver = S3ClientsAutodocResolver;
|
|
19
|
+
//# sourceMappingURL=s3-clients.autodoc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-clients.autodoc.js","sourceRoot":"","sources":["../src/s3-clients.autodoc.ts"],"names":[],"mappings":";;;AACA,6DAA0D;AAI1D,2CAA6D;AAG7D,MAAa,wBAAwB;IACnC,OAAO,CAAC,YAAkC;QACxC,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAChC,0CAA8B,CAC/B,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,4BAAS,CAClB,IAAI,wBAAK,CACP,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YACzD,WAAW;YACX,UAAU;SACX,CAAC,CAAC,CACJ,EACD,YAAY,CACb,CAAC;IACJ,CAAC;CACF;AApBD,4DAoBC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPropertyKey = exports.getClientToken = void 0;
|
|
4
|
+
const common_1 = require("@rsdk/common");
|
|
5
|
+
const getClientToken = (storageName, bucketName) => `S3_CLIENT_${storageName}:${bucketName}`;
|
|
6
|
+
exports.getClientToken = getClientToken;
|
|
7
|
+
const getPropertyKey = (storageName) => `S3_URL_${common_1.Case.toUpperSnake(storageName)}`;
|
|
8
|
+
exports.getPropertyKey = getPropertyKey;
|
|
9
|
+
//# sourceMappingURL=token.factories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.factories.js","sourceRoot":"","sources":["../src/token.factories.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AAE7B,MAAM,cAAc,GAAG,CAC5B,WAAmB,EACnB,UAAkB,EACV,EAAE,CAAC,aAAa,WAAW,IAAI,UAAU,EAAE,CAAC;AAHzC,QAAA,cAAc,kBAG2B;AAE/C,MAAM,cAAc,GAAG,CAAC,WAAmB,EAAU,EAAE,CAC5D,UAAU,aAAI,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC;AADhC,QAAA,cAAc,kBACkB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rsdk/s3",
|
|
3
|
+
"version": "4.2.0-next.0",
|
|
4
|
+
"description": "Toolkit for S3 interface",
|
|
5
|
+
"license": "Apache License 2.0",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"*.md"
|
|
10
|
+
],
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"aws-sdk": "^2.1468.0",
|
|
16
|
+
"mime-types": "^2.1.35"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@nestjs/common": "^10.0.0",
|
|
20
|
+
"@rsdk/autodoc.protocol": "^4.2.0-next.0",
|
|
21
|
+
"@rsdk/common": "^4.2.0-next.0",
|
|
22
|
+
"@rsdk/common.node": "^4.2.0-next.0",
|
|
23
|
+
"@rsdk/core": "^4.2.0-next.0",
|
|
24
|
+
"@rsdk/logging": "^4.2.0-next.0",
|
|
25
|
+
"@rsdk/metadata": "^4.2.0-next.0",
|
|
26
|
+
"reflect-metadata": "^0.1.13",
|
|
27
|
+
"rxjs": "^7.0.0"
|
|
28
|
+
},
|
|
29
|
+
"gitHead": "e4b95e1971841f8492f9df493fa4fe4f13f9bb5f"
|
|
30
|
+
}
|