@teqfw/di 1.1.2 → 1.2.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 +10 -0
- package/README.md +98 -92
- package/package.json +1 -1
- package/types.d.ts +24 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
- Documented the dependency declaration model in the README and product overview.
|
|
6
|
+
- Refined the type map rules to clarify tsserver scope and public vs internal type visibility.
|
|
7
|
+
- Updated `types.d.ts` mappings to use `InstanceType` for class defaults and split internal aliases from globals.
|
|
8
|
+
|
|
9
|
+
## 1.1.3
|
|
10
|
+
|
|
11
|
+
- Added global type declarations to `types.d.ts` to match the type map architecture rules.
|
|
12
|
+
|
|
3
13
|
## 1.1.2
|
|
4
14
|
|
|
5
15
|
- Moved architecture diagrams into `ctx/img/` and updated the context map accordingly.
|
package/README.md
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|

|
|
4
4
|

|
|
5
5
|
|
|
6
|
-
> [!IMPORTANT]
|
|
7
|
-
> **Breaking Changes in v1.0.0**
|
|
6
|
+
> [!IMPORTANT] > **Breaking Changes in v1.0.0**
|
|
8
7
|
>
|
|
9
8
|
> The library has been stable for a long time and is now promoted to its first major version. To improve security, the Object Container can no longer access itself, so all configuration must occur in the Composition Root. This restriction ensures that third-party plugins cannot override or modify the container's internal functionality. Legacy versions are maintained in the `forerunner` branch, and packages like `@teqfw/core` should depend on `@teqfw/di` versions below `1.0.0`.
|
|
10
9
|
|
|
@@ -40,6 +39,17 @@ To explore the conceptual background, see: **[TeqFW Philosophy](./PHILOSOPHY.md)
|
|
|
40
39
|
|
|
41
40
|
---
|
|
42
41
|
|
|
42
|
+
## Dependency Declaration Model
|
|
43
|
+
|
|
44
|
+
In `@teqfw/di`, dependencies are declared **exclusively in the constructor (or factory) signature**.
|
|
45
|
+
A component defines its dependencies using a **single object parameter**, where each property name
|
|
46
|
+
is a dependency identifier interpreted by the container.
|
|
47
|
+
|
|
48
|
+
The container analyzes the constructor signature, resolves all declared identifiers **before object
|
|
49
|
+
creation**, and invokes the constructor with a fully populated argument object. Created objects are isolated from the container.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
43
53
|
## Samples
|
|
44
54
|
|
|
45
55
|
Explore `@teqfw/di` in action through the following demo applications:
|
|
@@ -70,41 +80,42 @@ configuring the container, and finally retrieving the main object with injected
|
|
|
70
80
|
Here’s an example of how files might be organized in a project. This structure can vary depending on your project needs,
|
|
71
81
|
as the container can be configured to work with any layout (e.g., within `/home/user/project/`):
|
|
72
82
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
```text
|
|
84
|
+
./src/
|
|
85
|
+
./Service/
|
|
86
|
+
./Customer.js
|
|
87
|
+
./Sale.js
|
|
88
|
+
./Config.js
|
|
89
|
+
./Logger.js
|
|
90
|
+
./Main.js
|
|
91
|
+
```
|
|
82
92
|
|
|
83
93
|
### Step 2: Declare Dependencies
|
|
84
94
|
|
|
85
|
-
In your code, declare dependencies by specifying them as keys in the constructor.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
In your code, declare dependencies by specifying them as keys in the constructor. This is the only supported
|
|
96
|
+
way to declare dependencies in `@teqfw/di`. Dependency identifiers here follow a namespace style similar to PHP
|
|
97
|
+
Zend 1, which is used by default in this library. You can also implement a custom parser if you prefer a
|
|
98
|
+
different naming convention or mapping strategy.
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
export default class App_Main {
|
|
102
|
+
constructor({
|
|
103
|
+
App_Config$: config,
|
|
104
|
+
App_Logger$: logger,
|
|
105
|
+
App_Service_Customer$: servCustomer,
|
|
106
|
+
App_Service_Sale$: servSale,
|
|
107
|
+
}) {
|
|
108
|
+
/* ... */
|
|
109
|
+
}
|
|
99
110
|
}
|
|
100
|
-
|
|
111
|
+
```
|
|
101
112
|
|
|
102
113
|
### Step 3: Configure the Container
|
|
103
114
|
|
|
104
115
|
Next, set up the container and configure it to use the correct namespace and path for your dependencies:
|
|
105
116
|
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
```js
|
|
118
|
+
import Container from "@teqfw/di";
|
|
108
119
|
|
|
109
120
|
// Create a new instance of the container
|
|
110
121
|
const container = new Container();
|
|
@@ -113,17 +124,17 @@ const container = new Container();
|
|
|
113
124
|
const resolver = container.getResolver();
|
|
114
125
|
|
|
115
126
|
// Define the namespace root for dependencies, allowing the container to resolve identifiers like 'App_*'
|
|
116
|
-
resolver.addNamespaceRoot(
|
|
117
|
-
|
|
127
|
+
resolver.addNamespaceRoot("App_", "/home/user/project/src");
|
|
128
|
+
```
|
|
118
129
|
|
|
119
130
|
### Step 4: Retrieve the Main Object with Dependencies
|
|
120
131
|
|
|
121
132
|
Finally, retrieve your main application instance. The container automatically injects all declared dependencies:
|
|
122
133
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const app = await container.get(
|
|
126
|
-
|
|
134
|
+
```js
|
|
135
|
+
// Retrieve the main application instance as a singleton asynchronously
|
|
136
|
+
const app = await container.get("App_Main$");
|
|
137
|
+
```
|
|
127
138
|
|
|
128
139
|
---
|
|
129
140
|
|
|
@@ -136,7 +147,7 @@ When test mode is enabled via `container.enableTestMode()`, you can manually reg
|
|
|
136
147
|
|
|
137
148
|
```js
|
|
138
149
|
container.enableTestMode();
|
|
139
|
-
container.register(
|
|
150
|
+
container.register("App_Service_Customer$", mockCustomerService);
|
|
140
151
|
```
|
|
141
152
|
|
|
142
153
|
This makes it easy to substitute real implementations with mocks or stubs during tests, without altering production
|
|
@@ -148,17 +159,17 @@ A powerful feature of `@teqfw/di` is the ability to mock **Node.js built-in libr
|
|
|
148
159
|
`process`. This is useful for isolating side effects and simulating system behavior:
|
|
149
160
|
|
|
150
161
|
```js
|
|
151
|
-
container.register(
|
|
152
|
-
|
|
162
|
+
container.register("node:fs", {
|
|
163
|
+
existsSync: (path) => path.endsWith(".html"),
|
|
153
164
|
});
|
|
154
165
|
```
|
|
155
166
|
|
|
156
167
|
You can also register mocks for custom logic or environment-specific behavior:
|
|
157
168
|
|
|
158
169
|
```js
|
|
159
|
-
container.register(
|
|
160
|
-
|
|
161
|
-
|
|
170
|
+
container.register("node:path", {
|
|
171
|
+
join: (...args) => args.join("/"),
|
|
172
|
+
resolve: (p) => `/abs/${p}`,
|
|
162
173
|
});
|
|
163
174
|
```
|
|
164
175
|
|
|
@@ -173,9 +184,8 @@ isolated, and deterministic unit tests — even for logic that relies on the fil
|
|
|
173
184
|
extensive flexibility and configurability. This allows the library to adapt seamlessly to a wide range of project needs.
|
|
174
185
|
Here’s what makes it stand out:
|
|
175
186
|
|
|
176
|
-
- **Automatic Dependency Resolution**: The library
|
|
177
|
-
|
|
178
|
-
box but can be fully customized if needed.
|
|
187
|
+
- **Automatic Dependency Resolution**: The library resolves and injects dependencies by interpreting constructor
|
|
188
|
+
signatures. This basic functionality works out of the box but can be fully customized if needed.
|
|
179
189
|
|
|
180
190
|
- **Flexible Dependency ID Configuration**: With customizable parsers and chunks, you can define unique ID schemes for
|
|
181
191
|
dependencies, making it easy to adapt the library to specific naming conventions or custom mapping rules.
|
|
@@ -210,45 +220,43 @@ be easily customized to meet unique project demands.
|
|
|
210
220
|
|
|
211
221
|
To install `@teqfw/di` in a Node.js environment, use the following command:
|
|
212
222
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
223
|
+
```shell
|
|
224
|
+
npm install @teqfw/di
|
|
225
|
+
```
|
|
216
226
|
|
|
217
227
|
Then, import and initialize the container:
|
|
218
228
|
|
|
219
|
-
|
|
220
|
-
|
|
229
|
+
```js
|
|
230
|
+
import Container from "@teqfw/di";
|
|
221
231
|
|
|
222
232
|
/** @type {TeqFw_Di_Container} */
|
|
223
233
|
const container = new Container();
|
|
224
|
-
|
|
234
|
+
```
|
|
225
235
|
|
|
226
236
|
### For the Browser (ESM Module)
|
|
227
237
|
|
|
228
238
|
To use `@teqfw/di` in a browser environment with ES modules, include it as follows (~5KB):
|
|
229
239
|
|
|
230
|
-
|
|
231
|
-
|
|
240
|
+
```html
|
|
232
241
|
<script type="module">
|
|
233
|
-
|
|
242
|
+
import Container from "https://cdn.jsdelivr.net/npm/@teqfw/di@latest/+esm";
|
|
234
243
|
|
|
235
|
-
|
|
236
|
-
|
|
244
|
+
/** @type {TeqFw_Di_Container} */
|
|
245
|
+
const container = new Container();
|
|
237
246
|
</script>
|
|
238
|
-
|
|
247
|
+
```
|
|
239
248
|
|
|
240
249
|
### For the Browser (UMD Module)
|
|
241
250
|
|
|
242
251
|
Alternatively, you can use the UMD version in the browser (~5KB):
|
|
243
252
|
|
|
244
|
-
|
|
245
|
-
|
|
253
|
+
```html
|
|
246
254
|
<script src="https://cdn.jsdelivr.net/npm/@teqfw/di@latest/dist/umd.js"></script>
|
|
247
255
|
<script>
|
|
248
|
-
|
|
249
|
-
|
|
256
|
+
/** @type {TeqFw_Di_Container} */
|
|
257
|
+
const container = new window.TeqFw_Di_Container();
|
|
250
258
|
</script>
|
|
251
|
-
|
|
259
|
+
```
|
|
252
260
|
|
|
253
261
|
---
|
|
254
262
|
|
|
@@ -259,35 +267,35 @@ Alternatively, you can use the UMD version in the browser (~5KB):
|
|
|
259
267
|
1. **Configure Dependency Mapping**: Configure the resolver to detect the platform environment. Then, set up namespace
|
|
260
268
|
roots to map dependency IDs to their source paths.
|
|
261
269
|
|
|
262
|
-
|
|
263
|
-
|
|
270
|
+
```js
|
|
271
|
+
import { platform } from "node:process";
|
|
264
272
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
273
|
+
const resolver = container.getResolver();
|
|
274
|
+
resolver.setWindowsEnv(platform === "win32"); // Adjusts for Windows environment if needed
|
|
275
|
+
resolver.addNamespaceRoot("App_", "/path/to/src");
|
|
276
|
+
```
|
|
269
277
|
|
|
270
278
|
2. **Retrieve Singleton Instances**: Retrieve the main application instance as a singleton asynchronously:
|
|
271
279
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
280
|
+
```js
|
|
281
|
+
const app = await container.get("App_Main$");
|
|
282
|
+
```
|
|
275
283
|
|
|
276
284
|
### In the Browser
|
|
277
285
|
|
|
278
286
|
1. **Configure Dependency Mapping**: Set up namespace roots to map dependency IDs to their source paths, using URLs as
|
|
279
287
|
needed.
|
|
280
288
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
289
|
+
```js
|
|
290
|
+
const resolver = container.getResolver();
|
|
291
|
+
resolver.addNamespaceRoot("App_", "https://cdn.jsdelivr.net/npm/@flancer64/demo-di-app@0.2/src");
|
|
292
|
+
```
|
|
285
293
|
|
|
286
294
|
2. **Retrieve Singleton Instances**: Retrieve the main application instance as a singleton asynchronously:
|
|
287
295
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
296
|
+
```js
|
|
297
|
+
const app = await container.get("App_Main$");
|
|
298
|
+
```
|
|
291
299
|
|
|
292
300
|
With these steps, the container is configured to automatically resolve and inject dependencies based on your setup,
|
|
293
301
|
whether in Node.js or in a browser environment.
|
|
@@ -300,7 +308,7 @@ whether in Node.js or in a browser environment.
|
|
|
300
308
|
quick reference:
|
|
301
309
|
|
|
302
310
|
| Dependency ID | Import Style | Description |
|
|
303
|
-
|
|
311
|
+
| --------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
|
|
304
312
|
| `App_Service` | `import * as Service from './App/Service.js';` | Imports the entire module as an ES module. |
|
|
305
313
|
| `App_Service.default` | `import {default} from './App/Service.js';` | Imports the default export as-is. |
|
|
306
314
|
| `App_Service.name` | `import {name} from './App/Service.js';` | Imports a named export as-is. |
|
|
@@ -316,20 +324,18 @@ Here’s an example showing a class with multiple dependencies, each using diffe
|
|
|
316
324
|
|
|
317
325
|
```js
|
|
318
326
|
export default class App_Main {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
const {default: SrvDef, name: SrvName} = EsModule; // Deconstruct the module and access the exports
|
|
332
|
-
}
|
|
327
|
+
constructor({
|
|
328
|
+
App_Service: EsModule,
|
|
329
|
+
"App_Service.default": defaultExportAsIs,
|
|
330
|
+
"App_Service.name": namedExportAsIs,
|
|
331
|
+
App_Service$: defaultExportAsSingleton,
|
|
332
|
+
App_Service$$: defaultExportAsInstance,
|
|
333
|
+
"App_Service.name$": namedExportAsSingleton,
|
|
334
|
+
"App_Service.name$$": namedExportAsInstance,
|
|
335
|
+
"App_Service.name(factory)": factoryToCreateInstancesFromNamedExport,
|
|
336
|
+
}) {
|
|
337
|
+
const { default: SrvDef, name: SrvName } = EsModule; // Deconstruct the module and access the exports
|
|
338
|
+
}
|
|
333
339
|
}
|
|
334
340
|
```
|
|
335
341
|
|
|
@@ -353,4 +359,4 @@ channels:
|
|
|
353
359
|
|
|
354
360
|
You can also leave suggestions, feedback, and feature requests directly on GitHub by opening an issue in the repository.
|
|
355
361
|
|
|
356
|
-
Happy coding!
|
|
362
|
+
Happy coding!
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
type TeqFw_Di_Container_A_Composer = InstanceType<typeof import("./src/Container/A/Composer.js").default>;
|
|
2
|
+
type TeqFw_Di_Container_A_Composer_A_SpecParser = import("./src/Container/A/Composer/A/SpecParser.js").default;
|
|
3
|
+
type TeqFw_Di_Container_A_Parser_Chunk_Def = InstanceType<typeof import("./src/Container/A/Parser/Chunk/Def.js").default>;
|
|
4
|
+
type TeqFw_Di_Container_A_Parser_Chunk_V02X = InstanceType<typeof import("./src/Container/A/Parser/Chunk/V02X.js").default>;
|
|
5
|
+
type TeqFw_Di_Container_Parser = InstanceType<typeof import("./src/Container/Parser.js").default>;
|
|
6
|
+
type TeqFw_Di_Container_PostProcessor = InstanceType<typeof import("./src/Container/PostProcessor.js").default>;
|
|
7
|
+
type TeqFw_Di_Container_PreProcessor = InstanceType<typeof import("./src/Container/PreProcessor.js").default>;
|
|
8
|
+
type TeqFw_Di_Container_Resolver = InstanceType<typeof import("./src/Container/Resolver.js").default>;
|
|
9
|
+
|
|
10
|
+
declare global {
|
|
11
|
+
type TeqFw_Di_Api_Container_Parser = InstanceType<typeof import("./src/Api/Container/Parser.js").default>;
|
|
12
|
+
type TeqFw_Di_Api_Container_Parser_Chunk = InstanceType<typeof import("./src/Api/Container/Parser/Chunk.js").default>;
|
|
13
|
+
type TeqFw_Di_Api_Container_PostProcessor = InstanceType<typeof import("./src/Api/Container/PostProcessor.js").default>;
|
|
14
|
+
type TeqFw_Di_Api_Container_PostProcessor_Chunk = InstanceType<typeof import("./src/Api/Container/PostProcessor/Chunk.js").default>;
|
|
15
|
+
type TeqFw_Di_Api_Container_PreProcessor = InstanceType<typeof import("./src/Api/Container/PreProcessor.js").default>;
|
|
16
|
+
type TeqFw_Di_Api_Container_PreProcessor_Chunk = InstanceType<typeof import("./src/Api/Container/PreProcessor/Chunk.js").default>;
|
|
17
|
+
type TeqFw_Di_Api_Container_Resolver = InstanceType<typeof import("./src/Api/Container/Resolver.js").default>;
|
|
18
|
+
type TeqFw_Di_Container = InstanceType<typeof import("./src/Container.js").default>;
|
|
19
|
+
type TeqFw_Di_Defs = import("./src/Defs.js").default;
|
|
20
|
+
type TeqFw_Di_DepId = InstanceType<typeof import("./src/DepId.js").default>;
|
|
21
|
+
type TeqFw_Di_Pre_Replace = InstanceType<typeof import("./src/Pre/Replace.js").default>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {};
|