@qrvey/object-storage 0.0.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 +20 -0
- package/dist/cjs/index.js +291 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/blobStorage.service-Q2W6LO3S.mjs +105 -0
- package/dist/esm/blobStorage.service-Q2W6LO3S.mjs.map +1 -0
- package/dist/esm/chunk-JHXQKOVY.mjs +10 -0
- package/dist/esm/chunk-JHXQKOVY.mjs.map +1 -0
- package/dist/esm/index.mjs +59 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/s3Storage.service-OZGBAWBM.mjs +100 -0
- package/dist/esm/s3Storage.service-OZGBAWBM.mjs.map +1 -0
- package/dist/types/index.d.ts +45 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @qrvey/object-storage
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
The `@qrvey/object-storage` package provides a unified interface for ...
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
You can install the package using npm or yarn:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @qrvey/object-storage
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Or with yarn:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
yarn add @qrvey/object-storage
|
|
20
|
+
```
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var storageBlob = require('@azure/storage-blob');
|
|
4
|
+
var clientS3 = require('@aws-sdk/client-s3');
|
|
5
|
+
var s3RequestPresigner = require('@aws-sdk/s3-request-presigner');
|
|
6
|
+
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
9
|
+
var __knownSymbol = (name, symbol) => {
|
|
10
|
+
if (symbol = Symbol[name])
|
|
11
|
+
return symbol;
|
|
12
|
+
throw Error("Symbol." + name + " is not defined");
|
|
13
|
+
};
|
|
14
|
+
var __esm = (fn, res) => function __init() {
|
|
15
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
16
|
+
};
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
20
|
+
};
|
|
21
|
+
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
|
|
22
|
+
|
|
23
|
+
// src/services/storage/blob/blobStorage.service.ts
|
|
24
|
+
var blobStorage_service_exports = {};
|
|
25
|
+
__export(blobStorage_service_exports, {
|
|
26
|
+
BlobStorageService: () => BlobStorageService
|
|
27
|
+
});
|
|
28
|
+
var BlobStorageService;
|
|
29
|
+
var init_blobStorage_service = __esm({
|
|
30
|
+
"src/services/storage/blob/blobStorage.service.ts"() {
|
|
31
|
+
BlobStorageService = class {
|
|
32
|
+
constructor(containerName) {
|
|
33
|
+
this.containerName = containerName;
|
|
34
|
+
this.blobServiceClient = storageBlob.BlobServiceClient.fromConnectionString(
|
|
35
|
+
process.env.AZURE_STORAGE_CONNECTION_STRING
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
async list() {
|
|
39
|
+
const list = [];
|
|
40
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
41
|
+
this.containerName
|
|
42
|
+
);
|
|
43
|
+
try {
|
|
44
|
+
for (var iter = __forAwait(containerClient.listBlobsFlat()), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
45
|
+
const containerItem = temp.value;
|
|
46
|
+
list.push(containerItem.name);
|
|
47
|
+
}
|
|
48
|
+
} catch (temp) {
|
|
49
|
+
error = [temp];
|
|
50
|
+
} finally {
|
|
51
|
+
try {
|
|
52
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
53
|
+
} finally {
|
|
54
|
+
if (error)
|
|
55
|
+
throw error[0];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return new Promise((resolve) => resolve({ keys: list }));
|
|
59
|
+
}
|
|
60
|
+
getObject(blobName) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
try {
|
|
63
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
64
|
+
this.containerName
|
|
65
|
+
);
|
|
66
|
+
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
|
67
|
+
blockBlobClient.download(0).then((downloadBlockBlobResponse) => {
|
|
68
|
+
return resolve({
|
|
69
|
+
body: downloadBlockBlobResponse.readableStreamBody,
|
|
70
|
+
metadata: {},
|
|
71
|
+
contentType: "",
|
|
72
|
+
contentLength: 0
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
} catch (error) {
|
|
76
|
+
return reject(error);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async getSignedUrl(blobName, expiresInMinutes) {
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
try {
|
|
83
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
84
|
+
this.containerName
|
|
85
|
+
);
|
|
86
|
+
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
|
87
|
+
const startDate = /* @__PURE__ */ new Date();
|
|
88
|
+
const expiryDate = new Date(startDate);
|
|
89
|
+
expiryDate.setMinutes(
|
|
90
|
+
startDate.getMinutes() + expiresInMinutes
|
|
91
|
+
);
|
|
92
|
+
blockBlobClient.generateSasUrl({
|
|
93
|
+
permissions: storageBlob.BlobSASPermissions.parse("r"),
|
|
94
|
+
startsOn: startDate,
|
|
95
|
+
expiresOn: expiryDate
|
|
96
|
+
}).then((sasUrl) => resolve(sasUrl));
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return reject(error);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
async upload(blobName, body, metadata) {
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
try {
|
|
105
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
106
|
+
this.containerName
|
|
107
|
+
);
|
|
108
|
+
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
|
109
|
+
blockBlobClient.uploadStream(body).then(() => resolve({ key: blobName }));
|
|
110
|
+
} catch (error) {
|
|
111
|
+
return reject(error);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
delete(blobName) {
|
|
116
|
+
return new Promise((resolve, reject) => {
|
|
117
|
+
try {
|
|
118
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
119
|
+
this.containerName
|
|
120
|
+
);
|
|
121
|
+
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
|
122
|
+
blockBlobClient.delete().then(() => resolve(true));
|
|
123
|
+
} catch (error) {
|
|
124
|
+
return reject(error);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// src/services/storage/s3/s3Storage.service.ts
|
|
133
|
+
var s3Storage_service_exports = {};
|
|
134
|
+
__export(s3Storage_service_exports, {
|
|
135
|
+
S3StorageService: () => S3StorageService
|
|
136
|
+
});
|
|
137
|
+
var S3StorageService;
|
|
138
|
+
var init_s3Storage_service = __esm({
|
|
139
|
+
"src/services/storage/s3/s3Storage.service.ts"() {
|
|
140
|
+
S3StorageService = class {
|
|
141
|
+
constructor(bucketName) {
|
|
142
|
+
this.bucketName = bucketName;
|
|
143
|
+
this.s3Client = new clientS3.S3Client({});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Lists all objects in the S3 bucket.
|
|
147
|
+
* @returns A promise that resolves to a list of object keys.
|
|
148
|
+
*/
|
|
149
|
+
async list() {
|
|
150
|
+
const allKeys = [];
|
|
151
|
+
let continuationToken = void 0;
|
|
152
|
+
do {
|
|
153
|
+
const command = new clientS3.ListObjectsV2Command({
|
|
154
|
+
Bucket: this.bucketName,
|
|
155
|
+
ContinuationToken: continuationToken
|
|
156
|
+
});
|
|
157
|
+
const response = await this.s3Client.send(command);
|
|
158
|
+
if (response.Contents) {
|
|
159
|
+
for (const item of response.Contents) {
|
|
160
|
+
if (item.Key)
|
|
161
|
+
allKeys.push(item.Key);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
continuationToken = response.NextContinuationToken;
|
|
165
|
+
} while (continuationToken);
|
|
166
|
+
return { keys: allKeys };
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Retrieves an object from the S3 bucket.
|
|
170
|
+
* @param key - The key of the object to retrieve.
|
|
171
|
+
* @returns A promise that resolves to the content of the file.
|
|
172
|
+
*/
|
|
173
|
+
async getObject(key) {
|
|
174
|
+
var _a, _b;
|
|
175
|
+
const command = new clientS3.GetObjectCommand({
|
|
176
|
+
Bucket: this.bucketName,
|
|
177
|
+
Key: key
|
|
178
|
+
});
|
|
179
|
+
const response = await this.s3Client.send(command);
|
|
180
|
+
return {
|
|
181
|
+
body: response.Body,
|
|
182
|
+
metadata: (_a = response.Metadata) != null ? _a : {},
|
|
183
|
+
contentType: (_b = response.ContentType) != null ? _b : "",
|
|
184
|
+
contentLength: response.ContentLength
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Generates a signed URL for accessing an object in the S3 bucket.
|
|
189
|
+
* @param key - The key of the object.
|
|
190
|
+
* @param expiresInMinutes - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.
|
|
191
|
+
* @returns A promise that resolves to the signed URL.
|
|
192
|
+
*/
|
|
193
|
+
getSignedUrl(key, expiresInMinutes = 60) {
|
|
194
|
+
const expiresIn = expiresInMinutes * 60;
|
|
195
|
+
const command = new clientS3.GetObjectCommand({
|
|
196
|
+
Bucket: this.bucketName,
|
|
197
|
+
Key: key
|
|
198
|
+
});
|
|
199
|
+
return s3RequestPresigner.getSignedUrl(this.s3Client, command, { expiresIn });
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Uploads an object to the S3 bucket.
|
|
203
|
+
* @param key - The key of the object to upload.
|
|
204
|
+
* @param body - The content of the object to upload.
|
|
205
|
+
* @param metadata - Optional metadata to associate with the object.
|
|
206
|
+
* @returns A promise that resolves to the response containing the key of the uploaded object.
|
|
207
|
+
*/
|
|
208
|
+
async upload(key, body, metadata) {
|
|
209
|
+
const command = new clientS3.PutObjectCommand({
|
|
210
|
+
Bucket: this.bucketName,
|
|
211
|
+
Key: key,
|
|
212
|
+
Body: body,
|
|
213
|
+
Metadata: metadata
|
|
214
|
+
});
|
|
215
|
+
await this.s3Client.send(command);
|
|
216
|
+
return { key };
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Deletes an object from the S3 bucket.
|
|
220
|
+
* @param key - The key of the object to delete.
|
|
221
|
+
* @returns A promise that resolves to true if the object was deleted successfully.
|
|
222
|
+
*/
|
|
223
|
+
async delete(key) {
|
|
224
|
+
const command = new clientS3.DeleteObjectCommand({
|
|
225
|
+
Bucket: this.bucketName,
|
|
226
|
+
Key: key
|
|
227
|
+
});
|
|
228
|
+
await this.s3Client.send(command);
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// src/services/objectStorageFactory.service.ts
|
|
236
|
+
var ObjectStorageFactory = class {
|
|
237
|
+
static async instance(bucketName) {
|
|
238
|
+
var _a;
|
|
239
|
+
const isBlobStorageService = ((_a = process.env.OBJECT_STORAGE_SERVICE) == null ? void 0 : _a.toLowerCase()) === "azure_blob_storage";
|
|
240
|
+
let ObjectStorageService2;
|
|
241
|
+
if (isBlobStorageService) {
|
|
242
|
+
const module = await Promise.resolve().then(() => (init_blobStorage_service(), blobStorage_service_exports));
|
|
243
|
+
ObjectStorageService2 = module.BlobStorageService;
|
|
244
|
+
} else {
|
|
245
|
+
const module = await Promise.resolve().then(() => (init_s3Storage_service(), s3Storage_service_exports));
|
|
246
|
+
ObjectStorageService2 = module.S3StorageService;
|
|
247
|
+
}
|
|
248
|
+
return new ObjectStorageService2(bucketName);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// src/services/objectStorage.service.ts
|
|
253
|
+
var ObjectStorageService = class _ObjectStorageService {
|
|
254
|
+
constructor(bucketName) {
|
|
255
|
+
_ObjectStorageService.bucketName = bucketName;
|
|
256
|
+
}
|
|
257
|
+
static async getObjectStorageServiceInstance(bucketName = _ObjectStorageService.bucketName) {
|
|
258
|
+
if (!bucketName)
|
|
259
|
+
throw new Error("Bucket name not provided or not valid value");
|
|
260
|
+
return ObjectStorageFactory.instance(bucketName);
|
|
261
|
+
}
|
|
262
|
+
static async list(bucketName) {
|
|
263
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
264
|
+
bucketName
|
|
265
|
+
).then((instance) => instance.list());
|
|
266
|
+
}
|
|
267
|
+
static async getObject(key, bucketName) {
|
|
268
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
269
|
+
bucketName
|
|
270
|
+
).then((instance) => instance.getObject(key));
|
|
271
|
+
}
|
|
272
|
+
static async getSignedUrl(key, expiresInMinutes, bucketName) {
|
|
273
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
274
|
+
bucketName
|
|
275
|
+
).then((instance) => instance.getSignedUrl(key, expiresInMinutes));
|
|
276
|
+
}
|
|
277
|
+
static async upload(key, body, metadata, bucketName) {
|
|
278
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
279
|
+
bucketName
|
|
280
|
+
).then((instance) => instance.upload(key, body, metadata));
|
|
281
|
+
}
|
|
282
|
+
static async delete(key, bucketName) {
|
|
283
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
284
|
+
bucketName
|
|
285
|
+
).then((instance) => instance.delete(key));
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
exports.ObjectStorageService = ObjectStorageService;
|
|
290
|
+
//# sourceMappingURL=out.js.map
|
|
291
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/storage/blob/blobStorage.service.ts","../../src/services/storage/s3/s3Storage.service.ts","../../src/services/objectStorageFactory.service.ts","../../src/services/objectStorage.service.ts"],"names":["ObjectStorageService"],"mappings":"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","sourcesContent":["import { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n ListResponse,\n UploadResponse,\n GetObjectResponse,\n} from '../../../types';\nimport { BlobServiceClient, BlobSASPermissions } from '@azure/storage-blob';\n\nimport { Readable } from 'stream';\nexport class BlobStorageService implements IObjectStorage {\n private blobServiceClient: BlobServiceClient;\n private containerName: string;\n constructor(containerName: string) {\n this.containerName = containerName;\n this.blobServiceClient = BlobServiceClient.fromConnectionString(\n process.env.AZURE_STORAGE_CONNECTION_STRING!,\n );\n }\n async list(): Promise<ListResponse> {\n const list: string[] = [];\n const containerClient = this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n for await (const containerItem of containerClient.listBlobsFlat()) {\n list.push(containerItem.name);\n }\n return new Promise((resolve) => resolve({ keys: list }));\n }\n\n getObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .download(0)\n .then((downloadBlockBlobResponse) => {\n return resolve({\n body: downloadBlockBlobResponse.readableStreamBody as Readable,\n metadata: {},\n contentType: '',\n contentLength: 0,\n });\n });\n } catch (error) {\n return reject(error);\n }\n });\n }\n async getSignedUrl(\n blobName: string,\n expiresInMinutes: number,\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n const startDate = new Date();\n const expiryDate = new Date(startDate);\n expiryDate.setMinutes(\n startDate.getMinutes() + expiresInMinutes,\n );\n\n blockBlobClient\n .generateSasUrl({\n permissions: BlobSASPermissions.parse('r'),\n startsOn: startDate,\n expiresOn: expiryDate,\n })\n .then((sasUrl) => resolve(sasUrl));\n } catch (error) {\n return reject(error);\n }\n });\n }\n async upload(\n blobName: string,\n body: FileContent,\n metadata?: { [key: string]: string } | undefined,\n ): Promise<UploadResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .uploadStream(body as Readable)\n .then(() => resolve({ key: blobName }));\n } catch (error) {\n return reject(error);\n }\n });\n }\n delete(blobName: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient.delete().then(() => resolve(true));\n } catch (error) {\n return reject(error);\n }\n });\n }\n}\n","import {\n DeleteObjectCommand,\n GetObjectCommand,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n PutObjectCommand,\n S3Client,\n} from '@aws-sdk/client-s3';\nimport { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n GetObjectResponse,\n ListResponse,\n UploadResponse,\n} from '../../../types';\nimport { Readable } from 'stream';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\n\nexport class S3StorageService implements IObjectStorage {\n private s3Client: S3Client;\n private bucketName: string;\n\n constructor(bucketName: string) {\n this.bucketName = bucketName;\n this.s3Client = new S3Client({});\n }\n\n /**\n * Lists all objects in the S3 bucket.\n * @returns A promise that resolves to a list of object keys.\n */\n\n async list(): Promise<ListResponse> {\n const allKeys: string[] = [];\n\n let continuationToken: string | undefined = undefined;\n do {\n const command: ListObjectsV2Command = new ListObjectsV2Command({\n Bucket: this.bucketName,\n ContinuationToken: continuationToken,\n });\n\n const response: ListObjectsV2CommandOutput =\n await this.s3Client.send(command);\n if (response.Contents) {\n for (const item of response.Contents) {\n if (item.Key) allKeys.push(item.Key);\n }\n }\n\n continuationToken = response.NextContinuationToken;\n } while (continuationToken);\n\n return { keys: allKeys };\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getObject(key: string): Promise<GetObjectResponse> {\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return {\n body: response.Body as Readable,\n metadata: response.Metadata ?? {},\n contentType: response.ContentType ?? '',\n contentLength: response.ContentLength as number,\n };\n }\n\n /**\n * Generates a signed URL for accessing an object in the S3 bucket.\n * @param key - The key of the object.\n * @param expiresInMinutes - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n getSignedUrl(key: string, expiresInMinutes: number = 60): Promise<string> {\n const expiresIn = expiresInMinutes * 60;\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n return getSignedUrl(this.s3Client, command, { expiresIn });\n }\n\n /**\n * Uploads an object to the S3 bucket.\n * @param key - The key of the object to upload.\n * @param body - The content of the object to upload.\n * @param metadata - Optional metadata to associate with the object.\n * @returns A promise that resolves to the response containing the key of the uploaded object.\n */\n async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n ): Promise<UploadResponse> {\n const command = new PutObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n Body: body,\n Metadata: metadata,\n });\n await this.s3Client.send(command);\n return { key };\n }\n\n /**\n * Deletes an object from the S3 bucket.\n * @param key - The key of the object to delete.\n * @returns A promise that resolves to true if the object was deleted successfully.\n */\n async delete(key: string): Promise<boolean> {\n const command = new DeleteObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n await this.s3Client.send(command);\n return true;\n }\n}\n","import { IObjectStorage } from '../interfaces';\nexport class ObjectStorageFactory {\n static async instance(bucketName: string): Promise<IObjectStorage> {\n const isBlobStorageService =\n process.env.OBJECT_STORAGE_SERVICE?.toLowerCase() ===\n 'azure_blob_storage';\n\n let ObjectStorageService: new (bucketName: string) => IObjectStorage;\n\n if (isBlobStorageService) {\n const module = await import('./storage/blob/blobStorage.service');\n ObjectStorageService = module.BlobStorageService;\n } else {\n const module = await import('./storage/s3/s3Storage.service');\n ObjectStorageService = module.S3StorageService;\n }\n\n return new ObjectStorageService(bucketName);\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { IObjectStorage } from '../interfaces';\nimport {\n ListResponse,\n FileContent,\n UploadResponse,\n GetObjectResponse,\n} from '../types';\nimport { ObjectStorageFactory } from '../services/objectStorageFactory.service';\n\nexport default class ObjectStorageService {\n static bucketName: string;\n\n constructor(bucketName: string) {\n ObjectStorageService.bucketName = bucketName;\n }\n\n static async getObjectStorageServiceInstance(\n bucketName: string = ObjectStorageService.bucketName,\n ): Promise<IObjectStorage> {\n if (!bucketName)\n throw new Error('Bucket name not provided or not valid value');\n return ObjectStorageFactory.instance(bucketName);\n }\n\n static async list(bucketName?: string): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.list());\n }\n\n static async getObject(\n key: string,\n bucketName?: string,\n ): Promise<GetObjectResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getObject(key));\n }\n\n static async getSignedUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<string> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getSignedUrl(key, expiresInMinutes));\n }\n\n static async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n bucketName?: string,\n ): Promise<UploadResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.upload(key, body, metadata));\n }\n\n static async delete(key: string, bucketName?: string): Promise<boolean> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.delete(key));\n }\n}\n"]}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { __forAwait } from './chunk-JHXQKOVY.mjs';
|
|
2
|
+
import { BlobServiceClient, BlobSASPermissions } from '@azure/storage-blob';
|
|
3
|
+
|
|
4
|
+
var BlobStorageService = class {
|
|
5
|
+
constructor(containerName) {
|
|
6
|
+
this.containerName = containerName;
|
|
7
|
+
this.blobServiceClient = BlobServiceClient.fromConnectionString(
|
|
8
|
+
process.env.AZURE_STORAGE_CONNECTION_STRING
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
async list() {
|
|
12
|
+
const list = [];
|
|
13
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
14
|
+
this.containerName
|
|
15
|
+
);
|
|
16
|
+
try {
|
|
17
|
+
for (var iter = __forAwait(containerClient.listBlobsFlat()), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
18
|
+
const containerItem = temp.value;
|
|
19
|
+
list.push(containerItem.name);
|
|
20
|
+
}
|
|
21
|
+
} catch (temp) {
|
|
22
|
+
error = [temp];
|
|
23
|
+
} finally {
|
|
24
|
+
try {
|
|
25
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
26
|
+
} finally {
|
|
27
|
+
if (error)
|
|
28
|
+
throw error[0];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return new Promise((resolve) => resolve({ keys: list }));
|
|
32
|
+
}
|
|
33
|
+
getObject(blobName) {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
try {
|
|
36
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
37
|
+
this.containerName
|
|
38
|
+
);
|
|
39
|
+
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
|
40
|
+
blockBlobClient.download(0).then((downloadBlockBlobResponse) => {
|
|
41
|
+
return resolve({
|
|
42
|
+
body: downloadBlockBlobResponse.readableStreamBody,
|
|
43
|
+
metadata: {},
|
|
44
|
+
contentType: "",
|
|
45
|
+
contentLength: 0
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return reject(error);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async getSignedUrl(blobName, expiresInMinutes) {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
try {
|
|
56
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
57
|
+
this.containerName
|
|
58
|
+
);
|
|
59
|
+
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
|
60
|
+
const startDate = /* @__PURE__ */ new Date();
|
|
61
|
+
const expiryDate = new Date(startDate);
|
|
62
|
+
expiryDate.setMinutes(
|
|
63
|
+
startDate.getMinutes() + expiresInMinutes
|
|
64
|
+
);
|
|
65
|
+
blockBlobClient.generateSasUrl({
|
|
66
|
+
permissions: BlobSASPermissions.parse("r"),
|
|
67
|
+
startsOn: startDate,
|
|
68
|
+
expiresOn: expiryDate
|
|
69
|
+
}).then((sasUrl) => resolve(sasUrl));
|
|
70
|
+
} catch (error) {
|
|
71
|
+
return reject(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async upload(blobName, body, metadata) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
try {
|
|
78
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
79
|
+
this.containerName
|
|
80
|
+
);
|
|
81
|
+
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
|
82
|
+
blockBlobClient.uploadStream(body).then(() => resolve({ key: blobName }));
|
|
83
|
+
} catch (error) {
|
|
84
|
+
return reject(error);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
delete(blobName) {
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
try {
|
|
91
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
92
|
+
this.containerName
|
|
93
|
+
);
|
|
94
|
+
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
|
95
|
+
blockBlobClient.delete().then(() => resolve(true));
|
|
96
|
+
} catch (error) {
|
|
97
|
+
return reject(error);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export { BlobStorageService };
|
|
104
|
+
//# sourceMappingURL=out.js.map
|
|
105
|
+
//# sourceMappingURL=blobStorage.service-Q2W6LO3S.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/storage/blob/blobStorage.service.ts"],"names":[],"mappings":";;;;;AAOA,SAAS,mBAAmB,0BAA0B;AAG/C,IAAM,qBAAN,MAAmD;AAAA,EAGtD,YAAY,eAAuB;AAC/B,SAAK,gBAAgB;AACrB,SAAK,oBAAoB,kBAAkB;AAAA,MACvC,QAAQ,IAAI;AAAA,IAChB;AAAA,EACJ;AAAA,EACA,MAAM,OAA8B;AAChC,UAAM,OAAiB,CAAC;AACxB,UAAM,kBAAkB,KAAK,kBAAkB;AAAA,MAC3C,KAAK;AAAA,IACT;AACA;AAAA,iCAAkC,gBAAgB,cAAc,IAAhE,0EAAmE;AAAxD,cAAM,gBAAjB;AACI,aAAK,KAAK,cAAc,IAAI;AAAA,MAChC;AAAA,aAFA,MAxBR;AAwBQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,WAAO,IAAI,QAAQ,CAAC,YAAY,QAAQ,EAAE,MAAM,KAAK,CAAC,CAAC;AAAA,EAC3D;AAAA,EAEA,UAAU,UAA8C;AACpD,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,UAAI;AACA,cAAM,kBACF,KAAK,kBAAkB;AAAA,UACnB,KAAK;AAAA,QACT;AACJ,cAAM,kBACF,gBAAgB,mBAAmB,QAAQ;AAC/C,wBACK,SAAS,CAAC,EACV,KAAK,CAAC,8BAA8B;AACjC,iBAAO,QAAQ;AAAA,YACX,MAAM,0BAA0B;AAAA,YAChC,UAAU,CAAC;AAAA,YACX,aAAa;AAAA,YACb,eAAe;AAAA,UACnB,CAAC;AAAA,QACL,CAAC;AAAA,MACT,SAAS,OAAO;AACZ,eAAO,OAAO,KAAK;AAAA,MACvB;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EACA,MAAM,aACF,UACA,kBACe;AACf,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,UAAI;AACA,cAAM,kBACF,KAAK,kBAAkB;AAAA,UACnB,KAAK;AAAA,QACT;AACJ,cAAM,kBACF,gBAAgB,mBAAmB,QAAQ;AAE/C,cAAM,YAAY,oBAAI,KAAK;AAC3B,cAAM,aAAa,IAAI,KAAK,SAAS;AACrC,mBAAW;AAAA,UACP,UAAU,WAAW,IAAI;AAAA,QAC7B;AAEA,wBACK,eAAe;AAAA,UACZ,aAAa,mBAAmB,MAAM,GAAG;AAAA,UACzC,UAAU;AAAA,UACV,WAAW;AAAA,QACf,CAAC,EACA,KAAK,CAAC,WAAW,QAAQ,MAAM,CAAC;AAAA,MACzC,SAAS,OAAO;AACZ,eAAO,OAAO,KAAK;AAAA,MACvB;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EACA,MAAM,OACF,UACA,MACA,UACuB;AACvB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,UAAI;AACA,cAAM,kBACF,KAAK,kBAAkB;AAAA,UACnB,KAAK;AAAA,QACT;AACJ,cAAM,kBACF,gBAAgB,mBAAmB,QAAQ;AAC/C,wBACK,aAAa,IAAgB,EAC7B,KAAK,MAAM,QAAQ,EAAE,KAAK,SAAS,CAAC,CAAC;AAAA,MAC9C,SAAS,OAAO;AACZ,eAAO,OAAO,KAAK;AAAA,MACvB;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EACA,OAAO,UAAoC;AACvC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,UAAI;AACA,cAAM,kBACF,KAAK,kBAAkB;AAAA,UACnB,KAAK;AAAA,QACT;AACJ,cAAM,kBACF,gBAAgB,mBAAmB,QAAQ;AAC/C,wBAAgB,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAI,CAAC;AAAA,MACrD,SAAS,OAAO;AACZ,eAAO,OAAO,KAAK;AAAA,MACvB;AAAA,IACJ,CAAC;AAAA,EACL;AACJ","sourcesContent":["import { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n ListResponse,\n UploadResponse,\n GetObjectResponse,\n} from '../../../types';\nimport { BlobServiceClient, BlobSASPermissions } from '@azure/storage-blob';\n\nimport { Readable } from 'stream';\nexport class BlobStorageService implements IObjectStorage {\n private blobServiceClient: BlobServiceClient;\n private containerName: string;\n constructor(containerName: string) {\n this.containerName = containerName;\n this.blobServiceClient = BlobServiceClient.fromConnectionString(\n process.env.AZURE_STORAGE_CONNECTION_STRING!,\n );\n }\n async list(): Promise<ListResponse> {\n const list: string[] = [];\n const containerClient = this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n for await (const containerItem of containerClient.listBlobsFlat()) {\n list.push(containerItem.name);\n }\n return new Promise((resolve) => resolve({ keys: list }));\n }\n\n getObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .download(0)\n .then((downloadBlockBlobResponse) => {\n return resolve({\n body: downloadBlockBlobResponse.readableStreamBody as Readable,\n metadata: {},\n contentType: '',\n contentLength: 0,\n });\n });\n } catch (error) {\n return reject(error);\n }\n });\n }\n async getSignedUrl(\n blobName: string,\n expiresInMinutes: number,\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n const startDate = new Date();\n const expiryDate = new Date(startDate);\n expiryDate.setMinutes(\n startDate.getMinutes() + expiresInMinutes,\n );\n\n blockBlobClient\n .generateSasUrl({\n permissions: BlobSASPermissions.parse('r'),\n startsOn: startDate,\n expiresOn: expiryDate,\n })\n .then((sasUrl) => resolve(sasUrl));\n } catch (error) {\n return reject(error);\n }\n });\n }\n async upload(\n blobName: string,\n body: FileContent,\n metadata?: { [key: string]: string } | undefined,\n ): Promise<UploadResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .uploadStream(body as Readable)\n .then(() => resolve({ key: blobName }));\n } catch (error) {\n return reject(error);\n }\n });\n }\n delete(blobName: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient.delete().then(() => resolve(true));\n } catch (error) {\n return reject(error);\n }\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var __knownSymbol = (name, symbol) => {
|
|
2
|
+
if (symbol = Symbol[name])
|
|
3
|
+
return symbol;
|
|
4
|
+
throw Error("Symbol." + name + " is not defined");
|
|
5
|
+
};
|
|
6
|
+
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
|
|
7
|
+
|
|
8
|
+
export { __forAwait };
|
|
9
|
+
//# sourceMappingURL=out.js.map
|
|
10
|
+
//# sourceMappingURL=chunk-JHXQKOVY.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","sourcesContent":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import './chunk-JHXQKOVY.mjs';
|
|
2
|
+
|
|
3
|
+
// src/services/objectStorageFactory.service.ts
|
|
4
|
+
var ObjectStorageFactory = class {
|
|
5
|
+
static async instance(bucketName) {
|
|
6
|
+
var _a;
|
|
7
|
+
const isBlobStorageService = ((_a = process.env.OBJECT_STORAGE_SERVICE) == null ? void 0 : _a.toLowerCase()) === "azure_blob_storage";
|
|
8
|
+
let ObjectStorageService2;
|
|
9
|
+
if (isBlobStorageService) {
|
|
10
|
+
const module = await import('./blobStorage.service-Q2W6LO3S.mjs');
|
|
11
|
+
ObjectStorageService2 = module.BlobStorageService;
|
|
12
|
+
} else {
|
|
13
|
+
const module = await import('./s3Storage.service-OZGBAWBM.mjs');
|
|
14
|
+
ObjectStorageService2 = module.S3StorageService;
|
|
15
|
+
}
|
|
16
|
+
return new ObjectStorageService2(bucketName);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// src/services/objectStorage.service.ts
|
|
21
|
+
var ObjectStorageService = class _ObjectStorageService {
|
|
22
|
+
constructor(bucketName) {
|
|
23
|
+
_ObjectStorageService.bucketName = bucketName;
|
|
24
|
+
}
|
|
25
|
+
static async getObjectStorageServiceInstance(bucketName = _ObjectStorageService.bucketName) {
|
|
26
|
+
if (!bucketName)
|
|
27
|
+
throw new Error("Bucket name not provided or not valid value");
|
|
28
|
+
return ObjectStorageFactory.instance(bucketName);
|
|
29
|
+
}
|
|
30
|
+
static async list(bucketName) {
|
|
31
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
32
|
+
bucketName
|
|
33
|
+
).then((instance) => instance.list());
|
|
34
|
+
}
|
|
35
|
+
static async getObject(key, bucketName) {
|
|
36
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
37
|
+
bucketName
|
|
38
|
+
).then((instance) => instance.getObject(key));
|
|
39
|
+
}
|
|
40
|
+
static async getSignedUrl(key, expiresInMinutes, bucketName) {
|
|
41
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
42
|
+
bucketName
|
|
43
|
+
).then((instance) => instance.getSignedUrl(key, expiresInMinutes));
|
|
44
|
+
}
|
|
45
|
+
static async upload(key, body, metadata, bucketName) {
|
|
46
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
47
|
+
bucketName
|
|
48
|
+
).then((instance) => instance.upload(key, body, metadata));
|
|
49
|
+
}
|
|
50
|
+
static async delete(key, bucketName) {
|
|
51
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
52
|
+
bucketName
|
|
53
|
+
).then((instance) => instance.delete(key));
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export { ObjectStorageService };
|
|
58
|
+
//# sourceMappingURL=out.js.map
|
|
59
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/objectStorageFactory.service.ts","../../src/services/objectStorage.service.ts"],"names":["ObjectStorageService"],"mappings":";;;AACO,IAAM,uBAAN,MAA2B;AAAA,EAC9B,aAAa,SAAS,YAA6C;AAFvE;AAGQ,UAAM,yBACF,aAAQ,IAAI,2BAAZ,mBAAoC,mBACpC;AAEJ,QAAIA;AAEJ,QAAI,sBAAsB;AACtB,YAAM,SAAS,MAAM,OAAO,oCAAoC;AAChE,MAAAA,wBAAuB,OAAO;AAAA,IAClC,OAAO;AACH,YAAM,SAAS,MAAM,OAAO,kCAAgC;AAC5D,MAAAA,wBAAuB,OAAO;AAAA,IAClC;AAEA,WAAO,IAAIA,sBAAqB,UAAU;AAAA,EAC9C;AACJ;;;ACRA,IAAqB,uBAArB,MAAqB,sBAAqB;AAAA,EAGtC,YAAY,YAAoB;AAC5B,0BAAqB,aAAa;AAAA,EACtC;AAAA,EAEA,aAAa,gCACT,aAAqB,sBAAqB,YACnB;AACvB,QAAI,CAAC;AACD,YAAM,IAAI,MAAM,6CAA6C;AACjE,WAAO,qBAAqB,SAAS,UAAU;AAAA,EACnD;AAAA,EAEA,aAAa,KAAK,YAA4C;AAC1D,WAAO,sBAAqB;AAAA,MACxB;AAAA,IACJ,EAAE,KAAK,CAAC,aAAa,SAAS,KAAK,CAAC;AAAA,EACxC;AAAA,EAEA,aAAa,UACT,KACA,YAC0B;AAC1B,WAAO,sBAAqB;AAAA,MACxB;AAAA,IACJ,EAAE,KAAK,CAAC,aAAa,SAAS,UAAU,GAAG,CAAC;AAAA,EAChD;AAAA,EAEA,aAAa,aACT,KACA,kBACA,YACe;AACf,WAAO,sBAAqB;AAAA,MACxB;AAAA,IACJ,EAAE,KAAK,CAAC,aAAa,SAAS,aAAa,KAAK,gBAAgB,CAAC;AAAA,EACrE;AAAA,EAEA,aAAa,OACT,KACA,MACA,UACA,YACuB;AACvB,WAAO,sBAAqB;AAAA,MACxB;AAAA,IACJ,EAAE,KAAK,CAAC,aAAa,SAAS,OAAO,KAAK,MAAM,QAAQ,CAAC;AAAA,EAC7D;AAAA,EAEA,aAAa,OAAO,KAAa,YAAuC;AACpE,WAAO,sBAAqB;AAAA,MACxB;AAAA,IACJ,EAAE,KAAK,CAAC,aAAa,SAAS,OAAO,GAAG,CAAC;AAAA,EAC7C;AACJ","sourcesContent":["import { IObjectStorage } from '../interfaces';\nexport class ObjectStorageFactory {\n static async instance(bucketName: string): Promise<IObjectStorage> {\n const isBlobStorageService =\n process.env.OBJECT_STORAGE_SERVICE?.toLowerCase() ===\n 'azure_blob_storage';\n\n let ObjectStorageService: new (bucketName: string) => IObjectStorage;\n\n if (isBlobStorageService) {\n const module = await import('./storage/blob/blobStorage.service');\n ObjectStorageService = module.BlobStorageService;\n } else {\n const module = await import('./storage/s3/s3Storage.service');\n ObjectStorageService = module.S3StorageService;\n }\n\n return new ObjectStorageService(bucketName);\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { IObjectStorage } from '../interfaces';\nimport {\n ListResponse,\n FileContent,\n UploadResponse,\n GetObjectResponse,\n} from '../types';\nimport { ObjectStorageFactory } from '../services/objectStorageFactory.service';\n\nexport default class ObjectStorageService {\n static bucketName: string;\n\n constructor(bucketName: string) {\n ObjectStorageService.bucketName = bucketName;\n }\n\n static async getObjectStorageServiceInstance(\n bucketName: string = ObjectStorageService.bucketName,\n ): Promise<IObjectStorage> {\n if (!bucketName)\n throw new Error('Bucket name not provided or not valid value');\n return ObjectStorageFactory.instance(bucketName);\n }\n\n static async list(bucketName?: string): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.list());\n }\n\n static async getObject(\n key: string,\n bucketName?: string,\n ): Promise<GetObjectResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getObject(key));\n }\n\n static async getSignedUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<string> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getSignedUrl(key, expiresInMinutes));\n }\n\n static async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n bucketName?: string,\n ): Promise<UploadResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.upload(key, body, metadata));\n }\n\n static async delete(key: string, bucketName?: string): Promise<boolean> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.delete(key));\n }\n}\n"]}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import './chunk-JHXQKOVY.mjs';
|
|
2
|
+
import { S3Client, ListObjectsV2Command, GetObjectCommand, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
|
|
3
|
+
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
4
|
+
|
|
5
|
+
var S3StorageService = class {
|
|
6
|
+
constructor(bucketName) {
|
|
7
|
+
this.bucketName = bucketName;
|
|
8
|
+
this.s3Client = new S3Client({});
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Lists all objects in the S3 bucket.
|
|
12
|
+
* @returns A promise that resolves to a list of object keys.
|
|
13
|
+
*/
|
|
14
|
+
async list() {
|
|
15
|
+
const allKeys = [];
|
|
16
|
+
let continuationToken = void 0;
|
|
17
|
+
do {
|
|
18
|
+
const command = new ListObjectsV2Command({
|
|
19
|
+
Bucket: this.bucketName,
|
|
20
|
+
ContinuationToken: continuationToken
|
|
21
|
+
});
|
|
22
|
+
const response = await this.s3Client.send(command);
|
|
23
|
+
if (response.Contents) {
|
|
24
|
+
for (const item of response.Contents) {
|
|
25
|
+
if (item.Key)
|
|
26
|
+
allKeys.push(item.Key);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
continuationToken = response.NextContinuationToken;
|
|
30
|
+
} while (continuationToken);
|
|
31
|
+
return { keys: allKeys };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves an object from the S3 bucket.
|
|
35
|
+
* @param key - The key of the object to retrieve.
|
|
36
|
+
* @returns A promise that resolves to the content of the file.
|
|
37
|
+
*/
|
|
38
|
+
async getObject(key) {
|
|
39
|
+
var _a, _b;
|
|
40
|
+
const command = new GetObjectCommand({
|
|
41
|
+
Bucket: this.bucketName,
|
|
42
|
+
Key: key
|
|
43
|
+
});
|
|
44
|
+
const response = await this.s3Client.send(command);
|
|
45
|
+
return {
|
|
46
|
+
body: response.Body,
|
|
47
|
+
metadata: (_a = response.Metadata) != null ? _a : {},
|
|
48
|
+
contentType: (_b = response.ContentType) != null ? _b : "",
|
|
49
|
+
contentLength: response.ContentLength
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generates a signed URL for accessing an object in the S3 bucket.
|
|
54
|
+
* @param key - The key of the object.
|
|
55
|
+
* @param expiresInMinutes - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.
|
|
56
|
+
* @returns A promise that resolves to the signed URL.
|
|
57
|
+
*/
|
|
58
|
+
getSignedUrl(key, expiresInMinutes = 60) {
|
|
59
|
+
const expiresIn = expiresInMinutes * 60;
|
|
60
|
+
const command = new GetObjectCommand({
|
|
61
|
+
Bucket: this.bucketName,
|
|
62
|
+
Key: key
|
|
63
|
+
});
|
|
64
|
+
return getSignedUrl(this.s3Client, command, { expiresIn });
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Uploads an object to the S3 bucket.
|
|
68
|
+
* @param key - The key of the object to upload.
|
|
69
|
+
* @param body - The content of the object to upload.
|
|
70
|
+
* @param metadata - Optional metadata to associate with the object.
|
|
71
|
+
* @returns A promise that resolves to the response containing the key of the uploaded object.
|
|
72
|
+
*/
|
|
73
|
+
async upload(key, body, metadata) {
|
|
74
|
+
const command = new PutObjectCommand({
|
|
75
|
+
Bucket: this.bucketName,
|
|
76
|
+
Key: key,
|
|
77
|
+
Body: body,
|
|
78
|
+
Metadata: metadata
|
|
79
|
+
});
|
|
80
|
+
await this.s3Client.send(command);
|
|
81
|
+
return { key };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Deletes an object from the S3 bucket.
|
|
85
|
+
* @param key - The key of the object to delete.
|
|
86
|
+
* @returns A promise that resolves to true if the object was deleted successfully.
|
|
87
|
+
*/
|
|
88
|
+
async delete(key) {
|
|
89
|
+
const command = new DeleteObjectCommand({
|
|
90
|
+
Bucket: this.bucketName,
|
|
91
|
+
Key: key
|
|
92
|
+
});
|
|
93
|
+
await this.s3Client.send(command);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export { S3StorageService };
|
|
99
|
+
//# sourceMappingURL=out.js.map
|
|
100
|
+
//# sourceMappingURL=s3Storage.service-OZGBAWBM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/storage/s3/s3Storage.service.ts"],"names":[],"mappings":";;;AAAA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,OACG;AASP,SAAS,oBAAoB;AAEtB,IAAM,mBAAN,MAAiD;AAAA,EAIpD,YAAY,YAAoB;AAC5B,SAAK,aAAa;AAClB,SAAK,WAAW,IAAI,SAAS,CAAC,CAAC;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAA8B;AAChC,UAAM,UAAoB,CAAC;AAE3B,QAAI,oBAAwC;AAC5C,OAAG;AACC,YAAM,UAAgC,IAAI,qBAAqB;AAAA,QAC3D,QAAQ,KAAK;AAAA,QACb,mBAAmB;AAAA,MACvB,CAAC;AAED,YAAM,WACF,MAAM,KAAK,SAAS,KAAK,OAAO;AACpC,UAAI,SAAS,UAAU;AACnB,mBAAW,QAAQ,SAAS,UAAU;AAClC,cAAI,KAAK;AAAK,oBAAQ,KAAK,KAAK,GAAG;AAAA,QACvC;AAAA,MACJ;AAEA,0BAAoB,SAAS;AAAA,IACjC,SAAS;AAET,WAAO,EAAE,MAAM,QAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,KAAyC;AA7D7D;AA8DQ,UAAM,UAAU,IAAI,iBAAiB;AAAA,MACjC,QAAQ,KAAK;AAAA,MACb,KAAK;AAAA,IACT,CAAC;AACD,UAAM,WAAW,MAAM,KAAK,SAAS,KAAK,OAAO;AACjD,WAAO;AAAA,MACH,MAAM,SAAS;AAAA,MACf,WAAU,cAAS,aAAT,YAAqB,CAAC;AAAA,MAChC,cAAa,cAAS,gBAAT,YAAwB;AAAA,MACrC,eAAe,SAAS;AAAA,IAC5B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,KAAa,mBAA2B,IAAqB;AACtE,UAAM,YAAY,mBAAmB;AACrC,UAAM,UAAU,IAAI,iBAAiB;AAAA,MACjC,QAAQ,KAAK;AAAA,MACb,KAAK;AAAA,IACT,CAAC;AACD,WAAO,aAAa,KAAK,UAAU,SAAS,EAAE,UAAU,CAAC;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OACF,KACA,MACA,UACuB;AACvB,UAAM,UAAU,IAAI,iBAAiB;AAAA,MACjC,QAAQ,KAAK;AAAA,MACb,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,IACd,CAAC;AACD,UAAM,KAAK,SAAS,KAAK,OAAO;AAChC,WAAO,EAAE,IAAI;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,KAA+B;AACxC,UAAM,UAAU,IAAI,oBAAoB;AAAA,MACpC,QAAQ,KAAK;AAAA,MACb,KAAK;AAAA,IACT,CAAC;AACD,UAAM,KAAK,SAAS,KAAK,OAAO;AAChC,WAAO;AAAA,EACX;AACJ","sourcesContent":["import {\n DeleteObjectCommand,\n GetObjectCommand,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n PutObjectCommand,\n S3Client,\n} from '@aws-sdk/client-s3';\nimport { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n GetObjectResponse,\n ListResponse,\n UploadResponse,\n} from '../../../types';\nimport { Readable } from 'stream';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\n\nexport class S3StorageService implements IObjectStorage {\n private s3Client: S3Client;\n private bucketName: string;\n\n constructor(bucketName: string) {\n this.bucketName = bucketName;\n this.s3Client = new S3Client({});\n }\n\n /**\n * Lists all objects in the S3 bucket.\n * @returns A promise that resolves to a list of object keys.\n */\n\n async list(): Promise<ListResponse> {\n const allKeys: string[] = [];\n\n let continuationToken: string | undefined = undefined;\n do {\n const command: ListObjectsV2Command = new ListObjectsV2Command({\n Bucket: this.bucketName,\n ContinuationToken: continuationToken,\n });\n\n const response: ListObjectsV2CommandOutput =\n await this.s3Client.send(command);\n if (response.Contents) {\n for (const item of response.Contents) {\n if (item.Key) allKeys.push(item.Key);\n }\n }\n\n continuationToken = response.NextContinuationToken;\n } while (continuationToken);\n\n return { keys: allKeys };\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getObject(key: string): Promise<GetObjectResponse> {\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return {\n body: response.Body as Readable,\n metadata: response.Metadata ?? {},\n contentType: response.ContentType ?? '',\n contentLength: response.ContentLength as number,\n };\n }\n\n /**\n * Generates a signed URL for accessing an object in the S3 bucket.\n * @param key - The key of the object.\n * @param expiresInMinutes - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n getSignedUrl(key: string, expiresInMinutes: number = 60): Promise<string> {\n const expiresIn = expiresInMinutes * 60;\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n return getSignedUrl(this.s3Client, command, { expiresIn });\n }\n\n /**\n * Uploads an object to the S3 bucket.\n * @param key - The key of the object to upload.\n * @param body - The content of the object to upload.\n * @param metadata - Optional metadata to associate with the object.\n * @returns A promise that resolves to the response containing the key of the uploaded object.\n */\n async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n ): Promise<UploadResponse> {\n const command = new PutObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n Body: body,\n Metadata: metadata,\n });\n await this.s3Client.send(command);\n return { key };\n }\n\n /**\n * Deletes an object from the S3 bucket.\n * @param key - The key of the object to delete.\n * @returns A promise that resolves to true if the object was deleted successfully.\n */\n async delete(key: string): Promise<boolean> {\n const command = new DeleteObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n await this.s3Client.send(command);\n return true;\n }\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Readable } from 'stream';
|
|
2
|
+
|
|
3
|
+
type UploadResponse = {
|
|
4
|
+
key: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
type FileContent = Readable | ReadableStream | Blob;
|
|
8
|
+
|
|
9
|
+
type ListResponse = {
|
|
10
|
+
keys: string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type GetObjectResponse = {
|
|
14
|
+
body: any;
|
|
15
|
+
contentType: string;
|
|
16
|
+
contentLength: number;
|
|
17
|
+
metadata: {
|
|
18
|
+
[key: string]: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
interface IObjectStorage {
|
|
23
|
+
list(): Promise<ListResponse>;
|
|
24
|
+
getObject(key: string): Promise<GetObjectResponse>;
|
|
25
|
+
getSignedUrl(key: string, expiresInMinutes: number): Promise<string>;
|
|
26
|
+
upload(key: string, body: FileContent, metadata?: {
|
|
27
|
+
[key: string]: string;
|
|
28
|
+
}): Promise<UploadResponse>;
|
|
29
|
+
delete(key: string): Promise<boolean>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare class ObjectStorageService {
|
|
33
|
+
static bucketName: string;
|
|
34
|
+
constructor(bucketName: string);
|
|
35
|
+
static getObjectStorageServiceInstance(bucketName?: string): Promise<IObjectStorage>;
|
|
36
|
+
static list(bucketName?: string): Promise<ListResponse>;
|
|
37
|
+
static getObject(key: string, bucketName?: string): Promise<GetObjectResponse>;
|
|
38
|
+
static getSignedUrl(key: string, expiresInMinutes: number, bucketName?: string): Promise<string>;
|
|
39
|
+
static upload(key: string, body: FileContent, metadata?: {
|
|
40
|
+
[key: string]: string;
|
|
41
|
+
}, bucketName?: string): Promise<UploadResponse>;
|
|
42
|
+
static delete(key: string, bucketName?: string): Promise<boolean>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { ObjectStorageService };
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@qrvey/object-storage",
|
|
3
|
+
"types": "dist/types/index.d.ts",
|
|
4
|
+
"main": "dist/cjs/index.js",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/esm/index.mjs",
|
|
10
|
+
"require": "./dist/cjs/index.js",
|
|
11
|
+
"default": "./dist/cjs/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "jest",
|
|
16
|
+
"test:cov": "jest --coverage && chmod +x ./coverageReader.sh && sh ./coverageReader.sh",
|
|
17
|
+
"type-check": "tsc",
|
|
18
|
+
"build:clean": "rm -rf dist",
|
|
19
|
+
"build:compile:cjs": "tsup --config ./tsup.config.cjs.ts",
|
|
20
|
+
"build:compile:esm": "tsup --config ./tsup.config.esm.ts",
|
|
21
|
+
"build:compile:types": "tsup --config ./tsup.config.types.ts",
|
|
22
|
+
"build:compile": "yarn build:compile:cjs && yarn build:compile:esm && yarn build:compile:types",
|
|
23
|
+
"build": "yarn build:clean && yarn build:compile",
|
|
24
|
+
"prepare-publish": "yarn install && yarn test:cov && yarn build",
|
|
25
|
+
"publish-package": "yarn prepare-publish && npm publish"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@aws-sdk/client-s3": "3.x",
|
|
29
|
+
"@aws-sdk/s3-request-presigner": "3.x",
|
|
30
|
+
"@azure/storage-blob": "12.23.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependenciesMeta": {
|
|
33
|
+
"@aws-sdk/client-s3": {
|
|
34
|
+
"optional": true
|
|
35
|
+
},
|
|
36
|
+
"@aws-sdk/s3-request-presigner": {
|
|
37
|
+
"optional": true
|
|
38
|
+
},
|
|
39
|
+
"@azure/storage-blob": {
|
|
40
|
+
"optional": true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/jest": "29.5.5",
|
|
45
|
+
"auto-version-js": "0.3.10",
|
|
46
|
+
"eslint-config-custom": "*",
|
|
47
|
+
"jest": "29.7.0",
|
|
48
|
+
"ts-jest": "29.1.1",
|
|
49
|
+
"tsconfig": "*",
|
|
50
|
+
"tsup": "7.2.0",
|
|
51
|
+
"typescript": "5.2.2"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"files": [
|
|
57
|
+
"dist/*"
|
|
58
|
+
],
|
|
59
|
+
"keywords": [
|
|
60
|
+
"qrvey",
|
|
61
|
+
"aws lambda",
|
|
62
|
+
"fetch",
|
|
63
|
+
"rest"
|
|
64
|
+
]
|
|
65
|
+
}
|