@adaas/a-concept 0.3.6 → 0.3.8
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-chaining.bench.ts +465 -0
- package/benchmarks/feature-lifecycle.bench.ts +245 -0
- package/benchmarks/feature-optimize.bench.ts +205 -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 +72 -3
- package/dist/browser/index.mjs +2 -2
- package/dist/browser/index.mjs.map +1 -1
- package/dist/node/index.cjs +244 -87
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.mts +72 -3
- package/dist/node/index.d.ts +72 -3
- package/dist/node/index.mjs +244 -87
- package/dist/node/index.mjs.map +1 -1
- package/package.json +11 -1
- package/src/lib/A-Context/A-Context.class.ts +155 -60
- package/src/lib/A-Entity/A-Entity.class.ts +3 -3
- package/src/lib/A-Feature/A-Feature.class.ts +46 -41
- 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 +101 -0
- package/tsconfig.json +1 -0
package/dist/node/index.cjs
CHANGED
|
@@ -1119,13 +1119,13 @@ var A_Entity = class {
|
|
|
1119
1119
|
* @param lifecycleMethod
|
|
1120
1120
|
* @param args
|
|
1121
1121
|
*/
|
|
1122
|
-
|
|
1122
|
+
call(feature, scope) {
|
|
1123
1123
|
const newFeature = new A_Feature({
|
|
1124
1124
|
name: feature,
|
|
1125
1125
|
component: this,
|
|
1126
1126
|
scope
|
|
1127
1127
|
});
|
|
1128
|
-
return
|
|
1128
|
+
return newFeature.process(scope);
|
|
1129
1129
|
}
|
|
1130
1130
|
// ====================================================================
|
|
1131
1131
|
// ================== Entity Base Methods =============================
|
|
@@ -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.
|
|
@@ -3329,7 +3326,7 @@ var A_Feature = class _A_Feature {
|
|
|
3329
3326
|
if (!params || typeof params !== "object") {
|
|
3330
3327
|
throw new A_FeatureError(
|
|
3331
3328
|
A_FeatureError.FeatureInitializationError,
|
|
3332
|
-
`Invalid A-Feature initialization parameters of type: ${typeof params} with value: ${JSON.stringify(params)
|
|
3329
|
+
`Invalid A-Feature initialization parameters of type: ${typeof params} with value: ${JSON.stringify(params)?.slice(0, 100)}...`
|
|
3333
3330
|
);
|
|
3334
3331
|
}
|
|
3335
3332
|
}
|
|
@@ -3348,7 +3345,7 @@ var A_Feature = class _A_Feature {
|
|
|
3348
3345
|
default:
|
|
3349
3346
|
throw new A_FeatureError(
|
|
3350
3347
|
A_FeatureError.FeatureInitializationError,
|
|
3351
|
-
`Invalid A-Feature initialization parameters of type: ${typeof params} with value: ${JSON.stringify(params)
|
|
3348
|
+
`Invalid A-Feature initialization parameters of type: ${typeof params} with value: ${JSON.stringify(params)?.slice(0, 100)}...`
|
|
3352
3349
|
);
|
|
3353
3350
|
}
|
|
3354
3351
|
}
|
|
@@ -3361,13 +3358,13 @@ var A_Feature = class _A_Feature {
|
|
|
3361
3358
|
if (!params.template || !Array.isArray(params.template)) {
|
|
3362
3359
|
throw new A_FeatureError(
|
|
3363
3360
|
A_FeatureError.FeatureInitializationError,
|
|
3364
|
-
`Invalid A-Feature template provided of type: ${typeof params.template} with value: ${JSON.stringify(params.template)
|
|
3361
|
+
`Invalid A-Feature template provided of type: ${typeof params.template} with value: ${JSON.stringify(params.template)?.slice(0, 100)}...`
|
|
3365
3362
|
);
|
|
3366
3363
|
}
|
|
3367
3364
|
if (!params.component && (!params.scope || !(params.scope instanceof A_Scope))) {
|
|
3368
3365
|
throw new A_FeatureError(
|
|
3369
3366
|
A_FeatureError.FeatureInitializationError,
|
|
3370
|
-
`Invalid A-Feature scope provided of type: ${typeof params.scope} with value: ${JSON.stringify(params.scope)
|
|
3367
|
+
`Invalid A-Feature scope provided of type: ${typeof params.scope} with value: ${JSON.stringify(params.scope)?.slice(0, 100)}...`
|
|
3371
3368
|
);
|
|
3372
3369
|
}
|
|
3373
3370
|
this._name = params.name;
|
|
@@ -3399,7 +3396,7 @@ var A_Feature = class _A_Feature {
|
|
|
3399
3396
|
if (!params.component || !A_TypeGuards.isAllowedForFeatureDefinition(params.component)) {
|
|
3400
3397
|
throw new A_FeatureError(
|
|
3401
3398
|
A_FeatureError.FeatureInitializationError,
|
|
3402
|
-
`Invalid A-Feature component provided of type: ${typeof params.component} with value: ${JSON.stringify(params.component)
|
|
3399
|
+
`Invalid A-Feature component provided of type: ${typeof params.component} with value: ${JSON.stringify(params.component)?.slice(0, 100)}...`
|
|
3403
3400
|
);
|
|
3404
3401
|
}
|
|
3405
3402
|
this._name = params.name;
|
|
@@ -3449,41 +3446,42 @@ var A_Feature = class _A_Feature {
|
|
|
3449
3446
|
* Process stages one by one, ensuring each stage completes before starting the next
|
|
3450
3447
|
*/
|
|
3451
3448
|
processStagesSequentially(stages, scope, index) {
|
|
3452
|
-
|
|
3453
|
-
if (this.state === "INTERRUPTED" /* INTERRUPTED */)
|
|
3454
|
-
return;
|
|
3455
|
-
}
|
|
3456
|
-
if (index >= stages.length) {
|
|
3457
|
-
this.completed();
|
|
3458
|
-
return;
|
|
3459
|
-
}
|
|
3449
|
+
while (index < stages.length) {
|
|
3450
|
+
if (this.state === "INTERRUPTED" /* INTERRUPTED */) return;
|
|
3460
3451
|
const stage = stages[index];
|
|
3461
|
-
|
|
3452
|
+
let result;
|
|
3453
|
+
try {
|
|
3454
|
+
result = stage.process(scope);
|
|
3455
|
+
} catch (error) {
|
|
3456
|
+
throw this.createStageError(error, stage);
|
|
3457
|
+
}
|
|
3462
3458
|
if (A_TypeGuards.isPromiseInstance(result)) {
|
|
3463
3459
|
return result.then(() => {
|
|
3464
|
-
if (this.state === "INTERRUPTED" /* INTERRUPTED */)
|
|
3465
|
-
return;
|
|
3466
|
-
}
|
|
3460
|
+
if (this.state === "INTERRUPTED" /* INTERRUPTED */) return;
|
|
3467
3461
|
return this.processStagesSequentially(stages, scope, index + 1);
|
|
3468
3462
|
}).catch((error) => {
|
|
3469
|
-
throw this.
|
|
3470
|
-
title: A_FeatureError.FeatureProcessingError,
|
|
3471
|
-
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${stage.name}.`,
|
|
3472
|
-
stage,
|
|
3473
|
-
originalError: error
|
|
3474
|
-
}));
|
|
3463
|
+
throw this.createStageError(error, stage);
|
|
3475
3464
|
});
|
|
3476
|
-
} else {
|
|
3477
|
-
return this.processStagesSequentially(stages, scope, index + 1);
|
|
3478
3465
|
}
|
|
3479
|
-
|
|
3480
|
-
throw this.failed(new A_FeatureError({
|
|
3481
|
-
title: A_FeatureError.FeatureProcessingError,
|
|
3482
|
-
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${this.stage?.name || "N/A"}.`,
|
|
3483
|
-
stage: this.stage,
|
|
3484
|
-
originalError: error
|
|
3485
|
-
}));
|
|
3466
|
+
index++;
|
|
3486
3467
|
}
|
|
3468
|
+
if (this.state !== "INTERRUPTED" /* INTERRUPTED */) {
|
|
3469
|
+
this.completed();
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
createStageError(error, stage) {
|
|
3473
|
+
this.failed(new A_FeatureError({
|
|
3474
|
+
title: A_FeatureError.FeatureProcessingError,
|
|
3475
|
+
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${stage.name}.`,
|
|
3476
|
+
stage,
|
|
3477
|
+
originalError: error
|
|
3478
|
+
}));
|
|
3479
|
+
return new A_FeatureError({
|
|
3480
|
+
title: A_FeatureError.FeatureProcessingError,
|
|
3481
|
+
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${stage.name}.`,
|
|
3482
|
+
stage,
|
|
3483
|
+
originalError: error
|
|
3484
|
+
});
|
|
3487
3485
|
}
|
|
3488
3486
|
/**
|
|
3489
3487
|
* This method moves the feature to the next stage
|
|
@@ -3684,8 +3682,13 @@ var A_ComponentMeta = class extends A_Meta {
|
|
|
3684
3682
|
};
|
|
3685
3683
|
|
|
3686
3684
|
// src/lib/A-Scope/A-Scope.class.ts
|
|
3687
|
-
var
|
|
3685
|
+
var _A_Scope = class _A_Scope {
|
|
3688
3686
|
constructor(param1, param2) {
|
|
3687
|
+
/**
|
|
3688
|
+
* Unique numeric ID for this scope instance. Used as a cache key discriminator
|
|
3689
|
+
* to prevent collisions between scopes with the same name or version.
|
|
3690
|
+
*/
|
|
3691
|
+
this.uid = _A_Scope._nextUid++;
|
|
3689
3692
|
/**
|
|
3690
3693
|
* Internal meta storage using A_Meta for type-safe key-value operations.
|
|
3691
3694
|
* This stores all the scope's runtime data that can be accessed and modified
|
|
@@ -3693,6 +3696,23 @@ var A_Scope = class {
|
|
|
3693
3696
|
*/
|
|
3694
3697
|
this._meta = new A_Meta();
|
|
3695
3698
|
// ===========================================================================
|
|
3699
|
+
// --------------------Cache & Versioning--------------------------------------
|
|
3700
|
+
// ===========================================================================
|
|
3701
|
+
/**
|
|
3702
|
+
* Monotonically increasing version counter. Incremented on every mutation
|
|
3703
|
+
* (register, deregister, import, deimport, inherit, destroy) so that
|
|
3704
|
+
* external caches (e.g. A_Context feature-extension cache) can detect
|
|
3705
|
+
* staleness cheaply via numeric comparison.
|
|
3706
|
+
*/
|
|
3707
|
+
this._version = 0;
|
|
3708
|
+
/**
|
|
3709
|
+
* Cache for resolveConstructor results (both positive and negative).
|
|
3710
|
+
* Key = constructor name (string) or constructor reference toString.
|
|
3711
|
+
* Value = resolved constructor or `null` for negative results.
|
|
3712
|
+
* Invalidated by incrementing _version (cache is cleared on bump).
|
|
3713
|
+
*/
|
|
3714
|
+
this._resolveConstructorCache = /* @__PURE__ */ new Map();
|
|
3715
|
+
// ===========================================================================
|
|
3696
3716
|
// --------------------ALLowed Constructors--------------------------------
|
|
3697
3717
|
// ===========================================================================
|
|
3698
3718
|
/**
|
|
@@ -3777,6 +3797,13 @@ var A_Scope = class {
|
|
|
3777
3797
|
get allowedErrors() {
|
|
3778
3798
|
return this._allowedErrors;
|
|
3779
3799
|
}
|
|
3800
|
+
/**
|
|
3801
|
+
* Returns the current version of the scope. Each mutation increments the version,
|
|
3802
|
+
* allowing external caches to detect staleness via numeric comparison.
|
|
3803
|
+
*/
|
|
3804
|
+
get version() {
|
|
3805
|
+
return this._version;
|
|
3806
|
+
}
|
|
3780
3807
|
// ===========================================================================
|
|
3781
3808
|
// --------------------Readonly Registered Properties--------------------------
|
|
3782
3809
|
// ===========================================================================
|
|
@@ -3828,6 +3855,14 @@ var A_Scope = class {
|
|
|
3828
3855
|
get parent() {
|
|
3829
3856
|
return this._parent;
|
|
3830
3857
|
}
|
|
3858
|
+
/**
|
|
3859
|
+
* Increments the scope version and clears internal caches.
|
|
3860
|
+
* Must be called on every scope mutation (register, deregister, import, deimport, inherit, destroy).
|
|
3861
|
+
*/
|
|
3862
|
+
bumpVersion() {
|
|
3863
|
+
this._version++;
|
|
3864
|
+
this._resolveConstructorCache.clear();
|
|
3865
|
+
}
|
|
3831
3866
|
/**
|
|
3832
3867
|
* Generator to iterate through all parent scopes
|
|
3833
3868
|
*/
|
|
@@ -3961,6 +3996,7 @@ var A_Scope = class {
|
|
|
3961
3996
|
if (this.issuer()) {
|
|
3962
3997
|
A_Context.deallocate(this);
|
|
3963
3998
|
}
|
|
3999
|
+
this.bumpVersion();
|
|
3964
4000
|
}
|
|
3965
4001
|
/**
|
|
3966
4002
|
* Retrieves a value from the scope's meta.
|
|
@@ -4036,6 +4072,7 @@ var A_Scope = class {
|
|
|
4036
4072
|
`Circular inheritance detected: ${[...circularCheck, parent.name].join(" -> ")}`
|
|
4037
4073
|
);
|
|
4038
4074
|
this._parent = parent;
|
|
4075
|
+
this.bumpVersion();
|
|
4039
4076
|
return this;
|
|
4040
4077
|
}
|
|
4041
4078
|
/**
|
|
@@ -4057,6 +4094,7 @@ var A_Scope = class {
|
|
|
4057
4094
|
if (this._imports.has(scope))
|
|
4058
4095
|
return;
|
|
4059
4096
|
this._imports.add(scope);
|
|
4097
|
+
this.bumpVersion();
|
|
4060
4098
|
});
|
|
4061
4099
|
return this;
|
|
4062
4100
|
}
|
|
@@ -4069,8 +4107,10 @@ var A_Scope = class {
|
|
|
4069
4107
|
*/
|
|
4070
4108
|
deimport(...scopes) {
|
|
4071
4109
|
scopes.forEach((scope) => {
|
|
4072
|
-
if (this._imports.has(scope))
|
|
4110
|
+
if (this._imports.has(scope)) {
|
|
4073
4111
|
this._imports.delete(scope);
|
|
4112
|
+
this.bumpVersion();
|
|
4113
|
+
}
|
|
4074
4114
|
});
|
|
4075
4115
|
return this;
|
|
4076
4116
|
}
|
|
@@ -4211,6 +4251,20 @@ var A_Scope = class {
|
|
|
4211
4251
|
A_ScopeError.ResolutionError,
|
|
4212
4252
|
`Invalid constructor name provided: ${name}`
|
|
4213
4253
|
);
|
|
4254
|
+
const cacheKey = name;
|
|
4255
|
+
if (this._resolveConstructorCache.has(cacheKey)) {
|
|
4256
|
+
const cached = this._resolveConstructorCache.get(cacheKey);
|
|
4257
|
+
return cached === null ? void 0 : cached;
|
|
4258
|
+
}
|
|
4259
|
+
const resolved = this._resolveConstructorUncached(name);
|
|
4260
|
+
this._resolveConstructorCache.set(cacheKey, resolved ?? null);
|
|
4261
|
+
return resolved;
|
|
4262
|
+
}
|
|
4263
|
+
/**
|
|
4264
|
+
* Internal uncached implementation of resolveConstructor for string names.
|
|
4265
|
+
* Separated to allow the public method to wrap with caching.
|
|
4266
|
+
*/
|
|
4267
|
+
_resolveConstructorUncached(name) {
|
|
4214
4268
|
const component = Array.from(this.allowedComponents).find(
|
|
4215
4269
|
(c) => c.name === name || c.name === A_FormatterHelper.toPascalCase(name)
|
|
4216
4270
|
);
|
|
@@ -4558,6 +4612,7 @@ var A_Scope = class {
|
|
|
4558
4612
|
param1
|
|
4559
4613
|
);
|
|
4560
4614
|
A_Context.register(this, param1);
|
|
4615
|
+
this.bumpVersion();
|
|
4561
4616
|
break;
|
|
4562
4617
|
}
|
|
4563
4618
|
// 3) In case when it's a A-Entity instance
|
|
@@ -4566,6 +4621,7 @@ var A_Scope = class {
|
|
|
4566
4621
|
this.allowedEntities.add(param1.constructor);
|
|
4567
4622
|
this._entities.set(param1.aseid.toString(), param1);
|
|
4568
4623
|
A_Context.register(this, param1);
|
|
4624
|
+
this.bumpVersion();
|
|
4569
4625
|
break;
|
|
4570
4626
|
}
|
|
4571
4627
|
// 4) In case when it's a A-Fragment instance
|
|
@@ -4577,6 +4633,7 @@ var A_Scope = class {
|
|
|
4577
4633
|
param1
|
|
4578
4634
|
);
|
|
4579
4635
|
A_Context.register(this, param1);
|
|
4636
|
+
this.bumpVersion();
|
|
4580
4637
|
break;
|
|
4581
4638
|
}
|
|
4582
4639
|
// 5) In case when it's a A-Error instance
|
|
@@ -4588,6 +4645,7 @@ var A_Scope = class {
|
|
|
4588
4645
|
param1
|
|
4589
4646
|
);
|
|
4590
4647
|
A_Context.register(this, param1);
|
|
4648
|
+
this.bumpVersion();
|
|
4591
4649
|
break;
|
|
4592
4650
|
}
|
|
4593
4651
|
// ------------------------------------------
|
|
@@ -4595,26 +4653,34 @@ var A_Scope = class {
|
|
|
4595
4653
|
// ------------------------------------------
|
|
4596
4654
|
// 6) In case when it's a A-Component constructor
|
|
4597
4655
|
case A_TypeGuards.isComponentConstructor(param1): {
|
|
4598
|
-
if (!this.allowedComponents.has(param1))
|
|
4656
|
+
if (!this.allowedComponents.has(param1)) {
|
|
4599
4657
|
this.allowedComponents.add(param1);
|
|
4658
|
+
this.bumpVersion();
|
|
4659
|
+
}
|
|
4600
4660
|
break;
|
|
4601
4661
|
}
|
|
4602
4662
|
// 8) In case when it's a A-Fragment constructor
|
|
4603
4663
|
case A_TypeGuards.isFragmentConstructor(param1): {
|
|
4604
|
-
if (!this.allowedFragments.has(param1))
|
|
4664
|
+
if (!this.allowedFragments.has(param1)) {
|
|
4605
4665
|
this.allowedFragments.add(param1);
|
|
4666
|
+
this.bumpVersion();
|
|
4667
|
+
}
|
|
4606
4668
|
break;
|
|
4607
4669
|
}
|
|
4608
4670
|
// 9) In case when it's a A-Entity constructor
|
|
4609
4671
|
case A_TypeGuards.isEntityConstructor(param1): {
|
|
4610
|
-
if (!this.allowedEntities.has(param1))
|
|
4672
|
+
if (!this.allowedEntities.has(param1)) {
|
|
4611
4673
|
this.allowedEntities.add(param1);
|
|
4674
|
+
this.bumpVersion();
|
|
4675
|
+
}
|
|
4612
4676
|
break;
|
|
4613
4677
|
}
|
|
4614
4678
|
// 10) In case when it's a A-Error constructor
|
|
4615
4679
|
case A_TypeGuards.isErrorConstructor(param1): {
|
|
4616
|
-
if (!this.allowedErrors.has(param1))
|
|
4680
|
+
if (!this.allowedErrors.has(param1)) {
|
|
4617
4681
|
this.allowedErrors.add(param1);
|
|
4682
|
+
this.bumpVersion();
|
|
4683
|
+
}
|
|
4618
4684
|
break;
|
|
4619
4685
|
}
|
|
4620
4686
|
// ------------------------------------------
|
|
@@ -4654,6 +4720,7 @@ var A_Scope = class {
|
|
|
4654
4720
|
if (!hasComponent) {
|
|
4655
4721
|
this.allowedComponents.delete(ctor);
|
|
4656
4722
|
}
|
|
4723
|
+
this.bumpVersion();
|
|
4657
4724
|
break;
|
|
4658
4725
|
}
|
|
4659
4726
|
// 3) In case when it's a A-Entity instance
|
|
@@ -4665,6 +4732,7 @@ var A_Scope = class {
|
|
|
4665
4732
|
if (!hasEntity) {
|
|
4666
4733
|
this.allowedEntities.delete(ctor);
|
|
4667
4734
|
}
|
|
4735
|
+
this.bumpVersion();
|
|
4668
4736
|
break;
|
|
4669
4737
|
}
|
|
4670
4738
|
// 4) In case when it's a A-Fragment instance
|
|
@@ -4676,6 +4744,7 @@ var A_Scope = class {
|
|
|
4676
4744
|
if (!hasFragment) {
|
|
4677
4745
|
this.allowedFragments.delete(ctor);
|
|
4678
4746
|
}
|
|
4747
|
+
this.bumpVersion();
|
|
4679
4748
|
break;
|
|
4680
4749
|
}
|
|
4681
4750
|
// 5) In case when it's a A-Error instance
|
|
@@ -4687,6 +4756,7 @@ var A_Scope = class {
|
|
|
4687
4756
|
if (!hasError) {
|
|
4688
4757
|
this.allowedErrors.delete(ctor);
|
|
4689
4758
|
}
|
|
4759
|
+
this.bumpVersion();
|
|
4690
4760
|
break;
|
|
4691
4761
|
}
|
|
4692
4762
|
// ------------------------------------------
|
|
@@ -4695,6 +4765,7 @@ var A_Scope = class {
|
|
|
4695
4765
|
// 6) In case when it's a A-Component constructor
|
|
4696
4766
|
case A_TypeGuards.isComponentConstructor(param1): {
|
|
4697
4767
|
this.allowedComponents.delete(param1);
|
|
4768
|
+
this.bumpVersion();
|
|
4698
4769
|
break;
|
|
4699
4770
|
}
|
|
4700
4771
|
// 8) In case when it's a A-Fragment constructor
|
|
@@ -4706,6 +4777,7 @@ var A_Scope = class {
|
|
|
4706
4777
|
A_Context.deregister(instance);
|
|
4707
4778
|
}
|
|
4708
4779
|
});
|
|
4780
|
+
this.bumpVersion();
|
|
4709
4781
|
break;
|
|
4710
4782
|
}
|
|
4711
4783
|
// 9) In case when it's a A-Entity constructor
|
|
@@ -4717,6 +4789,7 @@ var A_Scope = class {
|
|
|
4717
4789
|
A_Context.deregister(instance);
|
|
4718
4790
|
}
|
|
4719
4791
|
});
|
|
4792
|
+
this.bumpVersion();
|
|
4720
4793
|
break;
|
|
4721
4794
|
}
|
|
4722
4795
|
// 10) In case when it's a A-Error constructor
|
|
@@ -4728,6 +4801,7 @@ var A_Scope = class {
|
|
|
4728
4801
|
A_Context.deregister(instance);
|
|
4729
4802
|
}
|
|
4730
4803
|
});
|
|
4804
|
+
this.bumpVersion();
|
|
4731
4805
|
break;
|
|
4732
4806
|
}
|
|
4733
4807
|
// ------------------------------------------
|
|
@@ -4848,6 +4922,11 @@ var A_Scope = class {
|
|
|
4848
4922
|
console.log(chain.join(" -> "));
|
|
4849
4923
|
}
|
|
4850
4924
|
};
|
|
4925
|
+
/**
|
|
4926
|
+
* Auto-incrementing counter for generating unique scope IDs.
|
|
4927
|
+
*/
|
|
4928
|
+
_A_Scope._nextUid = 0;
|
|
4929
|
+
var A_Scope = _A_Scope;
|
|
4851
4930
|
|
|
4852
4931
|
// src/lib/A-Scope/A-Scope.error.ts
|
|
4853
4932
|
var A_ScopeError = class extends A_Error {
|
|
@@ -4884,7 +4963,7 @@ A_ContextError.ComponentNotRegisteredError = "Component not registered in the co
|
|
|
4884
4963
|
A_ContextError.InvalidDeregisterParameterError = "Invalid parameter provided to deregister component";
|
|
4885
4964
|
|
|
4886
4965
|
// src/lib/A-Context/A-Context.class.ts
|
|
4887
|
-
var
|
|
4966
|
+
var _A_Context = class _A_Context {
|
|
4888
4967
|
/**
|
|
4889
4968
|
* Private constructor to enforce singleton pattern.
|
|
4890
4969
|
*
|
|
@@ -4911,6 +4990,18 @@ var A_Context = class _A_Context {
|
|
|
4911
4990
|
* Meta provides to store extra information about the class behavior and configuration.
|
|
4912
4991
|
*/
|
|
4913
4992
|
this._metaStorage = /* @__PURE__ */ new Map();
|
|
4993
|
+
/**
|
|
4994
|
+
* Monotonically increasing version counter for _metaStorage.
|
|
4995
|
+
* Incremented whenever a new entry is added to _metaStorage so that
|
|
4996
|
+
* caches depending on meta content can detect staleness.
|
|
4997
|
+
*/
|
|
4998
|
+
this._metaVersion = 0;
|
|
4999
|
+
/**
|
|
5000
|
+
* Cache for featureExtensions results.
|
|
5001
|
+
* Key format: `${featureName}::${componentConstructorName}::${scopeVersion}::${metaVersion}`
|
|
5002
|
+
* Automatically invalidated when scope version or meta version changes.
|
|
5003
|
+
*/
|
|
5004
|
+
this._featureExtensionsCache = /* @__PURE__ */ new Map();
|
|
4914
5005
|
this._globals = /* @__PURE__ */ new Map();
|
|
4915
5006
|
const name = String(A_CONCEPT_ENV.A_CONCEPT_ROOT_SCOPE) || "root";
|
|
4916
5007
|
this._root = new A_Scope({ name });
|
|
@@ -5114,6 +5205,7 @@ var A_Context = class _A_Context {
|
|
|
5114
5205
|
if (!inheritedMeta)
|
|
5115
5206
|
inheritedMeta = new metaType();
|
|
5116
5207
|
instance._metaStorage.set(property, inheritedMeta.clone());
|
|
5208
|
+
instance._metaVersion++;
|
|
5117
5209
|
}
|
|
5118
5210
|
return instance._metaStorage.get(property);
|
|
5119
5211
|
}
|
|
@@ -5122,6 +5214,7 @@ var A_Context = class _A_Context {
|
|
|
5122
5214
|
const existingMeta = _A_Context.meta(param1);
|
|
5123
5215
|
const constructor = typeof param1 === "function" ? param1 : param1.constructor;
|
|
5124
5216
|
instance._metaStorage.set(constructor, existingMeta ? meta.from(existingMeta) : meta);
|
|
5217
|
+
instance._metaVersion++;
|
|
5125
5218
|
}
|
|
5126
5219
|
/**
|
|
5127
5220
|
*
|
|
@@ -5177,11 +5270,10 @@ var A_Context = class _A_Context {
|
|
|
5177
5270
|
* @param name
|
|
5178
5271
|
*/
|
|
5179
5272
|
static featureTemplate(name, component, scope = this.scope(component)) {
|
|
5180
|
-
const componentName = A_CommonHelper.getComponentName(component);
|
|
5181
5273
|
if (!component) throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Component cannot be null or undefined.`);
|
|
5182
5274
|
if (!name) throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Feature name cannot be null or undefined.`);
|
|
5183
5275
|
if (!A_TypeGuards.isAllowedForFeatureDefinition(component))
|
|
5184
|
-
throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Component of type ${
|
|
5276
|
+
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.`);
|
|
5185
5277
|
const steps = [
|
|
5186
5278
|
// 1) Get the base feature definition from the component
|
|
5187
5279
|
...this.featureDefinition(name, component),
|
|
@@ -5204,59 +5296,116 @@ var A_Context = class _A_Context {
|
|
|
5204
5296
|
*/
|
|
5205
5297
|
static featureExtensions(name, component, scope) {
|
|
5206
5298
|
const instance = this.getInstance();
|
|
5207
|
-
const componentName = A_CommonHelper.getComponentName(component);
|
|
5208
5299
|
if (!component) throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Component cannot be null or undefined.`);
|
|
5209
5300
|
if (!name) throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Feature name cannot be null or undefined.`);
|
|
5210
5301
|
if (!A_TypeGuards.isAllowedForFeatureDefinition(component))
|
|
5211
|
-
throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Component of type ${
|
|
5302
|
+
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.`);
|
|
5303
|
+
const componentCtor = typeof component === "function" ? component : component.constructor;
|
|
5304
|
+
const effectiveScope = scope.parent || scope;
|
|
5305
|
+
const cacheKey = `${String(name)}::${componentCtor.name}::s${effectiveScope.uid}v${effectiveScope.version}::m${instance._metaVersion}`;
|
|
5306
|
+
const cached = instance._featureExtensionsCache.get(cacheKey);
|
|
5307
|
+
if (cached) {
|
|
5308
|
+
return cached;
|
|
5309
|
+
}
|
|
5212
5310
|
const callNames = A_CommonHelper.getClassInheritanceChain(component).filter((c) => c !== A_Component && c !== A_Container && c !== A_Entity).map((c) => `${c.name}.${name}`);
|
|
5213
5311
|
const steps = /* @__PURE__ */ new Map();
|
|
5214
5312
|
const allowedComponents = /* @__PURE__ */ new Set();
|
|
5313
|
+
const componentNameCache = /* @__PURE__ */ new Map();
|
|
5314
|
+
const dependencyCache = /* @__PURE__ */ new Map();
|
|
5315
|
+
const getNameCached = (cmp) => {
|
|
5316
|
+
let n = componentNameCache.get(cmp);
|
|
5317
|
+
if (n === void 0) {
|
|
5318
|
+
n = A_CommonHelper.getComponentName(cmp);
|
|
5319
|
+
componentNameCache.set(cmp, n);
|
|
5320
|
+
}
|
|
5321
|
+
return n;
|
|
5322
|
+
};
|
|
5323
|
+
const getDependencyCached = (cmp) => {
|
|
5324
|
+
let d = dependencyCache.get(cmp);
|
|
5325
|
+
if (!d) {
|
|
5326
|
+
d = new A_Dependency(cmp);
|
|
5327
|
+
dependencyCache.set(cmp, d);
|
|
5328
|
+
}
|
|
5329
|
+
return d;
|
|
5330
|
+
};
|
|
5331
|
+
const scopeFilteredMetas = [];
|
|
5332
|
+
for (const [cmp, meta] of instance._metaStorage) {
|
|
5333
|
+
if (scope.has(cmp) && (A_TypeGuards.isComponentMetaInstance(meta) || A_TypeGuards.isContainerMetaInstance(meta))) {
|
|
5334
|
+
scopeFilteredMetas.push([cmp, meta]);
|
|
5335
|
+
}
|
|
5336
|
+
}
|
|
5215
5337
|
for (const callName of callNames) {
|
|
5216
|
-
for (const [cmp, meta] of
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
}
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5338
|
+
for (const [cmp, meta] of scopeFilteredMetas) {
|
|
5339
|
+
allowedComponents.add(cmp);
|
|
5340
|
+
const extensions = meta.extensions(callName);
|
|
5341
|
+
for (let i = 0; i < extensions.length; i++) {
|
|
5342
|
+
const declaration = extensions[i];
|
|
5343
|
+
const inherited = Array.from(allowedComponents).reverse().find((c) => A_CommonHelper.isInheritedFrom(cmp, c) && c !== cmp);
|
|
5344
|
+
if (inherited) {
|
|
5345
|
+
steps.delete(`${getNameCached(inherited)}.${declaration.handler}`);
|
|
5346
|
+
}
|
|
5347
|
+
if (declaration.override) {
|
|
5348
|
+
const overrideRegexp = new RegExp(declaration.override);
|
|
5349
|
+
for (const [stepKey, step] of steps) {
|
|
5350
|
+
if (overrideRegexp.test(stepKey) || overrideRegexp.test(step.handler)) {
|
|
5351
|
+
steps.delete(stepKey);
|
|
5230
5352
|
}
|
|
5231
5353
|
}
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5354
|
+
}
|
|
5355
|
+
steps.set(`${getNameCached(cmp)}.${declaration.handler}`, {
|
|
5356
|
+
dependency: getDependencyCached(cmp),
|
|
5357
|
+
...declaration
|
|
5236
5358
|
});
|
|
5237
5359
|
}
|
|
5238
5360
|
}
|
|
5239
5361
|
}
|
|
5240
|
-
|
|
5362
|
+
const result = instance.filterToMostDerived(scope, Array.from(steps.values()));
|
|
5363
|
+
if (instance._featureExtensionsCache.size >= _A_Context.FEATURE_EXTENSIONS_CACHE_MAX_SIZE) {
|
|
5364
|
+
instance._featureExtensionsCache.clear();
|
|
5365
|
+
}
|
|
5366
|
+
instance._featureExtensionsCache.set(cacheKey, result);
|
|
5367
|
+
return result;
|
|
5241
5368
|
}
|
|
5242
5369
|
/**
|
|
5243
5370
|
* method helps to filter steps in a way that only the most derived classes are kept.
|
|
5244
5371
|
*
|
|
5372
|
+
* Optimized: Uses a pre-built constructor→class map and single-pass prototype chain
|
|
5373
|
+
* walk to eliminate parent classes in O(n·d) where d is inheritance depth,
|
|
5374
|
+
* instead of the previous O(n²) with isPrototypeOf checks.
|
|
5375
|
+
*
|
|
5245
5376
|
* @param scope
|
|
5246
5377
|
* @param items
|
|
5247
5378
|
* @returns
|
|
5248
5379
|
*/
|
|
5249
5380
|
filterToMostDerived(scope, items) {
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
}
|
|
5258
|
-
|
|
5259
|
-
}
|
|
5381
|
+
if (items.length <= 1) return items;
|
|
5382
|
+
const resolvedClasses = /* @__PURE__ */ new Map();
|
|
5383
|
+
const presentNames = /* @__PURE__ */ new Set();
|
|
5384
|
+
for (const item of items) {
|
|
5385
|
+
const depName = item.dependency.name;
|
|
5386
|
+
if (!resolvedClasses.has(depName)) {
|
|
5387
|
+
resolvedClasses.set(depName, scope.resolveConstructor(depName));
|
|
5388
|
+
}
|
|
5389
|
+
presentNames.add(depName);
|
|
5390
|
+
}
|
|
5391
|
+
const parentNames = /* @__PURE__ */ new Set();
|
|
5392
|
+
const ctorToName = /* @__PURE__ */ new Map();
|
|
5393
|
+
for (const [depName, ctor] of resolvedClasses) {
|
|
5394
|
+
if (ctor) ctorToName.set(ctor, depName);
|
|
5395
|
+
}
|
|
5396
|
+
for (const [depName, ctor] of resolvedClasses) {
|
|
5397
|
+
if (!ctor) continue;
|
|
5398
|
+
let ancestor = Object.getPrototypeOf(ctor.prototype);
|
|
5399
|
+
while (ancestor && ancestor !== Object.prototype) {
|
|
5400
|
+
const ancestorCtor = ancestor.constructor;
|
|
5401
|
+
const ancestorName = ctorToName.get(ancestorCtor);
|
|
5402
|
+
if (ancestorName && ancestorName !== depName && presentNames.has(ancestorName)) {
|
|
5403
|
+
parentNames.add(ancestorName);
|
|
5404
|
+
}
|
|
5405
|
+
ancestor = Object.getPrototypeOf(ancestor);
|
|
5406
|
+
}
|
|
5407
|
+
}
|
|
5408
|
+
return items.filter((item) => !parentNames.has(item.dependency.name));
|
|
5260
5409
|
}
|
|
5261
5410
|
/**
|
|
5262
5411
|
* This method returns the feature template definition without any extensions.
|
|
@@ -5371,6 +5520,8 @@ var A_Context = class _A_Context {
|
|
|
5371
5520
|
static reset() {
|
|
5372
5521
|
const instance = _A_Context.getInstance();
|
|
5373
5522
|
instance._registry = /* @__PURE__ */ new WeakMap();
|
|
5523
|
+
instance._featureExtensionsCache.clear();
|
|
5524
|
+
instance._metaVersion++;
|
|
5374
5525
|
const name = String(A_CONCEPT_ENV.A_CONCEPT_ROOT_SCOPE) || "root";
|
|
5375
5526
|
instance._root = new A_Scope({ name });
|
|
5376
5527
|
}
|
|
@@ -5414,6 +5565,12 @@ var A_Context = class _A_Context {
|
|
|
5414
5565
|
return A_TypeGuards.isContainerConstructor(param) || A_TypeGuards.isComponentConstructor(param) || A_TypeGuards.isEntityConstructor(param);
|
|
5415
5566
|
}
|
|
5416
5567
|
};
|
|
5568
|
+
/**
|
|
5569
|
+
* Maximum number of entries in the featureExtensions cache.
|
|
5570
|
+
* When exceeded, the entire cache is cleared to prevent unbounded growth.
|
|
5571
|
+
*/
|
|
5572
|
+
_A_Context.FEATURE_EXTENSIONS_CACHE_MAX_SIZE = 1024;
|
|
5573
|
+
var A_Context = _A_Context;
|
|
5417
5574
|
|
|
5418
5575
|
// src/lib/A-Abstraction/A-Abstraction.error.ts
|
|
5419
5576
|
var A_AbstractionError = class extends A_Error {
|