@adaas/a-concept 0.2.4 → 0.2.6
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 +16 -16
- package/dist/index.d.ts +16 -16
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/global/A-Component/A-Component.class.ts +3 -3
- package/src/global/A-Dependency/A-Dependency-All.decorator.ts +1 -6
- package/src/global/A-Dependency/A-Dependency.class.ts +1 -0
- package/src/global/A-Feature/A-Feature.class.ts +52 -9
- package/src/global/A-Scope/A-Scope.class.ts +29 -10
- package/src/global/A-Stage/A-Stage.class.ts +54 -52
- package/src/helpers/A_TypeGuards.helper.ts +5 -0
- package/tests/A-Abstraction.test.ts +0 -2
- package/tests/A-Dependency.test.ts +93 -1
- package/tests/A-Feature.test.ts +86 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaas/a-concept",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "A-Concept is a framework of the new generation that is tailored to use AI, enabling developers to create AI-powered applications with ease. It provides a structured approach to building, managing, and deploying AI-driven solutions.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -29,7 +29,7 @@ export class A_Component {
|
|
|
29
29
|
* @param scope - the scope in which to call the feature
|
|
30
30
|
* @returns - void
|
|
31
31
|
*/
|
|
32
|
-
|
|
32
|
+
call(
|
|
33
33
|
/**
|
|
34
34
|
* Name of the feature to call
|
|
35
35
|
*/
|
|
@@ -38,13 +38,13 @@ export class A_Component {
|
|
|
38
38
|
* Scope in which the feature will be executed
|
|
39
39
|
*/
|
|
40
40
|
scope?: A_Scope
|
|
41
|
-
) {
|
|
41
|
+
): Promise<any> | void {
|
|
42
42
|
const newFeature = new A_Feature({
|
|
43
43
|
name: feature,
|
|
44
44
|
component: this
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
-
return
|
|
47
|
+
return newFeature.process(scope);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -16,12 +16,7 @@ import { A_TYPES__EntityMetaKey } from "../A-Entity/A-Entity.constants";
|
|
|
16
16
|
/**
|
|
17
17
|
* Should indicate which All is required
|
|
18
18
|
*/
|
|
19
|
-
export function A_Dependency_All
|
|
20
|
-
/**
|
|
21
|
-
* Constructor Parameters that will be used to create the default instance
|
|
22
|
-
*/
|
|
23
|
-
entity: A_TYPES__Entity_Constructor<T>
|
|
24
|
-
): A_TYPES__A_Dependency_AllDecoratorReturn {
|
|
19
|
+
export function A_Dependency_All(): A_TYPES__A_Dependency_AllDecoratorReturn {
|
|
25
20
|
|
|
26
21
|
return function (
|
|
27
22
|
target: A_TYPES__InjectableTargets,
|
|
@@ -355,13 +355,13 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
|
|
|
355
355
|
* This method processes the feature by executing all the stages
|
|
356
356
|
*
|
|
357
357
|
*/
|
|
358
|
-
|
|
358
|
+
process(
|
|
359
359
|
/**
|
|
360
360
|
* Optional scope to be used to resolve the steps dependencies
|
|
361
361
|
* If not provided, the scope of the caller component will be used
|
|
362
362
|
*/
|
|
363
363
|
scope?: A_Scope,
|
|
364
|
-
) {
|
|
364
|
+
): Promise<void> | void {
|
|
365
365
|
try {
|
|
366
366
|
// It seems like this is a bad idea to enforce scope inheritance here
|
|
367
367
|
// ---------------------------------------------------------------
|
|
@@ -373,20 +373,63 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
|
|
|
373
373
|
|
|
374
374
|
this._state = A_TYPES__FeatureState.PROCESSING;
|
|
375
375
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
376
|
+
// Convert iterator to array to get all stages
|
|
377
|
+
const stages = Array.from(this);
|
|
378
|
+
|
|
379
|
+
return this.processStagesSequentially(stages, scope, 0);
|
|
379
380
|
|
|
380
|
-
return await this.completed();
|
|
381
381
|
} catch (error) {
|
|
382
|
-
|
|
382
|
+
this.failed(new A_FeatureError({
|
|
383
383
|
title: A_FeatureError.FeatureProcessingError,
|
|
384
384
|
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${this.stage?.name || 'N/A'}.`,
|
|
385
385
|
stage: this.stage,
|
|
386
386
|
originalError: error
|
|
387
387
|
}));
|
|
388
388
|
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Process stages one by one, ensuring each stage completes before starting the next
|
|
393
|
+
*/
|
|
394
|
+
private processStagesSequentially(
|
|
395
|
+
stages: A_Stage[],
|
|
396
|
+
scope: A_Scope | undefined,
|
|
397
|
+
index: number
|
|
398
|
+
): Promise<void> | void {
|
|
399
|
+
try {
|
|
400
|
+
// If we've processed all stages, complete the feature
|
|
401
|
+
if (index >= stages.length) {
|
|
402
|
+
this.completed();
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
389
405
|
|
|
406
|
+
const stage = stages[index];
|
|
407
|
+
const result = stage.process(scope);
|
|
408
|
+
|
|
409
|
+
if (A_TypeGuards.isPromiseInstance(result)) {
|
|
410
|
+
// Async stage - return promise that processes remaining stages
|
|
411
|
+
return result.then(() => {
|
|
412
|
+
return this.processStagesSequentially(stages, scope, index + 1);
|
|
413
|
+
}).catch(error => {
|
|
414
|
+
this.failed(new A_FeatureError({
|
|
415
|
+
title: A_FeatureError.FeatureProcessingError,
|
|
416
|
+
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${stage.name}.`,
|
|
417
|
+
stage: stage,
|
|
418
|
+
originalError: error
|
|
419
|
+
}));
|
|
420
|
+
});
|
|
421
|
+
} else {
|
|
422
|
+
// Sync stage - continue to next stage immediately
|
|
423
|
+
return this.processStagesSequentially(stages, scope, index + 1);
|
|
424
|
+
}
|
|
425
|
+
} catch (error) {
|
|
426
|
+
this.failed(new A_FeatureError({
|
|
427
|
+
title: A_FeatureError.FeatureProcessingError,
|
|
428
|
+
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${this.stage?.name || 'N/A'}.`,
|
|
429
|
+
stage: this.stage,
|
|
430
|
+
originalError: error
|
|
431
|
+
}));
|
|
432
|
+
}
|
|
390
433
|
}
|
|
391
434
|
/**
|
|
392
435
|
* This method moves the feature to the next stage
|
|
@@ -409,7 +452,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
|
|
|
409
452
|
* @param result
|
|
410
453
|
* @returns
|
|
411
454
|
*/
|
|
412
|
-
|
|
455
|
+
completed(): void {
|
|
413
456
|
if (this.isProcessed) return;
|
|
414
457
|
|
|
415
458
|
|
|
@@ -423,7 +466,7 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
|
|
|
423
466
|
*
|
|
424
467
|
* @param error
|
|
425
468
|
*/
|
|
426
|
-
|
|
469
|
+
failed(error: A_FeatureError) {
|
|
427
470
|
if (this.isProcessed) return;
|
|
428
471
|
|
|
429
472
|
this._state = A_TYPES__FeatureState.FAILED;
|
|
@@ -766,20 +766,36 @@ export class A_Scope<
|
|
|
766
766
|
|
|
767
767
|
|
|
768
768
|
// 5) apply pagination
|
|
769
|
+
|
|
769
770
|
const count = dependency.pagination.count;
|
|
770
771
|
const from = dependency.pagination.from; // from start or from end
|
|
771
772
|
|
|
772
773
|
|
|
774
|
+
|
|
773
775
|
const startSliceIndex = from === 'end'
|
|
774
|
-
? Math.max(result.length - count, 0)
|
|
776
|
+
? (count === -1 ? 0 : Math.max(result.length - count, 0))
|
|
775
777
|
: 0;
|
|
778
|
+
|
|
779
|
+
// end slice should handle -1 for all items
|
|
776
780
|
const endSliceIndex = from === 'end'
|
|
777
781
|
? result.length
|
|
778
|
-
: Math.min(count, result.length);
|
|
782
|
+
: (count === -1 ? result.length : Math.min(count, result.length));
|
|
779
783
|
|
|
780
784
|
const slice = result.slice(startSliceIndex, endSliceIndex);
|
|
781
785
|
|
|
782
|
-
|
|
786
|
+
/**
|
|
787
|
+
* Default behavior is to return single instance if count is 1
|
|
788
|
+
*
|
|
789
|
+
* If Directive All (-1) is provided or count > 1, an array is returned
|
|
790
|
+
*
|
|
791
|
+
* If no instances found, undefined is returned
|
|
792
|
+
*/
|
|
793
|
+
return slice.length === 1
|
|
794
|
+
&& count !== -1
|
|
795
|
+
? slice[0]
|
|
796
|
+
: slice.length
|
|
797
|
+
? slice
|
|
798
|
+
: undefined;
|
|
783
799
|
}
|
|
784
800
|
|
|
785
801
|
|
|
@@ -940,17 +956,20 @@ export class A_Scope<
|
|
|
940
956
|
param1: A_TYPES__Ctor<A_TYPES__A_DependencyInjectable> | string
|
|
941
957
|
): Array<T> {
|
|
942
958
|
|
|
943
|
-
const results:
|
|
959
|
+
const results: Set<T> = new Set();
|
|
944
960
|
|
|
945
961
|
// 1) Resolve all in the current scope
|
|
946
962
|
const currentResults = this.resolveFlatAll<T>(param1 as any);
|
|
947
|
-
results.
|
|
963
|
+
currentResults.forEach(result => results.add(result));
|
|
948
964
|
|
|
949
965
|
// 2) resolve all in the imported scopes
|
|
950
966
|
this._imports.forEach(importedScope => {
|
|
967
|
+
|
|
951
968
|
if (importedScope.has(param1 as any)) {
|
|
952
969
|
const importedResults = importedScope.resolveFlatAll<T>(param1 as any);
|
|
953
|
-
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
importedResults.forEach(result => results.add(result));
|
|
954
973
|
}
|
|
955
974
|
});
|
|
956
975
|
|
|
@@ -958,8 +977,9 @@ export class A_Scope<
|
|
|
958
977
|
let parentScope = this._parent;
|
|
959
978
|
|
|
960
979
|
while (parentScope && parentScope.has(param1 as any)) {
|
|
961
|
-
|
|
962
|
-
|
|
980
|
+
|
|
981
|
+
const parentResults = parentScope.resolveAll<T>(param1 as any);
|
|
982
|
+
parentResults.forEach(result => results.add(result));
|
|
963
983
|
|
|
964
984
|
// Move to the next parent scope
|
|
965
985
|
parentScope = parentScope._parent;
|
|
@@ -967,7 +987,7 @@ export class A_Scope<
|
|
|
967
987
|
|
|
968
988
|
|
|
969
989
|
|
|
970
|
-
return results;
|
|
990
|
+
return Array.from(results);
|
|
971
991
|
}
|
|
972
992
|
|
|
973
993
|
|
|
@@ -1128,7 +1148,6 @@ export class A_Scope<
|
|
|
1128
1148
|
param1 as A_Dependency<T> :
|
|
1129
1149
|
new A_Dependency<T>(param1)
|
|
1130
1150
|
|
|
1131
|
-
|
|
1132
1151
|
return this.resolveDependency<T>(dependency);
|
|
1133
1152
|
}
|
|
1134
1153
|
|
|
@@ -35,11 +35,6 @@ export class A_Stage {
|
|
|
35
35
|
*/
|
|
36
36
|
private _status: A_TYPES__A_Stage_Status = A_TYPES__A_Stage_Status.INITIALIZED;
|
|
37
37
|
|
|
38
|
-
/**
|
|
39
|
-
* Promise that will be resolved when the stage is Processed
|
|
40
|
-
*/
|
|
41
|
-
private _processed: Promise<void> | undefined;
|
|
42
|
-
|
|
43
38
|
|
|
44
39
|
/**
|
|
45
40
|
* A_Stage is a callable A_Function within A_Feature that should be run with specific parameters.
|
|
@@ -106,7 +101,7 @@ export class A_Stage {
|
|
|
106
101
|
* @param step
|
|
107
102
|
* @returns
|
|
108
103
|
*/
|
|
109
|
-
protected
|
|
104
|
+
protected getStepArgs(
|
|
110
105
|
scope: A_Scope,
|
|
111
106
|
step: A_TYPES__A_StageStep
|
|
112
107
|
) {
|
|
@@ -114,24 +109,22 @@ export class A_Stage {
|
|
|
114
109
|
(step.dependency.target as A_TYPES__Container_Constructor | A_TYPES__Component_Constructor)
|
|
115
110
|
|| scope.resolveConstructor(step.dependency.name);
|
|
116
111
|
|
|
117
|
-
return
|
|
118
|
-
.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return this._feature.caller.component;
|
|
112
|
+
return A_Context
|
|
113
|
+
.meta(resolverConstructor)
|
|
114
|
+
.injections(step.handler)
|
|
115
|
+
.map(dependency => {
|
|
116
|
+
switch (true) {
|
|
117
|
+
case A_TypeGuards.isCallerConstructor(dependency.target):
|
|
118
|
+
return this._feature.caller.component;
|
|
125
119
|
|
|
126
|
-
|
|
127
|
-
|
|
120
|
+
case A_TypeGuards.isFeatureConstructor(dependency.target):
|
|
121
|
+
return this._feature;
|
|
128
122
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
123
|
+
default: {
|
|
124
|
+
return scope.resolve(dependency);
|
|
132
125
|
}
|
|
133
|
-
}
|
|
134
|
-
)
|
|
126
|
+
}
|
|
127
|
+
})
|
|
135
128
|
}
|
|
136
129
|
|
|
137
130
|
|
|
@@ -174,17 +167,23 @@ export class A_Stage {
|
|
|
174
167
|
* @param step
|
|
175
168
|
* @returns
|
|
176
169
|
*/
|
|
177
|
-
protected
|
|
170
|
+
protected callStepHandler(
|
|
178
171
|
step: A_TYPES__A_StageStep,
|
|
179
172
|
scope: A_Scope
|
|
180
|
-
) {
|
|
173
|
+
): {
|
|
174
|
+
handler: Function,
|
|
175
|
+
params: any[]
|
|
176
|
+
} {
|
|
181
177
|
// 1) Resolve component
|
|
182
|
-
const component =
|
|
178
|
+
const component = this.getStepComponent(scope, step);
|
|
183
179
|
// 2) Resolve arguments
|
|
184
|
-
const callArgs =
|
|
180
|
+
const callArgs = this.getStepArgs(scope, step);
|
|
185
181
|
|
|
186
182
|
// 3) Call handler
|
|
187
|
-
return
|
|
183
|
+
return {
|
|
184
|
+
handler: component[step.handler].bind(component),
|
|
185
|
+
params: callArgs
|
|
186
|
+
}
|
|
188
187
|
}
|
|
189
188
|
|
|
190
189
|
|
|
@@ -198,48 +197,51 @@ export class A_Stage {
|
|
|
198
197
|
*
|
|
199
198
|
* @param scope - Scope to be used to resolve the steps dependencies
|
|
200
199
|
*/
|
|
201
|
-
|
|
200
|
+
process(
|
|
202
201
|
/**
|
|
203
202
|
* Scope to be used to resolve the steps dependencies
|
|
204
203
|
*/
|
|
205
204
|
scope?: A_Scope,
|
|
206
|
-
): Promise<void> {
|
|
205
|
+
): Promise<void> | void {
|
|
207
206
|
|
|
208
207
|
const targetScope = A_TypeGuards.isScopeInstance(scope)
|
|
209
208
|
? scope
|
|
210
209
|
: this._feature.scope;
|
|
211
210
|
|
|
212
|
-
if (!this.
|
|
213
|
-
this.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
this._status = A_TYPES__A_Stage_Status.PROCESSING;
|
|
217
|
-
|
|
218
|
-
if (this._definition.behavior === 'sync') {
|
|
219
|
-
// in case we have to wait for the result
|
|
220
|
-
await this.callStepHandler(this._definition, targetScope);
|
|
221
|
-
} else {
|
|
222
|
-
// in case we don't have to wait for the result
|
|
223
|
-
this.callStepHandler(this._definition, targetScope);
|
|
224
|
-
}
|
|
211
|
+
if (!this.isProcessed) {
|
|
212
|
+
this._status = A_TYPES__A_Stage_Status.PROCESSING;
|
|
213
|
+
|
|
214
|
+
const { handler, params } = this.callStepHandler(this._definition, targetScope);
|
|
225
215
|
|
|
226
|
-
|
|
216
|
+
const result = handler(...params);
|
|
227
217
|
|
|
228
|
-
|
|
229
|
-
} catch (error) {
|
|
230
|
-
const wrappedError = new A_Error(error as any);
|
|
218
|
+
if (A_TypeGuards.isPromiseInstance(result)) {
|
|
231
219
|
|
|
232
|
-
|
|
220
|
+
return new Promise<void>(
|
|
221
|
+
async (resolve, reject) => {
|
|
222
|
+
try {
|
|
223
|
+
await result;
|
|
224
|
+
|
|
225
|
+
this.completed();
|
|
233
226
|
|
|
234
|
-
if (this._definition.throwOnError) {
|
|
235
227
|
return resolve();
|
|
236
|
-
}
|
|
237
|
-
|
|
228
|
+
} catch (error) {
|
|
229
|
+
const wrappedError = new A_Error(error as any);
|
|
230
|
+
|
|
231
|
+
this.failed(wrappedError);
|
|
232
|
+
|
|
233
|
+
if (this._definition.throwOnError) {
|
|
234
|
+
return resolve();
|
|
235
|
+
} else {
|
|
236
|
+
return reject(wrappedError);
|
|
237
|
+
}
|
|
238
238
|
}
|
|
239
|
-
}
|
|
240
|
-
|
|
239
|
+
});
|
|
240
|
+
} else {
|
|
241
|
+
this.completed();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
241
244
|
|
|
242
|
-
return this._processed;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
247
|
|
|
@@ -367,4 +367,9 @@ export class A_TypeGuards {
|
|
|
367
367
|
static isErrorSerializedType<T extends A_TYPES__Error_Serialized>(param: any): param is T {
|
|
368
368
|
return !!param && A_TypeGuards.isObject(param) && !(param instanceof Error) && "aseid" in param && ASEID.isASEID(param.aseid);
|
|
369
369
|
}
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
static isPromiseInstance<T>(value: any): value is Promise<T> {
|
|
373
|
+
return value instanceof Promise;
|
|
374
|
+
}
|
|
370
375
|
}
|
|
@@ -49,7 +49,7 @@ describe('A-Dependency tests', () => {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
class testEntity extends A_Entity {
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
@A_Feature.Extend({
|
|
54
54
|
name: 'test'
|
|
55
55
|
})
|
|
@@ -357,5 +357,97 @@ describe('A-Dependency tests', () => {
|
|
|
357
357
|
// });
|
|
358
358
|
|
|
359
359
|
});
|
|
360
|
+
it('Should support directive All for query', async () => {
|
|
361
|
+
|
|
362
|
+
const executionChain: number[] = [];
|
|
363
|
+
|
|
364
|
+
class MyEntity_A extends A_Entity<{ name: string }> {
|
|
365
|
+
name!: string;
|
|
366
|
+
|
|
367
|
+
fromNew(newEntity: { name: string; }): void {
|
|
368
|
+
super.fromNew(newEntity);
|
|
369
|
+
this.name = newEntity.name;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
class MyComponent extends A_Component {
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@A_Feature.Extend()
|
|
377
|
+
async allEntities(
|
|
378
|
+
@A_Dependency.All()
|
|
379
|
+
@A_Inject(MyEntity_A) entities: MyEntity_A[],
|
|
380
|
+
@A_Inject(A_Scope) scope: A_Scope,
|
|
381
|
+
) {
|
|
382
|
+
executionChain.push(entities.length);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
@A_Feature.Extend()
|
|
386
|
+
async allFlatEntities(
|
|
387
|
+
@A_Dependency.Flat()
|
|
388
|
+
// That's important because current scope is feature scope, and plat applies for current scope only
|
|
389
|
+
@A_Dependency.All()
|
|
390
|
+
@A_Dependency.Parent(-1)
|
|
391
|
+
@A_Inject(MyEntity_A) entities: MyEntity_A[],
|
|
392
|
+
@A_Inject(A_Scope) scope: A_Scope,
|
|
393
|
+
|
|
394
|
+
) {
|
|
395
|
+
executionChain.push(entities.length);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
@A_Feature.Extend()
|
|
399
|
+
async withImportedEntities(
|
|
400
|
+
@A_Dependency.All()
|
|
401
|
+
@A_Inject(MyEntity_A) entities: MyEntity_A[],
|
|
402
|
+
) {
|
|
403
|
+
executionChain.push(entities.length);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const parentScope = new A_Scope({
|
|
408
|
+
name: 'Parent Scope',
|
|
409
|
+
entities: [
|
|
410
|
+
new MyEntity_A({ name: 'Entity 1' }),
|
|
411
|
+
new MyEntity_A({ name: 'Entity 2' }),
|
|
412
|
+
new MyEntity_A({ name: 'Entity 3' }),
|
|
413
|
+
]
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
const childScope = new A_Scope({
|
|
417
|
+
name: 'Child Scope',
|
|
418
|
+
components: [MyComponent],
|
|
419
|
+
entities: [
|
|
420
|
+
new MyEntity_A({ name: 'Entity 4' }),
|
|
421
|
+
new MyEntity_A({ name: 'Entity 5' }),
|
|
422
|
+
]
|
|
423
|
+
}, { parent: parentScope });
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
const importScope = new A_Scope({
|
|
427
|
+
name: 'Import Scope',
|
|
428
|
+
entities: [
|
|
429
|
+
new MyEntity_A({ name: 'Entity 6' }),
|
|
430
|
+
]
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
const componentInstance = childScope.resolve(MyComponent);
|
|
436
|
+
|
|
437
|
+
await componentInstance?.call('allEntities');
|
|
438
|
+
await componentInstance?.call('allFlatEntities');
|
|
439
|
+
await componentInstance?.call('withImportedEntities');
|
|
440
|
+
|
|
441
|
+
expect(executionChain).toEqual([5, 2, 5]);
|
|
442
|
+
|
|
443
|
+
childScope.import(importScope);
|
|
444
|
+
|
|
445
|
+
await componentInstance?.call('withImportedEntities');
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
expect(executionChain).toEqual([5, 2, 5, 6]);
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
});
|
|
360
452
|
|
|
361
453
|
});
|
package/tests/A-Feature.test.ts
CHANGED
|
@@ -644,7 +644,7 @@ describe('A-Feature tests', () => {
|
|
|
644
644
|
await baseEntity.test();
|
|
645
645
|
|
|
646
646
|
expect(executionResults).toEqual(['testMethod']);
|
|
647
|
-
|
|
647
|
+
|
|
648
648
|
await myEntity.test();
|
|
649
649
|
|
|
650
650
|
expect(executionResults).toEqual(['testMethod', 'testMethod']);
|
|
@@ -783,4 +783,89 @@ describe('A-Feature tests', () => {
|
|
|
783
783
|
]);
|
|
784
784
|
|
|
785
785
|
})
|
|
786
|
+
it('Should execute Sync operations properly', async () => {
|
|
787
|
+
|
|
788
|
+
const resultChain: string[] = [];
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
class ChildComponent_A extends A_Component {
|
|
792
|
+
@A_Feature.Extend({
|
|
793
|
+
name: 'testFeature',
|
|
794
|
+
})
|
|
795
|
+
test1() {
|
|
796
|
+
resultChain.push('ChildComponent_A.test');
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
class ChildComponent_B extends A_Component {
|
|
801
|
+
@A_Feature.Extend({
|
|
802
|
+
name: 'testFeature',
|
|
803
|
+
})
|
|
804
|
+
test2() {
|
|
805
|
+
resultChain.push('ChildComponent_B.test');
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
const testScope = new A_Scope({ name: 'TestScope', components: [ChildComponent_A, ChildComponent_B] });
|
|
811
|
+
|
|
812
|
+
testScope.resolve(ChildComponent_A)!.call('testFeature');
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
expect(resultChain).toEqual([
|
|
816
|
+
'ChildComponent_A.test',
|
|
817
|
+
'ChildComponent_B.test'
|
|
818
|
+
]);
|
|
819
|
+
|
|
820
|
+
})
|
|
821
|
+
|
|
822
|
+
it('Should execute Async operations properly', async () => {
|
|
823
|
+
|
|
824
|
+
const resultChain: string[] = [];
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
class ChildComponent_A extends A_Component {
|
|
828
|
+
@A_Feature.Extend({
|
|
829
|
+
name: 'testFeature',
|
|
830
|
+
})
|
|
831
|
+
async test1() {
|
|
832
|
+
resultChain.push('ChildComponent_A.test');
|
|
833
|
+
|
|
834
|
+
await new Promise<void>(async (resolve) => {
|
|
835
|
+
setTimeout(() => {
|
|
836
|
+
resolve();
|
|
837
|
+
}, 3000);
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
class ChildComponent_B extends A_Component {
|
|
843
|
+
@A_Feature.Extend({
|
|
844
|
+
name: 'testFeature',
|
|
845
|
+
})
|
|
846
|
+
async test2() {
|
|
847
|
+
resultChain.push('ChildComponent_B.test');
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
const testScope = new A_Scope({ name: 'TestScope', components: [ChildComponent_A, ChildComponent_B] });
|
|
852
|
+
|
|
853
|
+
await Promise.all([
|
|
854
|
+
new Promise<void>(async (resolve) => {
|
|
855
|
+
setTimeout(() => {
|
|
856
|
+
resultChain.push('feature3');
|
|
857
|
+
|
|
858
|
+
resolve();
|
|
859
|
+
}, 2000);
|
|
860
|
+
}),
|
|
861
|
+
testScope.resolve(ChildComponent_A)!.call('testFeature')
|
|
862
|
+
]);
|
|
863
|
+
|
|
864
|
+
expect(resultChain).toEqual([
|
|
865
|
+
'ChildComponent_A.test',
|
|
866
|
+
'feature3',
|
|
867
|
+
'ChildComponent_B.test'
|
|
868
|
+
]);
|
|
869
|
+
|
|
870
|
+
})
|
|
786
871
|
});
|