inwire 1.0.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/LICENSE +21 -0
- package/README.md +465 -0
- package/dist/index.cjs +590 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +387 -0
- package/dist/index.d.ts +387 -0
- package/dist/index.js +553 -0
- package/dist/index.js.map +1 -0
- package/llms-full.txt +523 -0
- package/llms.txt +53 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 inwire contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
# inwire
|
|
2
|
+
|
|
3
|
+
Zero-ceremony dependency injection for TypeScript. Full inference, no decorators, no tokens. Built-in introspection for AI tooling and debugging.
|
|
4
|
+
|
|
5
|
+
[](https://bundlephobia.com/package/inwire)
|
|
6
|
+
[](https://www.npmjs.com/package/inwire)
|
|
7
|
+
[](https://github.com)
|
|
8
|
+
[](https://github.com)
|
|
9
|
+
[](./vitest.config.ts)
|
|
10
|
+
[](https://www.typescriptlang.org/)
|
|
11
|
+
[](./LICENSE)
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm/pnpm i inwire
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { createContainer } from 'inwire';
|
|
23
|
+
|
|
24
|
+
const container = createContainer({
|
|
25
|
+
logger: () => new LoggerService(),
|
|
26
|
+
db: () => new Database(process.env.DB_URL!),
|
|
27
|
+
userRepo: (c): UserRepository => new PgUserRepo(c.db),
|
|
28
|
+
userService: (c) => new UserService(c.userRepo, c.logger),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
container.userService; // lazy, singleton, fully typed
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
That's it. Every dependency is a factory function `(container) => instance`. Access a property, get a singleton. TypeScript infers everything.
|
|
35
|
+
|
|
36
|
+
## ⚠️ Important: Async Lifecycle
|
|
37
|
+
|
|
38
|
+
Property access on the container is **synchronous**. If your service implements `onInit()` with an async function, it will be called but **not awaited** — errors are silently swallowed and your service may be used before it's ready.
|
|
39
|
+
|
|
40
|
+
**`preload()` is the only way to safely initialize async services.**
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
class Database implements OnInit {
|
|
44
|
+
async onInit() { await this.connect(); }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const container = createContainer({
|
|
48
|
+
db: () => new Database(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// ❌ BAD — onInit() fires but is NOT awaited, errors are lost
|
|
52
|
+
container.db;
|
|
53
|
+
|
|
54
|
+
// ✅ GOOD — onInit() is awaited, errors surface immediately
|
|
55
|
+
await container.preload('db');
|
|
56
|
+
container.db; // safe to use, fully initialized
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Why use a DI container?
|
|
60
|
+
|
|
61
|
+
Most JS/TS projects wire dependencies through direct imports. A DI container gives you three things imports don't:
|
|
62
|
+
|
|
63
|
+
- **Testability** — swap any dependency for a mock at creation time, no monkey-patching or `jest.mock`
|
|
64
|
+
- **Decoupling** — program against interfaces, not concrete imports; swap implementations without touching consumers
|
|
65
|
+
- **Visibility** — inspect the full dependency graph at runtime, catch scope mismatches, and monitor container health
|
|
66
|
+
|
|
67
|
+
## Features
|
|
68
|
+
|
|
69
|
+
### Lazy Singletons (default)
|
|
70
|
+
|
|
71
|
+
Factories run on first access and the result is cached forever. No eager init, no manual wiring.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
const container = createContainer({
|
|
75
|
+
db: () => new Database(process.env.DB_URL!),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
container.db; // creates Database
|
|
79
|
+
container.db; // same instance (cached)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Dependency Inversion
|
|
83
|
+
|
|
84
|
+
Annotate the return type to program against an interface:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
const container = createContainer({
|
|
88
|
+
userRepo: (c): UserRepository => new PgUserRepo(c.db),
|
|
89
|
+
// ^^^^^^^^^^^^^^^^^
|
|
90
|
+
// contract, not implementation
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
container.userRepo; // typed as UserRepository
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Modules = Spread Objects
|
|
97
|
+
|
|
98
|
+
Group related factories into plain objects and spread them:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const dbModule = {
|
|
102
|
+
db: () => new Database(process.env.DB_URL!),
|
|
103
|
+
redis: () => new Redis(process.env.REDIS_URL!),
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const serviceModule = {
|
|
107
|
+
userService: (c) => new UserService(c.db),
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const container = createContainer({
|
|
111
|
+
...dbModule,
|
|
112
|
+
...serviceModule,
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Test Overrides
|
|
117
|
+
|
|
118
|
+
Replace any dependency with a mock at container creation:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
const container = createContainer({
|
|
122
|
+
...productionDeps,
|
|
123
|
+
db: () => new InMemoryDatabase(), // override
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Scopes
|
|
128
|
+
|
|
129
|
+
Create child containers for request-level isolation. The child inherits all parent singletons and adds its own:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const container = createContainer({
|
|
133
|
+
logger: () => new LoggerService(),
|
|
134
|
+
db: () => new Database(),
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Per-request child container
|
|
138
|
+
const request = container.scope({
|
|
139
|
+
requestId: () => crypto.randomUUID(),
|
|
140
|
+
currentUser: () => getCurrentUser(),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
request.requestId; // scoped singleton (unique to this child)
|
|
144
|
+
request.logger; // inherited from parent
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Named Scopes
|
|
148
|
+
|
|
149
|
+
Pass an options object to name a scope for debugging and introspection:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const request = container.scope(
|
|
153
|
+
{ requestId: () => crypto.randomUUID() },
|
|
154
|
+
{ name: 'request-123' },
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
String(request); // "Scope(request-123) { requestId (pending) }"
|
|
158
|
+
request.inspect().name; // "request-123"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Transient
|
|
162
|
+
|
|
163
|
+
By default every dependency is a **singleton** (created once, cached forever). When you need a **fresh instance on every access**, wrap the factory with `transient()`:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { createContainer, transient } from 'inwire';
|
|
167
|
+
|
|
168
|
+
const container = createContainer({
|
|
169
|
+
logger: () => new LoggerService(), // singleton (default)
|
|
170
|
+
requestId: transient(() => crypto.randomUUID()), // new value every time
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
container.logger === container.logger; // true — same instance
|
|
174
|
+
container.requestId === container.requestId; // false — different every time
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Lifecycle (onInit / onDestroy / dispose)
|
|
178
|
+
|
|
179
|
+
Implement `onInit()` for post-creation setup and `onDestroy()` for cleanup:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import type { OnInit, OnDestroy } from 'inwire';
|
|
183
|
+
|
|
184
|
+
class Database implements OnInit, OnDestroy {
|
|
185
|
+
async onInit() { await this.connect(); }
|
|
186
|
+
async onDestroy() { await this.disconnect(); }
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const container = createContainer({
|
|
190
|
+
db: () => new Database(),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
container.db; // resolves + calls onInit()
|
|
194
|
+
await container.dispose(); // calls onDestroy() on all resolved instances (LIFO order)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Async `onInit()` is fire-and-forget during property access.** Because container property access is synchronous, any async `onInit()` runs without being awaited — errors won't surface and the service may not be ready. Use `preload()` to await async initialization. See [⚠️ Important: Async Lifecycle](#️-important-async-lifecycle) above.
|
|
198
|
+
|
|
199
|
+
### Extend
|
|
200
|
+
|
|
201
|
+
Add dependencies to an existing container without mutating it. Existing singletons are shared:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
const base = createContainer({
|
|
205
|
+
logger: () => new LoggerService(),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const extended = base.extend({
|
|
209
|
+
db: (c) => new Database(c.logger),
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
extended.logger; // shared singleton from base
|
|
213
|
+
extended.db; // new dependency
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
> **scope vs extend:** `scope()` creates a parent-child chain — the child delegates unresolved keys to the parent. `extend()` creates a flat container with a merged factory map and shared cache. Use `scope()` for per-request isolation, `extend()` for additive composition.
|
|
217
|
+
|
|
218
|
+
### Preload
|
|
219
|
+
|
|
220
|
+
Eagerly resolve specific dependencies at startup (warm-up):
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
const container = createContainer({
|
|
224
|
+
db: () => new Database(),
|
|
225
|
+
cache: () => new Redis(),
|
|
226
|
+
logger: () => new LoggerService(),
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
await container.preload('db', 'cache');
|
|
230
|
+
// db and cache are now resolved, logger is still lazy
|
|
231
|
+
|
|
232
|
+
await container.preload();
|
|
233
|
+
// resolve ALL dependencies at once
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**This is how you safely initialize async services.** See [⚠️ Important: Async Lifecycle](#️-important-async-lifecycle) above.
|
|
237
|
+
|
|
238
|
+
### Reset
|
|
239
|
+
|
|
240
|
+
Invalidate cached singletons to force re-creation on next access:
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
const container = createContainer({
|
|
244
|
+
db: () => new Database(),
|
|
245
|
+
cache: () => new Redis(),
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
container.db; // creates Database
|
|
249
|
+
container.reset('db');
|
|
250
|
+
container.db; // creates a NEW Database instance
|
|
251
|
+
|
|
252
|
+
// Other singletons are untouched
|
|
253
|
+
// Reset in a scope does not affect the parent
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Introspection
|
|
257
|
+
|
|
258
|
+
Built-in tools for debugging and AI analysis:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// Full dependency graph
|
|
262
|
+
container.inspect();
|
|
263
|
+
// { providers: { db: { key: 'db', resolved: true, deps: [], scope: 'singleton' }, ... } }
|
|
264
|
+
|
|
265
|
+
// Single provider details
|
|
266
|
+
container.describe('userService');
|
|
267
|
+
// { key: 'userService', resolved: true, deps: ['userRepo', 'logger'], scope: 'singleton' }
|
|
268
|
+
|
|
269
|
+
// Health check
|
|
270
|
+
container.health();
|
|
271
|
+
// { totalProviders: 4, resolved: ['db', 'logger'], unresolved: ['cache'], warnings: [] }
|
|
272
|
+
|
|
273
|
+
// Human-readable string
|
|
274
|
+
String(container);
|
|
275
|
+
// "Container { db -> [] (resolved), logger (pending) }"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Feed the graph to an LLM or diagnostic tool:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
const graph = JSON.stringify(container.inspect(), null, 2);
|
|
282
|
+
|
|
283
|
+
const response = await anthropic.messages.create({
|
|
284
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
285
|
+
messages: [{ role: 'user', content: `Analyze this dependency graph for issues:\n${graph}` }],
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Smart Errors
|
|
290
|
+
|
|
291
|
+
7 error types, each with `hint`, `details`, and actionable suggestions:
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
// Non-function value
|
|
295
|
+
createContainer({ apiKey: 'sk-123' });
|
|
296
|
+
// ContainerConfigError: 'apiKey' must be a factory function, got string.
|
|
297
|
+
// hint: "Wrap it: apiKey: () => 'sk-123'"
|
|
298
|
+
|
|
299
|
+
// Reserved key
|
|
300
|
+
createContainer({ inspect: () => 'foo' });
|
|
301
|
+
// ReservedKeyError: 'inspect' is a reserved container method.
|
|
302
|
+
// hint: "Rename this dependency, e.g. 'inspectService' or 'myInspect'."
|
|
303
|
+
|
|
304
|
+
// Missing dependency with fuzzy suggestion
|
|
305
|
+
container.userServce; // typo
|
|
306
|
+
// ProviderNotFoundError: Cannot resolve 'userServce': dependency 'userServce' not found.
|
|
307
|
+
// hint: "Did you mean 'userService'?"
|
|
308
|
+
|
|
309
|
+
// Circular dependency
|
|
310
|
+
// CircularDependencyError: Circular dependency detected while resolving 'authService'.
|
|
311
|
+
// Cycle: authService -> userService -> authService
|
|
312
|
+
|
|
313
|
+
// Undefined return
|
|
314
|
+
// UndefinedReturnError: Factory 'db' returned undefined.
|
|
315
|
+
// hint: "Did you forget a return statement?"
|
|
316
|
+
|
|
317
|
+
// Factory runtime error
|
|
318
|
+
// FactoryError: Factory 'db' threw an error: "Connection refused"
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Scope Mismatch Detection
|
|
322
|
+
|
|
323
|
+
Warns when a singleton depends on a transient (the transient value gets frozen inside the singleton):
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
const container = createContainer({
|
|
327
|
+
requestId: transient(() => crypto.randomUUID()),
|
|
328
|
+
userService: (c) => new UserService(c.requestId), // singleton depends on transient!
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
container.health().warnings;
|
|
332
|
+
// [{ type: 'scope_mismatch', message: "Singleton 'userService' depends on transient 'requestId'." }]
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Fuzzy Key Suggestion
|
|
336
|
+
|
|
337
|
+
When a key is not found, Levenshtein-based matching suggests the closest registered key (>= 50% similarity):
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
container.userServce;
|
|
341
|
+
// ProviderNotFoundError: Did you mean 'userService'?
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Duplicate Key Detection
|
|
345
|
+
|
|
346
|
+
Detect accidental key collisions when spreading modules:
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
import { detectDuplicateKeys } from 'inwire';
|
|
350
|
+
|
|
351
|
+
const duplicates = detectDuplicateKeys(authModule, userModule, dbModule);
|
|
352
|
+
// ['logger'] — appears in more than one module
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Comparison
|
|
356
|
+
|
|
357
|
+
| Feature | inwire | awilix | tsyringe | Inversify | NestJS |
|
|
358
|
+
|---|---|---|---|---|---|
|
|
359
|
+
| Decorators required | No | No | Yes | Yes | Yes |
|
|
360
|
+
| Tokens/symbols | No | No | Yes | Yes | Yes |
|
|
361
|
+
| Full TS inference | Yes | No (manual Cradle) | Partial | Partial | Partial |
|
|
362
|
+
| Lazy singletons | Default | Default | Manual | Manual | Manual |
|
|
363
|
+
| Scoped containers | `.scope()` | `.createScope()` | `.createChildContainer()` | `.createChild()` | Module scope |
|
|
364
|
+
| Lifecycle hooks | `onInit`/`onDestroy` | `dispose()` | `beforeResolution`/`afterResolution` | No | `onModuleInit`/`onModuleDestroy` |
|
|
365
|
+
| Introspection | Built-in JSON graph | `.registrations` | `isRegistered()` | No | DevTools |
|
|
366
|
+
| Smart errors | 7 types + hints | Resolution chain | Generic | Generic | Generic |
|
|
367
|
+
| Bundle size (gzip) | ~4.7 KB | ~3.6 KB | ~5.6 KB (+reflect-metadata) | ~50 KB | Framework |
|
|
368
|
+
| Runtime deps | 0 | 1 | 1 (+reflect-metadata) | 2 | Many |
|
|
369
|
+
|
|
370
|
+
## Architecture
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
src/
|
|
374
|
+
index.ts # barrel export
|
|
375
|
+
domain/
|
|
376
|
+
types.ts # interfaces, types, RESERVED_KEYS
|
|
377
|
+
errors.ts # 7 error classes + ScopeMismatchWarning
|
|
378
|
+
lifecycle.ts # OnInit / OnDestroy interfaces
|
|
379
|
+
validation.ts # Validator, detectDuplicateKeys, Levenshtein
|
|
380
|
+
infrastructure/
|
|
381
|
+
proxy-handler.ts # Resolver (Proxy handler, cache, cycle detection)
|
|
382
|
+
transient.ts # transient() marker
|
|
383
|
+
application/
|
|
384
|
+
create-container.ts # createContainer, buildContainerProxy
|
|
385
|
+
scope.ts # createScope (child containers)
|
|
386
|
+
introspection.ts # inspect, describe, health, toString
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## LLM / AI Integration
|
|
390
|
+
|
|
391
|
+
This package ships with [llms.txt](https://llmstxt.org/) files for AI-assisted development:
|
|
392
|
+
|
|
393
|
+
- **`llms.txt`** — Concise index following the llms.txt standard
|
|
394
|
+
- **`llms-full.txt`** — Complete API reference optimized for LLM context windows
|
|
395
|
+
|
|
396
|
+
Use them to feed inwire documentation to any LLM or AI coding tool:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
cat node_modules/inwire/llms-full.txt
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Compatible with [Context7](https://context7.com/) and any tool that supports the llms.txt standard.
|
|
403
|
+
|
|
404
|
+
At runtime, `.inspect()` returns the full dependency graph as serializable JSON — pipe it directly into an LLM for architecture analysis:
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
const graph = JSON.stringify(container.inspect(), null, 2);
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## API Reference
|
|
411
|
+
|
|
412
|
+
### Functions
|
|
413
|
+
|
|
414
|
+
| Export | Description |
|
|
415
|
+
|---|---|
|
|
416
|
+
| `createContainer(defs)` | Creates a DI container from factory functions |
|
|
417
|
+
| `transient(factory)` | Marks a factory as transient (new instance per access) |
|
|
418
|
+
| `detectDuplicateKeys(...modules)` | Detects duplicate keys across spread modules |
|
|
419
|
+
|
|
420
|
+
### Container Methods
|
|
421
|
+
|
|
422
|
+
| Method | Description |
|
|
423
|
+
|---|---|
|
|
424
|
+
| `container.scope(extra, options?)` | Creates a child container with additional deps. Pass `{ name }` for debugging |
|
|
425
|
+
| `container.extend(extra)` | Returns a new container with additional deps (shared cache) |
|
|
426
|
+
| `container.preload(...keys)` | Eagerly resolves specific dependencies, or all if no keys given |
|
|
427
|
+
| `container.reset(...keys)` | Invalidates cached singletons, forcing re-creation on next access |
|
|
428
|
+
| `container.inspect()` | Returns the full dependency graph |
|
|
429
|
+
| `container.describe(key)` | Returns info about a single provider |
|
|
430
|
+
| `container.health()` | Returns health status and warnings |
|
|
431
|
+
| `container.dispose()` | Calls `onDestroy()` on all resolved instances |
|
|
432
|
+
|
|
433
|
+
### Types
|
|
434
|
+
|
|
435
|
+
| Export | Description |
|
|
436
|
+
|---|---|
|
|
437
|
+
| `Container<T>` | Full container type (resolved deps + methods) |
|
|
438
|
+
| `DepsDefinition` | `Record<string, Factory>` |
|
|
439
|
+
| `Factory<T>` | `(container) => T` |
|
|
440
|
+
| `ResolvedDeps<T>` | Extracts return types from a `DepsDefinition` |
|
|
441
|
+
| `OnInit` | Interface with `onInit(): void \| Promise<void>` |
|
|
442
|
+
| `OnDestroy` | Interface with `onDestroy(): void \| Promise<void>` |
|
|
443
|
+
| `ContainerGraph` | Return type of `inspect()` |
|
|
444
|
+
| `ContainerHealth` | Return type of `health()` |
|
|
445
|
+
| `ContainerWarning` | Warning object (`scope_mismatch` \| `duplicate_key`) |
|
|
446
|
+
| `ProviderInfo` | Return type of `describe()` |
|
|
447
|
+
| `IContainer<T>` | Container methods interface |
|
|
448
|
+
| `ScopeOptions` | Options for `scope()` (`{ name?: string }`) |
|
|
449
|
+
|
|
450
|
+
### Errors
|
|
451
|
+
|
|
452
|
+
| Export | Thrown when |
|
|
453
|
+
|---|---|
|
|
454
|
+
| `ContainerError` | Base class for all errors |
|
|
455
|
+
| `ContainerConfigError` | Non-function value in deps definition |
|
|
456
|
+
| `ReservedKeyError` | Reserved key used as dependency name |
|
|
457
|
+
| `ProviderNotFoundError` | Dependency not found during resolution |
|
|
458
|
+
| `CircularDependencyError` | Circular dependency detected |
|
|
459
|
+
| `UndefinedReturnError` | Factory returned `undefined` |
|
|
460
|
+
| `FactoryError` | Factory threw during resolution |
|
|
461
|
+
| `ScopeMismatchWarning` | Singleton depends on transient |
|
|
462
|
+
|
|
463
|
+
## License
|
|
464
|
+
|
|
465
|
+
MIT
|