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/llms-full.txt ADDED
@@ -0,0 +1,523 @@
1
+ # inwire — Complete API Reference
2
+
3
+ > Zero-ceremony dependency injection for TypeScript. Full inference, no decorators, no tokens.
4
+ > Proxy-based lazy singleton resolution. ~4.7KB gzipped, 0 runtime deps.
5
+
6
+ Install: `npm i inwire`
7
+ License: MIT
8
+ Exports: ESM + CJS with full .d.ts
9
+
10
+ ## How It Works
11
+
12
+ The container is a Proxy. Each dependency is defined as a factory function `(container) => instance`. When you access a property on the container, the Proxy intercepts it and delegates to the Resolver. The Resolver:
13
+
14
+ 1. Checks the singleton cache — if already resolved, returns the cached instance
15
+ 2. Detects circular dependencies via a `resolving` Set
16
+ 3. Creates a tracking Proxy to record which other deps the factory accesses (builds the dep graph)
17
+ 4. Calls the factory function with the tracking proxy
18
+ 5. Caches the result (unless marked transient)
19
+ 6. Calls `onInit()` if the instance implements it (fire-and-forget, not awaited)
20
+
21
+ TypeScript infers the full container type from the factory definitions — `Container<ResolvedDeps<T>>` maps each key to the return type of its factory.
22
+
23
+ ## createContainer(defs)
24
+
25
+ ```typescript
26
+ function createContainer<T extends DepsDefinition>(defs: T): Container<ResolvedDeps<T>>
27
+ ```
28
+
29
+ Creates a DI container from an object of factory functions. Each factory receives the container as its argument and returns an instance. Dependencies are resolved lazily on first property access and cached as singletons by default.
30
+
31
+ ```typescript
32
+ import { createContainer } from 'inwire';
33
+
34
+ const container = createContainer({
35
+ logger: () => new LoggerService(),
36
+ db: () => new Database(process.env.DB_URL!),
37
+ userRepo: (c): UserRepository => new PgUserRepo(c.db),
38
+ userService: (c) => new UserService(c.userRepo, c.logger),
39
+ });
40
+
41
+ container.userService; // lazy, singleton, fully typed
42
+ ```
43
+
44
+ Annotate the return type to program against an interface (dependency inversion):
45
+
46
+ ```typescript
47
+ const container = createContainer({
48
+ userRepo: (c): UserRepository => new PgUserRepo(c.db),
49
+ // ^^^^^^^^^^^^^^^^ contract, not implementation
50
+ });
51
+ container.userRepo; // typed as UserRepository
52
+ ```
53
+
54
+ Validation runs at creation time: non-function values throw `ContainerConfigError`, reserved keys throw `ReservedKeyError`.
55
+
56
+ ## transient(factory)
57
+
58
+ ```typescript
59
+ function transient<T>(factory: Factory<T>): Factory<T>
60
+ ```
61
+
62
+ Marks a factory as transient — a new instance is created on every property access, bypassing the singleton cache. Internally attaches a `Symbol.for('inwire:transient')` marker.
63
+
64
+ ```typescript
65
+ import { createContainer, transient } from 'inwire';
66
+
67
+ const container = createContainer({
68
+ logger: () => new LoggerService(), // singleton (default)
69
+ requestId: transient(() => crypto.randomUUID()), // new value every time
70
+ });
71
+
72
+ container.logger === container.logger; // true — same instance
73
+ container.requestId === container.requestId; // false — different every time
74
+ ```
75
+
76
+ ## container.scope(extra, options?)
77
+
78
+ ```typescript
79
+ scope<E extends DepsDefinition>(extra: E, options?: ScopeOptions): Container<T & ResolvedDeps<E>>
80
+ ```
81
+
82
+ Creates a child container with additional dependencies. The child inherits all parent singletons via a parent Resolver chain. Scoped singletons are independent — they are cached in the child's own cache.
83
+
84
+ ```typescript
85
+ const app = createContainer({
86
+ logger: () => new LoggerService(),
87
+ db: () => new Database(),
88
+ });
89
+
90
+ const request = app.scope({
91
+ requestId: () => crypto.randomUUID(),
92
+ currentUser: () => getCurrentUser(),
93
+ });
94
+
95
+ request.requestId; // scoped singleton (unique to this child)
96
+ request.logger; // inherited from parent (same instance)
97
+ ```
98
+
99
+ Use `scope()` for request-level isolation where child deps should not pollute the parent.
100
+
101
+ ### Named Scopes
102
+
103
+ Pass `{ name }` for debugging and introspection:
104
+
105
+ ```typescript
106
+ const request = app.scope(
107
+ { requestId: () => crypto.randomUUID() },
108
+ { name: 'request-123' },
109
+ );
110
+
111
+ String(request); // "Scope(request-123) { requestId (pending) }"
112
+ request.inspect().name; // "request-123"
113
+ ```
114
+
115
+ Named scopes show their name in `toString()` output (`Scope(name) { ... }` instead of `Container { ... }`) and include the name in `inspect()` results.
116
+
117
+ ## container.extend(extra)
118
+
119
+ ```typescript
120
+ extend<E extends DepsDefinition>(extra: E): Container<T & ResolvedDeps<E>>
121
+ ```
122
+
123
+ Returns a new container with additional dependencies. Unlike `scope()`, the existing singleton cache is **shared** (copied) — already-resolved singletons from the original container are available without re-resolution.
124
+
125
+ ```typescript
126
+ const base = createContainer({
127
+ logger: () => new LoggerService(),
128
+ });
129
+
130
+ const extended = base.extend({
131
+ db: (c) => new Database(c.logger),
132
+ });
133
+
134
+ extended.logger; // shared singleton from base
135
+ extended.db; // new dependency
136
+ ```
137
+
138
+ **scope vs extend**: `scope()` creates a parent-child chain (child delegates to parent for unknown keys). `extend()` creates a flat merged container with a shared cache snapshot. Use `scope()` for request isolation, `extend()` for composition.
139
+
140
+ **GOTCHA**: Because `extend()` shares the cache, singletons resolved in the original container will be the same objects in the extended container. New singletons resolved in the extended container do NOT propagate back to the original.
141
+
142
+ ## container.preload(...keys)
143
+
144
+ ```typescript
145
+ preload(...keys: (keyof T)[]): Promise<void>
146
+ ```
147
+
148
+ Eagerly resolves specific dependencies (warm-up). Call with specific keys to resolve only those, or **without arguments to resolve all dependencies**.
149
+
150
+ ```typescript
151
+ const container = createContainer({
152
+ db: () => new Database(),
153
+ cache: () => new Redis(),
154
+ logger: () => new LoggerService(),
155
+ });
156
+
157
+ await container.preload('db', 'cache');
158
+ // db and cache are now resolved, logger is still lazy
159
+
160
+ await container.preload();
161
+ // resolve ALL dependencies at once
162
+ ```
163
+
164
+ **GOTCHA — CRITICAL**: `preload()` is the **only** way to properly await async `onInit()` hooks. During normal property access, `onInit()` is called but NOT awaited (fire-and-forget, errors swallowed). If your service has async initialization (e.g. database connection), you MUST use `preload()` to surface errors.
165
+
166
+ ## container.reset(...keys)
167
+
168
+ ```typescript
169
+ reset(...keys: (keyof T)[]): void
170
+ ```
171
+
172
+ Invalidates cached singletons, forcing re-creation on next access. The next property access will re-execute the factory and call `onInit()` again if implemented.
173
+
174
+ ```typescript
175
+ const container = createContainer({
176
+ db: () => new Database(),
177
+ });
178
+
179
+ container.db; // creates Database
180
+ container.reset('db');
181
+ container.db; // creates a NEW Database instance
182
+ ```
183
+
184
+ `reset()` does not affect parent scopes — it only clears the cache of the container it's called on. Resetting an unresolved key is a silent no-op.
185
+
186
+ ## container.inspect()
187
+
188
+ ```typescript
189
+ inspect(): ContainerGraph
190
+ ```
191
+
192
+ Returns the full dependency graph as a serializable JSON object. Named scopes include a `name` field.
193
+
194
+ ```typescript
195
+ interface ContainerGraph {
196
+ name?: string;
197
+ providers: Record<string, ProviderInfo>;
198
+ }
199
+
200
+ interface ProviderInfo {
201
+ key: string;
202
+ resolved: boolean;
203
+ deps: string[];
204
+ scope: 'singleton' | 'transient';
205
+ }
206
+ ```
207
+
208
+ ```typescript
209
+ container.inspect();
210
+ // {
211
+ // providers: {
212
+ // db: { key: 'db', resolved: true, deps: [], scope: 'singleton' },
213
+ // userRepo: { key: 'userRepo', resolved: true, deps: ['db'], scope: 'singleton' },
214
+ // logger: { key: 'logger', resolved: false, deps: [], scope: 'singleton' }
215
+ // }
216
+ // }
217
+ ```
218
+
219
+ **AI usage**: Pipe `JSON.stringify(container.inspect(), null, 2)` into an LLM to analyze the architecture, detect issues, or generate documentation from the live dependency graph.
220
+
221
+ ## container.describe(key)
222
+
223
+ ```typescript
224
+ describe(key: keyof T): ProviderInfo
225
+ ```
226
+
227
+ Returns detailed information about a single provider.
228
+
229
+ ```typescript
230
+ container.describe('userService');
231
+ // { key: 'userService', resolved: true, deps: ['userRepo', 'logger'], scope: 'singleton' }
232
+ ```
233
+
234
+ If the key is not registered, returns `{ key, resolved: false, deps: [], scope: 'singleton' }`.
235
+
236
+ ## container.health()
237
+
238
+ ```typescript
239
+ health(): ContainerHealth
240
+ ```
241
+
242
+ Returns container health status and warnings.
243
+
244
+ ```typescript
245
+ interface ContainerHealth {
246
+ totalProviders: number;
247
+ resolved: string[];
248
+ unresolved: string[];
249
+ warnings: ContainerWarning[];
250
+ }
251
+
252
+ interface ContainerWarning {
253
+ type: 'scope_mismatch' | 'duplicate_key';
254
+ message: string;
255
+ details: Record<string, unknown>;
256
+ }
257
+ ```
258
+
259
+ ```typescript
260
+ container.health();
261
+ // {
262
+ // totalProviders: 4,
263
+ // resolved: ['db', 'logger'],
264
+ // unresolved: ['cache', 'userService'],
265
+ // warnings: [
266
+ // { type: 'scope_mismatch', message: "Singleton 'userService' depends on transient 'requestId'.", details: { singleton: 'userService', transient: 'requestId' } }
267
+ // ]
268
+ // }
269
+ ```
270
+
271
+ ## container.dispose()
272
+
273
+ ```typescript
274
+ dispose(): Promise<void>
275
+ ```
276
+
277
+ Disposes the container. Calls `onDestroy()` on all resolved instances that implement it, in **reverse resolution order** (LIFO). Clears the singleton cache after disposal.
278
+
279
+ ```typescript
280
+ const container = createContainer({
281
+ db: () => new Database(), // resolved first
282
+ cache: () => new Redis(), // resolved second
283
+ });
284
+
285
+ container.db;
286
+ container.cache;
287
+ await container.dispose(); // calls cache.onDestroy() then db.onDestroy()
288
+ ```
289
+
290
+ **GOTCHA**: After `dispose()`, accessing dependencies will re-resolve them (cache is cleared). This can cause unexpected behavior if you continue using the container after disposal.
291
+
292
+ ## detectDuplicateKeys(...modules)
293
+
294
+ ```typescript
295
+ function detectDuplicateKeys(...modules: Record<string, unknown>[]): string[]
296
+ ```
297
+
298
+ Detects duplicate keys across multiple module objects. Returns an array of keys that appear in more than one module. Use this before spreading modules into `createContainer()` to catch accidental collisions.
299
+
300
+ ```typescript
301
+ import { detectDuplicateKeys } from 'inwire';
302
+
303
+ const authModule = { logger: () => new AuthLogger(), auth: () => new AuthService() };
304
+ const userModule = { logger: () => new UserLogger(), user: () => new UserService() };
305
+
306
+ detectDuplicateKeys(authModule, userModule);
307
+ // ['logger'] — appears in both modules
308
+ ```
309
+
310
+ ## String(container)
311
+
312
+ Containers implement `toString()` for human-readable output:
313
+
314
+ ```typescript
315
+ String(container);
316
+ // "Container { db -> [] (resolved), logger (pending) }"
317
+ ```
318
+
319
+ Also works with `Symbol.toPrimitive` and `Symbol.toStringTag`.
320
+
321
+ ## Lifecycle Hooks: OnInit / OnDestroy
322
+
323
+ ```typescript
324
+ interface OnInit {
325
+ onInit(): void | Promise<void>;
326
+ }
327
+
328
+ interface OnDestroy {
329
+ onDestroy(): void | Promise<void>;
330
+ }
331
+ ```
332
+
333
+ Lifecycle hooks are **duck-typed** — no need to explicitly implement the interface. Any object with an `onInit` or `onDestroy` method will be detected automatically.
334
+
335
+ ```typescript
336
+ import type { OnInit, OnDestroy } from 'inwire';
337
+
338
+ class Database implements OnInit, OnDestroy {
339
+ async onInit() { await this.connect(); }
340
+ async onDestroy() { await this.disconnect(); }
341
+ }
342
+
343
+ const container = createContainer({
344
+ db: () => new Database(),
345
+ });
346
+
347
+ // Use preload to properly await async onInit:
348
+ await container.preload('db');
349
+
350
+ // Later, dispose calls onDestroy in LIFO order:
351
+ await container.dispose();
352
+ ```
353
+
354
+ **GOTCHA — CRITICAL**: During normal property access (`container.db`), `onInit()` IS called but NOT awaited. It runs as fire-and-forget. If `onInit()` returns a Promise:
355
+ - The Promise is caught silently (errors are swallowed)
356
+ - The instance is returned immediately, potentially before initialization completes
357
+ - Use `await container.preload('db')` to ensure `onInit()` completes and errors surface
358
+
359
+ This is by design: property access in JavaScript is synchronous, so the Proxy cannot await.
360
+
361
+ ## Modules Pattern
362
+
363
+ Group related factories into plain objects and spread them into `createContainer()`:
364
+
365
+ ```typescript
366
+ const dbModule = {
367
+ db: () => new Database(process.env.DB_URL!),
368
+ redis: () => new Redis(process.env.REDIS_URL!),
369
+ };
370
+
371
+ const serviceModule = {
372
+ userService: (c) => new UserService(c.db),
373
+ };
374
+
375
+ const container = createContainer({
376
+ ...dbModule,
377
+ ...serviceModule,
378
+ });
379
+ ```
380
+
381
+ Use `satisfies DepsDefinition` on module objects for type checking without losing literal types:
382
+
383
+ ```typescript
384
+ import type { DepsDefinition } from 'inwire';
385
+
386
+ const dbModule = {
387
+ db: () => new Database(),
388
+ } satisfies DepsDefinition;
389
+ ```
390
+
391
+ ## Test Overrides Pattern
392
+
393
+ Replace any dependency with a mock by spreading production deps and overriding:
394
+
395
+ ```typescript
396
+ const container = createContainer({
397
+ ...productionDeps,
398
+ db: () => new InMemoryDatabase(), // override
399
+ });
400
+ ```
401
+
402
+ No special test API needed — last spread wins.
403
+
404
+ ## Type Utilities
405
+
406
+ ```typescript
407
+ type Factory<T = any> = (container: any) => T;
408
+ type DepsDefinition = Record<string, Factory>;
409
+ type ResolvedDeps<T extends DepsDefinition> = { readonly [K in keyof T]: ReturnType<T[K]> };
410
+ type Container<T extends Record<string, any> = Record<string, any>> = T & IContainer<T>;
411
+ interface ScopeOptions { name?: string }
412
+ ```
413
+
414
+ ## Error Reference
415
+
416
+ All errors extend `ContainerError`, which extends `Error`. Every error has:
417
+ - `hint: string` — actionable fix suggestion
418
+ - `details: Record<string, unknown>` — structured context for programmatic consumption
419
+
420
+ ### ContainerConfigError
421
+
422
+ Thrown when a non-function value is passed in the deps definition.
423
+
424
+ ```
425
+ 'apiKey' must be a factory function, got string.
426
+ hint: "Wrap it: apiKey: () => 'sk-123'"
427
+ ```
428
+
429
+ Constructor: `new ContainerConfigError(key: string, actualType: string)`
430
+ Details: `{ key, actualType }`
431
+
432
+ ### ReservedKeyError
433
+
434
+ Thrown when a reserved container method name is used as a dependency key. Reserved keys: `scope`, `extend`, `preload`, `reset`, `inspect`, `describe`, `health`, `dispose`, `toString`.
435
+
436
+ ```
437
+ 'inspect' is a reserved container method.
438
+ hint: "Rename this dependency, e.g. 'inspectService' or 'myInspect'."
439
+ ```
440
+
441
+ Constructor: `new ReservedKeyError(key: string, reserved: readonly string[])`
442
+ Details: `{ key, reserved }`
443
+
444
+ ### ProviderNotFoundError
445
+
446
+ Thrown when a dependency cannot be found during resolution. Includes Levenshtein-based fuzzy suggestion if a similar key exists (>= 50% similarity).
447
+
448
+ ```
449
+ Cannot resolve 'userServce': dependency 'userServce' not found.
450
+ Registered keys: [userService, logger, db]
451
+ Did you mean 'userService'?
452
+ hint: "Did you mean 'userService'? Or add 'userServce' to your container: ..."
453
+ ```
454
+
455
+ Constructor: `new ProviderNotFoundError(key: string, chain: string[], registered: string[], suggestion?: string)`
456
+ Details: `{ key, chain, registered, suggestion }`
457
+
458
+ ### CircularDependencyError
459
+
460
+ Thrown when a circular dependency is detected in the resolution chain.
461
+
462
+ ```
463
+ Circular dependency detected while resolving 'authService'.
464
+ Cycle: authService -> userService -> authService
465
+ ```
466
+
467
+ Constructor: `new CircularDependencyError(key: string, chain: string[])`
468
+ Details: `{ key, chain, cycle }`
469
+
470
+ ### UndefinedReturnError
471
+
472
+ Thrown when a factory function returns `undefined`.
473
+
474
+ ```
475
+ Factory 'db' returned undefined.
476
+ hint: "Your factory function returned undefined. Did you forget a return statement?"
477
+ ```
478
+
479
+ Constructor: `new UndefinedReturnError(key: string, chain: string[])`
480
+ Details: `{ key, chain }`
481
+
482
+ ### FactoryError
483
+
484
+ Thrown when a factory function throws an error during resolution. Wraps the original error.
485
+
486
+ ```
487
+ Factory 'db' threw an error: "Connection refused"
488
+ hint: "Check the factory function for 'db'. The error occurred during instantiation."
489
+ ```
490
+
491
+ Constructor: `new FactoryError(key: string, chain: string[], originalError: unknown)`
492
+ Details: `{ key, chain, originalError }` (originalError is the message string)
493
+ Additional property: `originalError: unknown` (the raw error object)
494
+
495
+ ### ScopeMismatchWarning
496
+
497
+ Not an error — a warning emitted when a singleton depends on a transient. Surfaced via `container.health().warnings`.
498
+
499
+ ```
500
+ Singleton 'userService' depends on transient 'requestId'.
501
+ hint: "The transient value was resolved once and is now frozen inside the singleton. ..."
502
+ ```
503
+
504
+ Constructor: `new ScopeMismatchWarning(singletonKey: string, transientKey: string)`
505
+ Properties: `type: 'scope_mismatch'`, `message`, `hint`, `details: { singleton, transient }`
506
+
507
+ ## Gotchas and Common Pitfalls
508
+
509
+ 1. **Async onInit is fire-and-forget**: `onInit()` is called during property access but NOT awaited. Errors are swallowed. Use `await container.preload('key')` to properly await async initialization.
510
+
511
+ 2. **Scope mismatch**: A singleton depending on a transient freezes the transient value. The singleton will always see the first resolved value. Check `container.health().warnings` for `scope_mismatch` warnings.
512
+
513
+ 3. **Reserved keys**: `scope`, `extend`, `preload`, `reset`, `inspect`, `describe`, `health`, `dispose`, `toString` cannot be used as dependency keys. Using them throws `ReservedKeyError`.
514
+
515
+ 4. **Undefined return**: Factories that return `undefined` (missing return statement, void function) throw `UndefinedReturnError`. Every factory must return a value.
516
+
517
+ 5. **LIFO dispose order**: `dispose()` calls `onDestroy()` in reverse resolution order. If `db` was resolved before `cache`, `cache.onDestroy()` runs first.
518
+
519
+ 6. **extend() shares cache**: `extend()` copies the singleton cache. Already-resolved singletons are shared. New resolutions in the extended container do NOT propagate back to the original.
520
+
521
+ 7. **scope() vs extend()**: `scope()` creates a parent-child chain (child delegates unknown keys to parent). `extend()` creates a flat merged container. Use `scope()` for request-level isolation, `extend()` for additive composition.
522
+
523
+ 8. **reset() is scope-local**: `reset()` only clears the cache of the container it's called on. In a scope, resetting a key does not affect the parent container's cache.
package/llms.txt ADDED
@@ -0,0 +1,53 @@
1
+ # inwire
2
+
3
+ > Zero-ceremony dependency injection for TypeScript. Full inference, no decorators, no tokens.
4
+ > Proxy-based lazy singleton resolution. ~4.7KB gzipped, 0 runtime deps.
5
+
6
+ inwire uses factory functions `(container) => instance` as the single abstraction. Property access on the container triggers lazy resolution through a Proxy. Instances are cached as singletons by default. TypeScript infers the full container type from the factory definitions — no manual type wiring. Built-in introspection methods return serializable JSON, making the dependency graph directly consumable by LLMs and AI tooling.
7
+
8
+ ## Core API
9
+
10
+ - `createContainer(defs)` — Creates a DI container from an object of factory functions. Returns a fully-typed Proxy.
11
+ - `transient(factory)` — Marks a factory as transient (new instance on every access, no caching).
12
+ - `detectDuplicateKeys(...modules)` — Detects keys that appear in more than one module object.
13
+
14
+ ## Container Methods
15
+
16
+ - `.scope(extra, options?)` — Creates a child container with additional deps. Child inherits parent singletons. Pass `{ name }` for debugging/introspection.
17
+ - `.extend(extra)` — Returns a new container with merged factories. Shares existing singleton cache.
18
+ - `.preload(...keys)` — Eagerly resolves specific dependencies, or all if no keys given. Only way to await async `onInit()`.
19
+ - `.reset(...keys)` — Invalidates cached singletons, forcing re-creation on next access. Does not affect parent scopes.
20
+ - `.inspect()` — Returns the full dependency graph as `ContainerGraph` (serializable JSON).
21
+ - `.describe(key)` — Returns `ProviderInfo` for a single provider.
22
+ - `.health()` — Returns `ContainerHealth` with warnings (e.g. scope mismatches).
23
+ - `.dispose()` — Calls `onDestroy()` on all resolved instances in LIFO order.
24
+
25
+ ## Types
26
+
27
+ - `Container<T>` — Resolved deps + container methods
28
+ - `Factory<T>` — `(container: any) => T`
29
+ - `DepsDefinition` — `Record<string, Factory>`
30
+ - `ResolvedDeps<T>` — Maps each key to its factory's return type
31
+ - `OnInit` — Interface: `onInit(): void | Promise<void>`
32
+ - `OnDestroy` — Interface: `onDestroy(): void | Promise<void>`
33
+ - `ScopeOptions` — `{ name?: string }` — options for `scope()`
34
+ - `ContainerGraph` — `{ name?: string, providers: Record<string, ProviderInfo> }`
35
+ - `ContainerHealth` — `{ totalProviders, resolved, unresolved, warnings }`
36
+ - `ContainerWarning` — `{ type: 'scope_mismatch' | 'duplicate_key', message, details }`
37
+ - `ProviderInfo` — `{ key, resolved, deps, scope: 'singleton' | 'transient' }`
38
+
39
+ ## Errors
40
+
41
+ All errors extend `ContainerError` and include `hint` (actionable fix) and `details` (structured context).
42
+
43
+ - `ContainerConfigError` — Non-function value in deps definition
44
+ - `ReservedKeyError` — Reserved container method name used as dependency key (`reset` included)
45
+ - `ProviderNotFoundError` — Dependency not found during resolution (includes fuzzy suggestion)
46
+ - `CircularDependencyError` — Circular dependency detected in resolution chain
47
+ - `UndefinedReturnError` — Factory returned `undefined`
48
+ - `FactoryError` — Factory threw an error during resolution (wraps original error)
49
+ - `ScopeMismatchWarning` — Singleton depends on transient (warning, not error)
50
+
51
+ ## Full Documentation
52
+
53
+ See `llms-full.txt` for complete API reference with signatures, examples, and gotchas.
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "inwire",
3
+ "version": "1.0.0",
4
+ "description": "Zero-ceremony dependency injection for TypeScript. Full inference, no decorators, no tokens. Built-in introspection for AI tooling.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "llms.txt",
24
+ "llms-full.txt"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsup",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "test:coverage": "vitest run --coverage",
31
+ "lint": "tsc --noEmit",
32
+ "prepublishOnly": "npm run build"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "keywords": [
38
+ "dependency-injection",
39
+ "di",
40
+ "ioc",
41
+ "typescript",
42
+ "proxy",
43
+ "ai-first",
44
+ "clean-architecture"
45
+ ],
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/axelhamil/inwire.git"
49
+ },
50
+ "homepage": "https://github.com/axelhamil/inwire#readme",
51
+ "bugs": {
52
+ "url": "https://github.com/axelhamil/inwire/issues"
53
+ },
54
+ "license": "MIT",
55
+ "devDependencies": {
56
+ "@semantic-release/changelog": "^6.0.0",
57
+ "@semantic-release/git": "^10.0.0",
58
+ "@vitest/coverage-v8": "^3.2.4",
59
+ "semantic-release": "^24.0.0",
60
+ "tsup": "^8.0.0",
61
+ "typescript": "^5.4.0",
62
+ "vitest": "^3.0.0"
63
+ }
64
+ }