@syncbridge/common 0.6.10 → 0.6.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/constants.js +1 -1
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/models/metadata/component-metadata.js +2 -3
- package/models/metadata/element-metadata.js +2 -3
- package/package.json +3 -3
- package/registry/extension-package.d.ts +1 -9
- package/registry/extension-package.js +0 -157
- package/registry/extension-registry.d.ts +48 -15
- package/registry/extension-registry.js +145 -60
- package/registry/locate-package-json.d.ts +4 -0
- package/registry/locate-package-json.js +17 -0
- package/utils/normalize-metadata.d.ts +12 -0
- package/utils/normalize-metadata.js +149 -0
- package/registry/normalize-metadata.d.ts +0 -3
- package/registry/normalize-metadata.js +0 -98
package/constants.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const version = '0.6.
|
|
1
|
+
export const version = '0.6.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');
|
package/index.d.ts
CHANGED
|
@@ -18,3 +18,5 @@ export * from './registry/extension-package.js';
|
|
|
18
18
|
export * from './registry/extension-registry.js';
|
|
19
19
|
export * from './utils/decode-profile.js';
|
|
20
20
|
export * from './utils/materialize-metadata.js';
|
|
21
|
+
export * from './utils/normalize-metadata.js';
|
|
22
|
+
export * from './utils/type-guartds.js';
|
package/index.js
CHANGED
|
@@ -18,3 +18,5 @@ export * from './registry/extension-package.js';
|
|
|
18
18
|
export * from './registry/extension-registry.js';
|
|
19
19
|
export * from './utils/decode-profile.js';
|
|
20
20
|
export * from './utils/materialize-metadata.js';
|
|
21
|
+
export * from './utils/normalize-metadata.js';
|
|
22
|
+
export * from './utils/type-guartds.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
|
-
import { ApiField, ComplexType } from '@opra/common';
|
|
2
|
+
import { ApiField, ArrayType, ComplexType } from '@opra/common';
|
|
3
3
|
import { ElementMetadata } from './element-metadata.js';
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
@@ -13,8 +13,7 @@ __decorate([
|
|
|
13
13
|
ApiField({
|
|
14
14
|
label: 'Interfaces',
|
|
15
15
|
description: 'Interfaces which this component implemented',
|
|
16
|
-
type: 'string',
|
|
17
|
-
isArray: true,
|
|
16
|
+
type: ArrayType('string'),
|
|
18
17
|
}),
|
|
19
18
|
__metadata("design:type", Array)
|
|
20
19
|
], ComponentMetadata.prototype, "interfaces", void 0);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
|
-
import { ApiField, ComplexType } from '@opra/common';
|
|
2
|
+
import { ApiField, ArrayType, ComplexType } from '@opra/common';
|
|
3
3
|
import { AuthorMetadata } from './author-metadata.js';
|
|
4
4
|
import { VariableMetadataRecord } from './variable-metadata.js';
|
|
5
5
|
/**
|
|
@@ -69,8 +69,7 @@ __decorate([
|
|
|
69
69
|
ApiField({
|
|
70
70
|
label: 'Tags',
|
|
71
71
|
description: 'Tags of the component. Tags are used to group components',
|
|
72
|
-
type: 'string',
|
|
73
|
-
isArray: true,
|
|
72
|
+
type: ArrayType('string'),
|
|
74
73
|
}),
|
|
75
74
|
__metadata("design:type", Array)
|
|
76
75
|
], ElementMetadata.prototype, "tags", void 0);
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncbridge/common",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.12",
|
|
4
4
|
"description": "SyncBridge Common utilities",
|
|
5
5
|
"author": "Panates Inc",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@jsopen/objects": "^2.2.0",
|
|
9
9
|
"fast-deep-equal": "^3.1.3",
|
|
10
|
-
"node-events-async": "^1.5.
|
|
10
|
+
"node-events-async": "^1.5.2",
|
|
11
11
|
"reflect-metadata": "^0.2.2",
|
|
12
12
|
"semver": "^7.7.4",
|
|
13
|
-
"ts-gems": "^3.11.
|
|
13
|
+
"ts-gems": "^3.11.5",
|
|
14
14
|
"valgen": "^5.19.5"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
@@ -3,7 +3,6 @@ import { Type } from 'ts-gems';
|
|
|
3
3
|
import { ComponentBase } from '../classes/component-base.js';
|
|
4
4
|
import { ProcessorBase } from '../classes/processor-base.js';
|
|
5
5
|
import { ComponentMetadata, ProcessorMetadata } from '../models/index.js';
|
|
6
|
-
import type { ExtensionRegistry } from './extension-registry.js';
|
|
7
6
|
/**
|
|
8
7
|
*
|
|
9
8
|
*/
|
|
@@ -11,18 +10,11 @@ export declare class ExtensionPackage {
|
|
|
11
10
|
name: string;
|
|
12
11
|
version: string;
|
|
13
12
|
description: string;
|
|
13
|
+
path: string;
|
|
14
14
|
entryPoint: string;
|
|
15
15
|
components: ComponentExtension[];
|
|
16
16
|
processors: ProcessorExtension[];
|
|
17
17
|
errors: Error[];
|
|
18
|
-
sortVersions(): void;
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
* @param directory
|
|
22
|
-
* @static
|
|
23
|
-
*/
|
|
24
|
-
static fromDirectory(directory: string): Promise<ExtensionPackage>;
|
|
25
|
-
static fromNodePackage(specifier: string, resolver: ExtensionRegistry.Resolver | undefined): Promise<ExtensionPackage>;
|
|
26
18
|
}
|
|
27
19
|
/**
|
|
28
20
|
*
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import process from 'node:process';
|
|
5
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
|
-
import { updateErrorMessage } from '@jsopen/objects';
|
|
7
2
|
import { SbError } from '../classes/sb-error.js';
|
|
8
|
-
import { COMPONENT_OPTIONS, PROCESSOR_OPTIONS } from '../constants.js';
|
|
9
3
|
import { isComponentBase, isProcessorBase } from '../utils/type-guartds.js';
|
|
10
|
-
import { normalizeComponentMetadata, normalizeProcessorMetadata, } from './normalize-metadata.js';
|
|
11
4
|
/**
|
|
12
5
|
*
|
|
13
6
|
*/
|
|
@@ -15,140 +8,6 @@ export class ExtensionPackage {
|
|
|
15
8
|
components = [];
|
|
16
9
|
processors = [];
|
|
17
10
|
errors = [];
|
|
18
|
-
sortVersions() {
|
|
19
|
-
this.components.sort((a, b) => a.version.localeCompare(b.version));
|
|
20
|
-
this.processors.sort((a, b) => a.version.localeCompare(b.version));
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* @param directory
|
|
25
|
-
* @static
|
|
26
|
-
*/
|
|
27
|
-
static async fromDirectory(directory) {
|
|
28
|
-
let filename = path.join(directory, 'package.json');
|
|
29
|
-
if (!fs.existsSync(filename))
|
|
30
|
-
throw new SbError(`Directory "${directory}" does not contain package.json`);
|
|
31
|
-
const pkgJson = JSON.parse(fs.readFileSync(filename, 'utf8'));
|
|
32
|
-
if (!pkgJson.syncbridge)
|
|
33
|
-
throw new SbError(`"${pkgJson.name}" is not a SyncBridge extension package`);
|
|
34
|
-
const out = new ExtensionPackage();
|
|
35
|
-
out.name = pkgJson.name;
|
|
36
|
-
out.version = pkgJson.version;
|
|
37
|
-
out.description = pkgJson.description;
|
|
38
|
-
out.entryPoint = path.join(directory, pkgJson.module || pkgJson.main);
|
|
39
|
-
let metadata;
|
|
40
|
-
if (pkgJson.syncbridge.components) {
|
|
41
|
-
for (const ctorName of pkgJson.syncbridge.components) {
|
|
42
|
-
filename = path.join(directory, 'metadata', ctorName + '.json');
|
|
43
|
-
if (!fs.existsSync(filename)) {
|
|
44
|
-
out.errors.push(new Error(`Component (${ctorName}) metadata file not found`));
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
try {
|
|
48
|
-
metadata = JSON.parse(fs.readFileSync(filename, 'utf8'));
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
out.errors.push(new Error(`Component (${ctorName}) metadata file read error`));
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
metadata = await normalizeComponentMetadata(metadata);
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
updateErrorMessage(e, `Component (${ctorName}) metadata validation error. ` + e.message);
|
|
59
|
-
out.errors.push(e);
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
if (metadata.abstract)
|
|
63
|
-
continue;
|
|
64
|
-
out.components = out.components || [];
|
|
65
|
-
out.components.push(new ComponentExtension(out, ctorName, metadata));
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (pkgJson.syncbridge.processors) {
|
|
69
|
-
for (const ctorName of pkgJson.syncbridge.processors) {
|
|
70
|
-
filename = path.join(directory, 'metadata', ctorName + '.json');
|
|
71
|
-
if (!fs.existsSync(filename)) {
|
|
72
|
-
out.errors.push(new Error(`Processors (${ctorName}) metadata file not found`));
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
metadata = JSON.parse(fs.readFileSync(filename, 'utf8'));
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
out.errors.push(new Error(`Processors (${ctorName}) metadata file read error`));
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
try {
|
|
83
|
-
metadata = await normalizeProcessorMetadata(metadata);
|
|
84
|
-
}
|
|
85
|
-
catch (e) {
|
|
86
|
-
updateErrorMessage(e, `Processor (${ctorName}) metadata validation error. ` + e.message);
|
|
87
|
-
out.errors.push(e);
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (metadata.abstract)
|
|
91
|
-
continue;
|
|
92
|
-
out.processors = out.processors || [];
|
|
93
|
-
out.processors.push(new ProcessorExtension(out, ctorName, metadata));
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
out.sortVersions();
|
|
97
|
-
return out;
|
|
98
|
-
}
|
|
99
|
-
static async fromNodePackage(specifier, resolver) {
|
|
100
|
-
// const resolver = createRequire(parentPath || import.meta.url).resolve;
|
|
101
|
-
let entryPoint = (resolver || import.meta.resolve)(specifier);
|
|
102
|
-
const pkgJson = locatePkgJson(path.dirname(entryPoint));
|
|
103
|
-
if (!pkgJson) {
|
|
104
|
-
throw new SbError(`Can't locate package.json file for "${specifier}"`);
|
|
105
|
-
}
|
|
106
|
-
if (path.isAbsolute(entryPoint) && process.platform === 'win32') {
|
|
107
|
-
entryPoint = pathToFileURL(entryPoint).href;
|
|
108
|
-
}
|
|
109
|
-
const out = new ExtensionPackage();
|
|
110
|
-
out.name = pkgJson.name;
|
|
111
|
-
out.version = pkgJson.version;
|
|
112
|
-
out.description = pkgJson.description;
|
|
113
|
-
out.entryPoint = entryPoint;
|
|
114
|
-
const module = await import(entryPoint);
|
|
115
|
-
for (const [ctorName, v] of Object.entries(module)) {
|
|
116
|
-
if (typeof v !== 'function')
|
|
117
|
-
continue;
|
|
118
|
-
let metadata = Reflect.getMetadata(COMPONENT_OPTIONS, v);
|
|
119
|
-
if (metadata) {
|
|
120
|
-
try {
|
|
121
|
-
metadata = await normalizeComponentMetadata(metadata);
|
|
122
|
-
}
|
|
123
|
-
catch (e) {
|
|
124
|
-
updateErrorMessage(e, `Component (${ctorName}) metadata validation error. ` + e.message);
|
|
125
|
-
out.errors.push(e);
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
if (metadata.abstract)
|
|
129
|
-
continue;
|
|
130
|
-
out.components = out.components || [];
|
|
131
|
-
out.components.push(new ComponentExtension(out, ctorName, metadata));
|
|
132
|
-
}
|
|
133
|
-
metadata = Reflect.getMetadata(PROCESSOR_OPTIONS, v);
|
|
134
|
-
if (metadata) {
|
|
135
|
-
try {
|
|
136
|
-
metadata = await normalizeProcessorMetadata(metadata);
|
|
137
|
-
}
|
|
138
|
-
catch (e) {
|
|
139
|
-
updateErrorMessage(e, `Processor (${ctorName}) metadata validation error. ` + e.message);
|
|
140
|
-
out.errors.push(e);
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
if (metadata.abstract)
|
|
144
|
-
continue;
|
|
145
|
-
out.processors = out.processors || [];
|
|
146
|
-
out.processors.push(new ProcessorExtension(out, ctorName, metadata));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
out.sortVersions();
|
|
150
|
-
return out;
|
|
151
|
-
}
|
|
152
11
|
}
|
|
153
12
|
/**
|
|
154
13
|
*
|
|
@@ -226,19 +85,3 @@ export class ProcessorExtension {
|
|
|
226
85
|
return this._ctor;
|
|
227
86
|
}
|
|
228
87
|
}
|
|
229
|
-
/**
|
|
230
|
-
*
|
|
231
|
-
*/
|
|
232
|
-
function locatePkgJson(directory) {
|
|
233
|
-
if (directory.startsWith('file:'))
|
|
234
|
-
directory = fileURLToPath(directory);
|
|
235
|
-
for (let i = 0; i < 3; i++) {
|
|
236
|
-
const f = path.resolve(directory, 'package.json');
|
|
237
|
-
if (fs.existsSync(f)) {
|
|
238
|
-
const json = JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
239
|
-
if (json.name && json.version)
|
|
240
|
-
return json;
|
|
241
|
-
}
|
|
242
|
-
directory = path.dirname(directory);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
@@ -1,39 +1,72 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ResponsiveMap } from '@opra/common';
|
|
2
2
|
import { Type } from 'ts-gems';
|
|
3
3
|
import { ComponentExtension, ExtensionPackage, ProcessorExtension } from './extension-package.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
declare const instanceSymbol: unique symbol;
|
|
5
|
+
/**
|
|
6
|
+
* The `ExtensionRegistry` class is responsible for managing component and processor extensions,
|
|
7
|
+
* as well as handling the registration of extension packages. It provides methods to locate and
|
|
8
|
+
* retrieve extensions by their class name and version, and offers the ability to dynamically register
|
|
9
|
+
* packages, components, and processors at runtime.
|
|
10
|
+
*
|
|
11
|
+
* @class ExtensionRegistry
|
|
12
|
+
*/
|
|
13
|
+
export declare class ExtensionRegistry {
|
|
14
|
+
protected static [instanceSymbol]: ExtensionRegistry;
|
|
15
|
+
static get packages(): ResponsiveMap<ExtensionPackage[]>;
|
|
16
|
+
static get components(): ResponsiveMap<ComponentExtension[]>;
|
|
17
|
+
static get processors(): ResponsiveMap<ProcessorExtension[]>;
|
|
18
|
+
static setResolver(fn: ExtensionRegistry.PackageResolver | undefined): void;
|
|
19
|
+
static findComponent(className: string, version?: string): ComponentExtension | undefined;
|
|
20
|
+
static getComponent(className: string, version?: string): ComponentExtension;
|
|
21
|
+
static findProcessor(className: string, version?: string): ProcessorExtension | undefined;
|
|
22
|
+
static getProcessor(className: string, version?: string): ProcessorExtension;
|
|
23
|
+
static registerPackage(specifier: string): Promise<ExtensionPackage>;
|
|
24
|
+
static registerComponent(ctor: Type): Promise<ComponentExtension | undefined>;
|
|
25
|
+
static registerProcessor(ctor: Type): Promise<ProcessorExtension | undefined>;
|
|
26
|
+
static storePackage(pkg: ExtensionPackage): void;
|
|
27
|
+
protected _resolver: ExtensionRegistry.PackageResolver;
|
|
28
|
+
readonly packages: ResponsiveMap<ExtensionPackage[]>;
|
|
29
|
+
readonly components: ResponsiveMap<ComponentExtension[]>;
|
|
30
|
+
readonly processors: ResponsiveMap<ProcessorExtension[]>;
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
setResolver(fn: ExtensionRegistry.PackageResolver | undefined): void;
|
|
9
35
|
/**
|
|
10
36
|
*
|
|
11
37
|
*/
|
|
12
|
-
|
|
38
|
+
findComponent(className: string, version?: string): ComponentExtension | undefined;
|
|
13
39
|
/**
|
|
14
40
|
*
|
|
15
41
|
*/
|
|
16
|
-
|
|
42
|
+
getComponent(className: string, version?: string): ComponentExtension;
|
|
17
43
|
/**
|
|
18
44
|
*
|
|
19
45
|
*/
|
|
20
|
-
|
|
46
|
+
findProcessor(className: string, version?: string): ProcessorExtension | undefined;
|
|
21
47
|
/**
|
|
22
48
|
*
|
|
23
49
|
*/
|
|
24
|
-
|
|
50
|
+
getProcessor(className: string, version?: string): ProcessorExtension;
|
|
25
51
|
/**
|
|
26
52
|
*
|
|
27
53
|
*/
|
|
28
|
-
|
|
54
|
+
registerPackage(specifier: string): Promise<ExtensionPackage>;
|
|
55
|
+
registerComponent(ctor: Type): Promise<ComponentExtension | undefined>;
|
|
29
56
|
/**
|
|
30
57
|
*
|
|
31
58
|
*/
|
|
32
|
-
|
|
59
|
+
registerProcessor(ctor: Type): Promise<ProcessorExtension | undefined>;
|
|
33
60
|
/**
|
|
34
61
|
*
|
|
35
62
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
63
|
+
storePackage(pkg: ExtensionPackage): void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @namespace ExtensionRegistry
|
|
68
|
+
*/
|
|
69
|
+
export declare namespace ExtensionRegistry {
|
|
70
|
+
type PackageResolver = (specifier: string) => string;
|
|
39
71
|
}
|
|
72
|
+
export {};
|
|
@@ -1,89 +1,175 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { updateErrorMessage } from '@jsopen/objects';
|
|
5
|
+
import { ResponsiveMap } from '@opra/common';
|
|
1
6
|
import semver from 'semver';
|
|
2
7
|
import { SbError } from '../classes/sb-error.js';
|
|
3
8
|
import { COMPONENT_OPTIONS, PROCESSOR_OPTIONS } from '../constants.js';
|
|
9
|
+
import { normalizeComponentMetadata, normalizeProcessorMetadata, } from '../utils/normalize-metadata.js';
|
|
4
10
|
import { ComponentExtension, ExtensionPackage, ProcessorExtension, } from './extension-package.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
import { locatePackageJson } from './locate-package-json.js';
|
|
12
|
+
const instanceSymbol = Symbol.for('instance');
|
|
13
|
+
/**
|
|
14
|
+
* The `ExtensionRegistry` class is responsible for managing component and processor extensions,
|
|
15
|
+
* as well as handling the registration of extension packages. It provides methods to locate and
|
|
16
|
+
* retrieve extensions by their class name and version, and offers the ability to dynamically register
|
|
17
|
+
* packages, components, and processors at runtime.
|
|
18
|
+
*
|
|
19
|
+
* @class ExtensionRegistry
|
|
20
|
+
*/
|
|
21
|
+
export class ExtensionRegistry {
|
|
22
|
+
static [instanceSymbol] = new ExtensionRegistry();
|
|
23
|
+
static get packages() {
|
|
24
|
+
return this[instanceSymbol].packages;
|
|
25
|
+
}
|
|
26
|
+
static get components() {
|
|
27
|
+
return this[instanceSymbol].components;
|
|
28
|
+
}
|
|
29
|
+
static get processors() {
|
|
30
|
+
return this[instanceSymbol].processors;
|
|
31
|
+
}
|
|
32
|
+
static setResolver(fn) {
|
|
33
|
+
this[instanceSymbol].setResolver(fn);
|
|
34
|
+
}
|
|
35
|
+
static findComponent(className, version = '*') {
|
|
36
|
+
return this[instanceSymbol].findComponent(className, version);
|
|
19
37
|
}
|
|
20
|
-
|
|
38
|
+
static getComponent(className, version = '*') {
|
|
39
|
+
return this[instanceSymbol].getComponent(className, version);
|
|
40
|
+
}
|
|
41
|
+
static findProcessor(className, version = '*') {
|
|
42
|
+
return this[instanceSymbol].findProcessor(className, version);
|
|
43
|
+
}
|
|
44
|
+
static getProcessor(className, version = '*') {
|
|
45
|
+
return this[instanceSymbol].getProcessor(className, version);
|
|
46
|
+
}
|
|
47
|
+
static async registerPackage(specifier) {
|
|
48
|
+
return this[instanceSymbol].registerPackage(specifier);
|
|
49
|
+
}
|
|
50
|
+
static async registerComponent(ctor) {
|
|
51
|
+
return this[instanceSymbol].registerComponent(ctor);
|
|
52
|
+
}
|
|
53
|
+
static async registerProcessor(ctor) {
|
|
54
|
+
return this[instanceSymbol].registerProcessor(ctor);
|
|
55
|
+
}
|
|
56
|
+
static storePackage(pkg) {
|
|
57
|
+
return this[instanceSymbol].storePackage(pkg);
|
|
58
|
+
}
|
|
59
|
+
_resolver = import.meta.resolve;
|
|
60
|
+
packages = new ResponsiveMap();
|
|
61
|
+
components = new ResponsiveMap();
|
|
62
|
+
processors = new ResponsiveMap();
|
|
21
63
|
/**
|
|
22
64
|
*
|
|
23
65
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (cmp)
|
|
27
|
-
return cmp;
|
|
28
|
-
throw new SbError(`Component "${className}" version "${version}" not found in registry`);
|
|
66
|
+
setResolver(fn) {
|
|
67
|
+
this._resolver = fn || import.meta.resolve;
|
|
29
68
|
}
|
|
30
|
-
ExtensionRegistry.getComponent = getComponent;
|
|
31
69
|
/**
|
|
32
70
|
*
|
|
33
71
|
*/
|
|
34
|
-
|
|
35
|
-
return
|
|
72
|
+
findComponent(className, version = '*') {
|
|
73
|
+
return this.components
|
|
36
74
|
.get(className)
|
|
37
75
|
?.find(v => semver.satisfies(v.version, version || '*'));
|
|
38
76
|
}
|
|
39
|
-
ExtensionRegistry.findProcessor = findProcessor;
|
|
40
77
|
/**
|
|
41
78
|
*
|
|
42
79
|
*/
|
|
43
|
-
|
|
44
|
-
const cmp =
|
|
80
|
+
getComponent(className, version = '*') {
|
|
81
|
+
const cmp = this.findComponent(className, version);
|
|
45
82
|
if (!cmp) {
|
|
46
|
-
throw new SbError(`
|
|
83
|
+
throw new SbError(`Component "${className}@${version}" not found in registry`);
|
|
47
84
|
}
|
|
48
85
|
return cmp;
|
|
49
86
|
}
|
|
50
|
-
ExtensionRegistry.getProcessor = getProcessor;
|
|
51
87
|
/**
|
|
52
88
|
*
|
|
53
89
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
90
|
+
findProcessor(className, version = '*') {
|
|
91
|
+
return this.processors
|
|
92
|
+
.get(className)
|
|
93
|
+
?.find(v => semver.satisfies(v.version, version || '*'));
|
|
56
94
|
}
|
|
57
|
-
ExtensionRegistry.setResolver = setResolver;
|
|
58
95
|
/**
|
|
59
96
|
*
|
|
60
97
|
*/
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
98
|
+
getProcessor(className, version = '*') {
|
|
99
|
+
const cmp = this.findProcessor(className, version);
|
|
100
|
+
if (!cmp) {
|
|
101
|
+
throw new SbError(`Processor "${className}@${version}" not found in registry`);
|
|
102
|
+
}
|
|
103
|
+
return cmp;
|
|
65
104
|
}
|
|
66
|
-
ExtensionRegistry.registerExtensionPackage = registerExtensionPackage;
|
|
67
105
|
/**
|
|
68
106
|
*
|
|
69
107
|
*/
|
|
70
|
-
async
|
|
71
|
-
|
|
72
|
-
|
|
108
|
+
async registerPackage(specifier) {
|
|
109
|
+
let entryPoint = this._resolver(specifier);
|
|
110
|
+
const pkgDir = locatePackageJson(path.dirname(entryPoint));
|
|
111
|
+
if (!pkgDir) {
|
|
112
|
+
throw new SbError(`Can't locate package.json file for "${specifier}"`);
|
|
113
|
+
}
|
|
114
|
+
const pkgJson = JSON.parse(fs.readFileSync(path.join(pkgDir, 'package.json'), 'utf8'));
|
|
115
|
+
if (path.isAbsolute(entryPoint) && process.platform === 'win32') {
|
|
116
|
+
entryPoint = pathToFileURL(entryPoint).href;
|
|
117
|
+
}
|
|
118
|
+
const pkg = new ExtensionPackage();
|
|
119
|
+
pkg.name = pkgJson.name;
|
|
120
|
+
pkg.version = pkgJson.version;
|
|
121
|
+
pkg.description = pkgJson.description;
|
|
122
|
+
pkg.path = pkgDir;
|
|
123
|
+
pkg.entryPoint = entryPoint;
|
|
124
|
+
const module = await import(entryPoint);
|
|
125
|
+
for (const [ctorName, v] of Object.entries(module)) {
|
|
126
|
+
if (typeof v !== 'function')
|
|
127
|
+
continue;
|
|
128
|
+
let metadata = Reflect.getMetadata(COMPONENT_OPTIONS, v);
|
|
129
|
+
if (metadata) {
|
|
130
|
+
try {
|
|
131
|
+
metadata = await normalizeComponentMetadata(metadata);
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
updateErrorMessage(e, `Component (${ctorName}) metadata validation error. ` + e.message);
|
|
135
|
+
pkg.errors.push(e);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (metadata.abstract)
|
|
139
|
+
continue;
|
|
140
|
+
pkg.components = pkg.components || [];
|
|
141
|
+
pkg.components.push(new ComponentExtension(pkg, ctorName, metadata));
|
|
142
|
+
}
|
|
143
|
+
metadata = Reflect.getMetadata(PROCESSOR_OPTIONS, v);
|
|
144
|
+
if (metadata) {
|
|
145
|
+
try {
|
|
146
|
+
metadata = await normalizeProcessorMetadata(metadata);
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
updateErrorMessage(e, `Processor (${ctorName}) metadata validation error. ` + e.message);
|
|
150
|
+
pkg.errors.push(e);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (metadata.abstract)
|
|
154
|
+
continue;
|
|
155
|
+
pkg.processors = pkg.processors || [];
|
|
156
|
+
pkg.processors.push(new ProcessorExtension(pkg, ctorName, metadata));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
this.storePackage(pkg);
|
|
73
160
|
return pkg;
|
|
74
161
|
}
|
|
75
|
-
|
|
76
|
-
async function registerComponent(ctor) {
|
|
162
|
+
async registerComponent(ctor) {
|
|
77
163
|
const _metadata = Reflect.getMetadata(COMPONENT_OPTIONS, ctor);
|
|
78
164
|
if (!_metadata)
|
|
79
165
|
throw new SbError(`Class "${ctor.name}" has no component metadata.`);
|
|
80
166
|
if (_metadata.abstract)
|
|
81
167
|
return;
|
|
82
168
|
const metadata = await normalizeComponentMetadata(_metadata);
|
|
83
|
-
let versions =
|
|
169
|
+
let versions = this.packages.get('internal');
|
|
84
170
|
if (!versions) {
|
|
85
171
|
versions = [];
|
|
86
|
-
|
|
172
|
+
this.packages.set('internal', versions);
|
|
87
173
|
}
|
|
88
174
|
let pkg = versions[0];
|
|
89
175
|
if (!pkg) {
|
|
@@ -94,21 +180,23 @@ export var ExtensionRegistry;
|
|
|
94
180
|
}
|
|
95
181
|
const cmp = new ComponentExtension(pkg, ctor.name, metadata, ctor);
|
|
96
182
|
pkg.components.push(cmp);
|
|
97
|
-
storePackage(pkg);
|
|
183
|
+
this.storePackage(pkg);
|
|
98
184
|
return cmp;
|
|
99
185
|
}
|
|
100
|
-
|
|
101
|
-
|
|
186
|
+
/**
|
|
187
|
+
*
|
|
188
|
+
*/
|
|
189
|
+
async registerProcessor(ctor) {
|
|
102
190
|
const _metadata = Reflect.getMetadata(PROCESSOR_OPTIONS, ctor);
|
|
103
191
|
if (!_metadata)
|
|
104
192
|
throw new SbError(`Class "${ctor.name}" has no processor metadata.`);
|
|
105
193
|
if (_metadata.abstract)
|
|
106
194
|
return;
|
|
107
195
|
const metadata = await normalizeProcessorMetadata(_metadata);
|
|
108
|
-
let versions =
|
|
196
|
+
let versions = this.packages.get('internal');
|
|
109
197
|
if (!versions) {
|
|
110
198
|
versions = [];
|
|
111
|
-
|
|
199
|
+
this.packages.set('internal', versions);
|
|
112
200
|
}
|
|
113
201
|
let pkg = versions[0];
|
|
114
202
|
if (!pkg) {
|
|
@@ -119,20 +207,17 @@ export var ExtensionRegistry;
|
|
|
119
207
|
}
|
|
120
208
|
const prc = new ProcessorExtension(pkg, ctor.name, metadata, ctor);
|
|
121
209
|
pkg.processors.push(prc);
|
|
122
|
-
storePackage(pkg);
|
|
210
|
+
this.storePackage(pkg);
|
|
123
211
|
return prc;
|
|
124
212
|
}
|
|
125
|
-
ExtensionRegistry.registerProcessor = registerProcessor;
|
|
126
213
|
/**
|
|
127
214
|
*
|
|
128
|
-
* @private
|
|
129
215
|
*/
|
|
130
|
-
|
|
131
|
-
pkg.
|
|
132
|
-
let pkgVersions = ExtensionRegistry.packages.get(pkg.name);
|
|
216
|
+
storePackage(pkg) {
|
|
217
|
+
let pkgVersions = this.packages.get(pkg.name);
|
|
133
218
|
if (!pkgVersions) {
|
|
134
219
|
pkgVersions = [];
|
|
135
|
-
|
|
220
|
+
this.packages.set(pkg.name, pkgVersions);
|
|
136
221
|
}
|
|
137
222
|
let i = pkgVersions.findIndex(v => v.version === pkg.version);
|
|
138
223
|
if (i >= 0)
|
|
@@ -142,10 +227,10 @@ export var ExtensionRegistry;
|
|
|
142
227
|
pkgVersions.sort((a, b) => a.version.localeCompare(b.version));
|
|
143
228
|
if (pkg.components?.length) {
|
|
144
229
|
for (const cmp of pkg.components) {
|
|
145
|
-
let versions =
|
|
230
|
+
let versions = this.components.get(cmp.className);
|
|
146
231
|
if (!versions) {
|
|
147
232
|
versions = [];
|
|
148
|
-
|
|
233
|
+
this.components.set(cmp.className, versions);
|
|
149
234
|
}
|
|
150
235
|
i = versions.findIndex(v => v.version === cmp.version);
|
|
151
236
|
if (i >= 0)
|
|
@@ -156,10 +241,10 @@ export var ExtensionRegistry;
|
|
|
156
241
|
}
|
|
157
242
|
if (pkg.processors?.length) {
|
|
158
243
|
for (const prc of pkg.processors) {
|
|
159
|
-
let versions =
|
|
244
|
+
let versions = this.processors.get(prc.className);
|
|
160
245
|
if (!versions) {
|
|
161
246
|
versions = [];
|
|
162
|
-
|
|
247
|
+
this.processors.set(prc.className, versions);
|
|
163
248
|
}
|
|
164
249
|
i = versions.findIndex(v => v.version === prc.version);
|
|
165
250
|
if (i >= 0)
|
|
@@ -169,4 +254,4 @@ export var ExtensionRegistry;
|
|
|
169
254
|
}
|
|
170
255
|
}
|
|
171
256
|
}
|
|
172
|
-
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
export function locatePackageJson(directory) {
|
|
8
|
+
if (directory.startsWith('file:'))
|
|
9
|
+
directory = fileURLToPath(directory);
|
|
10
|
+
for (let i = 0; i < 3; i++) {
|
|
11
|
+
const f = path.resolve(directory, 'package.json');
|
|
12
|
+
if (fs.existsSync(f)) {
|
|
13
|
+
return directory;
|
|
14
|
+
}
|
|
15
|
+
directory = path.dirname(directory);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StackExecutor } from '../classes/stack-executor.js';
|
|
2
|
+
import { ComponentMetadata, ProcessorMetadata } from '../models/index.js';
|
|
3
|
+
export declare function normalizeProcessorMetadata(metadata: ProcessorMetadata): Promise<ProcessorMetadata>;
|
|
4
|
+
export declare function normalizeProcessorMetadataSilent(metadata: ProcessorMetadata): Promise<{
|
|
5
|
+
metadata: ProcessorMetadata;
|
|
6
|
+
issues?: StackExecutor.Issue[];
|
|
7
|
+
}>;
|
|
8
|
+
export declare function normalizeComponentMetadata(metadata: ComponentMetadata): Promise<ComponentMetadata>;
|
|
9
|
+
export declare function normalizeComponentMetadataSilent(metadata: ComponentMetadata): Promise<{
|
|
10
|
+
metadata: ComponentMetadata;
|
|
11
|
+
issues?: StackExecutor.Issue[];
|
|
12
|
+
}>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { deepClone, merge } from '@jsopen/objects';
|
|
2
|
+
import { SbValidationError } from '../classes/sb-error.js';
|
|
3
|
+
import { ComponentMetadata, ProcessorMetadata, } from '../models/index.js';
|
|
4
|
+
import { initializeModelsDocument } from '../models-document.js';
|
|
5
|
+
import { resolvePromisesDeep } from './resolve-promises.js';
|
|
6
|
+
export async function normalizeProcessorMetadata(metadata) {
|
|
7
|
+
const { metadata: out, issues } = await normalizeProcessorMetadataSilent(metadata);
|
|
8
|
+
if (issues?.length) {
|
|
9
|
+
const msg = 'Worker profile decoding error.\n ' +
|
|
10
|
+
issues
|
|
11
|
+
.map(issue => `- ${issue.message}. Location: /${issue.location}`)
|
|
12
|
+
.join('\n ');
|
|
13
|
+
issues.forEach(issue => {
|
|
14
|
+
if (issue instanceof SbValidationError)
|
|
15
|
+
delete issue.stack;
|
|
16
|
+
});
|
|
17
|
+
throw new SbValidationError(msg, {
|
|
18
|
+
issues,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
export async function normalizeProcessorMetadataSilent(metadata) {
|
|
24
|
+
const decoder = await getProcMetadataTypeDecoder();
|
|
25
|
+
let cloned = deepClone({
|
|
26
|
+
className: metadata.className,
|
|
27
|
+
displayName: metadata.displayName,
|
|
28
|
+
description: metadata.description,
|
|
29
|
+
iconUrl: metadata.iconUrl,
|
|
30
|
+
author: metadata.author,
|
|
31
|
+
tags: metadata.tags,
|
|
32
|
+
abstract: metadata.abstract,
|
|
33
|
+
variables: metadata.variables,
|
|
34
|
+
components: metadata.components,
|
|
35
|
+
...metadata,
|
|
36
|
+
});
|
|
37
|
+
cloned = await resolvePromisesDeep(cloned);
|
|
38
|
+
cloned.variables = normalizeVariables(cloned.variables);
|
|
39
|
+
cloned.components = normalizeComponents(cloned.components);
|
|
40
|
+
const { value, errors } = decoder.silent(cloned);
|
|
41
|
+
merge(value, metadata, { keepExisting: true, deep: 'full' });
|
|
42
|
+
return {
|
|
43
|
+
metadata: value || cloned,
|
|
44
|
+
issues: errors?.map(x => ({
|
|
45
|
+
...x.issue,
|
|
46
|
+
severity: 'error',
|
|
47
|
+
})),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export async function normalizeComponentMetadata(metadata) {
|
|
51
|
+
const { metadata: out, issues } = await normalizeComponentMetadataSilent(metadata);
|
|
52
|
+
if (issues?.length) {
|
|
53
|
+
const msg = 'Worker profile decoding error.\n ' +
|
|
54
|
+
issues
|
|
55
|
+
.map(issue => `- ${issue.message}. Location: /${issue.location}`)
|
|
56
|
+
.join('\n ');
|
|
57
|
+
issues.forEach(issue => {
|
|
58
|
+
if (issue instanceof SbValidationError)
|
|
59
|
+
delete issue.stack;
|
|
60
|
+
});
|
|
61
|
+
throw new SbValidationError(msg, {
|
|
62
|
+
issues,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
export async function normalizeComponentMetadataSilent(metadata) {
|
|
68
|
+
const decoder = await getCompMetadataTypeDecoder();
|
|
69
|
+
let cloned = deepClone({
|
|
70
|
+
className: metadata.className,
|
|
71
|
+
displayName: metadata.displayName,
|
|
72
|
+
description: metadata.description,
|
|
73
|
+
iconUrl: metadata.iconUrl,
|
|
74
|
+
author: metadata.author,
|
|
75
|
+
interfaces: metadata.interfaces,
|
|
76
|
+
tags: metadata.tags,
|
|
77
|
+
abstract: metadata.abstract,
|
|
78
|
+
variables: metadata.variables,
|
|
79
|
+
components: metadata.components,
|
|
80
|
+
...metadata,
|
|
81
|
+
});
|
|
82
|
+
cloned = await resolvePromisesDeep(cloned);
|
|
83
|
+
cloned.variables = normalizeVariables(cloned.variables);
|
|
84
|
+
cloned.components = normalizeComponents(cloned.components);
|
|
85
|
+
const { value, errors } = decoder.silent(cloned);
|
|
86
|
+
merge(value, metadata, { keepExisting: true, deep: 'full' });
|
|
87
|
+
return {
|
|
88
|
+
metadata: value || cloned,
|
|
89
|
+
issues: errors?.map(x => ({
|
|
90
|
+
...x.issue,
|
|
91
|
+
severity: 'error',
|
|
92
|
+
})),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function normalizeComponents(components) {
|
|
96
|
+
if (!components)
|
|
97
|
+
return;
|
|
98
|
+
for (const component of Object.values(components)) {
|
|
99
|
+
if (component.variables)
|
|
100
|
+
component.variables = normalizeVariables(component.variables);
|
|
101
|
+
if (component.components)
|
|
102
|
+
component.components = normalizeComponents(component.components);
|
|
103
|
+
}
|
|
104
|
+
return components;
|
|
105
|
+
}
|
|
106
|
+
function normalizeVariables(variables) {
|
|
107
|
+
if (!variables)
|
|
108
|
+
return;
|
|
109
|
+
/** Convert object enumValues to arrays */
|
|
110
|
+
for (const v of Object.values(variables)) {
|
|
111
|
+
if (v.enumValues &&
|
|
112
|
+
typeof v.enumValues === 'object' &&
|
|
113
|
+
!Array.isArray(v.enumValues)) {
|
|
114
|
+
let values = v.enumValues;
|
|
115
|
+
const keys = Object.keys(values).filter(k => !/^\d+$/.test(k));
|
|
116
|
+
values = keys.reduce((a, k) => {
|
|
117
|
+
if (values[k] != null)
|
|
118
|
+
a.push(values[k]);
|
|
119
|
+
return a;
|
|
120
|
+
}, []);
|
|
121
|
+
v.enumValues = values;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return variables;
|
|
125
|
+
}
|
|
126
|
+
// ************************************************************************
|
|
127
|
+
// ************************************************************************
|
|
128
|
+
let _compMetadataTypeDecoder;
|
|
129
|
+
let _procMetadataTypeDecoder;
|
|
130
|
+
async function getCompMetadataTypeDecoder() {
|
|
131
|
+
if (!_compMetadataTypeDecoder) {
|
|
132
|
+
const apiDoc = await initializeModelsDocument();
|
|
133
|
+
const compMetadataType = apiDoc.node.getComplexType(ComponentMetadata);
|
|
134
|
+
_compMetadataTypeDecoder = compMetadataType.generateCodec('decode', {
|
|
135
|
+
coerce: true,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return _compMetadataTypeDecoder;
|
|
139
|
+
}
|
|
140
|
+
async function getProcMetadataTypeDecoder() {
|
|
141
|
+
if (!_procMetadataTypeDecoder) {
|
|
142
|
+
const apiDoc = await initializeModelsDocument();
|
|
143
|
+
const procMetadataType = apiDoc.node.getComplexType(ProcessorMetadata);
|
|
144
|
+
_procMetadataTypeDecoder = procMetadataType.generateCodec('decode', {
|
|
145
|
+
coerce: true,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return _procMetadataTypeDecoder;
|
|
149
|
+
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { ComponentMetadata, ProcessorMetadata } from '../models/index.js';
|
|
2
|
-
export declare function normalizeProcessorMetadata(metadata: ProcessorMetadata): Promise<ProcessorMetadata>;
|
|
3
|
-
export declare function normalizeComponentMetadata(metadata: ComponentMetadata): Promise<ComponentMetadata>;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { deepClone, merge } from '@jsopen/objects';
|
|
2
|
-
import { ComponentMetadata, ProcessorMetadata, } from '../models/index.js';
|
|
3
|
-
import { initializeModelsDocument } from '../models-document.js';
|
|
4
|
-
import { resolvePromisesDeep } from '../utils/resolve-promises.js';
|
|
5
|
-
export async function normalizeProcessorMetadata(metadata) {
|
|
6
|
-
const decoder = await getProcMetadataTypeDecoder();
|
|
7
|
-
let out = await resolvePromisesDeep(metadata);
|
|
8
|
-
out = deepClone(out);
|
|
9
|
-
out = decoder({
|
|
10
|
-
className: out.className,
|
|
11
|
-
displayName: out.displayName,
|
|
12
|
-
description: out.description,
|
|
13
|
-
iconUrl: out.iconUrl,
|
|
14
|
-
author: out.author,
|
|
15
|
-
tags: out.tags,
|
|
16
|
-
abstract: out.abstract,
|
|
17
|
-
variables: normalizeVariables(out.variables),
|
|
18
|
-
components: normalizeComponents(out.components),
|
|
19
|
-
...out,
|
|
20
|
-
});
|
|
21
|
-
merge(out, metadata, { keepExisting: true, deep: 'full' });
|
|
22
|
-
return out;
|
|
23
|
-
}
|
|
24
|
-
export async function normalizeComponentMetadata(metadata) {
|
|
25
|
-
const decoder = await getCompMetadataTypeDecoder();
|
|
26
|
-
let out = await resolvePromisesDeep(metadata);
|
|
27
|
-
out = deepClone(out);
|
|
28
|
-
out = decoder({
|
|
29
|
-
className: out.className,
|
|
30
|
-
displayName: out.displayName,
|
|
31
|
-
description: out.description,
|
|
32
|
-
iconUrl: out.iconUrl,
|
|
33
|
-
author: out.author,
|
|
34
|
-
interfaces: out.interfaces,
|
|
35
|
-
tags: out.tags,
|
|
36
|
-
abstract: out.abstract,
|
|
37
|
-
variables: normalizeVariables(out.variables),
|
|
38
|
-
components: normalizeComponents(out.components),
|
|
39
|
-
...out,
|
|
40
|
-
});
|
|
41
|
-
merge(out, metadata, { keepExisting: true, deep: 'full' });
|
|
42
|
-
return out;
|
|
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
|
-
}
|
|
75
|
-
// ************************************************************************
|
|
76
|
-
// ************************************************************************
|
|
77
|
-
let _compMetadataTypeDecoder;
|
|
78
|
-
let _procMetadataTypeDecoder;
|
|
79
|
-
async function getCompMetadataTypeDecoder() {
|
|
80
|
-
if (!_compMetadataTypeDecoder) {
|
|
81
|
-
const apiDoc = await initializeModelsDocument();
|
|
82
|
-
const compMetadataType = apiDoc.node.getComplexType(ComponentMetadata);
|
|
83
|
-
_compMetadataTypeDecoder = compMetadataType.generateCodec('decode', {
|
|
84
|
-
coerce: true,
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return _compMetadataTypeDecoder;
|
|
88
|
-
}
|
|
89
|
-
async function getProcMetadataTypeDecoder() {
|
|
90
|
-
if (!_procMetadataTypeDecoder) {
|
|
91
|
-
const apiDoc = await initializeModelsDocument();
|
|
92
|
-
const procMetadataType = apiDoc.node.getComplexType(ProcessorMetadata);
|
|
93
|
-
_procMetadataTypeDecoder = procMetadataType.generateCodec('decode', {
|
|
94
|
-
coerce: true,
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
return _procMetadataTypeDecoder;
|
|
98
|
-
}
|