@adaas/a-utils 0.1.17 → 0.1.19

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 (47) hide show
  1. package/dist/index.d.mts +964 -354
  2. package/dist/index.d.ts +964 -354
  3. package/dist/index.js +1426 -714
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1426 -714
  6. package/dist/index.mjs.map +1 -1
  7. package/examples/A-Channel-examples.ts +13 -11
  8. package/examples/A-Command-examples-2.ts +429 -0
  9. package/examples/A-Command-examples.ts +487 -202
  10. package/examples/A-StateMachine-examples.ts +609 -0
  11. package/package.json +3 -2
  12. package/src/index.ts +1 -2
  13. package/src/lib/A-Channel/A-Channel.component.ts +14 -74
  14. package/src/lib/A-Channel/A-Channel.error.ts +5 -5
  15. package/src/lib/A-Channel/A-Channel.types.ts +2 -10
  16. package/src/lib/A-Channel/A-ChannelRequest.context.ts +25 -74
  17. package/src/lib/A-Command/A-Command.constants.ts +78 -23
  18. package/src/lib/A-Command/A-Command.entity.ts +447 -119
  19. package/src/lib/A-Command/A-Command.error.ts +11 -0
  20. package/src/lib/A-Command/A-Command.types.ts +96 -20
  21. package/src/lib/A-Command/A-CommandExecution.context.ts +0 -0
  22. package/src/lib/A-Command/README.md +164 -68
  23. package/src/lib/A-Config/A-Config.container.ts +2 -2
  24. package/src/lib/A-Config/A-Config.context.ts +19 -5
  25. package/src/lib/A-Config/components/ConfigReader.component.ts +1 -1
  26. package/src/lib/A-Logger/A-Logger.component.ts +211 -35
  27. package/src/lib/A-Logger/A-Logger.constants.ts +50 -10
  28. package/src/lib/A-Logger/A-Logger.env.ts +17 -1
  29. package/src/lib/A-Memory/A-Memory.component.ts +440 -0
  30. package/src/lib/A-Memory/A-Memory.constants.ts +49 -0
  31. package/src/lib/A-Memory/A-Memory.context.ts +14 -118
  32. package/src/lib/A-Memory/A-Memory.error.ts +21 -0
  33. package/src/lib/A-Memory/A-Memory.types.ts +21 -0
  34. package/src/lib/A-Operation/A-Operation.context.ts +58 -0
  35. package/src/lib/A-Operation/A-Operation.types.ts +47 -0
  36. package/src/lib/A-StateMachine/A-StateMachine.component.ts +258 -0
  37. package/src/lib/A-StateMachine/A-StateMachine.constants.ts +18 -0
  38. package/src/lib/A-StateMachine/A-StateMachine.error.ts +10 -0
  39. package/src/lib/A-StateMachine/A-StateMachine.types.ts +20 -0
  40. package/src/lib/A-StateMachine/A-StateMachineTransition.context.ts +41 -0
  41. package/src/lib/A-StateMachine/README.md +391 -0
  42. package/tests/A-Channel.test.ts +17 -14
  43. package/tests/A-Command.test.ts +548 -460
  44. package/tests/A-Logger.test.ts +8 -4
  45. package/tests/A-Memory.test.ts +151 -115
  46. package/tests/A-Schedule.test.ts +2 -2
  47. package/tests/A-StateMachine.test.ts +760 -0
@@ -0,0 +1,58 @@
1
+ import { A_Error, A_Fragment } from "@adaas/a-concept";
2
+ import { A_Operation_Serialized, A_Operation_Storage } from "./A-Operation.types";
3
+
4
+ export class A_OperationContext<
5
+ _AllowedOperations extends string = string,
6
+ _ParamsType extends Record<string, any> = Record<string, any>,
7
+ _ResultType = any,
8
+ _StorageType extends A_Operation_Storage<_ResultType, _ParamsType> = A_Operation_Storage<_ResultType, _ParamsType>
9
+ > extends A_Fragment<
10
+ _StorageType,
11
+ A_Operation_Serialized<_ResultType, _ParamsType>
12
+ > {
13
+
14
+ constructor(
15
+ operation: _AllowedOperations,
16
+ params?: _ParamsType
17
+ ) {
18
+ super();
19
+
20
+ this.meta.set('name', operation);
21
+ this.meta.set('params', params || {} as _ParamsType);
22
+ }
23
+
24
+ get name(): _AllowedOperations {
25
+ return (this._meta.get('name') || this._name) as _AllowedOperations;
26
+ }
27
+
28
+ get result(): _ResultType | undefined {
29
+ return this._meta.get('result');
30
+ }
31
+
32
+ get error(): A_Error | undefined {
33
+ return this._meta.get('error');
34
+ }
35
+
36
+ get params(): _ParamsType {
37
+ return this._meta.get('params') || {} as _ParamsType;
38
+ }
39
+
40
+
41
+ fail(error: A_Error): void {
42
+ this._meta.set('error', error);
43
+ }
44
+
45
+ succeed(result: _ResultType): void {
46
+ this._meta.set('result', result);
47
+ }
48
+
49
+
50
+ toJSON(): A_Operation_Serialized<_ResultType, _ParamsType> {
51
+ return {
52
+ name: this.name,
53
+ params: this.params,
54
+ result: this.result || {} as _ResultType,
55
+ error: this.error?.toJSON(),
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,47 @@
1
+ import { A_Error, A_TYPES__Error_Serialized } from "@adaas/a-concept"
2
+
3
+
4
+ export type A_Operation_Storage<
5
+ _Result_type extends any = any,
6
+ _ParamsType extends Record<string, any> = Record<string, any>,
7
+ > = {
8
+ /**
9
+ * The name of the operation
10
+ */
11
+ name: string,
12
+ /**
13
+ * The parameters for the operation
14
+ */
15
+ params: _ParamsType,
16
+ /**
17
+ * The result of the operation
18
+ */
19
+ result: _Result_type,
20
+ /**
21
+ * Any error that occurred during the operation
22
+ */
23
+ error?: A_Error
24
+ }
25
+
26
+
27
+ export type A_Operation_Serialized<
28
+ _Result_type extends any = any,
29
+ _ParamsType extends Record<string, any> = Record<string, any>,
30
+ > = {
31
+ /**
32
+ * The name of the operation
33
+ */
34
+ name: string,
35
+ /**
36
+ * The parameters for the operation
37
+ */
38
+ params: _ParamsType,
39
+ /**
40
+ * The result of the operation
41
+ */
42
+ result: _Result_type,
43
+ /**
44
+ * Any error that occurred during the operation
45
+ */
46
+ error?: A_TYPES__Error_Serialized,
47
+ }
@@ -0,0 +1,258 @@
1
+ import { A_Component, A_Context, A_Feature, A_FormatterHelper, A_Scope } from "@adaas/a-concept";
2
+ import { A_StateMachineError } from "./A-StateMachine.error";
3
+ import { A_StateMachineFeatures } from "./A-StateMachine.constants";
4
+ import { A_StateMachineTransition } from "./A-StateMachineTransition.context";
5
+
6
+ /**
7
+ * A_StateMachine is a powerful state machine implementation that allows you to define and manage
8
+ * complex state transitions with validation, hooks, and error handling.
9
+ *
10
+ * @template T - A record type defining the state transitions and their associated data types.
11
+ * Each key represents a state name, and the value represents the data type for that state.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * interface OrderStates {
16
+ * pending: { orderId: string };
17
+ * processing: { orderId: string; processedBy: string };
18
+ * completed: { orderId: string; completedAt: Date };
19
+ * cancelled: { orderId: string; reason: string };
20
+ * }
21
+ *
22
+ * class OrderStateMachine extends A_StateMachine<OrderStates> {
23
+ * // Define custom transition logic
24
+ * async pending_processing(scope: A_Scope) {
25
+ * const operation = scope.resolve(A_StateMachineTransition)!;
26
+ * const { orderId } = operation.props;
27
+ * // Custom validation and business logic
28
+ * }
29
+ * }
30
+ * ```
31
+ */
32
+ export class A_StateMachine<
33
+ T extends Record<string, any> = Record<string, any>
34
+ > extends A_Component {
35
+
36
+ /**
37
+ * Internal promise that tracks the initialization state of the state machine.
38
+ * Used to ensure the state machine is properly initialized before allowing transitions.
39
+ */
40
+ protected _initialized?: Promise<void>;
41
+
42
+ /**
43
+ * Gets a promise that resolves when the state machine is fully initialized and ready for transitions.
44
+ * This ensures that all initialization hooks have been executed before allowing state transitions.
45
+ *
46
+ * @returns Promise<void> that resolves when initialization is complete
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const stateMachine = new MyStateMachine();
51
+ * await stateMachine.ready; // Wait for initialization
52
+ * await stateMachine.transition('idle', 'running');
53
+ * ```
54
+ */
55
+ get ready(): Promise<void> {
56
+ if (!this._initialized) {
57
+ this._initialized = this.call(A_StateMachineFeatures.onInitialize);
58
+ }
59
+
60
+ return this._initialized;
61
+ }
62
+
63
+
64
+
65
+ /**
66
+ * Initialization hook that runs when the state machine is first created.
67
+ * This method can be extended to add custom initialization logic.
68
+ *
69
+ * @param args - Variable arguments passed during initialization
70
+ * @returns Promise<void>
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * class MyStateMachine extends A_StateMachine {
75
+ * @A_Feature.Extend()
76
+ * async [A_StateMachineFeatures.onInitialize]() {
77
+ * // Custom initialization logic
78
+ * console.log('State machine initialized');
79
+ * }
80
+ * }
81
+ * ```
82
+ */
83
+ @A_Feature.Extend()
84
+ async [A_StateMachineFeatures.onInitialize](...args: any[]): Promise<void> {
85
+ // Initialization logic can be added here
86
+ }
87
+
88
+ /**
89
+ * Hook that runs before any state transition occurs.
90
+ * Use this to add validation, logging, or preparation logic that should run for all transitions.
91
+ *
92
+ * @param args - Variable arguments, typically includes the transition scope
93
+ * @returns Promise<void>
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * class MyStateMachine extends A_StateMachine {
98
+ * @A_Feature.Extend()
99
+ * async [A_StateMachineFeatures.onBeforeTransition](scope: A_Scope) {
100
+ * const operation = scope.resolve(A_StateMachineTransition)!;
101
+ * console.log(`Transitioning from ${operation.props.from} to ${operation.props.to}`);
102
+ * }
103
+ * }
104
+ * ```
105
+ */
106
+ @A_Feature.Extend()
107
+ async [A_StateMachineFeatures.onBeforeTransition](...args: any[]): Promise<void> {
108
+
109
+ }
110
+
111
+ /**
112
+ * Hook that runs after a successful state transition.
113
+ * Use this to add cleanup, logging, or post-transition logic that should run for all transitions.
114
+ *
115
+ * @param args - Variable arguments, typically includes the transition scope
116
+ * @returns Promise<void>
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * class MyStateMachine extends A_StateMachine {
121
+ * @A_Feature.Extend()
122
+ * async [A_StateMachineFeatures.onAfterTransition](scope: A_Scope) {
123
+ * const operation = scope.resolve(A_StateMachineTransition)!;
124
+ * console.log(`Successfully transitioned to ${operation.props.to}`);
125
+ * }
126
+ * }
127
+ * ```
128
+ */
129
+ @A_Feature.Extend()
130
+ async [A_StateMachineFeatures.onAfterTransition](...args: any[]): Promise<void> {
131
+
132
+ }
133
+
134
+ /**
135
+ * Error handling hook that runs when a transition fails.
136
+ * Use this to add custom error handling, logging, or recovery logic.
137
+ *
138
+ * @param args - Variable arguments, typically includes the error scope
139
+ * @returns Promise<void>
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * class MyStateMachine extends A_StateMachine {
144
+ * @A_Feature.Extend()
145
+ * async [A_StateMachineFeatures.onError](scope: A_Scope) {
146
+ * const error = scope.resolve(A_StateMachineError);
147
+ * console.error('Transition failed:', error?.message);
148
+ * }
149
+ * }
150
+ * ```
151
+ */
152
+ @A_Feature.Extend()
153
+ async [A_StateMachineFeatures.onError](...args: any[]): Promise<void> {
154
+ // Default error handling logic can be added here
155
+ }
156
+
157
+
158
+
159
+ /**
160
+ * Executes a state transition from one state to another.
161
+ * This is the core method of the state machine that handles the complete transition lifecycle.
162
+ *
163
+ * @param from - The state to transition from (must be a key of T)
164
+ * @param to - The state to transition to (must be a key of T)
165
+ * @param props - Optional properties to pass to the transition context (should match T[keyof T])
166
+ * @returns Promise<void> that resolves when the transition is complete
167
+ *
168
+ * @throws {A_StateMachineError} When the transition fails for any reason
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * interface OrderStates {
173
+ * pending: { orderId: string };
174
+ * processing: { orderId: string; processedBy: string };
175
+ * }
176
+ *
177
+ * const orderMachine = new A_StateMachine<OrderStates>();
178
+ *
179
+ * // Transition with props
180
+ * await orderMachine.transition('pending', 'processing', {
181
+ * orderId: '12345',
182
+ * processedBy: 'user-456'
183
+ * });
184
+ * ```
185
+ *
186
+ * The transition process follows this lifecycle:
187
+ * 1. Wait for state machine initialization (ready)
188
+ * 2. Create transition name in camelCase format (e.g., "pending_processing")
189
+ * 3. Create operation context with transition data
190
+ * 4. Create isolated scope for the transition
191
+ * 5. Call onBeforeTransition hook
192
+ * 6. Execute the specific transition method (if defined)
193
+ * 7. Call onAfterTransition hook
194
+ * 8. Clean up scope and return result
195
+ *
196
+ * If any step fails, the onError hook is called and a wrapped error is thrown.
197
+ */
198
+ async transition(
199
+ /**
200
+ * The state to transition from
201
+ */
202
+ from: keyof T,
203
+ /**
204
+ * The state to transition to
205
+ */
206
+ to: keyof T,
207
+ /**
208
+ * Optional properties to pass to the transition context
209
+ */
210
+ props?: T[keyof T]
211
+ ): Promise<void> {
212
+
213
+ await this.ready;
214
+
215
+ const transitionName = `${A_FormatterHelper.toCamelCase(String(from))}_${A_FormatterHelper.toCamelCase(String(to))}`;
216
+
217
+ const transition = new A_StateMachineTransition({
218
+ from: String(from),
219
+ to: String(to),
220
+ props
221
+ });
222
+
223
+ const scope = new A_Scope({
224
+ name: `A-StateMachine-Transition-Scope-${transitionName}`,
225
+ fragments: [transition]
226
+ });
227
+
228
+ try {
229
+
230
+ await this.call(A_StateMachineFeatures.onBeforeTransition, scope);
231
+
232
+ await this.call(transitionName, scope);
233
+
234
+ await this.call(A_StateMachineFeatures.onAfterTransition, scope);
235
+
236
+ scope.destroy();
237
+
238
+ return transition.result;
239
+
240
+ } catch (error) {
241
+ const wrappedError = new A_StateMachineError({
242
+ title: A_StateMachineError.TransitionError,
243
+ description: `An error occurred while transitioning to "${transitionName}"`,
244
+ originalError: error
245
+ });
246
+
247
+ scope.register(wrappedError);
248
+
249
+ await this.call(A_StateMachineFeatures.onError, scope);
250
+
251
+ scope.destroy();
252
+
253
+ throw wrappedError;
254
+ }
255
+ }
256
+ }
257
+
258
+
@@ -0,0 +1,18 @@
1
+ export enum A_StateMachineFeatures {
2
+ /**
3
+ * Allows to extend error handling logic and behavior
4
+ */
5
+ onError = 'onError',
6
+ /**
7
+ * Allows to extend initialization logic and behavior
8
+ */
9
+ onInitialize = 'onInitialize',
10
+ /**
11
+ * Allows to extend transition validation logic and behavior
12
+ */
13
+ onBeforeTransition = 'onBeforeTransition',
14
+ /**
15
+ * Allows to extend post-transition logic and behavior
16
+ */
17
+ onAfterTransition = 'onAfterTransition',
18
+ }
@@ -0,0 +1,10 @@
1
+ import { A_Error } from "@adaas/a-concept";
2
+
3
+
4
+ export class A_StateMachineError extends A_Error {
5
+
6
+ static readonly InitializationError = 'A-StateMachine Initialization Error';
7
+
8
+ static readonly TransitionError = 'A-StateMachine Transition Error';
9
+
10
+ }
@@ -0,0 +1,20 @@
1
+ import { A_Operation_Storage } from "../A-Operation/A-Operation.types";
2
+
3
+
4
+ export type A_StateMachineTransitionParams<
5
+ T = any
6
+ > = {
7
+ from: string;
8
+ to: string;
9
+ props?: T
10
+ }
11
+
12
+
13
+
14
+ export type A_StateMachineTransitionStorage<
15
+ _ResultType extends any = any,
16
+ _ParamsType extends any = any
17
+ > = {
18
+ from: string,
19
+ to: string
20
+ } & A_Operation_Storage<_ResultType, A_StateMachineTransitionParams<_ParamsType>>
@@ -0,0 +1,41 @@
1
+ import { A_OperationContext } from "../A-Operation/A-Operation.context";
2
+ import { A_StateMachineTransitionParams, A_StateMachineTransitionStorage } from "./A-StateMachine.types";
3
+
4
+
5
+
6
+ export class A_StateMachineTransition<
7
+ _ParamsType = any,
8
+ _ResultType = any
9
+ > extends A_OperationContext<
10
+ 'a-state-machine-transition',
11
+ A_StateMachineTransitionParams<_ParamsType>,
12
+ _ResultType,
13
+ A_StateMachineTransitionStorage<_ResultType, _ParamsType>
14
+ > {
15
+
16
+
17
+ constructor(
18
+ params: A_StateMachineTransitionParams<_ParamsType>
19
+ ) {
20
+ super(
21
+ 'a-state-machine-transition',
22
+ params
23
+ );
24
+
25
+ this._meta.set('from', params.from);
26
+ this._meta.set('to', params.to);
27
+ }
28
+
29
+
30
+
31
+ get from(): string {
32
+ return this._meta.get('from')!;
33
+ }
34
+
35
+
36
+
37
+ get to(): string {
38
+ return this._meta.get('to')!;
39
+ }
40
+
41
+ }