@adaas/a-concept 0.1.50 → 0.1.52
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 +31 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/global/A-Entity/A-Entity.class.ts +21 -12
- package/src/global/A-Scope/A-Scope.class.ts +113 -0
- package/tests/A-Scope.test.ts +58 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaas/a-concept",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.52",
|
|
4
4
|
"description": "A-Concept is a framework to build new Applications within or outside the ADAAS ecosystem. This framework is designed to be modular structure regardless environment and program goal.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -10,6 +10,7 @@ import { ASEID } from "../ASEID/ASEID.class";
|
|
|
10
10
|
import { A_IdentityHelper } from "@adaas/a-concept/helpers/A_Identity.helper";
|
|
11
11
|
import { A_EntityError } from "./A-Entity.error";
|
|
12
12
|
import { A_Feature } from "../A-Feature/A-Feature.class";
|
|
13
|
+
import { A_TYPES__ASEID_Constructor } from "../ASEID/ASEID.types";
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -239,6 +240,23 @@ export class A_Entity<
|
|
|
239
240
|
throw new A_EntityError(A_EntityError.ValidationError, 'Unable to determine A-Entity constructor initialization method. Please check the provided parameters.');
|
|
240
241
|
}
|
|
241
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Generates a new ASEID for the entity.
|
|
245
|
+
* It uses class definitions for concept, scope, and entity,
|
|
246
|
+
* and allows overriding any of these values.
|
|
247
|
+
*
|
|
248
|
+
* @param override
|
|
249
|
+
* @returns
|
|
250
|
+
*/
|
|
251
|
+
protected generateASEID(override?: Partial<A_TYPES__ASEID_Constructor>): ASEID {
|
|
252
|
+
return new ASEID({
|
|
253
|
+
concept: override?.concept || (this.constructor as typeof A_Entity).concept,
|
|
254
|
+
scope: override?.scope || (this.constructor as typeof A_Entity).scope,
|
|
255
|
+
entity: override?.entity || (this.constructor as typeof A_Entity).entity,
|
|
256
|
+
id: override?.id || A_IdentityHelper.generateTimeId()
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
242
260
|
|
|
243
261
|
/**
|
|
244
262
|
* Call a feature of the component with the provided scope
|
|
@@ -318,12 +336,8 @@ export class A_Entity<
|
|
|
318
336
|
* @returns
|
|
319
337
|
*/
|
|
320
338
|
fromUndefined(): void {
|
|
321
|
-
this.aseid =
|
|
322
|
-
|
|
323
|
-
scope: (this.constructor as typeof A_Entity).scope,
|
|
324
|
-
entity: (this.constructor as typeof A_Entity).entity,
|
|
325
|
-
id: A_IdentityHelper.generateTimeId()
|
|
326
|
-
});
|
|
339
|
+
this.aseid = this.generateASEID();
|
|
340
|
+
|
|
327
341
|
return;
|
|
328
342
|
}
|
|
329
343
|
|
|
@@ -336,12 +350,7 @@ export class A_Entity<
|
|
|
336
350
|
* @returns
|
|
337
351
|
*/
|
|
338
352
|
fromNew(newEntity: _ConstructorType): void {
|
|
339
|
-
this.aseid =
|
|
340
|
-
concept: (this.constructor as typeof A_Entity).concept,
|
|
341
|
-
scope: (this.constructor as typeof A_Entity).scope,
|
|
342
|
-
entity: (this.constructor as typeof A_Entity).entity,
|
|
343
|
-
id: A_IdentityHelper.generateTimeId()
|
|
344
|
-
});
|
|
353
|
+
this.aseid = this.generateASEID();
|
|
345
354
|
|
|
346
355
|
return;
|
|
347
356
|
}
|
|
@@ -641,6 +641,117 @@ export class A_Scope<
|
|
|
641
641
|
|
|
642
642
|
|
|
643
643
|
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* This method should resolve all instances of the components, or entities within the scope, by provided parent class
|
|
647
|
+
* So in case of providing a base class it should return all instances that extends this base class
|
|
648
|
+
*
|
|
649
|
+
* @param component
|
|
650
|
+
*/
|
|
651
|
+
resolveAll<T extends A_Component>(
|
|
652
|
+
/**
|
|
653
|
+
* Provide a component constructor to resolve its instance from the scope
|
|
654
|
+
*/
|
|
655
|
+
component: A_TYPES__Component_Constructor<T>
|
|
656
|
+
): Array<T>
|
|
657
|
+
resolveAll<T extends A_Fragment>(
|
|
658
|
+
/**
|
|
659
|
+
* Provide a fragment constructor to resolve its instance from the scope
|
|
660
|
+
*/
|
|
661
|
+
fragment: A_TYPES__Fragment_Constructor<T>
|
|
662
|
+
): Array<T>
|
|
663
|
+
resolveAll<T extends A_Entity>(
|
|
664
|
+
/**
|
|
665
|
+
* Provide an entity constructor to resolve its instance or an array of instances from the scope
|
|
666
|
+
*/
|
|
667
|
+
entity: A_TYPES__Entity_Constructor<T>
|
|
668
|
+
): Array<T>
|
|
669
|
+
resolveAll<T extends A_TYPES__ScopeResolvableComponents>(
|
|
670
|
+
constructorName: string
|
|
671
|
+
): Array<T>
|
|
672
|
+
resolveAll<T extends A_TYPES__ScopeResolvableComponents>(
|
|
673
|
+
/**
|
|
674
|
+
* Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
|
|
675
|
+
*/
|
|
676
|
+
param1: A_TYPES__InjectableConstructors
|
|
677
|
+
): Array<T> {
|
|
678
|
+
const results: Array<T> = [];
|
|
679
|
+
|
|
680
|
+
switch (true) {
|
|
681
|
+
// 1) if a parameter is a component constructor
|
|
682
|
+
case A_TypeGuards.isComponentConstructor(param1): {
|
|
683
|
+
// 1) Check components
|
|
684
|
+
this.allowedComponents.forEach(ctor => {
|
|
685
|
+
if (A_CommonHelper.isInheritedFrom(ctor, param1)) {
|
|
686
|
+
const instance = this.resolve<T>(ctor);
|
|
687
|
+
if (instance) results.push(instance as T);
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
// 2) if a parameter is a fragment constructor
|
|
693
|
+
case A_TypeGuards.isFragmentConstructor(param1): {
|
|
694
|
+
// 2) Check fragments
|
|
695
|
+
this.allowedFragments.forEach(ctor => {
|
|
696
|
+
if (A_CommonHelper.isInheritedFrom(ctor, param1)) {
|
|
697
|
+
const instance = this.resolve(ctor);
|
|
698
|
+
if (instance) results.push(instance as T);
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
break;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
case A_TypeGuards.isEntityConstructor(param1): {
|
|
705
|
+
// 3) Check entities
|
|
706
|
+
this.allowedEntities.forEach(ctor => {
|
|
707
|
+
if (A_CommonHelper.isInheritedFrom(ctor, param1)) {
|
|
708
|
+
const instance = this.resolve<T>(ctor);
|
|
709
|
+
if (instance) results.push(instance as T);
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
case A_TypeGuards.isString(param1): {
|
|
716
|
+
// 4) Check by name
|
|
717
|
+
const ctor = this.resolveConstructor(param1);
|
|
718
|
+
if (!A_TypeGuards.isComponentConstructor(ctor)
|
|
719
|
+
&& !A_TypeGuards.isEntityConstructor(ctor)
|
|
720
|
+
&& !A_TypeGuards.isFragmentConstructor(ctor)
|
|
721
|
+
)
|
|
722
|
+
throw new A_ScopeError(
|
|
723
|
+
A_ScopeError.ResolutionError,
|
|
724
|
+
`Unable to resolve all instances for name: ${param1} in scope ${this.name} as no matching component, entity or fragment constructor found`);
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
if (ctor) {
|
|
728
|
+
const instances = this.resolveAll<T>(ctor as any);
|
|
729
|
+
if (instances)
|
|
730
|
+
results.push(...instances);
|
|
731
|
+
}
|
|
732
|
+
break;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
default:
|
|
736
|
+
throw new A_ScopeError(
|
|
737
|
+
A_ScopeError.ResolutionError,
|
|
738
|
+
`Invalid parameter provided to resolveAll method: ${param1} in scope ${this.name}`);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
const parentScope = this._parent;
|
|
743
|
+
|
|
744
|
+
while (parentScope && parentScope.has(param1 as any)) {
|
|
745
|
+
const parentResults = parentScope.resolveAll<T>(param1 as any);
|
|
746
|
+
results.push(...parentResults);
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
return results;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
|
|
644
755
|
/**
|
|
645
756
|
* This method allows to resolve/inject a component, fragment or entity from the scope
|
|
646
757
|
* Depending on the provided parameters it can resolve:
|
|
@@ -762,6 +873,8 @@ export class A_Scope<
|
|
|
762
873
|
|
|
763
874
|
|
|
764
875
|
|
|
876
|
+
|
|
877
|
+
|
|
765
878
|
// ==================================================================================================
|
|
766
879
|
// --------------------------------------------------------------------------------------------------
|
|
767
880
|
// -------------------------------------INTERNAL RESOLVERS-------------------------------------------
|
package/tests/A-Scope.test.ts
CHANGED
|
@@ -375,5 +375,63 @@ describe('A-Scope tests', () => {
|
|
|
375
375
|
|
|
376
376
|
expect(container.scope.issuer()).toBe(container);
|
|
377
377
|
});
|
|
378
|
+
it('Should be able to resolve all Component of particular type from scope', async () => {
|
|
379
|
+
|
|
380
|
+
class BaseComponent extends A_Component { }
|
|
381
|
+
class ComponentA extends BaseComponent { }
|
|
382
|
+
class ComponentB extends BaseComponent { }
|
|
383
|
+
class ComponentC extends A_Component { }
|
|
384
|
+
|
|
385
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
386
|
+
|
|
387
|
+
scope.register(ComponentA);
|
|
388
|
+
scope.register(ComponentB);
|
|
389
|
+
scope.register(ComponentC);
|
|
390
|
+
|
|
391
|
+
const resolvedComponents = scope.resolveAll<BaseComponent>(BaseComponent);
|
|
392
|
+
|
|
393
|
+
expect(resolvedComponents.length).toBe(2);
|
|
394
|
+
// some of resolvedComponents should be instances of ComponentA and ComponentB
|
|
395
|
+
expect(resolvedComponents.some(c => c instanceof ComponentA)).toBe(true)
|
|
396
|
+
expect(resolvedComponents.some(c => c instanceof ComponentB)).toBe(true)
|
|
397
|
+
// should not contain class instance of ComponentC
|
|
398
|
+
expect(resolvedComponents.some(c => c instanceof ComponentC)).toBe(false)
|
|
399
|
+
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('Should be able to resolve all Component of particular type from all parent scopes as well with priority from current scope', async () => {
|
|
403
|
+
|
|
404
|
+
class BaseComponent extends A_Component { }
|
|
405
|
+
class ComponentA extends BaseComponent { }
|
|
406
|
+
class ComponentB extends BaseComponent { }
|
|
407
|
+
class ComponentC extends BaseComponent { }
|
|
408
|
+
class ComponentD extends A_Component { }
|
|
409
|
+
|
|
410
|
+
const parentScope = new A_Scope({ name: 'ParentScope' });
|
|
411
|
+
const childScope = new A_Scope({ name: 'ChildScope' });
|
|
412
|
+
|
|
413
|
+
childScope.inherit(parentScope);
|
|
414
|
+
|
|
415
|
+
parentScope.register(ComponentA);
|
|
416
|
+
parentScope.register(ComponentB);
|
|
417
|
+
childScope.register(ComponentC);
|
|
418
|
+
childScope.register(ComponentD);
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
const resolvedComponents = childScope.resolveAll<BaseComponent>(BaseComponent);
|
|
422
|
+
|
|
423
|
+
expect(resolvedComponents.length).toBe(3);
|
|
424
|
+
|
|
425
|
+
// should not contain class instance of ComponentD
|
|
426
|
+
expect(resolvedComponents).not.toContain(ComponentD);
|
|
427
|
+
|
|
428
|
+
// some of resolvedComponents should be instances of ComponentA, ComponentB and ComponentC
|
|
429
|
+
expect(resolvedComponents.some(c => c instanceof ComponentA)).toBe(true)
|
|
430
|
+
expect(resolvedComponents.some(c => c instanceof ComponentB)).toBe(true)
|
|
431
|
+
expect(resolvedComponents.some(c => c instanceof ComponentC)).toBe(true)
|
|
432
|
+
|
|
433
|
+
// the first element should be instance of ComponentC as it is registered in child scope
|
|
434
|
+
expect(resolvedComponents[0] instanceof ComponentC).toBe(true);
|
|
435
|
+
});
|
|
378
436
|
|
|
379
437
|
});
|