@twin.org/engine-core 0.0.2-next.4 → 0.0.2-next.6
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.
- package/dist/cjs/index.cjs +103 -39
- package/dist/esm/index.mjs +103 -39
- package/dist/types/engineCore.d.ts +22 -8
- package/docs/changelog.md +28 -0
- package/docs/reference/classes/EngineCore.md +73 -13
- package/locales/en.json +2 -1
- package/package.json +2 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -73,10 +73,16 @@ class EngineCore {
|
|
|
73
73
|
* Name for the engine logger.
|
|
74
74
|
*/
|
|
75
75
|
static LOGGER_TYPE_NAME = "engine";
|
|
76
|
+
/**
|
|
77
|
+
* Runtime name for the class in camel case.
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
static _CLASS_NAME_CAMEL_CASE = core.StringHelper.camelCase("EngineCore");
|
|
76
81
|
/**
|
|
77
82
|
* Runtime name for the class.
|
|
83
|
+
* @internal
|
|
78
84
|
*/
|
|
79
|
-
|
|
85
|
+
static _CLASS_NAME = "EngineCore";
|
|
80
86
|
/**
|
|
81
87
|
* The core context.
|
|
82
88
|
*/
|
|
@@ -87,10 +93,10 @@ class EngineCore {
|
|
|
87
93
|
*/
|
|
88
94
|
_stateStorage;
|
|
89
95
|
/**
|
|
90
|
-
* The logging
|
|
96
|
+
* The logging component for the engine.
|
|
91
97
|
* @internal
|
|
92
98
|
*/
|
|
93
|
-
|
|
99
|
+
_engineLoggingComponent;
|
|
94
100
|
/**
|
|
95
101
|
* Skip the bootstrap process.
|
|
96
102
|
* @internal
|
|
@@ -138,7 +144,7 @@ class EngineCore {
|
|
|
138
144
|
this._typeInitialisers = [];
|
|
139
145
|
this._context = {
|
|
140
146
|
config: options.config,
|
|
141
|
-
|
|
147
|
+
registeredInstances: {},
|
|
142
148
|
componentInstances: [],
|
|
143
149
|
state: { componentStates: {} },
|
|
144
150
|
stateDirty: false
|
|
@@ -175,9 +181,9 @@ class EngineCore {
|
|
|
175
181
|
return false;
|
|
176
182
|
}
|
|
177
183
|
this.setupEngineLogger();
|
|
178
|
-
this.logInfo(core.I18n.formatMessage(
|
|
184
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.starting`));
|
|
179
185
|
if (this._context.config.debug) {
|
|
180
|
-
this.logInfo(core.I18n.formatMessage(
|
|
186
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.debuggingEnabled`));
|
|
181
187
|
}
|
|
182
188
|
let canContinue;
|
|
183
189
|
try {
|
|
@@ -187,11 +193,11 @@ class EngineCore {
|
|
|
187
193
|
await this.initialiseTypeConfig(type, typeConfig, module, method);
|
|
188
194
|
}
|
|
189
195
|
await this.bootstrap();
|
|
190
|
-
this.logInfo(core.I18n.formatMessage(
|
|
196
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStarting`));
|
|
191
197
|
for (const instance of this._context.componentInstances) {
|
|
192
198
|
if (core.Is.function(instance.component.start)) {
|
|
193
199
|
const instanceName = this.getInstanceName(instance);
|
|
194
|
-
this.logInfo(core.I18n.formatMessage(
|
|
200
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentStarting`, {
|
|
195
201
|
element: instance.instanceType
|
|
196
202
|
}));
|
|
197
203
|
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
@@ -203,9 +209,9 @@ class EngineCore {
|
|
|
203
209
|
}
|
|
204
210
|
}
|
|
205
211
|
}
|
|
206
|
-
this.logInfo(core.I18n.formatMessage(
|
|
212
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsComplete`));
|
|
207
213
|
}
|
|
208
|
-
this.logInfo(core.I18n.formatMessage(
|
|
214
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.started`));
|
|
209
215
|
this._isStarted = true;
|
|
210
216
|
}
|
|
211
217
|
catch (err) {
|
|
@@ -224,14 +230,16 @@ class EngineCore {
|
|
|
224
230
|
* @returns Nothing.
|
|
225
231
|
*/
|
|
226
232
|
async stop() {
|
|
227
|
-
this.logInfo(core.I18n.formatMessage(
|
|
228
|
-
this.logInfo(core.I18n.formatMessage(
|
|
233
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.stopping`));
|
|
234
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStopping`));
|
|
229
235
|
for (const instance of this._context.componentInstances) {
|
|
230
236
|
if (core.Is.function(instance.component.stop)) {
|
|
231
237
|
const instanceName = this.getInstanceName(instance);
|
|
232
238
|
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
233
239
|
const lastState = core.ObjectHelper.clone(componentState);
|
|
234
|
-
this.logInfo(core.I18n.formatMessage(
|
|
240
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentStopping`, {
|
|
241
|
+
element: instance.instanceType
|
|
242
|
+
}));
|
|
235
243
|
try {
|
|
236
244
|
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
|
|
237
245
|
if (!core.ObjectHelper.equal(lastState, componentState)) {
|
|
@@ -240,23 +248,23 @@ class EngineCore {
|
|
|
240
248
|
}
|
|
241
249
|
}
|
|
242
250
|
catch (err) {
|
|
243
|
-
this.logError(new core.GeneralError(
|
|
251
|
+
this.logError(new core.GeneralError(EngineCore._CLASS_NAME, "componentStopFailed", {
|
|
244
252
|
component: instance.instanceType
|
|
245
253
|
}, core.BaseError.fromError(err)));
|
|
246
254
|
}
|
|
247
255
|
}
|
|
248
256
|
}
|
|
249
257
|
await this.stateSave();
|
|
250
|
-
this.logInfo(core.I18n.formatMessage(
|
|
251
|
-
this.logInfo(core.I18n.formatMessage(
|
|
258
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStopped`));
|
|
259
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.stopped`));
|
|
252
260
|
}
|
|
253
261
|
/**
|
|
254
262
|
* Log info.
|
|
255
263
|
* @param message The message to log.
|
|
256
264
|
*/
|
|
257
265
|
logInfo(message) {
|
|
258
|
-
this.
|
|
259
|
-
source:
|
|
266
|
+
this._engineLoggingComponent?.log({
|
|
267
|
+
source: EngineCore._CLASS_NAME,
|
|
260
268
|
level: "info",
|
|
261
269
|
message
|
|
262
270
|
});
|
|
@@ -274,8 +282,8 @@ class EngineCore {
|
|
|
274
282
|
if (this._context.config.debug && core.Is.stringValue(formattedError.stack)) {
|
|
275
283
|
message += `\n${formattedError.stack}`;
|
|
276
284
|
}
|
|
277
|
-
this.
|
|
278
|
-
source:
|
|
285
|
+
this._engineLoggingComponent?.log({
|
|
286
|
+
source: EngineCore._CLASS_NAME,
|
|
279
287
|
level: "error",
|
|
280
288
|
message
|
|
281
289
|
});
|
|
@@ -296,11 +304,48 @@ class EngineCore {
|
|
|
296
304
|
return this._context.state;
|
|
297
305
|
}
|
|
298
306
|
/**
|
|
299
|
-
* Get the
|
|
300
|
-
* @returns The
|
|
307
|
+
* Get all the registered instances.
|
|
308
|
+
* @returns The registered instances.
|
|
301
309
|
*/
|
|
302
|
-
|
|
303
|
-
return this._context.
|
|
310
|
+
getRegisteredInstances() {
|
|
311
|
+
return this._context.registeredInstances;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Get the registered instance type for the component/connector.
|
|
315
|
+
* @param componentConnectorType The type of the component/connector.
|
|
316
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
317
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
318
|
+
* @throws If a matching instance was not found.
|
|
319
|
+
*/
|
|
320
|
+
getRegisteredInstanceType(componentConnectorType, features) {
|
|
321
|
+
core.Guards.stringValue(EngineCore._CLASS_NAME, "componentConnectorType", componentConnectorType);
|
|
322
|
+
const registeredType = this.getRegisteredInstanceTypeOptional(componentConnectorType, features);
|
|
323
|
+
if (!core.Is.stringValue(registeredType)) {
|
|
324
|
+
throw new core.GeneralError(EngineCore._CLASS_NAME, "instanceTypeNotFound", {
|
|
325
|
+
type: componentConnectorType,
|
|
326
|
+
features: (features ?? ["default"]).join(",")
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
return registeredType;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get the registered instance type for the component/connector if it exists.
|
|
333
|
+
* @param componentConnectorType The type of the component/connector.
|
|
334
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
335
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
336
|
+
*/
|
|
337
|
+
getRegisteredInstanceTypeOptional(componentConnectorType, features) {
|
|
338
|
+
let registeredType;
|
|
339
|
+
const registeredTypes = this._context.registeredInstances[componentConnectorType];
|
|
340
|
+
if (core.Is.arrayValue(registeredTypes)) {
|
|
341
|
+
if (core.Is.arrayValue(features)) {
|
|
342
|
+
registeredType = registeredTypes.find(t => t.features?.every(f => features.includes(f)))?.type;
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
registeredType = registeredTypes[0]?.type;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return registeredType;
|
|
304
349
|
}
|
|
305
350
|
/**
|
|
306
351
|
* Get the data required to create a clone of the engine.
|
|
@@ -327,10 +372,10 @@ class EngineCore {
|
|
|
327
372
|
* @param silent Should the clone be silent.
|
|
328
373
|
*/
|
|
329
374
|
populateClone(cloneData, silent) {
|
|
330
|
-
core.Guards.object(
|
|
331
|
-
core.Guards.object(
|
|
332
|
-
core.Guards.object(
|
|
333
|
-
core.Guards.array(
|
|
375
|
+
core.Guards.object(EngineCore._CLASS_NAME, "cloneData", cloneData);
|
|
376
|
+
core.Guards.object(EngineCore._CLASS_NAME, "cloneData.config", cloneData.config);
|
|
377
|
+
core.Guards.object(EngineCore._CLASS_NAME, "cloneData.state", cloneData.state);
|
|
378
|
+
core.Guards.array(EngineCore._CLASS_NAME, "cloneData.typeInitialisers", cloneData.typeInitialisers);
|
|
334
379
|
this._loggerTypeName = cloneData.loggerTypeName;
|
|
335
380
|
this._skipBootstrap = true;
|
|
336
381
|
if (silent ?? false) {
|
|
@@ -338,7 +383,7 @@ class EngineCore {
|
|
|
338
383
|
}
|
|
339
384
|
this._context = {
|
|
340
385
|
config: cloneData.config,
|
|
341
|
-
|
|
386
|
+
registeredInstances: {},
|
|
342
387
|
componentInstances: [],
|
|
343
388
|
state: { componentStates: {} },
|
|
344
389
|
stateDirty: false
|
|
@@ -361,9 +406,20 @@ class EngineCore {
|
|
|
361
406
|
const instanceMethod = await modules.ModuleHelper.getModuleEntry(module, method);
|
|
362
407
|
for (let i = 0; i < typeConfig.length; i++) {
|
|
363
408
|
const instanceType = instanceMethod(this, this._context, typeConfig[i], typeConfig[i].overrideInstanceType);
|
|
364
|
-
if (core.Is.stringValue(instanceType)
|
|
365
|
-
|
|
366
|
-
|
|
409
|
+
if (core.Is.stringValue(instanceType)) {
|
|
410
|
+
this._context.registeredInstances[typeKey] ??= [];
|
|
411
|
+
if (typeConfig[i].isDefault ?? false) {
|
|
412
|
+
this._context.registeredInstances[typeKey].unshift({
|
|
413
|
+
type: instanceType,
|
|
414
|
+
features: typeConfig[i].features
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
this._context.registeredInstances[typeKey].push({
|
|
419
|
+
type: instanceType,
|
|
420
|
+
features: typeConfig[i].features
|
|
421
|
+
});
|
|
422
|
+
}
|
|
367
423
|
}
|
|
368
424
|
}
|
|
369
425
|
}
|
|
@@ -387,13 +443,21 @@ class EngineCore {
|
|
|
387
443
|
component: engineLoggerConnector
|
|
388
444
|
});
|
|
389
445
|
loggingModels.LoggingConnectorFactory.register(this._loggerTypeName, () => engineLoggerConnector);
|
|
390
|
-
this.
|
|
391
|
-
|
|
446
|
+
this._context.registeredInstances.loggingConnector = [
|
|
447
|
+
{
|
|
448
|
+
type: this._loggerTypeName
|
|
449
|
+
}
|
|
450
|
+
];
|
|
392
451
|
const engineLoggerComponent = new loggingService.LoggingService({
|
|
393
452
|
loggingConnectorType: this._loggerTypeName
|
|
394
453
|
});
|
|
454
|
+
this._engineLoggingComponent = engineLoggerComponent;
|
|
395
455
|
core.ComponentFactory.register("logging-service", () => engineLoggerComponent);
|
|
396
|
-
this._context.
|
|
456
|
+
this._context.registeredInstances.loggingComponent = [
|
|
457
|
+
{
|
|
458
|
+
type: "logging-service"
|
|
459
|
+
}
|
|
460
|
+
];
|
|
397
461
|
}
|
|
398
462
|
/**
|
|
399
463
|
* Load the state.
|
|
@@ -442,12 +506,12 @@ class EngineCore {
|
|
|
442
506
|
*/
|
|
443
507
|
async bootstrap() {
|
|
444
508
|
if (!this._skipBootstrap) {
|
|
445
|
-
this.logInfo(core.I18n.formatMessage(
|
|
509
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapStarted`));
|
|
446
510
|
// First bootstrap the components.
|
|
447
511
|
for (const instance of this._context.componentInstances) {
|
|
448
512
|
if (core.Is.function(instance.component.bootstrap)) {
|
|
449
513
|
const instanceName = this.getInstanceName(instance);
|
|
450
|
-
this.logInfo(core.I18n.formatMessage(
|
|
514
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapping`, {
|
|
451
515
|
element: instanceName
|
|
452
516
|
}));
|
|
453
517
|
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
@@ -455,7 +519,7 @@ class EngineCore {
|
|
|
455
519
|
const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName, componentState);
|
|
456
520
|
// If the bootstrap method failed then throw an error
|
|
457
521
|
if (!bootstrapSuccess) {
|
|
458
|
-
throw new core.GeneralError(
|
|
522
|
+
throw new core.GeneralError(EngineCore._CLASS_NAME, "bootstrapFailed", {
|
|
459
523
|
component: `${instance.component.CLASS_NAME}:${instance.instanceType}`
|
|
460
524
|
});
|
|
461
525
|
}
|
|
@@ -469,7 +533,7 @@ class EngineCore {
|
|
|
469
533
|
if (core.Is.function(this._customBootstrap)) {
|
|
470
534
|
await this._customBootstrap(this, this._context);
|
|
471
535
|
}
|
|
472
|
-
this.logInfo(core.I18n.formatMessage(
|
|
536
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapComplete`));
|
|
473
537
|
}
|
|
474
538
|
}
|
|
475
539
|
/**
|
package/dist/esm/index.mjs
CHANGED
|
@@ -71,10 +71,16 @@ class EngineCore {
|
|
|
71
71
|
* Name for the engine logger.
|
|
72
72
|
*/
|
|
73
73
|
static LOGGER_TYPE_NAME = "engine";
|
|
74
|
+
/**
|
|
75
|
+
* Runtime name for the class in camel case.
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
static _CLASS_NAME_CAMEL_CASE = StringHelper.camelCase("EngineCore");
|
|
74
79
|
/**
|
|
75
80
|
* Runtime name for the class.
|
|
81
|
+
* @internal
|
|
76
82
|
*/
|
|
77
|
-
|
|
83
|
+
static _CLASS_NAME = "EngineCore";
|
|
78
84
|
/**
|
|
79
85
|
* The core context.
|
|
80
86
|
*/
|
|
@@ -85,10 +91,10 @@ class EngineCore {
|
|
|
85
91
|
*/
|
|
86
92
|
_stateStorage;
|
|
87
93
|
/**
|
|
88
|
-
* The logging
|
|
94
|
+
* The logging component for the engine.
|
|
89
95
|
* @internal
|
|
90
96
|
*/
|
|
91
|
-
|
|
97
|
+
_engineLoggingComponent;
|
|
92
98
|
/**
|
|
93
99
|
* Skip the bootstrap process.
|
|
94
100
|
* @internal
|
|
@@ -136,7 +142,7 @@ class EngineCore {
|
|
|
136
142
|
this._typeInitialisers = [];
|
|
137
143
|
this._context = {
|
|
138
144
|
config: options.config,
|
|
139
|
-
|
|
145
|
+
registeredInstances: {},
|
|
140
146
|
componentInstances: [],
|
|
141
147
|
state: { componentStates: {} },
|
|
142
148
|
stateDirty: false
|
|
@@ -173,9 +179,9 @@ class EngineCore {
|
|
|
173
179
|
return false;
|
|
174
180
|
}
|
|
175
181
|
this.setupEngineLogger();
|
|
176
|
-
this.logInfo(I18n.formatMessage(
|
|
182
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.starting`));
|
|
177
183
|
if (this._context.config.debug) {
|
|
178
|
-
this.logInfo(I18n.formatMessage(
|
|
184
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.debuggingEnabled`));
|
|
179
185
|
}
|
|
180
186
|
let canContinue;
|
|
181
187
|
try {
|
|
@@ -185,11 +191,11 @@ class EngineCore {
|
|
|
185
191
|
await this.initialiseTypeConfig(type, typeConfig, module, method);
|
|
186
192
|
}
|
|
187
193
|
await this.bootstrap();
|
|
188
|
-
this.logInfo(I18n.formatMessage(
|
|
194
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStarting`));
|
|
189
195
|
for (const instance of this._context.componentInstances) {
|
|
190
196
|
if (Is.function(instance.component.start)) {
|
|
191
197
|
const instanceName = this.getInstanceName(instance);
|
|
192
|
-
this.logInfo(I18n.formatMessage(
|
|
198
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentStarting`, {
|
|
193
199
|
element: instance.instanceType
|
|
194
200
|
}));
|
|
195
201
|
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
@@ -201,9 +207,9 @@ class EngineCore {
|
|
|
201
207
|
}
|
|
202
208
|
}
|
|
203
209
|
}
|
|
204
|
-
this.logInfo(I18n.formatMessage(
|
|
210
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsComplete`));
|
|
205
211
|
}
|
|
206
|
-
this.logInfo(I18n.formatMessage(
|
|
212
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.started`));
|
|
207
213
|
this._isStarted = true;
|
|
208
214
|
}
|
|
209
215
|
catch (err) {
|
|
@@ -222,14 +228,16 @@ class EngineCore {
|
|
|
222
228
|
* @returns Nothing.
|
|
223
229
|
*/
|
|
224
230
|
async stop() {
|
|
225
|
-
this.logInfo(I18n.formatMessage(
|
|
226
|
-
this.logInfo(I18n.formatMessage(
|
|
231
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.stopping`));
|
|
232
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStopping`));
|
|
227
233
|
for (const instance of this._context.componentInstances) {
|
|
228
234
|
if (Is.function(instance.component.stop)) {
|
|
229
235
|
const instanceName = this.getInstanceName(instance);
|
|
230
236
|
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
231
237
|
const lastState = ObjectHelper.clone(componentState);
|
|
232
|
-
this.logInfo(I18n.formatMessage(
|
|
238
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentStopping`, {
|
|
239
|
+
element: instance.instanceType
|
|
240
|
+
}));
|
|
233
241
|
try {
|
|
234
242
|
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
|
|
235
243
|
if (!ObjectHelper.equal(lastState, componentState)) {
|
|
@@ -238,23 +246,23 @@ class EngineCore {
|
|
|
238
246
|
}
|
|
239
247
|
}
|
|
240
248
|
catch (err) {
|
|
241
|
-
this.logError(new GeneralError(
|
|
249
|
+
this.logError(new GeneralError(EngineCore._CLASS_NAME, "componentStopFailed", {
|
|
242
250
|
component: instance.instanceType
|
|
243
251
|
}, BaseError.fromError(err)));
|
|
244
252
|
}
|
|
245
253
|
}
|
|
246
254
|
}
|
|
247
255
|
await this.stateSave();
|
|
248
|
-
this.logInfo(I18n.formatMessage(
|
|
249
|
-
this.logInfo(I18n.formatMessage(
|
|
256
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStopped`));
|
|
257
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.stopped`));
|
|
250
258
|
}
|
|
251
259
|
/**
|
|
252
260
|
* Log info.
|
|
253
261
|
* @param message The message to log.
|
|
254
262
|
*/
|
|
255
263
|
logInfo(message) {
|
|
256
|
-
this.
|
|
257
|
-
source:
|
|
264
|
+
this._engineLoggingComponent?.log({
|
|
265
|
+
source: EngineCore._CLASS_NAME,
|
|
258
266
|
level: "info",
|
|
259
267
|
message
|
|
260
268
|
});
|
|
@@ -272,8 +280,8 @@ class EngineCore {
|
|
|
272
280
|
if (this._context.config.debug && Is.stringValue(formattedError.stack)) {
|
|
273
281
|
message += `\n${formattedError.stack}`;
|
|
274
282
|
}
|
|
275
|
-
this.
|
|
276
|
-
source:
|
|
283
|
+
this._engineLoggingComponent?.log({
|
|
284
|
+
source: EngineCore._CLASS_NAME,
|
|
277
285
|
level: "error",
|
|
278
286
|
message
|
|
279
287
|
});
|
|
@@ -294,11 +302,48 @@ class EngineCore {
|
|
|
294
302
|
return this._context.state;
|
|
295
303
|
}
|
|
296
304
|
/**
|
|
297
|
-
* Get the
|
|
298
|
-
* @returns The
|
|
305
|
+
* Get all the registered instances.
|
|
306
|
+
* @returns The registered instances.
|
|
299
307
|
*/
|
|
300
|
-
|
|
301
|
-
return this._context.
|
|
308
|
+
getRegisteredInstances() {
|
|
309
|
+
return this._context.registeredInstances;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Get the registered instance type for the component/connector.
|
|
313
|
+
* @param componentConnectorType The type of the component/connector.
|
|
314
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
315
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
316
|
+
* @throws If a matching instance was not found.
|
|
317
|
+
*/
|
|
318
|
+
getRegisteredInstanceType(componentConnectorType, features) {
|
|
319
|
+
Guards.stringValue(EngineCore._CLASS_NAME, "componentConnectorType", componentConnectorType);
|
|
320
|
+
const registeredType = this.getRegisteredInstanceTypeOptional(componentConnectorType, features);
|
|
321
|
+
if (!Is.stringValue(registeredType)) {
|
|
322
|
+
throw new GeneralError(EngineCore._CLASS_NAME, "instanceTypeNotFound", {
|
|
323
|
+
type: componentConnectorType,
|
|
324
|
+
features: (features ?? ["default"]).join(",")
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
return registeredType;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Get the registered instance type for the component/connector if it exists.
|
|
331
|
+
* @param componentConnectorType The type of the component/connector.
|
|
332
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
333
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
334
|
+
*/
|
|
335
|
+
getRegisteredInstanceTypeOptional(componentConnectorType, features) {
|
|
336
|
+
let registeredType;
|
|
337
|
+
const registeredTypes = this._context.registeredInstances[componentConnectorType];
|
|
338
|
+
if (Is.arrayValue(registeredTypes)) {
|
|
339
|
+
if (Is.arrayValue(features)) {
|
|
340
|
+
registeredType = registeredTypes.find(t => t.features?.every(f => features.includes(f)))?.type;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
registeredType = registeredTypes[0]?.type;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return registeredType;
|
|
302
347
|
}
|
|
303
348
|
/**
|
|
304
349
|
* Get the data required to create a clone of the engine.
|
|
@@ -325,10 +370,10 @@ class EngineCore {
|
|
|
325
370
|
* @param silent Should the clone be silent.
|
|
326
371
|
*/
|
|
327
372
|
populateClone(cloneData, silent) {
|
|
328
|
-
Guards.object(
|
|
329
|
-
Guards.object(
|
|
330
|
-
Guards.object(
|
|
331
|
-
Guards.array(
|
|
373
|
+
Guards.object(EngineCore._CLASS_NAME, "cloneData", cloneData);
|
|
374
|
+
Guards.object(EngineCore._CLASS_NAME, "cloneData.config", cloneData.config);
|
|
375
|
+
Guards.object(EngineCore._CLASS_NAME, "cloneData.state", cloneData.state);
|
|
376
|
+
Guards.array(EngineCore._CLASS_NAME, "cloneData.typeInitialisers", cloneData.typeInitialisers);
|
|
332
377
|
this._loggerTypeName = cloneData.loggerTypeName;
|
|
333
378
|
this._skipBootstrap = true;
|
|
334
379
|
if (silent ?? false) {
|
|
@@ -336,7 +381,7 @@ class EngineCore {
|
|
|
336
381
|
}
|
|
337
382
|
this._context = {
|
|
338
383
|
config: cloneData.config,
|
|
339
|
-
|
|
384
|
+
registeredInstances: {},
|
|
340
385
|
componentInstances: [],
|
|
341
386
|
state: { componentStates: {} },
|
|
342
387
|
stateDirty: false
|
|
@@ -359,9 +404,20 @@ class EngineCore {
|
|
|
359
404
|
const instanceMethod = await ModuleHelper.getModuleEntry(module, method);
|
|
360
405
|
for (let i = 0; i < typeConfig.length; i++) {
|
|
361
406
|
const instanceType = instanceMethod(this, this._context, typeConfig[i], typeConfig[i].overrideInstanceType);
|
|
362
|
-
if (Is.stringValue(instanceType)
|
|
363
|
-
|
|
364
|
-
|
|
407
|
+
if (Is.stringValue(instanceType)) {
|
|
408
|
+
this._context.registeredInstances[typeKey] ??= [];
|
|
409
|
+
if (typeConfig[i].isDefault ?? false) {
|
|
410
|
+
this._context.registeredInstances[typeKey].unshift({
|
|
411
|
+
type: instanceType,
|
|
412
|
+
features: typeConfig[i].features
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
this._context.registeredInstances[typeKey].push({
|
|
417
|
+
type: instanceType,
|
|
418
|
+
features: typeConfig[i].features
|
|
419
|
+
});
|
|
420
|
+
}
|
|
365
421
|
}
|
|
366
422
|
}
|
|
367
423
|
}
|
|
@@ -385,13 +441,21 @@ class EngineCore {
|
|
|
385
441
|
component: engineLoggerConnector
|
|
386
442
|
});
|
|
387
443
|
LoggingConnectorFactory.register(this._loggerTypeName, () => engineLoggerConnector);
|
|
388
|
-
this.
|
|
389
|
-
|
|
444
|
+
this._context.registeredInstances.loggingConnector = [
|
|
445
|
+
{
|
|
446
|
+
type: this._loggerTypeName
|
|
447
|
+
}
|
|
448
|
+
];
|
|
390
449
|
const engineLoggerComponent = new LoggingService({
|
|
391
450
|
loggingConnectorType: this._loggerTypeName
|
|
392
451
|
});
|
|
452
|
+
this._engineLoggingComponent = engineLoggerComponent;
|
|
393
453
|
ComponentFactory.register("logging-service", () => engineLoggerComponent);
|
|
394
|
-
this._context.
|
|
454
|
+
this._context.registeredInstances.loggingComponent = [
|
|
455
|
+
{
|
|
456
|
+
type: "logging-service"
|
|
457
|
+
}
|
|
458
|
+
];
|
|
395
459
|
}
|
|
396
460
|
/**
|
|
397
461
|
* Load the state.
|
|
@@ -440,12 +504,12 @@ class EngineCore {
|
|
|
440
504
|
*/
|
|
441
505
|
async bootstrap() {
|
|
442
506
|
if (!this._skipBootstrap) {
|
|
443
|
-
this.logInfo(I18n.formatMessage(
|
|
507
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapStarted`));
|
|
444
508
|
// First bootstrap the components.
|
|
445
509
|
for (const instance of this._context.componentInstances) {
|
|
446
510
|
if (Is.function(instance.component.bootstrap)) {
|
|
447
511
|
const instanceName = this.getInstanceName(instance);
|
|
448
|
-
this.logInfo(I18n.formatMessage(
|
|
512
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapping`, {
|
|
449
513
|
element: instanceName
|
|
450
514
|
}));
|
|
451
515
|
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
@@ -453,7 +517,7 @@ class EngineCore {
|
|
|
453
517
|
const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName, componentState);
|
|
454
518
|
// If the bootstrap method failed then throw an error
|
|
455
519
|
if (!bootstrapSuccess) {
|
|
456
|
-
throw new GeneralError(
|
|
520
|
+
throw new GeneralError(EngineCore._CLASS_NAME, "bootstrapFailed", {
|
|
457
521
|
component: `${instance.component.CLASS_NAME}:${instance.instanceType}`
|
|
458
522
|
});
|
|
459
523
|
}
|
|
@@ -467,7 +531,7 @@ class EngineCore {
|
|
|
467
531
|
if (Is.function(this._customBootstrap)) {
|
|
468
532
|
await this._customBootstrap(this, this._context);
|
|
469
533
|
}
|
|
470
|
-
this.logInfo(I18n.formatMessage(
|
|
534
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapComplete`));
|
|
471
535
|
}
|
|
472
536
|
}
|
|
473
537
|
/**
|
|
@@ -9,10 +9,6 @@ export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig,
|
|
|
9
9
|
* Name for the engine logger.
|
|
10
10
|
*/
|
|
11
11
|
static readonly LOGGER_TYPE_NAME: string;
|
|
12
|
-
/**
|
|
13
|
-
* Runtime name for the class.
|
|
14
|
-
*/
|
|
15
|
-
readonly CLASS_NAME: string;
|
|
16
12
|
/**
|
|
17
13
|
* The core context.
|
|
18
14
|
*/
|
|
@@ -61,12 +57,30 @@ export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig,
|
|
|
61
57
|
*/
|
|
62
58
|
getState(): S;
|
|
63
59
|
/**
|
|
64
|
-
* Get the
|
|
65
|
-
* @returns The
|
|
60
|
+
* Get all the registered instances.
|
|
61
|
+
* @returns The registered instances.
|
|
66
62
|
*/
|
|
67
|
-
|
|
68
|
-
[
|
|
63
|
+
getRegisteredInstances(): {
|
|
64
|
+
[name: string]: {
|
|
65
|
+
type: string;
|
|
66
|
+
features?: string[];
|
|
67
|
+
}[];
|
|
69
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* Get the registered instance type for the component/connector.
|
|
71
|
+
* @param componentConnectorType The type of the component/connector.
|
|
72
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
73
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
74
|
+
* @throws If a matching instance was not found.
|
|
75
|
+
*/
|
|
76
|
+
getRegisteredInstanceType(componentConnectorType: string, features?: string[]): string;
|
|
77
|
+
/**
|
|
78
|
+
* Get the registered instance type for the component/connector if it exists.
|
|
79
|
+
* @param componentConnectorType The type of the component/connector.
|
|
80
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
81
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
82
|
+
*/
|
|
83
|
+
getRegisteredInstanceTypeOptional(componentConnectorType: string, features?: string[]): string | undefined;
|
|
70
84
|
/**
|
|
71
85
|
* Get the data required to create a clone of the engine.
|
|
72
86
|
* @returns The clone data.
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @twin.org/engine-core - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.2-next.6](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.5...engine-core-v0.0.2-next.6) (2025-08-21)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* update framework core ([acc0f8d](https://github.com/twinfoundation/engine/commit/acc0f8d455a4b8ec47f1da643139fa0f07775fa6))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/engine-models bumped from 0.0.2-next.5 to 0.0.2-next.6
|
|
16
|
+
|
|
17
|
+
## [0.0.2-next.5](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.4...engine-core-v0.0.2-next.5) (2025-08-14)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add synchronised storage support ([5142e34](https://github.com/twinfoundation/engine/commit/5142e3488f09195cf9f48a9c6c6d1014231a4c2c))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Dependencies
|
|
26
|
+
|
|
27
|
+
* The following workspace dependencies were updated
|
|
28
|
+
* dependencies
|
|
29
|
+
* @twin.org/engine-models bumped from 0.0.2-next.4 to 0.0.2-next.5
|
|
30
|
+
|
|
3
31
|
## [0.0.2-next.4](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.3...engine-core-v0.0.2-next.4) (2025-07-25)
|
|
4
32
|
|
|
5
33
|
|
|
@@ -46,14 +46,6 @@ Name for the engine logger.
|
|
|
46
46
|
|
|
47
47
|
***
|
|
48
48
|
|
|
49
|
-
### CLASS\_NAME
|
|
50
|
-
|
|
51
|
-
> `readonly` **CLASS\_NAME**: `string`
|
|
52
|
-
|
|
53
|
-
Runtime name for the class.
|
|
54
|
-
|
|
55
|
-
***
|
|
56
|
-
|
|
57
49
|
### \_context
|
|
58
50
|
|
|
59
51
|
> `protected` **\_context**: `IEngineCoreContext`\<`C`, `S`\>
|
|
@@ -224,21 +216,89 @@ The state of the engine.
|
|
|
224
216
|
|
|
225
217
|
***
|
|
226
218
|
|
|
227
|
-
###
|
|
219
|
+
### getRegisteredInstances()
|
|
228
220
|
|
|
229
|
-
> **
|
|
221
|
+
> **getRegisteredInstances**(): `object`
|
|
230
222
|
|
|
231
|
-
Get the
|
|
223
|
+
Get all the registered instances.
|
|
232
224
|
|
|
233
225
|
#### Returns
|
|
234
226
|
|
|
235
227
|
`object`
|
|
236
228
|
|
|
237
|
-
The
|
|
229
|
+
The registered instances.
|
|
230
|
+
|
|
231
|
+
#### Implementation of
|
|
232
|
+
|
|
233
|
+
`IEngineCore.getRegisteredInstances`
|
|
234
|
+
|
|
235
|
+
***
|
|
236
|
+
|
|
237
|
+
### getRegisteredInstanceType()
|
|
238
|
+
|
|
239
|
+
> **getRegisteredInstanceType**(`componentConnectorType`, `features?`): `string`
|
|
240
|
+
|
|
241
|
+
Get the registered instance type for the component/connector.
|
|
242
|
+
|
|
243
|
+
#### Parameters
|
|
244
|
+
|
|
245
|
+
##### componentConnectorType
|
|
246
|
+
|
|
247
|
+
`string`
|
|
248
|
+
|
|
249
|
+
The type of the component/connector.
|
|
250
|
+
|
|
251
|
+
##### features?
|
|
252
|
+
|
|
253
|
+
`string`[]
|
|
254
|
+
|
|
255
|
+
The requested features of the component, if not specified the default entry will be retrieved.
|
|
256
|
+
|
|
257
|
+
#### Returns
|
|
258
|
+
|
|
259
|
+
`string`
|
|
260
|
+
|
|
261
|
+
The instance type matching the criteria if one is registered.
|
|
262
|
+
|
|
263
|
+
#### Throws
|
|
264
|
+
|
|
265
|
+
If a matching instance was not found.
|
|
266
|
+
|
|
267
|
+
#### Implementation of
|
|
268
|
+
|
|
269
|
+
`IEngineCore.getRegisteredInstanceType`
|
|
270
|
+
|
|
271
|
+
***
|
|
272
|
+
|
|
273
|
+
### getRegisteredInstanceTypeOptional()
|
|
274
|
+
|
|
275
|
+
> **getRegisteredInstanceTypeOptional**(`componentConnectorType`, `features?`): `undefined` \| `string`
|
|
276
|
+
|
|
277
|
+
Get the registered instance type for the component/connector if it exists.
|
|
278
|
+
|
|
279
|
+
#### Parameters
|
|
280
|
+
|
|
281
|
+
##### componentConnectorType
|
|
282
|
+
|
|
283
|
+
`string`
|
|
284
|
+
|
|
285
|
+
The type of the component/connector.
|
|
286
|
+
|
|
287
|
+
##### features?
|
|
288
|
+
|
|
289
|
+
`string`[]
|
|
290
|
+
|
|
291
|
+
The requested features of the component, if not specified the default entry will be retrieved.
|
|
292
|
+
|
|
293
|
+
#### Returns
|
|
294
|
+
|
|
295
|
+
`undefined` \| `string`
|
|
296
|
+
|
|
297
|
+
The instance type matching the criteria if one is registered.
|
|
238
298
|
|
|
239
299
|
#### Implementation of
|
|
240
300
|
|
|
241
|
-
`IEngineCore.
|
|
301
|
+
`IEngineCore.getRegisteredInstanceTypeOptional`
|
|
242
302
|
|
|
243
303
|
***
|
|
244
304
|
|
package/locales/en.json
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
"entityStorageCustomMissing": "Entity storage custom \"{typeCustom}\" missing for component \"{storageName}\"",
|
|
7
7
|
"entityStorageMissing": "Entity storage configuration missing for component \"{storageName}\"",
|
|
8
8
|
"bootstrapFailed": "Bootstrap failed for component \"{component}\", please check the logs for more information",
|
|
9
|
-
"componentStopFailed": "Failed to stop component \"{component}\""
|
|
9
|
+
"componentStopFailed": "Failed to stop component \"{component}\"",
|
|
10
|
+
"instanceTypeNotFound": "Instance type not found for \"{type}\" with features \"{features}\""
|
|
10
11
|
},
|
|
11
12
|
"fileStateStorage": {
|
|
12
13
|
"failedLoading": "Failed to load file state storage from \"{filename}\"",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/engine-core",
|
|
3
|
-
"version": "0.0.2-next.
|
|
3
|
+
"version": "0.0.2-next.6",
|
|
4
4
|
"description": "Engine core.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@twin.org/core": "next",
|
|
18
18
|
"@twin.org/crypto": "next",
|
|
19
19
|
"@twin.org/data-core": "next",
|
|
20
|
-
"@twin.org/engine-models": "0.0.2-next.
|
|
20
|
+
"@twin.org/engine-models": "0.0.2-next.6",
|
|
21
21
|
"@twin.org/entity": "next",
|
|
22
22
|
"@twin.org/logging-connector-console": "next",
|
|
23
23
|
"@twin.org/logging-models": "next",
|