@adaas/a-concept 0.3.4 → 0.3.5
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/browser/index.d.mts +19 -0
- package/dist/browser/index.mjs +2 -2
- package/dist/browser/index.mjs.map +1 -1
- package/dist/node/index.cjs +58 -5
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.mts +19 -0
- package/dist/node/index.d.ts +19 -0
- package/dist/node/index.mjs +58 -5
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/A-Component/A-Component.meta.ts +1 -1
- package/src/lib/A-Context/A-Context.class.ts +11 -0
- package/src/lib/A-StepManager/A-StepManager.class.ts +59 -5
- package/tests/A-Feature.test.ts +76 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaas/a-concept",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "A-Concept is a framework of the new generation that is tailored to use AI, enabling developers to create AI-powered applications with ease. It provides a structured approach to building, managing, and deploying AI-driven solutions.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": {
|
|
@@ -50,7 +50,7 @@ export class A_ComponentMeta<T extends A_TYPES__ComponentMeta = A_TYPES__Compone
|
|
|
50
50
|
before: extension.before || '',
|
|
51
51
|
after: extension.after || '',
|
|
52
52
|
throwOnError: extension.throwOnError || true,
|
|
53
|
-
override: ''
|
|
53
|
+
override: extension.override || '',
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
});
|
|
@@ -834,6 +834,17 @@ export class A_Context {
|
|
|
834
834
|
steps.delete(`${A_CommonHelper.getComponentName(inherited)}.${declaration.handler}`);
|
|
835
835
|
}
|
|
836
836
|
|
|
837
|
+
// Check if the declaration has an override regexp and remove matching steps
|
|
838
|
+
// Match against both the full step key (Component.handler) and the handler alone
|
|
839
|
+
if (declaration.override) {
|
|
840
|
+
const overrideRegexp = new RegExp(declaration.override);
|
|
841
|
+
for (const [stepKey, step] of steps) {
|
|
842
|
+
if (overrideRegexp.test(stepKey) || overrideRegexp.test(step.handler)) {
|
|
843
|
+
steps.delete(stepKey);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
837
848
|
steps.set(`${A_CommonHelper.getComponentName(cmp)}.${declaration.handler}`, {
|
|
838
849
|
dependency: new A_Dependency(cmp),
|
|
839
850
|
...declaration
|
|
@@ -16,6 +16,11 @@ export class A_StepsManager {
|
|
|
16
16
|
public tempMark: Set<string>;
|
|
17
17
|
public sortedEntities: string[];
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Maps each step instance to a unique ID.
|
|
21
|
+
* Duplicate steps (same dependency.name + handler) get indexed suffixes (e.g., #1, #2).
|
|
22
|
+
*/
|
|
23
|
+
private _uniqueIdMap: Map<A_TYPES__A_StageStep, string> = new Map();
|
|
19
24
|
|
|
20
25
|
private _isBuilt: boolean = false;
|
|
21
26
|
|
|
@@ -27,6 +32,7 @@ export class A_StepsManager {
|
|
|
27
32
|
this.tempMark = new Set();
|
|
28
33
|
this.sortedEntities = [];
|
|
29
34
|
|
|
35
|
+
this.assignUniqueIds();
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
private prepareSteps(
|
|
@@ -44,20 +50,68 @@ export class A_StepsManager {
|
|
|
44
50
|
}));
|
|
45
51
|
}
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Returns the base (non-unique) ID for a step: `dependency.name.handler`
|
|
55
|
+
*/
|
|
56
|
+
private baseID(step: A_TYPES__A_StageStep) {
|
|
48
57
|
return `${step.dependency.name}.${step.handler}`;
|
|
49
58
|
}
|
|
50
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Returns the unique ID assigned to a specific step instance.
|
|
62
|
+
* Falls back to baseID if not yet assigned.
|
|
63
|
+
*/
|
|
64
|
+
private ID(step: A_TYPES__A_StageStep) {
|
|
65
|
+
return this._uniqueIdMap.get(step) || this.baseID(step);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Assigns unique IDs to all steps.
|
|
70
|
+
* Duplicate base IDs get an index suffix (#0, #1, ...).
|
|
71
|
+
* Steps with unique base IDs keep their original ID (no suffix).
|
|
72
|
+
*/
|
|
73
|
+
private assignUniqueIds() {
|
|
74
|
+
// Count occurrences of each base ID
|
|
75
|
+
const counts = new Map<string, number>();
|
|
76
|
+
for (const step of this.entities) {
|
|
77
|
+
const base = this.baseID(step);
|
|
78
|
+
counts.set(base, (counts.get(base) || 0) + 1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Assign unique IDs with index suffix only for duplicates
|
|
82
|
+
const indexTracker = new Map<string, number>();
|
|
83
|
+
for (const step of this.entities) {
|
|
84
|
+
const base = this.baseID(step);
|
|
85
|
+
if (counts.get(base)! > 1) {
|
|
86
|
+
const idx = indexTracker.get(base) || 0;
|
|
87
|
+
this._uniqueIdMap.set(step, `${base}#${idx}`);
|
|
88
|
+
indexTracker.set(base, idx + 1);
|
|
89
|
+
} else {
|
|
90
|
+
this._uniqueIdMap.set(step, base);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
51
95
|
private buildGraph() {
|
|
52
96
|
if (this._isBuilt) return;
|
|
53
97
|
this._isBuilt = true;
|
|
54
98
|
|
|
55
|
-
// Filter override
|
|
99
|
+
// Filter override — match against both the full base ID and handler name
|
|
100
|
+
// so both formats work (e.g., `^.*\.step(4|5)$` and `^test1$`)
|
|
101
|
+
// A step's own override pattern should not cause it to filter itself out
|
|
56
102
|
this.entities = this.entities
|
|
57
103
|
.filter((step, i, self) =>
|
|
58
|
-
!self.some(s
|
|
104
|
+
!self.some((s, j) => {
|
|
105
|
+
if (i === j || !s.override) return false;
|
|
106
|
+
const re = new RegExp(s.override);
|
|
107
|
+
return re.test(this.baseID(step)) || re.test(step.handler);
|
|
108
|
+
})
|
|
59
109
|
);
|
|
60
110
|
|
|
111
|
+
// Re-assign unique IDs after filtering
|
|
112
|
+
this._uniqueIdMap.clear();
|
|
113
|
+
this.assignUniqueIds();
|
|
114
|
+
|
|
61
115
|
// Initialize graph nodes
|
|
62
116
|
this.entities.forEach(entity => this.graph.set(this.ID(entity), new Set()));
|
|
63
117
|
|
|
@@ -90,12 +144,12 @@ export class A_StepsManager {
|
|
|
90
144
|
});
|
|
91
145
|
}
|
|
92
146
|
|
|
93
|
-
// Match entities by name or regex
|
|
147
|
+
// Match entities by name or regex — matches against the base ID for pattern compatibility
|
|
94
148
|
private matchEntities(entityId: string, pattern: string): string[] {
|
|
95
149
|
const regex = new RegExp(pattern);
|
|
96
150
|
|
|
97
151
|
return this.entities
|
|
98
|
-
.filter(entity => regex.test(this.
|
|
152
|
+
.filter(entity => regex.test(this.baseID(entity)) && this.ID(entity) !== entityId)
|
|
99
153
|
.map(entity => this.ID(entity));
|
|
100
154
|
}
|
|
101
155
|
|
package/tests/A-Feature.test.ts
CHANGED
|
@@ -1038,4 +1038,80 @@ describe('A-Feature tests', () => {
|
|
|
1038
1038
|
'ChildComponent_A.test'
|
|
1039
1039
|
]);
|
|
1040
1040
|
})
|
|
1041
|
+
it('Should keep override definition', async () => {
|
|
1042
|
+
|
|
1043
|
+
const resultChain: string[] = [];
|
|
1044
|
+
|
|
1045
|
+
class ChildComponent_A extends A_Component {
|
|
1046
|
+
@A_Feature.Extend({
|
|
1047
|
+
name: 'testFeature',
|
|
1048
|
+
})
|
|
1049
|
+
async test1() {
|
|
1050
|
+
resultChain.push('ChildComponent_A.test1');
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
@A_Feature.Extend({
|
|
1054
|
+
name: 'testFeature',
|
|
1055
|
+
override: ['test1']
|
|
1056
|
+
})
|
|
1057
|
+
async test2() {
|
|
1058
|
+
resultChain.push('ChildComponent_A.test2');
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
const testScope = new A_Scope({ name: 'TestScope', components: [ChildComponent_A] });
|
|
1063
|
+
|
|
1064
|
+
const featureDefinition = A_Context.featureTemplate('testFeature', testScope.resolve(ChildComponent_A)!, testScope);
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
expect(featureDefinition).toBeDefined();
|
|
1068
|
+
expect(featureDefinition.length).toBe(1);
|
|
1069
|
+
expect(featureDefinition[0].handler).toBe('test2');
|
|
1070
|
+
|
|
1071
|
+
await testScope.resolve(ChildComponent_A)!.call('testFeature');
|
|
1072
|
+
|
|
1073
|
+
expect(resultChain).toEqual([
|
|
1074
|
+
'ChildComponent_A.test2'
|
|
1075
|
+
]);
|
|
1076
|
+
})
|
|
1077
|
+
|
|
1078
|
+
it('Should allow to run feature with the same steps', async () => {
|
|
1079
|
+
|
|
1080
|
+
const resultChain: string[] = [];
|
|
1081
|
+
|
|
1082
|
+
class ComponentA extends A_Component {
|
|
1083
|
+
@A_Feature.Extend({
|
|
1084
|
+
name: 'testFeature',
|
|
1085
|
+
})
|
|
1086
|
+
async feature1() {
|
|
1087
|
+
resultChain.push('ComponentA.feature1');
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
const testScope = new A_Scope({ name: 'TestScope', components: [ComponentA] });
|
|
1092
|
+
|
|
1093
|
+
const feature = new A_Feature({
|
|
1094
|
+
name: 'testFeature',
|
|
1095
|
+
scope: testScope,
|
|
1096
|
+
template: [
|
|
1097
|
+
{
|
|
1098
|
+
name: 'ComponentA.feature1',
|
|
1099
|
+
dependency: new A_Dependency('ComponentA'),
|
|
1100
|
+
handler: 'feature1',
|
|
1101
|
+
},
|
|
1102
|
+
{
|
|
1103
|
+
name: 'ComponentA.feature1',
|
|
1104
|
+
dependency: new A_Dependency('ComponentA'),
|
|
1105
|
+
handler: 'feature1',
|
|
1106
|
+
},
|
|
1107
|
+
]
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
await feature.process();
|
|
1111
|
+
|
|
1112
|
+
expect(resultChain).toEqual([
|
|
1113
|
+
'ComponentA.feature1',
|
|
1114
|
+
'ComponentA.feature1'
|
|
1115
|
+
]);
|
|
1116
|
+
})
|
|
1041
1117
|
});
|