@syncbridge/common 0.5.11 → 0.6.0
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/classes/base-element.d.ts +1 -0
- package/classes/base-element.js +7 -3
- package/constants.js +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/models/enums/log-level.d.ts +1 -0
- package/models/enums/log-level.js +1 -0
- package/package.json +3 -2
- package/processor-factory.d.ts +4 -2
- package/processor-factory.js +162 -59
- /package/utils/{metadata-utils.d.ts → materialize-metadata.d.ts} +0 -0
- /package/utils/{metadata-utils.js → materialize-metadata.js} +0 -0
package/classes/base-element.js
CHANGED
|
@@ -12,8 +12,10 @@ export class BaseElement extends Runnable {
|
|
|
12
12
|
this.logger = init.logger;
|
|
13
13
|
this.name = init.name;
|
|
14
14
|
this.values = init.values;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
this.on('error', err => this.logger?.error(err));
|
|
16
|
+
this.on('values-updated', (properties) => {
|
|
17
|
+
this.logger?.info(`Configuration changed. Updated properties: ${properties.join(',')}`);
|
|
18
|
+
});
|
|
17
19
|
}
|
|
18
20
|
get status() {
|
|
19
21
|
return this._context.calculatedStatus || this._context.status;
|
|
@@ -48,7 +50,9 @@ export class BaseElement extends Runnable {
|
|
|
48
50
|
await Promise.all(Object.values(this.components).map(component => component.init()));
|
|
49
51
|
}
|
|
50
52
|
async _start(abortSignal) {
|
|
51
|
-
|
|
53
|
+
if (this.status === ServiceStatus.starting ||
|
|
54
|
+
this.status === ServiceStatus.started)
|
|
55
|
+
await Promise.all(Object.values(this.components).map(component => component.start(abortSignal)));
|
|
52
56
|
}
|
|
53
57
|
async _stop() {
|
|
54
58
|
await Promise.all(Object.values(this.components)
|
package/constants.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const version = '0.
|
|
1
|
+
export const version = '0.6.0';
|
|
2
2
|
export const OWN_ELEMENT_METADATA = Symbol.for('OWN_ELEMENT_METADATA');
|
|
3
3
|
export const COMPONENT_OPTIONS = Symbol.for('COMPONENT_OPTIONS');
|
|
4
4
|
export const PROCESSOR_OPTIONS = Symbol.for('PROCESSOR_OPTIONS');
|
package/index.d.ts
CHANGED
|
@@ -16,5 +16,5 @@ export * from './models-document.js';
|
|
|
16
16
|
export * from './processor-factory.js';
|
|
17
17
|
export * from './registry/extension-package.js';
|
|
18
18
|
export * from './registry/extension-registry.js';
|
|
19
|
-
export * from './utils/metadata
|
|
19
|
+
export * from './utils/materialize-metadata.js';
|
|
20
20
|
export * from './utils/profile-utils.js';
|
package/index.js
CHANGED
|
@@ -16,5 +16,5 @@ export * from './models-document.js';
|
|
|
16
16
|
export * from './processor-factory.js';
|
|
17
17
|
export * from './registry/extension-package.js';
|
|
18
18
|
export * from './registry/extension-registry.js';
|
|
19
|
-
export * from './utils/metadata
|
|
19
|
+
export * from './utils/materialize-metadata.js';
|
|
20
20
|
export * from './utils/profile-utils.js';
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncbridge/common",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "SyncBridge Common utilities",
|
|
5
5
|
"author": "Panates Inc",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@jsopen/objects": "^2.1.1",
|
|
9
|
+
"fast-deep-equal": "^3.1.3",
|
|
9
10
|
"node-events-async": "^1.5.0",
|
|
10
11
|
"reflect-metadata": "^0.2.2",
|
|
11
12
|
"semver": "^7.7.4",
|
|
12
13
|
"ts-gems": "^3.11.3",
|
|
13
|
-
"valgen": "^5.19.
|
|
14
|
+
"valgen": "^5.19.5"
|
|
14
15
|
},
|
|
15
16
|
"peerDependencies": {
|
|
16
17
|
"@opra/common": ">=1.17.1 <2"
|
package/processor-factory.d.ts
CHANGED
|
@@ -6,12 +6,14 @@ export declare namespace ProcessorFactory {
|
|
|
6
6
|
const METADATA_KEY: unique symbol;
|
|
7
7
|
const PROFILE_KEY: unique symbol;
|
|
8
8
|
interface ProcessorOptions {
|
|
9
|
-
logger
|
|
9
|
+
logger?: ILogger;
|
|
10
10
|
dataDirectory?: string;
|
|
11
11
|
}
|
|
12
12
|
function createProcessor<T extends ProcessorBase>(profile: Profile, options?: ProcessorOptions): Promise<{
|
|
13
13
|
processor: T;
|
|
14
14
|
issues: StackExecutor.Issue[];
|
|
15
15
|
}>;
|
|
16
|
-
function updateProcessor(processor: ProcessorBase, profile: Profile, options?: ProcessorOptions): Promise<
|
|
16
|
+
function updateProcessor(processor: ProcessorBase, profile: Profile, options?: ProcessorOptions): Promise<{
|
|
17
|
+
issues: StackExecutor.Issue[];
|
|
18
|
+
}>;
|
|
17
19
|
}
|
package/processor-factory.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import equal from 'fast-deep-equal';
|
|
1
2
|
import { StackExecutor } from './classes/stack-executor.js';
|
|
2
3
|
import { initializeModelsDocument } from './models-document.js';
|
|
3
4
|
import { ExtensionRegistry } from './registry/extension-registry.js';
|
|
4
|
-
import { materializeMetadata } from './utils/metadata
|
|
5
|
+
import { materializeMetadata } from './utils/materialize-metadata.js';
|
|
5
6
|
export var ProcessorFactory;
|
|
6
7
|
(function (ProcessorFactory) {
|
|
7
8
|
ProcessorFactory.METADATA_KEY = Symbol('METADATA');
|
|
@@ -16,10 +17,17 @@ export var ProcessorFactory;
|
|
|
16
17
|
values: profile.values || {},
|
|
17
18
|
dataDirectory: options?.dataDirectory,
|
|
18
19
|
});
|
|
19
|
-
const
|
|
20
|
+
const ctx = {
|
|
21
|
+
stackExecutor: new StackExecutor(),
|
|
22
|
+
processor,
|
|
23
|
+
profile,
|
|
24
|
+
options,
|
|
25
|
+
valueUpdates: new Map(),
|
|
26
|
+
};
|
|
27
|
+
await _configureProcessor(ctx);
|
|
20
28
|
return {
|
|
21
29
|
processor: processor,
|
|
22
|
-
issues,
|
|
30
|
+
issues: ctx.stackExecutor.issues,
|
|
23
31
|
};
|
|
24
32
|
}
|
|
25
33
|
ProcessorFactory.createProcessor = createProcessor;
|
|
@@ -28,69 +36,164 @@ export var ProcessorFactory;
|
|
|
28
36
|
processor.logger = options.logger;
|
|
29
37
|
if (options?.dataDirectory)
|
|
30
38
|
processor.dataDirectory = options.dataDirectory;
|
|
31
|
-
|
|
39
|
+
const ctx = {
|
|
40
|
+
stackExecutor: new StackExecutor(),
|
|
41
|
+
processor,
|
|
42
|
+
profile,
|
|
43
|
+
options,
|
|
44
|
+
valueUpdates: new Map(),
|
|
45
|
+
};
|
|
46
|
+
await _configureProcessor(ctx);
|
|
47
|
+
const signalUpdates = async (obj) => {
|
|
48
|
+
if (obj.components) {
|
|
49
|
+
for (const component of Object.values(obj.components)) {
|
|
50
|
+
await signalUpdates(component);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const properties = ctx.valueUpdates.get(obj);
|
|
54
|
+
if (properties?.length) {
|
|
55
|
+
await obj.emitAsyncSafe('values-updated', properties);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
await signalUpdates(processor);
|
|
59
|
+
return {
|
|
60
|
+
issues: ctx.stackExecutor.issues,
|
|
61
|
+
};
|
|
32
62
|
}
|
|
33
63
|
ProcessorFactory.updateProcessor = updateProcessor;
|
|
34
|
-
async function _configureProcessor(
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
64
|
+
async function _configureProcessor(ctx) {
|
|
65
|
+
const { processor, profile } = ctx;
|
|
66
|
+
const cmpCtx = {
|
|
67
|
+
...ctx,
|
|
68
|
+
owner: processor,
|
|
69
|
+
curPath: '',
|
|
70
|
+
newMetadata: materializeMetadata(profile),
|
|
71
|
+
newProfile: profile,
|
|
72
|
+
oldMetadata: processor[ProcessorFactory.METADATA_KEY],
|
|
73
|
+
oldProfile: processor[ProcessorFactory.PROFILE_KEY],
|
|
74
|
+
};
|
|
75
|
+
_validateComponents(cmpCtx);
|
|
76
|
+
await _configureComponents(cmpCtx);
|
|
77
|
+
processor[ProcessorFactory.METADATA_KEY] = cmpCtx.newMetadata;
|
|
78
|
+
processor[ProcessorFactory.PROFILE_KEY] = profile;
|
|
79
|
+
}
|
|
80
|
+
function _validateComponents(ctx) {
|
|
81
|
+
const { newMetadata, newProfile, oldMetadata, oldProfile, curPath, owner, stackExecutor, processor, } = ctx;
|
|
82
|
+
if (!newMetadata.components)
|
|
83
|
+
return;
|
|
84
|
+
// Stack: components
|
|
85
|
+
stackExecutor.execute('components', () => {
|
|
86
|
+
for (const [key, childMetadata] of Object.entries(newMetadata.components)) {
|
|
87
|
+
// Stack: components/componentName
|
|
88
|
+
stackExecutor.execute(key, () => {
|
|
89
|
+
const oldChildMetadata = oldMetadata?.components?.[key];
|
|
90
|
+
const oldChildProfile = oldProfile?.components?.[key];
|
|
91
|
+
const childProfile = newProfile.components[key];
|
|
92
|
+
const componentPath = curPath ? curPath + '/' + key : key;
|
|
93
|
+
const componentInstance = owner.components?.[key];
|
|
94
|
+
if (processor.stopped &&
|
|
95
|
+
oldMetadata?.className &&
|
|
96
|
+
oldMetadata?.className !== newMetadata.className)
|
|
97
|
+
throw new Error('Can not change component class while processor running. You should stop it first.');
|
|
98
|
+
/** Validate sub components */
|
|
99
|
+
if (childMetadata.components) {
|
|
100
|
+
_validateComponents({
|
|
101
|
+
...ctx,
|
|
102
|
+
owner: componentInstance,
|
|
103
|
+
curPath: componentPath,
|
|
104
|
+
newMetadata: childMetadata,
|
|
105
|
+
newProfile: childProfile,
|
|
106
|
+
oldMetadata: oldChildMetadata,
|
|
107
|
+
oldProfile: oldChildProfile,
|
|
78
108
|
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
async function _configureComponents(ctx) {
|
|
115
|
+
const { newMetadata, stackExecutor } = ctx;
|
|
116
|
+
if (!newMetadata.components)
|
|
117
|
+
return;
|
|
118
|
+
// Stack: components
|
|
119
|
+
await stackExecutor.executeAsync('components', async () => {
|
|
120
|
+
for (const [key, childMetadata] of Object.entries(newMetadata.components)) {
|
|
121
|
+
// Stack: components/componentName
|
|
122
|
+
await stackExecutor.executeAsync(key, async () => {
|
|
123
|
+
await _configureComponent(ctx, key, childMetadata);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async function _configureComponent(ctx, key, childMetadata) {
|
|
129
|
+
const { newProfile, oldMetadata, oldProfile, curPath, owner, processor } = ctx;
|
|
130
|
+
const oldChildMetadata = oldMetadata?.components?.[key];
|
|
131
|
+
const oldChildProfile = oldProfile?.components?.[key];
|
|
132
|
+
const childProfile = newProfile.components[key];
|
|
133
|
+
const componentPath = curPath ? curPath + '/' + key : key;
|
|
134
|
+
let componentInstance = owner.components?.[key];
|
|
135
|
+
/** Create the component only if the owner stopped */ // todo implement hotplug components
|
|
136
|
+
if (owner.stopped) {
|
|
137
|
+
const compReg = ExtensionRegistry.getComponent(childMetadata.className);
|
|
138
|
+
/** Create the component instance */
|
|
139
|
+
const compClass = await compReg.getClass();
|
|
140
|
+
componentInstance = new compClass({
|
|
141
|
+
processor: processor,
|
|
142
|
+
parent: owner,
|
|
143
|
+
name: key,
|
|
144
|
+
path: componentPath,
|
|
145
|
+
values: childProfile.values || {},
|
|
146
|
+
});
|
|
147
|
+
owner.components = owner.components || {};
|
|
148
|
+
owner.components[key] = componentInstance;
|
|
149
|
+
if (childMetadata.propertyKey)
|
|
150
|
+
owner[childMetadata.propertyKey] = componentInstance;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
componentInstance.values = {};
|
|
154
|
+
const patchValues = (target, valPath, newValues, newVariables, oldValues, oldVariables) => {
|
|
155
|
+
if (oldValues)
|
|
156
|
+
Object.assign(target, oldValues);
|
|
157
|
+
const updatedValues = ctx.valueUpdates.get(componentInstance) || [];
|
|
158
|
+
ctx.valueUpdates.set(componentInstance, updatedValues);
|
|
159
|
+
if (newVariables) {
|
|
160
|
+
for (const [varKey, varMeta] of Object.entries(newVariables)) {
|
|
161
|
+
const keyPath = valPath ? valPath + '.' + varKey : varKey;
|
|
162
|
+
/** Update only hotplug variables */
|
|
163
|
+
if (varMeta?.hotPlug !== true)
|
|
164
|
+
continue;
|
|
165
|
+
if (varMeta.type === 'nested') {
|
|
166
|
+
target[varKey] = {};
|
|
167
|
+
patchValues(target[varKey], keyPath, newValues[varKey], newVariables[varKey]?.variables || {}, oldValues?.[varKey], oldVariables?.[varKey]?.variables);
|
|
168
|
+
continue;
|
|
82
169
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
170
|
+
if (!equal(target[varKey], newValues[varKey])) {
|
|
171
|
+
updatedValues.push(keyPath);
|
|
172
|
+
target[varKey] = newValues[varKey];
|
|
86
173
|
}
|
|
87
|
-
}
|
|
174
|
+
}
|
|
88
175
|
}
|
|
176
|
+
};
|
|
177
|
+
patchValues(componentInstance.values, '', childProfile.values || {}, childMetadata.variables || {}, oldChildProfile?.values, oldChildMetadata?.variables);
|
|
178
|
+
}
|
|
179
|
+
/** Create the child logger */
|
|
180
|
+
componentInstance.logger = owner.logger?.child({
|
|
181
|
+
component: componentPath,
|
|
182
|
+
});
|
|
183
|
+
if (childProfile.settings?.logs?.level) {
|
|
184
|
+
componentInstance.logger.level = childProfile.settings?.logs?.level;
|
|
185
|
+
}
|
|
186
|
+
/** Initialize sub components */
|
|
187
|
+
if (childMetadata.components) {
|
|
188
|
+
await _configureComponents({
|
|
189
|
+
...ctx,
|
|
190
|
+
owner: componentInstance,
|
|
191
|
+
curPath: componentPath,
|
|
192
|
+
newMetadata: childMetadata,
|
|
193
|
+
newProfile: childProfile,
|
|
194
|
+
oldMetadata: oldChildMetadata,
|
|
195
|
+
oldProfile: oldChildProfile,
|
|
89
196
|
});
|
|
90
197
|
}
|
|
91
|
-
await configureComponents(processor, '', processorMetadata, profile, processor[ProcessorFactory.METADATA_KEY], processor[ProcessorFactory.PROFILE_KEY]);
|
|
92
|
-
processor[ProcessorFactory.METADATA_KEY] = processorMetadata;
|
|
93
|
-
processor[ProcessorFactory.PROFILE_KEY] = profile;
|
|
94
|
-
return stackExecutor.issues;
|
|
95
198
|
}
|
|
96
199
|
})(ProcessorFactory || (ProcessorFactory = {}));
|
|
File without changes
|
|
File without changes
|