@twin.org/engine-core 0.9.1-next.5 → 0.9.1-next.7

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.
@@ -2,10 +2,11 @@
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  import { isMainThread } from "node:worker_threads";
4
4
  import { ContextIdHandlerFactory, ContextIdStore } from "@twin.org/context";
5
- import { BaseError, ComponentFactory, ErrorHelper, GeneralError, Guards, I18n, Is } from "@twin.org/core";
5
+ import { BaseError, ComponentFactory, ErrorHelper, GeneralError, Guards, I18n, Is, ObjectHelper } from "@twin.org/core";
6
+ import { EngineLogLevel } from "@twin.org/engine-models";
6
7
  import { EntitySchemaFactory } from "@twin.org/entity";
7
8
  import { ConsoleLoggingConnector } from "@twin.org/logging-connector-console";
8
- import { LoggingConnectorFactory, SilentLoggingConnector } from "@twin.org/logging-models";
9
+ import { LoggingConnectorFactory, LogLevel, SilentLoggingConnector } from "@twin.org/logging-models";
9
10
  import { LoggingService } from "@twin.org/logging-service";
10
11
  import { ModuleHelper } from "@twin.org/modules";
11
12
  import { MemoryStateStorage } from "./storage/memoryStateStorage.js";
@@ -195,6 +196,8 @@ export class EngineCore {
195
196
  this._isStarted = true;
196
197
  if (!skipComponent) {
197
198
  await this.logInfo(I18n.formatMessage(`${"engineCore"}.componentsStarting`));
199
+ const componentTimings = [];
200
+ const componentsStartTime = performance.now();
198
201
  await ContextIdStore.run(this._contextIds ?? {}, async () => {
199
202
  for (const instance of this._context.componentInstances) {
200
203
  if (!instance.initialised) {
@@ -205,6 +208,7 @@ export class EngineCore {
205
208
  className: instance.component.className(),
206
209
  instanceType: instance.instanceType
207
210
  }));
211
+ const componentStartTime = performance.now();
208
212
  try {
209
213
  await startMethod(EngineCore.LOGGING_COMPONENT_TYPE_NAME);
210
214
  }
@@ -215,10 +219,33 @@ export class EngineCore {
215
219
  }, BaseError.fromError(err)));
216
220
  throw err;
217
221
  }
222
+ const elapsedMs = Math.round(performance.now() - componentStartTime);
223
+ componentTimings.push({
224
+ className: instance.component.className(),
225
+ instanceType: instance.instanceType,
226
+ elapsedMs
227
+ });
228
+ await this.logDebug(I18n.formatMessage(`${"engineCore"}.componentStarted`, {
229
+ className: instance.component.className(),
230
+ instanceType: instance.instanceType,
231
+ elapsedMs
232
+ }));
218
233
  }
219
234
  }
220
235
  }
221
236
  });
237
+ if (componentTimings.length > 0) {
238
+ const totalMs = Math.round(performance.now() - componentsStartTime);
239
+ const slowestComponents = componentTimings
240
+ .sort((a, b) => b.elapsedMs - a.elapsedMs)
241
+ .slice(0, 3)
242
+ .map(t => `${t.className} (${t.instanceType}) ${t.elapsedMs}ms`)
243
+ .join(", ");
244
+ await this.logDebug(I18n.formatMessage(`${"engineCore"}.componentsSummary`, {
245
+ totalMs,
246
+ slowestComponents
247
+ }));
248
+ }
222
249
  await this.logInfo(I18n.formatMessage(`${"engineCore"}.componentsComplete`));
223
250
  }
224
251
  else {
@@ -444,8 +471,19 @@ export class EngineCore {
444
471
  for (const schemaName of entitySchemaNames) {
445
472
  entitySchemas[schemaName] = EntitySchemaFactory.get(schemaName);
446
473
  }
474
+ const sourceConfig = this._context.config;
475
+ const cloneTypes = {};
476
+ for (const typeKey of Object.keys(sourceConfig.types ?? {})) {
477
+ const entries = sourceConfig.types?.[typeKey];
478
+ if (Is.arrayValue(entries)) {
479
+ const cloneableEntries = entries.filter(e => e.isCloneable !== false);
480
+ if (cloneableEntries.length > 0) {
481
+ cloneTypes[typeKey] = cloneableEntries;
482
+ }
483
+ }
484
+ }
447
485
  const cloneData = {
448
- config: this._context.config,
486
+ config: { ...sourceConfig, types: cloneTypes },
449
487
  state: this._context.state,
450
488
  typeInitialisers: this._typeInitialisers,
451
489
  entitySchemas,
@@ -457,30 +495,84 @@ export class EngineCore {
457
495
  * Populate the engine from the clone data.
458
496
  * @param cloneData The clone data to populate from.
459
497
  * @param contextIds The context IDs to use for the clone.
460
- * @param silent Should the clone be silent.
498
+ * @param options An optional object containing the log level, types and entity types to include.
499
+ * @param options.logLevel The log level for the clone, true maps to error level.
500
+ * @param options.types An optional allowlist of type keys to include; when omitted all types are cloned.
501
+ * @param options.entityTypes An optional allowlist of entity type names; when provided only those entity schemas and their associated storage components are cloned.
461
502
  */
462
- populateClone(cloneData, contextIds, silent) {
503
+ populateClone(cloneData, contextIds, options) {
463
504
  Guards.object(EngineCore.CLASS_NAME, "cloneData", cloneData);
464
505
  Guards.object(EngineCore.CLASS_NAME, "cloneData.config", cloneData.config);
465
506
  Guards.object(EngineCore.CLASS_NAME, "cloneData.state", cloneData.state);
466
507
  Guards.array(EngineCore.CLASS_NAME, "cloneData.typeInitialisers", cloneData.typeInitialisers);
467
508
  this._skipBootstrap = true;
468
509
  this._isClone = true;
469
- if (silent ?? false) {
470
- cloneData.config.silent = true;
510
+ let optionsEntityTypes;
511
+ let optionsTypes;
512
+ if (Is.object(options)) {
513
+ if (!Is.empty(options.logLevel)) {
514
+ const logLevel = options.logLevel;
515
+ Guards.arrayOneOf(EngineCore.CLASS_NAME, "logLevel", logLevel, Object.values(EngineLogLevel));
516
+ cloneData.config.logLevel = logLevel;
517
+ }
518
+ optionsEntityTypes = options.entityTypes;
519
+ optionsTypes = options.types;
520
+ }
521
+ else if (options === true) {
522
+ cloneData.config.logLevel = EngineLogLevel.Error;
523
+ }
524
+ let cloneEntitySchemas = cloneData.entitySchemas;
525
+ const safeTypes = {};
526
+ for (const typeKey of Object.keys(cloneData.config.types ?? {})) {
527
+ const entries = cloneData.config.types?.[typeKey];
528
+ if (Is.arrayValue(entries)) {
529
+ const cloneableEntries = entries.filter(e => e.isCloneable !== false);
530
+ if (cloneableEntries.length > 0) {
531
+ safeTypes[typeKey] = cloneableEntries;
532
+ }
533
+ }
534
+ }
535
+ let cloneConfig = { ...cloneData.config, types: safeTypes };
536
+ if (Is.arrayValue(optionsEntityTypes)) {
537
+ const filteredSchemas = {};
538
+ for (const schemaName of Object.keys(cloneData.entitySchemas)) {
539
+ if (optionsEntityTypes.includes(schemaName)) {
540
+ filteredSchemas[schemaName] = cloneData.entitySchemas[schemaName];
541
+ }
542
+ }
543
+ cloneEntitySchemas = filteredSchemas;
544
+ const filteredTypes = {};
545
+ for (const typeKey of Object.keys(safeTypes)) {
546
+ const entries = safeTypes[typeKey];
547
+ if (Is.arrayValue(entries)) {
548
+ const kept = entries.filter(e => {
549
+ const storageType = ObjectHelper.propertyGet(e.options, "entityStorageType");
550
+ if (Is.stringValue(storageType)) {
551
+ return optionsEntityTypes.includes(storageType);
552
+ }
553
+ return true;
554
+ });
555
+ if (kept.length > 0) {
556
+ filteredTypes[typeKey] = kept;
557
+ }
558
+ }
559
+ }
560
+ cloneConfig = { ...cloneData.config, types: filteredTypes };
471
561
  }
472
562
  this._context = {
473
- config: cloneData.config,
563
+ config: cloneConfig,
474
564
  registeredInstances: {},
475
565
  componentInstances: [],
476
566
  state: {},
477
567
  stateDirty: false
478
568
  };
479
- this._typeInitialisers = cloneData.typeInitialisers;
569
+ this._typeInitialisers = Is.arrayValue(optionsTypes)
570
+ ? cloneData.typeInitialisers.filter(t => optionsTypes.includes(t.type))
571
+ : cloneData.typeInitialisers;
480
572
  this._contextIdKeys.push(...cloneData.contextIdKeys);
481
573
  this._contextIds = contextIds;
482
- for (const schemaName of Object.keys(cloneData.entitySchemas)) {
483
- EntitySchemaFactory.register(schemaName, () => cloneData.entitySchemas[schemaName]);
574
+ for (const schemaName of Object.keys(cloneEntitySchemas)) {
575
+ EntitySchemaFactory.register(schemaName, () => cloneEntitySchemas[schemaName]);
484
576
  }
485
577
  this._stateStorage = new MemoryStateStorage(true, cloneData.state);
486
578
  this._isStarted = false;
@@ -549,15 +641,28 @@ export class EngineCore {
549
641
  * @internal
550
642
  */
551
643
  setupEngineLogger() {
552
- const silent = this._context.config.silent ?? false;
553
- const engineLoggerConnector = silent
554
- ? new SilentLoggingConnector()
555
- : new ConsoleLoggingConnector({
644
+ const logLevel = this._context.config.logLevel ??
645
+ ((this._context.config.silent ?? false) ? EngineLogLevel.None : EngineLogLevel.All);
646
+ let engineLoggerConnector;
647
+ if (logLevel === EngineLogLevel.None) {
648
+ engineLoggerConnector = new SilentLoggingConnector();
649
+ }
650
+ else {
651
+ let levels;
652
+ if (logLevel === EngineLogLevel.Error) {
653
+ levels = [LogLevel.Error];
654
+ }
655
+ else if (logLevel === EngineLogLevel.Warn) {
656
+ levels = [LogLevel.Error, LogLevel.Warn];
657
+ }
658
+ engineLoggerConnector = new ConsoleLoggingConnector({
556
659
  config: {
557
660
  translateMessages: true,
558
- hideGroups: true
661
+ hideGroups: true,
662
+ levels
559
663
  }
560
664
  });
665
+ }
561
666
  this._context.componentInstances.push({
562
667
  instanceType: EngineCore.LOGGING_CONNECTOR_TYPE_NAME,
563
668
  component: engineLoggerConnector,
@@ -580,6 +685,21 @@ export class EngineCore {
580
685
  }
581
686
  ];
582
687
  }
688
+ /**
689
+ * Log debug.
690
+ * @param message The message to log.
691
+ * @returns A promise that resolves when the message has been logged.
692
+ * @internal
693
+ */
694
+ async logDebug(message) {
695
+ if (!this._context.config.silentLoggers?.includes(EngineCore.CLASS_NAME)) {
696
+ await this._engineLoggingComponent?.log({
697
+ source: EngineCore.CLASS_NAME,
698
+ level: "debug",
699
+ message
700
+ });
701
+ }
702
+ }
583
703
  /**
584
704
  * Load the state.
585
705
  * @returns A promise that resolves when the state has been loaded.
@@ -1 +1 @@
1
- {"version":3,"file":"engineCore.js","sourceRoot":"","sources":["../../src/engineCore.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { isMainThread } from \"node:worker_threads\";\nimport {\n\tContextIdHandlerFactory,\n\tContextIdStore,\n\ttype IContextIdHandler,\n\ttype IContextIds\n} from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tComponentFactory,\n\tErrorHelper,\n\tGeneralError,\n\tGuards,\n\tI18n,\n\ttype IComponent,\n\ttype IError,\n\tIs\n} from \"@twin.org/core\";\nimport type {\n\tEngineTypeInitialiser,\n\tIEngineCore,\n\tIEngineCoreClone,\n\tIEngineCoreConfig,\n\tIEngineCoreContext,\n\tIEngineCoreTypeConfig,\n\tIEngineState,\n\tIEngineStateStorage\n} from \"@twin.org/engine-models\";\nimport { EntitySchemaFactory, type IEntitySchema } from \"@twin.org/entity\";\nimport { ConsoleLoggingConnector } from \"@twin.org/logging-connector-console\";\nimport {\n\ttype ILoggingComponent,\n\tLoggingConnectorFactory,\n\tSilentLoggingConnector\n} from \"@twin.org/logging-models\";\nimport { LoggingService } from \"@twin.org/logging-service\";\nimport { ModuleHelper } from \"@twin.org/modules\";\nimport { nameof, nameofCamelCase } from \"@twin.org/nameof\";\nimport type { IEngineCoreOptions } from \"./models/IEngineCoreOptions.js\";\nimport { MemoryStateStorage } from \"./storage/memoryStateStorage.js\";\n\n/**\n * Core for the engine.\n */\nexport class EngineCore<\n\tC extends IEngineCoreConfig = IEngineCoreConfig,\n\tS extends IEngineState = IEngineState\n> implements IEngineCore<C, S> {\n\t/**\n\t * Name for the engine logger component, used for direct console logging.\n\t */\n\tpublic static readonly LOGGING_COMPONENT_TYPE_NAME: string = \"engine-logging-service\";\n\n\t/**\n\t * Name for the engine logger connector, used for direct console logging.\n\t */\n\tpublic static readonly LOGGING_CONNECTOR_TYPE_NAME: string = \"engine-logging-connector\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<EngineCore>();\n\n\t/**\n\t * The core context.\n\t */\n\tprotected _context: IEngineCoreContext<C, S>;\n\n\t/**\n\t * The context ID keys.\n\t */\n\tprotected readonly _contextIdKeys: { key: string; componentFeatures: string[] }[];\n\n\t/**\n\t * The context IDs.\n\t */\n\tprotected _contextIds?: IContextIds;\n\n\t/**\n\t * The state storage interface.\n\t * @internal\n\t */\n\tprivate _stateStorage?: IEngineStateStorage<S>;\n\n\t/**\n\t * The logging component for the engine.\n\t * @internal\n\t */\n\tprivate _engineLoggingComponent?: ILoggingComponent;\n\n\t/**\n\t * Skip the bootstrap process.\n\t * @internal\n\t */\n\tprivate _skipBootstrap?: boolean;\n\n\t/**\n\t * The type initialisers.\n\t * @internal\n\t */\n\tprivate _typeInitialisers: {\n\t\ttype: string;\n\t\tmodule: string;\n\t\tmethod: string;\n\t}[];\n\n\t/**\n\t * Is the engine started.\n\t * @internal\n\t */\n\tprivate _isStarted: boolean;\n\n\t/**\n\t * Is the engine a clone.\n\t * @internal\n\t */\n\tprivate _isClone: boolean;\n\n\t/**\n\t * Add type initialisers to the engine.\n\t * @internal\n\t */\n\tprivate readonly _populateTypeInitialisers?: (\n\t\tengineCore: IEngineCore<C, S>,\n\t\tcontext: IEngineCoreContext<C, S>\n\t) => void;\n\n\t/**\n\t * Method for bootstrapping any data for the engine.\n\t * @internal\n\t */\n\tprivate readonly _customBootstrap?: (\n\t\tengineCore: IEngineCore<C, S>,\n\t\tcontext: IEngineCoreContext<C, S>\n\t) => Promise<void>;\n\n\t/**\n\t * Create a new instance of EngineCore.\n\t * @param options The options for the engine.\n\t */\n\tconstructor(options?: IEngineCoreOptions<C, S>) {\n\t\toptions = options ?? {};\n\t\toptions.config = options.config ?? ({} as C);\n\t\toptions.config.debug = options.config.debug ?? false;\n\t\toptions.config.silent = options.config.silent ?? false;\n\t\toptions.config.types ??= {};\n\n\t\tthis._skipBootstrap = options.skipBootstrap ?? false;\n\t\tthis._populateTypeInitialisers = options.populateTypeInitialisers;\n\t\tthis._customBootstrap = options.customBootstrap;\n\t\tthis._typeInitialisers = [];\n\t\tthis._contextIdKeys = [];\n\n\t\tthis._context = {\n\t\t\tconfig: options.config,\n\t\t\tregisteredInstances: {},\n\t\t\tcomponentInstances: [],\n\t\t\tstate: {} as S,\n\t\t\tstateDirty: false\n\t\t};\n\t\tthis._stateStorage = options.stateStorage;\n\t\tthis._isStarted = false;\n\t\tthis._isClone = false;\n\n\t\tif (Is.function(this._populateTypeInitialisers)) {\n\t\t\tthis._populateTypeInitialisers(this, this._context);\n\t\t}\n\t}\n\n\t/**\n\t * Add a type initialiser.\n\t * @param type The type to add the initialiser for.\n\t * @param module The name of the module which contains the initialiser method.\n\t * @param method The name of the method to call.\n\t */\n\tpublic addTypeInitialiser(type: string, module: string, method: string): void {\n\t\tGuards.stringValue(EngineCore.CLASS_NAME, nameof(type), type);\n\t\tGuards.stringValue(EngineCore.CLASS_NAME, nameof(module), module);\n\t\tGuards.stringValue(EngineCore.CLASS_NAME, nameof(method), method);\n\n\t\tconst currentIndex = this._typeInitialisers.findIndex(t => t.type === type);\n\t\tif (currentIndex >= 0) {\n\t\t\tthis._typeInitialisers[currentIndex].module = module;\n\t\t\tthis._typeInitialisers[currentIndex].method = method;\n\t\t} else {\n\t\t\tthis._typeInitialisers.push({\n\t\t\t\ttype,\n\t\t\t\tmodule,\n\t\t\t\tmethod\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Get the type config for a specific type.\n\t * @param type The type to get the config for.\n\t * @returns The type config or undefined if not found.\n\t */\n\tpublic getTypeConfig(type: string): IEngineCoreTypeConfig[] | undefined {\n\t\tGuards.stringValue(EngineCore.CLASS_NAME, nameof(type), type);\n\t\treturn this._context.config.types?.[type];\n\t}\n\n\t/**\n\t * Add a context ID key to the engine.\n\t * @param key The context ID key.\n\t * @param componentFeatures The component features for the context ID handler.\n\t */\n\tpublic addContextIdKey(key: string, componentFeatures: string[]): void {\n\t\tconst exists = this._contextIdKeys.find(k => k.key === key);\n\t\tif (Is.empty(exists)) {\n\t\t\tthis._contextIdKeys.push({ key, componentFeatures });\n\t\t}\n\t}\n\n\t/**\n\t * Get the context ID keys for the engine.\n\t * @returns The context IDs keys.\n\t */\n\tpublic getContextIdKeys(): string[] {\n\t\treturn this._contextIdKeys.map(k => k.key);\n\t}\n\n\t/**\n\t * Add a context ID to the engine.\n\t * @param key The context ID key.\n\t * @param value The context ID value.\n\t */\n\tpublic addContextId(key: string, value: string): void {\n\t\tthis._contextIds ??= {};\n\t\tthis._contextIds[key] = value;\n\t}\n\n\t/**\n\t * Get the context IDs for the engine.\n\t * @returns The context IDs or undefined if none are set.\n\t */\n\tpublic getContextIds(): IContextIds | undefined {\n\t\treturn this._contextIds;\n\t}\n\n\t/**\n\t * Start the engine core.\n\t * @param skipComponentStart Should the component start be skipped.\n\t * @returns A promise that resolves when the engine and all components have started.\n\t */\n\tpublic async start(skipComponentStart?: boolean): Promise<void> {\n\t\tif (!this._isStarted) {\n\t\t\tthis.setupEngineLogger();\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.starting`));\n\n\t\t\tif (this._context.config.debug) {\n\t\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.debuggingEnabled`));\n\t\t\t}\n\n\t\t\tconst skipComponent = skipComponentStart ?? false;\n\t\t\ttry {\n\t\t\t\tawait this.stateLoad();\n\n\t\t\t\tfor (const { type, module, method } of this._typeInitialisers) {\n\t\t\t\t\tawait this.initialiseTypeConfig(type, module, method);\n\t\t\t\t}\n\n\t\t\t\tthis.initialiseContextIdHandlers();\n\n\t\t\t\tawait this.bootstrap();\n\n\t\t\t\tthis._isStarted = true;\n\n\t\t\t\tif (!skipComponent) {\n\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsStarting`)\n\t\t\t\t\t);\n\n\t\t\t\t\tawait ContextIdStore.run(this._contextIds ?? {}, async () => {\n\t\t\t\t\t\tfor (const instance of this._context.componentInstances) {\n\t\t\t\t\t\t\tif (!instance.initialised) {\n\t\t\t\t\t\t\t\tinstance.initialised = true;\n\n\t\t\t\t\t\t\t\tconst startMethod = instance.component.start?.bind(instance.component);\n\t\t\t\t\t\t\t\tif (Is.function(startMethod)) {\n\t\t\t\t\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentStarting`, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait startMethod(EngineCore.LOGGING_COMPONENT_TYPE_NAME);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\tawait this.logError(\n\t\t\t\t\t\t\t\t\t\t\tnew GeneralError(\n\t\t\t\t\t\t\t\t\t\t\t\tEngineCore.CLASS_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\"componentStartFailed\",\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tBaseError.fromError(err)\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\tthrow err;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsComplete`)\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// If we are skipping component start then just mark them as initialised\n\t\t\t\t\t// we still need to be able to call stop on them to clean up\n\t\t\t\t\tfor (const instance of this._context.componentInstances) {\n\t\t\t\t\t\tinstance.initialised = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.started`));\n\t\t\t} catch (err) {\n\t\t\t\tawait this.stop();\n\t\t\t\tawait this.logError(BaseError.fromError(err));\n\t\t\t\tthrow err;\n\t\t\t} finally {\n\t\t\t\tawait this.stateSave();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Stop the engine core.\n\t * @returns A promise that resolves when all components have stopped and state has been saved.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tif (this._isStarted) {\n\t\t\tthis._isStarted = false;\n\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.stopping`));\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsStopping`));\n\n\t\t\tawait ContextIdStore.run(this._contextIds ?? {}, async () => {\n\t\t\t\tfor (const instance of this._context.componentInstances) {\n\t\t\t\t\tif (instance.initialised) {\n\t\t\t\t\t\tinstance.initialised = false;\n\t\t\t\t\t\tconst stopMethod = instance.component.stop?.bind(instance.component);\n\t\t\t\t\t\tif (Is.function(stopMethod)) {\n\t\t\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentStopping`, {\n\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait stopMethod(EngineCore.LOGGING_COMPONENT_TYPE_NAME);\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tawait this.logError(\n\t\t\t\t\t\t\t\t\tnew GeneralError(\n\t\t\t\t\t\t\t\t\t\tEngineCore.CLASS_NAME,\n\t\t\t\t\t\t\t\t\t\t\"componentStopFailed\",\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tBaseError.fromError(err)\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsStopped`));\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.stopped`));\n\t\t}\n\n\t\tawait this.stateSave();\n\t}\n\n\t/**\n\t * Is the engine started.\n\t * @returns True if the engine is started.\n\t */\n\tpublic isStarted(): boolean {\n\t\treturn this._isStarted;\n\t}\n\n\t/**\n\t * Is this the primary engine instance.\n\t * @returns True if the engine is the primary instance.\n\t */\n\tpublic isPrimary(): boolean {\n\t\treturn isMainThread && !this._isClone;\n\t}\n\n\t/**\n\t * Is this engine instance a clone.\n\t * @returns True if the engine instance is a clone.\n\t */\n\tpublic isClone(): boolean {\n\t\treturn this._isClone;\n\t}\n\n\t/**\n\t * Log info.\n\t * @param message The message to log.\n\t * @returns A promise that resolves when the message has been logged.\n\t */\n\tpublic async logInfo(message: string): Promise<void> {\n\t\tif (!this._context.config.silentLoggers?.includes(EngineCore.CLASS_NAME)) {\n\t\t\tawait this._engineLoggingComponent?.log({\n\t\t\t\tsource: EngineCore.CLASS_NAME,\n\t\t\t\tlevel: \"info\",\n\t\t\t\tmessage\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Log error.\n\t * @param error The error to log.\n\t * @returns A promise that resolves when the error has been logged.\n\t */\n\tpublic async logError(error: IError): Promise<void> {\n\t\tconst formattedErrors = ErrorHelper.localizeErrors(error);\n\t\tfor (const formattedError of formattedErrors) {\n\t\t\tlet message = Is.stringValue(formattedError.source)\n\t\t\t\t? `${formattedError.source}: ${formattedError.message}`\n\t\t\t\t: formattedError.message;\n\t\t\tif (this._context.config.debug && Is.stringValue(formattedError.stack)) {\n\t\t\t\tmessage += `\\n${formattedError.stack}`;\n\t\t\t}\n\t\t\tawait this._engineLoggingComponent?.log({\n\t\t\t\tsource: EngineCore.CLASS_NAME,\n\t\t\t\tlevel: \"error\",\n\t\t\t\tmessage\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Get the config for the engine.\n\t * @returns The config for the engine.\n\t */\n\tpublic getConfig(): C {\n\t\treturn this._context.config;\n\t}\n\n\t/**\n\t * Get the state of the engine.\n\t * @returns The state of the engine.\n\t */\n\tpublic getState(): S {\n\t\treturn this._context.state;\n\t}\n\n\t/**\n\t * Set the state to dirty so it gets saved.\n\t */\n\tpublic setStateDirty(): void {\n\t\tthis._context.stateDirty = true;\n\t}\n\n\t/**\n\t * Get all the registered instances.\n\t * @returns The registered instances.\n\t */\n\tpublic getRegisteredInstances(): {\n\t\t[name: string]: {\n\t\t\ttype: string;\n\t\t\tisDefault?: boolean;\n\t\t\tfeatures?: string[];\n\t\t}[];\n\t} {\n\t\treturn this._context.registeredInstances;\n\t}\n\n\t/**\n\t * Get the registered instance type for the component/connector.\n\t * @param componentConnectorType The type of the component/connector.\n\t * @param features The requested features of the component, if not specified the default entry will be retrieved.\n\t * @returns The instance type matching the criteria if one is registered.\n\t * @throws If a matching instance was not found.\n\t */\n\tpublic getRegisteredInstanceType(componentConnectorType: string, features?: string[]): string {\n\t\tGuards.stringValue(\n\t\t\tEngineCore.CLASS_NAME,\n\t\t\tnameof(componentConnectorType),\n\t\t\tcomponentConnectorType\n\t\t);\n\n\t\tconst registeredType = this.getRegisteredInstanceTypeOptional(componentConnectorType, features);\n\n\t\tif (!Is.stringValue(registeredType)) {\n\t\t\tif (Is.arrayValue(features)) {\n\t\t\t\tthrow new GeneralError(EngineCore.CLASS_NAME, \"instanceTypeNotFoundWithFeatures\", {\n\t\t\t\t\ttype: componentConnectorType,\n\t\t\t\t\tfeatures: features.join(\",\")\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow new GeneralError(EngineCore.CLASS_NAME, \"instanceTypeNotFound\", {\n\t\t\t\ttype: componentConnectorType\n\t\t\t});\n\t\t}\n\n\t\treturn registeredType;\n\t}\n\n\t/**\n\t * Get the registered instance type for the component/connector if it exists.\n\t * @param componentConnectorType The type of the component/connector.\n\t * @param features The requested features of the component, if not specified the default entry will be retrieved.\n\t * @returns The instance type matching the criteria if one is registered.\n\t */\n\tpublic getRegisteredInstanceTypeOptional(\n\t\tcomponentConnectorType: string,\n\t\tfeatures?: string[]\n\t): string | undefined {\n\t\tlet registeredType: string | undefined;\n\n\t\tconst registeredTypes = this._context.registeredInstances[componentConnectorType];\n\t\tif (Is.arrayValue(registeredTypes)) {\n\t\t\tif (Is.arrayValue(features)) {\n\t\t\t\tregisteredType = registeredTypes.find(t =>\n\t\t\t\t\tt.features?.every(f => features.includes(f))\n\t\t\t\t)?.type;\n\t\t\t} else {\n\t\t\t\t// First look for the default entry\n\t\t\t\tregisteredType = registeredTypes.find(t => t.isDefault)?.type;\n\n\t\t\t\t// Can't find a default so just use the first entry\n\t\t\t\tif (!Is.stringValue(registeredType)) {\n\t\t\t\t\tregisteredType = registeredTypes[0]?.type;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn registeredType;\n\t}\n\n\t/**\n\t * Get the registered logger for the component/connector.\n\t * @param componentName The name of the component to get the logger for.\n\t * @returns The logger type name if one is registered and not silenced.\n\t */\n\tpublic getRegisteredLoggerType(componentName: string): string | undefined {\n\t\tif (this._context.config.silentLoggers?.includes(componentName)) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.getRegisteredInstanceTypeOptional(\"loggingComponent\");\n\t}\n\n\t/**\n\t * Get the registered components.\n\t * @returns The registered components.\n\t */\n\tpublic async getRegisteredComponents(): Promise<\n\t\t{\n\t\t\tinstanceType: string;\n\t\t\tcomponent: IComponent;\n\t\t\tinitialised: boolean;\n\t\t}[]\n\t> {\n\t\treturn this._context.componentInstances;\n\t}\n\n\t/**\n\t * Add a registered component to the engine.\n\t * @param instanceType The instance type to register the component under.\n\t * @param component The component to register.\n\t * @returns A promise that resolves when the component has been registered.\n\t */\n\tpublic async addRegisteredComponent(instanceType: string, component: IComponent): Promise<void> {\n\t\tthis._context.componentInstances.push({ instanceType, component, initialised: true });\n\t}\n\n\t/**\n\t * Get the data required to create a clone of the engine.\n\t * @returns The clone data.\n\t */\n\tpublic getCloneData(): IEngineCoreClone<C, S> {\n\t\tconst entitySchemas: {\n\t\t\t[schema: string]: IEntitySchema;\n\t\t} = {};\n\n\t\tconst entitySchemaNames = EntitySchemaFactory.names();\n\t\tfor (const schemaName of entitySchemaNames) {\n\t\t\tentitySchemas[schemaName] = EntitySchemaFactory.get(schemaName);\n\t\t}\n\n\t\tconst cloneData: IEngineCoreClone<C, S> = {\n\t\t\tconfig: this._context.config,\n\t\t\tstate: this._context.state,\n\t\t\ttypeInitialisers: this._typeInitialisers,\n\t\t\tentitySchemas,\n\t\t\tcontextIdKeys: this._contextIdKeys\n\t\t};\n\n\t\treturn cloneData;\n\t}\n\n\t/**\n\t * Populate the engine from the clone data.\n\t * @param cloneData The clone data to populate from.\n\t * @param contextIds The context IDs to use for the clone.\n\t * @param silent Should the clone be silent.\n\t */\n\tpublic populateClone(\n\t\tcloneData: IEngineCoreClone<C, S>,\n\t\tcontextIds?: IContextIds,\n\t\tsilent?: boolean\n\t): void {\n\t\tGuards.object(EngineCore.CLASS_NAME, nameof(cloneData), cloneData);\n\t\tGuards.object(EngineCore.CLASS_NAME, nameof(cloneData.config), cloneData.config);\n\t\tGuards.object(EngineCore.CLASS_NAME, nameof(cloneData.state), cloneData.state);\n\t\tGuards.array(\n\t\t\tEngineCore.CLASS_NAME,\n\t\t\tnameof(cloneData.typeInitialisers),\n\t\t\tcloneData.typeInitialisers\n\t\t);\n\n\t\tthis._skipBootstrap = true;\n\t\tthis._isClone = true;\n\n\t\tif (silent ?? false) {\n\t\t\tcloneData.config.silent = true;\n\t\t}\n\n\t\tthis._context = {\n\t\t\tconfig: cloneData.config,\n\t\t\tregisteredInstances: {},\n\t\t\tcomponentInstances: [],\n\t\t\tstate: {} as S,\n\t\t\tstateDirty: false\n\t\t};\n\n\t\tthis._typeInitialisers = cloneData.typeInitialisers;\n\t\tthis._contextIdKeys.push(...cloneData.contextIdKeys);\n\t\tthis._contextIds = contextIds;\n\n\t\tfor (const schemaName of Object.keys(cloneData.entitySchemas)) {\n\t\t\tEntitySchemaFactory.register(schemaName, () => cloneData.entitySchemas[schemaName]);\n\t\t}\n\n\t\tthis._stateStorage = new MemoryStateStorage(true, cloneData.state);\n\t\tthis._isStarted = false;\n\t}\n\n\t/**\n\t * Initialise the types from connector.\n\t * @param typeKey The key for the default types.\n\t * @param module The module containing the initialiser.\n\t * @param method The method to initialise the instance.\n\t * @returns A promise that resolves when the type configuration has been initialised.\n\t * @internal\n\t */\n\tprivate async initialiseTypeConfig(\n\t\ttypeKey: string,\n\t\tmodule: string,\n\t\tmethod: string\n\t): Promise<void> {\n\t\tconst typeConfig: IEngineCoreTypeConfig[] | undefined = this._context.config.types?.[typeKey];\n\n\t\tif (Is.arrayValue(typeConfig)) {\n\t\t\tconst instanceMethod = await ModuleHelper.getModuleEntry<EngineTypeInitialiser>(\n\t\t\t\tmodule,\n\t\t\t\tmethod\n\t\t\t);\n\n\t\t\tfor (let i = 0; i < typeConfig.length; i++) {\n\t\t\t\tawait this.logInfo(\n\t\t\t\t\tI18n.formatMessage(\"engineCore.configuring\", {\n\t\t\t\t\t\tcomponentType: typeKey,\n\t\t\t\t\t\tconfigType: typeConfig[i].type\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tconst result = instanceMethod(this, this._context, typeConfig[i]);\n\t\t\t\tconst componentCreateMethod = result.createComponent;\n\n\t\t\t\tif (Is.stringValue(result.instanceTypeName) && Is.function(componentCreateMethod)) {\n\t\t\t\t\tconst finalInstanceType = typeConfig[i].overrideInstanceType ?? result.instanceTypeName;\n\n\t\t\t\t\t// If this is a multi instance component we need to make sure we\n\t\t\t\t\t// generate a unique instance for every factory call\n\t\t\t\t\t// this is often used for REST clients where each instance might\n\t\t\t\t\t// use a different endpoint url\n\t\t\t\t\t// They are generated using the create method of factory\n\t\t\t\t\t// passing custom options, instead of the regular get method\n\t\t\t\t\t// which doesn't allow for custom options\n\t\t\t\t\tif (typeConfig[i].isMultiInstance ?? false) {\n\t\t\t\t\t\tresult.factory?.register(finalInstanceType, params =>\n\t\t\t\t\t\t\tcomponentCreateMethod({\n\t\t\t\t\t\t\t\ttype: typeConfig[i].type,\n\t\t\t\t\t\t\t\toptions: params\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst component = componentCreateMethod(typeConfig[i]);\n\t\t\t\t\t\tthis._context.componentInstances.push({\n\t\t\t\t\t\t\tinstanceType: finalInstanceType,\n\t\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\t\tinitialised: false\n\t\t\t\t\t\t});\n\t\t\t\t\t\tresult.factory?.register(finalInstanceType, () => component);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._context.registeredInstances[typeKey] ??= [];\n\t\t\t\t\tthis._context.registeredInstances[typeKey].push({\n\t\t\t\t\t\ttype: finalInstanceType,\n\t\t\t\t\t\tisDefault: typeConfig[i].isDefault,\n\t\t\t\t\t\tfeatures: typeConfig[i].features\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthrow new GeneralError(\"engineCore\", \"componentUnknownType\", {\n\t\t\t\t\t\ttype: typeConfig[i].type,\n\t\t\t\t\t\tcomponentType: typeKey\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 * Setup the engine logger.\n\t * @internal\n\t */\n\tprivate setupEngineLogger(): void {\n\t\tconst silent = this._context.config.silent ?? false;\n\t\tconst engineLoggerConnector = silent\n\t\t\t? new SilentLoggingConnector()\n\t\t\t: new ConsoleLoggingConnector({\n\t\t\t\t\tconfig: {\n\t\t\t\t\t\ttranslateMessages: true,\n\t\t\t\t\t\thideGroups: true\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\tthis._context.componentInstances.push({\n\t\t\tinstanceType: EngineCore.LOGGING_CONNECTOR_TYPE_NAME,\n\t\t\tcomponent: engineLoggerConnector,\n\t\t\tinitialised: false\n\t\t});\n\n\t\tLoggingConnectorFactory.register(\n\t\t\tEngineCore.LOGGING_CONNECTOR_TYPE_NAME,\n\t\t\t() => engineLoggerConnector\n\t\t);\n\n\t\tthis._context.registeredInstances.loggingConnector = [\n\t\t\t{\n\t\t\t\ttype: EngineCore.LOGGING_CONNECTOR_TYPE_NAME\n\t\t\t}\n\t\t];\n\n\t\tconst engineLoggerComponent = new LoggingService({\n\t\t\tloggingConnectorType: EngineCore.LOGGING_CONNECTOR_TYPE_NAME\n\t\t});\n\t\tthis._engineLoggingComponent = engineLoggerComponent;\n\n\t\tComponentFactory.register(EngineCore.LOGGING_COMPONENT_TYPE_NAME, () => engineLoggerComponent);\n\t\tthis._context.registeredInstances.loggingComponent = [\n\t\t\t{\n\t\t\t\ttype: EngineCore.LOGGING_COMPONENT_TYPE_NAME\n\t\t\t}\n\t\t];\n\t}\n\n\t/**\n\t * Load the state.\n\t * @returns A promise that resolves when the state has been loaded.\n\t * @internal\n\t */\n\tprivate async stateLoad(): Promise<void> {\n\t\tif (this._stateStorage) {\n\t\t\ttry {\n\t\t\t\tthis._context.state = ((await this._stateStorage.load(this)) ?? {}) as S;\n\t\t\t\tthis._context.stateDirty = false;\n\t\t\t} catch (err) {\n\t\t\t\tawait this.logError(BaseError.fromError(err));\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Save the state.\n\t * @returns A promise that resolves when the state has been persisted.\n\t * @internal\n\t */\n\tprivate async stateSave(): Promise<void> {\n\t\tif (this._stateStorage && !Is.empty(this._context.state) && this._context.stateDirty) {\n\t\t\ttry {\n\t\t\t\tawait this._stateStorage.save(this, this._context.state);\n\t\t\t\tthis._context.stateDirty = false;\n\t\t\t} catch (err) {\n\t\t\t\tawait this.logError(BaseError.fromError(err));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Bootstrap the engine.\n\t * @returns A promise that resolves when bootstrapping is complete.\n\t * @internal\n\t */\n\tprivate async bootstrap(): Promise<void> {\n\t\tif (!this._skipBootstrap) {\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.bootstrapStarted`));\n\n\t\t\t// First bootstrap the components.\n\t\t\tfor (const instance of this._context.componentInstances) {\n\t\t\t\tconst bootstrapMethod = instance.component.bootstrap?.bind(instance.component);\n\t\t\t\tif (Is.function(bootstrapMethod)) {\n\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.bootstrapping`, {\n\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\n\t\t\t\t\tconst bootstrapSuccess = await bootstrapMethod(EngineCore.LOGGING_COMPONENT_TYPE_NAME);\n\n\t\t\t\t\t// If the bootstrap method failed then throw an error\n\t\t\t\t\tif (!bootstrapSuccess) {\n\t\t\t\t\t\tthrow new GeneralError(EngineCore.CLASS_NAME, \"bootstrapFailed\", {\n\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\tinstanceType: instance.instanceType\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\t// Now perform any custom bootstrap operations\n\t\t\tconst customBootstrap = this._customBootstrap;\n\t\t\tif (Is.function(customBootstrap)) {\n\t\t\t\tawait customBootstrap.call(this, this, this._context);\n\t\t\t}\n\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.bootstrapComplete`));\n\t\t}\n\t}\n\n\t/**\n\t * Initialise the context ID handlers.\n\t * @internal\n\t */\n\tprivate initialiseContextIdHandlers(): void {\n\t\tfor (const contextIdKey of this._contextIdKeys) {\n\t\t\tconst handlerType: string | undefined = this.getRegisteredInstanceTypeOptional(\n\t\t\t\t\"contextIdHandlerComponent\",\n\t\t\t\tcontextIdKey.componentFeatures\n\t\t\t);\n\t\t\tif (Is.stringValue(handlerType)) {\n\t\t\t\tconst handler = ComponentFactory.get<IContextIdHandler>(handlerType);\n\t\t\t\tContextIdHandlerFactory.register(contextIdKey.key, () => handler);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"engineCore.js","sourceRoot":"","sources":["../../src/engineCore.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { isMainThread } from \"node:worker_threads\";\nimport {\n\tContextIdHandlerFactory,\n\tContextIdStore,\n\ttype IContextIdHandler,\n\ttype IContextIds\n} from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tComponentFactory,\n\tErrorHelper,\n\tGeneralError,\n\tGuards,\n\tI18n,\n\ttype IComponent,\n\ttype IError,\n\tIs,\n\tObjectHelper\n} from \"@twin.org/core\";\nimport {\n\tEngineLogLevel,\n\ttype EngineTypeInitialiser,\n\ttype IEngineCore,\n\ttype IEngineCoreClone,\n\ttype IEngineCoreConfig,\n\ttype IEngineCoreContext,\n\ttype IEngineCoreTypeConfig,\n\ttype IEngineState,\n\ttype IEngineStateStorage\n} from \"@twin.org/engine-models\";\nimport { EntitySchemaFactory, type IEntitySchema } from \"@twin.org/entity\";\nimport { ConsoleLoggingConnector } from \"@twin.org/logging-connector-console\";\nimport {\n\ttype ILoggingComponent,\n\ttype ILoggingConnector,\n\tLoggingConnectorFactory,\n\tLogLevel,\n\tSilentLoggingConnector\n} from \"@twin.org/logging-models\";\nimport { LoggingService } from \"@twin.org/logging-service\";\nimport { ModuleHelper } from \"@twin.org/modules\";\nimport { nameof, nameofCamelCase } from \"@twin.org/nameof\";\nimport type { IEngineCoreOptions } from \"./models/IEngineCoreOptions.js\";\nimport { MemoryStateStorage } from \"./storage/memoryStateStorage.js\";\n\n/**\n * Core for the engine.\n */\nexport class EngineCore<\n\tC extends IEngineCoreConfig = IEngineCoreConfig,\n\tS extends IEngineState = IEngineState\n> implements IEngineCore<C, S> {\n\t/**\n\t * Name for the engine logger component, used for direct console logging.\n\t */\n\tpublic static readonly LOGGING_COMPONENT_TYPE_NAME: string = \"engine-logging-service\";\n\n\t/**\n\t * Name for the engine logger connector, used for direct console logging.\n\t */\n\tpublic static readonly LOGGING_CONNECTOR_TYPE_NAME: string = \"engine-logging-connector\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<EngineCore>();\n\n\t/**\n\t * The core context.\n\t */\n\tprotected _context: IEngineCoreContext<C, S>;\n\n\t/**\n\t * The context ID keys.\n\t */\n\tprotected readonly _contextIdKeys: { key: string; componentFeatures: string[] }[];\n\n\t/**\n\t * The context IDs.\n\t */\n\tprotected _contextIds?: IContextIds;\n\n\t/**\n\t * The state storage interface.\n\t * @internal\n\t */\n\tprivate _stateStorage?: IEngineStateStorage<S>;\n\n\t/**\n\t * The logging component for the engine.\n\t * @internal\n\t */\n\tprivate _engineLoggingComponent?: ILoggingComponent;\n\n\t/**\n\t * Skip the bootstrap process.\n\t * @internal\n\t */\n\tprivate _skipBootstrap?: boolean;\n\n\t/**\n\t * The type initialisers.\n\t * @internal\n\t */\n\tprivate _typeInitialisers: {\n\t\ttype: string;\n\t\tmodule: string;\n\t\tmethod: string;\n\t}[];\n\n\t/**\n\t * Is the engine started.\n\t * @internal\n\t */\n\tprivate _isStarted: boolean;\n\n\t/**\n\t * Is the engine a clone.\n\t * @internal\n\t */\n\tprivate _isClone: boolean;\n\n\t/**\n\t * Add type initialisers to the engine.\n\t * @internal\n\t */\n\tprivate readonly _populateTypeInitialisers?: (\n\t\tengineCore: IEngineCore<C, S>,\n\t\tcontext: IEngineCoreContext<C, S>\n\t) => void;\n\n\t/**\n\t * Method for bootstrapping any data for the engine.\n\t * @internal\n\t */\n\tprivate readonly _customBootstrap?: (\n\t\tengineCore: IEngineCore<C, S>,\n\t\tcontext: IEngineCoreContext<C, S>\n\t) => Promise<void>;\n\n\t/**\n\t * Create a new instance of EngineCore.\n\t * @param options The options for the engine.\n\t */\n\tconstructor(options?: IEngineCoreOptions<C, S>) {\n\t\toptions = options ?? {};\n\t\toptions.config = options.config ?? ({} as C);\n\t\toptions.config.debug = options.config.debug ?? false;\n\t\toptions.config.silent = options.config.silent ?? false;\n\t\toptions.config.types ??= {};\n\n\t\tthis._skipBootstrap = options.skipBootstrap ?? false;\n\t\tthis._populateTypeInitialisers = options.populateTypeInitialisers;\n\t\tthis._customBootstrap = options.customBootstrap;\n\t\tthis._typeInitialisers = [];\n\t\tthis._contextIdKeys = [];\n\n\t\tthis._context = {\n\t\t\tconfig: options.config,\n\t\t\tregisteredInstances: {},\n\t\t\tcomponentInstances: [],\n\t\t\tstate: {} as S,\n\t\t\tstateDirty: false\n\t\t};\n\t\tthis._stateStorage = options.stateStorage;\n\t\tthis._isStarted = false;\n\t\tthis._isClone = false;\n\n\t\tif (Is.function(this._populateTypeInitialisers)) {\n\t\t\tthis._populateTypeInitialisers(this, this._context);\n\t\t}\n\t}\n\n\t/**\n\t * Add a type initialiser.\n\t * @param type The type to add the initialiser for.\n\t * @param module The name of the module which contains the initialiser method.\n\t * @param method The name of the method to call.\n\t */\n\tpublic addTypeInitialiser(type: string, module: string, method: string): void {\n\t\tGuards.stringValue(EngineCore.CLASS_NAME, nameof(type), type);\n\t\tGuards.stringValue(EngineCore.CLASS_NAME, nameof(module), module);\n\t\tGuards.stringValue(EngineCore.CLASS_NAME, nameof(method), method);\n\n\t\tconst currentIndex = this._typeInitialisers.findIndex(t => t.type === type);\n\t\tif (currentIndex >= 0) {\n\t\t\tthis._typeInitialisers[currentIndex].module = module;\n\t\t\tthis._typeInitialisers[currentIndex].method = method;\n\t\t} else {\n\t\t\tthis._typeInitialisers.push({\n\t\t\t\ttype,\n\t\t\t\tmodule,\n\t\t\t\tmethod\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Get the type config for a specific type.\n\t * @param type The type to get the config for.\n\t * @returns The type config or undefined if not found.\n\t */\n\tpublic getTypeConfig(type: string): IEngineCoreTypeConfig[] | undefined {\n\t\tGuards.stringValue(EngineCore.CLASS_NAME, nameof(type), type);\n\t\treturn this._context.config.types?.[type];\n\t}\n\n\t/**\n\t * Add a context ID key to the engine.\n\t * @param key The context ID key.\n\t * @param componentFeatures The component features for the context ID handler.\n\t */\n\tpublic addContextIdKey(key: string, componentFeatures: string[]): void {\n\t\tconst exists = this._contextIdKeys.find(k => k.key === key);\n\t\tif (Is.empty(exists)) {\n\t\t\tthis._contextIdKeys.push({ key, componentFeatures });\n\t\t}\n\t}\n\n\t/**\n\t * Get the context ID keys for the engine.\n\t * @returns The context IDs keys.\n\t */\n\tpublic getContextIdKeys(): string[] {\n\t\treturn this._contextIdKeys.map(k => k.key);\n\t}\n\n\t/**\n\t * Add a context ID to the engine.\n\t * @param key The context ID key.\n\t * @param value The context ID value.\n\t */\n\tpublic addContextId(key: string, value: string): void {\n\t\tthis._contextIds ??= {};\n\t\tthis._contextIds[key] = value;\n\t}\n\n\t/**\n\t * Get the context IDs for the engine.\n\t * @returns The context IDs or undefined if none are set.\n\t */\n\tpublic getContextIds(): IContextIds | undefined {\n\t\treturn this._contextIds;\n\t}\n\n\t/**\n\t * Start the engine core.\n\t * @param skipComponentStart Should the component start be skipped.\n\t * @returns A promise that resolves when the engine and all components have started.\n\t */\n\tpublic async start(skipComponentStart?: boolean): Promise<void> {\n\t\tif (!this._isStarted) {\n\t\t\tthis.setupEngineLogger();\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.starting`));\n\n\t\t\tif (this._context.config.debug) {\n\t\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.debuggingEnabled`));\n\t\t\t}\n\n\t\t\tconst skipComponent = skipComponentStart ?? false;\n\t\t\ttry {\n\t\t\t\tawait this.stateLoad();\n\n\t\t\t\tfor (const { type, module, method } of this._typeInitialisers) {\n\t\t\t\t\tawait this.initialiseTypeConfig(type, module, method);\n\t\t\t\t}\n\n\t\t\t\tthis.initialiseContextIdHandlers();\n\n\t\t\t\tawait this.bootstrap();\n\n\t\t\t\tthis._isStarted = true;\n\n\t\t\t\tif (!skipComponent) {\n\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsStarting`)\n\t\t\t\t\t);\n\n\t\t\t\t\tconst componentTimings: {\n\t\t\t\t\t\tclassName: string;\n\t\t\t\t\t\tinstanceType: string;\n\t\t\t\t\t\telapsedMs: number;\n\t\t\t\t\t}[] = [];\n\t\t\t\t\tconst componentsStartTime = performance.now();\n\n\t\t\t\t\tawait ContextIdStore.run(this._contextIds ?? {}, async () => {\n\t\t\t\t\t\tfor (const instance of this._context.componentInstances) {\n\t\t\t\t\t\t\tif (!instance.initialised) {\n\t\t\t\t\t\t\t\tinstance.initialised = true;\n\n\t\t\t\t\t\t\t\tconst startMethod = instance.component.start?.bind(instance.component);\n\t\t\t\t\t\t\t\tif (Is.function(startMethod)) {\n\t\t\t\t\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentStarting`, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\tconst componentStartTime = performance.now();\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait startMethod(EngineCore.LOGGING_COMPONENT_TYPE_NAME);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\tawait this.logError(\n\t\t\t\t\t\t\t\t\t\t\tnew GeneralError(\n\t\t\t\t\t\t\t\t\t\t\t\tEngineCore.CLASS_NAME,\n\t\t\t\t\t\t\t\t\t\t\t\t\"componentStartFailed\",\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tBaseError.fromError(err)\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\tthrow err;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tconst elapsedMs = Math.round(performance.now() - componentStartTime);\n\t\t\t\t\t\t\t\t\tcomponentTimings.push({\n\t\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType,\n\t\t\t\t\t\t\t\t\t\telapsedMs\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tawait this.logDebug(\n\t\t\t\t\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentStarted`, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType,\n\t\t\t\t\t\t\t\t\t\t\telapsedMs\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tif (componentTimings.length > 0) {\n\t\t\t\t\t\tconst totalMs = Math.round(performance.now() - componentsStartTime);\n\t\t\t\t\t\tconst slowestComponents = componentTimings\n\t\t\t\t\t\t\t.sort((a, b) => b.elapsedMs - a.elapsedMs)\n\t\t\t\t\t\t\t.slice(0, 3)\n\t\t\t\t\t\t\t.map(t => `${t.className} (${t.instanceType}) ${t.elapsedMs}ms`)\n\t\t\t\t\t\t\t.join(\", \");\n\t\t\t\t\t\tawait this.logDebug(\n\t\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsSummary`, {\n\t\t\t\t\t\t\t\ttotalMs,\n\t\t\t\t\t\t\t\tslowestComponents\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsComplete`)\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// If we are skipping component start then just mark them as initialised\n\t\t\t\t\t// we still need to be able to call stop on them to clean up\n\t\t\t\t\tfor (const instance of this._context.componentInstances) {\n\t\t\t\t\t\tinstance.initialised = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.started`));\n\t\t\t} catch (err) {\n\t\t\t\tawait this.stop();\n\t\t\t\tawait this.logError(BaseError.fromError(err));\n\t\t\t\tthrow err;\n\t\t\t} finally {\n\t\t\t\tawait this.stateSave();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Stop the engine core.\n\t * @returns A promise that resolves when all components have stopped and state has been saved.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tif (this._isStarted) {\n\t\t\tthis._isStarted = false;\n\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.stopping`));\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsStopping`));\n\n\t\t\tawait ContextIdStore.run(this._contextIds ?? {}, async () => {\n\t\t\t\tfor (const instance of this._context.componentInstances) {\n\t\t\t\t\tif (instance.initialised) {\n\t\t\t\t\t\tinstance.initialised = false;\n\t\t\t\t\t\tconst stopMethod = instance.component.stop?.bind(instance.component);\n\t\t\t\t\t\tif (Is.function(stopMethod)) {\n\t\t\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentStopping`, {\n\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait stopMethod(EngineCore.LOGGING_COMPONENT_TYPE_NAME);\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tawait this.logError(\n\t\t\t\t\t\t\t\t\tnew GeneralError(\n\t\t\t\t\t\t\t\t\t\tEngineCore.CLASS_NAME,\n\t\t\t\t\t\t\t\t\t\t\"componentStopFailed\",\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tBaseError.fromError(err)\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.componentsStopped`));\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.stopped`));\n\t\t}\n\n\t\tawait this.stateSave();\n\t}\n\n\t/**\n\t * Is the engine started.\n\t * @returns True if the engine is started.\n\t */\n\tpublic isStarted(): boolean {\n\t\treturn this._isStarted;\n\t}\n\n\t/**\n\t * Is this the primary engine instance.\n\t * @returns True if the engine is the primary instance.\n\t */\n\tpublic isPrimary(): boolean {\n\t\treturn isMainThread && !this._isClone;\n\t}\n\n\t/**\n\t * Is this engine instance a clone.\n\t * @returns True if the engine instance is a clone.\n\t */\n\tpublic isClone(): boolean {\n\t\treturn this._isClone;\n\t}\n\n\t/**\n\t * Log info.\n\t * @param message The message to log.\n\t * @returns A promise that resolves when the message has been logged.\n\t */\n\tpublic async logInfo(message: string): Promise<void> {\n\t\tif (!this._context.config.silentLoggers?.includes(EngineCore.CLASS_NAME)) {\n\t\t\tawait this._engineLoggingComponent?.log({\n\t\t\t\tsource: EngineCore.CLASS_NAME,\n\t\t\t\tlevel: \"info\",\n\t\t\t\tmessage\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Log error.\n\t * @param error The error to log.\n\t * @returns A promise that resolves when the error has been logged.\n\t */\n\tpublic async logError(error: IError): Promise<void> {\n\t\tconst formattedErrors = ErrorHelper.localizeErrors(error);\n\t\tfor (const formattedError of formattedErrors) {\n\t\t\tlet message = Is.stringValue(formattedError.source)\n\t\t\t\t? `${formattedError.source}: ${formattedError.message}`\n\t\t\t\t: formattedError.message;\n\t\t\tif (this._context.config.debug && Is.stringValue(formattedError.stack)) {\n\t\t\t\tmessage += `\\n${formattedError.stack}`;\n\t\t\t}\n\t\t\tawait this._engineLoggingComponent?.log({\n\t\t\t\tsource: EngineCore.CLASS_NAME,\n\t\t\t\tlevel: \"error\",\n\t\t\t\tmessage\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Get the config for the engine.\n\t * @returns The config for the engine.\n\t */\n\tpublic getConfig(): C {\n\t\treturn this._context.config;\n\t}\n\n\t/**\n\t * Get the state of the engine.\n\t * @returns The state of the engine.\n\t */\n\tpublic getState(): S {\n\t\treturn this._context.state;\n\t}\n\n\t/**\n\t * Set the state to dirty so it gets saved.\n\t */\n\tpublic setStateDirty(): void {\n\t\tthis._context.stateDirty = true;\n\t}\n\n\t/**\n\t * Get all the registered instances.\n\t * @returns The registered instances.\n\t */\n\tpublic getRegisteredInstances(): {\n\t\t[name: string]: {\n\t\t\ttype: string;\n\t\t\tisDefault?: boolean;\n\t\t\tfeatures?: string[];\n\t\t}[];\n\t} {\n\t\treturn this._context.registeredInstances;\n\t}\n\n\t/**\n\t * Get the registered instance type for the component/connector.\n\t * @param componentConnectorType The type of the component/connector.\n\t * @param features The requested features of the component, if not specified the default entry will be retrieved.\n\t * @returns The instance type matching the criteria if one is registered.\n\t * @throws If a matching instance was not found.\n\t */\n\tpublic getRegisteredInstanceType(componentConnectorType: string, features?: string[]): string {\n\t\tGuards.stringValue(\n\t\t\tEngineCore.CLASS_NAME,\n\t\t\tnameof(componentConnectorType),\n\t\t\tcomponentConnectorType\n\t\t);\n\n\t\tconst registeredType = this.getRegisteredInstanceTypeOptional(componentConnectorType, features);\n\n\t\tif (!Is.stringValue(registeredType)) {\n\t\t\tif (Is.arrayValue(features)) {\n\t\t\t\tthrow new GeneralError(EngineCore.CLASS_NAME, \"instanceTypeNotFoundWithFeatures\", {\n\t\t\t\t\ttype: componentConnectorType,\n\t\t\t\t\tfeatures: features.join(\",\")\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow new GeneralError(EngineCore.CLASS_NAME, \"instanceTypeNotFound\", {\n\t\t\t\ttype: componentConnectorType\n\t\t\t});\n\t\t}\n\n\t\treturn registeredType;\n\t}\n\n\t/**\n\t * Get the registered instance type for the component/connector if it exists.\n\t * @param componentConnectorType The type of the component/connector.\n\t * @param features The requested features of the component, if not specified the default entry will be retrieved.\n\t * @returns The instance type matching the criteria if one is registered.\n\t */\n\tpublic getRegisteredInstanceTypeOptional(\n\t\tcomponentConnectorType: string,\n\t\tfeatures?: string[]\n\t): string | undefined {\n\t\tlet registeredType: string | undefined;\n\n\t\tconst registeredTypes = this._context.registeredInstances[componentConnectorType];\n\t\tif (Is.arrayValue(registeredTypes)) {\n\t\t\tif (Is.arrayValue(features)) {\n\t\t\t\tregisteredType = registeredTypes.find(t =>\n\t\t\t\t\tt.features?.every(f => features.includes(f))\n\t\t\t\t)?.type;\n\t\t\t} else {\n\t\t\t\t// First look for the default entry\n\t\t\t\tregisteredType = registeredTypes.find(t => t.isDefault)?.type;\n\n\t\t\t\t// Can't find a default so just use the first entry\n\t\t\t\tif (!Is.stringValue(registeredType)) {\n\t\t\t\t\tregisteredType = registeredTypes[0]?.type;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn registeredType;\n\t}\n\n\t/**\n\t * Get the registered logger for the component/connector.\n\t * @param componentName The name of the component to get the logger for.\n\t * @returns The logger type name if one is registered and not silenced.\n\t */\n\tpublic getRegisteredLoggerType(componentName: string): string | undefined {\n\t\tif (this._context.config.silentLoggers?.includes(componentName)) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.getRegisteredInstanceTypeOptional(\"loggingComponent\");\n\t}\n\n\t/**\n\t * Get the registered components.\n\t * @returns The registered components.\n\t */\n\tpublic async getRegisteredComponents(): Promise<\n\t\t{\n\t\t\tinstanceType: string;\n\t\t\tcomponent: IComponent;\n\t\t\tinitialised: boolean;\n\t\t}[]\n\t> {\n\t\treturn this._context.componentInstances;\n\t}\n\n\t/**\n\t * Add a registered component to the engine.\n\t * @param instanceType The instance type to register the component under.\n\t * @param component The component to register.\n\t * @returns A promise that resolves when the component has been registered.\n\t */\n\tpublic async addRegisteredComponent(instanceType: string, component: IComponent): Promise<void> {\n\t\tthis._context.componentInstances.push({ instanceType, component, initialised: true });\n\t}\n\n\t/**\n\t * Get the data required to create a clone of the engine.\n\t * @returns The clone data.\n\t */\n\tpublic getCloneData(): IEngineCoreClone<C, S> {\n\t\tconst entitySchemas: {\n\t\t\t[schema: string]: IEntitySchema;\n\t\t} = {};\n\n\t\tconst entitySchemaNames = EntitySchemaFactory.names();\n\t\tfor (const schemaName of entitySchemaNames) {\n\t\t\tentitySchemas[schemaName] = EntitySchemaFactory.get(schemaName);\n\t\t}\n\n\t\tconst sourceConfig = this._context.config;\n\t\tconst cloneTypes: { [type: string]: IEngineCoreTypeConfig[] } = {};\n\t\tfor (const typeKey of Object.keys(sourceConfig.types ?? {})) {\n\t\t\tconst entries = sourceConfig.types?.[typeKey];\n\t\t\tif (Is.arrayValue(entries)) {\n\t\t\t\tconst cloneableEntries = entries.filter(e => e.isCloneable !== false);\n\t\t\t\tif (cloneableEntries.length > 0) {\n\t\t\t\t\tcloneTypes[typeKey] = cloneableEntries;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst cloneData: IEngineCoreClone<C, S> = {\n\t\t\tconfig: { ...sourceConfig, types: cloneTypes },\n\t\t\tstate: this._context.state,\n\t\t\ttypeInitialisers: this._typeInitialisers,\n\t\t\tentitySchemas,\n\t\t\tcontextIdKeys: this._contextIdKeys\n\t\t};\n\n\t\treturn cloneData;\n\t}\n\n\t/**\n\t * Populate the engine from the clone data.\n\t * @param cloneData The clone data to populate from.\n\t * @param contextIds The context IDs to use for the clone.\n\t * @param options An optional object containing the log level, types and entity types to include.\n\t * @param options.logLevel The log level for the clone, true maps to error level.\n\t * @param options.types An optional allowlist of type keys to include; when omitted all types are cloned.\n\t * @param options.entityTypes An optional allowlist of entity type names; when provided only those entity schemas and their associated storage components are cloned.\n\t */\n\tpublic populateClone(\n\t\tcloneData: IEngineCoreClone<C, S>,\n\t\tcontextIds?: IContextIds,\n\t\toptions?: boolean | { logLevel?: EngineLogLevel; types?: string[]; entityTypes?: string[] }\n\t): void {\n\t\tGuards.object(EngineCore.CLASS_NAME, nameof(cloneData), cloneData);\n\t\tGuards.object(EngineCore.CLASS_NAME, nameof(cloneData.config), cloneData.config);\n\t\tGuards.object(EngineCore.CLASS_NAME, nameof(cloneData.state), cloneData.state);\n\t\tGuards.array(\n\t\t\tEngineCore.CLASS_NAME,\n\t\t\tnameof(cloneData.typeInitialisers),\n\t\t\tcloneData.typeInitialisers\n\t\t);\n\n\t\tthis._skipBootstrap = true;\n\t\tthis._isClone = true;\n\n\t\tlet optionsEntityTypes: string[] | undefined;\n\t\tlet optionsTypes: string[] | undefined;\n\t\tif (Is.object(options)) {\n\t\t\tif (!Is.empty(options.logLevel)) {\n\t\t\t\tconst logLevel = options.logLevel;\n\t\t\t\tGuards.arrayOneOf(\n\t\t\t\t\tEngineCore.CLASS_NAME,\n\t\t\t\t\tnameof(logLevel),\n\t\t\t\t\tlogLevel,\n\t\t\t\t\tObject.values(EngineLogLevel)\n\t\t\t\t);\n\t\t\t\tcloneData.config.logLevel = logLevel;\n\t\t\t}\n\t\t\toptionsEntityTypes = options.entityTypes;\n\t\t\toptionsTypes = options.types;\n\t\t} else if (options === true) {\n\t\t\tcloneData.config.logLevel = EngineLogLevel.Error;\n\t\t}\n\n\t\tlet cloneEntitySchemas = cloneData.entitySchemas;\n\n\t\tconst safeTypes: { [type: string]: IEngineCoreTypeConfig[] } = {};\n\t\tfor (const typeKey of Object.keys(cloneData.config.types ?? {})) {\n\t\t\tconst entries = cloneData.config.types?.[typeKey];\n\t\t\tif (Is.arrayValue(entries)) {\n\t\t\t\tconst cloneableEntries = entries.filter(e => e.isCloneable !== false);\n\t\t\t\tif (cloneableEntries.length > 0) {\n\t\t\t\t\tsafeTypes[typeKey] = cloneableEntries;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlet cloneConfig: IEngineCoreConfig = { ...cloneData.config, types: safeTypes };\n\n\t\tif (Is.arrayValue(optionsEntityTypes)) {\n\t\t\tconst filteredSchemas: { [schema: string]: IEntitySchema } = {};\n\t\t\tfor (const schemaName of Object.keys(cloneData.entitySchemas)) {\n\t\t\t\tif (optionsEntityTypes.includes(schemaName)) {\n\t\t\t\t\tfilteredSchemas[schemaName] = cloneData.entitySchemas[schemaName];\n\t\t\t\t}\n\t\t\t}\n\t\t\tcloneEntitySchemas = filteredSchemas;\n\n\t\t\tconst filteredTypes: { [type: string]: IEngineCoreTypeConfig[] } = {};\n\t\t\tfor (const typeKey of Object.keys(safeTypes)) {\n\t\t\t\tconst entries = safeTypes[typeKey];\n\t\t\t\tif (Is.arrayValue(entries)) {\n\t\t\t\t\tconst kept = entries.filter(e => {\n\t\t\t\t\t\tconst storageType = ObjectHelper.propertyGet(e.options, \"entityStorageType\");\n\t\t\t\t\t\tif (Is.stringValue(storageType)) {\n\t\t\t\t\t\t\treturn optionsEntityTypes.includes(storageType);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t});\n\t\t\t\t\tif (kept.length > 0) {\n\t\t\t\t\t\tfilteredTypes[typeKey] = kept;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcloneConfig = { ...cloneData.config, types: filteredTypes };\n\t\t}\n\n\t\tthis._context = {\n\t\t\tconfig: cloneConfig as C,\n\t\t\tregisteredInstances: {},\n\t\t\tcomponentInstances: [],\n\t\t\tstate: {} as S,\n\t\t\tstateDirty: false\n\t\t};\n\n\t\tthis._typeInitialisers = Is.arrayValue(optionsTypes)\n\t\t\t? cloneData.typeInitialisers.filter(t => optionsTypes.includes(t.type))\n\t\t\t: cloneData.typeInitialisers;\n\t\tthis._contextIdKeys.push(...cloneData.contextIdKeys);\n\t\tthis._contextIds = contextIds;\n\n\t\tfor (const schemaName of Object.keys(cloneEntitySchemas)) {\n\t\t\tEntitySchemaFactory.register(schemaName, () => cloneEntitySchemas[schemaName]);\n\t\t}\n\n\t\tthis._stateStorage = new MemoryStateStorage(true, cloneData.state);\n\t\tthis._isStarted = false;\n\t}\n\n\t/**\n\t * Initialise the types from connector.\n\t * @param typeKey The key for the default types.\n\t * @param module The module containing the initialiser.\n\t * @param method The method to initialise the instance.\n\t * @returns A promise that resolves when the type configuration has been initialised.\n\t * @internal\n\t */\n\tprivate async initialiseTypeConfig(\n\t\ttypeKey: string,\n\t\tmodule: string,\n\t\tmethod: string\n\t): Promise<void> {\n\t\tconst typeConfig: IEngineCoreTypeConfig[] | undefined = this._context.config.types?.[typeKey];\n\n\t\tif (Is.arrayValue(typeConfig)) {\n\t\t\tconst instanceMethod = await ModuleHelper.getModuleEntry<EngineTypeInitialiser>(\n\t\t\t\tmodule,\n\t\t\t\tmethod\n\t\t\t);\n\n\t\t\tfor (let i = 0; i < typeConfig.length; i++) {\n\t\t\t\tawait this.logInfo(\n\t\t\t\t\tI18n.formatMessage(\"engineCore.configuring\", {\n\t\t\t\t\t\tcomponentType: typeKey,\n\t\t\t\t\t\tconfigType: typeConfig[i].type\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tconst result = instanceMethod(this, this._context, typeConfig[i]);\n\t\t\t\tconst componentCreateMethod = result.createComponent;\n\n\t\t\t\tif (Is.stringValue(result.instanceTypeName) && Is.function(componentCreateMethod)) {\n\t\t\t\t\tconst finalInstanceType = typeConfig[i].overrideInstanceType ?? result.instanceTypeName;\n\n\t\t\t\t\t// If this is a multi instance component we need to make sure we\n\t\t\t\t\t// generate a unique instance for every factory call\n\t\t\t\t\t// this is often used for REST clients where each instance might\n\t\t\t\t\t// use a different endpoint url\n\t\t\t\t\t// They are generated using the create method of factory\n\t\t\t\t\t// passing custom options, instead of the regular get method\n\t\t\t\t\t// which doesn't allow for custom options\n\t\t\t\t\tif (typeConfig[i].isMultiInstance ?? false) {\n\t\t\t\t\t\tresult.factory?.register(finalInstanceType, params =>\n\t\t\t\t\t\t\tcomponentCreateMethod({\n\t\t\t\t\t\t\t\ttype: typeConfig[i].type,\n\t\t\t\t\t\t\t\toptions: params\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst component = componentCreateMethod(typeConfig[i]);\n\t\t\t\t\t\tthis._context.componentInstances.push({\n\t\t\t\t\t\t\tinstanceType: finalInstanceType,\n\t\t\t\t\t\t\tcomponent,\n\t\t\t\t\t\t\tinitialised: false\n\t\t\t\t\t\t});\n\t\t\t\t\t\tresult.factory?.register(finalInstanceType, () => component);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._context.registeredInstances[typeKey] ??= [];\n\t\t\t\t\tthis._context.registeredInstances[typeKey].push({\n\t\t\t\t\t\ttype: finalInstanceType,\n\t\t\t\t\t\tisDefault: typeConfig[i].isDefault,\n\t\t\t\t\t\tfeatures: typeConfig[i].features\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthrow new GeneralError(\"engineCore\", \"componentUnknownType\", {\n\t\t\t\t\t\ttype: typeConfig[i].type,\n\t\t\t\t\t\tcomponentType: typeKey\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 * Setup the engine logger.\n\t * @internal\n\t */\n\tprivate setupEngineLogger(): void {\n\t\tconst logLevel =\n\t\t\tthis._context.config.logLevel ??\n\t\t\t((this._context.config.silent ?? false) ? EngineLogLevel.None : EngineLogLevel.All);\n\n\t\tlet engineLoggerConnector: ILoggingConnector;\n\t\tif (logLevel === EngineLogLevel.None) {\n\t\t\tengineLoggerConnector = new SilentLoggingConnector();\n\t\t} else {\n\t\t\tlet levels: LogLevel[] | undefined;\n\t\t\tif (logLevel === EngineLogLevel.Error) {\n\t\t\t\tlevels = [LogLevel.Error];\n\t\t\t} else if (logLevel === EngineLogLevel.Warn) {\n\t\t\t\tlevels = [LogLevel.Error, LogLevel.Warn];\n\t\t\t}\n\t\t\tengineLoggerConnector = new ConsoleLoggingConnector({\n\t\t\t\tconfig: {\n\t\t\t\t\ttranslateMessages: true,\n\t\t\t\t\thideGroups: true,\n\t\t\t\t\tlevels\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tthis._context.componentInstances.push({\n\t\t\tinstanceType: EngineCore.LOGGING_CONNECTOR_TYPE_NAME,\n\t\t\tcomponent: engineLoggerConnector,\n\t\t\tinitialised: false\n\t\t});\n\n\t\tLoggingConnectorFactory.register(\n\t\t\tEngineCore.LOGGING_CONNECTOR_TYPE_NAME,\n\t\t\t() => engineLoggerConnector\n\t\t);\n\n\t\tthis._context.registeredInstances.loggingConnector = [\n\t\t\t{\n\t\t\t\ttype: EngineCore.LOGGING_CONNECTOR_TYPE_NAME\n\t\t\t}\n\t\t];\n\n\t\tconst engineLoggerComponent = new LoggingService({\n\t\t\tloggingConnectorType: EngineCore.LOGGING_CONNECTOR_TYPE_NAME\n\t\t});\n\t\tthis._engineLoggingComponent = engineLoggerComponent;\n\n\t\tComponentFactory.register(EngineCore.LOGGING_COMPONENT_TYPE_NAME, () => engineLoggerComponent);\n\t\tthis._context.registeredInstances.loggingComponent = [\n\t\t\t{\n\t\t\t\ttype: EngineCore.LOGGING_COMPONENT_TYPE_NAME\n\t\t\t}\n\t\t];\n\t}\n\n\t/**\n\t * Log debug.\n\t * @param message The message to log.\n\t * @returns A promise that resolves when the message has been logged.\n\t * @internal\n\t */\n\tprivate async logDebug(message: string): Promise<void> {\n\t\tif (!this._context.config.silentLoggers?.includes(EngineCore.CLASS_NAME)) {\n\t\t\tawait this._engineLoggingComponent?.log({\n\t\t\t\tsource: EngineCore.CLASS_NAME,\n\t\t\t\tlevel: \"debug\",\n\t\t\t\tmessage\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Load the state.\n\t * @returns A promise that resolves when the state has been loaded.\n\t * @internal\n\t */\n\tprivate async stateLoad(): Promise<void> {\n\t\tif (this._stateStorage) {\n\t\t\ttry {\n\t\t\t\tthis._context.state = ((await this._stateStorage.load(this)) ?? {}) as S;\n\t\t\t\tthis._context.stateDirty = false;\n\t\t\t} catch (err) {\n\t\t\t\tawait this.logError(BaseError.fromError(err));\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Save the state.\n\t * @returns A promise that resolves when the state has been persisted.\n\t * @internal\n\t */\n\tprivate async stateSave(): Promise<void> {\n\t\tif (this._stateStorage && !Is.empty(this._context.state) && this._context.stateDirty) {\n\t\t\ttry {\n\t\t\t\tawait this._stateStorage.save(this, this._context.state);\n\t\t\t\tthis._context.stateDirty = false;\n\t\t\t} catch (err) {\n\t\t\t\tawait this.logError(BaseError.fromError(err));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Bootstrap the engine.\n\t * @returns A promise that resolves when bootstrapping is complete.\n\t * @internal\n\t */\n\tprivate async bootstrap(): Promise<void> {\n\t\tif (!this._skipBootstrap) {\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.bootstrapStarted`));\n\n\t\t\t// First bootstrap the components.\n\t\t\tfor (const instance of this._context.componentInstances) {\n\t\t\t\tconst bootstrapMethod = instance.component.bootstrap?.bind(instance.component);\n\t\t\t\tif (Is.function(bootstrapMethod)) {\n\t\t\t\t\tawait this.logInfo(\n\t\t\t\t\t\tI18n.formatMessage(`${nameofCamelCase<EngineCore>()}.bootstrapping`, {\n\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\tinstanceType: instance.instanceType\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\n\t\t\t\t\tconst bootstrapSuccess = await bootstrapMethod(EngineCore.LOGGING_COMPONENT_TYPE_NAME);\n\n\t\t\t\t\t// If the bootstrap method failed then throw an error\n\t\t\t\t\tif (!bootstrapSuccess) {\n\t\t\t\t\t\tthrow new GeneralError(EngineCore.CLASS_NAME, \"bootstrapFailed\", {\n\t\t\t\t\t\t\tclassName: instance.component.className(),\n\t\t\t\t\t\t\tinstanceType: instance.instanceType\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\t// Now perform any custom bootstrap operations\n\t\t\tconst customBootstrap = this._customBootstrap;\n\t\t\tif (Is.function(customBootstrap)) {\n\t\t\t\tawait customBootstrap.call(this, this, this._context);\n\t\t\t}\n\n\t\t\tawait this.logInfo(I18n.formatMessage(`${nameofCamelCase<EngineCore>()}.bootstrapComplete`));\n\t\t}\n\t}\n\n\t/**\n\t * Initialise the context ID handlers.\n\t * @internal\n\t */\n\tprivate initialiseContextIdHandlers(): void {\n\t\tfor (const contextIdKey of this._contextIdKeys) {\n\t\t\tconst handlerType: string | undefined = this.getRegisteredInstanceTypeOptional(\n\t\t\t\t\"contextIdHandlerComponent\",\n\t\t\t\tcontextIdKey.componentFeatures\n\t\t\t);\n\t\t\tif (Is.stringValue(handlerType)) {\n\t\t\t\tconst handler = ComponentFactory.get<IContextIdHandler>(handlerType);\n\t\t\t\tContextIdHandlerFactory.register(contextIdKey.key, () => handler);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { type IContextIds } from "@twin.org/context";
2
2
  import { type IComponent, type IError } from "@twin.org/core";
3
- import type { IEngineCore, IEngineCoreClone, IEngineCoreConfig, IEngineCoreContext, IEngineCoreTypeConfig, IEngineState } from "@twin.org/engine-models";
3
+ import { EngineLogLevel, type IEngineCore, type IEngineCoreClone, type IEngineCoreConfig, type IEngineCoreContext, type IEngineCoreTypeConfig, type IEngineState } from "@twin.org/engine-models";
4
4
  import type { IEngineCoreOptions } from "./models/IEngineCoreOptions.js";
5
5
  /**
6
6
  * Core for the engine.
@@ -182,7 +182,14 @@ export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig,
182
182
  * Populate the engine from the clone data.
183
183
  * @param cloneData The clone data to populate from.
184
184
  * @param contextIds The context IDs to use for the clone.
185
- * @param silent Should the clone be silent.
186
- */
187
- populateClone(cloneData: IEngineCoreClone<C, S>, contextIds?: IContextIds, silent?: boolean): void;
185
+ * @param options An optional object containing the log level, types and entity types to include.
186
+ * @param options.logLevel The log level for the clone, true maps to error level.
187
+ * @param options.types An optional allowlist of type keys to include; when omitted all types are cloned.
188
+ * @param options.entityTypes An optional allowlist of entity type names; when provided only those entity schemas and their associated storage components are cloned.
189
+ */
190
+ populateClone(cloneData: IEngineCoreClone<C, S>, contextIds?: IContextIds, options?: boolean | {
191
+ logLevel?: EngineLogLevel;
192
+ types?: string[];
193
+ entityTypes?: string[];
194
+ }): void;
188
195
  }
package/docs/changelog.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.1-next.7](https://github.com/iotaledger/twin-engine/compare/engine-core-v0.9.1-next.6...engine-core-v0.9.1-next.7) (2026-07-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * clone log-level control and per-component start timing in engine core ([#189](https://github.com/iotaledger/twin-engine/issues/189)) ([8e4e26d](https://github.com/iotaledger/twin-engine/commit/8e4e26d9992955d380ef2873ad6ad54c31faaf68))
9
+ * improved cloning ([#190](https://github.com/iotaledger/twin-engine/issues/190)) ([b43833b](https://github.com/iotaledger/twin-engine/commit/b43833b8bbcf4b1257abbe9c2552238963d3f6e2))
10
+
11
+
12
+ ### Dependencies
13
+
14
+ * The following workspace dependencies were updated
15
+ * dependencies
16
+ * @twin.org/engine-models bumped from 0.9.1-next.6 to 0.9.1-next.7
17
+
18
+ ## [0.9.1-next.6](https://github.com/iotaledger/twin-engine/compare/engine-core-v0.9.1-next.5...engine-core-v0.9.1-next.6) (2026-07-20)
19
+
20
+
21
+ ### Miscellaneous Chores
22
+
23
+ * **engine-core:** Synchronize repo versions
24
+
25
+
26
+ ### Dependencies
27
+
28
+ * The following workspace dependencies were updated
29
+ * dependencies
30
+ * @twin.org/engine-models bumped from 0.9.1-next.5 to 0.9.1-next.6
31
+
3
32
  ## [0.9.1-next.5](https://github.com/iotaledger/twin-engine/compare/engine-core-v0.9.1-next.4...engine-core-v0.9.1-next.5) (2026-07-02)
4
33
 
5
34
 
@@ -636,7 +636,7 @@ The clone data.
636
636
 
637
637
  ### populateClone() {#populateclone}
638
638
 
639
- > **populateClone**(`cloneData`, `contextIds?`, `silent?`): `void`
639
+ > **populateClone**(`cloneData`, `contextIds?`, `options?`): `void`
640
640
 
641
641
  Populate the engine from the clone data.
642
642
 
@@ -654,11 +654,39 @@ The clone data to populate from.
654
654
 
655
655
  The context IDs to use for the clone.
656
656
 
657
- ##### silent?
657
+ ##### options?
658
+
659
+ `boolean` \| \{ `logLevel?`: `EngineLogLevel`; `types?`: `string`[]; `entityTypes?`: `string`[]; \}
660
+
661
+ An optional object containing the log level, types and entity types to include.
658
662
 
659
663
  `boolean`
660
664
 
661
- Should the clone be silent.
665
+ ***
666
+
667
+ ###### Type Literal
668
+
669
+ \{ `logLevel?`: `EngineLogLevel`; `types?`: `string`[]; `entityTypes?`: `string`[]; \}
670
+
671
+ An optional object containing the log level, types and entity types to include.
672
+
673
+ ###### logLevel?
674
+
675
+ `EngineLogLevel`
676
+
677
+ The log level for the clone, true maps to error level.
678
+
679
+ ###### types?
680
+
681
+ `string`[]
682
+
683
+ An optional allowlist of type keys to include; when omitted all types are cloned.
684
+
685
+ ###### entityTypes?
686
+
687
+ `string`[]
688
+
689
+ An optional allowlist of entity type names; when provided only those entity schemas and their associated storage components are cloned.
662
690
 
663
691
  #### Returns
664
692
 
package/locales/en.json CHANGED
@@ -25,9 +25,11 @@
25
25
  "bootstrapping": "Bootstrapping component type \"{className}\" with instance type \"{instanceType}\"",
26
26
  "componentsStarting": "Components are starting",
27
27
  "componentsComplete": "Components have started",
28
+ "componentsSummary": "Components started in {totalMs}ms, slowest: {slowestComponents}",
28
29
  "componentsStopping": "Components are stopping",
29
30
  "componentsStopped": "Components have stopped",
30
31
  "componentStarting": "Starting component type \"{className}\" with instance type \"{instanceType}\"",
32
+ "componentStarted": "Started component type \"{className}\" with instance type \"{instanceType}\" in {elapsedMs}ms",
31
33
  "componentStopping": "Stopping component type \"{className}\" with instance type \"{instanceType}\""
32
34
  },
33
35
  "fileStateStorage": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/engine-core",
3
- "version": "0.9.1-next.5",
3
+ "version": "0.9.1-next.7",
4
4
  "description": "Core runtime lifecycle and state orchestration for engine instances.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,14 +11,14 @@
11
11
  "license": "Apache-2.0",
12
12
  "type": "module",
13
13
  "engines": {
14
- "node": ">=20.0.0"
14
+ "node": ">=24.0.0"
15
15
  },
16
16
  "dependencies": {
17
17
  "@twin.org/context": "next",
18
18
  "@twin.org/core": "next",
19
19
  "@twin.org/crypto": "next",
20
20
  "@twin.org/data-core": "next",
21
- "@twin.org/engine-models": "0.9.1-next.5",
21
+ "@twin.org/engine-models": "0.9.1-next.7",
22
22
  "@twin.org/entity": "next",
23
23
  "@twin.org/logging-connector-console": "next",
24
24
  "@twin.org/logging-models": "next",