@twin.org/core 0.9.3-next.2 → 0.9.3-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ // Copyright 2026 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { Factory } from "./factory.js";
4
+ /**
5
+ * Factory for creating implementation of facade types.
6
+ */
7
+ // eslint-disable-next-line @typescript-eslint/naming-convention
8
+ export const FacadeFactory = Factory.createFactory("facade");
9
+ //# sourceMappingURL=facadeFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facadeFactory.js","sourceRoot":"","sources":["../../../src/factories/facadeFactory.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC;;GAEG;AACH,gEAAgE;AAChE,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAU,QAAQ,CAAC,CAAC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Factory } from \"./factory.js\";\nimport type { IFacade } from \"../models/IFacade.js\";\n\n/**\n * Factory for creating implementation of facade types.\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const FacadeFactory = Factory.createFactory<IFacade>(\"facade\");\n"]}
@@ -25,6 +25,27 @@ export class Factory {
25
25
  * @internal
26
26
  */
27
27
  _instances;
28
+ /**
29
+ * The factory the facades are resolved from, held once resolved. It cannot be resolved in the
30
+ * constructor, because createFactory only stores a factory after constructing it, so the facade
31
+ * factory would recurse while constructing itself.
32
+ * @internal
33
+ */
34
+ _facadeFactory;
35
+ /**
36
+ * The facades applied to the instances, in the order they were activated. The facade is
37
+ * resolved when it is activated rather than when an instance is produced, so unregistering or
38
+ * replacing it afterwards cannot affect a factory which has already activated it.
39
+ * @internal
40
+ */
41
+ _facades;
42
+ /**
43
+ * Store the instances with the facades applied, keyed as the instances are.
44
+ * The unwrapped instances stay in _instances, so activating or deactivating a facade only has
45
+ * to discard this cache rather than rebuild the components themselves.
46
+ * @internal
47
+ */
48
+ _wrappedInstances;
28
49
  /**
29
50
  * Counter for the ordering.
30
51
  * @internal
@@ -51,6 +72,8 @@ export class Factory {
51
72
  this._typeName = typeName;
52
73
  this._generators = {};
53
74
  this._instances = {};
75
+ this._facades = [];
76
+ this._wrappedInstances = {};
54
77
  this._orderCounter = 0;
55
78
  this._autoInstance = autoInstance;
56
79
  this._matcher = matcher ?? this.defaultMatcher.bind(this);
@@ -180,7 +203,7 @@ export class Factory {
180
203
  this._instances[matchName] = this._generators[matchName].generator();
181
204
  }
182
205
  if (this._instances[matchName]) {
183
- return this._instances[matchName];
206
+ return this.wrappedInstance(matchName);
184
207
  }
185
208
  }
186
209
  }
@@ -215,7 +238,10 @@ export class Factory {
215
238
  Guards.stringValue(Factory.CLASS_NAME, "name", name);
216
239
  const matchName = this._matcher(Object.keys(this._generators), name);
217
240
  if (Is.stringValue(matchName) && this._generators[matchName]) {
218
- return this._generators[matchName].generator(args);
241
+ const instance = this._generators[matchName].generator(args);
242
+ if (!Is.empty(instance)) {
243
+ return this.applyFacades(instance);
244
+ }
219
245
  }
220
246
  }
221
247
  /**
@@ -226,31 +252,85 @@ export class Factory {
226
252
  this.removeInstance(name);
227
253
  }
228
254
  this._instances = {};
255
+ this._wrappedInstances = {};
229
256
  }
230
257
  /**
231
258
  * Remove all the instances and the generators.
232
259
  */
233
260
  clear() {
234
261
  this._instances = {};
262
+ this._wrappedInstances = {};
263
+ this._facades = [];
235
264
  this._generators = {};
236
265
  this._orderCounter = 0;
237
266
  }
267
+ /**
268
+ * Activate a facade for this factory, so every instance it produces is wrapped by it.
269
+ * An instance is passed through the facades in the order they were activated, so the facade
270
+ * activated first is the outermost. Activating a facade which is already active does nothing.
271
+ * @param name The name of the facade, as registered with the facade factory.
272
+ * @throws GuardError if the parameters are invalid.
273
+ * @throws GeneralError if no facade is registered with the name, or the factory is the facade
274
+ * factory itself.
275
+ */
276
+ useFacade(name) {
277
+ Guards.stringValue(Factory.CLASS_NAME, "name", name);
278
+ const facadeFactory = this.facadeFactory();
279
+ // Wrapping the facades themselves would mean resolving a facade in order to apply it.
280
+ if (this._typeName === facadeFactory.typeName()) {
281
+ throw new GeneralError(Factory.CLASS_NAME, "noFacadeOnFacades");
282
+ }
283
+ if (!facadeFactory.hasName(name)) {
284
+ throw new GeneralError(Factory.CLASS_NAME, "noFacade", {
285
+ typeName: this._typeName,
286
+ name
287
+ });
288
+ }
289
+ if (!this._facades.some(f => f.name === name)) {
290
+ this._facades.push({ name, facade: facadeFactory.get(name) });
291
+ // Instances handed out before this point keep the facades they were built with, the
292
+ // change applies to instances produced from here on.
293
+ this._wrappedInstances = {};
294
+ }
295
+ }
296
+ /**
297
+ * Deactivate a facade for this factory. Deactivating a facade which is not active does nothing.
298
+ * @param name The name of the facade to deactivate.
299
+ * @throws GuardError if the parameters are invalid.
300
+ */
301
+ unuseFacade(name) {
302
+ Guards.stringValue(Factory.CLASS_NAME, "name", name);
303
+ const index = this._facades.findIndex(f => f.name === name);
304
+ if (index >= 0) {
305
+ this._facades.splice(index, 1);
306
+ this._wrappedInstances = {};
307
+ }
308
+ }
238
309
  /**
239
310
  * Get all the instances as a map.
311
+ * @param withFacade Return the instances with the active facades applied, defaults to false.
240
312
  * @returns The instances as a map.
241
313
  */
242
- instancesMap() {
243
- return this._instances;
314
+ instancesMap(withFacade) {
315
+ if (!withFacade) {
316
+ return this._instances;
317
+ }
318
+ const instances = {};
319
+ for (const instanceName in this._instances) {
320
+ instances[instanceName] = this.wrappedInstance(instanceName);
321
+ }
322
+ return instances;
244
323
  }
245
324
  /**
246
325
  * Get all the instances as a list in the order they were registered.
326
+ * @param withFacade Return the instances with the active facades applied, defaults to false.
247
327
  * @returns The instances as a list in the order they were registered.
248
328
  */
249
- instancesList() {
329
+ instancesList(withFacade) {
250
330
  const orderedInstances = [];
251
331
  for (const instanceName in this._instances) {
252
332
  orderedInstances.push({
253
- instance: this._instances[instanceName],
333
+ instance: withFacade ? this.wrappedInstance(instanceName) : this._instances[instanceName],
254
334
  order: this._generators[instanceName].order
255
335
  });
256
336
  }
@@ -286,6 +366,47 @@ export class Factory {
286
366
  */
287
367
  removeInstance(name) {
288
368
  delete this._instances[name];
369
+ delete this._wrappedInstances[name];
370
+ }
371
+ /**
372
+ * Get the factory the facades are resolved from, resolving it on first use.
373
+ * @returns The facade factory.
374
+ * @internal
375
+ */
376
+ facadeFactory() {
377
+ this._facadeFactory ??= Factory.createFactory("facade");
378
+ return this._facadeFactory;
379
+ }
380
+ /**
381
+ * Get an instance with the active facades applied, wrapping it on first use.
382
+ * @param name The name of the instance, which must already have been created.
383
+ * @returns The wrapped instance.
384
+ * @throws GeneralError if a facade does not return a wrapped instance.
385
+ * @internal
386
+ */
387
+ wrappedInstance(name) {
388
+ this._wrappedInstances[name] ??= this.applyFacades(this._instances[name]);
389
+ return this._wrappedInstances[name];
390
+ }
391
+ /**
392
+ * Wrap an instance in the active facades. The first activated facade ends up outermost.
393
+ * @param instance The instance to wrap.
394
+ * @returns The wrapped instance, or the instance itself when no facades are active.
395
+ * @throws GeneralError if a facade does not return a wrapped instance.
396
+ * @internal
397
+ */
398
+ applyFacades(instance) {
399
+ let wrapped = instance;
400
+ for (let i = this._facades.length - 1; i >= 0; i--) {
401
+ wrapped = this._facades[i].facade.wrap(wrapped);
402
+ if (Is.empty(wrapped)) {
403
+ throw new GeneralError(Factory.CLASS_NAME, "noFacadeWrap", {
404
+ typeName: this._typeName,
405
+ name: this._facades[i].name
406
+ });
407
+ }
408
+ }
409
+ return wrapped;
289
410
  }
290
411
  /**
291
412
  * Match the requested name to the generator name.
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/factories/factory.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { nameof } from \"@twin.org/nameof\";\nimport { GeneralError } from \"../errors/generalError.js\";\nimport { Guards } from \"../utils/guards.js\";\nimport { Is } from \"../utils/is.js\";\nimport { SharedStore } from \"../utils/sharedStore.js\";\n\n/**\n * Factory for creating implementation of generic types.\n */\nexport class Factory<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Factory<unknown>>();\n\n\t/**\n\t * Type name for the instances.\n\t * @internal\n\t */\n\tprivate readonly _typeName: string;\n\n\t/**\n\t * Store the generators.\n\t * @internal\n\t */\n\tprivate _generators: {\n\t\t[name: string]: {\n\t\t\tgenerator: (args?: unknown) => T;\n\t\t\torder: number;\n\t\t};\n\t};\n\n\t/**\n\t * Store the created instances.\n\t * @internal\n\t */\n\tprivate _instances: { [name: string]: T };\n\n\t/**\n\t * Counter for the ordering.\n\t * @internal\n\t */\n\tprivate _orderCounter: number;\n\n\t/**\n\t * Automatically created an instance when registered.\n\t * @internal\n\t */\n\tprivate readonly _autoInstance: boolean;\n\n\t/**\n\t * Match the name of the instance.\n\t * @internal\n\t */\n\tprivate readonly _matcher: (names: string[], name: string) => string | undefined;\n\n\t/**\n\t * Create a new instance of Factory, private use createFactory.\n\t * @param typeName The type name for the instances.\n\t * @param autoInstance Automatically create an instance when registered.\n\t * @param matcher Match the name of the instance.\n\t * @internal\n\t */\n\tprivate constructor(\n\t\ttypeName: string,\n\t\tautoInstance: boolean = false,\n\t\tmatcher?: (names: string[], name: string) => string | undefined\n\t) {\n\t\tthis._typeName = typeName;\n\t\tthis._generators = {};\n\t\tthis._instances = {};\n\t\tthis._orderCounter = 0;\n\t\tthis._autoInstance = autoInstance;\n\t\tthis._matcher = matcher ?? this.defaultMatcher.bind(this);\n\t}\n\n\t/**\n\t * Create a new factory, which is shared throughout all library instances.\n\t * @param typeName The type name for the instances.\n\t * @param autoInstance Automatically create an instance when registered.\n\t * @param matcher Match the name of the instance.\n\t * @returns The factory instance.\n\t */\n\tpublic static createFactory<U>(\n\t\ttypeName: string,\n\t\tautoInstance: boolean = false,\n\t\tmatcher?: (names: string[], name: string) => string | undefined\n\t): Factory<U> {\n\t\tconst factories = Factory.getFactories();\n\n\t\tif (Is.undefined(factories[typeName])) {\n\t\t\tfactories[typeName] = new Factory<U>(typeName, autoInstance, matcher);\n\t\t}\n\t\treturn factories[typeName] as Factory<U>;\n\t}\n\n\t/**\n\t * Get all the factories.\n\t * @returns All the factories.\n\t */\n\tpublic static getFactories(): { [typeName: string]: Factory<unknown> } {\n\t\treturn SharedStore.get<{\n\t\t\t[typeName: string]: Factory<unknown>;\n\t\t}>(\"factories\", () => ({}));\n\t}\n\n\t/**\n\t * Get a specific factory by type name.\n\t * @param typeName The type name of the factory.\n\t * @returns The factory instance if it exists, otherwise undefined.\n\t */\n\tpublic static getFactory<T = unknown>(typeName: string): Factory<T> | undefined {\n\t\tconst factories = Factory.getFactories();\n\n\t\treturn factories[typeName] as Factory<T> | undefined;\n\t}\n\n\t/**\n\t * Reset all the factories, which removes any created instances, but not the registrations.\n\t */\n\tpublic static resetFactories(): void {\n\t\tconst factories = Factory.getFactories();\n\n\t\tfor (const typeName in factories) {\n\t\t\tfactories[typeName].reset();\n\t\t}\n\t}\n\n\t/**\n\t * Clear all the factories, which removes anything registered with the factories.\n\t */\n\tpublic static clearFactories(): void {\n\t\tconst factories = Factory.getFactories();\n\n\t\tfor (const typeName in factories) {\n\t\t\tfactories[typeName].clear();\n\t\t}\n\t}\n\n\t/**\n\t * Get the type name of the factory.\n\t * @returns The type name of the factory.\n\t */\n\tpublic typeName(): string {\n\t\treturn this._typeName;\n\t}\n\n\t/**\n\t * Register a new generator.\n\t * @param name The name of the generator.\n\t * @param generator The function to create an instance.\n\t */\n\tpublic register<U extends T>(name: string, generator: (args?: unknown) => U): void {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tGuards.function(Factory.CLASS_NAME, nameof(generator), generator);\n\t\tthis._generators[name] = {\n\t\t\tgenerator,\n\t\t\torder: this._orderCounter++\n\t\t};\n\n\t\t// Remove any existing instance\n\t\tthis.removeInstance(name);\n\t\tif (this._autoInstance) {\n\t\t\tthis._instances[name] = generator();\n\t\t}\n\t}\n\n\t/**\n\t * Unregister a generator.\n\t * @param name The name of the generator to unregister.\n\t * @throws GuardError if the parameters are invalid.\n\t * @throws GeneralError if no generator exists.\n\t */\n\tpublic unregister(name: string): void {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tif (!this._generators[name]) {\n\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noUnregister\", {\n\t\t\t\ttypeName: this._typeName,\n\t\t\t\tname\n\t\t\t});\n\t\t}\n\t\tdelete this._generators[name];\n\t\t// Remove any existing instance\n\t\tthis.removeInstance(name);\n\t}\n\n\t/**\n\t * Get a generator instance.\n\t * @param name The name of the instance to generate.\n\t * @returns An instance of the item.\n\t * @throws GuardError if the parameters are invalid.\n\t * @throws GeneralError if no item exists to get.\n\t */\n\tpublic get<U extends T>(name: string): U {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tconst instance = this.getIfExists(name);\n\t\tif (!instance) {\n\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noGet\", {\n\t\t\t\ttypeName: this._typeName,\n\t\t\t\tname\n\t\t\t});\n\t\t}\n\t\treturn instance as U;\n\t}\n\n\t/**\n\t * Get a generator instance with no exceptions.\n\t * @param name The name of the instance to generate.\n\t * @returns An instance of the item or undefined if it does not exist.\n\t */\n\tpublic getIfExists<U extends T>(name?: string): U | undefined {\n\t\tif (Is.empty(name)) {\n\t\t\treturn;\n\t\t}\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\n\t\tconst matchName = this._matcher(Object.keys(this._generators), name);\n\n\t\tif (Is.stringValue(matchName) && this._generators[matchName]) {\n\t\t\tif (!this._instances[matchName]) {\n\t\t\t\tthis._instances[matchName] = this._generators[matchName].generator();\n\t\t\t}\n\t\t\tif (this._instances[matchName]) {\n\t\t\t\treturn this._instances[matchName] as U;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Create a new instance without caching it.\n\t * @param name The name of the instance to generate.\n\t * @param args The arguments to pass to the generator.\n\t * @returns A new instance of the item.\n\t * @throws GuardError if the parameters are invalid.\n\t * @throws GeneralError if no item exists to create.\n\t */\n\tpublic create<U extends T>(name: string, args?: unknown): U {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tconst instance = this.createIfExists(name, args);\n\t\tif (!instance) {\n\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noCreate\", {\n\t\t\t\ttypeName: this._typeName,\n\t\t\t\tname,\n\t\t\t\targs: Is.undefined(args) ? \"\" : JSON.stringify(args)\n\t\t\t});\n\t\t}\n\t\treturn instance as U;\n\t}\n\n\t/**\n\t * Create a new instance without caching it if it exists.\n\t * @param name The name of the instance to generate.\n\t * @param args The arguments to pass to the generator.\n\t * @returns A new instance of the item if it exists.\n\t * @throws GuardError if the parameters are invalid.\n\t */\n\tpublic createIfExists<U extends T>(name: string, args?: unknown): U | undefined {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tconst matchName = this._matcher(Object.keys(this._generators), name);\n\n\t\tif (Is.stringValue(matchName) && this._generators[matchName]) {\n\t\t\treturn this._generators[matchName].generator(args) as U;\n\t\t}\n\t}\n\n\t/**\n\t * Remove all the instances and leave the generators intact.\n\t */\n\tpublic reset(): void {\n\t\tfor (const name in this._generators) {\n\t\t\tthis.removeInstance(name);\n\t\t}\n\t\tthis._instances = {};\n\t}\n\n\t/**\n\t * Remove all the instances and the generators.\n\t */\n\tpublic clear(): void {\n\t\tthis._instances = {};\n\t\tthis._generators = {};\n\t\tthis._orderCounter = 0;\n\t}\n\n\t/**\n\t * Get all the instances as a map.\n\t * @returns The instances as a map.\n\t */\n\tpublic instancesMap(): { [name: string]: T } {\n\t\treturn this._instances;\n\t}\n\n\t/**\n\t * Get all the instances as a list in the order they were registered.\n\t * @returns The instances as a list in the order they were registered.\n\t */\n\tpublic instancesList(): T[] {\n\t\tconst orderedInstances: { instance: T; order: number }[] = [];\n\t\tfor (const instanceName in this._instances) {\n\t\t\torderedInstances.push({\n\t\t\t\tinstance: this._instances[instanceName],\n\t\t\t\torder: this._generators[instanceName].order\n\t\t\t});\n\t\t}\n\t\treturn orderedInstances.sort((a, b) => a.order - b.order).map(o => o.instance);\n\t}\n\n\t/**\n\t * Get all the generator names in the order they were registered.\n\t * @returns The ordered generator names.\n\t */\n\tpublic names(): string[] {\n\t\tconst orderedNames: { name: string; order: number }[] = [];\n\t\tfor (const generator in this._generators) {\n\t\t\torderedNames.push({\n\t\t\t\tname: generator,\n\t\t\t\torder: this._generators[generator].order\n\t\t\t});\n\t\t}\n\t\treturn orderedNames.sort((a, b) => a.order - b.order).map(o => o.name);\n\t}\n\n\t/**\n\t * Does the factory contain the name.\n\t * @param name The name of the instance to find.\n\t * @returns True if the factory has a matching name.\n\t */\n\tpublic hasName(name: string): boolean {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\treturn Is.stringValue(this._matcher(Object.keys(this._generators), name));\n\t}\n\n\t/**\n\t * Remove any instances of the given name.\n\t * @param name The name of the instances to remove.\n\t * @internal\n\t */\n\tprivate removeInstance(name: string): void {\n\t\tdelete this._instances[name];\n\t}\n\n\t/**\n\t * Match the requested name to the generator name.\n\t * @param names The list of names for all the generators.\n\t * @param name The name to match.\n\t * @returns The matched name or undefined if no match.\n\t * @internal\n\t */\n\tprivate defaultMatcher(names: string[], name: string): string | undefined {\n\t\treturn this._generators[name] ? name : undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/factories/factory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD;;GAEG;AACH,MAAM,OAAO,OAAO;IACnB;;OAEG;IACI,MAAM,CAAU,UAAU,aAAsC;IAEvE;;;OAGG;IACc,SAAS,CAAS;IAEnC;;;OAGG;IACK,WAAW,CAKjB;IAEF;;;OAGG;IACK,UAAU,CAAwB;IAE1C;;;;;OAKG;IACK,cAAc,CAAoB;IAE1C;;;;;OAKG;IACK,QAAQ,CAAsC;IAEtD;;;;;OAKG;IACK,iBAAiB,CAAwB;IAEjD;;;OAGG;IACK,aAAa,CAAS;IAE9B;;;OAGG;IACc,aAAa,CAAU;IAExC;;;OAGG;IACc,QAAQ,CAAwD;IAEjF;;;;;;OAMG;IACH,YACC,QAAgB,EAChB,eAAwB,KAAK,EAC7B,OAA+D;QAE/D,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,aAAa,CAC1B,QAAgB,EAChB,eAAwB,KAAK,EAC7B,OAA+D;QAE/D,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QAEzC,IAAI,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YACvC,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,OAAO,CAAI,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,SAAS,CAAC,QAAQ,CAAe,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,YAAY;QACzB,OAAO,WAAW,CAAC,GAAG,CAEnB,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,UAAU,CAAc,QAAgB;QACrD,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QAEzC,OAAO,SAAS,CAAC,QAAQ,CAA2B,CAAC;IACtD,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,cAAc;QAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QAEzC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;IACF,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,cAAc;QAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QAEzC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,QAAQ;QACd,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACI,QAAQ,CAAc,IAAY,EAAE,SAAgC;QAC1E,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAC3D,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,eAAqB,SAAS,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG;YACxB,SAAS;YACT,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE;SAC3B,CAAC;QAEF,+BAA+B;QAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC;QACrC,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACI,UAAU,CAAC,IAAY;QAC7B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,EAAE;gBAC1D,QAAQ,EAAE,IAAI,CAAC,SAAS;gBACxB,IAAI;aACJ,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC9B,+BAA+B;QAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACI,GAAG,CAAc,IAAY;QACnC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE;gBACnD,QAAQ,EAAE,IAAI,CAAC,SAAS;gBACxB,IAAI;aACJ,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,QAAa,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACI,WAAW,CAAc,IAAa;QAC5C,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,OAAO;QACR,CAAC;QACD,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAE3D,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;QAErE,IAAI,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,CAAC;YACtE,CAAC;YACD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC,eAAe,CAAC,SAAS,CAAM,CAAC;YAC7C,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAc,IAAY,EAAE,IAAc;QACtD,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE;gBACtD,QAAQ,EAAE,IAAI,CAAC,SAAS;gBACxB,IAAI;gBACJ,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aACpD,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,QAAa,CAAC;IACtB,CAAC;IAED;;;;;;OAMG;IACI,cAAc,CAAc,IAAY,EAAE,IAAc;QAC9D,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;QAErE,IAAI,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAE7D,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAM,CAAC;YACzC,CAAC;QACF,CAAC;IACF,CAAC;IAED;;OAEG;IACI,KAAK;QACX,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,KAAK;QACX,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;IACxB,CAAC;IAED;;;;;;;;OAQG;IACI,SAAS,CAAC,IAAY;QAC5B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAE3D,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAE3C,sFAAsF;QACtF,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC;YACjD,MAAM,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE;gBACtD,QAAQ,EAAE,IAAI,CAAC,SAAS;gBACxB,IAAI;aACJ,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9D,oFAAoF;YACpF,qDAAqD;YACrD,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC7B,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,WAAW,CAAC,IAAY;QAC9B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAE3D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC5D,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YAChB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC/B,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC7B,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,YAAY,CAAC,UAAoB;QACvC,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,UAAU,CAAC;QACxB,CAAC;QAED,MAAM,SAAS,GAA0B,EAAE,CAAC;QAC5C,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC5C,SAAS,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACI,aAAa,CAAC,UAAoB;QACxC,MAAM,gBAAgB,GAAqC,EAAE,CAAC;QAC9D,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC5C,gBAAgB,CAAC,IAAI,CAAC;gBACrB,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;gBACzF,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,KAAK;aAC3C,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAChF,CAAC;IAED;;;OAGG;IACI,KAAK;QACX,MAAM,YAAY,GAAsC,EAAE,CAAC;QAC3D,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC1C,YAAY,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,KAAK;aACxC,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxE,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAC,IAAY;QAC1B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAC3D,OAAO,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED;;;;OAIG;IACK,cAAc,CAAC,IAAY;QAClC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACK,aAAa;QACpB,IAAI,CAAC,cAAc,KAAK,OAAO,CAAC,aAAa,CAAU,QAAQ,CAAC,CAAC;QAEjE,OAAO,IAAI,CAAC,cAAc,CAAC;IAC5B,CAAC;IAED;;;;;;OAMG;IACK,eAAe,CAAC,IAAY;QACnC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAE1E,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACK,YAAY,CAAC,QAAW;QAC/B,IAAI,OAAO,GAAG,QAAQ,CAAC;QAEvB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACpD,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAM,CAAC;YAErD,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,EAAE;oBAC1D,QAAQ,EAAE,IAAI,CAAC,SAAS;oBACxB,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;iBAC3B,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QAED,OAAO,OAAO,CAAC;IAChB,CAAC;IAED;;;;;;OAMG;IACK,cAAc,CAAC,KAAe,EAAE,IAAY;QACnD,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { nameof } from \"@twin.org/nameof\";\nimport { GeneralError } from \"../errors/generalError.js\";\nimport type { IFacade } from \"../models/IFacade.js\";\nimport { Guards } from \"../utils/guards.js\";\nimport { Is } from \"../utils/is.js\";\nimport { SharedStore } from \"../utils/sharedStore.js\";\n\n/**\n * Factory for creating implementation of generic types.\n */\nexport class Factory<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Factory<unknown>>();\n\n\t/**\n\t * Type name for the instances.\n\t * @internal\n\t */\n\tprivate readonly _typeName: string;\n\n\t/**\n\t * Store the generators.\n\t * @internal\n\t */\n\tprivate _generators: {\n\t\t[name: string]: {\n\t\t\tgenerator: (args?: unknown) => T;\n\t\t\torder: number;\n\t\t};\n\t};\n\n\t/**\n\t * Store the created instances.\n\t * @internal\n\t */\n\tprivate _instances: { [name: string]: T };\n\n\t/**\n\t * The factory the facades are resolved from, held once resolved. It cannot be resolved in the\n\t * constructor, because createFactory only stores a factory after constructing it, so the facade\n\t * factory would recurse while constructing itself.\n\t * @internal\n\t */\n\tprivate _facadeFactory?: Factory<IFacade>;\n\n\t/**\n\t * The facades applied to the instances, in the order they were activated. The facade is\n\t * resolved when it is activated rather than when an instance is produced, so unregistering or\n\t * replacing it afterwards cannot affect a factory which has already activated it.\n\t * @internal\n\t */\n\tprivate _facades: { name: string; facade: IFacade }[];\n\n\t/**\n\t * Store the instances with the facades applied, keyed as the instances are.\n\t * The unwrapped instances stay in _instances, so activating or deactivating a facade only has\n\t * to discard this cache rather than rebuild the components themselves.\n\t * @internal\n\t */\n\tprivate _wrappedInstances: { [name: string]: T };\n\n\t/**\n\t * Counter for the ordering.\n\t * @internal\n\t */\n\tprivate _orderCounter: number;\n\n\t/**\n\t * Automatically created an instance when registered.\n\t * @internal\n\t */\n\tprivate readonly _autoInstance: boolean;\n\n\t/**\n\t * Match the name of the instance.\n\t * @internal\n\t */\n\tprivate readonly _matcher: (names: string[], name: string) => string | undefined;\n\n\t/**\n\t * Create a new instance of Factory, private use createFactory.\n\t * @param typeName The type name for the instances.\n\t * @param autoInstance Automatically create an instance when registered.\n\t * @param matcher Match the name of the instance.\n\t * @internal\n\t */\n\tprivate constructor(\n\t\ttypeName: string,\n\t\tautoInstance: boolean = false,\n\t\tmatcher?: (names: string[], name: string) => string | undefined\n\t) {\n\t\tthis._typeName = typeName;\n\t\tthis._generators = {};\n\t\tthis._instances = {};\n\t\tthis._facades = [];\n\t\tthis._wrappedInstances = {};\n\t\tthis._orderCounter = 0;\n\t\tthis._autoInstance = autoInstance;\n\t\tthis._matcher = matcher ?? this.defaultMatcher.bind(this);\n\t}\n\n\t/**\n\t * Create a new factory, which is shared throughout all library instances.\n\t * @param typeName The type name for the instances.\n\t * @param autoInstance Automatically create an instance when registered.\n\t * @param matcher Match the name of the instance.\n\t * @returns The factory instance.\n\t */\n\tpublic static createFactory<U>(\n\t\ttypeName: string,\n\t\tautoInstance: boolean = false,\n\t\tmatcher?: (names: string[], name: string) => string | undefined\n\t): Factory<U> {\n\t\tconst factories = Factory.getFactories();\n\n\t\tif (Is.undefined(factories[typeName])) {\n\t\t\tfactories[typeName] = new Factory<U>(typeName, autoInstance, matcher);\n\t\t}\n\t\treturn factories[typeName] as Factory<U>;\n\t}\n\n\t/**\n\t * Get all the factories.\n\t * @returns All the factories.\n\t */\n\tpublic static getFactories(): { [typeName: string]: Factory<unknown> } {\n\t\treturn SharedStore.get<{\n\t\t\t[typeName: string]: Factory<unknown>;\n\t\t}>(\"factories\", () => ({}));\n\t}\n\n\t/**\n\t * Get a specific factory by type name.\n\t * @param typeName The type name of the factory.\n\t * @returns The factory instance if it exists, otherwise undefined.\n\t */\n\tpublic static getFactory<T = unknown>(typeName: string): Factory<T> | undefined {\n\t\tconst factories = Factory.getFactories();\n\n\t\treturn factories[typeName] as Factory<T> | undefined;\n\t}\n\n\t/**\n\t * Reset all the factories, which removes any created instances, but not the registrations.\n\t */\n\tpublic static resetFactories(): void {\n\t\tconst factories = Factory.getFactories();\n\n\t\tfor (const typeName in factories) {\n\t\t\tfactories[typeName].reset();\n\t\t}\n\t}\n\n\t/**\n\t * Clear all the factories, which removes anything registered with the factories.\n\t */\n\tpublic static clearFactories(): void {\n\t\tconst factories = Factory.getFactories();\n\n\t\tfor (const typeName in factories) {\n\t\t\tfactories[typeName].clear();\n\t\t}\n\t}\n\n\t/**\n\t * Get the type name of the factory.\n\t * @returns The type name of the factory.\n\t */\n\tpublic typeName(): string {\n\t\treturn this._typeName;\n\t}\n\n\t/**\n\t * Register a new generator.\n\t * @param name The name of the generator.\n\t * @param generator The function to create an instance.\n\t */\n\tpublic register<U extends T>(name: string, generator: (args?: unknown) => U): void {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tGuards.function(Factory.CLASS_NAME, nameof(generator), generator);\n\t\tthis._generators[name] = {\n\t\t\tgenerator,\n\t\t\torder: this._orderCounter++\n\t\t};\n\n\t\t// Remove any existing instance\n\t\tthis.removeInstance(name);\n\t\tif (this._autoInstance) {\n\t\t\tthis._instances[name] = generator();\n\t\t}\n\t}\n\n\t/**\n\t * Unregister a generator.\n\t * @param name The name of the generator to unregister.\n\t * @throws GuardError if the parameters are invalid.\n\t * @throws GeneralError if no generator exists.\n\t */\n\tpublic unregister(name: string): void {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tif (!this._generators[name]) {\n\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noUnregister\", {\n\t\t\t\ttypeName: this._typeName,\n\t\t\t\tname\n\t\t\t});\n\t\t}\n\t\tdelete this._generators[name];\n\t\t// Remove any existing instance\n\t\tthis.removeInstance(name);\n\t}\n\n\t/**\n\t * Get a generator instance.\n\t * @param name The name of the instance to generate.\n\t * @returns An instance of the item.\n\t * @throws GuardError if the parameters are invalid.\n\t * @throws GeneralError if no item exists to get.\n\t */\n\tpublic get<U extends T>(name: string): U {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tconst instance = this.getIfExists(name);\n\t\tif (!instance) {\n\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noGet\", {\n\t\t\t\ttypeName: this._typeName,\n\t\t\t\tname\n\t\t\t});\n\t\t}\n\t\treturn instance as U;\n\t}\n\n\t/**\n\t * Get a generator instance with no exceptions.\n\t * @param name The name of the instance to generate.\n\t * @returns An instance of the item or undefined if it does not exist.\n\t */\n\tpublic getIfExists<U extends T>(name?: string): U | undefined {\n\t\tif (Is.empty(name)) {\n\t\t\treturn;\n\t\t}\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\n\t\tconst matchName = this._matcher(Object.keys(this._generators), name);\n\n\t\tif (Is.stringValue(matchName) && this._generators[matchName]) {\n\t\t\tif (!this._instances[matchName]) {\n\t\t\t\tthis._instances[matchName] = this._generators[matchName].generator();\n\t\t\t}\n\t\t\tif (this._instances[matchName]) {\n\t\t\t\treturn this.wrappedInstance(matchName) as U;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Create a new instance without caching it.\n\t * @param name The name of the instance to generate.\n\t * @param args The arguments to pass to the generator.\n\t * @returns A new instance of the item.\n\t * @throws GuardError if the parameters are invalid.\n\t * @throws GeneralError if no item exists to create.\n\t */\n\tpublic create<U extends T>(name: string, args?: unknown): U {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tconst instance = this.createIfExists(name, args);\n\t\tif (!instance) {\n\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noCreate\", {\n\t\t\t\ttypeName: this._typeName,\n\t\t\t\tname,\n\t\t\t\targs: Is.undefined(args) ? \"\" : JSON.stringify(args)\n\t\t\t});\n\t\t}\n\t\treturn instance as U;\n\t}\n\n\t/**\n\t * Create a new instance without caching it if it exists.\n\t * @param name The name of the instance to generate.\n\t * @param args The arguments to pass to the generator.\n\t * @returns A new instance of the item if it exists.\n\t * @throws GuardError if the parameters are invalid.\n\t */\n\tpublic createIfExists<U extends T>(name: string, args?: unknown): U | undefined {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\tconst matchName = this._matcher(Object.keys(this._generators), name);\n\n\t\tif (Is.stringValue(matchName) && this._generators[matchName]) {\n\t\t\tconst instance = this._generators[matchName].generator(args);\n\n\t\t\tif (!Is.empty(instance)) {\n\t\t\t\treturn this.applyFacades(instance) as U;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove all the instances and leave the generators intact.\n\t */\n\tpublic reset(): void {\n\t\tfor (const name in this._generators) {\n\t\t\tthis.removeInstance(name);\n\t\t}\n\t\tthis._instances = {};\n\t\tthis._wrappedInstances = {};\n\t}\n\n\t/**\n\t * Remove all the instances and the generators.\n\t */\n\tpublic clear(): void {\n\t\tthis._instances = {};\n\t\tthis._wrappedInstances = {};\n\t\tthis._facades = [];\n\t\tthis._generators = {};\n\t\tthis._orderCounter = 0;\n\t}\n\n\t/**\n\t * Activate a facade for this factory, so every instance it produces is wrapped by it.\n\t * An instance is passed through the facades in the order they were activated, so the facade\n\t * activated first is the outermost. Activating a facade which is already active does nothing.\n\t * @param name The name of the facade, as registered with the facade factory.\n\t * @throws GuardError if the parameters are invalid.\n\t * @throws GeneralError if no facade is registered with the name, or the factory is the facade\n\t * factory itself.\n\t */\n\tpublic useFacade(name: string): void {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\n\t\tconst facadeFactory = this.facadeFactory();\n\n\t\t// Wrapping the facades themselves would mean resolving a facade in order to apply it.\n\t\tif (this._typeName === facadeFactory.typeName()) {\n\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noFacadeOnFacades\");\n\t\t}\n\n\t\tif (!facadeFactory.hasName(name)) {\n\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noFacade\", {\n\t\t\t\ttypeName: this._typeName,\n\t\t\t\tname\n\t\t\t});\n\t\t}\n\n\t\tif (!this._facades.some(f => f.name === name)) {\n\t\t\tthis._facades.push({ name, facade: facadeFactory.get(name) });\n\t\t\t// Instances handed out before this point keep the facades they were built with, the\n\t\t\t// change applies to instances produced from here on.\n\t\t\tthis._wrappedInstances = {};\n\t\t}\n\t}\n\n\t/**\n\t * Deactivate a facade for this factory. Deactivating a facade which is not active does nothing.\n\t * @param name The name of the facade to deactivate.\n\t * @throws GuardError if the parameters are invalid.\n\t */\n\tpublic unuseFacade(name: string): void {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\n\t\tconst index = this._facades.findIndex(f => f.name === name);\n\t\tif (index >= 0) {\n\t\t\tthis._facades.splice(index, 1);\n\t\t\tthis._wrappedInstances = {};\n\t\t}\n\t}\n\n\t/**\n\t * Get all the instances as a map.\n\t * @param withFacade Return the instances with the active facades applied, defaults to false.\n\t * @returns The instances as a map.\n\t */\n\tpublic instancesMap(withFacade?: boolean): { [name: string]: T } {\n\t\tif (!withFacade) {\n\t\t\treturn this._instances;\n\t\t}\n\n\t\tconst instances: { [name: string]: T } = {};\n\t\tfor (const instanceName in this._instances) {\n\t\t\tinstances[instanceName] = this.wrappedInstance(instanceName);\n\t\t}\n\t\treturn instances;\n\t}\n\n\t/**\n\t * Get all the instances as a list in the order they were registered.\n\t * @param withFacade Return the instances with the active facades applied, defaults to false.\n\t * @returns The instances as a list in the order they were registered.\n\t */\n\tpublic instancesList(withFacade?: boolean): T[] {\n\t\tconst orderedInstances: { instance: T; order: number }[] = [];\n\t\tfor (const instanceName in this._instances) {\n\t\t\torderedInstances.push({\n\t\t\t\tinstance: withFacade ? this.wrappedInstance(instanceName) : this._instances[instanceName],\n\t\t\t\torder: this._generators[instanceName].order\n\t\t\t});\n\t\t}\n\t\treturn orderedInstances.sort((a, b) => a.order - b.order).map(o => o.instance);\n\t}\n\n\t/**\n\t * Get all the generator names in the order they were registered.\n\t * @returns The ordered generator names.\n\t */\n\tpublic names(): string[] {\n\t\tconst orderedNames: { name: string; order: number }[] = [];\n\t\tfor (const generator in this._generators) {\n\t\t\torderedNames.push({\n\t\t\t\tname: generator,\n\t\t\t\torder: this._generators[generator].order\n\t\t\t});\n\t\t}\n\t\treturn orderedNames.sort((a, b) => a.order - b.order).map(o => o.name);\n\t}\n\n\t/**\n\t * Does the factory contain the name.\n\t * @param name The name of the instance to find.\n\t * @returns True if the factory has a matching name.\n\t */\n\tpublic hasName(name: string): boolean {\n\t\tGuards.stringValue(Factory.CLASS_NAME, nameof(name), name);\n\t\treturn Is.stringValue(this._matcher(Object.keys(this._generators), name));\n\t}\n\n\t/**\n\t * Remove any instances of the given name.\n\t * @param name The name of the instances to remove.\n\t * @internal\n\t */\n\tprivate removeInstance(name: string): void {\n\t\tdelete this._instances[name];\n\t\tdelete this._wrappedInstances[name];\n\t}\n\n\t/**\n\t * Get the factory the facades are resolved from, resolving it on first use.\n\t * @returns The facade factory.\n\t * @internal\n\t */\n\tprivate facadeFactory(): Factory<IFacade> {\n\t\tthis._facadeFactory ??= Factory.createFactory<IFacade>(\"facade\");\n\n\t\treturn this._facadeFactory;\n\t}\n\n\t/**\n\t * Get an instance with the active facades applied, wrapping it on first use.\n\t * @param name The name of the instance, which must already have been created.\n\t * @returns The wrapped instance.\n\t * @throws GeneralError if a facade does not return a wrapped instance.\n\t * @internal\n\t */\n\tprivate wrappedInstance(name: string): T {\n\t\tthis._wrappedInstances[name] ??= this.applyFacades(this._instances[name]);\n\n\t\treturn this._wrappedInstances[name];\n\t}\n\n\t/**\n\t * Wrap an instance in the active facades. The first activated facade ends up outermost.\n\t * @param instance The instance to wrap.\n\t * @returns The wrapped instance, or the instance itself when no facades are active.\n\t * @throws GeneralError if a facade does not return a wrapped instance.\n\t * @internal\n\t */\n\tprivate applyFacades(instance: T): T {\n\t\tlet wrapped = instance;\n\n\t\tfor (let i = this._facades.length - 1; i >= 0; i--) {\n\t\t\twrapped = this._facades[i].facade.wrap(wrapped) as T;\n\n\t\t\tif (Is.empty(wrapped)) {\n\t\t\t\tthrow new GeneralError(Factory.CLASS_NAME, \"noFacadeWrap\", {\n\t\t\t\t\ttypeName: this._typeName,\n\t\t\t\t\tname: this._facades[i].name\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn wrapped;\n\t}\n\n\t/**\n\t * Match the requested name to the generator name.\n\t * @param names The list of names for all the generators.\n\t * @param name The name to match.\n\t * @returns The matched name or undefined if no match.\n\t * @internal\n\t */\n\tprivate defaultMatcher(names: string[], name: string): string | undefined {\n\t\treturn this._generators[name] ? name : undefined;\n\t}\n}\n"]}
package/dist/es/index.js CHANGED
@@ -16,6 +16,7 @@ export * from "./errors/unauthorizedError.js";
16
16
  export * from "./errors/unprocessableError.js";
17
17
  export * from "./errors/validationError.js";
18
18
  export * from "./factories/componentFactory.js";
19
+ export * from "./factories/facadeFactory.js";
19
20
  export * from "./factories/factory.js";
20
21
  export * from "./helpers/arrayHelper.js";
21
22
  export * from "./helpers/envHelper.js";
@@ -32,6 +33,7 @@ export * from "./models/coerceType.js";
32
33
  export * from "./models/IDuration.js";
33
34
  export * from "./models/compressionType.js";
34
35
  export * from "./models/IComponent.js";
36
+ export * from "./models/IFacade.js";
35
37
  export * from "./models/IError.js";
36
38
  export * from "./models/II18nShared.js";
37
39
  export * from "./models/IKeyValue.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./encoding/base32.js\";\nexport * from \"./encoding/base58.js\";\nexport * from \"./encoding/base64.js\";\nexport * from \"./encoding/base64Url.js\";\nexport * from \"./errors/alreadyExistsError.js\";\nexport * from \"./errors/baseError.js\";\nexport * from \"./errors/conflictError.js\";\nexport * from \"./errors/generalError.js\";\nexport * from \"./errors/guardError.js\";\nexport * from \"./errors/notFoundError.js\";\nexport * from \"./errors/notImplementedError.js\";\nexport * from \"./errors/notSupportedError.js\";\nexport * from \"./errors/unauthorizedError.js\";\nexport * from \"./errors/unprocessableError.js\";\nexport * from \"./errors/validationError.js\";\nexport * from \"./factories/componentFactory.js\";\nexport * from \"./factories/factory.js\";\nexport * from \"./helpers/arrayHelper.js\";\nexport * from \"./helpers/envHelper.js\";\nexport * from \"./helpers/errorHelper.js\";\nexport * from \"./helpers/filenameHelper.js\";\nexport * from \"./helpers/hexHelper.js\";\nexport * from \"./helpers/jsonHelper.js\";\nexport * from \"./helpers/numberHelper.js\";\nexport * from \"./helpers/objectHelper.js\";\nexport * from \"./helpers/randomHelper.js\";\nexport * from \"./helpers/stringHelper.js\";\nexport * from \"./helpers/uint8ArrayHelper.js\";\nexport * from \"./models/coerceType.js\";\nexport * from \"./models/IDuration.js\";\nexport * from \"./models/compressionType.js\";\nexport * from \"./models/IComponent.js\";\nexport * from \"./models/IError.js\";\nexport * from \"./models/II18nShared.js\";\nexport * from \"./models/IKeyValue.js\";\nexport * from \"./models/ILabelledValue.js\";\nexport * from \"./models/ILocale.js\";\nexport * from \"./models/ILocaleDictionary.js\";\nexport * from \"./models/ILocalesIndex.js\";\nexport * from \"./models/IMutexWorkerMessage.js\";\nexport * from \"./models/IPatchOperation.js\";\nexport * from \"./models/ISharedObjectBufferOptions.js\";\nexport * from \"./models/ISharedObjectBufferWorkerMessage.js\";\nexport * from \"./models/IUrlParts.js\";\nexport * from \"./models/IValidationFailure.js\";\nexport * from \"./models/mutexMessageTypes.js\";\nexport * from \"./models/sharedObjectBufferMessageTypes.js\";\nexport * from \"./types/bitString.js\";\nexport * from \"./types/duration.js\";\nexport * from \"./types/durationRegExp.js\";\nexport * from \"./types/objectOrArray.js\";\nexport * from \"./types/singleOccurrenceArray.js\";\nexport * from \"./types/singleOccurrenceArrayDepthHelper.js\";\nexport * from \"./types/url.js\";\nexport * from \"./types/urn.js\";\nexport * from \"./utils/asyncCache.js\";\nexport * from \"./utils/lfuCache.js\";\nexport * from \"./utils/lruCache.js\";\nexport * from \"./utils/coerce.js\";\nexport * from \"./utils/compression.js\";\nexport * from \"./utils/converter.js\";\nexport * from \"./utils/guards.js\";\nexport * from \"./utils/i18n.js\";\nexport * from \"./utils/is.js\";\nexport * from \"./utils/mutex.js\";\nexport * from \"./utils/sharedObjectBuffer.js\";\nexport * from \"./utils/sharedStore.js\";\nexport * from \"./utils/validation.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./encoding/base32.js\";\nexport * from \"./encoding/base58.js\";\nexport * from \"./encoding/base64.js\";\nexport * from \"./encoding/base64Url.js\";\nexport * from \"./errors/alreadyExistsError.js\";\nexport * from \"./errors/baseError.js\";\nexport * from \"./errors/conflictError.js\";\nexport * from \"./errors/generalError.js\";\nexport * from \"./errors/guardError.js\";\nexport * from \"./errors/notFoundError.js\";\nexport * from \"./errors/notImplementedError.js\";\nexport * from \"./errors/notSupportedError.js\";\nexport * from \"./errors/unauthorizedError.js\";\nexport * from \"./errors/unprocessableError.js\";\nexport * from \"./errors/validationError.js\";\nexport * from \"./factories/componentFactory.js\";\nexport * from \"./factories/facadeFactory.js\";\nexport * from \"./factories/factory.js\";\nexport * from \"./helpers/arrayHelper.js\";\nexport * from \"./helpers/envHelper.js\";\nexport * from \"./helpers/errorHelper.js\";\nexport * from \"./helpers/filenameHelper.js\";\nexport * from \"./helpers/hexHelper.js\";\nexport * from \"./helpers/jsonHelper.js\";\nexport * from \"./helpers/numberHelper.js\";\nexport * from \"./helpers/objectHelper.js\";\nexport * from \"./helpers/randomHelper.js\";\nexport * from \"./helpers/stringHelper.js\";\nexport * from \"./helpers/uint8ArrayHelper.js\";\nexport * from \"./models/coerceType.js\";\nexport * from \"./models/IDuration.js\";\nexport * from \"./models/compressionType.js\";\nexport * from \"./models/IComponent.js\";\nexport * from \"./models/IFacade.js\";\nexport * from \"./models/IError.js\";\nexport * from \"./models/II18nShared.js\";\nexport * from \"./models/IKeyValue.js\";\nexport * from \"./models/ILabelledValue.js\";\nexport * from \"./models/ILocale.js\";\nexport * from \"./models/ILocaleDictionary.js\";\nexport * from \"./models/ILocalesIndex.js\";\nexport * from \"./models/IMutexWorkerMessage.js\";\nexport * from \"./models/IPatchOperation.js\";\nexport * from \"./models/ISharedObjectBufferOptions.js\";\nexport * from \"./models/ISharedObjectBufferWorkerMessage.js\";\nexport * from \"./models/IUrlParts.js\";\nexport * from \"./models/IValidationFailure.js\";\nexport * from \"./models/mutexMessageTypes.js\";\nexport * from \"./models/sharedObjectBufferMessageTypes.js\";\nexport * from \"./types/bitString.js\";\nexport * from \"./types/duration.js\";\nexport * from \"./types/durationRegExp.js\";\nexport * from \"./types/objectOrArray.js\";\nexport * from \"./types/singleOccurrenceArray.js\";\nexport * from \"./types/singleOccurrenceArrayDepthHelper.js\";\nexport * from \"./types/url.js\";\nexport * from \"./types/urn.js\";\nexport * from \"./utils/asyncCache.js\";\nexport * from \"./utils/lfuCache.js\";\nexport * from \"./utils/lruCache.js\";\nexport * from \"./utils/coerce.js\";\nexport * from \"./utils/compression.js\";\nexport * from \"./utils/converter.js\";\nexport * from \"./utils/guards.js\";\nexport * from \"./utils/i18n.js\";\nexport * from \"./utils/is.js\";\nexport * from \"./utils/mutex.js\";\nexport * from \"./utils/sharedObjectBuffer.js\";\nexport * from \"./utils/sharedStore.js\";\nexport * from \"./utils/validation.js\";\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2026 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=IFacade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IFacade.js","sourceRoot":"","sources":["../../../src/models/IFacade.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * A facade wraps a component so a cross cutting concern can be applied to it without the\n * component being modified. The wrapped component is returned in place of the original.\n */\nexport interface IFacade<T = unknown> {\n\t/**\n\t * Wrap the target, returning a replacement.\n\t * @param target The component to wrap.\n\t * @returns The wrapped component.\n\t */\n\twrap(target: T): T;\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import { Factory } from "./factory.js";
2
+ import type { IFacade } from "../models/IFacade.js";
3
+ /**
4
+ * Factory for creating implementation of facade types.
5
+ */
6
+ export declare const FacadeFactory: Factory<IFacade<unknown>>;
@@ -92,18 +92,36 @@ export declare class Factory<T> {
92
92
  * Remove all the instances and the generators.
93
93
  */
94
94
  clear(): void;
95
+ /**
96
+ * Activate a facade for this factory, so every instance it produces is wrapped by it.
97
+ * An instance is passed through the facades in the order they were activated, so the facade
98
+ * activated first is the outermost. Activating a facade which is already active does nothing.
99
+ * @param name The name of the facade, as registered with the facade factory.
100
+ * @throws GuardError if the parameters are invalid.
101
+ * @throws GeneralError if no facade is registered with the name, or the factory is the facade
102
+ * factory itself.
103
+ */
104
+ useFacade(name: string): void;
105
+ /**
106
+ * Deactivate a facade for this factory. Deactivating a facade which is not active does nothing.
107
+ * @param name The name of the facade to deactivate.
108
+ * @throws GuardError if the parameters are invalid.
109
+ */
110
+ unuseFacade(name: string): void;
95
111
  /**
96
112
  * Get all the instances as a map.
113
+ * @param withFacade Return the instances with the active facades applied, defaults to false.
97
114
  * @returns The instances as a map.
98
115
  */
99
- instancesMap(): {
116
+ instancesMap(withFacade?: boolean): {
100
117
  [name: string]: T;
101
118
  };
102
119
  /**
103
120
  * Get all the instances as a list in the order they were registered.
121
+ * @param withFacade Return the instances with the active facades applied, defaults to false.
104
122
  * @returns The instances as a list in the order they were registered.
105
123
  */
106
- instancesList(): T[];
124
+ instancesList(withFacade?: boolean): T[];
107
125
  /**
108
126
  * Get all the generator names in the order they were registered.
109
127
  * @returns The ordered generator names.
@@ -14,6 +14,7 @@ export * from "./errors/unauthorizedError.js";
14
14
  export * from "./errors/unprocessableError.js";
15
15
  export * from "./errors/validationError.js";
16
16
  export * from "./factories/componentFactory.js";
17
+ export * from "./factories/facadeFactory.js";
17
18
  export * from "./factories/factory.js";
18
19
  export * from "./helpers/arrayHelper.js";
19
20
  export * from "./helpers/envHelper.js";
@@ -30,6 +31,7 @@ export * from "./models/coerceType.js";
30
31
  export * from "./models/IDuration.js";
31
32
  export * from "./models/compressionType.js";
32
33
  export * from "./models/IComponent.js";
34
+ export * from "./models/IFacade.js";
33
35
  export * from "./models/IError.js";
34
36
  export * from "./models/II18nShared.js";
35
37
  export * from "./models/IKeyValue.js";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * A facade wraps a component so a cross cutting concern can be applied to it without the
3
+ * component being modified. The wrapped component is returned in place of the original.
4
+ */
5
+ export interface IFacade<T = unknown> {
6
+ /**
7
+ * Wrap the target, returning a replacement.
8
+ * @param target The component to wrap.
9
+ * @returns The wrapped component.
10
+ */
11
+ wrap(target: T): T;
12
+ }
package/docs/changelog.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.3-next.3](https://github.com/iotaledger/twin-framework/compare/core-v0.9.3-next.2...core-v0.9.3-next.3) (2026-09-02)
4
+
5
+
6
+ ### Features
7
+
8
+ * factory facades ([#470](https://github.com/iotaledger/twin-framework/issues/470)) ([004aade](https://github.com/iotaledger/twin-framework/commit/004aade8340ff640f24dbe2f05330e8f5920d3a9))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/nameof bumped from 0.9.3-next.2 to 0.9.3-next.3
16
+ * devDependencies
17
+ * @twin.org/nameof-transformer bumped from 0.9.3-next.2 to 0.9.3-next.3
18
+ * @twin.org/nameof-vitest-plugin bumped from 0.9.3-next.2 to 0.9.3-next.3
19
+
3
20
  ## [0.9.3-next.2](https://github.com/iotaledger/twin-framework/compare/core-v0.9.3-next.1...core-v0.9.3-next.2) (2026-08-28)
4
21
 
5
22
 
package/docs/examples.md CHANGED
@@ -171,12 +171,49 @@ class SimpleHasher implements IHasher {
171
171
  }
172
172
  }
173
173
 
174
- const factory = new Factory<IHasher>('hashers');
174
+ const factory = Factory.createFactory<IHasher>('hashers');
175
175
  factory.register('simple', () => new SimpleHasher());
176
176
 
177
177
  factory.create('simple').hash('abc'); // 'abc-hash'
178
178
  ```
179
179
 
180
+ ## Factory Facades
181
+
182
+ A facade wraps the components a factory produces, so a cross cutting concern can be applied without modifying them.
183
+
184
+ ```typescript
185
+ import { ComponentFactory, FacadeFactory, Is, type IFacade } from '@twin.org/core';
186
+
187
+ class LoggingFacade implements IFacade {
188
+ public wrap(target: unknown): unknown {
189
+ return new Proxy(target as object, {
190
+ get(t, prop, receiver): unknown {
191
+ const value = Reflect.get(t, prop, receiver);
192
+
193
+ if (!Is.function(value)) {
194
+ return value;
195
+ }
196
+
197
+ return (...args: unknown[]): unknown => {
198
+ globalThis.console.log('calling', String(prop));
199
+ return value.apply(t, args);
200
+ };
201
+ }
202
+ });
203
+ }
204
+ }
205
+
206
+ FacadeFactory.register('logging', () => new LoggingFacade());
207
+
208
+ // Every component the factory produces from here on is wrapped.
209
+ ComponentFactory.useFacade('logging');
210
+
211
+ // No longer wrapped, for instances produced after this call.
212
+ ComponentFactory.unuseFacade('logging');
213
+ ```
214
+
215
+ An instance is passed through the facades in the order they were activated, so the first activated is the outermost.
216
+
180
217
  ## Encoding and Compression
181
218
 
182
219
  ```typescript
@@ -366,12 +366,75 @@ Remove all the instances and the generators.
366
366
 
367
367
  ***
368
368
 
369
+ ### useFacade() {#usefacade}
370
+
371
+ > **useFacade**(`name`): `void`
372
+
373
+ Activate a facade for this factory, so every instance it produces is wrapped by it.
374
+ An instance is passed through the facades in the order they were activated, so the facade
375
+ activated first is the outermost. Activating a facade which is already active does nothing.
376
+
377
+ #### Parameters
378
+
379
+ ##### name
380
+
381
+ `string`
382
+
383
+ The name of the facade, as registered with the facade factory.
384
+
385
+ #### Returns
386
+
387
+ `void`
388
+
389
+ #### Throws
390
+
391
+ GuardError if the parameters are invalid.
392
+
393
+ #### Throws
394
+
395
+ GeneralError if no facade is registered with the name, or the factory is the facade
396
+ factory itself.
397
+
398
+ ***
399
+
400
+ ### unuseFacade() {#unusefacade}
401
+
402
+ > **unuseFacade**(`name`): `void`
403
+
404
+ Deactivate a facade for this factory. Deactivating a facade which is not active does nothing.
405
+
406
+ #### Parameters
407
+
408
+ ##### name
409
+
410
+ `string`
411
+
412
+ The name of the facade to deactivate.
413
+
414
+ #### Returns
415
+
416
+ `void`
417
+
418
+ #### Throws
419
+
420
+ GuardError if the parameters are invalid.
421
+
422
+ ***
423
+
369
424
  ### instancesMap() {#instancesmap}
370
425
 
371
- > **instancesMap**(): `object`
426
+ > **instancesMap**(`withFacade?`): `object`
372
427
 
373
428
  Get all the instances as a map.
374
429
 
430
+ #### Parameters
431
+
432
+ ##### withFacade?
433
+
434
+ `boolean`
435
+
436
+ Return the instances with the active facades applied, defaults to false.
437
+
375
438
  #### Returns
376
439
 
377
440
  `object`
@@ -382,10 +445,18 @@ The instances as a map.
382
445
 
383
446
  ### instancesList() {#instanceslist}
384
447
 
385
- > **instancesList**(): `T`[]
448
+ > **instancesList**(`withFacade?`): `T`[]
386
449
 
387
450
  Get all the instances as a list in the order they were registered.
388
451
 
452
+ #### Parameters
453
+
454
+ ##### withFacade?
455
+
456
+ `boolean`
457
+
458
+ Return the instances with the active facades applied, defaults to false.
459
+
389
460
  #### Returns
390
461
 
391
462
  `T`[]
@@ -52,6 +52,7 @@
52
52
  - [IComponent](interfaces/IComponent.md)
53
53
  - [IDuration](interfaces/IDuration.md)
54
54
  - [IError](interfaces/IError.md)
55
+ - [IFacade](interfaces/IFacade.md)
55
56
  - [II18nShared](interfaces/II18nShared.md)
56
57
  - [IKeyValue](interfaces/IKeyValue.md)
57
58
  - [ILabelledValue](interfaces/ILabelledValue.md)
@@ -78,6 +79,7 @@
78
79
  ## Variables
79
80
 
80
81
  - [ComponentFactory](variables/ComponentFactory.md)
82
+ - [FacadeFactory](variables/FacadeFactory.md)
81
83
  - [CoerceType](variables/CoerceType.md)
82
84
  - [CompressionType](variables/CompressionType.md)
83
85
  - [MutexMessageTypes](variables/MutexMessageTypes.md)
@@ -0,0 +1,32 @@
1
+ # Interface: IFacade\<T\>
2
+
3
+ A facade wraps a component so a cross cutting concern can be applied to it without the
4
+ component being modified. The wrapped component is returned in place of the original.
5
+
6
+ ## Type Parameters
7
+
8
+ ### T
9
+
10
+ `T` = `unknown`
11
+
12
+ ## Methods
13
+
14
+ ### wrap() {#wrap}
15
+
16
+ > **wrap**(`target`): `T`
17
+
18
+ Wrap the target, returning a replacement.
19
+
20
+ #### Parameters
21
+
22
+ ##### target
23
+
24
+ `T`
25
+
26
+ The component to wrap.
27
+
28
+ #### Returns
29
+
30
+ `T`
31
+
32
+ The wrapped component.
@@ -0,0 +1,5 @@
1
+ # Variable: FacadeFactory
2
+
3
+ > `const` **FacadeFactory**: [`Factory`](../classes/Factory.md)\<[`IFacade`](../interfaces/IFacade.md)\<`unknown`\>\>
4
+
5
+ Factory for creating implementation of facade types.
package/locales/en.json CHANGED
@@ -91,7 +91,10 @@
91
91
  "factory": {
92
92
  "noUnregister": "There is no {typeName} registered with the name \"{name}\"",
93
93
  "noGet": "The requested {typeName} \"{name}\" does not exist in the factory",
94
- "noCreate": "The requested {typeName} \"{name}\" cannot be created by the factory, with params \"{params}\""
94
+ "noCreate": "The requested {typeName} \"{name}\" cannot be created by the factory, with params \"{params}\"",
95
+ "noFacade": "The requested facade \"{name}\" is not registered, so it cannot be applied to the {typeName} factory",
96
+ "noFacadeOnFacades": "Facades cannot be applied to the facade factory itself",
97
+ "noFacadeWrap": "The facade \"{name}\" did not return a wrapped instance for the {typeName} factory"
95
98
  },
96
99
  "bitString": {
97
100
  "outOfRange": "The index should be >= 0 and less than the length of the bit string, the index is \"{index}\" and the number of bit is \"{numberBits}\""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/core",
3
- "version": "0.9.3-next.2",
3
+ "version": "0.9.3-next.3",
4
4
  "description": "Helper methods/classes for data type checking/validation/guarding/error handling",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,7 @@
14
14
  "node": ">=24.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/nameof": "0.9.3-next.2",
17
+ "@twin.org/nameof": "0.9.3-next.3",
18
18
  "intl-messageformat": "11.2.13",
19
19
  "rfc6902": "5.3.0"
20
20
  },