@teqfw/di 2.5.0 → 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 +14 -0
- package/README.md +449 -263
- package/ai/AGENTS.md +42 -55
- package/ai/concepts.md +11 -54
- package/ai/container.md +57 -45
- package/ai/dependency-id.md +78 -58
- package/ai/extensions.md +68 -38
- package/ai/package-api.ts +13 -11
- package/ai/usage.md +80 -205
- 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 -28
- package/src/Container/Runtime.mjs +244 -0
- package/src/Container.mjs +14 -387
- 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/README.md
CHANGED
|
@@ -3,199 +3,389 @@
|
|
|
3
3
|

|
|
4
4
|

|
|
5
5
|
|
|
6
|
-
**
|
|
6
|
+
**Enterprise-scale dependency architecture for pure JavaScript.**
|
|
7
7
|
|
|
8
|
-
`@teqfw/di`
|
|
8
|
+
`@teqfw/di` replaces fragile file-path-based wiring with namespace-based component contracts and deterministic runtime linking, so large JavaScript codebases remain understandable to humans and reconstructible by coding agents.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
It is built for pure JavaScript ES modules.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
No TypeScript metadata.
|
|
13
|
+
No decorators.
|
|
14
|
+
No reflection.
|
|
15
|
+
No framework-managed injection.
|
|
16
|
+
No transpilation requirement.
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
- generate
|
|
16
|
-
- refactor
|
|
17
|
-
- extend
|
|
18
|
+
The package uses dependency injection techniques, but its main purpose is architectural governance, not constructor convenience.
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
## Why JavaScript Dependency Wiring Breaks at Scale
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
JavaScript applications usually express dependencies through static imports:
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
```javascript
|
|
25
|
+
import Repository from "../repository/UserRepository.js";
|
|
26
|
+
```
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
This looks simple.
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
But this line says two different things at once:
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- tight coupling to file structure
|
|
32
|
-
- constructor-based dependency inference
|
|
32
|
+
1. what the module needs;
|
|
33
|
+
2. where that dependency is physically located.
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
That coupling is acceptable in small codebases.
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
It becomes a structural problem when the application grows.
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
As modules multiply, dependency intent becomes scattered across:
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
- file paths;
|
|
42
|
+
- package specifiers;
|
|
43
|
+
- framework conventions;
|
|
44
|
+
- bundler configuration;
|
|
45
|
+
- generated code;
|
|
46
|
+
- decorators;
|
|
47
|
+
- local composition logic.
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
The architecture becomes harder to supervise because the real dependency graph is embedded inside implementation details.
|
|
43
50
|
|
|
44
|
-
|
|
51
|
+
A developer no longer sees a component dependency model.
|
|
45
52
|
|
|
46
|
-
|
|
53
|
+
The developer sees a filesystem.
|
|
47
54
|
|
|
48
|
-
-
|
|
49
|
-
- explicit dependency contracts (**CDC — Canonical Dependency Codes**)
|
|
50
|
-
- module dependency descriptors (`__deps__`)
|
|
51
|
-
- namespace-based module resolution
|
|
52
|
-
- runtime lifecycle management
|
|
53
|
-
- wrapper-based behavioral extensions
|
|
55
|
+
## Why AI-Assisted Development Makes This More Important
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
Coding agents change the practical scale of JavaScript development.
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
One developer working with agents can now create and maintain systems whose size was previously more typical for enterprise teams.
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
The bottleneck is no longer only code generation.
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
| ---------------- | ------------------------ | ------------------ |
|
|
63
|
-
| Dependencies | implicit imports | explicit contracts |
|
|
64
|
-
| Dependency graph | implicit | deterministic |
|
|
65
|
-
| Refactoring | fragile | stable |
|
|
66
|
-
| Testing | manual wiring | container driven |
|
|
67
|
-
| AI compatibility | accidental | intentional |
|
|
63
|
+
The bottleneck is architectural control.
|
|
68
64
|
|
|
69
|
-
|
|
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.
|
|
70
66
|
|
|
71
|
-
|
|
67
|
+
That does not scale well.
|
|
72
68
|
|
|
73
|
-
|
|
69
|
+
Large AI-assisted JavaScript systems need dependency structure that is:
|
|
74
70
|
|
|
75
|
-
|
|
71
|
+
- explicit;
|
|
72
|
+
- stable;
|
|
73
|
+
- reviewable;
|
|
74
|
+
- machine-readable;
|
|
75
|
+
- independent from local file layout;
|
|
76
|
+
- deterministic at runtime.
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
2. LLM agents generate the implementation
|
|
79
|
-
3. The generated code is reviewed and integrated
|
|
78
|
+
This is the problem `@teqfw/di` addresses.
|
|
80
79
|
|
|
81
|
-
|
|
80
|
+
## The Enterprise Shift: From Files to Components
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
The current version demonstrates how software can be developed using **human-defined architecture and AI-generated code**.
|
|
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.
|
|
85
83
|
|
|
86
|
-
|
|
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
|
+
```
|
|
87
91
|
|
|
88
|
-
|
|
92
|
+
the module declares a dependency on a component:
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
```javascript
|
|
95
|
+
export const __deps__ = {
|
|
96
|
+
repository: "App_User_Repository$",
|
|
97
|
+
};
|
|
98
|
+
```
|
|
91
99
|
|
|
92
|
-
|
|
100
|
+
This declaration says:
|
|
93
101
|
|
|
94
|
-
|
|
95
|
-
- what Canonical Dependency Codes are
|
|
96
|
-
- how modules declare dependencies
|
|
97
|
-
- how runtime linking works
|
|
98
|
-
- how to integrate the library in real applications
|
|
102
|
+
> This module needs the `App_User_Repository` component.
|
|
99
103
|
|
|
100
|
-
|
|
104
|
+
It does not say where the source file is located.
|
|
101
105
|
|
|
102
|
-
|
|
106
|
+
The physical module location is resolved later by the container through configured namespace roots.
|
|
103
107
|
|
|
104
|
-
|
|
108
|
+
This is the central shift:
|
|
105
109
|
|
|
106
|
-
|
|
110
|
+
```text
|
|
111
|
+
from file paths
|
|
112
|
+
to component addresses
|
|
107
113
|
|
|
108
|
-
|
|
114
|
+
from local imports
|
|
115
|
+
to explicit dependency contracts
|
|
109
116
|
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
from scattered wiring
|
|
118
|
+
to deterministic runtime composition
|
|
112
119
|
```
|
|
113
120
|
|
|
114
|
-
|
|
121
|
+
## What @teqfw/di Is
|
|
122
|
+
|
|
123
|
+
`@teqfw/di` is a runtime composition layer for pure JavaScript ES modules.
|
|
115
124
|
|
|
116
|
-
|
|
125
|
+
It provides:
|
|
117
126
|
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
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.
|
|
123
136
|
|
|
124
|
-
|
|
137
|
+
The ES module system remains the underlying loading mechanism.
|
|
125
138
|
|
|
126
|
-
|
|
139
|
+
The package does not replace ESM.
|
|
127
140
|
|
|
128
|
-
|
|
141
|
+
It replaces application-level dependency wiring through static imports.
|
|
129
142
|
|
|
130
|
-
|
|
143
|
+
## Product Goal
|
|
131
144
|
|
|
132
|
-
-
|
|
133
|
-
- namespace-based module organization
|
|
134
|
-
- modular monolith architecture
|
|
135
|
-
- pure JavaScript without compilation
|
|
136
|
-
- system structures optimized for collaboration with LLM agents
|
|
145
|
+
The goal of `@teqfw/di` is to make enterprise-scale dependency architecture practical in pure JavaScript.
|
|
137
146
|
|
|
138
|
-
|
|
147
|
+
The package gives JavaScript applications a dependency model that is:
|
|
139
148
|
|
|
140
|
-
|
|
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.
|
|
141
156
|
|
|
142
|
-
|
|
157
|
+
The intended result is architectural supervision.
|
|
143
158
|
|
|
144
|
-
|
|
145
|
-
|
|
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:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
Namespace
|
|
171
|
+
-> Component Address
|
|
172
|
+
-> CDC
|
|
173
|
+
-> __deps__
|
|
174
|
+
-> Namespace Root
|
|
175
|
+
-> Runtime Linker
|
|
176
|
+
-> Linked Object
|
|
146
177
|
```
|
|
147
178
|
|
|
148
|
-
|
|
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__`.
|
|
149
186
|
|
|
150
|
-
|
|
187
|
+
A **namespace root** maps a namespace prefix to a concrete runtime module location.
|
|
151
188
|
|
|
152
|
-
|
|
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:
|
|
153
198
|
|
|
154
199
|
```javascript
|
|
155
|
-
|
|
156
|
-
return { name: "child" };
|
|
157
|
-
}
|
|
200
|
+
import Repository from "../repository/UserRepository.js";
|
|
158
201
|
```
|
|
159
202
|
|
|
160
|
-
|
|
203
|
+
This is file-oriented.
|
|
204
|
+
|
|
205
|
+
The module depends on a concrete module specifier.
|
|
206
|
+
|
|
207
|
+
With `@teqfw/di`:
|
|
161
208
|
|
|
162
209
|
```javascript
|
|
163
|
-
export
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
};
|
|
167
|
-
}
|
|
210
|
+
export const __deps__ = {
|
|
211
|
+
repository: "App_User_Repository$",
|
|
212
|
+
};
|
|
168
213
|
```
|
|
169
214
|
|
|
170
|
-
|
|
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:
|
|
171
228
|
|
|
172
229
|
```javascript
|
|
173
230
|
export const __deps__ = {
|
|
174
|
-
|
|
231
|
+
repository: "App_User_Repository$",
|
|
232
|
+
logger: "App_Logger$",
|
|
233
|
+
config: "App_Config$",
|
|
175
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.
|
|
176
248
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Quick Start
|
|
356
|
+
|
|
357
|
+
Define one repository module and one service module that declares the repository as an explicit dependency.
|
|
358
|
+
|
|
359
|
+
`src/App/User/Repository.mjs`
|
|
360
|
+
|
|
361
|
+
```javascript
|
|
362
|
+
export default function Repository() {
|
|
363
|
+
return {
|
|
364
|
+
async findNameById(id) {
|
|
365
|
+
return `User ${id}`;
|
|
366
|
+
},
|
|
367
|
+
};
|
|
183
368
|
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
`src/App/User/Service.mjs`
|
|
184
372
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
};
|
|
194
|
-
}
|
|
373
|
+
```javascript
|
|
374
|
+
export default function Service({ repository }) {
|
|
375
|
+
return {
|
|
376
|
+
async getProfile(id) {
|
|
377
|
+
const name = await repository.findNameById(id);
|
|
378
|
+
return { id, name };
|
|
379
|
+
},
|
|
380
|
+
};
|
|
195
381
|
}
|
|
382
|
+
|
|
383
|
+
export const __deps__ = {
|
|
384
|
+
repository: "App_User_Repository$",
|
|
385
|
+
};
|
|
196
386
|
```
|
|
197
387
|
|
|
198
|
-
|
|
388
|
+
Configure the container and request the dependency:
|
|
199
389
|
|
|
200
390
|
```javascript
|
|
201
391
|
import path from "node:path";
|
|
@@ -206,151 +396,164 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
206
396
|
const __dirname = path.dirname(__filename);
|
|
207
397
|
|
|
208
398
|
const container = new Container();
|
|
209
|
-
|
|
210
399
|
container.addNamespaceRoot("App_", path.resolve(__dirname, "./src/App"), ".mjs");
|
|
211
400
|
|
|
212
|
-
const
|
|
401
|
+
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
|
+
```
|
|
413
|
+
|
|
414
|
+
In this flow the container:
|
|
415
|
+
|
|
416
|
+
- parses the dependency request;
|
|
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.
|
|
423
|
+
|
|
424
|
+
## Core Concepts
|
|
425
|
+
|
|
426
|
+
### Namespace
|
|
427
|
+
|
|
428
|
+
A namespace defines a stable addressing space for application components.
|
|
429
|
+
|
|
430
|
+
In TeqFW, a dependency address such as:
|
|
431
|
+
|
|
432
|
+
```text
|
|
433
|
+
App_User_Repository$
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
uses `App_` as a namespace prefix.
|
|
437
|
+
|
|
438
|
+
The namespace makes the dependency address independent from local file paths and runtime-specific module specifiers.
|
|
439
|
+
|
|
440
|
+
### Component Address
|
|
213
441
|
|
|
214
|
-
|
|
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]
|
|
215
464
|
```
|
|
216
465
|
|
|
217
|
-
|
|
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.
|
|
218
482
|
|
|
219
|
-
|
|
220
|
-
- resolves dependency contracts
|
|
221
|
-
- constructs the object graph
|
|
222
|
-
- returns **frozen linked objects**
|
|
483
|
+
### `__deps__`
|
|
223
484
|
|
|
224
|
-
|
|
485
|
+
`__deps__` is a source-attached dependency declaration.
|
|
225
486
|
|
|
226
|
-
|
|
487
|
+
For a single-export module, dependencies can be declared in shorthand form:
|
|
227
488
|
|
|
228
489
|
```javascript
|
|
229
490
|
export const __deps__ = {
|
|
230
|
-
|
|
231
|
-
localName: "Dependency_CDC",
|
|
232
|
-
},
|
|
233
|
-
Factory: {
|
|
234
|
-
localName: "Dependency_CDC",
|
|
235
|
-
},
|
|
491
|
+
localName: "Dependency_CDC",
|
|
236
492
|
};
|
|
237
493
|
```
|
|
238
494
|
|
|
239
495
|
Rules:
|
|
240
496
|
|
|
241
|
-
- the canonical form is hierarchical and keyed by export name
|
|
242
|
-
- each export entry maps constructor argument names to CDC
|
|
243
|
-
- if `__deps__` is absent
|
|
244
|
-
- a flat `__deps__` object is
|
|
245
|
-
- dependencies are resolved recursively
|
|
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.
|
|
246
501
|
|
|
247
|
-
Canonical
|
|
502
|
+
Canonical export-scoped form:
|
|
248
503
|
|
|
249
504
|
```javascript
|
|
250
505
|
export const __deps__ = {
|
|
251
506
|
default: {
|
|
252
|
-
|
|
507
|
+
localName: "Dependency_CDC",
|
|
253
508
|
},
|
|
254
509
|
Factory: {
|
|
255
|
-
|
|
510
|
+
localName: "Dependency_CDC",
|
|
256
511
|
},
|
|
257
512
|
};
|
|
258
|
-
|
|
259
|
-
export default class RuntimeWrapper {
|
|
260
|
-
constructor() {
|
|
261
|
-
return {
|
|
262
|
-
mode: "runtime-wrapper",
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export class Factory {
|
|
268
|
-
constructor({ cast }) {
|
|
269
|
-
this.configure = function (params = {}) {
|
|
270
|
-
// DI-managed component
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
513
|
```
|
|
275
514
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
- the default export is the runtime wrapper or module shell
|
|
279
|
-
- the named `Factory` export is the DI-managed component
|
|
280
|
-
- `__deps__` applies to the export selected by the CDC, such as `App_Module__Factory$`
|
|
515
|
+
### Namespace Root
|
|
281
516
|
|
|
282
|
-
|
|
517
|
+
A namespace root maps a namespace prefix to a module-specifier base:
|
|
283
518
|
|
|
284
519
|
```javascript
|
|
285
|
-
|
|
286
|
-
cast: "Fl32_Web_Helper_Cast$",
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
export default class RuntimeWrapper {
|
|
290
|
-
constructor() {
|
|
291
|
-
return {
|
|
292
|
-
mode: "runtime-wrapper",
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
}
|
|
520
|
+
container.addNamespaceRoot("App_", "/abs/path/to/src/App", ".mjs");
|
|
296
521
|
```
|
|
297
522
|
|
|
298
|
-
|
|
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:
|
|
299
526
|
|
|
300
527
|
```javascript
|
|
301
|
-
|
|
302
|
-
constructor() {
|
|
303
|
-
this.ready = function () {
|
|
304
|
-
return true;
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
}
|
|
528
|
+
container.addNamespaceRoot("App_", "/project/src/App", ".mjs");
|
|
308
529
|
```
|
|
309
530
|
|
|
310
|
-
In
|
|
311
|
-
|
|
312
|
-
- the module has no declared dependencies
|
|
313
|
-
- `__deps__` is omitted entirely
|
|
314
|
-
- the empty form is valid and intentionally explicit through omission
|
|
315
|
-
|
|
316
|
-
## Canonical Dependency Codes (CDC)
|
|
317
|
-
|
|
318
|
-
CDC identifiers describe **how dependencies should be resolved**.
|
|
531
|
+
In a browser-oriented or isomorphic application, it can also mean URL-backed roots:
|
|
319
532
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
[PlatformPrefix]ModuleName[__ExportName][LifecycleAndWrappers]
|
|
533
|
+
```javascript
|
|
534
|
+
container.addNamespaceRoot("App_", "https://cdn.example.com/app", ".mjs");
|
|
535
|
+
container.addNamespaceRoot("Web_", "//cdn.example.com/web", ".mjs");
|
|
324
536
|
```
|
|
325
537
|
|
|
326
|
-
|
|
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.
|
|
327
539
|
|
|
328
|
-
|
|
329
|
-
App_Service
|
|
330
|
-
App_Service$
|
|
331
|
-
App_Service__build$$
|
|
332
|
-
App_Service$$_wrapLog_wrapTrace
|
|
333
|
-
node:fs
|
|
334
|
-
npm:@humanfs/core
|
|
335
|
-
node:worker_threads
|
|
336
|
-
npm:lodash
|
|
337
|
-
```
|
|
540
|
+
### Runtime Linking
|
|
338
541
|
|
|
339
|
-
|
|
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.
|
|
340
543
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
- `$$` new instance lifecycle
|
|
345
|
-
- wrappers modify runtime behavior
|
|
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.
|
|
346
547
|
|
|
347
548
|
## Public API
|
|
348
549
|
|
|
550
|
+
Create a container:
|
|
551
|
+
|
|
349
552
|
```javascript
|
|
350
553
|
const container = new Container();
|
|
351
554
|
```
|
|
352
555
|
|
|
353
|
-
|
|
556
|
+
Configure it before the first `get(...)`:
|
|
354
557
|
|
|
355
558
|
- `setParser(parser)`
|
|
356
559
|
- `addNamespaceRoot(prefix, target, defaultExt)`
|
|
@@ -360,55 +563,26 @@ Configuration methods (before first `get`):
|
|
|
360
563
|
- `enableTestMode()`
|
|
361
564
|
- `register(cdc, mock)`
|
|
362
565
|
|
|
363
|
-
|
|
566
|
+
Resolve dependencies:
|
|
364
567
|
|
|
365
568
|
```javascript
|
|
366
569
|
await container.get(cdc);
|
|
367
570
|
```
|
|
368
571
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
- deterministic linking
|
|
372
|
-
- fail-fast resolution pipeline
|
|
373
|
-
- immutable returned objects
|
|
374
|
-
- container enters failed state on fatal errors
|
|
375
|
-
|
|
376
|
-
## Wrappers
|
|
377
|
-
|
|
378
|
-
Wrappers allow cross-cutting behavior to be applied declaratively.
|
|
379
|
-
|
|
380
|
-
Example CDC:
|
|
381
|
-
|
|
382
|
-
```txt
|
|
383
|
-
App_Service$$_log_trace
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
Wrappers can implement:
|
|
572
|
+
The container is builder-configurable until the first `get(...)`.
|
|
387
573
|
|
|
388
|
-
|
|
389
|
-
- metrics
|
|
390
|
-
- tracing
|
|
391
|
-
- security checks
|
|
392
|
-
- behavioral instrumentation
|
|
393
|
-
|
|
394
|
-
This acts as a lightweight **DI-level AOP mechanism.**
|
|
395
|
-
|
|
396
|
-
Platform-specific examples:
|
|
397
|
-
|
|
398
|
-
```txt
|
|
399
|
-
node:worker_threads
|
|
400
|
-
npm:@humanfs/core
|
|
401
|
-
```
|
|
574
|
+
After that point configuration is locked.
|
|
402
575
|
|
|
403
576
|
## Test Mode
|
|
404
577
|
|
|
578
|
+
Test mode allows registered mocks to be resolved before module instantiation:
|
|
579
|
+
|
|
405
580
|
```javascript
|
|
406
581
|
container.enableTestMode();
|
|
407
|
-
|
|
408
582
|
container.register("App_Service$", mockService);
|
|
409
583
|
```
|
|
410
584
|
|
|
411
|
-
|
|
585
|
+
This keeps replacement explicit and local to container configuration.
|
|
412
586
|
|
|
413
587
|
## Browser Usage
|
|
414
588
|
|
|
@@ -420,24 +594,36 @@ Mocks are resolved before module instantiation.
|
|
|
420
594
|
</script>
|
|
421
595
|
```
|
|
422
596
|
|
|
423
|
-
## Documentation
|
|
597
|
+
## Documentation for Agents
|
|
598
|
+
|
|
599
|
+
This package includes a machine-oriented package interface under `./ai/`.
|
|
600
|
+
|
|
601
|
+
Those files are intended for system prompts, examples, and agent consumption. They describe:
|
|
602
|
+
|
|
603
|
+
- container usage;
|
|
604
|
+
- dependency descriptors;
|
|
605
|
+
- CDC behavior;
|
|
606
|
+
- integration patterns.
|
|
607
|
+
|
|
608
|
+
The package ships both a human-facing README and a machine-oriented interface for agents that need to use it as a dependency.
|
|
609
|
+
|
|
610
|
+
## Further Reading
|
|
424
611
|
|
|
425
|
-
|
|
612
|
+
- Usage guide: `ai/usage.md`
|
|
613
|
+
- Container API notes: `ai/container.md`
|
|
614
|
+
- Dependency descriptor concepts: `ai/concepts.md`
|
|
615
|
+
- Dependency ID format: `ai/dependency-id.md`
|
|
616
|
+
- Extension points: `ai/extensions.md`
|
|
617
|
+
- Project philosophy and intended application domain: `PHILOSOPHY.md`
|
|
426
618
|
|
|
427
|
-
|
|
428
|
-
- `ctx/docs/product/default-cdc-profile.md`
|
|
429
|
-
- `ctx/docs/architecture/cdc-profile/default/grammar.md`
|
|
430
|
-
- `ctx/docs/architecture/cdc-profile/default/transformation.md`
|
|
431
|
-
- `ctx/docs/architecture/cdc-profile/default/validation.md`
|
|
432
|
-
- `ctx/docs/code/components/container.md`
|
|
619
|
+
## TeqFW Context
|
|
433
620
|
|
|
434
|
-
|
|
621
|
+
`@teqfw/di` is the core dependency-linking building block of the Tequila Framework.
|
|
435
622
|
|
|
436
|
-
|
|
623
|
+
TeqFW is aimed at building modular monolith web applications with a unified JavaScript codebase across browser and server runtimes. The method favors namespace-based component addressing, late binding, explicit contracts, pure JavaScript, and source artifacts that remain legible to both humans and LLM agents.
|
|
437
624
|
|
|
438
|
-
|
|
625
|
+
The broader TeqFW position is that AI-assisted development changes not only how code is written, but also what kind of structure a solo developer needs in order to supervise a growing application.
|
|
439
626
|
|
|
440
|
-
-
|
|
441
|
-
- **ADSM (Agent-Driven Software Management)**
|
|
627
|
+
When JavaScript applications reach enterprise scale under human-agent development, file-path-based dependency wiring becomes too local and too implicit.
|
|
442
628
|
|
|
443
|
-
|
|
629
|
+
`@teqfw/di` is one concrete answer to that change: enterprise-scale dependency architecture for pure JavaScript.
|