@adaas/a-concept 0.1.17 → 0.1.19

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.
Files changed (56) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +5 -2
  3. package/dist/index.js.map +1 -1
  4. package/dist/src/global/A-Abstraction/A-Abstraction-Extend.decorator.js +22 -7
  5. package/dist/src/global/A-Abstraction/A-Abstraction-Extend.decorator.js.map +1 -1
  6. package/dist/src/global/A-Component/A-Component.meta.js +2 -1
  7. package/dist/src/global/A-Component/A-Component.meta.js.map +1 -1
  8. package/dist/src/global/A-Component/A-Component.types.d.ts +2 -11
  9. package/dist/src/global/A-Concept/A-Concept.types.d.ts +4 -21
  10. package/dist/src/global/A-Container/A-Container.meta.js +4 -2
  11. package/dist/src/global/A-Container/A-Container.meta.js.map +1 -1
  12. package/dist/src/global/A-Container/A-Container.types.d.ts +2 -11
  13. package/dist/src/global/A-Context/A-Context.class.d.ts +8 -0
  14. package/dist/src/global/A-Context/A-Context.class.js +30 -2
  15. package/dist/src/global/A-Context/A-Context.class.js.map +1 -1
  16. package/dist/src/global/A-Feature/A-Feature-Define.decorator.js +1 -1
  17. package/dist/src/global/A-Feature/A-Feature-Define.decorator.js.map +1 -1
  18. package/dist/src/global/A-Feature/A-Feature-Extend.decorator.js +27 -8
  19. package/dist/src/global/A-Feature/A-Feature-Extend.decorator.js.map +1 -1
  20. package/dist/src/global/A-Feature/A-Feature.class.d.ts +2 -1
  21. package/dist/src/global/A-Feature/A-Feature.class.js +7 -3
  22. package/dist/src/global/A-Feature/A-Feature.class.js.map +1 -1
  23. package/dist/src/global/A-Feature/A-Feature.types.d.ts +69 -27
  24. package/dist/src/global/A-Stage/A-Stage.class.d.ts +37 -28
  25. package/dist/src/global/A-Stage/A-Stage.class.js +62 -98
  26. package/dist/src/global/A-Stage/A-Stage.class.js.map +1 -1
  27. package/dist/src/global/A-Stage/A-Stage.types.d.ts +30 -3
  28. package/dist/src/global/A-Stage/A-Stage.types.js.map +1 -1
  29. package/dist/src/global/A-StepManager/A-StepManager.class.d.ts +20 -0
  30. package/dist/src/{helpers/A_StepsManager.class.js → global/A-StepManager/A-StepManager.class.js} +38 -64
  31. package/dist/src/global/A-StepManager/A-StepManager.class.js.map +1 -0
  32. package/dist/src/global/A-StepManager/A-StepManager.error.d.ts +4 -0
  33. package/dist/src/global/A-StepManager/A-StepManager.error.js +9 -0
  34. package/dist/src/global/A-StepManager/A-StepManager.error.js.map +1 -0
  35. package/index.ts +2 -1
  36. package/package.json +3 -3
  37. package/src/global/A-Abstraction/A-Abstraction-Extend.decorator.ts +27 -7
  38. package/src/global/A-Component/A-Component.meta.ts +2 -1
  39. package/src/global/A-Component/A-Component.types.ts +2 -11
  40. package/src/global/A-Concept/A-Concept.types.ts +4 -21
  41. package/src/global/A-Container/A-Container.meta.ts +4 -2
  42. package/src/global/A-Container/A-Container.types.ts +2 -11
  43. package/src/global/A-Context/A-Context.class.ts +40 -3
  44. package/src/global/A-Feature/A-Feature-Define.decorator.ts +1 -0
  45. package/src/global/A-Feature/A-Feature-Extend.decorator.ts +34 -8
  46. package/src/global/A-Feature/A-Feature.class.ts +8 -1
  47. package/src/global/A-Feature/A-Feature.types.ts +80 -33
  48. package/src/global/A-Stage/A-Stage.class.ts +71 -143
  49. package/src/global/A-Stage/A-Stage.types.ts +34 -3
  50. package/src/{helpers/A_StepsManager.class.ts → global/A-StepManager/A-StepManager.class.ts} +53 -87
  51. package/src/global/A-StepManager/A-StepManager.error.ts +10 -0
  52. package/tests/A-Abstraction.test.ts +274 -190
  53. package/tests/A-Feature.test.ts +84 -1
  54. package/tests/A-StepManager.test.ts +346 -0
  55. package/dist/src/helpers/A_StepsManager.class.d.ts +0 -35
  56. package/dist/src/helpers/A_StepsManager.class.js.map +0 -1
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.A_TmpStage = exports.A_StepsManager = void 0;
4
- const A_Error_class_1 = require("../global/A-Error/A_Error.class");
5
- const A_Stage_class_1 = require("../global/A-Stage/A-Stage.class");
3
+ exports.A_StepsManager = void 0;
4
+ const A_Stage_class_1 = require("../A-Stage/A-Stage.class");
5
+ const A_StepManager_error_1 = require("./A-StepManager.error");
6
6
  class A_StepsManager {
7
7
  constructor(entities) {
8
+ this._isBuilt = false;
8
9
  this.entities = this.prepareSteps(entities);
9
10
  this.graph = new Map();
10
11
  this.visited = new Set();
@@ -13,13 +14,16 @@ class A_StepsManager {
13
14
  }
14
15
  prepareSteps(entities) {
15
16
  return entities.map(step => {
16
- return Object.assign(Object.assign({}, step), { behavior: step.behavior || 'sync', before: step.before || [], after: step.after || [] });
17
+ return Object.assign(Object.assign({}, step), { behavior: step.behavior || 'sync', before: step.before || [], after: step.after || [], throwOnError: false });
17
18
  });
18
19
  }
19
20
  ID(step) {
20
21
  return `${typeof step.component === 'string' ? step.component : step.component.name}.${step.handler}`;
21
22
  }
22
23
  buildGraph() {
24
+ if (this._isBuilt)
25
+ return;
26
+ this._isBuilt = true;
23
27
  // Initialize graph nodes
24
28
  this.entities.forEach(entity => this.graph.set(this.ID(entity), new Set()));
25
29
  // Add directed edges based on 'before' and 'after'
@@ -30,7 +34,7 @@ class A_StepsManager {
30
34
  // If entity should execute before targets, then targets depend on entity
31
35
  // So we add edges: target -> entity (target depends on entity)
32
36
  before.forEach(dep => {
33
- const targets = this.matchEntities(dep);
37
+ const targets = this.matchEntities(entityId, dep);
34
38
  targets.forEach(target => {
35
39
  if (!this.graph.has(target))
36
40
  this.graph.set(target, new Set());
@@ -41,7 +45,7 @@ class A_StepsManager {
41
45
  // If entity should execute after sources, then entity depends on sources
42
46
  // So we add edges: entity -> source (entity depends on source)
43
47
  after.forEach(dep => {
44
- const sources = this.matchEntities(dep);
48
+ const sources = this.matchEntities(entityId, dep);
45
49
  sources.forEach(source => {
46
50
  if (!this.graph.has(entityId))
47
51
  this.graph.set(entityId, new Set());
@@ -51,87 +55,57 @@ class A_StepsManager {
51
55
  });
52
56
  }
53
57
  // Match entities by name or regex
54
- matchEntities(pattern) {
55
- const regex = new RegExp(`^${pattern}$`);
58
+ matchEntities(entityId, pattern) {
59
+ const regex = new RegExp(pattern);
56
60
  return this.entities
57
- .filter(entity => regex.test(this.ID(entity)))
61
+ .filter(entity => regex.test(this.ID(entity)) && this.ID(entity) !== entityId)
58
62
  .map(entity => this.ID(entity));
59
63
  }
60
64
  // Topological sort with cycle detection
61
65
  visit(node) {
62
- if (this.tempMark.has(node))
63
- throw new A_Error_class_1.A_Error("Circular dependency detected");
66
+ if (this.tempMark.has(node)) {
67
+ return;
68
+ // TODO: maybe we have to keep this error but only for partial cases
69
+ throw new A_StepManager_error_1.A_StepManagerError(A_StepManager_error_1.A_StepManagerError.CircularDependencyError, `Circular dependency detected involving step: ${node}. Make sure that your 'before' and 'after' dependencies do not create cycles.`);
70
+ }
64
71
  if (!this.visited.has(node)) {
65
72
  this.tempMark.add(node);
66
73
  (this.graph.get(node) || []).forEach(neighbor => this.visit(neighbor));
67
74
  this.tempMark.delete(node);
68
75
  this.visited.add(node);
69
76
  this.sortedEntities.push(node);
77
+ // // Visit neighbors in stable order (preserving original order)
78
+ // const neighbors = Array.from(this.graph.get(node) || []);
79
+ // // neighbors.sort((a, b) => {
80
+ // // const orderA = this.originalOrder.get(a) || 0;
81
+ // // const orderB = this.originalOrder.get(b) || 0;
82
+ // // return orderA - orderB;
83
+ // // });
84
+ // neighbors.forEach(neighbor => this.visit(neighbor));
85
+ // this.tempMark.delete(node);
86
+ // this.visited.add(node);
87
+ // this.sortedEntities.push(node);
70
88
  }
71
89
  }
72
- // Sort the entities based on dependencies
73
- toStages(feature) {
90
+ toSortedArray() {
74
91
  this.buildGraph();
75
92
  // Start topological sort
76
93
  this.entities.forEach(entity => {
77
94
  if (!this.visited.has(this.ID(entity)))
78
95
  this.visit(this.ID(entity));
79
96
  });
80
- const stages = [];
97
+ return this.sortedEntities;
98
+ }
99
+ // Sort the entities based on dependencies
100
+ toStages(feature) {
101
+ const sortedNames = this.toSortedArray();
81
102
  // Map sorted names back to entity objects
82
- this.sortedEntities
103
+ return sortedNames
83
104
  .map(id => {
84
105
  const step = this.entities.find(entity => this.ID(entity) === id);
85
- let stage = stages.find(stage => {
86
- return stage.after.every(after => step.after.includes(after))
87
- && step.before.every(before => stage.after.includes(before));
88
- });
89
- if (!stage) {
90
- stage = new A_TmpStage();
91
- stages.push(stage);
92
- }
93
- stage.add(step);
106
+ return new A_Stage_class_1.A_Stage(feature, step);
94
107
  });
95
- return stages.map(stage => new A_Stage_class_1.A_Stage(feature, stage.steps));
96
108
  }
97
109
  }
98
110
  exports.A_StepsManager = A_StepsManager;
99
- class A_TmpStage {
100
- constructor(_steps = []) {
101
- this.name = 'A_TmpStage';
102
- this._steps = _steps;
103
- }
104
- get before() {
105
- return this._steps.reduce((acc, step) => ([
106
- ...acc,
107
- ...step.before
108
- ]), []);
109
- }
110
- get after() {
111
- return this._steps.reduce((acc, step) => ([
112
- ...acc,
113
- ...step.after
114
- ]), []);
115
- }
116
- get steps() {
117
- return this._steps;
118
- }
119
- get asyncSteps() {
120
- return this._steps.filter(step => step.behavior === 'async');
121
- }
122
- get syncSteps() {
123
- return this._steps.filter(step => step.behavior === 'sync');
124
- }
125
- /**
126
- * Adds a step to the stage
127
- *
128
- * @param step
129
- * @returns
130
- */
131
- add(step) {
132
- this._steps.push(step);
133
- return this;
134
- }
135
- }
136
- exports.A_TmpStage = A_TmpStage;
137
- //# sourceMappingURL=A_StepsManager.class.js.map
111
+ //# sourceMappingURL=A-StepManager.class.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"A-StepManager.class.js","sourceRoot":"","sources":["../../../../src/global/A-StepManager/A-StepManager.class.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { A_Error } from "../A-Error/A_Error.class";
2
+ export declare class A_StepManagerError extends A_Error {
3
+ static readonly CircularDependencyError = "A-StepManager Circular Dependency Error";
4
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.A_StepManagerError = void 0;
4
+ const A_Error_class_1 = require("../A-Error/A_Error.class");
5
+ class A_StepManagerError extends A_Error_class_1.A_Error {
6
+ }
7
+ exports.A_StepManagerError = A_StepManagerError;
8
+ A_StepManagerError.CircularDependencyError = 'A-StepManager Circular Dependency Error';
9
+ //# sourceMappingURL=A-StepManager.error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"A-StepManager.error.js","sourceRoot":"","sources":["../../../../src/global/A-StepManager/A-StepManager.error.ts"],"names":[],"mappings":";;;AAAA,4DAAmD;AAInD,MAAa,kBAAmB,SAAQ,uBAAO;;AAA/C,gDAKC;AAFmB,0CAAuB,GAAG,yCAAyC,CAAC"}
package/index.ts CHANGED
@@ -75,6 +75,7 @@ export { A_Abstraction_Extend } from './src/global/A-Abstraction/A-Abstraction-E
75
75
  export { A_CommonHelper } from './src/helpers/A_Common.helper';
76
76
  export { A_FormatterHelper } from './src/helpers/A_Formatter.helper';
77
77
  export { A_IdentityHelper, A_ID_TYPES__TimeId_Parts } from './src/helpers/A_Identity.helper';
78
- // export { A_StepsManager } from './src/helpers/A_StepsManager.class';
78
+ export { A_StepsManager } from './src/global/A-StepManager/A-StepManager.class';
79
+ export { A_StepManagerError } from './src/global/A-StepManager/A-StepManager.error';
79
80
  export { A_TypeGuards } from './src/helpers/A_TypeGuards.helper';
80
81
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaas/a-concept",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
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,8 +20,8 @@
20
20
  "ext": "ts, js"
21
21
  },
22
22
  "scripts": {
23
- "test": "jest",
24
- "start": "nodemon ./tests/log.ts",
23
+ "test": "jest ",
24
+ "start": "nodemon ./tests/example-usage.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",
27
27
  "example:http": "nodemon ./examples/simple-http-server/concept.ts",
@@ -79,19 +79,39 @@ export function A_Abstraction_Extend(
79
79
  // Set the metadata of the method to define a custom Stage with name
80
80
  const existedMetaValue = existedMeta.get(setName) || [];
81
81
 
82
- // Add the new method to the metadata
83
- existedMetaValue.push({
82
+ const existedIndex = existedMetaValue.findIndex(item => item.handler === propertyKey);
83
+
84
+ const abstraction = {
84
85
  name: setName,
85
86
  handler: propertyKey,
86
- before: config.before || [],
87
- after: config.after || [],
88
- behavior: config.behavior || 'sync'
89
- });
87
+ behavior: config.behavior || 'sync',
88
+ throwOnError: config.throwOnError !== undefined ? config.throwOnError : true,
89
+
90
+ before: (config.before
91
+ ?.map(b =>
92
+ b instanceof RegExp
93
+ ? b.source
94
+ : new RegExp(`^.*${b.replace(/\./g, '\\.')}$`).source)
95
+ || []),
96
+ after: (config.after
97
+ ?.map(a =>
98
+ a instanceof RegExp
99
+ ? a.source
100
+ : new RegExp(`^.*${a.replace(/\./g, '\\.')}$`).source)
101
+ || []),
102
+ }
103
+
104
+ if (existedIndex !== -1) {
105
+ // Update the existing method in the metadata
106
+ existedMetaValue[existedIndex] = abstraction;
107
+ } else {
108
+ // Add the new method to the metadata
109
+ existedMetaValue.push(abstraction);
110
+ }
90
111
 
91
112
  // Set the metadata of the method to define a custom Feature with name
92
113
  existedMeta.set(setName, existedMetaValue);
93
114
 
94
-
95
115
  // Update the metadata of the container with the new Stage definition
96
116
  A_Context
97
117
  .meta(target)
@@ -48,7 +48,8 @@ export class A_ComponentMeta extends A_Meta<A_TYPES__ComponentMeta> {
48
48
  handler: extension.handler,
49
49
  behavior: extension.behavior,
50
50
  before: extension.before || [],
51
- after: extension.after || []
51
+ after: extension.after || [],
52
+ throwOnError: extension.throwOnError || true,
52
53
  });
53
54
 
54
55
  });
@@ -3,7 +3,7 @@ import { A_Meta } from "../A-Meta/A-Meta.class"
3
3
  import { A_TYPES__ConceptAbstraction } from "../A-Concept/A-Concept.types"
4
4
  import { A_Component } from "./A-Component.class"
5
5
  import { A_TYPES__ComponentMetaKey } from "./A-Component.constants"
6
- import { A_TYPES__FeatureDefineDecoratorMeta, A_TYPES__FeatureExtendDecoratorBehaviorConfig, A_TYPES__FeatureExtendDecoratorMeta } from "../A-Feature/A-Feature.types"
6
+ import { A_TYPES__FeatureDefineDecoratorMeta, A_TYPES__FeatureExtendDecoratorMeta } from "../A-Feature/A-Feature.types"
7
7
 
8
8
 
9
9
 
@@ -91,15 +91,6 @@ export type A_TYPES__ComponentMeta = {
91
91
 
92
92
 
93
93
 
94
- export type A_TYPES__ComponentMetaExtension = {
95
- /**
96
- * The name of original Extension Definition
97
- */
98
- name: string,
99
- /**
100
- * The name of the handler that will be used to apply the extension
101
- */
102
- handler: string,
103
- } & A_TYPES__FeatureExtendDecoratorBehaviorConfig
94
+ export type A_TYPES__ComponentMetaExtension = A_TYPES__FeatureExtendDecoratorMeta
104
95
 
105
96
 
@@ -1,10 +1,10 @@
1
- import { A_TYPES__A_InjectDecorator_Meta } from "@adaas/a-concept/global/A-Inject/A-Inject.types";
2
1
  import { A_Container } from "../A-Container/A-Container.class";
3
2
  import { A_Concept } from "./A-Concept.class";
4
- import { A_TYPES__FeatureExtendDecoratorBehaviorConfig } from "../A-Feature/A-Feature.types";
3
+ import { A_TYPES__FeatureExtendDecoratorMeta } from "../A-Feature/A-Feature.types";
5
4
  import { A_TYPES__Component_Constructor } from "../A-Component/A-Component.types";
6
5
  import { A_TYPES__Fragment_Constructor } from "../A-Fragment/A-Fragment.types";
7
6
  import { A_TYPES__Entity_Constructor } from "../A-Entity/A-Entity.types";
7
+ import { A_TYPES__A_InjectDecorator_Meta } from "../A-Inject/A-Inject.types";
8
8
 
9
9
 
10
10
  // ============================================================================
@@ -69,32 +69,15 @@ export type A_TYPES__Concept_Serialized = {
69
69
  * Uses as a transfer object to pass configurations to Feature constructor
70
70
  */
71
71
  export type A_TYPES__ConceptAbstractionMeta = {
72
- /**
73
- * The name of original Extension Definition
74
- */
75
- name: string,
76
- /**
77
- * The name of the handler that will be used to apply the extension
78
- */
79
- handler: string,
80
72
  /**
81
73
  * The arguments that will be passed to the handler
82
74
  */
83
75
  args: A_TYPES__A_InjectDecorator_Meta
84
- } & A_TYPES__FeatureExtendDecoratorBehaviorConfig
76
+ } & A_TYPES__FeatureExtendDecoratorMeta
85
77
 
86
78
 
87
79
 
88
80
  /**
89
81
  * Uses to define the extension that will be applied to the Concept
90
82
  */
91
- export type A_TYPES__ConceptAbstraction = {
92
- /**
93
- * The name of original Extension Definition
94
- */
95
- name: string,
96
- /**
97
- * The name of the handler that will be used to apply the extension
98
- */
99
- handler: string,
100
- } & A_TYPES__FeatureExtendDecoratorBehaviorConfig
83
+ export type A_TYPES__ConceptAbstraction = A_TYPES__FeatureExtendDecoratorMeta
@@ -69,7 +69,8 @@ export class A_ContainerMeta extends A_Meta<A_TYPES__ContainerMeta> {
69
69
  args,
70
70
  before: extension.before,
71
71
  behavior: extension.behavior,
72
- after: extension.after
72
+ after: extension.after,
73
+ throwOnError: extension.throwOnError,
73
74
  });
74
75
 
75
76
  });
@@ -104,7 +105,8 @@ export class A_ContainerMeta extends A_Meta<A_TYPES__ContainerMeta> {
104
105
  handler: extension.handler,
105
106
  behavior: extension.behavior,
106
107
  before: extension.before || [],
107
- after: extension.after || []
108
+ after: extension.after || [],
109
+ throwOnError: extension.throwOnError || true,
108
110
  });
109
111
 
110
112
  });
@@ -4,7 +4,7 @@ import { A_Meta } from "../A-Meta/A-Meta.class";
4
4
  import { A_TYPES__Scope_Init } from "../A-Scope/A-Scope.types";
5
5
  import { A_TYPES__ContainerMetaKey } from "./A-Container.constants";
6
6
  import { A_Container } from "./A-Container.class";
7
- import { A_TYPES__FeatureDefineDecoratorMeta, A_TYPES__FeatureExtendDecoratorBehaviorConfig, A_TYPES__FeatureExtendDecoratorMeta } from "../A-Feature/A-Feature.types";
7
+ import { A_TYPES__FeatureDefineDecoratorMeta, A_TYPES__FeatureExtendDecoratorMeta } from "../A-Feature/A-Feature.types";
8
8
 
9
9
 
10
10
  // ============================================================================
@@ -85,13 +85,4 @@ export type A_TYPES__ContainerMeta = {
85
85
  }
86
86
 
87
87
 
88
- export type A_TYPES__ContainerMetaExtension = {
89
- /**
90
- * The name of original Extension Definition
91
- */
92
- name: string,
93
- /**
94
- * The name of the handler that will be used to apply the extension
95
- */
96
- handler: string,
97
- } & A_TYPES__FeatureExtendDecoratorBehaviorConfig
88
+ export type A_TYPES__ContainerMetaExtension = A_TYPES__FeatureExtendDecoratorMeta
@@ -662,8 +662,46 @@ export class A_Context {
662
662
  }
663
663
  }
664
664
 
665
- return steps;
665
+ return instance.filterToMostDerived(scope, steps);
666
+ }
667
+
668
+
669
+ /**
670
+ * method helps to filter steps in a way that only the most derived classes are kept.
671
+ *
672
+ * @param scope
673
+ * @param items
674
+ * @returns
675
+ */
676
+ private filterToMostDerived(
677
+ scope: A_Scope,
678
+ items: A_TYPES__A_StageStep[]): Array<A_TYPES__A_StageStep> {
679
+ return items.filter(item => {
680
+ const currentClass = typeof item.component === 'string'
681
+ ? scope.resolveConstructor(item.component)
682
+ : A_TypeGuards.isContainerInstance(item.component)
683
+ ? item.component.constructor : item.component;
684
+
685
+ // Check if this class is parent of any other in the list
686
+ const isParentOfAnother = items.some(other => {
687
+ if (other === item) return false;
688
+
689
+ const otherClass = typeof other.component === 'string'
690
+ ? scope.resolveConstructor(other.component)
691
+ : A_TypeGuards.isContainerInstance(other.component)
692
+ ? other.component.constructor
693
+ : other.component;
694
+
695
+
696
+ return currentClass.prototype.isPrototypeOf(otherClass.prototype);
697
+ });
698
+
699
+ // Keep only classes that are not parent of any other
700
+ return !isParentOfAnother;
701
+ });
666
702
  }
703
+
704
+
667
705
  /**
668
706
  * This method returns the feature template definition without any extensions.
669
707
  * It can be used to retrieve the base template for a feature before any modifications are applied.
@@ -825,11 +863,10 @@ export class A_Context {
825
863
  }
826
864
  }
827
865
 
828
- return steps;
866
+ return instance.filterToMostDerived(scope, steps);
829
867
  }
830
868
 
831
869
 
832
-
833
870
  /**
834
871
  * Resets the Context to its initial state.
835
872
  */
@@ -90,6 +90,7 @@ export function A_Feature_Define(
90
90
  before: item.before || [],
91
91
  after: item.after || [],
92
92
  behavior: item.behavior || 'sync',
93
+ throwOnError: true
93
94
  })
94
95
  ) : [],
95
96
  });
@@ -1,4 +1,3 @@
1
- import { A_Component } from "@adaas/a-concept/global/A-Component/A-Component.class";
2
1
  import { A_Context } from "@adaas/a-concept/global/A-Context/A-Context.class";
3
2
  import { A_Meta } from "@adaas/a-concept/global/A-Meta/A-Meta.class";
4
3
  import { A_TYPES__FeatureExtendDecoratorConfig, A_TYPES__FeatureExtendDecoratorDescriptor, A_TYPES__FeatureExtendDecoratorScopeItem, A_TYPES__FeatureExtendDecoratorTarget } from "./A-Feature.types";
@@ -79,6 +78,7 @@ export function A_Feature_Extend(
79
78
  let after: string[] = [];
80
79
  let include: Array<A_TYPES__FeatureExtendDecoratorScopeItem> = [];
81
80
  let exclude: Array<A_TYPES__FeatureExtendDecoratorScopeItem> = [];
81
+ let throwOnError: boolean = true;
82
82
 
83
83
 
84
84
 
@@ -102,12 +102,25 @@ export function A_Feature_Extend(
102
102
  targetRegexp = buildTargetRegexp(param1, include, exclude, propertyKey);
103
103
 
104
104
  behavior = param1.behavior || behavior;
105
- before = param1.before || before;
106
- after = param1.after || after;
105
+ throwOnError = param1.throwOnError !== undefined ? param1.throwOnError : throwOnError;
106
+
107
+ before = param1.before
108
+ ?.map(e =>
109
+ e instanceof RegExp
110
+ ? e.source
111
+ : new RegExp(`^.*${e.replace(/\./g, '\\.')}$`).source)
112
+ || before;
113
+ after = param1.after
114
+ ?.map(e =>
115
+ e instanceof RegExp
116
+ ? e.source
117
+ : new RegExp(`^.*${e.replace(/\./g, '\\.')}$`).source)
118
+ || after;
119
+
107
120
  break;
108
121
 
109
122
  default:
110
- targetRegexp = new RegExp(`^.*\\.${propertyKey}$`);
123
+ targetRegexp = new RegExp(`^.*${propertyKey.replace(/\./g, '\\.')}$`);
111
124
  break;
112
125
  }
113
126
 
@@ -136,14 +149,27 @@ export function A_Feature_Extend(
136
149
 
137
150
  const existedMetaValue = existedMeta.get(targetRegexp.source) || [];
138
151
 
139
- // Add the new method to the metadata
140
- existedMetaValue.push({
152
+ const existedIndex = existedMetaValue.findIndex(item => item.handler === propertyKey);
153
+
154
+ const extension = {
141
155
  name: targetRegexp.source,
142
156
  handler: propertyKey,
143
157
  behavior,
144
158
  before,
145
- after
146
- });
159
+ after,
160
+ throwOnError
161
+ }
162
+
163
+ if (existedIndex !== -1) {
164
+ // Update the existing method in the metadata
165
+ existedMetaValue[existedIndex] = extension;
166
+ } else {
167
+ // Add the new method to the metadata
168
+ existedMetaValue.push(extension);
169
+ }
170
+
171
+ // Add the new method to the metadata
172
+ existedMetaValue.push();
147
173
 
148
174
  // Set the metadata of the method to define a custom Feature with name
149
175
  existedMeta.set(targetRegexp.source, existedMetaValue);
@@ -8,7 +8,7 @@ import {
8
8
  import { A_Feature_Define } from "@adaas/a-concept/global/A-Feature/A-Feature-Define.decorator";
9
9
  import { A_Feature_Extend } from "@adaas/a-concept/global/A-Feature/A-Feature-Extend.decorator";
10
10
  import { A_Stage } from "../A-Stage/A-Stage.class";
11
- import { A_StepsManager } from "@adaas/a-concept/helpers/A_StepsManager.class";
11
+ import { A_StepsManager } from "@adaas/a-concept/global/A-StepManager/A-StepManager.class";
12
12
  import { A_StageError } from "../A-Stage/A-Stage.error";
13
13
  import { A_TypeGuards } from "@adaas/a-concept/helpers/A_TypeGuards.helper";
14
14
  import { A_FeatureError } from "./A-Feature.error";
@@ -391,4 +391,11 @@ export class A_Feature<T extends A_TYPES__FeatureAvailableComponents = A_TYPES__
391
391
 
392
392
  this._state = A_TYPES__FeatureState.INTERRUPTED;
393
393
  }
394
+
395
+
396
+
397
+
398
+ toString(): string {
399
+ return `A-Feature(${this.caller.component?.constructor?.name || 'Unknown'}::${this.name})`;
400
+ }
394
401
  }