@adaas/a-concept 0.1.4 → 0.1.6

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 (50) hide show
  1. package/dist/src/global/A-Abstraction/A-Abstraction-Extend.decorator.js +5 -4
  2. package/dist/src/global/A-Abstraction/A-Abstraction-Extend.decorator.js.map +1 -1
  3. package/dist/src/global/A-Abstraction/A-Abstraction.class.d.ts +2 -1
  4. package/dist/src/global/A-Abstraction/A-Abstraction.class.js +7 -1
  5. package/dist/src/global/A-Abstraction/A-Abstraction.class.js.map +1 -1
  6. package/dist/src/global/A-Abstraction/A-Abstraction.types.d.ts +2 -1
  7. package/dist/src/global/A-Component/A-Component.meta.js +1 -1
  8. package/dist/src/global/A-Component/A-Component.meta.js.map +1 -1
  9. package/dist/src/global/A-Container/A-Container.class.d.ts +1 -1
  10. package/dist/src/global/A-Container/A-Container.class.js +1 -1
  11. package/dist/src/global/A-Container/A-Container.class.js.map +1 -1
  12. package/dist/src/global/A-Container/A-Container.constants.d.ts +2 -1
  13. package/dist/src/global/A-Container/A-Container.constants.js +1 -0
  14. package/dist/src/global/A-Container/A-Container.constants.js.map +1 -1
  15. package/dist/src/global/A-Container/A-Container.meta.d.ts +11 -3
  16. package/dist/src/global/A-Container/A-Container.meta.js +25 -0
  17. package/dist/src/global/A-Container/A-Container.meta.js.map +1 -1
  18. package/dist/src/global/A-Container/A-Container.types.d.ts +24 -1
  19. package/dist/src/global/A-Context/A-Context.class.d.ts +6 -14
  20. package/dist/src/global/A-Context/A-Context.class.js +16 -20
  21. package/dist/src/global/A-Context/A-Context.class.js.map +1 -1
  22. package/dist/src/global/A-Feature/A-Feature.class.d.ts +1 -1
  23. package/dist/src/global/A-Feature/A-Feature.class.js +6 -4
  24. package/dist/src/global/A-Feature/A-Feature.class.js.map +1 -1
  25. package/dist/src/global/A-Feature/A-Feature.types.d.ts +9 -2
  26. package/dist/src/global/A-Feature/A-Feature.types.js.map +1 -1
  27. package/dist/src/global/A-Scope/A-Scope.class.d.ts +7 -1
  28. package/dist/src/global/A-Scope/A-Scope.class.js +22 -2
  29. package/dist/src/global/A-Scope/A-Scope.class.js.map +1 -1
  30. package/dist/src/global/A-Scope/A-Scope.types.d.ts +6 -0
  31. package/dist/src/helpers/A_TypeGuards.helper.d.ts +3 -1
  32. package/dist/src/helpers/A_TypeGuards.helper.js +10 -2
  33. package/dist/src/helpers/A_TypeGuards.helper.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/global/A-Abstraction/A-Abstraction-Extend.decorator.ts +5 -4
  36. package/src/global/A-Abstraction/A-Abstraction.class.ts +12 -2
  37. package/src/global/A-Abstraction/A-Abstraction.types.ts +2 -1
  38. package/src/global/A-Component/A-Component.meta.ts +1 -1
  39. package/src/global/A-Container/A-Container.class.ts +1 -1
  40. package/src/global/A-Container/A-Container.constants.ts +1 -0
  41. package/src/global/A-Container/A-Container.meta.ts +38 -3
  42. package/src/global/A-Container/A-Container.types.ts +27 -2
  43. package/src/global/A-Context/A-Context.class.ts +22 -21
  44. package/src/global/A-Feature/A-Feature.class.ts +7 -5
  45. package/src/global/A-Feature/A-Feature.types.ts +9 -2
  46. package/src/global/A-Scope/A-Scope.class.ts +62 -13
  47. package/src/global/A-Scope/A-Scope.types.ts +7 -3
  48. package/src/helpers/A_TypeGuards.helper.ts +12 -3
  49. package/tests/A-Abstraction.test.ts +72 -0
  50. package/tests/A-Common.test.ts +2 -1
@@ -203,7 +203,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
203
203
  ): (param1: any) => void | (() => void) {
204
204
 
205
205
  switch (true) {
206
- case 'component' in params:
206
+ case !('template' in params):
207
207
  return this.fromComponent;
208
208
 
209
209
  case 'template' in params:
@@ -221,7 +221,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
221
221
  * @param params
222
222
  */
223
223
  protected fromTemplate(
224
- params: A_TYPES__Feature_InitWithTemplate
224
+ params: A_TYPES__Feature_InitWithTemplate<T>
225
225
  ) {
226
226
  if (!params.template || !Array.isArray(params.template)) {
227
227
  throw new A_FeatureError(
@@ -230,7 +230,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
230
230
  );
231
231
  }
232
232
 
233
- if (!params.scope || !(params.scope instanceof A_Scope)) {
233
+ if (!params.component && (!params.scope || !(params.scope instanceof A_Scope))) {
234
234
  throw new A_FeatureError(
235
235
  A_FeatureError.FeatureInitializationError,
236
236
  `Invalid A-Feature scope provided of type: ${typeof params.scope} with value: ${JSON.stringify(params.scope).slice(0, 100)}...`
@@ -241,12 +241,14 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
241
241
  this._name = params.name;
242
242
 
243
243
  // 2) get scope from where feature is called
244
- const componentScope = params.scope;
244
+ const componentScope = params.component
245
+ ? A_Context.scope(params.component)
246
+ : params.scope as A_Scope;
245
247
 
246
248
  // 3) create caller wrapper for the simple injection of the caller component
247
249
  // - Just to prevent issues with undefined caller in features without component
248
250
  // - TODO: maybe would be better to allow passing caller in params?
249
- this._caller = new A_Caller<T>(new A_Component() as T);
251
+ this._caller = new A_Caller<T>(params.component || new A_Component() as T);
250
252
 
251
253
  // 4) allocate new scope for the feature
252
254
  const scope = A_Context.allocate(this);
@@ -22,7 +22,7 @@ export type A_TYPES__Feature_Constructor<T = A_Feature> = new (...args: any[]) =
22
22
  /**
23
23
  * Feature initialization type
24
24
  */
25
- export type A_TYPES__Feature_Init<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__FeatureAvailableComponents> = A_TYPES__Feature_InitWithComponent<T> | A_TYPES__Feature_InitWithTemplate
25
+ export type A_TYPES__Feature_Init<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__FeatureAvailableComponents> = A_TYPES__Feature_InitWithComponent<T> | A_TYPES__Feature_InitWithTemplate<T>
26
26
  /**
27
27
  * Feature initialization type using component
28
28
  */
@@ -42,7 +42,7 @@ export type A_TYPES__Feature_InitWithComponent<T extends A_TYPES__FeatureAvailab
42
42
  /**
43
43
  * Feature initialization type using template
44
44
  */
45
- export type A_TYPES__Feature_InitWithTemplate = {
45
+ export type A_TYPES__Feature_InitWithTemplate<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__FeatureAvailableComponents> = {
46
46
  /**
47
47
  * Feature Name
48
48
  */
@@ -53,6 +53,13 @@ export type A_TYPES__Feature_InitWithTemplate = {
53
53
  * [!] Important for proper scoping.
54
54
  */
55
55
  scope: A_Scope
56
+ /**
57
+ * The component from where the feature is calling. It's important for proper scoping.
58
+ * Based on the component would be retrieved connected components, entities and containers.
59
+ *
60
+ * [!] Could be Container, Entity, Component or Command
61
+ */
62
+ component?: T,
56
63
  /**
57
64
  * Optional Feature template to be used instead of building it from decorators
58
65
  */
@@ -3,7 +3,8 @@ import {
3
3
  A_TYPES__Scope_Init,
4
4
  A_TYPES__ScopeLinkedComponents,
5
5
  A_TYPES__ScopeResolvableComponents,
6
- A_TYPES__Scope_Constructor
6
+ A_TYPES__Scope_Constructor,
7
+ A_TYPES__ScopeLinkedConstructors
7
8
  } from './A-Scope.types'
8
9
  import {
9
10
  A_TYPES__A_InjectDecorator_EntityInjectionInstructions,
@@ -401,6 +402,11 @@ export class A_Scope<
401
402
 
402
403
  break;
403
404
  }
405
+ // check scope issuer
406
+ case this.issuer().constructor === ctor: {
407
+ found = true;
408
+ break;
409
+ }
404
410
  }
405
411
 
406
412
  if (!found && !!this._parent)
@@ -574,6 +580,13 @@ export class A_Scope<
574
580
  */
575
581
  param1: A_TYPES__InjectableConstructors,
576
582
 
583
+ ): T | Array<T>
584
+ resolve<T extends A_TYPES__ScopeLinkedConstructors>(
585
+ /**
586
+ * Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
587
+ */
588
+ param1: T,
589
+
577
590
  ): T | Array<T>
578
591
  resolve<T extends A_TYPES__ScopeResolvableComponents>(
579
592
  /**
@@ -593,7 +606,7 @@ export class A_Scope<
593
606
  }
594
607
 
595
608
  case A_TypeGuards.isFunction(param1): {
596
- return this.resolveOnce(param1, param2);
609
+ return this.resolveOnce(param1, param2) as T;
597
610
  }
598
611
 
599
612
  case A_TypeGuards.isString(param1): {
@@ -665,35 +678,68 @@ export class A_Scope<
665
678
  * @param instructions
666
679
  * @returns
667
680
  */
668
- private resolveOnce<T extends A_Component | A_Fragment | A_Entity | A_Scope>(
669
- component: unknown,
681
+ private resolveOnce(
682
+ component: any,
670
683
  instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
671
- ): T | Array<T> {
684
+ ): A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | Array<A_TYPES__ScopeResolvableComponents> {
685
+
686
+ if (!component || !this.has(component))
687
+ throw new A_ScopeError(
688
+ A_ScopeError.ResolutionError,
689
+ `Injected Component ${component} not found in the scope`
690
+ );
672
691
 
673
692
  if (A_TypeGuards.isScopeConstructor(component))
674
693
  component
675
694
 
676
- if (typeof component == 'function' && (component as any).name === 'A_Scope')
695
+ if (typeof component == 'function' && component.name === 'A_Scope')
677
696
  component
678
697
 
698
+
699
+
700
+
679
701
  switch (true) {
702
+ case A_TypeGuards.isConstructorAllowedForScopeAllocation(component): {
703
+ return this.resolveIssuer(component);
704
+ }
680
705
  case A_TypeGuards.isEntityConstructor(component): {
681
- return this.resolveEntity(component, instructions) as T | Array<T>;
706
+ return this.resolveEntity(component, instructions);
682
707
  }
683
708
  case A_TypeGuards.isFragmentConstructor(component): {
684
- return this.resolveFragment(component) as T;
709
+ return this.resolveFragment(component);
685
710
  }
686
711
  case A_TypeGuards.isScopeConstructor(component): {
687
- return this.resolveScope(component) as T;
712
+ return this.resolveScope(component);
688
713
  }
689
714
  case A_TypeGuards.isComponentConstructor(component): {
690
- return this.resolveComponent(component) as T;
715
+ return this.resolveComponent(component);
691
716
  }
692
717
  default:
693
- throw new Error(`Injected Component ${component} not found in the scope`);
718
+ throw new A_ScopeError(
719
+ A_ScopeError.ResolutionError,
720
+ `Injected Component ${component} not found in the scope`
721
+ );
694
722
  }
695
723
  }
696
724
 
725
+ private resolveIssuer(
726
+ ctor: A_TYPES__ScopeLinkedConstructors
727
+ ): A_TYPES__ScopeLinkedComponents {
728
+ const isCurrent = ctor === this.issuer().constructor;
729
+
730
+ if (isCurrent) {
731
+ return this.issuer();
732
+ }
733
+ if (!!this._parent) {
734
+ return this._parent.resolveIssuer(ctor);
735
+ }
736
+
737
+ throw new A_ScopeError(
738
+ A_ScopeError.ResolutionError,
739
+ `Issuer ${ctor.name} not found in the scope ${this.name}`
740
+ );
741
+ }
742
+
697
743
  /**
698
744
  * This method is used internally to resolve a single entity from the scope based on the provided instructions
699
745
  *
@@ -706,7 +752,7 @@ export class A_Scope<
706
752
  private resolveEntity<T extends A_Entity>(
707
753
  entity: A_TYPES__Entity_Constructor<T>,
708
754
  instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<T>>
709
- ): T | Array<T> | undefined {
755
+ ): T | Array<T> {
710
756
 
711
757
  const query = instructions?.query || {} as Partial<A_TYPES__A_InjectDecorator_EntityInjectionQuery<T>>;
712
758
  const count = instructions?.pagination?.count || 1;
@@ -729,7 +775,10 @@ export class A_Scope<
729
775
  return this._parent.resolveEntity(entity, instructions);
730
776
 
731
777
  default:
732
- throw new Error(`Entity ${entity.name} not found in the scope ${this.name}`);
778
+ throw new A_ScopeError(
779
+ A_ScopeError.ResolutionError,
780
+ `Entity ${entity.name} not found in the scope ${this.name}`
781
+ );
733
782
  }
734
783
  }
735
784
  /**
@@ -9,6 +9,8 @@ import { A_Caller } from "../A-Caller/A_Caller.class"
9
9
  import { A_Error } from "../A-Error/A_Error.class"
10
10
  import { A_TYPES__Error_Constructor } from "../A-Error/A_Error.types"
11
11
  import { A_Scope } from "./A-Scope.class"
12
+ import { A_TYPES__Container_Constructor } from "../A-Container/A-Container.types"
13
+ import { A_TYPES__Feature_Constructor } from "../A-Feature/A-Feature.types"
12
14
 
13
15
 
14
16
  // ============================================================================
@@ -68,8 +70,10 @@ export type A_TYPES__ScopeConfig = {
68
70
  export type A_TYPES__Scope_Serialized = {}
69
71
 
70
72
 
71
-
72
-
73
+ /**
74
+ *
75
+ */
76
+ export type A_TYPES__ScopeLinkedConstructors = A_TYPES__Container_Constructor | A_TYPES__Feature_Constructor;
73
77
  /**
74
78
  * A list of components that can have a scope associated with them
75
79
  */
@@ -77,7 +81,7 @@ export type A_TYPES__ScopeLinkedComponents = A_Container | A_Feature;
77
81
  /**
78
82
  * A list of components that can be resolved by a scope
79
83
  */
80
- export type A_TYPES__ScopeResolvableComponents = A_Component | A_Fragment | A_Entity
84
+ export type A_TYPES__ScopeResolvableComponents = A_Component | A_Fragment | A_Entity
81
85
  /**
82
86
  * A list of components that are dependent on a scope and do not have their own scope
83
87
  */
@@ -25,7 +25,7 @@ import { A_TYPES__Caller_Constructor } from "../global/A-Caller/A_Caller.types";
25
25
  import { A_Error } from "../global/A-Error/A_Error.class";
26
26
  import { A_CommonHelper } from "./A_Common.helper";
27
27
  import { A_TYPES__AbstractionAvailableComponents } from "../global/A-Abstraction/A-Abstraction.types";
28
- import { A_TYPES__Scope_Constructor } from "../global/A-Scope/A-Scope.types";
28
+ import { A_TYPES__Scope_Constructor, A_TYPES__ScopeLinkedComponents, A_TYPES__ScopeLinkedConstructors } from "../global/A-Scope/A-Scope.types";
29
29
  import { A_TYPES__InjectableTargets } from "../global/A-Inject/A-Inject.types";
30
30
 
31
31
 
@@ -273,9 +273,18 @@ export class A_TypeGuards {
273
273
  // ==========================================================================
274
274
  // ========================= SPECIAL Type Guards =============================
275
275
  // ===========================================================================
276
- static isConstructorAvailableForAbstraction(target: any): target is A_TYPES__AbstractionAvailableComponents {
276
+ static isConstructorAllowedForScopeAllocation(target: any): target is A_TYPES__ScopeLinkedConstructors {
277
277
  return A_TypeGuards.isContainerConstructor(target)
278
- || A_TypeGuards.isComponentConstructor(target);
278
+ || A_TypeGuards.isFeatureConstructor(target);
279
+ }
280
+ static isInstanceAllowedForScopeAllocation(target: any): target is A_TYPES__ScopeLinkedComponents {
281
+ return A_TypeGuards.isContainerInstance(target)
282
+ || A_TypeGuards.isFeatureInstance(target);
283
+ }
284
+
285
+ static isConstructorAvailableForAbstraction(target: any): target is A_TYPES__AbstractionAvailableComponents {
286
+ return A_TypeGuards.isContainerInstance(target)
287
+ || A_TypeGuards.isComponentInstance(target);
279
288
  }
280
289
 
281
290
 
@@ -0,0 +1,72 @@
1
+ import { A_Component } from '@adaas/a-concept/global/A-Component/A-Component.class';
2
+ import './test.setup'
3
+ import { A_Concept } from '@adaas/a-concept/global/A-Concept/A-Concept.class';
4
+ import { A_Container } from '@adaas/a-concept/global/A-Container/A-Container.class';
5
+
6
+ jest.retryTimes(0);
7
+
8
+ describe('A-Abstraction Tests', () => {
9
+ it('It should be possible to extend abstraction on A-Component level', async () => {
10
+ class MyComponent extends A_Component {
11
+ private _test: number = 0
12
+
13
+ @A_Concept.Load()
14
+ myMethod() {
15
+ this._test++;
16
+ }
17
+ }
18
+ });
19
+
20
+ it('It should be possible to extend abstraction on A-Container level', async () => {
21
+ class MyContainer extends A_Container {
22
+ private _test: number = 0
23
+
24
+ @A_Concept.Load()
25
+ myMethod() {
26
+ this._test++;
27
+ }
28
+ }
29
+ });
30
+
31
+
32
+ it('It should be possible to proceed Concept Abstraction', async () => {
33
+ class MyComponent extends A_Component {
34
+ _test2: number = 0
35
+
36
+ @A_Concept.Load()
37
+ myMethod() {
38
+ this._test2++;
39
+ }
40
+ }
41
+
42
+ class MyContainer extends A_Container {
43
+ _test: number = 0
44
+
45
+ @A_Concept.Load()
46
+ myMethod() {
47
+ this._test++;
48
+ }
49
+ }
50
+
51
+ const myContainer = new MyContainer({
52
+ name: 'MyContainer',
53
+ components: [MyComponent]
54
+ });
55
+
56
+ const testConcept = new A_Concept({
57
+ name: 'TestConcept',
58
+ containers: [myContainer]
59
+ });
60
+
61
+ await testConcept.load();
62
+
63
+
64
+ const resolvedComponent = myContainer.scope.resolve(MyComponent);
65
+
66
+ expect(resolvedComponent).toBeInstanceOf(MyComponent);
67
+ expect(myContainer._test).toBe(1);
68
+ expect(resolvedComponent._test2).toBe(1);
69
+
70
+ });
71
+ });
72
+
@@ -1,9 +1,10 @@
1
+ import './test.setup'
1
2
  import { A_CommonHelper } from "@adaas/a-concept/helpers/A_Common.helper";
2
3
  import { A_IdentityHelper } from "@adaas/a-concept/helpers/A_Identity.helper";
3
4
  import { A_TYPES__DeepPartial } from "@adaas/a-concept/types/A_Common.types";
4
5
  jest.retryTimes(0);
5
6
 
6
- describe('CommonHelper Tests', () => {
7
+ describe('A-Common Tests', () => {
7
8
  it('Deep Clone and Merge ', async () => {
8
9
 
9
10
  type TestType = {