@adaas/a-utils 0.1.40 → 0.2.2

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 (39) hide show
  1. package/dist/index.cjs +16 -16
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.mts +17 -24
  4. package/dist/index.d.ts +17 -24
  5. package/dist/index.mjs +16 -16
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +3 -2
  8. package/src/index.ts +1 -1
  9. package/src/lib/A-Channel/A-Channel.component.ts +6 -0
  10. package/src/lib/A-Channel/A-ChannelRequest.context.ts +7 -0
  11. package/src/lib/A-Command/A-Command.entity.ts +7 -1
  12. package/src/lib/A-Command/A-Command.error.ts +0 -1
  13. package/src/lib/A-Config/A-Config.container.ts +7 -0
  14. package/src/lib/A-Config/A-Config.context.ts +7 -0
  15. package/src/lib/A-Config/components/ConfigReader.component.ts +6 -0
  16. package/src/lib/A-Config/components/ENVConfigReader.component.ts +7 -0
  17. package/src/lib/A-Config/components/FileConfigReader.component.ts +8 -0
  18. package/src/lib/A-Execution/A-Execution.context.ts +7 -0
  19. package/src/lib/A-Logger/A-Logger.component.ts +30 -24
  20. package/src/lib/A-Manifest/A-Manifest.context.ts +6 -0
  21. package/src/lib/A-Memory/A-Memory.component.ts +7 -0
  22. package/src/lib/A-Memory/A-Memory.context.ts +6 -0
  23. package/src/lib/A-Operation/A-Operation.context.ts +8 -0
  24. package/src/lib/A-Polyfill/A-Polyfill.component.ts +9 -0
  25. package/src/lib/A-Route/A-Route.entity.ts +7 -0
  26. package/src/lib/A-Schedule/A-Schedule.component.ts +8 -1
  27. package/src/lib/A-Service/A-Service.container.ts +6 -0
  28. package/src/lib/A-Signal/A-Signal.constants.ts +0 -10
  29. package/src/lib/A-Signal/components/A-SignalBus.component.ts +120 -36
  30. package/src/lib/A-Signal/components/A-SignalBus.constants.ts +7 -0
  31. package/src/lib/A-Signal/components/A-SignalBus.error.ts +9 -0
  32. package/src/lib/A-Signal/context/A-SignalConfig.context.ts +6 -0
  33. package/src/lib/A-Signal/context/A-SignalState.context.ts +6 -0
  34. package/src/lib/A-Signal/entities/A-Signal.entity.ts +6 -12
  35. package/src/lib/A-Signal/entities/A-SignalVector.entity.ts +6 -10
  36. package/src/lib/A-StateMachine/A-StateMachine.component.ts +11 -0
  37. package/src/lib/A-StateMachine/A-StateMachineTransition.context.ts +11 -5
  38. package/tests/A-Signal.test.ts +9 -13
  39. /package/src/lib/{A-Command/A-CommandExecution.context.ts → A-Signal/components/A-SignalBus.types.ts} +0 -0
@@ -1,10 +1,12 @@
1
- import { A_Caller, A_Component, A_Context, A_Feature, A_Inject, A_Scope } from "@adaas/a-concept";
2
- import { A_SignalFeatures } from "../A-Signal.constants";
1
+ import { A_Caller, A_Component, A_Context, A_Dependency, A_Error, A_Feature, A_Inject, A_Scope } from "@adaas/a-concept";
3
2
  import { A_SignalState } from "../context/A-SignalState.context";
4
3
  import { A_SignalConfig } from "../context/A-SignalConfig.context";
5
4
  import { A_Config } from "../../A-Config/A-Config.context";
6
5
  import { A_Logger } from "../../A-Logger/A-Logger.component";
7
6
  import { A_Signal } from "../entities/A-Signal.entity";
7
+ import { A_Frame } from "@adaas/a-frame";
8
+ import { A_SignalBusFeatures } from "./A-SignalBus.constants";
9
+ import { A_SignalBusError } from "./A-SignalBus.error";
8
10
 
9
11
 
10
12
 
@@ -18,47 +20,90 @@ import { A_Signal } from "../entities/A-Signal.entity";
18
20
  *
19
21
  * The component itself is stateless and all methods uses only parameters (context) is provided with.
20
22
  */
23
+ @A_Frame.Component({
24
+ namespace: 'A-Utils',
25
+ name: 'A-SignalBus',
26
+ description: 'Signal bus component that manages the emission and state of signals within a given scope. It listens for emitted signals, updates their state, and forwards them to registered watchers. The bus ensures a consistent signal vector structure based on the defined configuration, facilitating signal management across multiple components.'
27
+ })
21
28
  export class A_SignalBus extends A_Component {
22
29
 
23
30
 
24
- /**
25
- * This methods extends A-Signal Emit feature to handle signal emission within the bus.
26
- *
27
- * It updates the signal state and emits the updated signal vector.
28
- *
29
- * @param signal
30
- * @param globalConfig
31
- * @param logger
32
- * @param state
33
- * @param config
34
- * @returns
35
- */
31
+ @A_Frame.Method({
32
+ description: 'Emit multiple signals through the signal bus.'
33
+ })
34
+ async next(...signals: A_Signal[]) {
35
+ const scope = new A_Scope({
36
+ name: `A_SignalBus-Next-Scope`,
37
+ entities: signals
38
+ })
39
+ .inherit(A_Context.scope(this));
40
+
41
+ try {
42
+ await this.call(A_SignalBusFeatures.onBeforeNext, scope);
43
+ await this.call(A_SignalBusFeatures.onNext, scope);
44
+
45
+ scope.destroy();
46
+
47
+ } catch (error) {
48
+
49
+ let wrappedError;
50
+
51
+ switch (true) {
52
+ case error instanceof A_SignalBusError:
53
+ wrappedError = error;
54
+ break;
55
+
56
+ case error instanceof A_Error && error.originalError instanceof A_SignalBusError:
57
+ wrappedError = error.originalError;
58
+ break;
59
+
60
+ default:
61
+ wrappedError = new A_SignalBusError({
62
+ title: A_SignalBusError.SignalProcessingError,
63
+ description: `An error occurred while processing the signal.`,
64
+ originalError: error
65
+ })
66
+ break;
67
+ }
68
+
69
+ scope.register(wrappedError);
70
+
71
+ await this.call(A_SignalBusFeatures.onError);
72
+
73
+ scope.destroy();
74
+ }
75
+ }
76
+
77
+
78
+ @A_Feature.Extend({
79
+ before: /.*/
80
+ })
81
+ protected async [A_SignalBusFeatures.onError](
82
+ @A_Inject(A_Error) error: A_Error,
83
+ @A_Inject(A_Logger) logger?: A_Logger,
84
+ ...args: any[]
85
+ ) {
86
+ logger?.error(error);
87
+ }
88
+
36
89
  @A_Feature.Extend({
37
- scope: [A_Signal]
90
+ scope: [A_SignalBus],
91
+ before: /.*/
38
92
  })
39
- async [A_SignalFeatures.Next](
40
- @A_Inject(A_Caller) signal: A_Signal,
93
+ async [A_SignalBusFeatures.onBeforeNext](
41
94
  @A_Inject(A_Scope) scope: A_Scope,
42
95
 
43
96
  @A_Inject(A_Config) globalConfig?: A_Config<['A_SIGNAL_VECTOR_STRUCTURE']>,
44
- @A_Inject(A_Logger) logger?: A_Logger,
45
97
  @A_Inject(A_SignalState) state?: A_SignalState,
98
+
99
+ @A_Inject(A_Logger) logger?: A_Logger,
46
100
  @A_Inject(A_SignalConfig) config?: A_SignalConfig,
47
101
  ) {
48
-
49
- /*
50
- 1) create a signal when it occurs via new A_Signal('somedata')
51
- 2) emit a signal when needed via signal.emit(scope)
52
- 3) the bus should listen for all emitted signals within the scope
53
- 4) when a signal is emitted, the bus should store a signal in some place (probably it's memory)
54
- */
55
-
56
102
  /**
57
103
  * We need a context where component is registered, to prevent any duplicate registrations
58
104
  */
59
105
  const componentContext = A_Context.scope(this);
60
106
 
61
-
62
107
  if (!config) {
63
108
  config = new A_SignalConfig({
64
109
  stringStructure: globalConfig?.get('A_SIGNAL_VECTOR_STRUCTURE') || undefined
@@ -74,22 +119,61 @@ export class A_SignalBus extends A_Component {
74
119
  state = new A_SignalState(config.structure);
75
120
  componentContext.register(state);
76
121
  }
122
+ }
123
+
124
+ /**
125
+ * This methods extends A-Signal Emit feature to handle signal emission within the bus.
126
+ *
127
+ * It updates the signal state and emits the updated signal vector.
128
+ *
129
+ * @param signal
130
+ * @param globalConfig
131
+ * @param logger
132
+ * @param state
133
+ * @param config
134
+ * @returns
135
+ */
136
+ @A_Feature.Extend({
137
+ scope: [A_SignalBus],
138
+ before: /.*/
139
+ })
140
+ async [A_SignalBusFeatures.onNext](
141
+ // @A_Dependency.All()
142
+ // @A_Inject(A_Signal) signal: A_Signal[],
143
+ @A_Inject(A_Scope) scope: A_Scope,
144
+
145
+ @A_Dependency.Required()
146
+ @A_Inject(A_SignalState) state: A_SignalState,
147
+
148
+ @A_Inject(A_Config) globalConfig?: A_Config<['A_SIGNAL_VECTOR_STRUCTURE']>,
149
+ @A_Inject(A_Logger) logger?: A_Logger,
150
+ @A_Inject(A_SignalConfig) config?: A_SignalConfig,
151
+ ) {
152
+ /*
153
+ 1) create a signal when it occurs via new A_Signal('somedata')
154
+ 2) emit a signal when needed via bus.next(signal)
155
+ 3) the bus should listen for all emitted signals within the scope
156
+ 4) when a signal is emitted, the bus should store a signal in some place (probably it's memory)
157
+ */
158
+ const signals = scope.resolveFlatAll<A_Signal>(A_Signal);
77
159
 
160
+ for (const signal of signals) {
78
161
 
79
- if (!state.has(signal))
80
- return;
162
+ if (!state.has(signal))
163
+ return;
81
164
 
165
+ // ------------------------------------------------------------------
166
+ // And finally if all checks are passed, we can update the state
167
+ // ------------------------------------------------------------------
82
168
 
83
- // ------------------------------------------------------------------
84
- // And finally if all checks are passed, we can update the state
85
- // ------------------------------------------------------------------
169
+ logger?.debug(`A_SignalBus: Updating state for signal '${signal.constructor.name}' with data:`, signal.data);
86
170
 
87
- logger?.debug(`A_SignalBus: Updating state for signal '${signal.constructor.name}' with data:`, signal.data);
171
+ state.set(signal);
88
172
 
89
- state.set(signal);
173
+ const vector = state.toVector();
90
174
 
91
- const vector = state.toVector();
175
+ scope.register(vector);
92
176
 
93
- await vector.next(scope);
177
+ }
94
178
  }
95
179
  }
@@ -0,0 +1,7 @@
1
+
2
+ export enum A_SignalBusFeatures {
3
+ onBeforeNext = '_A_SignalBusFeatures_onBeforeNext',
4
+ onNext = '_A_SignalBusFeatures_onNext',
5
+
6
+ onError = '_A_SignalBusFeatures_onError',
7
+ }
@@ -0,0 +1,9 @@
1
+ import { A_Error } from "@adaas/a-concept";
2
+
3
+
4
+
5
+ export class A_SignalBusError extends A_Error {
6
+
7
+
8
+ static readonly SignalProcessingError = 'Signal processing error';
9
+ }
@@ -1,6 +1,7 @@
1
1
  import { A_CommonHelper, A_Context, A_Fragment, A_TYPES__Component_Constructor, A_TYPES__Entity_Constructor } from "@adaas/a-concept";
2
2
  import { A_SignalConfig_Init } from "../A-Signal.types";
3
3
  import { A_Signal } from "../entities/A-Signal.entity";
4
+ import { A_Frame } from "@adaas/a-frame";
4
5
 
5
6
 
6
7
 
@@ -11,6 +12,11 @@ import { A_Signal } from "../entities/A-Signal.entity";
11
12
  * e.g. [A_RouterWatcher, A_ScopeWatcher, A_LoggerWatcher]
12
13
  * This structure then should be used for any further processing of signals within the scope.
13
14
  */
15
+ @A_Frame.Fragment({
16
+ namespace: 'A-Utils',
17
+ name: 'A-SignalConfig',
18
+ description: 'Signal configuration fragment that defines the structure and types of signals within a given scope. It allows specifying the expected signal constructors and their order, facilitating consistent signal management and processing across components that emit or listen to signals.'
19
+ })
14
20
  export class A_SignalConfig extends A_Fragment {
15
21
 
16
22
  protected _structure?: Array<A_TYPES__Entity_Constructor<A_Signal>>;
@@ -1,6 +1,7 @@
1
1
  import { A_Context, A_Fragment, A_TYPES__Component_Constructor } from "@adaas/a-concept";
2
2
  import { A_Signal } from "../entities/A-Signal.entity";
3
3
  import { A_SignalVector } from "../entities/A-SignalVector.entity";
4
+ import { A_Frame } from "@adaas/a-frame";
4
5
 
5
6
  /**
6
7
  * A_SignalState manages the latest state of all signals within a given scope.
@@ -15,6 +16,11 @@ import { A_SignalVector } from "../entities/A-SignalVector.entity";
15
16
  * - Signal instances and their emitted value types
16
17
  * - Vector structure and the data it contains
17
18
  */
19
+ @A_Frame.Fragment({
20
+ namespace: 'A-Utils',
21
+ name: 'A-SignalState',
22
+ description: 'Manages the latest state of all signals within a given scope, maintaining a mapping between signal constructors and their most recently emitted values.'
23
+ })
18
24
  export class A_SignalState<
19
25
  TSignalData extends Record<string, any> = Record<string, any>
20
26
  > extends A_Fragment {
@@ -1,6 +1,6 @@
1
1
  import { A_Entity, A_Scope } from "@adaas/a-concept";
2
2
  import { A_Signal_Init, A_Signal_Serialized } from "../A-Signal.types";
3
- import { A_SignalFeatures } from "../A-Signal.constants";
3
+ import { A_Frame } from "@adaas/a-frame";
4
4
 
5
5
  /**
6
6
  * A Signal Entity is an individual signal instance that carries data.
@@ -15,6 +15,11 @@ import { A_SignalFeatures } from "../A-Signal.constants";
15
15
  * Signals are typically used in scenarios where the current state is more important than individual events,
16
16
  * such as monitoring systems, real-time dashboards, or stateful applications.
17
17
  */
18
+ @A_Frame.Entity({
19
+ namespace: 'A-Utils',
20
+ name: 'A-Signal',
21
+ description: 'A Signal Entity represents an individual signal instance that carries data, used for managing state within an application context. Signals are designed to reflect the current state rather than individual events, making them suitable for scenarios where state monitoring and real-time updates are essential.'
22
+ })
18
23
  export class A_Signal<
19
24
  _TSignalDataType extends Record<string, any> = Record<string, any>
20
25
  > extends A_Entity<A_Signal_Init<_TSignalDataType>, A_Signal_Serialized<_TSignalDataType>> {
@@ -46,17 +51,6 @@ export class A_Signal<
46
51
  this.data = newEntity.data;
47
52
  }
48
53
 
49
- /**
50
- * Emits this signal within the provided scope.
51
- *
52
- * Scope is mandatory since signal itself should not be registered in the scope,
53
- * but should use particular scope context to use proper set of components
54
- *
55
- * @param scope
56
- */
57
- async next(scope: A_Scope) {
58
- await this.call(A_SignalFeatures.Next, scope);
59
- }
60
54
 
61
55
 
62
56
  toJSON(): A_Signal_Serialized<_TSignalDataType> {
@@ -1,7 +1,7 @@
1
1
  import { A_Entity, A_Scope, A_TYPES__Component_Constructor, A_TYPES__Entity_Constructor } from "@adaas/a-concept";
2
2
  import { A_SignalVector_Serialized, A_SignalVector_Init } from "../A-Signal.types";
3
3
  import { A_Signal } from "./A-Signal.entity";
4
- import { A_SignalVectorFeatures } from "../A-Signal.constants";
4
+ import { A_Frame } from "@adaas/a-frame";
5
5
 
6
6
 
7
7
  /**
@@ -14,6 +14,11 @@ import { A_SignalVectorFeatures } from "../A-Signal.constants";
14
14
  * @template TSignalsConstructors - Array of signal constructor types (e.g., [typeof MySignal, typeof CustomSignal])
15
15
  * @template TSignals - Array of signal instances derived from constructors
16
16
  */
17
+ @A_Frame.Entity({
18
+ namespace: 'A-Utils',
19
+ name: 'A-SignalVector',
20
+ description: 'A Signal Vector Entity represents a collection of signals structured in a specific way, allowing for batch processing and transmission of related signals as a unified state representation.'
21
+ })
17
22
  export class A_SignalVector<
18
23
  TSignals extends Array<A_Signal> = Array<A_Signal>,
19
24
  TSignalsConstructors extends Array<A_TYPES__Entity_Constructor<A_Signal>> = TSignals extends Array<infer U> ? U extends A_Signal ? A_TYPES__Entity_Constructor<U>[] : never : never
@@ -88,15 +93,6 @@ export class A_SignalVector<
88
93
  }
89
94
 
90
95
 
91
- /**
92
- * Emits the signal vector to the specified scope.
93
- *
94
- * @param scope
95
- */
96
- async next(scope: A_Scope): Promise<void> {
97
- return await this.call(A_SignalVectorFeatures.Next, scope);
98
- }
99
-
100
96
 
101
97
  /**
102
98
  * Checks if the vector contains a signal of the specified type.
@@ -2,6 +2,7 @@ import { A_Component, A_Context, A_Feature, A_FormatterHelper, A_Scope } from "@
2
2
  import { A_StateMachineError } from "./A-StateMachine.error";
3
3
  import { A_StateMachineFeatures } from "./A-StateMachine.constants";
4
4
  import { A_StateMachineTransition } from "./A-StateMachineTransition.context";
5
+ import { A_Frame } from "@adaas/a-frame";
5
6
 
6
7
  /**
7
8
  * A_StateMachine is a powerful state machine implementation that allows you to define and manage
@@ -29,6 +30,12 @@ import { A_StateMachineTransition } from "./A-StateMachineTransition.context";
29
30
  * }
30
31
  * ```
31
32
  */
33
+
34
+ @A_Frame.Namespace('A-Utils')
35
+ @A_Frame.Component({
36
+ name: 'A-StateMachine',
37
+ description: 'A powerful state machine component for managing complex state transitions.'
38
+ })
32
39
  export class A_StateMachine<
33
40
  T extends Record<string, any> = Record<string, any>
34
41
  > extends A_Component {
@@ -195,6 +202,10 @@ export class A_StateMachine<
195
202
  *
196
203
  * If any step fails, the onError hook is called and a wrapped error is thrown.
197
204
  */
205
+ @A_Frame.Method({
206
+ name: 'transition',
207
+ description: 'Executes a state transition from one state to another.'
208
+ })
198
209
  async transition(
199
210
  /**
200
211
  * The state to transition from
@@ -1,8 +1,13 @@
1
+ import { A_Frame } from "@adaas/a-frame";
1
2
  import { A_OperationContext } from "../A-Operation/A-Operation.context";
2
3
  import { A_StateMachineTransitionParams, A_StateMachineTransitionStorage } from "./A-StateMachine.types";
3
4
 
4
5
 
5
6
 
7
+ @A_Frame.Fragment({
8
+ name: 'A-StateMachineTransition',
9
+ description: 'Context for managing state machine transitions.'
10
+ })
6
11
  export class A_StateMachineTransition<
7
12
  _ParamsType = any,
8
13
  _ResultType = any
@@ -13,7 +18,6 @@ export class A_StateMachineTransition<
13
18
  A_StateMachineTransitionStorage<_ResultType, _ParamsType>
14
19
  > {
15
20
 
16
-
17
21
  constructor(
18
22
  params: A_StateMachineTransitionParams<_ParamsType>
19
23
  ) {
@@ -26,14 +30,16 @@ export class A_StateMachineTransition<
26
30
  this._meta.set('to', params.to);
27
31
  }
28
32
 
29
-
30
-
33
+ /**
34
+ * The state to transition from
35
+ */
31
36
  get from(): string {
32
37
  return this._meta.get('from')!;
33
38
  }
34
39
 
35
-
36
-
40
+ /**
41
+ * The state to transition to
42
+ */
37
43
  get to(): string {
38
44
  return this._meta.get('to')!;
39
45
  }
@@ -1,6 +1,6 @@
1
- import { A_Caller, A_Component, A_Concept, A_Container, A_Context, A_Feature, A_Inject, A_Scope } from "@adaas/a-concept";
2
- import { A_SignalVectorFeatures } from "@adaas/a-utils/lib/A-Signal/A-Signal.constants";
1
+ import { A_Component, A_Concept, A_Container, A_Context, A_Feature, A_Inject, A_Scope } from "@adaas/a-concept";
3
2
  import { A_SignalBus } from "@adaas/a-utils/lib/A-Signal/components/A-SignalBus.component";
3
+ import { A_SignalBusFeatures } from "@adaas/a-utils/lib/A-Signal/components/A-SignalBus.constants";
4
4
  import { A_SignalConfig } from "@adaas/a-utils/lib/A-Signal/context/A-SignalConfig.context";
5
5
  import { A_Signal } from "@adaas/a-utils/lib/A-Signal/entities/A-Signal.entity";
6
6
  import { A_SignalVector } from "@adaas/a-utils/lib/A-Signal/entities/A-SignalVector.entity";
@@ -71,23 +71,19 @@ describe('A-Signal tests', () => {
71
71
  class UserIntentionListener extends A_Component {
72
72
  @A_Concept.Start()
73
73
  async start(
74
- @A_Inject(A_Scope) scope: A_Scope,
75
74
  @A_Inject(A_SignalBus) bus: A_SignalBus
76
75
  ) {
77
-
78
-
79
- const signal = new A_Signal({
76
+ await bus.next(new A_Signal({
80
77
  data: {
81
78
  buttonId: 'submit-order'
82
79
  }
83
- })
84
- await signal.next(scope)
80
+ }))
85
81
  }
86
82
 
87
83
 
88
84
  @A_Feature.Extend()
89
- async [A_SignalVectorFeatures.Next](
90
- @A_Inject(A_Caller) vector: A_SignalVector
85
+ async [A_SignalBusFeatures.onNext](
86
+ @A_Inject(A_SignalVector) vector: A_SignalVector
91
87
  ) {
92
88
  result = vector;
93
89
  }
@@ -145,13 +141,13 @@ describe('A-Signal tests', () => {
145
141
  }
146
142
  })
147
143
 
148
- await signal.next(scope)
144
+ await bus.next(signal)
149
145
  }
150
146
 
151
147
 
152
148
  @A_Feature.Extend()
153
- async [A_SignalVectorFeatures.Next](
154
- @A_Inject(A_Caller) vector: A_SignalVector
149
+ async [A_SignalBusFeatures.onNext](
150
+ @A_Inject(A_SignalVector) vector: A_SignalVector
155
151
  ) {
156
152
  result = vector;
157
153
  }