@adaas/a-concept 0.1.55 → 0.1.56

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaas/a-concept",
3
- "version": "0.1.55",
3
+ "version": "0.1.56",
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",
@@ -460,6 +460,63 @@ export class A_Scope<
460
460
  ctor: unknown
461
461
  ): boolean {
462
462
 
463
+ let found = this.hasFlat(ctor as any);
464
+
465
+ if (!found && !!this._parent)
466
+ try {
467
+ return this._parent.has(ctor as any);
468
+ } catch (error) {
469
+ return false;
470
+ }
471
+
472
+ return found;
473
+ }
474
+
475
+
476
+ /**
477
+ * This method is used to check if the component is available in the scope
478
+ *
479
+ * [!] Note that this method checks for the component ONLY in the current scope
480
+ *
481
+ * @param component
482
+ * @returns
483
+ */
484
+ hasFlat<T extends A_Component>(
485
+ /**
486
+ * Provide a component constructor to check if it's available in the scope
487
+ */
488
+ component: A_TYPES__Component_Constructor<T>
489
+ ): boolean
490
+ hasFlat<T extends A_Entity>(
491
+ /**
492
+ * Provide an entity constructor to check if it's available in the scope
493
+ *
494
+ * [!] Note that entities are unique per aseid, so this method checks if there's at least one entity of the provided type in the scope
495
+ */
496
+ entity: A_TYPES__Entity_Constructor<T>
497
+ ): boolean
498
+ hasFlat<T extends A_Fragment>(
499
+ /**
500
+ * Provide a fragment constructor to check if it's available in the scope
501
+ */
502
+ fragment: A_TYPES__Fragment_Constructor<T>
503
+ ): boolean
504
+ hasFlat<T extends A_Error>(
505
+ /**
506
+ * Provide an error constructor to check if it's available in the scope
507
+ */
508
+ error: A_TYPES__Error_Constructor<T>
509
+ ): boolean
510
+ hasFlat(
511
+ /**
512
+ * Provide a string to check if a component, entity or fragment with the provided name is available in the scope
513
+ */
514
+ constructor: string
515
+ ): boolean
516
+ hasFlat(
517
+ ctor: unknown
518
+ ): boolean {
519
+
463
520
  let found = false;
464
521
 
465
522
  switch (true) {
@@ -468,7 +525,8 @@ export class A_Scope<
468
525
  return true;
469
526
 
470
527
  // 2) Check by string name.
471
- case typeof ctor === 'string': {
528
+ case A_TypeGuards.isString(ctor): {
529
+
472
530
  // 2.1 Check if it's a component name
473
531
  const possibleComponent = Array.from(this.allowedComponents).find(c => c.name === ctor);
474
532
  if (possibleComponent) found = true;
@@ -485,11 +543,7 @@ export class A_Scope<
485
543
  const possibleError = Array.from(this.allowedErrors).find(e => e.name === ctor);
486
544
  if (possibleError) found = true;
487
545
 
488
- // 2.5 If not found in current scope, check parent scope
489
- if (!!this._parent)
490
- return this._parent.has(ctor);
491
-
492
- return false;
546
+ break;
493
547
  }
494
548
  // 3) Check if it's a Component
495
549
  case A_TypeGuards.isComponentConstructor(ctor): {
@@ -536,15 +590,6 @@ export class A_Scope<
536
590
  }
537
591
  }
538
592
 
539
- // 7) Check parent scope in case not found
540
- if (!found && !!this._parent)
541
- try {
542
- return this._parent.has(ctor as any);
543
- } catch (error) {
544
- return false;
545
- }
546
-
547
-
548
593
  return found;
549
594
  }
550
595
 
@@ -646,6 +691,8 @@ export class A_Scope<
646
691
  * This method should resolve all instances of the components, or entities within the scope, by provided parent class
647
692
  * So in case of providing a base class it should return all instances that extends this base class
648
693
  *
694
+ * [!] Applicable for the current scope ONLY, no parent scopes are checked
695
+ *
649
696
  * @param component
650
697
  */
651
698
  resolveAll<T extends A_Component>(
@@ -675,6 +722,68 @@ export class A_Scope<
675
722
  */
676
723
  param1: A_TYPES__InjectableConstructors
677
724
  ): Array<T> {
725
+
726
+ const results: Array<T> = [];
727
+
728
+ // 1) Resolve all in the current scope
729
+ const currentResults = this.resolveFlatAll<T>(param1 as any);
730
+ results.push(...currentResults);
731
+
732
+ // 2) Resolve all in the parent scope
733
+
734
+ let parentScope = this._parent;
735
+
736
+ while (parentScope && parentScope.has(param1 as any)) {
737
+ const parentResults = parentScope.resolveFlatAll<T>(param1 as any);
738
+ results.push(...parentResults);
739
+
740
+ // Move to the next parent scope
741
+ parentScope = parentScope._parent;
742
+ }
743
+
744
+
745
+ return results;
746
+ }
747
+
748
+
749
+
750
+
751
+ /**
752
+ * This method should resolve all instances of the components, or entities within the scope, by provided parent class
753
+ * So in case of providing a base class it should return all instances that extends this base class
754
+ *
755
+ * [!] Applicable for the current scope ONLY, no parent scopes are checked
756
+ *
757
+ * @param component
758
+ */
759
+ resolveFlatAll<T extends A_Component>(
760
+ /**
761
+ * Provide a component constructor to resolve its instance from the scope
762
+ */
763
+ component: A_TYPES__Component_Constructor<T>
764
+ ): Array<T>
765
+ resolveFlatAll<T extends A_Fragment>(
766
+ /**
767
+ * Provide a fragment constructor to resolve its instance from the scope
768
+ */
769
+ fragment: A_TYPES__Fragment_Constructor<T>
770
+ ): Array<T>
771
+ resolveFlatAll<T extends A_Entity>(
772
+ /**
773
+ * Provide an entity constructor to resolve its instance or an array of instances from the scope
774
+ */
775
+ entity: A_TYPES__Entity_Constructor<T>
776
+ ): Array<T>
777
+ resolveFlatAll<T extends A_TYPES__ScopeResolvableComponents>(
778
+ constructorName: string
779
+ ): Array<T>
780
+ resolveFlatAll<T extends A_TYPES__ScopeResolvableComponents>(
781
+ /**
782
+ * Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
783
+ */
784
+ param1: A_TYPES__InjectableConstructors
785
+ ): Array<T> {
786
+
678
787
  const results: Array<T> = [];
679
788
 
680
789
  switch (true) {
@@ -704,6 +813,7 @@ export class A_Scope<
704
813
  case A_TypeGuards.isEntityConstructor(param1): {
705
814
  // 3) Check entities
706
815
  this.entities.forEach(entity => {
816
+
707
817
  if (A_CommonHelper.isInheritedFrom(entity.constructor, param1)) {
708
818
  results.push(entity as T);
709
819
  }
@@ -738,19 +848,11 @@ export class A_Scope<
738
848
  }
739
849
 
740
850
 
741
- const parentScope = this._parent;
742
-
743
- while (parentScope && parentScope.has(param1 as any)) {
744
- const parentResults = parentScope.resolveAll<T>(param1 as any);
745
- results.push(...parentResults);
746
- break;
747
- }
748
-
749
-
750
851
  return results;
751
852
  }
752
853
 
753
854
 
855
+
754
856
  /**
755
857
  * This method allows to resolve/inject a component, fragment or entity from the scope
756
858
  * Depending on the provided parameters it can resolve:
@@ -843,29 +945,114 @@ export class A_Scope<
843
945
  param1: A_TYPES__InjectableConstructors | Array<A_TYPES__InjectableConstructors>,
844
946
  param2?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
845
947
  ): T | Array<T> | undefined {
846
- switch (true) {
847
- case A_TypeGuards.isArray(param1): {
848
- return param1.map(c => {
849
- if (A_TypeGuards.isString(c))
850
- return this.resolveByName(c);
851
- else
852
- return this.resolveOnce(c, param2);
853
- }).filter(Boolean) as Array<T>;
854
- }
855
948
 
856
- case A_TypeGuards.isFunction(param1): {
857
- return this.resolveOnce(param1, param2) as T;
858
- }
859
949
 
860
- case A_TypeGuards.isString(param1): {
861
- return this.resolveByName(param1) as T;
862
- }
950
+ if (A_TypeGuards.isArray(param1)) {
951
+ return param1.map(c => this.resolveOnce(c, param2)) as Array<T>;
952
+ } else {
953
+ return this.resolveOnce(param1, param2) as T;
954
+ }
955
+ }
863
956
 
864
- default: {
865
- throw new A_ScopeError(
866
- A_ScopeError.ResolutionError,
867
- `Invalid parameter provided to resolve method: ${param1} in scope ${this.name}`);
868
- }
957
+
958
+ /**
959
+ * This polymorphic method allows to resolve/inject a component, fragment or entity from the scope
960
+ * Depending on the provided parameters it can resolve:
961
+ * - A single component/fragment/entity by its constructor or name
962
+ * - An array of components/fragments/entities by providing an array of constructors
963
+ * - An entity or an array of entities by providing the entity constructor and query instructions
964
+ *
965
+ * [!] Applicable for the current scope ONLY, no parent scopes are checked
966
+ *
967
+ * @param component
968
+ */
969
+ resolveFlat<T extends A_Component>(
970
+ /**
971
+ * Provide a component constructor to resolve its instance from the scope
972
+ */
973
+ component: A_TYPES__Component_Constructor<T>
974
+ ): T | undefined
975
+ resolveFlat<T extends A_TYPES__Component_Constructor[]>(
976
+ /**
977
+ * Provide an array of component constructors to resolve their instances from the scope
978
+ */
979
+ components: [...T]
980
+ ): Array<InstanceType<T[number]>> | undefined
981
+ resolveFlat<T extends A_Fragment>(
982
+ /**
983
+ * Provide a fragment constructor to resolve its instance from the scope
984
+ */
985
+ fragment: A_TYPES__Fragment_Constructor<T>
986
+ ): T | undefined
987
+ resolveFlat<T extends A_TYPES__Fragment_Constructor[]>(
988
+ /**
989
+ * Provide an array of fragment constructors to resolve their instances from the scope
990
+ */
991
+ fragments: [...T]
992
+ ): Array<InstanceType<T[number]>> | undefined
993
+ resolveFlat<T extends A_Entity>(
994
+ /**
995
+ * Provide an entity constructor to resolve its instance or an array of instances from the scope
996
+ */
997
+ entity: A_TYPES__Entity_Constructor<T>
998
+ ): T | undefined
999
+
1000
+ resolveFlat<T extends A_Entity>(
1001
+ /**
1002
+ * Provide an entity constructor to resolve its instance or an array of instances from the scope
1003
+ */
1004
+ entity: A_TYPES__Entity_Constructor<T>,
1005
+ /**
1006
+ * Provide optional instructions to find a specific entity or a set of entities
1007
+ */
1008
+ instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<T>>
1009
+ ): Array<T>
1010
+ resolveFlat<T extends A_Scope>(
1011
+ /**
1012
+ * Uses only in case of resolving a single entity
1013
+ *
1014
+ * Provide an entity constructor to resolve its instance from the scope
1015
+ */
1016
+ scope: A_TYPES__Scope_Constructor<T>
1017
+ ): T | undefined
1018
+ resolveFlat<T extends A_Error>(
1019
+ /**
1020
+ * Uses only in case of resolving a single entity
1021
+ *
1022
+ * Provide an entity constructor to resolve its instance from the scope
1023
+ */
1024
+ scope: A_TYPES__Error_Constructor<T>
1025
+ ): T | undefined
1026
+ resolveFlat<T extends A_TYPES__ScopeResolvableComponents>(
1027
+ constructorName: string
1028
+ ): T | undefined
1029
+ // base definition
1030
+ resolveFlat<T extends A_TYPES__ScopeResolvableComponents>(
1031
+ /**
1032
+ * Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
1033
+ */
1034
+ param1: A_TYPES__InjectableConstructors,
1035
+
1036
+ ): T | Array<T> | undefined
1037
+ resolveFlat<T extends A_TYPES__ScopeLinkedConstructors>(
1038
+ /**
1039
+ * Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
1040
+ */
1041
+ param1: InstanceType<T>,
1042
+
1043
+ ): T | Array<T> | undefined
1044
+ resolveFlat<T extends A_TYPES__ScopeResolvableComponents>(
1045
+ /**
1046
+ * Provide a component, fragment or entity constructor or an array of constructors to resolve its instance(s) from the scope
1047
+ */
1048
+ param1: A_TYPES__InjectableConstructors | Array<A_TYPES__InjectableConstructors>,
1049
+ param2?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
1050
+ ): T | Array<T | undefined> | undefined {
1051
+
1052
+ if (A_TypeGuards.isArray(param1)) {
1053
+ return param1.map(c => this.resolveFlatOnce(c, param2)) as Array<T>;
1054
+ } else {
1055
+ return this.resolveFlatOnce(param1, param2) as T;
869
1056
  }
870
1057
  }
871
1058
 
@@ -883,6 +1070,7 @@ export class A_Scope<
883
1070
  * This method is used internally to resolve a component, fragment or entity by its constructor name
884
1071
  *
885
1072
  * [!] Note that this method checks for the component, fragment or entity in the current scope and all parent scopes
1073
+ * [!!] Note: No parent scopes are checked
886
1074
  *
887
1075
  * @param name - name of the component, fragment or entity to resolve (constructor name for components and fragments, static entity property for entities, static code property for commands)
888
1076
  * @returns
@@ -925,26 +1113,21 @@ export class A_Scope<
925
1113
  );
926
1114
  if (error) return this.resolveOnce(error) as InstanceType<_ErrorType[number]>;
927
1115
 
928
- // If not found in current scope, check parent scope
929
- if (!!this._parent) {
930
- return this._parent.resolveByName(name) as any;
931
- }
932
-
933
1116
  return undefined;
934
1117
  }
935
1118
 
936
1119
  /**
937
- * This method is used internally to resolve a single component, fragment or entity from the scope
1120
+ * Resolves a component, fragment or entity from the scope without checking parent scopes
938
1121
  *
939
1122
  * @param component
940
1123
  * @param instructions
941
- * @returns
942
1124
  */
943
- private resolveOnce(
1125
+ private resolveFlatOnce(
944
1126
  component: any,
945
1127
  instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
946
1128
  ): A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | Array<A_TYPES__ScopeResolvableComponents> | undefined {
947
1129
 
1130
+ let value: A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | Array<A_TYPES__ScopeResolvableComponents> | undefined = undefined;
948
1131
 
949
1132
  const componentName = A_CommonHelper.getComponentName(component);
950
1133
 
@@ -952,23 +1135,33 @@ export class A_Scope<
952
1135
  return undefined;
953
1136
 
954
1137
  switch (true) {
1138
+ case A_TypeGuards.isString(component): {
1139
+ value = this.resolveByName(component) as A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | undefined;
1140
+ break;
1141
+ }
955
1142
  case A_TypeGuards.isConstructorAllowedForScopeAllocation(component): {
956
- return this.resolveIssuer(component);
1143
+ value = this.resolveIssuer(component);
1144
+ break;
957
1145
  }
958
1146
  case A_TypeGuards.isEntityConstructor(component): {
959
- return this.resolveEntity(component, instructions);
1147
+ value = this.resolveEntity(component, instructions);
1148
+ break;
960
1149
  }
961
1150
  case A_TypeGuards.isFragmentConstructor(component): {
962
- return this.resolveFragment(component);
1151
+ value = this.resolveFragment(component);
1152
+ break;
963
1153
  }
964
1154
  case A_TypeGuards.isScopeConstructor(component): {
965
- return this.resolveScope(component);
1155
+ value = this.resolveScope(component);
1156
+ break;
966
1157
  }
967
1158
  case A_TypeGuards.isComponentConstructor(component): {
968
- return this.resolveComponent(component);
1159
+ value = this.resolveComponent(component);
1160
+ break;
969
1161
  }
970
1162
  case A_TypeGuards.isErrorConstructor(component): {
971
- return this.resolveError(component);
1163
+ value = this.resolveError(component);
1164
+ break;
972
1165
  }
973
1166
  default:
974
1167
  throw new A_ScopeError(
@@ -976,8 +1169,44 @@ export class A_Scope<
976
1169
  `Injected Component ${componentName} not found in the scope`
977
1170
  );
978
1171
  }
1172
+
1173
+ return value;
979
1174
  }
980
1175
 
1176
+ /**
1177
+ * This method is used internally to resolve a single component, fragment or entity from the scope
1178
+ *
1179
+ * @param component
1180
+ * @param instructions
1181
+ * @returns
1182
+ */
1183
+ private resolveOnce(
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
+ const values = this.resolveFlatOnce(component, instructions);
1189
+
1190
+ // The idea here that in case when Scope has no exact component we have to resolve it from the _parent
1191
+ // That means that we should ensure that there's no components that are children of the required component
1192
+ if (!values && !!this.parent) {
1193
+ return this.parent.resolveOnce(component, instructions);
1194
+ }
1195
+
1196
+ return values;
1197
+ }
1198
+
1199
+
1200
+ /**
1201
+ * Resolves the issuer of the scope by provided constructor
1202
+ *
1203
+ * [!] Note that this method checks ONLY for the direct issuer of the scope
1204
+ * [!!] No parent scopes are checked
1205
+ *
1206
+ *
1207
+ * @param ctor
1208
+ * @returns
1209
+ */
981
1210
  private resolveIssuer(
982
1211
  ctor: A_TYPES__ScopeLinkedConstructors
983
1212
  ): A_TYPES__ScopeLinkedComponents | undefined {
@@ -991,9 +1220,7 @@ export class A_Scope<
991
1220
  )) {
992
1221
  return issuer!;
993
1222
  }
994
- if (!!this._parent) {
995
- return this._parent.resolveIssuer(ctor);
996
- }
1223
+
997
1224
 
998
1225
  return undefined;
999
1226
  }
@@ -1002,6 +1229,7 @@ export class A_Scope<
1002
1229
  * This method is used internally to resolve a single entity from the scope based on the provided instructions
1003
1230
  *
1004
1231
  * [!] Note that this method can return either a single entity or an array of entities depending on the instructions provided
1232
+ * [!!] Note: No parent scopes are checked
1005
1233
  *
1006
1234
  * @param entity
1007
1235
  * @param instructions
@@ -1023,18 +1251,7 @@ export class A_Scope<
1023
1251
  * [!!] In case when no entity found in the current scope, it tries to resolve it from the parent scope (if exists)
1024
1252
  */
1025
1253
  case !instructions: {
1026
- const found = this.entities.find(e => e instanceof entity);
1027
-
1028
- switch (true) {
1029
- case !!found:
1030
- return found as T;
1031
-
1032
- case !found && !!this._parent:
1033
- return this._parent.resolveEntity(entity, instructions);
1034
-
1035
- default:
1036
- return undefined;
1037
- }
1254
+ return this.entities.find(e => e instanceof entity) as T | undefined;
1038
1255
  }
1039
1256
  /**
1040
1257
  * 2) In case when aseid is provided in the query, we can directly get the entity from the map
@@ -1091,8 +1308,8 @@ export class A_Scope<
1091
1308
  });
1092
1309
  });
1093
1310
 
1094
- if (found.length === 0 && !!this._parent)
1095
- return this._parent.resolveEntity(entity, instructions);
1311
+ if (found.length === 0)
1312
+ return undefined;
1096
1313
 
1097
1314
  if (count === 1)
1098
1315
  return found[0] as T;
@@ -1104,27 +1321,21 @@ export class A_Scope<
1104
1321
  /**
1105
1322
  * This method is used internally to resolve a single error from the scope
1106
1323
  *
1324
+ * [!] Note that errors are singleton instances within the scope
1325
+ * [!!] No parent scopes are checked
1326
+ *
1107
1327
  * @param error
1108
1328
  * @returns
1109
1329
  */
1110
1330
  private resolveError<T extends A_Error>(error: A_TYPES__Error_Constructor<T>): T | undefined {
1111
1331
 
1112
- const found = this.errors.find(e => e instanceof error);
1113
-
1114
- switch (true) {
1115
- case !!found:
1116
- return found as T;
1117
-
1118
- case !found && !!this._parent:
1119
- return this._parent.resolveError(error);
1120
-
1121
- default:
1122
- return undefined;
1123
- }
1332
+ return this.errors.find(e => e instanceof error) as T | undefined;
1124
1333
  }
1125
1334
  /**
1126
1335
  * This method is used internally to resolve a single fragment from the scope
1127
1336
  *
1337
+ * [!] Note that this method checks for the fragment in the current scope and all parent scopes
1338
+ *
1128
1339
  * @param fragment
1129
1340
  * @returns
1130
1341
  */
@@ -1142,9 +1353,6 @@ export class A_Scope<
1142
1353
  return this.resolveFragment(found);
1143
1354
  }
1144
1355
 
1145
- case !fragmentInstancePresented && !!this._parent:
1146
- return this._parent.resolveFragment(fragment);
1147
-
1148
1356
  default:
1149
1357
  return undefined;
1150
1358
  }
@@ -1158,17 +1366,18 @@ export class A_Scope<
1158
1366
  private resolveScope(scope: A_TYPES__Scope_Constructor): A_Scope {
1159
1367
  return this;
1160
1368
  }
1369
+
1161
1370
  /**
1162
1371
  * This method is used internally to resolve a single component from the scope
1163
1372
  *
1373
+ * [!!] Note: No parent scopes are checked
1374
+ *
1164
1375
  * @param component
1165
1376
  * @returns
1166
1377
  */
1167
1378
  private resolveComponent<T extends A_Component>(component: A_TYPES__Component_Constructor<T>): InstanceType<_ComponentType[number]> | undefined {
1168
1379
 
1169
- // The idea here that in case when Scope has no exact component we have to resolve it from the _parent
1170
- // BUT: if it's not presented in _parent we have to check for inheritance
1171
- // That means that we should ensure that there's no components that are children of the required component
1380
+
1172
1381
  switch (true) {
1173
1382
  // 1) In case when the component is available and exists in the scope
1174
1383
  case this.allowedComponents.has(component) && this._components.has(component): {
@@ -1233,16 +1442,8 @@ export class A_Scope<
1233
1442
  return this.resolveComponent(found);
1234
1443
  }
1235
1444
 
1236
- // 4) In case when the component is not available in the scope but the _parent is available
1237
- case !!this._parent: {
1238
- return this._parent.resolveComponent(component) as InstanceType<_ComponentType[number]>;
1239
- }
1240
-
1241
1445
  default:
1242
- throw new A_ScopeError(
1243
- A_ScopeError.ResolutionError,
1244
- `Component ${component.name} not found in the scope ${this.name}`
1245
- );
1446
+ return undefined;
1246
1447
  }
1247
1448
  }
1248
1449