@adaas/a-concept 0.0.60 → 0.0.62

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 (79) hide show
  1. package/dist/index.d.ts +4 -4
  2. package/dist/index.js +5 -5
  3. package/dist/index.js.map +1 -1
  4. package/dist/src/base/A-Config/A-Config.container.js +2 -2
  5. package/dist/src/base/A-Config/A-Config.container.js.map +1 -1
  6. package/dist/src/base/A-Config/A-Config.context.js +3 -3
  7. package/dist/src/base/A-Config/A-Config.context.js.map +1 -1
  8. package/dist/src/base/A-Config/components/ENVConfigReader.component.js +1 -5
  9. package/dist/src/base/A-Config/components/ENVConfigReader.component.js.map +1 -1
  10. package/dist/src/base/A-Config/components/FileConfigReader.component.js +2 -1
  11. package/dist/src/base/A-Config/components/FileConfigReader.component.js.map +1 -1
  12. package/dist/src/decorators/A-Feature/A-Feature-Define.decorator.d.ts +2 -1
  13. package/dist/src/decorators/A-Feature/A-Feature-Define.decorator.js +9 -2
  14. package/dist/src/decorators/A-Feature/A-Feature-Define.decorator.js.map +1 -1
  15. package/dist/src/{base/A-Command/A_Command.entity.d.ts → global/A-Command/A-Command.class.d.ts} +72 -10
  16. package/dist/src/{base/A-Command/A_Command.entity.js → global/A-Command/A-Command.class.js} +119 -46
  17. package/dist/src/global/A-Command/A-Command.class.js.map +1 -0
  18. package/dist/src/{base/A-Command/A_Command.constants.js → global/A-Command/A-Command.constants.js} +1 -1
  19. package/dist/src/global/A-Command/A-Command.constants.js.map +1 -0
  20. package/dist/src/global/A-Command/A-Command.meta.d.ts +11 -0
  21. package/dist/src/global/A-Command/A-Command.meta.js +18 -0
  22. package/dist/src/global/A-Command/A-Command.meta.js.map +1 -0
  23. package/dist/src/global/A-Command/A-Command.types.d.ts +43 -0
  24. package/dist/src/global/A-Command/A-Command.types.js +10 -0
  25. package/dist/src/global/A-Command/A-Command.types.js.map +1 -0
  26. package/dist/src/{base → global}/A-Command/context/A_Command.context.d.ts +1 -1
  27. package/dist/src/{base → global}/A-Command/context/A_Command.context.js +1 -1
  28. package/dist/src/global/A-Command/context/A_Command.context.js.map +1 -0
  29. package/dist/src/global/A-Concept/A_Concept.class.js +2 -0
  30. package/dist/src/global/A-Concept/A_Concept.class.js.map +1 -1
  31. package/dist/src/global/A-Concept/A_Concept.types.d.ts +10 -0
  32. package/dist/src/global/A-Concept/A_Concept.types.js.map +1 -1
  33. package/dist/src/global/A-Context/A-Context.class.d.ts +3 -1
  34. package/dist/src/global/A-Context/A-Context.class.js +16 -6
  35. package/dist/src/global/A-Context/A-Context.class.js.map +1 -1
  36. package/dist/src/global/A-Entity/A-Entity.class.js +1 -4
  37. package/dist/src/global/A-Entity/A-Entity.class.js.map +1 -1
  38. package/dist/src/global/A-Feature/A-FeatureCaller.class.d.ts +4 -3
  39. package/dist/src/global/A-Feature/A-FeatureCaller.class.js.map +1 -1
  40. package/dist/src/global/A-Scope/A-Scope.class.d.ts +15 -1
  41. package/dist/src/global/A-Scope/A-Scope.class.js +59 -5
  42. package/dist/src/global/A-Scope/A-Scope.class.js.map +1 -1
  43. package/dist/src/global/A-Scope/A-Scope.types.d.ts +7 -0
  44. package/dist/src/global/A-Stage/A-Stage.class.d.ts +1 -1
  45. package/index.ts +4 -4
  46. package/package.json +2 -2
  47. package/src/base/A-Config/A-Config.container.ts +2 -2
  48. package/src/base/A-Config/A-Config.context.ts +6 -3
  49. package/src/base/A-Config/components/ENVConfigReader.component.ts +1 -6
  50. package/src/base/A-Config/components/FileConfigReader.component.ts +2 -1
  51. package/src/decorators/A-Feature/A-Feature-Define.decorator.ts +13 -6
  52. package/src/{base/A-Command/A_Command.entity.ts → global/A-Command/A-Command.class.ts} +149 -35
  53. package/src/global/A-Command/A-Command.meta.ts +22 -0
  54. package/src/global/A-Command/A-Command.types.ts +71 -0
  55. package/src/global/A-Concept/A_Concept.class.ts +3 -0
  56. package/src/global/A-Concept/A_Concept.types.ts +10 -0
  57. package/src/global/A-Context/A-Context.class.ts +23 -5
  58. package/src/global/A-Entity/A-Entity.class.ts +1 -4
  59. package/src/global/A-Feature/A-FeatureCaller.class.ts +4 -3
  60. package/src/global/A-Scope/A-Scope.class.ts +77 -9
  61. package/src/global/A-Scope/A-Scope.types.ts +7 -0
  62. package/tests/A-Command.test.ts +16 -13
  63. package/tests/A-Component.test.ts +2 -0
  64. package/tests/A-Concept.test.ts +112 -0
  65. package/tests/A-Config.test.ts +72 -6
  66. package/tests/A-Entity.test.ts +2 -0
  67. package/tests/A-Feature.test.ts +2 -0
  68. package/tests/A-Scope.test.ts +47 -4
  69. package/tests/test.setup.ts +30 -0
  70. package/dist/src/base/A-Command/A_Command.constants.js.map +0 -1
  71. package/dist/src/base/A-Command/A_Command.entity.js.map +0 -1
  72. package/dist/src/base/A-Command/A_Command.types.d.ts +0 -15
  73. package/dist/src/base/A-Command/A_Command.types.js +0 -3
  74. package/dist/src/base/A-Command/A_Command.types.js.map +0 -1
  75. package/dist/src/base/A-Command/context/A_Command.context.js.map +0 -1
  76. package/src/base/A-Command/A_Command.types.ts +0 -34
  77. /package/dist/src/{base/A-Command/A_Command.constants.d.ts → global/A-Command/A-Command.constants.d.ts} +0 -0
  78. /package/src/{base/A-Command/A_Command.constants.ts → global/A-Command/A-Command.constants.ts} +0 -0
  79. /package/src/{base → global}/A-Command/context/A_Command.context.ts +0 -0
@@ -106,6 +106,9 @@ export class A_Concept<
106
106
  if (props.entities && props.entities.length)
107
107
  props.entities.forEach(entity => this.Scope.register(entity))
108
108
 
109
+ if (props.commands && props.commands.length)
110
+ props.commands.forEach(command => this.Scope.register(command))
111
+
109
112
  this.containers = props.containers || [];
110
113
  }
111
114
 
@@ -4,6 +4,7 @@ import { A_Fragment } from "../A-Fragment/A-Fragment.class";
4
4
  import { A_Entity } from "../A-Entity/A-Entity.class";
5
5
  import { A_Component } from "../A-Component/A-Component.class";
6
6
  import { A_TYPES__A_ExtendDecorator_BehaviorConfig } from "@adaas/a-concept/decorators/A-Feature/A-Feature.decorator.types";
7
+ import { A_Command } from "../A-Command/A-Command.class";
7
8
 
8
9
 
9
10
  export enum A_TYPES__ConceptStage {
@@ -68,6 +69,15 @@ export interface A_TYPES__IConceptConstructor<
68
69
  * [!] Note that these components will be available in all containers and fragments in the concept.
69
70
  */
70
71
  components?: Array<{ new(...args: any[]): A_Component }>
72
+
73
+
74
+ /**
75
+ * A set of Commands available for all containers and fragments in the concept.
76
+ * These commands will be registered in the root scope of the concept.
77
+ *
78
+ * [!] Note that these commands will be available in all containers and fragments in the concept.
79
+ */
80
+ commands?: Array<{ new(...args: any[]): A_Command }>
71
81
  }
72
82
 
73
83
 
@@ -22,6 +22,8 @@ import { A_TYPES__ComponentMetaKey } from "../A-Component/A-Component.types";
22
22
  import { A_TYPES__ConceptStage } from "../A-Concept/A_Concept.types";
23
23
  import { A_TYPES__A_DefineDecorator_Meta } from "@adaas/a-concept/decorators/A-Feature/A-Feature.decorator.types";
24
24
  import { A_CONSTANTS__DEFAULT_ENV_VARIABLES } from "@adaas/a-concept/constants/env.constants";
25
+ import { A_Command } from "../A-Command/A-Command.class";
26
+ import { A_TYPES__CommandMetaKey } from "../A-Command/A-Command.types";
25
27
 
26
28
 
27
29
 
@@ -47,6 +49,9 @@ export class A_Context {
47
49
  protected features: WeakMap<A_Feature, A_Scope> = new WeakMap();
48
50
 
49
51
 
52
+ protected commands: WeakMap<A_Command, A_Scope> = new WeakMap();
53
+
54
+
50
55
  /**
51
56
  * Uses to store the scope of every element in the program.
52
57
  */
@@ -164,6 +169,11 @@ export class A_Context {
164
169
 
165
170
  break;
166
171
 
172
+ case param1 instanceof A_Command:
173
+ instance.commands.set(param1, newScope);
174
+
175
+ break;
176
+
167
177
  default:
168
178
  throw new Error(`[!] A-Concept Context: Unknown type of the parameter.`);
169
179
  }
@@ -356,6 +366,9 @@ export class A_Context {
356
366
  case param1 instanceof A_Fragment:
357
367
  return instance.registry.get(param1);
358
368
 
369
+ case param1 instanceof A_Command:
370
+ return instance.commands.get(param1);
371
+
359
372
  default:
360
373
  throw new Error(`[!] A-Concept Context: Unknown type of the parameter.`);
361
374
  }
@@ -444,10 +457,13 @@ export class A_Context {
444
457
  case component instanceof A_Container:
445
458
  metaKey = A_TYPES__ContainerMetaKey.FEATURES
446
459
  break;
447
- case component instanceof A_Component: {
460
+ case component instanceof A_Component:
448
461
  metaKey = A_TYPES__ComponentMetaKey.FEATURES
449
- }
450
462
  break;
463
+ case component instanceof A_Command:
464
+ metaKey = A_TYPES__CommandMetaKey.FEATURES
465
+ break;
466
+
451
467
  default:
452
468
  throw new Error(`A-Feature cannot be defined on the ${component} level`);
453
469
  }
@@ -499,7 +515,7 @@ export class A_Context {
499
515
  * @returns
500
516
  */
501
517
  static abstractionDefinition(
502
- component: A_Component | A_Container | A_Entity,
518
+ component: A_Component | A_Container | A_Entity | A_Command,
503
519
  abstraction: A_TYPES__ConceptStage,
504
520
  scope: A_Scope
505
521
  ): A_TYPES__FeatureConstructor {
@@ -516,9 +532,11 @@ export class A_Context {
516
532
  case component instanceof A_Container:
517
533
  metaKey = A_TYPES__ContainerMetaKey.ABSTRACTIONS
518
534
  break;
519
- case component instanceof A_Component: {
535
+ case component instanceof A_Component:
520
536
  metaKey = A_TYPES__ComponentMetaKey.ABSTRACTIONS
521
- }
537
+ break;
538
+ case component instanceof A_Command:
539
+ metaKey = A_TYPES__CommandMetaKey.ABSTRACTIONS
522
540
  break;
523
541
  default:
524
542
  throw new Error(`A-Feature cannot be defined on the ${component} level`);
@@ -36,10 +36,7 @@ export class A_Entity<
36
36
  * Entity Identifier that corresponds to the class name
37
37
  */
38
38
  static get entity(): string {
39
- return A_CommonHelper
40
- .toUpperSnakeCase(this.name)
41
- .toLocaleLowerCase()
42
- .replace(/_/g, '-');
39
+ return A_CommonHelper.toKebabCase(this.name);
43
40
  }
44
41
 
45
42
  /**
@@ -1,3 +1,4 @@
1
+ import { A_Command } from "../A-Command/A-Command.class";
1
2
  import { A_Component } from "../A-Component/A-Component.class";
2
3
  import { A_Container } from "../A-Container/A-Container.class";
3
4
  import { A_Feature } from "./A-Feature.class";
@@ -15,10 +16,10 @@ import { A_Feature } from "./A-Feature.class";
15
16
  export class A_FeatureCaller {
16
17
 
17
18
 
18
- protected _component: A_Component | A_Feature | A_Container;
19
+ protected _component: A_Component | A_Feature | A_Container | A_Command;
19
20
 
20
21
  constructor(
21
- component: A_Component | A_Feature | A_Container
22
+ component: A_Component | A_Feature | A_Container | A_Command
22
23
  ) {
23
24
  this._component = component;
24
25
  }
@@ -29,7 +30,7 @@ export class A_FeatureCaller {
29
30
  *
30
31
  * @returns
31
32
  */
32
- resolve(): A_Component | A_Feature | A_Container {
33
+ resolve(): A_Component | A_Feature | A_Container | A_Command {
33
34
  return this._component;
34
35
  }
35
36
 
@@ -12,6 +12,7 @@ import {
12
12
  A_TYPES__A_InjectDecorator_EntityInjectionQuery,
13
13
  A_TYPES__A_InjectDecorator_Injectable
14
14
  } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator.types";
15
+ import { A_Command } from "../A-Command/A-Command.class";
15
16
 
16
17
 
17
18
  /**
@@ -33,6 +34,7 @@ export class A_Scope {
33
34
 
34
35
  private _components: WeakMap<typeof A_Component.constructor, any> = new WeakMap();
35
36
  private _fragments: WeakMap<typeof A_Fragment.constructor, any> = new WeakMap();
37
+ private _commands: Map<string, A_Command> = new Map();
36
38
  private _entities: Map<string, A_Entity> = new Map();
37
39
 
38
40
  private _parent?: A_Scope;
@@ -52,6 +54,7 @@ export class A_Scope {
52
54
  components: [],
53
55
  fragments: [],
54
56
  entities: [],
57
+ commands: [],
55
58
  };
56
59
 
57
60
 
@@ -90,6 +93,10 @@ export class A_Scope {
90
93
  return this.params.components || [];
91
94
  }
92
95
 
96
+ get commands() {
97
+ return this.params.commands || [];
98
+ }
99
+
93
100
  get fragments() {
94
101
  return this.params.fragments || [];
95
102
  }
@@ -189,7 +196,7 @@ export class A_Scope {
189
196
  has(
190
197
  constructor: string
191
198
  ): boolean
192
- has<T extends A_Fragment | A_Component | A_Entity>(
199
+ has<T extends A_Fragment | A_Component | A_Entity | A_Command>(
193
200
  entity: T | string | (new (...args: any[]) => T)
194
201
  ): boolean {
195
202
 
@@ -221,7 +228,7 @@ export class A_Scope {
221
228
 
222
229
  case typeof entity === 'function'
223
230
  && A_CommonHelper.isInheritedFrom(entity, A_Component): {
224
- const found = this.params.components.includes(entity as { new(...args: any[]): A_Component });
231
+ const found = this.components.includes(entity as { new(...args: any[]): A_Component });
225
232
 
226
233
  if (!found && !!this._parent) {
227
234
  return this._parent.has(entity as any);
@@ -248,6 +255,16 @@ export class A_Scope {
248
255
 
249
256
  return found;
250
257
  }
258
+ case typeof entity === 'function'
259
+ && A_CommonHelper.isInheritedFrom(entity, A_Command): {
260
+ const found = this.commands.includes(entity as { new(...args: any[]): A_Command });
261
+
262
+ if (!found && !!this._parent)
263
+ return this._parent.has(entity as any);
264
+
265
+ return found;
266
+ }
267
+
251
268
 
252
269
  default: {
253
270
  return false;
@@ -295,19 +312,33 @@ export class A_Scope {
295
312
  /**
296
313
  * Allows to retrieve the constructor of the component or entity by its name
297
314
  *
315
+ * [!] Notes:
316
+ * - In case of search for A-Entity please ensure that provided string corresponds to the static entity property of the class. [!] By default it's the kebab-case of the class name
317
+ * - In case of search for A_Command please ensure that provided string corresponds to the static code property of the class. [!] By default it's the kebab-case of the class name
318
+ * - In case of search for A_Component please ensure that provided string corresponds to the class name in PascalCase
298
319
  *
299
320
  * @param name
300
321
  * @returns
301
322
  */
302
323
  resolveConstructor<T extends A_Component | A_Entity>(name: string): new (...args: any[]) => T {
303
324
  // Check components
304
- const component = this.params.components.find(c => c.name === name);
325
+ const component = this.params.components.find(c => c.name === A_CommonHelper.toPascalCase(name));
305
326
  if (component) return component as any;
306
327
 
307
328
  // Check entities
308
- const entity = this.params.entities.find(e => e.constructor.name === name);
329
+ const entity = this.params.entities.find(e => (e.constructor as any).entity === name
330
+ || (e.constructor as any).name === A_CommonHelper.toPascalCase(name)
331
+ || (e.constructor as any).entity === A_CommonHelper.toKebabCase(name)
332
+ );
309
333
  if (entity) return entity.constructor as any;
310
334
 
335
+ // Check commands
336
+ const command = this.params.commands.find(c => (c as any).code === name
337
+ || (c as any).name === A_CommonHelper.toPascalCase(name)
338
+ || (c as any).code === A_CommonHelper.toKebabCase(name)
339
+ );
340
+ if (command) return command as any;
341
+
311
342
  // If not found in current scope, check parent scope
312
343
  if (!!this._parent) {
313
344
  return this._parent.resolveConstructor(name);
@@ -371,6 +402,10 @@ export class A_Scope {
371
402
  const component = this.params.components.find(c => c.name === name);
372
403
  if (component) return this.resolveComponent(component);
373
404
 
405
+ // Check commands
406
+ const command = this.params.commands.find(c => c.name === name);
407
+ if (command) return this.resolveComponent(command);
408
+
374
409
  // Check fragments
375
410
  const fragment = this.params.fragments.find(f => f.constructor.name === name);
376
411
  if (fragment) return this.resolveFragment(fragment.constructor as any);
@@ -436,10 +471,8 @@ export class A_Scope {
436
471
 
437
472
  switch (true) {
438
473
  case !instructions: {
439
-
440
474
  const entities = Array.from(this._entities.values());
441
475
 
442
-
443
476
  const found = entities.find(e => e instanceof entity);
444
477
 
445
478
  switch (true) {
@@ -593,6 +626,31 @@ export class A_Scope {
593
626
  }
594
627
 
595
628
 
629
+ /**
630
+ * Should be similar to resolveEntity but for commands
631
+ *
632
+ * @param command
633
+ */
634
+ private resolveCommand<T extends A_Command>(command: {
635
+ new(...args: any[]): T
636
+ }): T {
637
+ const commands = Array.from(this._commands.values());
638
+
639
+ const found = commands.find(e => e instanceof command);
640
+
641
+ switch (true) {
642
+ case !!found:
643
+ return found as T;
644
+
645
+ case !found && !!this._parent:
646
+ return this._parent.resolveCommand(command);
647
+
648
+ default:
649
+ throw new Error(`Command ${command.name} not found in the scope ${this.name}`);
650
+ }
651
+ }
652
+
653
+
596
654
 
597
655
  /**
598
656
  * This method is used to register the component in the scope
@@ -600,7 +658,8 @@ export class A_Scope {
600
658
  * @param fragment
601
659
  */
602
660
  register<T extends A_Component>(component: new (...args: any[]) => T): void
603
- register<T extends A_Entity>(component: new (...args: any[]) => T): void
661
+ register<T extends A_Entity>(entity: new (...args: any[]) => T): void
662
+ register<T extends A_Command>(command: new (...args: any[]) => T): void
604
663
  register(entity: A_Entity): void
605
664
  register(component: A_Component): void
606
665
  register(fragment: A_Fragment): void
@@ -610,6 +669,7 @@ export class A_Scope {
610
669
  | A_Entity
611
670
  | (new (...args: any[]) => A_Component)
612
671
  | (new (...args: any[]) => A_Entity)
672
+ | (new (...args: any[]) => A_Command)
613
673
  ): void {
614
674
  switch (true) {
615
675
  case param1 instanceof A_Component && !this._components.has(param1.constructor): {
@@ -664,13 +724,21 @@ export class A_Scope {
664
724
  break;
665
725
  }
666
726
  case typeof param1 === 'function' && A_CommonHelper.isInheritedFrom(param1, A_Entity): {
667
- const allowedComponent = this.params.entities.find(e => e.constructor === param1);
727
+ const allowedEntity = this.params.entities.find(e => e.constructor === param1);
668
728
 
669
- if (!allowedComponent) {
729
+ if (!allowedEntity) {
670
730
  this.params.entities.push(new (param1 as any)());
671
731
  }
672
732
  break;
673
733
  }
734
+ case typeof param1 === 'function' && A_CommonHelper.isInheritedFrom(param1, A_Command): {
735
+ const allowedCommand = this.commands.find(c => c === param1);
736
+
737
+ if (!allowedCommand) {
738
+ this.commands.push(param1 as any);
739
+ }
740
+ break;
741
+ }
674
742
 
675
743
  default:
676
744
  if (param1 instanceof A_Entity)
@@ -1,3 +1,4 @@
1
+ import { A_Command } from "../A-Command/A-Command.class"
1
2
  import { A_Component } from "../A-Component/A-Component.class"
2
3
  import { A_Entity } from "../A-Entity/A-Entity.class"
3
4
  import { A_Fragment } from "../A-Fragment/A-Fragment.class"
@@ -25,6 +26,12 @@ export type A_TYPES__ScopeConstructor = {
25
26
  */
26
27
  entities: Array<A_Entity>
27
28
 
29
+
30
+ /**
31
+ * A set of Commands available in the Scope
32
+ */
33
+ commands: Array<{ new(...args: any[]): A_Command }>
34
+
28
35
  /**
29
36
  * A list of Features/Lifecycle Hooks available in the Scope
30
37
  */
@@ -1,14 +1,14 @@
1
+ import './test.setup';
1
2
 
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";
3
+ import { A_CONSTANTS__A_Command_Status, A_CONSTANTS_A_Command_Features } from "@adaas/a-concept/global/A-Command/A-Command.constants";
4
+ import { A_Command } from "@adaas/a-concept/global/A-Command/A-Command.class";
5
+ import { A_CommandContext } from "@adaas/a-concept/global/A-Command/context/A_Command.context";
7
6
  import { A_Inject } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator";
8
7
  import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
9
8
  import { A_Feature } from "@adaas/a-concept/global/A-Feature/A-Feature.class";
10
9
  import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
11
10
  import { A_Error } from "@adaas/a-utils";
11
+ import { A_Context } from "@adaas/a-concept/global/A-Context/A-Context.class";
12
12
 
13
13
  jest.retryTimes(0);
14
14
 
@@ -17,7 +17,7 @@ describe('A-Command tests', () => {
17
17
  it('Should Allow to create a command', async () => {
18
18
  const command = new A_Command({});
19
19
  expect(command).toBeInstanceOf(A_Command);
20
- expect(command.Code).toBe('A_Command');
20
+ expect(command.Code).toBe('a-command');
21
21
  expect(command.id).toBeDefined();
22
22
  expect(command.aseid).toBeDefined();
23
23
  expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.INITIALIZED);
@@ -58,12 +58,15 @@ describe('A-Command tests', () => {
58
58
  it('Should allow to execute a command with custom logic', async () => {
59
59
 
60
60
  // 1) create a scope
61
- const scope = new A_Scope({ name: 'TestScope' });
61
+ A_Context.reset();
62
+
62
63
  // 2) create a new command
63
64
  type resultType = { bar: string };
64
65
  type invokeType = { foo: string };
65
66
  class MyCommand extends A_Command<invokeType, resultType> { }
66
67
 
68
+ A_Context.root.register(MyCommand);
69
+
67
70
  // 3) create a custom component with custom logic
68
71
  class MyComponent extends A_Component {
69
72
 
@@ -76,11 +79,10 @@ describe('A-Command tests', () => {
76
79
  }
77
80
 
78
81
  // 4) register component in the scope
79
- scope.register(MyComponent);
82
+ A_Context.root.register(MyComponent);
80
83
 
81
84
  // 5) create a new command instance within the scope
82
85
  const command = new MyCommand({ foo: 'bar' });
83
- scope.register(command);
84
86
 
85
87
  // 6) execute the command
86
88
  await command.execute();
@@ -91,14 +93,16 @@ describe('A-Command tests', () => {
91
93
  expect(command.Result).toEqual({ bar: 'baz' });
92
94
  })
93
95
  it('Should allow to fail a command with custom logic', async () => {
96
+ // 1) reset context to have a clean scope
97
+ A_Context.reset();
94
98
 
95
- // 1) create a scope
96
- const scope = new A_Scope({ name: 'TestScope' });
97
99
  // 2) create a new command
98
100
  type resultType = { bar: string };
99
101
  type invokeType = { foo: string };
100
102
  class MyCommand extends A_Command<invokeType, resultType> { }
101
103
 
104
+ A_Context.root.register(MyCommand);
105
+
102
106
  // 3) create a custom component with custom logic
103
107
  class MyComponent extends A_Component {
104
108
 
@@ -113,10 +117,9 @@ describe('A-Command tests', () => {
113
117
  }
114
118
 
115
119
  // 4) register component in the scope
116
- scope.register(MyComponent);
120
+ A_Context.root.register(MyComponent);
117
121
  // 5) create a new command instance within the scope
118
122
  const command = new MyCommand({ foo: 'bar' });
119
- scope.register(command);
120
123
 
121
124
  // 6) execute the command
122
125
  await command.execute();
@@ -1,3 +1,5 @@
1
+ import './test.setup';
2
+
1
3
  import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
2
4
 
3
5
  jest.retryTimes(0);
@@ -0,0 +1,112 @@
1
+ import './test.setup';
2
+
3
+ import { A_Command } from "@adaas/a-concept/global/A-Command/A-Command.class";
4
+ import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
5
+ import { A_Concept } from "@adaas/a-concept/global/A-Concept/A_Concept.class";
6
+ import { A_Container } from "@adaas/a-concept/global/A-Container/A-Container.class";
7
+ import { A_Context } from "@adaas/a-concept/global/A-Context/A-Context.class";
8
+ import { A_Entity } from "@adaas/a-concept/global/A-Entity/A-Entity.class";
9
+ import { A_Fragment } from "@adaas/a-concept/global/A-Fragment/A-Fragment.class";
10
+ import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
11
+
12
+
13
+ jest.retryTimes(0);
14
+
15
+ describe('A-Concept tests', () => {
16
+
17
+ it('Should Allow to create a concept', async () => {
18
+ const concept = new A_Concept({ name: 'TestConcept' });
19
+ expect(concept).toBeInstanceOf(A_Concept);
20
+ expect(concept.Scope).toBeDefined();
21
+ expect(concept.Scope).toBeInstanceOf(A_Scope);
22
+ });
23
+ it('Should allow to load a concept', async () => {
24
+ const concept = new A_Concept({ name: 'TestConcept' });
25
+ await concept.load();
26
+ });
27
+ it('Should allow to run concept abstractions', async () => {
28
+ const concept = new A_Concept({ name: 'TestConcept' });
29
+ await concept.load();
30
+ await concept.start();
31
+ await concept.deploy();
32
+ await concept.build();
33
+ await concept.publish();
34
+ await concept.stop();
35
+ });
36
+ it('Should allow to provide all base entities to the concept', async () => {
37
+ A_Context.reset();
38
+
39
+ class MyCommand extends A_Command { }
40
+ class MyEntity extends A_Entity { }
41
+ class MyComponent extends A_Component { }
42
+ class MyContainer extends A_Container { }
43
+ class MyContext extends A_Fragment { }
44
+
45
+ const concept = new A_Concept({
46
+ name: 'TestConcept',
47
+ commands: [MyCommand],
48
+ entities: [new MyEntity()],
49
+ components: [MyComponent],
50
+ containers: [new MyContainer({ name: 'test' })],
51
+ fragments: [new MyContext({ name: 'test' })]
52
+ });
53
+
54
+
55
+ expect(concept.Scope.resolveConstructor('MyCommand')).toBe(MyCommand);
56
+ expect(concept.Scope.resolve(MyEntity)).toBeInstanceOf(MyEntity);
57
+ expect(concept.Scope.resolve(MyComponent)).toBeInstanceOf(MyComponent);
58
+ expect(concept.Scope.resolve(MyContext)).toBeInstanceOf(MyContext);
59
+ });
60
+ it('Should allow to separate entities by containers', async () => {
61
+ A_Context.reset();
62
+
63
+ class MyCommandA extends A_Command { }
64
+ class MyCommandB extends A_Command { }
65
+ class MyComponentA extends A_Component { }
66
+ class MyComponentB extends A_Component { }
67
+ class MyContainer extends A_Container { }
68
+ class MyContext extends A_Fragment { }
69
+
70
+ const containerA = new MyContainer({
71
+ name: 'test',
72
+ commands: [MyCommandA],
73
+ components: [MyComponentA]
74
+
75
+ });
76
+
77
+ const containerB = new MyContainer({
78
+ name: 'test2',
79
+ commands: [MyCommandB],
80
+ components: [MyComponentB]
81
+ })
82
+
83
+ const sharedContext = new MyContext({ name: 'test' })
84
+
85
+ const concept = new A_Concept({
86
+ name: 'TestConcept',
87
+ containers: [
88
+ containerA,
89
+ containerB
90
+
91
+ ],
92
+ fragments: [sharedContext]
93
+ });
94
+
95
+ const containerAScope = A_Context.scope(containerA)
96
+ const containerBScope = A_Context.scope(containerB)
97
+
98
+ expect(containerAScope.resolveConstructor('MyCommandA')).toBe(MyCommandA);
99
+ expect(() => {
100
+ containerAScope.resolveConstructor('MyCommandB');
101
+ }).toThrow();
102
+
103
+ expect(containerBScope.resolveConstructor('MyCommandB')).toBe(MyCommandB);
104
+ expect(() => {
105
+ containerBScope.resolveConstructor('MyCommandA');
106
+ }).toThrow();
107
+
108
+ expect(concept.Scope.resolve(MyContext)).toEqual(sharedContext);
109
+ expect(concept.Scope.resolve(MyContext)).toEqual(sharedContext);
110
+ });
111
+
112
+ });