@adaas/a-concept 0.3.5 → 0.3.7
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/README.md +116 -78
- package/benchmarks/feature-lifecycle.bench.ts +245 -0
- package/benchmarks/feature-profiling.bench.ts +415 -0
- package/benchmarks/feature-template.bench.ts +211 -0
- package/benchmarks/helpers.ts +97 -0
- package/benchmarks/run-all.ts +58 -0
- package/benchmarks/scope-resolve.bench.ts +245 -0
- package/benchmarks/step-manager.bench.ts +146 -0
- package/dist/browser/index.d.mts +70 -2
- package/dist/browser/index.mjs +2 -2
- package/dist/browser/index.mjs.map +1 -1
- package/dist/node/index.cjs +220 -58
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.mts +70 -2
- package/dist/node/index.d.ts +70 -2
- package/dist/node/index.mjs +220 -58
- package/dist/node/index.mjs.map +1 -1
- package/package.json +9 -1
- package/src/lib/A-Context/A-Context.class.ts +155 -60
- package/src/lib/A-Feature/A-Feature-Extend.decorator.ts +23 -7
- package/src/lib/A-Feature/A-Feature.types.ts +6 -10
- package/src/lib/A-Meta/A-Meta.class.ts +18 -3
- package/src/lib/A-Scope/A-Scope.class.ts +98 -5
- package/tests/A-Feature.test.ts +10 -19
- package/tsconfig.json +1 -0
package/dist/node/index.mjs
CHANGED
|
@@ -1320,20 +1320,17 @@ var A_Meta = class _A_Meta {
|
|
|
1320
1320
|
size() {
|
|
1321
1321
|
return this.meta.size;
|
|
1322
1322
|
}
|
|
1323
|
-
/**
|
|
1324
|
-
* This method is needed to convert the key to a regular expression and cover cases like:
|
|
1325
|
-
*
|
|
1326
|
-
* simple * e.g. "a*" instead of "a.*"
|
|
1327
|
-
*
|
|
1328
|
-
* simple ? e.g. "a?" instead of "a."
|
|
1329
|
-
*
|
|
1330
|
-
* etc.
|
|
1331
|
-
*
|
|
1332
|
-
* @param key
|
|
1333
|
-
* @returns
|
|
1334
|
-
*/
|
|
1335
1323
|
convertToRegExp(key) {
|
|
1336
|
-
|
|
1324
|
+
if (key instanceof RegExp) return key;
|
|
1325
|
+
if (!this._regExpCache) {
|
|
1326
|
+
this._regExpCache = /* @__PURE__ */ new Map();
|
|
1327
|
+
}
|
|
1328
|
+
let cached = this._regExpCache.get(key);
|
|
1329
|
+
if (!cached) {
|
|
1330
|
+
cached = new RegExp(key);
|
|
1331
|
+
this._regExpCache.set(key, cached);
|
|
1332
|
+
}
|
|
1333
|
+
return cached;
|
|
1337
1334
|
}
|
|
1338
1335
|
/**
|
|
1339
1336
|
* Method to find values in the map by name.
|
|
@@ -2812,14 +2809,20 @@ function A_Feature_Extend(param1) {
|
|
|
2812
2809
|
const existedMetaValue = [
|
|
2813
2810
|
...existedMeta.get(targetRegexp.source) || []
|
|
2814
2811
|
];
|
|
2812
|
+
const currentFeatureName = param1 && typeof param1 === "object" && !A_TypeGuards.isRegExp(param1) && param1.name || propertyKey;
|
|
2815
2813
|
for (const [key, handlers] of existedMeta.entries()) {
|
|
2816
2814
|
const indexInAnother = handlers.findIndex((item) => item.handler === propertyKey);
|
|
2817
2815
|
if (key !== targetRegexp.source && indexInAnother !== -1) {
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2816
|
+
const keyStr = String(key);
|
|
2817
|
+
const featureNameMatch = keyStr.match(/\\\.\s*([^\\.$]+)\$$/);
|
|
2818
|
+
const otherFeatureName = featureNameMatch ? featureNameMatch[1] : null;
|
|
2819
|
+
if (otherFeatureName === currentFeatureName) {
|
|
2820
|
+
handlers.splice(indexInAnother, 1);
|
|
2821
|
+
if (handlers.length === 0) {
|
|
2822
|
+
existedMeta.delete(key);
|
|
2823
|
+
} else {
|
|
2824
|
+
existedMeta.set(key, handlers);
|
|
2825
|
+
}
|
|
2823
2826
|
}
|
|
2824
2827
|
}
|
|
2825
2828
|
}
|
|
@@ -3676,8 +3679,13 @@ var A_ComponentMeta = class extends A_Meta {
|
|
|
3676
3679
|
};
|
|
3677
3680
|
|
|
3678
3681
|
// src/lib/A-Scope/A-Scope.class.ts
|
|
3679
|
-
var
|
|
3682
|
+
var _A_Scope = class _A_Scope {
|
|
3680
3683
|
constructor(param1, param2) {
|
|
3684
|
+
/**
|
|
3685
|
+
* Unique numeric ID for this scope instance. Used as a cache key discriminator
|
|
3686
|
+
* to prevent collisions between scopes with the same name or version.
|
|
3687
|
+
*/
|
|
3688
|
+
this.uid = _A_Scope._nextUid++;
|
|
3681
3689
|
/**
|
|
3682
3690
|
* Internal meta storage using A_Meta for type-safe key-value operations.
|
|
3683
3691
|
* This stores all the scope's runtime data that can be accessed and modified
|
|
@@ -3685,6 +3693,23 @@ var A_Scope = class {
|
|
|
3685
3693
|
*/
|
|
3686
3694
|
this._meta = new A_Meta();
|
|
3687
3695
|
// ===========================================================================
|
|
3696
|
+
// --------------------Cache & Versioning--------------------------------------
|
|
3697
|
+
// ===========================================================================
|
|
3698
|
+
/**
|
|
3699
|
+
* Monotonically increasing version counter. Incremented on every mutation
|
|
3700
|
+
* (register, deregister, import, deimport, inherit, destroy) so that
|
|
3701
|
+
* external caches (e.g. A_Context feature-extension cache) can detect
|
|
3702
|
+
* staleness cheaply via numeric comparison.
|
|
3703
|
+
*/
|
|
3704
|
+
this._version = 0;
|
|
3705
|
+
/**
|
|
3706
|
+
* Cache for resolveConstructor results (both positive and negative).
|
|
3707
|
+
* Key = constructor name (string) or constructor reference toString.
|
|
3708
|
+
* Value = resolved constructor or `null` for negative results.
|
|
3709
|
+
* Invalidated by incrementing _version (cache is cleared on bump).
|
|
3710
|
+
*/
|
|
3711
|
+
this._resolveConstructorCache = /* @__PURE__ */ new Map();
|
|
3712
|
+
// ===========================================================================
|
|
3688
3713
|
// --------------------ALLowed Constructors--------------------------------
|
|
3689
3714
|
// ===========================================================================
|
|
3690
3715
|
/**
|
|
@@ -3769,6 +3794,13 @@ var A_Scope = class {
|
|
|
3769
3794
|
get allowedErrors() {
|
|
3770
3795
|
return this._allowedErrors;
|
|
3771
3796
|
}
|
|
3797
|
+
/**
|
|
3798
|
+
* Returns the current version of the scope. Each mutation increments the version,
|
|
3799
|
+
* allowing external caches to detect staleness via numeric comparison.
|
|
3800
|
+
*/
|
|
3801
|
+
get version() {
|
|
3802
|
+
return this._version;
|
|
3803
|
+
}
|
|
3772
3804
|
// ===========================================================================
|
|
3773
3805
|
// --------------------Readonly Registered Properties--------------------------
|
|
3774
3806
|
// ===========================================================================
|
|
@@ -3820,6 +3852,14 @@ var A_Scope = class {
|
|
|
3820
3852
|
get parent() {
|
|
3821
3853
|
return this._parent;
|
|
3822
3854
|
}
|
|
3855
|
+
/**
|
|
3856
|
+
* Increments the scope version and clears internal caches.
|
|
3857
|
+
* Must be called on every scope mutation (register, deregister, import, deimport, inherit, destroy).
|
|
3858
|
+
*/
|
|
3859
|
+
bumpVersion() {
|
|
3860
|
+
this._version++;
|
|
3861
|
+
this._resolveConstructorCache.clear();
|
|
3862
|
+
}
|
|
3823
3863
|
/**
|
|
3824
3864
|
* Generator to iterate through all parent scopes
|
|
3825
3865
|
*/
|
|
@@ -3953,6 +3993,7 @@ var A_Scope = class {
|
|
|
3953
3993
|
if (this.issuer()) {
|
|
3954
3994
|
A_Context.deallocate(this);
|
|
3955
3995
|
}
|
|
3996
|
+
this.bumpVersion();
|
|
3956
3997
|
}
|
|
3957
3998
|
/**
|
|
3958
3999
|
* Retrieves a value from the scope's meta.
|
|
@@ -4028,6 +4069,7 @@ var A_Scope = class {
|
|
|
4028
4069
|
`Circular inheritance detected: ${[...circularCheck, parent.name].join(" -> ")}`
|
|
4029
4070
|
);
|
|
4030
4071
|
this._parent = parent;
|
|
4072
|
+
this.bumpVersion();
|
|
4031
4073
|
return this;
|
|
4032
4074
|
}
|
|
4033
4075
|
/**
|
|
@@ -4049,6 +4091,7 @@ var A_Scope = class {
|
|
|
4049
4091
|
if (this._imports.has(scope))
|
|
4050
4092
|
return;
|
|
4051
4093
|
this._imports.add(scope);
|
|
4094
|
+
this.bumpVersion();
|
|
4052
4095
|
});
|
|
4053
4096
|
return this;
|
|
4054
4097
|
}
|
|
@@ -4061,8 +4104,10 @@ var A_Scope = class {
|
|
|
4061
4104
|
*/
|
|
4062
4105
|
deimport(...scopes) {
|
|
4063
4106
|
scopes.forEach((scope) => {
|
|
4064
|
-
if (this._imports.has(scope))
|
|
4107
|
+
if (this._imports.has(scope)) {
|
|
4065
4108
|
this._imports.delete(scope);
|
|
4109
|
+
this.bumpVersion();
|
|
4110
|
+
}
|
|
4066
4111
|
});
|
|
4067
4112
|
return this;
|
|
4068
4113
|
}
|
|
@@ -4203,6 +4248,20 @@ var A_Scope = class {
|
|
|
4203
4248
|
A_ScopeError.ResolutionError,
|
|
4204
4249
|
`Invalid constructor name provided: ${name}`
|
|
4205
4250
|
);
|
|
4251
|
+
const cacheKey = name;
|
|
4252
|
+
if (this._resolveConstructorCache.has(cacheKey)) {
|
|
4253
|
+
const cached = this._resolveConstructorCache.get(cacheKey);
|
|
4254
|
+
return cached === null ? void 0 : cached;
|
|
4255
|
+
}
|
|
4256
|
+
const resolved = this._resolveConstructorUncached(name);
|
|
4257
|
+
this._resolveConstructorCache.set(cacheKey, resolved ?? null);
|
|
4258
|
+
return resolved;
|
|
4259
|
+
}
|
|
4260
|
+
/**
|
|
4261
|
+
* Internal uncached implementation of resolveConstructor for string names.
|
|
4262
|
+
* Separated to allow the public method to wrap with caching.
|
|
4263
|
+
*/
|
|
4264
|
+
_resolveConstructorUncached(name) {
|
|
4206
4265
|
const component = Array.from(this.allowedComponents).find(
|
|
4207
4266
|
(c) => c.name === name || c.name === A_FormatterHelper.toPascalCase(name)
|
|
4208
4267
|
);
|
|
@@ -4550,6 +4609,7 @@ var A_Scope = class {
|
|
|
4550
4609
|
param1
|
|
4551
4610
|
);
|
|
4552
4611
|
A_Context.register(this, param1);
|
|
4612
|
+
this.bumpVersion();
|
|
4553
4613
|
break;
|
|
4554
4614
|
}
|
|
4555
4615
|
// 3) In case when it's a A-Entity instance
|
|
@@ -4558,6 +4618,7 @@ var A_Scope = class {
|
|
|
4558
4618
|
this.allowedEntities.add(param1.constructor);
|
|
4559
4619
|
this._entities.set(param1.aseid.toString(), param1);
|
|
4560
4620
|
A_Context.register(this, param1);
|
|
4621
|
+
this.bumpVersion();
|
|
4561
4622
|
break;
|
|
4562
4623
|
}
|
|
4563
4624
|
// 4) In case when it's a A-Fragment instance
|
|
@@ -4569,6 +4630,7 @@ var A_Scope = class {
|
|
|
4569
4630
|
param1
|
|
4570
4631
|
);
|
|
4571
4632
|
A_Context.register(this, param1);
|
|
4633
|
+
this.bumpVersion();
|
|
4572
4634
|
break;
|
|
4573
4635
|
}
|
|
4574
4636
|
// 5) In case when it's a A-Error instance
|
|
@@ -4580,6 +4642,7 @@ var A_Scope = class {
|
|
|
4580
4642
|
param1
|
|
4581
4643
|
);
|
|
4582
4644
|
A_Context.register(this, param1);
|
|
4645
|
+
this.bumpVersion();
|
|
4583
4646
|
break;
|
|
4584
4647
|
}
|
|
4585
4648
|
// ------------------------------------------
|
|
@@ -4587,26 +4650,34 @@ var A_Scope = class {
|
|
|
4587
4650
|
// ------------------------------------------
|
|
4588
4651
|
// 6) In case when it's a A-Component constructor
|
|
4589
4652
|
case A_TypeGuards.isComponentConstructor(param1): {
|
|
4590
|
-
if (!this.allowedComponents.has(param1))
|
|
4653
|
+
if (!this.allowedComponents.has(param1)) {
|
|
4591
4654
|
this.allowedComponents.add(param1);
|
|
4655
|
+
this.bumpVersion();
|
|
4656
|
+
}
|
|
4592
4657
|
break;
|
|
4593
4658
|
}
|
|
4594
4659
|
// 8) In case when it's a A-Fragment constructor
|
|
4595
4660
|
case A_TypeGuards.isFragmentConstructor(param1): {
|
|
4596
|
-
if (!this.allowedFragments.has(param1))
|
|
4661
|
+
if (!this.allowedFragments.has(param1)) {
|
|
4597
4662
|
this.allowedFragments.add(param1);
|
|
4663
|
+
this.bumpVersion();
|
|
4664
|
+
}
|
|
4598
4665
|
break;
|
|
4599
4666
|
}
|
|
4600
4667
|
// 9) In case when it's a A-Entity constructor
|
|
4601
4668
|
case A_TypeGuards.isEntityConstructor(param1): {
|
|
4602
|
-
if (!this.allowedEntities.has(param1))
|
|
4669
|
+
if (!this.allowedEntities.has(param1)) {
|
|
4603
4670
|
this.allowedEntities.add(param1);
|
|
4671
|
+
this.bumpVersion();
|
|
4672
|
+
}
|
|
4604
4673
|
break;
|
|
4605
4674
|
}
|
|
4606
4675
|
// 10) In case when it's a A-Error constructor
|
|
4607
4676
|
case A_TypeGuards.isErrorConstructor(param1): {
|
|
4608
|
-
if (!this.allowedErrors.has(param1))
|
|
4677
|
+
if (!this.allowedErrors.has(param1)) {
|
|
4609
4678
|
this.allowedErrors.add(param1);
|
|
4679
|
+
this.bumpVersion();
|
|
4680
|
+
}
|
|
4610
4681
|
break;
|
|
4611
4682
|
}
|
|
4612
4683
|
// ------------------------------------------
|
|
@@ -4646,6 +4717,7 @@ var A_Scope = class {
|
|
|
4646
4717
|
if (!hasComponent) {
|
|
4647
4718
|
this.allowedComponents.delete(ctor);
|
|
4648
4719
|
}
|
|
4720
|
+
this.bumpVersion();
|
|
4649
4721
|
break;
|
|
4650
4722
|
}
|
|
4651
4723
|
// 3) In case when it's a A-Entity instance
|
|
@@ -4657,6 +4729,7 @@ var A_Scope = class {
|
|
|
4657
4729
|
if (!hasEntity) {
|
|
4658
4730
|
this.allowedEntities.delete(ctor);
|
|
4659
4731
|
}
|
|
4732
|
+
this.bumpVersion();
|
|
4660
4733
|
break;
|
|
4661
4734
|
}
|
|
4662
4735
|
// 4) In case when it's a A-Fragment instance
|
|
@@ -4668,6 +4741,7 @@ var A_Scope = class {
|
|
|
4668
4741
|
if (!hasFragment) {
|
|
4669
4742
|
this.allowedFragments.delete(ctor);
|
|
4670
4743
|
}
|
|
4744
|
+
this.bumpVersion();
|
|
4671
4745
|
break;
|
|
4672
4746
|
}
|
|
4673
4747
|
// 5) In case when it's a A-Error instance
|
|
@@ -4679,6 +4753,7 @@ var A_Scope = class {
|
|
|
4679
4753
|
if (!hasError) {
|
|
4680
4754
|
this.allowedErrors.delete(ctor);
|
|
4681
4755
|
}
|
|
4756
|
+
this.bumpVersion();
|
|
4682
4757
|
break;
|
|
4683
4758
|
}
|
|
4684
4759
|
// ------------------------------------------
|
|
@@ -4687,6 +4762,7 @@ var A_Scope = class {
|
|
|
4687
4762
|
// 6) In case when it's a A-Component constructor
|
|
4688
4763
|
case A_TypeGuards.isComponentConstructor(param1): {
|
|
4689
4764
|
this.allowedComponents.delete(param1);
|
|
4765
|
+
this.bumpVersion();
|
|
4690
4766
|
break;
|
|
4691
4767
|
}
|
|
4692
4768
|
// 8) In case when it's a A-Fragment constructor
|
|
@@ -4698,6 +4774,7 @@ var A_Scope = class {
|
|
|
4698
4774
|
A_Context.deregister(instance);
|
|
4699
4775
|
}
|
|
4700
4776
|
});
|
|
4777
|
+
this.bumpVersion();
|
|
4701
4778
|
break;
|
|
4702
4779
|
}
|
|
4703
4780
|
// 9) In case when it's a A-Entity constructor
|
|
@@ -4709,6 +4786,7 @@ var A_Scope = class {
|
|
|
4709
4786
|
A_Context.deregister(instance);
|
|
4710
4787
|
}
|
|
4711
4788
|
});
|
|
4789
|
+
this.bumpVersion();
|
|
4712
4790
|
break;
|
|
4713
4791
|
}
|
|
4714
4792
|
// 10) In case when it's a A-Error constructor
|
|
@@ -4720,6 +4798,7 @@ var A_Scope = class {
|
|
|
4720
4798
|
A_Context.deregister(instance);
|
|
4721
4799
|
}
|
|
4722
4800
|
});
|
|
4801
|
+
this.bumpVersion();
|
|
4723
4802
|
break;
|
|
4724
4803
|
}
|
|
4725
4804
|
// ------------------------------------------
|
|
@@ -4840,6 +4919,11 @@ var A_Scope = class {
|
|
|
4840
4919
|
console.log(chain.join(" -> "));
|
|
4841
4920
|
}
|
|
4842
4921
|
};
|
|
4922
|
+
/**
|
|
4923
|
+
* Auto-incrementing counter for generating unique scope IDs.
|
|
4924
|
+
*/
|
|
4925
|
+
_A_Scope._nextUid = 0;
|
|
4926
|
+
var A_Scope = _A_Scope;
|
|
4843
4927
|
|
|
4844
4928
|
// src/lib/A-Scope/A-Scope.error.ts
|
|
4845
4929
|
var A_ScopeError = class extends A_Error {
|
|
@@ -4876,7 +4960,7 @@ A_ContextError.ComponentNotRegisteredError = "Component not registered in the co
|
|
|
4876
4960
|
A_ContextError.InvalidDeregisterParameterError = "Invalid parameter provided to deregister component";
|
|
4877
4961
|
|
|
4878
4962
|
// src/lib/A-Context/A-Context.class.ts
|
|
4879
|
-
var
|
|
4963
|
+
var _A_Context = class _A_Context {
|
|
4880
4964
|
/**
|
|
4881
4965
|
* Private constructor to enforce singleton pattern.
|
|
4882
4966
|
*
|
|
@@ -4903,6 +4987,18 @@ var A_Context = class _A_Context {
|
|
|
4903
4987
|
* Meta provides to store extra information about the class behavior and configuration.
|
|
4904
4988
|
*/
|
|
4905
4989
|
this._metaStorage = /* @__PURE__ */ new Map();
|
|
4990
|
+
/**
|
|
4991
|
+
* Monotonically increasing version counter for _metaStorage.
|
|
4992
|
+
* Incremented whenever a new entry is added to _metaStorage so that
|
|
4993
|
+
* caches depending on meta content can detect staleness.
|
|
4994
|
+
*/
|
|
4995
|
+
this._metaVersion = 0;
|
|
4996
|
+
/**
|
|
4997
|
+
* Cache for featureExtensions results.
|
|
4998
|
+
* Key format: `${featureName}::${componentConstructorName}::${scopeVersion}::${metaVersion}`
|
|
4999
|
+
* Automatically invalidated when scope version or meta version changes.
|
|
5000
|
+
*/
|
|
5001
|
+
this._featureExtensionsCache = /* @__PURE__ */ new Map();
|
|
4906
5002
|
this._globals = /* @__PURE__ */ new Map();
|
|
4907
5003
|
const name = String(A_CONCEPT_ENV.A_CONCEPT_ROOT_SCOPE) || "root";
|
|
4908
5004
|
this._root = new A_Scope({ name });
|
|
@@ -5106,6 +5202,7 @@ var A_Context = class _A_Context {
|
|
|
5106
5202
|
if (!inheritedMeta)
|
|
5107
5203
|
inheritedMeta = new metaType();
|
|
5108
5204
|
instance._metaStorage.set(property, inheritedMeta.clone());
|
|
5205
|
+
instance._metaVersion++;
|
|
5109
5206
|
}
|
|
5110
5207
|
return instance._metaStorage.get(property);
|
|
5111
5208
|
}
|
|
@@ -5114,6 +5211,7 @@ var A_Context = class _A_Context {
|
|
|
5114
5211
|
const existingMeta = _A_Context.meta(param1);
|
|
5115
5212
|
const constructor = typeof param1 === "function" ? param1 : param1.constructor;
|
|
5116
5213
|
instance._metaStorage.set(constructor, existingMeta ? meta.from(existingMeta) : meta);
|
|
5214
|
+
instance._metaVersion++;
|
|
5117
5215
|
}
|
|
5118
5216
|
/**
|
|
5119
5217
|
*
|
|
@@ -5169,11 +5267,10 @@ var A_Context = class _A_Context {
|
|
|
5169
5267
|
* @param name
|
|
5170
5268
|
*/
|
|
5171
5269
|
static featureTemplate(name, component, scope = this.scope(component)) {
|
|
5172
|
-
const componentName = A_CommonHelper.getComponentName(component);
|
|
5173
5270
|
if (!component) throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Component cannot be null or undefined.`);
|
|
5174
5271
|
if (!name) throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Feature name cannot be null or undefined.`);
|
|
5175
5272
|
if (!A_TypeGuards.isAllowedForFeatureDefinition(component))
|
|
5176
|
-
throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Component of type ${
|
|
5273
|
+
throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Component of type ${A_CommonHelper.getComponentName(component)} is not allowed for feature definition.`);
|
|
5177
5274
|
const steps = [
|
|
5178
5275
|
// 1) Get the base feature definition from the component
|
|
5179
5276
|
...this.featureDefinition(name, component),
|
|
@@ -5196,59 +5293,116 @@ var A_Context = class _A_Context {
|
|
|
5196
5293
|
*/
|
|
5197
5294
|
static featureExtensions(name, component, scope) {
|
|
5198
5295
|
const instance = this.getInstance();
|
|
5199
|
-
const componentName = A_CommonHelper.getComponentName(component);
|
|
5200
5296
|
if (!component) throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Component cannot be null or undefined.`);
|
|
5201
5297
|
if (!name) throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Feature name cannot be null or undefined.`);
|
|
5202
5298
|
if (!A_TypeGuards.isAllowedForFeatureDefinition(component))
|
|
5203
|
-
throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Component of type ${
|
|
5299
|
+
throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Component of type ${A_CommonHelper.getComponentName(component)} is not allowed for feature definition.`);
|
|
5300
|
+
const componentCtor = typeof component === "function" ? component : component.constructor;
|
|
5301
|
+
const effectiveScope = scope.parent || scope;
|
|
5302
|
+
const cacheKey = `${String(name)}::${componentCtor.name}::s${effectiveScope.uid}v${effectiveScope.version}::m${instance._metaVersion}`;
|
|
5303
|
+
const cached = instance._featureExtensionsCache.get(cacheKey);
|
|
5304
|
+
if (cached) {
|
|
5305
|
+
return cached;
|
|
5306
|
+
}
|
|
5204
5307
|
const callNames = A_CommonHelper.getClassInheritanceChain(component).filter((c) => c !== A_Component && c !== A_Container && c !== A_Entity).map((c) => `${c.name}.${name}`);
|
|
5205
5308
|
const steps = /* @__PURE__ */ new Map();
|
|
5206
5309
|
const allowedComponents = /* @__PURE__ */ new Set();
|
|
5310
|
+
const componentNameCache = /* @__PURE__ */ new Map();
|
|
5311
|
+
const dependencyCache = /* @__PURE__ */ new Map();
|
|
5312
|
+
const getNameCached = (cmp) => {
|
|
5313
|
+
let n = componentNameCache.get(cmp);
|
|
5314
|
+
if (n === void 0) {
|
|
5315
|
+
n = A_CommonHelper.getComponentName(cmp);
|
|
5316
|
+
componentNameCache.set(cmp, n);
|
|
5317
|
+
}
|
|
5318
|
+
return n;
|
|
5319
|
+
};
|
|
5320
|
+
const getDependencyCached = (cmp) => {
|
|
5321
|
+
let d = dependencyCache.get(cmp);
|
|
5322
|
+
if (!d) {
|
|
5323
|
+
d = new A_Dependency(cmp);
|
|
5324
|
+
dependencyCache.set(cmp, d);
|
|
5325
|
+
}
|
|
5326
|
+
return d;
|
|
5327
|
+
};
|
|
5328
|
+
const scopeFilteredMetas = [];
|
|
5329
|
+
for (const [cmp, meta] of instance._metaStorage) {
|
|
5330
|
+
if (scope.has(cmp) && (A_TypeGuards.isComponentMetaInstance(meta) || A_TypeGuards.isContainerMetaInstance(meta))) {
|
|
5331
|
+
scopeFilteredMetas.push([cmp, meta]);
|
|
5332
|
+
}
|
|
5333
|
+
}
|
|
5207
5334
|
for (const callName of callNames) {
|
|
5208
|
-
for (const [cmp, meta] of
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
}
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5335
|
+
for (const [cmp, meta] of scopeFilteredMetas) {
|
|
5336
|
+
allowedComponents.add(cmp);
|
|
5337
|
+
const extensions = meta.extensions(callName);
|
|
5338
|
+
for (let i = 0; i < extensions.length; i++) {
|
|
5339
|
+
const declaration = extensions[i];
|
|
5340
|
+
const inherited = Array.from(allowedComponents).reverse().find((c) => A_CommonHelper.isInheritedFrom(cmp, c) && c !== cmp);
|
|
5341
|
+
if (inherited) {
|
|
5342
|
+
steps.delete(`${getNameCached(inherited)}.${declaration.handler}`);
|
|
5343
|
+
}
|
|
5344
|
+
if (declaration.override) {
|
|
5345
|
+
const overrideRegexp = new RegExp(declaration.override);
|
|
5346
|
+
for (const [stepKey, step] of steps) {
|
|
5347
|
+
if (overrideRegexp.test(stepKey) || overrideRegexp.test(step.handler)) {
|
|
5348
|
+
steps.delete(stepKey);
|
|
5222
5349
|
}
|
|
5223
5350
|
}
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5351
|
+
}
|
|
5352
|
+
steps.set(`${getNameCached(cmp)}.${declaration.handler}`, {
|
|
5353
|
+
dependency: getDependencyCached(cmp),
|
|
5354
|
+
...declaration
|
|
5228
5355
|
});
|
|
5229
5356
|
}
|
|
5230
5357
|
}
|
|
5231
5358
|
}
|
|
5232
|
-
|
|
5359
|
+
const result = instance.filterToMostDerived(scope, Array.from(steps.values()));
|
|
5360
|
+
if (instance._featureExtensionsCache.size >= _A_Context.FEATURE_EXTENSIONS_CACHE_MAX_SIZE) {
|
|
5361
|
+
instance._featureExtensionsCache.clear();
|
|
5362
|
+
}
|
|
5363
|
+
instance._featureExtensionsCache.set(cacheKey, result);
|
|
5364
|
+
return result;
|
|
5233
5365
|
}
|
|
5234
5366
|
/**
|
|
5235
5367
|
* method helps to filter steps in a way that only the most derived classes are kept.
|
|
5236
5368
|
*
|
|
5369
|
+
* Optimized: Uses a pre-built constructor→class map and single-pass prototype chain
|
|
5370
|
+
* walk to eliminate parent classes in O(n·d) where d is inheritance depth,
|
|
5371
|
+
* instead of the previous O(n²) with isPrototypeOf checks.
|
|
5372
|
+
*
|
|
5237
5373
|
* @param scope
|
|
5238
5374
|
* @param items
|
|
5239
5375
|
* @returns
|
|
5240
5376
|
*/
|
|
5241
5377
|
filterToMostDerived(scope, items) {
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
}
|
|
5250
|
-
|
|
5251
|
-
}
|
|
5378
|
+
if (items.length <= 1) return items;
|
|
5379
|
+
const resolvedClasses = /* @__PURE__ */ new Map();
|
|
5380
|
+
const presentNames = /* @__PURE__ */ new Set();
|
|
5381
|
+
for (const item of items) {
|
|
5382
|
+
const depName = item.dependency.name;
|
|
5383
|
+
if (!resolvedClasses.has(depName)) {
|
|
5384
|
+
resolvedClasses.set(depName, scope.resolveConstructor(depName));
|
|
5385
|
+
}
|
|
5386
|
+
presentNames.add(depName);
|
|
5387
|
+
}
|
|
5388
|
+
const parentNames = /* @__PURE__ */ new Set();
|
|
5389
|
+
const ctorToName = /* @__PURE__ */ new Map();
|
|
5390
|
+
for (const [depName, ctor] of resolvedClasses) {
|
|
5391
|
+
if (ctor) ctorToName.set(ctor, depName);
|
|
5392
|
+
}
|
|
5393
|
+
for (const [depName, ctor] of resolvedClasses) {
|
|
5394
|
+
if (!ctor) continue;
|
|
5395
|
+
let ancestor = Object.getPrototypeOf(ctor.prototype);
|
|
5396
|
+
while (ancestor && ancestor !== Object.prototype) {
|
|
5397
|
+
const ancestorCtor = ancestor.constructor;
|
|
5398
|
+
const ancestorName = ctorToName.get(ancestorCtor);
|
|
5399
|
+
if (ancestorName && ancestorName !== depName && presentNames.has(ancestorName)) {
|
|
5400
|
+
parentNames.add(ancestorName);
|
|
5401
|
+
}
|
|
5402
|
+
ancestor = Object.getPrototypeOf(ancestor);
|
|
5403
|
+
}
|
|
5404
|
+
}
|
|
5405
|
+
return items.filter((item) => !parentNames.has(item.dependency.name));
|
|
5252
5406
|
}
|
|
5253
5407
|
/**
|
|
5254
5408
|
* This method returns the feature template definition without any extensions.
|
|
@@ -5363,6 +5517,8 @@ var A_Context = class _A_Context {
|
|
|
5363
5517
|
static reset() {
|
|
5364
5518
|
const instance = _A_Context.getInstance();
|
|
5365
5519
|
instance._registry = /* @__PURE__ */ new WeakMap();
|
|
5520
|
+
instance._featureExtensionsCache.clear();
|
|
5521
|
+
instance._metaVersion++;
|
|
5366
5522
|
const name = String(A_CONCEPT_ENV.A_CONCEPT_ROOT_SCOPE) || "root";
|
|
5367
5523
|
instance._root = new A_Scope({ name });
|
|
5368
5524
|
}
|
|
@@ -5406,6 +5562,12 @@ var A_Context = class _A_Context {
|
|
|
5406
5562
|
return A_TypeGuards.isContainerConstructor(param) || A_TypeGuards.isComponentConstructor(param) || A_TypeGuards.isEntityConstructor(param);
|
|
5407
5563
|
}
|
|
5408
5564
|
};
|
|
5565
|
+
/**
|
|
5566
|
+
* Maximum number of entries in the featureExtensions cache.
|
|
5567
|
+
* When exceeded, the entire cache is cleared to prevent unbounded growth.
|
|
5568
|
+
*/
|
|
5569
|
+
_A_Context.FEATURE_EXTENSIONS_CACHE_MAX_SIZE = 1024;
|
|
5570
|
+
var A_Context = _A_Context;
|
|
5409
5571
|
|
|
5410
5572
|
// src/lib/A-Abstraction/A-Abstraction.error.ts
|
|
5411
5573
|
var A_AbstractionError = class extends A_Error {
|