@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/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/global/A-Error/A_Error.class.ts +28 -6
- package/src/global/A-Feature/A-Feature.class.ts +12 -6
- package/src/global/A-Stage/A-Stage.class.ts +0 -1
- package/src/helpers/A_TypeGuards.helper.ts +9 -2
- package/tests/A-Feature.test.ts +63 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaas/a-concept",
|
|
3
|
-
"version": "0.1.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
448
|
+
if (this.isProcessed) return;
|
|
443
449
|
|
|
444
450
|
this._state = A_TYPES__FeatureState.INTERRUPTED;
|
|
445
451
|
|
|
@@ -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
|
|
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
|
}
|
package/tests/A-Feature.test.ts
CHANGED
|
@@ -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'
|
|
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
|