@adaas/a-concept 0.1.42 → 0.1.44

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.42",
3
+ "version": "0.1.44",
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",
@@ -157,11 +157,15 @@ export class A_Error<
157
157
  super(param1.message);
158
158
  break;
159
159
 
160
- case A_TypeGuards.isConstructorType<_ConstructorType>(param1) && 'description' in param1:
160
+ case A_TypeGuards.isErrorSerializedType<_SerializedType>(param1):
161
+ super(param1.message);
162
+ break;
163
+
164
+ case A_TypeGuards.isErrorConstructorType<_ConstructorType>(param1) && 'description' in param1:
161
165
  super(`[${param1.title}]: ${param1.description}`);
162
166
  break;
163
167
 
164
- case A_TypeGuards.isConstructorType<_ConstructorType>(param1) && !('description' in param1):
168
+ case A_TypeGuards.isErrorConstructorType<_ConstructorType>(param1) && !('description' in param1):
165
169
  super(param1.title);
166
170
  break;
167
171
 
@@ -305,6 +309,7 @@ export class A_Error<
305
309
  param2?: string
306
310
  ): (param1: any, param2: any) => void | (() => void) {
307
311
  switch (true) {
312
+
308
313
  case A_TypeGuards.isString(param1) && !param2:
309
314
  return this.fromMessage;
310
315
 
@@ -314,13 +319,13 @@ export class A_Error<
314
319
  case param1 instanceof Error:
315
320
  return this.fromError;
316
321
 
322
+ case A_TypeGuards.isErrorSerializedType<_SerializedType>(param1):
323
+ return this.fromJSON;
317
324
 
318
- case A_TypeGuards.isConstructorType<_ConstructorType>(param1):
325
+ case A_TypeGuards.isErrorConstructorType<_ConstructorType>(param1):
319
326
  return this.fromConstructor;
320
327
 
321
328
  default: {
322
- console.log('INVALID PARAMS PROVIDED TO A_ERROR CONSTRUCTOR: ', param1);
323
-
324
329
  throw new A_Error(
325
330
  A_CONSTANTS__ERROR_CODES.VALIDATION_ERROR,
326
331
  'Invalid parameters provided to A_Error constructor'
@@ -365,6 +370,23 @@ export class A_Error<
365
370
  this._link = undefined;
366
371
  this._originalError = undefined;
367
372
  }
373
+ /**
374
+ * Initializes the A_Error instance from a serialized object.
375
+ *
376
+ * @param serialized
377
+ */
378
+ protected fromJSON(serialized: _SerializedType): void {
379
+ this._aseid = new ASEID(serialized.aseid);
380
+ super.message = serialized.message;
381
+ this._title = serialized.title;
382
+ this._code = serialized.code;
383
+ this._scope = serialized.scope;
384
+ this._description = serialized.description;
385
+ // Note: originalError is deserialized as message only
386
+ this._originalError = serialized.originalError ? new A_Error(serialized.originalError) : undefined;
387
+ this._link = serialized.link;
388
+ }
389
+
368
390
 
369
391
 
370
392
  fromTitle(title: string, description: string): void {
@@ -404,7 +426,7 @@ export class A_Error<
404
426
 
405
427
  this._description = params.description;
406
428
  this._link = params.link;
407
-
429
+
408
430
  // Handle originalError: if it's an A_Error, we should trace back to the root cause
409
431
  // to avoid infinite nesting of A_Error instances
410
432
  if (params.originalError instanceof A_Error) {
@@ -149,8 +149,14 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
149
149
  */
150
150
  get isDone(): boolean {
151
151
  return !this.stage
152
- || this._index >= this._stages.length
153
- || this.state === A_TYPES__FeatureState.COMPLETED
152
+ || this._index >= this._stages.length;
153
+ }
154
+ /**
155
+ * Indicates whether the feature has been processed (completed, failed, or interrupted)
156
+ */
157
+ get isProcessed(): boolean {
158
+ return this.state === A_TYPES__FeatureState.COMPLETED
159
+ || this.state === A_TYPES__FeatureState.FAILED
154
160
  || this.state === A_TYPES__FeatureState.INTERRUPTED;
155
161
  }
156
162
  /**
@@ -361,7 +367,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
361
367
  scope.inherit(A_Context.scope(this));
362
368
 
363
369
 
364
- if (this.isDone)
370
+ if (this.isProcessed)
365
371
  return;
366
372
 
367
373
  this._state = A_TYPES__FeatureState.PROCESSING;
@@ -403,7 +409,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
403
409
  * @returns
404
410
  */
405
411
  async completed(): Promise<void> {
406
- if (this.isDone) return;
412
+ if (this.isProcessed) return;
407
413
 
408
414
 
409
415
  this._state = A_TYPES__FeatureState.COMPLETED;
@@ -417,7 +423,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
417
423
  * @param error
418
424
  */
419
425
  async failed(error: A_FeatureError) {
420
- if (this.isDone) return;
426
+ if (this.isProcessed) return;
421
427
 
422
428
  this._state = A_TYPES__FeatureState.FAILED;
423
429
 
@@ -439,7 +445,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
439
445
  */
440
446
  reason?: string | A_StageError | Error
441
447
  ) {
442
- if (this.isDone) return;
448
+ if (this.isProcessed) return;
443
449
 
444
450
  this._state = A_TYPES__FeatureState.INTERRUPTED;
445
451
 
@@ -274,7 +274,6 @@ export class A_Stage {
274
274
 
275
275
  this.failed(wrappedError);
276
276
 
277
-
278
277
  if (this._definition.throwOnError) {
279
278
  return resolve();
280
279
  } else {
@@ -5,7 +5,8 @@ import {
5
5
  } from "../global/A-Feature/A-Feature.types";
6
6
  import {
7
7
  A_TYPES__Error_Constructor,
8
- A_TYPES__Error_Init
8
+ A_TYPES__Error_Init,
9
+ A_TYPES__Error_Serialized
9
10
  } from "../global/A-Error/A_Error.types";
10
11
  import { A_Component } from "../global/A-Component/A-Component.class";
11
12
  import { A_ComponentMeta } from "../global/A-Component/A-Component.meta";
@@ -27,6 +28,7 @@ import { A_CommonHelper } from "./A_Common.helper";
27
28
  import { A_TYPES__AbstractionAvailableComponents } from "../global/A-Abstraction/A-Abstraction.types";
28
29
  import { A_TYPES__Scope_Constructor, A_TYPES__ScopeLinkedComponents, A_TYPES__ScopeLinkedConstructors } from "../global/A-Scope/A-Scope.types";
29
30
  import { A_TYPES__InjectableTargets } from "../global/A-Inject/A-Inject.types";
31
+ import { ASEID } from "../global/ASEID/ASEID.class";
30
32
 
31
33
 
32
34
 
@@ -332,7 +334,12 @@ export class A_TypeGuards {
332
334
  * @param param
333
335
  * @returns
334
336
  */
335
- static isConstructorType<T extends A_TYPES__Error_Init>(param: any): param is T {
337
+ static isErrorConstructorType<T extends A_TYPES__Error_Init>(param: any): param is T {
336
338
  return !!param && A_TypeGuards.isObject(param) && !(param instanceof Error) && "title" in param;
337
339
  }
340
+
341
+
342
+ static isErrorSerializedType<T extends A_TYPES__Error_Serialized>(param: any): param is T {
343
+ return !!param && A_TypeGuards.isObject(param) && !(param instanceof Error) && "aseid" in param && ASEID.isASEID(param.aseid);
344
+ }
338
345
  }
@@ -5,7 +5,7 @@ import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
5
5
  import { A_Caller } from '@adaas/a-concept/global/A-Caller/A_Caller.class';
6
6
  import { A_Context } from '@adaas/a-concept/global/A-Context/A-Context.class';
7
7
  import { A_TYPES__ComponentMetaKey } from '@adaas/a-concept/global/A-Component/A-Component.constants';
8
- import { A_TYPES__FeatureState } from "../src";
8
+ import { A_Error, A_TYPES__FeatureState } from "../src";
9
9
 
10
10
  jest.retryTimes(0);
11
11
 
@@ -92,6 +92,67 @@ describe('A-Feature tests', () => {
92
92
  expect(myComponent.sum).toBe(2);
93
93
 
94
94
  });
95
+
96
+
97
+ it('Should fail execution when error occurs', async () => {
98
+ // 1) create a base component with some feature
99
+ class MyExtendedComponent extends A_Component {
100
+
101
+ async testHandler(
102
+ @A_Inject(A_Caller) caller: MyComponent
103
+ ) {
104
+ throw new Error('Deliberate error in testHandler');
105
+ }
106
+ }
107
+
108
+ // 2) create a custom component with a defined template feature
109
+ class MyComponent extends A_Component {
110
+ sum: number = 0;
111
+
112
+ @A_Feature.Define({
113
+ invoke: true,
114
+ template: [{
115
+ name: 'MyExtendedComponent.testHandler',
116
+ component: MyExtendedComponent,
117
+ handler: 'testHandler',
118
+ behavior: 'sync',
119
+ before: '',
120
+ after: ''
121
+ },
122
+ {
123
+ name: 'MyExtendedComponent.testHandler',
124
+ component: MyExtendedComponent,
125
+ handler: 'testHandler'
126
+ }]
127
+ })
128
+ async testHandler() { }
129
+ }
130
+
131
+
132
+ // 3) create a running scope
133
+ const scope = new A_Scope({ name: 'TestScope' });
134
+ scope.register(MyExtendedComponent);
135
+ scope.register(MyComponent);
136
+
137
+ // 4) create an instance of the component from the scope
138
+ const myComponent = scope.resolve(MyComponent)!;
139
+ expect(myComponent).toBeInstanceOf(MyComponent);
140
+ expect(myComponent.sum).toBe(0);
141
+
142
+ // 5) call the feature caller to execute the feature
143
+ try {
144
+ await myComponent.testHandler();
145
+
146
+ } catch (error) {
147
+ expect(error).toBeInstanceOf(A_Error);
148
+ expect((error as A_Error).originalError).toBeInstanceOf(Error);
149
+ expect((error as A_Error).originalError.message).toBe('Deliberate error in testHandler');
150
+ }
151
+
152
+ // 6) check the results
153
+ expect(myComponent.sum).toBe(0);
154
+
155
+ });
95
156
  it('Should be possible to execute a feature with steps as a template on the component with string component declaration', async () => {
96
157
  // 1) create a base component with some feature
97
158
  class MyExtendedComponent2 extends A_Component {
@@ -407,7 +468,7 @@ describe('A-Feature tests', () => {
407
468
 
408
469
 
409
470
  // 2) create a running scope
410
- const scope = new A_Scope({ name: 'TestScope' , components: [ComponentA, ComponentB] });
471
+ const scope = new A_Scope({ name: 'TestScope', components: [ComponentA, ComponentB] });
411
472
 
412
473
 
413
474
  // 3) create an instance of the component from the scope