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