@adaas/a-concept 0.0.56 → 0.0.58
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/.nvmrc +1 -1
- package/dist/src/base/A-Command/A_Command.constants.d.ts +12 -0
- package/dist/src/base/A-Command/A_Command.constants.js +17 -0
- package/dist/src/base/A-Command/A_Command.constants.js.map +1 -0
- package/dist/src/base/A-Command/A_Command.entity.d.ts +123 -0
- package/dist/src/base/A-Command/A_Command.entity.js +259 -0
- package/dist/src/base/A-Command/A_Command.entity.js.map +1 -0
- package/dist/src/base/A-Command/A_Command.types.d.ts +15 -0
- package/dist/src/base/A-Command/A_Command.types.js +3 -0
- package/dist/src/base/A-Command/A_Command.types.js.map +1 -0
- package/dist/src/base/A-Command/context/A_Command.context.d.ts +64 -0
- package/dist/src/base/A-Command/context/A_Command.context.js +85 -0
- package/dist/src/base/A-Command/context/A_Command.context.js.map +1 -0
- package/dist/src/base/A-Command/context/A_CommandFactory.context.js +2 -0
- package/dist/src/base/A-Command/context/A_CommandFactory.context.js.map +1 -0
- package/dist/src/base/A-Config/A-Config.container.d.ts +1 -2
- package/dist/src/base/A-Config/A-Config.container.js +2 -4
- package/dist/src/base/A-Config/A-Config.container.js.map +1 -1
- package/dist/src/base/A-Config/A-Config.context.d.ts +10 -11
- package/dist/src/base/A-Config/A-Config.context.js +5 -24
- package/dist/src/base/A-Config/A-Config.context.js.map +1 -1
- package/dist/src/base/A-Config/A-Config.types.d.ts +4 -4
- package/dist/src/base/A-Config/A-Config.types.js.map +1 -1
- package/dist/src/base/A-Config/components/ConfigReader.component.js +6 -12
- package/dist/src/base/A-Config/components/ConfigReader.component.js.map +1 -1
- package/dist/src/base/A-Config/components/ENVConfigReader.component.js +5 -1
- package/dist/src/base/A-Config/components/ENVConfigReader.component.js.map +1 -1
- package/dist/src/constants/env.constants.d.ts +26 -0
- package/dist/src/constants/env.constants.js +40 -0
- package/dist/src/constants/env.constants.js.map +1 -0
- package/dist/src/decorators/A-Inject/A-Inject.decorator.d.ts +3 -3
- package/dist/src/decorators/A-Inject/A-Inject.decorator.types.d.ts +9 -10
- package/dist/src/global/A-Channel/A-Channel.class.d.ts +2 -0
- package/dist/src/global/A-Channel/A-Channel.class.js +2 -0
- package/dist/src/global/A-Channel/A-Channel.class.js.map +1 -1
- package/dist/src/global/A-Concept/A_Concept.class.d.ts +5 -3
- package/dist/src/global/A-Concept/A_Concept.class.js +32 -27
- package/dist/src/global/A-Concept/A_Concept.class.js.map +1 -1
- package/dist/src/global/A-Concept/A_Concept.meta.d.ts +1 -8
- package/dist/src/global/A-Concept/A_Concept.meta.js +1 -25
- package/dist/src/global/A-Concept/A_Concept.meta.js.map +1 -1
- package/dist/src/global/A-Concept/A_Concept.types.d.ts +10 -1
- package/dist/src/global/A-Container/A-Container.class.d.ts +5 -0
- package/dist/src/global/A-Container/A-Container.class.js +5 -0
- package/dist/src/global/A-Container/A-Container.class.js.map +1 -1
- package/dist/src/global/A-Context/A-Context.class.d.ts +23 -1
- package/dist/src/global/A-Context/A-Context.class.js +38 -1
- package/dist/src/global/A-Context/A-Context.class.js.map +1 -1
- package/dist/src/global/A-Entity/A-Entity.class.d.ts +124 -23
- package/dist/src/global/A-Entity/A-Entity.class.js +159 -49
- package/dist/src/global/A-Entity/A-Entity.class.js.map +1 -1
- package/dist/src/global/A-Scope/A-Scope.class.d.ts +7 -6
- package/dist/src/global/A-Scope/A-Scope.class.js +57 -20
- package/dist/src/global/A-Scope/A-Scope.class.js.map +1 -1
- package/dist/src/global/A-Stage/A-Stage.class.d.ts +3 -2
- package/dist/src/global/A-Stage/A-Stage.class.js +9 -6
- package/dist/src/global/A-Stage/A-Stage.class.js.map +1 -1
- package/dist/src/global/A-Stage/A-Stage.types.d.ts +1 -1
- package/dist/src/helpers/StepsManager.class.js +1 -1
- package/dist/src/helpers/StepsManager.class.js.map +1 -1
- package/examples/simple/components/A.component.ts +9 -2
- package/examples/simple/concept.ts +6 -0
- package/examples/simple/entities/EntityA.entity.ts +18 -0
- package/jest.config.ts +1 -1
- package/package.json +3 -3
- package/src/base/A-Command/A_Command.constants.ts +20 -0
- package/src/base/A-Command/A_Command.entity.ts +287 -0
- package/src/base/A-Command/A_Command.types.ts +34 -0
- package/src/base/A-Command/context/A_Command.context.ts +114 -0
- package/src/base/A-Command/context/A_CommandFactory.context.ts +0 -0
- package/src/base/A-Config/A-Config.container.ts +0 -1
- package/src/base/A-Config/A-Config.context.ts +22 -28
- package/src/base/A-Config/A-Config.types.ts +5 -24
- package/src/base/A-Config/components/ConfigReader.component.ts +6 -15
- package/src/base/A-Config/components/ENVConfigReader.component.ts +6 -1
- package/src/constants/env.constants.ts +44 -0
- package/src/decorators/A-Inject/A-Inject.decorator.ts +3 -3
- package/src/decorators/A-Inject/A-Inject.decorator.types.ts +10 -9
- package/src/global/A-Channel/A-Channel.class.ts +2 -0
- package/src/global/A-Concept/A_Concept.class.ts +49 -32
- package/src/global/A-Concept/A_Concept.meta.ts +3 -41
- package/src/global/A-Concept/A_Concept.types.ts +6 -4
- package/src/global/A-Container/A-Container.class.ts +5 -2
- package/src/global/A-Context/A-Context.class.ts +67 -8
- package/src/global/A-Entity/A-Entity.class.ts +203 -73
- package/src/global/A-Scope/A-Scope.class.ts +88 -39
- package/src/global/A-Stage/A-Stage.class.ts +11 -7
- package/src/global/A-Stage/A-Stage.types.ts +1 -1
- package/src/helpers/StepsManager.class.ts +2 -2
- package/tests/A-Command.test.ts +130 -0
- package/tests/A-Component.test.ts +25 -0
- package/tests/A-Config.test.ts +106 -0
- package/tests/A-Entity.test.ts +191 -0
- package/tests/A-Feature.test.ts +131 -0
- package/tests/A-Scope.test.ts +163 -0
- package/dist/src/constants/A_ConceptLifecycle.constants.js +0 -11
- package/dist/src/constants/A_ConceptLifecycle.constants.js.map +0 -1
- package/src/constants/A_ConceptLifecycle.constants.ts +0 -12
- package/tests/channel.ts +0 -213
- package/tests/context.test.ts +0 -124
- package/tests/default.test.ts +0 -159
- package/tests/log.ts +0 -102
- package/tests/polyfill.test.ts +0 -37
- /package/dist/src/{constants/A_ConceptLifecycle.constants.d.ts → base/A-Command/context/A_CommandFactory.context.d.ts} +0 -0
|
@@ -9,6 +9,7 @@ import { A_Component } from "../A-Component/A-Component.class";
|
|
|
9
9
|
import { A_Entity } from "../A-Entity/A-Entity.class";
|
|
10
10
|
import {
|
|
11
11
|
A_TYPES__A_InjectDecorator_EntityInjectionInstructions,
|
|
12
|
+
A_TYPES__A_InjectDecorator_EntityInjectionQuery,
|
|
12
13
|
A_TYPES__A_InjectDecorator_Injectable
|
|
13
14
|
} from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator.types";
|
|
14
15
|
|
|
@@ -176,20 +177,20 @@ export class A_Scope {
|
|
|
176
177
|
* @param component
|
|
177
178
|
* @returns
|
|
178
179
|
*/
|
|
179
|
-
has(
|
|
180
|
-
component:
|
|
180
|
+
has<T extends A_Component>(
|
|
181
|
+
component: new (...args: any[]) => T
|
|
181
182
|
): boolean
|
|
182
|
-
has(
|
|
183
|
-
entity:
|
|
183
|
+
has<T extends A_Entity>(
|
|
184
|
+
entity: new (...args: any[]) => T
|
|
184
185
|
): boolean
|
|
185
|
-
has(
|
|
186
|
-
fragment:
|
|
186
|
+
has<T extends A_Fragment>(
|
|
187
|
+
fragment: new (...args: any[]) => T
|
|
187
188
|
): boolean
|
|
188
189
|
has(
|
|
189
190
|
constructor: string
|
|
190
191
|
): boolean
|
|
191
|
-
has(
|
|
192
|
-
entity:
|
|
192
|
+
has<T extends A_Fragment | A_Component | A_Entity>(
|
|
193
|
+
entity: T | string | (new (...args: any[]) => T)
|
|
193
194
|
): boolean {
|
|
194
195
|
|
|
195
196
|
|
|
@@ -218,31 +219,35 @@ export class A_Scope {
|
|
|
218
219
|
return false;
|
|
219
220
|
}
|
|
220
221
|
|
|
221
|
-
case
|
|
222
|
-
|
|
222
|
+
case typeof entity === 'function'
|
|
223
|
+
&& A_CommonHelper.isInheritedFrom(entity, A_Component): {
|
|
224
|
+
const found = this.params.components.includes(entity as { new(...args: any[]): A_Component });
|
|
223
225
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
+
if (!found && !!this._parent) {
|
|
227
|
+
return this._parent.has(entity as any);
|
|
228
|
+
}
|
|
226
229
|
|
|
227
|
-
|
|
228
|
-
|
|
230
|
+
return found;
|
|
231
|
+
}
|
|
229
232
|
|
|
230
|
-
case
|
|
231
|
-
|
|
233
|
+
case typeof entity === 'function'
|
|
234
|
+
&& A_CommonHelper.isInheritedFrom(entity, A_Entity): {
|
|
235
|
+
const entities = Array.from(this._entities.values());
|
|
232
236
|
|
|
233
|
-
|
|
237
|
+
const found = entities.find(e => e instanceof entity);
|
|
234
238
|
|
|
235
|
-
|
|
236
|
-
|
|
239
|
+
return !!found;
|
|
240
|
+
}
|
|
237
241
|
|
|
238
|
-
case
|
|
239
|
-
|
|
242
|
+
case typeof entity === 'function'
|
|
243
|
+
&& A_CommonHelper.isInheritedFrom(entity, A_Fragment): {
|
|
244
|
+
const found = this._fragments.has(entity);
|
|
240
245
|
|
|
241
|
-
|
|
242
|
-
|
|
246
|
+
if (!found && !!this._parent)
|
|
247
|
+
return this._parent.has(entity as any);
|
|
243
248
|
|
|
244
|
-
|
|
245
|
-
|
|
249
|
+
return found;
|
|
250
|
+
}
|
|
246
251
|
|
|
247
252
|
default: {
|
|
248
253
|
return false;
|
|
@@ -251,7 +256,6 @@ export class A_Scope {
|
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
|
|
254
|
-
|
|
255
259
|
/**
|
|
256
260
|
* Merges two scopes into a new one
|
|
257
261
|
*
|
|
@@ -300,10 +304,10 @@ export class A_Scope {
|
|
|
300
304
|
resolve<T extends A_TYPES__A_InjectDecorator_Injectable>(
|
|
301
305
|
component: T
|
|
302
306
|
): InstanceType<T>
|
|
303
|
-
resolve<T extends
|
|
304
|
-
entity: T,
|
|
305
|
-
instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions
|
|
306
|
-
):
|
|
307
|
+
resolve<T extends A_Entity>(
|
|
308
|
+
entity: { new(...args: any[]): T },
|
|
309
|
+
instructions: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<T>>
|
|
310
|
+
): T | Array<T>
|
|
307
311
|
resolve<T extends A_TYPES__A_InjectDecorator_Injectable>(
|
|
308
312
|
component: Array<T>
|
|
309
313
|
): Array<InstanceType<T>>
|
|
@@ -313,6 +317,7 @@ export class A_Scope {
|
|
|
313
317
|
param2?: string | Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions>
|
|
314
318
|
): Array<InstanceType<T>> | InstanceType<T> {
|
|
315
319
|
|
|
320
|
+
|
|
316
321
|
switch (true) {
|
|
317
322
|
case Array.isArray(param1): {
|
|
318
323
|
return param1.map(c => this.resolveOnce(param1 as any, param2 as any));
|
|
@@ -372,7 +377,7 @@ export class A_Scope {
|
|
|
372
377
|
|
|
373
378
|
switch (true) {
|
|
374
379
|
case A_CommonHelper.isInheritedFrom(component, A_Entity): {
|
|
375
|
-
return this.resolveEntity(component as
|
|
380
|
+
return this.resolveEntity(component as any, instructions) as InstanceType<T>;
|
|
376
381
|
}
|
|
377
382
|
|
|
378
383
|
case A_CommonHelper.isInheritedFrom(component, A_Fragment): {
|
|
@@ -395,18 +400,18 @@ export class A_Scope {
|
|
|
395
400
|
|
|
396
401
|
private resolveEntity<T extends { new(...args: any[]): A_Entity }>(
|
|
397
402
|
entity: T,
|
|
398
|
-
instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions
|
|
399
|
-
): InstanceType<T> | undefined {
|
|
403
|
+
instructions?: Partial<A_TYPES__A_InjectDecorator_EntityInjectionInstructions<InstanceType<T>>>
|
|
404
|
+
): InstanceType<T> | undefined | InstanceType<T>[] {
|
|
400
405
|
|
|
401
|
-
const query = instructions?.query || {}
|
|
406
|
+
const query = instructions?.query || {} as Partial<A_TYPES__A_InjectDecorator_EntityInjectionQuery<InstanceType<T>>>;
|
|
402
407
|
const count = instructions?.pagination?.count || 1;
|
|
403
408
|
|
|
404
|
-
|
|
405
409
|
switch (true) {
|
|
406
410
|
case !instructions: {
|
|
407
411
|
|
|
408
412
|
const entities = Array.from(this._entities.values());
|
|
409
413
|
|
|
414
|
+
|
|
410
415
|
const found = entities.find(e => e instanceof entity);
|
|
411
416
|
|
|
412
417
|
switch (true) {
|
|
@@ -417,7 +422,7 @@ export class A_Scope {
|
|
|
417
422
|
return this._parent.resolveEntity(entity, instructions);
|
|
418
423
|
|
|
419
424
|
default:
|
|
420
|
-
throw new Error(`
|
|
425
|
+
throw new Error(`Entity ${entity.name} not found in the scope ${this.name}`);
|
|
421
426
|
}
|
|
422
427
|
}
|
|
423
428
|
|
|
@@ -428,6 +433,7 @@ export class A_Scope {
|
|
|
428
433
|
}
|
|
429
434
|
|
|
430
435
|
case !!query.aseid
|
|
436
|
+
&& typeof query.aseid === 'object'
|
|
431
437
|
&& query.aseid instanceof ASEID
|
|
432
438
|
&& this._entities.has(query.aseid.toString()): {
|
|
433
439
|
return this._entities.get(query.aseid.toString()) as InstanceType<T>;
|
|
@@ -447,8 +453,29 @@ export class A_Scope {
|
|
|
447
453
|
return found as InstanceType<T>;
|
|
448
454
|
}
|
|
449
455
|
|
|
450
|
-
default:
|
|
451
|
-
|
|
456
|
+
default: {
|
|
457
|
+
const entities = Array.from(this._entities.values());
|
|
458
|
+
|
|
459
|
+
const found = entities.filter(
|
|
460
|
+
e => e instanceof entity
|
|
461
|
+
).filter(e => {
|
|
462
|
+
return Object.entries(query).every(([key, value]) => {
|
|
463
|
+
if (key in e) {
|
|
464
|
+
return (e as any)[key] === value;
|
|
465
|
+
}
|
|
466
|
+
return false;
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
if (found.length === 0 && !!this._parent)
|
|
471
|
+
return this._parent.resolveEntity(entity, instructions);
|
|
472
|
+
|
|
473
|
+
if (count === 1)
|
|
474
|
+
return found[0] as InstanceType<T>;
|
|
475
|
+
|
|
476
|
+
return found as InstanceType<T>[];
|
|
477
|
+
}
|
|
478
|
+
|
|
452
479
|
}
|
|
453
480
|
}
|
|
454
481
|
|
|
@@ -458,6 +485,7 @@ export class A_Scope {
|
|
|
458
485
|
|
|
459
486
|
const fragmentInstancePresented = this.fragments.some(fr => fr instanceof fragment);
|
|
460
487
|
|
|
488
|
+
|
|
461
489
|
switch (true) {
|
|
462
490
|
|
|
463
491
|
case fragmentInstancePresented && this._fragments.has(fragment):
|
|
@@ -543,13 +571,27 @@ export class A_Scope {
|
|
|
543
571
|
*
|
|
544
572
|
* @param fragment
|
|
545
573
|
*/
|
|
574
|
+
register<T extends A_Component>(component: new (...args: any[]) => T): void
|
|
546
575
|
register(entity: A_Entity): void
|
|
547
576
|
register(component: A_Component): void
|
|
548
577
|
register(fragment: A_Fragment): void
|
|
549
578
|
register(
|
|
550
|
-
param1: A_Fragment | A_Component | A_Entity
|
|
579
|
+
param1: A_Fragment | A_Component | A_Entity | (new (...args: any[]) => A_Component)
|
|
551
580
|
): void {
|
|
552
581
|
switch (true) {
|
|
582
|
+
case param1 instanceof A_Component && !this._components.has(param1.constructor): {
|
|
583
|
+
this._components.set(param1.constructor, param1);
|
|
584
|
+
|
|
585
|
+
const allowedComponent = this.components.find(c => c === param1.constructor);
|
|
586
|
+
|
|
587
|
+
if (!allowedComponent) {
|
|
588
|
+
this.components.push(param1.constructor as any);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
A_Context.register(this, param1);
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
|
|
553
595
|
case param1 instanceof A_Entity && !this._entities.has(param1.aseid.toString()): {
|
|
554
596
|
this._entities.set(param1.aseid.toString(), param1);
|
|
555
597
|
A_Context.register(this, param1);
|
|
@@ -581,6 +623,13 @@ export class A_Scope {
|
|
|
581
623
|
break;
|
|
582
624
|
}
|
|
583
625
|
|
|
626
|
+
case typeof param1 === 'function' && A_CommonHelper.isInheritedFrom(param1, A_Component): {
|
|
627
|
+
const allowedComponent = this.components.find(c => c === param1);
|
|
628
|
+
|
|
629
|
+
if (!allowedComponent)
|
|
630
|
+
this.components.push(param1);
|
|
631
|
+
break;
|
|
632
|
+
}
|
|
584
633
|
default:
|
|
585
634
|
if (param1 instanceof A_Entity)
|
|
586
635
|
throw new Error(`Entity with ASEID ${param1.aseid.toString()} is already registered in the scope ${this.name}`);
|
|
@@ -6,6 +6,7 @@ import { A_Container } from "../A-Container/A-Container.class";
|
|
|
6
6
|
import { A_Scope } from "../A-Scope/A-Scope.class";
|
|
7
7
|
import { A_StageError } from "./A-Stage.error";
|
|
8
8
|
import { A_FeatureCaller } from "../A-Feature/A-FeatureCaller.class";
|
|
9
|
+
import { A_Entity } from "../A-Entity/A-Entity.class";
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -30,10 +31,10 @@ export class A_Stage {
|
|
|
30
31
|
this._steps = _steps;
|
|
31
32
|
this.name = `${this.feature.name}::a-stage:[sync:${this
|
|
32
33
|
.syncSteps
|
|
33
|
-
.map(s => s.component.name + '.' + s.handler)
|
|
34
|
+
.map(s => typeof s.component === 'string' ? s.component : s.component.name + '.' + s.handler)
|
|
34
35
|
.join(' -> ')}][async:${this
|
|
35
36
|
.asyncSteps
|
|
36
|
-
.map(s => s.component.name + '.' + s.handler)
|
|
37
|
+
.map(s => typeof s.component === 'string' ? s.component : s.component.name + '.' + s.handler)
|
|
37
38
|
.join(' -> ')}]`;
|
|
38
39
|
|
|
39
40
|
}
|
|
@@ -87,9 +88,11 @@ export class A_Stage {
|
|
|
87
88
|
return Promise
|
|
88
89
|
.all(A_Context
|
|
89
90
|
.meta(
|
|
90
|
-
|
|
91
|
+
// TODO: fix types
|
|
92
|
+
(step.component instanceof A_Container
|
|
91
93
|
? step.component.constructor
|
|
92
|
-
: step.component
|
|
94
|
+
: step.component) as any
|
|
95
|
+
|
|
93
96
|
)
|
|
94
97
|
.injections(step.handler)
|
|
95
98
|
.map(async arg => {
|
|
@@ -100,7 +103,7 @@ export class A_Stage {
|
|
|
100
103
|
if (A_CommonHelper.isInheritedFrom(arg.target, A_Feature))
|
|
101
104
|
return this.feature;
|
|
102
105
|
|
|
103
|
-
return scope.resolve(arg.target)
|
|
106
|
+
return scope.resolve((arg as any).target, (arg as any).instructions)
|
|
104
107
|
})
|
|
105
108
|
)
|
|
106
109
|
}
|
|
@@ -134,10 +137,11 @@ export class A_Stage {
|
|
|
134
137
|
// TODO: probably would be better to do it another way. let's think about it
|
|
135
138
|
const instance = component instanceof A_Container
|
|
136
139
|
? component
|
|
137
|
-
:
|
|
140
|
+
// TODO: fix types
|
|
141
|
+
: this.feature.Scope.resolve(component as any);
|
|
138
142
|
|
|
139
143
|
if (!instance)
|
|
140
|
-
throw new Error(`Unable to resolve component ${component.name}`);
|
|
144
|
+
throw new Error(`Unable to resolve component ${typeof component === 'string' ? component : component.name} from scope ${this.feature.Scope.name}`);
|
|
141
145
|
|
|
142
146
|
if (!instance[handler])
|
|
143
147
|
throw new Error(`Handler ${handler} not found in ${instance.constructor.name}`);
|
|
@@ -21,7 +21,7 @@ export class StepsManager {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
private ID(step: A_TYPES__A_StageStep) {
|
|
24
|
-
return `${step.component.name}.${step.handler}`;
|
|
24
|
+
return `${typeof step.component === 'string' ? step.component : step.component.name}.${step.handler}`;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
private buildGraph() {
|
|
@@ -103,7 +103,7 @@ export class StepsManager {
|
|
|
103
103
|
stage.add(step);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
return stages.map(stage => new A_Stage(feature, stage.steps)
|
|
106
|
+
return stages.map(stage => new A_Stage(feature, stage.steps));
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { A_CONSTANTS__A_Command_Status, A_CONSTANTS_A_Command_Features } from "@adaas/a-concept/base/A-Command/A_Command.constants";
|
|
5
|
+
import { A_Command } from "@adaas/a-concept/base/A-Command/A_Command.entity";
|
|
6
|
+
import { A_CommandContext } from "@adaas/a-concept/base/A-Command/context/A_Command.context";
|
|
7
|
+
import { A_Inject } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator";
|
|
8
|
+
import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
|
|
9
|
+
import { A_Feature } from "@adaas/a-concept/global/A-Feature/A-Feature.class";
|
|
10
|
+
import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
|
|
11
|
+
import { A_Error } from "@adaas/a-utils";
|
|
12
|
+
|
|
13
|
+
jest.retryTimes(0);
|
|
14
|
+
|
|
15
|
+
describe('A-Command tests', () => {
|
|
16
|
+
|
|
17
|
+
it('Should Allow to create a command', async () => {
|
|
18
|
+
const command = new A_Command({});
|
|
19
|
+
expect(command).toBeInstanceOf(A_Command);
|
|
20
|
+
expect(command.Code).toBe('A_Command');
|
|
21
|
+
expect(command.id).toBeDefined();
|
|
22
|
+
expect(command.aseid).toBeDefined();
|
|
23
|
+
expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.INITIALIZED);
|
|
24
|
+
expect(command.Scope).toBeInstanceOf(A_Scope);
|
|
25
|
+
expect(command.Scope.resolve(A_CommandContext)).toBeInstanceOf(A_CommandContext);
|
|
26
|
+
});
|
|
27
|
+
it('Should allow to execute a command', async () => {
|
|
28
|
+
const command = new A_Command({});
|
|
29
|
+
|
|
30
|
+
await command.execute();
|
|
31
|
+
|
|
32
|
+
expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.COMPLETED);
|
|
33
|
+
expect(command.StartedAt).toBeInstanceOf(Date);
|
|
34
|
+
expect(command.EndedAt).toBeInstanceOf(Date);
|
|
35
|
+
});
|
|
36
|
+
it('Should allow to serialize and deserialize a command', async () => {
|
|
37
|
+
const command = new A_Command({});
|
|
38
|
+
|
|
39
|
+
await command.execute();
|
|
40
|
+
|
|
41
|
+
const serialized = command.toJSON();
|
|
42
|
+
expect(serialized).toBeDefined();
|
|
43
|
+
expect(serialized.aseid).toBe(command.aseid.toString());
|
|
44
|
+
expect(serialized.code).toBe(command.Code);
|
|
45
|
+
expect(serialized.status).toBe(command.Status);
|
|
46
|
+
expect(serialized.startedAt).toBe(command.StartedAt?.toISOString());
|
|
47
|
+
expect(serialized.duration).toBe(command.Duration);
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
const deserializedCommand = new A_Command(serialized);
|
|
51
|
+
expect(deserializedCommand).toBeInstanceOf(A_Command);
|
|
52
|
+
expect(deserializedCommand.aseid.toString()).toBe(command.aseid.toString());
|
|
53
|
+
expect(deserializedCommand.Code).toBe(command.Code);
|
|
54
|
+
expect(deserializedCommand.Status).toBe(command.Status);
|
|
55
|
+
expect(deserializedCommand.StartedAt?.toISOString()).toBe(command.StartedAt?.toISOString());
|
|
56
|
+
expect(deserializedCommand.Duration).toBe(command.Duration);
|
|
57
|
+
});
|
|
58
|
+
it('Should allow to execute a command with custom logic', async () => {
|
|
59
|
+
|
|
60
|
+
// 1) create a scope
|
|
61
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
62
|
+
// 2) create a new command
|
|
63
|
+
type resultType = { bar: string };
|
|
64
|
+
type invokeType = { foo: string };
|
|
65
|
+
class MyCommand extends A_Command<invokeType, resultType> { }
|
|
66
|
+
|
|
67
|
+
// 3) create a custom component with custom logic
|
|
68
|
+
class MyComponent extends A_Component {
|
|
69
|
+
|
|
70
|
+
@A_Feature.Extend({ scope: [MyCommand] })
|
|
71
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
72
|
+
@A_Inject(A_CommandContext) context: A_CommandContext<resultType>
|
|
73
|
+
) {
|
|
74
|
+
context.save('bar', 'baz');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 4) register component in the scope
|
|
79
|
+
scope.register(MyComponent);
|
|
80
|
+
|
|
81
|
+
// 5) create a new command instance within the scope
|
|
82
|
+
const command = new MyCommand({ foo: 'bar' });
|
|
83
|
+
scope.register(command);
|
|
84
|
+
|
|
85
|
+
// 6) execute the command
|
|
86
|
+
await command.execute();
|
|
87
|
+
|
|
88
|
+
// 7) verify that command was executed with custom logic from MyComponent
|
|
89
|
+
expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.COMPLETED);
|
|
90
|
+
expect(command.Result).toBeDefined();
|
|
91
|
+
expect(command.Result).toEqual({ bar: 'baz' });
|
|
92
|
+
})
|
|
93
|
+
it('Should allow to fail a command with custom logic', async () => {
|
|
94
|
+
|
|
95
|
+
// 1) create a scope
|
|
96
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
97
|
+
// 2) create a new command
|
|
98
|
+
type resultType = { bar: string };
|
|
99
|
+
type invokeType = { foo: string };
|
|
100
|
+
class MyCommand extends A_Command<invokeType, resultType> { }
|
|
101
|
+
|
|
102
|
+
// 3) create a custom component with custom logic
|
|
103
|
+
class MyComponent extends A_Component {
|
|
104
|
+
|
|
105
|
+
@A_Feature.Extend({ scope: [MyCommand] })
|
|
106
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
107
|
+
@A_Inject(A_CommandContext) context: A_CommandContext<resultType>
|
|
108
|
+
) {
|
|
109
|
+
context.error(new A_Error({ message: 'Test error' }));
|
|
110
|
+
// it's optional to throw an error here, as the command may contain multiple errors that also can be a result of async operations
|
|
111
|
+
throw new A_Error({ message: 'Test error thrown' });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 4) register component in the scope
|
|
116
|
+
scope.register(MyComponent);
|
|
117
|
+
// 5) create a new command instance within the scope
|
|
118
|
+
const command = new MyCommand({ foo: 'bar' });
|
|
119
|
+
scope.register(command);
|
|
120
|
+
|
|
121
|
+
// 6) execute the command
|
|
122
|
+
await command.execute();
|
|
123
|
+
|
|
124
|
+
// 7) verify that command was executed with custom logic from MyComponent
|
|
125
|
+
expect(command.Status).toBe(A_CONSTANTS__A_Command_Status.FAILED);
|
|
126
|
+
expect(command.Errors).toBeDefined();
|
|
127
|
+
expect(command.Errors?.size).toBe(1);
|
|
128
|
+
expect(Array.from(command.Errors?.values() || [])[0].message).toBe('Test error');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
|
|
2
|
+
|
|
3
|
+
jest.retryTimes(0);
|
|
4
|
+
|
|
5
|
+
describe('A-Component tests', () => {
|
|
6
|
+
|
|
7
|
+
it('Should Allow to create a component', async () => {
|
|
8
|
+
const component = new A_Component();
|
|
9
|
+
});
|
|
10
|
+
it('Should Allow to create a component with dependencies', async () => {
|
|
11
|
+
class DependentComponent extends A_Component {
|
|
12
|
+
constructor(
|
|
13
|
+
public dependency: A_Component
|
|
14
|
+
) {
|
|
15
|
+
super();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const component = new A_Component();
|
|
20
|
+
const dependentComponent = new DependentComponent(component);
|
|
21
|
+
expect(dependentComponent.dependency).toBe(component);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { A_ConfigLoader } from "@adaas/a-concept/base/A-Config/A-Config.container";
|
|
2
|
+
import { A_Config } from "@adaas/a-concept/base/A-Config/A-Config.context";
|
|
3
|
+
import { ENVConfigReader } from "@adaas/a-concept/base/A-Config/components/ENVConfigReader.component";
|
|
4
|
+
import { A_CONSTANTS__DEFAULT_ENV_VARIABLES } from "@adaas/a-concept/constants/env.constants";
|
|
5
|
+
import { A_Context } from "@adaas/a-concept/global/A-Context/A-Context.class";
|
|
6
|
+
import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
|
|
7
|
+
|
|
8
|
+
jest.retryTimes(0);
|
|
9
|
+
|
|
10
|
+
describe('A-Config tests', () => {
|
|
11
|
+
it('Should Allow to create a config object', async () => {
|
|
12
|
+
const config = new A_Config({
|
|
13
|
+
variables: [],
|
|
14
|
+
defaults: {}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
it('Should Allow to create a config object with default values', async () => {
|
|
18
|
+
const config = new A_Config({
|
|
19
|
+
variables: ['TEST_VAR1', 'TEST_VAR2'] as const,
|
|
20
|
+
defaults: {
|
|
21
|
+
TEST_VAR1: 'default1',
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
expect(config.get('TEST_VAR1')).toBe('default1');
|
|
26
|
+
expect(config.get('TEST_VAR2')).toBeUndefined();
|
|
27
|
+
});
|
|
28
|
+
it('Should Allow to create a config object with ENV values', async () => {
|
|
29
|
+
process.env['A_CONCEPT_TEST_VAR1'] = 'env1';
|
|
30
|
+
process.env['A_CONCEPT_TEST_VAR2'] = 'env2';
|
|
31
|
+
|
|
32
|
+
const config = new A_Config({
|
|
33
|
+
variables: ['TEST_VAR1', 'TEST_VAR2'] as const,
|
|
34
|
+
defaults: {
|
|
35
|
+
TEST_VAR1: 'default1',
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const configLoader = new A_ConfigLoader({
|
|
40
|
+
name: 'test-config-loader',
|
|
41
|
+
fragments: [config],
|
|
42
|
+
components: [ENVConfigReader]
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
await configLoader.prepare(config as any);
|
|
46
|
+
await configLoader.readVariables(config as any);
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
expect(config.get('TEST_VAR1')).toBe('env1');
|
|
51
|
+
expect(config.get('TEST_VAR2')).toBe('env2');
|
|
52
|
+
|
|
53
|
+
delete process.env['A_CONCEPT_TEST_VAR1'];
|
|
54
|
+
delete process.env['A_CONCEPT_TEST_VAR2'];
|
|
55
|
+
});
|
|
56
|
+
it('Should not Change Names of default env variables', async () => {
|
|
57
|
+
process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAMESPACE] = 'my-project';
|
|
58
|
+
process.env['MY_PROJECT_TEST_VAR2'] = 'env2';
|
|
59
|
+
|
|
60
|
+
A_Context.reset();
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
const config = new A_Config({
|
|
64
|
+
variables: ['TEST_VAR1', 'TEST_VAR2'] as const,
|
|
65
|
+
defaults: {
|
|
66
|
+
TEST_VAR1: 'default1',
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const configLoader = new A_ConfigLoader({
|
|
71
|
+
name: 'test-config-loader',
|
|
72
|
+
fragments: [config],
|
|
73
|
+
components: [ENVConfigReader]
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
await configLoader.prepare(config as any);
|
|
78
|
+
await configLoader.readVariables(config as any);
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
expect(config.get('TEST_VAR1')).toBe('default1');
|
|
82
|
+
expect(config.get('TEST_VAR2')).toBe('env2');
|
|
83
|
+
expect(config.get('A_CONCEPT_NAMESPACE')).toBe('my-project');
|
|
84
|
+
|
|
85
|
+
delete process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAMESPACE];
|
|
86
|
+
delete process.env['TEST_VAR2'];
|
|
87
|
+
|
|
88
|
+
// then reset context root
|
|
89
|
+
A_Context.reset();
|
|
90
|
+
|
|
91
|
+
});
|
|
92
|
+
it('Should Throw an error if strict is true and variable is not defined', async () => {
|
|
93
|
+
expect(() => {
|
|
94
|
+
const config = new A_Config({
|
|
95
|
+
strict: true,
|
|
96
|
+
variables: ['TEST_VAR1', 'TEST_VAR2'] as const,
|
|
97
|
+
defaults: {
|
|
98
|
+
TEST_VAR1: 'default1',
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
config.get('TEST_VAR3' as any);
|
|
103
|
+
|
|
104
|
+
}).toThrowError();
|
|
105
|
+
});
|
|
106
|
+
});
|