@teqfw/di 2.0.3 → 2.0.4

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.4 - 2026-03-10 - LLM-first project positioning
4
+
5
+ - Reframed `README.md` around TeqFW architecture, runtime linking, and LLM-agent-oriented development.
6
+ - Rewrote `PHILOSOPHY.md` into a concise statement of TeqFW principles for human and machine-oriented development.
7
+ - Updated package version metadata to `2.0.4`.
8
+
3
9
  ## 2.0.3 - 2026-03-07 - Package agent interface
4
10
 
5
11
  - Added `ai/` to the published package file list.
package/README.md CHANGED
@@ -3,17 +3,141 @@
3
3
  ![npms.io](https://img.shields.io/npm/dm/@teqfw/di)
4
4
  ![jsdelivr](https://img.shields.io/jsdelivr/npm/hm/@teqfw/di)
5
5
 
6
- Deterministic runtime DI container for native ES modules.
6
+ **Runtime dependency linker for JavaScript applications designed for development with LLM agents.**
7
7
 
8
- `@teqfw/di` uses explicit dependency contracts (CDC strings) and module-level dependency descriptors (`__deps__`).
9
- It does not infer dependencies from constructor signatures.
8
+ `@teqfw/di` is the core infrastructure of the **Tequila Framework (TeqFW)** — an architectural approach for building web applications in which **humans design system architecture and specifications, while LLM agents generate and maintain the implementation.**
10
9
 
11
- ## Version Line
10
+ Instead of wiring modules through static imports, TeqFW applications declare **explicit dependency contracts**, and the container performs **deterministic runtime linking**.
12
11
 
13
- This branch is the v2 line.
12
+ The result is an application architecture that is easier to:
14
13
 
15
- - package version: `2.0.0`
16
- - changelog starts from `2.0.0`
14
+ - analyze
15
+ - generate
16
+ - refactor
17
+ - extend
18
+
19
+ — both for **human developers and AI agents**.
20
+
21
+ ## The Shift in Software Development
22
+
23
+ Large language models are becoming a permanent part of the development process.
24
+
25
+ However, most software architectures were designed for **human-written code**, not for **code generated and maintained by AI agents**.
26
+
27
+ Typical JavaScript applications rely on:
28
+
29
+ - static imports
30
+ - implicit dependency graphs
31
+ - tight coupling to file structure
32
+ - constructor-based dependency inference
33
+
34
+ These patterns work well for humans but are difficult for automated agents to reason about reliably.
35
+
36
+ **TeqFW proposes a different architecture.**
37
+
38
+ Modules declare **explicit dependency contracts**, and a runtime container resolves those contracts deterministically.
39
+
40
+ This transforms the dependency graph into something that can be **analyzed, generated and modified programmatically.**
41
+
42
+ ## What This Library Provides
43
+
44
+ `@teqfw/di` implements the runtime container that enables this architecture.
45
+
46
+ It provides:
47
+
48
+ - deterministic runtime linking of ES modules
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
54
+
55
+ The container acts as a **runtime linker for JavaScript applications**.
56
+
57
+ ## Designed for Development with LLM Agents
58
+
59
+ When software is generated or maintained by LLM agents, several structural problems appear.
60
+
61
+ | Problem | Traditional Architecture | TeqFW Approach |
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 |
68
+
69
+ TeqFW structures the application so that **LLM agents can reliably understand and modify the system.**
70
+
71
+ ## Agent-Driven Implementation
72
+
73
+ Starting from version **2.0.0**, the source code of this library is **written primarily by Codex agents**.
74
+
75
+ The development workflow follows **specification-driven development**:
76
+
77
+ 1. The human architect defines **product specifications**
78
+ 2. LLM agents generate the implementation
79
+ 3. The generated code is reviewed and integrated
80
+
81
+ This workflow follows the **ADSM methodology (Agent-Driven Software Management)** developed by **Alex Gusev**.
82
+
83
+ Earlier versions of the library (<2.0.0) were written manually.
84
+ The current version demonstrates how software can be developed using **human-defined architecture and AI-generated code**.
85
+
86
+ ## Learn the Architecture (Interactive Onboarding)
87
+
88
+ Understanding this architecture can take time.
89
+
90
+ To make onboarding easier, an **interactive AI assistant** [is available](https://fly.wiredgeese.com/flancer/gpt/teqfw/guide/di/).
91
+
92
+ The assistant can explain:
93
+
94
+ - how the container works
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
99
+
100
+ The assistant acts as **interactive documentation** for the project.
101
+
102
+ Custom onboarding assistants like this can also be created **as a service** for other projects and libraries.
103
+
104
+ ## Agent Interface (Documentation for LLM Agents)
105
+
106
+ This package includes **agent interface documentation** intended for LLM agents that use the library as an npm dependency.
107
+
108
+ These documents are distributed inside the package in:
109
+
110
+ ```txt
111
+ ./ai/
112
+ ```
113
+
114
+ The files in this directory describe the **public interface of the package in an agent-friendly form**.
115
+
116
+ They explain:
117
+
118
+ - the container API
119
+ - dependency descriptors (`__deps__`)
120
+ - Canonical Dependency Codes (CDC)
121
+ - dependency resolution behavior
122
+ - integration patterns
123
+
124
+ Human developers typically read the README and source code, while **LLM agents can rely on the documentation in `./ai/`.**
125
+
126
+ ## Tequila Framework Philosophy
127
+
128
+ `@teqfw/di` is the core building block of the **Tequila Framework (TeqFW)** ecosystem.
129
+
130
+ TeqFW is based on several architectural principles:
131
+
132
+ - runtime late binding between components
133
+ - namespace-based module organization
134
+ - modular monolith architecture
135
+ - pure JavaScript without compilation
136
+ - system structures optimized for collaboration with LLM agents
137
+
138
+ Full philosophy:
139
+
140
+ `PHILOSOPHY.md`
17
141
 
18
142
  ## Installation
19
143
 
@@ -21,13 +145,13 @@ This branch is the v2 line.
21
145
  npm install @teqfw/di
22
146
  ```
23
147
 
24
- ## Quick Start
148
+ ## Quick Example
25
149
 
26
- ### 1. Define modules with `__deps__`
150
+ ### Define modules
27
151
 
28
152
  `src/App/Child.mjs`
29
153
 
30
- ```js
154
+ ```javascript
31
155
  export default function App_Child() {
32
156
  return { name: "child" };
33
157
  }
@@ -35,7 +159,7 @@ export default function App_Child() {
35
159
 
36
160
  `src/App/Root.mjs`
37
161
 
38
- ```js
162
+ ```javascript
39
163
  export const __deps__ = {
40
164
  child: "App_Child$",
41
165
  };
@@ -48,9 +172,9 @@ export default function App_Root({ child }) {
48
172
  }
49
173
  ```
50
174
 
51
- ### 2. Configure container in composition root
175
+ ### Configure container
52
176
 
53
- ```js
177
+ ```javascript
54
178
  import path from "node:path";
55
179
  import { fileURLToPath } from "node:url";
56
180
  import Container from "@teqfw/di";
@@ -59,68 +183,73 @@ const __filename = fileURLToPath(import.meta.url);
59
183
  const __dirname = path.dirname(__filename);
60
184
 
61
185
  const container = new Container();
186
+
62
187
  container.addNamespaceRoot("App_", path.resolve(__dirname, "./src/App"), ".mjs");
63
188
 
64
189
  const root = await container.get("App_Root$");
65
- console.log(root.name); // root
66
- console.log(root.child.name); // child
67
- console.log(Object.isFrozen(root)); // true
190
+
191
+ console.log(root.name);
192
+ console.log(root.child.name);
68
193
  ```
69
194
 
70
- ## Dependency Descriptor (`__deps__`)
195
+ The container:
71
196
 
72
- `__deps__` is a static module export:
197
+ - loads modules
198
+ - resolves dependency contracts
199
+ - constructs the object graph
200
+ - returns **frozen linked objects**
73
201
 
74
- ```js
202
+ ## Dependency Contracts (`__deps__`)
203
+
204
+ Modules declare dependencies using a static export.
205
+
206
+ ```javascript
75
207
  export const __deps__ = {
76
- localName: "Some_CDC",
208
+ localName: "Dependency_CDC",
77
209
  };
78
210
  ```
79
211
 
80
- Rules used by container runtime:
212
+ Rules:
213
+
214
+ - if `__deps__` is absent — module has no dependencies
215
+ - keys correspond to constructor argument names
216
+ - values are CDC dependency identifiers
217
+ - dependencies are resolved recursively
81
218
 
82
- - if `__deps__` is missing: module has zero dependencies
83
- - keys are local argument names passed into factory/class constructor
84
- - values are CDC strings
85
- - dependencies are resolved recursively before instantiation
219
+ ## Canonical Dependency Codes (CDC)
86
220
 
87
- ## CDC Grammar (Default Profile)
221
+ CDC identifiers describe **how dependencies should be resolved**.
88
222
 
89
- Surface form:
223
+ General form:
90
224
 
91
- ```text
225
+ ```txt
92
226
  [PlatformPrefix]ModuleName[__ExportName][LifecycleAndWrappers]
93
227
  ```
94
228
 
95
- Where:
96
-
97
- - `PlatformPrefix`: `node_` | `npm_` | omitted (`teq` by default)
98
- - `Export segment`: `__ExportName`
99
- - `Lifecycle marker`: `$` | `$$` | `$$$`
100
- - `Wrappers`: `_<wrapperId>` suffixes after lifecycle marker
101
-
102
229
  Examples:
103
230
 
104
- - `App_Service` - whole module (`as-is`)
105
- - `App_Service$` - default export as factory with lifecycle marker
106
- - `App_Service__build$$` - named export `build` with lifecycle marker
107
- - `App_Service$$_wrapLog_wrapTrace` - wrapper chain in declared order
108
- - `node_fs` - Node builtin
109
- - `npm_lodash` - npm package
231
+ ```txt
232
+ App_Service
233
+ App_Service$
234
+ App_Service__build$$
235
+ App_Service$$_wrapLog_wrapTrace
236
+ node_fs
237
+ npm_lodash
238
+ ```
110
239
 
111
- Notes:
240
+ Where:
112
241
 
113
- - explicit `teq_` prefix is forbidden
114
- - wrappers without lifecycle marker are invalid
115
- - parser is deterministic and fail-fast
242
+ - `$` singleton lifecycle
243
+ - `$$` new instance lifecycle
244
+ - wrappers modify runtime behavior
116
245
 
117
246
  ## Public API
118
247
 
119
- ```js
248
+ ```javascript
120
249
  const container = new Container();
121
250
  ```
122
251
 
123
- Builder stage methods (only before first `get`):
252
+ Configuration methods (before first `get`):
124
253
 
125
254
  - `setParser(parser)`
126
255
  - `addNamespaceRoot(prefix, target, defaultExt)`
@@ -128,137 +257,79 @@ Builder stage methods (only before first `get`):
128
257
  - `addPostprocess(fn)`
129
258
  - `enableLogging()`
130
259
  - `enableTestMode()`
131
- - `register(cdc, mock)` (only in test mode)
132
-
133
- Resolution:
134
-
135
- - `await container.get(cdc)`
136
-
137
- Behavioral guarantees:
138
-
139
- - configuration is locked after first `get`
140
- - fail-fast pipeline
141
- - deterministic linking under identical contracts and config
142
- - produced values are frozen
143
- - container enters failed state after fatal linking error
144
-
145
- ## Wrappers
146
-
147
- Wrappers are postprocess plugins registered during container configuration.
148
- They are activated by wrapper markers in the CDC string and applied to the produced value after instantiation.
149
-
150
- Wrappers:
260
+ - `register(cdc, mock)`
151
261
 
152
- - are **container-level plugins**
153
- - are **not module exports**
154
- - are applied in declared order
155
- - must return synchronously
156
- - run before lifecycle enforcement and freeze
262
+ Dependency resolution:
157
263
 
158
- Surface form:
159
-
160
- ```text
161
- ModuleName$$_wrapperA_wrapperB
264
+ ```javascript
265
+ await container.get(cdc);
162
266
  ```
163
267
 
164
- Wrappers are part of the dependency contract (CDC).
165
- They declaratively modify how a resolved value behaves.
166
-
167
- ---
168
-
169
- ### Example: Logging Wrapper
268
+ Behavior:
170
269
 
171
- Suppose we want to log all method calls of a service without modifying the service itself.
270
+ - deterministic linking
271
+ - fail-fast resolution pipeline
272
+ - immutable returned objects
273
+ - container enters failed state on fatal errors
172
274
 
173
- #### Service module
174
-
175
- ```js
176
- export default function App_Service() {
177
- return {
178
- sum(a, b) {
179
- return a + b;
180
- },
181
- multiply(a, b) {
182
- return a * b;
183
- },
184
- };
185
- }
186
- ```
187
-
188
- #### Container configuration
189
-
190
- ```js
191
- container.addPostprocessWrapper("logIO", (value) => {
192
- return new Proxy(value, {
193
- get(target, prop, receiver) {
194
- const original = Reflect.get(target, prop, receiver);
195
-
196
- if (typeof original !== "function") {
197
- return original;
198
- }
199
-
200
- return function (...args) {
201
- console.log(`[CALL] ${String(prop)} ->`, args);
202
- const result = original.apply(this, args);
203
- console.log(`[RETURN] ${String(prop)} ->`, result);
204
- return result;
205
- };
206
- },
207
- });
208
- });
209
- ```
275
+ ## Wrappers
210
276
 
211
- #### Request
277
+ Wrappers allow cross-cutting behavior to be applied declaratively.
212
278
 
213
- ```js
214
- const service = await container.get("App_Service$$_logIO");
279
+ Example CDC:
215
280
 
216
- service.sum(2, 3);
217
- // [CALL] sum -> [2, 3]
218
- // [RETURN] sum -> 5
281
+ ```txt
282
+ App_Service$$_log_trace
219
283
  ```
220
284
 
221
- The module remains unaware of logging.
222
- The wrapper applies cross-cutting behavior declaratively through CDC.
223
-
224
- This allows:
285
+ Wrappers can implement:
225
286
 
287
+ - logging
288
+ - metrics
226
289
  - tracing
227
- - metrics collection
228
- - access control
290
+ - security checks
229
291
  - behavioral instrumentation
230
292
 
231
- without modifying business logic or module structure.
232
-
233
- Wrappers therefore act as a declarative DI-level AOP mechanism.
293
+ This acts as a lightweight **DI-level AOP mechanism.**
234
294
 
235
- ## Test Mode and Mocks
295
+ ## Test Mode
236
296
 
237
- ```js
297
+ ```javascript
238
298
  container.enableTestMode();
239
- container.register("App_Service$", { name: "mock-service" });
299
+
300
+ container.register("App_Service$", mockService);
240
301
  ```
241
302
 
242
- Mock lookup uses canonical parsed dependency identity and is applied before resolver/instantiation.
303
+ Mocks are resolved before module instantiation.
243
304
 
244
305
  ## Browser Usage
245
306
 
246
- ESM via jsDelivr:
247
-
248
307
  ```html
249
308
  <script type="module">
250
309
  import Container from "https://cdn.jsdelivr.net/npm/@teqfw/di@2/+esm";
310
+
251
311
  const container = new Container();
252
312
  </script>
253
313
  ```
254
314
 
255
- ## Documentation Source
315
+ ## Documentation
316
+
317
+ Detailed documentation lives in `ctx/`:
318
+
319
+ - `ctx/docs/product/overview.md`
320
+ - `ctx/docs/product/default-cdc-profile.md`
321
+ - `ctx/docs/architecture/cdc-profile/default/grammar.md`
322
+ - `ctx/docs/architecture/cdc-profile/default/transformation.md`
323
+ - `ctx/docs/architecture/cdc-profile/default/validation.md`
324
+ - `ctx/docs/code/components/container.md`
325
+
326
+ ## Author
327
+
328
+ **Alex Gusev**
329
+
330
+ Creator of:
256
331
 
257
- Normative docs live in `ctx/`:
332
+ - **Tequila Framework (TeqFW)**
333
+ - **ADSM (Agent-Driven Software Management)**
258
334
 
259
- - product overview: `ctx/docs/product/overview.md`
260
- - default CDC profile: `ctx/docs/product/default-cdc-profile.md`
261
- - grammar: `ctx/docs/architecture/cdc-profile/default/grammar.md`
262
- - transformation: `ctx/docs/architecture/cdc-profile/default/transformation.md`
263
- - validation: `ctx/docs/architecture/cdc-profile/default/validation.md`
264
- - container contract: `ctx/docs/code/components/container.md`
335
+ The project explores how software architecture evolves when **LLM agents become active participants in the development process**.
package/ai/AGENTS.md CHANGED
@@ -50,13 +50,14 @@ This mechanism separates module implementation from dependency binding and allow
50
50
  Agents should read the documents in this directory in the following order:
51
51
 
52
52
  1. **AGENTS.md** — overview of the package and navigation of the Agent Interface.
53
- 2. **concepts.md** — architectural concepts and design principles.
54
- 3. **container.md** — container responsibilities and dependency resolution pipeline.
55
- 4. **dependency-id.md** — syntax and semantics of dependency identifiers.
56
- 5. **extensions.md** — extension mechanisms such as preprocessors and wrappers.
57
- 6. **usage.md** — minimal usage scenarios and examples.
58
-
59
- This sequence reflects the conceptual flow required to understand the package: architectural model → operational mechanism → dependency addressing → extension points → practical usage.
53
+ 2. **package-api.ts** — machine-readable contract of the supported programmatic API, public entrypoints, structural contracts, and internal exclusions.
54
+ 3. **concepts.md** — architectural concepts and design principles.
55
+ 4. **container.md** — container responsibilities and dependency resolution pipeline.
56
+ 5. **dependency-id.md** — syntax and semantics of dependency identifiers.
57
+ 6. **extensions.md** — extension mechanisms such as preprocessors and wrappers.
58
+ 7. **usage.md** — minimal usage scenarios and examples.
59
+
60
+ This sequence reflects the intended agent workflow: contract surface first, then architectural model, operational mechanism, dependency addressing, extension points, and practical usage.
60
61
 
61
62
  ## Interface Scope
62
63
 
@@ -0,0 +1,440 @@
1
+ export type ApiExposure =
2
+ | 'public-runtime'
3
+ | 'public-structural'
4
+ | 'internal';
5
+
6
+ export interface ImportBinding {
7
+ readonly specifier: string;
8
+ readonly exportName: 'default' | string;
9
+ readonly canonical: boolean;
10
+ readonly note?: string;
11
+ }
12
+
13
+ export interface MethodContract {
14
+ readonly name: string;
15
+ readonly signature: string;
16
+ readonly stage?: 'builder' | 'runtime' | 'composition';
17
+ readonly summary: string;
18
+ readonly constraints?: readonly string[];
19
+ }
20
+
21
+ export interface RuntimeComponentContract {
22
+ readonly alias: string;
23
+ readonly kind: 'class';
24
+ readonly role: string;
25
+ readonly imports: readonly ImportBinding[];
26
+ readonly methods: readonly MethodContract[];
27
+ }
28
+
29
+ export interface StructuralContract {
30
+ readonly name: string;
31
+ readonly kind: 'dto' | 'enum' | 'protocol' | 'module-contract';
32
+ readonly summary: string;
33
+ readonly aliases?: readonly string[];
34
+ readonly fields?: Readonly<Record<string, string>>;
35
+ readonly values?: Readonly<Record<string, string>>;
36
+ readonly notes?: readonly string[];
37
+ }
38
+
39
+ export interface TypeAliasClassification {
40
+ readonly alias: string;
41
+ readonly source: string;
42
+ readonly exposure: ApiExposure;
43
+ readonly reason: string;
44
+ readonly canonicalUse?: string;
45
+ readonly sameAs?: readonly string[];
46
+ }
47
+
48
+ export interface PackageApiContract {
49
+ readonly packageName: '@teqfw/di';
50
+ readonly packageRole: string;
51
+ readonly canonicalEntrypoints: readonly string[];
52
+ readonly publicRuntime: readonly RuntimeComponentContract[];
53
+ readonly structuralContracts: readonly StructuralContract[];
54
+ readonly typeMapClassification: readonly TypeAliasClassification[];
55
+ readonly operationalNotes: readonly string[];
56
+ }
57
+
58
+ /**
59
+ * Public package contract intended for agents that consume `@teqfw/di`
60
+ * as an npm dependency.
61
+ *
62
+ * This file distinguishes between:
63
+ * - importable runtime API supported by `package.json#exports`
64
+ * - structural contracts that external code may rely on indirectly
65
+ * - internal implementation aliases present in `types.d.ts`
66
+ */
67
+ export const PACKAGE_API: PackageApiContract = {
68
+ packageName: '@teqfw/di',
69
+ packageRole: 'Deterministic runtime DI container for native ES modules with explicit CDC contracts.',
70
+ canonicalEntrypoints: [
71
+ '@teqfw/di',
72
+ '@teqfw/di/src/Config/NamespaceRegistry.mjs',
73
+ ],
74
+ publicRuntime: [
75
+ {
76
+ alias: 'TeqFw_Di_Container',
77
+ kind: 'class',
78
+ role: 'Primary runtime composition root. Resolves CDC identifiers into frozen linked values.',
79
+ imports: [
80
+ {
81
+ specifier: '@teqfw/di',
82
+ exportName: 'default',
83
+ canonical: true,
84
+ },
85
+ {
86
+ specifier: '@teqfw/di/src/Container.mjs',
87
+ exportName: 'default',
88
+ canonical: false,
89
+ note: 'Explicit source subpath export. Prefer the package root import.',
90
+ },
91
+ ],
92
+ methods: [
93
+ {
94
+ name: 'constructor',
95
+ signature: 'new Container()',
96
+ stage: 'builder',
97
+ summary: 'Creates a container in builder stage. The constructor accepts no arguments.',
98
+ },
99
+ {
100
+ name: 'setParser',
101
+ signature: 'setParser(parser: { parse(cdc: string): TeqFw_Di_DepId$DTO }): void',
102
+ stage: 'builder',
103
+ summary: 'Replaces the default CDC parser before the first resolution.',
104
+ constraints: [
105
+ 'Allowed only before the first get().',
106
+ 'The parser contract is structural. The package does not export the default parser runtime class.',
107
+ ],
108
+ },
109
+ {
110
+ name: 'addNamespaceRoot',
111
+ signature: 'addNamespaceRoot(prefix: string, target: string, defaultExt: string): void',
112
+ stage: 'builder',
113
+ summary: 'Registers one namespace-to-filesystem mapping rule.',
114
+ constraints: [
115
+ 'Allowed only before the first get().',
116
+ 'Namespace rules are snapshotted and locked on the first get().',
117
+ ],
118
+ },
119
+ {
120
+ name: 'addPreprocess',
121
+ signature: 'addPreprocess(fn: (depId: TeqFw_Di_DepId$DTO) => TeqFw_Di_DepId$DTO): void',
122
+ stage: 'builder',
123
+ summary: 'Adds an ordered CDC preprocessing hook.',
124
+ constraints: [
125
+ 'Allowed only before the first get().',
126
+ 'Each hook must return another DepId DTO.',
127
+ ],
128
+ },
129
+ {
130
+ name: 'addPostprocess',
131
+ signature: 'addPostprocess(fn: (value: unknown) => unknown): void',
132
+ stage: 'builder',
133
+ summary: 'Adds an ordered post-instantiation value transform applied to every resolved value.',
134
+ constraints: [
135
+ 'Allowed only before the first get().',
136
+ 'Runs before wrapper exports and before freeze.',
137
+ ],
138
+ },
139
+ {
140
+ name: 'enableLogging',
141
+ signature: 'enableLogging(): void',
142
+ stage: 'builder',
143
+ summary: 'Turns on diagnostic console logging without changing linking semantics.',
144
+ constraints: [
145
+ 'Allowed only before the first get().',
146
+ ],
147
+ },
148
+ {
149
+ name: 'enableTestMode',
150
+ signature: 'enableTestMode(): void',
151
+ stage: 'builder',
152
+ summary: 'Enables structural mock registration for tests.',
153
+ constraints: [
154
+ 'Allowed only before the first get().',
155
+ ],
156
+ },
157
+ {
158
+ name: 'register',
159
+ signature: 'register(cdc: string, mock: unknown): void',
160
+ stage: 'builder',
161
+ summary: 'Registers a mock by canonical DepId identity after parsing the provided CDC.',
162
+ constraints: [
163
+ 'Allowed only before the first get().',
164
+ 'Requires enableTestMode() first.',
165
+ ],
166
+ },
167
+ {
168
+ name: 'get',
169
+ signature: 'get(cdc: string): Promise<any>',
170
+ stage: 'runtime',
171
+ summary: 'Parses, resolves, instantiates, postprocesses, wraps, applies lifecycle, freezes, and returns a linked value.',
172
+ constraints: [
173
+ 'The first get() locks configuration and creates internal infrastructure.',
174
+ 'Any fatal pipeline error moves the container into failed state.',
175
+ 'All subsequent get() calls reject once the container is failed.',
176
+ ],
177
+ },
178
+ ],
179
+ },
180
+ {
181
+ alias: 'TeqFw_Di_Config_NamespaceRegistry',
182
+ kind: 'class',
183
+ role: 'Composition-stage helper that discovers namespace roots from the root package and installed npm dependencies.',
184
+ imports: [
185
+ {
186
+ specifier: '@teqfw/di/src/Config/NamespaceRegistry.mjs',
187
+ exportName: 'default',
188
+ canonical: true,
189
+ },
190
+ ],
191
+ methods: [
192
+ {
193
+ name: 'constructor',
194
+ signature: 'new NamespaceRegistry({ fs, path, appRoot })',
195
+ stage: 'composition',
196
+ summary: 'Creates a registry builder over filesystem and path adapters.',
197
+ constraints: [
198
+ 'Intended for composition root code, not for DI-managed runtime modules.',
199
+ 'Consumes static package.json metadata only.',
200
+ ],
201
+ },
202
+ {
203
+ name: 'build',
204
+ signature: 'build(): Promise<ReadonlyArray<{ prefix: string; dirAbs: string; ext: string }>>',
205
+ stage: 'composition',
206
+ summary: 'Builds an immutable namespace registry sorted by descending prefix length.',
207
+ constraints: [
208
+ 'Fails fast on invalid namespace metadata or duplicate canonical prefixes.',
209
+ ],
210
+ },
211
+ ],
212
+ },
213
+ ],
214
+ structuralContracts: [
215
+ {
216
+ name: 'DepId DTO',
217
+ kind: 'dto',
218
+ aliases: ['TeqFw_Di_DepId$DTO', 'TeqFw_Di_Dto_DepId$DTO'],
219
+ summary: 'Canonical structural dependency identity passed to preprocess hooks and expected from custom parsers.',
220
+ fields: {
221
+ moduleName: 'Logical module identifier without platform prefix.',
222
+ platform: '"teq" | "node" | "npm".',
223
+ exportName: 'Named export or "default"; null means whole-module/as-is resolution.',
224
+ composition: '"A" | "F" in the current implementation.',
225
+ life: '"S" | "T" | null in the current implementation.',
226
+ wrappers: 'Ordered wrapper export names.',
227
+ origin: 'Original CDC string for diagnostics.',
228
+ },
229
+ notes: [
230
+ 'Identity excludes origin.',
231
+ 'Consumers should treat it as a structural protocol, not as a factory import surface.',
232
+ ],
233
+ },
234
+ {
235
+ name: 'Parser Protocol',
236
+ kind: 'protocol',
237
+ aliases: ['TeqFw_Di_Def_Parser'],
238
+ summary: 'Structural contract accepted by Container.setParser().',
239
+ fields: {
240
+ parse: '(cdc: string) => TeqFw_Di_DepId$DTO',
241
+ },
242
+ notes: [
243
+ 'The package does not export the default parser runtime class through package exports.',
244
+ 'External code may provide any object that satisfies the parse() contract.',
245
+ ],
246
+ },
247
+ {
248
+ name: 'DepId Enums',
249
+ kind: 'enum',
250
+ aliases: [
251
+ 'TeqFw_Di_Enum_Composition',
252
+ 'TeqFw_Di_Enum_Life',
253
+ 'TeqFw_Di_Enum_Platform',
254
+ ],
255
+ summary: 'Current implementation literals used inside DepId DTO values.',
256
+ values: {
257
+ composition: 'AS_IS -> "A", FACTORY -> "F"',
258
+ life: 'SINGLETON -> "S", TRANSIENT -> "T"',
259
+ platform: 'TEQ -> "teq", NODE -> "node", NPM -> "npm"',
260
+ },
261
+ notes: [
262
+ 'These aliases are useful for tooling and JSDoc, not for runtime imports from the package.',
263
+ ],
264
+ },
265
+ {
266
+ name: 'Module Contract',
267
+ kind: 'module-contract',
268
+ summary: 'Shape expected from application modules resolved by the container.',
269
+ fields: {
270
+ __deps__: 'Optional top-level Record<string, string> mapping constructor keys to CDC strings.',
271
+ moduleNamespace: 'Whole ES module namespace object returned for as-is CDC without selected export.',
272
+ 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 functions.',
274
+ wrapperExport: 'Named export whose identifier appears in depId.wrappers; it must be synchronous and unary.',
275
+ },
276
+ notes: [
277
+ 'The current runtime reads namespace.__deps__ directly; it does not use export-scoped dependency maps.',
278
+ 'Wrapper functions are exported by the same resolved module namespace, not registered globally in the container.',
279
+ ],
280
+ },
281
+ ],
282
+ typeMapClassification: [
283
+ {
284
+ alias: 'TeqFw_Di_Config_NamespaceRegistry',
285
+ source: './src/Config/NamespaceRegistry.mjs',
286
+ exposure: 'public-runtime',
287
+ reason: 'Exported through package.json exports as a supported subpath entrypoint.',
288
+ canonicalUse: 'Composition-stage helper imported from @teqfw/di/src/Config/NamespaceRegistry.mjs.',
289
+ },
290
+ {
291
+ alias: 'TeqFw_Di_Container',
292
+ source: './src/Container.mjs',
293
+ exposure: 'public-runtime',
294
+ reason: 'Default export of the package root and of the explicit source subpath.',
295
+ canonicalUse: 'Primary container API imported from @teqfw/di.',
296
+ },
297
+ {
298
+ alias: 'TeqFw_Di_Container_Instantiate_ExportSelector',
299
+ source: './src/Container/Instantiate/ExportSelector.mjs',
300
+ exposure: 'internal',
301
+ reason: 'Internal immutable-core helper. Not exported via package.json.',
302
+ },
303
+ {
304
+ alias: 'TeqFw_Di_Container_Instantiate_Instantiator',
305
+ source: './src/Container/Instantiate/Instantiator.mjs',
306
+ exposure: 'internal',
307
+ reason: 'Internal immutable-core helper. Not exported via package.json.',
308
+ },
309
+ {
310
+ alias: 'TeqFw_Di_Container_Lifecycle_Registry',
311
+ source: './src/Container/Lifecycle/Registry.mjs',
312
+ exposure: 'internal',
313
+ reason: 'Internal lifecycle cache component. Not exported via package.json.',
314
+ },
315
+ {
316
+ alias: 'TeqFw_Di_Container_Resolve_GraphResolver',
317
+ source: './src/Container/Resolve/GraphResolver.mjs',
318
+ exposure: 'internal',
319
+ reason: 'Internal graph builder used by Container.get(). Not exported via package.json.',
320
+ },
321
+ {
322
+ alias: 'TeqFw_Di_Container_Wrapper_Executor',
323
+ source: './src/Container/Wrapper/Executor.mjs',
324
+ exposure: 'internal',
325
+ reason: 'Internal wrapper-stage executor. Not exported via package.json.',
326
+ },
327
+ {
328
+ alias: 'TeqFw_Di_Def_Parser',
329
+ source: './src/Def/Parser.mjs',
330
+ exposure: 'public-structural',
331
+ reason: 'Container.setParser() accepts this structural contract, but the runtime class is not importable from the package.',
332
+ canonicalUse: 'Typing/protocol alias for custom parser implementations.',
333
+ },
334
+ {
335
+ alias: 'TeqFw_Di_DepId',
336
+ source: './src/Dto/DepId.mjs',
337
+ exposure: 'internal',
338
+ reason: 'Factory class behind the DepId DTO module. Not needed for the supported package runtime API.',
339
+ sameAs: ['TeqFw_Di_Dto_DepId'],
340
+ },
341
+ {
342
+ alias: 'TeqFw_Di_DepId$DTO',
343
+ source: './src/Dto/DepId.mjs#DTO',
344
+ exposure: 'public-structural',
345
+ reason: 'Public structural protocol used by preprocess hooks and parser replacement.',
346
+ canonicalUse: 'Primary type alias for canonical dependency identity.',
347
+ sameAs: ['TeqFw_Di_Dto_DepId$DTO'],
348
+ },
349
+ {
350
+ alias: 'TeqFw_Di_Dto_DepId',
351
+ source: './src/Dto/DepId.mjs',
352
+ exposure: 'internal',
353
+ reason: 'Legacy-namespaced alias of the DepId factory class; not part of the supported runtime import surface.',
354
+ sameAs: ['TeqFw_Di_DepId'],
355
+ },
356
+ {
357
+ alias: 'TeqFw_Di_Dto_DepId$DTO',
358
+ source: './src/Dto/DepId.mjs#DTO',
359
+ exposure: 'public-structural',
360
+ reason: 'Synonym of TeqFw_Di_DepId$DTO kept in the type map.',
361
+ sameAs: ['TeqFw_Di_DepId$DTO'],
362
+ },
363
+ {
364
+ alias: 'TeqFw_Di_Dto_Resolver_Config',
365
+ source: './src/Dto/Resolver/Config.mjs',
366
+ exposure: 'internal',
367
+ reason: 'Internal DTO factory used inside Container when bootstrapping Resolver.',
368
+ },
369
+ {
370
+ alias: 'TeqFw_Di_Dto_Resolver_Config$DTO',
371
+ source: './src/Dto/Resolver/Config.mjs#DTO',
372
+ exposure: 'internal',
373
+ reason: 'Internal resolver configuration DTO. External code configures the container through addNamespaceRoot() instead.',
374
+ },
375
+ {
376
+ alias: 'TeqFw_Di_Dto_Resolver_Config_Namespace',
377
+ source: './src/Dto/Resolver/Config/Namespace.mjs',
378
+ exposure: 'internal',
379
+ reason: 'Internal DTO factory for resolver namespace rules.',
380
+ },
381
+ {
382
+ alias: 'TeqFw_Di_Dto_Resolver_Config_Namespace$DTO',
383
+ source: './src/Dto/Resolver/Config/Namespace.mjs#DTO',
384
+ exposure: 'internal',
385
+ reason: 'Internal resolver namespace DTO alias retained for type-map completeness.',
386
+ sameAs: ['TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$'],
387
+ },
388
+ {
389
+ alias: 'TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$',
390
+ source: './src/Dto/Resolver/Config/Namespace.mjs#DTO',
391
+ exposure: 'internal',
392
+ reason: 'Duplicate DTO alias retained for compatibility inside implementation typings.',
393
+ sameAs: ['TeqFw_Di_Dto_Resolver_Config_Namespace$DTO'],
394
+ },
395
+ {
396
+ alias: 'TeqFw_Di_Enum_Composition',
397
+ source: './src/Enum/Composition.mjs',
398
+ exposure: 'public-structural',
399
+ reason: 'Useful static vocabulary for interpreting DepId.composition values.',
400
+ canonicalUse: 'Type/JSDoc vocabulary only; no package export for runtime import.',
401
+ },
402
+ {
403
+ alias: 'TeqFw_Di_Enum_Life',
404
+ source: './src/Enum/Life.mjs',
405
+ exposure: 'public-structural',
406
+ reason: 'Useful static vocabulary for interpreting DepId.life values.',
407
+ canonicalUse: 'Type/JSDoc vocabulary only; no package export for runtime import.',
408
+ },
409
+ {
410
+ alias: 'TeqFw_Di_Enum_Platform',
411
+ source: './src/Enum/Platform.mjs',
412
+ exposure: 'public-structural',
413
+ reason: 'Useful static vocabulary for interpreting DepId.platform values.',
414
+ canonicalUse: 'Type/JSDoc vocabulary only; no package export for runtime import.',
415
+ },
416
+ {
417
+ alias: 'TeqFw_Di_Internal_Logger',
418
+ source: './src/Internal/Logger.mjs',
419
+ exposure: 'internal',
420
+ reason: 'Diagnostic helper used only inside the container implementation.',
421
+ },
422
+ {
423
+ alias: 'TeqFw_Di_Resolver',
424
+ source: './src/Container/Resolver.mjs',
425
+ exposure: 'internal',
426
+ reason: 'Internal module resolver infrastructure. Consumers should configure the Container, not instantiate Resolver directly.',
427
+ },
428
+ ],
429
+ operationalNotes: [
430
+ 'Only two runtime entrypoints are supported by package.json exports: @teqfw/di and @teqfw/di/src/Config/NamespaceRegistry.mjs.',
431
+ 'Resolved values are frozen before being returned.',
432
+ 'The current runtime reads __deps__ as a flat top-level map exported by the module namespace.',
433
+ 'With the default parser, CDC without lifecycle returns the whole module namespace as-is; named export selection implies factory composition.',
434
+ 'Named wrapper exports are executed after addPostprocess() hooks and before freeze.',
435
+ 'In the current implementation, CDC markers $$ and $$$ both end up as transient/no-cache behavior.',
436
+ '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.',
437
+ ],
438
+ } as const;
439
+
440
+ export default PACKAGE_API;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teqfw/di",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "Dependency Injection container for ES6 modules that works in both browser and Node.js apps.",
5
5
  "keywords": [
6
6
  "dependency injection",