@syncbridge/common 0.5.11 → 0.5.12

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