@adaas/a-concept 0.1.60 → 0.2.1
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.
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1584 -1456
- package/dist/index.d.ts +1584 -1456
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/global/A-Abstraction/A-Abstraction.types.ts +2 -3
- package/src/global/A-Caller/A_Caller.types.ts +2 -1
- package/src/global/A-Component/A-Component.types.ts +2 -1
- package/src/global/A-Concept/A-Concept.types.ts +2 -1
- package/src/global/A-Container/A-Container.types.ts +2 -1
- package/src/global/A-Context/A-Context.class.ts +56 -25
- package/src/global/A-Dependency/A-Dependency-All.decorator.ts +77 -0
- package/src/global/A-Dependency/A-Dependency-Default.decorator.ts +4 -4
- package/src/global/A-Dependency/A-Dependency-Flat.decorator.ts +3 -2
- package/src/global/A-Dependency/A-Dependency-Load.decorator.ts +9 -13
- package/src/global/A-Dependency/A-Dependency-Parent.decorator.ts +2 -3
- package/src/global/A-Dependency/A-Dependency-Require.decorator.ts +1 -2
- package/src/global/A-Dependency/A-Dependency.class.ts +144 -5
- package/src/global/A-Dependency/A-Dependency.error.ts +3 -0
- package/src/global/A-Dependency/A-Dependency.types.ts +124 -3
- package/src/global/A-Entity/A-Entity.types.ts +2 -1
- package/src/global/A-Error/A_Error.types.ts +2 -1
- package/src/global/A-Feature/A-Feature-Define.decorator.ts +0 -1
- package/src/global/A-Feature/A-Feature-Extend.decorator.ts +1 -5
- package/src/global/A-Feature/A-Feature.types.ts +3 -3
- package/src/global/A-Fragment/A-Fragment.types.ts +2 -1
- package/src/global/A-Inject/A-Inject.decorator.ts +70 -42
- package/src/global/A-Inject/A-Inject.types.ts +2 -42
- package/src/global/A-Meta/A-Meta.decorator.ts +5 -3
- package/src/global/A-Meta/A-Meta.types.ts +2 -1
- package/src/global/A-Scope/A-Scope.class.ts +409 -389
- package/src/global/A-Scope/A-Scope.error.ts +2 -0
- package/src/global/A-Scope/A-Scope.types.ts +4 -8
- package/src/global/A-Stage/A-Stage.class.ts +19 -86
- package/src/global/A-Stage/A-Stage.types.ts +3 -1
- package/src/global/A-StepManager/A-StepManager.class.ts +1 -1
- package/src/global/ASEID/ASEID.class.ts +20 -0
- package/src/helpers/A_Common.helper.ts +4 -0
- package/src/helpers/A_TypeGuards.helper.ts +28 -3
- package/src/types/A_Common.types.ts +4 -0
- package/tests/A-Abstraction.test.ts +2 -0
- package/tests/A-Dependency.test.ts +49 -5
- package/tests/A-Feature.test.ts +44 -19
- package/tests/A-Meta.test.ts +4 -0
- package/tests/A-Scope.test.ts +38 -9
- package/tests/A-StepManager.test.ts +40 -39
|
@@ -2,15 +2,9 @@ import {
|
|
|
2
2
|
A_TYPES__ScopeConfig,
|
|
3
3
|
A_TYPES__Scope_Init,
|
|
4
4
|
A_TYPES__ScopeLinkedComponents,
|
|
5
|
-
A_TYPES__ScopeResolvableComponents,
|
|
6
5
|
A_TYPES__Scope_Constructor,
|
|
7
6
|
A_TYPES__ScopeLinkedConstructors
|
|
8
7
|
} from './A-Scope.types'
|
|
9
|
-
import {
|
|
10
|
-
A_TYPES__A_InjectDecorator_EntityInjectionInstructions,
|
|
11
|
-
A_TYPES__A_InjectDecorator_EntityInjectionQuery,
|
|
12
|
-
A_TYPES__InjectableConstructors,
|
|
13
|
-
} from "@adaas/a-concept/global/A-Inject/A-Inject.types";
|
|
14
8
|
import { A_Fragment } from "../A-Fragment/A-Fragment.class";
|
|
15
9
|
import { A_Context } from "../A-Context/A-Context.class";
|
|
16
10
|
import { A_Component } from "../A-Component/A-Component.class";
|
|
@@ -18,7 +12,6 @@ import { A_Entity } from "../A-Entity/A-Entity.class";
|
|
|
18
12
|
import { A_TypeGuards } from "@adaas/a-concept/helpers/A_TypeGuards.helper";
|
|
19
13
|
import { A_Error } from "../A-Error/A_Error.class";
|
|
20
14
|
import { A_FormatterHelper } from '@adaas/a-concept/helpers/A_Formatter.helper';
|
|
21
|
-
import { ASEID } from '../ASEID/ASEID.class';
|
|
22
15
|
import { A_CommonHelper } from '@adaas/a-concept/helpers/A_Common.helper';
|
|
23
16
|
import { A_TYPES__Entity_Constructor } from '../A-Entity/A-Entity.types';
|
|
24
17
|
import { A_ScopeError } from './A-Scope.error';
|
|
@@ -27,6 +20,10 @@ import { A_TYPES__Fragment_Constructor } from '../A-Fragment/A-Fragment.types';
|
|
|
27
20
|
import { A_TYPES__Error_Constructor } from '../A-Error/A_Error.types';
|
|
28
21
|
import { A_TYPES__ComponentMetaKey } from '../A-Component/A-Component.constants';
|
|
29
22
|
import { A_Meta } from '../A-Meta/A-Meta.class';
|
|
23
|
+
import { A_Dependency } from '../A-Dependency/A-Dependency.class';
|
|
24
|
+
import { A_TYPES__A_DependencyInjectable } from '../A-Dependency/A-Dependency.types';
|
|
25
|
+
import { A_TYPES__Ctor } from '@adaas/a-concept/types/A_Common.types';
|
|
26
|
+
import { ASEID } from '../ASEID/ASEID.class';
|
|
30
27
|
|
|
31
28
|
|
|
32
29
|
|
|
@@ -96,7 +93,10 @@ export class A_Scope<
|
|
|
96
93
|
* Storage for the fragments, should be weak as fragments are singletons per scope
|
|
97
94
|
*/
|
|
98
95
|
protected _fragments: Map<A_TYPES__Fragment_Constructor<_FragmentType[number]>, _FragmentType[number]> = new Map();
|
|
99
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Storage for imported scopes
|
|
98
|
+
*/
|
|
99
|
+
protected _imports: Set<A_Scope> = new Set();
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
|
|
@@ -154,6 +154,11 @@ export class A_Scope<
|
|
|
154
154
|
* [!] One error per code
|
|
155
155
|
*/
|
|
156
156
|
get errors(): Array<InstanceType<_ErrorType[number]>> { return Array.from(this._errors.values()) }
|
|
157
|
+
/**
|
|
158
|
+
* Returns an Array of imported scopes
|
|
159
|
+
* [!] Imported scopes are scopes that have been imported into the current scope using the import() method
|
|
160
|
+
*/
|
|
161
|
+
get imports(): Array<A_Scope> { return Array.from(this._imports.values()) }
|
|
157
162
|
|
|
158
163
|
/**
|
|
159
164
|
* Returns the parent scope of the current scope
|
|
@@ -220,25 +225,25 @@ export class A_Scope<
|
|
|
220
225
|
* @param level
|
|
221
226
|
* @returns
|
|
222
227
|
*/
|
|
223
|
-
parentOffset(
|
|
228
|
+
parentOffset<T extends A_Scope>(
|
|
224
229
|
/**
|
|
225
230
|
* Level of the parent scope to retrieve
|
|
226
231
|
*
|
|
227
232
|
* Examples:
|
|
228
|
-
* - level 0 -
|
|
229
|
-
* - level -1 -
|
|
230
|
-
* - level -2 -
|
|
233
|
+
* - level 0 - this scope
|
|
234
|
+
* - level -1 - parent
|
|
235
|
+
* - level -2 - grandparent
|
|
231
236
|
*/
|
|
232
237
|
layerOffset: number
|
|
233
|
-
):
|
|
234
|
-
let parentScope = this
|
|
238
|
+
): T | undefined {
|
|
239
|
+
let parentScope: A_Scope | undefined = this;
|
|
235
240
|
|
|
236
|
-
while (layerOffset
|
|
241
|
+
while (layerOffset <= -1 && parentScope) {
|
|
237
242
|
parentScope = parentScope.parent;
|
|
238
243
|
layerOffset++;
|
|
239
244
|
}
|
|
240
245
|
|
|
241
|
-
return parentScope
|
|
246
|
+
return parentScope as T
|
|
242
247
|
}
|
|
243
248
|
|
|
244
249
|
|
|
@@ -357,9 +362,9 @@ export class A_Scope<
|
|
|
357
362
|
this._errors.clear();
|
|
358
363
|
this._fragments.clear();
|
|
359
364
|
this._entities.clear();
|
|
365
|
+
this._imports.clear();
|
|
360
366
|
|
|
361
367
|
if (this.issuer()) {
|
|
362
|
-
|
|
363
368
|
A_Context.deallocate(this);
|
|
364
369
|
}
|
|
365
370
|
}
|
|
@@ -456,6 +461,49 @@ export class A_Scope<
|
|
|
456
461
|
}
|
|
457
462
|
|
|
458
463
|
|
|
464
|
+
/**
|
|
465
|
+
* This method allows to import other scopes, to make their dependencies available in the current scope
|
|
466
|
+
*
|
|
467
|
+
* [!] Import doesn't create a parent-child relationship between scopes, it just copies the dependencies from the imported scopes
|
|
468
|
+
* [!] It doesn't change the entities ownership, so entities remain unique to their original scopes
|
|
469
|
+
*
|
|
470
|
+
* @param scopes
|
|
471
|
+
* @returns
|
|
472
|
+
*/
|
|
473
|
+
import(...scopes: A_Scope[]): A_Scope {
|
|
474
|
+
|
|
475
|
+
scopes.forEach(scope => {
|
|
476
|
+
if (scope === this)
|
|
477
|
+
throw new A_ScopeError(
|
|
478
|
+
A_ScopeError.CircularImportError,
|
|
479
|
+
`Unable to import scope ${this.name} into itself`
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
if (this._imports.has(scope))
|
|
483
|
+
return;
|
|
484
|
+
|
|
485
|
+
this._imports.add(scope);
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
return this;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* This method allows to deimport other scopes, to remove their dependencies from the current scope
|
|
493
|
+
*
|
|
494
|
+
*
|
|
495
|
+
* @param scopes
|
|
496
|
+
* @returns
|
|
497
|
+
*/
|
|
498
|
+
deimport(...scopes: A_Scope[]): A_Scope {
|
|
499
|
+
|
|
500
|
+
scopes.forEach(scope => {
|
|
501
|
+
if (this._imports.has(scope))
|
|
502
|
+
this._imports.delete(scope);
|
|
503
|
+
});
|
|
504
|
+
return this;
|
|
505
|
+
}
|
|
506
|
+
|
|
459
507
|
/**
|
|
460
508
|
* This method is used to check if the component is available in the scope
|
|
461
509
|
*
|
|
@@ -496,8 +544,11 @@ export class A_Scope<
|
|
|
496
544
|
*/
|
|
497
545
|
constructor: string
|
|
498
546
|
): boolean
|
|
499
|
-
has(
|
|
500
|
-
ctor:
|
|
547
|
+
has<T extends A_TYPES__A_DependencyInjectable>(
|
|
548
|
+
ctor: A_TYPES__Ctor<T> | string
|
|
549
|
+
): boolean
|
|
550
|
+
has<T extends A_TYPES__A_DependencyInjectable>(
|
|
551
|
+
ctor: A_TYPES__Ctor<T> | string
|
|
501
552
|
): boolean {
|
|
502
553
|
|
|
503
554
|
let found = this.hasFlat(ctor as any);
|
|
@@ -635,33 +686,100 @@ export class A_Scope<
|
|
|
635
686
|
|
|
636
687
|
|
|
637
688
|
/**
|
|
638
|
-
*
|
|
689
|
+
* Allows to resolve a specific dependency
|
|
639
690
|
*
|
|
640
|
-
*
|
|
641
|
-
* - this method does NOT modify the existing scopes
|
|
642
|
-
* - parent of the new scope will be the parent of the current scope or the parent of anotherScope (if exists)
|
|
643
|
-
*
|
|
644
|
-
* @param anotherScope
|
|
691
|
+
* @param dependency
|
|
645
692
|
* @returns
|
|
646
693
|
*/
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
694
|
+
resolveDependency<T extends A_TYPES__A_DependencyInjectable>(
|
|
695
|
+
dependency: A_Dependency<T>
|
|
696
|
+
): T | Array<T> | undefined {
|
|
697
|
+
|
|
698
|
+
let result: Array<T> = [];
|
|
699
|
+
let targetScope: A_Scope = this.parentOffset(dependency.parent) || this;
|
|
700
|
+
|
|
701
|
+
// first deal with level conditions and
|
|
702
|
+
switch (true) {
|
|
703
|
+
// 1) Flat resolution
|
|
704
|
+
case dependency.flat && !dependency.all: {
|
|
705
|
+
const resolved = targetScope.resolveFlatOnce<T>(dependency.target || dependency.name);
|
|
706
|
+
if (resolved)
|
|
707
|
+
result = [resolved];
|
|
708
|
+
break;
|
|
661
709
|
}
|
|
662
|
-
|
|
710
|
+
case dependency.flat && dependency.all: {
|
|
711
|
+
result = targetScope.resolveFlatAll<T>(dependency.target || dependency.name);
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
case !dependency.flat && !dependency.all: {
|
|
715
|
+
const resolved = targetScope.resolveOnce<T>(dependency.target || dependency.name);
|
|
716
|
+
if (resolved)
|
|
717
|
+
result = [resolved];
|
|
718
|
+
break;
|
|
719
|
+
}
|
|
720
|
+
case !dependency.flat && dependency.all: {
|
|
721
|
+
result = targetScope.resolveAll<T>(dependency.target || dependency.name);
|
|
722
|
+
break;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
default:
|
|
726
|
+
result = [];
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// 2) create if not found and allowed
|
|
730
|
+
if (dependency.create
|
|
731
|
+
&& !result.length
|
|
732
|
+
&& A_TypeGuards.isAllowedForDependencyDefaultCreation(dependency.target)
|
|
733
|
+
) {
|
|
734
|
+
|
|
735
|
+
const newDependency = new dependency.target(...dependency.args);
|
|
736
|
+
|
|
737
|
+
targetScope.register(newDependency);
|
|
738
|
+
|
|
739
|
+
result.push(newDependency as T);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// 3) handle required dependencies
|
|
743
|
+
if (dependency.require && !result.length) {
|
|
744
|
+
throw new A_ScopeError(
|
|
745
|
+
A_ScopeError.ResolutionError,
|
|
746
|
+
`Dependency ${dependency.name} is required but could not be resolved in scope ${targetScope.name}`
|
|
747
|
+
);
|
|
748
|
+
}
|
|
663
749
|
|
|
664
|
-
|
|
750
|
+
|
|
751
|
+
// 4) Apply filters
|
|
752
|
+
if (dependency.query.aseid)
|
|
753
|
+
// in this case we should return only one dependency by aseid
|
|
754
|
+
result = result.filter(dep => A_TypeGuards.hasASEID(dep) && ASEID.compare(dep.aseid, dependency.query.aseid));
|
|
755
|
+
|
|
756
|
+
else if (Object.keys(dependency.query).length > 0)
|
|
757
|
+
result = result
|
|
758
|
+
.filter(dep => {
|
|
759
|
+
const query = dependency.query;
|
|
760
|
+
if (!query) return true;
|
|
761
|
+
|
|
762
|
+
return Object.entries(query).every(([key, value]) => {
|
|
763
|
+
return (dep as any)[key] === value;
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
// 5) apply pagination
|
|
769
|
+
const count = dependency.pagination.count;
|
|
770
|
+
const from = dependency.pagination.from; // from start or from end
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
const startSliceIndex = from === 'end'
|
|
774
|
+
? Math.max(result.length - count, 0)
|
|
775
|
+
: 0;
|
|
776
|
+
const endSliceIndex = from === 'end'
|
|
777
|
+
? result.length
|
|
778
|
+
: Math.min(count, result.length);
|
|
779
|
+
|
|
780
|
+
const slice = result.slice(startSliceIndex, endSliceIndex);
|
|
781
|
+
|
|
782
|
+
return slice.length === 1 ? slice[0] : slice.length ? slice : undefined;
|
|
665
783
|
}
|
|
666
784
|
|
|
667
785
|
|
|
@@ -693,13 +811,39 @@ export class A_Scope<
|
|
|
693
811
|
*/
|
|
694
812
|
name: string
|
|
695
813
|
): A_TYPES__Fragment_Constructor<T>
|
|
696
|
-
resolveConstructor<T extends
|
|
814
|
+
resolveConstructor<T extends A_TYPES__A_DependencyInjectable>(name: string): A_TYPES__Entity_Constructor<T> | A_TYPES__Component_Constructor<T> | A_TYPES__Fragment_Constructor<T> | undefined
|
|
815
|
+
resolveConstructor<T extends A_TYPES__A_DependencyInjectable>(name: string): A_TYPES__Entity_Constructor<T> | A_TYPES__Component_Constructor<T> | A_TYPES__Fragment_Constructor<T> | undefined {
|
|
697
816
|
// 1) Check components
|
|
698
817
|
const component = Array.from(this.allowedComponents).find(
|
|
699
818
|
c => c.name === name
|
|
700
819
|
|| c.name === A_FormatterHelper.toPascalCase(name)
|
|
701
820
|
);
|
|
821
|
+
|
|
702
822
|
if (component) return component as A_TYPES__Component_Constructor<T>;
|
|
823
|
+
else
|
|
824
|
+
// 1.2) Check components prototypes
|
|
825
|
+
{
|
|
826
|
+
const protoComponent = Array.from(this.allowedComponents).find(
|
|
827
|
+
|
|
828
|
+
// it should go rthough prototyopes and check their names to be equal to the provided name
|
|
829
|
+
c => {
|
|
830
|
+
let current = c;
|
|
831
|
+
|
|
832
|
+
while (current) {
|
|
833
|
+
if (current.name === name
|
|
834
|
+
|| current.name === A_FormatterHelper.toPascalCase(name)
|
|
835
|
+
) {
|
|
836
|
+
return true;
|
|
837
|
+
}
|
|
838
|
+
current = Object.getPrototypeOf(current);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
return false;
|
|
842
|
+
|
|
843
|
+
}
|
|
844
|
+
);
|
|
845
|
+
if (protoComponent) return protoComponent as A_TYPES__Component_Constructor<T>;
|
|
846
|
+
}
|
|
703
847
|
|
|
704
848
|
// 2) Check entities
|
|
705
849
|
const entity = Array.from(this.allowedEntities).find(
|
|
@@ -709,14 +853,38 @@ export class A_Scope<
|
|
|
709
853
|
|| (e as any).entity === A_FormatterHelper.toKebabCase(name)
|
|
710
854
|
);
|
|
711
855
|
if (entity) return entity as A_TYPES__Entity_Constructor<T>;
|
|
856
|
+
else
|
|
857
|
+
// 2.2) Check entities prototypes
|
|
858
|
+
{
|
|
859
|
+
const protoEntity = Array.from(this.allowedEntities).find(
|
|
860
|
+
e => A_CommonHelper.isInheritedFrom(e, name as any)
|
|
861
|
+
);
|
|
862
|
+
if (protoEntity) return protoEntity as A_TYPES__Entity_Constructor<T>;
|
|
863
|
+
}
|
|
712
864
|
|
|
713
865
|
// 3) Check fragments
|
|
714
866
|
const fragment = Array.from(this.allowedFragments).find(f => f.name === name
|
|
715
867
|
|| f.name === A_FormatterHelper.toPascalCase(name)
|
|
716
868
|
);
|
|
717
869
|
if (fragment) return fragment as A_TYPES__Fragment_Constructor<T>;
|
|
870
|
+
else
|
|
871
|
+
// 3.2) Check fragments prototypes
|
|
872
|
+
{
|
|
873
|
+
const protoFragment = Array.from(this.allowedFragments).find(
|
|
874
|
+
f => A_CommonHelper.isInheritedFrom(f, name as any)
|
|
875
|
+
);
|
|
876
|
+
if (protoFragment) return protoFragment as A_TYPES__Fragment_Constructor<T>;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// If not found in current scope, check imported scopes
|
|
880
|
+
for (const importedScope of this._imports) {
|
|
881
|
+
const importedConstructor = importedScope.resolveConstructor<T>(name);
|
|
882
|
+
if (importedConstructor) {
|
|
883
|
+
return importedConstructor;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
718
886
|
|
|
719
|
-
//
|
|
887
|
+
// Then, finally check parent scope
|
|
720
888
|
if (!!this._parent) {
|
|
721
889
|
return this._parent.resolveConstructor(name) as any;
|
|
722
890
|
}
|
|
@@ -753,14 +921,23 @@ export class A_Scope<
|
|
|
753
921
|
*/
|
|
754
922
|
entity: A_TYPES__Entity_Constructor<T>
|
|
755
923
|
): Array<T>
|
|
756
|
-
resolveAll<T extends
|
|
924
|
+
resolveAll<T extends A_TYPES__A_DependencyInjectable>(
|
|
925
|
+
/**
|
|
926
|
+
* Provide a component, fragment or entity constructor to resolve its instance(s) from the scope
|
|
927
|
+
*/
|
|
757
928
|
constructorName: string
|
|
758
929
|
): Array<T>
|
|
759
|
-
resolveAll<T extends
|
|
930
|
+
resolveAll<T extends A_TYPES__A_DependencyInjectable>(
|
|
931
|
+
/**
|
|
932
|
+
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
933
|
+
*/
|
|
934
|
+
ctor: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string
|
|
935
|
+
): Array<T>
|
|
936
|
+
resolveAll<T extends A_TYPES__A_DependencyInjectable>(
|
|
760
937
|
/**
|
|
761
938
|
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
762
939
|
*/
|
|
763
|
-
param1:
|
|
940
|
+
param1: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string
|
|
764
941
|
): Array<T> {
|
|
765
942
|
|
|
766
943
|
const results: Array<T> = [];
|
|
@@ -769,8 +946,15 @@ export class A_Scope<
|
|
|
769
946
|
const currentResults = this.resolveFlatAll<T>(param1 as any);
|
|
770
947
|
results.push(...currentResults);
|
|
771
948
|
|
|
772
|
-
// 2)
|
|
949
|
+
// 2) resolve all in the imported scopes
|
|
950
|
+
this._imports.forEach(importedScope => {
|
|
951
|
+
if (importedScope.has(param1 as any)) {
|
|
952
|
+
const importedResults = importedScope.resolveFlatAll<T>(param1 as any);
|
|
953
|
+
results.push(...importedResults);
|
|
954
|
+
}
|
|
955
|
+
});
|
|
773
956
|
|
|
957
|
+
// 3) Resolve all in the parent scope
|
|
774
958
|
let parentScope = this._parent;
|
|
775
959
|
|
|
776
960
|
while (parentScope && parentScope.has(param1 as any)) {
|
|
@@ -782,6 +966,7 @@ export class A_Scope<
|
|
|
782
966
|
}
|
|
783
967
|
|
|
784
968
|
|
|
969
|
+
|
|
785
970
|
return results;
|
|
786
971
|
}
|
|
787
972
|
|
|
@@ -814,14 +999,23 @@ export class A_Scope<
|
|
|
814
999
|
*/
|
|
815
1000
|
entity: A_TYPES__Entity_Constructor<T>
|
|
816
1001
|
): Array<T>
|
|
817
|
-
resolveFlatAll<T extends
|
|
1002
|
+
resolveFlatAll<T extends A_TYPES__A_DependencyInjectable>(
|
|
1003
|
+
/**
|
|
1004
|
+
* Provide a component, fragment or entity constructor to resolve its instance(s) from the scope
|
|
1005
|
+
*/
|
|
818
1006
|
constructorName: string
|
|
819
1007
|
): Array<T>
|
|
820
|
-
resolveFlatAll<T extends
|
|
1008
|
+
resolveFlatAll<T extends A_TYPES__A_DependencyInjectable>(
|
|
821
1009
|
/**
|
|
822
1010
|
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
823
1011
|
*/
|
|
824
|
-
|
|
1012
|
+
ctor: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string,
|
|
1013
|
+
): Array<T>
|
|
1014
|
+
resolveFlatAll<T extends A_TYPES__A_DependencyInjectable>(
|
|
1015
|
+
/**
|
|
1016
|
+
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
1017
|
+
*/
|
|
1018
|
+
param1: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string,
|
|
825
1019
|
): Array<T> {
|
|
826
1020
|
|
|
827
1021
|
const results: Array<T> = [];
|
|
@@ -832,7 +1026,7 @@ export class A_Scope<
|
|
|
832
1026
|
// 1) Check components
|
|
833
1027
|
this.allowedComponents.forEach(ctor => {
|
|
834
1028
|
if (A_CommonHelper.isInheritedFrom(ctor, param1)) {
|
|
835
|
-
const instance = this.
|
|
1029
|
+
const instance = this.resolveOnce<T>(ctor);
|
|
836
1030
|
if (instance) results.push(instance as T);
|
|
837
1031
|
}
|
|
838
1032
|
});
|
|
@@ -843,7 +1037,7 @@ export class A_Scope<
|
|
|
843
1037
|
// 2) Check fragments
|
|
844
1038
|
this.allowedFragments.forEach(ctor => {
|
|
845
1039
|
if (A_CommonHelper.isInheritedFrom(ctor, param1)) {
|
|
846
|
-
const instance = this.
|
|
1040
|
+
const instance = this.resolveOnce<T>(ctor);
|
|
847
1041
|
if (instance) results.push(instance as T);
|
|
848
1042
|
}
|
|
849
1043
|
});
|
|
@@ -903,57 +1097,70 @@ export class A_Scope<
|
|
|
903
1097
|
* @param component
|
|
904
1098
|
* @returns
|
|
905
1099
|
*/
|
|
906
|
-
resolve<T extends
|
|
1100
|
+
resolve<T extends A_TYPES__A_DependencyInjectable>(
|
|
907
1101
|
/**
|
|
908
1102
|
* Provide a component constructor to resolve its instance from the scope
|
|
909
1103
|
*/
|
|
910
|
-
component:
|
|
1104
|
+
component: A_TYPES__Ctor<T>
|
|
911
1105
|
): T | undefined
|
|
912
|
-
resolve<T extends
|
|
1106
|
+
resolve<T extends A_TYPES__A_DependencyInjectable>(
|
|
913
1107
|
/**
|
|
914
|
-
* Provide
|
|
1108
|
+
* Provide a target dependency to resolve its instance from the scope
|
|
1109
|
+
*
|
|
1110
|
+
* [!] In this case its possible to provide a custom resolution strategy via A_Dependency options
|
|
915
1111
|
*/
|
|
916
|
-
|
|
917
|
-
): Array<
|
|
918
|
-
resolve<T extends
|
|
1112
|
+
dependency: A_Dependency<T>
|
|
1113
|
+
): T | Array<T> | undefined
|
|
1114
|
+
resolve<T extends A_TYPES__A_DependencyInjectable>(
|
|
919
1115
|
/**
|
|
920
|
-
* Provide a
|
|
1116
|
+
* Provide a component constructor to resolve its instance from the scope
|
|
921
1117
|
*/
|
|
922
|
-
|
|
923
|
-
): T | undefined
|
|
924
|
-
resolve<T extends
|
|
1118
|
+
component: string
|
|
1119
|
+
): T | Array<T> | undefined
|
|
1120
|
+
resolve<T extends A_TYPES__A_DependencyInjectable>(
|
|
925
1121
|
/**
|
|
926
|
-
* Provide an array of
|
|
1122
|
+
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
927
1123
|
*/
|
|
928
|
-
|
|
929
|
-
): Array<
|
|
930
|
-
|
|
1124
|
+
param1: A_TYPES__Ctor<T> | A_Dependency<T> | string
|
|
1125
|
+
): T | Array<T> | undefined {
|
|
1126
|
+
|
|
1127
|
+
const dependency = A_TypeGuards.isDependencyInstance(param1) ?
|
|
1128
|
+
param1 as A_Dependency<T> :
|
|
1129
|
+
new A_Dependency<T>(param1)
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
return this.resolveDependency<T>(dependency);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
* This method allows to resolve/inject a component, fragment or entity from the scope
|
|
1137
|
+
* Depending on the provided parameters it can resolve:
|
|
1138
|
+
* - A single component/fragment/entity by its constructor or name
|
|
1139
|
+
* - An array of components/fragments/entities by providing an array of constructors
|
|
1140
|
+
* - An entity or an array of entities by providing the entity constructor and query instructions
|
|
1141
|
+
*
|
|
1142
|
+
* @param component
|
|
1143
|
+
* @returns
|
|
1144
|
+
*/
|
|
1145
|
+
resolveOnce<T extends A_Component>(
|
|
931
1146
|
/**
|
|
932
|
-
* Provide
|
|
1147
|
+
* Provide a component constructor to resolve its instance from the scope
|
|
933
1148
|
*/
|
|
934
|
-
|
|
1149
|
+
component: A_TYPES__Component_Constructor<T>
|
|
935
1150
|
): T | undefined
|
|
936
|
-
|
|
1151
|
+
resolveOnce<T extends A_Fragment>(
|
|
937
1152
|
/**
|
|
938
|
-
* Provide
|
|
939
|
-
*/
|
|
940
|
-
entity: A_TYPES__Entity_Constructor<T>,
|
|
941
|
-
/**
|
|
942
|
-
* Only Aseid Provided, in this case one entity will be returned
|
|
1153
|
+
* Provide a fragment constructor to resolve its instance from the scope
|
|
943
1154
|
*/
|
|
944
|
-
|
|
1155
|
+
fragment: A_TYPES__Fragment_Constructor<T>
|
|
945
1156
|
): T | undefined
|
|
946
|
-
|
|
1157
|
+
resolveOnce<T extends A_Entity>(
|
|
947
1158
|
/**
|
|
948
1159
|
* Provide an entity constructor to resolve its instance or an array of instances from the scope
|
|
949
1160
|
*/
|
|
950
|
-
entity: A_TYPES__Entity_Constructor<T
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
*/
|
|
954
|
-
instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<T>>
|
|
955
|
-
): Array<T>
|
|
956
|
-
resolve<T extends A_Scope>(
|
|
1161
|
+
entity: A_TYPES__Entity_Constructor<T>
|
|
1162
|
+
): T | undefined
|
|
1163
|
+
resolveOnce<T extends A_Scope>(
|
|
957
1164
|
/**
|
|
958
1165
|
* Uses only in case of resolving a single entity
|
|
959
1166
|
*
|
|
@@ -961,46 +1168,54 @@ export class A_Scope<
|
|
|
961
1168
|
*/
|
|
962
1169
|
scope: A_TYPES__Scope_Constructor<T>
|
|
963
1170
|
): T | undefined
|
|
964
|
-
|
|
1171
|
+
resolveOnce<T extends A_Error>(
|
|
965
1172
|
/**
|
|
966
1173
|
* Uses only in case of resolving a single entity
|
|
967
1174
|
*
|
|
968
1175
|
* Provide an entity constructor to resolve its instance from the scope
|
|
969
1176
|
*/
|
|
970
|
-
|
|
1177
|
+
error: A_TYPES__Error_Constructor<T>
|
|
971
1178
|
): T | undefined
|
|
972
|
-
|
|
1179
|
+
resolveOnce<T extends A_TYPES__A_DependencyInjectable>(
|
|
1180
|
+
/**
|
|
1181
|
+
* Provide a component, fragment or entity constructor to resolve its instance(s) from the scope
|
|
1182
|
+
*/
|
|
973
1183
|
constructorName: string
|
|
974
1184
|
): T | undefined
|
|
975
|
-
|
|
976
|
-
resolve<T extends A_TYPES__ScopeResolvableComponents>(
|
|
1185
|
+
resolveOnce<T extends A_TYPES__A_DependencyInjectable>(
|
|
977
1186
|
/**
|
|
978
1187
|
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
979
1188
|
*/
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
resolve<T extends A_TYPES__ScopeLinkedConstructors>(
|
|
1189
|
+
ctor: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string
|
|
1190
|
+
): T | undefined
|
|
1191
|
+
resolveOnce<T extends A_TYPES__A_DependencyInjectable>(
|
|
984
1192
|
/**
|
|
985
1193
|
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
986
1194
|
*/
|
|
987
|
-
param1:
|
|
1195
|
+
param1: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string
|
|
1196
|
+
): T | undefined {
|
|
988
1197
|
|
|
989
|
-
|
|
990
|
-
resolve<T extends A_TYPES__ScopeResolvableComponents>(
|
|
991
|
-
/**
|
|
992
|
-
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
993
|
-
*/
|
|
994
|
-
param1: A_TYPES__InjectableConstructors | Array<A_TYPES__InjectableConstructors>,
|
|
995
|
-
param2?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
|
|
996
|
-
): T | Array<T> | undefined {
|
|
1198
|
+
const value = this.resolveFlatOnce(param1);
|
|
997
1199
|
|
|
1200
|
+
// if not found in the current scope, check imported scopes
|
|
1201
|
+
if (!value) {
|
|
1202
|
+
for (const importedScope of this._imports) {
|
|
1203
|
+
if (importedScope.has(param1 as any)) {
|
|
1204
|
+
const importedValue = importedScope.resolveFlatOnce<T>(param1 as any);
|
|
1205
|
+
if (importedValue) {
|
|
1206
|
+
return importedValue;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
998
1211
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
return this.resolveOnce(param1
|
|
1212
|
+
// The idea here that in case when Scope has no exact component we have to resolve it from the _parent
|
|
1213
|
+
// That means that we should ensure that there's no components that are children of the required component
|
|
1214
|
+
if (!value && !!this.parent) {
|
|
1215
|
+
return this.parent.resolveOnce<T>(param1);
|
|
1003
1216
|
}
|
|
1217
|
+
|
|
1218
|
+
return value as T;
|
|
1004
1219
|
}
|
|
1005
1220
|
|
|
1006
1221
|
|
|
@@ -1021,50 +1236,18 @@ export class A_Scope<
|
|
|
1021
1236
|
*/
|
|
1022
1237
|
component: A_TYPES__Component_Constructor<T>
|
|
1023
1238
|
): T | undefined
|
|
1024
|
-
resolveFlat<T extends A_TYPES__Component_Constructor[]>(
|
|
1025
|
-
/**
|
|
1026
|
-
* Provide an array of component constructors to resolve their instances from the scope
|
|
1027
|
-
*/
|
|
1028
|
-
components: [...T]
|
|
1029
|
-
): Array<InstanceType<T[number]>> | undefined
|
|
1030
1239
|
resolveFlat<T extends A_Fragment>(
|
|
1031
1240
|
/**
|
|
1032
1241
|
* Provide a fragment constructor to resolve its instance from the scope
|
|
1033
1242
|
*/
|
|
1034
1243
|
fragment: A_TYPES__Fragment_Constructor<T>
|
|
1035
1244
|
): T | undefined
|
|
1036
|
-
resolveFlat<T extends A_TYPES__Fragment_Constructor[]>(
|
|
1037
|
-
/**
|
|
1038
|
-
* Provide an array of fragment constructors to resolve their instances from the scope
|
|
1039
|
-
*/
|
|
1040
|
-
fragments: [...T]
|
|
1041
|
-
): Array<InstanceType<T[number]>> | undefined
|
|
1042
1245
|
resolveFlat<T extends A_Entity>(
|
|
1043
1246
|
/**
|
|
1044
1247
|
* Provide an entity constructor to resolve its instance or an array of instances from the scope
|
|
1045
1248
|
*/
|
|
1046
1249
|
entity: A_TYPES__Entity_Constructor<T>
|
|
1047
1250
|
): T | undefined
|
|
1048
|
-
resolveFlat<T extends A_Entity>(
|
|
1049
|
-
/**
|
|
1050
|
-
* Provide an entity constructor to resolve its instance or an array of instances from the scope
|
|
1051
|
-
*/
|
|
1052
|
-
entity: A_TYPES__Entity_Constructor<T>,
|
|
1053
|
-
/**
|
|
1054
|
-
* Only Aseid Provided, in this case one entity will be returned
|
|
1055
|
-
*/
|
|
1056
|
-
instructions: { query: { aseid: string | ASEID } }
|
|
1057
|
-
): T | undefined
|
|
1058
|
-
resolveFlat<T extends A_Entity>(
|
|
1059
|
-
/**
|
|
1060
|
-
* Provide an entity constructor to resolve its instance or an array of instances from the scope
|
|
1061
|
-
*/
|
|
1062
|
-
entity: A_TYPES__Entity_Constructor<T>,
|
|
1063
|
-
/**
|
|
1064
|
-
* Provide optional instructions to find a specific entity or a set of entities
|
|
1065
|
-
*/
|
|
1066
|
-
instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<T>>
|
|
1067
|
-
): Array<T>
|
|
1068
1251
|
resolveFlat<T extends A_Scope>(
|
|
1069
1252
|
/**
|
|
1070
1253
|
* Uses only in case of resolving a single entity
|
|
@@ -1079,43 +1262,87 @@ export class A_Scope<
|
|
|
1079
1262
|
*
|
|
1080
1263
|
* Provide an entity constructor to resolve its instance from the scope
|
|
1081
1264
|
*/
|
|
1082
|
-
|
|
1265
|
+
error: A_TYPES__Error_Constructor<T>
|
|
1083
1266
|
): T | undefined
|
|
1084
|
-
resolveFlat<T extends
|
|
1267
|
+
resolveFlat<T extends A_TYPES__A_DependencyInjectable>(
|
|
1268
|
+
/**
|
|
1269
|
+
* Provide a component, fragment or entity constructor to resolve its instance(s) from the scope
|
|
1270
|
+
*/
|
|
1085
1271
|
constructorName: string
|
|
1086
1272
|
): T | undefined
|
|
1087
|
-
|
|
1088
|
-
resolveFlat<T extends A_TYPES__ScopeResolvableComponents>(
|
|
1273
|
+
resolveFlat<T extends A_TYPES__A_DependencyInjectable>(
|
|
1089
1274
|
/**
|
|
1090
1275
|
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
1091
1276
|
*/
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
resolveFlat<T extends A_TYPES__ScopeLinkedConstructors>(
|
|
1277
|
+
ctor: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable>,
|
|
1278
|
+
): T | undefined
|
|
1279
|
+
resolveFlat<T extends A_TYPES__A_DependencyInjectable>(
|
|
1096
1280
|
/**
|
|
1097
1281
|
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
1098
1282
|
*/
|
|
1099
|
-
param1:
|
|
1283
|
+
param1: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string,
|
|
1284
|
+
): T | undefined {
|
|
1285
|
+
return this.resolveFlatOnce(param1) as T;
|
|
1286
|
+
}
|
|
1100
1287
|
|
|
1101
|
-
): T | Array<T> | undefined
|
|
1102
|
-
resolveFlat<T extends A_TYPES__ScopeResolvableComponents>(
|
|
1103
|
-
/**
|
|
1104
|
-
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
1105
|
-
*/
|
|
1106
|
-
param1: A_TYPES__InjectableConstructors | Array<A_TYPES__InjectableConstructors>,
|
|
1107
|
-
param2?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
|
|
1108
|
-
): T | Array<T | undefined> | undefined {
|
|
1109
1288
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1289
|
+
/**
|
|
1290
|
+
* Resolves a component, fragment or entity from the scope without checking parent scopes
|
|
1291
|
+
*
|
|
1292
|
+
* @param component
|
|
1293
|
+
* @param instructions
|
|
1294
|
+
*/
|
|
1295
|
+
resolveFlatOnce<T extends A_TYPES__A_DependencyInjectable>(
|
|
1296
|
+
component: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string,
|
|
1297
|
+
): T | undefined {
|
|
1298
|
+
|
|
1299
|
+
let value: T | undefined = undefined;
|
|
1300
|
+
|
|
1301
|
+
const componentName = A_CommonHelper.getComponentName(component);
|
|
1116
1302
|
|
|
1117
1303
|
|
|
1304
|
+
if (!component || !this.has(component)) {
|
|
1305
|
+
return undefined;
|
|
1306
|
+
}
|
|
1118
1307
|
|
|
1308
|
+
switch (true) {
|
|
1309
|
+
case A_TypeGuards.isString(component): {
|
|
1310
|
+
value = this.resolveByName(component) as T;
|
|
1311
|
+
break;
|
|
1312
|
+
}
|
|
1313
|
+
case A_TypeGuards.isConstructorAllowedForScopeAllocation(component): {
|
|
1314
|
+
value = this.resolveIssuer(component) as T;
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1317
|
+
case A_TypeGuards.isScopeConstructor(component): {
|
|
1318
|
+
value = this.resolveScope(component) as T
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1321
|
+
case A_TypeGuards.isEntityConstructor(component): {
|
|
1322
|
+
value = this.resolveEntity(component) as T
|
|
1323
|
+
break;
|
|
1324
|
+
}
|
|
1325
|
+
case A_TypeGuards.isFragmentConstructor(component): {
|
|
1326
|
+
value = this.resolveFragment(component) as T;
|
|
1327
|
+
break;
|
|
1328
|
+
}
|
|
1329
|
+
case A_TypeGuards.isComponentConstructor(component): {
|
|
1330
|
+
value = this.resolveComponent(component) as T;
|
|
1331
|
+
break;
|
|
1332
|
+
}
|
|
1333
|
+
case A_TypeGuards.isErrorConstructor(component): {
|
|
1334
|
+
value = this.resolveError(component) as T;
|
|
1335
|
+
break;
|
|
1336
|
+
}
|
|
1337
|
+
default:
|
|
1338
|
+
throw new A_ScopeError(
|
|
1339
|
+
A_ScopeError.ResolutionError,
|
|
1340
|
+
`Injected Component ${componentName} not found in the scope`
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
return value
|
|
1345
|
+
}
|
|
1119
1346
|
|
|
1120
1347
|
|
|
1121
1348
|
|
|
@@ -1174,86 +1401,6 @@ export class A_Scope<
|
|
|
1174
1401
|
return undefined;
|
|
1175
1402
|
}
|
|
1176
1403
|
|
|
1177
|
-
/**
|
|
1178
|
-
* Resolves a component, fragment or entity from the scope without checking parent scopes
|
|
1179
|
-
*
|
|
1180
|
-
* @param component
|
|
1181
|
-
* @param instructions
|
|
1182
|
-
*/
|
|
1183
|
-
private resolveFlatOnce(
|
|
1184
|
-
component: any,
|
|
1185
|
-
instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
|
|
1186
|
-
): A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | Array<A_TYPES__ScopeResolvableComponents> | undefined {
|
|
1187
|
-
|
|
1188
|
-
let value: A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | Array<A_TYPES__ScopeResolvableComponents> | undefined = undefined;
|
|
1189
|
-
|
|
1190
|
-
const componentName = A_CommonHelper.getComponentName(component);
|
|
1191
|
-
|
|
1192
|
-
if (!component || !this.has(component))
|
|
1193
|
-
return undefined;
|
|
1194
|
-
|
|
1195
|
-
switch (true) {
|
|
1196
|
-
case A_TypeGuards.isString(component): {
|
|
1197
|
-
value = this.resolveByName(component) as A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | undefined;
|
|
1198
|
-
break;
|
|
1199
|
-
}
|
|
1200
|
-
case A_TypeGuards.isConstructorAllowedForScopeAllocation(component): {
|
|
1201
|
-
value = this.resolveIssuer(component);
|
|
1202
|
-
break;
|
|
1203
|
-
}
|
|
1204
|
-
case A_TypeGuards.isEntityConstructor(component): {
|
|
1205
|
-
value = this.resolveEntity(component, instructions);
|
|
1206
|
-
break;
|
|
1207
|
-
}
|
|
1208
|
-
case A_TypeGuards.isFragmentConstructor(component): {
|
|
1209
|
-
value = this.resolveFragment(component);
|
|
1210
|
-
break;
|
|
1211
|
-
}
|
|
1212
|
-
case A_TypeGuards.isScopeConstructor(component): {
|
|
1213
|
-
value = this.resolveScope(component);
|
|
1214
|
-
break;
|
|
1215
|
-
}
|
|
1216
|
-
case A_TypeGuards.isComponentConstructor(component): {
|
|
1217
|
-
value = this.resolveComponent(component);
|
|
1218
|
-
break;
|
|
1219
|
-
}
|
|
1220
|
-
case A_TypeGuards.isErrorConstructor(component): {
|
|
1221
|
-
value = this.resolveError(component);
|
|
1222
|
-
break;
|
|
1223
|
-
}
|
|
1224
|
-
default:
|
|
1225
|
-
throw new A_ScopeError(
|
|
1226
|
-
A_ScopeError.ResolutionError,
|
|
1227
|
-
`Injected Component ${componentName} not found in the scope`
|
|
1228
|
-
);
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
return value;
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
/**
|
|
1235
|
-
* This method is used internally to resolve a single component, fragment or entity from the scope
|
|
1236
|
-
*
|
|
1237
|
-
* @param component
|
|
1238
|
-
* @param instructions
|
|
1239
|
-
* @returns
|
|
1240
|
-
*/
|
|
1241
|
-
private resolveOnce(
|
|
1242
|
-
component: any,
|
|
1243
|
-
instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
|
|
1244
|
-
): A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | Array<A_TYPES__ScopeResolvableComponents> | undefined {
|
|
1245
|
-
|
|
1246
|
-
const values = this.resolveFlatOnce(component, instructions);
|
|
1247
|
-
|
|
1248
|
-
// The idea here that in case when Scope has no exact component we have to resolve it from the _parent
|
|
1249
|
-
// That means that we should ensure that there's no components that are children of the required component
|
|
1250
|
-
if (!values && !!this.parent) {
|
|
1251
|
-
return this.parent.resolveOnce(component, instructions);
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
return values;
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
1404
|
|
|
1258
1405
|
/**
|
|
1259
1406
|
* Resolves the issuer of the scope by provided constructor
|
|
@@ -1294,87 +1441,18 @@ export class A_Scope<
|
|
|
1294
1441
|
* @returns
|
|
1295
1442
|
*/
|
|
1296
1443
|
private resolveEntity<T extends A_Entity>(
|
|
1297
|
-
entity: A_TYPES__Entity_Constructor<T
|
|
1298
|
-
instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<T>>
|
|
1444
|
+
entity: A_TYPES__Entity_Constructor<T>
|
|
1299
1445
|
): T | Array<T> | undefined {
|
|
1300
1446
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
*
|
|
1308
|
-
* [!] Note that it returns ONLY ONE entity
|
|
1309
|
-
* [!!] In case when no entity found in the current scope, it tries to resolve it from the parent scope (if exists)
|
|
1310
|
-
*/
|
|
1311
|
-
case !instructions: {
|
|
1312
|
-
return this.entities.find(e => e instanceof entity) as T | undefined;
|
|
1313
|
-
}
|
|
1314
|
-
/**
|
|
1315
|
-
* 2) In case when aseid is provided in the query, we can directly get the entity from the map
|
|
1316
|
-
*
|
|
1317
|
-
* [!] Note that it returns ONLY ONE entity
|
|
1318
|
-
*/
|
|
1319
|
-
case !!query.aseid
|
|
1320
|
-
&& typeof query.aseid === 'string'
|
|
1321
|
-
&& this._entities.has(query.aseid): {
|
|
1322
|
-
return this._entities.get(query.aseid) as T;
|
|
1323
|
-
}
|
|
1324
|
-
/**
|
|
1325
|
-
* 3) In case when aseid is provided as ASEID instance, we can directly get the entity from the map
|
|
1326
|
-
*
|
|
1327
|
-
* [!] Note that it returns ONLY ONE entity
|
|
1328
|
-
*/
|
|
1329
|
-
case !!query.aseid
|
|
1330
|
-
&& typeof query.aseid === 'object'
|
|
1331
|
-
&& query.aseid instanceof ASEID
|
|
1332
|
-
&& this._entities.has(query.aseid.toString()): {
|
|
1333
|
-
return this._entities.get(query.aseid.toString()) as T;
|
|
1334
|
-
}
|
|
1335
|
-
/**
|
|
1336
|
-
* 4) In case when id is provided in the query, we have to find the entity by the id
|
|
1337
|
-
*
|
|
1338
|
-
* [!] Note that it returns ONLY ONE entity
|
|
1339
|
-
*/
|
|
1340
|
-
case !!query.id: {
|
|
1341
|
-
|
|
1342
|
-
const found = this.entities
|
|
1343
|
-
.filter(e => e instanceof entity)
|
|
1344
|
-
.find(e => String(e.id) === String(query.id));
|
|
1345
|
-
|
|
1346
|
-
return found as T;
|
|
1347
|
-
}
|
|
1348
|
-
/**
|
|
1349
|
-
* 5) In case when there's a query object, we have to filter the entities by the query
|
|
1350
|
-
*
|
|
1351
|
-
* [!] Note that it can return either a single entity or an array of entities depending on the count instruction
|
|
1352
|
-
* [!!] In case when no entity found in the current scope, it tries to resolve it from the parent scope (if exists)
|
|
1353
|
-
*/
|
|
1354
|
-
default: {
|
|
1355
|
-
|
|
1356
|
-
const found = this.entities
|
|
1357
|
-
.filter(e => e instanceof entity)
|
|
1358
|
-
.filter(e => {
|
|
1359
|
-
return Object
|
|
1360
|
-
.entries(query)
|
|
1361
|
-
.every(([key, value]) => {
|
|
1362
|
-
if (key in e) {
|
|
1363
|
-
return (e as any)[key] === value;
|
|
1364
|
-
}
|
|
1365
|
-
return false;
|
|
1366
|
-
});
|
|
1367
|
-
});
|
|
1368
|
-
|
|
1369
|
-
if (found.length === 0)
|
|
1370
|
-
return undefined;
|
|
1447
|
+
/**
|
|
1448
|
+
* 1) In case when no instructions provided, return the first found entity of the provided type
|
|
1449
|
+
*
|
|
1450
|
+
* [!] Note that it returns ONLY ONE entity
|
|
1451
|
+
* [!!] In case when no entity found in the current scope, it tries to resolve it from the parent scope (if exists)
|
|
1452
|
+
*/
|
|
1371
1453
|
|
|
1372
|
-
|
|
1373
|
-
return found[0] as T;
|
|
1454
|
+
return this.entities.find(e => e instanceof entity) as T | undefined;
|
|
1374
1455
|
|
|
1375
|
-
return found as T[];
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
1456
|
}
|
|
1379
1457
|
/**
|
|
1380
1458
|
* This method is used internally to resolve a single error from the scope
|
|
@@ -1449,74 +1527,8 @@ export class A_Scope<
|
|
|
1449
1527
|
const argsMeta = componentMeta.get(A_TYPES__ComponentMetaKey.INJECTIONS);
|
|
1450
1528
|
|
|
1451
1529
|
const resolvedArgs = (argsMeta?.get('constructor') || [])
|
|
1452
|
-
.map(
|
|
1453
|
-
|
|
1454
|
-
const componentName = A_CommonHelper.getComponentName(arg.target)
|
|
1455
|
-
|
|
1456
|
-
if ('instructions' in arg && !!arg.instructions) {
|
|
1457
|
-
const { target, parent, flat, instructions } = arg
|
|
1458
|
-
const dependency = this.resolve(target as any, instructions);
|
|
1459
|
-
if (!dependency)
|
|
1460
|
-
throw new A_ScopeError(
|
|
1461
|
-
A_ScopeError.ResolutionError,
|
|
1462
|
-
`Unable to resolve dependency ${componentName} for component ${component.name} in scope ${this.name}`
|
|
1463
|
-
);
|
|
1464
|
-
|
|
1465
|
-
return dependency;
|
|
1466
|
-
} else {
|
|
1467
|
-
const { target, require, create, defaultArgs, parent, flat, } = arg;
|
|
1468
|
-
|
|
1469
|
-
let dependency;
|
|
1470
|
-
|
|
1471
|
-
// ----------------- Resolution Strategies -----------------
|
|
1472
|
-
switch (true) {
|
|
1473
|
-
// 1) Flat resolution
|
|
1474
|
-
case flat: {
|
|
1475
|
-
dependency = this.resolveFlat(target);
|
|
1476
|
-
break;
|
|
1477
|
-
}
|
|
1478
|
-
// 2) Parent resolution
|
|
1479
|
-
case parent && typeof parent.layerOffset === 'number': {
|
|
1480
|
-
const targetParent = this.parentOffset(parent.layerOffset);
|
|
1481
|
-
if (!targetParent) {
|
|
1482
|
-
throw new A_ScopeError(
|
|
1483
|
-
A_ScopeError.ResolutionError,
|
|
1484
|
-
`Unable to resolve parent scope at offset ${parent.layerOffset} for dependency ${componentName} for component ${component.name} in scope ${this.name}`
|
|
1485
|
-
);
|
|
1486
|
-
}
|
|
1487
|
-
dependency = targetParent.resolve(target);
|
|
1488
|
-
|
|
1489
|
-
break;
|
|
1490
|
-
}
|
|
1491
|
-
// 3) Normal resolution
|
|
1492
|
-
default: {
|
|
1493
|
-
dependency = this.resolve(target);
|
|
1494
|
-
break;
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
|
|
1498
|
-
// ----------------- Post-Resolution Actions -----------------
|
|
1499
|
-
|
|
1500
|
-
// 1) Create default instance in case when allowed
|
|
1501
|
-
if (create && !dependency && A_TypeGuards.isAllowedForDependencyDefaultCreation(target)) {
|
|
1502
|
-
dependency = new target(...defaultArgs);
|
|
1503
|
-
|
|
1504
|
-
this.register(dependency);
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
// 2) Throw error in case when required but not resolved
|
|
1508
|
-
if (require && !dependency) {
|
|
1509
|
-
throw new A_ScopeError(
|
|
1510
|
-
A_ScopeError.ResolutionError,
|
|
1511
|
-
`Unable to resolve required dependency ${componentName} for component ${component.name} in scope ${this.name}`
|
|
1512
|
-
);
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
// Finally, return the dependency (either resolved or undefined)
|
|
1517
|
-
return dependency;
|
|
1518
|
-
}
|
|
1519
|
-
});
|
|
1530
|
+
.map(dependency => this.resolve(dependency));
|
|
1531
|
+
|
|
1520
1532
|
|
|
1521
1533
|
const newComponent = new component(...resolvedArgs)
|
|
1522
1534
|
|
|
@@ -1591,9 +1603,17 @@ export class A_Scope<
|
|
|
1591
1603
|
*/
|
|
1592
1604
|
entity: T
|
|
1593
1605
|
): void
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1606
|
+
register<T extends A_TYPES__A_DependencyInjectable>(
|
|
1607
|
+
/**
|
|
1608
|
+
* Provide an entity instance to register it in the scope
|
|
1609
|
+
*/
|
|
1610
|
+
entity: T
|
|
1611
|
+
): void
|
|
1612
|
+
register<T extends A_TYPES__A_DependencyInjectable>(
|
|
1613
|
+
/**
|
|
1614
|
+
* Provide an entity instance to register it in the scope
|
|
1615
|
+
*/
|
|
1616
|
+
param1: T
|
|
1597
1617
|
): void {
|
|
1598
1618
|
switch (true) {
|
|
1599
1619
|
// ------------------------------------------
|