@syncbridge/common 1.1.4 → 2.0.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/README.md +192 -1
- package/app-factory.d.ts +29 -0
- package/{processor-factory.js → app-factory.js} +63 -44
- package/classes/{processor-base.d.ts → app-base.d.ts} +3 -3
- package/classes/app-base.js +10 -0
- package/classes/base-element.d.ts +3 -0
- package/classes/base-element.js +2 -1
- package/classes/component-base.d.ts +6 -6
- package/classes/component-base.js +2 -3
- package/classes/console-logger.js +0 -1
- package/classes/frame-stream.js +0 -1
- package/classes/log-channel-writer.d.ts +32 -0
- package/classes/log-channel-writer.js +96 -0
- package/classes/runnable.d.ts +6 -0
- package/classes/runnable.js +22 -1
- package/classes/sb-error.js +0 -1
- package/classes/stack-executor.js +0 -1
- package/constants.d.ts +1 -1
- package/constants.js +1 -2
- package/decorators/app-events.decorator.d.ts +5 -0
- package/decorators/{processor-events.decorator.js → app-events.decorator.js} +0 -1
- package/decorators/app.decorator.d.ts +29 -0
- package/decorators/{processor.decorator.js → app.decorator.js} +24 -19
- package/decorators/component.decorator.js +13 -6
- package/decorators/decorator-helpers.js +0 -1
- package/decorators/define-variable.decorator.d.ts +6 -1
- package/decorators/define-variable.decorator.js +5 -2
- package/decorators/log-channel.decorator.d.ts +97 -0
- package/decorators/log-channel.decorator.js +33 -0
- package/decorators/use-component.decorator.d.ts +2 -2
- package/decorators/use-component.decorator.js +1 -2
- package/decorators/use-variables.decorator.d.ts +2 -2
- package/decorators/use-variables.decorator.js +0 -1
- package/host-link/host-identity.d.ts +53 -0
- package/host-link/host-identity.js +139 -0
- package/host-link/host-link.d.ts +43 -0
- package/host-link/host-link.js +53 -0
- package/host-link/host-packages.d.ts +25 -0
- package/host-link/host-packages.js +9 -0
- package/host-link/host-workers.d.ts +75 -0
- package/host-link/host-workers.js +28 -0
- package/host-link/multiplexer.d.ts +115 -0
- package/host-link/multiplexer.js +288 -0
- package/host-link/sealed-box.d.ts +21 -0
- package/host-link/sealed-box.js +103 -0
- package/index.d.ts +16 -3
- package/index.js +16 -4
- package/interfaces/index.js +0 -1
- package/interfaces/logger.interface.js +0 -1
- package/models/enums/enum-source.enum.d.ts +11 -0
- package/models/enums/enum-source.enum.js +21 -0
- package/models/enums/log-channel-kind.d.ts +7 -0
- package/models/enums/log-channel-kind.js +13 -0
- package/models/enums/log-level.js +0 -1
- package/models/enums/service-status.d.ts +5 -1
- package/models/enums/service-status.js +4 -1
- package/models/enums/variable-format.enum.js +0 -1
- package/models/enums/variable-type.enum.js +0 -1
- package/models/enums/worker-permission.enum.d.ts +16 -0
- package/models/enums/worker-permission.enum.js +27 -0
- package/models/index.d.ts +6 -1
- package/models/index.js +6 -2
- package/models/metadata/app-metadata.d.ts +6 -0
- package/models/metadata/{processor-metadata.js → app-metadata.js} +6 -7
- package/models/metadata/component-metadata.js +0 -1
- package/models/metadata/element-component-metadata.d.ts +2 -0
- package/models/metadata/element-component-metadata.js +10 -3
- package/models/metadata/element-metadata.d.ts +8 -0
- package/models/metadata/element-metadata.js +40 -1
- package/models/metadata/log-channel-metadata.d.ts +23 -0
- package/models/metadata/log-channel-metadata.js +72 -0
- package/models/metadata/package-metadata.js +0 -1
- package/models/metadata/plugin-metadata.d.ts +15 -0
- package/models/metadata/plugin-metadata.js +65 -0
- package/models/metadata/variable-metadata.d.ts +3 -0
- package/models/metadata/variable-metadata.js +15 -2
- package/models/profile/log-options.d.ts +17 -0
- package/models/profile/log-options.js +58 -2
- package/models/profile/profile-component.js +0 -1
- package/models/profile/profile.d.ts +2 -2
- package/models/profile/profile.js +9 -10
- package/models-document.js +0 -1
- package/package.json +6 -2
- package/registry/docs-sidebar.d.ts +59 -0
- package/registry/docs-sidebar.js +169 -0
- package/registry/extension-package.d.ts +40 -13
- package/registry/extension-package.js +59 -19
- package/registry/extension-registry.d.ts +16 -16
- package/registry/extension-registry.js +59 -45
- package/registry/module-catalog.d.ts +31 -0
- package/registry/module-catalog.js +88 -0
- package/registry/package-docs.d.ts +98 -0
- package/registry/package-docs.js +159 -0
- package/registry/package-manifest.d.ts +54 -3
- package/registry/package-manifest.js +59 -2
- package/utils/decode-profile.d.ts +18 -2
- package/utils/decode-profile.js +65 -10
- package/utils/encrypt-helpers.d.ts +7 -0
- package/utils/encrypt-helpers.js +12 -6
- package/utils/locate-package-json.js +0 -1
- package/utils/materialize-metadata.d.ts +3 -3
- package/utils/materialize-metadata.js +16 -13
- package/utils/normalize-metadata.d.ts +23 -4
- package/utils/normalize-metadata.js +52 -7
- package/utils/registry-names.js +0 -1
- package/utils/resolve-promises.js +0 -1
- package/utils/type-guards.d.ts +2 -2
- package/utils/type-guards.js +4 -5
- package/utils/uri-to-id.js +0 -1
- package/utils/worker-permissions.d.ts +25 -0
- package/utils/worker-permissions.js +59 -0
- package/classes/base-element.js.map +0 -1
- package/classes/component-base.js.map +0 -1
- package/classes/console-logger.js.map +0 -1
- package/classes/frame-stream.js.map +0 -1
- package/classes/processor-base.js +0 -11
- package/classes/processor-base.js.map +0 -1
- package/classes/runnable.js.map +0 -1
- package/classes/sb-error.js.map +0 -1
- package/classes/stack-executor.js.map +0 -1
- package/constants.js.map +0 -1
- package/decorators/component.decorator.js.map +0 -1
- package/decorators/decorator-helpers.js.map +0 -1
- package/decorators/define-variable.decorator.js.map +0 -1
- package/decorators/processor-events.decorator.d.ts +0 -5
- package/decorators/processor-events.decorator.js.map +0 -1
- package/decorators/processor.decorator.d.ts +0 -29
- package/decorators/processor.decorator.js.map +0 -1
- package/decorators/use-component.decorator.js.map +0 -1
- package/decorators/use-variables.decorator.js.map +0 -1
- package/index.js.map +0 -1
- package/interfaces/index.js.map +0 -1
- package/interfaces/logger.interface.js.map +0 -1
- package/models/enums/log-level.js.map +0 -1
- package/models/enums/service-status.js.map +0 -1
- package/models/enums/variable-format.enum.js.map +0 -1
- package/models/enums/variable-type.enum.js.map +0 -1
- package/models/index.js.map +0 -1
- package/models/metadata/component-metadata.js.map +0 -1
- package/models/metadata/element-component-metadata.js.map +0 -1
- package/models/metadata/element-metadata.js.map +0 -1
- package/models/metadata/package-metadata.js.map +0 -1
- package/models/metadata/processor-metadata.d.ts +0 -6
- package/models/metadata/processor-metadata.js.map +0 -1
- package/models/metadata/variable-metadata.js.map +0 -1
- package/models/profile/log-options.js.map +0 -1
- package/models/profile/profile-component.js.map +0 -1
- package/models/profile/profile.js.map +0 -1
- package/models-document.js.map +0 -1
- package/processor-factory.d.ts +0 -26
- package/processor-factory.js.map +0 -1
- package/registry/extension-package.js.map +0 -1
- package/registry/extension-registry.js.map +0 -1
- package/registry/package-manifest.js.map +0 -1
- package/utils/decode-profile.js.map +0 -1
- package/utils/encrypt-helpers.js.map +0 -1
- package/utils/locate-package-json.js.map +0 -1
- package/utils/materialize-metadata.js.map +0 -1
- package/utils/normalize-metadata.js.map +0 -1
- package/utils/registry-names.js.map +0 -1
- package/utils/resolve-promises.js.map +0 -1
- package/utils/type-guards.js.map +0 -1
- package/utils/uri-to-id.js.map +0 -1
|
@@ -1,14 +1,45 @@
|
|
|
1
|
+
import type { AppMetadata, ComponentMetadata, PluginMetadata } from '../models/index.js';
|
|
2
|
+
/** The file an extension package's manifest is in, at its root */
|
|
3
|
+
export declare const MANIFEST_FILE = "syncbridge-manifest.json";
|
|
1
4
|
/**
|
|
2
|
-
*
|
|
5
|
+
* An extension package's manifest: what it brings and what it needs.
|
|
6
|
+
*
|
|
7
|
+
* Its author writes `name` and `dependencies`, in the `syncbridge` field of
|
|
8
|
+
* `package.json` or in `syncbridge-manifest.json` at the package's root -
|
|
9
|
+
* never both. `syncbuild` adds what the package brings and writes the
|
|
10
|
+
* manifest of the package it builds to `syncbridge-manifest.json` only, so
|
|
11
|
+
* an installed package's manifest is always that file.
|
|
12
|
+
*
|
|
13
|
+
* Fields SyncBridge does not know are passed over with a warning: one added
|
|
14
|
+
* later breaks neither an older SyncBridge nor an older package.
|
|
3
15
|
*/
|
|
4
16
|
export interface SyncBridgeManifest {
|
|
5
17
|
/** The name the package registers under, when it differs from `name` */
|
|
6
18
|
name?: string;
|
|
7
19
|
/** Registry packages this one depends on: registry name -> semver range */
|
|
8
20
|
dependencies?: Record<string, string>;
|
|
9
|
-
|
|
10
|
-
|
|
21
|
+
/** The apps the package brings, each with its definition */
|
|
22
|
+
apps?: ManifestEntry<AppMetadata>[];
|
|
23
|
+
/** The components the package brings, each with its definition */
|
|
24
|
+
components?: ManifestEntry<ComponentMetadata>[];
|
|
25
|
+
/** The plugins the package brings, each with its definition */
|
|
26
|
+
plugins?: ManifestEntry<PluginMetadata>[];
|
|
27
|
+
/**
|
|
28
|
+
* The language of its documents that name none (README.md, not
|
|
29
|
+
* README.tr.md): ISO 639-1, its region if any - `en` when not told
|
|
30
|
+
*/
|
|
31
|
+
docsLanguage?: string;
|
|
11
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Something a package brings: its definition, and where its class is - the
|
|
35
|
+
* module it is exported from, so a worker loads only what it runs
|
|
36
|
+
*/
|
|
37
|
+
export type ManifestEntry<T> = T & {
|
|
38
|
+
/** The name the class is exported under from its module */
|
|
39
|
+
exportName: string;
|
|
40
|
+
/** Its module, relative to the package's root: `./hl7-bridge.app.js` */
|
|
41
|
+
entryPoint: string;
|
|
42
|
+
};
|
|
12
43
|
/**
|
|
13
44
|
* The parts of an extension package's `package.json` SyncBridge reads.
|
|
14
45
|
*/
|
|
@@ -22,3 +53,23 @@ export interface ExtensionPackageJson {
|
|
|
22
53
|
peerDependencies?: Record<string, string>;
|
|
23
54
|
syncbridge?: SyncBridgeManifest;
|
|
24
55
|
}
|
|
56
|
+
/** A package's manifest as read, with where it was and what was not known */
|
|
57
|
+
export interface ReadManifest {
|
|
58
|
+
manifest: SyncBridgeManifest;
|
|
59
|
+
/** `file`: syncbridge-manifest.json; `package.json`: its syncbridge field */
|
|
60
|
+
source: 'file' | 'package.json';
|
|
61
|
+
/** Fields of the manifest SyncBridge does not know, passed over */
|
|
62
|
+
unknownFields: string[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Reads the manifest of the package in `packageDir`: its
|
|
66
|
+
* syncbridge-manifest.json, or else the `syncbridge` field of its
|
|
67
|
+
* package.json. Undefined when it has neither: it is not an extension
|
|
68
|
+
* package. Throws when it has both, as which one counts would be unclear.
|
|
69
|
+
*/
|
|
70
|
+
export declare function readExtensionManifest(packageDir: string, pkgJson?: ExtensionPackageJson): ReadManifest | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* The manifest of the package in `packageDir`, when it is an extension
|
|
73
|
+
* package (see readExtensionManifest)
|
|
74
|
+
*/
|
|
75
|
+
export declare function manifestOf(packageDir: string, pkgJson?: ExtensionPackageJson): SyncBridgeManifest | undefined;
|
|
@@ -1,2 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { SbError } from '../classes/sb-error.js';
|
|
4
|
+
/** The file an extension package's manifest is in, at its root */
|
|
5
|
+
export const MANIFEST_FILE = 'syncbridge-manifest.json';
|
|
6
|
+
/** The fields of a manifest SyncBridge knows */
|
|
7
|
+
const KNOWN_FIELDS = new Set([
|
|
8
|
+
'name',
|
|
9
|
+
'dependencies',
|
|
10
|
+
'apps',
|
|
11
|
+
'components',
|
|
12
|
+
'plugins',
|
|
13
|
+
'docsLanguage',
|
|
14
|
+
]);
|
|
15
|
+
/**
|
|
16
|
+
* Reads the manifest of the package in `packageDir`: its
|
|
17
|
+
* syncbridge-manifest.json, or else the `syncbridge` field of its
|
|
18
|
+
* package.json. Undefined when it has neither: it is not an extension
|
|
19
|
+
* package. Throws when it has both, as which one counts would be unclear.
|
|
20
|
+
*/
|
|
21
|
+
export function readExtensionManifest(packageDir, pkgJson) {
|
|
22
|
+
pkgJson =
|
|
23
|
+
pkgJson ||
|
|
24
|
+
(fs.existsSync(path.join(packageDir, 'package.json'))
|
|
25
|
+
? JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8'))
|
|
26
|
+
: undefined);
|
|
27
|
+
const file = path.join(packageDir, MANIFEST_FILE);
|
|
28
|
+
const inFile = fs.existsSync(file);
|
|
29
|
+
const inPackageJson = pkgJson?.syncbridge != null;
|
|
30
|
+
if (inFile && inPackageJson)
|
|
31
|
+
throw new SbError(`"${pkgJson.name}" has a manifest both in ${MANIFEST_FILE} and in the "syncbridge" field of package.json: keep one`);
|
|
32
|
+
let manifest;
|
|
33
|
+
if (inFile) {
|
|
34
|
+
try {
|
|
35
|
+
manifest = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
throw new SbError(`${file} is not valid JSON: ${e.message}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (inPackageJson)
|
|
42
|
+
manifest = pkgJson.syncbridge;
|
|
43
|
+
else
|
|
44
|
+
return;
|
|
45
|
+
if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest))
|
|
46
|
+
throw new SbError(`The manifest of "${pkgJson?.name || packageDir}" must be an object`);
|
|
47
|
+
return {
|
|
48
|
+
manifest,
|
|
49
|
+
source: inFile ? 'file' : 'package.json',
|
|
50
|
+
unknownFields: Object.keys(manifest).filter(k => !KNOWN_FIELDS.has(k)),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The manifest of the package in `packageDir`, when it is an extension
|
|
55
|
+
* package (see readExtensionManifest)
|
|
56
|
+
*/
|
|
57
|
+
export function manifestOf(packageDir, pkgJson) {
|
|
58
|
+
return readExtensionManifest(packageDir, pkgJson)?.manifest;
|
|
59
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
2
|
-
import {
|
|
2
|
+
import { AppMetadata, Profile, VariableMetadataRecord } from '../models/index.js';
|
|
3
3
|
export interface CodecOptions {
|
|
4
4
|
setDefaultValues?: boolean;
|
|
5
5
|
cryptoSecretKey?: string;
|
|
@@ -11,7 +11,7 @@ export declare function decodeProfile(profile: Profile, options?: CodecOptions):
|
|
|
11
11
|
export declare function decodeProfileSilent(profile: Profile, options?: CodecOptions): {
|
|
12
12
|
result: true;
|
|
13
13
|
profile: Profile;
|
|
14
|
-
metadata:
|
|
14
|
+
metadata: AppMetadata;
|
|
15
15
|
issues?: StackExecutor.Issue[];
|
|
16
16
|
} | {
|
|
17
17
|
result: false;
|
|
@@ -32,3 +32,19 @@ export declare function encodeProfileSilent(profile: Profile, options?: CodecOpt
|
|
|
32
32
|
result: false;
|
|
33
33
|
issues: StackExecutor.Issue[];
|
|
34
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Decodes values by the variables that define them - checks each against
|
|
37
|
+
* its type and rules and sets the defaults - as a profile's values are.
|
|
38
|
+
* Values no variable defines are left out. Issues are located by the
|
|
39
|
+
* values' keys, below `location` when one is given.
|
|
40
|
+
*/
|
|
41
|
+
export declare function decodeValues(variables: VariableMetadataRecord, values: Record<string, any> | undefined, options?: CodecOptions & {
|
|
42
|
+
location?: string;
|
|
43
|
+
}): {
|
|
44
|
+
result: true;
|
|
45
|
+
values: Record<string, any>;
|
|
46
|
+
issues: StackExecutor.Issue[];
|
|
47
|
+
} | {
|
|
48
|
+
result: false;
|
|
49
|
+
issues: StackExecutor.Issue[];
|
|
50
|
+
};
|
package/utils/decode-profile.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isAny, isBase64, isBigint, isBoolean, isDateString, isEmail, isHex, isNumber, isString, isTime, isURL, validator, vg, } from 'valgen';
|
|
2
2
|
import { SbValidationError } from '../classes/sb-error.js';
|
|
3
3
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
4
|
-
import {
|
|
4
|
+
import { AppMetadata, ElementComponentMetadata, Profile, ProfileComponent, VariableMetadataRecord, VariableType, } from '../models/index.js';
|
|
5
5
|
import { getModelsDocument } from '../models-document.js';
|
|
6
6
|
import { secretDecryptor, secretEncryptor } from './encrypt-helpers.js';
|
|
7
7
|
import { materializeMetadataSilent } from './materialize-metadata.js';
|
|
@@ -81,7 +81,7 @@ export function encodeProfileSilent(profile, options) {
|
|
|
81
81
|
const fn = t.generateCodec('encode', { coerce: true });
|
|
82
82
|
const out = fn({
|
|
83
83
|
id: profile.id,
|
|
84
|
-
|
|
84
|
+
appUri: profile.appUri,
|
|
85
85
|
displayName: profile.displayName,
|
|
86
86
|
group: profile.group,
|
|
87
87
|
description: profile.description,
|
|
@@ -106,6 +106,8 @@ export function encodeProfileSilent(profile, options) {
|
|
|
106
106
|
* @private
|
|
107
107
|
*/
|
|
108
108
|
function _codecProcessElement(stackExecutor, codec, metadata, profile, options) {
|
|
109
|
+
if (codec === 'decode')
|
|
110
|
+
_checkLogChannels(stackExecutor, metadata, profile);
|
|
109
111
|
profile.values = profile.values || {};
|
|
110
112
|
if (metadata.variables) {
|
|
111
113
|
stackExecutor.execute('values', () => {
|
|
@@ -134,18 +136,67 @@ function _codecProcessElement(stackExecutor, codec, metadata, profile, options)
|
|
|
134
136
|
delete profile?.components;
|
|
135
137
|
}
|
|
136
138
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
+
* Warns of an element's log channel settings that name what it does not
|
|
140
|
+
* have: a channel, or an event its channel does not write. Warnings only:
|
|
141
|
+
* a package's next version may drop either, and a worker does not stop
|
|
142
|
+
* for a log setting.
|
|
143
|
+
*/
|
|
144
|
+
function _checkLogChannels(stackExecutor, metadata, profile) {
|
|
145
|
+
const settings = profile.settings?.logs?.channels;
|
|
146
|
+
if (!settings)
|
|
147
|
+
return;
|
|
148
|
+
const at = stackExecutor.stack.join('/');
|
|
149
|
+
const warn = (location, message) => stackExecutor.issues.push({
|
|
150
|
+
message,
|
|
151
|
+
severity: 'warning',
|
|
152
|
+
location: (at ? at + '/' : '') + location,
|
|
153
|
+
});
|
|
154
|
+
for (const [name, channelSettings] of Object.entries(settings)) {
|
|
155
|
+
const where = `settings/logs/channels/${name}`;
|
|
156
|
+
const definition = metadata.logChannels?.[name];
|
|
157
|
+
if (!definition) {
|
|
158
|
+
/* The app's settings keep the worker's console, defined by none */
|
|
159
|
+
if (!(name === 'console' && !at))
|
|
160
|
+
warn(where, `"${name}" is not a log channel of this element`);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const unknown = (channelSettings?.events || []).filter(event => !definition.events?.includes(event));
|
|
164
|
+
if (unknown.length)
|
|
165
|
+
warn(`${where}/events`, `${unknown.map(e => `"${e}"`).join(', ')} ${unknown.length === 1 ? 'is not an event' : 'are not events'} of the "${name}" channel. It has: ${definition.events?.join(', ') || 'none'}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Decodes values by the variables that define them - checks each against
|
|
170
|
+
* its type and rules and sets the defaults - as a profile's values are.
|
|
171
|
+
* Values no variable defines are left out. Issues are located by the
|
|
172
|
+
* values' keys, below `location` when one is given.
|
|
139
173
|
*/
|
|
174
|
+
export function decodeValues(variables, values, options) {
|
|
175
|
+
const stackExecutor = new StackExecutor();
|
|
176
|
+
let out = {};
|
|
177
|
+
const run = () => {
|
|
178
|
+
out = _codecValues(stackExecutor, 'decode', variables, values, options);
|
|
179
|
+
};
|
|
180
|
+
if (options?.location)
|
|
181
|
+
stackExecutor.execute(options.location, run);
|
|
182
|
+
else
|
|
183
|
+
run();
|
|
184
|
+
if (stackExecutor.issues.find(i => !(i.severity === 'warning' || i.severity === 'info')))
|
|
185
|
+
return { result: false, issues: stackExecutor.issues };
|
|
186
|
+
return { result: true, values: out, issues: stackExecutor.issues };
|
|
187
|
+
}
|
|
140
188
|
function _decodeVariables(stackExecutor, codec, metadata, profile, options) {
|
|
141
189
|
if (!metadata.variables) {
|
|
142
190
|
delete profile.values;
|
|
143
191
|
return;
|
|
144
192
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
193
|
+
profile.values = _codecValues(stackExecutor, codec, metadata.variables, profile.values, options);
|
|
194
|
+
}
|
|
195
|
+
/** The values the variables define, decoded or encoded */
|
|
196
|
+
function _codecValues(stackExecutor, codec, variables, oldValues, options) {
|
|
197
|
+
const values = {};
|
|
198
|
+
const process = (defs, target, oldVals) => {
|
|
199
|
+
for (const [k, defVariable] of Object.entries(defs)) {
|
|
149
200
|
stackExecutor.execute(k, () => {
|
|
150
201
|
if (defVariable == null)
|
|
151
202
|
return;
|
|
@@ -280,6 +331,10 @@ function _decodeVariables(stackExecutor, codec, metadata, profile, options) {
|
|
|
280
331
|
valueFn = vg.pipe([valueFn, ...fns]);
|
|
281
332
|
}
|
|
282
333
|
}
|
|
334
|
+
/* A required value that is missing is told as such, not as a value
|
|
335
|
+
* of the wrong type */
|
|
336
|
+
if (defVariable.required && !hasDefault && codec === 'decode')
|
|
337
|
+
valueFn = vg.required(valueFn);
|
|
283
338
|
if (!defVariable.required && !hasDefault) {
|
|
284
339
|
valueFn = defVariable.nullable
|
|
285
340
|
? vg.nullable(valueFn)
|
|
@@ -289,6 +344,6 @@ function _decodeVariables(stackExecutor, codec, metadata, profile, options) {
|
|
|
289
344
|
});
|
|
290
345
|
}
|
|
291
346
|
};
|
|
292
|
-
process(
|
|
347
|
+
process(variables, values, oldValues);
|
|
348
|
+
return values;
|
|
293
349
|
}
|
|
294
|
-
//# sourceMappingURL=decode-profile.js.map
|
|
@@ -1,2 +1,9 @@
|
|
|
1
|
+
/** What marks a value encrypted, before its text */
|
|
2
|
+
export declare const SECRET_PREFIX = "sbscrt::";
|
|
3
|
+
/**
|
|
4
|
+
* A secret value kept encrypted: one already so, encrypted anew (a fresh
|
|
5
|
+
* salt and IV) - its text, not its prefix, taken as encrypted
|
|
6
|
+
*/
|
|
1
7
|
export declare const secretEncryptor: (secretKey: string) => import("valgen").Validator<string, string, import("valgen").ExecutionOptions>;
|
|
8
|
+
/** A secret value read: one encrypted, its text; any other, as it is */
|
|
2
9
|
export declare const secretDecryptor: (secretKey: string) => import("valgen").Validator<string, string, import("valgen").ExecutionOptions>;
|
package/utils/encrypt-helpers.js
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
2
|
import { validator } from 'valgen';
|
|
3
|
+
/** What marks a value encrypted, before its text */
|
|
4
|
+
export const SECRET_PREFIX = 'sbscrt::';
|
|
5
|
+
/**
|
|
6
|
+
* A secret value kept encrypted: one already so, encrypted anew (a fresh
|
|
7
|
+
* salt and IV) - its text, not its prefix, taken as encrypted
|
|
8
|
+
*/
|
|
3
9
|
export const secretEncryptor = (secretKey) => {
|
|
4
10
|
return validator((input) => {
|
|
5
|
-
if (input.startsWith(
|
|
6
|
-
input = decryptText(input, secretKey);
|
|
11
|
+
if (input.startsWith(SECRET_PREFIX)) {
|
|
12
|
+
input = decryptText(input.substring(SECRET_PREFIX.length), secretKey);
|
|
7
13
|
}
|
|
8
|
-
return
|
|
14
|
+
return SECRET_PREFIX + encryptText(input, secretKey);
|
|
9
15
|
});
|
|
10
16
|
};
|
|
17
|
+
/** A secret value read: one encrypted, its text; any other, as it is */
|
|
11
18
|
export const secretDecryptor = (secretKey) => {
|
|
12
19
|
return validator((input) => {
|
|
13
|
-
if (input.startsWith(
|
|
14
|
-
return decryptText(input.substring(
|
|
20
|
+
if (input.startsWith(SECRET_PREFIX)) {
|
|
21
|
+
return decryptText(input.substring(SECRET_PREFIX.length), secretKey);
|
|
15
22
|
}
|
|
16
23
|
return input;
|
|
17
24
|
});
|
|
@@ -41,4 +48,3 @@ function decryptText(input, secretKey) {
|
|
|
41
48
|
]);
|
|
42
49
|
return decrypted.toString('utf8');
|
|
43
50
|
}
|
|
44
|
-
//# sourceMappingURL=encrypt-helpers.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
2
|
-
import {
|
|
2
|
+
import { AppMetadata, Profile } from '../models/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Materializes metadata from profile.
|
|
5
5
|
*/
|
|
6
6
|
export declare function materializeMetadata(profile: Profile, options?: {
|
|
7
7
|
returnUndefinedComponentsAsAbstract?: boolean;
|
|
8
8
|
removeIgnoredVariables?: boolean;
|
|
9
|
-
}):
|
|
9
|
+
}): AppMetadata;
|
|
10
10
|
/**
|
|
11
11
|
*
|
|
12
12
|
*/
|
|
@@ -15,7 +15,7 @@ export declare function materializeMetadataSilent(profile: Profile, options?: {
|
|
|
15
15
|
removeIgnoredVariables?: boolean;
|
|
16
16
|
}): {
|
|
17
17
|
result: true;
|
|
18
|
-
metadata:
|
|
18
|
+
metadata: AppMetadata;
|
|
19
19
|
issues: StackExecutor.Issue[];
|
|
20
20
|
} | {
|
|
21
21
|
result: false;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clone, merge, omit, omitUndefined } from '@jsopen/objects';
|
|
2
2
|
import { SbValidationError } from '../classes/sb-error.js';
|
|
3
3
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
4
|
-
import { ElementComponentMetadata, ElementComponentMetadataRecord,
|
|
4
|
+
import { AppMetadata, ElementComponentMetadata, ElementComponentMetadataRecord, Profile, ProfileComponent, VariableMetadata, VariableMetadataRecord, VariableType, } from '../models/index.js';
|
|
5
5
|
import { ExtensionRegistry } from '../registry/extension-registry.js';
|
|
6
6
|
/**
|
|
7
7
|
* Materializes metadata from profile.
|
|
@@ -29,18 +29,18 @@ export function materializeMetadata(profile, options) {
|
|
|
29
29
|
*/
|
|
30
30
|
export function materializeMetadataSilent(profile, options) {
|
|
31
31
|
const stackExecutor = new StackExecutor();
|
|
32
|
-
const
|
|
32
|
+
const appRec = ExtensionRegistry.getApp(profile.appUri, profile.appVersion);
|
|
33
33
|
const metadata = omitUndefined(clone({
|
|
34
|
-
classType:
|
|
35
|
-
className:
|
|
36
|
-
version:
|
|
37
|
-
displayName:
|
|
38
|
-
description:
|
|
39
|
-
iconUrl:
|
|
40
|
-
tags:
|
|
41
|
-
variables:
|
|
42
|
-
components:
|
|
43
|
-
...
|
|
34
|
+
classType: appRec.metadata.classType,
|
|
35
|
+
className: appRec.metadata.className,
|
|
36
|
+
version: appRec.version,
|
|
37
|
+
displayName: appRec.metadata.displayName,
|
|
38
|
+
description: appRec.metadata.description,
|
|
39
|
+
iconUrl: appRec.metadata.iconUrl,
|
|
40
|
+
tags: appRec.metadata.tags,
|
|
41
|
+
variables: appRec.metadata.variables,
|
|
42
|
+
components: appRec.metadata.components,
|
|
43
|
+
...appRec.metadata,
|
|
44
44
|
}, { deep: 'full' }));
|
|
45
45
|
if (metadata.variables) {
|
|
46
46
|
/* Remove ignored variables */
|
|
@@ -101,6 +101,10 @@ function _materializeComponents(stackExecutor, srcMetadata, profile, options) {
|
|
|
101
101
|
};
|
|
102
102
|
materializedComponent.variables = merge({}, [reg.metadata.variables || {}, metadataComponent.variables || {}], { deep: 'full' });
|
|
103
103
|
materializedComponent.variables = sortVariables(materializedComponent.variables);
|
|
104
|
+
if (reg.metadata.logChannels)
|
|
105
|
+
materializedComponent.logChannels = clone(reg.metadata.logChannels, {
|
|
106
|
+
deep: 'full',
|
|
107
|
+
});
|
|
104
108
|
out[componentName] = materializedComponent;
|
|
105
109
|
/** Remove ignored variables */
|
|
106
110
|
for (const [k, variable] of Object.entries(materializedComponent.variables)) {
|
|
@@ -142,4 +146,3 @@ function sortVariables(variables) {
|
|
|
142
146
|
return a;
|
|
143
147
|
}, {});
|
|
144
148
|
}
|
|
145
|
-
//# sourceMappingURL=materialize-metadata.js.map
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import type { Type } from 'ts-gems';
|
|
1
3
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
2
|
-
import { ComponentMetadata,
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
metadata:
|
|
4
|
+
import { AppMetadata, ComponentMetadata, PluginMetadata, VariableMetadataRecord } from '../models/index.js';
|
|
5
|
+
export declare function normalizeAppMetadata(metadata: AppMetadata): Promise<AppMetadata>;
|
|
6
|
+
export declare function normalizeAppMetadataSilent(metadata: AppMetadata): Promise<{
|
|
7
|
+
metadata: AppMetadata;
|
|
6
8
|
issues?: StackExecutor.Issue[];
|
|
7
9
|
}>;
|
|
8
10
|
export declare function normalizeComponentMetadata(metadata: ComponentMetadata): Promise<ComponentMetadata>;
|
|
@@ -10,3 +12,20 @@ export declare function normalizeComponentMetadataSilent(metadata: ComponentMeta
|
|
|
10
12
|
metadata: ComponentMetadata;
|
|
11
13
|
issues?: StackExecutor.Issue[];
|
|
12
14
|
}>;
|
|
15
|
+
/**
|
|
16
|
+
* A plugin's definition checked and given its defaults; throws an
|
|
17
|
+
* SbValidationError listing what is wrong
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizePluginMetadata(metadata: PluginMetadata): Promise<PluginMetadata>;
|
|
20
|
+
/**
|
|
21
|
+
* The variables a class defines with @DefineVariable, as they are now: read
|
|
22
|
+
* them when the class is defined, as metadata read later may be gone if
|
|
23
|
+
* another copy of reflect-metadata took over the global Reflect since.
|
|
24
|
+
* Undefined when the class defines none.
|
|
25
|
+
*/
|
|
26
|
+
export declare function readVariables(variablesClass: Type): VariableMetadataRecord | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Variables as the metadata of an element holds them: what they are given
|
|
29
|
+
* as promises resolved, enum values as arrays
|
|
30
|
+
*/
|
|
31
|
+
export declare function normalizeVariablesMetadata(variables: VariableMetadataRecord): Promise<VariableMetadataRecord>;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
1
2
|
import { deepClone, merge } from '@jsopen/objects';
|
|
2
3
|
import { SbValidationError } from '../classes/sb-error.js';
|
|
3
4
|
import { StackExecutor } from '../classes/stack-executor.js';
|
|
4
|
-
import {
|
|
5
|
+
import { VARIABLE_CONTAINER } from '../constants.js';
|
|
6
|
+
import { AppMetadata, ComponentMetadata, ElementComponentMetadataRecord, PluginMetadata, VariableMetadataRecord, } from '../models/index.js';
|
|
5
7
|
import { initializeModelsDocument } from '../models-document.js';
|
|
6
8
|
import { resolvePromisesDeep } from './resolve-promises.js';
|
|
7
|
-
export async function
|
|
8
|
-
const { metadata: out, issues } = await
|
|
9
|
+
export async function normalizeAppMetadata(metadata) {
|
|
10
|
+
const { metadata: out, issues } = await normalizeAppMetadataSilent(metadata);
|
|
9
11
|
if (issues?.length) {
|
|
10
12
|
const msg = 'Worker profile decoding error.\n ' +
|
|
11
13
|
issues
|
|
@@ -21,10 +23,10 @@ export async function normalizeProcessorMetadata(metadata) {
|
|
|
21
23
|
}
|
|
22
24
|
return out;
|
|
23
25
|
}
|
|
24
|
-
export async function
|
|
26
|
+
export async function normalizeAppMetadataSilent(metadata) {
|
|
25
27
|
const decoder = await getProcMetadataTypeDecoder();
|
|
26
28
|
let cloned = deepClone({
|
|
27
|
-
classType: '
|
|
29
|
+
classType: 'app',
|
|
28
30
|
className: metadata.className,
|
|
29
31
|
displayName: metadata.displayName,
|
|
30
32
|
description: metadata.description,
|
|
@@ -99,6 +101,32 @@ export async function normalizeComponentMetadataSilent(metadata) {
|
|
|
99
101
|
})),
|
|
100
102
|
};
|
|
101
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* A plugin's definition checked and given its defaults; throws an
|
|
106
|
+
* SbValidationError listing what is wrong
|
|
107
|
+
*/
|
|
108
|
+
export async function normalizePluginMetadata(metadata) {
|
|
109
|
+
if (!_pluginMetadataTypeDecoder) {
|
|
110
|
+
const apiDoc = await initializeModelsDocument();
|
|
111
|
+
_pluginMetadataTypeDecoder = apiDoc.node
|
|
112
|
+
.getComplexType(PluginMetadata)
|
|
113
|
+
.generateCodec('decode', { coerce: true });
|
|
114
|
+
}
|
|
115
|
+
const cloned = await resolvePromisesDeep(deepClone({ ...metadata, classType: 'plugin' }));
|
|
116
|
+
cloned.settings = normalizeVariables(cloned.settings);
|
|
117
|
+
const { value, errors } = _pluginMetadataTypeDecoder.silent(cloned);
|
|
118
|
+
if (!errors?.length)
|
|
119
|
+
return value;
|
|
120
|
+
throw new SbValidationError('Invalid plugin definition.\n ' +
|
|
121
|
+
errors.map(e => `- ${e.message}. Location: /${e.location}`).join('\n '), {
|
|
122
|
+
issues: errors.map(e => ({
|
|
123
|
+
message: e.message,
|
|
124
|
+
severity: 'error',
|
|
125
|
+
location: e.location,
|
|
126
|
+
code: 'validation-error:' + e.rule,
|
|
127
|
+
})),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
102
130
|
function normalizeComponents(components) {
|
|
103
131
|
if (!components)
|
|
104
132
|
return;
|
|
@@ -110,6 +138,23 @@ function normalizeComponents(components) {
|
|
|
110
138
|
}
|
|
111
139
|
return components;
|
|
112
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* The variables a class defines with @DefineVariable, as they are now: read
|
|
143
|
+
* them when the class is defined, as metadata read later may be gone if
|
|
144
|
+
* another copy of reflect-metadata took over the global Reflect since.
|
|
145
|
+
* Undefined when the class defines none.
|
|
146
|
+
*/
|
|
147
|
+
export function readVariables(variablesClass) {
|
|
148
|
+
const variables = Reflect.getMetadata(VARIABLE_CONTAINER, variablesClass.prototype);
|
|
149
|
+
return variables ? deepClone(variables) : undefined;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Variables as the metadata of an element holds them: what they are given
|
|
153
|
+
* as promises resolved, enum values as arrays
|
|
154
|
+
*/
|
|
155
|
+
export async function normalizeVariablesMetadata(variables) {
|
|
156
|
+
return normalizeVariables(await resolvePromisesDeep(deepClone(variables)));
|
|
157
|
+
}
|
|
113
158
|
function normalizeVariables(variables) {
|
|
114
159
|
if (!variables)
|
|
115
160
|
return;
|
|
@@ -134,6 +179,7 @@ function normalizeVariables(variables) {
|
|
|
134
179
|
// ************************************************************************
|
|
135
180
|
let _compMetadataTypeDecoder;
|
|
136
181
|
let _procMetadataTypeDecoder;
|
|
182
|
+
let _pluginMetadataTypeDecoder;
|
|
137
183
|
async function getCompMetadataTypeDecoder() {
|
|
138
184
|
if (!_compMetadataTypeDecoder) {
|
|
139
185
|
const apiDoc = await initializeModelsDocument();
|
|
@@ -147,11 +193,10 @@ async function getCompMetadataTypeDecoder() {
|
|
|
147
193
|
async function getProcMetadataTypeDecoder() {
|
|
148
194
|
if (!_procMetadataTypeDecoder) {
|
|
149
195
|
const apiDoc = await initializeModelsDocument();
|
|
150
|
-
const procMetadataType = apiDoc.node.getComplexType(
|
|
196
|
+
const procMetadataType = apiDoc.node.getComplexType(AppMetadata);
|
|
151
197
|
_procMetadataTypeDecoder = procMetadataType.generateCodec('decode', {
|
|
152
198
|
coerce: true,
|
|
153
199
|
});
|
|
154
200
|
}
|
|
155
201
|
return _procMetadataTypeDecoder;
|
|
156
202
|
}
|
|
157
|
-
//# sourceMappingURL=normalize-metadata.js.map
|
package/utils/registry-names.js
CHANGED
package/utils/type-guards.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { AppBase } from '../classes/app-base.js';
|
|
1
2
|
import { ComponentBase } from '../classes/component-base.js';
|
|
2
|
-
import { ProcessorBase } from '../classes/processor-base.js';
|
|
3
3
|
import { Runnable } from '../classes/runnable.js';
|
|
4
4
|
export declare function isRunnable(proto: any): proto is Runnable;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function isAppBase(proto: any): proto is AppBase;
|
|
6
6
|
export declare function isComponentBase(proto: any): proto is ComponentBase;
|
package/utils/type-guards.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
+
import { AppBase } from '../classes/app-base.js';
|
|
1
2
|
import { ComponentBase } from '../classes/component-base.js';
|
|
2
|
-
import { ProcessorBase } from '../classes/processor-base.js';
|
|
3
3
|
import { Runnable } from '../classes/runnable.js';
|
|
4
4
|
const RUNNABLE_TOKEN = Symbol.for(Runnable.name);
|
|
5
|
-
const
|
|
5
|
+
const APP_BASE_TOKEN = Symbol.for(AppBase.name);
|
|
6
6
|
const COMPONENT_BASE_TOKEN = Symbol.for(ComponentBase.name);
|
|
7
7
|
export function isRunnable(proto) {
|
|
8
8
|
return !!proto[RUNNABLE_TOKEN];
|
|
9
9
|
}
|
|
10
|
-
export function
|
|
11
|
-
return !!proto[
|
|
10
|
+
export function isAppBase(proto) {
|
|
11
|
+
return !!proto[APP_BASE_TOKEN];
|
|
12
12
|
}
|
|
13
13
|
export function isComponentBase(proto) {
|
|
14
14
|
return !!proto[COMPONENT_BASE_TOKEN];
|
|
15
15
|
}
|
|
16
|
-
//# sourceMappingURL=type-guards.js.map
|
package/utils/uri-to-id.js
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { WorkerPermission } from '../models/enums/worker-permission.enum.js';
|
|
2
|
+
import type { AppMetadata } from '../models/metadata/app-metadata.js';
|
|
3
|
+
import type { ComponentMetadata } from '../models/metadata/component-metadata.js';
|
|
4
|
+
/**
|
|
5
|
+
* What of the server a worker reaches: as its app declares, and each
|
|
6
|
+
* component it is given - the one its profile chose, else the one its app
|
|
7
|
+
* asks for - and theirs, all the way down
|
|
8
|
+
*/
|
|
9
|
+
export declare function workerPermissionsOf(metadata: AppMetadata | undefined, find: (uri: string) => ComponentMetadata | undefined): WorkerPermission[];
|
|
10
|
+
/**
|
|
11
|
+
* Node's permission model for a worker: it reads and writes the paths
|
|
12
|
+
* told (any, when none), and reaches native addons and other programs as
|
|
13
|
+
* it declares them (native-code, child-processes) - both outside the
|
|
14
|
+
* model; worker threads never, outside it too
|
|
15
|
+
*/
|
|
16
|
+
export declare function nodePermissionArgs(args: {
|
|
17
|
+
read?: string[];
|
|
18
|
+
write?: string[];
|
|
19
|
+
permissions: string[];
|
|
20
|
+
}): string[];
|
|
21
|
+
/**
|
|
22
|
+
* What a worker refused by the permission model is to declare, from the
|
|
23
|
+
* error it failed with: none, it was not refused so
|
|
24
|
+
*/
|
|
25
|
+
export declare function missingPermissionOf(message: string): WorkerPermission | undefined;
|