@teqfw/di 2.6.2 → 2.8.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 +24 -0
- package/README.md +63 -561
- package/ai/AGENTS.md +10 -54
- package/dist/esm.js +1 -1
- package/dist/umd.js +1 -1
- package/package.json +23 -16
- package/skills/teqfw-di/SKILL.md +36 -0
- package/skills/teqfw-di/agents/openai.yaml +4 -0
- package/skills/teqfw-di/references/compatibility.md +35 -0
- package/skills/teqfw-di/references/concepts.md +43 -0
- package/{ai → skills/teqfw-di/references}/container.md +12 -6
- package/{ai → skills/teqfw-di/references}/dependency-id.md +28 -11
- package/skills/teqfw-di/references/distribution.md +24 -0
- package/{ai → skills/teqfw-di/references}/extensions.md +18 -7
- package/{ai → skills/teqfw-di/references}/package-api.ts +58 -35
- package/skills/teqfw-di/references/usage.md +283 -0
- package/src/AGENTS.md +20 -16
- package/src/Config/NamespaceRegistry.mjs +3 -213
- package/src/Container/Executor.mjs +2 -2
- package/src/Container/GraphResolver.mjs +24 -13
- package/src/Container/Instantiate.mjs +2 -2
- package/src/Container/Lifecycle.mjs +2 -2
- package/src/Container/Pipeline.mjs +20 -22
- package/src/Container.mjs +67 -35
- package/src/Dto/DepId.mjs +1 -1
- package/src/Internal/DepsDecl.mjs +2 -2
- package/src/Node/Registry/Namespace.mjs +208 -0
- package/src/Node/Registry/Package.mjs +215 -0
- package/src/Parser.mjs +18 -18
- package/types.d.ts +9 -4
- package/ai/concepts.md +0 -25
- package/ai/usage.md +0 -194
package/README.md
CHANGED
|
@@ -1,628 +1,130 @@
|
|
|
1
1
|
# @teqfw/di
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-

|
|
3
|
+
**JavaScript applications do not need a compiler to gain late binding, explicit contracts, controlled composition, and agent-readable architecture.**
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
`@teqfw/di` brings these capabilities to native ESM without TypeScript, decorators, reflection, generated code, or transpilation. Business modules depend on stable logical tokens instead of concrete file paths; the host application decides which implementation to load, how to create it, how long to keep it, and which cross-cutting policies to apply.
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
This is the runtime-linking foundation of Tequila Framework and a practical choice for long-lived applications maintained by developers together with coding agents.
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
## Why use it
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
No decorators.
|
|
14
|
-
No reflection.
|
|
15
|
-
No framework-managed injection.
|
|
16
|
-
No transpilation requirement.
|
|
17
|
-
|
|
18
|
-
The package uses dependency injection techniques, but its main purpose is architectural governance, not constructor convenience.
|
|
19
|
-
|
|
20
|
-
## Why JavaScript Dependency Wiring Breaks at Scale
|
|
21
|
-
|
|
22
|
-
JavaScript applications usually express dependencies through static imports:
|
|
23
|
-
|
|
24
|
-
```javascript
|
|
25
|
-
import Repository from "../repository/UserRepository.js";
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
This looks simple.
|
|
29
|
-
|
|
30
|
-
But this line says two different things at once:
|
|
31
|
-
|
|
32
|
-
1. what the module needs;
|
|
33
|
-
2. where that dependency is physically located.
|
|
34
|
-
|
|
35
|
-
That coupling is acceptable in small codebases.
|
|
36
|
-
|
|
37
|
-
It becomes a structural problem when the application grows.
|
|
38
|
-
|
|
39
|
-
As modules multiply, dependency intent becomes scattered across:
|
|
40
|
-
|
|
41
|
-
- file paths;
|
|
42
|
-
- package specifiers;
|
|
43
|
-
- framework conventions;
|
|
44
|
-
- bundler configuration;
|
|
45
|
-
- generated code;
|
|
46
|
-
- decorators;
|
|
47
|
-
- local composition logic.
|
|
48
|
-
|
|
49
|
-
The architecture becomes harder to supervise because the real dependency graph is embedded inside implementation details.
|
|
50
|
-
|
|
51
|
-
A developer no longer sees a component dependency model.
|
|
52
|
-
|
|
53
|
-
The developer sees a filesystem.
|
|
54
|
-
|
|
55
|
-
## Why AI-Assisted Development Makes This More Important
|
|
56
|
-
|
|
57
|
-
Coding agents change the practical scale of JavaScript development.
|
|
58
|
-
|
|
59
|
-
One developer working with agents can now create and maintain systems whose size was previously more typical for enterprise teams.
|
|
60
|
-
|
|
61
|
-
The bottleneck is no longer only code generation.
|
|
62
|
-
|
|
63
|
-
The bottleneck is architectural control.
|
|
64
|
-
|
|
65
|
-
Agents can generate files quickly. They can modify many modules in one iteration. They can refactor local code. But if the dependency structure is hidden inside file paths and framework conventions, both the agent and the human supervisor must reconstruct architectural intent indirectly.
|
|
66
|
-
|
|
67
|
-
That does not scale well.
|
|
68
|
-
|
|
69
|
-
Large AI-assisted JavaScript systems need dependency structure that is:
|
|
70
|
-
|
|
71
|
-
- explicit;
|
|
72
|
-
- stable;
|
|
73
|
-
- reviewable;
|
|
74
|
-
- machine-readable;
|
|
75
|
-
- independent from local file layout;
|
|
76
|
-
- deterministic at runtime.
|
|
77
|
-
|
|
78
|
-
This is the problem `@teqfw/di` addresses.
|
|
79
|
-
|
|
80
|
-
## The Enterprise Shift: From Files to Components
|
|
81
|
-
|
|
82
|
-
Enterprise ecosystems such as Java and C# have long used namespaces, dependency inversion, IoC containers, component identifiers, explicit contracts, and runtime composition to keep large systems manageable.
|
|
83
|
-
|
|
84
|
-
`@teqfw/di` brings that model of thinking to pure JavaScript.
|
|
85
|
-
|
|
86
|
-
Instead of making a module depend on a file path:
|
|
87
|
-
|
|
88
|
-
```javascript
|
|
89
|
-
import Repository from "../repository/UserRepository.js";
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
the module declares a dependency on a component:
|
|
93
|
-
|
|
94
|
-
```javascript
|
|
95
|
-
export const __deps__ = {
|
|
96
|
-
repository: "App_User_Repository$",
|
|
97
|
-
};
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
This declaration says:
|
|
101
|
-
|
|
102
|
-
> This module needs the `App_User_Repository` component.
|
|
103
|
-
|
|
104
|
-
It does not say where the source file is located.
|
|
105
|
-
|
|
106
|
-
The physical module location is resolved later by the container through configured namespace roots.
|
|
107
|
-
|
|
108
|
-
This is the central shift:
|
|
11
|
+
Static imports bind a consumer to a concrete module:
|
|
109
12
|
|
|
110
13
|
```text
|
|
111
|
-
|
|
112
|
-
to component addresses
|
|
113
|
-
|
|
114
|
-
from local imports
|
|
115
|
-
to explicit dependency contracts
|
|
116
|
-
|
|
117
|
-
from scattered wiring
|
|
118
|
-
to deterministic runtime composition
|
|
14
|
+
consumer → file path → implementation
|
|
119
15
|
```
|
|
120
16
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
`@teqfw/di` is a runtime composition layer for pure JavaScript ES modules.
|
|
124
|
-
|
|
125
|
-
It provides:
|
|
126
|
-
|
|
127
|
-
- namespace-based component addressing;
|
|
128
|
-
- Canonical Dependency Codes;
|
|
129
|
-
- source-attached dependency declarations through `__deps__`;
|
|
130
|
-
- deterministic runtime linking;
|
|
131
|
-
- namespace root mapping for Node.js and browser environments;
|
|
132
|
-
- lifecycle control for singleton and new-instance dependencies;
|
|
133
|
-
- explicit replacement in test mode;
|
|
134
|
-
- wrapper-based extension points;
|
|
135
|
-
- immutable linked objects.
|
|
136
|
-
|
|
137
|
-
The ES module system remains the underlying loading mechanism.
|
|
138
|
-
|
|
139
|
-
The package does not replace ESM.
|
|
140
|
-
|
|
141
|
-
It replaces application-level dependency wiring through static imports.
|
|
142
|
-
|
|
143
|
-
## Product Goal
|
|
144
|
-
|
|
145
|
-
The goal of `@teqfw/di` is to make enterprise-scale dependency architecture practical in pure JavaScript.
|
|
146
|
-
|
|
147
|
-
The package gives JavaScript applications a dependency model that is:
|
|
148
|
-
|
|
149
|
-
- based on stable namespace-based component addresses;
|
|
150
|
-
- explicit in source artifacts;
|
|
151
|
-
- deterministic under finalized runtime configuration;
|
|
152
|
-
- usable across browser and Node.js environments;
|
|
153
|
-
- readable by humans;
|
|
154
|
-
- reconstructible by coding agents;
|
|
155
|
-
- independent from TypeScript metadata, decorators, reflection, and framework-managed injection.
|
|
156
|
-
|
|
157
|
-
The intended result is architectural supervision.
|
|
158
|
-
|
|
159
|
-
A developer should be able to see what a component needs without tracing import paths across the filesystem.
|
|
160
|
-
|
|
161
|
-
An agent should be able to modify code without silently destroying the dependency structure.
|
|
162
|
-
|
|
163
|
-
A runtime should be able to link components through explicit contracts rather than inference.
|
|
164
|
-
|
|
165
|
-
## Core Model
|
|
166
|
-
|
|
167
|
-
The model follows this chain:
|
|
17
|
+
`@teqfw/di` separates the contract from the implementation:
|
|
168
18
|
|
|
169
19
|
```text
|
|
170
|
-
|
|
171
|
-
-> Component Address
|
|
172
|
-
-> CDC
|
|
173
|
-
-> __deps__
|
|
174
|
-
-> Namespace Root
|
|
175
|
-
-> Runtime Linker
|
|
176
|
-
-> Linked Object
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
A **namespace** defines a stable application-level addressing space.
|
|
180
|
-
|
|
181
|
-
A **component address** identifies a component inside that namespace.
|
|
182
|
-
|
|
183
|
-
A **CDC** — Canonical Dependency Code — encodes the component address and linking semantics.
|
|
184
|
-
|
|
185
|
-
A module declares its dependencies through `__deps__`.
|
|
186
|
-
|
|
187
|
-
A **namespace root** maps a namespace prefix to a concrete runtime module location.
|
|
188
|
-
|
|
189
|
-
The container resolves CDC values under finalized configuration, imports the required ES modules, links declared dependencies, and returns linked objects.
|
|
190
|
-
|
|
191
|
-
The linking happens at runtime, but it is not heuristic. The container does not infer dependencies from behavior, constructor signatures, decorators, reflection, or naming guesses.
|
|
192
|
-
|
|
193
|
-
For identical dependency declarations, CDC values, namespace roots, module exports, lifecycle rules, and finalized container configuration, the container must produce the same linked result or the same failure.
|
|
194
|
-
|
|
195
|
-
## Example: File-Oriented vs Component-Oriented Wiring
|
|
196
|
-
|
|
197
|
-
Traditional JavaScript wiring:
|
|
198
|
-
|
|
199
|
-
```javascript
|
|
200
|
-
import Repository from "../repository/UserRepository.js";
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
This is file-oriented.
|
|
204
|
-
|
|
205
|
-
The module depends on a concrete module specifier.
|
|
206
|
-
|
|
207
|
-
With `@teqfw/di`:
|
|
208
|
-
|
|
209
|
-
```javascript
|
|
210
|
-
export const __deps__ = {
|
|
211
|
-
repository: "App_User_Repository$",
|
|
212
|
-
};
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
This is component-oriented.
|
|
216
|
-
|
|
217
|
-
The module depends on a logical component address.
|
|
218
|
-
|
|
219
|
-
The difference is not just technical.
|
|
220
|
-
|
|
221
|
-
It changes the source of architectural truth.
|
|
222
|
-
|
|
223
|
-
## Why It Matters for Coding Agents
|
|
224
|
-
|
|
225
|
-
In agent-assisted development, dependency declarations become part of the shared cognitive field between the human developer, the coding agent, and the runtime system.
|
|
226
|
-
|
|
227
|
-
A module can expose its dependency intent as data:
|
|
228
|
-
|
|
229
|
-
```javascript
|
|
230
|
-
export const __deps__ = {
|
|
231
|
-
repository: "App_User_Repository$",
|
|
232
|
-
logger: "App_Logger$",
|
|
233
|
-
config: "App_Config$",
|
|
234
|
-
};
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
This structure is easy for agents to generate.
|
|
238
|
-
|
|
239
|
-
It is easy for humans to review.
|
|
240
|
-
|
|
241
|
-
It is deterministic for the container to execute.
|
|
242
|
-
|
|
243
|
-
Agent readability is not a separate feature. It is a consequence of explicit namespace-based dependency structure.
|
|
244
|
-
|
|
245
|
-
## Why It Matters for Browser and Node.js
|
|
246
|
-
|
|
247
|
-
Browser and Node.js environments both support ES modules, but they do not provide one shared application-level dependency wiring model.
|
|
248
|
-
|
|
249
|
-
Static imports usually depend on:
|
|
250
|
-
|
|
251
|
-
- file layout;
|
|
252
|
-
- package layout;
|
|
253
|
-
- URL layout;
|
|
254
|
-
- bundler behavior;
|
|
255
|
-
- runtime-specific module resolution.
|
|
256
|
-
|
|
257
|
-
`@teqfw/di` moves dependency intent away from those concrete specifiers.
|
|
258
|
-
|
|
259
|
-
The same source module can declare:
|
|
260
|
-
|
|
261
|
-
```javascript
|
|
262
|
-
export const __deps__ = {
|
|
263
|
-
repository: "App_User_Repository$",
|
|
264
|
-
};
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
In Node.js, `App_` may point to a filesystem directory.
|
|
268
|
-
|
|
269
|
-
In a browser, `App_` may point to a URL base.
|
|
270
|
-
|
|
271
|
-
The dependency declaration remains stable.
|
|
272
|
-
|
|
273
|
-
Only the namespace root changes.
|
|
274
|
-
|
|
275
|
-
## Who It Is For
|
|
276
|
-
|
|
277
|
-
`@teqfw/di` is designed primarily for:
|
|
278
|
-
|
|
279
|
-
- solo developers and small teams building long-lived web applications;
|
|
280
|
-
- developers using coding agents as active implementation and maintenance participants;
|
|
281
|
-
- modular monolith applications;
|
|
282
|
-
- isomorphic JavaScript systems that share code between browser and server;
|
|
283
|
-
- pure JavaScript + JSDoc codebases;
|
|
284
|
-
- projects where explicit dependency structure is more important than minimal local ceremony;
|
|
285
|
-
- applications expected to grow beyond prototype size.
|
|
286
|
-
|
|
287
|
-
It is especially relevant when one human remains responsible for architectural supervision while agents participate in code generation, maintenance, and refactoring.
|
|
288
|
-
|
|
289
|
-
## When It Is Not the Best Fit
|
|
290
|
-
|
|
291
|
-
`@teqfw/di` is usually not the best fit when:
|
|
292
|
-
|
|
293
|
-
- the project is a short-lived prototype;
|
|
294
|
-
- the application is small enough for direct imports to remain clear;
|
|
295
|
-
- the team is fully committed to a decorator-driven TypeScript framework;
|
|
296
|
-
- framework conventions are more important than explicit dependency contracts;
|
|
297
|
-
- minimal local ceremony is more valuable than architectural traceability;
|
|
298
|
-
- runtime linking is not acceptable for the project’s deployment model.
|
|
299
|
-
|
|
300
|
-
This package is a deliberate architectural tradeoff.
|
|
301
|
-
|
|
302
|
-
It favors explicit structure over local simplicity.
|
|
303
|
-
|
|
304
|
-
## How It Fits in JavaScript
|
|
305
|
-
|
|
306
|
-
This approach is unusual in mainstream JavaScript.
|
|
307
|
-
|
|
308
|
-
Most JavaScript and TypeScript projects express application dependency structure through some mix of:
|
|
309
|
-
|
|
310
|
-
- static imports;
|
|
311
|
-
- file paths;
|
|
312
|
-
- package specifiers;
|
|
313
|
-
- framework conventions;
|
|
314
|
-
- TypeScript-first source architecture;
|
|
315
|
-
- decorators or metadata-driven injection;
|
|
316
|
-
- framework-managed DI;
|
|
317
|
-
- bundler-controlled module graphs.
|
|
318
|
-
|
|
319
|
-
`@teqfw/di` makes a different tradeoff.
|
|
320
|
-
|
|
321
|
-
It favors namespace-based component addresses and explicit runtime contracts over hidden or inferred wiring.
|
|
322
|
-
|
|
323
|
-
TypeScript has had a major influence on the JavaScript ecosystem, and that influence has been broadly positive. At the same time, TeqFW targets a different design space:
|
|
324
|
-
|
|
325
|
-
- pure JavaScript + JSDoc;
|
|
326
|
-
- no transpilation requirement;
|
|
327
|
-
- isomorphic runtime behavior;
|
|
328
|
-
- namespace-based addressing;
|
|
329
|
-
- explicit dependency declarations;
|
|
330
|
-
- source artifacts readable by humans and agents.
|
|
331
|
-
|
|
332
|
-
This is not presented as the only correct way to structure JavaScript.
|
|
333
|
-
|
|
334
|
-
It is a focused alternative for projects that need stronger runtime explicitness and machine-reconstructible structure.
|
|
335
|
-
|
|
336
|
-
## Comparison
|
|
337
|
-
|
|
338
|
-
| Concern | Common JS/TS Approach | `@teqfw/di` |
|
|
339
|
-
| -------------------------- | ----------------------------------------------------- | --------------------------------------- |
|
|
340
|
-
| Dependency expression | Static imports, decorators, framework wiring | `__deps__` declarations with CDC values |
|
|
341
|
-
| Addressing model | File-based, package-based, or framework-defined | Namespace-based component addressing |
|
|
342
|
-
| Resolution model | Static, implicit, framework-driven, or bundler-driven | Deterministic runtime linking |
|
|
343
|
-
| Structural source of truth | Spread across code, metadata, config, and conventions | Source-attached dependency contracts |
|
|
344
|
-
| Cross-environment wiring | Bundlers, adapters, duplicated specifiers | Namespace roots |
|
|
345
|
-
| Best fit | Framework-led or TypeScript-first applications | Pure JavaScript + JSDoc modular systems |
|
|
346
|
-
| Agent readability | Mixed and often indirect | Explicit and reconstructible |
|
|
347
|
-
| Architectural mindset | Local module graph | Enterprise-scale component composition |
|
|
348
|
-
|
|
349
|
-
## Installation
|
|
350
|
-
|
|
351
|
-
```bash
|
|
352
|
-
npm install @teqfw/di
|
|
20
|
+
consumer → dependency token → host policy → implementation
|
|
353
21
|
```
|
|
354
22
|
|
|
355
|
-
|
|
23
|
+
That enables:
|
|
356
24
|
|
|
357
|
-
|
|
25
|
+
- late binding and replaceable implementations;
|
|
26
|
+
- isomorphic modules for Node.js and browser environments;
|
|
27
|
+
- explicit dependency graphs that agents can analyze;
|
|
28
|
+
- lifecycle control for transient and singleton values;
|
|
29
|
+
- preprocessing, postprocessing, wrappers, diagnostics, and test substitution at the composition boundary;
|
|
30
|
+
- shallow hardening of resolved values against ordinary runtime patching.
|
|
358
31
|
|
|
359
|
-
`
|
|
32
|
+
The package uses native ESM, dynamic `import()`, JSDoc, and standard JavaScript runtime features. No compilation layer is required.
|
|
360
33
|
|
|
361
|
-
|
|
362
|
-
export default function Repository() {
|
|
363
|
-
return {
|
|
364
|
-
async findNameById(id) {
|
|
365
|
-
return `User ${id}`;
|
|
366
|
-
},
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
```
|
|
34
|
+
<details>
|
|
370
35
|
|
|
371
|
-
|
|
36
|
+
<summary><strong>Quick Start</strong></summary>
|
|
372
37
|
|
|
373
|
-
```
|
|
38
|
+
```js
|
|
374
39
|
export default function Service({ repository }) {
|
|
375
40
|
return {
|
|
376
41
|
async getProfile(id) {
|
|
377
|
-
|
|
378
|
-
return { id, name };
|
|
42
|
+
return { id, name: await repository.findNameById(id) };
|
|
379
43
|
},
|
|
380
44
|
};
|
|
381
45
|
}
|
|
382
46
|
|
|
383
47
|
export const __deps__ = {
|
|
384
|
-
|
|
48
|
+
default: {
|
|
49
|
+
repository: "App_User_Repository$",
|
|
50
|
+
},
|
|
385
51
|
};
|
|
386
52
|
```
|
|
387
53
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
```javascript
|
|
54
|
+
```js
|
|
391
55
|
import path from "node:path";
|
|
392
56
|
import { fileURLToPath } from "node:url";
|
|
393
57
|
import Container from "@teqfw/di";
|
|
394
58
|
|
|
395
|
-
const
|
|
396
|
-
const __dirname = path.dirname(__filename);
|
|
59
|
+
const rootDir = path.dirname(fileURLToPath(import.meta.url));
|
|
397
60
|
|
|
398
61
|
const container = new Container();
|
|
399
|
-
container.addNamespaceRoot("App_", path.
|
|
62
|
+
container.addNamespaceRoot("App_", path.join(rootDir, "src/App"), ".mjs");
|
|
400
63
|
|
|
401
64
|
const service = await container.get("App_User_Service$");
|
|
402
|
-
|
|
403
|
-
const profile = await service.getProfile(42);
|
|
404
|
-
|
|
405
|
-
console.log(profile);
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
Output:
|
|
409
|
-
|
|
410
|
-
```javascript
|
|
411
|
-
{ id: 42, name: "User 42" }
|
|
412
65
|
```
|
|
413
66
|
|
|
414
|
-
|
|
67
|
+
</details>
|
|
415
68
|
|
|
416
|
-
-
|
|
417
|
-
- resolves `App_` through the registered namespace root;
|
|
418
|
-
- translates `App_User_Repository$` into a concrete ES module location;
|
|
419
|
-
- imports the module;
|
|
420
|
-
- reads `__deps__` for the selected export;
|
|
421
|
-
- recursively links dependencies;
|
|
422
|
-
- returns a frozen linked object.
|
|
69
|
+
## Agent-ready package
|
|
423
70
|
|
|
424
|
-
|
|
71
|
+
The package ships with three aligned interfaces:
|
|
425
72
|
|
|
426
|
-
|
|
73
|
+
- runtime code in `src`;
|
|
74
|
+
- type information through JSDoc and `types.d.ts`;
|
|
75
|
+
- a version-matched Agent Skill in `skills/teqfw-di`.
|
|
427
76
|
|
|
428
|
-
|
|
77
|
+
The skill explains the token model, module contracts, lifecycle, configuration, testing, environment boundaries, and approved integration patterns. An agent does not need to reconstruct the package architecture from source code alone.
|
|
429
78
|
|
|
430
|
-
|
|
79
|
+
Mount it into the host project:
|
|
431
80
|
|
|
432
|
-
```
|
|
433
|
-
|
|
81
|
+
```sh
|
|
82
|
+
mkdir -p .agents/skills
|
|
83
|
+
cd .agents/skills
|
|
84
|
+
ln -s ../../node_modules/@teqfw/di/skills/teqfw-di
|
|
434
85
|
```
|
|
435
86
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
The namespace makes the dependency address independent from local file paths and runtime-specific module specifiers.
|
|
439
|
-
|
|
440
|
-
### Component Address
|
|
441
|
-
|
|
442
|
-
A component address identifies an application component inside a namespace.
|
|
443
|
-
|
|
444
|
-
For example:
|
|
445
|
-
|
|
446
|
-
```text
|
|
447
|
-
App_User_Repository
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
identifies the `Repository` component inside the `App_` namespace.
|
|
451
|
-
|
|
452
|
-
The component address is logical.
|
|
453
|
-
|
|
454
|
-
It is not itself a file path or URL.
|
|
455
|
-
|
|
456
|
-
### CDC
|
|
457
|
-
|
|
458
|
-
A **Canonical Dependency Code** is the string contract used to request a dependency.
|
|
459
|
-
|
|
460
|
-
General form:
|
|
461
|
-
|
|
462
|
-
```text
|
|
463
|
-
[PlatformPrefix]ModuleName[__ExportName][LifecycleAndWrappers]
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
Examples:
|
|
467
|
-
|
|
468
|
-
```text
|
|
469
|
-
App_User_Repository$
|
|
470
|
-
App_User_Repository__Factory$$
|
|
471
|
-
node:fs
|
|
472
|
-
npm:lodash
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
Where:
|
|
476
|
-
|
|
477
|
-
- `App_User_Repository` is the namespace-based component address;
|
|
478
|
-
- `__Factory` selects a named export;
|
|
479
|
-
- `$` means singleton lifecycle;
|
|
480
|
-
- `$$` means new instance lifecycle;
|
|
481
|
-
- `node:` and `npm:` address platform-specific modules.
|
|
482
|
-
|
|
483
|
-
### `__deps__`
|
|
484
|
-
|
|
485
|
-
`__deps__` is a source-attached dependency declaration.
|
|
486
|
-
|
|
487
|
-
For a single-export module, dependencies can be declared in shorthand form:
|
|
488
|
-
|
|
489
|
-
```javascript
|
|
490
|
-
export const __deps__ = {
|
|
491
|
-
localName: "Dependency_CDC",
|
|
492
|
-
};
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
Rules:
|
|
496
|
-
|
|
497
|
-
- the canonical form is hierarchical and keyed by export name;
|
|
498
|
-
- each export entry maps constructor argument names to CDC strings;
|
|
499
|
-
- if `__deps__` is absent, the export has no declared dependencies;
|
|
500
|
-
- a flat `__deps__` object is shorthand for limited single-export cases.
|
|
501
|
-
|
|
502
|
-
Canonical export-scoped form:
|
|
503
|
-
|
|
504
|
-
```javascript
|
|
505
|
-
export const __deps__ = {
|
|
506
|
-
default: {
|
|
507
|
-
localName: "Dependency_CDC",
|
|
508
|
-
},
|
|
509
|
-
Factory: {
|
|
510
|
-
localName: "Dependency_CDC",
|
|
511
|
-
},
|
|
512
|
-
};
|
|
513
|
-
```
|
|
514
|
-
|
|
515
|
-
### Namespace Root
|
|
516
|
-
|
|
517
|
-
A namespace root maps a namespace prefix to a module-specifier base:
|
|
518
|
-
|
|
519
|
-
```javascript
|
|
520
|
-
container.addNamespaceRoot("App_", "/abs/path/to/src/App", ".mjs");
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
This lets the container translate logical module names such as `App_User_Repository$` into concrete ES module files or URL-based module specifiers.
|
|
524
|
-
|
|
525
|
-
In Node.js, that often means filesystem-backed module roots:
|
|
526
|
-
|
|
527
|
-
```javascript
|
|
528
|
-
container.addNamespaceRoot("App_", "/project/src/App", ".mjs");
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
In a browser-oriented or isomorphic application, it can also mean URL-backed roots:
|
|
532
|
-
|
|
533
|
-
```javascript
|
|
534
|
-
container.addNamespaceRoot("App_", "https://cdn.example.com/app", ".mjs");
|
|
535
|
-
container.addNamespaceRoot("Web_", "//cdn.example.com/web", ".mjs");
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
This keeps dependency addressing stable while allowing the same logical naming model to work across shared application code, browser-facing modules, and different runtime environments.
|
|
539
|
-
|
|
540
|
-
### Runtime Linking
|
|
541
|
-
|
|
542
|
-
Runtime linking is the process of resolving CDC values under finalized container configuration, importing the corresponding ES modules, injecting declared dependencies, and returning linked objects.
|
|
543
|
-
|
|
544
|
-
The mechanism is dynamic because it runs at runtime.
|
|
545
|
-
|
|
546
|
-
The mechanism is deterministic because dependencies are declared explicitly and resolved through fixed namespace roots and configuration.
|
|
87
|
+
Project instructions and application architecture remain authoritative. The package skill supplies product knowledge; the host supplies intent and policy.
|
|
547
88
|
|
|
548
89
|
## Public API
|
|
549
90
|
|
|
550
|
-
|
|
91
|
+
- `@teqfw/di` — `Container`;
|
|
92
|
+
- `@teqfw/di/node/registry/namespace` — namespace discovery;
|
|
93
|
+
- `@teqfw/di/node/registry/package` — package graph discovery.
|
|
551
94
|
|
|
552
|
-
|
|
553
|
-
const container = new Container();
|
|
554
|
-
```
|
|
555
|
-
|
|
556
|
-
Configure it before the first `get(...)`:
|
|
95
|
+
Do not import `@teqfw/di/src/**`.
|
|
557
96
|
|
|
558
|
-
|
|
559
|
-
- `addPreprocess(fn)`
|
|
560
|
-
- `addPostprocess(fn)`
|
|
561
|
-
- `enableLogging()`
|
|
562
|
-
- `enableTestMode()`
|
|
563
|
-
- `register(cdc, mock)`
|
|
97
|
+
## Best fit
|
|
564
98
|
|
|
565
|
-
|
|
99
|
+
Use `@teqfw/di` for modular, long-lived, plugin-oriented ESM applications where implementations, environments, and integrations will evolve.
|
|
566
100
|
|
|
567
|
-
|
|
568
|
-
await container.get(cdc);
|
|
569
|
-
```
|
|
101
|
+
Use direct imports for small applications where runtime composition adds no practical value.
|
|
570
102
|
|
|
571
|
-
|
|
103
|
+
## Add to a project
|
|
572
104
|
|
|
573
|
-
|
|
105
|
+
Install the runtime package as a project dependency:
|
|
574
106
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
Test mode allows registered mocks to be resolved before module instantiation:
|
|
578
|
-
|
|
579
|
-
```javascript
|
|
580
|
-
container.enableTestMode();
|
|
581
|
-
container.register("App_Service$", mockService);
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
This keeps replacement explicit and local to container configuration.
|
|
585
|
-
|
|
586
|
-
## Browser Usage
|
|
587
|
-
|
|
588
|
-
```html
|
|
589
|
-
<script type="module">
|
|
590
|
-
import Container from "https://cdn.jsdelivr.net/npm/@teqfw/di@2/+esm";
|
|
591
|
-
|
|
592
|
-
const container = new Container();
|
|
593
|
-
</script>
|
|
107
|
+
```sh
|
|
108
|
+
npm install @teqfw/di
|
|
594
109
|
```
|
|
595
110
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
This package includes a machine-oriented package interface under `./ai/`.
|
|
599
|
-
|
|
600
|
-
Those files are intended for system prompts, examples, and agent consumption. They describe:
|
|
601
|
-
|
|
602
|
-
- container usage;
|
|
603
|
-
- dependency descriptors;
|
|
604
|
-
- CDC behavior;
|
|
605
|
-
- integration patterns.
|
|
606
|
-
|
|
607
|
-
The package ships both a human-facing README and a machine-oriented interface for agents that need to use it as a dependency.
|
|
608
|
-
|
|
609
|
-
## Further Reading
|
|
111
|
+
For agent-assisted development, provide the coding agent with the skills relevant to its task:
|
|
610
112
|
|
|
611
|
-
-
|
|
612
|
-
-
|
|
613
|
-
-
|
|
614
|
-
- Dependency ID format: `ai/dependency-id.md`
|
|
615
|
-
- Extension points: `ai/extensions.md`
|
|
616
|
-
- Project philosophy and intended application domain: `PHILOSOPHY.md`
|
|
113
|
+
- `teqfw-di` — version-matched guidance for the `@teqfw/di` API, dependency tokens, module contracts, lifecycle, testing, and composition rules;
|
|
114
|
+
- `teqfw-platform` — the architecture, philosophy, conventions, plugin model, and integration rules of the Tequila Framework;
|
|
115
|
+
- `teqfw-esm-validator` — validation rules for native ESM modules and TeqFW-compatible JavaScript structure.
|
|
617
116
|
|
|
618
|
-
|
|
117
|
+
The package includes `teqfw-di`. The other skills are installed or mounted separately by the host project. Project instructions and cognitive context remain authoritative over all package-level guidance.
|
|
619
118
|
|
|
620
|
-
|
|
119
|
+
## Boundaries
|
|
621
120
|
|
|
622
|
-
|
|
121
|
+
The package provides interface-like contracts, composition interception, and shallow value hardening. It does not claim language-level interfaces, full general-purpose AOP, or deep immutability of arbitrary object graphs.
|
|
623
122
|
|
|
624
|
-
|
|
123
|
+
## Development and Ecosystem
|
|
625
124
|
|
|
626
|
-
|
|
125
|
+
This product is developed by AI agents under the direction of Alex Gusev, following the Agent-Driven Software Management (ADSM) methodology. It is built for the Tequila Framework (TeqFW) platform and contributes to its ecosystem.
|
|
627
126
|
|
|
628
|
-
|
|
127
|
+
- [Tequila Framework](https://teqfw.com/?teqfw-di)
|
|
128
|
+
- [Alex Gusev's Personal Website](https://wiredgeese.com/?teqfw-di)
|
|
129
|
+
- [Alex Gusev's Telegram Channel](https://t.me/alexgusev_lab_en)
|
|
130
|
+
- [Agent-Driven Software Management: A Practical Guide](http://fly.wiredgeese.com/flancer/leanpub/adsm-en/?teqfw-di)
|