@twin.org/blob-storage-connector-ipfs 0.0.3-next.13 → 0.0.3-next.15

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 CHANGED
@@ -13,7 +13,7 @@ npm install @twin.org/blob-storage-connector-ipfs
13
13
  To perform testing of this component it may be necessary to launch a local instance to communicate with.
14
14
 
15
15
  ```shell
16
- docker run -d --name twin-blob-storage-ipfs -p 4001:4001 -p 4001:4001/udp -p 18080:8080 -p 5001:5001 ipfs/kubo:latest
16
+ docker run -d --name twin-blob-storage-ipfs -p 24001:4001 -p 24001:4001/udp -p 28080:8080 -p 25001:5001 ipfs/kubo:latest
17
17
  ```
18
18
 
19
19
  ## Examples
@@ -150,14 +150,9 @@ export class IpfsBlobStorageConnector {
150
150
  }
151
151
  };
152
152
  this.addSecurity(fetchOptions);
153
- const responseStat = await fetch(`${this._config.apiUrl}/block/stat?arg=${ipfsHash}&local=true`, fetchOptions);
154
- if (!responseStat.ok) {
155
- const resp = await responseStat.json();
156
- if (Is.object(resp) &&
157
- Is.stringValue(resp.Message) &&
158
- resp.Message.includes("not found")) {
159
- return;
160
- }
153
+ const pinResponse = await fetch(`${this._config.apiUrl}/pin/ls?arg=${ipfsHash}`, fetchOptions);
154
+ if (!pinResponse.ok) {
155
+ return undefined;
161
156
  }
162
157
  const response = await fetch(`${this._config.apiUrl}/cat?arg=${ipfsHash}`, fetchOptions);
163
158
  if (response.ok) {
@@ -224,7 +219,7 @@ export class IpfsBlobStorageConnector {
224
219
  }
225
220
  /**
226
221
  * Remove all blobs from the storage.
227
- * @returns Nothing.
222
+ * @returns A promise that resolves when all pinned blobs have been unpinned and garbage collected.
228
223
  */
229
224
  async empty() {
230
225
  try {
@@ -297,16 +292,15 @@ export class IpfsBlobStorageConnector {
297
292
  if (response.ok) {
298
293
  return true;
299
294
  }
300
- const error = await response.json();
301
- throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "fetchFail", error);
295
+ return false;
302
296
  }
303
297
  catch (err) {
304
298
  throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "removeBlobFailed", undefined, err);
305
299
  }
306
300
  }
307
301
  /**
308
- * Add the security to the request.
309
- * @param requestInit The request options.
302
+ * Add the security headers to the request if a bearer token is configured.
303
+ * @param requestInit The request options to augment with security headers.
310
304
  * @internal
311
305
  */
312
306
  addSecurity(requestInit) {
@@ -1 +1 @@
1
- {"version":3,"file":"ipfsBlobStorageConnector.js","sourceRoot":"","sources":["../../src/ipfsBlobStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\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\tHealthStatus,\n\tIs,\n\tStringHelper,\n\tUrn,\n\ttype IHealth\n} from \"@twin.org/core\";\nimport { Blake2b } from \"@twin.org/crypto\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { HeaderHelper, HeaderTypes, HttpMethod, MimeTypes } from \"@twin.org/web\";\nimport type { IIpfsBlobStorageConnectorConfig } from \"./models/IIpfsBlobStorageConnectorConfig.js\";\nimport type { IIpfsBlobStorageConnectorConstructorOptions } from \"./models/IIpfsBlobStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing blob storage operations on IPFS.\n * See https://docs.ipfs.tech/reference/kubo/rpc/ for more information.\n */\nexport class IpfsBlobStorageConnector implements IBlobStorageConnector {\n\t/**\n\t * The namespace for the items.\n\t */\n\tpublic static readonly NAMESPACE: string = \"ipfs\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<IpfsBlobStorageConnector>();\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IIpfsBlobStorageConnectorConfig;\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 * Create a new instance of IpfsBlobStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IIpfsBlobStorageConnectorConstructorOptions) {\n\t\tGuards.object(IpfsBlobStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.object<IIpfsBlobStorageConnectorConfig>(\n\t\t\tIpfsBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tIpfsBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.apiUrl),\n\t\t\toptions.config.apiUrl\n\t\t);\n\n\t\tthis._config = options.config;\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._config.apiUrl = StringHelper.trimTrailingSlashes(this._config.apiUrl);\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 IpfsBlobStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.addSecurity(fetchOptions);\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/version`, fetchOptions);\n\t\t\tif (response.ok) {\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tapiUrl: this._config.apiUrl\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\t\t} catch {}\n\t\treturn [\n\t\t\t{\n\t\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\tmessage: \"healthCheckFailed\",\n\t\t\t\tdata: {\n\t\t\t\t\tapiUrl: this._config.apiUrl\n\t\t\t\t}\n\t\t\t}\n\t\t];\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(IpfsBlobStorageConnector.CLASS_NAME, nameof(blob), blob);\n\n\t\ttry {\n\t\t\tconst formBlob = new Blob([new Uint8Array(blob)], { type: MimeTypes.OctetStream });\n\t\t\tconst formData = new FormData();\n\t\t\tformData.append(\"file\", formBlob);\n\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\tbody: formData,\n\t\t\t\theaders: {\n\t\t\t\t\t[HeaderTypes.Accept]: MimeTypes.Json,\n\t\t\t\t\t[HeaderTypes.ContentDisposition]: \"form-data\"\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/add?pin=true`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst result = (await response.json()) as {\n\t\t\t\t\tName: string;\n\t\t\t\t\tHash: string;\n\t\t\t\t\tSize: string;\n\t\t\t\t};\n\n\t\t\t\tconst partitionSegment = await this.buildPartitionSegment();\n\t\t\t\tconst urnParts = Is.stringValue(partitionSegment)\n\t\t\t\t\t? [result.Hash, partitionSegment]\n\t\t\t\t\t: [result.Hash];\n\n\t\t\t\treturn `blob:${new Urn(IpfsBlobStorageConnector.NAMESPACE, urnParts).toString()}`;\n\t\t\t}\n\n\t\t\tconst error = await response.json();\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"fetchFail\", error);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.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(IpfsBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceMethod() !== IpfsBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: IpfsBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\tconst partitionSegment = await this.buildPartitionSegment();\n\t\tconst storedPartitionSegment = Is.stringValue(urnParsed.namespaceSpecific(2))\n\t\t\t? urnParsed.namespaceSpecific(2)\n\t\t\t: undefined;\n\n\t\tif (partitionSegment !== storedPartitionSegment) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst ipfsHash = urnParsed.namespaceSpecific(1).split(\":\")[0];\n\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst responseStat = await fetch(\n\t\t\t\t`${this._config.apiUrl}/block/stat?arg=${ipfsHash}&local=true`,\n\t\t\t\tfetchOptions\n\t\t\t);\n\n\t\t\tif (!responseStat.ok) {\n\t\t\t\tconst resp = await responseStat.json();\n\t\t\t\tif (\n\t\t\t\t\tIs.object<{ Message: string }>(resp) &&\n\t\t\t\t\tIs.stringValue(resp.Message) &&\n\t\t\t\t\tresp.Message.includes(\"not found\")\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/cat?arg=${ipfsHash}`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst result = await response.arrayBuffer();\n\t\t\t\treturn new Uint8Array(result);\n\t\t\t}\n\n\t\t\tconst error = await response.json();\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"fetchFail\", error);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"getBlobFailed\", undefined, err);\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the component and remove any resources it created.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\tmessage: \"storeTearingDown\"\n\t\t});\n\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/pin/ls`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst result = (await response.json()) as { Keys: { [cid: string]: unknown } };\n\n\t\t\t\tfor (const cid of Object.keys(result.Keys)) {\n\t\t\t\t\tconst unpinFetchOptions: RequestInit = {\n\t\t\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tthis.addSecurity(unpinFetchOptions);\n\t\t\t\t\tawait fetch(`${this._config.apiUrl}/pin/rm?arg=${cid}`, unpinFetchOptions);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"storeTornDown\"\n\t\t\t});\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove all blobs from the storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/pin/ls`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst result = (await response.json()) as { Keys: { [cid: string]: unknown } };\n\n\t\t\t\tfor (const cid of Object.keys(result.Keys)) {\n\t\t\t\t\tconst unpinFetchOptions: RequestInit = {\n\t\t\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tthis.addSecurity(unpinFetchOptions);\n\t\t\t\t\tawait fetch(`${this._config.apiUrl}/pin/rm?arg=${cid}`, unpinFetchOptions);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst gcFetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.addSecurity(gcFetchOptions);\n\t\t\tconst gcResponse = await fetch(`${this._config.apiUrl}/repo/gc`, gcFetchOptions);\n\t\t\tawait gcResponse.text();\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"emptyFailed\", undefined, 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(IpfsBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceMethod() !== IpfsBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: IpfsBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\tconst partitionSegment = await this.buildPartitionSegment();\n\t\tconst storedPartitionSegment = Is.stringValue(urnParsed.namespaceSpecific(2))\n\t\t\t? urnParsed.namespaceSpecific(2)\n\t\t\t: undefined;\n\n\t\tif (partitionSegment !== storedPartitionSegment) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst ipfsHash = urnParsed.namespaceSpecific(1).split(\":\")[0];\n\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/pin/rm?arg=${ipfsHash}`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst error = await response.json();\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"fetchFail\", error);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tIpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeBlobFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Add the security to the request.\n\t * @param requestInit The request options.\n\t * @internal\n\t */\n\tprivate addSecurity(requestInit: RequestInit): void {\n\t\tif (Is.stringValue(this._config.bearerToken)) {\n\t\t\trequestInit.headers = {\n\t\t\t\t...requestInit.headers,\n\t\t\t\t[HeaderTypes.Authorization]: HeaderHelper.createBearer(this._config.bearerToken)\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Build the partition segment from the current context.\n\t * @returns The hex-encoded Blake2b hash of the partition key, or undefined if no partition applies.\n\t * @internal\n\t */\n\tprivate async buildPartitionSegment(): Promise<string | undefined> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\treturn Converter.bytesToHex(Blake2b.sum256(Converter.utf8ToBytes(partitionKey)));\n\t\t}\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"ipfsBlobStorageConnector.js","sourceRoot":"","sources":["../../src/ipfsBlobStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\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\tHealthStatus,\n\tIs,\n\tStringHelper,\n\tUrn,\n\ttype IHealth\n} from \"@twin.org/core\";\nimport { Blake2b } from \"@twin.org/crypto\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { HeaderHelper, HeaderTypes, HttpMethod, MimeTypes } from \"@twin.org/web\";\nimport type { IIpfsBlobStorageConnectorConfig } from \"./models/IIpfsBlobStorageConnectorConfig.js\";\nimport type { IIpfsBlobStorageConnectorConstructorOptions } from \"./models/IIpfsBlobStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing blob storage operations on IPFS.\n * See https://docs.ipfs.tech/reference/kubo/rpc/ for more information.\n */\nexport class IpfsBlobStorageConnector implements IBlobStorageConnector {\n\t/**\n\t * The namespace for the items.\n\t */\n\tpublic static readonly NAMESPACE: string = \"ipfs\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<IpfsBlobStorageConnector>();\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IIpfsBlobStorageConnectorConfig;\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 * Create a new instance of IpfsBlobStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IIpfsBlobStorageConnectorConstructorOptions) {\n\t\tGuards.object(IpfsBlobStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.object<IIpfsBlobStorageConnectorConfig>(\n\t\t\tIpfsBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tIpfsBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.apiUrl),\n\t\t\toptions.config.apiUrl\n\t\t);\n\n\t\tthis._config = options.config;\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._config.apiUrl = StringHelper.trimTrailingSlashes(this._config.apiUrl);\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 IpfsBlobStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.addSecurity(fetchOptions);\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/version`, fetchOptions);\n\t\t\tif (response.ok) {\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tapiUrl: this._config.apiUrl\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\t\t} catch {}\n\t\treturn [\n\t\t\t{\n\t\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\tmessage: \"healthCheckFailed\",\n\t\t\t\tdata: {\n\t\t\t\t\tapiUrl: this._config.apiUrl\n\t\t\t\t}\n\t\t\t}\n\t\t];\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(IpfsBlobStorageConnector.CLASS_NAME, nameof(blob), blob);\n\n\t\ttry {\n\t\t\tconst formBlob = new Blob([new Uint8Array(blob)], { type: MimeTypes.OctetStream });\n\t\t\tconst formData = new FormData();\n\t\t\tformData.append(\"file\", formBlob);\n\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\tbody: formData,\n\t\t\t\theaders: {\n\t\t\t\t\t[HeaderTypes.Accept]: MimeTypes.Json,\n\t\t\t\t\t[HeaderTypes.ContentDisposition]: \"form-data\"\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/add?pin=true`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst result = (await response.json()) as {\n\t\t\t\t\tName: string;\n\t\t\t\t\tHash: string;\n\t\t\t\t\tSize: string;\n\t\t\t\t};\n\n\t\t\t\tconst partitionSegment = await this.buildPartitionSegment();\n\t\t\t\tconst urnParts = Is.stringValue(partitionSegment)\n\t\t\t\t\t? [result.Hash, partitionSegment]\n\t\t\t\t\t: [result.Hash];\n\n\t\t\t\treturn `blob:${new Urn(IpfsBlobStorageConnector.NAMESPACE, urnParts).toString()}`;\n\t\t\t}\n\n\t\t\tconst error = await response.json();\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"fetchFail\", error);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.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(IpfsBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceMethod() !== IpfsBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: IpfsBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\tconst partitionSegment = await this.buildPartitionSegment();\n\t\tconst storedPartitionSegment = Is.stringValue(urnParsed.namespaceSpecific(2))\n\t\t\t? urnParsed.namespaceSpecific(2)\n\t\t\t: undefined;\n\n\t\tif (partitionSegment !== storedPartitionSegment) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst ipfsHash = urnParsed.namespaceSpecific(1).split(\":\")[0];\n\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst pinResponse = await fetch(\n\t\t\t\t`${this._config.apiUrl}/pin/ls?arg=${ipfsHash}`,\n\t\t\t\tfetchOptions\n\t\t\t);\n\n\t\t\tif (!pinResponse.ok) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/cat?arg=${ipfsHash}`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst result = await response.arrayBuffer();\n\t\t\t\treturn new Uint8Array(result);\n\t\t\t}\n\n\t\t\tconst error = await response.json();\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"fetchFail\", error);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"getBlobFailed\", undefined, err);\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the component and remove any resources it created.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\tmessage: \"storeTearingDown\"\n\t\t});\n\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/pin/ls`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst result = (await response.json()) as { Keys: { [cid: string]: unknown } };\n\n\t\t\t\tfor (const cid of Object.keys(result.Keys)) {\n\t\t\t\t\tconst unpinFetchOptions: RequestInit = {\n\t\t\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tthis.addSecurity(unpinFetchOptions);\n\t\t\t\t\tawait fetch(`${this._config.apiUrl}/pin/rm?arg=${cid}`, unpinFetchOptions);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"storeTornDown\"\n\t\t\t});\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: IpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove all blobs from the storage.\n\t * @returns A promise that resolves when all pinned blobs have been unpinned and garbage collected.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/pin/ls`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst result = (await response.json()) as { Keys: { [cid: string]: unknown } };\n\n\t\t\t\tfor (const cid of Object.keys(result.Keys)) {\n\t\t\t\t\tconst unpinFetchOptions: RequestInit = {\n\t\t\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tthis.addSecurity(unpinFetchOptions);\n\t\t\t\t\tawait fetch(`${this._config.apiUrl}/pin/rm?arg=${cid}`, unpinFetchOptions);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst gcFetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.addSecurity(gcFetchOptions);\n\t\t\tconst gcResponse = await fetch(`${this._config.apiUrl}/repo/gc`, gcFetchOptions);\n\t\t\tawait gcResponse.text();\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"emptyFailed\", undefined, 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(IpfsBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceMethod() !== IpfsBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: IpfsBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\tconst partitionSegment = await this.buildPartitionSegment();\n\t\tconst storedPartitionSegment = Is.stringValue(urnParsed.namespaceSpecific(2))\n\t\t\t? urnParsed.namespaceSpecific(2)\n\t\t\t: undefined;\n\n\t\tif (partitionSegment !== storedPartitionSegment) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst ipfsHash = urnParsed.namespaceSpecific(1).split(\":\")[0];\n\n\t\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\theaders: {\n\t\t\t\t\taccept: MimeTypes.Json\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.addSecurity(fetchOptions);\n\n\t\t\tconst response = await fetch(`${this._config.apiUrl}/pin/rm?arg=${ipfsHash}`, fetchOptions);\n\n\t\t\tif (response.ok) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tIpfsBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeBlobFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Add the security headers to the request if a bearer token is configured.\n\t * @param requestInit The request options to augment with security headers.\n\t * @internal\n\t */\n\tprivate addSecurity(requestInit: RequestInit): void {\n\t\tif (Is.stringValue(this._config.bearerToken)) {\n\t\t\trequestInit.headers = {\n\t\t\t\t...requestInit.headers,\n\t\t\t\t[HeaderTypes.Authorization]: HeaderHelper.createBearer(this._config.bearerToken)\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Build the partition segment from the current context.\n\t * @returns The hex-encoded Blake2b hash of the partition key, or undefined if no partition applies.\n\t * @internal\n\t */\n\tprivate async buildPartitionSegment(): Promise<string | undefined> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\treturn Converter.bytesToHex(Blake2b.sum256(Converter.utf8ToBytes(partitionKey)));\n\t\t}\n\t\treturn undefined;\n\t}\n}\n"]}
@@ -49,7 +49,7 @@ export declare class IpfsBlobStorageConnector implements IBlobStorageConnector {
49
49
  teardown(nodeLoggingComponentType?: string): Promise<boolean>;
50
50
  /**
51
51
  * Remove all blobs from the storage.
52
- * @returns Nothing.
52
+ * @returns A promise that resolves when all pinned blobs have been unpinned and garbage collected.
53
53
  */
54
54
  empty(): Promise<void>;
55
55
  /**
package/docs/changelog.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.3-next.15](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-ipfs-v0.0.3-next.14...blob-storage-connector-ipfs-v0.0.3-next.15) (2026-06-15)
4
+
5
+
6
+ ### Features
7
+
8
+ * async getStore ([#59](https://github.com/iotaledger/twin-blob-storage/issues/59)) ([2de1ae5](https://github.com/iotaledger/twin-blob-storage/commit/2de1ae5c274b84a2320f75ac4628b81e9459c540))
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.14 to 0.0.3-next.15
16
+
17
+ ## [0.0.3-next.14](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-ipfs-v0.0.3-next.13...blob-storage-connector-ipfs-v0.0.3-next.14) (2026-06-11)
18
+
19
+
20
+ ### Miscellaneous Chores
21
+
22
+ * **blob-storage-connector-ipfs:** Synchronize repo versions
23
+
24
+
25
+ ### Dependencies
26
+
27
+ * The following workspace dependencies were updated
28
+ * dependencies
29
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.13 to 0.0.3-next.14
30
+
3
31
  ## [0.0.3-next.13](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-ipfs-v0.0.3-next.12...blob-storage-connector-ipfs-v0.0.3-next.13) (2026-05-20)
4
32
 
5
33
 
@@ -169,7 +169,7 @@ Remove all blobs from the storage.
169
169
 
170
170
  `Promise`\<`void`\>
171
171
 
172
- Nothing.
172
+ A promise that resolves when all pinned blobs have been unpinned and garbage collected.
173
173
 
174
174
  #### Implementation of
175
175
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@twin.org/blob-storage-connector-ipfs",
3
- "version": "0.0.3-next.13",
3
+ "version": "0.0.3-next.15",
4
4
  "description": "Stores and retrieves blobs through IPFS for content-addressed and distributed workflows.",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "git+https://github.com/iotaledger/blob-storage.git",
7
+ "url": "git+https://github.com/iotaledger/twin-blob-storage.git",
8
8
  "directory": "packages/blob-storage-connector-ipfs"
9
9
  },
10
10
  "author": "martyn.janes@iota.org",
@@ -14,7 +14,7 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/blob-storage-models": "0.0.3-next.13",
17
+ "@twin.org/blob-storage-models": "0.0.3-next.15",
18
18
  "@twin.org/context": "next",
19
19
  "@twin.org/core": "next",
20
20
  "@twin.org/crypto": "next",
@@ -54,7 +54,7 @@
54
54
  "integration"
55
55
  ],
56
56
  "bugs": {
57
- "url": "git+https://github.com/iotaledger/blob-storage/issues"
57
+ "url": "git+https://github.com/iotaledger/twin-blob-storage/issues"
58
58
  },
59
59
  "homepage": "https://twindev.org"
60
60
  }