@adaas/a-concept 0.0.56 → 0.0.58

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 (104) hide show
  1. package/.nvmrc +1 -1
  2. package/dist/src/base/A-Command/A_Command.constants.d.ts +12 -0
  3. package/dist/src/base/A-Command/A_Command.constants.js +17 -0
  4. package/dist/src/base/A-Command/A_Command.constants.js.map +1 -0
  5. package/dist/src/base/A-Command/A_Command.entity.d.ts +123 -0
  6. package/dist/src/base/A-Command/A_Command.entity.js +259 -0
  7. package/dist/src/base/A-Command/A_Command.entity.js.map +1 -0
  8. package/dist/src/base/A-Command/A_Command.types.d.ts +15 -0
  9. package/dist/src/base/A-Command/A_Command.types.js +3 -0
  10. package/dist/src/base/A-Command/A_Command.types.js.map +1 -0
  11. package/dist/src/base/A-Command/context/A_Command.context.d.ts +64 -0
  12. package/dist/src/base/A-Command/context/A_Command.context.js +85 -0
  13. package/dist/src/base/A-Command/context/A_Command.context.js.map +1 -0
  14. package/dist/src/base/A-Command/context/A_CommandFactory.context.js +2 -0
  15. package/dist/src/base/A-Command/context/A_CommandFactory.context.js.map +1 -0
  16. package/dist/src/base/A-Config/A-Config.container.d.ts +1 -2
  17. package/dist/src/base/A-Config/A-Config.container.js +2 -4
  18. package/dist/src/base/A-Config/A-Config.container.js.map +1 -1
  19. package/dist/src/base/A-Config/A-Config.context.d.ts +10 -11
  20. package/dist/src/base/A-Config/A-Config.context.js +5 -24
  21. package/dist/src/base/A-Config/A-Config.context.js.map +1 -1
  22. package/dist/src/base/A-Config/A-Config.types.d.ts +4 -4
  23. package/dist/src/base/A-Config/A-Config.types.js.map +1 -1
  24. package/dist/src/base/A-Config/components/ConfigReader.component.js +6 -12
  25. package/dist/src/base/A-Config/components/ConfigReader.component.js.map +1 -1
  26. package/dist/src/base/A-Config/components/ENVConfigReader.component.js +5 -1
  27. package/dist/src/base/A-Config/components/ENVConfigReader.component.js.map +1 -1
  28. package/dist/src/constants/env.constants.d.ts +26 -0
  29. package/dist/src/constants/env.constants.js +40 -0
  30. package/dist/src/constants/env.constants.js.map +1 -0
  31. package/dist/src/decorators/A-Inject/A-Inject.decorator.d.ts +3 -3
  32. package/dist/src/decorators/A-Inject/A-Inject.decorator.types.d.ts +9 -10
  33. package/dist/src/global/A-Channel/A-Channel.class.d.ts +2 -0
  34. package/dist/src/global/A-Channel/A-Channel.class.js +2 -0
  35. package/dist/src/global/A-Channel/A-Channel.class.js.map +1 -1
  36. package/dist/src/global/A-Concept/A_Concept.class.d.ts +5 -3
  37. package/dist/src/global/A-Concept/A_Concept.class.js +32 -27
  38. package/dist/src/global/A-Concept/A_Concept.class.js.map +1 -1
  39. package/dist/src/global/A-Concept/A_Concept.meta.d.ts +1 -8
  40. package/dist/src/global/A-Concept/A_Concept.meta.js +1 -25
  41. package/dist/src/global/A-Concept/A_Concept.meta.js.map +1 -1
  42. package/dist/src/global/A-Concept/A_Concept.types.d.ts +10 -1
  43. package/dist/src/global/A-Container/A-Container.class.d.ts +5 -0
  44. package/dist/src/global/A-Container/A-Container.class.js +5 -0
  45. package/dist/src/global/A-Container/A-Container.class.js.map +1 -1
  46. package/dist/src/global/A-Context/A-Context.class.d.ts +23 -1
  47. package/dist/src/global/A-Context/A-Context.class.js +38 -1
  48. package/dist/src/global/A-Context/A-Context.class.js.map +1 -1
  49. package/dist/src/global/A-Entity/A-Entity.class.d.ts +124 -23
  50. package/dist/src/global/A-Entity/A-Entity.class.js +159 -49
  51. package/dist/src/global/A-Entity/A-Entity.class.js.map +1 -1
  52. package/dist/src/global/A-Scope/A-Scope.class.d.ts +7 -6
  53. package/dist/src/global/A-Scope/A-Scope.class.js +57 -20
  54. package/dist/src/global/A-Scope/A-Scope.class.js.map +1 -1
  55. package/dist/src/global/A-Stage/A-Stage.class.d.ts +3 -2
  56. package/dist/src/global/A-Stage/A-Stage.class.js +9 -6
  57. package/dist/src/global/A-Stage/A-Stage.class.js.map +1 -1
  58. package/dist/src/global/A-Stage/A-Stage.types.d.ts +1 -1
  59. package/dist/src/helpers/StepsManager.class.js +1 -1
  60. package/dist/src/helpers/StepsManager.class.js.map +1 -1
  61. package/examples/simple/components/A.component.ts +9 -2
  62. package/examples/simple/concept.ts +6 -0
  63. package/examples/simple/entities/EntityA.entity.ts +18 -0
  64. package/jest.config.ts +1 -1
  65. package/package.json +3 -3
  66. package/src/base/A-Command/A_Command.constants.ts +20 -0
  67. package/src/base/A-Command/A_Command.entity.ts +287 -0
  68. package/src/base/A-Command/A_Command.types.ts +34 -0
  69. package/src/base/A-Command/context/A_Command.context.ts +114 -0
  70. package/src/base/A-Command/context/A_CommandFactory.context.ts +0 -0
  71. package/src/base/A-Config/A-Config.container.ts +0 -1
  72. package/src/base/A-Config/A-Config.context.ts +22 -28
  73. package/src/base/A-Config/A-Config.types.ts +5 -24
  74. package/src/base/A-Config/components/ConfigReader.component.ts +6 -15
  75. package/src/base/A-Config/components/ENVConfigReader.component.ts +6 -1
  76. package/src/constants/env.constants.ts +44 -0
  77. package/src/decorators/A-Inject/A-Inject.decorator.ts +3 -3
  78. package/src/decorators/A-Inject/A-Inject.decorator.types.ts +10 -9
  79. package/src/global/A-Channel/A-Channel.class.ts +2 -0
  80. package/src/global/A-Concept/A_Concept.class.ts +49 -32
  81. package/src/global/A-Concept/A_Concept.meta.ts +3 -41
  82. package/src/global/A-Concept/A_Concept.types.ts +6 -4
  83. package/src/global/A-Container/A-Container.class.ts +5 -2
  84. package/src/global/A-Context/A-Context.class.ts +67 -8
  85. package/src/global/A-Entity/A-Entity.class.ts +203 -73
  86. package/src/global/A-Scope/A-Scope.class.ts +88 -39
  87. package/src/global/A-Stage/A-Stage.class.ts +11 -7
  88. package/src/global/A-Stage/A-Stage.types.ts +1 -1
  89. package/src/helpers/StepsManager.class.ts +2 -2
  90. package/tests/A-Command.test.ts +130 -0
  91. package/tests/A-Component.test.ts +25 -0
  92. package/tests/A-Config.test.ts +106 -0
  93. package/tests/A-Entity.test.ts +191 -0
  94. package/tests/A-Feature.test.ts +131 -0
  95. package/tests/A-Scope.test.ts +163 -0
  96. package/dist/src/constants/A_ConceptLifecycle.constants.js +0 -11
  97. package/dist/src/constants/A_ConceptLifecycle.constants.js.map +0 -1
  98. package/src/constants/A_ConceptLifecycle.constants.ts +0 -12
  99. package/tests/channel.ts +0 -213
  100. package/tests/context.test.ts +0 -124
  101. package/tests/default.test.ts +0 -159
  102. package/tests/log.ts +0 -102
  103. package/tests/polyfill.test.ts +0 -37
  104. /package/dist/src/{constants/A_ConceptLifecycle.constants.d.ts → base/A-Command/context/A_CommandFactory.context.d.ts} +0 -0
@@ -9,6 +9,7 @@ import { A_Component } from "../A-Component/A-Component.class";
9
9
  import { A_Entity } from "../A-Entity/A-Entity.class";
10
10
  import {
11
11
  A_TYPES__A_InjectDecorator_EntityInjectionInstructions,
12
+ A_TYPES__A_InjectDecorator_EntityInjectionQuery,
12
13
  A_TYPES__A_InjectDecorator_Injectable
13
14
  } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator.types";
14
15
 
@@ -176,20 +177,20 @@ export class A_Scope {
176
177
  * @param component
177
178
  * @returns
178
179
  */
179
- has(
180
- component: typeof A_Component
180
+ has<T extends A_Component>(
181
+ component: new (...args: any[]) => T
181
182
  ): boolean
182
- has(
183
- entity: typeof A_Entity
183
+ has<T extends A_Entity>(
184
+ entity: new (...args: any[]) => T
184
185
  ): boolean
185
- has(
186
- fragment: typeof A_Fragment
186
+ has<T extends A_Fragment>(
187
+ fragment: new (...args: any[]) => T
187
188
  ): boolean
188
189
  has(
189
190
  constructor: string
190
191
  ): boolean
191
- has(
192
- entity: typeof A_Fragment | typeof A_Component | typeof A_Entity | string
192
+ has<T extends A_Fragment | A_Component | A_Entity>(
193
+ entity: T | string | (new (...args: any[]) => T)
193
194
  ): boolean {
194
195
 
195
196
 
@@ -218,31 +219,35 @@ export class A_Scope {
218
219
  return false;
219
220
  }
220
221
 
221
- case A_CommonHelper.isInheritedFrom(entity, A_Component): {
222
- const found = this.params.components.includes(entity as { new(...args: any[]): A_Component });
222
+ case typeof entity === 'function'
223
+ && A_CommonHelper.isInheritedFrom(entity, A_Component): {
224
+ const found = this.params.components.includes(entity as { new(...args: any[]): A_Component });
223
225
 
224
- if (!found && !!this._parent)
225
- return this._parent.has(entity as any);
226
+ if (!found && !!this._parent) {
227
+ return this._parent.has(entity as any);
228
+ }
226
229
 
227
- return found;
228
- }
230
+ return found;
231
+ }
229
232
 
230
- case A_CommonHelper.isInheritedFrom(entity, A_Entity): {
231
- const entities = Array.from(this._entities.values());
233
+ case typeof entity === 'function'
234
+ && A_CommonHelper.isInheritedFrom(entity, A_Entity): {
235
+ const entities = Array.from(this._entities.values());
232
236
 
233
- const found = entities.find(e => e instanceof entity);
237
+ const found = entities.find(e => e instanceof entity);
234
238
 
235
- return !!found;
236
- }
239
+ return !!found;
240
+ }
237
241
 
238
- case A_CommonHelper.isInheritedFrom(entity, A_Fragment): {
239
- const found = this._fragments.has(entity);
242
+ case typeof entity === 'function'
243
+ && A_CommonHelper.isInheritedFrom(entity, A_Fragment): {
244
+ const found = this._fragments.has(entity);
240
245
 
241
- if (!found && !!this._parent)
242
- return this._parent.has(entity as any);
246
+ if (!found && !!this._parent)
247
+ return this._parent.has(entity as any);
243
248
 
244
- return found;
245
- }
249
+ return found;
250
+ }
246
251
 
247
252
  default: {
248
253
  return false;
@@ -251,7 +256,6 @@ export class A_Scope {
251
256
  }
252
257
 
253
258
 
254
-
255
259
  /**
256
260
  * Merges two scopes into a new one
257
261
  *
@@ -300,10 +304,10 @@ export class A_Scope {
300
304
  resolve<T extends A_TYPES__A_InjectDecorator_Injectable>(
301
305
  component: T
302
306
  ): InstanceType<T>
303
- resolve<T extends { new(...args: any[]): A_Entity }>(
304
- entity: T,
305
- instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
306
- ): InstanceType<T>
307
+ resolve<T extends A_Entity>(
308
+ entity: { new(...args: any[]): T },
309
+ instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<T>>
310
+ ): T | Array<T>
307
311
  resolve<T extends A_TYPES__A_InjectDecorator_Injectable>(
308
312
  component: Array<T>
309
313
  ): Array<InstanceType<T>>
@@ -313,6 +317,7 @@ export class A_Scope {
313
317
  param2?: string | Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
314
318
  ): Array<InstanceType<T>> | InstanceType<T> {
315
319
 
320
+
316
321
  switch (true) {
317
322
  case Array.isArray(param1): {
318
323
  return param1.map(c => this.resolveOnce(param1 as any, param2 as any));
@@ -372,7 +377,7 @@ export class A_Scope {
372
377
 
373
378
  switch (true) {
374
379
  case A_CommonHelper.isInheritedFrom(component, A_Entity): {
375
- return this.resolveEntity(component as typeof A_Entity, instructions) as InstanceType<T>;
380
+ return this.resolveEntity(component as any, instructions) as InstanceType<T>;
376
381
  }
377
382
 
378
383
  case A_CommonHelper.isInheritedFrom(component, A_Fragment): {
@@ -395,18 +400,18 @@ export class A_Scope {
395
400
 
396
401
  private resolveEntity<T extends { new(...args: any[]): A_Entity }>(
397
402
  entity: T,
398
- instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
399
- ): InstanceType<T> | undefined {
403
+ instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<InstanceType<T>>>
404
+ ): InstanceType<T> | undefined | InstanceType<T>[] {
400
405
 
401
- const query = instructions?.query || {};
406
+ const query = instructions?.query || {} as Partial<A_TYPES__A_InjectDecorator_EntityInjectionQuery<InstanceType<T>>>;
402
407
  const count = instructions?.pagination?.count || 1;
403
408
 
404
-
405
409
  switch (true) {
406
410
  case !instructions: {
407
411
 
408
412
  const entities = Array.from(this._entities.values());
409
413
 
414
+
410
415
  const found = entities.find(e => e instanceof entity);
411
416
 
412
417
  switch (true) {
@@ -417,7 +422,7 @@ export class A_Scope {
417
422
  return this._parent.resolveEntity(entity, instructions);
418
423
 
419
424
  default:
420
- throw new Error(`Fragment ${entity.name} not found in the scope ${this.name}`);
425
+ throw new Error(`Entity ${entity.name} not found in the scope ${this.name}`);
421
426
  }
422
427
  }
423
428
 
@@ -428,6 +433,7 @@ export class A_Scope {
428
433
  }
429
434
 
430
435
  case !!query.aseid
436
+ && typeof query.aseid === 'object'
431
437
  && query.aseid instanceof ASEID
432
438
  && this._entities.has(query.aseid.toString()): {
433
439
  return this._entities.get(query.aseid.toString()) as InstanceType<T>;
@@ -447,8 +453,29 @@ export class A_Scope {
447
453
  return found as InstanceType<T>;
448
454
  }
449
455
 
450
- default:
451
- throw new Error(`Entity ${entity.constructor.name} not found in the scope ${this.name}`);
456
+ default: {
457
+ const entities = Array.from(this._entities.values());
458
+
459
+ const found = entities.filter(
460
+ e => e instanceof entity
461
+ ).filter(e => {
462
+ return Object.entries(query).every(([key, value]) => {
463
+ if (key in e) {
464
+ return (e as any)[key] === value;
465
+ }
466
+ return false;
467
+ });
468
+ });
469
+
470
+ if (found.length === 0 && !!this._parent)
471
+ return this._parent.resolveEntity(entity, instructions);
472
+
473
+ if (count === 1)
474
+ return found[0] as InstanceType<T>;
475
+
476
+ return found as InstanceType<T>[];
477
+ }
478
+
452
479
  }
453
480
  }
454
481
 
@@ -458,6 +485,7 @@ export class A_Scope {
458
485
 
459
486
  const fragmentInstancePresented = this.fragments.some(fr => fr instanceof fragment);
460
487
 
488
+
461
489
  switch (true) {
462
490
 
463
491
  case fragmentInstancePresented && this._fragments.has(fragment):
@@ -543,13 +571,27 @@ export class A_Scope {
543
571
  *
544
572
  * @param fragment
545
573
  */
574
+ register<T extends A_Component>(component: new (...args: any[]) => T): void
546
575
  register(entity: A_Entity): void
547
576
  register(component: A_Component): void
548
577
  register(fragment: A_Fragment): void
549
578
  register(
550
- param1: A_Fragment | A_Component | A_Entity
579
+ param1: A_Fragment | A_Component | A_Entity | (new (...args: any[]) => A_Component)
551
580
  ): void {
552
581
  switch (true) {
582
+ case param1 instanceof A_Component && !this._components.has(param1.constructor): {
583
+ this._components.set(param1.constructor, param1);
584
+
585
+ const allowedComponent = this.components.find(c => c === param1.constructor);
586
+
587
+ if (!allowedComponent) {
588
+ this.components.push(param1.constructor as any);
589
+ }
590
+
591
+ A_Context.register(this, param1);
592
+ break;
593
+ }
594
+
553
595
  case param1 instanceof A_Entity && !this._entities.has(param1.aseid.toString()): {
554
596
  this._entities.set(param1.aseid.toString(), param1);
555
597
  A_Context.register(this, param1);
@@ -581,6 +623,13 @@ export class A_Scope {
581
623
  break;
582
624
  }
583
625
 
626
+ case typeof param1 === 'function' && A_CommonHelper.isInheritedFrom(param1, A_Component): {
627
+ const allowedComponent = this.components.find(c => c === param1);
628
+
629
+ if (!allowedComponent)
630
+ this.components.push(param1);
631
+ break;
632
+ }
584
633
  default:
585
634
  if (param1 instanceof A_Entity)
586
635
  throw new Error(`Entity with ASEID ${param1.aseid.toString()} is already registered in the scope ${this.name}`);
@@ -6,6 +6,7 @@ import { A_Container } from "../A-Container/A-Container.class";
6
6
  import { A_Scope } from "../A-Scope/A-Scope.class";
7
7
  import { A_StageError } from "./A-Stage.error";
8
8
  import { A_FeatureCaller } from "../A-Feature/A-FeatureCaller.class";
9
+ import { A_Entity } from "../A-Entity/A-Entity.class";
9
10
 
10
11
 
11
12
  /**
@@ -30,10 +31,10 @@ export class A_Stage {
30
31
  this._steps = _steps;
31
32
  this.name = `${this.feature.name}::a-stage:[sync:${this
32
33
  .syncSteps
33
- .map(s => s.component.name + '.' + s.handler)
34
+ .map(s => typeof s.component === 'string' ? s.component : s.component.name + '.' + s.handler)
34
35
  .join(' -> ')}][async:${this
35
36
  .asyncSteps
36
- .map(s => s.component.name + '.' + s.handler)
37
+ .map(s => typeof s.component === 'string' ? s.component : s.component.name + '.' + s.handler)
37
38
  .join(' -> ')}]`;
38
39
 
39
40
  }
@@ -87,9 +88,11 @@ export class A_Stage {
87
88
  return Promise
88
89
  .all(A_Context
89
90
  .meta(
90
- step.component instanceof A_Container
91
+ // TODO: fix types
92
+ (step.component instanceof A_Container
91
93
  ? step.component.constructor
92
- : step.component
94
+ : step.component) as any
95
+
93
96
  )
94
97
  .injections(step.handler)
95
98
  .map(async arg => {
@@ -100,7 +103,7 @@ export class A_Stage {
100
103
  if (A_CommonHelper.isInheritedFrom(arg.target, A_Feature))
101
104
  return this.feature;
102
105
 
103
- return scope.resolve(arg.target)
106
+ return scope.resolve((arg as any).target, (arg as any).instructions)
104
107
  })
105
108
  )
106
109
  }
@@ -134,10 +137,11 @@ export class A_Stage {
134
137
  // TODO: probably would be better to do it another way. let's think about it
135
138
  const instance = component instanceof A_Container
136
139
  ? component
137
- : this.feature.Scope.resolve(component);
140
+ // TODO: fix types
141
+ : this.feature.Scope.resolve(component as any);
138
142
 
139
143
  if (!instance)
140
- throw new Error(`Unable to resolve component ${component.name}`);
144
+ throw new Error(`Unable to resolve component ${typeof component === 'string' ? component : component.name} from scope ${this.feature.Scope.name}`);
141
145
 
142
146
  if (!instance[handler])
143
147
  throw new Error(`Handler ${handler} not found in ${instance.constructor.name}`);
@@ -67,7 +67,7 @@ export type A_TYPES__A_StageStep = {
67
67
  /**
68
68
  * The component to be called
69
69
  */
70
- component: typeof A_Component | A_Container
70
+ component: typeof A_Component | A_Container | string
71
71
 
72
72
  /**
73
73
  * The method to be called on the component
@@ -21,7 +21,7 @@ export class StepsManager {
21
21
  }
22
22
 
23
23
  private ID(step: A_TYPES__A_StageStep) {
24
- return `${step.component.name}.${step.handler}`;
24
+ return `${typeof step.component === 'string' ? step.component : step.component.name}.${step.handler}`;
25
25
  }
26
26
 
27
27
  private buildGraph() {
@@ -103,7 +103,7 @@ export class StepsManager {
103
103
  stage.add(step);
104
104
  });
105
105
 
106
- return stages.map(stage => new A_Stage(feature, stage.steps) );
106
+ return stages.map(stage => new A_Stage(feature, stage.steps));
107
107
  }
108
108
  }
109
109
 
@@ -0,0 +1,130 @@
1
+
2
+
3
+
4
+ import { A_CONSTANTS__A_Command_Status, A_CONSTANTS_A_Command_Features } from "@adaas/a-concept/base/A-Command/A_Command.constants";
5
+ import { A_Command } from "@adaas/a-concept/base/A-Command/A_Command.entity";
6
+ import { A_CommandContext } from "@adaas/a-concept/base/A-Command/context/A_Command.context";
7
+ import { A_Inject } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator";
8
+ import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
9
+ import { A_Feature } from "@adaas/a-concept/global/A-Feature/A-Feature.class";
10
+ import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
11
+ import { A_Error } from "@adaas/a-utils";
12
+
13
+ jest.retryTimes(0);
14
+
15
+ describe('A-Command tests', () => {
16
+
17
+ it('Should Allow to create a command', async () => {
18
+ const command = new A_Command({});
19
+ expect(command).toBeInstanceOf(A_Command);
20
+ expect(command.Code).toBe('A_Command');
21
+ expect(command.id).toBeDefined();
22
+ expect(command.aseid).toBeDefined();
23
+ expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.INITIALIZED);
24
+ expect(command.Scope).toBeInstanceOf(A_Scope);
25
+ expect(command.Scope.resolve(A_CommandContext)).toBeInstanceOf(A_CommandContext);
26
+ });
27
+ it('Should allow to execute a command', async () => {
28
+ const command = new A_Command({});
29
+
30
+ await command.execute();
31
+
32
+ expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.COMPLETED);
33
+ expect(command.StartedAt).toBeInstanceOf(Date);
34
+ expect(command.EndedAt).toBeInstanceOf(Date);
35
+ });
36
+ it('Should allow to serialize and deserialize a command', async () => {
37
+ const command = new A_Command({});
38
+
39
+ await command.execute();
40
+
41
+ const serialized = command.toJSON();
42
+ expect(serialized).toBeDefined();
43
+ expect(serialized.aseid).toBe(command.aseid.toString());
44
+ expect(serialized.code).toBe(command.Code);
45
+ expect(serialized.status).toBe(command.Status);
46
+ expect(serialized.startedAt).toBe(command.StartedAt?.toISOString());
47
+ expect(serialized.duration).toBe(command.Duration);
48
+
49
+
50
+ const deserializedCommand = new A_Command(serialized);
51
+ expect(deserializedCommand).toBeInstanceOf(A_Command);
52
+ expect(deserializedCommand.aseid.toString()).toBe(command.aseid.toString());
53
+ expect(deserializedCommand.Code).toBe(command.Code);
54
+ expect(deserializedCommand.Status).toBe(command.Status);
55
+ expect(deserializedCommand.StartedAt?.toISOString()).toBe(command.StartedAt?.toISOString());
56
+ expect(deserializedCommand.Duration).toBe(command.Duration);
57
+ });
58
+ it('Should allow to execute a command with custom logic', async () => {
59
+
60
+ // 1) create a scope
61
+ const scope = new A_Scope({ name: 'TestScope' });
62
+ // 2) create a new command
63
+ type resultType = { bar: string };
64
+ type invokeType = { foo: string };
65
+ class MyCommand extends A_Command<invokeType, resultType> { }
66
+
67
+ // 3) create a custom component with custom logic
68
+ class MyComponent extends A_Component {
69
+
70
+ @A_Feature.Extend({ scope: [MyCommand] })
71
+ async [A_CONSTANTS_A_Command_Features.EXECUTE](
72
+ @A_Inject(A_CommandContext) context: A_CommandContext<resultType>
73
+ ) {
74
+ context.save('bar', 'baz');
75
+ }
76
+ }
77
+
78
+ // 4) register component in the scope
79
+ scope.register(MyComponent);
80
+
81
+ // 5) create a new command instance within the scope
82
+ const command = new MyCommand({ foo: 'bar' });
83
+ scope.register(command);
84
+
85
+ // 6) execute the command
86
+ await command.execute();
87
+
88
+ // 7) verify that command was executed with custom logic from MyComponent
89
+ expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.COMPLETED);
90
+ expect(command.Result).toBeDefined();
91
+ expect(command.Result).toEqual({ bar: 'baz' });
92
+ })
93
+ it('Should allow to fail a command with custom logic', async () => {
94
+
95
+ // 1) create a scope
96
+ const scope = new A_Scope({ name: 'TestScope' });
97
+ // 2) create a new command
98
+ type resultType = { bar: string };
99
+ type invokeType = { foo: string };
100
+ class MyCommand extends A_Command<invokeType, resultType> { }
101
+
102
+ // 3) create a custom component with custom logic
103
+ class MyComponent extends A_Component {
104
+
105
+ @A_Feature.Extend({ scope: [MyCommand] })
106
+ async [A_CONSTANTS_A_Command_Features.EXECUTE](
107
+ @A_Inject(A_CommandContext) context: A_CommandContext<resultType>
108
+ ) {
109
+ context.error(new A_Error({ message: 'Test error' }));
110
+ // it's optional to throw an error here, as the command may contain multiple errors that also can be a result of async operations
111
+ throw new A_Error({ message: 'Test error thrown' });
112
+ }
113
+ }
114
+
115
+ // 4) register component in the scope
116
+ scope.register(MyComponent);
117
+ // 5) create a new command instance within the scope
118
+ const command = new MyCommand({ foo: 'bar' });
119
+ scope.register(command);
120
+
121
+ // 6) execute the command
122
+ await command.execute();
123
+
124
+ // 7) verify that command was executed with custom logic from MyComponent
125
+ expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.FAILED);
126
+ expect(command.Errors).toBeDefined();
127
+ expect(command.Errors?.size).toBe(1);
128
+ expect(Array.from(command.Errors?.values() || [])[0].message).toBe('Test error');
129
+ });
130
+ });
@@ -0,0 +1,25 @@
1
+ import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
2
+
3
+ jest.retryTimes(0);
4
+
5
+ describe('A-Component tests', () => {
6
+
7
+ it('Should Allow to create a component', async () => {
8
+ const component = new A_Component();
9
+ });
10
+ it('Should Allow to create a component with dependencies', async () => {
11
+ class DependentComponent extends A_Component {
12
+ constructor(
13
+ public dependency: A_Component
14
+ ) {
15
+ super();
16
+ }
17
+ }
18
+
19
+ const component = new A_Component();
20
+ const dependentComponent = new DependentComponent(component);
21
+ expect(dependentComponent.dependency).toBe(component);
22
+ });
23
+
24
+
25
+ });
@@ -0,0 +1,106 @@
1
+ import { A_ConfigLoader } from "@adaas/a-concept/base/A-Config/A-Config.container";
2
+ import { A_Config } from "@adaas/a-concept/base/A-Config/A-Config.context";
3
+ import { ENVConfigReader } from "@adaas/a-concept/base/A-Config/components/ENVConfigReader.component";
4
+ import { A_CONSTANTS__DEFAULT_ENV_VARIABLES } from "@adaas/a-concept/constants/env.constants";
5
+ import { A_Context } from "@adaas/a-concept/global/A-Context/A-Context.class";
6
+ import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
7
+
8
+ jest.retryTimes(0);
9
+
10
+ describe('A-Config tests', () => {
11
+ it('Should Allow to create a config object', async () => {
12
+ const config = new A_Config({
13
+ variables: [],
14
+ defaults: {}
15
+ });
16
+ });
17
+ it('Should Allow to create a config object with default values', async () => {
18
+ const config = new A_Config({
19
+ variables: ['TEST_VAR1', 'TEST_VAR2'] as const,
20
+ defaults: {
21
+ TEST_VAR1: 'default1',
22
+ }
23
+ });
24
+
25
+ expect(config.get('TEST_VAR1')).toBe('default1');
26
+ expect(config.get('TEST_VAR2')).toBeUndefined();
27
+ });
28
+ it('Should Allow to create a config object with ENV values', async () => {
29
+ process.env['A_CONCEPT_TEST_VAR1'] = 'env1';
30
+ process.env['A_CONCEPT_TEST_VAR2'] = 'env2';
31
+
32
+ const config = new A_Config({
33
+ variables: ['TEST_VAR1', 'TEST_VAR2'] as const,
34
+ defaults: {
35
+ TEST_VAR1: 'default1',
36
+ }
37
+ });
38
+
39
+ const configLoader = new A_ConfigLoader({
40
+ name: 'test-config-loader',
41
+ fragments: [config],
42
+ components: [ENVConfigReader]
43
+ })
44
+
45
+ await configLoader.prepare(config as any);
46
+ await configLoader.readVariables(config as any);
47
+
48
+
49
+
50
+ expect(config.get('TEST_VAR1')).toBe('env1');
51
+ expect(config.get('TEST_VAR2')).toBe('env2');
52
+
53
+ delete process.env['A_CONCEPT_TEST_VAR1'];
54
+ delete process.env['A_CONCEPT_TEST_VAR2'];
55
+ });
56
+ it('Should not Change Names of default env variables', async () => {
57
+ process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAMESPACE] = 'my-project';
58
+ process.env['MY_PROJECT_TEST_VAR2'] = 'env2';
59
+
60
+ A_Context.reset();
61
+
62
+
63
+ const config = new A_Config({
64
+ variables: ['TEST_VAR1', 'TEST_VAR2'] as const,
65
+ defaults: {
66
+ TEST_VAR1: 'default1',
67
+ }
68
+ });
69
+
70
+ const configLoader = new A_ConfigLoader({
71
+ name: 'test-config-loader',
72
+ fragments: [config],
73
+ components: [ENVConfigReader]
74
+ })
75
+
76
+
77
+ await configLoader.prepare(config as any);
78
+ await configLoader.readVariables(config as any);
79
+
80
+
81
+ expect(config.get('TEST_VAR1')).toBe('default1');
82
+ expect(config.get('TEST_VAR2')).toBe('env2');
83
+ expect(config.get('A_CONCEPT_NAMESPACE')).toBe('my-project');
84
+
85
+ delete process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAMESPACE];
86
+ delete process.env['TEST_VAR2'];
87
+
88
+ // then reset context root
89
+ A_Context.reset();
90
+
91
+ });
92
+ it('Should Throw an error if strict is true and variable is not defined', async () => {
93
+ expect(() => {
94
+ const config = new A_Config({
95
+ strict: true,
96
+ variables: ['TEST_VAR1', 'TEST_VAR2'] as const,
97
+ defaults: {
98
+ TEST_VAR1: 'default1',
99
+ }
100
+ });
101
+
102
+ config.get('TEST_VAR3' as any);
103
+
104
+ }).toThrowError();
105
+ });
106
+ });