@twin.org/blob-storage-service 0.0.1-next.35 → 0.0.1-next.37
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/dist/cjs/index.cjs +43 -19
- package/dist/esm/index.mjs +45 -21
- package/dist/types/blobStorageService.d.ts +5 -3
- package/dist/types/entities/blobStorageEntry.d.ts +5 -0
- package/docs/changelog.md +32 -0
- package/docs/open-api/spec.json +35 -15
- package/docs/reference/classes/BlobStorageEntry.md +8 -0
- package/docs/reference/classes/BlobStorageService.md +8 -2
- package/package.json +2 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -427,7 +427,7 @@ async function blobStorageGet(httpRequestContext, componentName, request) {
|
|
|
427
427
|
const component = core.ComponentFactory.get(componentName);
|
|
428
428
|
const result = await component.get(request.pathParams.id, {
|
|
429
429
|
includeContent: core.Coerce.boolean(request.query?.includeContent),
|
|
430
|
-
|
|
430
|
+
decompress: core.Coerce.boolean(request.query?.decompress),
|
|
431
431
|
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
432
432
|
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
433
433
|
return {
|
|
@@ -449,22 +449,34 @@ async function blobStorageGetContent(httpRequestContext, componentName, request)
|
|
|
449
449
|
core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
450
450
|
core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
451
451
|
const component = core.ComponentFactory.get(componentName);
|
|
452
|
+
const decompress = core.Coerce.boolean(request.query?.decompress);
|
|
453
|
+
const download = core.Coerce.boolean(request.query?.download) ?? false;
|
|
452
454
|
const result = await component.get(request.pathParams.id, {
|
|
453
455
|
includeContent: true,
|
|
454
|
-
|
|
456
|
+
decompress,
|
|
455
457
|
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
456
458
|
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
457
459
|
const encodingFormat = result?.encodingFormat ?? web.MimeTypes.OctetStream;
|
|
460
|
+
let compressedEncodingFormat;
|
|
461
|
+
let compressedExtension = "";
|
|
462
|
+
// If the entry is compressed and we are not decompressing
|
|
463
|
+
// we need to override the encoding format to the compressed type
|
|
464
|
+
// and append an additional extension to the filename.
|
|
465
|
+
if (result.compression && !decompress) {
|
|
466
|
+
compressedEncodingFormat =
|
|
467
|
+
result.compression === blobStorageModels.BlobStorageCompressionType.Gzip ? web.MimeTypes.Gzip : web.MimeTypes.Zlib;
|
|
468
|
+
compressedExtension = `.${web.MimeTypeHelper.defaultExtension(compressedEncodingFormat)}`;
|
|
469
|
+
}
|
|
458
470
|
let filename = request.query?.filename;
|
|
459
471
|
if (!core.Is.stringValue(filename)) {
|
|
460
|
-
filename = `file.${result.fileExtension ?? web.MimeTypeHelper.defaultExtension(encodingFormat)}`;
|
|
472
|
+
filename = `file.${result.fileExtension ?? web.MimeTypeHelper.defaultExtension(encodingFormat)}${compressedExtension}`;
|
|
461
473
|
}
|
|
462
474
|
return {
|
|
463
475
|
body: core.Is.stringBase64(result.blob) ? core.Converter.base64ToBytes(result.blob) : new Uint8Array(),
|
|
464
476
|
attachment: {
|
|
465
|
-
mimeType: encodingFormat,
|
|
477
|
+
mimeType: compressedEncodingFormat ?? encodingFormat,
|
|
466
478
|
filename,
|
|
467
|
-
inline: !
|
|
479
|
+
inline: !download
|
|
468
480
|
}
|
|
469
481
|
};
|
|
470
482
|
}
|
|
@@ -595,6 +607,7 @@ class BlobStorageService {
|
|
|
595
607
|
* @param options Optional options for the creation of the blob.
|
|
596
608
|
* @param options.disableEncryption Disables encryption if enabled by default.
|
|
597
609
|
* @param options.overrideVaultKeyId Use a different vault key id for encryption, if not provided the default vault key id will be used.
|
|
610
|
+
* @param options.compress Optional compression type to use for the blob, defaults to no compression.*
|
|
598
611
|
* @param options.namespace The namespace to use for storing, defaults to component configured namespace.
|
|
599
612
|
* @param userIdentity The user identity to use with storage operations.
|
|
600
613
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
@@ -632,6 +645,9 @@ class BlobStorageService {
|
|
|
632
645
|
core.Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
|
|
633
646
|
}
|
|
634
647
|
const blobHash = `sha256:${core.Converter.bytesToBase64(crypto.Sha256.sum256(storeBlob))}`;
|
|
648
|
+
if (!core.Is.empty(options?.compress)) {
|
|
649
|
+
storeBlob = await core.Compression.compress(storeBlob, options.compress);
|
|
650
|
+
}
|
|
635
651
|
// If we have a vault connector then encrypt the data.
|
|
636
652
|
if (encryptionEnabled) {
|
|
637
653
|
if (core.Is.empty(this._vaultConnector)) {
|
|
@@ -650,7 +666,8 @@ class BlobStorageService {
|
|
|
650
666
|
encodingFormat,
|
|
651
667
|
fileExtension,
|
|
652
668
|
metadata,
|
|
653
|
-
isEncrypted: encryptionEnabled
|
|
669
|
+
isEncrypted: encryptionEnabled,
|
|
670
|
+
compression: options?.compress
|
|
654
671
|
};
|
|
655
672
|
const conditions = [];
|
|
656
673
|
if (this._includeUserIdentity) {
|
|
@@ -673,8 +690,8 @@ class BlobStorageService {
|
|
|
673
690
|
* @param id The id of the blob to get in urn format.
|
|
674
691
|
* @param options Optional options for the retrieval of the blob.
|
|
675
692
|
* @param options.includeContent Include the content, or just get the metadata.
|
|
676
|
-
* @param options.disableDecryption Disables decryption if enabled by default.
|
|
677
693
|
* @param options.overrideVaultKeyId Use a different vault key id for decryption, if not provided the default vault key id will be used.
|
|
694
|
+
* @param options.decompress If the content should be decompressed, if it was compressed when stored, defaults to true.
|
|
678
695
|
* @param userIdentity The user identity to use with storage operations.
|
|
679
696
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
680
697
|
* @returns The entry and data for the blob if it can be found.
|
|
@@ -683,9 +700,7 @@ class BlobStorageService {
|
|
|
683
700
|
async get(id, options, userIdentity, nodeIdentity) {
|
|
684
701
|
core.Urn.guard(this.CLASS_NAME, "id", id);
|
|
685
702
|
const includeContent = options?.includeContent ?? false;
|
|
686
|
-
const disableEncryption = options?.disableDecryption ?? false;
|
|
687
703
|
const vaultKeyId = options?.overrideVaultKeyId ?? this._vaultKeyId;
|
|
688
|
-
const decryptionEnabled = !disableEncryption && core.Is.stringValue(vaultKeyId);
|
|
689
704
|
const conditions = [];
|
|
690
705
|
if (this._includeUserIdentity) {
|
|
691
706
|
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
@@ -712,13 +727,17 @@ class BlobStorageService {
|
|
|
712
727
|
if (core.Is.undefined(returnBlob)) {
|
|
713
728
|
throw new core.NotFoundError(this.CLASS_NAME, "blobNotFound", id);
|
|
714
729
|
}
|
|
715
|
-
// If
|
|
730
|
+
// If the data is encrypted then decrypt it.
|
|
731
|
+
const decryptionEnabled = blobEntry.isEncrypted && core.Is.stringValue(vaultKeyId);
|
|
716
732
|
if (decryptionEnabled) {
|
|
717
733
|
if (core.Is.empty(this._vaultConnector)) {
|
|
718
734
|
throw new core.GeneralError(this.CLASS_NAME, "vaultConnectorNotConfigured");
|
|
719
735
|
}
|
|
720
736
|
returnBlob = await this._vaultConnector.decrypt(`${nodeIdentity}/${vaultKeyId}`, vaultModels.VaultEncryptionType.ChaCha20Poly1305, returnBlob);
|
|
721
737
|
}
|
|
738
|
+
if (!core.Is.empty(blobEntry.compression) && (options?.decompress ?? true)) {
|
|
739
|
+
returnBlob = await core.Compression.decompress(returnBlob, blobEntry.compression);
|
|
740
|
+
}
|
|
722
741
|
}
|
|
723
742
|
const jsonLd = this.entryToJsonLd(blobEntry, returnBlob);
|
|
724
743
|
return dataJsonLd.JsonLdProcessor.compact(jsonLd, jsonLd["@context"]);
|
|
@@ -766,7 +785,8 @@ class BlobStorageService {
|
|
|
766
785
|
encodingFormat: encodingFormat ?? blobEntry.encodingFormat,
|
|
767
786
|
fileExtension: fileExtension ?? blobEntry.fileExtension,
|
|
768
787
|
metadata: metadata ?? blobEntry.metadata,
|
|
769
|
-
isEncrypted: blobEntry.isEncrypted
|
|
788
|
+
isEncrypted: blobEntry.isEncrypted,
|
|
789
|
+
compression: blobEntry.compression
|
|
770
790
|
};
|
|
771
791
|
const conditions = [];
|
|
772
792
|
if (this._includeUserIdentity) {
|
|
@@ -861,10 +881,6 @@ class BlobStorageService {
|
|
|
861
881
|
sortDirection: orderDirection
|
|
862
882
|
}
|
|
863
883
|
], undefined, cursor, pageSize);
|
|
864
|
-
for (const entity of result.entities) {
|
|
865
|
-
core.ObjectHelper.propertyDelete(entity, "nodeIdentity");
|
|
866
|
-
core.ObjectHelper.propertyDelete(entity, "userIdentity");
|
|
867
|
-
}
|
|
868
884
|
let context = [
|
|
869
885
|
standardsSchemaOrg.SchemaOrgContexts.ContextRoot,
|
|
870
886
|
blobStorageModels.BlobStorageContexts.ContextRoot,
|
|
@@ -948,9 +964,7 @@ class BlobStorageService {
|
|
|
948
964
|
if (core.Is.empty(entity$1)) {
|
|
949
965
|
throw new core.NotFoundError(this.CLASS_NAME, "entityNotFound", id);
|
|
950
966
|
}
|
|
951
|
-
core.ObjectHelper.
|
|
952
|
-
core.ObjectHelper.propertyDelete(entity$1, "userIdentity");
|
|
953
|
-
return entity$1;
|
|
967
|
+
return core.ObjectHelper.omit(entity$1, ["nodeIdentity", "userIdentity"]);
|
|
954
968
|
}
|
|
955
969
|
/**
|
|
956
970
|
* Convert the entry to JSON-LD.
|
|
@@ -975,7 +989,9 @@ class BlobStorageService {
|
|
|
975
989
|
encodingFormat: entry?.encodingFormat,
|
|
976
990
|
fileExtension: entry?.fileExtension,
|
|
977
991
|
metadata: entry?.metadata,
|
|
978
|
-
blob: core.Is.uint8Array(blob) ? core.Converter.bytesToBase64(blob) : undefined
|
|
992
|
+
blob: core.Is.uint8Array(blob) ? core.Converter.bytesToBase64(blob) : undefined,
|
|
993
|
+
isEncrypted: entry.isEncrypted,
|
|
994
|
+
compression: entry.compression
|
|
979
995
|
};
|
|
980
996
|
return jsonLd;
|
|
981
997
|
}
|
|
@@ -1021,6 +1037,10 @@ exports.BlobStorageEntry = class BlobStorageEntry {
|
|
|
1021
1037
|
* Is the entry encrypted.
|
|
1022
1038
|
*/
|
|
1023
1039
|
isEncrypted;
|
|
1040
|
+
/**
|
|
1041
|
+
* Is the entry compressed.
|
|
1042
|
+
*/
|
|
1043
|
+
compression;
|
|
1024
1044
|
/**
|
|
1025
1045
|
* The user identity that created the blob.
|
|
1026
1046
|
*/
|
|
@@ -1071,6 +1091,10 @@ __decorate([
|
|
|
1071
1091
|
entity.property({ type: "boolean" }),
|
|
1072
1092
|
__metadata("design:type", Boolean)
|
|
1073
1093
|
], exports.BlobStorageEntry.prototype, "isEncrypted", void 0);
|
|
1094
|
+
__decorate([
|
|
1095
|
+
entity.property({ type: "string", optional: true }),
|
|
1096
|
+
__metadata("design:type", String)
|
|
1097
|
+
], exports.BlobStorageEntry.prototype, "compression", void 0);
|
|
1074
1098
|
__decorate([
|
|
1075
1099
|
entity.property({ type: "string", optional: true }),
|
|
1076
1100
|
__metadata("design:type", String)
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HttpParameterHelper } from '@twin.org/api-models';
|
|
2
|
-
import { BlobStorageTypes, BlobStorageContexts, BlobStorageConnectorFactory } from '@twin.org/blob-storage-models';
|
|
3
|
-
import { StringHelper, Guards, ComponentFactory, Coerce, Is, Converter, GeneralError, Validation, ObjectHelper, Urn, NotFoundError } from '@twin.org/core';
|
|
2
|
+
import { BlobStorageTypes, BlobStorageContexts, BlobStorageCompressionType, BlobStorageConnectorFactory } from '@twin.org/blob-storage-models';
|
|
3
|
+
import { StringHelper, Guards, ComponentFactory, Coerce, Is, Converter, GeneralError, Validation, Compression, ObjectHelper, Urn, NotFoundError } from '@twin.org/core';
|
|
4
4
|
import { SchemaOrgContexts, SchemaOrgTypes, SchemaOrgDataTypes } from '@twin.org/standards-schema-org';
|
|
5
5
|
import { HttpStatusCode, HeaderTypes, MimeTypes, MimeTypeHelper } from '@twin.org/web';
|
|
6
6
|
import { Sha256 } from '@twin.org/crypto';
|
|
@@ -425,7 +425,7 @@ async function blobStorageGet(httpRequestContext, componentName, request) {
|
|
|
425
425
|
const component = ComponentFactory.get(componentName);
|
|
426
426
|
const result = await component.get(request.pathParams.id, {
|
|
427
427
|
includeContent: Coerce.boolean(request.query?.includeContent),
|
|
428
|
-
|
|
428
|
+
decompress: Coerce.boolean(request.query?.decompress),
|
|
429
429
|
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
430
430
|
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
431
431
|
return {
|
|
@@ -447,22 +447,34 @@ async function blobStorageGetContent(httpRequestContext, componentName, request)
|
|
|
447
447
|
Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
448
448
|
Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
449
449
|
const component = ComponentFactory.get(componentName);
|
|
450
|
+
const decompress = Coerce.boolean(request.query?.decompress);
|
|
451
|
+
const download = Coerce.boolean(request.query?.download) ?? false;
|
|
450
452
|
const result = await component.get(request.pathParams.id, {
|
|
451
453
|
includeContent: true,
|
|
452
|
-
|
|
454
|
+
decompress,
|
|
453
455
|
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
454
456
|
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
455
457
|
const encodingFormat = result?.encodingFormat ?? MimeTypes.OctetStream;
|
|
458
|
+
let compressedEncodingFormat;
|
|
459
|
+
let compressedExtension = "";
|
|
460
|
+
// If the entry is compressed and we are not decompressing
|
|
461
|
+
// we need to override the encoding format to the compressed type
|
|
462
|
+
// and append an additional extension to the filename.
|
|
463
|
+
if (result.compression && !decompress) {
|
|
464
|
+
compressedEncodingFormat =
|
|
465
|
+
result.compression === BlobStorageCompressionType.Gzip ? MimeTypes.Gzip : MimeTypes.Zlib;
|
|
466
|
+
compressedExtension = `.${MimeTypeHelper.defaultExtension(compressedEncodingFormat)}`;
|
|
467
|
+
}
|
|
456
468
|
let filename = request.query?.filename;
|
|
457
469
|
if (!Is.stringValue(filename)) {
|
|
458
|
-
filename = `file.${result.fileExtension ?? MimeTypeHelper.defaultExtension(encodingFormat)}`;
|
|
470
|
+
filename = `file.${result.fileExtension ?? MimeTypeHelper.defaultExtension(encodingFormat)}${compressedExtension}`;
|
|
459
471
|
}
|
|
460
472
|
return {
|
|
461
473
|
body: Is.stringBase64(result.blob) ? Converter.base64ToBytes(result.blob) : new Uint8Array(),
|
|
462
474
|
attachment: {
|
|
463
|
-
mimeType: encodingFormat,
|
|
475
|
+
mimeType: compressedEncodingFormat ?? encodingFormat,
|
|
464
476
|
filename,
|
|
465
|
-
inline: !
|
|
477
|
+
inline: !download
|
|
466
478
|
}
|
|
467
479
|
};
|
|
468
480
|
}
|
|
@@ -593,6 +605,7 @@ class BlobStorageService {
|
|
|
593
605
|
* @param options Optional options for the creation of the blob.
|
|
594
606
|
* @param options.disableEncryption Disables encryption if enabled by default.
|
|
595
607
|
* @param options.overrideVaultKeyId Use a different vault key id for encryption, if not provided the default vault key id will be used.
|
|
608
|
+
* @param options.compress Optional compression type to use for the blob, defaults to no compression.*
|
|
596
609
|
* @param options.namespace The namespace to use for storing, defaults to component configured namespace.
|
|
597
610
|
* @param userIdentity The user identity to use with storage operations.
|
|
598
611
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
@@ -630,6 +643,9 @@ class BlobStorageService {
|
|
|
630
643
|
Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
|
|
631
644
|
}
|
|
632
645
|
const blobHash = `sha256:${Converter.bytesToBase64(Sha256.sum256(storeBlob))}`;
|
|
646
|
+
if (!Is.empty(options?.compress)) {
|
|
647
|
+
storeBlob = await Compression.compress(storeBlob, options.compress);
|
|
648
|
+
}
|
|
633
649
|
// If we have a vault connector then encrypt the data.
|
|
634
650
|
if (encryptionEnabled) {
|
|
635
651
|
if (Is.empty(this._vaultConnector)) {
|
|
@@ -648,7 +664,8 @@ class BlobStorageService {
|
|
|
648
664
|
encodingFormat,
|
|
649
665
|
fileExtension,
|
|
650
666
|
metadata,
|
|
651
|
-
isEncrypted: encryptionEnabled
|
|
667
|
+
isEncrypted: encryptionEnabled,
|
|
668
|
+
compression: options?.compress
|
|
652
669
|
};
|
|
653
670
|
const conditions = [];
|
|
654
671
|
if (this._includeUserIdentity) {
|
|
@@ -671,8 +688,8 @@ class BlobStorageService {
|
|
|
671
688
|
* @param id The id of the blob to get in urn format.
|
|
672
689
|
* @param options Optional options for the retrieval of the blob.
|
|
673
690
|
* @param options.includeContent Include the content, or just get the metadata.
|
|
674
|
-
* @param options.disableDecryption Disables decryption if enabled by default.
|
|
675
691
|
* @param options.overrideVaultKeyId Use a different vault key id for decryption, if not provided the default vault key id will be used.
|
|
692
|
+
* @param options.decompress If the content should be decompressed, if it was compressed when stored, defaults to true.
|
|
676
693
|
* @param userIdentity The user identity to use with storage operations.
|
|
677
694
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
678
695
|
* @returns The entry and data for the blob if it can be found.
|
|
@@ -681,9 +698,7 @@ class BlobStorageService {
|
|
|
681
698
|
async get(id, options, userIdentity, nodeIdentity) {
|
|
682
699
|
Urn.guard(this.CLASS_NAME, "id", id);
|
|
683
700
|
const includeContent = options?.includeContent ?? false;
|
|
684
|
-
const disableEncryption = options?.disableDecryption ?? false;
|
|
685
701
|
const vaultKeyId = options?.overrideVaultKeyId ?? this._vaultKeyId;
|
|
686
|
-
const decryptionEnabled = !disableEncryption && Is.stringValue(vaultKeyId);
|
|
687
702
|
const conditions = [];
|
|
688
703
|
if (this._includeUserIdentity) {
|
|
689
704
|
Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
@@ -710,13 +725,17 @@ class BlobStorageService {
|
|
|
710
725
|
if (Is.undefined(returnBlob)) {
|
|
711
726
|
throw new NotFoundError(this.CLASS_NAME, "blobNotFound", id);
|
|
712
727
|
}
|
|
713
|
-
// If
|
|
728
|
+
// If the data is encrypted then decrypt it.
|
|
729
|
+
const decryptionEnabled = blobEntry.isEncrypted && Is.stringValue(vaultKeyId);
|
|
714
730
|
if (decryptionEnabled) {
|
|
715
731
|
if (Is.empty(this._vaultConnector)) {
|
|
716
732
|
throw new GeneralError(this.CLASS_NAME, "vaultConnectorNotConfigured");
|
|
717
733
|
}
|
|
718
734
|
returnBlob = await this._vaultConnector.decrypt(`${nodeIdentity}/${vaultKeyId}`, VaultEncryptionType.ChaCha20Poly1305, returnBlob);
|
|
719
735
|
}
|
|
736
|
+
if (!Is.empty(blobEntry.compression) && (options?.decompress ?? true)) {
|
|
737
|
+
returnBlob = await Compression.decompress(returnBlob, blobEntry.compression);
|
|
738
|
+
}
|
|
720
739
|
}
|
|
721
740
|
const jsonLd = this.entryToJsonLd(blobEntry, returnBlob);
|
|
722
741
|
return JsonLdProcessor.compact(jsonLd, jsonLd["@context"]);
|
|
@@ -764,7 +783,8 @@ class BlobStorageService {
|
|
|
764
783
|
encodingFormat: encodingFormat ?? blobEntry.encodingFormat,
|
|
765
784
|
fileExtension: fileExtension ?? blobEntry.fileExtension,
|
|
766
785
|
metadata: metadata ?? blobEntry.metadata,
|
|
767
|
-
isEncrypted: blobEntry.isEncrypted
|
|
786
|
+
isEncrypted: blobEntry.isEncrypted,
|
|
787
|
+
compression: blobEntry.compression
|
|
768
788
|
};
|
|
769
789
|
const conditions = [];
|
|
770
790
|
if (this._includeUserIdentity) {
|
|
@@ -859,10 +879,6 @@ class BlobStorageService {
|
|
|
859
879
|
sortDirection: orderDirection
|
|
860
880
|
}
|
|
861
881
|
], undefined, cursor, pageSize);
|
|
862
|
-
for (const entity of result.entities) {
|
|
863
|
-
ObjectHelper.propertyDelete(entity, "nodeIdentity");
|
|
864
|
-
ObjectHelper.propertyDelete(entity, "userIdentity");
|
|
865
|
-
}
|
|
866
882
|
let context = [
|
|
867
883
|
SchemaOrgContexts.ContextRoot,
|
|
868
884
|
BlobStorageContexts.ContextRoot,
|
|
@@ -946,9 +962,7 @@ class BlobStorageService {
|
|
|
946
962
|
if (Is.empty(entity)) {
|
|
947
963
|
throw new NotFoundError(this.CLASS_NAME, "entityNotFound", id);
|
|
948
964
|
}
|
|
949
|
-
ObjectHelper.
|
|
950
|
-
ObjectHelper.propertyDelete(entity, "userIdentity");
|
|
951
|
-
return entity;
|
|
965
|
+
return ObjectHelper.omit(entity, ["nodeIdentity", "userIdentity"]);
|
|
952
966
|
}
|
|
953
967
|
/**
|
|
954
968
|
* Convert the entry to JSON-LD.
|
|
@@ -973,7 +987,9 @@ class BlobStorageService {
|
|
|
973
987
|
encodingFormat: entry?.encodingFormat,
|
|
974
988
|
fileExtension: entry?.fileExtension,
|
|
975
989
|
metadata: entry?.metadata,
|
|
976
|
-
blob: Is.uint8Array(blob) ? Converter.bytesToBase64(blob) : undefined
|
|
990
|
+
blob: Is.uint8Array(blob) ? Converter.bytesToBase64(blob) : undefined,
|
|
991
|
+
isEncrypted: entry.isEncrypted,
|
|
992
|
+
compression: entry.compression
|
|
977
993
|
};
|
|
978
994
|
return jsonLd;
|
|
979
995
|
}
|
|
@@ -1019,6 +1035,10 @@ let BlobStorageEntry = class BlobStorageEntry {
|
|
|
1019
1035
|
* Is the entry encrypted.
|
|
1020
1036
|
*/
|
|
1021
1037
|
isEncrypted;
|
|
1038
|
+
/**
|
|
1039
|
+
* Is the entry compressed.
|
|
1040
|
+
*/
|
|
1041
|
+
compression;
|
|
1022
1042
|
/**
|
|
1023
1043
|
* The user identity that created the blob.
|
|
1024
1044
|
*/
|
|
@@ -1069,6 +1089,10 @@ __decorate([
|
|
|
1069
1089
|
property({ type: "boolean" }),
|
|
1070
1090
|
__metadata("design:type", Boolean)
|
|
1071
1091
|
], BlobStorageEntry.prototype, "isEncrypted", void 0);
|
|
1092
|
+
__decorate([
|
|
1093
|
+
property({ type: "string", optional: true }),
|
|
1094
|
+
__metadata("design:type", String)
|
|
1095
|
+
], BlobStorageEntry.prototype, "compression", void 0);
|
|
1072
1096
|
__decorate([
|
|
1073
1097
|
property({ type: "string", optional: true }),
|
|
1074
1098
|
__metadata("design:type", String)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type IBlobStorageComponent, type IBlobStorageEntry, type IBlobStorageEntryList } from "@twin.org/blob-storage-models";
|
|
1
|
+
import { type BlobStorageCompressionType, type IBlobStorageComponent, type IBlobStorageEntry, type IBlobStorageEntryList } from "@twin.org/blob-storage-models";
|
|
2
2
|
import { type IJsonLdNodeObject } from "@twin.org/data-json-ld";
|
|
3
3
|
import { SortDirection, type EntityCondition } from "@twin.org/entity";
|
|
4
4
|
import type { IBlobStorageServiceConstructorOptions } from "./models/IBlobStorageServiceConstructorOptions";
|
|
@@ -28,6 +28,7 @@ export declare class BlobStorageService implements IBlobStorageComponent {
|
|
|
28
28
|
* @param options Optional options for the creation of the blob.
|
|
29
29
|
* @param options.disableEncryption Disables encryption if enabled by default.
|
|
30
30
|
* @param options.overrideVaultKeyId Use a different vault key id for encryption, if not provided the default vault key id will be used.
|
|
31
|
+
* @param options.compress Optional compression type to use for the blob, defaults to no compression.*
|
|
31
32
|
* @param options.namespace The namespace to use for storing, defaults to component configured namespace.
|
|
32
33
|
* @param userIdentity The user identity to use with storage operations.
|
|
33
34
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
@@ -36,6 +37,7 @@ export declare class BlobStorageService implements IBlobStorageComponent {
|
|
|
36
37
|
create(blob: string, encodingFormat?: string, fileExtension?: string, metadata?: IJsonLdNodeObject, options?: {
|
|
37
38
|
disableEncryption?: boolean;
|
|
38
39
|
overrideVaultKeyId?: string;
|
|
40
|
+
compress?: BlobStorageCompressionType;
|
|
39
41
|
namespace?: string;
|
|
40
42
|
}, userIdentity?: string, nodeIdentity?: string): Promise<string>;
|
|
41
43
|
/**
|
|
@@ -43,8 +45,8 @@ export declare class BlobStorageService implements IBlobStorageComponent {
|
|
|
43
45
|
* @param id The id of the blob to get in urn format.
|
|
44
46
|
* @param options Optional options for the retrieval of the blob.
|
|
45
47
|
* @param options.includeContent Include the content, or just get the metadata.
|
|
46
|
-
* @param options.disableDecryption Disables decryption if enabled by default.
|
|
47
48
|
* @param options.overrideVaultKeyId Use a different vault key id for decryption, if not provided the default vault key id will be used.
|
|
49
|
+
* @param options.decompress If the content should be decompressed, if it was compressed when stored, defaults to true.
|
|
48
50
|
* @param userIdentity The user identity to use with storage operations.
|
|
49
51
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
50
52
|
* @returns The entry and data for the blob if it can be found.
|
|
@@ -52,7 +54,7 @@ export declare class BlobStorageService implements IBlobStorageComponent {
|
|
|
52
54
|
*/
|
|
53
55
|
get(id: string, options?: {
|
|
54
56
|
includeContent?: boolean;
|
|
55
|
-
|
|
57
|
+
decompress?: boolean;
|
|
56
58
|
overrideVaultKeyId?: string;
|
|
57
59
|
}, userIdentity?: string, nodeIdentity?: string): Promise<IBlobStorageEntry>;
|
|
58
60
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BlobStorageCompressionType } from "@twin.org/blob-storage-models";
|
|
1
2
|
import type { IJsonLdNodeObject } from "@twin.org/data-json-ld";
|
|
2
3
|
/**
|
|
3
4
|
* Class representing entry for the blob storage.
|
|
@@ -39,6 +40,10 @@ export declare class BlobStorageEntry {
|
|
|
39
40
|
* Is the entry encrypted.
|
|
40
41
|
*/
|
|
41
42
|
isEncrypted: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Is the entry compressed.
|
|
45
|
+
*/
|
|
46
|
+
compression?: BlobStorageCompressionType;
|
|
42
47
|
/**
|
|
43
48
|
* The user identity that created the blob.
|
|
44
49
|
*/
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @twin.org/blob-storage-service - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.1-next.37](https://github.com/twinfoundation/blob-storage/compare/blob-storage-service-v0.0.1-next.36...blob-storage-service-v0.0.1-next.37) (2025-06-20)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* query params force coercion ([a5e547a](https://github.com/twinfoundation/blob-storage/commit/a5e547a775f8997cb04780938c7a9561ddb048d1))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/blob-storage-models bumped from 0.0.1-next.36 to 0.0.1-next.37
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @twin.org/blob-storage-connector-memory bumped from 0.0.1-next.36 to 0.0.1-next.37
|
|
18
|
+
|
|
19
|
+
## [0.0.1-next.36](https://github.com/twinfoundation/blob-storage/compare/blob-storage-service-v0.0.1-next.35...blob-storage-service-v0.0.1-next.36) (2025-06-19)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* add compression support ([67d239b](https://github.com/twinfoundation/blob-storage/commit/67d239bca8321bd90bf4ff93167c564130309730))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Dependencies
|
|
28
|
+
|
|
29
|
+
* The following workspace dependencies were updated
|
|
30
|
+
* dependencies
|
|
31
|
+
* @twin.org/blob-storage-models bumped from 0.0.1-next.35 to 0.0.1-next.36
|
|
32
|
+
* devDependencies
|
|
33
|
+
* @twin.org/blob-storage-connector-memory bumped from 0.0.1-next.35 to 0.0.1-next.36
|
|
34
|
+
|
|
3
35
|
## [0.0.1-next.35](https://github.com/twinfoundation/blob-storage/compare/blob-storage-service-v0.0.1-next.34...blob-storage-service-v0.0.1-next.35) (2025-06-17)
|
|
4
36
|
|
|
5
37
|
|
package/docs/open-api/spec.json
CHANGED
|
@@ -171,7 +171,10 @@
|
|
|
171
171
|
"in": "query",
|
|
172
172
|
"required": false,
|
|
173
173
|
"schema": {
|
|
174
|
-
"type":
|
|
174
|
+
"type": [
|
|
175
|
+
"number",
|
|
176
|
+
"string"
|
|
177
|
+
]
|
|
175
178
|
}
|
|
176
179
|
},
|
|
177
180
|
{
|
|
@@ -388,17 +391,23 @@
|
|
|
388
391
|
"in": "query",
|
|
389
392
|
"required": false,
|
|
390
393
|
"schema": {
|
|
391
|
-
"type":
|
|
394
|
+
"type": [
|
|
395
|
+
"boolean",
|
|
396
|
+
"string"
|
|
397
|
+
]
|
|
392
398
|
},
|
|
393
399
|
"example": "true"
|
|
394
400
|
},
|
|
395
401
|
{
|
|
396
|
-
"name": "
|
|
397
|
-
"description": "
|
|
402
|
+
"name": "decompress",
|
|
403
|
+
"description": "If the content should be decompressed, if it was compressed when stored, defaults to true.",
|
|
398
404
|
"in": "query",
|
|
399
405
|
"required": false,
|
|
400
406
|
"schema": {
|
|
401
|
-
"type":
|
|
407
|
+
"type": [
|
|
408
|
+
"boolean",
|
|
409
|
+
"string"
|
|
410
|
+
]
|
|
402
411
|
}
|
|
403
412
|
},
|
|
404
413
|
{
|
|
@@ -914,6 +923,21 @@
|
|
|
914
923
|
},
|
|
915
924
|
"components": {
|
|
916
925
|
"schemas": {
|
|
926
|
+
"BlobStorageCompressionType": {
|
|
927
|
+
"anyOf": [
|
|
928
|
+
{
|
|
929
|
+
"type": "string",
|
|
930
|
+
"const": "gzip",
|
|
931
|
+
"description": "Gzip."
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
"type": "string",
|
|
935
|
+
"const": "deflate",
|
|
936
|
+
"description": "Deflate."
|
|
937
|
+
}
|
|
938
|
+
],
|
|
939
|
+
"description": "The types of compression for blob storage data."
|
|
940
|
+
},
|
|
917
941
|
"BlobStorageCreateRequest": {
|
|
918
942
|
"type": "object",
|
|
919
943
|
"properties": {
|
|
@@ -937,6 +961,9 @@
|
|
|
937
961
|
"description": "Disables encryption if enabled by default.",
|
|
938
962
|
"default": false
|
|
939
963
|
},
|
|
964
|
+
"compress": {
|
|
965
|
+
"$ref": "#/components/schemas/BlobStorageCompressionType"
|
|
966
|
+
},
|
|
940
967
|
"overrideVaultKeyId": {
|
|
941
968
|
"type": "string",
|
|
942
969
|
"description": "Use a different vault key id for encryption, if not provided the default vault key id will be used.",
|
|
@@ -1007,6 +1034,9 @@
|
|
|
1007
1034
|
"type": "boolean",
|
|
1008
1035
|
"description": "Indicates if the blob is encrypted."
|
|
1009
1036
|
},
|
|
1037
|
+
"compression": {
|
|
1038
|
+
"$ref": "#/components/schemas/BlobStorageCompressionType"
|
|
1039
|
+
},
|
|
1010
1040
|
"fileExtension": {
|
|
1011
1041
|
"type": "string",
|
|
1012
1042
|
"description": "The extension."
|
|
@@ -1095,16 +1125,6 @@
|
|
|
1095
1125
|
},
|
|
1096
1126
|
"metadata": {
|
|
1097
1127
|
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
|
|
1098
|
-
},
|
|
1099
|
-
"disableEncryption": {
|
|
1100
|
-
"type": "boolean",
|
|
1101
|
-
"description": "Disables encryption if enabled by default.",
|
|
1102
|
-
"default": false
|
|
1103
|
-
},
|
|
1104
|
-
"overrideVaultKeyId": {
|
|
1105
|
-
"type": "string",
|
|
1106
|
-
"description": "Use a different vault key id for encryption, if not provided the default vault key id will be used.",
|
|
1107
|
-
"default": "undefined"
|
|
1108
1128
|
}
|
|
1109
1129
|
},
|
|
1110
1130
|
"additionalProperties": false,
|
|
@@ -96,6 +96,12 @@ Disables encryption if enabled by default.
|
|
|
96
96
|
|
|
97
97
|
Use a different vault key id for encryption, if not provided the default vault key id will be used.
|
|
98
98
|
|
|
99
|
+
###### compress?
|
|
100
|
+
|
|
101
|
+
`BlobStorageCompressionType`
|
|
102
|
+
|
|
103
|
+
Optional compression type to use for the blob, defaults to no compression.*
|
|
104
|
+
|
|
99
105
|
###### namespace?
|
|
100
106
|
|
|
101
107
|
`string`
|
|
@@ -150,11 +156,11 @@ Optional options for the retrieval of the blob.
|
|
|
150
156
|
|
|
151
157
|
Include the content, or just get the metadata.
|
|
152
158
|
|
|
153
|
-
######
|
|
159
|
+
###### decompress?
|
|
154
160
|
|
|
155
161
|
`boolean`
|
|
156
162
|
|
|
157
|
-
|
|
163
|
+
If the content should be decompressed, if it was compressed when stored, defaults to true.
|
|
158
164
|
|
|
159
165
|
###### overrideVaultKeyId?
|
|
160
166
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/blob-storage-service",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.37",
|
|
4
4
|
"description": "Blob storage contract implementation and REST endpoint definitions",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@twin.org/api-models": "next",
|
|
18
|
-
"@twin.org/blob-storage-models": "0.0.1-next.
|
|
18
|
+
"@twin.org/blob-storage-models": "0.0.1-next.37",
|
|
19
19
|
"@twin.org/core": "next",
|
|
20
20
|
"@twin.org/crypto": "next",
|
|
21
21
|
"@twin.org/data-json-ld": "next",
|