@navios/di 0.7.1 → 0.9.0
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/CHANGELOG.md +110 -0
- package/README.md +117 -17
- package/lib/browser/container/abstract-container.d.mts +112 -0
- package/lib/browser/container/abstract-container.d.mts.map +1 -0
- package/lib/browser/container/abstract-container.mjs +100 -0
- package/lib/browser/container/abstract-container.mjs.map +1 -0
- package/lib/browser/container/container.d.mts +100 -0
- package/lib/browser/container/container.d.mts.map +1 -0
- package/lib/browser/container/container.mjs +424 -0
- package/lib/browser/container/container.mjs.map +1 -0
- package/lib/browser/container/scoped-container.d.mts +93 -0
- package/lib/browser/container/scoped-container.d.mts.map +1 -0
- package/lib/browser/container/scoped-container.mjs +119 -0
- package/lib/browser/container/scoped-container.mjs.map +1 -0
- package/lib/browser/decorators/factory.decorator.d.mts +26 -0
- package/lib/browser/decorators/factory.decorator.d.mts.map +1 -0
- package/lib/browser/decorators/factory.decorator.mjs +20 -0
- package/lib/browser/decorators/factory.decorator.mjs.map +1 -0
- package/lib/browser/decorators/injectable.decorator.d.mts +38 -0
- package/lib/browser/decorators/injectable.decorator.d.mts.map +1 -0
- package/lib/browser/decorators/injectable.decorator.mjs +21 -0
- package/lib/browser/decorators/injectable.decorator.mjs.map +1 -0
- package/lib/browser/enums/injectable-scope.enum.d.mts +18 -0
- package/lib/browser/enums/injectable-scope.enum.d.mts.map +1 -0
- package/lib/browser/enums/injectable-scope.enum.mjs +20 -0
- package/lib/browser/enums/injectable-scope.enum.mjs.map +1 -0
- package/lib/browser/enums/injectable-type.enum.d.mts +8 -0
- package/lib/browser/enums/injectable-type.enum.d.mts.map +1 -0
- package/lib/browser/enums/injectable-type.enum.mjs +10 -0
- package/lib/browser/enums/injectable-type.enum.mjs.map +1 -0
- package/lib/browser/errors/di-error.d.mts +43 -0
- package/lib/browser/errors/di-error.d.mts.map +1 -0
- package/lib/browser/errors/di-error.mjs +98 -0
- package/lib/browser/errors/di-error.mjs.map +1 -0
- package/lib/browser/event-emitter.d.mts +16 -0
- package/lib/browser/event-emitter.d.mts.map +1 -0
- package/lib/browser/event-emitter.mjs +320 -0
- package/lib/browser/event-emitter.mjs.map +1 -0
- package/lib/browser/index.d.mts +37 -1508
- package/lib/browser/index.mjs +29 -2650
- package/lib/browser/interfaces/container.interface.d.mts +59 -0
- package/lib/browser/interfaces/container.interface.d.mts.map +1 -0
- package/lib/browser/interfaces/factory.interface.d.mts +14 -0
- package/lib/browser/interfaces/factory.interface.d.mts.map +1 -0
- package/lib/browser/interfaces/on-service-destroy.interface.d.mts +7 -0
- package/lib/browser/interfaces/on-service-destroy.interface.d.mts.map +1 -0
- package/lib/browser/interfaces/on-service-init.interface.d.mts +7 -0
- package/lib/browser/interfaces/on-service-init.interface.d.mts.map +1 -0
- package/lib/browser/internal/context/async-local-storage.browser.mjs +20 -0
- package/lib/browser/internal/context/async-local-storage.browser.mjs.map +1 -0
- package/lib/browser/internal/context/async-local-storage.d.mts +9 -0
- package/lib/browser/internal/context/async-local-storage.d.mts.map +1 -0
- package/lib/browser/internal/context/async-local-storage.types.d.mts +11 -0
- package/lib/browser/internal/context/async-local-storage.types.d.mts.map +1 -0
- package/lib/browser/internal/context/factory-context.d.mts +23 -0
- package/lib/browser/internal/context/factory-context.d.mts.map +1 -0
- package/lib/browser/internal/context/resolution-context.d.mts +43 -0
- package/lib/browser/internal/context/resolution-context.d.mts.map +1 -0
- package/lib/browser/internal/context/resolution-context.mjs +56 -0
- package/lib/browser/internal/context/resolution-context.mjs.map +1 -0
- package/lib/browser/internal/context/service-initialization-context.d.mts +48 -0
- package/lib/browser/internal/context/service-initialization-context.d.mts.map +1 -0
- package/lib/browser/internal/context/sync-local-storage.mjs +53 -0
- package/lib/browser/internal/context/sync-local-storage.mjs.map +1 -0
- package/lib/browser/internal/core/instance-resolver.d.mts +119 -0
- package/lib/browser/internal/core/instance-resolver.d.mts.map +1 -0
- package/lib/browser/internal/core/instance-resolver.mjs +306 -0
- package/lib/browser/internal/core/instance-resolver.mjs.map +1 -0
- package/lib/browser/internal/core/name-resolver.d.mts +52 -0
- package/lib/browser/internal/core/name-resolver.d.mts.map +1 -0
- package/lib/browser/internal/core/name-resolver.mjs +118 -0
- package/lib/browser/internal/core/name-resolver.mjs.map +1 -0
- package/lib/browser/internal/core/scope-tracker.d.mts +65 -0
- package/lib/browser/internal/core/scope-tracker.d.mts.map +1 -0
- package/lib/browser/internal/core/scope-tracker.mjs +120 -0
- package/lib/browser/internal/core/scope-tracker.mjs.map +1 -0
- package/lib/browser/internal/core/service-initializer.d.mts +44 -0
- package/lib/browser/internal/core/service-initializer.d.mts.map +1 -0
- package/lib/browser/internal/core/service-initializer.mjs +109 -0
- package/lib/browser/internal/core/service-initializer.mjs.map +1 -0
- package/lib/browser/internal/core/service-invalidator.d.mts +81 -0
- package/lib/browser/internal/core/service-invalidator.d.mts.map +1 -0
- package/lib/browser/internal/core/service-invalidator.mjs +142 -0
- package/lib/browser/internal/core/service-invalidator.mjs.map +1 -0
- package/lib/browser/internal/core/token-resolver.d.mts +54 -0
- package/lib/browser/internal/core/token-resolver.d.mts.map +1 -0
- package/lib/browser/internal/core/token-resolver.mjs +77 -0
- package/lib/browser/internal/core/token-resolver.mjs.map +1 -0
- package/lib/browser/internal/holder/holder-storage.interface.d.mts +99 -0
- package/lib/browser/internal/holder/holder-storage.interface.d.mts.map +1 -0
- package/lib/browser/internal/holder/instance-holder.d.mts +101 -0
- package/lib/browser/internal/holder/instance-holder.d.mts.map +1 -0
- package/lib/browser/internal/holder/instance-holder.mjs +19 -0
- package/lib/browser/internal/holder/instance-holder.mjs.map +1 -0
- package/lib/browser/internal/holder/unified-storage.d.mts +53 -0
- package/lib/browser/internal/holder/unified-storage.d.mts.map +1 -0
- package/lib/browser/internal/holder/unified-storage.mjs +144 -0
- package/lib/browser/internal/holder/unified-storage.mjs.map +1 -0
- package/lib/browser/internal/lifecycle/circular-detector.d.mts +39 -0
- package/lib/browser/internal/lifecycle/circular-detector.d.mts.map +1 -0
- package/lib/browser/internal/lifecycle/circular-detector.mjs +55 -0
- package/lib/browser/internal/lifecycle/circular-detector.mjs.map +1 -0
- package/lib/browser/internal/lifecycle/lifecycle-event-bus.d.mts +18 -0
- package/lib/browser/internal/lifecycle/lifecycle-event-bus.d.mts.map +1 -0
- package/lib/browser/internal/lifecycle/lifecycle-event-bus.mjs +43 -0
- package/lib/browser/internal/lifecycle/lifecycle-event-bus.mjs.map +1 -0
- package/lib/browser/internal/stub-factory-class.d.mts +14 -0
- package/lib/browser/internal/stub-factory-class.d.mts.map +1 -0
- package/lib/browser/internal/stub-factory-class.mjs +18 -0
- package/lib/browser/internal/stub-factory-class.mjs.map +1 -0
- package/lib/browser/symbols/injectable-token.d.mts +5 -0
- package/lib/browser/symbols/injectable-token.d.mts.map +1 -0
- package/lib/browser/symbols/injectable-token.mjs +6 -0
- package/lib/browser/symbols/injectable-token.mjs.map +1 -0
- package/lib/browser/token/injection-token.d.mts +55 -0
- package/lib/browser/token/injection-token.d.mts.map +1 -0
- package/lib/browser/token/injection-token.mjs +100 -0
- package/lib/browser/token/injection-token.mjs.map +1 -0
- package/lib/browser/token/registry.d.mts +37 -0
- package/lib/browser/token/registry.d.mts.map +1 -0
- package/lib/browser/token/registry.mjs +86 -0
- package/lib/browser/token/registry.mjs.map +1 -0
- package/lib/browser/utils/default-injectors.d.mts +12 -0
- package/lib/browser/utils/default-injectors.d.mts.map +1 -0
- package/lib/browser/utils/default-injectors.mjs +13 -0
- package/lib/browser/utils/default-injectors.mjs.map +1 -0
- package/lib/browser/utils/get-injectable-token.d.mts +9 -0
- package/lib/browser/utils/get-injectable-token.d.mts.map +1 -0
- package/lib/browser/utils/get-injectable-token.mjs +13 -0
- package/lib/browser/utils/get-injectable-token.mjs.map +1 -0
- package/lib/browser/utils/get-injectors.d.mts +55 -0
- package/lib/browser/utils/get-injectors.d.mts.map +1 -0
- package/lib/browser/utils/get-injectors.mjs +121 -0
- package/lib/browser/utils/get-injectors.mjs.map +1 -0
- package/lib/browser/utils/types.d.mts +23 -0
- package/lib/browser/utils/types.d.mts.map +1 -0
- package/lib/{container-Pb_Y4Z4x.mjs → container-8-z89TyQ.mjs} +1269 -1305
- package/lib/container-8-z89TyQ.mjs.map +1 -0
- package/lib/{container-BuAutHGg.d.mts → container-CNiqesCL.d.mts} +600 -569
- package/lib/container-CNiqesCL.d.mts.map +1 -0
- package/lib/{container-DnzgpfBe.cjs → container-CaY2fDuk.cjs} +1287 -1329
- package/lib/container-CaY2fDuk.cjs.map +1 -0
- package/lib/{container-oGTgX2iX.d.cts → container-D-0Ho3qL.d.cts} +601 -565
- package/lib/container-D-0Ho3qL.d.cts.map +1 -0
- package/lib/index.cjs +13 -15
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +58 -223
- package/lib/index.d.cts.map +1 -1
- package/lib/index.d.mts +62 -222
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +5 -6
- package/lib/index.mjs.map +1 -1
- package/lib/testing/index.cjs +569 -311
- package/lib/testing/index.cjs.map +1 -1
- package/lib/testing/index.d.cts +370 -41
- package/lib/testing/index.d.cts.map +1 -1
- package/lib/testing/index.d.mts +370 -41
- package/lib/testing/index.d.mts.map +1 -1
- package/lib/testing/index.mjs +568 -305
- package/lib/testing/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/__tests__/circular-detector.spec.mts +193 -0
- package/src/__tests__/concurrent.spec.mts +368 -0
- package/src/__tests__/container.spec.mts +32 -30
- package/src/__tests__/di-error.spec.mts +351 -0
- package/src/__tests__/e2e.browser.spec.mts +0 -4
- package/src/__tests__/e2e.spec.mts +10 -19
- package/src/__tests__/event-emitter.spec.mts +232 -109
- package/src/__tests__/get-injectors.spec.mts +250 -39
- package/src/__tests__/injection-token.spec.mts +293 -349
- package/src/__tests__/library-findings.spec.mts +8 -8
- package/src/__tests__/registry.spec.mts +358 -210
- package/src/__tests__/resolution-context.spec.mts +255 -0
- package/src/__tests__/scope-tracker.spec.mts +598 -0
- package/src/__tests__/scope-upgrade.spec.mts +808 -0
- package/src/__tests__/scoped-container.spec.mts +595 -0
- package/src/__tests__/test-container.spec.mts +293 -0
- package/src/__tests__/token-resolver.spec.mts +207 -0
- package/src/__tests__/unified-storage.spec.mts +535 -0
- package/src/__tests__/unit-test-container.spec.mts +405 -0
- package/src/__type-tests__/container.spec-d.mts +180 -0
- package/src/__type-tests__/factory.spec-d.mts +15 -3
- package/src/__type-tests__/inject.spec-d.mts +115 -20
- package/src/__type-tests__/injectable.spec-d.mts +69 -52
- package/src/__type-tests__/injection-token.spec-d.mts +176 -0
- package/src/__type-tests__/scoped-container.spec-d.mts +212 -0
- package/src/container/abstract-container.mts +327 -0
- package/src/container/container.mts +142 -170
- package/src/container/scoped-container.mts +126 -208
- package/src/decorators/factory.decorator.mts +16 -11
- package/src/decorators/injectable.decorator.mts +20 -16
- package/src/enums/index.mts +2 -2
- package/src/enums/injectable-scope.enum.mts +1 -0
- package/src/enums/injectable-type.enum.mts +1 -0
- package/src/errors/di-error.mts +96 -0
- package/src/event-emitter.mts +3 -27
- package/src/index.mts +6 -153
- package/src/interfaces/container.interface.mts +13 -0
- package/src/interfaces/factory.interface.mts +1 -1
- package/src/interfaces/index.mts +1 -1
- package/src/internal/context/async-local-storage.mts +3 -2
- package/src/internal/context/async-local-storage.types.mts +1 -0
- package/src/internal/context/factory-context.mts +1 -0
- package/src/internal/context/index.mts +3 -1
- package/src/internal/context/resolution-context.mts +1 -0
- package/src/internal/context/service-initialization-context.mts +43 -0
- package/src/internal/core/index.mts +5 -4
- package/src/internal/core/instance-resolver.mts +461 -292
- package/src/internal/core/name-resolver.mts +196 -0
- package/src/internal/core/scope-tracker.mts +242 -0
- package/src/internal/core/{instantiator.mts → service-initializer.mts} +51 -29
- package/src/internal/core/service-invalidator.mts +290 -0
- package/src/internal/core/{token-processor.mts → token-resolver.mts} +17 -88
- package/src/internal/holder/holder-storage.interface.mts +11 -5
- package/src/internal/holder/index.mts +2 -5
- package/src/internal/holder/instance-holder.mts +1 -3
- package/src/internal/holder/unified-storage.mts +245 -0
- package/src/internal/index.mts +2 -1
- package/src/internal/lifecycle/circular-detector.mts +1 -0
- package/src/internal/lifecycle/index.mts +1 -1
- package/src/internal/lifecycle/lifecycle-event-bus.mts +1 -0
- package/src/internal/stub-factory-class.mts +16 -0
- package/src/symbols/injectable-token.mts +3 -1
- package/src/testing/index.mts +2 -0
- package/src/testing/test-container.mts +546 -85
- package/src/testing/types.mts +117 -0
- package/src/testing/unit-test-container.mts +509 -0
- package/src/token/injection-token.mts +41 -4
- package/src/token/registry.mts +75 -9
- package/src/utils/default-injectors.mts +16 -0
- package/src/utils/get-injectable-token.mts +2 -3
- package/src/utils/get-injectors.mts +26 -15
- package/src/utils/index.mts +3 -1
- package/src/utils/types.mts +1 -0
- package/tsdown.config.mts +11 -1
- package/lib/browser/index.d.mts.map +0 -1
- package/lib/browser/index.mjs.map +0 -1
- package/lib/container-BuAutHGg.d.mts.map +0 -1
- package/lib/container-DnzgpfBe.cjs.map +0 -1
- package/lib/container-Pb_Y4Z4x.mjs.map +0 -1
- package/lib/container-oGTgX2iX.d.cts.map +0 -1
- package/src/__tests__/async-local-storage.browser.spec.mts +0 -166
- package/src/__tests__/async-local-storage.spec.mts +0 -333
- package/src/__tests__/errors.spec.mts +0 -87
- package/src/__tests__/factory.spec.mts +0 -137
- package/src/__tests__/injectable.spec.mts +0 -246
- package/src/__tests__/request-scope.spec.mts +0 -416
- package/src/__tests__/service-instantiator.spec.mts +0 -410
- package/src/__tests__/service-locator-event-bus.spec.mts +0 -242
- package/src/__tests__/service-locator-manager.spec.mts +0 -300
- package/src/__tests__/service-locator.spec.mts +0 -966
- package/src/__tests__/unified-api.spec.mts +0 -130
- package/src/browser.mts +0 -11
- package/src/injectors.mts +0 -18
- package/src/internal/context/request-context.mts +0 -214
- package/src/internal/core/invalidator.mts +0 -437
- package/src/internal/core/service-locator.mts +0 -202
- package/src/internal/holder/base-holder-manager.mts +0 -238
- package/src/internal/holder/holder-manager.mts +0 -85
- package/src/internal/holder/request-storage.mts +0 -134
- package/src/internal/holder/singleton-storage.mts +0 -105
- package/src/testing/README.md +0 -80
- package/src/testing/__tests__/test-container.spec.mts +0 -173
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { InstanceHolder } from "../holder/instance-holder.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/internal/lifecycle/circular-detector.d.mts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Detects circular dependencies by analyzing the waitingFor relationships
|
|
7
|
+
* between service holders.
|
|
8
|
+
*
|
|
9
|
+
* Uses BFS to traverse the waitingFor graph starting from a target holder
|
|
10
|
+
* and checks if following the chain leads back to the waiter, indicating a circular dependency.
|
|
11
|
+
*
|
|
12
|
+
* Note: In production (NODE_ENV === 'production'), detection is skipped for performance.
|
|
13
|
+
*/
|
|
14
|
+
declare class CircularDetector {
|
|
15
|
+
/**
|
|
16
|
+
* Detects if waiting for `targetName` from `waiterName` would create a cycle.
|
|
17
|
+
*
|
|
18
|
+
* This works by checking if `targetName` (or any holder in its waitingFor chain)
|
|
19
|
+
* is currently waiting for `waiterName`. If so, waiting would create a deadlock.
|
|
20
|
+
*
|
|
21
|
+
* In production mode, this always returns null to skip the BFS traversal overhead.
|
|
22
|
+
*
|
|
23
|
+
* @param waiterName The name of the holder that wants to wait
|
|
24
|
+
* @param targetName The name of the holder being waited on
|
|
25
|
+
* @param getHolder Function to retrieve a holder by name
|
|
26
|
+
* @returns The cycle path if a cycle is detected, null otherwise
|
|
27
|
+
*/
|
|
28
|
+
static detectCycle(waiterName: string, targetName: string, getHolder: (name: string) => InstanceHolder | undefined): string[] | null;
|
|
29
|
+
/**
|
|
30
|
+
* Formats a cycle path into a human-readable string.
|
|
31
|
+
*
|
|
32
|
+
* @param cycle The cycle path (array of service names)
|
|
33
|
+
* @returns Formatted string like "ServiceA -> ServiceB -> ServiceA"
|
|
34
|
+
*/
|
|
35
|
+
static formatCycle(cycle: string[]): string;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { CircularDetector };
|
|
39
|
+
//# sourceMappingURL=circular-detector.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circular-detector.d.mts","names":[],"sources":["../../../../src/internal/lifecycle/circular-detector.mts"],"sourcesContent":[],"mappings":";;;;;;AAiBA;;;;;;;cAAa,gBAAA;;;;;;;;;;;;;;0FAiBoB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//#region src/internal/lifecycle/circular-detector.mts
|
|
2
|
+
/**
|
|
3
|
+
* Detects circular dependencies by analyzing the waitingFor relationships
|
|
4
|
+
* between service holders.
|
|
5
|
+
*
|
|
6
|
+
* Uses BFS to traverse the waitingFor graph starting from a target holder
|
|
7
|
+
* and checks if following the chain leads back to the waiter, indicating a circular dependency.
|
|
8
|
+
*
|
|
9
|
+
* Note: In production (NODE_ENV === 'production'), detection is skipped for performance.
|
|
10
|
+
*/ var CircularDetector = class {
|
|
11
|
+
/**
|
|
12
|
+
* Detects if waiting for `targetName` from `waiterName` would create a cycle.
|
|
13
|
+
*
|
|
14
|
+
* This works by checking if `targetName` (or any holder in its waitingFor chain)
|
|
15
|
+
* is currently waiting for `waiterName`. If so, waiting would create a deadlock.
|
|
16
|
+
*
|
|
17
|
+
* In production mode, this always returns null to skip the BFS traversal overhead.
|
|
18
|
+
*
|
|
19
|
+
* @param waiterName The name of the holder that wants to wait
|
|
20
|
+
* @param targetName The name of the holder being waited on
|
|
21
|
+
* @param getHolder Function to retrieve a holder by name
|
|
22
|
+
* @returns The cycle path if a cycle is detected, null otherwise
|
|
23
|
+
*/ static detectCycle(waiterName, targetName, getHolder) {
|
|
24
|
+
const visited = /* @__PURE__ */ new Set();
|
|
25
|
+
const queue = [{
|
|
26
|
+
name: targetName,
|
|
27
|
+
path: [waiterName, targetName]
|
|
28
|
+
}];
|
|
29
|
+
while (queue.length > 0) {
|
|
30
|
+
const { name: currentName, path } = queue.shift();
|
|
31
|
+
if (currentName === waiterName) return path;
|
|
32
|
+
if (visited.has(currentName)) continue;
|
|
33
|
+
visited.add(currentName);
|
|
34
|
+
const holder = getHolder(currentName);
|
|
35
|
+
if (!holder) continue;
|
|
36
|
+
for (const waitingForName of holder.waitingFor) if (!visited.has(waitingForName)) queue.push({
|
|
37
|
+
name: waitingForName,
|
|
38
|
+
path: [...path, waitingForName]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Formats a cycle path into a human-readable string.
|
|
45
|
+
*
|
|
46
|
+
* @param cycle The cycle path (array of service names)
|
|
47
|
+
* @returns Formatted string like "ServiceA -> ServiceB -> ServiceA"
|
|
48
|
+
*/ static formatCycle(cycle) {
|
|
49
|
+
return cycle.join(" -> ");
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
export { CircularDetector };
|
|
55
|
+
//# sourceMappingURL=circular-detector.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circular-detector.mjs","names":["isProduction","process","env","NODE_ENV","CircularDetector","detectCycle","waiterName","targetName","getHolder","visited","Set","queue","name","path","length","currentName","shift","has","add","holder","waitingForName","waitingFor","push","formatCycle","cycle","join"],"sources":["../../../../src/internal/lifecycle/circular-detector.mts"],"sourcesContent":["import type { InstanceHolder } from '../holder/instance-holder.mjs'\n\n/**\n * Whether we're running in production mode.\n * In production, circular dependency detection is skipped for performance.\n */\nconst isProduction = process.env.NODE_ENV === 'production'\n\n/**\n * Detects circular dependencies by analyzing the waitingFor relationships\n * between service holders.\n *\n * Uses BFS to traverse the waitingFor graph starting from a target holder\n * and checks if following the chain leads back to the waiter, indicating a circular dependency.\n *\n * Note: In production (NODE_ENV === 'production'), detection is skipped for performance.\n */\nexport class CircularDetector {\n /**\n * Detects if waiting for `targetName` from `waiterName` would create a cycle.\n *\n * This works by checking if `targetName` (or any holder in its waitingFor chain)\n * is currently waiting for `waiterName`. If so, waiting would create a deadlock.\n *\n * In production mode, this always returns null to skip the BFS traversal overhead.\n *\n * @param waiterName The name of the holder that wants to wait\n * @param targetName The name of the holder being waited on\n * @param getHolder Function to retrieve a holder by name\n * @returns The cycle path if a cycle is detected, null otherwise\n */\n static detectCycle(\n waiterName: string,\n targetName: string,\n getHolder: (name: string) => InstanceHolder | undefined,\n ): string[] | null {\n // Skip circular dependency detection in production for performance\n if (isProduction) {\n return null\n }\n\n // Use BFS to find if there's a path from targetName back to waiterName\n const visited = new Set<string>()\n const queue: Array<{ name: string; path: string[] }> = [\n { name: targetName, path: [waiterName, targetName] },\n ]\n\n while (queue.length > 0) {\n const { name: currentName, path } = queue.shift()!\n\n // If we've reached back to the waiter, we have a cycle\n if (currentName === waiterName) {\n return path\n }\n\n // Skip if already visited\n if (visited.has(currentName)) {\n continue\n }\n visited.add(currentName)\n\n // Get the holder and check what it's waiting for\n const holder = getHolder(currentName)\n if (!holder) {\n continue\n }\n\n // Add all services this holder is waiting for to the queue\n for (const waitingForName of holder.waitingFor) {\n if (!visited.has(waitingForName)) {\n queue.push({\n name: waitingForName,\n path: [...path, waitingForName],\n })\n }\n }\n }\n\n // No path found from target back to waiter, no cycle\n return null\n }\n\n /**\n * Formats a cycle path into a human-readable string.\n *\n * @param cycle The cycle path (array of service names)\n * @returns Formatted string like \"ServiceA -> ServiceB -> ServiceA\"\n */\n static formatCycle(cycle: string[]): string {\n return cycle.join(' -> ')\n }\n}\n\n"],"mappings":";;;;;;;;;GAiBA,IAAaI,mBAAb,MAAaA;;;;;;;;;;;;;IAcX,OAAOC,YACLC,YACAC,YACAC,WACiB;EAOjB,MAAMC,0BAAU,IAAIC,KAAAA;EACpB,MAAMC,QAAiD,CACrD;GAAEC,MAAML;GAAYM,MAAM,CAACP,YAAYC,WAAW;GAAC,CACpD;AAED,SAAOI,MAAMG,SAAS,GAAG;GACvB,MAAM,EAAEF,MAAMG,aAAaF,SAASF,MAAMK,OAAK;AAG/C,OAAID,gBAAgBT,WAClB,QAAOO;AAIT,OAAIJ,QAAQQ,IAAIF,YAAAA,CACd;AAEFN,WAAQS,IAAIH,YAAAA;GAGZ,MAAMI,SAASX,UAAUO,YAAAA;AACzB,OAAI,CAACI,OACH;AAIF,QAAK,MAAMC,kBAAkBD,OAAOE,WAClC,KAAI,CAACZ,QAAQQ,IAAIG,eAAAA,CACfT,OAAMW,KAAK;IACTV,MAAMQ;IACNP,MAAM,IAAIA,MAAMO,eAAe;IACjC,CAAA;;AAMN,SAAO;;;;;;;IAST,OAAOG,YAAYC,OAAyB;AAC1C,SAAOA,MAAMC,KAAK,OAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/internal/lifecycle/lifecycle-event-bus.d.mts
|
|
2
|
+
/**
|
|
3
|
+
* Event bus for service lifecycle events (create, destroy, etc.).
|
|
4
|
+
*
|
|
5
|
+
* Enables loose coupling between services by allowing them to subscribe
|
|
6
|
+
* to lifecycle events of their dependencies without direct references.
|
|
7
|
+
* Used primarily for invalidation cascading.
|
|
8
|
+
*/
|
|
9
|
+
declare class LifecycleEventBus {
|
|
10
|
+
private readonly logger;
|
|
11
|
+
private listeners;
|
|
12
|
+
constructor(logger?: Console | null);
|
|
13
|
+
on<Event extends string | `pre:${string}` | `post:${string}`>(ns: string, event: Event, listener: (event: Event) => void): () => void;
|
|
14
|
+
emit(key: string, event: string): Promise<PromiseSettledResult<any>[] | undefined>;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { LifecycleEventBus };
|
|
18
|
+
//# sourceMappingURL=lifecycle-event-bus.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-event-bus.d.mts","names":[],"sources":["../../../../src/internal/lifecycle/lifecycle-event-bus.mts"],"sourcesContent":[],"mappings":";;AAaA;;;;;;AAgCuC,cAhC1B,iBAAA,CAgC0B;;;uBA9BA;mFAI5B,yBACW;oCAyBiB,QAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/internal/lifecycle/lifecycle-event-bus.mts
|
|
2
|
+
/**
|
|
3
|
+
* Event bus for service lifecycle events (create, destroy, etc.).
|
|
4
|
+
*
|
|
5
|
+
* Enables loose coupling between services by allowing them to subscribe
|
|
6
|
+
* to lifecycle events of their dependencies without direct references.
|
|
7
|
+
* Used primarily for invalidation cascading.
|
|
8
|
+
*/ var LifecycleEventBus = class {
|
|
9
|
+
logger;
|
|
10
|
+
listeners = /* @__PURE__ */ new Map();
|
|
11
|
+
constructor(logger = null) {
|
|
12
|
+
this.logger = logger;
|
|
13
|
+
}
|
|
14
|
+
on(ns, event, listener) {
|
|
15
|
+
this.logger?.debug(`[LifecycleEventBus]#on(): ns:${ns} event:${event}`);
|
|
16
|
+
if (!this.listeners.has(ns)) this.listeners.set(ns, /* @__PURE__ */ new Map());
|
|
17
|
+
const nsEvents = this.listeners.get(ns);
|
|
18
|
+
if (!nsEvents.has(event)) nsEvents.set(event, /* @__PURE__ */ new Set());
|
|
19
|
+
nsEvents.get(event).add(listener);
|
|
20
|
+
return () => {
|
|
21
|
+
nsEvents.get(event)?.delete(listener);
|
|
22
|
+
if (nsEvents.get(event)?.size === 0) nsEvents.delete(event);
|
|
23
|
+
if (nsEvents.size === 0) this.listeners.delete(ns);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async emit(key, event) {
|
|
27
|
+
if (!this.listeners.has(key)) return;
|
|
28
|
+
const events = this.listeners.get(key);
|
|
29
|
+
this.logger?.debug(`[LifecycleEventBus]#emit(): ${key}:${event}`);
|
|
30
|
+
return await Promise.allSettled([...events.get(event) ?? []].map((listener) => listener(event))).then((results) => {
|
|
31
|
+
const res = results.filter((result) => result.status === "rejected").map((result) => {
|
|
32
|
+
this.logger?.warn(`[LifecycleEventBus]#emit(): ${key}:${event} rejected with`, result.reason);
|
|
33
|
+
return result;
|
|
34
|
+
});
|
|
35
|
+
if (res.length > 0) return Promise.reject(res);
|
|
36
|
+
return results;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
export { LifecycleEventBus };
|
|
43
|
+
//# sourceMappingURL=lifecycle-event-bus.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-event-bus.mjs","names":["LifecycleEventBus","listeners","Map","logger","on","ns","event","listener","debug","has","set","nsEvents","get","Set","add","delete","size","emit","key","events","res","Promise","allSettled","map","then","results","filter","result","status","warn","reason","length","reject"],"sources":["../../../../src/internal/lifecycle/lifecycle-event-bus.mts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-empty-object-type */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n\ntype ListenersMap = Map<string, Map<string, Set<Function>>>\n\n/**\n * Event bus for service lifecycle events (create, destroy, etc.).\n *\n * Enables loose coupling between services by allowing them to subscribe\n * to lifecycle events of their dependencies without direct references.\n * Used primarily for invalidation cascading.\n */\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\nexport class LifecycleEventBus {\n private listeners: ListenersMap = new Map()\n constructor(private readonly logger: Console | null = null) {}\n\n on<Event extends string | `pre:${string}` | `post:${string}`>(\n ns: string,\n event: Event,\n listener: (event: Event) => void,\n ) {\n this.logger?.debug(`[LifecycleEventBus]#on(): ns:${ns} event:${event}`)\n if (!this.listeners.has(ns)) {\n this.listeners.set(ns, new Map())\n }\n\n const nsEvents = this.listeners.get(ns)!\n if (!nsEvents.has(event)) {\n nsEvents.set(event, new Set())\n }\n\n nsEvents.get(event)!.add(listener)\n\n return () => {\n nsEvents.get(event)?.delete(listener)\n if (nsEvents.get(event)?.size === 0) {\n nsEvents.delete(event)\n }\n if (nsEvents.size === 0) {\n this.listeners.delete(ns)\n }\n }\n }\n\n async emit(key: string, event: string) {\n if (!this.listeners.has(key)) {\n return\n }\n\n const events = this.listeners.get(key)!\n\n this.logger?.debug(`[LifecycleEventBus]#emit(): ${key}:${event}`)\n\n const res = await Promise.allSettled(\n [...(events.get(event) ?? [])!].map((listener) => listener(event)),\n ).then((results) => {\n const res = results\n .filter((result) => result.status === 'rejected')\n .map((result: PromiseRejectedResult) => {\n this.logger?.warn(\n `[LifecycleEventBus]#emit(): ${key}:${event} rejected with`,\n result.reason,\n )\n return result\n })\n\n if (res.length > 0) {\n return Promise.reject(res)\n }\n return results\n })\n return res\n }\n}\n\n"],"mappings":";;;;;;;GAaA,IAAaA,oBAAb,MAAaA;;CACHC,4BAA0B,IAAIC,KAAAA;CACtC,YAAY,SAA0C,MAAM;OAA/BC,SAAAA;;CAE7BC,GACEC,IACAC,OACAC,UACA;AACA,OAAKJ,QAAQK,MAAM,gCAAgCH,GAAG,SAASC,QAAO;AACtE,MAAI,CAAC,KAAKL,UAAUQ,IAAIJ,GAAAA,CACtB,MAAKJ,UAAUS,IAAIL,oBAAI,IAAIH,KAAAA,CAAAA;EAG7B,MAAMS,WAAW,KAAKV,UAAUW,IAAIP,GAAAA;AACpC,MAAI,CAACM,SAASF,IAAIH,MAAAA,CAChBK,UAASD,IAAIJ,uBAAO,IAAIO,KAAAA,CAAAA;AAG1BF,WAASC,IAAIN,MAAAA,CAAQQ,IAAIP,SAAAA;AAEzB,eAAO;AACLI,YAASC,IAAIN,MAAAA,EAAQS,OAAOR,SAAAA;AAC5B,OAAII,SAASC,IAAIN,MAAAA,EAAQU,SAAS,EAChCL,UAASI,OAAOT,MAAAA;AAElB,OAAIK,SAASK,SAAS,EACpB,MAAKf,UAAUc,OAAOV,GAAAA;;;CAK5B,MAAMY,KAAKC,KAAaZ,OAAe;AACrC,MAAI,CAAC,KAAKL,UAAUQ,IAAIS,IAAAA,CACtB;EAGF,MAAMC,SAAS,KAAKlB,UAAUW,IAAIM,IAAAA;AAElC,OAAKf,QAAQK,MAAM,+BAA+BU,IAAI,GAAGZ,QAAO;AAoBhE,SAlBY,MAAMe,QAAQC,WACxB,IAAKH,OAAOP,IAAIN,MAAAA,IAAU,EAAE,CAAG,CAACiB,KAAKhB,aAAaA,SAASD,MAAAA,CAAAA,CAAAA,CAC3DkB,MAAMC,YAAAA;GACN,MAAML,MAAMK,QACTC,QAAQC,WAAWA,OAAOC,WAAW,WAAA,CACrCL,KAAKI,WAAAA;AACJ,SAAKxB,QAAQ0B,KACX,+BAA+BX,IAAI,GAAGZ,MAAM,iBAC5CqB,OAAOG,OAAM;AAEf,WAAOH;KACT;AAEF,OAAIP,IAAIW,SAAS,EACf,QAAOV,QAAQW,OAAOZ,IAAAA;AAExB,UAAOK;IACT"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/internal/stub-factory-class.d.mts
|
|
2
|
+
/**
|
|
3
|
+
* Stub factory class used when registering InjectionTokens without a real class implementation.
|
|
4
|
+
* This is used in ScopedContainer.addInstance() to allow registering tokens that don't have
|
|
5
|
+
* a corresponding class, while preventing accidental instantiation.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
declare class StubFactoryClass {
|
|
10
|
+
constructor();
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { StubFactoryClass };
|
|
14
|
+
//# sourceMappingURL=stub-factory-class.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub-factory-class.d.mts","names":[],"sources":["../../../src/internal/stub-factory-class.mts"],"sourcesContent":[],"mappings":";;AASA;;;;;;cAAa,gBAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DIError } from "../errors/di-error.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/internal/stub-factory-class.mts
|
|
4
|
+
/**
|
|
5
|
+
* Stub factory class used when registering InjectionTokens without a real class implementation.
|
|
6
|
+
* This is used in ScopedContainer.addInstance() to allow registering tokens that don't have
|
|
7
|
+
* a corresponding class, while preventing accidental instantiation.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/ var StubFactoryClass = class {
|
|
11
|
+
constructor() {
|
|
12
|
+
throw DIError.factoryNotFound("Trying to get instance of factory without real implementation");
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { StubFactoryClass };
|
|
18
|
+
//# sourceMappingURL=stub-factory-class.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub-factory-class.mjs","names":["DIError","StubFactoryClass","factoryNotFound"],"sources":["../../../src/internal/stub-factory-class.mts"],"sourcesContent":["import { DIError } from '../errors/di-error.mjs'\n\n/**\n * Stub factory class used when registering InjectionTokens without a real class implementation.\n * This is used in ScopedContainer.addInstance() to allow registering tokens that don't have\n * a corresponding class, while preventing accidental instantiation.\n *\n * @internal\n */\nexport class StubFactoryClass {\n constructor() {\n throw DIError.factoryNotFound(\n 'Trying to get instance of factory without real implementation',\n )\n }\n}\n"],"mappings":";;;;;;;;;GASA,IAAaC,mBAAb,MAAaA;CACX,cAAc;AACZ,QAAMD,QAAQE,gBACZ,gEAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injectable-token.d.mts","names":[],"sources":["../../../src/symbols/injectable-token.mts"],"sourcesContent":[],"mappings":";cAAa"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injectable-token.mjs","names":[],"sources":["../../../src/symbols/injectable-token.mts"],"sourcesContent":["export const InjectableTokenMeta = /* #__PURE__ */ Symbol.for(\n 'InjectableTokenMeta',\n)\n"],"mappings":";AAAA,MAAa,sBAAsC,uBAAO,IACxD,sBACD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { FactoryContext } from "../internal/context/factory-context.mjs";
|
|
2
|
+
import { ZodObject, ZodOptional, ZodRecord, z } from "zod/v4";
|
|
3
|
+
|
|
4
|
+
//#region src/token/injection-token.d.mts
|
|
5
|
+
type ClassType = new (...args: any[]) => any;
|
|
6
|
+
type ClassTypeWithoutArguments = new () => any;
|
|
7
|
+
type ClassTypeWithArgument<Arg> = new (arg: Arg) => any;
|
|
8
|
+
type ClassTypeWithOptionalArgument<Arg> = new (arg?: Arg) => any;
|
|
9
|
+
type ClassTypeWithInstance<T> = new (...args: any[]) => T;
|
|
10
|
+
type ClassTypeWithInstanceAndArgument<T, Arg> = new (arg: Arg) => T;
|
|
11
|
+
type ClassTypeWithInstanceAndOptionalArgument<T, Arg> = new (arg?: Arg) => T;
|
|
12
|
+
type BaseInjectionTokenSchemaType = ZodObject | ZodRecord;
|
|
13
|
+
type OptionalInjectionTokenSchemaType = ZodOptional<ZodObject> | ZodOptional<ZodRecord>;
|
|
14
|
+
type InjectionTokenSchemaType = BaseInjectionTokenSchemaType | OptionalInjectionTokenSchemaType;
|
|
15
|
+
declare class InjectionToken<T, S extends InjectionTokenSchemaType | unknown = unknown, Required extends boolean = (S extends ZodOptional<ZodObject> ? false : S extends ZodOptional<ZodRecord> ? false : S extends ZodObject ? true : S extends ZodRecord ? true : false)> {
|
|
16
|
+
readonly name: string | symbol | ClassType;
|
|
17
|
+
readonly schema: ZodObject | undefined;
|
|
18
|
+
readonly id: string;
|
|
19
|
+
private formattedName;
|
|
20
|
+
constructor(name: string | symbol | ClassType, schema: ZodObject | undefined, customId?: string);
|
|
21
|
+
static create<T extends ClassType>(name: T): InjectionToken<InstanceType<T>, undefined>;
|
|
22
|
+
static create<T extends ClassType, Schema extends InjectionTokenSchemaType>(name: T, schema: Schema): Schema['_def']['type'] extends 'ZodOptional' ? InjectionToken<InstanceType<T>, Schema, false> : InjectionToken<InstanceType<T>, Schema, true>;
|
|
23
|
+
static create<T>(name: string | symbol): InjectionToken<T, undefined>;
|
|
24
|
+
static create<T, Schema extends InjectionTokenSchemaType>(name: string | any, schema: Schema): InjectionToken<T, Schema>;
|
|
25
|
+
static bound<T, S extends InjectionTokenSchemaType>(token: InjectionToken<T, S>, value: z.input<S>): BoundInjectionToken<T, S>;
|
|
26
|
+
static factory<T, S extends InjectionTokenSchemaType>(token: InjectionToken<T, S>, factory: (ctx: FactoryContext) => Promise<z.input<S>>): FactoryInjectionToken<T, S>;
|
|
27
|
+
static refineType<T>(token: BoundInjectionToken<any, any>): BoundInjectionToken<T, any>;
|
|
28
|
+
toString(): string;
|
|
29
|
+
}
|
|
30
|
+
declare class BoundInjectionToken<T, S extends InjectionTokenSchemaType> {
|
|
31
|
+
readonly token: InjectionToken<T, S>;
|
|
32
|
+
readonly value: z.input<S>;
|
|
33
|
+
id: string;
|
|
34
|
+
name: string | symbol | ClassType;
|
|
35
|
+
schema: InjectionTokenSchemaType;
|
|
36
|
+
constructor(token: InjectionToken<T, S>, value: z.input<S>);
|
|
37
|
+
toString(): string;
|
|
38
|
+
}
|
|
39
|
+
declare class FactoryInjectionToken<T, S extends InjectionTokenSchemaType> {
|
|
40
|
+
readonly token: InjectionToken<T, S>;
|
|
41
|
+
readonly factory: (ctx: FactoryContext) => Promise<z.input<S>>;
|
|
42
|
+
value?: z.input<S>;
|
|
43
|
+
resolved: boolean;
|
|
44
|
+
id: string;
|
|
45
|
+
name: string | symbol | ClassType;
|
|
46
|
+
schema: InjectionTokenSchemaType;
|
|
47
|
+
constructor(token: InjectionToken<T, S>, factory: (ctx: FactoryContext) => Promise<z.input<S>>);
|
|
48
|
+
resolve(ctx: FactoryContext): Promise<z.input<S>>;
|
|
49
|
+
toString(): string;
|
|
50
|
+
}
|
|
51
|
+
type AnyInjectableType = ClassType | InjectionToken<any, any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>;
|
|
52
|
+
type InjectionTokenType = InjectionToken<any, any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>;
|
|
53
|
+
//#endregion
|
|
54
|
+
export { AnyInjectableType, BaseInjectionTokenSchemaType, BoundInjectionToken, ClassType, ClassTypeWithArgument, ClassTypeWithInstance, ClassTypeWithInstanceAndArgument, ClassTypeWithInstanceAndOptionalArgument, ClassTypeWithOptionalArgument, ClassTypeWithoutArguments, FactoryInjectionToken, InjectionToken, InjectionTokenSchemaType, InjectionTokenType, OptionalInjectionTokenSchemaType };
|
|
55
|
+
//# sourceMappingURL=injection-token.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injection-token.d.mts","names":[],"sources":["../../../src/token/injection-token.mts"],"sourcesContent":[],"mappings":";;;;KAIY,SAAA;KACA,yBAAA;AADA,KAEA,qBAFS,CAAA,GAAA,CAAA,GAAA,KAAA,GAAA,EAE8B,GAF9B,EAAA,GAAA,GAAA;AACT,KAEA,6BAFyB,CAAA,GAAA,CAAA,GAAA,KAAA,GAAA,CAAA,EAEuB,GAFvB,EAAA,GAAA,GAAA;AACzB,KAGA,qBAHqB,CAAA,CAAA,CAAA,GAAA,KAAkB,GAAG,IAAA,EAAA,GAAA,EAAA,EAAA,GAGS,CAHT;AAC1C,KAGA,gCAH6B,CAAA,CAAA,EAAA,GAAmB,CAAA,GAAG,KAAA,GAAA,EAGE,GAHF,EAAA,GAGU,CAHV;AAEnD,KAEA,wCAFoD,CAAA,CAAA,EAAA,GAAA,CAAA,GAAA,KAAA,GAAA,CAAA,EAGxD,GAHwD,EAAA,GAI3D,CAJ2D;AACpD,KAKA,4BAAA,GAA+B,SALC,GAKW,SALmB;AAC9D,KAMA,gCAAA,GACR,WAPgD,CAOpC,SANR,CAAA,GAOJ,WANE,CAMU,SANV,CAAA;AAEM,KAMA,wBAAA,GACR,4BAPmD,GAQnD,gCAR4D;AAEpD,cAyCC,cAzCD,CAAA,CAAA,EAAgC,UA4ChC,wBA5CgC,GAAA,OAAA,GAAA,OAAA,EAAA,iBAAA,OAAA,IA8Cf,CA9Ce,SA8CL,WA9CK,CA8CO,SA9CP,CAAA,GAAA,KAAA,GAgDtC,CAhDsC,SAgD5B,WAhD4B,CAgDhB,SAhDgB,CAAA,GAAA,KAAA,GAkDpC,CAlDoC,SAkD1B,SAlD0B,GAAA,IAAA,GAoDlC,CApDkC,SAoDxB,SApDwB,GAAA,IAAA,GAAA,KAAA,EAAA,CAAA;EAC5B,SAAA,IAAA,EAAA,MAAA,GAAA,MAAA,GA2D4B,SA3D5B;EAAZ,SAAA,MAAA,EA4DwB,SA5DxB,GAAA,SAAA;EACY,SAAA,EAAA,EAAA,MAAA;EAAZ,QAAA,aAAA;EAAW,WAAA,CAAA,IAAA,EAAA,MAAA,GAAA,MAAA,GA0D6B,SA1D7B,EAAA,MAAA,EA2Da,SA3Db,GAAA,SAAA,EAAA,QAAA,CAAA,EAAA,MAAA;EAEH,OAAA,MAAA,CAAA,UA+Dc,SA/DU,CAAA,CAAA,IAChC,EA+DM,CA/DN,CAAA,EAgEC,cAhED,CAgEgB,YA/DhB,CA+D6B,CA/D7B,CAAA,EAAA,SAAA,CAAA;EAmCS,OAAA,MAAA,CAAA,UA6Ba,SA7BC,EAAA,eA6ByB,wBA7BzB,CAAA,CAAA,IAAA,EA8BjB,CA9BiB,EAAA,MAAA,EA+Bf,MA/Be,CAAA,EAgCtB,MAhCsB,CAAA,MAAA,CAAA,CAAA,MAAA,CAAA,SAAA,aAAA,GAiCrB,cAjCqB,CAiCN,YAjCM,CAiCO,CAjCP,CAAA,EAiCW,MAjCX,EAAA,KAAA,CAAA,GAkCrB,cAlCqB,CAkCN,YAlCM,CAkCO,CAlCP,CAAA,EAkCW,MAlCX,EAAA,IAAA,CAAA;EAGf,OAAA,MAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,GAAA,MAAA,CAAA,EAgC+B,cAhC/B,CAgC8C,CAhC9C,EAAA,SAAA,CAAA;EAEiB,OAAA,MAAA,CAAA,CAAA,EAAA,eA+BK,wBA/BL,CAAA,CAAA,IAAA,EAAA,MAAA,GAAA,GAAA,EAAA,MAAA,EAiCjB,MAjCiB,CAAA,EAkCxB,cAlCwB,CAkCT,CAlCS,EAkCN,MAlCM,CAAA;EAAsB,OAAA,KAAA,CAAA,CAAA,EAAA,UAwCvB,wBAxCuB,CAAA,CAAA,KAAA,EAyCxC,cAzCwC,CAyCzB,CAzCyB,EAyCtB,CAzCsB,CAAA,EAAA,KAAA,EA0CxC,CAAA,CAAE,KA1CsC,CA0ChC,CA1CgC,CAAA,CAAA,EA2C9C,mBA3C8C,CA2C1B,CA3C0B,EA2CvB,CA3CuB,CAAA;EAAZ,OAAA,OAAA,CAAA,CAAA,EAAA,UA+CT,wBA/CS,CAAA,CAAA,KAAA,EAgD5B,cAhD4B,CAgDb,CAhDa,EAgDV,CAhDU,CAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EAiDpB,cAjDoB,EAAA,GAiDD,OAjDC,CAiDO,CAAA,CAAE,KAjDT,CAiDe,CAjDf,CAAA,CAAA,CAAA,EAkDlC,qBAlDkC,CAkDZ,CAlDY,EAkDT,CAlDS,CAAA;EAEjC,OAAA,UAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAqDK,mBArDL,CAAA,GAAA,EAAA,GAAA,CAAA,CAAA,EAsDD,mBAtDC,CAsDmB,CAtDnB,EAAA,GAAA,CAAA;EAAsB,QAAA,CAAA,CAAA,EAAA,MAAA;;AAEpB,cA0EK,mBA1EL,CAAA,CAAA,EAAA,UA0EsC,wBA1EtC,CAAA,CAAA;EAAU,SAAA,KAAA,EAgFS,cAhFT,CAgFwB,CAhFxB,EAgF2B,CAhF3B,CAAA;EAER,SAAA,KAAA,EA+EiB,CAAA,CAAE,KA/EnB,CA+EyB,CA/EzB,CAAA;EAAU,EAAA,EAAA,MAAA;EAQwB,IAAA,EAAA,MAAA,GAAA,MAAA,GAkEX,SAlEW;EAChB,MAAA,EAkEX,wBAlEW;EADgB,WAAA,CAAA,KAAA,EAsEjB,cAtEiB,CAsEF,CAtEE,EAsEC,CAtED,CAAA,EAAA,KAAA,EAuEjB,CAAA,CAAE,KAvEe,CAuET,CAvES,CAAA;EAChB,QAAA,CAAA,CAAA,EAAA,MAAA;;AAOlB,cA2EG,qBA3EH,CAAA,CAAA,EAAA,UA2EsC,wBA3EtC,CAAA,CAAA;EACuB,SAAA,KAAA,EAkFN,cAlFM,CAkFS,CAlFT,EAkFY,CAlFZ,CAAA;EAAb,SAAA,OAAA,EAAA,CAAA,GAAA,EAmFe,cAnFf,EAAA,GAmFkC,OAnFlC,CAmF0C,CAAA,CAAE,KAnF5C,CAmFkD,CAnFlD,CAAA,CAAA;EAAf,KAAA,CAAA,EA2EY,CAAA,CAAE,KA3Ed,CA2EoB,CA3EpB,CAAA;EACqB,QAAA,EAAA,OAAA;EAA0B,EAAA,EAAA,MAAA;EAC1C,IAAA,EAAA,MAAA,GAAA,MAAA,GA4EuB,SA5EvB;EACE,MAAA,EA4EK,wBA5EL;EACP,WAAA,CAAA,KAAA,EA8EsB,cA9EtB,CA8EqC,CA9ErC,EA8EwC,CA9ExC,CAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EA+E8B,cA/E9B,EAAA,GA+EiD,OA/EjD,CA+EyD,CAAA,CAAE,KA/E3D,CA+EiE,CA/EjE,CAAA,CAAA;EAC6B,OAAA,CAAA,GAAA,EAqFb,cArFa,CAAA,EAqFI,OArFJ,CAqFY,CAAA,CAAE,KArFd,CAqFoB,CArFpB,CAAA,CAAA;EAAb,QAAA,CAAA,CAAA,EAAA,MAAA;;AAAf,KAkGM,iBAAA,GACR,SAnGE,GAoGF,cApGE,CAAA,GAAA,EAAA,GAAA,CAAA,GAqGF,mBArGE,CAAA,GAAA,EAAA,GAAA,CAAA,GAsGF,qBAtGE,CAAA,GAAA,EAAA,GAAA,CAAA;AAC4B,KAuGtB,kBAAA,GACR,cAxG8B,CAAA,GAAA,EAAA,GAAA,CAAA,GAyG9B,mBAzG8B,CAAA,GAAA,EAAA,GAAA,CAAA,GA0G9B,qBA1G8B,CAAA,GAAA,EAAA,GAAA,CAAA"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
//#region src/token/injection-token.mts
|
|
2
|
+
/**
|
|
3
|
+
* Simple hash function for deterministic ID generation
|
|
4
|
+
*/ function simpleHash(str) {
|
|
5
|
+
let hash = 0;
|
|
6
|
+
for (let i = 0; i < str.length; i++) {
|
|
7
|
+
const char = str.charCodeAt(i);
|
|
8
|
+
hash = (hash << 5) - hash + char;
|
|
9
|
+
hash = hash & hash;
|
|
10
|
+
}
|
|
11
|
+
return Math.abs(hash).toString(36);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Generate deterministic ID from token name
|
|
15
|
+
*/ function generateTokenId(name, customId) {
|
|
16
|
+
if (customId) return customId;
|
|
17
|
+
let base;
|
|
18
|
+
if (typeof name === "function") base = `${name.name}_${name.toString()}`;
|
|
19
|
+
else if (typeof name === "symbol") base = `symbol_${name.toString()}`;
|
|
20
|
+
else base = `token_${name}`;
|
|
21
|
+
return `${base.split("_")[0]}_${simpleHash(base)}`;
|
|
22
|
+
}
|
|
23
|
+
var InjectionToken = class InjectionToken {
|
|
24
|
+
name;
|
|
25
|
+
schema;
|
|
26
|
+
id;
|
|
27
|
+
formattedName = null;
|
|
28
|
+
constructor(name, schema, customId) {
|
|
29
|
+
this.name = name;
|
|
30
|
+
this.schema = schema;
|
|
31
|
+
this.id = generateTokenId(name, customId);
|
|
32
|
+
}
|
|
33
|
+
static create(name, schema, customId) {
|
|
34
|
+
return new InjectionToken(name, schema, customId);
|
|
35
|
+
}
|
|
36
|
+
static bound(token, value) {
|
|
37
|
+
return new BoundInjectionToken(token, value);
|
|
38
|
+
}
|
|
39
|
+
static factory(token, factory) {
|
|
40
|
+
return new FactoryInjectionToken(token, factory);
|
|
41
|
+
}
|
|
42
|
+
static refineType(token) {
|
|
43
|
+
return token;
|
|
44
|
+
}
|
|
45
|
+
toString() {
|
|
46
|
+
if (this.formattedName) return this.formattedName;
|
|
47
|
+
const { name } = this;
|
|
48
|
+
if (typeof name === "function") this.formattedName = `${name.name}(${this.id})`;
|
|
49
|
+
else if (typeof name === "symbol") this.formattedName = `${name.toString()}(${this.id})`;
|
|
50
|
+
else this.formattedName = `${name}(${this.id})`;
|
|
51
|
+
return this.formattedName;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var BoundInjectionToken = class {
|
|
55
|
+
token;
|
|
56
|
+
value;
|
|
57
|
+
id;
|
|
58
|
+
name;
|
|
59
|
+
schema;
|
|
60
|
+
constructor(token, value) {
|
|
61
|
+
this.token = token;
|
|
62
|
+
this.value = value;
|
|
63
|
+
this.name = token.name;
|
|
64
|
+
this.id = token.id;
|
|
65
|
+
this.schema = token.schema;
|
|
66
|
+
}
|
|
67
|
+
toString() {
|
|
68
|
+
return this.token.toString();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var FactoryInjectionToken = class {
|
|
72
|
+
token;
|
|
73
|
+
factory;
|
|
74
|
+
value;
|
|
75
|
+
resolved = false;
|
|
76
|
+
id;
|
|
77
|
+
name;
|
|
78
|
+
schema;
|
|
79
|
+
constructor(token, factory) {
|
|
80
|
+
this.token = token;
|
|
81
|
+
this.factory = factory;
|
|
82
|
+
this.name = token.name;
|
|
83
|
+
this.id = token.id;
|
|
84
|
+
this.schema = token.schema;
|
|
85
|
+
}
|
|
86
|
+
async resolve(ctx) {
|
|
87
|
+
if (!this.value) {
|
|
88
|
+
this.value = await this.factory(ctx);
|
|
89
|
+
this.resolved = true;
|
|
90
|
+
}
|
|
91
|
+
return this.value;
|
|
92
|
+
}
|
|
93
|
+
toString() {
|
|
94
|
+
return this.token.toString();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
export { BoundInjectionToken, FactoryInjectionToken, InjectionToken };
|
|
100
|
+
//# sourceMappingURL=injection-token.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injection-token.mjs","names":["simpleHash","str","hash","i","length","char","charCodeAt","Math","abs","toString","generateTokenId","name","customId","base","split","InjectionToken","id","formattedName","schema","create","bound","token","value","BoundInjectionToken","factory","FactoryInjectionToken","refineType","className","resolved","resolve","ctx"],"sources":["../../../src/token/injection-token.mts"],"sourcesContent":["import type { z, ZodObject, ZodOptional, ZodRecord } from 'zod/v4'\n\nimport type { FactoryContext } from '../internal/context/factory-context.mjs'\n\nexport type ClassType = new (...args: any[]) => any\nexport type ClassTypeWithoutArguments = new () => any\nexport type ClassTypeWithArgument<Arg> = new (arg: Arg) => any\nexport type ClassTypeWithOptionalArgument<Arg> = new (arg?: Arg) => any\n\nexport type ClassTypeWithInstance<T> = new (...args: any[]) => T\nexport type ClassTypeWithInstanceAndArgument<T, Arg> = new (arg: Arg) => T\nexport type ClassTypeWithInstanceAndOptionalArgument<T, Arg> = new (\n arg?: Arg,\n) => T\n\nexport type BaseInjectionTokenSchemaType = ZodObject | ZodRecord\n\nexport type OptionalInjectionTokenSchemaType =\n | ZodOptional<ZodObject>\n | ZodOptional<ZodRecord>\n\nexport type InjectionTokenSchemaType =\n | BaseInjectionTokenSchemaType\n | OptionalInjectionTokenSchemaType\n\n/**\n * Simple hash function for deterministic ID generation\n */\nfunction simpleHash(str: string): string {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash).toString(36)\n}\n\n/**\n * Generate deterministic ID from token name\n */\nfunction generateTokenId(name: string | symbol | ClassType, customId?: string): string {\n if (customId) {\n return customId\n }\n\n let base: string\n if (typeof name === 'function') {\n base = `${name.name}_${name.toString()}`\n } else if (typeof name === 'symbol') {\n base = `symbol_${name.toString()}`\n } else {\n base = `token_${name}`\n }\n\n return `${base.split('_')[0]}_${simpleHash(base)}`\n}\n\nexport class InjectionToken<\n // oxlint-disable-next-line no-unused-vars\n T,\n S extends InjectionTokenSchemaType | unknown = unknown,\n // oxlint-disable-next-line no-unused-vars\n Required extends boolean = S extends ZodOptional<ZodObject>\n ? false\n : S extends ZodOptional<ZodRecord>\n ? false\n : S extends ZodObject\n ? true\n : S extends ZodRecord\n ? true\n : false,\n> {\n public readonly id: string\n private formattedName: string | null = null\n\n constructor(\n public readonly name: string | symbol | ClassType,\n public readonly schema: ZodObject | undefined,\n customId?: string,\n ) {\n this.id = generateTokenId(name, customId)\n }\n\n static create<T extends ClassType>(\n name: T,\n ): InjectionToken<InstanceType<T>, undefined>\n static create<T extends ClassType, Schema extends InjectionTokenSchemaType>(\n name: T,\n schema: Schema,\n ): Schema['_def']['type'] extends 'ZodOptional'\n ? InjectionToken<InstanceType<T>, Schema, false>\n : InjectionToken<InstanceType<T>, Schema, true>\n static create<T>(name: string | symbol): InjectionToken<T, undefined>\n static create<T, Schema extends InjectionTokenSchemaType>(\n name: string | any,\n schema: Schema,\n ): InjectionToken<T, Schema>\n static create(name: string | symbol, schema?: unknown, customId?: string) {\n // @ts-expect-error\n return new InjectionToken(name, schema, customId)\n }\n\n static bound<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n value: z.input<S>,\n ): BoundInjectionToken<T, S> {\n return new BoundInjectionToken(token, value)\n }\n\n static factory<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n factory: (ctx: FactoryContext) => Promise<z.input<S>>,\n ): FactoryInjectionToken<T, S> {\n return new FactoryInjectionToken(token, factory)\n }\n\n static refineType<T>(\n token: BoundInjectionToken<any, any>,\n ): BoundInjectionToken<T, any> {\n return token as BoundInjectionToken<T, any>\n }\n\n toString() {\n if (this.formattedName) {\n return this.formattedName\n }\n const { name } = this\n if (typeof name === 'function') {\n const className = name.name\n this.formattedName = `${className}(${this.id})`\n } else if (typeof name === 'symbol') {\n this.formattedName = `${name.toString()}(${this.id})`\n } else {\n this.formattedName = `${name}(${this.id})`\n }\n\n return this.formattedName\n }\n}\n\nexport class BoundInjectionToken<T, S extends InjectionTokenSchemaType> {\n public id: string\n public name: string | symbol | ClassType\n public schema: InjectionTokenSchemaType\n\n constructor(\n public readonly token: InjectionToken<T, S>,\n public readonly value: z.input<S>,\n ) {\n this.name = token.name\n this.id = token.id\n this.schema = token.schema as InjectionTokenSchemaType\n }\n\n toString() {\n return this.token.toString()\n }\n}\n\nexport class FactoryInjectionToken<T, S extends InjectionTokenSchemaType> {\n public value?: z.input<S>\n public resolved = false\n public id: string\n public name: string | symbol | ClassType\n public schema: InjectionTokenSchemaType\n\n constructor(\n public readonly token: InjectionToken<T, S>,\n public readonly factory: (ctx: FactoryContext) => Promise<z.input<S>>,\n ) {\n this.name = token.name\n this.id = token.id\n this.schema = token.schema as InjectionTokenSchemaType\n }\n\n async resolve(ctx: FactoryContext): Promise<z.input<S>> {\n if (!this.value) {\n this.value = await this.factory(ctx)\n this.resolved = true\n }\n return this.value\n }\n\n toString() {\n return this.token.toString()\n }\n}\n\nexport type AnyInjectableType =\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>\n\nexport type InjectionTokenType =\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>\n\n"],"mappings":";;;GA4BA,SAASA,WAAWC,KAAW;CAC7B,IAAIC,OAAO;AACX,MAAK,IAAIC,IAAI,GAAGA,IAAIF,IAAIG,QAAQD,KAAK;EACnC,MAAME,OAAOJ,IAAIK,WAAWH,EAAAA;AAC5BD,UAAQA,QAAQ,KAAKA,OAAOG;AAC5BH,SAAOA,OAAOA;;AAEhB,QAAOK,KAAKC,IAAIN,KAAAA,CAAMO,SAAS,GAAA;;;;GAMjC,SAASC,gBAAgBC,MAAmCC,UAAiB;AAC3E,KAAIA,SACF,QAAOA;CAGT,IAAIC;AACJ,KAAI,OAAOF,SAAS,WAClBE,QAAO,GAAGF,KAAKA,KAAK,GAAGA,KAAKF,UAAQ;UAC3B,OAAOE,SAAS,SACzBE,QAAO,UAAUF,KAAKF,UAAQ;KAE9BI,QAAO,SAASF;AAGlB,QAAO,GAAGE,KAAKC,MAAM,IAAI,CAAC,GAAG,GAAGd,WAAWa,KAAAA;;AAG7C,IAAaE,iBAAb,MAAaA,eAAAA;;;CAeKC;CACRC,gBAA+B;CAEvC,YACE,MACA,QACAL,UACA;OAHgBD,OAAAA;OACAO,SAAAA;AAGhB,OAAKF,KAAKN,gBAAgBC,MAAMC,SAAAA;;CAiBlC,OAAOO,OAAOR,MAAuBO,QAAkBN,UAAmB;AAExE,SAAO,IAAIG,eAAeJ,MAAMO,QAAQN,SAAAA;;CAG1C,OAAOQ,MACLC,OACAC,OAC2B;AAC3B,SAAO,IAAIC,oBAAoBF,OAAOC,MAAAA;;CAGxC,OAAOE,QACLH,OACAG,SAC6B;AAC7B,SAAO,IAAIC,sBAAsBJ,OAAOG,QAAAA;;CAG1C,OAAOE,WACLL,OAC6B;AAC7B,SAAOA;;CAGTZ,WAAW;AACT,MAAI,KAAKQ,cACP,QAAO,KAAKA;EAEd,MAAM,EAAEN,SAAS;AACjB,MAAI,OAAOA,SAAS,WAElB,MAAKM,gBAAgB,GADHN,KAAKA,KACW,GAAG,KAAKK,GAAG;WACpC,OAAOL,SAAS,SACzB,MAAKM,gBAAgB,GAAGN,KAAKF,UAAQ,CAAG,GAAG,KAAKO,GAAG;MAEnD,MAAKC,gBAAgB,GAAGN,KAAK,GAAG,KAAKK,GAAG;AAG1C,SAAO,KAAKC;;;AAIhB,IAAaM,sBAAb,MAAaA;;;CACJP;CACAL;CACAO;CAEP,YACE,OACA,OACA;OAFgBG,QAAAA;OACAC,QAAAA;AAEhB,OAAKX,OAAOU,MAAMV;AAClB,OAAKK,KAAKK,MAAML;AAChB,OAAKE,SAASG,MAAMH;;CAGtBT,WAAW;AACT,SAAO,KAAKY,MAAMZ,UAAQ;;;AAI9B,IAAagB,wBAAb,MAAaA;;;CACJH;CACAM,WAAW;CACXZ;CACAL;CACAO;CAEP,YACE,OACA,SACA;OAFgBG,QAAAA;OACAG,UAAAA;AAEhB,OAAKb,OAAOU,MAAMV;AAClB,OAAKK,KAAKK,MAAML;AAChB,OAAKE,SAASG,MAAMH;;CAGtB,MAAMW,QAAQC,KAA0C;AACtD,MAAI,CAAC,KAAKR,OAAO;AACf,QAAKA,QAAQ,MAAM,KAAKE,QAAQM,IAAAA;AAChC,QAAKF,WAAW;;AAElB,SAAO,KAAKN;;CAGdb,WAAW;AACT,SAAO,KAAKY,MAAMZ,UAAQ"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ClassType, InjectionToken } from "./injection-token.mjs";
|
|
2
|
+
import { InjectableScope } from "../enums/injectable-scope.enum.mjs";
|
|
3
|
+
import { InjectableType } from "../enums/injectable-type.enum.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/token/registry.d.mts
|
|
6
|
+
type FactoryRecord<Instance = any, Schema = any> = {
|
|
7
|
+
scope: InjectableScope;
|
|
8
|
+
originalToken: InjectionToken<Instance, Schema>;
|
|
9
|
+
target: ClassType;
|
|
10
|
+
type: InjectableType;
|
|
11
|
+
priority: number;
|
|
12
|
+
};
|
|
13
|
+
declare class Registry {
|
|
14
|
+
private readonly parent?;
|
|
15
|
+
private readonly factories;
|
|
16
|
+
private readonly highestPriority;
|
|
17
|
+
constructor(parent?: Registry | undefined);
|
|
18
|
+
has(token: InjectionToken<any, any>): boolean;
|
|
19
|
+
get<Instance, Schema>(token: InjectionToken<Instance, Schema>): FactoryRecord<Instance, Schema>;
|
|
20
|
+
getAll<Instance, Schema>(token: InjectionToken<Instance, Schema>): FactoryRecord<Instance, Schema>[];
|
|
21
|
+
set<Instance, Schema>(token: InjectionToken<Instance, Schema>, scope: InjectableScope, target: ClassType, type: InjectableType, priority?: number): void;
|
|
22
|
+
delete(token: InjectionToken<any, any>): void;
|
|
23
|
+
/**
|
|
24
|
+
* Updates the scope of an already registered factory.
|
|
25
|
+
* This is useful when you need to dynamically change a service's scope
|
|
26
|
+
* (e.g., when a singleton controller has request-scoped dependencies).
|
|
27
|
+
*
|
|
28
|
+
* @param token The injection token to update
|
|
29
|
+
* @param scope The new scope to set
|
|
30
|
+
* @returns true if the scope was updated, false if the token was not found
|
|
31
|
+
*/
|
|
32
|
+
updateScope(token: InjectionToken<any, any>, scope: InjectableScope): boolean;
|
|
33
|
+
}
|
|
34
|
+
declare const globalRegistry: Registry;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { FactoryRecord, Registry, globalRegistry };
|
|
37
|
+
//# sourceMappingURL=registry.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.mts","names":[],"sources":["../../../src/token/registry.mts"],"sourcesContent":[],"mappings":";;;;;KAIY;SACH;iBACQ,eAAe,UAAU;EAF9B,MAAA,EAGF,SAHe;EAChB,IAAA,EAGD,cAHC;EACuB,QAAA,EAAA,MAAA;CAAU;AAAzB,cAMJ,QAAA,CANI;EACP,iBAAA,MAAA;EACF,iBAAA,SAAA;EAAc,iBAAA,eAAA;EAIT,WAAQ,CAAA,MAAA,CAAA,EAImB,QAJnB,GAAA,SAAA;EAImB,GAAA,CAAA,KAAA,EAE3B,cAF2B,CAAA,GAAA,EAAA,GAAA,CAAA,CAAA,EAAA,OAAA;EAE3B,GAAA,CAAA,QAAA,EAAA,MAAA,CAAA,CAAA,KAAA,EAWF,cAXE,CAWa,QAXb,EAWuB,MAXvB,CAAA,CAAA,EAYR,aAZQ,CAYM,QAZN,EAYgB,MAZhB,CAAA;EAWa,MAAA,CAAA,QAAA,EAAA,MAAA,CAAA,CAAA,KAAA,EAaf,cAbe,CAaA,QAbA,EAaU,MAbV,CAAA,CAAA,EAcrB,aAdqB,CAcP,QAdO,EAcG,MAdH,CAAA,EAAA;EAAU,GAAA,CAAA,QAAA,EAAA,MAAA,CAAA,CAAA,KAAA,EA2BzB,cA3ByB,CA2BV,QA3BU,EA2BA,MA3BA,CAAA,EAAA,KAAA,EA4BzB,eA5ByB,EAAA,MAAA,EA6BxB,SA7BwB,EAAA,IAAA,EA8B1B,cA9B0B,EAAA,QAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAzB,MAAA,CAAA,KAAA,EAqDK,cArDL,CAAA,GAAA,EAAA,GAAA,CAAA,CAAA,EAAA,IAAA;EACQ;;;;;;;;;EA0BO,WAAA,CAAA,KAAA,EA6Df,cA7De,CAAA,GAAA,EAAA,GAAA,CAAA,EAAA,KAAA,EA8Df,eA9De,CAAA,EAAA,OAAA;;AAAf,cAoFE,cApFF,EAoFgB,QApFhB"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//#region src/token/registry.mts
|
|
2
|
+
var Registry = class {
|
|
3
|
+
parent;
|
|
4
|
+
factories = /* @__PURE__ */ new Map();
|
|
5
|
+
highestPriority = /* @__PURE__ */ new Map();
|
|
6
|
+
constructor(parent) {
|
|
7
|
+
this.parent = parent;
|
|
8
|
+
}
|
|
9
|
+
has(token) {
|
|
10
|
+
if (this.factories.has(token.id)) return true;
|
|
11
|
+
if (this.parent) return this.parent.has(token);
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
get(token) {
|
|
15
|
+
const factory = this.highestPriority.get(token.id);
|
|
16
|
+
if (!factory) {
|
|
17
|
+
if (this.parent) return this.parent.get(token);
|
|
18
|
+
throw new Error(`[Registry] No factory found for ${token.toString()}`);
|
|
19
|
+
}
|
|
20
|
+
return factory;
|
|
21
|
+
}
|
|
22
|
+
getAll(token) {
|
|
23
|
+
const records = this.factories.get(token.id);
|
|
24
|
+
if (!records || records.length === 0) {
|
|
25
|
+
if (this.parent) return this.parent.getAll(token);
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
return [...records].sort((a, b) => b.priority - a.priority);
|
|
29
|
+
}
|
|
30
|
+
set(token, scope, target, type, priority = 0) {
|
|
31
|
+
const record = {
|
|
32
|
+
scope,
|
|
33
|
+
originalToken: token,
|
|
34
|
+
target,
|
|
35
|
+
type,
|
|
36
|
+
priority
|
|
37
|
+
};
|
|
38
|
+
const existing = this.factories.get(token.id) || [];
|
|
39
|
+
existing.push(record);
|
|
40
|
+
this.factories.set(token.id, existing);
|
|
41
|
+
const currentHighest = this.highestPriority.get(token.id);
|
|
42
|
+
if (!currentHighest || priority > currentHighest.priority) this.highestPriority.set(token.id, record);
|
|
43
|
+
}
|
|
44
|
+
delete(token) {
|
|
45
|
+
const records = this.factories.get(token.id);
|
|
46
|
+
if (records) {
|
|
47
|
+
const deletedHighest = this.highestPriority.get(token.id);
|
|
48
|
+
this.factories.delete(token.id);
|
|
49
|
+
this.highestPriority.delete(token.id);
|
|
50
|
+
if (deletedHighest && records.length > 1) {
|
|
51
|
+
const remaining = records.filter((r) => r.originalToken.id !== deletedHighest.originalToken.id || r.priority !== deletedHighest.priority);
|
|
52
|
+
if (remaining.length > 0) {
|
|
53
|
+
const newHighest = remaining.reduce((max, current) => current.priority > max.priority ? current : max);
|
|
54
|
+
this.highestPriority.set(token.id, newHighest);
|
|
55
|
+
this.factories.set(token.id, remaining);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Updates the scope of an already registered factory.
|
|
62
|
+
* This is useful when you need to dynamically change a service's scope
|
|
63
|
+
* (e.g., when a singleton controller has request-scoped dependencies).
|
|
64
|
+
*
|
|
65
|
+
* @param token The injection token to update
|
|
66
|
+
* @param scope The new scope to set
|
|
67
|
+
* @returns true if the scope was updated, false if the token was not found
|
|
68
|
+
*/ updateScope(token, scope) {
|
|
69
|
+
const records = this.factories.get(token.id);
|
|
70
|
+
if (records && records.length > 0) {
|
|
71
|
+
records.forEach((record) => {
|
|
72
|
+
record.scope = scope;
|
|
73
|
+
});
|
|
74
|
+
const highest = this.highestPriority.get(token.id);
|
|
75
|
+
if (highest) highest.scope = scope;
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (this.parent) return this.parent.updateScope(token, scope);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const globalRegistry = /* @__PURE__ */ new Registry();
|
|
83
|
+
|
|
84
|
+
//#endregion
|
|
85
|
+
export { Registry, globalRegistry };
|
|
86
|
+
//# sourceMappingURL=registry.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.mjs","names":["Registry","factories","Map","highestPriority","parent","has","token","id","get","factory","Error","toString","getAll","records","length","sort","a","b","priority","set","scope","target","type","record","originalToken","existing","push","currentHighest","delete","deletedHighest","remaining","filter","r","newHighest","reduce","max","current","updateScope","forEach","highest","globalRegistry"],"sources":["../../../src/token/registry.mts"],"sourcesContent":["import type { ClassType, InjectionToken } from './injection-token.mjs'\n\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\n\nexport type FactoryRecord<Instance = any, Schema = any> = {\n scope: InjectableScope\n originalToken: InjectionToken<Instance, Schema>\n target: ClassType\n type: InjectableType\n priority: number\n}\n\nexport class Registry {\n private readonly factories = new Map<string, FactoryRecord[]>()\n private readonly highestPriority = new Map<string, FactoryRecord>()\n\n constructor(private readonly parent?: Registry) {}\n\n has(token: InjectionToken<any, any>): boolean {\n if (this.factories.has(token.id)) {\n return true\n }\n if (this.parent) {\n return this.parent.has(token)\n }\n return false\n }\n\n get<Instance, Schema>(\n token: InjectionToken<Instance, Schema>,\n ): FactoryRecord<Instance, Schema> {\n const factory = this.highestPriority.get(token.id)\n if (!factory) {\n if (this.parent) {\n return this.parent.get(token)\n }\n throw new Error(`[Registry] No factory found for ${token.toString()}`)\n }\n return factory\n }\n\n getAll<Instance, Schema>(\n token: InjectionToken<Instance, Schema>,\n ): FactoryRecord<Instance, Schema>[] {\n const records = this.factories.get(token.id)\n if (!records || records.length === 0) {\n if (this.parent) {\n return this.parent.getAll(token)\n }\n return []\n }\n // Return sorted by priority (highest first)\n return [...records].sort((a, b) => b.priority - a.priority)\n }\n\n set<Instance, Schema>(\n token: InjectionToken<Instance, Schema>,\n scope: InjectableScope,\n target: ClassType,\n type: InjectableType,\n priority: number = 0,\n ) {\n const record: FactoryRecord<Instance, Schema> = {\n scope,\n originalToken: token,\n target,\n type,\n priority,\n }\n\n // Add to factories array\n const existing = this.factories.get(token.id) || []\n existing.push(record)\n this.factories.set(token.id, existing)\n\n // Update highest priority cache if needed\n const currentHighest = this.highestPriority.get(token.id)\n if (!currentHighest || priority > currentHighest.priority) {\n this.highestPriority.set(token.id, record)\n }\n }\n\n delete(token: InjectionToken<any, any>) {\n const records = this.factories.get(token.id)\n if (records) {\n const deletedHighest = this.highestPriority.get(token.id)\n this.factories.delete(token.id)\n this.highestPriority.delete(token.id)\n\n // If we deleted the highest priority record, recalculate from remaining records\n if (deletedHighest && records.length > 1) {\n const remaining = records.filter(\n (r) =>\n r.originalToken.id !== deletedHighest.originalToken.id ||\n r.priority !== deletedHighest.priority,\n )\n if (remaining.length > 0) {\n const newHighest = remaining.reduce((max, current) =>\n current.priority > max.priority ? current : max,\n )\n this.highestPriority.set(token.id, newHighest)\n this.factories.set(token.id, remaining)\n }\n }\n }\n }\n\n /**\n * Updates the scope of an already registered factory.\n * This is useful when you need to dynamically change a service's scope\n * (e.g., when a singleton controller has request-scoped dependencies).\n *\n * @param token The injection token to update\n * @param scope The new scope to set\n * @returns true if the scope was updated, false if the token was not found\n */\n updateScope(\n token: InjectionToken<any, any>,\n scope: InjectableScope,\n ): boolean {\n const records = this.factories.get(token.id)\n if (records && records.length > 0) {\n // Update all records\n records.forEach((record) => {\n record.scope = scope\n })\n // Update highest priority cache if it exists\n const highest = this.highestPriority.get(token.id)\n if (highest) {\n highest.scope = scope\n }\n return true\n }\n if (this.parent) {\n return this.parent.updateScope(token, scope)\n }\n return false\n }\n}\n\nexport const globalRegistry = /* #__PURE__ */ new Registry()\n"],"mappings":";AAYA,IAAaA,WAAb,MAAaA;;CACMC,4BAAY,IAAIC,KAAAA;CAChBC,kCAAkB,IAAID,KAAAA;CAEvC,YAAY,QAAoC;OAAnBE,SAAAA;;CAE7BC,IAAIC,OAA0C;AAC5C,MAAI,KAAKL,UAAUI,IAAIC,MAAMC,GAAE,CAC7B,QAAO;AAET,MAAI,KAAKH,OACP,QAAO,KAAKA,OAAOC,IAAIC,MAAAA;AAEzB,SAAO;;CAGTE,IACEF,OACiC;EACjC,MAAMG,UAAU,KAAKN,gBAAgBK,IAAIF,MAAMC,GAAE;AACjD,MAAI,CAACE,SAAS;AACZ,OAAI,KAAKL,OACP,QAAO,KAAKA,OAAOI,IAAIF,MAAAA;AAEzB,SAAM,IAAII,MAAM,mCAAmCJ,MAAMK,UAAQ,GAAI;;AAEvE,SAAOF;;CAGTG,OACEN,OACmC;EACnC,MAAMO,UAAU,KAAKZ,UAAUO,IAAIF,MAAMC,GAAE;AAC3C,MAAI,CAACM,WAAWA,QAAQC,WAAW,GAAG;AACpC,OAAI,KAAKV,OACP,QAAO,KAAKA,OAAOQ,OAAON,MAAAA;AAE5B,UAAO,EAAE;;AAGX,SAAO,IAAIO,QAAQ,CAACE,MAAMC,GAAGC,MAAMA,EAAEC,WAAWF,EAAEE,SAAQ;;CAG5DC,IACEb,OACAc,OACAC,QACAC,MACAJ,WAAmB,GACnB;EACA,MAAMK,SAA0C;GAC9CH;GACAI,eAAelB;GACfe;GACAC;GACAJ;GACF;EAGA,MAAMO,WAAW,KAAKxB,UAAUO,IAAIF,MAAMC,GAAE,IAAK,EAAE;AACnDkB,WAASC,KAAKH,OAAAA;AACd,OAAKtB,UAAUkB,IAAIb,MAAMC,IAAIkB,SAAAA;EAG7B,MAAME,iBAAiB,KAAKxB,gBAAgBK,IAAIF,MAAMC,GAAE;AACxD,MAAI,CAACoB,kBAAkBT,WAAWS,eAAeT,SAC/C,MAAKf,gBAAgBgB,IAAIb,MAAMC,IAAIgB,OAAAA;;CAIvCK,OAAOtB,OAAiC;EACtC,MAAMO,UAAU,KAAKZ,UAAUO,IAAIF,MAAMC,GAAE;AAC3C,MAAIM,SAAS;GACX,MAAMgB,iBAAiB,KAAK1B,gBAAgBK,IAAIF,MAAMC,GAAE;AACxD,QAAKN,UAAU2B,OAAOtB,MAAMC,GAAE;AAC9B,QAAKJ,gBAAgByB,OAAOtB,MAAMC,GAAE;AAGpC,OAAIsB,kBAAkBhB,QAAQC,SAAS,GAAG;IACxC,MAAMgB,YAAYjB,QAAQkB,QACvBC,MACCA,EAAER,cAAcjB,OAAOsB,eAAeL,cAAcjB,MACpDyB,EAAEd,aAAaW,eAAeX,SAAQ;AAE1C,QAAIY,UAAUhB,SAAS,GAAG;KACxB,MAAMmB,aAAaH,UAAUI,QAAQC,KAAKC,YACxCA,QAAQlB,WAAWiB,IAAIjB,WAAWkB,UAAUD,IAAAA;AAE9C,UAAKhC,gBAAgBgB,IAAIb,MAAMC,IAAI0B,WAAAA;AACnC,UAAKhC,UAAUkB,IAAIb,MAAMC,IAAIuB,UAAAA;;;;;;;;;;;;;IAerCO,YACE/B,OACAc,OACS;EACT,MAAMP,UAAU,KAAKZ,UAAUO,IAAIF,MAAMC,GAAE;AAC3C,MAAIM,WAAWA,QAAQC,SAAS,GAAG;AAEjCD,WAAQyB,SAASf,WAAAA;AACfA,WAAOH,QAAQA;KACjB;GAEA,MAAMmB,UAAU,KAAKpC,gBAAgBK,IAAIF,MAAMC,GAAE;AACjD,OAAIgC,QACFA,SAAQnB,QAAQA;AAElB,UAAO;;AAET,MAAI,KAAKhB,OACP,QAAO,KAAKA,OAAOiC,YAAY/B,OAAOc,MAAAA;AAExC,SAAO;;;AAIX,MAAaoB,iCAAiC,IAAIxC,UAAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Injectors } from "./get-injectors.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/default-injectors.d.mts
|
|
4
|
+
declare const defaultInjectors: Injectors;
|
|
5
|
+
declare const inject: Injectors['inject'];
|
|
6
|
+
declare const optional: Injectors['optional'];
|
|
7
|
+
declare const asyncInject: Injectors['asyncInject'];
|
|
8
|
+
declare const wrapSyncInit: Injectors['wrapSyncInit'];
|
|
9
|
+
declare const provideFactoryContext: Injectors['provideFactoryContext'];
|
|
10
|
+
//#endregion
|
|
11
|
+
export { asyncInject, defaultInjectors, inject, optional, provideFactoryContext, wrapSyncInit };
|
|
12
|
+
//# sourceMappingURL=default-injectors.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-injectors.d.mts","names":[],"sources":["../../../src/utils/default-injectors.mts"],"sourcesContent":[],"mappings":";;;cAIa,kBAAgB;cAEhB,QAAQ;AAFR,cAIA,QAJiD,EAIvC,SAJM,CAAA,UAAiC,CAAA;AAEjD,cAIA,WAJQ,EAIK,SAJI,CAAA,aAAA,CAAA;AAEjB,cAIA,YAJU,EAII,SAJK,CAAA,cAAA,CAAA;AAEnB,cAIA,qBAJsB,EAIC,SAJD,CAAA,uBAAA,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getInjectors } from "./get-injectors.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/default-injectors.mts
|
|
4
|
+
const defaultInjectors = /* @__PURE__ */ getInjectors();
|
|
5
|
+
const inject = defaultInjectors.inject;
|
|
6
|
+
const optional = defaultInjectors.optional;
|
|
7
|
+
const asyncInject = defaultInjectors.asyncInject;
|
|
8
|
+
const wrapSyncInit = defaultInjectors.wrapSyncInit;
|
|
9
|
+
const provideFactoryContext = defaultInjectors.provideFactoryContext;
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { asyncInject, defaultInjectors, inject, optional, provideFactoryContext, wrapSyncInit };
|
|
13
|
+
//# sourceMappingURL=default-injectors.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-injectors.mjs","names":["inject: Injectors['inject']","optional: Injectors['optional']","asyncInject: Injectors['asyncInject']","wrapSyncInit: Injectors['wrapSyncInit']","provideFactoryContext: Injectors['provideFactoryContext']"],"sources":["../../../src/utils/default-injectors.mts"],"sourcesContent":["import type { Injectors } from './get-injectors.mjs'\n\nimport { getInjectors } from './get-injectors.mjs'\n\nexport const defaultInjectors = /* #__PURE__ */ getInjectors()\n\nexport const inject: Injectors['inject'] =\n /* #__PURE__ */ defaultInjectors.inject\nexport const optional: Injectors['optional'] =\n /* #__PURE__ */ defaultInjectors.optional\nexport const asyncInject: Injectors['asyncInject'] =\n /* #__PURE__ */ defaultInjectors.asyncInject\nexport const wrapSyncInit: Injectors['wrapSyncInit'] =\n /* #__PURE__ */ defaultInjectors.wrapSyncInit\nexport const provideFactoryContext: Injectors['provideFactoryContext'] =\n /* #__PURE__ */ defaultInjectors.provideFactoryContext\n"],"mappings":";;;AAIA,MAAa,mBAAmC,8BAAc;AAE9D,MAAaA,SACK,iBAAiB;AACnC,MAAaC,WACK,iBAAiB;AACnC,MAAaC,cACK,iBAAiB;AACnC,MAAaC,eACK,iBAAiB;AACnC,MAAaC,wBACK,iBAAiB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ClassType, InjectionToken } from "../token/injection-token.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/get-injectable-token.d.mts
|
|
4
|
+
declare function getInjectableToken<R>(target: ClassType): R extends {
|
|
5
|
+
create(...args: any[]): infer V;
|
|
6
|
+
} ? InjectionToken<V> : InjectionToken<R>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { getInjectableToken };
|
|
9
|
+
//# sourceMappingURL=get-injectable-token.d.mts.map
|