@adaas/a-concept 0.0.29 → 0.0.30

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 (175) hide show
  1. package/dist/examples/fe-be/channels/Test.channel.d.ts +6 -0
  2. package/dist/examples/fe-be/channels/Test.channel.js +14 -0
  3. package/dist/examples/fe-be/channels/Test.channel.js.map +1 -0
  4. package/dist/examples/fe-be/components/BE-Controller.component.d.ts +4 -0
  5. package/dist/examples/fe-be/components/BE-Controller.component.js +24 -0
  6. package/dist/examples/fe-be/components/BE-Controller.component.js.map +1 -0
  7. package/dist/examples/fe-be/components/FE.component.d.ts +4 -0
  8. package/dist/examples/fe-be/components/FE.component.js +31 -0
  9. package/dist/examples/fe-be/components/FE.component.js.map +1 -0
  10. package/dist/examples/fe-be/components/UserActions.component.d.ts +5 -0
  11. package/dist/examples/fe-be/components/UserActions.component.js +25 -0
  12. package/dist/examples/fe-be/components/UserActions.component.js.map +1 -0
  13. package/dist/examples/fe-be/concept.d.ts +0 -0
  14. package/dist/examples/fe-be/concept.js +2 -0
  15. package/dist/examples/fe-be/concept.js.map +1 -0
  16. package/dist/examples/fe-be/containers/ServerApp.container.d.ts +3 -0
  17. package/dist/examples/fe-be/containers/ServerApp.container.js +8 -0
  18. package/dist/examples/fe-be/containers/ServerApp.container.js.map +1 -0
  19. package/dist/examples/fe-be/containers/WebApp.container.d.ts +3 -0
  20. package/dist/examples/fe-be/containers/WebApp.container.js +8 -0
  21. package/dist/examples/fe-be/containers/WebApp.container.js.map +1 -0
  22. package/dist/examples/multi-container/channels/Direct.channel.d.ts +9 -0
  23. package/dist/examples/multi-container/channels/Direct.channel.js +32 -0
  24. package/dist/examples/multi-container/channels/Direct.channel.js.map +1 -0
  25. package/dist/examples/multi-container/concept.d.ts +0 -0
  26. package/dist/examples/multi-container/concept.js +2 -0
  27. package/dist/examples/multi-container/concept.js.map +1 -0
  28. package/dist/examples/multi-container/containers/Command.container.d.ts +11 -0
  29. package/dist/examples/multi-container/containers/Command.container.js +51 -0
  30. package/dist/examples/multi-container/containers/Command.container.js.map +1 -0
  31. package/dist/examples/multi-container/containers/Schedule.container.d.ts +15 -0
  32. package/dist/examples/multi-container/containers/Schedule.container.js +67 -0
  33. package/dist/examples/multi-container/containers/Schedule.container.js.map +1 -0
  34. package/dist/examples/simple/components/A.component.js.map +1 -1
  35. package/dist/examples/simple/containers/Main.container.js +7 -3
  36. package/dist/examples/simple/containers/Main.container.js.map +1 -1
  37. package/dist/examples/simple/entities/EntityA.entity.d.ts +8 -0
  38. package/dist/examples/simple/entities/EntityA.entity.js +22 -0
  39. package/dist/examples/simple/entities/EntityA.entity.js.map +1 -0
  40. package/dist/examples/simple-http-server/contexts/http-request.context.d.ts +0 -1
  41. package/dist/examples/simple-http-server/contexts/http-request.context.js +6 -8
  42. package/dist/examples/simple-http-server/contexts/http-request.context.js.map +1 -1
  43. package/dist/index.d.ts +8 -2
  44. package/dist/index.js +16 -7
  45. package/dist/index.js.map +1 -1
  46. package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.d.ts +14 -0
  47. package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.js +53 -0
  48. package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.js.map +1 -0
  49. package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.types.d.ts +2 -0
  50. package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.types.js +3 -0
  51. package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.types.js.map +1 -0
  52. package/dist/src/decorators/A-Connect/A-Connect.decorator.d.ts +19 -0
  53. package/dist/src/decorators/A-Connect/A-Connect.decorator.js +31 -0
  54. package/dist/src/decorators/A-Connect/A-Connect.decorator.js.map +1 -0
  55. package/dist/src/decorators/A-Connect/A-Connect.decorator.types.d.ts +1 -0
  56. package/dist/src/decorators/A-Connect/A-Connect.decorator.types.js +3 -0
  57. package/dist/src/decorators/A-Connect/A-Connect.decorator.types.js.map +1 -0
  58. package/dist/src/decorators/A-Entity/A-Entity-List.decorator.d.ts +1 -0
  59. package/dist/src/decorators/A-Entity/A-Entity-List.decorator.js +8 -0
  60. package/dist/src/decorators/A-Entity/A-Entity-List.decorator.js.map +1 -0
  61. package/dist/src/decorators/A-Entity/A-Entity.decorator.types.d.ts +14 -0
  62. package/dist/src/decorators/A-Entity/A-Entity.decorator.types.js +3 -0
  63. package/dist/src/decorators/A-Entity/A-Entity.decorator.types.js.map +1 -0
  64. package/dist/src/decorators/A-Feature/A-Feature-Extend.decorator.js +9 -0
  65. package/dist/src/decorators/A-Feature/A-Feature-Extend.decorator.js.map +1 -1
  66. package/dist/src/decorators/A-Feature/A-Feature.decorator.types.d.ts +28 -0
  67. package/dist/src/decorators/A-Inject/A-Inject.decorator.d.ts +2 -3
  68. package/dist/src/decorators/A-Inject/A-Inject.decorator.js.map +1 -1
  69. package/dist/src/decorators/A-Inject/A-Inject.decorator.types.d.ts +44 -0
  70. package/dist/src/global/A-Channel/A-Channel.class.d.ts +8 -10
  71. package/dist/src/global/A-Channel/A-Channel.class.js +12 -26
  72. package/dist/src/global/A-Channel/A-Channel.class.js.map +1 -1
  73. package/dist/src/global/A-Channel/A-Channel.types.d.ts +32 -0
  74. package/dist/src/global/A-Component/A-Component.class.d.ts +2 -1
  75. package/dist/src/global/A-Component/A-Component.class.js +1 -0
  76. package/dist/src/global/A-Component/A-Component.class.js.map +1 -1
  77. package/dist/src/global/A-Component/A-Component.meta.d.ts +8 -0
  78. package/dist/src/global/A-Component/A-Component.meta.js +27 -1
  79. package/dist/src/global/A-Component/A-Component.meta.js.map +1 -1
  80. package/dist/src/global/A-Component/A-Component.types.d.ts +19 -34
  81. package/dist/src/global/A-Component/A-Component.types.js +1 -7
  82. package/dist/src/global/A-Component/A-Component.types.js.map +1 -1
  83. package/dist/src/global/A-Concept/A_Concept.class.d.ts +7 -7
  84. package/dist/src/global/A-Concept/A_Concept.class.js +30 -30
  85. package/dist/src/global/A-Concept/A_Concept.class.js.map +1 -1
  86. package/dist/src/global/A-Concept/A_Concept.types.d.ts +42 -2
  87. package/dist/src/global/A-Concept/A_Concept.types.js.map +1 -1
  88. package/dist/src/global/A-Container/A-Container.class.d.ts +1 -8
  89. package/dist/src/global/A-Container/A-Container.class.js +1 -31
  90. package/dist/src/global/A-Container/A-Container.class.js.map +1 -1
  91. package/dist/src/global/A-Container/A-Container.meta.d.ts +8 -0
  92. package/dist/src/global/A-Container/A-Container.meta.js +29 -0
  93. package/dist/src/global/A-Container/A-Container.meta.js.map +1 -1
  94. package/dist/src/global/A-Container/A-Container.types.d.ts +23 -7
  95. package/dist/src/global/A-Container/A-Container.types.js +2 -1
  96. package/dist/src/global/A-Container/A-Container.types.js.map +1 -1
  97. package/dist/src/global/A-Context/A-Context.class.js +6 -35
  98. package/dist/src/global/A-Context/A-Context.class.js.map +1 -1
  99. package/dist/src/global/A-Entity/A-Entity.class.d.ts +1 -2
  100. package/dist/src/global/A-Entity/A-Entity.class.js +6 -7
  101. package/dist/src/global/A-Entity/A-Entity.class.js.map +1 -1
  102. package/dist/src/global/A-Entity/A-Entity.types.d.ts +4 -5
  103. package/dist/src/global/A-Entity/A-Entity.types.js.map +1 -1
  104. package/dist/src/global/A-Feature/A-Feature.class.d.ts +30 -6
  105. package/dist/src/global/A-Feature/A-Feature.class.js +49 -40
  106. package/dist/src/global/A-Feature/A-Feature.class.js.map +1 -1
  107. package/dist/src/global/A-Feature/A-Feature.types.d.ts +2 -24
  108. package/dist/src/global/A-Feature/A-Feature.types.js +21 -0
  109. package/dist/src/global/A-Feature/A-Feature.types.js.map +1 -1
  110. package/dist/src/global/A-Fragment/A-Fragment.class.d.ts +8 -0
  111. package/dist/src/global/A-Fragment/A-Fragment.class.js +10 -0
  112. package/dist/src/global/A-Fragment/A-Fragment.class.js.map +1 -1
  113. package/dist/src/global/A-Scope/A-Scope.class.d.ts +7 -5
  114. package/dist/src/global/A-Scope/A-Scope.class.js +33 -10
  115. package/dist/src/global/A-Scope/A-Scope.class.js.map +1 -1
  116. package/dist/src/global/A-Scope/A-Scope.types.d.ts +2 -1
  117. package/dist/src/global/A-Stage/A-Stage.class.d.ts +69 -0
  118. package/dist/src/global/A-Stage/A-Stage.class.js +176 -0
  119. package/dist/src/global/A-Stage/A-Stage.class.js.map +1 -0
  120. package/dist/src/global/A-Stage/A-Stage.types.d.ts +83 -0
  121. package/dist/src/global/A-Stage/A-Stage.types.js +59 -0
  122. package/dist/src/global/A-Stage/A-Stage.types.js.map +1 -0
  123. package/dist/src/helpers/StepsManager.class.d.ts +15 -0
  124. package/dist/src/helpers/StepsManager.class.js +85 -0
  125. package/dist/src/helpers/StepsManager.class.js.map +1 -0
  126. package/examples/fe-be/channels/Test.channel.ts +24 -0
  127. package/examples/fe-be/components/BE-Controller.component.ts +20 -0
  128. package/examples/fe-be/components/FE.component.ts +13 -0
  129. package/examples/fe-be/concept.ts +0 -0
  130. package/examples/fe-be/containers/ServerApp.container.ts +8 -0
  131. package/examples/fe-be/containers/WebApp.container.ts +13 -0
  132. package/examples/multi-container/channels/Direct.channel.ts +39 -0
  133. package/examples/multi-container/concept.ts +0 -0
  134. package/examples/multi-container/containers/Command.container.ts +41 -0
  135. package/examples/multi-container/containers/Schedule.container.ts +57 -0
  136. package/examples/simple/components/A.component.ts +2 -1
  137. package/examples/simple/containers/Main.container.ts +11 -3
  138. package/examples/simple/entities/EntityA.entity.ts +16 -0
  139. package/examples/simple-http-server/contexts/http-request.context.ts +6 -6
  140. package/index.ts +12 -3
  141. package/package.json +1 -1
  142. package/src/decorators/A-Abstraction/A-Abstraction.decorator.ts +82 -0
  143. package/src/decorators/{A-Stage/A-Stage.decorator.types.ts → A-Abstraction/A-Abstraction.decorator.types.ts} +1 -3
  144. package/src/decorators/A-Connect/A-Connect.decorator.ts +71 -0
  145. package/src/decorators/A-Connect/A-Connect.decorator.types.ts +6 -0
  146. package/src/decorators/A-Entity/A-Entity-List.decorator.ts +12 -0
  147. package/src/decorators/A-Entity/A-Entity.decorator.types.ts +18 -0
  148. package/src/decorators/A-Feature/A-Feature-Extend.decorator.ts +10 -0
  149. package/src/decorators/A-Feature/A-Feature.decorator.types.ts +36 -0
  150. package/src/decorators/A-Inject/A-Inject.decorator.ts +7 -7
  151. package/src/decorators/A-Inject/A-Inject.decorator.types.ts +47 -1
  152. package/src/global/A-Channel/A-Channel.class.ts +25 -28
  153. package/src/global/A-Channel/A-Channel.types.ts +53 -0
  154. package/src/global/A-Component/A-Component.class.ts +10 -2
  155. package/src/global/A-Component/A-Component.meta.ts +42 -1
  156. package/src/global/A-Component/A-Component.types.ts +20 -40
  157. package/src/global/A-Concept/A_Concept.class.ts +52 -31
  158. package/src/global/A-Concept/A_Concept.types.ts +48 -3
  159. package/src/global/A-Container/A-Container.class.ts +3 -39
  160. package/src/global/A-Container/A-Container.meta.ts +41 -4
  161. package/src/global/A-Container/A-Container.types.ts +28 -7
  162. package/src/global/A-Context/A-Context.class.ts +9 -49
  163. package/src/global/A-Entity/A-Entity.class.ts +8 -6
  164. package/src/global/A-Entity/A-Entity.types.ts +4 -5
  165. package/src/global/A-Feature/A-Feature.class.ts +73 -61
  166. package/src/global/A-Feature/A-Feature.types.ts +24 -23
  167. package/src/global/A-Fragment/A-Fragment.class.ts +15 -0
  168. package/src/global/A-Scope/A-Scope.class.ts +58 -25
  169. package/src/global/A-Scope/A-Scope.types.ts +2 -1
  170. package/src/global/A-Stage/A-Stage.class.ts +225 -0
  171. package/src/global/A-Stage/A-Stage.types.ts +106 -0
  172. package/src/helpers/StepsManager.class.ts +104 -0
  173. package/tests/channel.ts +213 -0
  174. package/tests/log.ts +88 -40
  175. package/src/decorators/A-Stage/A-Stage.decorator.ts +0 -84
@@ -1,14 +1,13 @@
1
- import { A_CommonHelper } from "@adaas/a-utils";
1
+ import { A_CommonHelper, ASEID } from "@adaas/a-utils";
2
2
  import { A_TYPES__ScopeConfig, A_TYPES__ScopeConstructor } from "./A-Scope.types";
3
3
  import { A_Fragment } from "../A-Fragment/A-Fragment.class";
4
4
  import { A_Context } from "../A-Context/A-Context.class";
5
5
  import {
6
- A_TYPES__ComponentMeta_EntityInjectionInstructions,
7
- A_TYPES__ComponentMeta_InjectionParam,
8
6
  A_TYPES__ComponentMetaKey
9
7
  } from "../A-Component/A-Component.types";
10
8
  import { A_Component } from "../A-Component/A-Component.class";
11
9
  import { A_Entity } from "../A-Entity/A-Entity.class";
10
+ import { A_TYPES__A_InjectDecorator_EntityInjectionInstructions, A_TYPES__A_InjectDecorator_EntityInjectionQuery, A_TYPES__A_InjectDecorator_Injectable } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator.types";
12
11
 
13
12
  /**
14
13
  *
@@ -72,6 +71,10 @@ export class A_Scope {
72
71
  // })
73
72
  }
74
73
 
74
+ private initEntities(_entities: Array<A_Entity>) {
75
+ _entities.forEach(this.register.bind(this));
76
+ }
77
+
75
78
 
76
79
  private initFragments(_fragments: Array<A_Fragment>) {
77
80
  _fragments.forEach(this.register.bind(this));
@@ -111,7 +114,7 @@ export class A_Scope {
111
114
  switch (true) {
112
115
 
113
116
  case A_CommonHelper.isInheritedFrom(entity, A_Component): {
114
- const found = this.params.components.includes(entity);
117
+ const found = this.params.components.includes(entity as { new(...args: any[]): A_Component });
115
118
 
116
119
  if (!found && !!this.parent)
117
120
  return this.parent.has(entity as any);
@@ -149,20 +152,20 @@ export class A_Scope {
149
152
  * @param component
150
153
  * @returns
151
154
  */
152
- resolve<T extends A_TYPES__ComponentMeta_InjectionParam>(
155
+ resolve<T extends A_TYPES__A_InjectDecorator_Injectable>(
153
156
  component: T
154
157
  ): InstanceType<T>
155
158
  resolve<T extends { new(...args: any[]): A_Entity }>(
156
159
  entity: T,
157
- instructions: Partial<A_TYPES__ComponentMeta_EntityInjectionInstructions>
160
+ instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
158
161
  ): InstanceType<T>
159
- resolve<T extends A_TYPES__ComponentMeta_InjectionParam>(
162
+ resolve<T extends A_TYPES__A_InjectDecorator_Injectable>(
160
163
  component: Array<T>
161
164
  ): Array<InstanceType<T>>
162
165
  // base definition
163
- resolve<T extends A_TYPES__ComponentMeta_InjectionParam>(
166
+ resolve<T extends A_TYPES__A_InjectDecorator_Injectable>(
164
167
  param1: Array<T> | T,
165
- param2?: string | Partial<A_TYPES__ComponentMeta_EntityInjectionInstructions>
168
+ param2?: string | Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
166
169
  ): Array<InstanceType<T>> | InstanceType<T> {
167
170
 
168
171
  switch (true) {
@@ -182,16 +185,18 @@ export class A_Scope {
182
185
 
183
186
 
184
187
 
188
+
189
+
185
190
  private resolveOnce<T extends { new(...args: any[]): A_Entity }>(
186
191
  entity: T,
187
- instructions: Partial<A_TYPES__ComponentMeta_EntityInjectionInstructions>
192
+ instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
188
193
  ): InstanceType<T> | undefined
189
- private resolveOnce<T extends A_TYPES__ComponentMeta_InjectionParam>(
194
+ private resolveOnce<T extends A_TYPES__A_InjectDecorator_Injectable>(
190
195
  component: T
191
196
  ): InstanceType<T>
192
- private resolveOnce<T extends { new(...args: any[]): A_Entity } | A_TYPES__ComponentMeta_InjectionParam>(
197
+ private resolveOnce<T extends { new(...args: any[]): A_Entity } | A_TYPES__A_InjectDecorator_Injectable>(
193
198
  component: T,
194
- instructions?: Partial<A_TYPES__ComponentMeta_EntityInjectionInstructions>
199
+ instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
195
200
  ): InstanceType<T> {
196
201
  switch (true) {
197
202
  case A_CommonHelper.isInheritedFrom(component, A_Entity): {
@@ -218,9 +223,13 @@ export class A_Scope {
218
223
 
219
224
  private resolveEntity<T extends { new(...args: any[]): A_Entity }>(
220
225
  entity: T,
221
- instructions?: Partial<A_TYPES__ComponentMeta_EntityInjectionInstructions>
226
+ instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
222
227
  ): InstanceType<T> | undefined {
223
228
 
229
+ const query = instructions?.query || {};
230
+ const count = instructions?.pagination?.count || 1;
231
+
232
+
224
233
  switch (true) {
225
234
  case !instructions: {
226
235
 
@@ -233,25 +242,34 @@ export class A_Scope {
233
242
  return found as InstanceType<T>;
234
243
 
235
244
  case !found && !!this.parent:
236
- return this.parent.resolveFragment(entity);
245
+ return this.parent.resolveEntity(entity, instructions);
237
246
 
238
247
  default:
239
248
  throw new Error(`Fragment ${entity.name} not found in the scope ${this.name}`);
240
249
  }
241
250
  }
242
251
 
243
- case !!instructions && !!instructions.aseid && this._entities.has(instructions.aseid): {
244
- return this._entities.get(instructions.aseid) as InstanceType<T>;
245
- }
252
+ case !!query.aseid
253
+ && typeof query.aseid === 'string'
254
+ && this._entities.has(query.aseid): {
255
+ return this._entities.get(query.aseid) as InstanceType<T>;
256
+ }
246
257
 
247
- case !!instructions && !!instructions.id && this._entities.has(instructions.id): {
248
- // in this case we have to find the entity by the id
249
- const entities = Array.from(this._entities.values());
258
+ case !!query.aseid
259
+ && query.aseid instanceof ASEID
260
+ && this._entities.has(query.aseid.toString()): {
261
+ return this._entities.get(query.aseid.toString()) as InstanceType<T>;
262
+ }
250
263
 
251
- const found = entities.find(e => e.id === instructions.id);
264
+ case !!query.id
265
+ && this._entities.has(query.id): {
266
+ // in this case we have to find the entity by the id
267
+ const entities = Array.from(this._entities.values());
252
268
 
253
- return found as InstanceType<T>;
254
- }
269
+ const found = entities.find(e => e.id === query.id);
270
+
271
+ return found as InstanceType<T>;
272
+ }
255
273
 
256
274
  default:
257
275
  throw new Error(`Entity ${entity.constructor.name} not found in the scope ${this.name}`);
@@ -331,7 +349,7 @@ export class A_Scope {
331
349
 
332
350
  const found = this.components.find(el => A_CommonHelper.isInheritedFrom(el, component));
333
351
 
334
- return this.resolveComponent(found!);
352
+ return this.resolveComponent<T>(found as any);
335
353
  }
336
354
 
337
355
  // In case when the component is not available in the scope but the parent is available
@@ -398,4 +416,19 @@ export class A_Scope {
398
416
 
399
417
 
400
418
  }
419
+
420
+
421
+
422
+
423
+ toJSON(): Record<string, any> {
424
+ return this.fragments.reduce((acc, fragment) => {
425
+
426
+ const serialized = fragment.toJSON()
427
+
428
+ return {
429
+ ...acc,
430
+ [serialized.name]: serialized
431
+ }
432
+ }, {});
433
+ }
401
434
  }
@@ -1,3 +1,4 @@
1
+ import { A_Component } from "../A-Component/A-Component.class"
1
2
  import { A_Fragment } from "../A-Fragment/A-Fragment.class"
2
3
  import { A_Scope } from "./A-Scope.class"
3
4
 
@@ -15,7 +16,7 @@ export type A_TYPES__ScopeConstructor = {
15
16
  /**
16
17
  * A set of Components available in the Scope
17
18
  */
18
- components: Array<{ new(...args: any[]): any }>
19
+ components: Array<{ new(...args: any[]): A_Component }>
19
20
 
20
21
 
21
22
  /**
@@ -0,0 +1,225 @@
1
+ import { A_CommonHelper, A_Error } from "@adaas/a-utils";
2
+ import { A_Context } from "../A-Context/A-Context.class";
3
+ import { A_Feature } from "../A-Feature/A-Feature.class";
4
+ import { A_TYPES__A_Stage_JSON, A_TYPES__A_Stage_Status, A_TYPES__A_StageStep } from "./A-Stage.types";
5
+ import { A_Container } from "../A-Container/A-Container.class";
6
+
7
+
8
+
9
+ /**
10
+ * A_Stage is a set of A_Functions within A_Feature that should be run in a specific order.
11
+ * Each stage may contain one or more functions.
12
+ * [!] That always run in parallel (in NodeJS asynchronously), independently of each other.
13
+ *
14
+ * A-Stage is a common object that uses to simplify logic and re-use of A-Feature internals for better composition.
15
+ */
16
+ export class A_Stage {
17
+
18
+
19
+
20
+ constructor(
21
+ private feature: A_Feature,
22
+ private steps: A_TYPES__A_StageStep[] = []
23
+ ) {
24
+
25
+ }
26
+
27
+ status: A_TYPES__A_Stage_Status = A_TYPES__A_Stage_Status.INITIALIZED;
28
+ /**
29
+ * Promise that will be resolved when the stage is Processed
30
+ */
31
+ processed: Promise<void> | undefined;
32
+
33
+
34
+ get before(): string[] {
35
+ return this.steps.reduce((acc, step) => ([
36
+ ...acc,
37
+ ...step.before
38
+ ]), [] as string[]);
39
+ }
40
+
41
+ get after(): string[] {
42
+ return this.steps.reduce((acc, step) => ([
43
+ ...acc,
44
+ ...step.after
45
+ ]), [] as string[]);
46
+ }
47
+
48
+
49
+ /**
50
+ * Resolves the arguments of the step
51
+ *
52
+ * @param step
53
+ * @returns
54
+ */
55
+ protected async getStepArgs(step: A_TYPES__A_StageStep) {
56
+ return step.args.map(async arg =>
57
+ // In case if the target is a feature step then pass the current feature
58
+ A_CommonHelper.isInheritedFrom(arg.target, A_Feature)
59
+ ? this
60
+ : A_Context.scope(this.feature).resolve(arg.target)
61
+ );
62
+ }
63
+
64
+
65
+ /**
66
+ * Adds a step to the stage
67
+ *
68
+ * @param step
69
+ * @returns
70
+ */
71
+ add(
72
+ step: A_TYPES__A_StageStep
73
+ ): this {
74
+ this.steps.push(step);
75
+
76
+ return this;
77
+ }
78
+
79
+
80
+ /**
81
+ * Resolves the component of the step
82
+ *
83
+ * @param step
84
+ * @returns
85
+ */
86
+ protected getStepInstance(step: A_TYPES__A_StageStep) {
87
+ const { component, handler } = step;
88
+
89
+ // TODO: probably would be better to do it another way. let's think about it
90
+ const instance = component instanceof A_Container
91
+ ? component
92
+ : A_Context.scope(this.feature).resolve(component);
93
+
94
+ if (!instance)
95
+ throw new Error(`Unable to resolve component ${component.name}`);
96
+
97
+ if (!instance[handler])
98
+ throw new Error(`Handler ${handler} not found in ${instance.constructor.name}`);
99
+
100
+ return instance;
101
+ }
102
+
103
+
104
+
105
+ /**
106
+ * Calls the handler of the step
107
+ *
108
+ * @param step
109
+ * @returns
110
+ */
111
+ protected async getStepHandler(step: A_TYPES__A_StageStep) {
112
+
113
+ const instance = this.getStepInstance(step);
114
+ const callArgs = await this.getStepArgs(step);
115
+
116
+ return instance[step.handler](...callArgs);
117
+
118
+ }
119
+
120
+
121
+ /**
122
+ * Runs async all the steps of the stage
123
+ *
124
+ * @returns
125
+ */
126
+ async process(): Promise<void> {
127
+ if (!this.processed)
128
+ this.processed = new Promise<void>(
129
+ async (resolve, reject) => {
130
+ try {
131
+ this.status = A_TYPES__A_Stage_Status.PROCESSING;
132
+
133
+ const syncSteps = this.steps.filter(step => step.behavior === 'sync');
134
+ const asyncSteps = this.steps.filter(step => step.behavior === 'async');
135
+
136
+ // Run sync steps
137
+
138
+ await Promise
139
+ .all([
140
+
141
+ // Run async steps that are independent of each other
142
+ ...asyncSteps.map(step => this.getStepHandler(step)),
143
+
144
+ // Run sync steps that are dependent on each other
145
+ new Promise<void>(
146
+ async (r, j) => {
147
+ try {
148
+ for (const step of syncSteps) {
149
+ await this.getStepHandler(step);
150
+ }
151
+
152
+ return r();
153
+ } catch (error) {
154
+ return j(error);
155
+ }
156
+ }
157
+ )
158
+ ]);
159
+
160
+ this.completed();
161
+
162
+ return resolve();
163
+
164
+ } catch (error) {
165
+ this.failed(error);
166
+
167
+ return reject(error);
168
+ }
169
+ });
170
+
171
+
172
+ return this.processed;
173
+ }
174
+
175
+
176
+ /**
177
+ * Skips the stage
178
+ *
179
+ */
180
+ skip() {
181
+ this.status = A_TYPES__A_Stage_Status.SKIPPED;
182
+
183
+ this.feature.next(this);
184
+ }
185
+
186
+
187
+
188
+
189
+ // ==========================================
190
+ // ============ Status methods =============
191
+ // ==========================================
192
+
193
+ protected completed() {
194
+ this.status = A_TYPES__A_Stage_Status.COMPLETED;
195
+
196
+ this.feature.next(this);
197
+ }
198
+
199
+ protected failed(
200
+ error: Error | A_Error | unknown
201
+ ) {
202
+ this.status = A_TYPES__A_Stage_Status.FAILED;
203
+
204
+ this.feature.failed(error);
205
+ }
206
+
207
+
208
+
209
+ // ==========================================
210
+ // ============ Serialization ===============
211
+ // ==========================================
212
+
213
+
214
+ /**
215
+ * Serializes the stage to JSON
216
+ *
217
+ */
218
+ toJSON(): A_TYPES__A_Stage_JSON {
219
+
220
+ return {
221
+ name: 'A_Stage',
222
+ status: this.status,
223
+ }
224
+ }
225
+ }
@@ -0,0 +1,106 @@
1
+ import { A_TYPES__A_InjectDecorator_Meta } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator.types"
2
+ import { A_Component } from "../A-Component/A-Component.class"
3
+ import { A_Container } from "../A-Container/A-Container.class"
4
+ import { A_TYPES__A_ExtendDecorator_BehaviorConfig, A_TYPES__A_ExtendDecorator_Meta } from "@adaas/a-concept/decorators/A-Feature/A-Feature.decorator.types"
5
+
6
+
7
+
8
+ export enum A_TYPES__A_Stage_Status {
9
+ /**
10
+ * The stage is currently being processed
11
+ */
12
+ PROCESSING = 'PROCESSING',
13
+ /**
14
+ * The stage has been completed
15
+ */
16
+ COMPLETED = 'COMPLETED',
17
+ /**
18
+ * The stage has failed
19
+ */
20
+ FAILED = 'FAILED',
21
+ /**
22
+ * The stage has been skipped
23
+ */
24
+ SKIPPED = 'SKIPPED',
25
+ /**
26
+ * The stage has been paused
27
+ */
28
+ // PAUSED = 'PAUSED',
29
+ /**
30
+ * The stage has been stopped
31
+ */
32
+ // STOPPED = 'STOPPED',
33
+ /**
34
+ * The stage has been started
35
+ */
36
+ // STARTED = 'STARTED',
37
+ /**
38
+ * The stage has been initialized
39
+ */
40
+ INITIALIZED = 'INITIALIZED',
41
+ /**
42
+ * The stage has been reset
43
+ */
44
+ // RESET = 'RESET',
45
+ /**
46
+ * The stage has been resumed
47
+ */
48
+ // RESUMED = 'RESUMED',
49
+ /**
50
+ * The stage has been suspended
51
+ */
52
+ // SUSPENDED = 'SUSPENDED',
53
+ /**
54
+ * The stage has been terminated
55
+ */
56
+ // TERMINATED = 'TERMINATED',
57
+ /**
58
+ * The stage has been aborted
59
+ */
60
+ ABORTED = 'ABORTED'
61
+ }
62
+
63
+
64
+ export type A_TYPES__A_StageStep = {
65
+
66
+ /**
67
+ * The component to be called
68
+ */
69
+ component: typeof A_Component | typeof A_Container | A_Container<any>
70
+
71
+ /**
72
+ * The method to be called on the component
73
+ */
74
+ handler: string,
75
+
76
+ /**
77
+ * Original Feature Extension name
78
+ *
79
+ * [!] could be string or regex
80
+ *
81
+ */
82
+ name: string,
83
+
84
+ /**
85
+ * Arguments to be passed to the method
86
+ */
87
+ args: A_TYPES__A_InjectDecorator_Meta
88
+
89
+ } & A_TYPES__A_ExtendDecorator_BehaviorConfig
90
+
91
+
92
+
93
+ export type A_TYPES__A_Stage_JSON = {
94
+
95
+ /**
96
+ * The name of the stage
97
+ */
98
+ name: string,
99
+
100
+ /**
101
+ * The status of the stage
102
+ *
103
+ */
104
+ status: A_TYPES__A_Stage_Status,
105
+
106
+ }
@@ -0,0 +1,104 @@
1
+ import { A_Feature } from "../global/A-Feature/A-Feature.class";
2
+ import { A_Stage } from "../global/A-Stage/A-Stage.class";
3
+ import { A_TYPES__A_StageStep } from "../global/A-Stage/A-Stage.types";
4
+
5
+ export class StepsManager {
6
+
7
+ public entities: A_TYPES__A_StageStep[];
8
+ public graph: Map<string, Set<string>>;
9
+ public visited: Set<string>;
10
+ public tempMark: Set<string>;
11
+ public sortedEntities: string[];
12
+
13
+
14
+ constructor(entities: A_TYPES__A_StageStep[]) {
15
+ this.entities = entities;
16
+ this.graph = new Map();
17
+ this.visited = new Set();
18
+ this.tempMark = new Set();
19
+ this.sortedEntities = [];
20
+ }
21
+
22
+ private buildGraph() {
23
+ // Initialize graph nodes
24
+ this.entities.forEach(entity => this.graph.set(entity.name, new Set()));
25
+
26
+ // Add directed edges based on 'before' and 'after'
27
+ this.entities.forEach(entity => {
28
+ const { name, before = [], after = [] } = entity;
29
+
30
+ // Add edges for 'before' dependencies
31
+ before.forEach(dep => {
32
+ const targets = this.matchEntities(dep);
33
+ targets.forEach(target => {
34
+ if (!this.graph.has(target)) this.graph.set(target, new Set());
35
+ this.graph.get(target)!.add(name); // target -> name (target should be before name)
36
+ });
37
+ });
38
+
39
+ // Add edges for 'after' dependencies
40
+ after.forEach(dep => {
41
+ const sources = this.matchEntities(dep);
42
+ sources.forEach(source => {
43
+ if (!this.graph.has(name)) this.graph.set(name, new Set());
44
+ this.graph.get(name)!.add(source); // name -> source (name should be before source)
45
+ });
46
+ });
47
+ });
48
+ }
49
+
50
+ // Match entities by name or regex
51
+ private matchEntities(pattern) {
52
+ const regex = new RegExp(`^${pattern}$`);
53
+ return this.entities
54
+ .filter(entity => regex.test(entity.name))
55
+ .map(entity => entity.name);
56
+ }
57
+
58
+ // Topological sort with cycle detection
59
+ private visit(node) {
60
+ if (this.tempMark.has(node)) throw new Error("Circular dependency detected");
61
+
62
+ if (!this.visited.has(node)) {
63
+ this.tempMark.add(node);
64
+ (this.graph.get(node) || []).forEach(neighbor => this.visit(neighbor));
65
+ this.tempMark.delete(node);
66
+ this.visited.add(node);
67
+ this.sortedEntities.push(node);
68
+ }
69
+ }
70
+
71
+ // Sort the entities based on dependencies
72
+ toStages(feature: A_Feature): Array<A_Stage> {
73
+ this.buildGraph();
74
+
75
+ // Start topological sort
76
+ this.entities.forEach(entity => {
77
+ if (!this.visited.has(entity.name)) this.visit(entity.name);
78
+ });
79
+
80
+ const stages: A_Stage[] = [];
81
+
82
+ // Map sorted names back to entity objects
83
+ this.sortedEntities
84
+ .map(name => {
85
+
86
+ const step = this.entities.find(entity => entity.name === name)!;
87
+
88
+ let stage = stages.find(stage => {
89
+ return stage.after.every(after => step.after.includes(after))
90
+ && step.before.every(before => stage.after.includes(before));
91
+ });
92
+
93
+
94
+ if (!stage) {
95
+ stage = new A_Stage(feature);
96
+ stages.push(stage);
97
+ }
98
+
99
+ stage.add(step);
100
+ });
101
+
102
+ return stages;
103
+ }
104
+ }