@twin.org/blob-storage-connector-ipfs 0.0.2-next.4 → 0.0.3-next.1

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.
@@ -0,0 +1,6 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export * from "./ipfsBlobStorageConnector.js";
4
+ export * from "./models/IIpfsBlobStorageConnectorConfig.js";
5
+ export * from "./models/IIpfsBlobStorageConnectorConstructorOptions.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,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,yDAAyD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./ipfsBlobStorageConnector.js\";\nexport * from \"./models/IIpfsBlobStorageConnectorConfig.js\";\nexport * from \"./models/IIpfsBlobStorageConnectorConstructorOptions.js\";\n"]}
@@ -1,11 +1,10 @@
1
- import { Guards, StringHelper, Urn, GeneralError, Is } from '@twin.org/core';
2
- import { MimeTypes, HeaderTypes, HeaderHelper } from '@twin.org/web';
3
-
1
+ import { GeneralError, Guards, Is, StringHelper, Urn } from "@twin.org/core";
2
+ import { HeaderHelper, HeaderTypes, MimeTypes } from "@twin.org/web";
4
3
  /**
5
4
  * Class for performing blob storage operations on IPFS.
6
5
  * See https://docs.ipfs.tech/reference/kubo/rpc/ for more information.
7
6
  */
8
- class IpfsBlobStorageConnector {
7
+ export class IpfsBlobStorageConnector {
9
8
  /**
10
9
  * The namespace for the items.
11
10
  */
@@ -13,30 +12,43 @@ class IpfsBlobStorageConnector {
13
12
  /**
14
13
  * Runtime name for the class.
15
14
  */
16
- CLASS_NAME = "IpfsBlobStorageConnector";
15
+ static CLASS_NAME = "IpfsBlobStorageConnector";
17
16
  /**
18
17
  * The configuration for the connector.
19
18
  * @internal
20
19
  */
21
20
  _config;
21
+ /**
22
+ * The keys to use from the context ids to create partitions.
23
+ * @internal
24
+ */
25
+ _partitionContextIds;
22
26
  /**
23
27
  * Create a new instance of IpfsBlobStorageConnector.
24
28
  * @param options The options for the connector.
25
29
  */
26
30
  constructor(options) {
27
- Guards.object(this.CLASS_NAME, "options", options);
28
- Guards.object(this.CLASS_NAME, "options.config", options.config);
29
- Guards.stringValue(this.CLASS_NAME, "options.config.apiUrl", options.config.apiUrl);
31
+ Guards.object(IpfsBlobStorageConnector.CLASS_NAME, "options", options);
32
+ Guards.object(IpfsBlobStorageConnector.CLASS_NAME, "options.config", options.config);
33
+ Guards.stringValue(IpfsBlobStorageConnector.CLASS_NAME, "options.config.apiUrl", options.config.apiUrl);
30
34
  this._config = options.config;
35
+ this._partitionContextIds = options.partitionContextIds;
31
36
  this._config.apiUrl = StringHelper.trimTrailingSlashes(this._config.apiUrl);
32
37
  }
38
+ /**
39
+ * Returns the class name of the component.
40
+ * @returns The class name of the component.
41
+ */
42
+ className() {
43
+ return IpfsBlobStorageConnector.CLASS_NAME;
44
+ }
33
45
  /**
34
46
  * Set the blob.
35
47
  * @param blob The data for the blob.
36
48
  * @returns The id of the stored blob in urn format.
37
49
  */
38
50
  async set(blob) {
39
- Guards.uint8Array(this.CLASS_NAME, "blob", blob);
51
+ Guards.uint8Array(IpfsBlobStorageConnector.CLASS_NAME, "blob", blob);
40
52
  try {
41
53
  const formBlob = new Blob([new Uint8Array(blob)], { type: MimeTypes.OctetStream });
42
54
  const formData = new FormData();
@@ -56,10 +68,10 @@ class IpfsBlobStorageConnector {
56
68
  return `blob:${new Urn(IpfsBlobStorageConnector.NAMESPACE, result.Hash).toString()}`;
57
69
  }
58
70
  const error = await response.json();
59
- throw new GeneralError(this.CLASS_NAME, "fetchFail", error);
71
+ throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "fetchFail", error);
60
72
  }
61
73
  catch (err) {
62
- throw new GeneralError(this.CLASS_NAME, "setBlobFailed", undefined, err);
74
+ throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "setBlobFailed", undefined, err);
63
75
  }
64
76
  }
65
77
  /**
@@ -68,10 +80,10 @@ class IpfsBlobStorageConnector {
68
80
  * @returns The data for the blob if it can be found or undefined.
69
81
  */
70
82
  async get(id) {
71
- Urn.guard(this.CLASS_NAME, "id", id);
83
+ Urn.guard(IpfsBlobStorageConnector.CLASS_NAME, "id", id);
72
84
  const urnParsed = Urn.fromValidString(id);
73
85
  if (urnParsed.namespaceMethod() !== IpfsBlobStorageConnector.NAMESPACE) {
74
- throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
86
+ throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
75
87
  namespace: IpfsBlobStorageConnector.NAMESPACE,
76
88
  id
77
89
  });
@@ -84,16 +96,25 @@ class IpfsBlobStorageConnector {
84
96
  }
85
97
  };
86
98
  this.addSecurity(fetchOptions);
99
+ const responseStat = await fetch(`${this._config.apiUrl}/block/stat?arg=${urnParsed.namespaceSpecific(1)}&local=true`, fetchOptions);
100
+ if (!responseStat.ok) {
101
+ const resp = await responseStat.json();
102
+ if (Is.object(resp) &&
103
+ Is.stringValue(resp.Message) &&
104
+ resp.Message.includes("not found")) {
105
+ return;
106
+ }
107
+ }
87
108
  const response = await fetch(`${this._config.apiUrl}/cat?arg=${urnParsed.namespaceSpecific(1)}`, fetchOptions);
88
109
  if (response.ok) {
89
110
  const result = await response.arrayBuffer();
90
111
  return new Uint8Array(result);
91
112
  }
92
113
  const error = await response.json();
93
- throw new GeneralError(this.CLASS_NAME, "fetchFail", error);
114
+ throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "fetchFail", error);
94
115
  }
95
116
  catch (err) {
96
- throw new GeneralError(this.CLASS_NAME, "getBlobFailed", undefined, err);
117
+ throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "getBlobFailed", undefined, err);
97
118
  }
98
119
  }
99
120
  /**
@@ -102,10 +123,10 @@ class IpfsBlobStorageConnector {
102
123
  * @returns True if the blob was found.
103
124
  */
104
125
  async remove(id) {
105
- Urn.guard(this.CLASS_NAME, "id", id);
126
+ Urn.guard(IpfsBlobStorageConnector.CLASS_NAME, "id", id);
106
127
  const urnParsed = Urn.fromValidString(id);
107
128
  if (urnParsed.namespaceMethod() !== IpfsBlobStorageConnector.NAMESPACE) {
108
- throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
129
+ throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
109
130
  namespace: IpfsBlobStorageConnector.NAMESPACE,
110
131
  id
111
132
  });
@@ -123,10 +144,10 @@ class IpfsBlobStorageConnector {
123
144
  return true;
124
145
  }
125
146
  const error = await response.json();
126
- throw new GeneralError(this.CLASS_NAME, "fetchFail", error);
147
+ throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "fetchFail", error);
127
148
  }
128
149
  catch (err) {
129
- throw new GeneralError(this.CLASS_NAME, "removeBlobFailed", undefined, err);
150
+ throw new GeneralError(IpfsBlobStorageConnector.CLASS_NAME, "removeBlobFailed", undefined, err);
130
151
  }
131
152
  }
132
153
  /**
@@ -143,5 +164,4 @@ class IpfsBlobStorageConnector {
143
164
  }
144
165
  }
145
166
  }
146
-
147
- export { IpfsBlobStorageConnector };
167
+ //# sourceMappingURL=ipfsBlobStorageConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipfsBlobStorageConnector.js","sourceRoot":"","sources":["../../src/ipfsBlobStorageConnector.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAIrE;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IACpC;;OAEG;IACI,MAAM,CAAU,SAAS,GAAW,MAAM,CAAC;IAElD;;OAEG;IACI,MAAM,CAAU,UAAU,8BAA8C;IAE/E;;;OAGG;IACc,OAAO,CAAkC;IAE1D;;;OAGG;IACc,oBAAoB,CAAY;IAEjD;;;OAGG;IACH,YAAY,OAAoD;QAC/D,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,UAAU,aAAmB,OAAO,CAAC,CAAC;QAC7E,MAAM,CAAC,MAAM,CACZ,wBAAwB,CAAC,UAAU,oBAEnC,OAAO,CAAC,MAAM,CACd,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,wBAAwB,CAAC,UAAU,2BAEnC,OAAO,CAAC,MAAM,CAAC,MAAM,CACrB,CAAC;QAEF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;QACxD,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,YAAY,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7E,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,wBAAwB,CAAC,UAAU,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,GAAG,CAAC,IAAgB;QAChC,MAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAE3E,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;YACnF,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;YAChC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAElC,MAAM,YAAY,GAAgB;gBACjC,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE;oBACR,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,IAAI;oBACpC,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,WAAW;iBAC7C;aACD,CAAC;YAEF,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YAE/B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,eAAe,EAAE,YAAY,CAAC,CAAC;YAElF,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAIpC,CAAC;gBAEF,OAAO,QAAQ,IAAI,GAAG,CAAC,wBAAwB,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;YACtF,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QACjF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9F,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,GAAG,CAAC,EAAU;QAC1B,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAE1C,IAAI,SAAS,CAAC,eAAe,EAAE,KAAK,wBAAwB,CAAC,SAAS,EAAE,CAAC;YACxE,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,UAAU,EAAE,mBAAmB,EAAE;gBAChF,SAAS,EAAE,wBAAwB,CAAC,SAAS;gBAC7C,EAAE;aACF,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,YAAY,GAAgB;gBACjC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACR,MAAM,EAAE,SAAS,CAAC,IAAI;iBACtB;aACD,CAAC;YAEF,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YAE/B,MAAM,YAAY,GAAG,MAAM,KAAK,CAC/B,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,mBAAmB,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa,EACpF,YAAY,CACZ,CAAC;YAEF,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;gBACtB,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC;gBACvC,IACC,EAAE,CAAC,MAAM,CAAsB,IAAI,CAAC;oBACpC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC;oBAC5B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EACjC,CAAC;oBACF,OAAO;gBACR,CAAC;YACF,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC3B,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,YAAY,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAClE,YAAY,CACZ,CAAC;YAEF,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAC5C,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;YAC/B,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QACjF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9F,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,MAAM,CAAC,EAAU;QAC7B,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAE1C,IAAI,SAAS,CAAC,eAAe,EAAE,KAAK,wBAAwB,CAAC,SAAS,EAAE,CAAC;YACxE,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,UAAU,EAAE,mBAAmB,EAAE;gBAChF,SAAS,EAAE,wBAAwB,CAAC,SAAS;gBAC7C,EAAE;aACF,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,YAAY,GAAgB;gBACjC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACR,MAAM,EAAE,SAAS,CAAC,IAAI;iBACtB;aACD,CAAC;YAEF,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YAE/B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC3B,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,eAAe,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,EACrE,YAAY,CACZ,CAAC;YAEF,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,IAAI,CAAC;YACb,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QACjF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,wBAAwB,CAAC,UAAU,EACnC,kBAAkB,EAClB,SAAS,EACT,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;OAIG;IACK,WAAW,CAAC,WAAwB;QAC3C,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9C,WAAW,CAAC,OAAO,GAAG;gBACrB,GAAG,WAAW,CAAC,OAAO;gBACtB,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;aAChF,CAAC;QACH,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IBlobStorageConnector } from \"@twin.org/blob-storage-models\";\nimport { GeneralError, Guards, Is, StringHelper, Urn } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { HeaderHelper, HeaderTypes, 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 * 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: \"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\treturn `blob:${new Urn(IpfsBlobStorageConnector.NAMESPACE, result.Hash).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\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: \"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=${urnParsed.namespaceSpecific(1)}&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(\n\t\t\t\t`${this._config.apiUrl}/cat?arg=${urnParsed.namespaceSpecific(1)}`,\n\t\t\t\tfetchOptions\n\t\t\t);\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 * 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\ttry {\n\t\t\tconst fetchOptions: RequestInit = {\n\t\t\t\tmethod: \"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(\n\t\t\t\t`${this._config.apiUrl}/pin/rm?arg=${urnParsed.namespaceSpecific(1)}`,\n\t\t\t\tfetchOptions\n\t\t\t);\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"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=IIpfsBlobStorageConnectorConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IIpfsBlobStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/IIpfsBlobStorageConnectorConfig.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 IPFS Blob Storage Connector.\n */\nexport interface IIpfsBlobStorageConnectorConfig {\n\t/**\n\t * The url for API calls.\n\t */\n\tapiUrl: string;\n\n\t/**\n\t * The bearer token for authentication to the API.\n\t */\n\tbearerToken?: string;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IIpfsBlobStorageConnectorConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IIpfsBlobStorageConnectorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IIpfsBlobStorageConnectorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IIpfsBlobStorageConnectorConfig } from \"./IIpfsBlobStorageConnectorConfig.js\";\n\n/**\n * Options for the IPFS Blob Storage Connector constructor.\n */\nexport interface IIpfsBlobStorageConnectorConstructorOptions {\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: IIpfsBlobStorageConnectorConfig;\n}\n"]}
@@ -1,3 +1,3 @@
1
- export * from "./ipfsBlobStorageConnector";
2
- export * from "./models/IIpfsBlobStorageConnectorConfig";
3
- export * from "./models/IIpfsBlobStorageConnectorConstructorOptions";
1
+ export * from "./ipfsBlobStorageConnector.js";
2
+ export * from "./models/IIpfsBlobStorageConnectorConfig.js";
3
+ export * from "./models/IIpfsBlobStorageConnectorConstructorOptions.js";
@@ -1,5 +1,5 @@
1
1
  import type { IBlobStorageConnector } from "@twin.org/blob-storage-models";
2
- import type { IIpfsBlobStorageConnectorConstructorOptions } from "./models/IIpfsBlobStorageConnectorConstructorOptions";
2
+ import type { IIpfsBlobStorageConnectorConstructorOptions } from "./models/IIpfsBlobStorageConnectorConstructorOptions.js";
3
3
  /**
4
4
  * Class for performing blob storage operations on IPFS.
5
5
  * See https://docs.ipfs.tech/reference/kubo/rpc/ for more information.
@@ -12,12 +12,17 @@ export declare class IpfsBlobStorageConnector implements IBlobStorageConnector {
12
12
  /**
13
13
  * Runtime name for the class.
14
14
  */
15
- readonly CLASS_NAME: string;
15
+ static readonly CLASS_NAME: string;
16
16
  /**
17
17
  * Create a new instance of IpfsBlobStorageConnector.
18
18
  * @param options The options for the connector.
19
19
  */
20
20
  constructor(options: IIpfsBlobStorageConnectorConstructorOptions);
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
  * Set the blob.
23
28
  * @param blob The data for the blob.
@@ -1,8 +1,12 @@
1
- import type { IIpfsBlobStorageConnectorConfig } from "./IIpfsBlobStorageConnectorConfig";
1
+ import type { IIpfsBlobStorageConnectorConfig } from "./IIpfsBlobStorageConnectorConfig.js";
2
2
  /**
3
3
  * Options for the IPFS Blob Storage Connector constructor.
4
4
  */
5
5
  export interface IIpfsBlobStorageConnectorConstructorOptions {
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,40 @@
1
1
  # @twin.org/blob-storage-connector-ipfs - Changelog
2
2
 
3
+ ## [0.0.3-next.1](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-ipfs-v0.0.3-next.0...blob-storage-connector-ipfs-v0.0.3-next.1) (2025-11-11)
4
+
5
+
6
+ ### Features
7
+
8
+ * add context id features ([#30](https://github.com/twinfoundation/blob-storage/issues/30)) ([fbf1c92](https://github.com/twinfoundation/blob-storage/commit/fbf1c9276424c841ef5ef3f4de8469ab3fba7e9c))
9
+ * add validate-locales ([f20fcec](https://github.com/twinfoundation/blob-storage/commit/f20fceced91e39a0c9edb770b2e43ce944c92f3c))
10
+ * eslint migration to flat config ([e4239dd](https://github.com/twinfoundation/blob-storage/commit/e4239dd1c721955cff7f0357255d2bba15319972))
11
+ * update dependencies ([56f0094](https://github.com/twinfoundation/blob-storage/commit/56f0094b68d8bd22864cd899ac1b61d95540f719))
12
+ * update framework core ([ff339fe](https://github.com/twinfoundation/blob-storage/commit/ff339fe7e3f09ddff429907834bdf43617e9c05e))
13
+ * use new createBearer method ([f87c550](https://github.com/twinfoundation/blob-storage/commit/f87c5502fe3b5fee81257d7500f5d4500ea5ed28))
14
+ * use new createBearer method ([a965801](https://github.com/twinfoundation/blob-storage/commit/a96580160315c363fc0f06a1615cc92d4339a5e4))
15
+ * use shared store mechanism ([#12](https://github.com/twinfoundation/blob-storage/issues/12)) ([cae8110](https://github.com/twinfoundation/blob-storage/commit/cae8110681847a1ac4fcac968b8196694e49c320))
16
+
17
+
18
+ ### Dependencies
19
+
20
+ * The following workspace dependencies were updated
21
+ * dependencies
22
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.0 to 0.0.3-next.1
23
+
24
+ ## [0.0.2-next.5](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-ipfs-v0.0.2-next.4...blob-storage-connector-ipfs-v0.0.2-next.5) (2025-10-09)
25
+
26
+
27
+ ### Features
28
+
29
+ * add validate-locales ([f20fcec](https://github.com/twinfoundation/blob-storage/commit/f20fceced91e39a0c9edb770b2e43ce944c92f3c))
30
+
31
+
32
+ ### Dependencies
33
+
34
+ * The following workspace dependencies were updated
35
+ * dependencies
36
+ * @twin.org/blob-storage-models bumped from 0.0.2-next.4 to 0.0.2-next.5
37
+
3
38
  ## [0.0.2-next.4](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-ipfs-v0.0.2-next.3...blob-storage-connector-ipfs-v0.0.2-next.4) (2025-10-02)
4
39
 
5
40
 
@@ -39,15 +39,29 @@ The namespace for the items.
39
39
 
40
40
  ### CLASS\_NAME
41
41
 
42
- > `readonly` **CLASS\_NAME**: `string`
42
+ > `readonly` `static` **CLASS\_NAME**: `string`
43
43
 
44
44
  Runtime name for the class.
45
45
 
46
+ ## Methods
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
+
46
60
  #### Implementation of
47
61
 
48
- `IBlobStorageConnector.CLASS_NAME`
62
+ `IBlobStorageConnector.className`
49
63
 
50
- ## Methods
64
+ ***
51
65
 
52
66
  ### set()
53
67
 
@@ -77,7 +91,7 @@ The id of the stored blob in urn format.
77
91
 
78
92
  ### get()
79
93
 
80
- > **get**(`id`): `Promise`\<`undefined` \| `Uint8Array`\<`ArrayBufferLike`\>\>
94
+ > **get**(`id`): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\> \| `undefined`\>
81
95
 
82
96
  Get the blob.
83
97
 
@@ -91,7 +105,7 @@ The id of the blob to get in urn format.
91
105
 
92
106
  #### Returns
93
107
 
94
- `Promise`\<`undefined` \| `Uint8Array`\<`ArrayBufferLike`\>\>
108
+ `Promise`\<`Uint8Array`\<`ArrayBufferLike`\> \| `undefined`\>
95
109
 
96
110
  The data for the blob if it can be found or undefined.
97
111
 
@@ -4,6 +4,14 @@ Options for the IPFS 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**: [`IIpfsBlobStorageConnectorConfig`](IIpfsBlobStorageConnectorConfig.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/blob-storage-connector-ipfs",
3
- "version": "0.0.2-next.4",
3
+ "version": "0.0.3-next.1",
4
4
  "description": "Blob Storage connector implementation using IPFS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,26 +14,24 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/blob-storage-models": "0.0.2-next.4",
17
+ "@twin.org/blob-storage-models": "0.0.3-next.1",
18
18
  "@twin.org/core": "next",
19
19
  "@twin.org/crypto": "next",
20
20
  "@twin.org/nameof": "next",
21
21
  "@twin.org/web": "next"
22
22
  },
23
- "main": "./dist/cjs/index.cjs",
24
- "module": "./dist/esm/index.mjs",
23
+ "main": "./dist/es/index.js",
25
24
  "types": "./dist/types/index.d.ts",
26
25
  "exports": {
27
26
  ".": {
28
27
  "types": "./dist/types/index.d.ts",
29
- "require": "./dist/cjs/index.cjs",
30
- "import": "./dist/esm/index.mjs"
28
+ "import": "./dist/es/index.js",
29
+ "default": "./dist/es/index.js"
31
30
  },
32
31
  "./locales/*.json": "./locales/*.json"
33
32
  },
34
33
  "files": [
35
- "dist/cjs",
36
- "dist/esm",
34
+ "dist/es",
37
35
  "dist/types",
38
36
  "locales",
39
37
  "docs"
@@ -52,5 +50,9 @@
52
50
  "connector",
53
51
  "adapter",
54
52
  "integration"
55
- ]
53
+ ],
54
+ "bugs": {
55
+ "url": "git+https://github.com/twinfoundation/blob-storage/issues"
56
+ },
57
+ "homepage": "https://twindev.org"
56
58
  }
@@ -1,149 +0,0 @@
1
- 'use strict';
2
-
3
- var core = require('@twin.org/core');
4
- var web = require('@twin.org/web');
5
-
6
- /**
7
- * Class for performing blob storage operations on IPFS.
8
- * See https://docs.ipfs.tech/reference/kubo/rpc/ for more information.
9
- */
10
- class IpfsBlobStorageConnector {
11
- /**
12
- * The namespace for the items.
13
- */
14
- static NAMESPACE = "ipfs";
15
- /**
16
- * Runtime name for the class.
17
- */
18
- CLASS_NAME = "IpfsBlobStorageConnector";
19
- /**
20
- * The configuration for the connector.
21
- * @internal
22
- */
23
- _config;
24
- /**
25
- * Create a new instance of IpfsBlobStorageConnector.
26
- * @param options The options for the connector.
27
- */
28
- constructor(options) {
29
- core.Guards.object(this.CLASS_NAME, "options", options);
30
- core.Guards.object(this.CLASS_NAME, "options.config", options.config);
31
- core.Guards.stringValue(this.CLASS_NAME, "options.config.apiUrl", options.config.apiUrl);
32
- this._config = options.config;
33
- this._config.apiUrl = core.StringHelper.trimTrailingSlashes(this._config.apiUrl);
34
- }
35
- /**
36
- * Set the blob.
37
- * @param blob The data for the blob.
38
- * @returns The id of the stored blob in urn format.
39
- */
40
- async set(blob) {
41
- core.Guards.uint8Array(this.CLASS_NAME, "blob", blob);
42
- try {
43
- const formBlob = new Blob([new Uint8Array(blob)], { type: web.MimeTypes.OctetStream });
44
- const formData = new FormData();
45
- formData.append("file", formBlob);
46
- const fetchOptions = {
47
- method: "POST",
48
- body: formData,
49
- headers: {
50
- [web.HeaderTypes.Accept]: web.MimeTypes.Json,
51
- [web.HeaderTypes.ContentDisposition]: "form-data"
52
- }
53
- };
54
- this.addSecurity(fetchOptions);
55
- const response = await fetch(`${this._config.apiUrl}/add?pin=true`, fetchOptions);
56
- if (response.ok) {
57
- const result = (await response.json());
58
- return `blob:${new core.Urn(IpfsBlobStorageConnector.NAMESPACE, result.Hash).toString()}`;
59
- }
60
- const error = await response.json();
61
- throw new core.GeneralError(this.CLASS_NAME, "fetchFail", error);
62
- }
63
- catch (err) {
64
- throw new core.GeneralError(this.CLASS_NAME, "setBlobFailed", undefined, err);
65
- }
66
- }
67
- /**
68
- * Get the blob.
69
- * @param id The id of the blob to get in urn format.
70
- * @returns The data for the blob if it can be found or undefined.
71
- */
72
- async get(id) {
73
- core.Urn.guard(this.CLASS_NAME, "id", id);
74
- const urnParsed = core.Urn.fromValidString(id);
75
- if (urnParsed.namespaceMethod() !== IpfsBlobStorageConnector.NAMESPACE) {
76
- throw new core.GeneralError(this.CLASS_NAME, "namespaceMismatch", {
77
- namespace: IpfsBlobStorageConnector.NAMESPACE,
78
- id
79
- });
80
- }
81
- try {
82
- const fetchOptions = {
83
- method: "POST",
84
- headers: {
85
- accept: web.MimeTypes.Json
86
- }
87
- };
88
- this.addSecurity(fetchOptions);
89
- const response = await fetch(`${this._config.apiUrl}/cat?arg=${urnParsed.namespaceSpecific(1)}`, fetchOptions);
90
- if (response.ok) {
91
- const result = await response.arrayBuffer();
92
- return new Uint8Array(result);
93
- }
94
- const error = await response.json();
95
- throw new core.GeneralError(this.CLASS_NAME, "fetchFail", error);
96
- }
97
- catch (err) {
98
- throw new core.GeneralError(this.CLASS_NAME, "getBlobFailed", undefined, err);
99
- }
100
- }
101
- /**
102
- * Remove the blob.
103
- * @param id The id of the blob to remove in urn format.
104
- * @returns True if the blob was found.
105
- */
106
- async remove(id) {
107
- core.Urn.guard(this.CLASS_NAME, "id", id);
108
- const urnParsed = core.Urn.fromValidString(id);
109
- if (urnParsed.namespaceMethod() !== IpfsBlobStorageConnector.NAMESPACE) {
110
- throw new core.GeneralError(this.CLASS_NAME, "namespaceMismatch", {
111
- namespace: IpfsBlobStorageConnector.NAMESPACE,
112
- id
113
- });
114
- }
115
- try {
116
- const fetchOptions = {
117
- method: "POST",
118
- headers: {
119
- accept: web.MimeTypes.Json
120
- }
121
- };
122
- this.addSecurity(fetchOptions);
123
- const response = await fetch(`${this._config.apiUrl}/pin/rm?arg=${urnParsed.namespaceSpecific(1)}`, fetchOptions);
124
- if (response.ok) {
125
- return true;
126
- }
127
- const error = await response.json();
128
- throw new core.GeneralError(this.CLASS_NAME, "fetchFail", error);
129
- }
130
- catch (err) {
131
- throw new core.GeneralError(this.CLASS_NAME, "removeBlobFailed", undefined, err);
132
- }
133
- }
134
- /**
135
- * Add the security to the request.
136
- * @param requestInit The request options.
137
- * @internal
138
- */
139
- addSecurity(requestInit) {
140
- if (core.Is.stringValue(this._config.bearerToken)) {
141
- requestInit.headers = {
142
- ...requestInit.headers,
143
- [web.HeaderTypes.Authorization]: web.HeaderHelper.createBearer(this._config.bearerToken)
144
- };
145
- }
146
- }
147
- }
148
-
149
- exports.IpfsBlobStorageConnector = IpfsBlobStorageConnector;