@codefast/di 0.3.14-canary.1 → 0.3.14
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 +58 -0
- package/README.md +42 -26
- package/dist/binding-scope.d.mts +11 -0
- package/dist/binding-scope.mjs +19 -0
- package/dist/binding-select.d.mts +8 -26
- package/dist/binding-select.mjs +56 -49
- package/dist/binding.d.mts +107 -335
- package/dist/binding.mjs +19 -332
- package/dist/constraints.d.mts +11 -29
- package/dist/constraints.mjs +32 -36
- package/dist/constructor-type.d.mts +17 -0
- package/dist/constructor-type.mjs +1 -0
- package/dist/container.d.mts +43 -122
- package/dist/container.mjs +667 -482
- package/dist/decorators/inject.d.mts +19 -50
- package/dist/decorators/inject.mjs +131 -93
- package/dist/decorators/injectable.d.mts +16 -37
- package/dist/decorators/injectable.mjs +47 -66
- package/dist/decorators/lifecycle-decorators.d.mts +2 -22
- package/dist/decorators/lifecycle-decorators.mjs +81 -37
- package/dist/dependency-graph.d.mts +24 -54
- package/dist/dependency-graph.mjs +51 -153
- package/dist/environment.d.mts +38 -12
- package/dist/environment.mjs +82 -16
- package/dist/errors.d.mts +70 -189
- package/dist/errors.mjs +92 -219
- package/dist/graph-adapters/cytoscape.d.mts +21 -7
- package/dist/graph-adapters/cytoscape.mjs +18 -35
- package/dist/graph-adapters/dot.d.mts +1 -4
- package/dist/graph-adapters/dot.mjs +6 -86
- package/dist/graph-adapters/reactflow.d.mts +26 -7
- package/dist/graph-adapters/reactflow.mjs +21 -72
- package/dist/graph-adapters/types.d.mts +2 -91
- package/dist/index.d.mts +16 -8
- package/dist/index.mjs +8 -5
- package/dist/inspector.d.mts +35 -74
- package/dist/inspector.mjs +61 -88
- package/dist/lifecycle.d.mts +20 -53
- package/dist/lifecycle.mjs +129 -99
- package/dist/metadata/metadata-keys.d.mts +9 -26
- package/dist/metadata/metadata-keys.mjs +7 -28
- package/dist/metadata/metadata-reader-token.d.mts +7 -0
- package/dist/metadata/metadata-reader-token.mjs +5 -0
- package/dist/metadata/metadata-types.d.mts +26 -75
- package/dist/metadata/symbol-metadata-reader.d.mts +10 -26
- package/dist/metadata/symbol-metadata-reader.mjs +32 -45
- package/dist/module.d.mts +30 -96
- package/dist/module.mjs +26 -72
- package/dist/registry.d.mts +32 -63
- package/dist/registry.mjs +131 -82
- package/dist/resolve-options.d.mts +18 -0
- package/dist/resolve-options.mjs +22 -0
- package/dist/resolver.d.mts +67 -190
- package/dist/resolver.mjs +715 -424
- package/dist/scope.d.mts +19 -106
- package/dist/scope.mjs +37 -196
- package/dist/token.d.mts +8 -22
- package/dist/token.mjs +9 -11
- package/dist/types.d.mts +48 -0
- package/dist/types.mjs +1 -0
- package/package.json +36 -14
- package/dist/metadata/param-registry.d.mts +0 -16
- package/dist/metadata/param-registry.mjs +0 -31
- package/dist/scope-validation.d.mts +0 -21
- package/dist/scope-validation.mjs +0 -35
package/dist/inspector.mjs
CHANGED
|
@@ -1,96 +1,69 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { effectiveBindingScope } from "./binding-scope.mjs";
|
|
2
|
+
import { selectBinding } from "./binding-select.mjs";
|
|
3
|
+
import { tokenName } from "./token.mjs";
|
|
3
4
|
//#region src/inspector.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Returns `true` when the label string belongs to a framework-internal registry key.
|
|
13
|
-
*/
|
|
14
|
-
function registryKeyLabelIsInternal(label) {
|
|
15
|
-
return label.startsWith("CODEFAST_DI_");
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Returns `true` when the registry key resolves to an internal framework label.
|
|
19
|
-
*/
|
|
20
|
-
function isInternalRegistryKey(key) {
|
|
21
|
-
return registryKeyLabelIsInternal(registryKeyLabel(key));
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Reads the container's registry and scope-cache state to produce debug snapshots
|
|
25
|
-
* and canonical dependency-graph output (`nodes` + `edges`).
|
|
26
|
-
*
|
|
27
|
-
* Constructed internally by the container; advanced consumers can also construct it
|
|
28
|
-
* directly via the `@codefast/di/inspector` subpath export.
|
|
29
|
-
*/
|
|
30
|
-
var ContainerInspector = class {
|
|
31
|
-
constructor(ctx) {
|
|
32
|
-
this.ctx = ctx;
|
|
5
|
+
var Inspector = class {
|
|
6
|
+
constructor(_registry, _scope, _hasParent, _isDisposed) {
|
|
7
|
+
this._registry = _registry;
|
|
8
|
+
this._scope = _scope;
|
|
9
|
+
this._hasParent = _hasParent;
|
|
10
|
+
this._isDisposed = _isDisposed;
|
|
33
11
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
12
|
+
inspect() {
|
|
13
|
+
const snapshots = this.allBindingSnapshots();
|
|
14
|
+
return {
|
|
15
|
+
ownBindings: snapshots,
|
|
16
|
+
bindings: snapshots,
|
|
17
|
+
cachedSingletonCount: this._scope.getAllSingletons().size,
|
|
18
|
+
hasParent: this._hasParent,
|
|
19
|
+
isDisposed: this._isDisposed()
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
lookupBindings(token) {
|
|
23
|
+
return this._registry.getAll(token).map((b) => this._toSnapshot(b));
|
|
24
|
+
}
|
|
25
|
+
has(token, hint, parentHas) {
|
|
26
|
+
const bindings = this._registry.getAll(token);
|
|
27
|
+
if (bindings.length > 0) if (hint !== void 0) {
|
|
28
|
+
if (selectBinding(bindings, hint, {
|
|
29
|
+
resolutionPath: [],
|
|
30
|
+
materializationStack: [],
|
|
31
|
+
parent: void 0,
|
|
32
|
+
ancestors: [],
|
|
33
|
+
currentResolveHint: hint
|
|
34
|
+
}, tokenName(token)) !== void 0) return true;
|
|
35
|
+
} else return true;
|
|
36
|
+
return parentHas?.() ?? false;
|
|
37
|
+
}
|
|
38
|
+
hasOwn(token, hint) {
|
|
39
|
+
const bindings = this._registry.getAll(token);
|
|
40
|
+
if (bindings.length === 0) return false;
|
|
41
|
+
if (hint !== void 0) return selectBinding(bindings, hint, {
|
|
42
|
+
resolutionPath: [],
|
|
43
|
+
materializationStack: [],
|
|
44
|
+
parent: void 0,
|
|
45
|
+
ancestors: [],
|
|
46
|
+
currentResolveHint: hint
|
|
47
|
+
}, tokenName(token)) !== void 0;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
allBindingSnapshots() {
|
|
51
|
+
return this._registry.allBindings().map((b) => this._toSnapshot(b));
|
|
62
52
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const visibleNodes = hideInternals ? snapshot.bindings.filter((row) => !registryKeyLabelIsInternal(row.registryKeyLabel)) : [...snapshot.bindings];
|
|
70
|
-
const allowedBindingIds = new Set(visibleNodes.map((row) => row.bindingId));
|
|
71
|
-
const edges = [];
|
|
72
|
-
const edgeSeen = /* @__PURE__ */ new Set();
|
|
73
|
-
for (const registryKey of this.ctx.collectAllRegistryKeys()) {
|
|
74
|
-
if (hideInternals && isInternalRegistryKey(registryKey)) continue;
|
|
75
|
-
const list = this.ctx.lookupBindings(registryKey);
|
|
76
|
-
if (list === void 0) continue;
|
|
77
|
-
const pathStart = [registryKeyLabel(registryKey)];
|
|
78
|
-
for (const consumerBinding of list) {
|
|
79
|
-
if (hideInternals && !allowedBindingIds.has(consumerBinding.id)) continue;
|
|
80
|
-
for (const edge of collectStaticDependencyEdges(consumerBinding, (dependencyKey) => this.ctx.lookupBindings(dependencyKey), this.ctx.metadataReader, pathStart)) {
|
|
81
|
-
if (hideInternals && (!allowedBindingIds.has(edge.fromBindingId) || !allowedBindingIds.has(edge.toBindingId))) continue;
|
|
82
|
-
const edgeKey = `${edge.fromBindingId}->${edge.toBindingId}:${edge.edgeKind}:${edge.injectHintLabel ?? ""}`;
|
|
83
|
-
if (edgeSeen.has(edgeKey)) continue;
|
|
84
|
-
edgeSeen.add(edgeKey);
|
|
85
|
-
edges.push(edge);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
53
|
+
_toSnapshot(b) {
|
|
54
|
+
const scope = effectiveBindingScope(b);
|
|
55
|
+
const slot = b.slot.name !== void 0 ? {
|
|
56
|
+
name: b.slot.name,
|
|
57
|
+
tags: b.slot.tags
|
|
58
|
+
} : { tags: b.slot.tags };
|
|
89
59
|
return {
|
|
90
|
-
|
|
91
|
-
|
|
60
|
+
tokenName: tokenName(b.token),
|
|
61
|
+
kind: b.kind,
|
|
62
|
+
scope,
|
|
63
|
+
slot,
|
|
64
|
+
id: b.id
|
|
92
65
|
};
|
|
93
66
|
}
|
|
94
67
|
};
|
|
95
68
|
//#endregion
|
|
96
|
-
export {
|
|
69
|
+
export { Inspector };
|
package/dist/lifecycle.d.mts
CHANGED
|
@@ -1,56 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Constructor } from "./constructor-type.mjs";
|
|
2
|
+
import { Token } from "./token.mjs";
|
|
3
|
+
import { ActivationHandler, DeactivationHandler, ResolutionContext } from "./types.mjs";
|
|
4
|
+
import { Binding } from "./binding.mjs";
|
|
5
|
+
import { MetadataReader } from "./metadata/metadata-types.mjs";
|
|
3
6
|
|
|
4
7
|
//#region src/lifecycle.d.ts
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* Reads lifecycle metadata ({@link LifecycleMetadata}) directly from a constructor's
|
|
20
|
-
* `Symbol.metadata` object. Bypasses the {@link MetadataReader} abstraction —
|
|
21
|
-
* used by the scope manager during deactivation when the reader is not available.
|
|
22
|
-
*/
|
|
23
|
-
declare function readLifecycleMetadataFromCtor(implementationClass: Constructor<unknown>): LifecycleMetadata | undefined;
|
|
24
|
-
/**
|
|
25
|
-
* Runs the `@postConstruct()` method synchronously if present.
|
|
26
|
-
* Throws {@link AsyncResolutionError} if the method returns a Promise — async lifecycle
|
|
27
|
-
* methods require `resolveAsync`.
|
|
28
|
-
*
|
|
29
|
-
* Lifecycle ordering: `construct` → **`@postConstruct`** → `onActivation` → cache.
|
|
30
|
-
*/
|
|
31
|
-
declare function runPostConstruct(implementationClass: Constructor<unknown>, instance: unknown, pathLabels?: string[]): void;
|
|
32
|
-
/**
|
|
33
|
-
* Runs the `@postConstruct()` method, awaiting if it returns a Promise.
|
|
34
|
-
*/
|
|
35
|
-
declare function runPostConstructAsync(implementationClass: Constructor<unknown>, instance: unknown): Promise<void>;
|
|
36
|
-
/**
|
|
37
|
-
* Runs the `@preDestroy()` method synchronously if present.
|
|
38
|
-
* Throws if the method returns a Promise — use `disposeAsync()` / `unloadAsync()` for async teardown.
|
|
39
|
-
*
|
|
40
|
-
* Lifecycle ordering: `onDeactivation` → **`@preDestroy`**.
|
|
41
|
-
*/
|
|
42
|
-
declare function runPreDestroy(implementationClass: Constructor<unknown>, instance: unknown): void;
|
|
43
|
-
/**
|
|
44
|
-
* Runs the `@preDestroy()` method, awaiting if it returns a Promise.
|
|
45
|
-
*
|
|
46
|
-
* Lifecycle ordering: `onDeactivation` → **`@preDestroy`** (async variant).
|
|
47
|
-
*/
|
|
48
|
-
declare function runPreDestroyAsync(implementationClass: Constructor<unknown>, instance: unknown): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* Runs `onActivation`, awaiting if the handler returns a Promise.
|
|
51
|
-
*
|
|
52
|
-
* Lifecycle ordering: `construct` → `@postConstruct` → **`onActivation`** (async variant) → cache.
|
|
53
|
-
*/
|
|
54
|
-
declare function runActivationAsync(binding: Binding<unknown>, instance: unknown, ctx: ResolutionContext, _pathLabels: readonly string[]): Promise<unknown>;
|
|
8
|
+
declare class LifecycleManager {
|
|
9
|
+
private readonly _activationHooks;
|
|
10
|
+
private readonly _deactivationHooks;
|
|
11
|
+
private _activationVersion;
|
|
12
|
+
registerActivation<const Value>(t: Token<Value> | Constructor<Value>, handler: ActivationHandler<Value>): void;
|
|
13
|
+
hasActivationHandlers<const Value>(t: Token<Value> | Constructor<Value>): boolean;
|
|
14
|
+
get activationVersion(): number;
|
|
15
|
+
registerDeactivation<const Value>(t: Token<Value> | Constructor<Value>, handler: DeactivationHandler<Value>): void;
|
|
16
|
+
runActivation<const Value>(ctx: ResolutionContext, binding: Binding<Value>, instance: Value, metadataReader: MetadataReader): Promise<Value>;
|
|
17
|
+
runActivationSync<const Value>(ctx: ResolutionContext, binding: Binding<Value>, instance: Value, metadataReader: MetadataReader): Value;
|
|
18
|
+
runDeactivation<const Value>(binding: Binding<Value>, instance: Value, metadataReader: MetadataReader): Promise<void>;
|
|
19
|
+
runDeactivationSync<const Value>(binding: Binding<Value>, instance: Value, metadataReader: MetadataReader): void;
|
|
20
|
+
hasAsyncDeactivation<const Value>(binding: Binding<Value>, instance: Value, _metadataReader: MetadataReader): boolean;
|
|
21
|
+
}
|
|
55
22
|
//#endregion
|
|
56
|
-
export {
|
|
23
|
+
export { LifecycleManager };
|
package/dist/lifecycle.mjs
CHANGED
|
@@ -1,102 +1,132 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AsyncDeactivationError } from "./errors.mjs";
|
|
2
|
+
import { tokenName } from "./token.mjs";
|
|
3
3
|
//#region src/lifecycle.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* Lifecycle ordering: `construct` → `@postConstruct` → **`onActivation`** → cache.
|
|
17
|
-
*/
|
|
18
|
-
function runActivation(binding, instance, ctx, pathLabels) {
|
|
19
|
-
const handler = binding.onActivation;
|
|
20
|
-
if (handler === void 0) return instance;
|
|
21
|
-
const bindingLabel = pathLabels[pathLabels.length - 1] ?? "(unknown)";
|
|
22
|
-
const activationResult = handler(ctx, instance);
|
|
23
|
-
if (isPromiseLike(activationResult)) throw new AsyncResolutionError(bindingLabel, pathLabels, "onActivation returned a Promise during synchronous resolution");
|
|
24
|
-
return activationResult;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Reads lifecycle metadata ({@link LifecycleMetadata}) directly from a constructor's
|
|
28
|
-
* `Symbol.metadata` object. Bypasses the {@link MetadataReader} abstraction —
|
|
29
|
-
* used by the scope manager during deactivation when the reader is not available.
|
|
30
|
-
*/
|
|
31
|
-
function readLifecycleMetadataFromCtor(implementationClass) {
|
|
32
|
-
const metadataObject = implementationClass[decoratorMetadataObjectSymbol()];
|
|
33
|
-
if (typeof metadataObject !== "object" || metadataObject === null) return;
|
|
34
|
-
const raw = metadataObject[CODEFAST_DI_LIFECYCLE_METADATA];
|
|
35
|
-
return typeof raw === "object" && raw !== null ? raw : void 0;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Runs the `@postConstruct()` method synchronously if present.
|
|
39
|
-
* Throws {@link AsyncResolutionError} if the method returns a Promise — async lifecycle
|
|
40
|
-
* methods require `resolveAsync`.
|
|
41
|
-
*
|
|
42
|
-
* Lifecycle ordering: `construct` → **`@postConstruct`** → `onActivation` → cache.
|
|
43
|
-
*/
|
|
44
|
-
function runPostConstruct(implementationClass, instance, pathLabels) {
|
|
45
|
-
const meta = readLifecycleMetadataFromCtor(implementationClass);
|
|
46
|
-
if (meta?.postConstruct === void 0) return;
|
|
47
|
-
const methodName = meta.postConstruct;
|
|
48
|
-
const lifecycleMethod = instance[methodName];
|
|
49
|
-
if (typeof lifecycleMethod !== "function") return;
|
|
50
|
-
if (isPromiseLike(lifecycleMethod.call(instance))) {
|
|
51
|
-
const labels = pathLabels ?? [];
|
|
52
|
-
throw new AsyncResolutionError(labels[labels.length - 1] ?? "(unknown)", labels, `@postConstruct() "${methodName}" returned a Promise during synchronous resolution`);
|
|
4
|
+
var LifecycleManager = class {
|
|
5
|
+
_activationHooks = /* @__PURE__ */ new Map();
|
|
6
|
+
_deactivationHooks = /* @__PURE__ */ new Map();
|
|
7
|
+
_activationVersion = 0;
|
|
8
|
+
registerActivation(t, handler) {
|
|
9
|
+
this._activationVersion += 1;
|
|
10
|
+
let list = this._activationHooks.get(t);
|
|
11
|
+
if (list === void 0) {
|
|
12
|
+
list = [];
|
|
13
|
+
this._activationHooks.set(t, list);
|
|
14
|
+
}
|
|
15
|
+
list.push(handler);
|
|
53
16
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
17
|
+
hasActivationHandlers(t) {
|
|
18
|
+
if (this._activationHooks.size === 0) return false;
|
|
19
|
+
const list = this._activationHooks.get(t);
|
|
20
|
+
return list !== void 0 && list.length > 0;
|
|
21
|
+
}
|
|
22
|
+
get activationVersion() {
|
|
23
|
+
return this._activationVersion;
|
|
24
|
+
}
|
|
25
|
+
registerDeactivation(t, handler) {
|
|
26
|
+
let list = this._deactivationHooks.get(t);
|
|
27
|
+
if (list === void 0) {
|
|
28
|
+
list = [];
|
|
29
|
+
this._deactivationHooks.set(t, list);
|
|
30
|
+
}
|
|
31
|
+
list.push(handler);
|
|
32
|
+
}
|
|
33
|
+
async runActivation(ctx, binding, instance, metadataReader) {
|
|
34
|
+
let result = instance;
|
|
35
|
+
if (binding.kind === "class") {
|
|
36
|
+
const lifecycle = metadataReader.getLifecycleMetadata(binding.target);
|
|
37
|
+
if (lifecycle?.postConstruct && lifecycle.postConstruct.length > 0) for (const methodName of lifecycle.postConstruct) {
|
|
38
|
+
const method = result[methodName];
|
|
39
|
+
if (typeof method === "function") {
|
|
40
|
+
const r = method.call(result);
|
|
41
|
+
if (r instanceof Promise) await r;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (binding.kind !== "alias" && binding.onActivation !== void 0) {
|
|
46
|
+
const activated = binding.onActivation(ctx, result);
|
|
47
|
+
result = activated instanceof Promise ? await activated : activated;
|
|
48
|
+
}
|
|
49
|
+
const containerHooks = this._activationHooks.get(binding.token);
|
|
50
|
+
if (containerHooks !== void 0) for (const hook of containerHooks) {
|
|
51
|
+
const activated = hook(ctx, result);
|
|
52
|
+
result = activated instanceof Promise ? await activated : activated;
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
runActivationSync(ctx, binding, instance, metadataReader) {
|
|
57
|
+
let result = instance;
|
|
58
|
+
if (binding.kind === "class") {
|
|
59
|
+
const lifecycle = metadataReader.getLifecycleMetadata(binding.target);
|
|
60
|
+
if (lifecycle?.postConstruct && lifecycle.postConstruct.length > 0) for (const methodName of lifecycle.postConstruct) {
|
|
61
|
+
const method = result[methodName];
|
|
62
|
+
if (typeof method === "function") {
|
|
63
|
+
if (method.call(result) instanceof Promise) throw new Error(`@postConstruct method '${methodName}' returned a Promise. Use resolveAsync() instead.`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (binding.kind !== "alias" && binding.onActivation !== void 0) {
|
|
68
|
+
const activated = binding.onActivation(ctx, result);
|
|
69
|
+
if (activated instanceof Promise) throw new Error(`onActivation for '${tokenName(binding.token)}' returned a Promise. Use resolveAsync() instead.`);
|
|
70
|
+
result = activated;
|
|
71
|
+
}
|
|
72
|
+
const key = tokenName(binding.token);
|
|
73
|
+
const containerHooks = this._activationHooks.get(binding.token);
|
|
74
|
+
if (containerHooks !== void 0) for (const hook of containerHooks) {
|
|
75
|
+
const activated = hook(ctx, result);
|
|
76
|
+
if (activated instanceof Promise) throw new Error(`Container-level onActivation for '${key}' returned a Promise. Use resolveAsync() instead.`);
|
|
77
|
+
result = activated;
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
async runDeactivation(binding, instance, metadataReader) {
|
|
82
|
+
const key = binding.token;
|
|
83
|
+
const containerHooks = this._deactivationHooks.get(key);
|
|
84
|
+
if (containerHooks !== void 0) for (const hook of containerHooks) {
|
|
85
|
+
const r = hook(instance);
|
|
86
|
+
if (r instanceof Promise) await r;
|
|
87
|
+
}
|
|
88
|
+
if (binding.kind !== "alias" && binding.onDeactivation !== void 0) {
|
|
89
|
+
const r = binding.onDeactivation(instance);
|
|
90
|
+
if (r instanceof Promise) await r;
|
|
91
|
+
}
|
|
92
|
+
if (binding.kind === "class") {
|
|
93
|
+
const lifecycle = metadataReader.getLifecycleMetadata(binding.target);
|
|
94
|
+
if (lifecycle?.preDestroy && lifecycle.preDestroy.length > 0) for (const methodName of lifecycle.preDestroy) {
|
|
95
|
+
const method = instance[methodName];
|
|
96
|
+
if (typeof method === "function") {
|
|
97
|
+
const r = method.call(instance);
|
|
98
|
+
if (r instanceof Promise) await r;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
runDeactivationSync(binding, instance, metadataReader) {
|
|
104
|
+
const tName = tokenName(binding.token);
|
|
105
|
+
const key = binding.token;
|
|
106
|
+
const containerHooks = this._deactivationHooks.get(key);
|
|
107
|
+
if (containerHooks !== void 0) {
|
|
108
|
+
for (const hook of containerHooks) if (hook(instance) instanceof Promise) throw new AsyncDeactivationError(tName);
|
|
109
|
+
}
|
|
110
|
+
if (binding.kind !== "alias" && binding.onDeactivation !== void 0) {
|
|
111
|
+
if (binding.onDeactivation(instance) instanceof Promise) throw new AsyncDeactivationError(tName);
|
|
112
|
+
}
|
|
113
|
+
if (binding.kind === "class") {
|
|
114
|
+
const lifecycle = metadataReader.getLifecycleMetadata(binding.target);
|
|
115
|
+
if (lifecycle?.preDestroy && lifecycle.preDestroy.length > 0) for (const methodName of lifecycle.preDestroy) {
|
|
116
|
+
const method = instance[methodName];
|
|
117
|
+
if (typeof method === "function") {
|
|
118
|
+
if (method.call(instance) instanceof Promise) throw new AsyncDeactivationError(tName);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
hasAsyncDeactivation(binding, instance, _metadataReader) {
|
|
124
|
+
if (binding.kind === "alias") return false;
|
|
125
|
+
if (binding.onDeactivation !== void 0) {
|
|
126
|
+
if (binding.onDeactivation(instance) instanceof Promise) return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
101
131
|
//#endregion
|
|
102
|
-
export {
|
|
132
|
+
export { LifecycleManager };
|
|
@@ -1,28 +1,11 @@
|
|
|
1
|
+
import { ConstructorMetadata, MutableLifecycleMetadata } from "./metadata-types.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/metadata/metadata-keys.d.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
declare const
|
|
8
|
-
/**
|
|
9
|
-
* Well-known property key for accessor-field injection metadata on `Symbol.metadata`.
|
|
10
|
-
* Written by `@inject()` when used as an accessor decorator; read during post-construction
|
|
11
|
-
* property injection by the resolver.
|
|
12
|
-
*/
|
|
13
|
-
declare const CODEFAST_DI_ACCESSOR_INJECTIONS = "codefast/di:accessor-injections:v1";
|
|
14
|
-
/**
|
|
15
|
-
* Well-known key for lifecycle method names written by `@postConstruct()` / `@preDestroy()`.
|
|
16
|
-
*/
|
|
17
|
-
declare const CODEFAST_DI_LIFECYCLE_METADATA = "codefast/di:lifecycle-metadata:v1";
|
|
18
|
-
/**
|
|
19
|
-
* Returns the runtime symbol used to access TC39 decorator metadata on a class.
|
|
20
|
-
*
|
|
21
|
-
* Prefers the native `Symbol.metadata` when available (Stage 3 decorators); falls back to
|
|
22
|
-
* `Symbol.for("Symbol.metadata")` for Node/runtime versions that polyfill or partially
|
|
23
|
-
* implement the proposal. The fallback key is the de facto convention used by TypeScript
|
|
24
|
-
* and polyfill libraries.
|
|
25
|
-
*/
|
|
26
|
-
declare function decoratorMetadataObjectSymbol(): symbol;
|
|
4
|
+
declare const INJECTABLE_KEY: unique symbol;
|
|
5
|
+
declare const LIFECYCLE_KEY: unique symbol;
|
|
6
|
+
declare const INJECT_ACCESSOR_KEY: unique symbol;
|
|
7
|
+
declare const constructorMetadataMap: WeakMap<object, ConstructorMetadata>;
|
|
8
|
+
declare const lifecycleMetadataMap: WeakMap<object, MutableLifecycleMetadata>;
|
|
9
|
+
declare const lifecycleByConstructorMetadataMap: WeakMap<object, MutableLifecycleMetadata>;
|
|
27
10
|
//#endregion
|
|
28
|
-
export {
|
|
11
|
+
export { INJECTABLE_KEY, INJECT_ACCESSOR_KEY, LIFECYCLE_KEY, constructorMetadataMap, lifecycleByConstructorMetadataMap, lifecycleMetadataMap };
|
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
//#region src/metadata/metadata-keys.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
const
|
|
8
|
-
/**
|
|
9
|
-
* Well-known property key for accessor-field injection metadata on `Symbol.metadata`.
|
|
10
|
-
* Written by `@inject()` when used as an accessor decorator; read during post-construction
|
|
11
|
-
* property injection by the resolver.
|
|
12
|
-
*/
|
|
13
|
-
const CODEFAST_DI_ACCESSOR_INJECTIONS = "codefast/di:accessor-injections:v1";
|
|
14
|
-
/**
|
|
15
|
-
* Well-known key for lifecycle method names written by `@postConstruct()` / `@preDestroy()`.
|
|
16
|
-
*/
|
|
17
|
-
const CODEFAST_DI_LIFECYCLE_METADATA = "codefast/di:lifecycle-metadata:v1";
|
|
18
|
-
/**
|
|
19
|
-
* Returns the runtime symbol used to access TC39 decorator metadata on a class.
|
|
20
|
-
*
|
|
21
|
-
* Prefers the native `Symbol.metadata` when available (Stage 3 decorators); falls back to
|
|
22
|
-
* `Symbol.for("Symbol.metadata")` for Node/runtime versions that polyfill or partially
|
|
23
|
-
* implement the proposal. The fallback key is the de facto convention used by TypeScript
|
|
24
|
-
* and polyfill libraries.
|
|
25
|
-
*/
|
|
26
|
-
function decoratorMetadataObjectSymbol() {
|
|
27
|
-
return typeof Symbol.metadata === "symbol" ? Symbol.metadata : Symbol.for("Symbol.metadata");
|
|
28
|
-
}
|
|
2
|
+
const INJECTABLE_KEY = Symbol("di:injectable");
|
|
3
|
+
const LIFECYCLE_KEY = Symbol("di:lifecycle");
|
|
4
|
+
const INJECT_ACCESSOR_KEY = Symbol("di:inject-accessor");
|
|
5
|
+
const constructorMetadataMap = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
const lifecycleMetadataMap = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
const lifecycleByConstructorMetadataMap = /* @__PURE__ */ new WeakMap();
|
|
29
8
|
//#endregion
|
|
30
|
-
export {
|
|
9
|
+
export { INJECTABLE_KEY, INJECT_ACCESSOR_KEY, LIFECYCLE_KEY, constructorMetadataMap, lifecycleByConstructorMetadataMap, lifecycleMetadataMap };
|