@adaas/a-concept 0.0.29 → 0.0.31
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/examples/fe-be/channels/Test.channel.d.ts +6 -0
- package/dist/examples/fe-be/channels/Test.channel.js +14 -0
- package/dist/examples/fe-be/channels/Test.channel.js.map +1 -0
- package/dist/examples/fe-be/components/BE-Controller.component.d.ts +4 -0
- package/dist/examples/fe-be/components/BE-Controller.component.js +24 -0
- package/dist/examples/fe-be/components/BE-Controller.component.js.map +1 -0
- package/dist/examples/fe-be/components/FE.component.d.ts +4 -0
- package/dist/examples/fe-be/components/FE.component.js +31 -0
- package/dist/examples/fe-be/components/FE.component.js.map +1 -0
- package/dist/examples/fe-be/components/UserActions.component.d.ts +5 -0
- package/dist/examples/fe-be/components/UserActions.component.js +25 -0
- package/dist/examples/fe-be/components/UserActions.component.js.map +1 -0
- package/dist/examples/fe-be/concept.d.ts +0 -0
- package/dist/examples/fe-be/concept.js +2 -0
- package/dist/examples/fe-be/concept.js.map +1 -0
- package/dist/examples/fe-be/containers/ServerApp.container.d.ts +3 -0
- package/dist/examples/fe-be/containers/ServerApp.container.js +8 -0
- package/dist/examples/fe-be/containers/ServerApp.container.js.map +1 -0
- package/dist/examples/fe-be/containers/WebApp.container.d.ts +3 -0
- package/dist/examples/fe-be/containers/WebApp.container.js +8 -0
- package/dist/examples/fe-be/containers/WebApp.container.js.map +1 -0
- package/dist/examples/multi-container/channels/Direct.channel.d.ts +9 -0
- package/dist/examples/multi-container/channels/Direct.channel.js +32 -0
- package/dist/examples/multi-container/channels/Direct.channel.js.map +1 -0
- package/dist/examples/multi-container/concept.d.ts +0 -0
- package/dist/examples/multi-container/concept.js +2 -0
- package/dist/examples/multi-container/concept.js.map +1 -0
- package/dist/examples/multi-container/containers/Command.container.d.ts +11 -0
- package/dist/examples/multi-container/containers/Command.container.js +51 -0
- package/dist/examples/multi-container/containers/Command.container.js.map +1 -0
- package/dist/examples/multi-container/containers/Schedule.container.d.ts +15 -0
- package/dist/examples/multi-container/containers/Schedule.container.js +67 -0
- package/dist/examples/multi-container/containers/Schedule.container.js.map +1 -0
- package/dist/examples/simple/components/A.component.js.map +1 -1
- package/dist/examples/simple/containers/Main.container.js +7 -3
- package/dist/examples/simple/containers/Main.container.js.map +1 -1
- package/dist/examples/simple/entities/EntityA.entity.d.ts +8 -0
- package/dist/examples/simple/entities/EntityA.entity.js +22 -0
- package/dist/examples/simple/entities/EntityA.entity.js.map +1 -0
- package/dist/examples/simple-http-server/contexts/http-request.context.d.ts +0 -1
- package/dist/examples/simple-http-server/contexts/http-request.context.js +6 -8
- package/dist/examples/simple-http-server/contexts/http-request.context.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +16 -7
- package/dist/index.js.map +1 -1
- package/dist/src/base/A-Errors/A-Error.entity.d.ts +3 -0
- package/dist/src/base/A-Errors/A-Error.entity.js +8 -0
- package/dist/src/base/A-Errors/A-Error.entity.js.map +1 -0
- package/dist/src/base/A-Errors/A-Errors.context.js +1 -1
- package/dist/src/base/A-Errors/A-Errors.context.js.map +1 -1
- package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.d.ts +14 -0
- package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.js +53 -0
- package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.js.map +1 -0
- package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.types.d.ts +2 -0
- package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.types.js +3 -0
- package/dist/src/decorators/A-Abstraction/A-Abstraction.decorator.types.js.map +1 -0
- package/dist/src/decorators/A-Connect/A-Connect.decorator.d.ts +19 -0
- package/dist/src/decorators/A-Connect/A-Connect.decorator.js +31 -0
- package/dist/src/decorators/A-Connect/A-Connect.decorator.js.map +1 -0
- package/dist/src/decorators/A-Connect/A-Connect.decorator.types.d.ts +1 -0
- package/dist/src/decorators/A-Connect/A-Connect.decorator.types.js +3 -0
- package/dist/src/decorators/A-Connect/A-Connect.decorator.types.js.map +1 -0
- package/dist/src/decorators/A-Entity/A-Entity-List.decorator.d.ts +1 -0
- package/dist/src/decorators/A-Entity/A-Entity-List.decorator.js +8 -0
- package/dist/src/decorators/A-Entity/A-Entity-List.decorator.js.map +1 -0
- package/dist/src/decorators/A-Entity/A-Entity.decorator.types.d.ts +14 -0
- package/dist/src/decorators/A-Entity/A-Entity.decorator.types.js +3 -0
- package/dist/src/decorators/A-Entity/A-Entity.decorator.types.js.map +1 -0
- package/dist/src/decorators/A-Feature/A-Feature-Define.decorator.js +7 -5
- package/dist/src/decorators/A-Feature/A-Feature-Define.decorator.js.map +1 -1
- package/dist/src/decorators/A-Feature/A-Feature-Extend.decorator.js +9 -0
- package/dist/src/decorators/A-Feature/A-Feature-Extend.decorator.js.map +1 -1
- package/dist/src/decorators/A-Feature/A-Feature.decorator.types.d.ts +36 -0
- package/dist/src/decorators/A-Inject/A-Inject.decorator.d.ts +2 -3
- package/dist/src/decorators/A-Inject/A-Inject.decorator.js.map +1 -1
- package/dist/src/decorators/A-Inject/A-Inject.decorator.types.d.ts +44 -0
- package/dist/src/global/A-Channel/A-Channel.class.d.ts +8 -10
- package/dist/src/global/A-Channel/A-Channel.class.js +12 -26
- package/dist/src/global/A-Channel/A-Channel.class.js.map +1 -1
- package/dist/src/global/A-Channel/A-Channel.types.d.ts +32 -0
- package/dist/src/global/A-Component/A-Component.class.d.ts +2 -1
- package/dist/src/global/A-Component/A-Component.class.js +1 -0
- package/dist/src/global/A-Component/A-Component.class.js.map +1 -1
- package/dist/src/global/A-Component/A-Component.meta.d.ts +16 -0
- package/dist/src/global/A-Component/A-Component.meta.js +37 -3
- package/dist/src/global/A-Component/A-Component.meta.js.map +1 -1
- package/dist/src/global/A-Component/A-Component.types.d.ts +26 -38
- package/dist/src/global/A-Component/A-Component.types.js +1 -7
- package/dist/src/global/A-Component/A-Component.types.js.map +1 -1
- package/dist/src/global/A-Concept/A_Concept.class.d.ts +7 -7
- package/dist/src/global/A-Concept/A_Concept.class.js +30 -30
- package/dist/src/global/A-Concept/A_Concept.class.js.map +1 -1
- package/dist/src/global/A-Concept/A_Concept.types.d.ts +42 -2
- package/dist/src/global/A-Concept/A_Concept.types.js.map +1 -1
- package/dist/src/global/A-Container/A-Container.class.d.ts +1 -8
- package/dist/src/global/A-Container/A-Container.class.js +1 -31
- package/dist/src/global/A-Container/A-Container.class.js.map +1 -1
- package/dist/src/global/A-Container/A-Container.meta.d.ts +8 -0
- package/dist/src/global/A-Container/A-Container.meta.js +29 -0
- package/dist/src/global/A-Container/A-Container.meta.js.map +1 -1
- package/dist/src/global/A-Container/A-Container.types.d.ts +32 -8
- package/dist/src/global/A-Container/A-Container.types.js +2 -1
- package/dist/src/global/A-Container/A-Container.types.js.map +1 -1
- package/dist/src/global/A-Context/A-Context.class.js +29 -36
- package/dist/src/global/A-Context/A-Context.class.js.map +1 -1
- package/dist/src/global/A-Entity/A-Entity.class.d.ts +1 -2
- package/dist/src/global/A-Entity/A-Entity.class.js +6 -7
- package/dist/src/global/A-Entity/A-Entity.class.js.map +1 -1
- package/dist/src/global/A-Entity/A-Entity.types.d.ts +12 -6
- package/dist/src/global/A-Entity/A-Entity.types.js.map +1 -1
- package/dist/src/global/A-Feature/A-Feature.class.d.ts +30 -6
- package/dist/src/global/A-Feature/A-Feature.class.js +49 -40
- package/dist/src/global/A-Feature/A-Feature.class.js.map +1 -1
- package/dist/src/global/A-Feature/A-Feature.types.d.ts +2 -24
- package/dist/src/global/A-Feature/A-Feature.types.js +21 -0
- package/dist/src/global/A-Feature/A-Feature.types.js.map +1 -1
- package/dist/src/global/A-Fragment/A-Fragment.class.d.ts +8 -0
- package/dist/src/global/A-Fragment/A-Fragment.class.js +10 -0
- package/dist/src/global/A-Fragment/A-Fragment.class.js.map +1 -1
- package/dist/src/global/A-Scope/A-Scope.class.d.ts +7 -5
- package/dist/src/global/A-Scope/A-Scope.class.js +33 -10
- package/dist/src/global/A-Scope/A-Scope.class.js.map +1 -1
- package/dist/src/global/A-Scope/A-Scope.types.d.ts +2 -1
- package/dist/src/global/A-Stage/A-Stage.class.d.ts +69 -0
- package/dist/src/global/A-Stage/A-Stage.class.js +181 -0
- package/dist/src/global/A-Stage/A-Stage.class.js.map +1 -0
- package/dist/src/global/A-Stage/A-Stage.types.d.ts +78 -0
- package/dist/src/global/A-Stage/A-Stage.types.js +59 -0
- package/dist/src/global/A-Stage/A-Stage.types.js.map +1 -0
- package/dist/src/helpers/StepsManager.class.d.ts +15 -0
- package/dist/src/helpers/StepsManager.class.js +85 -0
- package/dist/src/helpers/StepsManager.class.js.map +1 -0
- package/examples/fe-be/channels/Test.channel.ts +24 -0
- package/examples/fe-be/components/BE-Controller.component.ts +20 -0
- package/examples/fe-be/components/FE.component.ts +13 -0
- package/examples/fe-be/concept.ts +0 -0
- package/examples/fe-be/containers/ServerApp.container.ts +8 -0
- package/examples/fe-be/containers/WebApp.container.ts +13 -0
- package/examples/multi-container/channels/Direct.channel.ts +39 -0
- package/examples/multi-container/concept.ts +0 -0
- package/examples/multi-container/containers/Command.container.ts +41 -0
- package/examples/multi-container/containers/Schedule.container.ts +57 -0
- package/examples/simple/components/A.component.ts +2 -1
- package/examples/simple/containers/Main.container.ts +11 -3
- package/examples/simple/entities/EntityA.entity.ts +16 -0
- package/examples/simple-http-server/contexts/http-request.context.ts +6 -6
- package/index.ts +12 -3
- package/package.json +1 -1
- package/src/base/A-Errors/A-Error.entity.ts +10 -0
- package/src/base/A-Errors/A-Errors.context.ts +2 -2
- package/src/decorators/A-Abstraction/A-Abstraction.decorator.ts +82 -0
- package/src/decorators/{A-Stage/A-Stage.decorator.types.ts → A-Abstraction/A-Abstraction.decorator.types.ts} +1 -3
- package/src/decorators/A-Connect/A-Connect.decorator.ts +71 -0
- package/src/decorators/A-Connect/A-Connect.decorator.types.ts +6 -0
- package/src/decorators/A-Entity/A-Entity-List.decorator.ts +12 -0
- package/src/decorators/A-Entity/A-Entity.decorator.types.ts +18 -0
- package/src/decorators/A-Feature/A-Feature-Define.decorator.ts +16 -9
- package/src/decorators/A-Feature/A-Feature-Extend.decorator.ts +10 -2
- package/src/decorators/A-Feature/A-Feature.decorator.types.ts +46 -0
- package/src/decorators/A-Inject/A-Inject.decorator.ts +7 -7
- package/src/decorators/A-Inject/A-Inject.decorator.types.ts +47 -1
- package/src/global/A-Channel/A-Channel.class.ts +25 -28
- package/src/global/A-Channel/A-Channel.types.ts +53 -0
- package/src/global/A-Component/A-Component.class.ts +10 -2
- package/src/global/A-Component/A-Component.meta.ts +59 -6
- package/src/global/A-Component/A-Component.types.ts +28 -45
- package/src/global/A-Concept/A_Concept.class.ts +52 -31
- package/src/global/A-Concept/A_Concept.types.ts +48 -3
- package/src/global/A-Container/A-Container.class.ts +3 -39
- package/src/global/A-Container/A-Container.meta.ts +41 -4
- package/src/global/A-Container/A-Container.types.ts +36 -8
- package/src/global/A-Context/A-Context.class.ts +37 -50
- package/src/global/A-Entity/A-Entity.class.ts +8 -6
- package/src/global/A-Entity/A-Entity.types.ts +13 -6
- package/src/global/A-Feature/A-Feature.class.ts +73 -61
- package/src/global/A-Feature/A-Feature.types.ts +24 -23
- package/src/global/A-Fragment/A-Fragment.class.ts +15 -0
- package/src/global/A-Scope/A-Scope.class.ts +58 -25
- package/src/global/A-Scope/A-Scope.types.ts +2 -1
- package/src/global/A-Stage/A-Stage.class.ts +234 -0
- package/src/global/A-Stage/A-Stage.types.ts +101 -0
- package/src/helpers/StepsManager.class.ts +104 -0
- package/tests/channel.ts +213 -0
- package/tests/log.ts +88 -40
- package/src/decorators/A-Stage/A-Stage.decorator.ts +0 -84
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { A_CommonHelper, A_Error } from "@adaas/a-utils";
|
|
2
|
+
import { A_Context } from "../A-Context/A-Context.class";
|
|
3
|
+
import { A_Feature } from "../A-Feature/A-Feature.class";
|
|
4
|
+
import { A_TYPES__A_Stage_JSON, A_TYPES__A_Stage_Status, A_TYPES__A_StageStep } from "./A-Stage.types";
|
|
5
|
+
import { A_Container } from "../A-Container/A-Container.class";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A_Stage is a set of A_Functions within A_Feature that should be run in a specific order.
|
|
11
|
+
* Each stage may contain one or more functions.
|
|
12
|
+
* [!] That always run in parallel (in NodeJS asynchronously), independently of each other.
|
|
13
|
+
*
|
|
14
|
+
* A-Stage is a common object that uses to simplify logic and re-use of A-Feature internals for better composition.
|
|
15
|
+
*/
|
|
16
|
+
export class A_Stage {
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
private feature: A_Feature,
|
|
22
|
+
private steps: A_TYPES__A_StageStep[] = []
|
|
23
|
+
) {
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
status: A_TYPES__A_Stage_Status = A_TYPES__A_Stage_Status.INITIALIZED;
|
|
28
|
+
/**
|
|
29
|
+
* Promise that will be resolved when the stage is Processed
|
|
30
|
+
*/
|
|
31
|
+
processed: Promise<void> | undefined;
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
get before(): string[] {
|
|
35
|
+
return this.steps.reduce((acc, step) => ([
|
|
36
|
+
...acc,
|
|
37
|
+
...step.before
|
|
38
|
+
]), [] as string[]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get after(): string[] {
|
|
42
|
+
return this.steps.reduce((acc, step) => ([
|
|
43
|
+
...acc,
|
|
44
|
+
...step.after
|
|
45
|
+
]), [] as string[]);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Resolves the arguments of the step
|
|
51
|
+
*
|
|
52
|
+
* @param step
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
55
|
+
protected async getStepArgs(step: A_TYPES__A_StageStep) {
|
|
56
|
+
|
|
57
|
+
const target = step.component instanceof A_Container ?
|
|
58
|
+
step.component.constructor : step.component;
|
|
59
|
+
|
|
60
|
+
return A_Context
|
|
61
|
+
.meta(target)
|
|
62
|
+
.injections(
|
|
63
|
+
step.handler
|
|
64
|
+
)
|
|
65
|
+
.map(async arg =>
|
|
66
|
+
// In case if the target is a feature step then pass the current feature
|
|
67
|
+
A_CommonHelper.isInheritedFrom(arg.target, A_Feature)
|
|
68
|
+
? this
|
|
69
|
+
: A_Context.scope(this.feature).resolve(arg.target)
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Adds a step to the stage
|
|
76
|
+
*
|
|
77
|
+
* @param step
|
|
78
|
+
* @returns
|
|
79
|
+
*/
|
|
80
|
+
add(
|
|
81
|
+
step: A_TYPES__A_StageStep
|
|
82
|
+
): this {
|
|
83
|
+
this.steps.push(step);
|
|
84
|
+
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolves the component of the step
|
|
91
|
+
*
|
|
92
|
+
* @param step
|
|
93
|
+
* @returns
|
|
94
|
+
*/
|
|
95
|
+
protected getStepInstance(step: A_TYPES__A_StageStep) {
|
|
96
|
+
const { component, handler } = step;
|
|
97
|
+
|
|
98
|
+
// TODO: probably would be better to do it another way. let's think about it
|
|
99
|
+
const instance = component instanceof A_Container
|
|
100
|
+
? component
|
|
101
|
+
: A_Context.scope(this.feature).resolve(component);
|
|
102
|
+
|
|
103
|
+
if (!instance)
|
|
104
|
+
throw new Error(`Unable to resolve component ${component.name}`);
|
|
105
|
+
|
|
106
|
+
if (!instance[handler])
|
|
107
|
+
throw new Error(`Handler ${handler} not found in ${instance.constructor.name}`);
|
|
108
|
+
|
|
109
|
+
return instance;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Calls the handler of the step
|
|
116
|
+
*
|
|
117
|
+
* @param step
|
|
118
|
+
* @returns
|
|
119
|
+
*/
|
|
120
|
+
protected async getStepHandler(step: A_TYPES__A_StageStep) {
|
|
121
|
+
|
|
122
|
+
const instance = this.getStepInstance(step);
|
|
123
|
+
const callArgs = await this.getStepArgs(step);
|
|
124
|
+
|
|
125
|
+
return instance[step.handler](...callArgs);
|
|
126
|
+
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Runs async all the steps of the stage
|
|
132
|
+
*
|
|
133
|
+
* @returns
|
|
134
|
+
*/
|
|
135
|
+
async process(): Promise<void> {
|
|
136
|
+
if (!this.processed)
|
|
137
|
+
this.processed = new Promise<void>(
|
|
138
|
+
async (resolve, reject) => {
|
|
139
|
+
try {
|
|
140
|
+
this.status = A_TYPES__A_Stage_Status.PROCESSING;
|
|
141
|
+
|
|
142
|
+
const syncSteps = this.steps.filter(step => step.behavior === 'sync');
|
|
143
|
+
const asyncSteps = this.steps.filter(step => step.behavior === 'async');
|
|
144
|
+
|
|
145
|
+
// Run sync steps
|
|
146
|
+
|
|
147
|
+
await Promise
|
|
148
|
+
.all([
|
|
149
|
+
|
|
150
|
+
// Run async steps that are independent of each other
|
|
151
|
+
...asyncSteps.map(step => this.getStepHandler(step)),
|
|
152
|
+
|
|
153
|
+
// Run sync steps that are dependent on each other
|
|
154
|
+
new Promise<void>(
|
|
155
|
+
async (r, j) => {
|
|
156
|
+
try {
|
|
157
|
+
for (const step of syncSteps) {
|
|
158
|
+
await this.getStepHandler(step);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return r();
|
|
162
|
+
} catch (error) {
|
|
163
|
+
return j(error);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
]);
|
|
168
|
+
|
|
169
|
+
this.completed();
|
|
170
|
+
|
|
171
|
+
return resolve();
|
|
172
|
+
|
|
173
|
+
} catch (error) {
|
|
174
|
+
this.failed(error);
|
|
175
|
+
|
|
176
|
+
return reject(error);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
return this.processed;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Skips the stage
|
|
187
|
+
*
|
|
188
|
+
*/
|
|
189
|
+
skip() {
|
|
190
|
+
this.status = A_TYPES__A_Stage_Status.SKIPPED;
|
|
191
|
+
|
|
192
|
+
this.feature.next(this);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
// ==========================================
|
|
199
|
+
// ============ Status methods =============
|
|
200
|
+
// ==========================================
|
|
201
|
+
|
|
202
|
+
protected completed() {
|
|
203
|
+
this.status = A_TYPES__A_Stage_Status.COMPLETED;
|
|
204
|
+
|
|
205
|
+
this.feature.next(this);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
protected failed(
|
|
209
|
+
error: Error | A_Error | unknown
|
|
210
|
+
) {
|
|
211
|
+
this.status = A_TYPES__A_Stage_Status.FAILED;
|
|
212
|
+
|
|
213
|
+
this.feature.failed(error);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
// ==========================================
|
|
219
|
+
// ============ Serialization ===============
|
|
220
|
+
// ==========================================
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Serializes the stage to JSON
|
|
225
|
+
*
|
|
226
|
+
*/
|
|
227
|
+
toJSON(): A_TYPES__A_Stage_JSON {
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
name: 'A_Stage',
|
|
231
|
+
status: this.status,
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { A_TYPES__A_InjectDecorator_Meta } from "@adaas/a-concept/decorators/A-Inject/A-Inject.decorator.types"
|
|
2
|
+
import { A_Component } from "../A-Component/A-Component.class"
|
|
3
|
+
import { A_Container } from "../A-Container/A-Container.class"
|
|
4
|
+
import { A_TYPES__A_ExtendDecorator_BehaviorConfig, A_TYPES__A_ExtendDecorator_Meta } from "@adaas/a-concept/decorators/A-Feature/A-Feature.decorator.types"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export enum A_TYPES__A_Stage_Status {
|
|
9
|
+
/**
|
|
10
|
+
* The stage is currently being processed
|
|
11
|
+
*/
|
|
12
|
+
PROCESSING = 'PROCESSING',
|
|
13
|
+
/**
|
|
14
|
+
* The stage has been completed
|
|
15
|
+
*/
|
|
16
|
+
COMPLETED = 'COMPLETED',
|
|
17
|
+
/**
|
|
18
|
+
* The stage has failed
|
|
19
|
+
*/
|
|
20
|
+
FAILED = 'FAILED',
|
|
21
|
+
/**
|
|
22
|
+
* The stage has been skipped
|
|
23
|
+
*/
|
|
24
|
+
SKIPPED = 'SKIPPED',
|
|
25
|
+
/**
|
|
26
|
+
* The stage has been paused
|
|
27
|
+
*/
|
|
28
|
+
// PAUSED = 'PAUSED',
|
|
29
|
+
/**
|
|
30
|
+
* The stage has been stopped
|
|
31
|
+
*/
|
|
32
|
+
// STOPPED = 'STOPPED',
|
|
33
|
+
/**
|
|
34
|
+
* The stage has been started
|
|
35
|
+
*/
|
|
36
|
+
// STARTED = 'STARTED',
|
|
37
|
+
/**
|
|
38
|
+
* The stage has been initialized
|
|
39
|
+
*/
|
|
40
|
+
INITIALIZED = 'INITIALIZED',
|
|
41
|
+
/**
|
|
42
|
+
* The stage has been reset
|
|
43
|
+
*/
|
|
44
|
+
// RESET = 'RESET',
|
|
45
|
+
/**
|
|
46
|
+
* The stage has been resumed
|
|
47
|
+
*/
|
|
48
|
+
// RESUMED = 'RESUMED',
|
|
49
|
+
/**
|
|
50
|
+
* The stage has been suspended
|
|
51
|
+
*/
|
|
52
|
+
// SUSPENDED = 'SUSPENDED',
|
|
53
|
+
/**
|
|
54
|
+
* The stage has been terminated
|
|
55
|
+
*/
|
|
56
|
+
// TERMINATED = 'TERMINATED',
|
|
57
|
+
/**
|
|
58
|
+
* The stage has been aborted
|
|
59
|
+
*/
|
|
60
|
+
ABORTED = 'ABORTED'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
export type A_TYPES__A_StageStep = {
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The component to be called
|
|
68
|
+
*/
|
|
69
|
+
component: typeof A_Component | typeof A_Container | A_Container<any>
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The method to be called on the component
|
|
73
|
+
*/
|
|
74
|
+
handler: string,
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Original Feature Extension name
|
|
78
|
+
*
|
|
79
|
+
* [!] could be string or regex
|
|
80
|
+
*
|
|
81
|
+
*/
|
|
82
|
+
name: string,
|
|
83
|
+
|
|
84
|
+
} & A_TYPES__A_ExtendDecorator_BehaviorConfig
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
export type A_TYPES__A_Stage_JSON = {
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The name of the stage
|
|
92
|
+
*/
|
|
93
|
+
name: string,
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The status of the stage
|
|
97
|
+
*
|
|
98
|
+
*/
|
|
99
|
+
status: A_TYPES__A_Stage_Status,
|
|
100
|
+
|
|
101
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { A_Feature } from "../global/A-Feature/A-Feature.class";
|
|
2
|
+
import { A_Stage } from "../global/A-Stage/A-Stage.class";
|
|
3
|
+
import { A_TYPES__A_StageStep } from "../global/A-Stage/A-Stage.types";
|
|
4
|
+
|
|
5
|
+
export class StepsManager {
|
|
6
|
+
|
|
7
|
+
public entities: A_TYPES__A_StageStep[];
|
|
8
|
+
public graph: Map<string, Set<string>>;
|
|
9
|
+
public visited: Set<string>;
|
|
10
|
+
public tempMark: Set<string>;
|
|
11
|
+
public sortedEntities: string[];
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
constructor(entities: A_TYPES__A_StageStep[]) {
|
|
15
|
+
this.entities = entities;
|
|
16
|
+
this.graph = new Map();
|
|
17
|
+
this.visited = new Set();
|
|
18
|
+
this.tempMark = new Set();
|
|
19
|
+
this.sortedEntities = [];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private buildGraph() {
|
|
23
|
+
// Initialize graph nodes
|
|
24
|
+
this.entities.forEach(entity => this.graph.set(entity.name, new Set()));
|
|
25
|
+
|
|
26
|
+
// Add directed edges based on 'before' and 'after'
|
|
27
|
+
this.entities.forEach(entity => {
|
|
28
|
+
const { name, before = [], after = [] } = entity;
|
|
29
|
+
|
|
30
|
+
// Add edges for 'before' dependencies
|
|
31
|
+
before.forEach(dep => {
|
|
32
|
+
const targets = this.matchEntities(dep);
|
|
33
|
+
targets.forEach(target => {
|
|
34
|
+
if (!this.graph.has(target)) this.graph.set(target, new Set());
|
|
35
|
+
this.graph.get(target)!.add(name); // target -> name (target should be before name)
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Add edges for 'after' dependencies
|
|
40
|
+
after.forEach(dep => {
|
|
41
|
+
const sources = this.matchEntities(dep);
|
|
42
|
+
sources.forEach(source => {
|
|
43
|
+
if (!this.graph.has(name)) this.graph.set(name, new Set());
|
|
44
|
+
this.graph.get(name)!.add(source); // name -> source (name should be before source)
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Match entities by name or regex
|
|
51
|
+
private matchEntities(pattern) {
|
|
52
|
+
const regex = new RegExp(`^${pattern}$`);
|
|
53
|
+
return this.entities
|
|
54
|
+
.filter(entity => regex.test(entity.name))
|
|
55
|
+
.map(entity => entity.name);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Topological sort with cycle detection
|
|
59
|
+
private visit(node) {
|
|
60
|
+
if (this.tempMark.has(node)) throw new Error("Circular dependency detected");
|
|
61
|
+
|
|
62
|
+
if (!this.visited.has(node)) {
|
|
63
|
+
this.tempMark.add(node);
|
|
64
|
+
(this.graph.get(node) || []).forEach(neighbor => this.visit(neighbor));
|
|
65
|
+
this.tempMark.delete(node);
|
|
66
|
+
this.visited.add(node);
|
|
67
|
+
this.sortedEntities.push(node);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Sort the entities based on dependencies
|
|
72
|
+
toStages(feature: A_Feature): Array<A_Stage> {
|
|
73
|
+
this.buildGraph();
|
|
74
|
+
|
|
75
|
+
// Start topological sort
|
|
76
|
+
this.entities.forEach(entity => {
|
|
77
|
+
if (!this.visited.has(entity.name)) this.visit(entity.name);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const stages: A_Stage[] = [];
|
|
81
|
+
|
|
82
|
+
// Map sorted names back to entity objects
|
|
83
|
+
this.sortedEntities
|
|
84
|
+
.map(name => {
|
|
85
|
+
|
|
86
|
+
const step = this.entities.find(entity => entity.name === name)!;
|
|
87
|
+
|
|
88
|
+
let stage = stages.find(stage => {
|
|
89
|
+
return stage.after.every(after => step.after.includes(after))
|
|
90
|
+
&& step.before.every(before => stage.after.includes(before));
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if (!stage) {
|
|
95
|
+
stage = new A_Stage(feature);
|
|
96
|
+
stages.push(stage);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
stage.add(step);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return stages;
|
|
103
|
+
}
|
|
104
|
+
}
|
package/tests/channel.ts
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
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_Container } from "@adaas/a-concept/global/A-Container/A-Container.class";
|
|
4
|
+
// import { A_Feature } from "@adaas/a-concept/global/A-Feature/A-Feature.class";
|
|
5
|
+
// import { EventEmitter } from "stream";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// class ComponentA extends A_Component<[
|
|
9
|
+
// 'method1',
|
|
10
|
+
// 'method2'
|
|
11
|
+
// ]> {
|
|
12
|
+
|
|
13
|
+
// @A_Feature.Define({
|
|
14
|
+
// name: 'method1',
|
|
15
|
+
// channels: []
|
|
16
|
+
// } as any)
|
|
17
|
+
// async method1() {
|
|
18
|
+
|
|
19
|
+
// }
|
|
20
|
+
|
|
21
|
+
// @A_Feature.Define({
|
|
22
|
+
// name: 'method2',
|
|
23
|
+
// channels: []
|
|
24
|
+
// } as any)
|
|
25
|
+
// async method2() {
|
|
26
|
+
|
|
27
|
+
// }
|
|
28
|
+
// }
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
// class ComponentB extends A_Component<[
|
|
32
|
+
// 'ComponentB_method3',
|
|
33
|
+
// 'ComponentB_method4'
|
|
34
|
+
// ]> {
|
|
35
|
+
|
|
36
|
+
// @A_Feature.Define({
|
|
37
|
+
// name: 'ComponentB_method3',
|
|
38
|
+
// channels: []
|
|
39
|
+
// } as any)
|
|
40
|
+
// async ComponentB_method3(param1: {
|
|
41
|
+
// key: string
|
|
42
|
+
// }) {
|
|
43
|
+
|
|
44
|
+
// }
|
|
45
|
+
|
|
46
|
+
// @A_Feature.Define({
|
|
47
|
+
// name: 'ComponentB_method4',
|
|
48
|
+
// channels: []
|
|
49
|
+
// } as any)
|
|
50
|
+
// async ComponentB_method4(foo: number) {
|
|
51
|
+
|
|
52
|
+
// }
|
|
53
|
+
// }
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
// type MethodsWithSpecificArg<T, ArgType> = {
|
|
58
|
+
// [K in keyof T]: T[K] extends (arg: ArgType, ...args: any[]) => Promise<any> ? K : never
|
|
59
|
+
// }[keyof T];
|
|
60
|
+
|
|
61
|
+
// // Example argument type
|
|
62
|
+
// type SpecificArgType = { key: string };
|
|
63
|
+
|
|
64
|
+
// type AggregateMethods<TClasses extends A_Component[]> = {
|
|
65
|
+
// [K in keyof TClasses]: TClasses[K] extends infer Instance
|
|
66
|
+
// ? MethodsWithSpecificArg<Instance, SpecificArgType>
|
|
67
|
+
// : never;
|
|
68
|
+
// }[number];
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
// type MethodObject2<TClasses extends any[]> = {
|
|
72
|
+
// [Method in AggregateMethods<TClasses>]: {
|
|
73
|
+
// [Class in keyof TClasses]: TClasses[Class] extends infer Instance
|
|
74
|
+
// ? Method extends keyof Instance
|
|
75
|
+
// ? Instance[Method]
|
|
76
|
+
// : never
|
|
77
|
+
// : never;
|
|
78
|
+
// }[number]; // Select the method signature from any matching class
|
|
79
|
+
// };
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
// // decorator to create a channel
|
|
84
|
+
// function A_Connect() {
|
|
85
|
+
// return function (target: any, prop: string) {
|
|
86
|
+
// console.log('A_Connect', target, prop);
|
|
87
|
+
// }
|
|
88
|
+
// }
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
// class Channel<T extends A_Component[]> {
|
|
93
|
+
|
|
94
|
+
// channel: MethodObject2<T>;
|
|
95
|
+
|
|
96
|
+
// constructor() {
|
|
97
|
+
// this.channel = new Proxy(
|
|
98
|
+
// {} as MethodObject2<T>,
|
|
99
|
+
// {
|
|
100
|
+
// get: (target, prop) => {
|
|
101
|
+
// return async (...args: any[]) => {
|
|
102
|
+
// this.call(prop as AggregateMethods<T>);
|
|
103
|
+
// };
|
|
104
|
+
// }
|
|
105
|
+
// });
|
|
106
|
+
// }
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
// async call(prop: AggregateMethods<T>) {
|
|
110
|
+
// // do HTTP Call or just inject class or whatever you want
|
|
111
|
+
|
|
112
|
+
// console.log('Calling method', prop);
|
|
113
|
+
// }
|
|
114
|
+
|
|
115
|
+
// }
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
// class HTTP<T extends A_Component[]> extends Channel<T> {
|
|
121
|
+
|
|
122
|
+
// async call(prop: AggregateMethods<T>): Promise<void> {
|
|
123
|
+
|
|
124
|
+
// console.log('HTTP Call', prop);
|
|
125
|
+
// }
|
|
126
|
+
// }
|
|
127
|
+
|
|
128
|
+
// class ConceptDirect<T extends A_Component[]> extends Channel<T> {
|
|
129
|
+
|
|
130
|
+
// // protected originalInstance: T;
|
|
131
|
+
|
|
132
|
+
// async call(prop: AggregateMethods<T>): Promise<void> {
|
|
133
|
+
// console.log('Direct Call', prop);
|
|
134
|
+
// }
|
|
135
|
+
|
|
136
|
+
// }
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
// class ConceptEE extends Channel<any> {
|
|
141
|
+
|
|
142
|
+
// private emitter: EventEmitter = new EventEmitter();
|
|
143
|
+
|
|
144
|
+
// constructor() {
|
|
145
|
+
// super();
|
|
146
|
+
// }
|
|
147
|
+
|
|
148
|
+
// async call(prop: string): Promise<void> {
|
|
149
|
+
// console.log('EE Call', prop);
|
|
150
|
+
// }
|
|
151
|
+
|
|
152
|
+
// on = this.emitter.on.bind(this.emitter);
|
|
153
|
+
|
|
154
|
+
// emit = this.emitter.emit.bind(this.emitter);
|
|
155
|
+
|
|
156
|
+
// }
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
// class FooContainer extends A_Container<[
|
|
179
|
+
// 'doSomething',
|
|
180
|
+
// 'doAnotherThing'
|
|
181
|
+
// ]> {
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
// @A_Feature.Define({
|
|
185
|
+
// name: 'doSomething',
|
|
186
|
+
// channels: [ConceptDirect, HTTP]
|
|
187
|
+
// } as any)
|
|
188
|
+
// async doSomething(
|
|
189
|
+
// @A_Inject(HTTP) http: HTTP<[ComponentA, ComponentB]>,
|
|
190
|
+
// ) {
|
|
191
|
+
|
|
192
|
+
// // @A_Connect(http, 'ComponentB_method3')
|
|
193
|
+
|
|
194
|
+
// const foo = await http.channel.ComponentB_method3({
|
|
195
|
+
// key: 'value'
|
|
196
|
+
// });
|
|
197
|
+
// }
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
// @A_Feature.Define({
|
|
203
|
+
// name: 'doAnotherThing',
|
|
204
|
+
// channels: [HTTP]
|
|
205
|
+
// } as any)
|
|
206
|
+
// async onRequest() {
|
|
207
|
+
// await this.call('doSomething');
|
|
208
|
+
// }
|
|
209
|
+
// }
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|