@teqfw/di 2.5.1 → 2.6.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 +8 -0
- package/README.md +430 -119
- package/ai/AGENTS.md +42 -74
- package/ai/concepts.md +11 -54
- package/ai/container.md +56 -47
- package/ai/dependency-id.md +77 -59
- package/ai/extensions.md +68 -38
- package/ai/package-api.ts +13 -11
- package/ai/usage.md +67 -207
- package/dist/esm.js +1 -1
- package/dist/umd.js +1 -1
- package/package.json +1 -1
- package/src/Config/NamespaceRegistry.mjs +19 -15
- package/src/Container/Lifecycle/Registry.mjs +2 -12
- package/src/Container/Resolve/GraphResolver.mjs +8 -40
- package/src/Container/Runtime.mjs +244 -0
- package/src/Container.mjs +14 -402
- package/src/Internal/DependencyKey.mjs +29 -0
- package/src/Internal/DepsDecl.mjs +42 -0
- package/src/Internal/PromiseSafe.mjs +39 -0
- package/src/{Def/Parser.mjs → Parser.mjs} +82 -35
- package/src/Container/Instantiate/ExportSelector.mjs +0 -44
package/ai/extensions.md
CHANGED
|
@@ -1,73 +1,103 @@
|
|
|
1
1
|
# extensions.md
|
|
2
2
|
|
|
3
|
-
Version:
|
|
3
|
+
Version: 20260606
|
|
4
4
|
|
|
5
5
|
## Purpose
|
|
6
6
|
|
|
7
|
-
The container supports controlled extension of
|
|
7
|
+
The container supports controlled extension of dependency resolution through three distinct mechanisms:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- preprocess hooks;
|
|
10
|
+
- postprocess hooks;
|
|
11
|
+
- wrapper exports.
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
These mechanisms are related but not interchangeable.
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
## Preprocess Hooks
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
- **Postprocess wrappers** — modify or decorate created objects after instantiation.
|
|
17
|
+
Preprocess hooks transform CDC identities before resolution.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
Signature:
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
```js
|
|
22
|
+
(depId) => depId
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Properties:
|
|
26
|
+
|
|
27
|
+
- registered with `addPreprocess()`;
|
|
28
|
+
- run in declared order;
|
|
29
|
+
- receive and return DepId DTO values;
|
|
30
|
+
- affect identifier interpretation before module resolution.
|
|
31
|
+
|
|
32
|
+
Typical uses:
|
|
33
|
+
|
|
34
|
+
- CDC alias rewriting;
|
|
35
|
+
- policy-driven identifier normalization;
|
|
36
|
+
- project-specific prefix adaptation.
|
|
37
|
+
|
|
38
|
+
## Postprocess Hooks
|
|
21
39
|
|
|
22
|
-
|
|
40
|
+
Postprocess hooks transform resolved values after instantiation and before wrapper exports.
|
|
23
41
|
|
|
24
|
-
|
|
42
|
+
Signature:
|
|
25
43
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
44
|
+
```js
|
|
45
|
+
(value) => value
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Properties:
|
|
49
|
+
|
|
50
|
+
- registered with `addPostprocess()`;
|
|
51
|
+
- run for every resolved value;
|
|
52
|
+
- run in declared order;
|
|
53
|
+
- do not alter CDC parsing or module resolution.
|
|
29
54
|
|
|
30
|
-
|
|
55
|
+
Typical uses:
|
|
31
56
|
|
|
32
|
-
|
|
57
|
+
- global instrumentation;
|
|
58
|
+
- value normalization;
|
|
59
|
+
- cross-cutting adaptation applied uniformly to all resolved values.
|
|
33
60
|
|
|
34
|
-
|
|
61
|
+
## Wrapper Exports
|
|
35
62
|
|
|
36
|
-
|
|
63
|
+
Wrapper exports are selected directly from CDC suffixes and are resolved from the same module namespace as the dependency being composed.
|
|
37
64
|
|
|
38
|
-
|
|
39
|
-
- instrumentation
|
|
40
|
-
- capability injection
|
|
41
|
-
- runtime adaptation of object behavior
|
|
65
|
+
Signature:
|
|
42
66
|
|
|
43
|
-
|
|
67
|
+
```js
|
|
68
|
+
(value) => value
|
|
69
|
+
```
|
|
44
70
|
|
|
45
|
-
|
|
71
|
+
Properties:
|
|
46
72
|
|
|
47
|
-
|
|
73
|
+
- selected by wrapper suffixes such as `_wrapLog`;
|
|
74
|
+
- applied only when present in the CDC;
|
|
75
|
+
- executed after postprocess hooks and before freeze;
|
|
76
|
+
- not registered globally in the container.
|
|
48
77
|
|
|
49
78
|
Example:
|
|
50
79
|
|
|
51
80
|
```txt
|
|
52
|
-
|
|
81
|
+
App_Service$$_wrapLog_wrapTrace
|
|
53
82
|
```
|
|
54
83
|
|
|
55
|
-
In this example the container
|
|
56
|
-
|
|
57
|
-
Wrappers do not change the structure of `__deps__`. Dependency descriptors remain either hierarchical export-scoped descriptors, shorthand flat descriptors for limited single-export cases, or omitted entirely for empty-descriptor modules.
|
|
84
|
+
In this example the container composes the dependency, applies postprocess hooks, then applies wrapper exports `wrapLog` and `wrapTrace` in that order.
|
|
58
85
|
|
|
59
86
|
## Execution Order
|
|
60
87
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
Each wrapper receives the object returned by the previous wrapper and may return a new object that becomes the input to the next wrapper.
|
|
88
|
+
The extension-related execution order is:
|
|
64
89
|
|
|
65
|
-
|
|
90
|
+
1. preprocess hooks;
|
|
91
|
+
2. instantiation or as-is resolution;
|
|
92
|
+
3. postprocess hooks;
|
|
93
|
+
4. wrapper exports;
|
|
94
|
+
5. freeze.
|
|
66
95
|
|
|
67
|
-
|
|
96
|
+
## Constraints
|
|
68
97
|
|
|
69
|
-
|
|
70
|
-
- they must be deterministic and free of side effects that alter container state
|
|
71
|
-
- they must not bypass lifecycle semantics enforced by the container
|
|
98
|
+
Extensions must satisfy these constraints:
|
|
72
99
|
|
|
73
|
-
|
|
100
|
+
- they must be registered before the first `get()` if they use container registration APIs;
|
|
101
|
+
- they should be deterministic for the same input;
|
|
102
|
+
- they must not rely on mutating frozen returned values;
|
|
103
|
+
- they must not bypass lifecycle semantics enforced by the container.
|
package/ai/package-api.ts
CHANGED
|
@@ -110,9 +110,10 @@ export const PACKAGE_API: PackageApiContract = {
|
|
|
110
110
|
name: 'addNamespaceRoot',
|
|
111
111
|
signature: 'addNamespaceRoot(prefix: string, target: string, defaultExt: string): void',
|
|
112
112
|
stage: 'builder',
|
|
113
|
-
summary: 'Registers one namespace
|
|
113
|
+
summary: 'Registers one namespace root that maps a CDC prefix to a module-specifier base.',
|
|
114
114
|
constraints: [
|
|
115
115
|
'Allowed only before the first get().',
|
|
116
|
+
'The target may be filesystem-backed or URL-backed depending on runtime environment.',
|
|
116
117
|
'Namespace rules are snapshotted and locked on the first get().',
|
|
117
118
|
],
|
|
118
119
|
},
|
|
@@ -130,10 +131,10 @@ export const PACKAGE_API: PackageApiContract = {
|
|
|
130
131
|
name: 'addPostprocess',
|
|
131
132
|
signature: 'addPostprocess(fn: (value: unknown) => unknown): void',
|
|
132
133
|
stage: 'builder',
|
|
133
|
-
summary: 'Adds an ordered
|
|
134
|
+
summary: 'Adds an ordered value transform applied to every resolved value after instantiation.',
|
|
134
135
|
constraints: [
|
|
135
136
|
'Allowed only before the first get().',
|
|
136
|
-
'Runs
|
|
137
|
+
'Runs after instantiation and before wrapper exports.',
|
|
137
138
|
],
|
|
138
139
|
},
|
|
139
140
|
{
|
|
@@ -168,7 +169,7 @@ export const PACKAGE_API: PackageApiContract = {
|
|
|
168
169
|
name: 'get',
|
|
169
170
|
signature: 'get(cdc: string): Promise<any>',
|
|
170
171
|
stage: 'runtime',
|
|
171
|
-
summary: 'Parses, resolves, instantiates, postprocesses, wraps, applies lifecycle, freezes, and returns a linked value.',
|
|
172
|
+
summary: 'Parses, preprocesses, resolves, instantiates, postprocesses, wraps, applies lifecycle, freezes, and returns a linked value.',
|
|
172
173
|
constraints: [
|
|
173
174
|
'The first get() locks configuration and creates internal infrastructure.',
|
|
174
175
|
'Any fatal pipeline error moves the container into failed state.',
|
|
@@ -220,7 +221,7 @@ export const PACKAGE_API: PackageApiContract = {
|
|
|
220
221
|
fields: {
|
|
221
222
|
moduleName: 'Logical module identifier without platform prefix.',
|
|
222
223
|
platform: '"teq" | "node" | "npm".',
|
|
223
|
-
exportName: 'Named export or "default"; null means whole-module
|
|
224
|
+
exportName: 'Named export or "default"; null means whole-module as-is resolution.',
|
|
224
225
|
composition: '"A" | "F" in the current implementation.',
|
|
225
226
|
life: '"S" | "T" | null in the current implementation.',
|
|
226
227
|
wrappers: 'Ordered wrapper export names.',
|
|
@@ -267,15 +268,16 @@ export const PACKAGE_API: PackageApiContract = {
|
|
|
267
268
|
kind: 'module-contract',
|
|
268
269
|
summary: 'Shape expected from application modules resolved by the container.',
|
|
269
270
|
fields: {
|
|
270
|
-
__deps__: 'Optional dependency descriptor.
|
|
271
|
+
__deps__: 'Optional dependency descriptor. Canonical form is hierarchical Record<exportName, Record<dependencyKey, CDC string>>. Supported shorthand form is a flat Record<dependencyKey, CDC string> for default-export-only modules. Omission means there are no declared dependencies.',
|
|
271
272
|
moduleNamespace: 'Whole ES module namespace object returned for as-is CDC without selected export.',
|
|
272
273
|
defaultExport: 'Used when the parsed DepId selects exportName="default" for factory composition.',
|
|
273
|
-
namedExports: 'May be selected via __ExportName for factory composition and may also provide wrapper
|
|
274
|
+
namedExports: 'May be selected via __ExportName for factory composition and may also provide wrapper exports.',
|
|
274
275
|
wrapperExport: 'Named export whose identifier appears in depId.wrappers; it must be synchronous and unary.',
|
|
275
276
|
},
|
|
276
277
|
notes: [
|
|
277
|
-
'The
|
|
278
|
-
'
|
|
278
|
+
'The hierarchical export-scoped descriptor is canonical.',
|
|
279
|
+
'The flat shorthand descriptor is supported only for default-export-only modules and does not replace the canonical hierarchical model.',
|
|
280
|
+
'Wrapper exports are resolved from the same module namespace and are not globally registered in the container.',
|
|
279
281
|
],
|
|
280
282
|
},
|
|
281
283
|
],
|
|
@@ -429,8 +431,8 @@ export const PACKAGE_API: PackageApiContract = {
|
|
|
429
431
|
operationalNotes: [
|
|
430
432
|
'Only two runtime entrypoints are supported by package.json exports: @teqfw/di and @teqfw/di/src/Config/NamespaceRegistry.mjs.',
|
|
431
433
|
'Resolved values are frozen before being returned.',
|
|
432
|
-
'
|
|
433
|
-
'With the default parser, CDC without lifecycle
|
|
434
|
+
'The hierarchical export-scoped descriptor is canonical. The flat shorthand descriptor is supported only for default-export-only modules.',
|
|
435
|
+
'With the default parser, CDC without lifecycle resolves the selected module export as-is.',
|
|
434
436
|
'Named wrapper exports are executed after addPostprocess() hooks and before freeze.',
|
|
435
437
|
'In the current implementation, CDC markers $$ and $$$ both end up as transient/no-cache behavior.',
|
|
436
438
|
'types.d.ts is broader than the runtime import surface. Presence of an alias there does not by itself make the underlying module a supported runtime entrypoint.',
|
package/ai/usage.md
CHANGED
|
@@ -1,26 +1,22 @@
|
|
|
1
1
|
# usage.md
|
|
2
2
|
|
|
3
|
-
Version:
|
|
3
|
+
Version: 20260606
|
|
4
4
|
|
|
5
5
|
## Purpose
|
|
6
6
|
|
|
7
|
-
This document
|
|
7
|
+
This document shows canonical usage patterns for the container. Examples are intentionally short and prioritize supported, recommended forms over convenience shorthand.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Canonical Module Descriptor
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Modules intended for container linking may expose a default export, a named export, or both. The static dependency descriptor `__deps__` is canonical when it is hierarchical and keyed by export name. It describes the dependencies of the export selected by the CDC.
|
|
14
|
-
|
|
15
|
-
Dependencies are injected into the constructor as a single structured object. In TeqFW-style modules the public API is defined inside the constructor through assignments to `this`, while internal state may be held in constructor-local variables captured by closures.
|
|
16
|
-
|
|
17
|
-
Minimal single-export example:
|
|
11
|
+
The canonical form of `__deps__` is hierarchical and keyed by export name.
|
|
18
12
|
|
|
19
13
|
```js
|
|
20
14
|
// @ts-check
|
|
21
15
|
|
|
22
16
|
export const __deps__ = {
|
|
23
|
-
|
|
17
|
+
default: {
|
|
18
|
+
cast: "App_Helper_Cast$",
|
|
19
|
+
},
|
|
24
20
|
};
|
|
25
21
|
|
|
26
22
|
export default class App_Root {
|
|
@@ -53,48 +49,14 @@ export default function App_Helper_Cast() {
|
|
|
53
49
|
|
|
54
50
|
Rules:
|
|
55
51
|
|
|
56
|
-
- the
|
|
57
|
-
- each export entry maps constructor dependency names to CDC identifiers
|
|
58
|
-
- if `__deps__` is
|
|
59
|
-
-
|
|
60
|
-
- a named export may declare dependencies without requiring a `default` entry
|
|
61
|
-
- dependencies are resolved recursively before instantiation
|
|
62
|
-
|
|
63
|
-
When the CDC selects `App_Module$`, the container uses the default export. When the CDC selects `App_Module__Factory$`, the container uses the named export `Factory`.
|
|
64
|
-
|
|
65
|
-
Canonical export-scoped form:
|
|
66
|
-
|
|
67
|
-
```js
|
|
68
|
-
export const __deps__ = {
|
|
69
|
-
default: {
|
|
70
|
-
cast: "App_Helper_Cast$",
|
|
71
|
-
},
|
|
72
|
-
Factory: {
|
|
73
|
-
cast: "App_Helper_Cast$",
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export default class RuntimeWrapper {
|
|
78
|
-
constructor() {
|
|
79
|
-
return {mode: "wrapper"};
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export class Factory {
|
|
84
|
-
constructor({ cast }) {
|
|
85
|
-
this.configure = function (params = {}) {
|
|
86
|
-
return {
|
|
87
|
-
mode: "factory",
|
|
88
|
-
name: cast(params.name ?? "app"),
|
|
89
|
-
};
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|
|
52
|
+
- the hierarchical export-scoped form is canonical;
|
|
53
|
+
- each export entry maps constructor dependency names to CDC identifiers;
|
|
54
|
+
- if `__deps__` is omitted, the module has no declared dependencies;
|
|
55
|
+
- dependencies are resolved recursively before instantiation.
|
|
94
56
|
|
|
95
|
-
## Container
|
|
57
|
+
## Canonical Container Setup
|
|
96
58
|
|
|
97
|
-
The container is configured in the composition root
|
|
59
|
+
The container is configured in the composition root before the first resolution.
|
|
98
60
|
|
|
99
61
|
```js
|
|
100
62
|
import path from "node:path";
|
|
@@ -105,230 +67,128 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
105
67
|
const __dirname = path.dirname(__filename);
|
|
106
68
|
|
|
107
69
|
const container = new Container();
|
|
108
|
-
|
|
109
70
|
container.addNamespaceRoot("App_", path.resolve(__dirname, "./src/App"), ".mjs");
|
|
110
71
|
```
|
|
111
72
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
Browser-oriented or isomorphic configuration may also use URL-based import roots:
|
|
73
|
+
Namespace roots may also use URL-backed module-specifier bases:
|
|
115
74
|
|
|
116
75
|
```js
|
|
117
76
|
container.addNamespaceRoot("App_", "https://cdn.example.com/app", ".mjs");
|
|
118
|
-
container.addNamespaceRoot("Web_", "//cdn.example.com/web", ".mjs");
|
|
119
77
|
```
|
|
120
78
|
|
|
121
|
-
##
|
|
79
|
+
## Resolve Root Dependency
|
|
122
80
|
|
|
123
|
-
|
|
81
|
+
Applications typically resolve one root dependency and let the container build the full object graph.
|
|
124
82
|
|
|
125
83
|
```js
|
|
126
84
|
const root = await container.get("App_Root$");
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
The container:
|
|
130
|
-
|
|
131
|
-
- parses the CDC
|
|
132
|
-
- loads the module
|
|
133
|
-
- resolves dependencies declared in `__deps__`
|
|
134
|
-
- instantiates modules
|
|
135
|
-
- links the dependency graph
|
|
136
|
-
- freezes the produced value
|
|
137
|
-
|
|
138
|
-
Example usage:
|
|
139
|
-
|
|
140
|
-
```js
|
|
141
85
|
console.log(root.configure({name: 123}).name);
|
|
142
86
|
console.log(Object.isFrozen(root));
|
|
143
87
|
```
|
|
144
88
|
|
|
145
|
-
##
|
|
146
|
-
|
|
147
|
-
CDC identifiers define how the container interprets a dependency. The following patterns represent common usage scenarios.
|
|
148
|
-
|
|
149
|
-
### Module As-Is
|
|
150
|
-
|
|
151
|
-
A CDC without lifecycle marker returns the module export as-is.
|
|
152
|
-
|
|
153
|
-
```text
|
|
154
|
-
App_Service
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Typical usage:
|
|
158
|
-
|
|
159
|
-
- utility modules
|
|
160
|
-
- stateless helpers
|
|
161
|
-
- constant providers
|
|
162
|
-
|
|
163
|
-
Example:
|
|
164
|
-
|
|
165
|
-
```js
|
|
166
|
-
const math = await container.get("App_Math");
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Singleton from Default Export
|
|
170
|
-
|
|
171
|
-
A lifecycle marker `$` creates a singleton instance.
|
|
172
|
-
|
|
173
|
-
```text
|
|
174
|
-
App_Service$
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Typical usage:
|
|
178
|
-
|
|
179
|
-
- application services
|
|
180
|
-
- repositories
|
|
181
|
-
- infrastructure adapters
|
|
182
|
-
|
|
183
|
-
### Transient Instance
|
|
184
|
-
|
|
185
|
-
Marker `$$` creates a new instance for every request.
|
|
186
|
-
|
|
187
|
-
```text
|
|
188
|
-
App_Service$$
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
Typical usage:
|
|
192
|
-
|
|
193
|
-
- request objects
|
|
194
|
-
- short-lived workers
|
|
195
|
-
- task processors
|
|
196
|
-
|
|
197
|
-
### Named Export Resolution
|
|
198
|
-
|
|
199
|
-
CDC may reference a named export using the `__ExportName` segment.
|
|
200
|
-
|
|
201
|
-
```text
|
|
202
|
-
App_Module__build$
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
Typical usage:
|
|
206
|
-
|
|
207
|
-
- builders
|
|
208
|
-
- factory entry points
|
|
209
|
-
- specialized constructors
|
|
89
|
+
## Named Export
|
|
210
90
|
|
|
211
|
-
|
|
91
|
+
Named exports use the `__ExportName` segment in the CDC and the same hierarchical `__deps__` structure.
|
|
212
92
|
|
|
213
93
|
```js
|
|
214
94
|
export const __deps__ = {
|
|
215
95
|
default: {
|
|
216
|
-
cast: "
|
|
96
|
+
cast: "App_Helper_Cast$",
|
|
217
97
|
},
|
|
218
98
|
Factory: {
|
|
219
|
-
cast: "
|
|
99
|
+
cast: "App_Helper_Cast$",
|
|
220
100
|
},
|
|
221
101
|
};
|
|
222
102
|
|
|
223
103
|
export default class RuntimeWrapper {
|
|
224
104
|
constructor() {
|
|
225
|
-
return {mode: "
|
|
105
|
+
return {mode: "runtime"};
|
|
226
106
|
}
|
|
227
107
|
}
|
|
228
108
|
|
|
229
109
|
export class Factory {
|
|
230
110
|
constructor({ cast }) {
|
|
231
111
|
this.configure = function (params = {}) {
|
|
232
|
-
return {
|
|
112
|
+
return {
|
|
113
|
+
mode: "factory",
|
|
114
|
+
name: cast(params.name ?? "app"),
|
|
115
|
+
};
|
|
233
116
|
};
|
|
234
117
|
}
|
|
235
118
|
}
|
|
236
119
|
```
|
|
237
120
|
|
|
238
|
-
|
|
121
|
+
Resolution examples:
|
|
239
122
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
App_Service$$_log_trace
|
|
123
|
+
```js
|
|
124
|
+
const runtime = await container.get("App_Module$");
|
|
125
|
+
const factory = await container.get("App_Module__Factory$");
|
|
244
126
|
```
|
|
245
127
|
|
|
246
|
-
|
|
128
|
+
## Singleton And Transient
|
|
247
129
|
|
|
248
|
-
|
|
130
|
+
Common lifecycle-based compositions:
|
|
249
131
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
cast: "App_Helper_Cast$",
|
|
255
|
-
};
|
|
132
|
+
```txt
|
|
133
|
+
App_Service$
|
|
134
|
+
App_Task$$
|
|
135
|
+
App_Task$$$
|
|
256
136
|
```
|
|
257
137
|
|
|
258
|
-
|
|
138
|
+
- `$` creates and reuses a singleton instance;
|
|
139
|
+
- `$$` creates a new instance for each request;
|
|
140
|
+
- `$$$` is a transient alias in the current implementation.
|
|
259
141
|
|
|
260
|
-
|
|
142
|
+
## Wrappers
|
|
261
143
|
|
|
262
|
-
|
|
144
|
+
Wrapper exports are selected by CDC suffixes and are applied after postprocess hooks.
|
|
263
145
|
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
constructor() {
|
|
267
|
-
this.ready = function () {
|
|
268
|
-
return true;
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
}
|
|
146
|
+
```txt
|
|
147
|
+
App_Service$$_wrapLog_wrapTrace
|
|
272
148
|
```
|
|
273
149
|
|
|
274
|
-
|
|
150
|
+
This pattern is useful when runtime behavior should be decorated without changing the service module contract.
|
|
275
151
|
|
|
276
|
-
|
|
277
|
-
- tracing
|
|
278
|
-
- metrics collection
|
|
279
|
-
- behavioral instrumentation
|
|
152
|
+
## Platform Modules
|
|
280
153
|
|
|
281
|
-
|
|
154
|
+
CDC may refer to platform modules directly.
|
|
282
155
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
```text
|
|
156
|
+
```txt
|
|
286
157
|
node:fs
|
|
287
158
|
npm:@humanfs/core
|
|
288
159
|
node:worker_threads
|
|
289
|
-
npm:lodash
|
|
290
160
|
```
|
|
291
161
|
|
|
292
|
-
These
|
|
293
|
-
|
|
294
|
-
Typical usage:
|
|
162
|
+
These forms resolve the selected platform module export as-is unless a lifecycle marker is explicitly added.
|
|
295
163
|
|
|
296
|
-
|
|
297
|
-
- `npm:@humanfs/core` for a scoped npm package dependency
|
|
164
|
+
## Non-Canonical Shorthand
|
|
298
165
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
Applications typically resolve a single root dependency.
|
|
166
|
+
A flat `__deps__` object is a supported shorthand for default-export-only modules, but it is not the canonical model.
|
|
302
167
|
|
|
303
168
|
```js
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
The container recursively resolves all dependencies declared through `__deps__` and constructs the object graph. Empty descriptor modules omit `__deps__` entirely.
|
|
308
|
-
|
|
309
|
-
## Wrapper-Based Behavioral Composition
|
|
310
|
-
|
|
311
|
-
Wrappers enable declarative behavioral composition at the dependency level. By attaching wrapper identifiers to CDC strings the caller can modify the runtime behavior of a dependency without modifying its module implementation.
|
|
312
|
-
|
|
313
|
-
Example:
|
|
169
|
+
export const __deps__ = {
|
|
170
|
+
cast: "App_Helper_Cast$",
|
|
171
|
+
};
|
|
314
172
|
|
|
315
|
-
|
|
316
|
-
|
|
173
|
+
export default class App_Short {
|
|
174
|
+
constructor({ cast }) {
|
|
175
|
+
this.cast = cast;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
317
178
|
```
|
|
318
179
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
This mechanism enables patterns similar to aspect-oriented programming while preserving deterministic dependency resolution.
|
|
180
|
+
Prefer the hierarchical form for new integrations and for any module that exposes named exports.
|
|
322
181
|
|
|
323
|
-
##
|
|
182
|
+
## Empty Descriptor
|
|
324
183
|
|
|
325
|
-
|
|
184
|
+
Modules with no declared dependencies omit `__deps__` entirely.
|
|
326
185
|
|
|
327
186
|
```js
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
187
|
+
export default class App_Empty {
|
|
188
|
+
constructor() {
|
|
189
|
+
this.ready = function () {
|
|
190
|
+
return true;
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
332
194
|
```
|
|
333
|
-
|
|
334
|
-
The container loads modules, resolves dependencies, instantiates objects, and returns a frozen result.
|