@syncbridge/common 0.9.6 → 0.10.0

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.
@@ -0,0 +1,13 @@
1
+ import { ILogger } from '../interfaces/index.js';
2
+ export declare class ConsoleLogger implements ILogger {
3
+ level: string;
4
+ critical(...args: any[]): ILogger;
5
+ debug(...args: any[]): ILogger;
6
+ error(...args: any[]): ILogger;
7
+ fatal(...args: any[]): ILogger;
8
+ info(...args: any[]): ILogger;
9
+ trace(...args: any[]): ILogger;
10
+ warn(...args: any[]): ILogger;
11
+ child(): ILogger;
12
+ close(): void | Promise<void>;
13
+ }
@@ -0,0 +1,37 @@
1
+ export class ConsoleLogger {
2
+ level = 'info';
3
+ critical(...args) {
4
+ console.warn(...args);
5
+ return this;
6
+ }
7
+ debug(...args) {
8
+ console.debug(...args);
9
+ return this;
10
+ }
11
+ error(...args) {
12
+ console.error(...args);
13
+ return this;
14
+ }
15
+ fatal(...args) {
16
+ console.error(...args);
17
+ return this;
18
+ }
19
+ info(...args) {
20
+ console.info(...args);
21
+ return this;
22
+ }
23
+ trace(...args) {
24
+ console.trace(...args);
25
+ return this;
26
+ }
27
+ warn(...args) {
28
+ console.warn(...args);
29
+ return this;
30
+ }
31
+ child() {
32
+ return this;
33
+ }
34
+ close() {
35
+ return undefined;
36
+ }
37
+ }
@@ -52,7 +52,7 @@ export class Runnable extends AsyncEventEmitter {
52
52
  await this._init().catch(e => {
53
53
  const err = e instanceof SbError ? e : new SbError(e);
54
54
  err.code = 'INIT_FAILED';
55
- err.message = `Initialization failed doe to: ${err.message}`;
55
+ err.message = `Initialization failed: ${err.message}`;
56
56
  this.setStatus(ServiceStatus.invalid, err.message);
57
57
  this.onError(err);
58
58
  throw err;
@@ -1,11 +1,13 @@
1
1
  import { ErrorIssue } from '@opra/common';
2
+ type NotPromise<T> = T extends Promise<any> ? never : T;
2
3
  export declare class StackExecutor {
3
4
  stack: string[];
4
5
  issues: StackExecutor.Issue[];
5
6
  executeAsync(stack: string, fn: () => Promise<any>): Promise<void>;
6
- execute(stack: string, fn: () => any): void;
7
+ execute<T>(stack: string, fn: () => NotPromise<T>): void;
7
8
  handleError(e: any): void;
8
9
  }
9
10
  export declare namespace StackExecutor {
10
11
  type Issue = ErrorIssue;
11
12
  }
13
+ export {};
package/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- export const version = '0.9.6';
1
+ export const version = '0.10.0';
2
2
  export const CLASS_METADATA = Symbol.for('CLASS_METADATA');
3
3
  export const CLASS_TYPE = Symbol.for('CLASS_TYPE');
4
4
  export const VARIABLE_CONTAINER = Symbol.for('VARIABLE_CONTAINER');
@@ -1,9 +1,11 @@
1
1
  import 'reflect-metadata';
2
+ import { StrictOmit } from 'ts-gems';
2
3
  import { ComponentBase } from '../classes/component-base.js';
3
4
  import { ProcessorBase } from '../classes/processor-base.js';
4
5
  import { ElementComponentMetadata } from '../models/index.js';
5
6
  export declare function UseComponent<T extends ProcessorBase | ComponentBase>(options?: UseComponent.Options): (target: T, propertyKey: string | symbol) => void;
6
7
  export declare namespace UseComponent {
7
- interface Options extends Partial<ElementComponentMetadata> {
8
+ interface Options extends Partial<StrictOmit<ElementComponentMetadata, 'classUri' | 'interfaceUri'>> {
9
+ uri?: string;
8
10
  }
9
11
  }
@@ -1,4 +1,5 @@
1
1
  import 'reflect-metadata';
2
+ import { omit } from '@jsopen/objects';
2
3
  import { CLASS_METADATA } from '../constants.js';
3
4
  import { defineOwnMetadata } from './decorator-helpers.js';
4
5
  export function UseComponent(options = {}) {
@@ -6,16 +7,18 @@ export function UseComponent(options = {}) {
6
7
  /** c8 ignore next */
7
8
  if (typeof propertyKey !== 'string')
8
9
  throw new TypeError('Property key must be a string');
9
- if (!options.uri) {
10
+ let uri = options.uri;
11
+ if (!uri) {
10
12
  const designType = Reflect.getMetadata('design:type', target, propertyKey);
11
13
  if (typeof designType === 'function' && designType.uri) {
12
- options.uri = designType.uri;
14
+ uri = designType.uri;
13
15
  }
14
16
  }
15
17
  const metadata = defineOwnMetadata(target.constructor, CLASS_METADATA);
16
18
  metadata.components = metadata.components || {};
17
19
  metadata.components[propertyKey] = {
18
- ...options,
20
+ interfaceUri: uri,
21
+ ...omit(options, ['classUri', 'interfaceUri']),
19
22
  propertyKey,
20
23
  };
21
24
  };
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './classes/base-element.js';
2
2
  export * from './classes/component-base.js';
3
+ export * from './classes/console-logger.js';
3
4
  export * from './classes/frame-stream.js';
4
5
  export * from './classes/processor-base.js';
5
6
  export * from './classes/runnable.js';
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './classes/base-element.js';
2
2
  export * from './classes/component-base.js';
3
+ export * from './classes/console-logger.js';
3
4
  export * from './classes/frame-stream.js';
4
5
  export * from './classes/processor-base.js';
5
6
  export * from './classes/runnable.js';
@@ -10,8 +10,8 @@ export declare class ElementComponentMetadataRecord {
10
10
  */
11
11
  export declare class ElementComponentMetadata {
12
12
  propertyKey?: string;
13
- abstract?: boolean;
14
- uri: string;
13
+ interfaceUri: string;
14
+ classUri?: string;
15
15
  description?: string;
16
16
  required?: boolean;
17
17
  variables?: VariableMetadataRecord;
@@ -21,20 +21,21 @@ let ElementComponentMetadata = class ElementComponentMetadata {
21
21
  };
22
22
  __decorate([
23
23
  ApiField({
24
- label: 'Abstract',
25
- description: 'Determines if the component uri is set in profile or it not. If set true an explicit uri is required.',
26
- examples: ['@syncbridge/net:TcpClient', '@syncbridge/sqb:SqbClient'],
24
+ label: 'Class URI',
25
+ description: 'The interface URI that the assigned class should implement.',
26
+ examples: ['@syncbridge/builtin:IoClient'],
27
+ required: true,
27
28
  }),
28
- __metadata("design:type", Boolean)
29
- ], ElementComponentMetadata.prototype, "abstract", void 0);
29
+ __metadata("design:type", String)
30
+ ], ElementComponentMetadata.prototype, "interfaceUri", void 0);
30
31
  __decorate([
31
32
  ApiField({
32
- label: 'Class URI',
33
- description: 'URI of the class',
33
+ label: 'Interface URI',
34
+ description: 'The required in URI for the class to be assigned.',
34
35
  examples: ['@syncbridge/net:TcpClient', '@syncbridge/sqb:SqbClient'],
35
36
  }),
36
37
  __metadata("design:type", String)
37
- ], ElementComponentMetadata.prototype, "uri", void 0);
38
+ ], ElementComponentMetadata.prototype, "classUri", void 0);
38
39
  __decorate([
39
40
  ApiField({
40
41
  label: 'Description',
@@ -2,7 +2,7 @@ import { LogOptions } from './log-options.js';
2
2
  /**
3
3
  * WorkerComponentRecord
4
4
  */
5
- export declare class WorkerComponentRecord {
5
+ export declare class ProfileComponentRecord {
6
6
  [key: string]: ProfileComponent;
7
7
  }
8
8
  /**
@@ -18,7 +18,7 @@ export declare class ProfileComponentSettings {
18
18
  export declare class ProfileComponent {
19
19
  uri: string;
20
20
  values?: Record<string, any>;
21
- components?: WorkerComponentRecord;
21
+ components?: ProfileComponentRecord;
22
22
  settings?: ProfileComponentSettings;
23
23
  disabled?: boolean;
24
24
  }
@@ -4,15 +4,15 @@ import { LogOptions } from './log-options.js';
4
4
  /**
5
5
  * WorkerComponentRecord
6
6
  */
7
- let WorkerComponentRecord = class WorkerComponentRecord {
7
+ let ProfileComponentRecord = class ProfileComponentRecord {
8
8
  };
9
- WorkerComponentRecord = __decorate([
9
+ ProfileComponentRecord = __decorate([
10
10
  ComplexType({
11
11
  description: 'Container for profile components',
12
12
  additionalFields: () => ProfileComponent,
13
13
  })
14
- ], WorkerComponentRecord);
15
- export { WorkerComponentRecord };
14
+ ], ProfileComponentRecord);
15
+ export { ProfileComponentRecord };
16
16
  /**
17
17
  * ProfileComponentSettings
18
18
  */
@@ -60,7 +60,7 @@ __decorate([
60
60
  label: 'Components',
61
61
  description: 'Sub components',
62
62
  }),
63
- __metadata("design:type", WorkerComponentRecord)
63
+ __metadata("design:type", ProfileComponentRecord)
64
64
  ], ProfileComponent.prototype, "components", void 0);
65
65
  __decorate([
66
66
  ApiField({
@@ -1,5 +1,5 @@
1
1
  import { ProfileLogOptions } from './log-options.js';
2
- import { WorkerComponentRecord } from './profile-component.js';
2
+ import { ProfileComponentRecord } from './profile-component.js';
3
3
  /**
4
4
  * ProfileSettings
5
5
  */
@@ -21,6 +21,6 @@ export declare class Profile {
21
21
  description?: string;
22
22
  iconUrl?: string;
23
23
  values?: Record<string, any>;
24
- components?: WorkerComponentRecord;
24
+ components?: ProfileComponentRecord;
25
25
  settings?: ProfileSettings;
26
26
  }
@@ -1,7 +1,7 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import { ApiField, ComplexType } from '@opra/common';
3
3
  import { ProfileLogOptions } from './log-options.js';
4
- import { WorkerComponentRecord } from './profile-component.js';
4
+ import { ProfileComponentRecord } from './profile-component.js';
5
5
  /**
6
6
  * ProfileSettings
7
7
  */
@@ -106,7 +106,7 @@ __decorate([
106
106
  label: 'Components',
107
107
  description: 'Components of the processor',
108
108
  }),
109
- __metadata("design:type", WorkerComponentRecord)
109
+ __metadata("design:type", ProfileComponentRecord)
110
110
  ], Profile.prototype, "components", void 0);
111
111
  __decorate([
112
112
  ApiField({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncbridge/common",
3
- "version": "0.9.6",
3
+ "version": "0.10.0",
4
4
  "description": "SyncBridge Common utilities",
5
5
  "author": "Panates Inc",
6
6
  "license": "MIT",
@@ -82,48 +82,49 @@ export var ProcessorFactory;
82
82
  ProcessorFactory.updateProcessor = updateProcessor;
83
83
  async function _configureProcessor(ctx) {
84
84
  const { processor, profile } = ctx;
85
+ const newMetadata = materializeMetadata(profile);
85
86
  const cmpCtx = {
86
87
  ...ctx,
87
88
  owner: processor,
88
89
  curPath: '',
89
- newMetadata: materializeMetadata(profile),
90
- newProfile: profile,
91
- oldMetadata: processor[ProcessorFactory.METADATA_KEY],
92
- oldProfile: processor[ProcessorFactory.PROFILE_KEY],
90
+ newMetadataComponents: newMetadata.components,
91
+ newProfileComponents: profile.components,
92
+ oldMetadataComponents: processor[ProcessorFactory.METADATA_KEY]?.components,
93
+ oldProfileComponents: processor[ProcessorFactory.PROFILE_KEY]?.components,
93
94
  };
94
95
  _validateComponents(cmpCtx);
95
96
  await _configureComponents(cmpCtx);
96
- processor[ProcessorFactory.METADATA_KEY] = cmpCtx.newMetadata;
97
+ processor[ProcessorFactory.METADATA_KEY] = newMetadata;
97
98
  processor[ProcessorFactory.PROFILE_KEY] = profile;
98
99
  }
99
100
  function _validateComponents(ctx) {
100
- const { newMetadata, newProfile, oldMetadata, oldProfile, curPath, owner, stackExecutor, processor, } = ctx;
101
- if (!newMetadata.components)
101
+ const { newMetadataComponents, newProfileComponents, oldMetadataComponents, oldProfileComponents, curPath, owner, stackExecutor, processor, } = ctx;
102
+ if (!newMetadataComponents)
102
103
  return;
103
104
  // Stack: components
104
105
  stackExecutor.execute('components', () => {
105
- for (const [key, childMetadata] of Object.entries(newMetadata.components)) {
106
+ for (const [key, newChildMetadata] of Object.entries(newMetadataComponents)) {
106
107
  // Stack: components/componentName
107
108
  stackExecutor.execute(key, () => {
108
- const oldChildMetadata = oldMetadata?.components?.[key];
109
- const oldChildProfile = oldProfile?.components?.[key];
110
- const childProfile = newProfile.components[key];
109
+ const oldChildMetadata = oldMetadataComponents?.[key];
110
+ const oldChildProfile = oldProfileComponents?.[key];
111
+ const newChildProfile = newProfileComponents[key];
111
112
  const componentPath = curPath ? curPath + '/' + key : key;
112
113
  const componentInstance = owner.components?.[key];
113
114
  if (processor.stopped &&
114
- oldMetadata?.uri &&
115
- oldMetadata?.uri !== newMetadata.uri)
115
+ oldChildProfile?.uri &&
116
+ oldChildProfile?.uri !== newChildProfile.uri)
116
117
  throw new SbError('Cannot change component class while processor running. You should stop it first.');
117
118
  /** Validate sub-components */
118
- if (childMetadata.components && componentInstance) {
119
+ if (newChildMetadata.components && componentInstance) {
119
120
  _validateComponents({
120
121
  ...ctx,
121
122
  owner: componentInstance,
122
123
  curPath: componentPath,
123
- newMetadata: childMetadata,
124
- newProfile: childProfile,
125
- oldMetadata: oldChildMetadata,
126
- oldProfile: oldChildProfile,
124
+ newMetadataComponents: newChildMetadata.components,
125
+ newProfileComponents: newChildProfile.components,
126
+ oldMetadataComponents: oldChildMetadata?.components,
127
+ oldProfileComponents: oldChildProfile?.components,
127
128
  });
128
129
  }
129
130
  });
@@ -131,91 +132,90 @@ export var ProcessorFactory;
131
132
  });
132
133
  }
133
134
  async function _configureComponents(ctx) {
134
- const { newMetadata, newProfile, stackExecutor } = ctx;
135
- if (!newMetadata.components)
135
+ const { newMetadataComponents, newProfileComponents, oldMetadataComponents, oldProfileComponents, curPath, owner, stackExecutor, processor, } = ctx;
136
+ if (!newMetadataComponents)
136
137
  return;
138
+ owner.components = owner.components || {};
137
139
  // Stack: components
138
140
  await stackExecutor.executeAsync('components', async () => {
139
- for (const [key, childMetadata] of Object.entries(newMetadata.components)) {
141
+ for (const [key, newChildMetadata] of Object.entries(newMetadataComponents)) {
140
142
  // Stack: components/componentName
141
143
  await stackExecutor.executeAsync(key, async () => {
142
- if (!newProfile.components?.[key]?.disabled)
143
- await _configureComponent(ctx, key, childMetadata);
144
- });
145
- }
146
- });
147
- }
148
- async function _configureComponent(ctx, key, childMetadata) {
149
- const { newProfile, oldMetadata, oldProfile, curPath, owner, processor } = ctx;
150
- const childProfile = newProfile.components[key];
151
- if (!childProfile?.uri)
152
- return;
153
- const oldChildMetadata = oldMetadata?.components?.[key];
154
- const oldChildProfile = oldProfile?.components?.[key];
155
- const componentPath = curPath ? curPath + '/' + key : key;
156
- let componentInstance = owner.components?.[key];
157
- /** Create the component only if the owner stopped */ // todo implement hotplug components
158
- if (owner.stopped) {
159
- const compReg = ExtensionRegistry.getComponent(childMetadata.uri);
160
- /** Create the component instance */
161
- const compClass = await compReg.getClass();
162
- componentInstance = new compClass({
163
- processor: processor,
164
- parent: owner,
165
- name: key,
166
- path: componentPath,
167
- values: childProfile.values || {},
168
- });
169
- owner.components = owner.components || {};
170
- owner.components[key] = componentInstance;
171
- if (childMetadata.propertyKey)
172
- owner[childMetadata.propertyKey] = componentInstance;
173
- }
174
- else {
175
- componentInstance.values = {};
176
- const patchValues = (target, valPath, newValues, newVariables, oldValues, oldVariables) => {
177
- if (oldValues)
178
- Object.assign(target, oldValues);
179
- const updatedValues = ctx.valueUpdates.get(componentInstance) || [];
180
- ctx.valueUpdates.set(componentInstance, updatedValues);
181
- if (newVariables) {
182
- for (const [varKey, varMeta] of Object.entries(newVariables)) {
183
- const keyPath = valPath ? valPath + '.' + varKey : varKey;
184
- /** Update only hotplug variables */
185
- if (varMeta?.hotPlug !== true)
186
- continue;
187
- if (varMeta.type === 'nested') {
188
- target[varKey] = {};
189
- patchValues(target[varKey], keyPath, newValues[varKey], newVariables[varKey]?.variables || {}, oldValues?.[varKey], oldVariables?.[varKey]?.variables);
190
- continue;
144
+ if (newProfileComponents?.[key]?.disabled)
145
+ return;
146
+ // Stack: components/componentName
147
+ await stackExecutor.executeAsync(key, async () => {
148
+ const oldChildMetadata = oldMetadataComponents?.[key];
149
+ const oldChildProfile = oldProfileComponents?.[key];
150
+ const newChildProfile = newProfileComponents[key];
151
+ const componentPath = curPath ? curPath + '/' + key : key;
152
+ let componentInstance = owner.components[key];
153
+ /** Create the component only if the owner stopped */ // todo implement hotplug components
154
+ if (owner.stopped) {
155
+ const compReg = ExtensionRegistry.getComponent(newChildMetadata.classUri);
156
+ /** Create the component instance */
157
+ const compClass = await compReg.getClass();
158
+ componentInstance = new compClass({
159
+ processor: processor,
160
+ parent: owner,
161
+ name: key,
162
+ path: componentPath,
163
+ values: newChildProfile.values || {},
164
+ });
165
+ owner.components[key] = componentInstance;
166
+ if (newChildMetadata.propertyKey)
167
+ owner[newChildMetadata.propertyKey] = componentInstance;
191
168
  }
192
- if (!equal(target[varKey], newValues[varKey])) {
193
- updatedValues.push(keyPath);
194
- target[varKey] = newValues[varKey];
169
+ else {
170
+ componentInstance.values = {};
171
+ const patchValues = (target, valPath, newValues, newVariables, oldValues, oldVariables) => {
172
+ if (oldValues)
173
+ Object.assign(target, oldValues);
174
+ const updatedValues = ctx.valueUpdates.get(componentInstance) || [];
175
+ ctx.valueUpdates.set(componentInstance, updatedValues);
176
+ if (newVariables) {
177
+ for (const [varKey, varMeta] of Object.entries(newVariables)) {
178
+ const keyPath = valPath ? valPath + '.' + varKey : varKey;
179
+ /** Update only hotplug variables */
180
+ if (varMeta?.hotPlug !== true)
181
+ continue;
182
+ if (varMeta.type === 'nested') {
183
+ target[varKey] = {};
184
+ patchValues(target[varKey], keyPath, newValues[varKey], newVariables[varKey]?.variables || {}, oldValues?.[varKey], oldVariables?.[varKey]?.variables);
185
+ continue;
186
+ }
187
+ if (!equal(target[varKey], newValues[varKey])) {
188
+ updatedValues.push(keyPath);
189
+ target[varKey] = newValues[varKey];
190
+ }
191
+ }
192
+ }
193
+ };
194
+ patchValues(componentInstance.values, '', newChildProfile.values || {}, newChildMetadata.variables || {}, oldChildProfile?.values, oldChildMetadata?.variables);
195
195
  }
196
- }
197
- }
198
- };
199
- patchValues(componentInstance.values, '', childProfile.values || {}, childMetadata.variables || {}, oldChildProfile?.values, oldChildMetadata?.variables);
200
- }
201
- /** Create the child logger */
202
- componentInstance.logger = owner.logger?.child({
203
- component: componentPath,
196
+ /** Create the child logger */
197
+ componentInstance.logger = owner.logger?.child({
198
+ component: componentPath,
199
+ });
200
+ if (newChildProfile.settings?.logs?.level) {
201
+ componentInstance.logger.level =
202
+ newChildProfile.settings?.logs?.level;
203
+ }
204
+ /** Initialize sub components */
205
+ if (newChildMetadata.components) {
206
+ await _configureComponents({
207
+ ...ctx,
208
+ owner: componentInstance,
209
+ curPath: componentPath,
210
+ newMetadataComponents: newChildMetadata.components,
211
+ newProfileComponents: newChildProfile.components,
212
+ oldMetadataComponents: oldChildMetadata?.components,
213
+ oldProfileComponents: oldChildProfile?.components,
214
+ });
215
+ }
216
+ });
217
+ });
218
+ }
204
219
  });
205
- if (childProfile.settings?.logs?.level) {
206
- componentInstance.logger.level = childProfile.settings?.logs?.level;
207
- }
208
- /** Initialize sub components */
209
- if (childMetadata.components) {
210
- await _configureComponents({
211
- ...ctx,
212
- owner: componentInstance,
213
- curPath: componentPath,
214
- newMetadata: childMetadata,
215
- newProfile: childProfile,
216
- oldMetadata: oldChildMetadata,
217
- oldProfile: oldChildProfile,
218
- });
219
- }
220
220
  }
221
221
  })(ProcessorFactory || (ProcessorFactory = {}));
@@ -68,8 +68,7 @@ function _materializeComponents(stackExecutor, srcMetadata, profile, returnUndef
68
68
  return;
69
69
  }
70
70
  materializedComponent = {
71
- abstract: true,
72
- uri: metadataComponent.uri,
71
+ interfaceUri: metadataComponent.interfaceUri,
73
72
  description: metadataComponent.description,
74
73
  required: metadataComponent.required,
75
74
  };
@@ -80,12 +79,15 @@ function _materializeComponents(stackExecutor, srcMetadata, profile, returnUndef
80
79
  if (!profileComponent.uri)
81
80
  throw new SbValidationError(`"uri" property required`);
82
81
  const reg = ExtensionRegistry.getComponent(profileComponent.uri);
83
- if (!(profileComponent.uri === metadataComponent.uri ||
84
- reg.metadata.interfaces?.includes(metadataComponent.uri)))
85
- throw new SbValidationError(`Selected component "${profileComponent.uri}" do not implement ${metadataComponent.uri}.`);
82
+ if (!(profileComponent.uri === metadataComponent.interfaceUri ||
83
+ reg.metadata.interfaces?.includes(metadataComponent.interfaceUri)))
84
+ throw new SbValidationError(`Selected component "${profileComponent.uri}" do not implement ${metadataComponent.interfaceUri}.`);
85
+ if (profileComponent.disabled && metadataComponent.required) {
86
+ throw new SbValidationError(`Component "${componentName}" is disabled but it is required.`);
87
+ }
86
88
  materializedComponent = {
87
- uri: profileComponent.uri,
88
- ...omit(metadataComponent, ['uri', 'variables']),
89
+ classUri: profileComponent.uri,
90
+ ...omit(metadataComponent, ['classUri', 'variables']),
89
91
  };
90
92
  materializedComponent.variables = merge({}, [reg.metadata.variables || {}, metadataComponent.variables || {}], { deep: 'full' });
91
93
  materializedComponent.variables = sortVariables(materializedComponent.variables);