@twin.org/blob-storage-connector-file 0.0.3-next.9 → 0.9.0

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.
@@ -1,6 +1,6 @@
1
1
  // Copyright 2024 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
- import { access, mkdir, readFile, unlink, writeFile } from "node:fs/promises";
3
+ import { access, mkdir, readFile, readdir, rm, unlink, writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
6
6
  import { BaseError, ComponentFactory, Converter, GeneralError, Guards, HealthStatus, Is, Urn } from "@twin.org/core";
@@ -61,7 +61,10 @@ export class FileBlobStorageConnector {
61
61
  {
62
62
  source: FileBlobStorageConnector.CLASS_NAME,
63
63
  status: HealthStatus.Ok,
64
- description: "healthDescription"
64
+ description: "healthDescription",
65
+ data: {
66
+ directory: this._directory
67
+ }
65
68
  }
66
69
  ];
67
70
  }
@@ -70,7 +73,10 @@ export class FileBlobStorageConnector {
70
73
  source: FileBlobStorageConnector.CLASS_NAME,
71
74
  status: HealthStatus.Error,
72
75
  description: "healthDescription",
73
- message: "healthCheckFailed"
76
+ message: "healthCheckFailed",
77
+ data: {
78
+ directory: this._directory
79
+ }
74
80
  }
75
81
  ];
76
82
  }
@@ -159,7 +165,7 @@ export class FileBlobStorageConnector {
159
165
  }
160
166
  try {
161
167
  const fullPath = this.createFullPath(urnParsed.namespaceSpecific(1), partitionKey);
162
- return await readFile(fullPath);
168
+ return new Uint8Array(await readFile(fullPath));
163
169
  }
164
170
  catch (err) {
165
171
  if (BaseError.isErrorCode(err, "ENOENT")) {
@@ -196,6 +202,70 @@ export class FileBlobStorageConnector {
196
202
  throw new GeneralError(FileBlobStorageConnector.CLASS_NAME, "removeBlobFailed", { id }, err);
197
203
  }
198
204
  }
205
+ /**
206
+ * Teardown the component and remove any resources it created.
207
+ * @param nodeLoggingComponentType The node logging component type.
208
+ * @returns True if the teardown process was successful.
209
+ */
210
+ async teardown(nodeLoggingComponentType) {
211
+ const nodeLogging = ComponentFactory.getIfExists(nodeLoggingComponentType);
212
+ await nodeLogging?.log({
213
+ level: "info",
214
+ source: FileBlobStorageConnector.CLASS_NAME,
215
+ message: "directoryRemoving",
216
+ data: {
217
+ directory: this._directory
218
+ }
219
+ });
220
+ try {
221
+ await rm(this._directory, { recursive: true, force: true });
222
+ await nodeLogging?.log({
223
+ level: "info",
224
+ source: FileBlobStorageConnector.CLASS_NAME,
225
+ message: "directoryRemoved",
226
+ data: {
227
+ directory: this._directory
228
+ }
229
+ });
230
+ return true;
231
+ }
232
+ catch (err) {
233
+ await nodeLogging?.log({
234
+ level: "error",
235
+ source: FileBlobStorageConnector.CLASS_NAME,
236
+ message: "teardownFailed",
237
+ data: {
238
+ directory: this._directory
239
+ },
240
+ error: BaseError.fromError(err)
241
+ });
242
+ return false;
243
+ }
244
+ }
245
+ /**
246
+ * Remove all blobs from the storage.
247
+ * @returns A promise that resolves when all blobs in the current partition have been removed.
248
+ */
249
+ async empty() {
250
+ try {
251
+ const contextIds = await ContextIdStore.getContextIds();
252
+ const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
253
+ if (Is.stringValue(partitionKey)) {
254
+ const partitionDir = path.join(this._directory, partitionKey);
255
+ await rm(partitionDir, { recursive: true, force: true });
256
+ }
257
+ else {
258
+ const entries = await readdir(this._directory, { withFileTypes: true });
259
+ for (const entry of entries) {
260
+ const fullPath = path.join(this._directory, entry.name);
261
+ await rm(fullPath, { recursive: true, force: true });
262
+ }
263
+ }
264
+ }
265
+ catch (err) {
266
+ throw new GeneralError(FileBlobStorageConnector.CLASS_NAME, "emptyFailed", { directory: this._directory }, err);
267
+ }
268
+ }
199
269
  /**
200
270
  * Check if the dir exists.
201
271
  * @param dir The directory to check.
@@ -1 +1 @@
1
- {"version":3,"file":"fileBlobStorageConnector.js","sourceRoot":"","sources":["../../src/fileBlobStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { access, mkdir, readFile, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\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\tUrn,\n\ttype IHealth\n} from \"@twin.org/core\";\nimport { Sha256 } from \"@twin.org/crypto\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IFileBlobStorageConnectorConstructorOptions } from \"./models/IFileBlobStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing blob storage operations in file.\n */\nexport class FileBlobStorageConnector implements IBlobStorageConnector {\n\t/**\n\t * The namespace for the items.\n\t */\n\tpublic static readonly NAMESPACE: string = \"file\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<FileBlobStorageConnector>();\n\n\t/**\n\t * The directory to use for storage.\n\t * @internal\n\t */\n\tprivate readonly _directory: string;\n\n\t/**\n\t * The extension to use for storage.\n\t * @internal\n\t */\n\tprivate readonly _extension: string;\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 FileBlobStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IFileBlobStorageConnectorConstructorOptions) {\n\t\tGuards.object(FileBlobStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.object(FileBlobStorageConnector.CLASS_NAME, nameof(options.config), options.config);\n\t\tGuards.stringValue(\n\t\t\tFileBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.directory),\n\t\t\toptions.config.directory\n\t\t);\n\t\tthis._directory = path.resolve(options.config.directory);\n\t\tthis._extension = options.config.extension ?? \".blob\";\n\t\tthis._partitionContextIds = options.partitionContextIds;\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 FileBlobStorageConnector.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\tif (await this.dirExists(this._directory)) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\"\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t\treturn [\n\t\t\t{\n\t\t\t\tsource: FileBlobStorageConnector.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}\n\t\t];\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\tif (!(await this.dirExists(this._directory))) {\n\t\t\ttry {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tmessage: \"directoryCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdirectory: this._directory\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tawait mkdir(this._directory, { recursive: true });\n\t\t\t} catch (err) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tmessage: \"directoryCreateFailed\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdirectory: this._directory\n\t\t\t\t\t},\n\t\t\t\t\terror: BaseError.fromError(err)\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"directoryExists\",\n\t\t\t\tdata: {\n\t\t\t\t\tdirectory: this._directory\n\t\t\t\t}\n\t\t\t});\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(FileBlobStorageConnector.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\n\t\t\tconst fullPath = this.createFullPath(id, partitionKey);\n\n\t\t\tconst dir = path.dirname(fullPath);\n\t\t\tif (!(await this.dirExists(dir))) {\n\t\t\t\tawait mkdir(dir, { recursive: true });\n\t\t\t}\n\n\t\t\tawait writeFile(fullPath, blob);\n\n\t\t\treturn `blob:${new Urn(FileBlobStorageConnector.NAMESPACE, id).toString()}`;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.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(FileBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (urnParsed.namespaceMethod() !== FileBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: FileBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst fullPath = this.createFullPath(urnParsed.namespaceSpecific(1), partitionKey);\n\n\t\t\treturn await readFile(fullPath);\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ENOENT\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.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(FileBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (urnParsed.namespaceMethod() !== FileBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: FileBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst fullPath = this.createFullPath(urnParsed.namespaceSpecific(1), partitionKey);\n\n\t\t\tawait unlink(fullPath);\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ENOENT\")) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.CLASS_NAME, \"removeBlobFailed\", { id }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Check if the dir exists.\n\t * @param dir The directory to check.\n\t * @returns True if the dir exists.\n\t * @internal\n\t */\n\tprivate async dirExists(dir: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait access(dir);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Create the full path for the blob.\n\t * @param id The id of the blob.\n\t * @param partitionKey The partition key.\n\t * @returns The full path for the blob.\n\t * @internal\n\t */\n\tprivate createFullPath(id: string, partitionKey?: string): string {\n\t\tconst partitionPath = Is.stringValue(partitionKey) ? path.join(partitionKey, id) : id;\n\t\treturn path.join(this._directory, `${partitionPath}${this._extension}`);\n\t}\n}\n"]}
1
+ {"version":3,"file":"fileBlobStorageConnector.js","sourceRoot":"","sources":["../../src/fileBlobStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { access, mkdir, readFile, readdir, rm, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\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\tUrn,\n\ttype IHealth\n} from \"@twin.org/core\";\nimport { Sha256 } from \"@twin.org/crypto\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IFileBlobStorageConnectorConstructorOptions } from \"./models/IFileBlobStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing blob storage operations in file.\n */\nexport class FileBlobStorageConnector implements IBlobStorageConnector {\n\t/**\n\t * The namespace for the items.\n\t */\n\tpublic static readonly NAMESPACE: string = \"file\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<FileBlobStorageConnector>();\n\n\t/**\n\t * The directory to use for storage.\n\t * @internal\n\t */\n\tprivate readonly _directory: string;\n\n\t/**\n\t * The extension to use for storage.\n\t * @internal\n\t */\n\tprivate readonly _extension: string;\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 FileBlobStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IFileBlobStorageConnectorConstructorOptions) {\n\t\tGuards.object(FileBlobStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.object(FileBlobStorageConnector.CLASS_NAME, nameof(options.config), options.config);\n\t\tGuards.stringValue(\n\t\t\tFileBlobStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.directory),\n\t\t\toptions.config.directory\n\t\t);\n\t\tthis._directory = path.resolve(options.config.directory);\n\t\tthis._extension = options.config.extension ?? \".blob\";\n\t\tthis._partitionContextIds = options.partitionContextIds;\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 FileBlobStorageConnector.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\tif (await this.dirExists(this._directory)) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdirectory: this._directory\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t\treturn [\n\t\t\t{\n\t\t\t\tsource: FileBlobStorageConnector.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\tdirectory: this._directory\n\t\t\t\t}\n\t\t\t}\n\t\t];\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\tif (!(await this.dirExists(this._directory))) {\n\t\t\ttry {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tmessage: \"directoryCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdirectory: this._directory\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tawait mkdir(this._directory, { recursive: true });\n\t\t\t} catch (err) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\tmessage: \"directoryCreateFailed\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdirectory: this._directory\n\t\t\t\t\t},\n\t\t\t\t\terror: BaseError.fromError(err)\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"directoryExists\",\n\t\t\t\tdata: {\n\t\t\t\t\tdirectory: this._directory\n\t\t\t\t}\n\t\t\t});\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(FileBlobStorageConnector.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\n\t\t\tconst fullPath = this.createFullPath(id, partitionKey);\n\n\t\t\tconst dir = path.dirname(fullPath);\n\t\t\tif (!(await this.dirExists(dir))) {\n\t\t\t\tawait mkdir(dir, { recursive: true });\n\t\t\t}\n\n\t\t\tawait writeFile(fullPath, blob);\n\n\t\t\treturn `blob:${new Urn(FileBlobStorageConnector.NAMESPACE, id).toString()}`;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.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(FileBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (urnParsed.namespaceMethod() !== FileBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: FileBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst fullPath = this.createFullPath(urnParsed.namespaceSpecific(1), partitionKey);\n\n\t\t\treturn new Uint8Array(await readFile(fullPath));\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ENOENT\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.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(FileBlobStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (urnParsed.namespaceMethod() !== FileBlobStorageConnector.NAMESPACE) {\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: FileBlobStorageConnector.NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst fullPath = this.createFullPath(urnParsed.namespaceSpecific(1), partitionKey);\n\n\t\t\tawait unlink(fullPath);\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ENOENT\")) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthrow new GeneralError(FileBlobStorageConnector.CLASS_NAME, \"removeBlobFailed\", { id }, 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: FileBlobStorageConnector.CLASS_NAME,\n\t\t\tmessage: \"directoryRemoving\",\n\t\t\tdata: {\n\t\t\t\tdirectory: this._directory\n\t\t\t}\n\t\t});\n\n\t\ttry {\n\t\t\tawait rm(this._directory, { recursive: true, force: true });\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"directoryRemoved\",\n\t\t\t\tdata: {\n\t\t\t\t\tdirectory: this._directory\n\t\t\t\t}\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: FileBlobStorageConnector.CLASS_NAME,\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\tdata: {\n\t\t\t\t\tdirectory: this._directory\n\t\t\t\t},\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 blobs in the current partition have been removed.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\ttry {\n\t\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\t\tconst partitionKey = ContextIdHelper.combinedContextKey(\n\t\t\t\tcontextIds,\n\t\t\t\tthis._partitionContextIds\n\t\t\t);\n\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tconst partitionDir = path.join(this._directory, partitionKey);\n\t\t\t\tawait rm(partitionDir, { recursive: true, force: true });\n\t\t\t} else {\n\t\t\t\tconst entries = await readdir(this._directory, { withFileTypes: true });\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tconst fullPath = path.join(this._directory, entry.name);\n\t\t\t\t\tawait rm(fullPath, { recursive: true, force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tFileBlobStorageConnector.CLASS_NAME,\n\t\t\t\t\"emptyFailed\",\n\t\t\t\t{ directory: this._directory },\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Check if the dir exists.\n\t * @param dir The directory to check.\n\t * @returns True if the dir exists.\n\t * @internal\n\t */\n\tprivate async dirExists(dir: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait access(dir);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Create the full path for the blob.\n\t * @param id The id of the blob.\n\t * @param partitionKey The partition key.\n\t * @returns The full path for the blob.\n\t * @internal\n\t */\n\tprivate createFullPath(id: string, partitionKey?: string): string {\n\t\tconst partitionPath = Is.stringValue(partitionKey) ? path.join(partitionKey, id) : id;\n\t\treturn path.join(this._directory, `${partitionPath}${this._extension}`);\n\t}\n}\n"]}
@@ -52,4 +52,15 @@ export declare class FileBlobStorageConnector implements IBlobStorageConnector {
52
52
  * @returns True if the blob was found.
53
53
  */
54
54
  remove(id: string): Promise<boolean>;
55
+ /**
56
+ * Teardown the component and remove any resources it created.
57
+ * @param nodeLoggingComponentType The node logging component type.
58
+ * @returns True if the teardown process was successful.
59
+ */
60
+ teardown(nodeLoggingComponentType?: string): Promise<boolean>;
61
+ /**
62
+ * Remove all blobs from the storage.
63
+ * @returns A promise that resolves when all blobs in the current partition have been removed.
64
+ */
65
+ empty(): Promise<void>;
55
66
  }
package/docs/changelog.md CHANGED
@@ -1,5 +1,142 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.0](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.9.0...blob-storage-connector-file-v0.9.0) (2026-06-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * release to production ([eacfe75](https://github.com/iotaledger/twin-blob-storage/commit/eacfe754a0dcd9243d9e13d86422327d0a605164))
9
+ * release to production ([#70](https://github.com/iotaledger/twin-blob-storage/issues/70)) ([6a38fe5](https://github.com/iotaledger/twin-blob-storage/commit/6a38fe583076baf1fc53d1d891d294b75ebbefd1))
10
+
11
+ ## [0.9.0-next.1](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.9.0-next.0...blob-storage-connector-file-v0.9.0-next.1) (2026-06-23)
12
+
13
+
14
+ ### Features
15
+
16
+ * add context id features ([#30](https://github.com/iotaledger/twin-blob-storage/issues/30)) ([fbf1c92](https://github.com/iotaledger/twin-blob-storage/commit/fbf1c9276424c841ef5ef3f4de8469ab3fba7e9c))
17
+ * add empty and teardown methods ([#49](https://github.com/iotaledger/twin-blob-storage/issues/49)) ([cec6248](https://github.com/iotaledger/twin-blob-storage/commit/cec624809ffd2f2baa4b7b8cbf72a7247b8703ed))
18
+ * add validate-locales ([f20fcec](https://github.com/iotaledger/twin-blob-storage/commit/f20fceced91e39a0c9edb770b2e43ce944c92f3c))
19
+ * additional information in health ([1ef83be](https://github.com/iotaledger/twin-blob-storage/commit/1ef83bef81148489b7950d5131a2af5121910e99))
20
+ * async getStore ([#59](https://github.com/iotaledger/twin-blob-storage/issues/59)) ([2de1ae5](https://github.com/iotaledger/twin-blob-storage/commit/2de1ae5c274b84a2320f75ac4628b81e9459c540))
21
+ * eslint migration to flat config ([e4239dd](https://github.com/iotaledger/twin-blob-storage/commit/e4239dd1c721955cff7f0357255d2bba15319972))
22
+ * health checks ([#44](https://github.com/iotaledger/twin-blob-storage/issues/44)) ([4a4041c](https://github.com/iotaledger/twin-blob-storage/commit/4a4041c19b68c40ed1aba6d1cdb4318ac4208b7d))
23
+ * skip ci for tests ([02b8095](https://github.com/iotaledger/twin-blob-storage/commit/02b8095dfabf8d9b3c6248a054a7657bfab1a374))
24
+ * typescript 6 update ([4eed54f](https://github.com/iotaledger/twin-blob-storage/commit/4eed54f5ce2dc697c06597269c97ad4cad108be5))
25
+ * update dependencies ([ca3c571](https://github.com/iotaledger/twin-blob-storage/commit/ca3c571573c771b8d25594f729651c8214e28263))
26
+ * update dependencies ([56f0094](https://github.com/iotaledger/twin-blob-storage/commit/56f0094b68d8bd22864cd899ac1b61d95540f719))
27
+ * update framework core ([ff339fe](https://github.com/iotaledger/twin-blob-storage/commit/ff339fe7e3f09ddff429907834bdf43617e9c05e))
28
+ * use shared store mechanism ([#12](https://github.com/iotaledger/twin-blob-storage/issues/12)) ([cae8110](https://github.com/iotaledger/twin-blob-storage/commit/cae8110681847a1ac4fcac968b8196694e49c320))
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * register platform mock in file blob storage connector tests ([#55](https://github.com/iotaledger/twin-blob-storage/issues/55)) ([fb83b24](https://github.com/iotaledger/twin-blob-storage/commit/fb83b2467daa74b2d45e32775ace42a5c4262768))
34
+
35
+
36
+ ### Dependencies
37
+
38
+ * The following workspace dependencies were updated
39
+ * dependencies
40
+ * @twin.org/blob-storage-models bumped from 0.9.0-next.0 to 0.9.0-next.1
41
+
42
+ ## [0.0.3-next.16](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.0.3-next.15...blob-storage-connector-file-v0.0.3-next.16) (2026-06-18)
43
+
44
+
45
+ ### Miscellaneous Chores
46
+
47
+ * **blob-storage-connector-file:** Synchronize repo versions
48
+
49
+
50
+ ### Dependencies
51
+
52
+ * The following workspace dependencies were updated
53
+ * dependencies
54
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.15 to 0.0.3-next.16
55
+
56
+ ## [0.0.3-next.15](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.0.3-next.14...blob-storage-connector-file-v0.0.3-next.15) (2026-06-15)
57
+
58
+
59
+ ### Features
60
+
61
+ * async getStore ([#59](https://github.com/iotaledger/twin-blob-storage/issues/59)) ([2de1ae5](https://github.com/iotaledger/twin-blob-storage/commit/2de1ae5c274b84a2320f75ac4628b81e9459c540))
62
+
63
+
64
+ ### Dependencies
65
+
66
+ * The following workspace dependencies were updated
67
+ * dependencies
68
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.14 to 0.0.3-next.15
69
+
70
+ ## [0.0.3-next.14](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.0.3-next.13...blob-storage-connector-file-v0.0.3-next.14) (2026-06-11)
71
+
72
+
73
+ ### Bug Fixes
74
+
75
+ * register platform mock in file blob storage connector tests ([#55](https://github.com/iotaledger/twin-blob-storage/issues/55)) ([fb83b24](https://github.com/iotaledger/twin-blob-storage/commit/fb83b2467daa74b2d45e32775ace42a5c4262768))
76
+
77
+
78
+ ### Dependencies
79
+
80
+ * The following workspace dependencies were updated
81
+ * dependencies
82
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.13 to 0.0.3-next.14
83
+
84
+ ## [0.0.3-next.13](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.0.3-next.12...blob-storage-connector-file-v0.0.3-next.13) (2026-05-20)
85
+
86
+
87
+ ### Features
88
+
89
+ * update dependencies ([ca3c571](https://github.com/iotaledger/twin-blob-storage/commit/ca3c571573c771b8d25594f729651c8214e28263))
90
+
91
+
92
+ ### Dependencies
93
+
94
+ * The following workspace dependencies were updated
95
+ * dependencies
96
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.12 to 0.0.3-next.13
97
+
98
+ ## [0.0.3-next.12](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.0.3-next.11...blob-storage-connector-file-v0.0.3-next.12) (2026-05-11)
99
+
100
+
101
+ ### Features
102
+
103
+ * typescript 6 update ([4eed54f](https://github.com/iotaledger/twin-blob-storage/commit/4eed54f5ce2dc697c06597269c97ad4cad108be5))
104
+
105
+
106
+ ### Dependencies
107
+
108
+ * The following workspace dependencies were updated
109
+ * dependencies
110
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.11 to 0.0.3-next.12
111
+
112
+ ## [0.0.3-next.11](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.0.3-next.10...blob-storage-connector-file-v0.0.3-next.11) (2026-05-08)
113
+
114
+
115
+ ### Features
116
+
117
+ * add empty and teardown methods ([#49](https://github.com/iotaledger/twin-blob-storage/issues/49)) ([cec6248](https://github.com/iotaledger/twin-blob-storage/commit/cec624809ffd2f2baa4b7b8cbf72a7247b8703ed))
118
+
119
+
120
+ ### Dependencies
121
+
122
+ * The following workspace dependencies were updated
123
+ * dependencies
124
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.10 to 0.0.3-next.11
125
+
126
+ ## [0.0.3-next.10](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.0.3-next.9...blob-storage-connector-file-v0.0.3-next.10) (2026-05-07)
127
+
128
+
129
+ ### Features
130
+
131
+ * additional information in health ([1ef83be](https://github.com/iotaledger/twin-blob-storage/commit/1ef83bef81148489b7950d5131a2af5121910e99))
132
+
133
+
134
+ ### Dependencies
135
+
136
+ * The following workspace dependencies were updated
137
+ * dependencies
138
+ * @twin.org/blob-storage-models bumped from 0.0.3-next.9 to 0.0.3-next.10
139
+
3
140
  ## [0.0.3-next.9](https://github.com/iotaledger/twin-blob-storage/compare/blob-storage-connector-file-v0.0.3-next.8...blob-storage-connector-file-v0.0.3-next.9) (2026-05-07)
4
141
 
5
142
 
@@ -181,3 +181,47 @@ True if the blob was found.
181
181
  #### Implementation of
182
182
 
183
183
  `IBlobStorageConnector.remove`
184
+
185
+ ***
186
+
187
+ ### teardown() {#teardown}
188
+
189
+ > **teardown**(`nodeLoggingComponentType?`): `Promise`\<`boolean`\>
190
+
191
+ Teardown the component and remove any resources it created.
192
+
193
+ #### Parameters
194
+
195
+ ##### nodeLoggingComponentType?
196
+
197
+ `string`
198
+
199
+ The node logging component type.
200
+
201
+ #### Returns
202
+
203
+ `Promise`\<`boolean`\>
204
+
205
+ True if the teardown process was successful.
206
+
207
+ #### Implementation of
208
+
209
+ `IBlobStorageConnector.teardown`
210
+
211
+ ***
212
+
213
+ ### empty() {#empty}
214
+
215
+ > **empty**(): `Promise`\<`void`\>
216
+
217
+ Remove all blobs from the storage.
218
+
219
+ #### Returns
220
+
221
+ `Promise`\<`void`\>
222
+
223
+ A promise that resolves when all blobs in the current partition have been removed.
224
+
225
+ #### Implementation of
226
+
227
+ `IBlobStorageConnector.empty`
package/locales/en.json CHANGED
@@ -2,13 +2,15 @@
2
2
  "info": {
3
3
  "fileBlobStorageConnector": {
4
4
  "directoryCreating": "Creating directory \"{directory}\"",
5
- "directoryExists": "Skipping create directory \"{directory}\" as it already exists"
5
+ "directoryExists": "Skipping create directory \"{directory}\" as it already exists",
6
+ "directoryRemoving": "Removing directory \"{directory}\"",
7
+ "directoryRemoved": "Directory \"{directory}\" removed"
6
8
  }
7
9
  },
8
10
  "health": {
9
11
  "fileBlobStorageConnector": {
10
- "healthDescription": "File blob storage connector is healthy",
11
- "healthCheckFailed": "Failed to access the storage directory"
12
+ "healthDescription": "File blob storage connector is healthy, directory \"{directory}\"",
13
+ "healthCheckFailed": "Failed to access the storage directory \"{directory}\""
12
14
  }
13
15
  },
14
16
  "error": {
@@ -17,6 +19,8 @@
17
19
  "getBlobFailed": "Unable to get blob \"{id}\"",
18
20
  "setBlobFailed": "Unable to set blob",
19
21
  "removeBlobFailed": "Unable to remove blob",
22
+ "emptyFailed": "Failed to empty file blob storage directory \"{directory}\"",
23
+ "teardownFailed": "Failed to teardown file blob storage directory \"{directory}\"",
20
24
  "namespaceMismatch": "The namespace in the urn \"{id}\" does not match the namespace of the blob storage \"{namespace}\""
21
25
  }
22
26
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@twin.org/blob-storage-connector-file",
3
- "version": "0.0.3-next.9",
3
+ "version": "0.9.0",
4
4
  "description": "Persists blobs to local directories or mounted volumes through a file system connector.",
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-file"
9
9
  },
10
10
  "author": "martyn.janes@iota.org",
@@ -14,12 +14,12 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/blob-storage-models": "0.0.3-next.9",
18
- "@twin.org/context": "next",
19
- "@twin.org/core": "next",
20
- "@twin.org/crypto": "next",
21
- "@twin.org/logging-models": "next",
22
- "@twin.org/nameof": "next"
17
+ "@twin.org/blob-storage-models": "^0.9.0",
18
+ "@twin.org/context": "^0.9.0",
19
+ "@twin.org/core": "^0.9.0",
20
+ "@twin.org/crypto": "^0.9.0",
21
+ "@twin.org/logging-models": "^0.9.0",
22
+ "@twin.org/nameof": "^0.9.0"
23
23
  },
24
24
  "main": "./dist/es/index.js",
25
25
  "types": "./dist/types/index.d.ts",
@@ -53,7 +53,7 @@
53
53
  "integration"
54
54
  ],
55
55
  "bugs": {
56
- "url": "git+https://github.com/iotaledger/blob-storage/issues"
56
+ "url": "git+https://github.com/iotaledger/twin-blob-storage/issues"
57
57
  },
58
58
  "homepage": "https://twindev.org"
59
59
  }