@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/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @qrvey/object-storage
|
|
2
2
|
|
|
3
3
|

|
|
4
|
-

|
|
5
5
|
|
|
6
6
|
The `@qrvey/object-storage` package provides a unified interface for ...
|
|
7
7
|
|
package/dist/cjs/index.js
CHANGED
|
@@ -16,6 +16,11 @@ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
|
16
16
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
17
17
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
18
18
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
19
|
+
var __knownSymbol = (name, symbol) => {
|
|
20
|
+
if (symbol = Symbol[name])
|
|
21
|
+
return symbol;
|
|
22
|
+
throw Error("Symbol." + name + " is not defined");
|
|
23
|
+
};
|
|
19
24
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
20
25
|
var __spreadValues = (a, b) => {
|
|
21
26
|
for (var prop in b || (b = {}))
|
|
@@ -41,6 +46,7 @@ var __objRest = (source, exclude) => {
|
|
|
41
46
|
}
|
|
42
47
|
return target;
|
|
43
48
|
};
|
|
49
|
+
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);
|
|
44
50
|
|
|
45
51
|
// src/shared/utils/errorHandler.ts
|
|
46
52
|
var errorMessages = {
|
|
@@ -453,6 +459,71 @@ var BlobStorageService = class {
|
|
|
453
459
|
);
|
|
454
460
|
}
|
|
455
461
|
}
|
|
462
|
+
async listMultipartUploadsForBucket() {
|
|
463
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
464
|
+
this.containerName
|
|
465
|
+
);
|
|
466
|
+
const blobList = containerClient.listBlobsFlat();
|
|
467
|
+
const uploads = [];
|
|
468
|
+
try {
|
|
469
|
+
for (var iter = __forAwait(blobList), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
470
|
+
const blob = temp.value;
|
|
471
|
+
uploads.push({
|
|
472
|
+
uploadId: blob.name,
|
|
473
|
+
key: blob.name,
|
|
474
|
+
initiated: blob.properties.createdOn || /* @__PURE__ */ new Date()
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
} catch (temp) {
|
|
478
|
+
error = [temp];
|
|
479
|
+
} finally {
|
|
480
|
+
try {
|
|
481
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
482
|
+
} finally {
|
|
483
|
+
if (error)
|
|
484
|
+
throw error[0];
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return {
|
|
488
|
+
bucketName: this.containerName,
|
|
489
|
+
uploads
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Retrieves the list of parts for a multipart upload.
|
|
494
|
+
*
|
|
495
|
+
* @param {string} blobName - The name of the blob (file) in Azure Blob Storage.
|
|
496
|
+
* @return {Promise<ListPartsMultipartUploadResponse>} A promise that resolves to the list of parts for the multipart upload.
|
|
497
|
+
*/
|
|
498
|
+
async listMultipartUploadsForKey(blobName) {
|
|
499
|
+
var _a;
|
|
500
|
+
const containerClient = this.blobServiceClient.getContainerClient(
|
|
501
|
+
this.containerName
|
|
502
|
+
);
|
|
503
|
+
const blobClient = containerClient.getBlockBlobClient(blobName);
|
|
504
|
+
const listResponse = await blobClient.getBlockList("all");
|
|
505
|
+
const parts = ((_a = listResponse == null ? void 0 : listResponse.committedBlocks) == null ? void 0 : _a.map((block, index) => ({
|
|
506
|
+
PartNumber: index + 1,
|
|
507
|
+
LastModified: /* @__PURE__ */ new Date(),
|
|
508
|
+
// Azure Blob Storage doesn't provide the last modified date for individual parts
|
|
509
|
+
ETag: block.name,
|
|
510
|
+
Size: block.size
|
|
511
|
+
}))) || [];
|
|
512
|
+
return {
|
|
513
|
+
Parts: parts
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Generates a unique upload ID for multipart uploads.
|
|
518
|
+
*
|
|
519
|
+
* @return {Promise<string>} A promise that resolves to a unique upload ID.
|
|
520
|
+
*/
|
|
521
|
+
async generateUploadIdMultipart() {
|
|
522
|
+
const timestamp = Date.now();
|
|
523
|
+
const randomNum = Math.floor(Math.random() * 100);
|
|
524
|
+
const blockIdBase = (timestamp - randomNum).toString();
|
|
525
|
+
return blockIdBase;
|
|
526
|
+
}
|
|
456
527
|
/**
|
|
457
528
|
* Uploads a part of a file as a block to Azure Blob Storage and updates the metadata with the block ID.
|
|
458
529
|
*
|
|
@@ -467,17 +538,10 @@ var BlobStorageService = class {
|
|
|
467
538
|
this.containerName
|
|
468
539
|
);
|
|
469
540
|
const blobClient = containerClient.getBlockBlobClient(blobName);
|
|
470
|
-
|
|
471
|
-
if (!blockIdBase) {
|
|
472
|
-
const timestamp = Date.now();
|
|
473
|
-
const randomNum = Math.floor(Math.random() * 100);
|
|
474
|
-
blockIdBase = (timestamp - randomNum).toString();
|
|
475
|
-
}
|
|
541
|
+
const blockIdBase = uploadId || await this.generateUploadIdMultipart();
|
|
476
542
|
const partId = partNumber.toString().padStart(6, "0");
|
|
477
543
|
const partIdBase64 = Buffer.from(partId).toString("base64");
|
|
478
544
|
await blobClient.stageBlock(partIdBase64, file, file.length);
|
|
479
|
-
const blockIdStorage = BlockIdStorage.getInstance();
|
|
480
|
-
blockIdStorage.addBlockId(blockIdBase, partIdBase64);
|
|
481
545
|
return blockIdBase;
|
|
482
546
|
}
|
|
483
547
|
/**
|
|
@@ -489,17 +553,17 @@ var BlobStorageService = class {
|
|
|
489
553
|
* @throws {Error} If no block IDs are found in the metadata.
|
|
490
554
|
*/
|
|
491
555
|
async completeMultipartUpload(blobName, uploadId) {
|
|
556
|
+
var _a;
|
|
492
557
|
const containerClient = this.blobServiceClient.getContainerClient(
|
|
493
558
|
this.containerName
|
|
494
559
|
);
|
|
495
560
|
const blobClient = containerClient.getBlockBlobClient(blobName);
|
|
496
|
-
const
|
|
497
|
-
const blockIds =
|
|
561
|
+
const listMultipartUploads = await this.listMultipartUploadsForKey(blobName);
|
|
562
|
+
const blockIds = ((_a = listMultipartUploads == null ? void 0 : listMultipartUploads.Parts) == null ? void 0 : _a.map((part) => part.ETag)) || [];
|
|
498
563
|
if (blockIds.length === 0) {
|
|
499
564
|
throw new Error("No block IDs found in metadata.");
|
|
500
565
|
}
|
|
501
566
|
await blobClient.commitBlockList(blockIds);
|
|
502
|
-
blockIdStorage.clearBlockIds(uploadId);
|
|
503
567
|
}
|
|
504
568
|
/**
|
|
505
569
|
* Aborts a multipart upload by deleting the specified blob and clearing its block IDs metadata.
|
|
@@ -517,6 +581,17 @@ var BlobStorageService = class {
|
|
|
517
581
|
blockIdStorage.clearBlockIds(uploadId);
|
|
518
582
|
await blobClient.delete();
|
|
519
583
|
}
|
|
584
|
+
async getMultipartUploadPresignedUrl(blobName, uploadId, partNumber, expiresInMinutes = 2) {
|
|
585
|
+
const partId = partNumber.toString().padStart(6, "0");
|
|
586
|
+
const partIdBase64 = Buffer.from(partId).toString("base64");
|
|
587
|
+
const sasUrl = await this.getSignatureUrl(
|
|
588
|
+
blobName,
|
|
589
|
+
expiresInMinutes,
|
|
590
|
+
"w"
|
|
591
|
+
);
|
|
592
|
+
const url = `${sasUrl}&comp=block&blockid=${partIdBase64}`;
|
|
593
|
+
return url;
|
|
594
|
+
}
|
|
520
595
|
};
|
|
521
596
|
|
|
522
597
|
// src/services/storage/s3/s3Helpers.ts
|
|
@@ -773,18 +848,69 @@ var S3StorageService = class {
|
|
|
773
848
|
);
|
|
774
849
|
}
|
|
775
850
|
}
|
|
851
|
+
/**
|
|
852
|
+
* Generates an upload ID for multipart upload in the S3 bucket.
|
|
853
|
+
*
|
|
854
|
+
* @param {string} key - The key of the object to upload.
|
|
855
|
+
* @return {Promise<string>} A promise that resolves to the generated upload ID.
|
|
856
|
+
* @throws {Error} If no upload ID was generated.
|
|
857
|
+
*/
|
|
858
|
+
async generateUploadIdMultipart(key) {
|
|
859
|
+
const params = {
|
|
860
|
+
Bucket: this.bucketName,
|
|
861
|
+
Key: key
|
|
862
|
+
};
|
|
863
|
+
const response = await this.s3.createMultipartUpload(params);
|
|
864
|
+
if (!(response == null ? void 0 : response.UploadId))
|
|
865
|
+
throw new Error("No upload ID was generated");
|
|
866
|
+
return response.UploadId;
|
|
867
|
+
}
|
|
868
|
+
async listMultipartUploadsForBucket() {
|
|
869
|
+
const params = {
|
|
870
|
+
Bucket: this.bucketName
|
|
871
|
+
};
|
|
872
|
+
const response = await this.s3.listMultipartUploads(params);
|
|
873
|
+
return {
|
|
874
|
+
bucketName: this.bucketName,
|
|
875
|
+
uploads: response.Uploads ? response.Uploads.map((upload) => {
|
|
876
|
+
var _a, _b;
|
|
877
|
+
return {
|
|
878
|
+
uploadId: upload.UploadId || "",
|
|
879
|
+
key: upload.Key || "",
|
|
880
|
+
initiator: ((_a = upload == null ? void 0 : upload.Initiator) == null ? void 0 : _a.ID) || "",
|
|
881
|
+
owner: ((_b = upload == null ? void 0 : upload.Owner) == null ? void 0 : _b.ID) || "",
|
|
882
|
+
storageClass: upload.StorageClass || "",
|
|
883
|
+
initiated: upload.Initiated || ""
|
|
884
|
+
};
|
|
885
|
+
}) : []
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Retrieves the list of parts for a multipart upload.
|
|
890
|
+
*
|
|
891
|
+
* @param {string} key - The key of the object being uploaded.
|
|
892
|
+
* @param {string} uploadId - The ID of the multipart upload.
|
|
893
|
+
* @return {Promise<ListPartsMultipartUploadResponse>} A promise that resolves to the list of parts for the multipart upload.
|
|
894
|
+
*/
|
|
895
|
+
async listMultipartUploadsForKey(key, uploadId) {
|
|
896
|
+
const params = {
|
|
897
|
+
Bucket: this.bucketName,
|
|
898
|
+
Key: key,
|
|
899
|
+
UploadId: uploadId
|
|
900
|
+
};
|
|
901
|
+
const response = await this.s3.listParts(params);
|
|
902
|
+
const parts = response.Parts ? response.Parts.map((part) => ({
|
|
903
|
+
PartNumber: part.PartNumber,
|
|
904
|
+
LastModified: part.LastModified,
|
|
905
|
+
ETag: part.ETag,
|
|
906
|
+
Size: part.Size
|
|
907
|
+
})) : [];
|
|
908
|
+
return {
|
|
909
|
+
Parts: parts
|
|
910
|
+
};
|
|
911
|
+
}
|
|
776
912
|
async uploadMultipart(key, file, partNumber, uploadId) {
|
|
777
|
-
|
|
778
|
-
if (!upId) {
|
|
779
|
-
const params2 = {
|
|
780
|
-
Bucket: this.bucketName,
|
|
781
|
-
Key: key
|
|
782
|
-
};
|
|
783
|
-
const response = await this.s3.createMultipartUpload(params2);
|
|
784
|
-
if (!(response == null ? void 0 : response.UploadId))
|
|
785
|
-
throw new Error("No upload ID was generated");
|
|
786
|
-
upId = response.UploadId;
|
|
787
|
-
}
|
|
913
|
+
const upId = uploadId || await this.generateUploadIdMultipart(key);
|
|
788
914
|
const params = {
|
|
789
915
|
Bucket: this.bucketName,
|
|
790
916
|
Key: key,
|
|
@@ -796,12 +922,10 @@ var S3StorageService = class {
|
|
|
796
922
|
return upId;
|
|
797
923
|
}
|
|
798
924
|
async completeMultipartUpload(key, uploadId) {
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
};
|
|
804
|
-
const partsResponse = await this.s3.listParts(listPartsParams);
|
|
925
|
+
const partsResponse = await this.listMultipartUploadsForKey(
|
|
926
|
+
key,
|
|
927
|
+
uploadId
|
|
928
|
+
);
|
|
805
929
|
const partsList = (partsResponse == null ? void 0 : partsResponse.Parts) && partsResponse.Parts.map(
|
|
806
930
|
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
|
807
931
|
(_a) => {
|
|
@@ -809,11 +933,14 @@ var S3StorageService = class {
|
|
|
809
933
|
return partList;
|
|
810
934
|
}
|
|
811
935
|
);
|
|
812
|
-
const completeMultipartParams =
|
|
936
|
+
const completeMultipartParams = {
|
|
937
|
+
Bucket: this.bucketName,
|
|
938
|
+
Key: key,
|
|
939
|
+
UploadId: uploadId,
|
|
813
940
|
MultipartUpload: {
|
|
814
941
|
Parts: partsList
|
|
815
942
|
}
|
|
816
|
-
}
|
|
943
|
+
};
|
|
817
944
|
await this.s3.completeMultipartUpload(completeMultipartParams);
|
|
818
945
|
}
|
|
819
946
|
async abortMultipartUpload(key, uploadId) {
|
|
@@ -824,6 +951,21 @@ var S3StorageService = class {
|
|
|
824
951
|
};
|
|
825
952
|
await this.s3.abortMultipartUpload(params);
|
|
826
953
|
}
|
|
954
|
+
async getMultipartUploadPresignedUrl(key, uploadId, partNumber, expiresInMinutes = 60) {
|
|
955
|
+
const uploadPartParams = {
|
|
956
|
+
Bucket: this.bucketName,
|
|
957
|
+
Key: key,
|
|
958
|
+
UploadId: uploadId,
|
|
959
|
+
PartNumber: parseInt(partNumber, 10)
|
|
960
|
+
};
|
|
961
|
+
const expiresIn = expiresInMinutes * 60;
|
|
962
|
+
const presignedUrl = await s3RequestPresigner.getSignedUrl(
|
|
963
|
+
this.s3Client,
|
|
964
|
+
new clientS3.UploadPartCommand(uploadPartParams),
|
|
965
|
+
{ expiresIn }
|
|
966
|
+
);
|
|
967
|
+
return presignedUrl;
|
|
968
|
+
}
|
|
827
969
|
};
|
|
828
970
|
|
|
829
971
|
// src/shared/utils/constants.ts
|
|
@@ -1002,6 +1144,44 @@ var ObjectStorageService = class _ObjectStorageService {
|
|
|
1002
1144
|
bucketName
|
|
1003
1145
|
).then((instance) => instance.getHeadBucket());
|
|
1004
1146
|
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Generates a unique upload ID for a multipart upload.
|
|
1149
|
+
*
|
|
1150
|
+
* @param {string} key - The key of the object to upload.
|
|
1151
|
+
* @param {string} [bucketName] - The name of the bucket. If not provided, the default bucket name will be used.
|
|
1152
|
+
* @return {Promise<string>} A promise that resolves to the generated upload ID.
|
|
1153
|
+
*/
|
|
1154
|
+
static async generateUploadIdMultipart(key, bucketName) {
|
|
1155
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
1156
|
+
bucketName
|
|
1157
|
+
).then((instance) => instance.generateUploadIdMultipart(key));
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Retrieves a list of multipart uploads for a specified key in the object storage service.
|
|
1161
|
+
*
|
|
1162
|
+
* @param {string} key - The key of the object to retrieve uploads for.
|
|
1163
|
+
* @param {string} [bucketName] - The name of the bucket. If not provided, the default bucket name will be used.
|
|
1164
|
+
* @param {string} [uploadId] - The upload ID to filter the results by.
|
|
1165
|
+
* @return {Promise<ListPartsMultipartUploadResponse>} A promise that resolves to the list of multipart uploads for the specified key.
|
|
1166
|
+
*/
|
|
1167
|
+
static async listMultipartUploadsForKey(key, bucketName, uploadId) {
|
|
1168
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
1169
|
+
bucketName
|
|
1170
|
+
).then(
|
|
1171
|
+
(instance) => instance.listMultipartUploadsForKey(key, uploadId)
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Retrieves a list of all multipart uploads for a specified bucket in the object storage service.
|
|
1176
|
+
*
|
|
1177
|
+
* @param {string} [bucketName] - The name of the bucket. If not provided, the default bucket name will be used.
|
|
1178
|
+
* @return {Promise<ListMultipartUploadsResponse>} A promise that resolves to the list of multipart uploads for the specified bucket.
|
|
1179
|
+
*/
|
|
1180
|
+
static async listMultipartUploadsForBucket(bucketName) {
|
|
1181
|
+
return _ObjectStorageService.getObjectStorageServiceInstance(
|
|
1182
|
+
bucketName
|
|
1183
|
+
).then((instance) => instance.listMultipartUploadsForBucket());
|
|
1184
|
+
}
|
|
1005
1185
|
/**
|
|
1006
1186
|
* Uploads a multipart file to the specified bucket in the object storage service.
|
|
1007
1187
|
*
|
|
@@ -1045,6 +1225,25 @@ var ObjectStorageService = class _ObjectStorageService {
|
|
|
1045
1225
|
bucketName
|
|
1046
1226
|
).then((instance) => instance.abortMultipartUpload(key, uploadId));
|
|
1047
1227
|
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Retrieves a presigned URL for a specific part of a multipart upload.
|
|
1230
|
+
*
|
|
1231
|
+
* @param {string} key - The key of the object for which to generate the presigned URL.
|
|
1232
|
+
* @param {string} uploadId - The ID of the multipart upload.
|
|
1233
|
+
* @param {string} partNumber - The number of the part for which to generate the presigned URL.
|
|
1234
|
+
* @param {number} [expiresInMinutes] - The number of minutes until the presigned URL expires. Default is 60 minutes.
|
|
1235
|
+
* @return {Promise<string>} A Promise that resolves to the presigned URL for the specified part of the multipart upload.
|
|
1236
|
+
*/
|
|
1237
|
+
static async getMultipartUploadPresignedUrl(key, uploadId, partNumber, expiresInMinutes) {
|
|
1238
|
+
return _ObjectStorageService.getObjectStorageServiceInstance().then(
|
|
1239
|
+
(instance) => instance.getMultipartUploadPresignedUrl(
|
|
1240
|
+
key,
|
|
1241
|
+
uploadId,
|
|
1242
|
+
partNumber,
|
|
1243
|
+
expiresInMinutes
|
|
1244
|
+
)
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1048
1247
|
};
|
|
1049
1248
|
|
|
1050
1249
|
exports.ObjectStorageService = ObjectStorageService;
|