@adaas/a-concept 0.1.31 → 0.1.33

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/jest.config.ts CHANGED
@@ -3,6 +3,7 @@ import type { Config } from '@jest/types';
3
3
  // Sync object
4
4
  const config: Config.InitialOptions = {
5
5
  verbose: true,
6
+ setupFilesAfterEnv: ['<rootDir>/tests/jest.setup.ts'],
6
7
  roots: ['<rootDir>/tests'],
7
8
  transform: {
8
9
  '^.+\\.tsx?$': 'ts-jest'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaas/a-concept",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
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",
@@ -206,7 +206,7 @@ export class A_Context {
206
206
  component: A_TYPES_ScopeDependentComponents,
207
207
  ): void {
208
208
  // uses only for error messages
209
- const componentName = A_CommonHelper.getComponentName(component);
209
+ const componentName = A_CommonHelper.getComponentName(component);
210
210
 
211
211
  const instance = this.getInstance();
212
212
 
@@ -985,7 +985,8 @@ export class A_Context {
985
985
  static isAllowedToBeRegistered(param: any): param is A_TYPES_ScopeDependentComponents {
986
986
  return A_TypeGuards.isEntityInstance(param)
987
987
  || A_TypeGuards.isComponentInstance(param)
988
- || A_TypeGuards.isFragmentInstance(param);
988
+ || A_TypeGuards.isFragmentInstance(param)
989
+ || A_TypeGuards.isErrorInstance(param);
989
990
  }
990
991
 
991
992
  /**
@@ -232,7 +232,7 @@ export type A_TYPES__FeatureExtendDecoratorDescriptor =
232
232
  *
233
233
  * [!] Can be applied only on A-Components
234
234
  */
235
- export type A_TYPES__FeatureExtendDecoratorTarget = A_Component
235
+ export type A_TYPES__FeatureExtendDecoratorTarget = A_Component | A_Container | A_Entity
236
236
 
237
237
  /**
238
238
  * Configuration type for A_Extend decorator
@@ -23,6 +23,8 @@ import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
23
23
  import { A_TYPES__Scope_Constructor } from "@adaas/a-concept/global/A-Scope/A-Scope.types";
24
24
  import { A_Feature } from "@adaas/a-concept/global/A-Feature/A-Feature.class";
25
25
  import { A_CommonHelper } from "@adaas/a-concept/helpers/A_Common.helper";
26
+ import { A_TYPES__Error_Constructor } from "../A-Error/A_Error.types";
27
+ import { A_Error } from "../A-Error/A_Error.class";
26
28
 
27
29
 
28
30
  /**
@@ -44,6 +46,14 @@ export function A_Inject<T extends A_Scope>(
44
46
  */
45
47
  scope: A_TYPES__Scope_Constructor<T>
46
48
  ): A_TYPES__A_InjectDecoratorReturn
49
+ export function A_Inject<T extends A_Error>(
50
+ /***
51
+ * Provide the Error constructor that will be associated with the injection.
52
+ *
53
+ * [!] It returns an Instance of the Error what is executed.
54
+ */
55
+ error: A_TYPES__Error_Constructor<T>
56
+ ): A_TYPES__A_InjectDecoratorReturn
47
57
  export function A_Inject<T extends A_Feature>(
48
58
  /**
49
59
  * Provide the Feature constructor that will be associated with the injection.
@@ -5,6 +5,7 @@ import { A_TYPES__Entity_Constructor } from "@adaas/a-concept/global/A-Entity/A-
5
5
  import { A_TYPES__Feature_Constructor } from "@adaas/a-concept/global/A-Feature/A-Feature.types";
6
6
  import { A_TYPES__Fragment_Constructor } from "@adaas/a-concept/global/A-Fragment/A-Fragment.types";
7
7
  import { A_TYPES__Caller_Constructor } from "@adaas/a-concept/global/A-Caller/A_Caller.types";
8
+ import { A_TYPES__Error_Constructor } from "../A-Error/A_Error.types";
8
9
 
9
10
 
10
11
  // ============================================================================
@@ -54,6 +55,7 @@ export type A_TYPES__InjectableConstructors = A_TYPES__Component_Constructor
54
55
  | A_TYPES__Feature_Constructor
55
56
  | A_TYPES__Caller_Constructor
56
57
  | A_TYPES__Fragment_Constructor
58
+ | A_TYPES__Error_Constructor
57
59
  | string;
58
60
 
59
61
 
@@ -138,6 +138,12 @@ export class A_Scope<
138
138
  * [!] One component instance per scope
139
139
  */
140
140
  get components(): Array<InstanceType<_ComponentType[number]>> { return Array.from(this._components.values()) }
141
+ /**
142
+ * Returns an Array of errors registered in the scope
143
+ *
144
+ * [!] One error per code
145
+ */
146
+ get errors(): Array<InstanceType<_ErrorType[number]>> { return Array.from(this._errors.values()) }
141
147
 
142
148
  /**
143
149
  * Returns the parent scope of the current scope
@@ -381,6 +387,12 @@ export class A_Scope<
381
387
  */
382
388
  fragment: A_TYPES__Fragment_Constructor<T>
383
389
  ): boolean
390
+ has<T extends A_Error>(
391
+ /**
392
+ * Provide an error constructor to check if it's available in the scope
393
+ */
394
+ error: A_TYPES__Error_Constructor<T>
395
+ ): boolean
384
396
  has(
385
397
  /**
386
398
  * Provide a string to check if a component, entity or fragment with the provided name is available in the scope
@@ -412,7 +424,11 @@ export class A_Scope<
412
424
  const possibleEntity = Array.from(this.allowedEntities).find(e => e.name === ctor);
413
425
  if (possibleEntity) found = true;
414
426
 
415
- // 2.4 If not found in current scope, check parent scope
427
+ // 2.4 Check if it's an error name
428
+ const possibleError = Array.from(this.allowedErrors).find(e => e.name === ctor);
429
+ if (possibleError) found = true;
430
+
431
+ // 2.5 If not found in current scope, check parent scope
416
432
  if (!!this._parent)
417
433
  return this._parent.has(ctor);
418
434
 
@@ -442,7 +458,17 @@ export class A_Scope<
442
458
 
443
459
  break;
444
460
  }
445
- // 6) Check scope issuer
461
+
462
+ // 6) Check if it's an Error
463
+ case A_TypeGuards.isErrorConstructor(ctor): {
464
+ found = this.isAllowedError(ctor)
465
+ || !![...this.allowedErrors]
466
+ .find(e => A_CommonHelper.isInheritedFrom(e, ctor));
467
+
468
+ break;
469
+ }
470
+
471
+ // 7) Check scope issuer
446
472
  case this.issuer()
447
473
  && (this.issuer()!.constructor === ctor
448
474
  || A_CommonHelper.isInheritedFrom(this.issuer()!.constructor, ctor
@@ -598,14 +624,7 @@ export class A_Scope<
598
624
  */
599
625
  entity: A_TYPES__Entity_Constructor<T>
600
626
  ): T | undefined
601
- resolve<T extends A_Scope>(
602
- /**
603
- * Uses only in case of resolving a single entity
604
- *
605
- * Provide an entity constructor to resolve its instance from the scope
606
- */
607
- scope: new (...args: any[]) => T
608
- ): T | undefined
627
+
609
628
  resolve<T extends A_Entity>(
610
629
  /**
611
630
  * Provide an entity constructor to resolve its instance or an array of instances from the scope
@@ -616,6 +635,22 @@ export class A_Scope<
616
635
  */
617
636
  instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<T>>
618
637
  ): Array<T>
638
+ resolve<T extends A_Scope>(
639
+ /**
640
+ * Uses only in case of resolving a single entity
641
+ *
642
+ * Provide an entity constructor to resolve its instance from the scope
643
+ */
644
+ scope: A_TYPES__Scope_Constructor<T>
645
+ ): T | undefined
646
+ resolve<T extends A_Error>(
647
+ /**
648
+ * Uses only in case of resolving a single entity
649
+ *
650
+ * Provide an entity constructor to resolve its instance from the scope
651
+ */
652
+ scope: A_TYPES__Error_Constructor<T>
653
+ ): T | undefined
619
654
  resolve<T extends A_TYPES__ScopeResolvableComponents>(
620
655
  constructorName: string
621
656
  ): T | undefined
@@ -688,7 +723,8 @@ export class A_Scope<
688
723
  * Provide the name of the component, fragment or entity to resolve
689
724
  */
690
725
  name: string
691
- ): _EntityType[number] | InstanceType<_ComponentType[number]> | _FragmentType[number] | undefined {
726
+ ): _EntityType[number] | InstanceType<_ComponentType[number]> | _FragmentType[number] |
727
+ InstanceType<_ErrorType[number]> | undefined {
692
728
  // 1) Check components
693
729
  const component = Array.from(this.allowedComponents).find(
694
730
  c => c.name === name
@@ -711,6 +747,15 @@ export class A_Scope<
711
747
  );
712
748
  if (fragment) return this.resolveOnce(fragment) as _FragmentType[number];
713
749
 
750
+ // 4) Check errors
751
+ const error = Array.from(this.allowedErrors).find(
752
+ e => e.name === name
753
+ || e.name === A_FormatterHelper.toPascalCase(name)
754
+ || (e as any).code === name
755
+ || (e as any).code === A_FormatterHelper.toKebabCase(name)
756
+ );
757
+ if (error) return this.resolveOnce(error) as InstanceType<_ErrorType[number]>;
758
+
714
759
  // If not found in current scope, check parent scope
715
760
  if (!!this._parent) {
716
761
  return this._parent.resolveByName(name) as any;
@@ -731,6 +776,7 @@ export class A_Scope<
731
776
  instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
732
777
  ): A_TYPES__ScopeResolvableComponents | A_Scope | A_TYPES__ScopeLinkedComponents | Array<A_TYPES__ScopeResolvableComponents> | undefined {
733
778
 
779
+
734
780
  const componentName = A_CommonHelper.getComponentName(component);
735
781
 
736
782
  if (!component || !this.has(component))
@@ -752,6 +798,9 @@ export class A_Scope<
752
798
  case A_TypeGuards.isComponentConstructor(component): {
753
799
  return this.resolveComponent(component);
754
800
  }
801
+ case A_TypeGuards.isErrorConstructor(component): {
802
+ return this.resolveError(component);
803
+ }
755
804
  default:
756
805
  throw new A_ScopeError(
757
806
  A_ScopeError.ResolutionError,
@@ -883,7 +932,27 @@ export class A_Scope<
883
932
  }
884
933
  }
885
934
  }
935
+ /**
936
+ * This method is used internally to resolve a single error from the scope
937
+ *
938
+ * @param error
939
+ * @returns
940
+ */
941
+ private resolveError<T extends A_Error>(error: A_TYPES__Error_Constructor<T>): T | undefined {
942
+
943
+ const found = this.errors.find(e => e instanceof error);
886
944
 
945
+ switch (true) {
946
+ case !!found:
947
+ return found as T;
948
+
949
+ case !found && !!this._parent:
950
+ return this._parent.resolveError(error);
951
+
952
+ default:
953
+ return undefined;
954
+ }
955
+ }
887
956
  /**
888
957
  * This method is used internally to resolve a single fragment from the scope
889
958
  *
@@ -1079,7 +1148,7 @@ export class A_Scope<
1079
1148
  break;
1080
1149
  }
1081
1150
  // 3) In case when it's a A-Entity instance
1082
- case param1 instanceof A_Entity && !this._entities.has(param1.aseid.toString()): {
1151
+ case A_TypeGuards.isEntityInstance(param1) && !this._entities.has(param1.aseid.toString()): {
1083
1152
 
1084
1153
  if (!this.allowedEntities.has(param1.constructor as _EntityType[number]))
1085
1154
  this.allowedEntities.add(param1.constructor as _EntityType[number]);
@@ -1089,7 +1158,7 @@ export class A_Scope<
1089
1158
  break;
1090
1159
  }
1091
1160
  // 4) In case when it's a A-Fragment instance
1092
- case param1 instanceof A_Fragment: {
1161
+ case A_TypeGuards.isFragmentInstance(param1): {
1093
1162
 
1094
1163
  if (!this.allowedFragments.has(param1.constructor as A_TYPES__Fragment_Constructor<_FragmentType[number]>))
1095
1164
  this.allowedFragments.add(param1.constructor as A_TYPES__Fragment_Constructor<_FragmentType[number]>);
@@ -1104,11 +1173,16 @@ export class A_Scope<
1104
1173
  break;
1105
1174
  }
1106
1175
  // 5) In case when it's a A-Error instance
1107
- case param1 instanceof A_Error: {
1176
+ case A_TypeGuards.isErrorInstance(param1): {
1108
1177
  if (!this.allowedErrors.has(param1.constructor as _ErrorType[number]))
1109
1178
  this.allowedErrors.add(param1.constructor as _ErrorType[number]);
1110
1179
 
1111
- // A_Context.register(this, param1);
1180
+ this._errors.set(
1181
+ param1.code,
1182
+ param1 as InstanceType<_ErrorType[number]>
1183
+ );
1184
+
1185
+ A_Context.register(this, param1);
1112
1186
  break;
1113
1187
  }
1114
1188
 
@@ -1167,7 +1241,135 @@ export class A_Scope<
1167
1241
  }
1168
1242
 
1169
1243
 
1244
+ /**
1245
+ * This method is used to deregister the component from the scope
1246
+ *
1247
+ * @param fragment
1248
+ */
1249
+ deregister<T extends A_Component>(
1250
+ /**
1251
+ * Provide a component constructor to deregister it in the scope
1252
+ */
1253
+ component: A_TYPES__Component_Constructor<T>
1254
+ ): void
1255
+ deregister(
1256
+ /**
1257
+ * Provide a command instance to deregister it in the scope
1258
+ */
1259
+ component: A_Component
1260
+ ): void
1261
+ deregister<T extends A_Error>(
1262
+ /**
1263
+ * Provide an error constructor to deregister it in the scope
1264
+ */
1265
+ error: A_TYPES__Error_Constructor<T>
1266
+ ): void
1267
+ deregister(
1268
+ /**
1269
+ * Provide an error instance to deregister it in the scope
1270
+ */
1271
+ error: A_Error
1272
+ ): void
1273
+ deregister<T extends A_Fragment>(
1274
+ /**
1275
+ * Provide a command instance to deregister it in the scope
1276
+ */
1277
+ fragment: A_TYPES__Fragment_Constructor<T>
1278
+ ): void
1279
+ deregister(
1280
+ /**
1281
+ * Provide a fragment instance to deregister it in the scope
1282
+ */
1283
+ fragment: A_Fragment
1284
+ ): void
1285
+ deregister<T extends A_Entity>(
1286
+ /**
1287
+ * Provide an entity constructor to deregister it in the scope
1288
+ */
1289
+ entity: A_TYPES__Entity_Constructor<T>
1290
+ ): void
1291
+ deregister(
1292
+ /**
1293
+ * Provide an entity instance to deregister it in the scope
1294
+ */
1295
+ entity: A_Entity
1296
+ ): void
1297
+
1298
+ deregister(
1299
+ param1: unknown
1300
+ ): void {
1301
+ switch (true) {
1302
+ // ------------------------------------------
1303
+ // ------------ Instances ----------------
1304
+ // ------------------------------------------
1305
+ // 1) In case when it's a A-Component instance
1306
+ case param1 instanceof A_Component: {
1307
+
1308
+ this._components.delete(param1.constructor as _ComponentType[number]);
1309
+ A_Context.deregister(param1);
1310
+
1311
+ break;
1312
+ }
1313
+ // 3) In case when it's a A-Entity instance
1314
+ case A_TypeGuards.isEntityInstance(param1): {
1315
+
1316
+ this._entities.delete(param1.aseid.toString());
1317
+ A_Context.deregister(param1);
1318
+ break;
1319
+ }
1320
+ // 4) In case when it's a A-Fragment instance
1321
+ case A_TypeGuards.isFragmentInstance(param1): {
1322
+
1323
+ this._fragments.delete(param1.constructor as A_TYPES__Fragment_Constructor<_FragmentType[number]>);
1324
+ A_Context.deregister(param1);
1170
1325
 
1326
+ break;
1327
+ }
1328
+ // 5) In case when it's a A-Error instance
1329
+ case A_TypeGuards.isErrorInstance(param1): {
1330
+
1331
+ this._errors.delete(param1.code);
1332
+ A_Context.deregister(param1);
1333
+ break;
1334
+ }
1335
+
1336
+ // ------------------------------------------
1337
+ // ------------ Constructors ----------------
1338
+ // ------------------------------------------
1339
+ // 6) In case when it's a A-Component constructor
1340
+ case A_TypeGuards.isComponentConstructor(param1): {
1341
+ this.allowedComponents.delete(param1 as _ComponentType[number]);
1342
+ break;
1343
+ }
1344
+ // 8) In case when it's a A-Fragment constructor
1345
+ case A_TypeGuards.isFragmentConstructor(param1): {
1346
+ this.allowedFragments.delete(param1 as A_TYPES__Fragment_Constructor<_FragmentType[number]>);
1347
+ break;
1348
+ }
1349
+ // 9) In case when it's a A-Entity constructor
1350
+ case A_TypeGuards.isEntityConstructor(param1): {
1351
+ this.allowedEntities.delete(param1 as _EntityType[number]);
1352
+ break;
1353
+ }
1354
+ // 10) In case when it's a A-Error constructor
1355
+ case A_TypeGuards.isErrorConstructor(param1): {
1356
+ this.allowedErrors.delete(param1 as _ErrorType[number]);
1357
+ break;
1358
+ }
1359
+
1360
+ // ------------------------------------------
1361
+ // ------------ Invalid Cases ----------------
1362
+ // ------------------------------------------
1363
+
1364
+ default:
1365
+ const componentName = A_CommonHelper.getComponentName(param1);
1366
+
1367
+ throw new A_ScopeError(
1368
+ A_ScopeError.DeregistrationError,
1369
+ `Cannot deregister ${componentName} from the scope ${this.name}`
1370
+ );
1371
+ }
1372
+ }
1171
1373
 
1172
1374
  /**
1173
1375
  * This method is useful when you want to serialize the scope to JSON
@@ -13,4 +13,5 @@ export class A_ScopeError extends A_Error {
13
13
 
14
14
  static readonly CircularInheritanceError = 'A-Scope Circular Inheritance Error';
15
15
 
16
+ static readonly DeregistrationError = 'A-Scope Deregistration Error';
16
17
  }
@@ -81,11 +81,11 @@ export type A_TYPES__ScopeLinkedComponents = A_Container | A_Feature;
81
81
  /**
82
82
  * A list of components that can be resolved by a scope
83
83
  */
84
- export type A_TYPES__ScopeResolvableComponents = A_Component | A_Fragment | A_Entity
84
+ export type A_TYPES__ScopeResolvableComponents = A_Component | A_Fragment | A_Entity | A_Error | A_Scope;
85
85
  /**
86
86
  * A list of components that are dependent on a scope and do not have their own scope
87
87
  */
88
- export type A_TYPES_ScopeDependentComponents = A_Component | A_Entity | A_Fragment
88
+ export type A_TYPES_ScopeDependentComponents = A_Component | A_Entity | A_Fragment | A_Error;
89
89
  /**
90
90
  * A list of components that are independent of a scope. They don't need a scope to be resolved
91
91
  * Those components haven't scope dependent features.
@@ -307,7 +307,9 @@ export class A_TypeGuards {
307
307
  }
308
308
 
309
309
  static isAllowedForFeatureExtension(param: any): param is A_TYPES__FeatureExtendDecoratorTarget {
310
- return A_TypeGuards.isComponentInstance(param);
310
+ return A_TypeGuards.isComponentInstance(param)
311
+ || A_TypeGuards.isContainerInstance(param)
312
+ || A_TypeGuards.isEntityInstance(param);
311
313
  }
312
314
 
313
315
  static isAllowedForAbstractionDefinition(param: any): param is A_TYPES__AbstractionAvailableComponents {