@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.
Files changed (163) hide show
  1. package/README.md +192 -1
  2. package/app-factory.d.ts +29 -0
  3. package/{processor-factory.js → app-factory.js} +63 -44
  4. package/classes/{processor-base.d.ts → app-base.d.ts} +3 -3
  5. package/classes/app-base.js +10 -0
  6. package/classes/base-element.d.ts +3 -0
  7. package/classes/base-element.js +2 -1
  8. package/classes/component-base.d.ts +6 -6
  9. package/classes/component-base.js +2 -3
  10. package/classes/console-logger.js +0 -1
  11. package/classes/frame-stream.js +0 -1
  12. package/classes/log-channel-writer.d.ts +32 -0
  13. package/classes/log-channel-writer.js +96 -0
  14. package/classes/runnable.d.ts +6 -0
  15. package/classes/runnable.js +22 -1
  16. package/classes/sb-error.js +0 -1
  17. package/classes/stack-executor.js +0 -1
  18. package/constants.d.ts +1 -1
  19. package/constants.js +1 -2
  20. package/decorators/app-events.decorator.d.ts +5 -0
  21. package/decorators/{processor-events.decorator.js → app-events.decorator.js} +0 -1
  22. package/decorators/app.decorator.d.ts +29 -0
  23. package/decorators/{processor.decorator.js → app.decorator.js} +24 -19
  24. package/decorators/component.decorator.js +13 -6
  25. package/decorators/decorator-helpers.js +0 -1
  26. package/decorators/define-variable.decorator.d.ts +6 -1
  27. package/decorators/define-variable.decorator.js +5 -2
  28. package/decorators/log-channel.decorator.d.ts +97 -0
  29. package/decorators/log-channel.decorator.js +33 -0
  30. package/decorators/use-component.decorator.d.ts +2 -2
  31. package/decorators/use-component.decorator.js +1 -2
  32. package/decorators/use-variables.decorator.d.ts +2 -2
  33. package/decorators/use-variables.decorator.js +0 -1
  34. package/host-link/host-identity.d.ts +53 -0
  35. package/host-link/host-identity.js +139 -0
  36. package/host-link/host-link.d.ts +43 -0
  37. package/host-link/host-link.js +53 -0
  38. package/host-link/host-packages.d.ts +25 -0
  39. package/host-link/host-packages.js +9 -0
  40. package/host-link/host-workers.d.ts +75 -0
  41. package/host-link/host-workers.js +28 -0
  42. package/host-link/multiplexer.d.ts +115 -0
  43. package/host-link/multiplexer.js +288 -0
  44. package/host-link/sealed-box.d.ts +21 -0
  45. package/host-link/sealed-box.js +103 -0
  46. package/index.d.ts +16 -3
  47. package/index.js +16 -4
  48. package/interfaces/index.js +0 -1
  49. package/interfaces/logger.interface.js +0 -1
  50. package/models/enums/enum-source.enum.d.ts +11 -0
  51. package/models/enums/enum-source.enum.js +21 -0
  52. package/models/enums/log-channel-kind.d.ts +7 -0
  53. package/models/enums/log-channel-kind.js +13 -0
  54. package/models/enums/log-level.js +0 -1
  55. package/models/enums/service-status.d.ts +5 -1
  56. package/models/enums/service-status.js +4 -1
  57. package/models/enums/variable-format.enum.js +0 -1
  58. package/models/enums/variable-type.enum.js +0 -1
  59. package/models/enums/worker-permission.enum.d.ts +16 -0
  60. package/models/enums/worker-permission.enum.js +27 -0
  61. package/models/index.d.ts +6 -1
  62. package/models/index.js +6 -2
  63. package/models/metadata/app-metadata.d.ts +6 -0
  64. package/models/metadata/{processor-metadata.js → app-metadata.js} +6 -7
  65. package/models/metadata/component-metadata.js +0 -1
  66. package/models/metadata/element-component-metadata.d.ts +2 -0
  67. package/models/metadata/element-component-metadata.js +10 -3
  68. package/models/metadata/element-metadata.d.ts +8 -0
  69. package/models/metadata/element-metadata.js +40 -1
  70. package/models/metadata/log-channel-metadata.d.ts +23 -0
  71. package/models/metadata/log-channel-metadata.js +72 -0
  72. package/models/metadata/package-metadata.js +0 -1
  73. package/models/metadata/plugin-metadata.d.ts +15 -0
  74. package/models/metadata/plugin-metadata.js +65 -0
  75. package/models/metadata/variable-metadata.d.ts +3 -0
  76. package/models/metadata/variable-metadata.js +15 -2
  77. package/models/profile/log-options.d.ts +17 -0
  78. package/models/profile/log-options.js +58 -2
  79. package/models/profile/profile-component.js +0 -1
  80. package/models/profile/profile.d.ts +2 -2
  81. package/models/profile/profile.js +9 -10
  82. package/models-document.js +0 -1
  83. package/package.json +6 -2
  84. package/registry/docs-sidebar.d.ts +59 -0
  85. package/registry/docs-sidebar.js +169 -0
  86. package/registry/extension-package.d.ts +40 -13
  87. package/registry/extension-package.js +59 -19
  88. package/registry/extension-registry.d.ts +16 -16
  89. package/registry/extension-registry.js +59 -45
  90. package/registry/module-catalog.d.ts +31 -0
  91. package/registry/module-catalog.js +88 -0
  92. package/registry/package-docs.d.ts +98 -0
  93. package/registry/package-docs.js +159 -0
  94. package/registry/package-manifest.d.ts +54 -3
  95. package/registry/package-manifest.js +59 -2
  96. package/utils/decode-profile.d.ts +18 -2
  97. package/utils/decode-profile.js +65 -10
  98. package/utils/encrypt-helpers.d.ts +7 -0
  99. package/utils/encrypt-helpers.js +12 -6
  100. package/utils/locate-package-json.js +0 -1
  101. package/utils/materialize-metadata.d.ts +3 -3
  102. package/utils/materialize-metadata.js +16 -13
  103. package/utils/normalize-metadata.d.ts +23 -4
  104. package/utils/normalize-metadata.js +52 -7
  105. package/utils/registry-names.js +0 -1
  106. package/utils/resolve-promises.js +0 -1
  107. package/utils/type-guards.d.ts +2 -2
  108. package/utils/type-guards.js +4 -5
  109. package/utils/uri-to-id.js +0 -1
  110. package/utils/worker-permissions.d.ts +25 -0
  111. package/utils/worker-permissions.js +59 -0
  112. package/classes/base-element.js.map +0 -1
  113. package/classes/component-base.js.map +0 -1
  114. package/classes/console-logger.js.map +0 -1
  115. package/classes/frame-stream.js.map +0 -1
  116. package/classes/processor-base.js +0 -11
  117. package/classes/processor-base.js.map +0 -1
  118. package/classes/runnable.js.map +0 -1
  119. package/classes/sb-error.js.map +0 -1
  120. package/classes/stack-executor.js.map +0 -1
  121. package/constants.js.map +0 -1
  122. package/decorators/component.decorator.js.map +0 -1
  123. package/decorators/decorator-helpers.js.map +0 -1
  124. package/decorators/define-variable.decorator.js.map +0 -1
  125. package/decorators/processor-events.decorator.d.ts +0 -5
  126. package/decorators/processor-events.decorator.js.map +0 -1
  127. package/decorators/processor.decorator.d.ts +0 -29
  128. package/decorators/processor.decorator.js.map +0 -1
  129. package/decorators/use-component.decorator.js.map +0 -1
  130. package/decorators/use-variables.decorator.js.map +0 -1
  131. package/index.js.map +0 -1
  132. package/interfaces/index.js.map +0 -1
  133. package/interfaces/logger.interface.js.map +0 -1
  134. package/models/enums/log-level.js.map +0 -1
  135. package/models/enums/service-status.js.map +0 -1
  136. package/models/enums/variable-format.enum.js.map +0 -1
  137. package/models/enums/variable-type.enum.js.map +0 -1
  138. package/models/index.js.map +0 -1
  139. package/models/metadata/component-metadata.js.map +0 -1
  140. package/models/metadata/element-component-metadata.js.map +0 -1
  141. package/models/metadata/element-metadata.js.map +0 -1
  142. package/models/metadata/package-metadata.js.map +0 -1
  143. package/models/metadata/processor-metadata.d.ts +0 -6
  144. package/models/metadata/processor-metadata.js.map +0 -1
  145. package/models/metadata/variable-metadata.js.map +0 -1
  146. package/models/profile/log-options.js.map +0 -1
  147. package/models/profile/profile-component.js.map +0 -1
  148. package/models/profile/profile.js.map +0 -1
  149. package/models-document.js.map +0 -1
  150. package/processor-factory.d.ts +0 -26
  151. package/processor-factory.js.map +0 -1
  152. package/registry/extension-package.js.map +0 -1
  153. package/registry/extension-registry.js.map +0 -1
  154. package/registry/package-manifest.js.map +0 -1
  155. package/utils/decode-profile.js.map +0 -1
  156. package/utils/encrypt-helpers.js.map +0 -1
  157. package/utils/locate-package-json.js.map +0 -1
  158. package/utils/materialize-metadata.js.map +0 -1
  159. package/utils/normalize-metadata.js.map +0 -1
  160. package/utils/registry-names.js.map +0 -1
  161. package/utils/resolve-promises.js.map +0 -1
  162. package/utils/type-guards.js.map +0 -1
  163. 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
- * The `syncbridge` field of an extension package's `package.json`.
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
- components?: string[];
10
- processors?: string[];
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
- export {};
2
- //# sourceMappingURL=package-manifest.js.map
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 { ProcessorMetadata, Profile } from '../models/index.js';
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: ProcessorMetadata;
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
+ };
@@ -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 { ElementComponentMetadata, ProcessorMetadata, Profile, ProfileComponent, VariableMetadataRecord, VariableType, } from '../models/index.js';
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
- processorUri: profile.processorUri,
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
- * @protected
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
- const oldValues = profile.values;
146
- profile.values = {};
147
- const process = (variables, target, oldVals) => {
148
- for (const [k, defVariable] of Object.entries(variables)) {
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(metadata.variables, profile.values, oldValues);
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>;
@@ -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('sbscrt::')) {
6
- input = decryptText(input, secretKey);
11
+ if (input.startsWith(SECRET_PREFIX)) {
12
+ input = decryptText(input.substring(SECRET_PREFIX.length), secretKey);
7
13
  }
8
- return 'sbscrt::' + encryptText(input, secretKey);
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('sbscrt::')) {
14
- return decryptText(input.substring(6), secretKey);
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
@@ -22,4 +22,3 @@ export function resolvePackageJson(directory) {
22
22
  const content = fs.readFileSync(path.resolve(pkg, 'package.json'), 'utf-8');
23
23
  return JSON.parse(content);
24
24
  }
25
- //# sourceMappingURL=locate-package-json.js.map
@@ -1,12 +1,12 @@
1
1
  import { StackExecutor } from '../classes/stack-executor.js';
2
- import { ProcessorMetadata, Profile } from '../models/index.js';
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
- }): ProcessorMetadata;
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: ProcessorMetadata;
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, ProcessorMetadata, Profile, ProfileComponent, VariableMetadata, VariableMetadataRecord, VariableType, } from '../models/index.js';
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 processorRec = ExtensionRegistry.getProcessor(profile.processorUri, profile.processorVersion);
32
+ const appRec = ExtensionRegistry.getApp(profile.appUri, profile.appVersion);
33
33
  const metadata = omitUndefined(clone({
34
- classType: processorRec.metadata.classType,
35
- className: processorRec.metadata.className,
36
- version: processorRec.version,
37
- displayName: processorRec.metadata.displayName,
38
- description: processorRec.metadata.description,
39
- iconUrl: processorRec.metadata.iconUrl,
40
- tags: processorRec.metadata.tags,
41
- variables: processorRec.metadata.variables,
42
- components: processorRec.metadata.components,
43
- ...processorRec.metadata,
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, 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;
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 { ComponentMetadata, ElementComponentMetadataRecord, ProcessorMetadata, VariableMetadataRecord, } from '../models/index.js';
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 normalizeProcessorMetadata(metadata) {
8
- const { metadata: out, issues } = await normalizeProcessorMetadataSilent(metadata);
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 normalizeProcessorMetadataSilent(metadata) {
26
+ export async function normalizeAppMetadataSilent(metadata) {
25
27
  const decoder = await getProcMetadataTypeDecoder();
26
28
  let cloned = deepClone({
27
- classType: 'processor',
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(ProcessorMetadata);
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
@@ -106,4 +106,3 @@ export function parseSbSpecifier(specifier) {
106
106
  assertRegistryName(m[1]);
107
107
  return { name: m[1], subpath: m[2] ? '.' + m[2] : '.' };
108
108
  }
109
- //# sourceMappingURL=registry-names.js.map
@@ -8,4 +8,3 @@ export async function resolvePromisesDeep(obj) {
8
8
  }
9
9
  return obj;
10
10
  }
11
- //# sourceMappingURL=resolve-promises.js.map
@@ -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 isProcessorBase(proto: any): proto is ProcessorBase;
5
+ export declare function isAppBase(proto: any): proto is AppBase;
6
6
  export declare function isComponentBase(proto: any): proto is ComponentBase;
@@ -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 PROCESSOR_BASE_TOKEN = Symbol.for(ProcessorBase.name);
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 isProcessorBase(proto) {
11
- return !!proto[PROCESSOR_BASE_TOKEN];
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
@@ -5,4 +5,3 @@ export function uriToId(uri) {
5
5
  .replace(/\W/g, '_')
6
6
  .toLowerCase();
7
7
  }
8
- //# sourceMappingURL=uri-to-id.js.map
@@ -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;