@adaas/a-concept 0.1.11 → 0.1.12
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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.A_TmpStage = exports.A_StepsManager = void 0;
|
|
4
|
+
const A_Error_class_1 = require("../global/A-Error/A_Error.class");
|
|
4
5
|
const A_Stage_class_1 = require("../global/A-Stage/A-Stage.class");
|
|
5
6
|
class A_StepsManager {
|
|
6
7
|
constructor(entities) {
|
|
@@ -23,23 +24,28 @@ class A_StepsManager {
|
|
|
23
24
|
this.entities.forEach(entity => this.graph.set(this.ID(entity), new Set()));
|
|
24
25
|
// Add directed edges based on 'before' and 'after'
|
|
25
26
|
this.entities.forEach(entity => {
|
|
26
|
-
const
|
|
27
|
+
const entityId = this.ID(entity);
|
|
28
|
+
const { before = [], after = [] } = entity;
|
|
27
29
|
// Add edges for 'before' dependencies
|
|
30
|
+
// If entity should execute before targets, then targets depend on entity
|
|
31
|
+
// So we add edges: target -> entity (target depends on entity)
|
|
28
32
|
before.forEach(dep => {
|
|
29
33
|
const targets = this.matchEntities(dep);
|
|
30
34
|
targets.forEach(target => {
|
|
31
35
|
if (!this.graph.has(target))
|
|
32
36
|
this.graph.set(target, new Set());
|
|
33
|
-
this.graph.get(target).add(
|
|
37
|
+
this.graph.get(target).add(entityId); // target depends on entity
|
|
34
38
|
});
|
|
35
39
|
});
|
|
36
|
-
// Add edges for 'after' dependencies
|
|
40
|
+
// Add edges for 'after' dependencies
|
|
41
|
+
// If entity should execute after sources, then entity depends on sources
|
|
42
|
+
// So we add edges: entity -> source (entity depends on source)
|
|
37
43
|
after.forEach(dep => {
|
|
38
44
|
const sources = this.matchEntities(dep);
|
|
39
45
|
sources.forEach(source => {
|
|
40
|
-
if (!this.graph.has(
|
|
41
|
-
this.graph.set(
|
|
42
|
-
this.graph.get(
|
|
46
|
+
if (!this.graph.has(entityId))
|
|
47
|
+
this.graph.set(entityId, new Set());
|
|
48
|
+
this.graph.get(entityId).add(source); // entity depends on source
|
|
43
49
|
});
|
|
44
50
|
});
|
|
45
51
|
});
|
|
@@ -54,7 +60,7 @@ class A_StepsManager {
|
|
|
54
60
|
// Topological sort with cycle detection
|
|
55
61
|
visit(node) {
|
|
56
62
|
if (this.tempMark.has(node))
|
|
57
|
-
throw new
|
|
63
|
+
throw new A_Error_class_1.A_Error("Circular dependency detected");
|
|
58
64
|
if (!this.visited.has(node)) {
|
|
59
65
|
this.tempMark.add(node);
|
|
60
66
|
(this.graph.get(node) || []).forEach(neighbor => this.visit(neighbor));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"A_StepsManager.class.js","sourceRoot":"","sources":["../../../src/helpers/A_StepsManager.class.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"A_StepsManager.class.js","sourceRoot":"","sources":["../../../src/helpers/A_StepsManager.class.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaas/a-concept",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
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
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"ext": "ts, js"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
-
"test": "jest
|
|
23
|
+
"test": "jest",
|
|
24
24
|
"start": "nodemon ./tests/log.ts",
|
|
25
25
|
"example:simple": "nodemon ./examples/simple/concept.ts",
|
|
26
26
|
"example:simple:trace": "node -r tsconfig-paths/register -r ts-node/register -r ./trace-require.js ./examples/simple/concept.ts",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { A_Error } from "../global/A-Error/A_Error.class";
|
|
1
2
|
import { A_Feature } from "../global/A-Feature/A-Feature.class";
|
|
2
3
|
import { A_TYPES__FeatureDefineDecoratorTemplateItem } from "../global/A-Feature/A-Feature.types";
|
|
3
4
|
import { A_Stage } from "../global/A-Stage/A-Stage.class";
|
|
@@ -46,30 +47,36 @@ export class A_StepsManager {
|
|
|
46
47
|
|
|
47
48
|
// Add directed edges based on 'before' and 'after'
|
|
48
49
|
this.entities.forEach(entity => {
|
|
49
|
-
const
|
|
50
|
+
const entityId = this.ID(entity);
|
|
51
|
+
const { before = [], after = [] } = entity;
|
|
50
52
|
|
|
51
53
|
// Add edges for 'before' dependencies
|
|
54
|
+
// If entity should execute before targets, then targets depend on entity
|
|
55
|
+
// So we add edges: target -> entity (target depends on entity)
|
|
52
56
|
before.forEach(dep => {
|
|
53
57
|
const targets = this.matchEntities(dep);
|
|
54
58
|
targets.forEach(target => {
|
|
55
59
|
if (!this.graph.has(target)) this.graph.set(target, new Set());
|
|
56
|
-
this.graph.get(target)!.add(
|
|
60
|
+
this.graph.get(target)!.add(entityId); // target depends on entity
|
|
57
61
|
});
|
|
58
62
|
});
|
|
59
63
|
|
|
60
|
-
// Add edges for 'after' dependencies
|
|
64
|
+
// Add edges for 'after' dependencies
|
|
65
|
+
// If entity should execute after sources, then entity depends on sources
|
|
66
|
+
// So we add edges: entity -> source (entity depends on source)
|
|
61
67
|
after.forEach(dep => {
|
|
62
68
|
const sources = this.matchEntities(dep);
|
|
69
|
+
|
|
63
70
|
sources.forEach(source => {
|
|
64
|
-
if (!this.graph.has(
|
|
65
|
-
this.graph.get(
|
|
71
|
+
if (!this.graph.has(entityId)) this.graph.set(entityId, new Set());
|
|
72
|
+
this.graph.get(entityId)!.add(source); // entity depends on source
|
|
66
73
|
});
|
|
67
74
|
});
|
|
68
75
|
});
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
// Match entities by name or regex
|
|
72
|
-
private matchEntities(pattern) {
|
|
79
|
+
private matchEntities(pattern: string): string[] {
|
|
73
80
|
const regex = new RegExp(`^${pattern}$`);
|
|
74
81
|
return this.entities
|
|
75
82
|
.filter(entity => regex.test(this.ID(entity)))
|
|
@@ -77,8 +84,8 @@ export class A_StepsManager {
|
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
// Topological sort with cycle detection
|
|
80
|
-
private visit(node) {
|
|
81
|
-
if (this.tempMark.has(node)) throw new
|
|
87
|
+
private visit(node: string): void {
|
|
88
|
+
if (this.tempMark.has(node)) throw new A_Error("Circular dependency detected");
|
|
82
89
|
|
|
83
90
|
if (!this.visited.has(node)) {
|
|
84
91
|
this.tempMark.add(node);
|
package/tests/A-Feature.test.ts
CHANGED
|
@@ -139,4 +139,93 @@ describe('A-Feature tests', () => {
|
|
|
139
139
|
expect(myComponent.sum).toBe(2);
|
|
140
140
|
|
|
141
141
|
});
|
|
142
|
+
it('Should execute feature steps in base order', async () => {
|
|
143
|
+
const executionOrder: string[] = [];
|
|
144
|
+
|
|
145
|
+
// 1) create a base component with some feature
|
|
146
|
+
class My_Component extends A_Component {
|
|
147
|
+
async methodA() {
|
|
148
|
+
await this.call('myFeature')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@A_Feature.Extend({
|
|
152
|
+
name: 'myFeature',
|
|
153
|
+
})
|
|
154
|
+
async stepOne(
|
|
155
|
+
) {
|
|
156
|
+
executionOrder.push('stepOne');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@A_Feature.Extend({
|
|
160
|
+
name: 'myFeature',
|
|
161
|
+
})
|
|
162
|
+
async stepTwo(
|
|
163
|
+
) {
|
|
164
|
+
executionOrder.push('stepTwo');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@A_Feature.Extend({
|
|
168
|
+
name: 'myFeature',
|
|
169
|
+
})
|
|
170
|
+
async stepThree(
|
|
171
|
+
) {
|
|
172
|
+
executionOrder.push('stepThree');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
// 2) create a running scope
|
|
178
|
+
const scope = new A_Scope({ name: 'TestScope', components: [My_Component] });
|
|
179
|
+
|
|
180
|
+
// 3) create an instance of the component from the scope
|
|
181
|
+
const myComponent = scope.resolve(My_Component);
|
|
182
|
+
expect(myComponent).toBeInstanceOf(My_Component);
|
|
183
|
+
|
|
184
|
+
// 4) call the feature caller to execute the feature
|
|
185
|
+
await myComponent.methodA();
|
|
186
|
+
|
|
187
|
+
// 5) check the results
|
|
188
|
+
expect(executionOrder).toEqual(['stepOne', 'stepTwo', 'stepThree']);
|
|
189
|
+
});
|
|
190
|
+
it('Should execute feature steps in proper order', async () => {
|
|
191
|
+
const executionOrder: string[] = [];
|
|
192
|
+
|
|
193
|
+
// 1) create a base component with some feature
|
|
194
|
+
class My_Component extends A_Component {
|
|
195
|
+
async methodA() {
|
|
196
|
+
await this.call('myFeature')
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@A_Feature.Extend({
|
|
200
|
+
name: 'myFeature',
|
|
201
|
+
after: ['My_Component.stepTwo'],
|
|
202
|
+
})
|
|
203
|
+
async stepOne(
|
|
204
|
+
) {
|
|
205
|
+
executionOrder.push('stepOne');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@A_Feature.Extend({
|
|
209
|
+
name: 'myFeature',
|
|
210
|
+
})
|
|
211
|
+
async stepTwo(
|
|
212
|
+
) {
|
|
213
|
+
executionOrder.push('stepTwo');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
// 2) create a running scope
|
|
219
|
+
const scope = new A_Scope({ name: 'TestScope', components: [My_Component] });
|
|
220
|
+
|
|
221
|
+
// 3) create an instance of the component from the scope
|
|
222
|
+
const myComponent = scope.resolve(My_Component);
|
|
223
|
+
expect(myComponent).toBeInstanceOf(My_Component);
|
|
224
|
+
|
|
225
|
+
// 4) call the feature caller to execute the feature
|
|
226
|
+
await myComponent.methodA();
|
|
227
|
+
|
|
228
|
+
// 5) check the results
|
|
229
|
+
expect(executionOrder).toEqual(['stepTwo', 'stepOne']);
|
|
230
|
+
});
|
|
142
231
|
});
|