@twin.org/engine-core 0.0.2-next.2 → 0.0.2-next.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,9 @@
1
- import { I18n, StringHelper, Is, ObjectHelper, BaseError, GeneralError, ErrorHelper, Guards } from '@twin.org/core';
1
+ import { isMainThread } from 'node:worker_threads';
2
+ import { I18n, StringHelper, Is, Guards, BaseError, GeneralError, ErrorHelper, ComponentFactory } from '@twin.org/core';
2
3
  import { EntitySchemaFactory } from '@twin.org/entity';
3
4
  import { ConsoleLoggingConnector } from '@twin.org/logging-connector-console';
4
5
  import { SilentLoggingConnector, LoggingConnectorFactory } from '@twin.org/logging-models';
6
+ import { LoggingService } from '@twin.org/logging-service';
5
7
  import { ModuleHelper } from '@twin.org/modules';
6
8
  import { readFile, mkdir, writeFile, stat } from 'node:fs/promises';
7
9
  import path from 'node:path';
@@ -67,13 +69,14 @@ class MemoryStateStorage {
67
69
  */
68
70
  class EngineCore {
69
71
  /**
70
- * Name for the engine logger.
72
+ * Name for the engine logger, used for direct console logging.
71
73
  */
72
- static LOGGER_TYPE_NAME = "engine";
74
+ static LOGGING_TYPE_NAME = "engine-logging-service";
73
75
  /**
74
76
  * Runtime name for the class.
77
+ * @internal
75
78
  */
76
- CLASS_NAME = "EngineCore";
79
+ static _CLASS_NAME = "EngineCore";
77
80
  /**
78
81
  * The core context.
79
82
  */
@@ -84,20 +87,15 @@ class EngineCore {
84
87
  */
85
88
  _stateStorage;
86
89
  /**
87
- * The logging connector for the engine.
90
+ * The logging component for the engine.
88
91
  * @internal
89
92
  */
90
- _engineLoggingConnector;
93
+ _engineLoggingComponent;
91
94
  /**
92
95
  * Skip the bootstrap process.
93
96
  * @internal
94
97
  */
95
98
  _skipBootstrap;
96
- /**
97
- * The logger type name to use.
98
- * @internal
99
- */
100
- _loggerTypeName;
101
99
  /**
102
100
  * The type initialisers.
103
101
  * @internal
@@ -108,6 +106,11 @@ class EngineCore {
108
106
  * @internal
109
107
  */
110
108
  _isStarted;
109
+ /**
110
+ * Is the engine a clone.
111
+ * @internal
112
+ */
113
+ _isClone;
111
114
  /**
112
115
  * Add type initialisers to the engine.
113
116
  * @internal
@@ -131,17 +134,17 @@ class EngineCore {
131
134
  this._skipBootstrap = options.skipBootstrap ?? false;
132
135
  this._populateTypeInitialisers = options.populateTypeInitialisers;
133
136
  this._customBootstrap = options.customBootstrap;
134
- this._loggerTypeName = options.loggerTypeName ?? EngineCore.LOGGER_TYPE_NAME;
135
137
  this._typeInitialisers = [];
136
138
  this._context = {
137
139
  config: options.config,
138
- defaultTypes: {},
140
+ registeredInstances: {},
139
141
  componentInstances: [],
140
- state: { componentStates: {} },
142
+ state: {},
141
143
  stateDirty: false
142
144
  };
143
145
  this._stateStorage = options.stateStorage;
144
146
  this._isStarted = false;
147
+ this._isClone = false;
145
148
  if (Is.function(this._populateTypeInitialisers)) {
146
149
  this._populateTypeInitialisers(this, this._context);
147
150
  }
@@ -149,19 +152,27 @@ class EngineCore {
149
152
  /**
150
153
  * Add a type initialiser.
151
154
  * @param type The type to add the initialiser for.
152
- * @param typeConfig The type config.
153
155
  * @param module The name of the module which contains the initialiser method.
154
156
  * @param method The name of the method to call.
155
157
  */
156
- addTypeInitialiser(type, typeConfig, module, method) {
157
- if (!Is.empty(typeConfig)) {
158
- this._typeInitialisers.push({
159
- type,
160
- typeConfig,
161
- module,
162
- method
163
- });
164
- }
158
+ addTypeInitialiser(type, module, method) {
159
+ Guards.stringValue(EngineCore._CLASS_NAME, "type", type);
160
+ Guards.stringValue(EngineCore._CLASS_NAME, "module", module);
161
+ Guards.stringValue(EngineCore._CLASS_NAME, "method", method);
162
+ this._typeInitialisers.push({
163
+ type,
164
+ module,
165
+ method
166
+ });
167
+ }
168
+ /**
169
+ * Get the type config for a specific type.
170
+ * @param type The type to get the config for.
171
+ * @returns The type config or undefined if not found.
172
+ */
173
+ getTypeConfig(type) {
174
+ Guards.stringValue(EngineCore._CLASS_NAME, "type", type);
175
+ return this._context.config.types?.[type];
165
176
  }
166
177
  /**
167
178
  * Start the engine core.
@@ -172,37 +183,30 @@ class EngineCore {
172
183
  return false;
173
184
  }
174
185
  this.setupEngineLogger();
175
- this.logInfo(I18n.formatMessage("engineCore.starting"));
186
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.starting`));
176
187
  if (this._context.config.debug) {
177
- this.logInfo(I18n.formatMessage("engineCore.debuggingEnabled"));
188
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.debuggingEnabled`));
178
189
  }
179
190
  let canContinue;
180
191
  try {
181
192
  canContinue = await this.stateLoad();
182
193
  if (canContinue) {
183
- for (const { type, typeConfig, module, method } of this._typeInitialisers) {
184
- await this.initialiseTypeConfig(type, typeConfig, module, method);
194
+ for (const { type, module, method } of this._typeInitialisers) {
195
+ await this.initialiseTypeConfig(type, module, method);
185
196
  }
186
197
  await this.bootstrap();
187
- this.logInfo(I18n.formatMessage("engineCore.componentsStarting"));
198
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.componentsStarting`));
188
199
  for (const instance of this._context.componentInstances) {
189
200
  if (Is.function(instance.component.start)) {
190
- const instanceName = this.getInstanceName(instance);
191
- this.logInfo(I18n.formatMessage("engineCore.componentStarting", {
201
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.componentStarting`, {
192
202
  element: instance.instanceType
193
203
  }));
194
- const componentState = this._context.state.componentStates[instanceName] ?? {};
195
- const lastState = ObjectHelper.clone(componentState);
196
- await instance.component.start(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
197
- if (!ObjectHelper.equal(lastState, componentState)) {
198
- this._context.state.componentStates[instanceName] = componentState;
199
- this._context.stateDirty = true;
200
- }
204
+ await instance.component.start(this._context.state.nodeIdentity, EngineCore.LOGGING_TYPE_NAME);
201
205
  }
202
206
  }
203
- this.logInfo(I18n.formatMessage("engineCore.componentsComplete"));
207
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.componentsComplete`));
204
208
  }
205
- this.logInfo(I18n.formatMessage("engineCore.started"));
209
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.started`));
206
210
  this._isStarted = true;
207
211
  }
208
212
  catch (err) {
@@ -221,39 +225,55 @@ class EngineCore {
221
225
  * @returns Nothing.
222
226
  */
223
227
  async stop() {
224
- this.logInfo(I18n.formatMessage("engineCore.stopping"));
225
- this.logInfo(I18n.formatMessage("engineCore.componentsStopping"));
228
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.stopping`));
229
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.componentsStopping`));
226
230
  for (const instance of this._context.componentInstances) {
227
231
  if (Is.function(instance.component.stop)) {
228
- const instanceName = this.getInstanceName(instance);
229
- const componentState = this._context.state.componentStates[instanceName] ?? {};
230
- const lastState = ObjectHelper.clone(componentState);
231
- this.logInfo(I18n.formatMessage("engineCore.componentStopping", { element: instance.instanceType }));
232
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.componentStopping`, {
233
+ element: instance.instanceType
234
+ }));
232
235
  try {
233
- await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
234
- if (!ObjectHelper.equal(lastState, componentState)) {
235
- this._context.state.componentStates[instanceName] = componentState;
236
- this._context.stateDirty = true;
237
- }
236
+ await instance.component.stop(this._context.state.nodeIdentity, EngineCore.LOGGING_TYPE_NAME);
238
237
  }
239
238
  catch (err) {
240
- this.logError(new GeneralError(this.CLASS_NAME, "componentStopFailed", {
239
+ this.logError(new GeneralError(EngineCore._CLASS_NAME, "componentStopFailed", {
241
240
  component: instance.instanceType
242
241
  }, BaseError.fromError(err)));
243
242
  }
244
243
  }
245
244
  }
246
245
  await this.stateSave();
247
- this.logInfo(I18n.formatMessage("engineCore.componentsStopped"));
248
- this.logInfo(I18n.formatMessage("engineCore.stopped"));
246
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.componentsStopped`));
247
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.stopped`));
248
+ }
249
+ /**
250
+ * Is the engine started.
251
+ * @returns True if the engine is started.
252
+ */
253
+ isStarted() {
254
+ return this._isStarted;
255
+ }
256
+ /**
257
+ * Is this the primary engine instance.
258
+ * @returns True if the engine is the primary instance.
259
+ */
260
+ isPrimary() {
261
+ return isMainThread && !this._isClone;
262
+ }
263
+ /**
264
+ * Is this engine instance a clone.
265
+ * @returns True if the engine instance is a clone.
266
+ */
267
+ isClone() {
268
+ return this._isClone;
249
269
  }
250
270
  /**
251
271
  * Log info.
252
272
  * @param message The message to log.
253
273
  */
254
274
  logInfo(message) {
255
- this._engineLoggingConnector?.log({
256
- source: this.CLASS_NAME,
275
+ this._engineLoggingComponent?.log({
276
+ source: EngineCore._CLASS_NAME,
257
277
  level: "info",
258
278
  message
259
279
  });
@@ -271,8 +291,8 @@ class EngineCore {
271
291
  if (this._context.config.debug && Is.stringValue(formattedError.stack)) {
272
292
  message += `\n${formattedError.stack}`;
273
293
  }
274
- this._engineLoggingConnector?.log({
275
- source: this.CLASS_NAME,
294
+ this._engineLoggingComponent?.log({
295
+ source: EngineCore._CLASS_NAME,
276
296
  level: "error",
277
297
  message
278
298
  });
@@ -293,11 +313,48 @@ class EngineCore {
293
313
  return this._context.state;
294
314
  }
295
315
  /**
296
- * Get the types for the component.
297
- * @returns The default types.
316
+ * Get all the registered instances.
317
+ * @returns The registered instances.
298
318
  */
299
- getDefaultTypes() {
300
- return this._context.defaultTypes;
319
+ getRegisteredInstances() {
320
+ return this._context.registeredInstances;
321
+ }
322
+ /**
323
+ * Get the registered instance type for the component/connector.
324
+ * @param componentConnectorType The type of the component/connector.
325
+ * @param features The requested features of the component, if not specified the default entry will be retrieved.
326
+ * @returns The instance type matching the criteria if one is registered.
327
+ * @throws If a matching instance was not found.
328
+ */
329
+ getRegisteredInstanceType(componentConnectorType, features) {
330
+ Guards.stringValue(EngineCore._CLASS_NAME, "componentConnectorType", componentConnectorType);
331
+ const registeredType = this.getRegisteredInstanceTypeOptional(componentConnectorType, features);
332
+ if (!Is.stringValue(registeredType)) {
333
+ throw new GeneralError(EngineCore._CLASS_NAME, "instanceTypeNotFound", {
334
+ type: componentConnectorType,
335
+ features: (features ?? ["default"]).join(",")
336
+ });
337
+ }
338
+ return registeredType;
339
+ }
340
+ /**
341
+ * Get the registered instance type for the component/connector if it exists.
342
+ * @param componentConnectorType The type of the component/connector.
343
+ * @param features The requested features of the component, if not specified the default entry will be retrieved.
344
+ * @returns The instance type matching the criteria if one is registered.
345
+ */
346
+ getRegisteredInstanceTypeOptional(componentConnectorType, features) {
347
+ let registeredType;
348
+ const registeredTypes = this._context.registeredInstances[componentConnectorType];
349
+ if (Is.arrayValue(registeredTypes)) {
350
+ if (Is.arrayValue(features)) {
351
+ registeredType = registeredTypes.find(t => t.features?.every(f => features.includes(f)))?.type;
352
+ }
353
+ else {
354
+ registeredType = registeredTypes[0]?.type;
355
+ }
356
+ }
357
+ return registeredType;
301
358
  }
302
359
  /**
303
360
  * Get the data required to create a clone of the engine.
@@ -313,8 +370,7 @@ class EngineCore {
313
370
  config: this._context.config,
314
371
  state: this._context.state,
315
372
  typeInitialisers: this._typeInitialisers,
316
- entitySchemas,
317
- loggerTypeName: this._loggerTypeName
373
+ entitySchemas
318
374
  };
319
375
  return cloneData;
320
376
  }
@@ -324,20 +380,20 @@ class EngineCore {
324
380
  * @param silent Should the clone be silent.
325
381
  */
326
382
  populateClone(cloneData, silent) {
327
- Guards.object(this.CLASS_NAME, "cloneData", cloneData);
328
- Guards.object(this.CLASS_NAME, "cloneData.config", cloneData.config);
329
- Guards.object(this.CLASS_NAME, "cloneData.state", cloneData.state);
330
- Guards.array(this.CLASS_NAME, "cloneData.typeInitialisers", cloneData.typeInitialisers);
331
- this._loggerTypeName = cloneData.loggerTypeName;
383
+ Guards.object(EngineCore._CLASS_NAME, "cloneData", cloneData);
384
+ Guards.object(EngineCore._CLASS_NAME, "cloneData.config", cloneData.config);
385
+ Guards.object(EngineCore._CLASS_NAME, "cloneData.state", cloneData.state);
386
+ Guards.array(EngineCore._CLASS_NAME, "cloneData.typeInitialisers", cloneData.typeInitialisers);
332
387
  this._skipBootstrap = true;
388
+ this._isClone = true;
333
389
  if (silent ?? false) {
334
390
  cloneData.config.silent = true;
335
391
  }
336
392
  this._context = {
337
393
  config: cloneData.config,
338
- defaultTypes: {},
394
+ registeredInstances: {},
339
395
  componentInstances: [],
340
- state: { componentStates: {} },
396
+ state: {},
341
397
  stateDirty: false
342
398
  };
343
399
  this._typeInitialisers = cloneData.typeInitialisers;
@@ -353,14 +409,41 @@ class EngineCore {
353
409
  * @param instanceMethod The function to initialise the instance.
354
410
  * @internal
355
411
  */
356
- async initialiseTypeConfig(typeKey, typeConfig, module, method) {
412
+ async initialiseTypeConfig(typeKey, module, method) {
413
+ const typeConfig = this._context.config.types?.[typeKey];
357
414
  if (Is.arrayValue(typeConfig)) {
358
415
  const instanceMethod = await ModuleHelper.getModuleEntry(module, method);
359
416
  for (let i = 0; i < typeConfig.length; i++) {
360
- const instanceType = instanceMethod(this, this._context, typeConfig[i], typeConfig[i].overrideInstanceType);
361
- if (Is.stringValue(instanceType) &&
362
- (Is.empty(this._context.defaultTypes[typeKey]) || typeConfig[i].isDefault)) {
363
- this._context.defaultTypes[typeKey] = instanceType;
417
+ this.logInfo(I18n.formatMessage("engineCore.configuring", {
418
+ element: `${typeKey}: ${typeConfig[i].type}`
419
+ }));
420
+ const result = await instanceMethod(this, this._context, typeConfig[i]);
421
+ if (Is.stringValue(result.instanceType) && Is.object(result.component)) {
422
+ const finalInstanceType = typeConfig[i].overrideInstanceType ?? result.instanceType;
423
+ this._context.componentInstances.push({
424
+ instanceType: finalInstanceType,
425
+ component: result.component
426
+ });
427
+ result.factory?.register(finalInstanceType, () => result.component);
428
+ this._context.registeredInstances[typeKey] ??= [];
429
+ if (typeConfig[i].isDefault ?? false) {
430
+ this._context.registeredInstances[typeKey].unshift({
431
+ type: finalInstanceType,
432
+ features: typeConfig[i].features
433
+ });
434
+ }
435
+ else {
436
+ this._context.registeredInstances[typeKey].push({
437
+ type: finalInstanceType,
438
+ features: typeConfig[i].features
439
+ });
440
+ }
441
+ }
442
+ else {
443
+ throw new GeneralError("engineCore", "componentUnknownType", {
444
+ type: typeConfig[i].type,
445
+ componentType: typeKey
446
+ });
364
447
  }
365
448
  }
366
449
  }
@@ -371,7 +454,7 @@ class EngineCore {
371
454
  */
372
455
  setupEngineLogger() {
373
456
  const silent = this._context.config.silent ?? false;
374
- const engineLogger = silent
457
+ const engineLoggerConnector = silent
375
458
  ? new SilentLoggingConnector()
376
459
  : new ConsoleLoggingConnector({
377
460
  config: {
@@ -380,12 +463,25 @@ class EngineCore {
380
463
  }
381
464
  });
382
465
  this._context.componentInstances.push({
383
- instanceType: this._loggerTypeName,
384
- component: engineLogger
466
+ instanceType: EngineCore.LOGGING_TYPE_NAME,
467
+ component: engineLoggerConnector
385
468
  });
386
- LoggingConnectorFactory.register(this._loggerTypeName, () => engineLogger);
387
- this._engineLoggingConnector = engineLogger;
388
- this._context.defaultTypes.loggingConnector = this._loggerTypeName;
469
+ LoggingConnectorFactory.register(EngineCore.LOGGING_TYPE_NAME, () => engineLoggerConnector);
470
+ this._context.registeredInstances.loggingConnector = [
471
+ {
472
+ type: EngineCore.LOGGING_TYPE_NAME
473
+ }
474
+ ];
475
+ const engineLoggerComponent = new LoggingService({
476
+ loggingConnectorType: EngineCore.LOGGING_TYPE_NAME
477
+ });
478
+ this._engineLoggingComponent = engineLoggerComponent;
479
+ ComponentFactory.register(EngineCore.LOGGING_TYPE_NAME, () => engineLoggerComponent);
480
+ this._context.registeredInstances.loggingComponent = [
481
+ {
482
+ type: EngineCore.LOGGING_TYPE_NAME
483
+ }
484
+ ];
389
485
  }
390
486
  /**
391
487
  * Load the state.
@@ -395,10 +491,7 @@ class EngineCore {
395
491
  async stateLoad() {
396
492
  if (this._stateStorage) {
397
493
  try {
398
- this._context.state = ((await this._stateStorage.load(this)) ?? {
399
- componentStates: {}
400
- });
401
- this._context.state.componentStates ??= {};
494
+ this._context.state = ((await this._stateStorage.load(this)) ?? {});
402
495
  this._context.stateDirty = false;
403
496
  return true;
404
497
  }
@@ -434,34 +527,28 @@ class EngineCore {
434
527
  */
435
528
  async bootstrap() {
436
529
  if (!this._skipBootstrap) {
437
- this.logInfo(I18n.formatMessage("engineCore.bootstrapStarted"));
530
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.bootstrapStarted`));
438
531
  // First bootstrap the components.
439
532
  for (const instance of this._context.componentInstances) {
440
533
  if (Is.function(instance.component.bootstrap)) {
441
534
  const instanceName = this.getInstanceName(instance);
442
- this.logInfo(I18n.formatMessage("engineCore.bootstrapping", {
535
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.bootstrapping`, {
443
536
  element: instanceName
444
537
  }));
445
- const componentState = this._context.state.componentStates[instanceName] ?? {};
446
- const lastState = ObjectHelper.clone(componentState);
447
- const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName, componentState);
538
+ const bootstrapSuccess = await instance.component.bootstrap(EngineCore.LOGGING_TYPE_NAME);
448
539
  // If the bootstrap method failed then throw an error
449
540
  if (!bootstrapSuccess) {
450
- throw new GeneralError(this.CLASS_NAME, "bootstrapFailed", {
541
+ throw new GeneralError(EngineCore._CLASS_NAME, "bootstrapFailed", {
451
542
  component: `${instance.component.CLASS_NAME}:${instance.instanceType}`
452
543
  });
453
544
  }
454
- if (!ObjectHelper.equal(lastState, componentState)) {
455
- this._context.state.componentStates[instanceName] = componentState;
456
- this._context.stateDirty = true;
457
- }
458
545
  }
459
546
  }
460
547
  // Now perform any custom bootstrap operations
461
548
  if (Is.function(this._customBootstrap)) {
462
549
  await this._customBootstrap(this, this._context);
463
550
  }
464
- this.logInfo(I18n.formatMessage("engineCore.bootstrapComplete"));
551
+ this.logInfo(I18n.formatMessage(`${"engineCore"}.bootstrapComplete`));
465
552
  }
466
553
  }
467
554
  /**
@@ -566,4 +653,48 @@ class FileStateStorage {
566
653
  }
567
654
  }
568
655
 
569
- export { EngineCore, FileStateStorage, MemoryStateStorage };
656
+ // Copyright 2024 IOTA Stiftung.
657
+ // SPDX-License-Identifier: Apache-2.0.
658
+ /**
659
+ * Helper class for engine modules.
660
+ */
661
+ class EngineModuleHelper {
662
+ /**
663
+ * Runtime name for the class.
664
+ */
665
+ static CLASS_NAME = "EngineModuleHelper";
666
+ /**
667
+ * Loads an engine component and constructs it with the relevant dependencies and configuration.
668
+ * @param engineCore The engine core.
669
+ * @param engineModuleConfig The configuration for the module.
670
+ * @returns The instantiated component.
671
+ */
672
+ static async loadComponent(engineCore, engineModuleConfig) {
673
+ const moduleClass = await ModuleHelper.getModuleEntry(engineModuleConfig.moduleName, engineModuleConfig.className);
674
+ const isClass = Is.class(moduleClass);
675
+ if (!isClass) {
676
+ throw new GeneralError(EngineModuleHelper.CLASS_NAME, "moduleNotClass", {
677
+ moduleName: engineModuleConfig.moduleName,
678
+ className: engineModuleConfig.className
679
+ });
680
+ }
681
+ const constructorOptions = {};
682
+ if (Is.arrayValue(engineModuleConfig.dependencies)) {
683
+ for (const dependency of engineModuleConfig.dependencies) {
684
+ if (dependency.isOptional ?? false) {
685
+ constructorOptions[dependency.propertyName] = engineCore.getRegisteredInstanceType(dependency.componentName, dependency.features);
686
+ }
687
+ else {
688
+ constructorOptions[dependency.propertyName] =
689
+ engineCore.getRegisteredInstanceTypeOptional(dependency.componentName, dependency.features);
690
+ }
691
+ }
692
+ }
693
+ if (Is.object(engineModuleConfig.config)) {
694
+ constructorOptions.config = engineModuleConfig.config;
695
+ }
696
+ return new moduleClass(constructorOptions);
697
+ }
698
+ }
699
+
700
+ export { EngineCore, EngineModuleHelper, FileStateStorage, MemoryStateStorage };
@@ -6,13 +6,9 @@ import type { IEngineCoreOptions } from "./models/IEngineCoreOptions";
6
6
  */
7
7
  export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig, S extends IEngineState = IEngineState> implements IEngineCore<C, S> {
8
8
  /**
9
- * Name for the engine logger.
9
+ * Name for the engine logger, used for direct console logging.
10
10
  */
11
- static readonly LOGGER_TYPE_NAME: string;
12
- /**
13
- * Runtime name for the class.
14
- */
15
- readonly CLASS_NAME: string;
11
+ static readonly LOGGING_TYPE_NAME: string;
16
12
  /**
17
13
  * The core context.
18
14
  */
@@ -25,11 +21,16 @@ export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig,
25
21
  /**
26
22
  * Add a type initialiser.
27
23
  * @param type The type to add the initialiser for.
28
- * @param typeConfig The type config.
29
24
  * @param module The name of the module which contains the initialiser method.
30
25
  * @param method The name of the method to call.
31
26
  */
32
- addTypeInitialiser(type: string, typeConfig: IEngineCoreTypeConfig[] | undefined, module: string, method: string): void;
27
+ addTypeInitialiser(type: string, module: string, method: string): void;
28
+ /**
29
+ * Get the type config for a specific type.
30
+ * @param type The type to get the config for.
31
+ * @returns The type config or undefined if not found.
32
+ */
33
+ getTypeConfig(type: string): IEngineCoreTypeConfig[] | undefined;
33
34
  /**
34
35
  * Start the engine core.
35
36
  * @returns True if the start was successful.
@@ -40,6 +41,21 @@ export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig,
40
41
  * @returns Nothing.
41
42
  */
42
43
  stop(): Promise<void>;
44
+ /**
45
+ * Is the engine started.
46
+ * @returns True if the engine is started.
47
+ */
48
+ isStarted(): boolean;
49
+ /**
50
+ * Is this the primary engine instance.
51
+ * @returns True if the engine is the primary instance.
52
+ */
53
+ isPrimary(): boolean;
54
+ /**
55
+ * Is this engine instance a clone.
56
+ * @returns True if the engine instance is a clone.
57
+ */
58
+ isClone(): boolean;
43
59
  /**
44
60
  * Log info.
45
61
  * @param message The message to log.
@@ -61,12 +77,30 @@ export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig,
61
77
  */
62
78
  getState(): S;
63
79
  /**
64
- * Get the types for the component.
65
- * @returns The default types.
80
+ * Get all the registered instances.
81
+ * @returns The registered instances.
66
82
  */
67
- getDefaultTypes(): {
68
- [type: string]: string;
83
+ getRegisteredInstances(): {
84
+ [name: string]: {
85
+ type: string;
86
+ features?: string[];
87
+ }[];
69
88
  };
89
+ /**
90
+ * Get the registered instance type for the component/connector.
91
+ * @param componentConnectorType The type of the component/connector.
92
+ * @param features The requested features of the component, if not specified the default entry will be retrieved.
93
+ * @returns The instance type matching the criteria if one is registered.
94
+ * @throws If a matching instance was not found.
95
+ */
96
+ getRegisteredInstanceType(componentConnectorType: string, features?: string[]): string;
97
+ /**
98
+ * Get the registered instance type for the component/connector if it exists.
99
+ * @param componentConnectorType The type of the component/connector.
100
+ * @param features The requested features of the component, if not specified the default entry will be retrieved.
101
+ * @returns The instance type matching the criteria if one is registered.
102
+ */
103
+ getRegisteredInstanceTypeOptional(componentConnectorType: string, features?: string[]): string | undefined;
70
104
  /**
71
105
  * Get the data required to create a clone of the engine.
72
106
  * @returns The clone data.
@@ -2,3 +2,4 @@ export * from "./engineCore";
2
2
  export * from "./models/IEngineCoreOptions";
3
3
  export * from "./storage/fileStateStorage";
4
4
  export * from "./storage/memoryStateStorage";
5
+ export * from "./utils/engineModuleHelper";
@@ -23,9 +23,4 @@ export interface IEngineCoreOptions<C extends IEngineCoreConfig = IEngineCoreCon
23
23
  * Custom bootstrap method for the engine.
24
24
  */
25
25
  customBootstrap?: (engineCore: IEngineCore<C, S>, context: IEngineCoreContext<C, S>) => Promise<void>;
26
- /**
27
- * The name of the logger to use in the engine.
28
- * @default engine
29
- */
30
- loggerTypeName?: string;
31
26
  }
@@ -0,0 +1,17 @@
1
+ import type { IEngineCore, IEngineModuleConfig } from "@twin.org/engine-models";
2
+ /**
3
+ * Helper class for engine modules.
4
+ */
5
+ export declare class EngineModuleHelper {
6
+ /**
7
+ * Runtime name for the class.
8
+ */
9
+ static readonly CLASS_NAME: string;
10
+ /**
11
+ * Loads an engine component and constructs it with the relevant dependencies and configuration.
12
+ * @param engineCore The engine core.
13
+ * @param engineModuleConfig The configuration for the module.
14
+ * @returns The instantiated component.
15
+ */
16
+ static loadComponent<T>(engineCore: IEngineCore, engineModuleConfig: IEngineModuleConfig): Promise<T>;
17
+ }