@syncbridge/common 0.6.0 → 0.6.1
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/sb-error.d.ts +9 -4
- package/classes/sb-error.js +6 -10
- package/classes/stack-executor.js +8 -11
- package/constants.js +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/models-document.js +4 -1
- package/package.json +1 -1
- package/processor-factory.js +2 -1
- package/registry/extension-package.js +10 -9
- package/registry/extension-registry.js +5 -4
- package/utils/{profile-utils.js → decode-profile.js} +3 -7
- package/utils/materialize-metadata.js +6 -6
- /package/utils/{profile-utils.d.ts → decode-profile.d.ts} +0 -0
package/classes/sb-error.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import { ErrorIssue } from '@opra/common';
|
|
2
|
+
export declare class SbError extends Error implements ErrorIssue {
|
|
2
3
|
readonly cause?: Error;
|
|
4
|
+
severity: ErrorIssue['severity'];
|
|
3
5
|
code?: string;
|
|
4
6
|
[index: string]: any;
|
|
5
7
|
constructor(message?: string | Error, options?: SbErrorOptions);
|
|
6
|
-
toJSON(): any;
|
|
7
8
|
}
|
|
8
|
-
export interface SbErrorOptions {
|
|
9
|
+
export interface SbErrorOptions extends Partial<ErrorIssue> {
|
|
9
10
|
cause?: Error;
|
|
10
|
-
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
export declare class SbValidationError extends SbError {
|
|
11
16
|
}
|
package/classes/sb-error.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isPlainObject } from '@jsopen/objects';
|
|
2
2
|
export class SbError extends Error {
|
|
3
|
+
severity = 'error';
|
|
3
4
|
code;
|
|
4
5
|
constructor(message, options) {
|
|
5
6
|
super(typeof message === 'object' ? message.message || '' : message);
|
|
@@ -41,14 +42,9 @@ export class SbError extends Error {
|
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (k !== 'stack')
|
|
50
|
-
out[k] = this[k];
|
|
51
|
-
}
|
|
52
|
-
return out;
|
|
53
|
-
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
*
|
|
48
|
+
*/
|
|
49
|
+
export class SbValidationError extends SbError {
|
|
54
50
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ValidationError } from 'valgen';
|
|
2
|
+
import { SbValidationError } from './sb-error.js';
|
|
2
3
|
export class StackExecutor {
|
|
3
4
|
stack = [];
|
|
4
5
|
issues = [];
|
|
@@ -30,20 +31,16 @@ export class StackExecutor {
|
|
|
30
31
|
const location = this.stack.join('/');
|
|
31
32
|
if (e instanceof ValidationError) {
|
|
32
33
|
e.issues.forEach(x => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
34
|
+
const issue = new SbValidationError(x.message, x);
|
|
35
|
+
x.severity = x.severity ?? 'error';
|
|
36
|
+
x.location = location + (x.location ? '/' + x.location : '');
|
|
37
|
+
this.issues.push(issue);
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
severity: 'error',
|
|
45
|
-
location,
|
|
46
|
-
});
|
|
41
|
+
e.severity = e.severity ?? 'error';
|
|
42
|
+
e.location = location;
|
|
43
|
+
this.issues.push(e);
|
|
47
44
|
}
|
|
48
45
|
}
|
|
49
46
|
}
|
package/constants.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const version = '0.6.
|
|
1
|
+
export const version = '0.6.1';
|
|
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/decode-profile.js';
|
|
19
20
|
export * from './utils/materialize-metadata.js';
|
|
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/decode-profile.js';
|
|
19
20
|
export * from './utils/materialize-metadata.js';
|
|
20
|
-
export * from './utils/profile-utils.js';
|
package/models-document.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApiDocumentFactory } from '@opra/common';
|
|
2
|
+
import { SbError } from './classes/sb-error.js';
|
|
2
3
|
import * as models from './models/index.js';
|
|
3
4
|
let doc;
|
|
4
5
|
export async function initializeModelsDocument() {
|
|
@@ -11,6 +12,8 @@ export async function initializeModelsDocument() {
|
|
|
11
12
|
}
|
|
12
13
|
export function getModelsDocument() {
|
|
13
14
|
if (!doc)
|
|
14
|
-
throw new
|
|
15
|
+
throw new SbError('You must call initializeModelsDocument() first', {
|
|
16
|
+
severity: 'fatal',
|
|
17
|
+
});
|
|
15
18
|
return doc;
|
|
16
19
|
}
|
package/package.json
CHANGED
package/processor-factory.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import equal from 'fast-deep-equal';
|
|
2
|
+
import { SbError } from './classes/sb-error.js';
|
|
2
3
|
import { StackExecutor } from './classes/stack-executor.js';
|
|
3
4
|
import { initializeModelsDocument } from './models-document.js';
|
|
4
5
|
import { ExtensionRegistry } from './registry/extension-registry.js';
|
|
@@ -94,7 +95,7 @@ export var ProcessorFactory;
|
|
|
94
95
|
if (processor.stopped &&
|
|
95
96
|
oldMetadata?.className &&
|
|
96
97
|
oldMetadata?.className !== newMetadata.className)
|
|
97
|
-
throw new
|
|
98
|
+
throw new SbError('Cannot change component class while processor running. You should stop it first.');
|
|
98
99
|
/** Validate sub components */
|
|
99
100
|
if (childMetadata.components) {
|
|
100
101
|
_validateComponents({
|
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import process from 'node:process';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
6
|
import { updateErrorMessage } from '@jsopen/objects';
|
|
7
|
+
import { SbError } from '../classes/sb-error.js';
|
|
7
8
|
import { COMPONENT_OPTIONS, PROCESSOR_OPTIONS } from '../constants.js';
|
|
8
9
|
import { isComponentBase, isProcessorBase } from '../utils/type-guartds.js';
|
|
9
10
|
import { normalizeComponentMetadata, normalizeProcessorMetadata, } from './helpers.js';
|
|
@@ -26,10 +27,10 @@ export class ExtensionPackage {
|
|
|
26
27
|
static async fromDirectory(directory) {
|
|
27
28
|
let filename = path.join(directory, 'package.json');
|
|
28
29
|
if (!fs.existsSync(filename))
|
|
29
|
-
throw new
|
|
30
|
+
throw new SbError(`Directory "${directory}" does not contain package.json`);
|
|
30
31
|
const pkgJson = JSON.parse(fs.readFileSync(filename, 'utf8'));
|
|
31
32
|
if (!pkgJson.syncbridge)
|
|
32
|
-
throw new
|
|
33
|
+
throw new SbError(`"${pkgJson.name}" is not a SyncBridge extension package`);
|
|
33
34
|
const out = new ExtensionPackage();
|
|
34
35
|
out.name = pkgJson.name;
|
|
35
36
|
out.version = pkgJson.version;
|
|
@@ -100,7 +101,7 @@ export class ExtensionPackage {
|
|
|
100
101
|
let entryPoint = (resolver || import.meta.resolve)(specifier);
|
|
101
102
|
const pkgJson = locatePkgJson(path.dirname(entryPoint));
|
|
102
103
|
if (!pkgJson) {
|
|
103
|
-
throw new
|
|
104
|
+
throw new SbError(`Can't locate package.json file for "${specifier}"`);
|
|
104
105
|
}
|
|
105
106
|
if (path.isAbsolute(entryPoint) && process.platform === 'win32') {
|
|
106
107
|
entryPoint = pathToFileURL(entryPoint).href;
|
|
@@ -178,11 +179,11 @@ export class ComponentExtension {
|
|
|
178
179
|
const module = await import(this.pkg.entryPoint);
|
|
179
180
|
const ctor = module[this.exportName];
|
|
180
181
|
if (!ctor)
|
|
181
|
-
throw new
|
|
182
|
+
throw new SbError(`Exported component "${this.exportName}" not found in package "${this.pkg.name}"`);
|
|
182
183
|
if (typeof ctor !== 'function')
|
|
183
|
-
throw new
|
|
184
|
+
throw new SbError(`Exported component "${this.exportName}" is not a class`);
|
|
184
185
|
if (!isComponentBase(ctor.prototype))
|
|
185
|
-
throw new
|
|
186
|
+
throw new SbError(`Exported component "${this.exportName}" does not extends ComponentBase`);
|
|
186
187
|
this._ctor = ctor;
|
|
187
188
|
return this._ctor;
|
|
188
189
|
}
|
|
@@ -216,11 +217,11 @@ export class ProcessorExtension {
|
|
|
216
217
|
const module = await import(this.pkg.entryPoint);
|
|
217
218
|
const ctor = module[this.exportName];
|
|
218
219
|
if (!ctor)
|
|
219
|
-
throw new
|
|
220
|
+
throw new SbError(`Exported processor "${this.exportName}" not found in package "${this.pkg.name}"`);
|
|
220
221
|
if (typeof ctor !== 'function')
|
|
221
|
-
throw new
|
|
222
|
+
throw new SbError(`Exported processor "${this.exportName}" is not a class`);
|
|
222
223
|
if (!isProcessorBase(ctor.prototype))
|
|
223
|
-
throw new
|
|
224
|
+
throw new SbError(`Exported processor "${this.exportName}" does not extends ProcessorBase`);
|
|
224
225
|
this._ctor = ctor;
|
|
225
226
|
return this._ctor;
|
|
226
227
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import semver from 'semver';
|
|
2
|
+
import { SbError } from '../classes/sb-error.js';
|
|
2
3
|
import { COMPONENT_OPTIONS, PROCESSOR_OPTIONS } from '../constants.js';
|
|
3
4
|
import { ComponentExtension, ExtensionPackage, ProcessorExtension, } from './extension-package.js';
|
|
4
5
|
import { normalizeComponentMetadata, normalizeProcessorMetadata, } from './helpers.js';
|
|
@@ -24,7 +25,7 @@ export var ExtensionRegistry;
|
|
|
24
25
|
const cmp = findComponent(className, version);
|
|
25
26
|
if (cmp)
|
|
26
27
|
return cmp;
|
|
27
|
-
throw new
|
|
28
|
+
throw new SbError(`Component "${className}" version "${version}" not found in registry`);
|
|
28
29
|
}
|
|
29
30
|
ExtensionRegistry.getComponent = getComponent;
|
|
30
31
|
/**
|
|
@@ -42,7 +43,7 @@ export var ExtensionRegistry;
|
|
|
42
43
|
function getProcessor(className, version = '*') {
|
|
43
44
|
const cmp = findProcessor(className, version);
|
|
44
45
|
if (!cmp) {
|
|
45
|
-
throw new
|
|
46
|
+
throw new SbError(`Processor "${className}" version "${version}" not found in registry`);
|
|
46
47
|
}
|
|
47
48
|
return cmp;
|
|
48
49
|
}
|
|
@@ -75,7 +76,7 @@ export var ExtensionRegistry;
|
|
|
75
76
|
async function registerComponent(ctor) {
|
|
76
77
|
const _metadata = Reflect.getMetadata(COMPONENT_OPTIONS, ctor);
|
|
77
78
|
if (!_metadata)
|
|
78
|
-
throw new
|
|
79
|
+
throw new SbError(`Class "${ctor.name}" has no component metadata.`);
|
|
79
80
|
if (_metadata.abstract)
|
|
80
81
|
return;
|
|
81
82
|
const metadata = await normalizeComponentMetadata(_metadata);
|
|
@@ -100,7 +101,7 @@ export var ExtensionRegistry;
|
|
|
100
101
|
async function registerProcessor(ctor) {
|
|
101
102
|
const _metadata = Reflect.getMetadata(PROCESSOR_OPTIONS, ctor);
|
|
102
103
|
if (!_metadata)
|
|
103
|
-
throw new
|
|
104
|
+
throw new SbError(`Class "${ctor.name}" has no processor metadata.`);
|
|
104
105
|
if (_metadata.abstract)
|
|
105
106
|
return;
|
|
106
107
|
const metadata = await normalizeProcessorMetadata(_metadata);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isAny, isBase64, isBoolean, isDateString, isEmail, isHex, isNumber, isString, isTime, isURL, validator, vg, } from 'valgen';
|
|
2
|
-
import {
|
|
2
|
+
import { SbValidationError } from '../classes/sb-error.js';
|
|
3
3
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
4
4
|
import { Profile, VariableType, } from '../models/index.js';
|
|
5
5
|
import { getModelsDocument } from '../models-document.js';
|
|
@@ -14,7 +14,7 @@ export function decodeProfile(materializedMetadata, rawProfile, options) {
|
|
|
14
14
|
issues
|
|
15
15
|
.map(issue => `- ${issue.message}. Location: /${issue.location}`)
|
|
16
16
|
.join('\n ');
|
|
17
|
-
throw new
|
|
17
|
+
throw new SbValidationError(msg, {
|
|
18
18
|
workerId: rawProfile.id,
|
|
19
19
|
issues,
|
|
20
20
|
});
|
|
@@ -75,11 +75,7 @@ function _codecProcessElement(stackExecutor, codec, metadata, profile, options)
|
|
|
75
75
|
for (const [k, defComponent] of Object.entries(metadata.components)) {
|
|
76
76
|
if (!profile.components[k]) {
|
|
77
77
|
if (defComponent.required) {
|
|
78
|
-
stackExecutor.issues.push({
|
|
79
|
-
message: `Component "${k}" is required`,
|
|
80
|
-
severity: 'error',
|
|
81
|
-
location: `/components/${k}`,
|
|
82
|
-
});
|
|
78
|
+
stackExecutor.issues.push(new SbValidationError(`Component "${k}" is required`));
|
|
83
79
|
}
|
|
84
80
|
continue;
|
|
85
81
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clone, merge, omitUndefined } from '@jsopen/objects';
|
|
2
|
-
import {
|
|
2
|
+
import { SbValidationError } from '../classes/sb-error.js';
|
|
3
3
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
4
4
|
import { VariableType, } from '../models/index.js';
|
|
5
5
|
import { ExtensionRegistry } from '../registry/extension-registry.js';
|
|
@@ -13,7 +13,7 @@ export function materializeMetadata(profile) {
|
|
|
13
13
|
issues
|
|
14
14
|
.map(issue => `- ${issue.message}. Location: /${issue.location}`)
|
|
15
15
|
.join('\n ');
|
|
16
|
-
throw new
|
|
16
|
+
throw new SbValidationError(msg, {
|
|
17
17
|
workerId: profile.id,
|
|
18
18
|
issues,
|
|
19
19
|
});
|
|
@@ -67,12 +67,12 @@ function _materializeComponents(stackExecutor, metadata, profile) {
|
|
|
67
67
|
const profileComponent = profile?.components?.[componentName];
|
|
68
68
|
if (!profileComponent) {
|
|
69
69
|
if (metadataComponent.required)
|
|
70
|
-
throw new
|
|
70
|
+
throw new SbValidationError(`Component "${componentName}" should be configured`);
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
/** istanbul ignore next */
|
|
74
74
|
if (!profileComponent.className)
|
|
75
|
-
throw new
|
|
75
|
+
throw new SbValidationError(`"className" property required`);
|
|
76
76
|
const reg = ExtensionRegistry.getComponent(profileComponent.className);
|
|
77
77
|
materializedComponent.className = profileComponent.className;
|
|
78
78
|
materializedComponent.variables = merge({}, [reg.metadata.variables || {}, metadataComponent.variables || {}], { deep: 'full' });
|
|
@@ -80,14 +80,14 @@ function _materializeComponents(stackExecutor, metadata, profile) {
|
|
|
80
80
|
if (metadataComponent.className) {
|
|
81
81
|
if (materializedComponent.className &&
|
|
82
82
|
materializedComponent.className !== metadataComponent.className)
|
|
83
|
-
throw new
|
|
83
|
+
throw new SbValidationError(`Selected component class "${profileComponent.className}" do not match with definition component class (${metadataComponent.className}).`);
|
|
84
84
|
}
|
|
85
85
|
else {
|
|
86
86
|
const requiredInterfaces = metadataComponent.interfaces || [];
|
|
87
87
|
const implementations = reg.metadata.interfaces || [];
|
|
88
88
|
const filtered = requiredInterfaces.filter(x => !implementations.includes(x));
|
|
89
89
|
if (filtered.length) {
|
|
90
|
-
throw new
|
|
90
|
+
throw new SbValidationError(`Selected component "${profileComponent.className}" do not implements some of required interfaces (${filtered.join(',')}).`);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
if (materializedComponent.variables) {
|
|
File without changes
|