@qrvey/object-storage 0.0.10-beta.2 → 0.0.10-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/index.js +229 -30
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.d.mts +73 -0
- package/dist/esm/index.mjs +230 -31
- package/dist/esm/index.mjs.map +1 -1
- package/dist/types/index.d.ts +73 -0
- package/package.json +2 -2
package/dist/esm/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import stream from 'stream';
|
|
2
2
|
import { BlobServiceClient, BlobSASPermissions } from '@azure/storage-blob';
|
|
3
|
-
import { S3Client, S3, ListObjectsV2Command, HeadObjectCommand, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, HeadBucketCommand } from '@aws-sdk/client-s3';
|
|
3
|
+
import { S3Client, S3, ListObjectsV2Command, HeadObjectCommand, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, HeadBucketCommand, UploadPartCommand } from '@aws-sdk/client-s3';
|
|
4
4
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
5
5
|
import { Upload } from '@aws-sdk/lib-storage';
|
|
6
6
|
|
|
@@ -10,6 +10,11 @@ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
|
10
10
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
11
11
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
12
12
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
13
|
+
var __knownSymbol = (name, symbol) => {
|
|
14
|
+
if (symbol = Symbol[name])
|
|
15
|
+
return symbol;
|
|
16
|
+
throw Error("Symbol." + name + " is not defined");
|
|
17
|
+
};
|
|
13
18
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
14
19
|
var __spreadValues = (a, b) => {
|
|
15
20
|
for (var prop in b || (b = {}))
|
|
@@ -35,6 +40,7 @@ var __objRest = (source, exclude) => {
|
|
|
35
40
|
}
|
|
36
41
|
return target;
|
|
37
42
|
};
|
|
43
|
+
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);
|
|
38
44
|
|
|
39
45
|
// src/shared/utils/errorHandler.ts
|
|
40
46
|
var errorMessages = {
|
|
@@ -447,6 +453,71 @@ var BlobStorageService = class {
|
|
|
447
453
|
);
|
|
448
454
|
}
|
|
449
455
|
}
|
|
456
|
+
async listMultipartUploadsForBucket() {
|
|
457
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
458
|
+
this.containerName
|
|
459
|
+
);
|
|
460
|
+
const blobList = containerClient.listBlobsFlat();
|
|
461
|
+
const uploads = [];
|
|
462
|
+
try {
|
|
463
|
+
for (var iter = __forAwait(blobList), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
464
|
+
const blob = temp.value;
|
|
465
|
+
uploads.push({
|
|
466
|
+
uploadId: blob.name,
|
|
467
|
+
key: blob.name,
|
|
468
|
+
initiated: blob.properties.createdOn || /* @__PURE__ */ new Date()
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
} catch (temp) {
|
|
472
|
+
error = [temp];
|
|
473
|
+
} finally {
|
|
474
|
+
try {
|
|
475
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
476
|
+
} finally {
|
|
477
|
+
if (error)
|
|
478
|
+
throw error[0];
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
bucketName: this.containerName,
|
|
483
|
+
uploads
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Retrieves the list of parts for a multipart upload.
|
|
488
|
+
*
|
|
489
|
+
* @param {string} blobName - The name of the blob (file) in Azure Blob Storage.
|
|
490
|
+
* @return {Promise<ListPartsMultipartUploadResponse>} A promise that resolves to the list of parts for the multipart upload.
|
|
491
|
+
*/
|
|
492
|
+
async listMultipartUploadsForKey(blobName) {
|
|
493
|
+
var _a;
|
|
494
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
495
|
+
this.containerName
|
|
496
|
+
);
|
|
497
|
+
const blobClient = containerClient.getBlockBlobClient(blobName);
|
|
498
|
+
const listResponse = await blobClient.getBlockList("all");
|
|
499
|
+
const parts = ((_a = listResponse == null ? void 0 : listResponse.committedBlocks) == null ? void 0 : _a.map((block, index) => ({
|
|
500
|
+
PartNumber: index + 1,
|
|
501
|
+
LastModified: /* @__PURE__ */ new Date(),
|
|
502
|
+
// Azure Blob Storage doesn't provide the last modified date for individual parts
|
|
503
|
+
ETag: block.name,
|
|
504
|
+
Size: block.size
|
|
505
|
+
}))) || [];
|
|
506
|
+
return {
|
|
507
|
+
Parts: parts
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Generates a unique upload ID for multipart uploads.
|
|
512
|
+
*
|
|
513
|
+
* @return {Promise<string>} A promise that resolves to a unique upload ID.
|
|
514
|
+
*/
|
|
515
|
+
async generateUploadIdMultipart() {
|
|
516
|
+
const timestamp = Date.now();
|
|
517
|
+
const randomNum = Math.floor(Math.random() * 100);
|
|
518
|
+
const blockIdBase = (timestamp - randomNum).toString();
|
|
519
|
+
return blockIdBase;
|
|
520
|
+
}
|
|
450
521
|
/**
|
|
451
522
|
* Uploads a part of a file as a block to Azure Blob Storage and updates the metadata with the block ID.
|
|
452
523
|
*
|
|
@@ -461,17 +532,10 @@ var BlobStorageService = class {
|
|
|
461
532
|
this.containerName
|
|
462
533
|
);
|
|
463
534
|
const blobClient = containerClient.getBlockBlobClient(blobName);
|
|
464
|
-
|
|
465
|
-
if (!blockIdBase) {
|
|
466
|
-
const timestamp = Date.now();
|
|
467
|
-
const randomNum = Math.floor(Math.random() * 100);
|
|
468
|
-
blockIdBase = (timestamp - randomNum).toString();
|
|
469
|
-
}
|
|
535
|
+
const blockIdBase = uploadId || await this.generateUploadIdMultipart();
|
|
470
536
|
const partId = partNumber.toString().padStart(6, "0");
|
|
471
537
|
const partIdBase64 = Buffer.from(partId).toString("base64");
|
|
472
538
|
await blobClient.stageBlock(partIdBase64, file, file.length);
|
|
473
|
-
const blockIdStorage = BlockIdStorage.getInstance();
|
|
474
|
-
blockIdStorage.addBlockId(blockIdBase, partIdBase64);
|
|
475
539
|
return blockIdBase;
|
|
476
540
|
}
|
|
477
541
|
/**
|
|
@@ -483,17 +547,17 @@ var BlobStorageService = class {
|
|
|
483
547
|
* @throws {Error} If no block IDs are found in the metadata.
|
|
484
548
|
*/
|
|
485
549
|
async completeMultipartUpload(blobName, uploadId) {
|
|
550
|
+
var _a;
|
|
486
551
|
const containerClient = this.blobServiceClient.getContainerClient(
|
|
487
552
|
this.containerName
|
|
488
553
|
);
|
|
489
554
|
const blobClient = containerClient.getBlockBlobClient(blobName);
|
|
490
|
-
const
|
|
491
|
-
const blockIds =
|
|
555
|
+
const listMultipartUploads = await this.listMultipartUploadsForKey(blobName);
|
|
556
|
+
const blockIds = ((_a = listMultipartUploads == null ? void 0 : listMultipartUploads.Parts) == null ? void 0 : _a.map((part) => part.ETag)) || [];
|
|
492
557
|
if (blockIds.length === 0) {
|
|
493
558
|
throw new Error("No block IDs found in metadata.");
|
|
494
559
|
}
|
|
495
560
|
await blobClient.commitBlockList(blockIds);
|
|
496
|
-
blockIdStorage.clearBlockIds(uploadId);
|
|
497
561
|
}
|
|
498
562
|
/**
|
|
499
563
|
* Aborts a multipart upload by deleting the specified blob and clearing its block IDs metadata.
|
|
@@ -511,6 +575,17 @@ var BlobStorageService = class {
|
|
|
511
575
|
blockIdStorage.clearBlockIds(uploadId);
|
|
512
576
|
await blobClient.delete();
|
|
513
577
|
}
|
|
578
|
+
async getMultipartUploadPresignedUrl(blobName, uploadId, partNumber, expiresInMinutes = 2) {
|
|
579
|
+
const partId = partNumber.toString().padStart(6, "0");
|
|
580
|
+
const partIdBase64 = Buffer.from(partId).toString("base64");
|
|
581
|
+
const sasUrl = await this.getSignatureUrl(
|
|
582
|
+
blobName,
|
|
583
|
+
expiresInMinutes,
|
|
584
|
+
"w"
|
|
585
|
+
);
|
|
586
|
+
const url = `${sasUrl}&comp=block&blockid=${partIdBase64}`;
|
|
587
|
+
return url;
|
|
588
|
+
}
|
|
514
589
|
};
|
|
515
590
|
|
|
516
591
|
// src/services/storage/s3/s3Helpers.ts
|
|
@@ -767,18 +842,69 @@ var S3StorageService = class {
|
|
|
767
842
|
);
|
|
768
843
|
}
|
|
769
844
|
}
|
|
845
|
+
/**
|
|
846
|
+
* Generates an upload ID for multipart upload in the S3 bucket.
|
|
847
|
+
*
|
|
848
|
+
* @param {string} key - The key of the object to upload.
|
|
849
|
+
* @return {Promise<string>} A promise that resolves to the generated upload ID.
|
|
850
|
+
* @throws {Error} If no upload ID was generated.
|
|
851
|
+
*/
|
|
852
|
+
async generateUploadIdMultipart(key) {
|
|
853
|
+
const params = {
|
|
854
|
+
Bucket: this.bucketName,
|
|
855
|
+
Key: key
|
|
856
|
+
};
|
|
857
|
+
const response = await this.s3.createMultipartUpload(params);
|
|
858
|
+
if (!(response == null ? void 0 : response.UploadId))
|
|
859
|
+
throw new Error("No upload ID was generated");
|
|
860
|
+
return response.UploadId;
|
|
861
|
+
}
|
|
862
|
+
async listMultipartUploadsForBucket() {
|
|
863
|
+
const params = {
|
|
864
|
+
Bucket: this.bucketName
|
|
865
|
+
};
|
|
866
|
+
const response = await this.s3.listMultipartUploads(params);
|
|
867
|
+
return {
|
|
868
|
+
bucketName: this.bucketName,
|
|
869
|
+
uploads: response.Uploads ? response.Uploads.map((upload) => {
|
|
870
|
+
var _a, _b;
|
|
871
|
+
return {
|
|
872
|
+
uploadId: upload.UploadId || "",
|
|
873
|
+
key: upload.Key || "",
|
|
874
|
+
initiator: ((_a = upload == null ? void 0 : upload.Initiator) == null ? void 0 : _a.ID) || "",
|
|
875
|
+
owner: ((_b = upload == null ? void 0 : upload.Owner) == null ? void 0 : _b.ID) || "",
|
|
876
|
+
storageClass: upload.StorageClass || "",
|
|
877
|
+
initiated: upload.Initiated || ""
|
|
878
|
+
};
|
|
879
|
+
}) : []
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Retrieves the list of parts for a multipart upload.
|
|
884
|
+
*
|
|
885
|
+
* @param {string} key - The key of the object being uploaded.
|
|
886
|
+
* @param {string} uploadId - The ID of the multipart upload.
|
|
887
|
+
* @return {Promise<ListPartsMultipartUploadResponse>} A promise that resolves to the list of parts for the multipart upload.
|
|
888
|
+
*/
|
|
889
|
+
async listMultipartUploadsForKey(key, uploadId) {
|
|
890
|
+
const params = {
|
|
891
|
+
Bucket: this.bucketName,
|
|
892
|
+
Key: key,
|
|
893
|
+
UploadId: uploadId
|
|
894
|
+
};
|
|
895
|
+
const response = await this.s3.listParts(params);
|
|
896
|
+
const parts = response.Parts ? response.Parts.map((part) => ({
|
|
897
|
+
PartNumber: part.PartNumber,
|
|
898
|
+
LastModified: part.LastModified,
|
|
899
|
+
ETag: part.ETag,
|
|
900
|
+
Size: part.Size
|
|
901
|
+
})) : [];
|
|
902
|
+
return {
|
|
903
|
+
Parts: parts
|
|
904
|
+
};
|
|
905
|
+
}
|
|
770
906
|
async uploadMultipart(key, file, partNumber, uploadId) {
|
|
771
|
-
|
|
772
|
-
if (!upId) {
|
|
773
|
-
const params2 = {
|
|
774
|
-
Bucket: this.bucketName,
|
|
775
|
-
Key: key
|
|
776
|
-
};
|
|
777
|
-
const response = await this.s3.createMultipartUpload(params2);
|
|
778
|
-
if (!(response == null ? void 0 : response.UploadId))
|
|
779
|
-
throw new Error("No upload ID was generated");
|
|
780
|
-
upId = response.UploadId;
|
|
781
|
-
}
|
|
907
|
+
const upId = uploadId || await this.generateUploadIdMultipart(key);
|
|
782
908
|
const params = {
|
|
783
909
|
Bucket: this.bucketName,
|
|
784
910
|
Key: key,
|
|
@@ -790,12 +916,10 @@ var S3StorageService = class {
|
|
|
790
916
|
return upId;
|
|
791
917
|
}
|
|
792
918
|
async completeMultipartUpload(key, uploadId) {
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
};
|
|
798
|
-
const partsResponse = await this.s3.listParts(listPartsParams);
|
|
919
|
+
const partsResponse = await this.listMultipartUploadsForKey(
|
|
920
|
+
key,
|
|
921
|
+
uploadId
|
|
922
|
+
);
|
|
799
923
|
const partsList = (partsResponse == null ? void 0 : partsResponse.Parts) && partsResponse.Parts.map(
|
|
800
924
|
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
|
801
925
|
(_a) => {
|
|
@@ -803,11 +927,14 @@ var S3StorageService = class {
|
|
|
803
927
|
return partList;
|
|
804
928
|
}
|
|
805
929
|
);
|
|
806
|
-
const completeMultipartParams =
|
|
930
|
+
const completeMultipartParams = {
|
|
931
|
+
Bucket: this.bucketName,
|
|
932
|
+
Key: key,
|
|
933
|
+
UploadId: uploadId,
|
|
807
934
|
MultipartUpload: {
|
|
808
935
|
Parts: partsList
|
|
809
936
|
}
|
|
810
|
-
}
|
|
937
|
+
};
|
|
811
938
|
await this.s3.completeMultipartUpload(completeMultipartParams);
|
|
812
939
|
}
|
|
813
940
|
async abortMultipartUpload(key, uploadId) {
|
|
@@ -818,6 +945,21 @@ var S3StorageService = class {
|
|
|
818
945
|
};
|
|
819
946
|
await this.s3.abortMultipartUpload(params);
|
|
820
947
|
}
|
|
948
|
+
async getMultipartUploadPresignedUrl(key, uploadId, partNumber, expiresInMinutes = 60) {
|
|
949
|
+
const uploadPartParams = {
|
|
950
|
+
Bucket: this.bucketName,
|
|
951
|
+
Key: key,
|
|
952
|
+
UploadId: uploadId,
|
|
953
|
+
PartNumber: parseInt(partNumber, 10)
|
|
954
|
+
};
|
|
955
|
+
const expiresIn = expiresInMinutes * 60;
|
|
956
|
+
const presignedUrl = await getSignedUrl(
|
|
957
|
+
this.s3Client,
|
|
958
|
+
new UploadPartCommand(uploadPartParams),
|
|
959
|
+
{ expiresIn }
|
|
960
|
+
);
|
|
961
|
+
return presignedUrl;
|
|
962
|
+
}
|
|
821
963
|
};
|
|
822
964
|
|
|
823
965
|
// src/shared/utils/constants.ts
|
|
@@ -996,6 +1138,44 @@ var ObjectStorageService = class _ObjectStorageService {
|
|
|
996
1138
|
bucketName
|
|
997
1139
|
).then((instance) => instance.getHeadBucket());
|
|
998
1140
|
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Generates a unique upload ID for a multipart upload.
|
|
1143
|
+
*
|
|
1144
|
+
* @param {string} key - The key of the object to upload.
|
|
1145
|
+
* @param {string} [bucketName] - The name of the bucket. If not provided, the default bucket name will be used.
|
|
1146
|
+
* @return {Promise<string>} A promise that resolves to the generated upload ID.
|
|
1147
|
+
*/
|
|
1148
|
+
static async generateUploadIdMultipart(key, bucketName) {
|
|
1149
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
1150
|
+
bucketName
|
|
1151
|
+
).then((instance) => instance.generateUploadIdMultipart(key));
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Retrieves a list of multipart uploads for a specified key in the object storage service.
|
|
1155
|
+
*
|
|
1156
|
+
* @param {string} key - The key of the object to retrieve uploads for.
|
|
1157
|
+
* @param {string} [bucketName] - The name of the bucket. If not provided, the default bucket name will be used.
|
|
1158
|
+
* @param {string} [uploadId] - The upload ID to filter the results by.
|
|
1159
|
+
* @return {Promise<ListPartsMultipartUploadResponse>} A promise that resolves to the list of multipart uploads for the specified key.
|
|
1160
|
+
*/
|
|
1161
|
+
static async listMultipartUploadsForKey(key, bucketName, uploadId) {
|
|
1162
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
1163
|
+
bucketName
|
|
1164
|
+
).then(
|
|
1165
|
+
(instance) => instance.listMultipartUploadsForKey(key, uploadId)
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Retrieves a list of all multipart uploads for a specified bucket in the object storage service.
|
|
1170
|
+
*
|
|
1171
|
+
* @param {string} [bucketName] - The name of the bucket. If not provided, the default bucket name will be used.
|
|
1172
|
+
* @return {Promise<ListMultipartUploadsResponse>} A promise that resolves to the list of multipart uploads for the specified bucket.
|
|
1173
|
+
*/
|
|
1174
|
+
static async listMultipartUploadsForBucket(bucketName) {
|
|
1175
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
1176
|
+
bucketName
|
|
1177
|
+
).then((instance) => instance.listMultipartUploadsForBucket());
|
|
1178
|
+
}
|
|
999
1179
|
/**
|
|
1000
1180
|
* Uploads a multipart file to the specified bucket in the object storage service.
|
|
1001
1181
|
*
|
|
@@ -1039,6 +1219,25 @@ var ObjectStorageService = class _ObjectStorageService {
|
|
|
1039
1219
|
bucketName
|
|
1040
1220
|
).then((instance) => instance.abortMultipartUpload(key, uploadId));
|
|
1041
1221
|
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Retrieves a presigned URL for a specific part of a multipart upload.
|
|
1224
|
+
*
|
|
1225
|
+
* @param {string} key - The key of the object for which to generate the presigned URL.
|
|
1226
|
+
* @param {string} uploadId - The ID of the multipart upload.
|
|
1227
|
+
* @param {string} partNumber - The number of the part for which to generate the presigned URL.
|
|
1228
|
+
* @param {number} [expiresInMinutes] - The number of minutes until the presigned URL expires. Default is 60 minutes.
|
|
1229
|
+
* @return {Promise<string>} A Promise that resolves to the presigned URL for the specified part of the multipart upload.
|
|
1230
|
+
*/
|
|
1231
|
+
static async getMultipartUploadPresignedUrl(key, uploadId, partNumber, expiresInMinutes) {
|
|
1232
|
+
return _ObjectStorageService.getObjectStorageServiceInstance().then(
|
|
1233
|
+
(instance) => instance.getMultipartUploadPresignedUrl(
|
|
1234
|
+
key,
|
|
1235
|
+
uploadId,
|
|
1236
|
+
partNumber,
|
|
1237
|
+
expiresInMinutes
|
|
1238
|
+
)
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1042
1241
|
};
|
|
1043
1242
|
|
|
1044
1243
|
export { ObjectStorageService };
|