@twin.org/modules 0.0.3-next.2 → 0.0.3-next.21

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.
@@ -70,7 +70,7 @@ export class ModuleHelper {
70
70
  }
71
71
  throw new GeneralError(ModuleHelper.CLASS_NAME, "notFunction", {
72
72
  module,
73
- entry: method
73
+ method
74
74
  });
75
75
  }
76
76
  const moduleEntry = await ModuleHelper.getModuleEntry(module, methodParts[0]);
@@ -79,7 +79,7 @@ export class ModuleHelper {
79
79
  }
80
80
  throw new GeneralError(ModuleHelper.CLASS_NAME, "notFunction", {
81
81
  module,
82
- entry: method
82
+ method
83
83
  });
84
84
  }
85
85
  /**
@@ -99,78 +99,106 @@ export class ModuleHelper {
99
99
  * @param module The module.
100
100
  * @param method The method to execute from the module.
101
101
  * @param args The arguments to pass to the method.
102
+ * @param contextIds The context IDs.
102
103
  * @returns The result of the method execution.
103
104
  * @throws GeneralError if executing the module entry failed.
104
105
  */
105
- static async execModuleMethodThread(module, method, args) {
106
+ static async execModuleMethodThread(module, method, args, contextIds) {
106
107
  return new Promise((resolve, reject) => {
107
- const worker = new Worker(`(async () => {
108
- try {
109
- const { workerData, parentPort } = await import('node:worker_threads');
108
+ const messageModule = ModuleHelper.execModuleMethodThreadMessage(module, (resultMethod, result, err) => {
109
+ if (err) {
110
+ reject(err);
111
+ }
112
+ else {
113
+ resolve(result);
114
+ }
115
+ });
116
+ messageModule.executeMethod(method, args, contextIds);
117
+ });
118
+ }
119
+ /**
120
+ * Load the module and provide a messaging interface.
121
+ * @param module The module.
122
+ * @param completed Callback called when the worker thread processes a completion.
123
+ * @param options Optional settings.
124
+ * @param options.threadName The name of the thread.
125
+ * @returns The messaging interface.
126
+ * @throws GeneralError if executing the module entry failed.
127
+ */
128
+ static execModuleMethodThreadMessage(module, completed, options) {
129
+ const worker = new Worker(`(async () => {
130
+ const { workerData, parentPort } = await import('node:worker_threads');
131
+ const { ContextIdStore } = await import('@twin.org/context');
132
+ const { BaseError } = await import('@twin.org/core');
133
+ const { module } = workerData;
110
134
 
111
- function rejectError(errorType, cause) {
112
- parentPort.postMessage({ errorType, cause });
113
- }
135
+ function rejectError(errorType, methodName, args, cause) {
136
+ parentPort.postMessage({ errorType, method: methodName, args, cause: BaseError.fromError(cause).toJsonObject(true) });
137
+ }
114
138
 
115
- async function executeMethod(method) {
116
- try {
139
+ async function executeMethod(method, methodName, args, contextIds) {
140
+ try {
141
+ await ContextIdStore.run(contextIds ?? {}, async () => {
117
142
  const result = await method(...(args ?? []));
118
143
 
119
- parentPort.postMessage({ result });
120
- } catch (err) {
121
- rejectError('resultError', err);
122
- }
144
+ parentPort.postMessage({ method: methodName, result });
145
+ });
146
+ } catch (err) {
147
+ rejectError('resultError', methodName, args, err);
123
148
  }
149
+ }
124
150
 
125
- const { module, method, args } = workerData;
151
+ const modules = {};
126
152
 
127
- const moduleInstance = await import(module);
128
- const methodParts = method.split('.');
129
- const moduleEntry = moduleInstance[methodParts[0]];
153
+ parentPort.on('message', async msg => {
154
+ const { method, args, contextIds } = msg;
130
155
 
131
- if (moduleEntry === undefined) {
132
- rejectError('entryNotFound');
133
- } else if (methodParts.length === 2) {
134
- const moduleMethod = moduleEntry[methodParts[1]];
135
- if (typeof moduleMethod === 'function') {
136
- await executeMethod(moduleMethod, args);
156
+ try {
157
+ const moduleInstance = modules[module] ?? (await import(module));
158
+ modules[module] = moduleInstance;
159
+
160
+ const methodParts = method.split('.');
161
+ const moduleEntry = moduleInstance[methodParts[0]];
162
+
163
+ if (moduleEntry === undefined) {
164
+ rejectError('entryNotFound', method, args);
165
+ } else if (methodParts.length === 2) {
166
+ const moduleMethod = moduleEntry[methodParts[1]];
167
+ if (typeof moduleMethod === 'function') {
168
+ await executeMethod(moduleMethod, method, args, contextIds);
169
+ } else {
170
+ rejectError('notFunction', method, args);
171
+ }
172
+ } else if (typeof moduleEntry === 'function') {
173
+ await executeMethod(moduleEntry, method, args, contextIds);
137
174
  } else {
138
- rejectError('notFunction');
175
+ rejectError('notFunction', method, args);
139
176
  }
140
- } else if (typeof moduleEntry === 'function') {
141
- await executeMethod(moduleEntry, args);
142
- } else {
143
- rejectError('notFunction');
177
+ } catch (errInner) {
178
+ rejectError('moduleNotFound', method, args, errInner);
144
179
  }
145
- } catch (err) {
146
- rejectError('moduleNotFound', err);
147
- }
148
- })();
149
- `, { eval: true, workerData: { module, method, args: args ?? [] } });
150
- worker.on("message", msg => {
151
- if (Is.stringValue(msg.errorType)) {
152
- reject(new GeneralError(ModuleHelper.CLASS_NAME, msg.errorType, { module, entry: method }, msg.cause));
153
- }
154
- else {
155
- resolve(msg.result);
156
- }
157
- });
158
- worker.on("error", err => {
159
- reject(new GeneralError(ModuleHelper.CLASS_NAME, "workerException", {
160
- module,
161
- entry: method
162
- }, err));
163
- });
164
- worker.on("exit", code => {
165
- if (code === 1) {
166
- reject(new GeneralError(ModuleHelper.CLASS_NAME, "workerFailed", {
167
- module,
168
- entry: method,
169
- exitCode: code
170
- }));
171
- }
172
- });
180
+ });
181
+ })();`, { eval: true, workerData: { module }, name: options?.threadName });
182
+ worker.on("message", msg => {
183
+ if (Is.stringValue(msg.errorType)) {
184
+ completed(msg.method, undefined, new GeneralError(ModuleHelper.CLASS_NAME, msg.errorType, { module, method: msg.method, args: msg.args }, msg.cause));
185
+ }
186
+ else {
187
+ completed(msg.method, msg.result);
188
+ }
189
+ });
190
+ worker.on("error", err => {
191
+ completed("error", undefined, new GeneralError(ModuleHelper.CLASS_NAME, "workerException", {
192
+ module
193
+ }, err));
194
+ });
195
+ worker.on("exit", code => {
196
+ completed("terminate", code);
173
197
  });
198
+ return {
199
+ executeMethod: (method, args, contextIds) => worker.postMessage({ method, args, contextIds }),
200
+ terminate: async () => worker.terminate()
201
+ };
174
202
  }
175
203
  /**
176
204
  * Check if a module is a local module.
@@ -1 +1 @@
1
- {"version":3,"file":"moduleHelper.js","sourceRoot":"","sources":["../../../src/helpers/moduleHelper.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG1E;;GAEG;AACH,MAAM,OAAO,YAAY;IACxB;;OAEG;IACI,MAAM,CAAU,UAAU,kBAAkC;IAEnE;;;OAGG;IACI,MAAM,CAAC,cAAc,CAC3B,cAA0F;QAE1F,WAAW,CAAC,GAAG,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,KAAK,CAAC,cAAc,CAAI,MAAc,EAAE,KAAa;QAClE,IAAI,cAAc,CAAC;QAEnB,IAAI,CAAC;YACJ,IAAI,UAAU,GAAG,IAAI,CAAC;YAEtB,MAAM,cAAc,GACnB,WAAW,CAAC,GAAG,CACd,gBAAgB,CAChB,CAAC;YAEH,IAAI,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACjC,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;gBAEpD,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC;gBACvC,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC;YACxC,CAAC;YAED,IAAI,UAAU,EAAE,CAAC;gBAChB,cAAc,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;YACvC,CAAC;QACF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,YAAY,CAAC,UAAU,EACvB,gBAAgB,EAChB;gBACC,MAAM;gBACN,KAAK;aACL,EACD,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CACxB,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC;QAE5C,IAAI,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,YAAY,CAAC,YAAY,CAAC,UAAU,EAAE,eAAe,EAAE;gBAChE,MAAM;gBACN,KAAK;aACL,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,WAAgB,CAAC;IACzB,CAAC;IAED;;;;;;OAMG;IACH,8DAA8D;IACvD,MAAM,CAAC,KAAK,CAAC,eAAe,CAClC,MAAc,EACd,MAAc;QAEd,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAEtC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,cAAc,CAElD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YAE3B,IAAI,EAAE,CAAC,QAAQ,CAAI,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjD,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,IAAI,YAAY,CAAC,YAAY,CAAC,UAAU,EAAE,aAAa,EAAE;gBAC9D,MAAM;gBACN,KAAK,EAAE,MAAM;aACb,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,cAAc,CAAI,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjF,IAAI,EAAE,CAAC,QAAQ,CAAI,WAAW,CAAC,EAAE,CAAC;YACjC,OAAO,WAAW,CAAC;QACpB,CAAC;QAED,MAAM,IAAI,YAAY,CAAC,YAAY,CAAC,UAAU,EAAE,aAAa,EAAE;YAC9D,MAAM;YACN,KAAK,EAAE,MAAM;SACb,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,KAAK,CAAC,gBAAgB,CACnC,MAAc,EACd,MAAc,EACd,IAAgB;QAEhB,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,eAAe,CACtD,MAAM,EACN,MAAM,CACN,CAAC;QAEF,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;IACtC,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,KAAK,CAAC,sBAAsB,CACzC,MAAc,EACd,MAAc,EACd,IAAgB;QAEhB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,MAAM,MAAM,GAAG,IAAI,MAAM,CACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA0CA,EACA,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,EAAE,EAAE,CAChE,CAAC;YAEF,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE;gBAC1B,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACnC,MAAM,CACL,IAAI,YAAY,CACf,YAAY,CAAC,UAAU,EACvB,GAAG,CAAC,SAAS,EACb,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EACzB,GAAG,CAAC,KAAK,CACT,CACD,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACP,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACrB,CAAC;YACF,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;gBACxB,MAAM,CACL,IAAI,YAAY,CACf,YAAY,CAAC,UAAU,EACvB,iBAAiB,EACjB;oBACC,MAAM;oBACN,KAAK,EAAE,MAAM;iBACb,EACD,GAAG,CACH,CACD,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE;gBACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBAChB,MAAM,CACL,IAAI,YAAY,CAAC,YAAY,CAAC,UAAU,EAAE,cAAc,EAAE;wBACzD,MAAM;wBACN,KAAK,EAAE,MAAM;wBACb,QAAQ,EAAE,IAAI;qBACd,CAAC,CACF,CAAC;gBACH,CAAC;YACF,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,aAAa,CAAC,IAAY;QACvC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACrD,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,gBAAgB,CAAC,IAAY;QAC1C,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Worker } from \"node:worker_threads\";\nimport { BaseError, GeneralError, Is, SharedStore } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Helper functions for modules.\n */\nexport class ModuleHelper {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<ModuleHelper>();\n\n\t/**\n\t * Override the import function for modules.\n\t * @param overrideImport The override import function.\n\t */\n\tpublic static overrideImport(\n\t\toverrideImport: (moduleName: string) => Promise<{ module?: unknown; useDefault: boolean }>\n\t): void {\n\t\tSharedStore.set(\"overrideImport\", overrideImport);\n\t}\n\n\t/**\n\t * Get the module entry.\n\t * @param module The module.\n\t * @param entry The entry to get from the module.\n\t * @returns The entry from the module.\n\t * @throws GeneralError if getting the module entry failed.\n\t */\n\tpublic static async getModuleEntry<T>(module: string, entry: string): Promise<T> {\n\t\tlet moduleInstance;\n\n\t\ttry {\n\t\t\tlet useDefault = true;\n\n\t\t\tconst overrideImport =\n\t\t\t\tSharedStore.get<(moduleName: string) => Promise<{ module?: unknown; useDefault: boolean }>>(\n\t\t\t\t\t\"overrideImport\"\n\t\t\t\t);\n\n\t\t\tif (Is.function(overrideImport)) {\n\t\t\t\tconst overrideResult = await overrideImport(module);\n\n\t\t\t\tmoduleInstance = overrideResult.module;\n\t\t\t\tuseDefault = overrideResult.useDefault;\n\t\t\t}\n\n\t\t\tif (useDefault) {\n\t\t\t\tmoduleInstance = await import(module);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tModuleHelper.CLASS_NAME,\n\t\t\t\t\"moduleNotFound\",\n\t\t\t\t{\n\t\t\t\t\tmodule,\n\t\t\t\t\tentry\n\t\t\t\t},\n\t\t\t\tBaseError.fromError(err)\n\t\t\t);\n\t\t}\n\n\t\tconst moduleEntry = moduleInstance?.[entry];\n\n\t\tif (Is.empty(moduleEntry)) {\n\t\t\tthrow new GeneralError(ModuleHelper.CLASS_NAME, \"entryNotFound\", {\n\t\t\t\tmodule,\n\t\t\t\tentry\n\t\t\t});\n\t\t}\n\n\t\treturn moduleEntry as T;\n\t}\n\n\t/**\n\t * Get the method from a module.\n\t * @param module The module.\n\t * @param method The method to execute from the module, use dot notation to get a static class method.\n\t * @returns The result of the method execution.\n\t * @throws GeneralError if executing the module entry failed.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic static async getModuleMethod<T extends (...args: any[]) => any = (...args: any[]) => any>(\n\t\tmodule: string,\n\t\tmethod: string\n\t): Promise<T> {\n\t\tconst methodParts = method.split(\".\");\n\n\t\tif (methodParts.length === 2) {\n\t\t\tconst moduleEntry = await ModuleHelper.getModuleEntry<{\n\t\t\t\t[id: string]: T;\n\t\t\t}>(module, methodParts[0]);\n\n\t\t\tif (Is.function<T>(moduleEntry[methodParts[1]])) {\n\t\t\t\treturn moduleEntry[methodParts[1]];\n\t\t\t}\n\t\t\tthrow new GeneralError(ModuleHelper.CLASS_NAME, \"notFunction\", {\n\t\t\t\tmodule,\n\t\t\t\tentry: method\n\t\t\t});\n\t\t}\n\n\t\tconst moduleEntry = await ModuleHelper.getModuleEntry<T>(module, methodParts[0]);\n\n\t\tif (Is.function<T>(moduleEntry)) {\n\t\t\treturn moduleEntry;\n\t\t}\n\n\t\tthrow new GeneralError(ModuleHelper.CLASS_NAME, \"notFunction\", {\n\t\t\tmodule,\n\t\t\tentry: method\n\t\t});\n\t}\n\n\t/**\n\t * Execute the method in the module.\n\t * @param module The module.\n\t * @param method The method to execute from the module.\n\t * @param args The arguments to pass to the method.\n\t * @returns The result of the method execution.\n\t * @throws GeneralError if executing the module entry failed.\n\t */\n\tpublic static async execModuleMethod<T>(\n\t\tmodule: string,\n\t\tmethod: string,\n\t\targs?: unknown[]\n\t): Promise<T> {\n\t\tconst moduleMethod = await ModuleHelper.getModuleMethod<(...args: unknown[]) => T>(\n\t\t\tmodule,\n\t\t\tmethod\n\t\t);\n\n\t\treturn moduleMethod(...(args ?? []));\n\t}\n\n\t/**\n\t * Execute the method in the module in a thread.\n\t * @param module The module.\n\t * @param method The method to execute from the module.\n\t * @param args The arguments to pass to the method.\n\t * @returns The result of the method execution.\n\t * @throws GeneralError if executing the module entry failed.\n\t */\n\tpublic static async execModuleMethodThread<T>(\n\t\tmodule: string,\n\t\tmethod: string,\n\t\targs?: unknown[]\n\t): Promise<T> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst worker = new Worker(\n\t\t\t\t`(async () => {\n\ttry {\n\t\tconst { workerData, parentPort } = await import('node:worker_threads');\n\n\t\tfunction rejectError(errorType, cause) {\n\t\t\tparentPort.postMessage({ errorType, cause });\n\t\t}\n\n\t\tasync function executeMethod(method) {\n\t\t\ttry {\n\t\t\t\tconst result = await method(...(args ?? []));\n\n\t\t\t\tparentPort.postMessage({ result });\n\t\t\t} catch (err) {\n\t\t\t\trejectError('resultError', err);\n\t\t\t}\n\t\t}\n\n\t\tconst { module, method, args } = workerData;\n\n\t\tconst moduleInstance = await import(module);\n\t\tconst methodParts = method.split('.');\n\t\tconst moduleEntry = moduleInstance[methodParts[0]];\n\n\t\tif (moduleEntry === undefined) {\n\t\t\trejectError('entryNotFound');\n\t\t} else if (methodParts.length === 2) {\n\t\t\tconst moduleMethod = moduleEntry[methodParts[1]];\n\t\t\tif (typeof moduleMethod === 'function') {\n\t\t\t\tawait executeMethod(moduleMethod, args);\n\t\t\t} else {\n\t\t\t\trejectError('notFunction');\n\t\t\t}\n\t\t} else if (typeof moduleEntry === 'function') {\n\t\t\tawait executeMethod(moduleEntry, args);\n\t\t} else {\n\t\t\trejectError('notFunction');\n\t\t}\n\t} catch (err) {\n\t\trejectError('moduleNotFound', err);\n\t}\n})();\n\t\t\t`,\n\t\t\t\t{ eval: true, workerData: { module, method, args: args ?? [] } }\n\t\t\t);\n\n\t\t\tworker.on(\"message\", msg => {\n\t\t\t\tif (Is.stringValue(msg.errorType)) {\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew GeneralError(\n\t\t\t\t\t\t\tModuleHelper.CLASS_NAME,\n\t\t\t\t\t\t\tmsg.errorType,\n\t\t\t\t\t\t\t{ module, entry: method },\n\t\t\t\t\t\t\tmsg.cause\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tresolve(msg.result);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tworker.on(\"error\", err => {\n\t\t\t\treject(\n\t\t\t\t\tnew GeneralError(\n\t\t\t\t\t\tModuleHelper.CLASS_NAME,\n\t\t\t\t\t\t\"workerException\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmodule,\n\t\t\t\t\t\t\tentry: method\n\t\t\t\t\t\t},\n\t\t\t\t\t\terr\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tworker.on(\"exit\", code => {\n\t\t\t\tif (code === 1) {\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew GeneralError(ModuleHelper.CLASS_NAME, \"workerFailed\", {\n\t\t\t\t\t\t\tmodule,\n\t\t\t\t\t\t\tentry: method,\n\t\t\t\t\t\t\texitCode: code\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});\n\t}\n\n\t/**\n\t * Check if a module is a local module.\n\t * @param name The name of the module.\n\t * @returns True if the module is local, false otherwise.\n\t */\n\tpublic static isLocalModule(name: string): boolean {\n\t\treturn name.startsWith(\".\") || name.startsWith(\"/\");\n\t}\n\n\t/**\n\t * Check if a module is a relative module.\n\t * @param name The name of the module.\n\t * @returns True if the module is relative, false otherwise.\n\t */\n\tpublic static isRelativeModule(name: string): boolean {\n\t\treturn name.startsWith(\".\");\n\t}\n}\n"]}
1
+ {"version":3,"file":"moduleHelper.js","sourceRoot":"","sources":["../../../src/helpers/moduleHelper.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Worker } from \"node:worker_threads\";\nimport type { IContextIds } from \"@twin.org/context\";\nimport { BaseError, GeneralError, Is, SharedStore } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IModuleWorker } from \"../models/IModuleWorker.js\";\n\n/**\n * Helper functions for modules.\n */\nexport class ModuleHelper {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<ModuleHelper>();\n\n\t/**\n\t * Override the import function for modules.\n\t * @param overrideImport The override import function.\n\t */\n\tpublic static overrideImport(\n\t\toverrideImport: (moduleName: string) => Promise<{ module?: unknown; useDefault: boolean }>\n\t): void {\n\t\tSharedStore.set(\"overrideImport\", overrideImport);\n\t}\n\n\t/**\n\t * Get the module entry.\n\t * @param module The module.\n\t * @param entry The entry to get from the module.\n\t * @returns The entry from the module.\n\t * @throws GeneralError if getting the module entry failed.\n\t */\n\tpublic static async getModuleEntry<T>(module: string, entry: string): Promise<T> {\n\t\tlet moduleInstance;\n\n\t\ttry {\n\t\t\tlet useDefault = true;\n\n\t\t\tconst overrideImport =\n\t\t\t\tSharedStore.get<(moduleName: string) => Promise<{ module?: unknown; useDefault: boolean }>>(\n\t\t\t\t\t\"overrideImport\"\n\t\t\t\t);\n\n\t\t\tif (Is.function(overrideImport)) {\n\t\t\t\tconst overrideResult = await overrideImport(module);\n\n\t\t\t\tmoduleInstance = overrideResult.module;\n\t\t\t\tuseDefault = overrideResult.useDefault;\n\t\t\t}\n\n\t\t\tif (useDefault) {\n\t\t\t\tmoduleInstance = await import(module);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tModuleHelper.CLASS_NAME,\n\t\t\t\t\"moduleNotFound\",\n\t\t\t\t{\n\t\t\t\t\tmodule,\n\t\t\t\t\tentry\n\t\t\t\t},\n\t\t\t\tBaseError.fromError(err)\n\t\t\t);\n\t\t}\n\n\t\tconst moduleEntry = moduleInstance?.[entry];\n\n\t\tif (Is.empty(moduleEntry)) {\n\t\t\tthrow new GeneralError(ModuleHelper.CLASS_NAME, \"entryNotFound\", {\n\t\t\t\tmodule,\n\t\t\t\tentry\n\t\t\t});\n\t\t}\n\n\t\treturn moduleEntry as T;\n\t}\n\n\t/**\n\t * Get the method from a module.\n\t * @param module The module.\n\t * @param method The method to execute from the module, use dot notation to get a static class method.\n\t * @returns The result of the method execution.\n\t * @throws GeneralError if executing the module entry failed.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic static async getModuleMethod<T extends (...args: any[]) => any = (...args: any[]) => any>(\n\t\tmodule: string,\n\t\tmethod: string\n\t): Promise<T> {\n\t\tconst methodParts = method.split(\".\");\n\n\t\tif (methodParts.length === 2) {\n\t\t\tconst moduleEntry = await ModuleHelper.getModuleEntry<{\n\t\t\t\t[id: string]: T;\n\t\t\t}>(module, methodParts[0]);\n\n\t\t\tif (Is.function<T>(moduleEntry[methodParts[1]])) {\n\t\t\t\treturn moduleEntry[methodParts[1]];\n\t\t\t}\n\t\t\tthrow new GeneralError(ModuleHelper.CLASS_NAME, \"notFunction\", {\n\t\t\t\tmodule,\n\t\t\t\tmethod\n\t\t\t});\n\t\t}\n\n\t\tconst moduleEntry = await ModuleHelper.getModuleEntry<T>(module, methodParts[0]);\n\n\t\tif (Is.function<T>(moduleEntry)) {\n\t\t\treturn moduleEntry;\n\t\t}\n\n\t\tthrow new GeneralError(ModuleHelper.CLASS_NAME, \"notFunction\", {\n\t\t\tmodule,\n\t\t\tmethod\n\t\t});\n\t}\n\n\t/**\n\t * Execute the method in the module.\n\t * @param module The module.\n\t * @param method The method to execute from the module.\n\t * @param args The arguments to pass to the method.\n\t * @returns The result of the method execution.\n\t * @throws GeneralError if executing the module entry failed.\n\t */\n\tpublic static async execModuleMethod<T>(\n\t\tmodule: string,\n\t\tmethod: string,\n\t\targs?: unknown[]\n\t): Promise<T> {\n\t\tconst moduleMethod = await ModuleHelper.getModuleMethod<(...args: unknown[]) => T>(\n\t\t\tmodule,\n\t\t\tmethod\n\t\t);\n\n\t\treturn moduleMethod(...(args ?? []));\n\t}\n\n\t/**\n\t * Execute the method in the module in a thread.\n\t * @param module The module.\n\t * @param method The method to execute from the module.\n\t * @param args The arguments to pass to the method.\n\t * @param contextIds The context IDs.\n\t * @returns The result of the method execution.\n\t * @throws GeneralError if executing the module entry failed.\n\t */\n\tpublic static async execModuleMethodThread<T>(\n\t\tmodule: string,\n\t\tmethod: string,\n\t\targs?: unknown[],\n\t\tcontextIds?: IContextIds\n\t): Promise<T> {\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst messageModule = ModuleHelper.execModuleMethodThreadMessage(\n\t\t\t\tmodule,\n\t\t\t\t(resultMethod, result, err) => {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresolve(result as T);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tmessageModule.executeMethod(method, args, contextIds);\n\t\t});\n\t}\n\n\t/**\n\t * Load the module and provide a messaging interface.\n\t * @param module The module.\n\t * @param completed Callback called when the worker thread processes a completion.\n\t * @param options Optional settings.\n\t * @param options.threadName The name of the thread.\n\t * @returns The messaging interface.\n\t * @throws GeneralError if executing the module entry failed.\n\t */\n\tpublic static execModuleMethodThreadMessage(\n\t\tmodule: string,\n\t\tcompleted: (operation: string, result?: unknown, err?: Error) => void,\n\t\toptions?: {\n\t\t\tthreadName?: string;\n\t\t}\n\t): IModuleWorker {\n\t\tconst worker = new Worker(\n\t\t\t`(async () => {\n\tconst { workerData, parentPort } = await import('node:worker_threads');\n\tconst { ContextIdStore } = await import('@twin.org/context');\n\tconst { BaseError } = await import('@twin.org/core');\n\tconst { module } = workerData;\n\n\tfunction rejectError(errorType, methodName, args, cause) {\n\t\tparentPort.postMessage({ errorType, method: methodName, args, cause: BaseError.fromError(cause).toJsonObject(true) });\n\t}\n\n\tasync function executeMethod(method, methodName, args, contextIds) {\n\t\ttry {\n\t\t\tawait ContextIdStore.run(contextIds ?? {}, async () => {\n\t\t\t\tconst result = await method(...(args ?? []));\n\n\t\t\t\tparentPort.postMessage({ method: methodName, result });\n\t\t\t});\n\t\t} catch (err) {\n\t\t\trejectError('resultError', methodName, args, err);\n\t\t}\n\t}\n\n\tconst modules = {};\n\n\tparentPort.on('message', async msg => {\n\t\tconst { method, args, contextIds } = msg;\n\n\t\ttry {\n\t\t\tconst moduleInstance = modules[module] ?? (await import(module));\n\t\t\tmodules[module] = moduleInstance;\n\n\t\t\tconst methodParts = method.split('.');\n\t\t\tconst moduleEntry = moduleInstance[methodParts[0]];\n\n\t\t\tif (moduleEntry === undefined) {\n\t\t\t\trejectError('entryNotFound', method, args);\n\t\t\t} else if (methodParts.length === 2) {\n\t\t\t\tconst moduleMethod = moduleEntry[methodParts[1]];\n\t\t\t\tif (typeof moduleMethod === 'function') {\n\t\t\t\t\tawait executeMethod(moduleMethod, method, args, contextIds);\n\t\t\t\t} else {\n\t\t\t\t\trejectError('notFunction', method, args);\n\t\t\t\t}\n\t\t\t} else if (typeof moduleEntry === 'function') {\n\t\t\t\tawait executeMethod(moduleEntry, method, args, contextIds);\n\t\t\t} else {\n\t\t\t\trejectError('notFunction', method, args);\n\t\t\t}\n\t\t} catch (errInner) {\n\t\t\t\trejectError('moduleNotFound', method, args, errInner);\n\t\t}\n\t});\n})();`,\n\t\t\t{ eval: true, workerData: { module }, name: options?.threadName }\n\t\t);\n\n\t\tworker.on(\"message\", msg => {\n\t\t\tif (Is.stringValue(msg.errorType)) {\n\t\t\t\tcompleted(\n\t\t\t\t\tmsg.method,\n\t\t\t\t\tundefined,\n\t\t\t\t\tnew GeneralError(\n\t\t\t\t\t\tModuleHelper.CLASS_NAME,\n\t\t\t\t\t\tmsg.errorType,\n\t\t\t\t\t\t{ module, method: msg.method, args: msg.args },\n\t\t\t\t\t\tmsg.cause\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcompleted(msg.method, msg.result);\n\t\t\t}\n\t\t});\n\n\t\tworker.on(\"error\", err => {\n\t\t\tcompleted(\n\t\t\t\t\"error\",\n\t\t\t\tundefined,\n\t\t\t\tnew GeneralError(\n\t\t\t\t\tModuleHelper.CLASS_NAME,\n\t\t\t\t\t\"workerException\",\n\t\t\t\t\t{\n\t\t\t\t\t\tmodule\n\t\t\t\t\t},\n\t\t\t\t\terr\n\t\t\t\t)\n\t\t\t);\n\t\t});\n\n\t\tworker.on(\"exit\", code => {\n\t\t\tcompleted(\"terminate\", code);\n\t\t});\n\n\t\treturn {\n\t\t\texecuteMethod: (method: string, args?: unknown, contextIds?: IContextIds) =>\n\t\t\t\tworker.postMessage({ method, args, contextIds }),\n\t\t\tterminate: async () => worker.terminate()\n\t\t};\n\t}\n\n\t/**\n\t * Check if a module is a local module.\n\t * @param name The name of the module.\n\t * @returns True if the module is local, false otherwise.\n\t */\n\tpublic static isLocalModule(name: string): boolean {\n\t\treturn name.startsWith(\".\") || name.startsWith(\"/\");\n\t}\n\n\t/**\n\t * Check if a module is a relative module.\n\t * @param name The name of the module.\n\t * @returns True if the module is relative, false otherwise.\n\t */\n\tpublic static isRelativeModule(name: string): boolean {\n\t\treturn name.startsWith(\".\");\n\t}\n}\n"]}
package/dist/es/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // Copyright 2024 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  export * from "./helpers/moduleHelper.js";
4
+ export * from "./models/IModuleWorker.js";
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,2BAA2B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./helpers/moduleHelper.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./helpers/moduleHelper.js\";\nexport * from \"./models/IModuleWorker.js\";\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IModuleWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IModuleWorker.js","sourceRoot":"","sources":["../../../src/models/IModuleWorker.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IContextIds } from \"@twin.org/context\";\n\n/**\n * Worker definition for modules.\n */\nexport interface IModuleWorker {\n\t/**\n\t * Execute a method in the module.\n\t * @param method The method to execute.\n\t * @param args The arguments for the method.\n\t * @param contextIds The context IDs.\n\t * @returns The result of the method.\n\t */\n\texecuteMethod(method: string, args?: unknown, contextIds?: IContextIds): void;\n\n\t/**\n\t * Terminate the worker.\n\t * @returns A promise that resolves when the worker is terminated including the exit code.\n\t */\n\tterminate(): Promise<number>;\n}\n"]}
@@ -1,3 +1,5 @@
1
+ import type { IContextIds } from "@twin.org/context";
2
+ import type { IModuleWorker } from "../models/IModuleWorker.js";
1
3
  /**
2
4
  * Helper functions for modules.
3
5
  */
@@ -44,10 +46,23 @@ export declare class ModuleHelper {
44
46
  * @param module The module.
45
47
  * @param method The method to execute from the module.
46
48
  * @param args The arguments to pass to the method.
49
+ * @param contextIds The context IDs.
47
50
  * @returns The result of the method execution.
48
51
  * @throws GeneralError if executing the module entry failed.
49
52
  */
50
- static execModuleMethodThread<T>(module: string, method: string, args?: unknown[]): Promise<T>;
53
+ static execModuleMethodThread<T>(module: string, method: string, args?: unknown[], contextIds?: IContextIds): Promise<T>;
54
+ /**
55
+ * Load the module and provide a messaging interface.
56
+ * @param module The module.
57
+ * @param completed Callback called when the worker thread processes a completion.
58
+ * @param options Optional settings.
59
+ * @param options.threadName The name of the thread.
60
+ * @returns The messaging interface.
61
+ * @throws GeneralError if executing the module entry failed.
62
+ */
63
+ static execModuleMethodThreadMessage(module: string, completed: (operation: string, result?: unknown, err?: Error) => void, options?: {
64
+ threadName?: string;
65
+ }): IModuleWorker;
51
66
  /**
52
67
  * Check if a module is a local module.
53
68
  * @param name The name of the module.
@@ -1 +1,2 @@
1
1
  export * from "./helpers/moduleHelper.js";
2
+ export * from "./models/IModuleWorker.js";
@@ -0,0 +1,19 @@
1
+ import type { IContextIds } from "@twin.org/context";
2
+ /**
3
+ * Worker definition for modules.
4
+ */
5
+ export interface IModuleWorker {
6
+ /**
7
+ * Execute a method in the module.
8
+ * @param method The method to execute.
9
+ * @param args The arguments for the method.
10
+ * @param contextIds The context IDs.
11
+ * @returns The result of the method.
12
+ */
13
+ executeMethod(method: string, args?: unknown, contextIds?: IContextIds): void;
14
+ /**
15
+ * Terminate the worker.
16
+ * @returns A promise that resolves when the worker is terminated including the exit code.
17
+ */
18
+ terminate(): Promise<number>;
19
+ }
package/docs/changelog.md CHANGED
@@ -1,5 +1,407 @@
1
1
  # @twin.org/modules - Changelog
2
2
 
3
+ ## [0.0.3-next.21](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.20...modules-v0.0.3-next.21) (2026-02-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * add context id features ([#206](https://github.com/twinfoundation/framework/issues/206)) ([ef0d4ee](https://github.com/twinfoundation/framework/commit/ef0d4ee11a4f5fc6cc6f52a4958ce905c04ee13b))
9
+ * add guards arrayEndsWith and arrayStartsWith ([95d875e](https://github.com/twinfoundation/framework/commit/95d875ec8ccb4713c145fdde941d4cfedcec2ed3))
10
+ * eslint migration to flat config ([74427d7](https://github.com/twinfoundation/framework/commit/74427d78d342167f7850e49ab87269326355befe))
11
+ * improve async pattern and error handling ([aaa1f68](https://github.com/twinfoundation/framework/commit/aaa1f6879d60adf04b78b0c1bbbec50f2873f020))
12
+ * improve Is.function and ModuleHelper.getModuleMethod signatures ([ecf968b](https://github.com/twinfoundation/framework/commit/ecf968b02934b3676be4bf7cd2d1e7f8e7af6ce2))
13
+ * locales validation ([#197](https://github.com/twinfoundation/framework/issues/197)) ([55fdadb](https://github.com/twinfoundation/framework/commit/55fdadb13595ce0047f787bd1d4135d429a99f12))
14
+ * module helper can now handle long running threads with messaging ([4ecbb9a](https://github.com/twinfoundation/framework/commit/4ecbb9a526927d462d4fb3f95ba2a44889202753))
15
+ * nodeIdentity optional in IComponent methods ([c78dc17](https://github.com/twinfoundation/framework/commit/c78dc17f4357d3e1ae40e415f468d3eae13e81f4))
16
+ * provide module helper override ([e998a64](https://github.com/twinfoundation/framework/commit/e998a64842cfd18693a14444be33b084fef2bb90))
17
+ * relocate core packages from tools ([bcab8f3](https://github.com/twinfoundation/framework/commit/bcab8f3160442ea4fcaf442947462504f3d6a17d))
18
+ * retain detail in Errors from background threads ([52bdeef](https://github.com/twinfoundation/framework/commit/52bdeef7a75fd462ed118073b9dc7612304e038d))
19
+ * update dependencies ([f3bd015](https://github.com/twinfoundation/framework/commit/f3bd015efd169196b7e0335f5cab876ba6ca1d75))
20
+ * use cause instead of inner for errors ([1f4acc4](https://github.com/twinfoundation/framework/commit/1f4acc4d7a6b71a134d9547da9bf40de1e1e49da))
21
+ * use new shared store mechanism ([#131](https://github.com/twinfoundation/framework/issues/131)) ([934385b](https://github.com/twinfoundation/framework/commit/934385b2fbaf9f5c00a505ebf9d093bd5a425f55))
22
+
23
+
24
+ ### Dependencies
25
+
26
+ * The following workspace dependencies were updated
27
+ * dependencies
28
+ * @twin.org/core bumped from 0.0.3-next.20 to 0.0.3-next.21
29
+ * @twin.org/context bumped from 0.0.3-next.20 to 0.0.3-next.21
30
+ * @twin.org/nameof bumped from 0.0.3-next.20 to 0.0.3-next.21
31
+ * devDependencies
32
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.20 to 0.0.3-next.21
33
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.20 to 0.0.3-next.21
34
+ * @twin.org/validate-locales bumped from 0.0.3-next.20 to 0.0.3-next.21
35
+
36
+ ## [0.0.3-next.20](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.19...modules-v0.0.3-next.20) (2026-02-26)
37
+
38
+
39
+ ### Miscellaneous Chores
40
+
41
+ * **modules:** Synchronize repo versions
42
+
43
+
44
+ ### Dependencies
45
+
46
+ * The following workspace dependencies were updated
47
+ * dependencies
48
+ * @twin.org/core bumped from 0.0.3-next.19 to 0.0.3-next.20
49
+ * @twin.org/context bumped from 0.0.3-next.19 to 0.0.3-next.20
50
+ * @twin.org/nameof bumped from 0.0.3-next.19 to 0.0.3-next.20
51
+ * devDependencies
52
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.19 to 0.0.3-next.20
53
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.19 to 0.0.3-next.20
54
+ * @twin.org/validate-locales bumped from 0.0.3-next.19 to 0.0.3-next.20
55
+
56
+ ## [0.0.3-next.19](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.18...modules-v0.0.3-next.19) (2026-02-26)
57
+
58
+
59
+ ### Miscellaneous Chores
60
+
61
+ * **modules:** Synchronize repo versions
62
+
63
+
64
+ ### Dependencies
65
+
66
+ * The following workspace dependencies were updated
67
+ * dependencies
68
+ * @twin.org/core bumped from 0.0.3-next.18 to 0.0.3-next.19
69
+ * @twin.org/context bumped from 0.0.3-next.18 to 0.0.3-next.19
70
+ * @twin.org/nameof bumped from 0.0.3-next.18 to 0.0.3-next.19
71
+ * devDependencies
72
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.18 to 0.0.3-next.19
73
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.18 to 0.0.3-next.19
74
+ * @twin.org/validate-locales bumped from 0.0.3-next.18 to 0.0.3-next.19
75
+
76
+ ## [0.0.3-next.18](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.17...modules-v0.0.3-next.18) (2026-02-23)
77
+
78
+
79
+ ### Miscellaneous Chores
80
+
81
+ * **modules:** Synchronize repo versions
82
+
83
+
84
+ ### Dependencies
85
+
86
+ * The following workspace dependencies were updated
87
+ * dependencies
88
+ * @twin.org/core bumped from 0.0.3-next.17 to 0.0.3-next.18
89
+ * @twin.org/context bumped from 0.0.3-next.17 to 0.0.3-next.18
90
+ * @twin.org/nameof bumped from 0.0.3-next.17 to 0.0.3-next.18
91
+ * devDependencies
92
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.17 to 0.0.3-next.18
93
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.17 to 0.0.3-next.18
94
+ * @twin.org/validate-locales bumped from 0.0.3-next.17 to 0.0.3-next.18
95
+
96
+ ## [0.0.3-next.17](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.16...modules-v0.0.3-next.17) (2026-02-09)
97
+
98
+
99
+ ### Miscellaneous Chores
100
+
101
+ * **modules:** Synchronize repo versions
102
+
103
+
104
+ ### Dependencies
105
+
106
+ * The following workspace dependencies were updated
107
+ * dependencies
108
+ * @twin.org/core bumped from 0.0.3-next.16 to 0.0.3-next.17
109
+ * @twin.org/context bumped from 0.0.3-next.16 to 0.0.3-next.17
110
+ * @twin.org/nameof bumped from 0.0.3-next.16 to 0.0.3-next.17
111
+ * devDependencies
112
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.16 to 0.0.3-next.17
113
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.16 to 0.0.3-next.17
114
+ * @twin.org/validate-locales bumped from 0.0.3-next.16 to 0.0.3-next.17
115
+
116
+ ## [0.0.3-next.16](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.15...modules-v0.0.3-next.16) (2026-02-06)
117
+
118
+
119
+ ### Miscellaneous Chores
120
+
121
+ * **modules:** Synchronize repo versions
122
+
123
+
124
+ ### Dependencies
125
+
126
+ * The following workspace dependencies were updated
127
+ * dependencies
128
+ * @twin.org/core bumped from 0.0.3-next.15 to 0.0.3-next.16
129
+ * @twin.org/context bumped from 0.0.3-next.15 to 0.0.3-next.16
130
+ * @twin.org/nameof bumped from 0.0.3-next.15 to 0.0.3-next.16
131
+ * devDependencies
132
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.15 to 0.0.3-next.16
133
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.15 to 0.0.3-next.16
134
+ * @twin.org/validate-locales bumped from 0.0.3-next.15 to 0.0.3-next.16
135
+
136
+ ## [0.0.3-next.15](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.14...modules-v0.0.3-next.15) (2026-01-29)
137
+
138
+
139
+ ### Miscellaneous Chores
140
+
141
+ * **modules:** Synchronize repo versions
142
+
143
+
144
+ ### Dependencies
145
+
146
+ * The following workspace dependencies were updated
147
+ * dependencies
148
+ * @twin.org/core bumped from 0.0.3-next.14 to 0.0.3-next.15
149
+ * @twin.org/context bumped from 0.0.3-next.14 to 0.0.3-next.15
150
+ * @twin.org/nameof bumped from 0.0.3-next.14 to 0.0.3-next.15
151
+ * devDependencies
152
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.14 to 0.0.3-next.15
153
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.14 to 0.0.3-next.15
154
+ * @twin.org/validate-locales bumped from 0.0.3-next.14 to 0.0.3-next.15
155
+
156
+ ## [0.0.3-next.14](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.13...modules-v0.0.3-next.14) (2026-01-22)
157
+
158
+
159
+ ### Miscellaneous Chores
160
+
161
+ * **modules:** Synchronize repo versions
162
+
163
+
164
+ ### Dependencies
165
+
166
+ * The following workspace dependencies were updated
167
+ * dependencies
168
+ * @twin.org/core bumped from 0.0.3-next.13 to 0.0.3-next.14
169
+ * @twin.org/context bumped from 0.0.3-next.13 to 0.0.3-next.14
170
+ * @twin.org/nameof bumped from 0.0.3-next.13 to 0.0.3-next.14
171
+ * devDependencies
172
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.13 to 0.0.3-next.14
173
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.13 to 0.0.3-next.14
174
+ * @twin.org/validate-locales bumped from 0.0.3-next.13 to 0.0.3-next.14
175
+
176
+ ## [0.0.3-next.13](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.12...modules-v0.0.3-next.13) (2026-01-08)
177
+
178
+
179
+ ### Miscellaneous Chores
180
+
181
+ * **modules:** Synchronize repo versions
182
+
183
+
184
+ ### Dependencies
185
+
186
+ * The following workspace dependencies were updated
187
+ * dependencies
188
+ * @twin.org/core bumped from 0.0.3-next.12 to 0.0.3-next.13
189
+ * @twin.org/context bumped from 0.0.3-next.12 to 0.0.3-next.13
190
+ * @twin.org/nameof bumped from 0.0.3-next.12 to 0.0.3-next.13
191
+ * devDependencies
192
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.12 to 0.0.3-next.13
193
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.12 to 0.0.3-next.13
194
+ * @twin.org/validate-locales bumped from 0.0.3-next.12 to 0.0.3-next.13
195
+
196
+ ## [0.0.3-next.12](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.11...modules-v0.0.3-next.12) (2026-01-08)
197
+
198
+
199
+ ### Miscellaneous Chores
200
+
201
+ * **modules:** Synchronize repo versions
202
+
203
+
204
+ ### Dependencies
205
+
206
+ * The following workspace dependencies were updated
207
+ * dependencies
208
+ * @twin.org/core bumped from 0.0.3-next.11 to 0.0.3-next.12
209
+ * @twin.org/context bumped from 0.0.3-next.11 to 0.0.3-next.12
210
+ * @twin.org/nameof bumped from 0.0.3-next.11 to 0.0.3-next.12
211
+ * devDependencies
212
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.11 to 0.0.3-next.12
213
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.11 to 0.0.3-next.12
214
+ * @twin.org/validate-locales bumped from 0.0.3-next.11 to 0.0.3-next.12
215
+
216
+ ## [0.0.3-next.11](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.10...modules-v0.0.3-next.11) (2026-01-07)
217
+
218
+
219
+ ### Miscellaneous Chores
220
+
221
+ * **modules:** Synchronize repo versions
222
+
223
+
224
+ ### Dependencies
225
+
226
+ * The following workspace dependencies were updated
227
+ * dependencies
228
+ * @twin.org/core bumped from 0.0.3-next.10 to 0.0.3-next.11
229
+ * @twin.org/context bumped from 0.0.3-next.10 to 0.0.3-next.11
230
+ * @twin.org/nameof bumped from 0.0.3-next.10 to 0.0.3-next.11
231
+ * devDependencies
232
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.10 to 0.0.3-next.11
233
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.10 to 0.0.3-next.11
234
+ * @twin.org/validate-locales bumped from 0.0.3-next.10 to 0.0.3-next.11
235
+
236
+ ## [0.0.3-next.10](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.9...modules-v0.0.3-next.10) (2026-01-07)
237
+
238
+
239
+ ### Features
240
+
241
+ * retain detail in Errors from background threads ([52bdeef](https://github.com/twinfoundation/framework/commit/52bdeef7a75fd462ed118073b9dc7612304e038d))
242
+
243
+
244
+ ### Dependencies
245
+
246
+ * The following workspace dependencies were updated
247
+ * dependencies
248
+ * @twin.org/core bumped from 0.0.3-next.9 to 0.0.3-next.10
249
+ * @twin.org/context bumped from 0.0.3-next.9 to 0.0.3-next.10
250
+ * @twin.org/nameof bumped from 0.0.3-next.9 to 0.0.3-next.10
251
+ * devDependencies
252
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.9 to 0.0.3-next.10
253
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.9 to 0.0.3-next.10
254
+ * @twin.org/validate-locales bumped from 0.0.3-next.9 to 0.0.3-next.10
255
+
256
+ ## [0.0.3-next.9](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.8...modules-v0.0.3-next.9) (2026-01-05)
257
+
258
+
259
+ ### Miscellaneous Chores
260
+
261
+ * **modules:** Synchronize repo versions
262
+
263
+
264
+ ### Dependencies
265
+
266
+ * The following workspace dependencies were updated
267
+ * dependencies
268
+ * @twin.org/core bumped from 0.0.3-next.8 to 0.0.3-next.9
269
+ * @twin.org/context bumped from 0.0.3-next.8 to 0.0.3-next.9
270
+ * @twin.org/nameof bumped from 0.0.3-next.8 to 0.0.3-next.9
271
+ * devDependencies
272
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.8 to 0.0.3-next.9
273
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.8 to 0.0.3-next.9
274
+ * @twin.org/validate-locales bumped from 0.0.3-next.8 to 0.0.3-next.9
275
+
276
+ ## [0.0.3-next.8](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.7...modules-v0.0.3-next.8) (2025-11-26)
277
+
278
+
279
+ ### Miscellaneous Chores
280
+
281
+ * **modules:** Synchronize repo versions
282
+
283
+
284
+ ### Dependencies
285
+
286
+ * The following workspace dependencies were updated
287
+ * dependencies
288
+ * @twin.org/core bumped from 0.0.3-next.7 to 0.0.3-next.8
289
+ * @twin.org/context bumped from 0.0.3-next.7 to 0.0.3-next.8
290
+ * @twin.org/nameof bumped from 0.0.3-next.7 to 0.0.3-next.8
291
+ * devDependencies
292
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.7 to 0.0.3-next.8
293
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.7 to 0.0.3-next.8
294
+ * @twin.org/validate-locales bumped from 0.0.3-next.7 to 0.0.3-next.8
295
+
296
+ ## [0.0.3-next.7](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.6...modules-v0.0.3-next.7) (2025-11-25)
297
+
298
+
299
+ ### Features
300
+
301
+ * add context id features ([#206](https://github.com/twinfoundation/framework/issues/206)) ([ef0d4ee](https://github.com/twinfoundation/framework/commit/ef0d4ee11a4f5fc6cc6f52a4958ce905c04ee13b))
302
+ * add guards arrayEndsWith and arrayStartsWith ([95d875e](https://github.com/twinfoundation/framework/commit/95d875ec8ccb4713c145fdde941d4cfedcec2ed3))
303
+ * eslint migration to flat config ([74427d7](https://github.com/twinfoundation/framework/commit/74427d78d342167f7850e49ab87269326355befe))
304
+ * improve async pattern and error handling ([aaa1f68](https://github.com/twinfoundation/framework/commit/aaa1f6879d60adf04b78b0c1bbbec50f2873f020))
305
+ * improve Is.function and ModuleHelper.getModuleMethod signatures ([ecf968b](https://github.com/twinfoundation/framework/commit/ecf968b02934b3676be4bf7cd2d1e7f8e7af6ce2))
306
+ * locales validation ([#197](https://github.com/twinfoundation/framework/issues/197)) ([55fdadb](https://github.com/twinfoundation/framework/commit/55fdadb13595ce0047f787bd1d4135d429a99f12))
307
+ * module helper can now handle long running threads with messaging ([4ecbb9a](https://github.com/twinfoundation/framework/commit/4ecbb9a526927d462d4fb3f95ba2a44889202753))
308
+ * nodeIdentity optional in IComponent methods ([c78dc17](https://github.com/twinfoundation/framework/commit/c78dc17f4357d3e1ae40e415f468d3eae13e81f4))
309
+ * provide module helper override ([e998a64](https://github.com/twinfoundation/framework/commit/e998a64842cfd18693a14444be33b084fef2bb90))
310
+ * relocate core packages from tools ([bcab8f3](https://github.com/twinfoundation/framework/commit/bcab8f3160442ea4fcaf442947462504f3d6a17d))
311
+ * update dependencies ([f3bd015](https://github.com/twinfoundation/framework/commit/f3bd015efd169196b7e0335f5cab876ba6ca1d75))
312
+ * use cause instead of inner for errors ([1f4acc4](https://github.com/twinfoundation/framework/commit/1f4acc4d7a6b71a134d9547da9bf40de1e1e49da))
313
+ * use new shared store mechanism ([#131](https://github.com/twinfoundation/framework/issues/131)) ([934385b](https://github.com/twinfoundation/framework/commit/934385b2fbaf9f5c00a505ebf9d093bd5a425f55))
314
+
315
+
316
+ ### Dependencies
317
+
318
+ * The following workspace dependencies were updated
319
+ * dependencies
320
+ * @twin.org/core bumped from 0.0.3-next.6 to 0.0.3-next.7
321
+ * @twin.org/context bumped from 0.0.3-next.6 to 0.0.3-next.7
322
+ * @twin.org/nameof bumped from 0.0.3-next.6 to 0.0.3-next.7
323
+ * devDependencies
324
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.6 to 0.0.3-next.7
325
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.6 to 0.0.3-next.7
326
+ * @twin.org/validate-locales bumped from 0.0.3-next.6 to 0.0.3-next.7
327
+
328
+ ## [0.0.3-next.6](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.5...modules-v0.0.3-next.6) (2025-11-25)
329
+
330
+
331
+ ### Features
332
+
333
+ * module helper can now handle long running threads with messaging ([4ecbb9a](https://github.com/twinfoundation/framework/commit/4ecbb9a526927d462d4fb3f95ba2a44889202753))
334
+
335
+
336
+ ### Dependencies
337
+
338
+ * The following workspace dependencies were updated
339
+ * dependencies
340
+ * @twin.org/core bumped from 0.0.3-next.5 to 0.0.3-next.6
341
+ * @twin.org/context bumped from 0.0.3-next.5 to 0.0.3-next.6
342
+ * @twin.org/nameof bumped from 0.0.3-next.5 to 0.0.3-next.6
343
+ * devDependencies
344
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.5 to 0.0.3-next.6
345
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.5 to 0.0.3-next.6
346
+ * @twin.org/validate-locales bumped from 0.0.3-next.5 to 0.0.3-next.6
347
+
348
+ ## [0.0.3-next.5](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.4...modules-v0.0.3-next.5) (2025-11-20)
349
+
350
+
351
+ ### Miscellaneous Chores
352
+
353
+ * **modules:** Synchronize repo versions
354
+
355
+
356
+ ### Dependencies
357
+
358
+ * The following workspace dependencies were updated
359
+ * dependencies
360
+ * @twin.org/core bumped from 0.0.3-next.4 to 0.0.3-next.5
361
+ * @twin.org/nameof bumped from 0.0.3-next.4 to 0.0.3-next.5
362
+ * devDependencies
363
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.4 to 0.0.3-next.5
364
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.4 to 0.0.3-next.5
365
+ * @twin.org/validate-locales bumped from 0.0.3-next.4 to 0.0.3-next.5
366
+
367
+ ## [0.0.3-next.4](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.3...modules-v0.0.3-next.4) (2025-11-13)
368
+
369
+
370
+ ### Miscellaneous Chores
371
+
372
+ * **modules:** Synchronize repo versions
373
+
374
+
375
+ ### Dependencies
376
+
377
+ * The following workspace dependencies were updated
378
+ * dependencies
379
+ * @twin.org/core bumped from 0.0.3-next.3 to 0.0.3-next.4
380
+ * @twin.org/nameof bumped from 0.0.3-next.3 to 0.0.3-next.4
381
+ * devDependencies
382
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.3 to 0.0.3-next.4
383
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.3 to 0.0.3-next.4
384
+ * @twin.org/validate-locales bumped from 0.0.3-next.3 to 0.0.3-next.4
385
+
386
+ ## [0.0.3-next.3](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.2...modules-v0.0.3-next.3) (2025-11-12)
387
+
388
+
389
+ ### Miscellaneous Chores
390
+
391
+ * **modules:** Synchronize repo versions
392
+
393
+
394
+ ### Dependencies
395
+
396
+ * The following workspace dependencies were updated
397
+ * dependencies
398
+ * @twin.org/core bumped from 0.0.3-next.2 to 0.0.3-next.3
399
+ * @twin.org/nameof bumped from 0.0.3-next.2 to 0.0.3-next.3
400
+ * devDependencies
401
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.2 to 0.0.3-next.3
402
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.2 to 0.0.3-next.3
403
+ * @twin.org/validate-locales bumped from 0.0.3-next.2 to 0.0.3-next.3
404
+
3
405
  ## [0.0.3-next.2](https://github.com/twinfoundation/framework/compare/modules-v0.0.3-next.1...modules-v0.0.3-next.2) (2025-11-12)
4
406
 
5
407
 
@@ -164,7 +164,7 @@ GeneralError if executing the module entry failed.
164
164
 
165
165
  ### execModuleMethodThread()
166
166
 
167
- > `static` **execModuleMethodThread**\<`T`\>(`module`, `method`, `args?`): `Promise`\<`T`\>
167
+ > `static` **execModuleMethodThread**\<`T`\>(`module`, `method`, `args?`, `contextIds?`): `Promise`\<`T`\>
168
168
 
169
169
  Execute the method in the module in a thread.
170
170
 
@@ -194,6 +194,12 @@ The method to execute from the module.
194
194
 
195
195
  The arguments to pass to the method.
196
196
 
197
+ ##### contextIds?
198
+
199
+ `IContextIds`
200
+
201
+ The context IDs.
202
+
197
203
  #### Returns
198
204
 
199
205
  `Promise`\<`T`\>
@@ -206,6 +212,48 @@ GeneralError if executing the module entry failed.
206
212
 
207
213
  ***
208
214
 
215
+ ### execModuleMethodThreadMessage()
216
+
217
+ > `static` **execModuleMethodThreadMessage**(`module`, `completed`, `options?`): [`IModuleWorker`](../interfaces/IModuleWorker.md)
218
+
219
+ Load the module and provide a messaging interface.
220
+
221
+ #### Parameters
222
+
223
+ ##### module
224
+
225
+ `string`
226
+
227
+ The module.
228
+
229
+ ##### completed
230
+
231
+ (`operation`, `result?`, `err?`) => `void`
232
+
233
+ Callback called when the worker thread processes a completion.
234
+
235
+ ##### options?
236
+
237
+ Optional settings.
238
+
239
+ ###### threadName?
240
+
241
+ `string`
242
+
243
+ The name of the thread.
244
+
245
+ #### Returns
246
+
247
+ [`IModuleWorker`](../interfaces/IModuleWorker.md)
248
+
249
+ The messaging interface.
250
+
251
+ #### Throws
252
+
253
+ GeneralError if executing the module entry failed.
254
+
255
+ ***
256
+
209
257
  ### isLocalModule()
210
258
 
211
259
  > `static` **isLocalModule**(`name`): `boolean`
@@ -3,3 +3,7 @@
3
3
  ## Classes
4
4
 
5
5
  - [ModuleHelper](classes/ModuleHelper.md)
6
+
7
+ ## Interfaces
8
+
9
+ - [IModuleWorker](interfaces/IModuleWorker.md)
@@ -0,0 +1,51 @@
1
+ # Interface: IModuleWorker
2
+
3
+ Worker definition for modules.
4
+
5
+ ## Methods
6
+
7
+ ### executeMethod()
8
+
9
+ > **executeMethod**(`method`, `args?`, `contextIds?`): `void`
10
+
11
+ Execute a method in the module.
12
+
13
+ #### Parameters
14
+
15
+ ##### method
16
+
17
+ `string`
18
+
19
+ The method to execute.
20
+
21
+ ##### args?
22
+
23
+ `unknown`
24
+
25
+ The arguments for the method.
26
+
27
+ ##### contextIds?
28
+
29
+ `IContextIds`
30
+
31
+ The context IDs.
32
+
33
+ #### Returns
34
+
35
+ `void`
36
+
37
+ The result of the method.
38
+
39
+ ***
40
+
41
+ ### terminate()
42
+
43
+ > **terminate**(): `Promise`\<`number`\>
44
+
45
+ Terminate the worker.
46
+
47
+ #### Returns
48
+
49
+ `Promise`\<`number`\>
50
+
51
+ A promise that resolves when the worker is terminated including the exit code.
package/locales/en.json CHANGED
@@ -3,9 +3,8 @@
3
3
  "moduleHelper": {
4
4
  "moduleNotFound": "Failed to load module \"{module}\"",
5
5
  "entryNotFound": "Failed to load entry \"{entry}\" from module \"{module}\"",
6
- "notFunction": "The entry \"{entry}\" in module \"{module}\" is not a function",
7
- "workerFailed": "The thread worker failed for \"{entry}\" in module \"{module}\" with exit code \"{exitCode}\"",
8
- "workerException": "The thread worker failed with an exception \"{entry}\" in module \"{module}\""
6
+ "notFunction": "The entry \"{method}\" in module \"{module}\" is not a function",
7
+ "workerException": "The thread worker failed with an exception in module \"{module}\""
9
8
  }
10
9
  }
11
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/modules",
3
- "version": "0.0.3-next.2",
3
+ "version": "0.0.3-next.21",
4
4
  "description": "Helper classes for loading and executing from modules",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,8 +14,9 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/core": "0.0.3-next.2",
18
- "@twin.org/nameof": "0.0.3-next.2"
17
+ "@twin.org/context": "0.0.3-next.21",
18
+ "@twin.org/core": "0.0.3-next.21",
19
+ "@twin.org/nameof": "0.0.3-next.21"
19
20
  },
20
21
  "main": "./dist/es/index.js",
21
22
  "types": "./dist/types/index.d.ts",