@adaas/a-concept 0.0.55 → 0.0.57
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.context.d.ts +7 -6
- package/dist/src/base/A-Config/A-Config.context.js +2 -6
- package/dist/src/base/A-Config/A-Config.context.js.map +1 -1
- package/dist/src/base/A-Config/components/ConfigReader.component.js +2 -12
- package/dist/src/base/A-Config/components/ConfigReader.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 +19 -1
- package/dist/src/global/A-Context/A-Context.class.js +20 -0
- 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 -21
- 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.context.ts +13 -17
- package/src/base/A-Config/components/ConfigReader.component.ts +2 -15
- package/src/constants/env.constants.ts +47 -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 +44 -7
- package/src/global/A-Entity/A-Entity.class.ts +203 -73
- package/src/global/A-Scope/A-Scope.class.ts +86 -43
- 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-Entity.test.ts +186 -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
|
@@ -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,186 @@
|
|
|
1
|
+
import { A_CONSTANTS__DEFAULT_ENV_VARIABLES } from "@adaas/a-concept/constants/env.constants";
|
|
2
|
+
import { A_Entity } from "@adaas/a-concept/global/A-Entity/A-Entity.class";
|
|
3
|
+
import { A_TYPES__Entity_JSON } from "@adaas/a-concept/global/A-Entity/A-Entity.types";
|
|
4
|
+
import { A_Feature } from "@adaas/a-concept/global/A-Feature/A-Feature.class";
|
|
5
|
+
import { ASEID } from "@adaas/a-utils";
|
|
6
|
+
|
|
7
|
+
jest.retryTimes(0);
|
|
8
|
+
|
|
9
|
+
describe('A-Entity tests', () => {
|
|
10
|
+
it('Should Allow to create an entity from undefined', async () => {
|
|
11
|
+
const entity = new A_Entity();
|
|
12
|
+
});
|
|
13
|
+
it('Should Allow to create an entity with Default ASEID', async () => {
|
|
14
|
+
const entity = new A_Entity();
|
|
15
|
+
|
|
16
|
+
expect(entity.aseid).toBeInstanceOf(ASEID);
|
|
17
|
+
expect(entity.aseid.scope).toBe('core');
|
|
18
|
+
expect(entity.aseid.namespace).toBe('a-concept');
|
|
19
|
+
|
|
20
|
+
});
|
|
21
|
+
it('Should Allow to create an entity with overridden ASEID Scope or Namespace', async () => {
|
|
22
|
+
class MyEntity extends A_Entity {
|
|
23
|
+
static get entity(): string {
|
|
24
|
+
return 'my-entity-test';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static get scope(): string {
|
|
28
|
+
return 'custom-scope';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static get namespace(): string {
|
|
32
|
+
return 'custom-namespace';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const entity = new MyEntity();
|
|
37
|
+
|
|
38
|
+
expect(entity.aseid).toBeInstanceOf(ASEID);
|
|
39
|
+
expect(entity.aseid.scope).toBe('custom-scope');
|
|
40
|
+
expect(entity.aseid.namespace).toBe('custom-namespace');
|
|
41
|
+
expect(entity.aseid.entity).toBe('my-entity-test');
|
|
42
|
+
|
|
43
|
+
});
|
|
44
|
+
it('Should Allow to create an entity with overridden ASEID Scope or Namespace from ENV Variables', async () => {
|
|
45
|
+
process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_DEFAULT_SCOPE] = 'env-scope';
|
|
46
|
+
process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAMESPACE] = 'env-namespace';
|
|
47
|
+
|
|
48
|
+
const entity = new A_Entity();
|
|
49
|
+
|
|
50
|
+
expect(entity.aseid).toBeInstanceOf(ASEID);
|
|
51
|
+
expect(entity.aseid.scope).toBe('env-scope');
|
|
52
|
+
expect(entity.aseid.namespace).toBe('env-namespace');
|
|
53
|
+
|
|
54
|
+
delete process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_DEFAULT_SCOPE];
|
|
55
|
+
delete process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAMESPACE];
|
|
56
|
+
});
|
|
57
|
+
it('Should Allow to create an entity from ASEID', async () => {
|
|
58
|
+
const entity = new A_Entity(
|
|
59
|
+
new ASEID({
|
|
60
|
+
namespace: 'default',
|
|
61
|
+
scope: 'default',
|
|
62
|
+
entity: 'entity-a',
|
|
63
|
+
id: Math.floor(Math.random() * 1000000000).toString(),
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
it('Should Allow to create an entity from string', async () => {
|
|
68
|
+
const entity = new A_Entity('default@default:entity-a:123456789');
|
|
69
|
+
|
|
70
|
+
expect(entity.aseid.toString()).toBe('default@default:entity-a:123456789');
|
|
71
|
+
expect(entity.aseid.id).toBe('123456789');
|
|
72
|
+
});
|
|
73
|
+
it('Should Allow to create an entity from object', async () => {
|
|
74
|
+
|
|
75
|
+
class MyEntity extends A_Entity<{ foo: string }, { foo: string } & A_TYPES__Entity_JSON> {
|
|
76
|
+
foo!: string;
|
|
77
|
+
|
|
78
|
+
fromNew(newEntity: { foo: string; }): void {
|
|
79
|
+
super.fromNew(newEntity);
|
|
80
|
+
this.aseid = new ASEID({
|
|
81
|
+
namespace: 'default',
|
|
82
|
+
scope: 'default',
|
|
83
|
+
entity: 'entity-a',
|
|
84
|
+
id: Math.floor(Math.random() * 1000000000).toString(),
|
|
85
|
+
});
|
|
86
|
+
this.foo = newEntity.foo;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const entity = new MyEntity({ foo: 'bar' });
|
|
91
|
+
|
|
92
|
+
expect(entity.foo).toBe('bar');
|
|
93
|
+
});
|
|
94
|
+
it('Should return an error when creating an entity from invalid string', async () => {
|
|
95
|
+
expect(() => {
|
|
96
|
+
const entity = new A_Entity('invalid-string');
|
|
97
|
+
}).toThrowError();
|
|
98
|
+
});
|
|
99
|
+
it('Should Allow to rewrite initializer method without changes to other methods', async () => {
|
|
100
|
+
|
|
101
|
+
class MyEntity extends A_Entity<{ foo: string }, { foo: string } & A_TYPES__Entity_JSON> {
|
|
102
|
+
foo!: string;
|
|
103
|
+
|
|
104
|
+
protected getInitializer(props?: string | { foo: string; } | ({ foo: string; } & A_TYPES__Entity_JSON) | ASEID | undefined): (props: any) => void | (() => void) {
|
|
105
|
+
if (typeof props === 'object' && props !== null && 'foo' in props) {
|
|
106
|
+
return this.fromFoo.bind(this);
|
|
107
|
+
}
|
|
108
|
+
return super.getInitializer(props);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
fromFoo(props: { foo: string; }): void {
|
|
113
|
+
this.foo = props.foo;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
fromNew(newEntity: { foo: string; }): void {
|
|
117
|
+
super.fromNew(newEntity);
|
|
118
|
+
this.aseid = new ASEID({
|
|
119
|
+
namespace: 'default',
|
|
120
|
+
scope: 'default',
|
|
121
|
+
entity: 'entity-a',
|
|
122
|
+
id: Math.floor(Math.random() * 1000000000).toString(),
|
|
123
|
+
});
|
|
124
|
+
this.foo = 'not a bar';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const entity = new MyEntity({ foo: 'bar' });
|
|
129
|
+
|
|
130
|
+
expect(entity.foo).toBe('bar');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('Should allow to define a feature on an entity', async () => {
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class MyEntity extends A_Entity {
|
|
137
|
+
public foo!: string;
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@A_Feature.Define()
|
|
141
|
+
async doSomething() { }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
});
|
|
145
|
+
it('Should allow to serialize and deserialize an entity', async () => {
|
|
146
|
+
|
|
147
|
+
class MyEntity extends A_Entity<{ foo: string }, { foo: string } & A_TYPES__Entity_JSON> {
|
|
148
|
+
public foo!: string;
|
|
149
|
+
|
|
150
|
+
fromNew(newEntity: { foo: string; }): void {
|
|
151
|
+
this.aseid = new ASEID({
|
|
152
|
+
namespace: 'default',
|
|
153
|
+
scope: 'default',
|
|
154
|
+
entity: 'entity-a',
|
|
155
|
+
id: Math.floor(Math.random() * 1000000000).toString(),
|
|
156
|
+
});
|
|
157
|
+
this.foo = newEntity.foo;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
fromJSON(serialized: { foo: string; } & A_TYPES__Entity_JSON): void {
|
|
161
|
+
this.aseid = new ASEID(serialized.aseid);
|
|
162
|
+
this.foo = serialized.foo;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
toJSON(): { foo: string } & A_TYPES__Entity_JSON {
|
|
167
|
+
return {
|
|
168
|
+
...super.toJSON(),
|
|
169
|
+
foo: this.foo,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const entity = new MyEntity({ foo: 'baz' });
|
|
175
|
+
const aseid = entity.aseid.toString();
|
|
176
|
+
|
|
177
|
+
const serialized = entity.toJSON();
|
|
178
|
+
expect(serialized.foo).toBe('baz');
|
|
179
|
+
|
|
180
|
+
const entity2 = new MyEntity(serialized);
|
|
181
|
+
expect(entity2.foo).toBe('baz');
|
|
182
|
+
expect(entity2.aseid.toString()).toBe(aseid);
|
|
183
|
+
expect(entity2.aseid.toString()).toBe(entity.aseid.toString());
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
});
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { A_Inject } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator";
|
|
2
|
+
import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
|
|
3
|
+
import { A_Feature } from "@adaas/a-concept/global/A-Feature/A-Feature.class";
|
|
4
|
+
import { A_FeatureCaller } from "@adaas/a-concept/global/A-Feature/A-FeatureCaller.class";
|
|
5
|
+
import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
|
|
6
|
+
|
|
7
|
+
jest.retryTimes(0);
|
|
8
|
+
|
|
9
|
+
describe('A-Feature tests', () => {
|
|
10
|
+
it('Should Allow to create a feature from undefined', async () => {
|
|
11
|
+
const feature = new A_Feature({
|
|
12
|
+
name: 'TestFeature',
|
|
13
|
+
scope: new A_Scope({ name: 'TestScope' }),
|
|
14
|
+
steps: [],
|
|
15
|
+
caller: new A_Component()
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
it('Should Allow to create a feature with steps', async () => {
|
|
19
|
+
const feature = new A_Feature({
|
|
20
|
+
name: 'TestFeature',
|
|
21
|
+
scope: new A_Scope({ name: 'TestScope' }),
|
|
22
|
+
steps: [
|
|
23
|
+
{
|
|
24
|
+
name: 'A_Component.testHandler',
|
|
25
|
+
component: A_Component,
|
|
26
|
+
handler: 'testHandler',
|
|
27
|
+
behavior: 'sync',
|
|
28
|
+
before: [],
|
|
29
|
+
after: []
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
caller: new A_Component()
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it('Should be possible to execute a feature with steps as a template on the component', async () => {
|
|
36
|
+
// 1) create a base component with some feature
|
|
37
|
+
class MyExtendedComponent extends A_Component {
|
|
38
|
+
|
|
39
|
+
async testHandler(
|
|
40
|
+
@A_Inject(A_FeatureCaller) caller: MyComponent
|
|
41
|
+
) {
|
|
42
|
+
caller.sum = 2;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 2) create a custom component with a defined template feature
|
|
47
|
+
class MyComponent extends A_Component {
|
|
48
|
+
sum: number = 0;
|
|
49
|
+
|
|
50
|
+
@A_Feature.Define({
|
|
51
|
+
invoke: true,
|
|
52
|
+
template: [{
|
|
53
|
+
name: 'MyExtendedComponent.testHandler',
|
|
54
|
+
component: MyExtendedComponent,
|
|
55
|
+
handler: 'testHandler',
|
|
56
|
+
behavior: 'sync',
|
|
57
|
+
before: [],
|
|
58
|
+
after: []
|
|
59
|
+
}]
|
|
60
|
+
})
|
|
61
|
+
async testHandler() { }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
// 3) create a running scope
|
|
66
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
67
|
+
scope.register(MyExtendedComponent);
|
|
68
|
+
scope.register(MyComponent);
|
|
69
|
+
|
|
70
|
+
// 4) create an instance of the component from the scope
|
|
71
|
+
const myComponent = scope.resolve(MyComponent);
|
|
72
|
+
expect(myComponent).toBeInstanceOf(MyComponent);
|
|
73
|
+
expect(myComponent.sum).toBe(0);
|
|
74
|
+
|
|
75
|
+
// 5) call the feature caller to execute the feature
|
|
76
|
+
await myComponent.testHandler();
|
|
77
|
+
|
|
78
|
+
// 6) check the results
|
|
79
|
+
expect(myComponent.sum).toBe(2);
|
|
80
|
+
|
|
81
|
+
});
|
|
82
|
+
it('Should be possible to execute a feature with steps as a template on the component with string component declaration', async () => {
|
|
83
|
+
// 1) create a base component with some feature
|
|
84
|
+
class MyExtendedComponent2 extends A_Component {
|
|
85
|
+
|
|
86
|
+
async testHandler(
|
|
87
|
+
@A_Inject(A_FeatureCaller) caller: MyComponent2
|
|
88
|
+
) {
|
|
89
|
+
caller.sum = 2;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 2) create a custom component with a defined template feature
|
|
94
|
+
class MyComponent2 extends A_Component {
|
|
95
|
+
sum: number = 0;
|
|
96
|
+
|
|
97
|
+
@A_Feature.Define({
|
|
98
|
+
invoke: true,
|
|
99
|
+
template: [{
|
|
100
|
+
name: 'MyExtendedComponent2.testHandler',
|
|
101
|
+
component: 'MyExtendedComponent2',
|
|
102
|
+
handler: 'testHandler',
|
|
103
|
+
behavior: 'sync',
|
|
104
|
+
before: [],
|
|
105
|
+
after: []
|
|
106
|
+
}]
|
|
107
|
+
})
|
|
108
|
+
async testHandler() { }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
// 3) create a running scope
|
|
113
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
114
|
+
scope.register(MyExtendedComponent2);
|
|
115
|
+
scope.register(MyComponent2);
|
|
116
|
+
|
|
117
|
+
// 4) create an instance of the component from the scope
|
|
118
|
+
const myComponent = scope.resolve(MyComponent2);
|
|
119
|
+
expect(myComponent).toBeInstanceOf(MyComponent2);
|
|
120
|
+
expect(myComponent.sum).toBe(0);
|
|
121
|
+
|
|
122
|
+
// 5) call the feature caller to execute the feature
|
|
123
|
+
await myComponent.testHandler();
|
|
124
|
+
|
|
125
|
+
// 6) check the results
|
|
126
|
+
expect(myComponent.sum).toBe(2);
|
|
127
|
+
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
});
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
|
|
2
|
+
import { A_Entity } from "@adaas/a-concept/global/A-Entity/A-Entity.class";
|
|
3
|
+
import { A_Scope } from "@adaas/a-concept/global/A-Scope/A-Scope.class";
|
|
4
|
+
import { ASEID } from "@adaas/a-utils";
|
|
5
|
+
|
|
6
|
+
jest.retryTimes(0);
|
|
7
|
+
|
|
8
|
+
describe('A-Scope tests', () => {
|
|
9
|
+
|
|
10
|
+
it('Should Allow to create a scope', async () => {
|
|
11
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
12
|
+
});
|
|
13
|
+
it('Should allow to register a component', async () => {
|
|
14
|
+
const component = new A_Component();
|
|
15
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
16
|
+
scope.register(component);
|
|
17
|
+
|
|
18
|
+
});
|
|
19
|
+
it('Should allow to resolve a component', async () => {
|
|
20
|
+
const component = new A_Component();
|
|
21
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
22
|
+
scope.register(component);
|
|
23
|
+
|
|
24
|
+
const resolved = scope.resolve(A_Component);
|
|
25
|
+
expect(resolved).toBe(component);
|
|
26
|
+
});
|
|
27
|
+
it('Should return an error when resolving a non-registered component', async () => {
|
|
28
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
29
|
+
expect(() => scope.resolve(A_Component)).toThrowError();
|
|
30
|
+
});
|
|
31
|
+
it('Should allow to register and resolve a component with dependencies', async () => {
|
|
32
|
+
class DependentComponent extends A_Component {
|
|
33
|
+
constructor(
|
|
34
|
+
public dependency: A_Component
|
|
35
|
+
) {
|
|
36
|
+
super();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const component = new A_Component();
|
|
41
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
42
|
+
scope.register(component);
|
|
43
|
+
scope.register(new DependentComponent(component));
|
|
44
|
+
|
|
45
|
+
const resolved = scope.resolve(DependentComponent);
|
|
46
|
+
expect(resolved).toBeInstanceOf(DependentComponent);
|
|
47
|
+
expect(resolved.dependency).toBe(component);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should resolve component registered in parent scope', async () => {
|
|
51
|
+
const parentScope = new A_Scope({ name: 'ParentScope' });
|
|
52
|
+
const childScope = new A_Scope({ name: 'ChildScope'});
|
|
53
|
+
|
|
54
|
+
childScope.parent(parentScope);
|
|
55
|
+
|
|
56
|
+
const component = new A_Component();
|
|
57
|
+
parentScope.register(component);
|
|
58
|
+
|
|
59
|
+
const resolved = childScope.resolve(A_Component);
|
|
60
|
+
expect(resolved).toBe(component);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('Should resolve only one entity if no query is provided', async () => {
|
|
64
|
+
class MyEntity extends A_Entity<{ bar: string }> {
|
|
65
|
+
public bar!: string;
|
|
66
|
+
fromNew(newEntity: { bar: string; }): void {
|
|
67
|
+
this.aseid = new ASEID({
|
|
68
|
+
namespace: 'default',
|
|
69
|
+
scope: 'default',
|
|
70
|
+
entity: 'entity-a',
|
|
71
|
+
id: Math.floor(Math.random() * 1000000000).toString(),
|
|
72
|
+
})
|
|
73
|
+
this.bar = newEntity.bar;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
79
|
+
const entity1 = new MyEntity({ bar: 'bar' });
|
|
80
|
+
const entity2 = new MyEntity({ bar: 'baz' });
|
|
81
|
+
scope.register(entity1);
|
|
82
|
+
scope.register(entity2);
|
|
83
|
+
const resolved = scope.resolve(MyEntity);
|
|
84
|
+
expect(resolved).toBe(entity1);
|
|
85
|
+
|
|
86
|
+
});
|
|
87
|
+
it('Should resolve entities based on a query', async () => {
|
|
88
|
+
class MyEntity extends A_Entity<{ bar: string }> {
|
|
89
|
+
public bar!: string;
|
|
90
|
+
fromNew(newEntity: { bar: string; }): void {
|
|
91
|
+
this.aseid = new ASEID({
|
|
92
|
+
namespace: 'default',
|
|
93
|
+
scope: 'default',
|
|
94
|
+
entity: 'entity-a',
|
|
95
|
+
id: Math.floor(Math.random() * 1000000000).toString(),
|
|
96
|
+
})
|
|
97
|
+
this.bar = newEntity.bar;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
102
|
+
const entity1 = new MyEntity({ bar: 'bar' });
|
|
103
|
+
const entity2 = new MyEntity({ bar: 'baz' });
|
|
104
|
+
scope.register(entity1);
|
|
105
|
+
scope.register(entity2);
|
|
106
|
+
const resolved = scope.resolve(MyEntity, { query: { bar: 'baz' } });
|
|
107
|
+
expect(resolved).toBe(entity2);
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
});
|
|
111
|
+
it('Should return array if pagination.count is provided', async () => {
|
|
112
|
+
class MyEntity extends A_Entity<{ foo: string }> {
|
|
113
|
+
public foo!: string;
|
|
114
|
+
fromNew(newEntity: { foo: string; }): void {
|
|
115
|
+
this.aseid = new ASEID({
|
|
116
|
+
namespace: 'default',
|
|
117
|
+
scope: 'default',
|
|
118
|
+
entity: 'entity-a',
|
|
119
|
+
id: Math.floor(Math.random() * 1000000000).toString(),
|
|
120
|
+
})
|
|
121
|
+
this.foo = newEntity.foo;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
125
|
+
for (let i = 0; i < 10; i++) {
|
|
126
|
+
const entity = new MyEntity({ foo: 'bar' });
|
|
127
|
+
scope.register(entity);
|
|
128
|
+
}
|
|
129
|
+
const resolved = scope.resolve(MyEntity, { pagination: { count: 10 } });
|
|
130
|
+
expect(Array.isArray(resolved)).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
it('Should return array with pagination.count and provided filter', async () => {
|
|
133
|
+
class MyEntity extends A_Entity<{ foo: string }> {
|
|
134
|
+
public foo!: string;
|
|
135
|
+
fromNew(newEntity: { foo: string; }): void {
|
|
136
|
+
this.aseid = new ASEID({
|
|
137
|
+
namespace: 'default',
|
|
138
|
+
scope: 'default',
|
|
139
|
+
entity: 'entity-a',
|
|
140
|
+
id: Math.floor(Math.random() * 1000000000).toString(),
|
|
141
|
+
})
|
|
142
|
+
this.foo = newEntity.foo;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const scope = new A_Scope({ name: 'TestScope' });
|
|
146
|
+
for (let i = 0; i < 5; i++) {
|
|
147
|
+
const entity = new MyEntity({ foo: 'bar' });
|
|
148
|
+
scope.register(entity);
|
|
149
|
+
}
|
|
150
|
+
for (let i = 0; i < 5; i++) {
|
|
151
|
+
const entity = new MyEntity({ foo: 'baz' });
|
|
152
|
+
scope.register(entity);
|
|
153
|
+
}
|
|
154
|
+
const resolved = scope.resolve(MyEntity, { query: { foo: 'baz' }, pagination: { count: 10 } });
|
|
155
|
+
expect(Array.isArray(resolved)).toBe(true);
|
|
156
|
+
expect((resolved as Array<MyEntity>).length).toBe(5);
|
|
157
|
+
(resolved as Array<MyEntity>).forEach(r => {
|
|
158
|
+
expect(r.foo).toBe('baz');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// import { A_TYPES__ConceptLifecycle_MethodDeclarationConfig } from "../decorators/A-ConceptLifecycle/A-ConceptLifecycle.decorator.types";
|
|
3
|
-
// export const A_CONSTANTS__DEFAULT_CONCEPT_LIFECYCLE_METHOD_DECLARATION_CONFIG: A_TYPES__ConceptLifecycle_MethodDeclarationConfig = {
|
|
4
|
-
// name: '',
|
|
5
|
-
// behavior: 'sync',
|
|
6
|
-
// type: 'extension',
|
|
7
|
-
// after: [],
|
|
8
|
-
// before: [],
|
|
9
|
-
// override: []
|
|
10
|
-
// }
|
|
11
|
-
//# sourceMappingURL=A_ConceptLifecycle.constants.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"A_ConceptLifecycle.constants.js","sourceRoot":"","sources":["../../../src/constants/A_ConceptLifecycle.constants.ts"],"names":[],"mappings":";AAAA,2IAA2I;AAI3I,uIAAuI;AACvI,gBAAgB;AAChB,wBAAwB;AACxB,yBAAyB;AACzB,iBAAiB;AACjB,kBAAkB;AAClB,mBAAmB;AACnB,KAAK"}
|