@syncbridge/common 0.5.10 → 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.
- package/classes/base-element.d.ts +1 -0
- package/classes/base-element.js +3 -1
- package/constants.js +1 -1
- package/decorators/define-variable.decorator.d.ts +1 -0
- package/decorators/define-variable.decorator.js +24 -22
- package/models/enums/log-level.d.ts +1 -0
- package/models/enums/log-level.js +1 -0
- package/models/metadata/variable-metadata.d.ts +1 -0
- package/models/metadata/variable-metadata.js +6 -0
- package/package.json +1 -1
- package/processor-factory.d.ts +4 -2
- package/processor-factory.js +158 -60
- package/registry/helpers.js +40 -44
- package/utils/metadata-utils.d.ts +6 -0
- package/utils/metadata-utils.js +34 -0
package/classes/base-element.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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');
|
|
@@ -10,47 +10,49 @@ export function DefineVariable(options) {
|
|
|
10
10
|
const designType = Reflect.getMetadata('design:type', target, propertyKey);
|
|
11
11
|
if (designType === Array)
|
|
12
12
|
options.isArray = true;
|
|
13
|
+
const base = Object.getPrototypeOf(target);
|
|
14
|
+
const baseMetadata = Reflect.hasMetadata(VARIABLE_CONTAINER, base)
|
|
15
|
+
? deepClone(Reflect.getMetadata(VARIABLE_CONTAINER, base))
|
|
16
|
+
: {};
|
|
17
|
+
let metadata = merge(options, baseMetadata[propertyKey] || {}, {
|
|
18
|
+
deep: 'full',
|
|
19
|
+
ignoreNulls: false,
|
|
20
|
+
ignoreUndefined: false,
|
|
21
|
+
keepExisting: true,
|
|
22
|
+
});
|
|
13
23
|
if (typeof options.variables === 'function') {
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
metadata.type = VariableType.Nested;
|
|
25
|
+
metadata.variables = Reflect.getMetadata(VARIABLE_CONTAINER, options.variables.prototype);
|
|
16
26
|
}
|
|
17
|
-
if (
|
|
18
|
-
|
|
27
|
+
if (metadata.enumValues && !metadata.type) {
|
|
28
|
+
metadata.type = VariableType.Enum;
|
|
19
29
|
}
|
|
20
|
-
if (
|
|
21
|
-
delete
|
|
22
|
-
if (!
|
|
30
|
+
if (metadata.type !== VariableType.Enum)
|
|
31
|
+
delete metadata.enumValues;
|
|
32
|
+
if (!metadata.type) {
|
|
23
33
|
if (designType === String)
|
|
24
|
-
|
|
34
|
+
metadata.type = VariableType.String;
|
|
25
35
|
else if (designType === Boolean)
|
|
26
|
-
|
|
36
|
+
metadata.type = VariableType.Boolean;
|
|
27
37
|
else if (designType === Number)
|
|
28
|
-
|
|
38
|
+
metadata.type = VariableType.Number;
|
|
29
39
|
else if (typeof designType === 'function' &&
|
|
30
40
|
Reflect.hasMetadata(VARIABLE_CONTAINER, designType.prototype)) {
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
metadata.type = VariableType.Nested;
|
|
42
|
+
metadata.variables = Reflect.getMetadata(VARIABLE_CONTAINER, designType.prototype);
|
|
33
43
|
}
|
|
34
44
|
}
|
|
35
|
-
if (
|
|
45
|
+
if (metadata.isArray && !metadata.type)
|
|
36
46
|
throw new TypeError('Array variables must have type defined. ' +
|
|
37
47
|
(target.constructor.name +
|
|
38
48
|
'.' +
|
|
39
49
|
propertyKey +
|
|
40
50
|
' is an array variable'));
|
|
41
|
-
const base = Object.getPrototypeOf(target);
|
|
42
|
-
const baseMetadata = Reflect.hasMetadata(VARIABLE_CONTAINER, base)
|
|
43
|
-
? deepClone(Reflect.getMetadata(VARIABLE_CONTAINER, base))
|
|
44
|
-
: {};
|
|
45
|
-
let metadata = merge(baseMetadata, options, {
|
|
46
|
-
deep: 'full',
|
|
47
|
-
ignoreNulls: false,
|
|
48
|
-
ignoreUndefined: false,
|
|
49
|
-
});
|
|
50
51
|
metadata = omitUndefined(metadata, 'full');
|
|
51
52
|
const metadataRecord = Reflect.hasOwnMetadata(VARIABLE_CONTAINER, target)
|
|
52
53
|
? Reflect.getMetadata(VARIABLE_CONTAINER, target)
|
|
53
54
|
: {};
|
|
55
|
+
merge(metadataRecord, baseMetadata);
|
|
54
56
|
metadataRecord[propertyKey] = metadata;
|
|
55
57
|
Reflect.defineMetadata(VARIABLE_CONTAINER, metadataRecord, target);
|
|
56
58
|
};
|
|
@@ -21,6 +21,12 @@ let VariableMetadata = class VariableMetadata {
|
|
|
21
21
|
ignored;
|
|
22
22
|
hotPlug;
|
|
23
23
|
};
|
|
24
|
+
__decorate([
|
|
25
|
+
ApiField({
|
|
26
|
+
description: 'Index of the variable. Variables with higher index will be displayed first',
|
|
27
|
+
}),
|
|
28
|
+
__metadata("design:type", Number)
|
|
29
|
+
], VariableMetadata.prototype, "index", void 0);
|
|
24
30
|
__decorate([
|
|
25
31
|
ApiField({
|
|
26
32
|
description: 'Determine if the variable can be changed while worker running',
|
package/package.json
CHANGED
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
|
@@ -16,10 +16,17 @@ export var ProcessorFactory;
|
|
|
16
16
|
values: profile.values || {},
|
|
17
17
|
dataDirectory: options?.dataDirectory,
|
|
18
18
|
});
|
|
19
|
-
const
|
|
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
|
-
|
|
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(
|
|
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
|
-
componentInstance
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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 = {}));
|
package/registry/helpers.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { deepClone, merge } from '@jsopen/objects';
|
|
2
|
-
import { ComponentMetadata, ProcessorMetadata } from '../models/index.js';
|
|
2
|
+
import { ComponentMetadata, ProcessorMetadata, } from '../models/index.js';
|
|
3
3
|
import { initializeModelsDocument } from '../models-document.js';
|
|
4
4
|
import { resolvePromisesDeep } from '../utils/resolve-promises.js';
|
|
5
5
|
export async function normalizeProcessorMetadata(metadata) {
|
|
6
6
|
const decoder = await getProcMetadataTypeDecoder();
|
|
7
7
|
let out = await resolvePromisesDeep(metadata);
|
|
8
|
-
out = deepClone(
|
|
8
|
+
out = deepClone(out);
|
|
9
|
+
out = decoder({
|
|
9
10
|
className: out.className,
|
|
10
11
|
displayName: out.displayName,
|
|
11
12
|
description: out.description,
|
|
@@ -13,35 +14,18 @@ export async function normalizeProcessorMetadata(metadata) {
|
|
|
13
14
|
author: out.author,
|
|
14
15
|
tags: out.tags,
|
|
15
16
|
abstract: out.abstract,
|
|
16
|
-
variables: out.variables,
|
|
17
|
-
components: out.components,
|
|
17
|
+
variables: normalizeVariables(out.variables),
|
|
18
|
+
components: normalizeComponents(out.components),
|
|
18
19
|
...out,
|
|
19
20
|
});
|
|
20
|
-
if (out.variables) {
|
|
21
|
-
/** Convert object enumValues to arrays */
|
|
22
|
-
for (const v of Object.values(out.variables)) {
|
|
23
|
-
if (v.enumValues &&
|
|
24
|
-
typeof v.enumValues === 'object' &&
|
|
25
|
-
!Array.isArray(v.enumValues)) {
|
|
26
|
-
let values = v.enumValues;
|
|
27
|
-
const keys = Object.keys(values).filter(k => !/^\d+$/.test(k));
|
|
28
|
-
values = keys.reduce((a, k) => {
|
|
29
|
-
if (values[k] != null)
|
|
30
|
-
a.push(values[k]);
|
|
31
|
-
return a;
|
|
32
|
-
}, []);
|
|
33
|
-
v.enumValues = values;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
out = decoder(out);
|
|
38
21
|
merge(out, metadata, { keepExisting: true, deep: 'full' });
|
|
39
22
|
return out;
|
|
40
23
|
}
|
|
41
24
|
export async function normalizeComponentMetadata(metadata) {
|
|
42
25
|
const decoder = await getCompMetadataTypeDecoder();
|
|
43
26
|
let out = await resolvePromisesDeep(metadata);
|
|
44
|
-
out = deepClone(
|
|
27
|
+
out = deepClone(out);
|
|
28
|
+
out = decoder({
|
|
45
29
|
className: out.className,
|
|
46
30
|
displayName: out.displayName,
|
|
47
31
|
description: out.description,
|
|
@@ -50,32 +34,44 @@ export async function normalizeComponentMetadata(metadata) {
|
|
|
50
34
|
interfaces: out.interfaces,
|
|
51
35
|
tags: out.tags,
|
|
52
36
|
abstract: out.abstract,
|
|
53
|
-
variables: out.variables,
|
|
54
|
-
components: out.components,
|
|
37
|
+
variables: normalizeVariables(out.variables),
|
|
38
|
+
components: normalizeComponents(out.components),
|
|
55
39
|
...out,
|
|
56
40
|
});
|
|
57
|
-
if (out.variables) {
|
|
58
|
-
/** Convert object enumValues to arrays */
|
|
59
|
-
for (const v of Object.values(out.variables)) {
|
|
60
|
-
if (v.enumValues &&
|
|
61
|
-
typeof v.enumValues === 'object' &&
|
|
62
|
-
!Array.isArray(v.enumValues)) {
|
|
63
|
-
let values = v.enumValues;
|
|
64
|
-
const keys = Object.keys(values).filter(k => !/^\d+$/.test(k));
|
|
65
|
-
values = keys.reduce((a, k) => {
|
|
66
|
-
if (values[k] != null)
|
|
67
|
-
a.push(values[k]);
|
|
68
|
-
return a;
|
|
69
|
-
// v => !(typeof v === 'number' && !keys.includes(String(v))),
|
|
70
|
-
}, []);
|
|
71
|
-
v.enumValues = values;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
out = decoder(out);
|
|
76
41
|
merge(out, metadata, { keepExisting: true, deep: 'full' });
|
|
77
42
|
return out;
|
|
78
43
|
}
|
|
44
|
+
function normalizeComponents(components) {
|
|
45
|
+
if (!components)
|
|
46
|
+
return;
|
|
47
|
+
for (const component of Object.values(components)) {
|
|
48
|
+
if (component.variables)
|
|
49
|
+
component.variables = normalizeVariables(component.variables);
|
|
50
|
+
if (component.components)
|
|
51
|
+
component.components = normalizeComponents(component.components);
|
|
52
|
+
}
|
|
53
|
+
return components;
|
|
54
|
+
}
|
|
55
|
+
function normalizeVariables(variables) {
|
|
56
|
+
if (!variables)
|
|
57
|
+
return;
|
|
58
|
+
/** Convert object enumValues to arrays */
|
|
59
|
+
for (const v of Object.values(variables)) {
|
|
60
|
+
if (v.enumValues &&
|
|
61
|
+
typeof v.enumValues === 'object' &&
|
|
62
|
+
!Array.isArray(v.enumValues)) {
|
|
63
|
+
let values = v.enumValues;
|
|
64
|
+
const keys = Object.keys(values).filter(k => !/^\d+$/.test(k));
|
|
65
|
+
values = keys.reduce((a, k) => {
|
|
66
|
+
if (values[k] != null)
|
|
67
|
+
a.push(values[k]);
|
|
68
|
+
return a;
|
|
69
|
+
}, []);
|
|
70
|
+
v.enumValues = values;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return variables;
|
|
74
|
+
}
|
|
79
75
|
// ************************************************************************
|
|
80
76
|
// ************************************************************************
|
|
81
77
|
let _compMetadataTypeDecoder;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
2
2
|
import { ProcessorMetadata, Profile } from '../models/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Materializes metadata from profile.
|
|
5
|
+
*/
|
|
3
6
|
export declare function materializeMetadata(profile: Profile): ProcessorMetadata;
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
4
10
|
export declare function materializeMetadataSilent(profile: Profile): {
|
|
5
11
|
metadata: ProcessorMetadata;
|
|
6
12
|
issues?: StackExecutor.Issue[];
|
package/utils/metadata-utils.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { clone, merge, omitUndefined } from '@jsopen/objects';
|
|
2
2
|
import { SbError } from '../classes/sb-error.js';
|
|
3
3
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
4
|
+
import { VariableType, } from '../models/index.js';
|
|
4
5
|
import { ExtensionRegistry } from '../registry/extension-registry.js';
|
|
6
|
+
/**
|
|
7
|
+
* Materializes metadata from profile.
|
|
8
|
+
*/
|
|
5
9
|
export function materializeMetadata(profile) {
|
|
6
10
|
const { metadata, issues } = materializeMetadataSilent(profile);
|
|
7
11
|
if (issues?.length) {
|
|
@@ -16,6 +20,9 @@ export function materializeMetadata(profile) {
|
|
|
16
20
|
}
|
|
17
21
|
return metadata;
|
|
18
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
19
26
|
export function materializeMetadataSilent(profile) {
|
|
20
27
|
const stackExecutor = new StackExecutor();
|
|
21
28
|
const processorRec = ExtensionRegistry.getProcessor(profile.processorClass);
|
|
@@ -69,6 +76,7 @@ function _materializeComponents(stackExecutor, metadata, profile) {
|
|
|
69
76
|
const reg = ExtensionRegistry.getComponent(profileComponent.className);
|
|
70
77
|
materializedComponent.className = profileComponent.className;
|
|
71
78
|
materializedComponent.variables = merge({}, [reg.metadata.variables || {}, metadataComponent.variables || {}], { deep: 'full' });
|
|
79
|
+
materializedComponent.variables = sortVariables(materializedComponent.variables);
|
|
72
80
|
if (metadataComponent.className) {
|
|
73
81
|
if (materializedComponent.className &&
|
|
74
82
|
materializedComponent.className !== metadataComponent.className)
|
|
@@ -97,3 +105,29 @@ function _materializeComponents(stackExecutor, metadata, profile) {
|
|
|
97
105
|
}
|
|
98
106
|
return out;
|
|
99
107
|
}
|
|
108
|
+
function sortVariables(variables) {
|
|
109
|
+
if (!variables)
|
|
110
|
+
return;
|
|
111
|
+
const keys = Object.keys(variables);
|
|
112
|
+
const sorted = [...keys]
|
|
113
|
+
.sort((a, b) => {
|
|
114
|
+
const va = variables[a];
|
|
115
|
+
const vb = variables[b];
|
|
116
|
+
const indexA = va.index ?? Number.MAX_SAFE_INTEGER;
|
|
117
|
+
const indexB = vb.index ?? Number.MAX_SAFE_INTEGER;
|
|
118
|
+
if (indexA > indexB)
|
|
119
|
+
return 1;
|
|
120
|
+
if (indexA < indexB)
|
|
121
|
+
return -1;
|
|
122
|
+
if (va.type === VariableType.Nested && vb.type !== VariableType.Nested)
|
|
123
|
+
return 1;
|
|
124
|
+
if (vb.type === VariableType.Nested && va.type !== VariableType.Nested)
|
|
125
|
+
return -1;
|
|
126
|
+
return keys.indexOf(a) > keys.indexOf(b) ? 1 : -1;
|
|
127
|
+
})
|
|
128
|
+
.reduce((a, k) => {
|
|
129
|
+
a[k] = variables[k];
|
|
130
|
+
return a;
|
|
131
|
+
}, {});
|
|
132
|
+
return sorted;
|
|
133
|
+
}
|