@twin.org/engine-core 0.0.1 → 0.0.2-next.10
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 +146 -70
- package/dist/esm/index.mjs +147 -71
- package/dist/types/engineCore.d.ts +37 -8
- package/docs/changelog.md +144 -0
- package/docs/reference/classes/EngineCore.md +127 -13
- package/locales/en.json +2 -1
- package/package.json +3 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var node_worker_threads = require('node:worker_threads');
|
|
3
4
|
var core = require('@twin.org/core');
|
|
4
5
|
var entity = require('@twin.org/entity');
|
|
5
6
|
var loggingConnectorConsole = require('@twin.org/logging-connector-console');
|
|
6
7
|
var loggingModels = require('@twin.org/logging-models');
|
|
8
|
+
var loggingService = require('@twin.org/logging-service');
|
|
7
9
|
var modules = require('@twin.org/modules');
|
|
8
10
|
var promises = require('node:fs/promises');
|
|
9
11
|
var path = require('node:path');
|
|
@@ -72,10 +74,16 @@ class EngineCore {
|
|
|
72
74
|
* Name for the engine logger.
|
|
73
75
|
*/
|
|
74
76
|
static LOGGER_TYPE_NAME = "engine";
|
|
77
|
+
/**
|
|
78
|
+
* Runtime name for the class in camel case.
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
static _CLASS_NAME_CAMEL_CASE = core.StringHelper.camelCase("EngineCore");
|
|
75
82
|
/**
|
|
76
83
|
* Runtime name for the class.
|
|
84
|
+
* @internal
|
|
77
85
|
*/
|
|
78
|
-
|
|
86
|
+
static _CLASS_NAME = "EngineCore";
|
|
79
87
|
/**
|
|
80
88
|
* The core context.
|
|
81
89
|
*/
|
|
@@ -86,10 +94,10 @@ class EngineCore {
|
|
|
86
94
|
*/
|
|
87
95
|
_stateStorage;
|
|
88
96
|
/**
|
|
89
|
-
* The logging
|
|
97
|
+
* The logging component for the engine.
|
|
90
98
|
* @internal
|
|
91
99
|
*/
|
|
92
|
-
|
|
100
|
+
_engineLoggingComponent;
|
|
93
101
|
/**
|
|
94
102
|
* Skip the bootstrap process.
|
|
95
103
|
* @internal
|
|
@@ -110,6 +118,11 @@ class EngineCore {
|
|
|
110
118
|
* @internal
|
|
111
119
|
*/
|
|
112
120
|
_isStarted;
|
|
121
|
+
/**
|
|
122
|
+
* Is the engine a clone.
|
|
123
|
+
* @internal
|
|
124
|
+
*/
|
|
125
|
+
_isClone;
|
|
113
126
|
/**
|
|
114
127
|
* Add type initialisers to the engine.
|
|
115
128
|
* @internal
|
|
@@ -137,13 +150,14 @@ class EngineCore {
|
|
|
137
150
|
this._typeInitialisers = [];
|
|
138
151
|
this._context = {
|
|
139
152
|
config: options.config,
|
|
140
|
-
|
|
153
|
+
registeredInstances: {},
|
|
141
154
|
componentInstances: [],
|
|
142
|
-
state: {
|
|
155
|
+
state: {},
|
|
143
156
|
stateDirty: false
|
|
144
157
|
};
|
|
145
158
|
this._stateStorage = options.stateStorage;
|
|
146
159
|
this._isStarted = false;
|
|
160
|
+
this._isClone = false;
|
|
147
161
|
if (core.Is.function(this._populateTypeInitialisers)) {
|
|
148
162
|
this._populateTypeInitialisers(this, this._context);
|
|
149
163
|
}
|
|
@@ -174,9 +188,9 @@ class EngineCore {
|
|
|
174
188
|
return false;
|
|
175
189
|
}
|
|
176
190
|
this.setupEngineLogger();
|
|
177
|
-
this.logInfo(core.I18n.formatMessage(
|
|
191
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.starting`));
|
|
178
192
|
if (this._context.config.debug) {
|
|
179
|
-
this.logInfo(core.I18n.formatMessage(
|
|
193
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.debuggingEnabled`));
|
|
180
194
|
}
|
|
181
195
|
let canContinue;
|
|
182
196
|
try {
|
|
@@ -186,25 +200,18 @@ class EngineCore {
|
|
|
186
200
|
await this.initialiseTypeConfig(type, typeConfig, module, method);
|
|
187
201
|
}
|
|
188
202
|
await this.bootstrap();
|
|
189
|
-
this.logInfo(core.I18n.formatMessage(
|
|
203
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStarting`));
|
|
190
204
|
for (const instance of this._context.componentInstances) {
|
|
191
205
|
if (core.Is.function(instance.component.start)) {
|
|
192
|
-
|
|
193
|
-
this.logInfo(core.I18n.formatMessage("engineCore.componentStarting", {
|
|
206
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentStarting`, {
|
|
194
207
|
element: instance.instanceType
|
|
195
208
|
}));
|
|
196
|
-
|
|
197
|
-
const lastState = core.ObjectHelper.clone(componentState);
|
|
198
|
-
await instance.component.start(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
|
|
199
|
-
if (!core.ObjectHelper.equal(lastState, componentState)) {
|
|
200
|
-
this._context.state.componentStates[instanceName] = componentState;
|
|
201
|
-
this._context.stateDirty = true;
|
|
202
|
-
}
|
|
209
|
+
await instance.component.start(this._context.state.nodeIdentity, this._loggerTypeName);
|
|
203
210
|
}
|
|
204
211
|
}
|
|
205
|
-
this.logInfo(core.I18n.formatMessage(
|
|
212
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsComplete`));
|
|
206
213
|
}
|
|
207
|
-
this.logInfo(core.I18n.formatMessage(
|
|
214
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.started`));
|
|
208
215
|
this._isStarted = true;
|
|
209
216
|
}
|
|
210
217
|
catch (err) {
|
|
@@ -223,39 +230,55 @@ class EngineCore {
|
|
|
223
230
|
* @returns Nothing.
|
|
224
231
|
*/
|
|
225
232
|
async stop() {
|
|
226
|
-
this.logInfo(core.I18n.formatMessage(
|
|
227
|
-
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`));
|
|
228
235
|
for (const instance of this._context.componentInstances) {
|
|
229
236
|
if (core.Is.function(instance.component.stop)) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
this.logInfo(core.I18n.formatMessage("engineCore.componentStopping", { element: instance.instanceType }));
|
|
237
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentStopping`, {
|
|
238
|
+
element: instance.instanceType
|
|
239
|
+
}));
|
|
234
240
|
try {
|
|
235
|
-
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName
|
|
236
|
-
if (!core.ObjectHelper.equal(lastState, componentState)) {
|
|
237
|
-
this._context.state.componentStates[instanceName] = componentState;
|
|
238
|
-
this._context.stateDirty = true;
|
|
239
|
-
}
|
|
241
|
+
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName);
|
|
240
242
|
}
|
|
241
243
|
catch (err) {
|
|
242
|
-
this.logError(new core.GeneralError(
|
|
244
|
+
this.logError(new core.GeneralError(EngineCore._CLASS_NAME, "componentStopFailed", {
|
|
243
245
|
component: instance.instanceType
|
|
244
246
|
}, core.BaseError.fromError(err)));
|
|
245
247
|
}
|
|
246
248
|
}
|
|
247
249
|
}
|
|
248
250
|
await this.stateSave();
|
|
249
|
-
this.logInfo(core.I18n.formatMessage(
|
|
250
|
-
this.logInfo(core.I18n.formatMessage(
|
|
251
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStopped`));
|
|
252
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.stopped`));
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Is the engine started.
|
|
256
|
+
* @returns True if the engine is started.
|
|
257
|
+
*/
|
|
258
|
+
isStarted() {
|
|
259
|
+
return this._isStarted;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Is this the primary engine instance.
|
|
263
|
+
* @returns True if the engine is the primary instance.
|
|
264
|
+
*/
|
|
265
|
+
isPrimary() {
|
|
266
|
+
return node_worker_threads.isMainThread && !this._isClone;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Is this engine instance a clone.
|
|
270
|
+
* @returns True if the engine instance is a clone.
|
|
271
|
+
*/
|
|
272
|
+
isClone() {
|
|
273
|
+
return this._isClone;
|
|
251
274
|
}
|
|
252
275
|
/**
|
|
253
276
|
* Log info.
|
|
254
277
|
* @param message The message to log.
|
|
255
278
|
*/
|
|
256
279
|
logInfo(message) {
|
|
257
|
-
this.
|
|
258
|
-
source:
|
|
280
|
+
this._engineLoggingComponent?.log({
|
|
281
|
+
source: EngineCore._CLASS_NAME,
|
|
259
282
|
level: "info",
|
|
260
283
|
message
|
|
261
284
|
});
|
|
@@ -273,8 +296,8 @@ class EngineCore {
|
|
|
273
296
|
if (this._context.config.debug && core.Is.stringValue(formattedError.stack)) {
|
|
274
297
|
message += `\n${formattedError.stack}`;
|
|
275
298
|
}
|
|
276
|
-
this.
|
|
277
|
-
source:
|
|
299
|
+
this._engineLoggingComponent?.log({
|
|
300
|
+
source: EngineCore._CLASS_NAME,
|
|
278
301
|
level: "error",
|
|
279
302
|
message
|
|
280
303
|
});
|
|
@@ -295,11 +318,48 @@ class EngineCore {
|
|
|
295
318
|
return this._context.state;
|
|
296
319
|
}
|
|
297
320
|
/**
|
|
298
|
-
* Get the
|
|
299
|
-
* @returns The
|
|
321
|
+
* Get all the registered instances.
|
|
322
|
+
* @returns The registered instances.
|
|
300
323
|
*/
|
|
301
|
-
|
|
302
|
-
return this._context.
|
|
324
|
+
getRegisteredInstances() {
|
|
325
|
+
return this._context.registeredInstances;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Get the registered instance type for the component/connector.
|
|
329
|
+
* @param componentConnectorType The type of the component/connector.
|
|
330
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
331
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
332
|
+
* @throws If a matching instance was not found.
|
|
333
|
+
*/
|
|
334
|
+
getRegisteredInstanceType(componentConnectorType, features) {
|
|
335
|
+
core.Guards.stringValue(EngineCore._CLASS_NAME, "componentConnectorType", componentConnectorType);
|
|
336
|
+
const registeredType = this.getRegisteredInstanceTypeOptional(componentConnectorType, features);
|
|
337
|
+
if (!core.Is.stringValue(registeredType)) {
|
|
338
|
+
throw new core.GeneralError(EngineCore._CLASS_NAME, "instanceTypeNotFound", {
|
|
339
|
+
type: componentConnectorType,
|
|
340
|
+
features: (features ?? ["default"]).join(",")
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
return registeredType;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Get the registered instance type for the component/connector if it exists.
|
|
347
|
+
* @param componentConnectorType The type of the component/connector.
|
|
348
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
349
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
350
|
+
*/
|
|
351
|
+
getRegisteredInstanceTypeOptional(componentConnectorType, features) {
|
|
352
|
+
let registeredType;
|
|
353
|
+
const registeredTypes = this._context.registeredInstances[componentConnectorType];
|
|
354
|
+
if (core.Is.arrayValue(registeredTypes)) {
|
|
355
|
+
if (core.Is.arrayValue(features)) {
|
|
356
|
+
registeredType = registeredTypes.find(t => t.features?.every(f => features.includes(f)))?.type;
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
registeredType = registeredTypes[0]?.type;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return registeredType;
|
|
303
363
|
}
|
|
304
364
|
/**
|
|
305
365
|
* Get the data required to create a clone of the engine.
|
|
@@ -326,20 +386,21 @@ class EngineCore {
|
|
|
326
386
|
* @param silent Should the clone be silent.
|
|
327
387
|
*/
|
|
328
388
|
populateClone(cloneData, silent) {
|
|
329
|
-
core.Guards.object(
|
|
330
|
-
core.Guards.object(
|
|
331
|
-
core.Guards.object(
|
|
332
|
-
core.Guards.array(
|
|
389
|
+
core.Guards.object(EngineCore._CLASS_NAME, "cloneData", cloneData);
|
|
390
|
+
core.Guards.object(EngineCore._CLASS_NAME, "cloneData.config", cloneData.config);
|
|
391
|
+
core.Guards.object(EngineCore._CLASS_NAME, "cloneData.state", cloneData.state);
|
|
392
|
+
core.Guards.array(EngineCore._CLASS_NAME, "cloneData.typeInitialisers", cloneData.typeInitialisers);
|
|
333
393
|
this._loggerTypeName = cloneData.loggerTypeName;
|
|
334
394
|
this._skipBootstrap = true;
|
|
395
|
+
this._isClone = true;
|
|
335
396
|
if (silent ?? false) {
|
|
336
397
|
cloneData.config.silent = true;
|
|
337
398
|
}
|
|
338
399
|
this._context = {
|
|
339
400
|
config: cloneData.config,
|
|
340
|
-
|
|
401
|
+
registeredInstances: {},
|
|
341
402
|
componentInstances: [],
|
|
342
|
-
state: {
|
|
403
|
+
state: {},
|
|
343
404
|
stateDirty: false
|
|
344
405
|
};
|
|
345
406
|
this._typeInitialisers = cloneData.typeInitialisers;
|
|
@@ -360,9 +421,20 @@ class EngineCore {
|
|
|
360
421
|
const instanceMethod = await modules.ModuleHelper.getModuleEntry(module, method);
|
|
361
422
|
for (let i = 0; i < typeConfig.length; i++) {
|
|
362
423
|
const instanceType = instanceMethod(this, this._context, typeConfig[i], typeConfig[i].overrideInstanceType);
|
|
363
|
-
if (core.Is.stringValue(instanceType)
|
|
364
|
-
|
|
365
|
-
|
|
424
|
+
if (core.Is.stringValue(instanceType)) {
|
|
425
|
+
this._context.registeredInstances[typeKey] ??= [];
|
|
426
|
+
if (typeConfig[i].isDefault ?? false) {
|
|
427
|
+
this._context.registeredInstances[typeKey].unshift({
|
|
428
|
+
type: instanceType,
|
|
429
|
+
features: typeConfig[i].features
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
this._context.registeredInstances[typeKey].push({
|
|
434
|
+
type: instanceType,
|
|
435
|
+
features: typeConfig[i].features
|
|
436
|
+
});
|
|
437
|
+
}
|
|
366
438
|
}
|
|
367
439
|
}
|
|
368
440
|
}
|
|
@@ -373,7 +445,7 @@ class EngineCore {
|
|
|
373
445
|
*/
|
|
374
446
|
setupEngineLogger() {
|
|
375
447
|
const silent = this._context.config.silent ?? false;
|
|
376
|
-
const
|
|
448
|
+
const engineLoggerConnector = silent
|
|
377
449
|
? new loggingModels.SilentLoggingConnector()
|
|
378
450
|
: new loggingConnectorConsole.ConsoleLoggingConnector({
|
|
379
451
|
config: {
|
|
@@ -383,11 +455,24 @@ class EngineCore {
|
|
|
383
455
|
});
|
|
384
456
|
this._context.componentInstances.push({
|
|
385
457
|
instanceType: this._loggerTypeName,
|
|
386
|
-
component:
|
|
458
|
+
component: engineLoggerConnector
|
|
387
459
|
});
|
|
388
|
-
loggingModels.LoggingConnectorFactory.register(this._loggerTypeName, () =>
|
|
389
|
-
this.
|
|
390
|
-
|
|
460
|
+
loggingModels.LoggingConnectorFactory.register(this._loggerTypeName, () => engineLoggerConnector);
|
|
461
|
+
this._context.registeredInstances.loggingConnector = [
|
|
462
|
+
{
|
|
463
|
+
type: this._loggerTypeName
|
|
464
|
+
}
|
|
465
|
+
];
|
|
466
|
+
const engineLoggerComponent = new loggingService.LoggingService({
|
|
467
|
+
loggingConnectorType: this._loggerTypeName
|
|
468
|
+
});
|
|
469
|
+
this._engineLoggingComponent = engineLoggerComponent;
|
|
470
|
+
core.ComponentFactory.register("logging-service", () => engineLoggerComponent);
|
|
471
|
+
this._context.registeredInstances.loggingComponent = [
|
|
472
|
+
{
|
|
473
|
+
type: "logging-service"
|
|
474
|
+
}
|
|
475
|
+
];
|
|
391
476
|
}
|
|
392
477
|
/**
|
|
393
478
|
* Load the state.
|
|
@@ -397,10 +482,7 @@ class EngineCore {
|
|
|
397
482
|
async stateLoad() {
|
|
398
483
|
if (this._stateStorage) {
|
|
399
484
|
try {
|
|
400
|
-
this._context.state = ((await this._stateStorage.load(this)) ?? {
|
|
401
|
-
componentStates: {}
|
|
402
|
-
});
|
|
403
|
-
this._context.state.componentStates ??= {};
|
|
485
|
+
this._context.state = ((await this._stateStorage.load(this)) ?? {});
|
|
404
486
|
this._context.stateDirty = false;
|
|
405
487
|
return true;
|
|
406
488
|
}
|
|
@@ -436,34 +518,28 @@ class EngineCore {
|
|
|
436
518
|
*/
|
|
437
519
|
async bootstrap() {
|
|
438
520
|
if (!this._skipBootstrap) {
|
|
439
|
-
this.logInfo(core.I18n.formatMessage(
|
|
521
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapStarted`));
|
|
440
522
|
// First bootstrap the components.
|
|
441
523
|
for (const instance of this._context.componentInstances) {
|
|
442
524
|
if (core.Is.function(instance.component.bootstrap)) {
|
|
443
525
|
const instanceName = this.getInstanceName(instance);
|
|
444
|
-
this.logInfo(core.I18n.formatMessage(
|
|
526
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapping`, {
|
|
445
527
|
element: instanceName
|
|
446
528
|
}));
|
|
447
|
-
const
|
|
448
|
-
const lastState = core.ObjectHelper.clone(componentState);
|
|
449
|
-
const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName, componentState);
|
|
529
|
+
const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName);
|
|
450
530
|
// If the bootstrap method failed then throw an error
|
|
451
531
|
if (!bootstrapSuccess) {
|
|
452
|
-
throw new core.GeneralError(
|
|
532
|
+
throw new core.GeneralError(EngineCore._CLASS_NAME, "bootstrapFailed", {
|
|
453
533
|
component: `${instance.component.CLASS_NAME}:${instance.instanceType}`
|
|
454
534
|
});
|
|
455
535
|
}
|
|
456
|
-
if (!core.ObjectHelper.equal(lastState, componentState)) {
|
|
457
|
-
this._context.state.componentStates[instanceName] = componentState;
|
|
458
|
-
this._context.stateDirty = true;
|
|
459
|
-
}
|
|
460
536
|
}
|
|
461
537
|
}
|
|
462
538
|
// Now perform any custom bootstrap operations
|
|
463
539
|
if (core.Is.function(this._customBootstrap)) {
|
|
464
540
|
await this._customBootstrap(this, this._context);
|
|
465
541
|
}
|
|
466
|
-
this.logInfo(core.I18n.formatMessage(
|
|
542
|
+
this.logInfo(core.I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapComplete`));
|
|
467
543
|
}
|
|
468
544
|
}
|
|
469
545
|
/**
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isMainThread } from 'node:worker_threads';
|
|
2
|
+
import { I18n, StringHelper, Is, BaseError, GeneralError, ErrorHelper, Guards, 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';
|
|
@@ -70,10 +72,16 @@ class EngineCore {
|
|
|
70
72
|
* Name for the engine logger.
|
|
71
73
|
*/
|
|
72
74
|
static LOGGER_TYPE_NAME = "engine";
|
|
75
|
+
/**
|
|
76
|
+
* Runtime name for the class in camel case.
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
79
|
+
static _CLASS_NAME_CAMEL_CASE = StringHelper.camelCase("EngineCore");
|
|
73
80
|
/**
|
|
74
81
|
* Runtime name for the class.
|
|
82
|
+
* @internal
|
|
75
83
|
*/
|
|
76
|
-
|
|
84
|
+
static _CLASS_NAME = "EngineCore";
|
|
77
85
|
/**
|
|
78
86
|
* The core context.
|
|
79
87
|
*/
|
|
@@ -84,10 +92,10 @@ class EngineCore {
|
|
|
84
92
|
*/
|
|
85
93
|
_stateStorage;
|
|
86
94
|
/**
|
|
87
|
-
* The logging
|
|
95
|
+
* The logging component for the engine.
|
|
88
96
|
* @internal
|
|
89
97
|
*/
|
|
90
|
-
|
|
98
|
+
_engineLoggingComponent;
|
|
91
99
|
/**
|
|
92
100
|
* Skip the bootstrap process.
|
|
93
101
|
* @internal
|
|
@@ -108,6 +116,11 @@ class EngineCore {
|
|
|
108
116
|
* @internal
|
|
109
117
|
*/
|
|
110
118
|
_isStarted;
|
|
119
|
+
/**
|
|
120
|
+
* Is the engine a clone.
|
|
121
|
+
* @internal
|
|
122
|
+
*/
|
|
123
|
+
_isClone;
|
|
111
124
|
/**
|
|
112
125
|
* Add type initialisers to the engine.
|
|
113
126
|
* @internal
|
|
@@ -135,13 +148,14 @@ class EngineCore {
|
|
|
135
148
|
this._typeInitialisers = [];
|
|
136
149
|
this._context = {
|
|
137
150
|
config: options.config,
|
|
138
|
-
|
|
151
|
+
registeredInstances: {},
|
|
139
152
|
componentInstances: [],
|
|
140
|
-
state: {
|
|
153
|
+
state: {},
|
|
141
154
|
stateDirty: false
|
|
142
155
|
};
|
|
143
156
|
this._stateStorage = options.stateStorage;
|
|
144
157
|
this._isStarted = false;
|
|
158
|
+
this._isClone = false;
|
|
145
159
|
if (Is.function(this._populateTypeInitialisers)) {
|
|
146
160
|
this._populateTypeInitialisers(this, this._context);
|
|
147
161
|
}
|
|
@@ -172,9 +186,9 @@ class EngineCore {
|
|
|
172
186
|
return false;
|
|
173
187
|
}
|
|
174
188
|
this.setupEngineLogger();
|
|
175
|
-
this.logInfo(I18n.formatMessage(
|
|
189
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.starting`));
|
|
176
190
|
if (this._context.config.debug) {
|
|
177
|
-
this.logInfo(I18n.formatMessage(
|
|
191
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.debuggingEnabled`));
|
|
178
192
|
}
|
|
179
193
|
let canContinue;
|
|
180
194
|
try {
|
|
@@ -184,25 +198,18 @@ class EngineCore {
|
|
|
184
198
|
await this.initialiseTypeConfig(type, typeConfig, module, method);
|
|
185
199
|
}
|
|
186
200
|
await this.bootstrap();
|
|
187
|
-
this.logInfo(I18n.formatMessage(
|
|
201
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStarting`));
|
|
188
202
|
for (const instance of this._context.componentInstances) {
|
|
189
203
|
if (Is.function(instance.component.start)) {
|
|
190
|
-
|
|
191
|
-
this.logInfo(I18n.formatMessage("engineCore.componentStarting", {
|
|
204
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentStarting`, {
|
|
192
205
|
element: instance.instanceType
|
|
193
206
|
}));
|
|
194
|
-
|
|
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
|
-
}
|
|
207
|
+
await instance.component.start(this._context.state.nodeIdentity, this._loggerTypeName);
|
|
201
208
|
}
|
|
202
209
|
}
|
|
203
|
-
this.logInfo(I18n.formatMessage(
|
|
210
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsComplete`));
|
|
204
211
|
}
|
|
205
|
-
this.logInfo(I18n.formatMessage(
|
|
212
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.started`));
|
|
206
213
|
this._isStarted = true;
|
|
207
214
|
}
|
|
208
215
|
catch (err) {
|
|
@@ -221,39 +228,55 @@ class EngineCore {
|
|
|
221
228
|
* @returns Nothing.
|
|
222
229
|
*/
|
|
223
230
|
async stop() {
|
|
224
|
-
this.logInfo(I18n.formatMessage(
|
|
225
|
-
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`));
|
|
226
233
|
for (const instance of this._context.componentInstances) {
|
|
227
234
|
if (Is.function(instance.component.stop)) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
this.logInfo(I18n.formatMessage("engineCore.componentStopping", { element: instance.instanceType }));
|
|
235
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentStopping`, {
|
|
236
|
+
element: instance.instanceType
|
|
237
|
+
}));
|
|
232
238
|
try {
|
|
233
|
-
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName
|
|
234
|
-
if (!ObjectHelper.equal(lastState, componentState)) {
|
|
235
|
-
this._context.state.componentStates[instanceName] = componentState;
|
|
236
|
-
this._context.stateDirty = true;
|
|
237
|
-
}
|
|
239
|
+
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName);
|
|
238
240
|
}
|
|
239
241
|
catch (err) {
|
|
240
|
-
this.logError(new GeneralError(
|
|
242
|
+
this.logError(new GeneralError(EngineCore._CLASS_NAME, "componentStopFailed", {
|
|
241
243
|
component: instance.instanceType
|
|
242
244
|
}, BaseError.fromError(err)));
|
|
243
245
|
}
|
|
244
246
|
}
|
|
245
247
|
}
|
|
246
248
|
await this.stateSave();
|
|
247
|
-
this.logInfo(I18n.formatMessage(
|
|
248
|
-
this.logInfo(I18n.formatMessage(
|
|
249
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.componentsStopped`));
|
|
250
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.stopped`));
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Is the engine started.
|
|
254
|
+
* @returns True if the engine is started.
|
|
255
|
+
*/
|
|
256
|
+
isStarted() {
|
|
257
|
+
return this._isStarted;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Is this the primary engine instance.
|
|
261
|
+
* @returns True if the engine is the primary instance.
|
|
262
|
+
*/
|
|
263
|
+
isPrimary() {
|
|
264
|
+
return isMainThread && !this._isClone;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Is this engine instance a clone.
|
|
268
|
+
* @returns True if the engine instance is a clone.
|
|
269
|
+
*/
|
|
270
|
+
isClone() {
|
|
271
|
+
return this._isClone;
|
|
249
272
|
}
|
|
250
273
|
/**
|
|
251
274
|
* Log info.
|
|
252
275
|
* @param message The message to log.
|
|
253
276
|
*/
|
|
254
277
|
logInfo(message) {
|
|
255
|
-
this.
|
|
256
|
-
source:
|
|
278
|
+
this._engineLoggingComponent?.log({
|
|
279
|
+
source: EngineCore._CLASS_NAME,
|
|
257
280
|
level: "info",
|
|
258
281
|
message
|
|
259
282
|
});
|
|
@@ -271,8 +294,8 @@ class EngineCore {
|
|
|
271
294
|
if (this._context.config.debug && Is.stringValue(formattedError.stack)) {
|
|
272
295
|
message += `\n${formattedError.stack}`;
|
|
273
296
|
}
|
|
274
|
-
this.
|
|
275
|
-
source:
|
|
297
|
+
this._engineLoggingComponent?.log({
|
|
298
|
+
source: EngineCore._CLASS_NAME,
|
|
276
299
|
level: "error",
|
|
277
300
|
message
|
|
278
301
|
});
|
|
@@ -293,11 +316,48 @@ class EngineCore {
|
|
|
293
316
|
return this._context.state;
|
|
294
317
|
}
|
|
295
318
|
/**
|
|
296
|
-
* Get the
|
|
297
|
-
* @returns The
|
|
319
|
+
* Get all the registered instances.
|
|
320
|
+
* @returns The registered instances.
|
|
298
321
|
*/
|
|
299
|
-
|
|
300
|
-
return this._context.
|
|
322
|
+
getRegisteredInstances() {
|
|
323
|
+
return this._context.registeredInstances;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Get the registered instance type for the component/connector.
|
|
327
|
+
* @param componentConnectorType The type of the component/connector.
|
|
328
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
329
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
330
|
+
* @throws If a matching instance was not found.
|
|
331
|
+
*/
|
|
332
|
+
getRegisteredInstanceType(componentConnectorType, features) {
|
|
333
|
+
Guards.stringValue(EngineCore._CLASS_NAME, "componentConnectorType", componentConnectorType);
|
|
334
|
+
const registeredType = this.getRegisteredInstanceTypeOptional(componentConnectorType, features);
|
|
335
|
+
if (!Is.stringValue(registeredType)) {
|
|
336
|
+
throw new GeneralError(EngineCore._CLASS_NAME, "instanceTypeNotFound", {
|
|
337
|
+
type: componentConnectorType,
|
|
338
|
+
features: (features ?? ["default"]).join(",")
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
return registeredType;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get the registered instance type for the component/connector if it exists.
|
|
345
|
+
* @param componentConnectorType The type of the component/connector.
|
|
346
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
347
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
348
|
+
*/
|
|
349
|
+
getRegisteredInstanceTypeOptional(componentConnectorType, features) {
|
|
350
|
+
let registeredType;
|
|
351
|
+
const registeredTypes = this._context.registeredInstances[componentConnectorType];
|
|
352
|
+
if (Is.arrayValue(registeredTypes)) {
|
|
353
|
+
if (Is.arrayValue(features)) {
|
|
354
|
+
registeredType = registeredTypes.find(t => t.features?.every(f => features.includes(f)))?.type;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
registeredType = registeredTypes[0]?.type;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return registeredType;
|
|
301
361
|
}
|
|
302
362
|
/**
|
|
303
363
|
* Get the data required to create a clone of the engine.
|
|
@@ -324,20 +384,21 @@ class EngineCore {
|
|
|
324
384
|
* @param silent Should the clone be silent.
|
|
325
385
|
*/
|
|
326
386
|
populateClone(cloneData, silent) {
|
|
327
|
-
Guards.object(
|
|
328
|
-
Guards.object(
|
|
329
|
-
Guards.object(
|
|
330
|
-
Guards.array(
|
|
387
|
+
Guards.object(EngineCore._CLASS_NAME, "cloneData", cloneData);
|
|
388
|
+
Guards.object(EngineCore._CLASS_NAME, "cloneData.config", cloneData.config);
|
|
389
|
+
Guards.object(EngineCore._CLASS_NAME, "cloneData.state", cloneData.state);
|
|
390
|
+
Guards.array(EngineCore._CLASS_NAME, "cloneData.typeInitialisers", cloneData.typeInitialisers);
|
|
331
391
|
this._loggerTypeName = cloneData.loggerTypeName;
|
|
332
392
|
this._skipBootstrap = true;
|
|
393
|
+
this._isClone = true;
|
|
333
394
|
if (silent ?? false) {
|
|
334
395
|
cloneData.config.silent = true;
|
|
335
396
|
}
|
|
336
397
|
this._context = {
|
|
337
398
|
config: cloneData.config,
|
|
338
|
-
|
|
399
|
+
registeredInstances: {},
|
|
339
400
|
componentInstances: [],
|
|
340
|
-
state: {
|
|
401
|
+
state: {},
|
|
341
402
|
stateDirty: false
|
|
342
403
|
};
|
|
343
404
|
this._typeInitialisers = cloneData.typeInitialisers;
|
|
@@ -358,9 +419,20 @@ class EngineCore {
|
|
|
358
419
|
const instanceMethod = await ModuleHelper.getModuleEntry(module, method);
|
|
359
420
|
for (let i = 0; i < typeConfig.length; i++) {
|
|
360
421
|
const instanceType = instanceMethod(this, this._context, typeConfig[i], typeConfig[i].overrideInstanceType);
|
|
361
|
-
if (Is.stringValue(instanceType)
|
|
362
|
-
|
|
363
|
-
|
|
422
|
+
if (Is.stringValue(instanceType)) {
|
|
423
|
+
this._context.registeredInstances[typeKey] ??= [];
|
|
424
|
+
if (typeConfig[i].isDefault ?? false) {
|
|
425
|
+
this._context.registeredInstances[typeKey].unshift({
|
|
426
|
+
type: instanceType,
|
|
427
|
+
features: typeConfig[i].features
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
this._context.registeredInstances[typeKey].push({
|
|
432
|
+
type: instanceType,
|
|
433
|
+
features: typeConfig[i].features
|
|
434
|
+
});
|
|
435
|
+
}
|
|
364
436
|
}
|
|
365
437
|
}
|
|
366
438
|
}
|
|
@@ -371,7 +443,7 @@ class EngineCore {
|
|
|
371
443
|
*/
|
|
372
444
|
setupEngineLogger() {
|
|
373
445
|
const silent = this._context.config.silent ?? false;
|
|
374
|
-
const
|
|
446
|
+
const engineLoggerConnector = silent
|
|
375
447
|
? new SilentLoggingConnector()
|
|
376
448
|
: new ConsoleLoggingConnector({
|
|
377
449
|
config: {
|
|
@@ -381,11 +453,24 @@ class EngineCore {
|
|
|
381
453
|
});
|
|
382
454
|
this._context.componentInstances.push({
|
|
383
455
|
instanceType: this._loggerTypeName,
|
|
384
|
-
component:
|
|
456
|
+
component: engineLoggerConnector
|
|
385
457
|
});
|
|
386
|
-
LoggingConnectorFactory.register(this._loggerTypeName, () =>
|
|
387
|
-
this.
|
|
388
|
-
|
|
458
|
+
LoggingConnectorFactory.register(this._loggerTypeName, () => engineLoggerConnector);
|
|
459
|
+
this._context.registeredInstances.loggingConnector = [
|
|
460
|
+
{
|
|
461
|
+
type: this._loggerTypeName
|
|
462
|
+
}
|
|
463
|
+
];
|
|
464
|
+
const engineLoggerComponent = new LoggingService({
|
|
465
|
+
loggingConnectorType: this._loggerTypeName
|
|
466
|
+
});
|
|
467
|
+
this._engineLoggingComponent = engineLoggerComponent;
|
|
468
|
+
ComponentFactory.register("logging-service", () => engineLoggerComponent);
|
|
469
|
+
this._context.registeredInstances.loggingComponent = [
|
|
470
|
+
{
|
|
471
|
+
type: "logging-service"
|
|
472
|
+
}
|
|
473
|
+
];
|
|
389
474
|
}
|
|
390
475
|
/**
|
|
391
476
|
* Load the state.
|
|
@@ -395,10 +480,7 @@ class EngineCore {
|
|
|
395
480
|
async stateLoad() {
|
|
396
481
|
if (this._stateStorage) {
|
|
397
482
|
try {
|
|
398
|
-
this._context.state = ((await this._stateStorage.load(this)) ?? {
|
|
399
|
-
componentStates: {}
|
|
400
|
-
});
|
|
401
|
-
this._context.state.componentStates ??= {};
|
|
483
|
+
this._context.state = ((await this._stateStorage.load(this)) ?? {});
|
|
402
484
|
this._context.stateDirty = false;
|
|
403
485
|
return true;
|
|
404
486
|
}
|
|
@@ -434,34 +516,28 @@ class EngineCore {
|
|
|
434
516
|
*/
|
|
435
517
|
async bootstrap() {
|
|
436
518
|
if (!this._skipBootstrap) {
|
|
437
|
-
this.logInfo(I18n.formatMessage(
|
|
519
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapStarted`));
|
|
438
520
|
// First bootstrap the components.
|
|
439
521
|
for (const instance of this._context.componentInstances) {
|
|
440
522
|
if (Is.function(instance.component.bootstrap)) {
|
|
441
523
|
const instanceName = this.getInstanceName(instance);
|
|
442
|
-
this.logInfo(I18n.formatMessage(
|
|
524
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapping`, {
|
|
443
525
|
element: instanceName
|
|
444
526
|
}));
|
|
445
|
-
const
|
|
446
|
-
const lastState = ObjectHelper.clone(componentState);
|
|
447
|
-
const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName, componentState);
|
|
527
|
+
const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName);
|
|
448
528
|
// If the bootstrap method failed then throw an error
|
|
449
529
|
if (!bootstrapSuccess) {
|
|
450
|
-
throw new GeneralError(
|
|
530
|
+
throw new GeneralError(EngineCore._CLASS_NAME, "bootstrapFailed", {
|
|
451
531
|
component: `${instance.component.CLASS_NAME}:${instance.instanceType}`
|
|
452
532
|
});
|
|
453
533
|
}
|
|
454
|
-
if (!ObjectHelper.equal(lastState, componentState)) {
|
|
455
|
-
this._context.state.componentStates[instanceName] = componentState;
|
|
456
|
-
this._context.stateDirty = true;
|
|
457
|
-
}
|
|
458
534
|
}
|
|
459
535
|
}
|
|
460
536
|
// Now perform any custom bootstrap operations
|
|
461
537
|
if (Is.function(this._customBootstrap)) {
|
|
462
538
|
await this._customBootstrap(this, this._context);
|
|
463
539
|
}
|
|
464
|
-
this.logInfo(I18n.formatMessage(
|
|
540
|
+
this.logInfo(I18n.formatMessage(`${EngineCore._CLASS_NAME_CAMEL_CASE}.bootstrapComplete`));
|
|
465
541
|
}
|
|
466
542
|
}
|
|
467
543
|
/**
|
|
@@ -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
|
*/
|
|
@@ -40,6 +36,21 @@ export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig,
|
|
|
40
36
|
* @returns Nothing.
|
|
41
37
|
*/
|
|
42
38
|
stop(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Is the engine started.
|
|
41
|
+
* @returns True if the engine is started.
|
|
42
|
+
*/
|
|
43
|
+
isStarted(): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Is this the primary engine instance.
|
|
46
|
+
* @returns True if the engine is the primary instance.
|
|
47
|
+
*/
|
|
48
|
+
isPrimary(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Is this engine instance a clone.
|
|
51
|
+
* @returns True if the engine instance is a clone.
|
|
52
|
+
*/
|
|
53
|
+
isClone(): boolean;
|
|
43
54
|
/**
|
|
44
55
|
* Log info.
|
|
45
56
|
* @param message The message to log.
|
|
@@ -61,12 +72,30 @@ export declare class EngineCore<C extends IEngineCoreConfig = IEngineCoreConfig,
|
|
|
61
72
|
*/
|
|
62
73
|
getState(): S;
|
|
63
74
|
/**
|
|
64
|
-
* Get the
|
|
65
|
-
* @returns The
|
|
75
|
+
* Get all the registered instances.
|
|
76
|
+
* @returns The registered instances.
|
|
66
77
|
*/
|
|
67
|
-
|
|
68
|
-
[
|
|
78
|
+
getRegisteredInstances(): {
|
|
79
|
+
[name: string]: {
|
|
80
|
+
type: string;
|
|
81
|
+
features?: string[];
|
|
82
|
+
}[];
|
|
69
83
|
};
|
|
84
|
+
/**
|
|
85
|
+
* Get the registered instance type for the component/connector.
|
|
86
|
+
* @param componentConnectorType The type of the component/connector.
|
|
87
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
88
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
89
|
+
* @throws If a matching instance was not found.
|
|
90
|
+
*/
|
|
91
|
+
getRegisteredInstanceType(componentConnectorType: string, features?: string[]): string;
|
|
92
|
+
/**
|
|
93
|
+
* Get the registered instance type for the component/connector if it exists.
|
|
94
|
+
* @param componentConnectorType The type of the component/connector.
|
|
95
|
+
* @param features The requested features of the component, if not specified the default entry will be retrieved.
|
|
96
|
+
* @returns The instance type matching the criteria if one is registered.
|
|
97
|
+
*/
|
|
98
|
+
getRegisteredInstanceTypeOptional(componentConnectorType: string, features?: string[]): string | undefined;
|
|
70
99
|
/**
|
|
71
100
|
* Get the data required to create a clone of the engine.
|
|
72
101
|
* @returns The clone data.
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,149 @@
|
|
|
1
1
|
# @twin.org/engine-core - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.2-next.10](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.9...engine-core-v0.0.2-next.10) (2025-08-26)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Miscellaneous Chores
|
|
7
|
+
|
|
8
|
+
* **engine-core:** Synchronize repo versions
|
|
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.9 to 0.0.2-next.10
|
|
16
|
+
|
|
17
|
+
## [0.0.2-next.9](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.8...engine-core-v0.0.2-next.9) (2025-08-25)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add isPrimary and isClone methods ([a7c63e9](https://github.com/twinfoundation/engine/commit/a7c63e97f54c95b104cc81e66d3fa42c6607bdc1))
|
|
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.8 to 0.0.2-next.9
|
|
30
|
+
|
|
31
|
+
## [0.0.2-next.8](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.7...engine-core-v0.0.2-next.8) (2025-08-22)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Miscellaneous Chores
|
|
35
|
+
|
|
36
|
+
* **engine-core:** Synchronize repo versions
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Dependencies
|
|
40
|
+
|
|
41
|
+
* The following workspace dependencies were updated
|
|
42
|
+
* dependencies
|
|
43
|
+
* @twin.org/engine-models bumped from 0.0.2-next.7 to 0.0.2-next.8
|
|
44
|
+
|
|
45
|
+
## [0.0.2-next.7](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.6...engine-core-v0.0.2-next.7) (2025-08-22)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
### Features
|
|
49
|
+
|
|
50
|
+
* remove unused component states ([d56d648](https://github.com/twinfoundation/engine/commit/d56d6486119ea8b8501a33f9e3a3101a08b826ed))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Dependencies
|
|
54
|
+
|
|
55
|
+
* The following workspace dependencies were updated
|
|
56
|
+
* dependencies
|
|
57
|
+
* @twin.org/engine-models bumped from 0.0.2-next.6 to 0.0.2-next.7
|
|
58
|
+
|
|
59
|
+
## [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)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
### Features
|
|
63
|
+
|
|
64
|
+
* update framework core ([acc0f8d](https://github.com/twinfoundation/engine/commit/acc0f8d455a4b8ec47f1da643139fa0f07775fa6))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### Dependencies
|
|
68
|
+
|
|
69
|
+
* The following workspace dependencies were updated
|
|
70
|
+
* dependencies
|
|
71
|
+
* @twin.org/engine-models bumped from 0.0.2-next.5 to 0.0.2-next.6
|
|
72
|
+
|
|
73
|
+
## [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)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
### Features
|
|
77
|
+
|
|
78
|
+
* add synchronised storage support ([5142e34](https://github.com/twinfoundation/engine/commit/5142e3488f09195cf9f48a9c6c6d1014231a4c2c))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### Dependencies
|
|
82
|
+
|
|
83
|
+
* The following workspace dependencies were updated
|
|
84
|
+
* dependencies
|
|
85
|
+
* @twin.org/engine-models bumped from 0.0.2-next.4 to 0.0.2-next.5
|
|
86
|
+
|
|
87
|
+
## [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)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
### Features
|
|
91
|
+
|
|
92
|
+
* add default logging component for web server ([8ad94f0](https://github.com/twinfoundation/engine/commit/8ad94f0d2d9a5241a8854b1e59fb9a55ce310142))
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
### Dependencies
|
|
96
|
+
|
|
97
|
+
* The following workspace dependencies were updated
|
|
98
|
+
* dependencies
|
|
99
|
+
* @twin.org/engine-models bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
100
|
+
|
|
101
|
+
## [0.0.2-next.3](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.2...engine-core-v0.0.2-next.3) (2025-07-24)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
### Miscellaneous Chores
|
|
105
|
+
|
|
106
|
+
* **engine-core:** Synchronize repo versions
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
### Dependencies
|
|
110
|
+
|
|
111
|
+
* The following workspace dependencies were updated
|
|
112
|
+
* dependencies
|
|
113
|
+
* @twin.org/engine-models bumped from 0.0.2-next.2 to 0.0.2-next.3
|
|
114
|
+
|
|
115
|
+
## [0.0.2-next.2](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.1...engine-core-v0.0.2-next.2) (2025-07-21)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
### Miscellaneous Chores
|
|
119
|
+
|
|
120
|
+
* **engine-core:** Synchronize repo versions
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
### Dependencies
|
|
124
|
+
|
|
125
|
+
* The following workspace dependencies were updated
|
|
126
|
+
* dependencies
|
|
127
|
+
* @twin.org/engine-models bumped from 0.0.2-next.1 to 0.0.2-next.2
|
|
128
|
+
|
|
129
|
+
## [0.0.2-next.1](https://github.com/twinfoundation/engine/compare/engine-core-v0.0.2-next.0...engine-core-v0.0.2-next.1) (2025-07-11)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
### Features
|
|
133
|
+
|
|
134
|
+
* add auth admin component ([201cd06](https://github.com/twinfoundation/engine/commit/201cd061be83afccb5a6b06856ffe7cf8db7d6b3))
|
|
135
|
+
* add mimeTypeProcessors and disableNodeIdentity ([bb7e81e](https://github.com/twinfoundation/engine/commit/bb7e81e2036fe042068a5645ec59b22e20d33aad))
|
|
136
|
+
* remove bootstrapped components, component should manage their own state ([5c7e9e4](https://github.com/twinfoundation/engine/commit/5c7e9e419ef26933e49c9c5a21a20a8961244e7f))
|
|
137
|
+
* update dependencies ([97c9f64](https://github.com/twinfoundation/engine/commit/97c9f64b6ef096963bcc5de338a2a9e99bdc1a11))
|
|
138
|
+
* use shared store mechanism ([#2](https://github.com/twinfoundation/engine/issues/2)) ([9eed8d7](https://github.com/twinfoundation/engine/commit/9eed8d7766388479b42f03e2542fe761f2156408))
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
### Dependencies
|
|
142
|
+
|
|
143
|
+
* The following workspace dependencies were updated
|
|
144
|
+
* dependencies
|
|
145
|
+
* @twin.org/engine-models bumped from 0.0.2-next.0 to 0.0.2-next.1
|
|
146
|
+
|
|
3
147
|
## 0.0.1 (2025-07-11)
|
|
4
148
|
|
|
5
149
|
|
|
@@ -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`\>
|
|
@@ -140,6 +132,60 @@ Nothing.
|
|
|
140
132
|
|
|
141
133
|
***
|
|
142
134
|
|
|
135
|
+
### isStarted()
|
|
136
|
+
|
|
137
|
+
> **isStarted**(): `boolean`
|
|
138
|
+
|
|
139
|
+
Is the engine started.
|
|
140
|
+
|
|
141
|
+
#### Returns
|
|
142
|
+
|
|
143
|
+
`boolean`
|
|
144
|
+
|
|
145
|
+
True if the engine is started.
|
|
146
|
+
|
|
147
|
+
#### Implementation of
|
|
148
|
+
|
|
149
|
+
`IEngineCore.isStarted`
|
|
150
|
+
|
|
151
|
+
***
|
|
152
|
+
|
|
153
|
+
### isPrimary()
|
|
154
|
+
|
|
155
|
+
> **isPrimary**(): `boolean`
|
|
156
|
+
|
|
157
|
+
Is this the primary engine instance.
|
|
158
|
+
|
|
159
|
+
#### Returns
|
|
160
|
+
|
|
161
|
+
`boolean`
|
|
162
|
+
|
|
163
|
+
True if the engine is the primary instance.
|
|
164
|
+
|
|
165
|
+
#### Implementation of
|
|
166
|
+
|
|
167
|
+
`IEngineCore.isPrimary`
|
|
168
|
+
|
|
169
|
+
***
|
|
170
|
+
|
|
171
|
+
### isClone()
|
|
172
|
+
|
|
173
|
+
> **isClone**(): `boolean`
|
|
174
|
+
|
|
175
|
+
Is this engine instance a clone.
|
|
176
|
+
|
|
177
|
+
#### Returns
|
|
178
|
+
|
|
179
|
+
`boolean`
|
|
180
|
+
|
|
181
|
+
True if the engine instance is a clone.
|
|
182
|
+
|
|
183
|
+
#### Implementation of
|
|
184
|
+
|
|
185
|
+
`IEngineCore.isClone`
|
|
186
|
+
|
|
187
|
+
***
|
|
188
|
+
|
|
143
189
|
### logInfo()
|
|
144
190
|
|
|
145
191
|
> **logInfo**(`message`): `void`
|
|
@@ -224,21 +270,89 @@ The state of the engine.
|
|
|
224
270
|
|
|
225
271
|
***
|
|
226
272
|
|
|
227
|
-
###
|
|
273
|
+
### getRegisteredInstances()
|
|
228
274
|
|
|
229
|
-
> **
|
|
275
|
+
> **getRegisteredInstances**(): `object`
|
|
230
276
|
|
|
231
|
-
Get the
|
|
277
|
+
Get all the registered instances.
|
|
232
278
|
|
|
233
279
|
#### Returns
|
|
234
280
|
|
|
235
281
|
`object`
|
|
236
282
|
|
|
237
|
-
The
|
|
283
|
+
The registered instances.
|
|
284
|
+
|
|
285
|
+
#### Implementation of
|
|
286
|
+
|
|
287
|
+
`IEngineCore.getRegisteredInstances`
|
|
288
|
+
|
|
289
|
+
***
|
|
290
|
+
|
|
291
|
+
### getRegisteredInstanceType()
|
|
292
|
+
|
|
293
|
+
> **getRegisteredInstanceType**(`componentConnectorType`, `features?`): `string`
|
|
294
|
+
|
|
295
|
+
Get the registered instance type for the component/connector.
|
|
296
|
+
|
|
297
|
+
#### Parameters
|
|
298
|
+
|
|
299
|
+
##### componentConnectorType
|
|
300
|
+
|
|
301
|
+
`string`
|
|
302
|
+
|
|
303
|
+
The type of the component/connector.
|
|
304
|
+
|
|
305
|
+
##### features?
|
|
306
|
+
|
|
307
|
+
`string`[]
|
|
308
|
+
|
|
309
|
+
The requested features of the component, if not specified the default entry will be retrieved.
|
|
310
|
+
|
|
311
|
+
#### Returns
|
|
312
|
+
|
|
313
|
+
`string`
|
|
314
|
+
|
|
315
|
+
The instance type matching the criteria if one is registered.
|
|
316
|
+
|
|
317
|
+
#### Throws
|
|
318
|
+
|
|
319
|
+
If a matching instance was not found.
|
|
320
|
+
|
|
321
|
+
#### Implementation of
|
|
322
|
+
|
|
323
|
+
`IEngineCore.getRegisteredInstanceType`
|
|
324
|
+
|
|
325
|
+
***
|
|
326
|
+
|
|
327
|
+
### getRegisteredInstanceTypeOptional()
|
|
328
|
+
|
|
329
|
+
> **getRegisteredInstanceTypeOptional**(`componentConnectorType`, `features?`): `undefined` \| `string`
|
|
330
|
+
|
|
331
|
+
Get the registered instance type for the component/connector if it exists.
|
|
332
|
+
|
|
333
|
+
#### Parameters
|
|
334
|
+
|
|
335
|
+
##### componentConnectorType
|
|
336
|
+
|
|
337
|
+
`string`
|
|
338
|
+
|
|
339
|
+
The type of the component/connector.
|
|
340
|
+
|
|
341
|
+
##### features?
|
|
342
|
+
|
|
343
|
+
`string`[]
|
|
344
|
+
|
|
345
|
+
The requested features of the component, if not specified the default entry will be retrieved.
|
|
346
|
+
|
|
347
|
+
#### Returns
|
|
348
|
+
|
|
349
|
+
`undefined` \| `string`
|
|
350
|
+
|
|
351
|
+
The instance type matching the criteria if one is registered.
|
|
238
352
|
|
|
239
353
|
#### Implementation of
|
|
240
354
|
|
|
241
|
-
`IEngineCore.
|
|
355
|
+
`IEngineCore.getRegisteredInstanceTypeOptional`
|
|
242
356
|
|
|
243
357
|
***
|
|
244
358
|
|
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.
|
|
3
|
+
"version": "0.0.2-next.10",
|
|
4
4
|
"description": "Engine core.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,10 +17,11 @@
|
|
|
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.
|
|
20
|
+
"@twin.org/engine-models": "0.0.2-next.10",
|
|
21
21
|
"@twin.org/entity": "next",
|
|
22
22
|
"@twin.org/logging-connector-console": "next",
|
|
23
23
|
"@twin.org/logging-models": "next",
|
|
24
|
+
"@twin.org/logging-service": "next",
|
|
24
25
|
"@twin.org/modules": "next",
|
|
25
26
|
"@twin.org/nameof": "next"
|
|
26
27
|
},
|