@twin.org/blob-storage-connector-azure 0.0.2-next.5 → 0.0.3-next.2
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/{esm/index.mjs → es/azureBlobStorageConnector.js} +33 -20
- package/dist/es/azureBlobStorageConnector.js.map +1 -0
- package/dist/es/index.js +6 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IAzureBlobStorageConnectorConfig.js +4 -0
- package/dist/es/models/IAzureBlobStorageConnectorConfig.js.map +1 -0
- package/dist/es/models/IAzureBlobStorageConnectorConstructorOptions.js +2 -0
- package/dist/es/models/IAzureBlobStorageConnectorConstructorOptions.js.map +1 -0
- package/dist/types/azureBlobStorageConnector.d.ts +6 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/models/IAzureBlobStorageConnectorConstructorOptions.d.ts +5 -1
- package/docs/changelog.md +33 -0
- package/docs/reference/classes/AzureBlobStorageConnector.md +20 -2
- package/docs/reference/interfaces/IAzureBlobStorageConnectorConstructorOptions.md +8 -0
- package/locales/en.json +0 -1
- package/package.json +8 -9
- package/dist/cjs/index.cjs +0 -183
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npm install @twin.org/blob-storage-connector-azure
|
|
|
13
13
|
The tests developed are functional tests and need an instance of Azure up and running. To run Azure locally using azurite as microsoft container:
|
|
14
14
|
|
|
15
15
|
```shell
|
|
16
|
-
docker run -p
|
|
16
|
+
docker run -p 20610:10000 --name twin-blob-azure -d -e AZURITE_ACCOUNTS=testAccount:testKey mcr.microsoft.com/azure-storage/azurite azurite-blob --blobHost 0.0.0.0
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Afterwards you can run the tests as follows:
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';
|
|
2
|
-
import { Guards, ComponentFactory, BaseError, Converter, Urn, GeneralError, Is } from '@twin.org/core';
|
|
3
|
-
import { Sha256 } from '@twin.org/crypto';
|
|
4
|
-
|
|
5
1
|
// Copyright 2024 IOTA Stiftung.
|
|
6
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob";
|
|
4
|
+
import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
|
|
5
|
+
import { BaseError, ComponentFactory, Converter, GeneralError, Guards, Is, Urn } from "@twin.org/core";
|
|
6
|
+
import { Sha256 } from "@twin.org/crypto";
|
|
7
7
|
/**
|
|
8
8
|
* Class for performing blob storage operations on Azure.
|
|
9
9
|
* See https://learn.microsoft.com/en-us/azure/storage/common/storage-samples-javascript?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json for more information.
|
|
10
10
|
*/
|
|
11
|
-
class AzureBlobStorageConnector {
|
|
11
|
+
export class AzureBlobStorageConnector {
|
|
12
12
|
/**
|
|
13
13
|
* The namespace for the items.
|
|
14
14
|
*/
|
|
@@ -22,6 +22,11 @@ class AzureBlobStorageConnector {
|
|
|
22
22
|
* @internal
|
|
23
23
|
*/
|
|
24
24
|
_config;
|
|
25
|
+
/**
|
|
26
|
+
* The keys to use from the context ids to create partitions.
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
_partitionContextIds;
|
|
25
30
|
/**
|
|
26
31
|
* The Azure Service client.
|
|
27
32
|
* @internal
|
|
@@ -43,9 +48,17 @@ class AzureBlobStorageConnector {
|
|
|
43
48
|
Guards.stringValue(AzureBlobStorageConnector.CLASS_NAME, "options.config.accountKey", options.config.accountKey);
|
|
44
49
|
Guards.stringValue(AzureBlobStorageConnector.CLASS_NAME, "options.config.containerName", options.config.containerName);
|
|
45
50
|
this._config = options.config;
|
|
51
|
+
this._partitionContextIds = options.partitionContextIds;
|
|
46
52
|
this._azureBlobServiceClient = new BlobServiceClient((options.config.endpoint ?? "https://{accountName}.blob.core.windows.net/").replace("{accountName}", options.config.accountName), new StorageSharedKeyCredential(options.config.accountName, options.config.accountKey));
|
|
47
53
|
this._azureContainerClient = this._azureBlobServiceClient.getContainerClient(options.config.containerName);
|
|
48
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns the class name of the component.
|
|
57
|
+
* @returns The class name of the component.
|
|
58
|
+
*/
|
|
59
|
+
className() {
|
|
60
|
+
return AzureBlobStorageConnector.CLASS_NAME;
|
|
61
|
+
}
|
|
49
62
|
/**
|
|
50
63
|
* Bootstrap the component by creating and initializing any resources it needs.
|
|
51
64
|
* @param nodeLoggingComponentType The node logging component type.
|
|
@@ -54,14 +67,6 @@ class AzureBlobStorageConnector {
|
|
|
54
67
|
async bootstrap(nodeLoggingComponentType) {
|
|
55
68
|
const nodeLogging = ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
56
69
|
try {
|
|
57
|
-
await nodeLogging?.log({
|
|
58
|
-
level: "info",
|
|
59
|
-
source: AzureBlobStorageConnector.CLASS_NAME,
|
|
60
|
-
message: "containerCreating",
|
|
61
|
-
data: {
|
|
62
|
-
container: this._config.containerName
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
70
|
const exists = await this._azureContainerClient.exists();
|
|
66
71
|
if (exists) {
|
|
67
72
|
await nodeLogging?.log({
|
|
@@ -74,15 +79,15 @@ class AzureBlobStorageConnector {
|
|
|
74
79
|
});
|
|
75
80
|
}
|
|
76
81
|
else {
|
|
77
|
-
await this._azureContainerClient.create();
|
|
78
82
|
await nodeLogging?.log({
|
|
79
83
|
level: "info",
|
|
80
84
|
source: AzureBlobStorageConnector.CLASS_NAME,
|
|
81
|
-
message: "
|
|
85
|
+
message: "containerCreating",
|
|
82
86
|
data: {
|
|
83
87
|
container: this._config.containerName
|
|
84
88
|
}
|
|
85
89
|
});
|
|
90
|
+
await this._azureContainerClient.create();
|
|
86
91
|
}
|
|
87
92
|
}
|
|
88
93
|
catch (err) {
|
|
@@ -106,9 +111,11 @@ class AzureBlobStorageConnector {
|
|
|
106
111
|
*/
|
|
107
112
|
async set(blob) {
|
|
108
113
|
Guards.uint8Array(AzureBlobStorageConnector.CLASS_NAME, "blob", blob);
|
|
114
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
115
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
109
116
|
try {
|
|
110
117
|
const id = Converter.bytesToHex(Sha256.sum256(blob));
|
|
111
|
-
const blockBlobClient = this._azureContainerClient.getBlockBlobClient(id);
|
|
118
|
+
const blockBlobClient = this._azureContainerClient.getBlockBlobClient(`${partitionKey ?? "root"}/${id}`);
|
|
112
119
|
await blockBlobClient.uploadData(blob);
|
|
113
120
|
return `blob:${new Urn(AzureBlobStorageConnector.NAMESPACE, id).toString()}`;
|
|
114
121
|
}
|
|
@@ -124,6 +131,8 @@ class AzureBlobStorageConnector {
|
|
|
124
131
|
async get(id) {
|
|
125
132
|
Urn.guard(AzureBlobStorageConnector.CLASS_NAME, "id", id);
|
|
126
133
|
const urnParsed = Urn.fromValidString(id);
|
|
134
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
135
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
127
136
|
if (urnParsed.namespaceMethod() !== AzureBlobStorageConnector.NAMESPACE) {
|
|
128
137
|
throw new GeneralError(AzureBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
|
|
129
138
|
namespace: AzureBlobStorageConnector.NAMESPACE,
|
|
@@ -132,11 +141,14 @@ class AzureBlobStorageConnector {
|
|
|
132
141
|
}
|
|
133
142
|
try {
|
|
134
143
|
const key = urnParsed.namespaceSpecific(1);
|
|
135
|
-
const blobClient = this._azureContainerClient.getBlobClient(key);
|
|
144
|
+
const blobClient = this._azureContainerClient.getBlobClient(`${partitionKey ?? "root"}/${key}`);
|
|
136
145
|
const buffer = await blobClient.downloadToBuffer();
|
|
137
146
|
return new Uint8Array(buffer);
|
|
138
147
|
}
|
|
139
148
|
catch (err) {
|
|
149
|
+
if (Is.object(err) && err.statusCode === 404) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
140
152
|
throw new GeneralError(AzureBlobStorageConnector.CLASS_NAME, "getBlobFailed", {
|
|
141
153
|
id,
|
|
142
154
|
namespace: AzureBlobStorageConnector.NAMESPACE
|
|
@@ -151,6 +163,8 @@ class AzureBlobStorageConnector {
|
|
|
151
163
|
async remove(id) {
|
|
152
164
|
Urn.guard(AzureBlobStorageConnector.CLASS_NAME, "id", id);
|
|
153
165
|
const urnParsed = Urn.fromValidString(id);
|
|
166
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
167
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
154
168
|
if (urnParsed.namespaceMethod() !== AzureBlobStorageConnector.NAMESPACE) {
|
|
155
169
|
throw new GeneralError(AzureBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
|
|
156
170
|
namespace: AzureBlobStorageConnector.NAMESPACE,
|
|
@@ -159,7 +173,7 @@ class AzureBlobStorageConnector {
|
|
|
159
173
|
}
|
|
160
174
|
try {
|
|
161
175
|
const key = urnParsed.namespaceSpecific(1);
|
|
162
|
-
const blockBlobClient =
|
|
176
|
+
const blockBlobClient = this._azureContainerClient.getBlockBlobClient(`${partitionKey ?? "root"}/${key}`);
|
|
163
177
|
const options = {
|
|
164
178
|
deleteSnapshots: "include"
|
|
165
179
|
};
|
|
@@ -177,5 +191,4 @@ class AzureBlobStorageConnector {
|
|
|
177
191
|
}
|
|
178
192
|
}
|
|
179
193
|
}
|
|
180
|
-
|
|
181
|
-
export { AzureBlobStorageConnector };
|
|
194
|
+
//# sourceMappingURL=azureBlobStorageConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azureBlobStorageConnector.js","sourceRoot":"","sources":["../../src/azureBlobStorageConnector.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAIN,iBAAiB,EAGjB,0BAA0B,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EACN,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,MAAM,EACN,EAAE,EACF,GAAG,EACH,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1C;;;GAGG;AACH,MAAM,OAAO,yBAAyB;IACrC;;OAEG;IACI,MAAM,CAAU,SAAS,GAAW,OAAO,CAAC;IAEnD;;OAEG;IACI,MAAM,CAAU,UAAU,+BAA+C;IAEhF;;;OAGG;IACc,OAAO,CAAmC;IAE3D;;;OAGG;IACc,oBAAoB,CAAY;IAEjD;;;OAGG;IACc,uBAAuB,CAAoB;IAE5D;;;OAGG;IACc,qBAAqB,CAAkB;IAExD;;;OAGG;IACH,YAAY,OAAqD;QAChE,MAAM,CAAC,MAAM,CAAC,yBAAyB,CAAC,UAAU,aAAmB,OAAO,CAAC,CAAC;QAC9E,MAAM,CAAC,MAAM,CACZ,yBAAyB,CAAC,UAAU,oBAEpC,OAAO,CAAC,MAAM,CACd,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,yBAAyB,CAAC,UAAU,gCAEpC,OAAO,CAAC,MAAM,CAAC,WAAW,CAC1B,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,yBAAyB,CAAC,UAAU,+BAEpC,OAAO,CAAC,MAAM,CAAC,UAAU,CACzB,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,yBAAyB,CAAC,UAAU,kCAEpC,OAAO,CAAC,MAAM,CAAC,aAAa,CAC5B,CAAC;QAEF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;QAExD,IAAI,CAAC,uBAAuB,GAAG,IAAI,iBAAiB,CACnD,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,8CAA8C,CAAC,CAAC,OAAO,CAClF,eAAe,EACf,OAAO,CAAC,MAAM,CAAC,WAAW,CAC1B,EACD,IAAI,0BAA0B,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CACrF,CAAC;QAEF,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,uBAAuB,CAAC,kBAAkB,CAC3E,OAAO,CAAC,MAAM,CAAC,aAAa,CAC5B,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,yBAAyB,CAAC,UAAU,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,SAAS,CAAC,wBAAiC;QACvD,MAAM,WAAW,GAAG,gBAAgB,CAAC,WAAW,CAAoB,wBAAwB,CAAC,CAAC;QAE9F,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,CAAC;YAEzD,IAAI,MAAM,EAAE,CAAC;gBACZ,MAAM,WAAW,EAAE,GAAG,CAAC;oBACtB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,yBAAyB,CAAC,UAAU;oBAC5C,OAAO,EAAE,iBAAiB;oBAC1B,IAAI,EAAE;wBACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa;qBACrC;iBACD,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,MAAM,WAAW,EAAE,GAAG,CAAC;oBACtB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,yBAAyB,CAAC,UAAU;oBAC5C,OAAO,EAAE,mBAAmB;oBAC5B,IAAI,EAAE;wBACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa;qBACrC;iBACD,CAAC,CAAC;gBACH,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,CAAC;YAC3C,CAAC;QACF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,WAAW,EAAE,GAAG,CAAC;gBACtB,KAAK,EAAE,OAAO;gBACd,MAAM,EAAE,yBAAyB,CAAC,UAAU;gBAC5C,OAAO,EAAE,uBAAuB;gBAChC,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa;iBACrC;gBACD,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC;aAC/B,CAAC,CAAC;YAEH,OAAO,KAAK,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,GAAG,CAAC,IAAgB;QAChC,MAAM,CAAC,UAAU,CAAC,yBAAyB,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAE5E,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,CAAC;YACJ,MAAM,EAAE,GAAG,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YACrD,MAAM,eAAe,GAAoB,IAAI,CAAC,qBAAqB,CAAC,kBAAkB,CACrF,GAAG,YAAY,IAAI,MAAM,IAAI,EAAE,EAAE,CACjC,CAAC;YACF,MAAM,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAEvC,OAAO,QAAQ,IAAI,GAAG,CAAC,yBAAyB,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC9E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CAAC,yBAAyB,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QAC/F,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,GAAG,CAAC,EAAU;QAC1B,GAAG,CAAC,KAAK,CAAC,yBAAyB,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAE1C,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,SAAS,CAAC,eAAe,EAAE,KAAK,yBAAyB,CAAC,SAAS,EAAE,CAAC;YACzE,MAAM,IAAI,YAAY,CAAC,yBAAyB,CAAC,UAAU,EAAE,mBAAmB,EAAE;gBACjF,SAAS,EAAE,yBAAyB,CAAC,SAAS;gBAC9C,EAAE;aACF,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,UAAU,GAAe,IAAI,CAAC,qBAAqB,CAAC,aAAa,CACtE,GAAG,YAAY,IAAI,MAAM,IAAI,GAAG,EAAE,CAClC,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,gBAAgB,EAAE,CAAC;YACnD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,EAAE,CAAC,MAAM,CAAyB,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBACtE,OAAO;YACR,CAAC;YACD,MAAM,IAAI,YAAY,CACrB,yBAAyB,CAAC,UAAU,EACpC,eAAe,EACf;gBACC,EAAE;gBACF,SAAS,EAAE,yBAAyB,CAAC,SAAS;aAC9C,EACD,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,MAAM,CAAC,EAAU;QAC7B,GAAG,CAAC,KAAK,CAAC,yBAAyB,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAE1C,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,SAAS,CAAC,eAAe,EAAE,KAAK,yBAAyB,CAAC,SAAS,EAAE,CAAC;YACzE,MAAM,IAAI,YAAY,CAAC,yBAAyB,CAAC,UAAU,EAAE,mBAAmB,EAAE;gBACjF,SAAS,EAAE,yBAAyB,CAAC,SAAS;gBAC9C,EAAE;aACF,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;YAE3C,MAAM,eAAe,GAAoB,IAAI,CAAC,qBAAqB,CAAC,kBAAkB,CACrF,GAAG,YAAY,IAAI,MAAM,IAAI,GAAG,EAAE,CAClC,CAAC;YAEF,MAAM,OAAO,GAAsB;gBAClC,eAAe,EAAE,SAAS;aAC1B,CAAC;YACF,MAAM,kBAAkB,GAAuB,MAAM,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAErF,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC;YACb,CAAC;YACD,OAAO,KAAK,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,EAAE,CAAC,MAAM,CAAyB,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBACtE,OAAO,KAAK,CAAC;YACd,CAAC;YACD,MAAM,IAAI,YAAY,CAAC,yBAAyB,CAAC,UAAU,EAAE,kBAAkB,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/F,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\ttype BlobClient,\n\ttype BlobDeleteOptions,\n\ttype BlobDeleteResponse,\n\tBlobServiceClient,\n\ttype BlockBlobClient,\n\ttype ContainerClient,\n\tStorageSharedKeyCredential\n} from \"@azure/storage-blob\";\nimport type { IBlobStorageConnector } from \"@twin.org/blob-storage-models\";\nimport { ContextIdHelper, ContextIdStore } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tComponentFactory,\n\tConverter,\n\tGeneralError,\n\tGuards,\n\tIs,\n\tUrn\n} from \"@twin.org/core\";\nimport { Sha256 } from \"@twin.org/crypto\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IAzureBlobStorageConnectorConfig } from \"./models/IAzureBlobStorageConnectorConfig.js\";\nimport type { IAzureBlobStorageConnectorConstructorOptions } from \"./models/IAzureBlobStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing blob storage operations on Azure.\n * See https://learn.microsoft.com/en-us/azure/storage/common/storage-samples-javascript?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json for more information.\n */\nexport class AzureBlobStorageConnector implements IBlobStorageConnector {\n\t/**\n\t * The namespace for the items.\n\t */\n\tpublic static readonly NAMESPACE: string = \"azure\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<AzureBlobStorageConnector>();\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IAzureBlobStorageConnectorConfig;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The Azure Service client.\n\t * @internal\n\t */\n\tprivate readonly _azureBlobServiceClient: BlobServiceClient;\n\n\t/**\n\t * The Azure Container client.\n\t * @internal\n\t */\n\tprivate readonly _azureContainerClient: ContainerClient;\n\n\t/**\n\t * Create a new instance of AzureBlobStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IAzureBlobStorageConnectorConstructorOptions) {\n\t\tGuards.object(AzureBlobStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.object<IAzureBlobStorageConnectorConfig>(\n\t\t\tAzureBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tAzureBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.accountName),\n\t\t\toptions.config.accountName\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tAzureBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.accountKey),\n\t\t\toptions.config.accountKey\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tAzureBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.containerName),\n\t\t\toptions.config.containerName\n\t\t);\n\n\t\tthis._config = options.config;\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\n\t\tthis._azureBlobServiceClient = new BlobServiceClient(\n\t\t\t(options.config.endpoint ?? \"https://{accountName}.blob.core.windows.net/\").replace(\n\t\t\t\t\"{accountName}\",\n\t\t\t\toptions.config.accountName\n\t\t\t),\n\t\t\tnew StorageSharedKeyCredential(options.config.accountName, options.config.accountKey)\n\t\t);\n\n\t\tthis._azureContainerClient = this._azureBlobServiceClient.getContainerClient(\n\t\t\toptions.config.containerName\n\t\t);\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn AzureBlobStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Bootstrap the component by creating and initializing any resources it needs.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the bootstrapping process was successful.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\ttry {\n\t\t\tconst exists = await this._azureContainerClient.exists();\n\n\t\t\tif (exists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: AzureBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tmessage: \"containerExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcontainer: this._config.containerName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: AzureBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tmessage: \"containerCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcontainer: this._config.containerName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tawait this._azureContainerClient.create();\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: AzureBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"containerCreateFailed\",\n\t\t\t\tdata: {\n\t\t\t\t\tcontainer: this._config.containerName\n\t\t\t\t},\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set the blob.\n\t * @param blob The data for the blob.\n\t * @returns The id of the stored blob in urn format.\n\t */\n\tpublic async set(blob: Uint8Array): Promise<string> {\n\t\tGuards.uint8Array(AzureBlobStorageConnector.CLASS_NAME, nameof(blob), blob);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst id = Converter.bytesToHex(Sha256.sum256(blob));\n\t\t\tconst blockBlobClient: BlockBlobClient = this._azureContainerClient.getBlockBlobClient(\n\t\t\t\t`${partitionKey ?? \"root\"}/${id}`\n\t\t\t);\n\t\t\tawait blockBlobClient.uploadData(blob);\n\n\t\t\treturn `blob:${new Urn(AzureBlobStorageConnector.NAMESPACE, id).toString()}`;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(AzureBlobStorageConnector.CLASS_NAME, \"setBlobFailed\", undefined, err);\n\t\t}\n\t}\n\n\t/**\n\t * Get the blob.\n\t * @param id The id of the blob to get in urn format.\n\t * @returns The data for the blob if it can be found or undefined.\n\t */\n\tpublic async get(id: string): Promise<Uint8Array | undefined> {\n\t\tUrn.guard(AzureBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (urnParsed.namespaceMethod() !== AzureBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(AzureBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: AzureBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst key = urnParsed.namespaceSpecific(1);\n\t\t\tconst blobClient: BlobClient = this._azureContainerClient.getBlobClient(\n\t\t\t\t`${partitionKey ?? \"root\"}/${key}`\n\t\t\t);\n\t\t\tconst buffer = await blobClient.downloadToBuffer();\n\t\t\treturn new Uint8Array(buffer);\n\t\t} catch (err) {\n\t\t\tif (Is.object<{ statusCode: number }>(err) && err.statusCode === 404) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new GeneralError(\n\t\t\t\tAzureBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\"getBlobFailed\",\n\t\t\t\t{\n\t\t\t\t\tid,\n\t\t\t\t\tnamespace: AzureBlobStorageConnector.NAMESPACE\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the blob.\n\t * @param id The id of the blob to remove in urn format.\n\t * @returns True if the blob was found.\n\t */\n\tpublic async remove(id: string): Promise<boolean> {\n\t\tUrn.guard(AzureBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (urnParsed.namespaceMethod() !== AzureBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(AzureBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: AzureBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst key = urnParsed.namespaceSpecific(1);\n\n\t\t\tconst blockBlobClient: BlockBlobClient = this._azureContainerClient.getBlockBlobClient(\n\t\t\t\t`${partitionKey ?? \"root\"}/${key}`\n\t\t\t);\n\n\t\t\tconst options: BlobDeleteOptions = {\n\t\t\t\tdeleteSnapshots: \"include\"\n\t\t\t};\n\t\t\tconst blobDeleteResponse: BlobDeleteResponse = await blockBlobClient.delete(options);\n\n\t\t\tif (!blobDeleteResponse.errorCode) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} catch (err) {\n\t\t\tif (Is.object<{ statusCode: number }>(err) && err.statusCode === 404) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthrow new GeneralError(AzureBlobStorageConnector.CLASS_NAME, \"removeBlobFailed\", { id }, err);\n\t\t}\n\t}\n}\n"]}
|
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
export * from "./azureBlobStorageConnector.js";
|
|
4
|
+
export * from "./models/IAzureBlobStorageConnectorConfig.js";
|
|
5
|
+
export * from "./models/IAzureBlobStorageConnectorConstructorOptions.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8CAA8C,CAAC;AAC7D,cAAc,0DAA0D,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./azureBlobStorageConnector.js\";\nexport * from \"./models/IAzureBlobStorageConnectorConfig.js\";\nexport * from \"./models/IAzureBlobStorageConnectorConstructorOptions.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IAzureBlobStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/IAzureBlobStorageConnectorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the Azure Blob Storage Connector.\n */\nexport interface IAzureBlobStorageConnectorConfig {\n\t/**\n\t * Storage account name.\n\t */\n\taccountName: string;\n\n\t/**\n\t * Account key.\n\t */\n\taccountKey: string;\n\n\t/**\n\t * The Azure container name.\n\t */\n\tcontainerName: string;\n\n\t/**\n\t * Endpoint defaults to `https://{accountName}.blob.core.windows.net/` where accountName will be\n\t * substituted.\n\t */\n\tendpoint?: string;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IAzureBlobStorageConnectorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IAzureBlobStorageConnectorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IAzureBlobStorageConnectorConfig } from \"./IAzureBlobStorageConnectorConfig.js\";\n\n/**\n * Options for the Azure Blob Storage Connector constructor.\n */\nexport interface IAzureBlobStorageConnectorConstructorOptions {\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t */\n\tpartitionContextIds?: string[];\n\n\t/**\n\t * The configuration for the connector.\n\t */\n\tconfig: IAzureBlobStorageConnectorConfig;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IBlobStorageConnector } from "@twin.org/blob-storage-models";
|
|
2
|
-
import type { IAzureBlobStorageConnectorConstructorOptions } from "./models/IAzureBlobStorageConnectorConstructorOptions";
|
|
2
|
+
import type { IAzureBlobStorageConnectorConstructorOptions } from "./models/IAzureBlobStorageConnectorConstructorOptions.js";
|
|
3
3
|
/**
|
|
4
4
|
* Class for performing blob storage operations on Azure.
|
|
5
5
|
* See https://learn.microsoft.com/en-us/azure/storage/common/storage-samples-javascript?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json for more information.
|
|
@@ -18,6 +18,11 @@ export declare class AzureBlobStorageConnector implements IBlobStorageConnector
|
|
|
18
18
|
* @param options The options for the connector.
|
|
19
19
|
*/
|
|
20
20
|
constructor(options: IAzureBlobStorageConnectorConstructorOptions);
|
|
21
|
+
/**
|
|
22
|
+
* Returns the class name of the component.
|
|
23
|
+
* @returns The class name of the component.
|
|
24
|
+
*/
|
|
25
|
+
className(): string;
|
|
21
26
|
/**
|
|
22
27
|
* Bootstrap the component by creating and initializing any resources it needs.
|
|
23
28
|
* @param nodeLoggingComponentType The node logging component type.
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from "./azureBlobStorageConnector";
|
|
2
|
-
export * from "./models/IAzureBlobStorageConnectorConfig";
|
|
3
|
-
export * from "./models/IAzureBlobStorageConnectorConstructorOptions";
|
|
1
|
+
export * from "./azureBlobStorageConnector.js";
|
|
2
|
+
export * from "./models/IAzureBlobStorageConnectorConfig.js";
|
|
3
|
+
export * from "./models/IAzureBlobStorageConnectorConstructorOptions.js";
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import type { IAzureBlobStorageConnectorConfig } from "./IAzureBlobStorageConnectorConfig";
|
|
1
|
+
import type { IAzureBlobStorageConnectorConfig } from "./IAzureBlobStorageConnectorConfig.js";
|
|
2
2
|
/**
|
|
3
3
|
* Options for the Azure Blob Storage Connector constructor.
|
|
4
4
|
*/
|
|
5
5
|
export interface IAzureBlobStorageConnectorConstructorOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The keys to use from the context ids to create partitions.
|
|
8
|
+
*/
|
|
9
|
+
partitionContextIds?: string[];
|
|
6
10
|
/**
|
|
7
11
|
* The configuration for the connector.
|
|
8
12
|
*/
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @twin.org/blob-storage-connector-azure - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.2](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-azure-v0.0.3-next.1...blob-storage-connector-azure-v0.0.3-next.2) (2026-01-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Miscellaneous Chores
|
|
7
|
+
|
|
8
|
+
* **blob-storage-connector-azure:** Synchronize repo versions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/blob-storage-models bumped from 0.0.3-next.1 to 0.0.3-next.2
|
|
16
|
+
|
|
17
|
+
## [0.0.3-next.1](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-azure-v0.0.3-next.0...blob-storage-connector-azure-v0.0.3-next.1) (2025-11-11)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add context id features ([#30](https://github.com/twinfoundation/blob-storage/issues/30)) ([fbf1c92](https://github.com/twinfoundation/blob-storage/commit/fbf1c9276424c841ef5ef3f4de8469ab3fba7e9c))
|
|
23
|
+
* add validate-locales ([f20fcec](https://github.com/twinfoundation/blob-storage/commit/f20fceced91e39a0c9edb770b2e43ce944c92f3c))
|
|
24
|
+
* eslint migration to flat config ([e4239dd](https://github.com/twinfoundation/blob-storage/commit/e4239dd1c721955cff7f0357255d2bba15319972))
|
|
25
|
+
* update dependencies ([56f0094](https://github.com/twinfoundation/blob-storage/commit/56f0094b68d8bd22864cd899ac1b61d95540f719))
|
|
26
|
+
* update framework core ([ff339fe](https://github.com/twinfoundation/blob-storage/commit/ff339fe7e3f09ddff429907834bdf43617e9c05e))
|
|
27
|
+
* use shared store mechanism ([#12](https://github.com/twinfoundation/blob-storage/issues/12)) ([cae8110](https://github.com/twinfoundation/blob-storage/commit/cae8110681847a1ac4fcac968b8196694e49c320))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Dependencies
|
|
31
|
+
|
|
32
|
+
* The following workspace dependencies were updated
|
|
33
|
+
* dependencies
|
|
34
|
+
* @twin.org/blob-storage-models bumped from 0.0.3-next.0 to 0.0.3-next.1
|
|
35
|
+
|
|
3
36
|
## [0.0.2-next.5](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-azure-v0.0.2-next.4...blob-storage-connector-azure-v0.0.2-next.5) (2025-10-09)
|
|
4
37
|
|
|
5
38
|
|
|
@@ -45,6 +45,24 @@ Runtime name for the class.
|
|
|
45
45
|
|
|
46
46
|
## Methods
|
|
47
47
|
|
|
48
|
+
### className()
|
|
49
|
+
|
|
50
|
+
> **className**(): `string`
|
|
51
|
+
|
|
52
|
+
Returns the class name of the component.
|
|
53
|
+
|
|
54
|
+
#### Returns
|
|
55
|
+
|
|
56
|
+
`string`
|
|
57
|
+
|
|
58
|
+
The class name of the component.
|
|
59
|
+
|
|
60
|
+
#### Implementation of
|
|
61
|
+
|
|
62
|
+
`IBlobStorageConnector.className`
|
|
63
|
+
|
|
64
|
+
***
|
|
65
|
+
|
|
48
66
|
### bootstrap()
|
|
49
67
|
|
|
50
68
|
> **bootstrap**(`nodeLoggingComponentType?`): `Promise`\<`boolean`\>
|
|
@@ -99,7 +117,7 @@ The id of the stored blob in urn format.
|
|
|
99
117
|
|
|
100
118
|
### get()
|
|
101
119
|
|
|
102
|
-
> **get**(`id`): `Promise`\<`
|
|
120
|
+
> **get**(`id`): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\> \| `undefined`\>
|
|
103
121
|
|
|
104
122
|
Get the blob.
|
|
105
123
|
|
|
@@ -113,7 +131,7 @@ The id of the blob to get in urn format.
|
|
|
113
131
|
|
|
114
132
|
#### Returns
|
|
115
133
|
|
|
116
|
-
`Promise`\<`
|
|
134
|
+
`Promise`\<`Uint8Array`\<`ArrayBufferLike`\> \| `undefined`\>
|
|
117
135
|
|
|
118
136
|
The data for the blob if it can be found or undefined.
|
|
119
137
|
|
|
@@ -4,6 +4,14 @@ Options for the Azure Blob Storage Connector constructor.
|
|
|
4
4
|
|
|
5
5
|
## Properties
|
|
6
6
|
|
|
7
|
+
### partitionContextIds?
|
|
8
|
+
|
|
9
|
+
> `optional` **partitionContextIds**: `string`[]
|
|
10
|
+
|
|
11
|
+
The keys to use from the context ids to create partitions.
|
|
12
|
+
|
|
13
|
+
***
|
|
14
|
+
|
|
7
15
|
### config
|
|
8
16
|
|
|
9
17
|
> **config**: [`IAzureBlobStorageConnectorConfig`](IAzureBlobStorageConnectorConfig.md)
|
package/locales/en.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/blob-storage-connector-azure",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3-next.2",
|
|
4
4
|
"description": "Blob Storage connector implementation using Azure",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,27 +14,26 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@azure/storage-blob": "12.
|
|
18
|
-
"@twin.org/blob-storage-models": "0.0.
|
|
17
|
+
"@azure/storage-blob": "12.29.1",
|
|
18
|
+
"@twin.org/blob-storage-models": "0.0.3-next.2",
|
|
19
|
+
"@twin.org/context": "next",
|
|
19
20
|
"@twin.org/core": "next",
|
|
20
21
|
"@twin.org/crypto": "next",
|
|
21
22
|
"@twin.org/logging-models": "next",
|
|
22
23
|
"@twin.org/nameof": "next"
|
|
23
24
|
},
|
|
24
|
-
"main": "./dist/
|
|
25
|
-
"module": "./dist/esm/index.mjs",
|
|
25
|
+
"main": "./dist/es/index.js",
|
|
26
26
|
"types": "./dist/types/index.d.ts",
|
|
27
27
|
"exports": {
|
|
28
28
|
".": {
|
|
29
29
|
"types": "./dist/types/index.d.ts",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
30
|
+
"import": "./dist/es/index.js",
|
|
31
|
+
"default": "./dist/es/index.js"
|
|
32
32
|
},
|
|
33
33
|
"./locales/*.json": "./locales/*.json"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
|
-
"dist/
|
|
37
|
-
"dist/esm",
|
|
36
|
+
"dist/es",
|
|
38
37
|
"dist/types",
|
|
39
38
|
"locales",
|
|
40
39
|
"docs"
|
package/dist/cjs/index.cjs
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var storageBlob = require('@azure/storage-blob');
|
|
4
|
-
var core = require('@twin.org/core');
|
|
5
|
-
var crypto = require('@twin.org/crypto');
|
|
6
|
-
|
|
7
|
-
// Copyright 2024 IOTA Stiftung.
|
|
8
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
9
|
-
/**
|
|
10
|
-
* Class for performing blob storage operations on Azure.
|
|
11
|
-
* See https://learn.microsoft.com/en-us/azure/storage/common/storage-samples-javascript?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json for more information.
|
|
12
|
-
*/
|
|
13
|
-
class AzureBlobStorageConnector {
|
|
14
|
-
/**
|
|
15
|
-
* The namespace for the items.
|
|
16
|
-
*/
|
|
17
|
-
static NAMESPACE = "azure";
|
|
18
|
-
/**
|
|
19
|
-
* Runtime name for the class.
|
|
20
|
-
*/
|
|
21
|
-
static CLASS_NAME = "AzureBlobStorageConnector";
|
|
22
|
-
/**
|
|
23
|
-
* The configuration for the connector.
|
|
24
|
-
* @internal
|
|
25
|
-
*/
|
|
26
|
-
_config;
|
|
27
|
-
/**
|
|
28
|
-
* The Azure Service client.
|
|
29
|
-
* @internal
|
|
30
|
-
*/
|
|
31
|
-
_azureBlobServiceClient;
|
|
32
|
-
/**
|
|
33
|
-
* The Azure Container client.
|
|
34
|
-
* @internal
|
|
35
|
-
*/
|
|
36
|
-
_azureContainerClient;
|
|
37
|
-
/**
|
|
38
|
-
* Create a new instance of AzureBlobStorageConnector.
|
|
39
|
-
* @param options The options for the connector.
|
|
40
|
-
*/
|
|
41
|
-
constructor(options) {
|
|
42
|
-
core.Guards.object(AzureBlobStorageConnector.CLASS_NAME, "options", options);
|
|
43
|
-
core.Guards.object(AzureBlobStorageConnector.CLASS_NAME, "options.config", options.config);
|
|
44
|
-
core.Guards.stringValue(AzureBlobStorageConnector.CLASS_NAME, "options.config.accountName", options.config.accountName);
|
|
45
|
-
core.Guards.stringValue(AzureBlobStorageConnector.CLASS_NAME, "options.config.accountKey", options.config.accountKey);
|
|
46
|
-
core.Guards.stringValue(AzureBlobStorageConnector.CLASS_NAME, "options.config.containerName", options.config.containerName);
|
|
47
|
-
this._config = options.config;
|
|
48
|
-
this._azureBlobServiceClient = new storageBlob.BlobServiceClient((options.config.endpoint ?? "https://{accountName}.blob.core.windows.net/").replace("{accountName}", options.config.accountName), new storageBlob.StorageSharedKeyCredential(options.config.accountName, options.config.accountKey));
|
|
49
|
-
this._azureContainerClient = this._azureBlobServiceClient.getContainerClient(options.config.containerName);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Bootstrap the component by creating and initializing any resources it needs.
|
|
53
|
-
* @param nodeLoggingComponentType The node logging component type.
|
|
54
|
-
* @returns True if the bootstrapping process was successful.
|
|
55
|
-
*/
|
|
56
|
-
async bootstrap(nodeLoggingComponentType) {
|
|
57
|
-
const nodeLogging = core.ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
58
|
-
try {
|
|
59
|
-
await nodeLogging?.log({
|
|
60
|
-
level: "info",
|
|
61
|
-
source: AzureBlobStorageConnector.CLASS_NAME,
|
|
62
|
-
message: "containerCreating",
|
|
63
|
-
data: {
|
|
64
|
-
container: this._config.containerName
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
const exists = await this._azureContainerClient.exists();
|
|
68
|
-
if (exists) {
|
|
69
|
-
await nodeLogging?.log({
|
|
70
|
-
level: "info",
|
|
71
|
-
source: AzureBlobStorageConnector.CLASS_NAME,
|
|
72
|
-
message: "containerExists",
|
|
73
|
-
data: {
|
|
74
|
-
container: this._config.containerName
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
await this._azureContainerClient.create();
|
|
80
|
-
await nodeLogging?.log({
|
|
81
|
-
level: "info",
|
|
82
|
-
source: AzureBlobStorageConnector.CLASS_NAME,
|
|
83
|
-
message: "containerCreated",
|
|
84
|
-
data: {
|
|
85
|
-
container: this._config.containerName
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
catch (err) {
|
|
91
|
-
await nodeLogging?.log({
|
|
92
|
-
level: "error",
|
|
93
|
-
source: AzureBlobStorageConnector.CLASS_NAME,
|
|
94
|
-
message: "containerCreateFailed",
|
|
95
|
-
data: {
|
|
96
|
-
container: this._config.containerName
|
|
97
|
-
},
|
|
98
|
-
error: core.BaseError.fromError(err)
|
|
99
|
-
});
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Set the blob.
|
|
106
|
-
* @param blob The data for the blob.
|
|
107
|
-
* @returns The id of the stored blob in urn format.
|
|
108
|
-
*/
|
|
109
|
-
async set(blob) {
|
|
110
|
-
core.Guards.uint8Array(AzureBlobStorageConnector.CLASS_NAME, "blob", blob);
|
|
111
|
-
try {
|
|
112
|
-
const id = core.Converter.bytesToHex(crypto.Sha256.sum256(blob));
|
|
113
|
-
const blockBlobClient = this._azureContainerClient.getBlockBlobClient(id);
|
|
114
|
-
await blockBlobClient.uploadData(blob);
|
|
115
|
-
return `blob:${new core.Urn(AzureBlobStorageConnector.NAMESPACE, id).toString()}`;
|
|
116
|
-
}
|
|
117
|
-
catch (err) {
|
|
118
|
-
throw new core.GeneralError(AzureBlobStorageConnector.CLASS_NAME, "setBlobFailed", undefined, err);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Get the blob.
|
|
123
|
-
* @param id The id of the blob to get in urn format.
|
|
124
|
-
* @returns The data for the blob if it can be found or undefined.
|
|
125
|
-
*/
|
|
126
|
-
async get(id) {
|
|
127
|
-
core.Urn.guard(AzureBlobStorageConnector.CLASS_NAME, "id", id);
|
|
128
|
-
const urnParsed = core.Urn.fromValidString(id);
|
|
129
|
-
if (urnParsed.namespaceMethod() !== AzureBlobStorageConnector.NAMESPACE) {
|
|
130
|
-
throw new core.GeneralError(AzureBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
|
|
131
|
-
namespace: AzureBlobStorageConnector.NAMESPACE,
|
|
132
|
-
id
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
try {
|
|
136
|
-
const key = urnParsed.namespaceSpecific(1);
|
|
137
|
-
const blobClient = this._azureContainerClient.getBlobClient(key);
|
|
138
|
-
const buffer = await blobClient.downloadToBuffer();
|
|
139
|
-
return new Uint8Array(buffer);
|
|
140
|
-
}
|
|
141
|
-
catch (err) {
|
|
142
|
-
throw new core.GeneralError(AzureBlobStorageConnector.CLASS_NAME, "getBlobFailed", {
|
|
143
|
-
id,
|
|
144
|
-
namespace: AzureBlobStorageConnector.NAMESPACE
|
|
145
|
-
}, err);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Remove the blob.
|
|
150
|
-
* @param id The id of the blob to remove in urn format.
|
|
151
|
-
* @returns True if the blob was found.
|
|
152
|
-
*/
|
|
153
|
-
async remove(id) {
|
|
154
|
-
core.Urn.guard(AzureBlobStorageConnector.CLASS_NAME, "id", id);
|
|
155
|
-
const urnParsed = core.Urn.fromValidString(id);
|
|
156
|
-
if (urnParsed.namespaceMethod() !== AzureBlobStorageConnector.NAMESPACE) {
|
|
157
|
-
throw new core.GeneralError(AzureBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
|
|
158
|
-
namespace: AzureBlobStorageConnector.NAMESPACE,
|
|
159
|
-
id
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
try {
|
|
163
|
-
const key = urnParsed.namespaceSpecific(1);
|
|
164
|
-
const blockBlobClient = await this._azureContainerClient.getBlockBlobClient(key);
|
|
165
|
-
const options = {
|
|
166
|
-
deleteSnapshots: "include"
|
|
167
|
-
};
|
|
168
|
-
const blobDeleteResponse = await blockBlobClient.delete(options);
|
|
169
|
-
if (!blobDeleteResponse.errorCode) {
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
172
|
-
return false;
|
|
173
|
-
}
|
|
174
|
-
catch (err) {
|
|
175
|
-
if (core.Is.object(err) && err.statusCode === 404) {
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
throw new core.GeneralError(AzureBlobStorageConnector.CLASS_NAME, "removeBlobFailed", { id }, err);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
exports.AzureBlobStorageConnector = AzureBlobStorageConnector;
|