@twin.org/blob-storage-connector-gcp 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/dist/{esm/index.mjs → es/gcpBlobStorageConnector.js} +31 -21
- package/dist/es/gcpBlobStorageConnector.js.map +1 -0
- package/dist/es/index.js +6 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IGcpBlobStorageConnectorConfig.js +4 -0
- package/dist/es/models/IGcpBlobStorageConnectorConfig.js.map +1 -0
- package/dist/es/models/IGcpBlobStorageConnectorConstructorOptions.js +2 -0
- package/dist/es/models/IGcpBlobStorageConnectorConstructorOptions.js.map +1 -0
- package/dist/types/gcpBlobStorageConnector.d.ts +6 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/models/IGcpBlobStorageConnectorConstructorOptions.d.ts +5 -1
- package/docs/changelog.md +34 -0
- package/docs/reference/classes/GcpBlobStorageConnector.md +20 -2
- package/docs/reference/interfaces/IGcpBlobStorageConnectorConstructorOptions.md +8 -0
- package/locales/en.json +0 -1
- package/package.json +8 -9
- package/dist/cjs/index.cjs +0 -188
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { Storage } from '@google-cloud/storage';
|
|
2
|
-
import { Guards, Is, ObjectHelper, Converter, ComponentFactory, BaseError, Urn, GeneralError } from '@twin.org/core';
|
|
3
|
-
import { Sha256 } from '@twin.org/crypto';
|
|
4
|
-
import { MimeTypes } from '@twin.org/web';
|
|
5
|
-
|
|
6
1
|
// Copyright 2024 IOTA Stiftung.
|
|
7
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { Storage } from "@google-cloud/storage";
|
|
4
|
+
import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
|
|
5
|
+
import { BaseError, ComponentFactory, Converter, GeneralError, Guards, Is, ObjectHelper, Urn } from "@twin.org/core";
|
|
6
|
+
import { Sha256 } from "@twin.org/crypto";
|
|
7
|
+
import { MimeTypes } from "@twin.org/web";
|
|
8
8
|
/**
|
|
9
9
|
* Class for performing blob storage operations on GCP Storage.
|
|
10
10
|
* See https://cloud.google.com/storage/docs/reference/libraries for more information.
|
|
11
11
|
*/
|
|
12
|
-
class GcpBlobStorageConnector {
|
|
12
|
+
export class GcpBlobStorageConnector {
|
|
13
13
|
/**
|
|
14
14
|
* The namespace for the items.
|
|
15
15
|
*/
|
|
@@ -23,6 +23,11 @@ class GcpBlobStorageConnector {
|
|
|
23
23
|
* @internal
|
|
24
24
|
*/
|
|
25
25
|
_config;
|
|
26
|
+
/**
|
|
27
|
+
* The keys to use from the context ids to create partitions.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
_partitionContextIds;
|
|
26
31
|
/**
|
|
27
32
|
* The GCP Storage client.
|
|
28
33
|
* @internal
|
|
@@ -43,12 +48,20 @@ class GcpBlobStorageConnector {
|
|
|
43
48
|
}
|
|
44
49
|
Guards.stringValue(GcpBlobStorageConnector.CLASS_NAME, "options.config.bucketName", options.config.bucketName);
|
|
45
50
|
this._config = options.config;
|
|
51
|
+
this._partitionContextIds = options.partitionContextIds;
|
|
46
52
|
this._storage = new Storage({
|
|
47
53
|
projectId: this._config.projectId,
|
|
48
54
|
apiEndpoint: this._config.apiEndpoint,
|
|
49
55
|
credentials
|
|
50
56
|
});
|
|
51
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns the class name of the component.
|
|
60
|
+
* @returns The class name of the component.
|
|
61
|
+
*/
|
|
62
|
+
className() {
|
|
63
|
+
return GcpBlobStorageConnector.CLASS_NAME;
|
|
64
|
+
}
|
|
52
65
|
/**
|
|
53
66
|
* Bootstrap the component by creating and initializing any resources it needs.
|
|
54
67
|
* @param nodeLoggingComponentType The node logging component type.
|
|
@@ -57,14 +70,6 @@ class GcpBlobStorageConnector {
|
|
|
57
70
|
async bootstrap(nodeLoggingComponentType) {
|
|
58
71
|
const nodeLogging = ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
59
72
|
try {
|
|
60
|
-
await nodeLogging?.log({
|
|
61
|
-
level: "info",
|
|
62
|
-
source: GcpBlobStorageConnector.CLASS_NAME,
|
|
63
|
-
message: "bucketCreating",
|
|
64
|
-
data: {
|
|
65
|
-
bucket: this._config.bucketName
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
73
|
const [buckets] = await this._storage.getBuckets();
|
|
69
74
|
const bucketExists = buckets.some(bucket => bucket.name === this._config.bucketName);
|
|
70
75
|
if (bucketExists) {
|
|
@@ -78,15 +83,15 @@ class GcpBlobStorageConnector {
|
|
|
78
83
|
});
|
|
79
84
|
}
|
|
80
85
|
else {
|
|
81
|
-
await this._storage.createBucket(this._config.bucketName);
|
|
82
86
|
await nodeLogging?.log({
|
|
83
87
|
level: "info",
|
|
84
88
|
source: GcpBlobStorageConnector.CLASS_NAME,
|
|
85
|
-
message: "
|
|
89
|
+
message: "bucketCreating",
|
|
86
90
|
data: {
|
|
87
91
|
bucket: this._config.bucketName
|
|
88
92
|
}
|
|
89
93
|
});
|
|
94
|
+
await this._storage.createBucket(this._config.bucketName);
|
|
90
95
|
}
|
|
91
96
|
}
|
|
92
97
|
catch (err) {
|
|
@@ -110,10 +115,12 @@ class GcpBlobStorageConnector {
|
|
|
110
115
|
*/
|
|
111
116
|
async set(blob) {
|
|
112
117
|
Guards.uint8Array(GcpBlobStorageConnector.CLASS_NAME, "blob", blob);
|
|
118
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
119
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
113
120
|
try {
|
|
114
121
|
const id = Converter.bytesToHex(Sha256.sum256(blob));
|
|
115
122
|
const bucket = this._storage.bucket(this._config.bucketName);
|
|
116
|
-
const file = bucket.file(id);
|
|
123
|
+
const file = bucket.file(`${partitionKey ?? "root"}/${id}`);
|
|
117
124
|
await file.save(blob, {
|
|
118
125
|
contentType: MimeTypes.OctetStream
|
|
119
126
|
});
|
|
@@ -130,6 +137,8 @@ class GcpBlobStorageConnector {
|
|
|
130
137
|
*/
|
|
131
138
|
async get(id) {
|
|
132
139
|
Urn.guard(GcpBlobStorageConnector.CLASS_NAME, "id", id);
|
|
140
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
141
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
133
142
|
const urnParsed = Urn.fromValidString(id);
|
|
134
143
|
if (urnParsed.namespaceMethod() !== GcpBlobStorageConnector.NAMESPACE) {
|
|
135
144
|
throw new GeneralError(GcpBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
|
|
@@ -140,7 +149,7 @@ class GcpBlobStorageConnector {
|
|
|
140
149
|
try {
|
|
141
150
|
const key = urnParsed.namespaceSpecific(1);
|
|
142
151
|
const bucket = this._storage.bucket(this._config.bucketName);
|
|
143
|
-
const file = bucket.file(key);
|
|
152
|
+
const file = bucket.file(`${partitionKey ?? "root"}/${key}`);
|
|
144
153
|
const [exists] = await file.exists();
|
|
145
154
|
if (!exists) {
|
|
146
155
|
return undefined;
|
|
@@ -159,6 +168,8 @@ class GcpBlobStorageConnector {
|
|
|
159
168
|
*/
|
|
160
169
|
async remove(id) {
|
|
161
170
|
Urn.guard(GcpBlobStorageConnector.CLASS_NAME, "id", id);
|
|
171
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
172
|
+
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
162
173
|
const urnParsed = Urn.fromValidString(id);
|
|
163
174
|
if (urnParsed.namespaceMethod() !== GcpBlobStorageConnector.NAMESPACE) {
|
|
164
175
|
throw new GeneralError(GcpBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
|
|
@@ -169,7 +180,7 @@ class GcpBlobStorageConnector {
|
|
|
169
180
|
try {
|
|
170
181
|
const key = urnParsed.namespaceSpecific(1);
|
|
171
182
|
const bucket = this._storage.bucket(this._config.bucketName);
|
|
172
|
-
const file = bucket.file(key);
|
|
183
|
+
const file = bucket.file(`${partitionKey ?? "root"}/${key}`);
|
|
173
184
|
const [exists] = await file.exists();
|
|
174
185
|
if (!exists) {
|
|
175
186
|
return false;
|
|
@@ -182,5 +193,4 @@ class GcpBlobStorageConnector {
|
|
|
182
193
|
}
|
|
183
194
|
}
|
|
184
195
|
}
|
|
185
|
-
|
|
186
|
-
export { GcpBlobStorageConnector };
|
|
196
|
+
//# sourceMappingURL=gcpBlobStorageConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gcpBlobStorageConnector.js","sourceRoot":"","sources":["../../src/gcpBlobStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Storage } from \"@google-cloud/storage\";\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\tObjectHelper,\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 { MimeTypes } from \"@twin.org/web\";\nimport type { JWTInput } from \"google-auth-library\";\nimport type { IGcpBlobStorageConnectorConfig } from \"./models/IGcpBlobStorageConnectorConfig.js\";\nimport type { IGcpBlobStorageConnectorConstructorOptions } from \"./models/IGcpBlobStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing blob storage operations on GCP Storage.\n * See https://cloud.google.com/storage/docs/reference/libraries for more information.\n */\nexport class GcpBlobStorageConnector implements IBlobStorageConnector {\n\t/**\n\t * The namespace for the items.\n\t */\n\tpublic static readonly NAMESPACE: string = \"gcp\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<GcpBlobStorageConnector>();\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IGcpBlobStorageConnectorConfig;\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 GCP Storage client.\n\t * @internal\n\t */\n\tprivate readonly _storage: Storage;\n\n\t/**\n\t * Create a new instance of GcpBlobStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IGcpBlobStorageConnectorConstructorOptions) {\n\t\tGuards.object(GcpBlobStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.object<IGcpBlobStorageConnectorConfig>(\n\t\t\tGcpBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tGcpBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.projectId),\n\t\t\toptions.config.projectId\n\t\t);\n\n\t\tlet credentials: JWTInput | undefined;\n\t\tif (!Is.empty(options.config.credentials)) {\n\t\t\tGuards.stringBase64(\n\t\t\t\tGcpBlobStorageConnector.CLASS_NAME,\n\t\t\t\tnameof(options.config.credentials),\n\t\t\t\toptions.config.credentials\n\t\t\t);\n\t\t\tcredentials = ObjectHelper.fromBytes<JWTInput>(\n\t\t\t\tConverter.base64ToBytes(options.config.credentials)\n\t\t\t);\n\t\t}\n\n\t\tGuards.stringValue(\n\t\t\tGcpBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.bucketName),\n\t\t\toptions.config.bucketName\n\t\t);\n\n\t\tthis._config = options.config;\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._storage = new Storage({\n\t\t\tprojectId: this._config.projectId,\n\t\t\tapiEndpoint: this._config.apiEndpoint,\n\t\t\tcredentials\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 GcpBlobStorageConnector.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 [buckets] = await this._storage.getBuckets();\n\t\t\tconst bucketExists = buckets.some(bucket => bucket.name === this._config.bucketName);\n\n\t\t\tif (bucketExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: GcpBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tmessage: \"bucketExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tbucket: this._config.bucketName\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: GcpBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tmessage: \"bucketCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tbucket: this._config.bucketName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tawait this._storage.createBucket(this._config.bucketName);\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: GcpBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"bucketCreateFailed\",\n\t\t\t\tdata: {\n\t\t\t\t\tbucket: this._config.bucketName\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(GcpBlobStorageConnector.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 bucket = this._storage.bucket(this._config.bucketName);\n\t\t\tconst file = bucket.file(`${partitionKey ?? \"root\"}/${id}`);\n\n\t\t\tawait file.save(blob, {\n\t\t\t\tcontentType: MimeTypes.OctetStream\n\t\t\t});\n\n\t\t\treturn `blob:${new Urn(GcpBlobStorageConnector.NAMESPACE, id).toString()}`;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(GcpBlobStorageConnector.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(GcpBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceMethod() !== GcpBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(GcpBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: GcpBlobStorageConnector.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 bucket = this._storage.bucket(this._config.bucketName);\n\t\t\tconst file = bucket.file(`${partitionKey ?? \"root\"}/${key}`);\n\n\t\t\tconst [exists] = await file.exists();\n\t\t\tif (!exists) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst [contents] = await file.download();\n\t\t\treturn new Uint8Array(contents);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(GcpBlobStorageConnector.CLASS_NAME, \"getBlobFailed\", { id }, err);\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(GcpBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceMethod() !== GcpBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(GcpBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: GcpBlobStorageConnector.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 bucket = this._storage.bucket(this._config.bucketName);\n\t\t\tconst file = bucket.file(`${partitionKey ?? \"root\"}/${key}`);\n\n\t\t\tconst [exists] = await file.exists();\n\t\t\tif (!exists) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tawait file.delete();\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(GcpBlobStorageConnector.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 "./gcpBlobStorageConnector.js";
|
|
4
|
+
export * from "./models/IGcpBlobStorageConnectorConfig.js";
|
|
5
|
+
export * from "./models/IGcpBlobStorageConnectorConstructorOptions.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,8BAA8B,CAAC;AAC7C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,wDAAwD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./gcpBlobStorageConnector.js\";\nexport * from \"./models/IGcpBlobStorageConnectorConfig.js\";\nexport * from \"./models/IGcpBlobStorageConnectorConstructorOptions.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IGcpBlobStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/IGcpBlobStorageConnectorConfig.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 GCP Blob Storage Connector.\n */\nexport interface IGcpBlobStorageConnectorConfig {\n\t/**\n\t * The GCP project ID.\n\t */\n\tprojectId: string;\n\n\t/**\n\t * The GCP credentials, a base64 encoded version of the JWTInput data type.\n\t */\n\tcredentials?: string;\n\n\t/**\n\t * The GCP bucket name.\n\t */\n\tbucketName: string;\n\n\t/**\n\t * Optional endpoint for GCP Storage emulator.\n\t */\n\tapiEndpoint?: string;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IGcpBlobStorageConnectorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IGcpBlobStorageConnectorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IGcpBlobStorageConnectorConfig } from \"./IGcpBlobStorageConnectorConfig.js\";\n\n/**\n * Options for the GCP Blob Storage Connector constructor.\n */\nexport interface IGcpBlobStorageConnectorConstructorOptions {\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: IGcpBlobStorageConnectorConfig;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IBlobStorageConnector } from "@twin.org/blob-storage-models";
|
|
2
|
-
import type { IGcpBlobStorageConnectorConstructorOptions } from "./models/IGcpBlobStorageConnectorConstructorOptions";
|
|
2
|
+
import type { IGcpBlobStorageConnectorConstructorOptions } from "./models/IGcpBlobStorageConnectorConstructorOptions.js";
|
|
3
3
|
/**
|
|
4
4
|
* Class for performing blob storage operations on GCP Storage.
|
|
5
5
|
* See https://cloud.google.com/storage/docs/reference/libraries for more information.
|
|
@@ -18,6 +18,11 @@ export declare class GcpBlobStorageConnector implements IBlobStorageConnector {
|
|
|
18
18
|
* @param options The options for the connector.
|
|
19
19
|
*/
|
|
20
20
|
constructor(options: IGcpBlobStorageConnectorConstructorOptions);
|
|
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 "./gcpBlobStorageConnector";
|
|
2
|
-
export * from "./models/IGcpBlobStorageConnectorConfig";
|
|
3
|
-
export * from "./models/IGcpBlobStorageConnectorConstructorOptions";
|
|
1
|
+
export * from "./gcpBlobStorageConnector.js";
|
|
2
|
+
export * from "./models/IGcpBlobStorageConnectorConfig.js";
|
|
3
|
+
export * from "./models/IGcpBlobStorageConnectorConstructorOptions.js";
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import type { IGcpBlobStorageConnectorConfig } from "./IGcpBlobStorageConnectorConfig";
|
|
1
|
+
import type { IGcpBlobStorageConnectorConfig } from "./IGcpBlobStorageConnectorConfig.js";
|
|
2
2
|
/**
|
|
3
3
|
* Options for the GCP Blob Storage Connector constructor.
|
|
4
4
|
*/
|
|
5
5
|
export interface IGcpBlobStorageConnectorConstructorOptions {
|
|
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,39 @@
|
|
|
1
1
|
# @twin.org/blob-storage-connector-gcp - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.2](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-gcp-v0.0.3-next.1...blob-storage-connector-gcp-v0.0.3-next.2) (2026-01-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Miscellaneous Chores
|
|
7
|
+
|
|
8
|
+
* **blob-storage-connector-gcp:** 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-gcp-v0.0.3-next.0...blob-storage-connector-gcp-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 GCP blob storage connector ([#8](https://github.com/twinfoundation/blob-storage/issues/8)) ([4f6d579](https://github.com/twinfoundation/blob-storage/commit/4f6d579c01b3ae13ebcd9029b279da62e4fde859))
|
|
24
|
+
* add validate-locales ([f20fcec](https://github.com/twinfoundation/blob-storage/commit/f20fceced91e39a0c9edb770b2e43ce944c92f3c))
|
|
25
|
+
* eslint migration to flat config ([e4239dd](https://github.com/twinfoundation/blob-storage/commit/e4239dd1c721955cff7f0357255d2bba15319972))
|
|
26
|
+
* update dependencies ([56f0094](https://github.com/twinfoundation/blob-storage/commit/56f0094b68d8bd22864cd899ac1b61d95540f719))
|
|
27
|
+
* update framework core ([ff339fe](https://github.com/twinfoundation/blob-storage/commit/ff339fe7e3f09ddff429907834bdf43617e9c05e))
|
|
28
|
+
* use shared store mechanism ([#12](https://github.com/twinfoundation/blob-storage/issues/12)) ([cae8110](https://github.com/twinfoundation/blob-storage/commit/cae8110681847a1ac4fcac968b8196694e49c320))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Dependencies
|
|
32
|
+
|
|
33
|
+
* The following workspace dependencies were updated
|
|
34
|
+
* dependencies
|
|
35
|
+
* @twin.org/blob-storage-models bumped from 0.0.3-next.0 to 0.0.3-next.1
|
|
36
|
+
|
|
3
37
|
## [0.0.2-next.5](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-gcp-v0.0.2-next.4...blob-storage-connector-gcp-v0.0.2-next.5) (2025-10-09)
|
|
4
38
|
|
|
5
39
|
|
|
@@ -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 GCP 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**: [`IGcpBlobStorageConnectorConfig`](IGcpBlobStorageConnectorConfig.md)
|
package/locales/en.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/blob-storage-connector-gcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3-next.2",
|
|
4
4
|
"description": "Blob Storage connector implementation using Google Cloud Storage",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,28 +14,27 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@google-cloud/storage": "7.17.
|
|
18
|
-
"@twin.org/blob-storage-models": "0.0.
|
|
17
|
+
"@google-cloud/storage": "7.17.3",
|
|
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
|
"@twin.org/web": "next"
|
|
24
25
|
},
|
|
25
|
-
"main": "./dist/
|
|
26
|
-
"module": "./dist/esm/index.mjs",
|
|
26
|
+
"main": "./dist/es/index.js",
|
|
27
27
|
"types": "./dist/types/index.d.ts",
|
|
28
28
|
"exports": {
|
|
29
29
|
".": {
|
|
30
30
|
"types": "./dist/types/index.d.ts",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
31
|
+
"import": "./dist/es/index.js",
|
|
32
|
+
"default": "./dist/es/index.js"
|
|
33
33
|
},
|
|
34
34
|
"./locales/*.json": "./locales/*.json"
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
|
-
"dist/
|
|
38
|
-
"dist/esm",
|
|
37
|
+
"dist/es",
|
|
39
38
|
"dist/types",
|
|
40
39
|
"locales",
|
|
41
40
|
"docs"
|
package/dist/cjs/index.cjs
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var storage = require('@google-cloud/storage');
|
|
4
|
-
var core = require('@twin.org/core');
|
|
5
|
-
var crypto = require('@twin.org/crypto');
|
|
6
|
-
var web = require('@twin.org/web');
|
|
7
|
-
|
|
8
|
-
// Copyright 2024 IOTA Stiftung.
|
|
9
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
10
|
-
/**
|
|
11
|
-
* Class for performing blob storage operations on GCP Storage.
|
|
12
|
-
* See https://cloud.google.com/storage/docs/reference/libraries for more information.
|
|
13
|
-
*/
|
|
14
|
-
class GcpBlobStorageConnector {
|
|
15
|
-
/**
|
|
16
|
-
* The namespace for the items.
|
|
17
|
-
*/
|
|
18
|
-
static NAMESPACE = "gcp";
|
|
19
|
-
/**
|
|
20
|
-
* Runtime name for the class.
|
|
21
|
-
*/
|
|
22
|
-
static CLASS_NAME = "GcpBlobStorageConnector";
|
|
23
|
-
/**
|
|
24
|
-
* The configuration for the connector.
|
|
25
|
-
* @internal
|
|
26
|
-
*/
|
|
27
|
-
_config;
|
|
28
|
-
/**
|
|
29
|
-
* The GCP Storage client.
|
|
30
|
-
* @internal
|
|
31
|
-
*/
|
|
32
|
-
_storage;
|
|
33
|
-
/**
|
|
34
|
-
* Create a new instance of GcpBlobStorageConnector.
|
|
35
|
-
* @param options The options for the connector.
|
|
36
|
-
*/
|
|
37
|
-
constructor(options) {
|
|
38
|
-
core.Guards.object(GcpBlobStorageConnector.CLASS_NAME, "options", options);
|
|
39
|
-
core.Guards.object(GcpBlobStorageConnector.CLASS_NAME, "options.config", options.config);
|
|
40
|
-
core.Guards.stringValue(GcpBlobStorageConnector.CLASS_NAME, "options.config.projectId", options.config.projectId);
|
|
41
|
-
let credentials;
|
|
42
|
-
if (!core.Is.empty(options.config.credentials)) {
|
|
43
|
-
core.Guards.stringBase64(GcpBlobStorageConnector.CLASS_NAME, "options.config.credentials", options.config.credentials);
|
|
44
|
-
credentials = core.ObjectHelper.fromBytes(core.Converter.base64ToBytes(options.config.credentials));
|
|
45
|
-
}
|
|
46
|
-
core.Guards.stringValue(GcpBlobStorageConnector.CLASS_NAME, "options.config.bucketName", options.config.bucketName);
|
|
47
|
-
this._config = options.config;
|
|
48
|
-
this._storage = new storage.Storage({
|
|
49
|
-
projectId: this._config.projectId,
|
|
50
|
-
apiEndpoint: this._config.apiEndpoint,
|
|
51
|
-
credentials
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Bootstrap the component by creating and initializing any resources it needs.
|
|
56
|
-
* @param nodeLoggingComponentType The node logging component type.
|
|
57
|
-
* @returns True if the bootstrapping process was successful.
|
|
58
|
-
*/
|
|
59
|
-
async bootstrap(nodeLoggingComponentType) {
|
|
60
|
-
const nodeLogging = core.ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
61
|
-
try {
|
|
62
|
-
await nodeLogging?.log({
|
|
63
|
-
level: "info",
|
|
64
|
-
source: GcpBlobStorageConnector.CLASS_NAME,
|
|
65
|
-
message: "bucketCreating",
|
|
66
|
-
data: {
|
|
67
|
-
bucket: this._config.bucketName
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
const [buckets] = await this._storage.getBuckets();
|
|
71
|
-
const bucketExists = buckets.some(bucket => bucket.name === this._config.bucketName);
|
|
72
|
-
if (bucketExists) {
|
|
73
|
-
await nodeLogging?.log({
|
|
74
|
-
level: "info",
|
|
75
|
-
source: GcpBlobStorageConnector.CLASS_NAME,
|
|
76
|
-
message: "bucketExists",
|
|
77
|
-
data: {
|
|
78
|
-
bucket: this._config.bucketName
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
await this._storage.createBucket(this._config.bucketName);
|
|
84
|
-
await nodeLogging?.log({
|
|
85
|
-
level: "info",
|
|
86
|
-
source: GcpBlobStorageConnector.CLASS_NAME,
|
|
87
|
-
message: "bucketCreated",
|
|
88
|
-
data: {
|
|
89
|
-
bucket: this._config.bucketName
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
catch (err) {
|
|
95
|
-
await nodeLogging?.log({
|
|
96
|
-
level: "error",
|
|
97
|
-
source: GcpBlobStorageConnector.CLASS_NAME,
|
|
98
|
-
message: "bucketCreateFailed",
|
|
99
|
-
data: {
|
|
100
|
-
bucket: this._config.bucketName
|
|
101
|
-
},
|
|
102
|
-
error: core.BaseError.fromError(err)
|
|
103
|
-
});
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Set the blob.
|
|
110
|
-
* @param blob The data for the blob.
|
|
111
|
-
* @returns The id of the stored blob in urn format.
|
|
112
|
-
*/
|
|
113
|
-
async set(blob) {
|
|
114
|
-
core.Guards.uint8Array(GcpBlobStorageConnector.CLASS_NAME, "blob", blob);
|
|
115
|
-
try {
|
|
116
|
-
const id = core.Converter.bytesToHex(crypto.Sha256.sum256(blob));
|
|
117
|
-
const bucket = this._storage.bucket(this._config.bucketName);
|
|
118
|
-
const file = bucket.file(id);
|
|
119
|
-
await file.save(blob, {
|
|
120
|
-
contentType: web.MimeTypes.OctetStream
|
|
121
|
-
});
|
|
122
|
-
return `blob:${new core.Urn(GcpBlobStorageConnector.NAMESPACE, id).toString()}`;
|
|
123
|
-
}
|
|
124
|
-
catch (err) {
|
|
125
|
-
throw new core.GeneralError(GcpBlobStorageConnector.CLASS_NAME, "setBlobFailed", undefined, err);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Get the blob.
|
|
130
|
-
* @param id The id of the blob to get in urn format.
|
|
131
|
-
* @returns The data for the blob if it can be found or undefined.
|
|
132
|
-
*/
|
|
133
|
-
async get(id) {
|
|
134
|
-
core.Urn.guard(GcpBlobStorageConnector.CLASS_NAME, "id", id);
|
|
135
|
-
const urnParsed = core.Urn.fromValidString(id);
|
|
136
|
-
if (urnParsed.namespaceMethod() !== GcpBlobStorageConnector.NAMESPACE) {
|
|
137
|
-
throw new core.GeneralError(GcpBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
|
|
138
|
-
namespace: GcpBlobStorageConnector.NAMESPACE,
|
|
139
|
-
id
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
const key = urnParsed.namespaceSpecific(1);
|
|
144
|
-
const bucket = this._storage.bucket(this._config.bucketName);
|
|
145
|
-
const file = bucket.file(key);
|
|
146
|
-
const [exists] = await file.exists();
|
|
147
|
-
if (!exists) {
|
|
148
|
-
return undefined;
|
|
149
|
-
}
|
|
150
|
-
const [contents] = await file.download();
|
|
151
|
-
return new Uint8Array(contents);
|
|
152
|
-
}
|
|
153
|
-
catch (err) {
|
|
154
|
-
throw new core.GeneralError(GcpBlobStorageConnector.CLASS_NAME, "getBlobFailed", { id }, err);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Remove the blob.
|
|
159
|
-
* @param id The id of the blob to remove in urn format.
|
|
160
|
-
* @returns True if the blob was found.
|
|
161
|
-
*/
|
|
162
|
-
async remove(id) {
|
|
163
|
-
core.Urn.guard(GcpBlobStorageConnector.CLASS_NAME, "id", id);
|
|
164
|
-
const urnParsed = core.Urn.fromValidString(id);
|
|
165
|
-
if (urnParsed.namespaceMethod() !== GcpBlobStorageConnector.NAMESPACE) {
|
|
166
|
-
throw new core.GeneralError(GcpBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
|
|
167
|
-
namespace: GcpBlobStorageConnector.NAMESPACE,
|
|
168
|
-
id
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
try {
|
|
172
|
-
const key = urnParsed.namespaceSpecific(1);
|
|
173
|
-
const bucket = this._storage.bucket(this._config.bucketName);
|
|
174
|
-
const file = bucket.file(key);
|
|
175
|
-
const [exists] = await file.exists();
|
|
176
|
-
if (!exists) {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
await file.delete();
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
catch (err) {
|
|
183
|
-
throw new core.GeneralError(GcpBlobStorageConnector.CLASS_NAME, "removeBlobFailed", { id }, err);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
exports.GcpBlobStorageConnector = GcpBlobStorageConnector;
|