inwire 2.1.7 → 2.2.1
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/README.md +66 -23
- package/dist/index.d.mts +61 -4
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -218,46 +218,84 @@ extended.db; // new dependency
|
|
|
218
218
|
|
|
219
219
|
### Modules
|
|
220
220
|
|
|
221
|
-
|
|
221
|
+
Split a large container into reusable modules. Each module declares its prerequisites locally — no shared `AppDeps` interface, no manual generics.
|
|
222
222
|
|
|
223
|
-
####
|
|
223
|
+
#### `defineModule()` — recommended pattern
|
|
224
|
+
|
|
225
|
+
`defineModule<Prerequisites>()(builder => builder.add(...))` infers the module's output from the chained `.add()` calls. Prerequisites are explicit and local to the module file.
|
|
224
226
|
|
|
225
227
|
```typescript
|
|
226
|
-
import { container,
|
|
228
|
+
import { container, defineModule } from 'inwire';
|
|
227
229
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
.add('db', (c) => new Database(c.
|
|
233
|
-
.add('cache', (c) => new Redis(c.
|
|
234
|
-
|
|
230
|
+
interface Logger { log: (msg: string) => void }
|
|
231
|
+
|
|
232
|
+
const dbModule = defineModule<{ logger: Logger }>()((b) =>
|
|
233
|
+
b
|
|
234
|
+
.add('db', (c) => new Database(c.logger))
|
|
235
|
+
.add('cache', (c) => new Redis(c.logger)),
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
const userModule = defineModule<{ db: Database; logger: Logger }>()((b) =>
|
|
239
|
+
b.add('userService', (c) => new UserService(c.db, c.logger)),
|
|
240
|
+
);
|
|
235
241
|
|
|
236
242
|
const app = container()
|
|
237
|
-
.add('
|
|
238
|
-
.add('logger', () => new Logger())
|
|
243
|
+
.add('logger', (): Logger => new ConsoleLogger())
|
|
239
244
|
.addModule(dbModule)
|
|
245
|
+
.addModule(userModule)
|
|
240
246
|
.build();
|
|
241
247
|
```
|
|
242
248
|
|
|
243
|
-
|
|
249
|
+
Why this works:
|
|
250
|
+
- Each module declares only what it **needs** — no import of a global `AppDeps` interface.
|
|
251
|
+
- The output type is inferred from the `.add()` chain — no duplicated signatures.
|
|
252
|
+
- Order of `addModule()` is enforced at compile time: applying `userModule` before `dbModule` would fail the prerequisite check.
|
|
244
253
|
|
|
245
|
-
|
|
254
|
+
#### `.merge()` — fuse standalone builders
|
|
255
|
+
|
|
256
|
+
When a module has no prerequisites (or just bundles independent bindings), define it as a standalone builder and merge it:
|
|
246
257
|
|
|
247
258
|
```typescript
|
|
248
|
-
const
|
|
249
|
-
.add('
|
|
259
|
+
const dbModule = container()
|
|
260
|
+
.add('db', () => new Database())
|
|
261
|
+
.add('cache', (c) => new Redis(c.db));
|
|
262
|
+
|
|
263
|
+
const app = container()
|
|
250
264
|
.add('logger', () => new Logger())
|
|
265
|
+
.merge(dbModule)
|
|
266
|
+
.add('api', (c) => new Api(c.db, c.logger))
|
|
251
267
|
.build();
|
|
268
|
+
```
|
|
252
269
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
270
|
+
`.merge()` copies factories into the host builder. Cross-builder dependencies are resolved at build time. Duplicate keys override (last write wins). Reserved keys throw.
|
|
271
|
+
|
|
272
|
+
#### Anti-pattern (avoid)
|
|
273
|
+
|
|
274
|
+
Older code may show this manual generic pattern — it works but is verbose, couples the module to a global `AppDeps`, and forces you to redeclare every prerequisite by hand:
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
// Don't do this anymore — use defineModule() instead.
|
|
278
|
+
function dbModule<T extends { logger: Logger }>(
|
|
279
|
+
b: ContainerBuilder<AppDeps, T>,
|
|
280
|
+
) {
|
|
281
|
+
return b.add('db', (c) => new Database(c.logger));
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### Post-build: `module()` on the container
|
|
286
|
+
|
|
287
|
+
Compose post-build using the same builder DX:
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
const core = container().add('logger', () => new Logger()).build();
|
|
291
|
+
|
|
292
|
+
const withDb = core.module((b) =>
|
|
293
|
+
b.add('db', (c) => new Database(c.logger)),
|
|
256
294
|
);
|
|
257
295
|
|
|
258
|
-
// Chainable
|
|
259
|
-
const full = withDb.module((b) =>
|
|
260
|
-
.add('userService', (c) => new UserService(c.db, c.logger))
|
|
296
|
+
// Chainable — c accumulates previous bindings
|
|
297
|
+
const full = withDb.module((b) =>
|
|
298
|
+
b.add('userService', (c) => new UserService(c.db, c.logger)),
|
|
261
299
|
);
|
|
262
300
|
```
|
|
263
301
|
|
|
@@ -388,6 +426,7 @@ Compatible with [Context7](https://context7.com/) and any tool that supports the
|
|
|
388
426
|
| Export | Description |
|
|
389
427
|
|---|---|
|
|
390
428
|
| `container<T?>()` | Creates a new `ContainerBuilder`. Pass interface `T` for contract mode. |
|
|
429
|
+
| `defineModule<Deps>()(fn)` | Creates a typed, reusable module with locally-declared prerequisites |
|
|
391
430
|
| `transient(factory)` | Marks a factory as transient (for scope/extend) |
|
|
392
431
|
| `detectDuplicateKeys(...modules)` | Pre-spread validation — detects duplicate keys |
|
|
393
432
|
|
|
@@ -397,7 +436,8 @@ Compatible with [Context7](https://context7.com/) and any tool that supports the
|
|
|
397
436
|
|---|---|
|
|
398
437
|
| `.add(key, factory)` | Register a dependency (factory or instance) |
|
|
399
438
|
| `.addTransient(key, factory)` | Register a transient dependency |
|
|
400
|
-
| `.addModule(module)` | Apply a module `(builder) => builder` |
|
|
439
|
+
| `.addModule(module)` | Apply a module `(builder) => builder` (use with `defineModule()`) |
|
|
440
|
+
| `.merge(otherBuilder)` | Merge a standalone builder's factories into this one |
|
|
401
441
|
| `.build()` | Build and return the container |
|
|
402
442
|
|
|
403
443
|
### Container Methods
|
|
@@ -421,6 +461,9 @@ Compatible with [Context7](https://context7.com/) and any tool that supports the
|
|
|
421
461
|
| `Container<T>` | Full container type (resolved deps + methods) |
|
|
422
462
|
| `ContainerBuilder<TContract, TBuilt>` | Fluent builder class (also used in `module()` callbacks) |
|
|
423
463
|
| `IContainer<T>` | Container methods interface |
|
|
464
|
+
| `Module<TDeps, TBuilt>` | Type of a reusable module (returned by `defineModule()`) |
|
|
465
|
+
| `InferModuleDeps<M>` / `InferModuleBuilt<M>` | Extract a module's prerequisites or full output type |
|
|
466
|
+
| `Factory<T>` | Function type for raw factories (`(c: unknown) => T`) |
|
|
424
467
|
| `OnInit` | Interface with `onInit(): void \| Promise<void>` |
|
|
425
468
|
| `OnDestroy` | Interface with `onDestroy(): void \| Promise<void>` |
|
|
426
469
|
| `ContainerGraph` | Return type of `inspect()` |
|
package/dist/index.d.mts
CHANGED
|
@@ -251,7 +251,7 @@ interface IContainer<T extends Record<string, any> = Record<string, unknown>> {
|
|
|
251
251
|
* );
|
|
252
252
|
* ```
|
|
253
253
|
*/
|
|
254
|
-
module<TNew extends Record<string, any>>(fn: (builder: ContainerBuilder<Record<string, unknown>, T>) => ContainerBuilder<Record<string, unknown>, TNew>): Container<TNew>;
|
|
254
|
+
module<TNew extends Record<string, any>>(fn: (builder: ContainerBuilder<Record<string, unknown>, T>) => ContainerBuilder<Record<string, unknown>, T & TNew>): Container<T & TNew>;
|
|
255
255
|
/**
|
|
256
256
|
* Pre-resolves dependencies (warm-up).
|
|
257
257
|
* Call with specific keys to resolve only those, or without arguments to resolve all.
|
|
@@ -378,10 +378,25 @@ declare class ContainerBuilder<TContract extends Record<string, any> = Record<st
|
|
|
378
378
|
* Applies a module — a function that chains `.add()` calls on this builder.
|
|
379
379
|
* `c` in the module's factories is fully typed with all previously registered deps.
|
|
380
380
|
*/
|
|
381
|
-
addModule<TNew extends Record<string, any>>(module: (builder: ContainerBuilder<TContract, TBuilt>) => ContainerBuilder<TContract, TNew>): ContainerBuilder<TContract, TNew>;
|
|
381
|
+
addModule<TNew extends Record<string, any>>(module: (builder: ContainerBuilder<TContract, TBuilt>) => ContainerBuilder<TContract, TNew>): ContainerBuilder<TContract, TBuilt & TNew>;
|
|
382
|
+
/**
|
|
383
|
+
* Merges a standalone builder into this one. All factories of `other` are copied.
|
|
384
|
+
* The accumulated type becomes `TBuilt & TOther`, so subsequent factories can
|
|
385
|
+
* consume keys from either side.
|
|
386
|
+
*
|
|
387
|
+
* Use this to compose builders that were defined independently:
|
|
388
|
+
* ```typescript
|
|
389
|
+
* const dbModule = container().add('db', () => new DB());
|
|
390
|
+
* const di = container().add('logger', () => new Logger()).merge(dbModule).build();
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* Cross-builder dependencies are resolved at build time. Reserved keys throw.
|
|
394
|
+
* Duplicate keys override silently — same semantics as `.add()` over an existing key.
|
|
395
|
+
*/
|
|
396
|
+
merge<TOther extends Record<string, unknown>>(other: ContainerBuilder<Record<string, unknown>, TOther>): ContainerBuilder<TContract, TBuilt & TOther>;
|
|
382
397
|
/**
|
|
383
398
|
* Returns the accumulated factories as a plain record.
|
|
384
|
-
* @internal Used by `module()` on the container.
|
|
399
|
+
* @internal Used by `module()` on the container and `merge()` on builders.
|
|
385
400
|
*/
|
|
386
401
|
_toRecord(): Record<string, Factory>;
|
|
387
402
|
/**
|
|
@@ -413,6 +428,48 @@ declare class ContainerBuilder<TContract extends Record<string, any> = Record<st
|
|
|
413
428
|
*/
|
|
414
429
|
declare function container<T extends Record<string, any> = Record<string, unknown>>(): ContainerBuilder<T>;
|
|
415
430
|
//#endregion
|
|
431
|
+
//#region src/application/define-module.d.ts
|
|
432
|
+
/**
|
|
433
|
+
* A reusable module: a function that extends a builder with new bindings.
|
|
434
|
+
*
|
|
435
|
+
* `TDeps` are the bindings the module **expects already present** on the target builder.
|
|
436
|
+
* `TBuilt` is the full set of bindings present after the module is applied (`TDeps` + what the module adds).
|
|
437
|
+
*
|
|
438
|
+
* Use {@link defineModule} to build a `Module` with strong inference.
|
|
439
|
+
*/
|
|
440
|
+
type Module<TDeps extends Record<string, any> = {}, TBuilt extends Record<string, any> = TDeps> = (builder: ContainerBuilder<Record<string, unknown>, TDeps>) => ContainerBuilder<Record<string, unknown>, TBuilt>;
|
|
441
|
+
/**
|
|
442
|
+
* Defines a reusable, strongly-typed module without importing the host's deps interface.
|
|
443
|
+
*
|
|
444
|
+
* Pattern: `defineModule<Prerequisites>()(builder => builder.add(...))`.
|
|
445
|
+
* Prerequisites are declared **locally**, not pulled from a global `AppDeps`.
|
|
446
|
+
* The output type is **inferred** from the chained `.add()` calls — no manual signature.
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```typescript
|
|
450
|
+
* import { defineModule } from 'inwire';
|
|
451
|
+
*
|
|
452
|
+
* const billingModule = defineModule<{ eventBus: EventBus }>()((b) =>
|
|
453
|
+
* b.add('subscribeUseCase', (c) => new SubscribeUseCase(c.eventBus)),
|
|
454
|
+
* );
|
|
455
|
+
*
|
|
456
|
+
* const di = container()
|
|
457
|
+
* .add('eventBus', () => new EventBus())
|
|
458
|
+
* .addModule(billingModule)
|
|
459
|
+
* .build();
|
|
460
|
+
* ```
|
|
461
|
+
*/
|
|
462
|
+
declare function defineModule<TDeps extends Record<string, any> = {}>(): <TBuilt extends Record<string, any>>(fn: (builder: ContainerBuilder<Record<string, unknown>, TDeps>) => ContainerBuilder<Record<string, unknown>, TBuilt>) => Module<TDeps, TBuilt>;
|
|
463
|
+
/**
|
|
464
|
+
* Extracts the prerequisite deps of a `Module`.
|
|
465
|
+
*/
|
|
466
|
+
type InferModuleDeps<M> = M extends Module<infer D, any> ? D : never;
|
|
467
|
+
/**
|
|
468
|
+
* Extracts the full set of bindings present after a `Module` is applied
|
|
469
|
+
* (prerequisites + bindings the module adds).
|
|
470
|
+
*/
|
|
471
|
+
type InferModuleBuilt<M> = M extends Module<any, infer B> ? B : never;
|
|
472
|
+
//#endregion
|
|
416
473
|
//#region src/domain/lifecycle.d.ts
|
|
417
474
|
/**
|
|
418
475
|
* Implement this interface (or just add an `onInit` method) to run
|
|
@@ -470,5 +527,5 @@ declare function detectDuplicateKeys(...modules: Record<string, unknown>[]): str
|
|
|
470
527
|
*/
|
|
471
528
|
declare function transient<T>(factory: Factory<T>): Factory<T>;
|
|
472
529
|
//#endregion
|
|
473
|
-
export { AsyncInitErrorWarning, CircularDependencyError, type Container, ContainerBuilder, ContainerConfigError, ContainerError, type ContainerGraph, type ContainerHealth, type ContainerWarning, FactoryError, type IContainer, type OnDestroy, type OnInit, type ProviderInfo, ProviderNotFoundError, ReservedKeyError, ScopeMismatchWarning, type ScopeOptions, UndefinedReturnError, container, detectDuplicateKeys, transient };
|
|
530
|
+
export { AsyncInitErrorWarning, CircularDependencyError, type Container, ContainerBuilder, ContainerConfigError, ContainerError, type ContainerGraph, type ContainerHealth, type ContainerWarning, type Factory, FactoryError, type IContainer, type InferModuleBuilt, type InferModuleDeps, type Module, type OnDestroy, type OnInit, type ProviderInfo, ProviderNotFoundError, ReservedKeyError, ScopeMismatchWarning, type ScopeOptions, UndefinedReturnError, container, defineModule, detectDuplicateKeys, transient };
|
|
474
531
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
var e=class extends Error{constructor(e){super(e),this.name=this.constructor.name}},t=class extends e{hint;details;constructor(e,t){super(`'${e}' must be a factory function, got ${t}.`),this.hint=`Wrap it: ${e}: () => <your ${t} value>`,this.details={key:e,actualType:t}}},n=class extends e{hint;details;constructor(e,t){super(`'${e}' is a reserved container method.`),this.hint=`Rename this dependency, e.g. '${e}Service' or 'my${e[0].toUpperCase()}${e.slice(1)}'.`,this.details={key:e,reserved:[...t]}}},r=class extends e{hint;details;constructor(e,t,n,r){let i=t.length>0?`\n\nResolution chain: ${[...t,`${e} (not found)`].join(` -> `)}`:``,a=`\nRegistered keys: [${n.join(`, `)}]`,o=r?`\n\nDid you mean '${r}'?`:``;super(`Cannot resolve '${t[0]??e}': dependency '${e}' not found.${i}${a}${o}`);let s=`.add('${e}', (c) => new ${e[0].toUpperCase()}${e.slice(1)}(/* deps */))`;this.hint=r?`Did you mean '${r}'? Or add '${e}' to your container:\n container()${s}`:`Add '${e}' to your container:\n container()${s}`,this.details={key:e,chain:t,registered:n,suggestion:r}}},i=class extends e{hint;details;constructor(e,t){let n=[...t,e].join(` -> `);super(`Circular dependency detected while resolving '${t[0]}'.\n\nCycle: ${n}`),this.hint=[`To fix:`,` 1. Extract shared logic into a new dependency both can use`,` 2. Restructure so one doesn't depend on the other`,` 3. Use a mediator/event pattern to decouple them`].join(`
|
|
2
2
|
`),this.details={key:e,chain:t,cycle:n}}},a=class extends e{hint;details;constructor(e,t){let n=t.length>1?`\n\nResolution chain: ${t.join(` -> `)}`:``;super(`Factory '${e}' returned undefined.${n}`),this.hint=`Your factory function returned undefined. Did you forget a return statement?`,this.details={key:e,chain:t}}},o=class extends e{hint;details;originalError;constructor(e,t,n){let r=n instanceof Error?n.message:String(n),i=t.length>1?`\n\nResolution chain: ${[...t.slice(0,-1),`${e} (factory threw)`].join(` -> `)}`:``;super(`Factory '${e}' threw an error: "${r}"${i}`),this.hint=`Check the factory function for '${e}'. The error occurred during instantiation.`,this.details={key:e,chain:t,originalError:r},this.originalError=n}},s=class{type=`scope_mismatch`;message;hint;details;constructor(e,t){this.message=`Singleton '${e}' depends on transient '${t}'.`,this.hint=[`The transient value was resolved once and is now frozen inside the singleton.`,`This is almost always a bug.`,``,`To fix:`,` 1. Make '${e}' transient too: transient((c) => new ${e[0].toUpperCase()}${e.slice(1)}(c.${t}))`,` 2. Make '${t}' singleton if it doesn't need to change`,` 3. Inject a factory instead: ${t}Factory: () => () => <your value>`].join(`
|
|
3
|
-
`),this.details={singleton:e,transient:t}}},c=class{type=`async_init_error`;message;hint;details;constructor(e,t){let n=t instanceof Error?t.message:String(t);this.message=`onInit() for '${e}' rejected: ${n}`,this.hint=`Use preload('${e}') to await and handle async init errors.`,this.details={key:e,error:n}}};const l=[`scope`,`extend`,`module`,`preload`,`reset`,`inspect`,`describe`,`health`,`dispose`,`toString`];var u=class{resolving=new Set;enter(e){this.resolving.add(e)}leave(e){this.resolving.delete(e)}isResolving(e){return this.resolving.has(e)}},d=class{depGraph=new Map;createTrackingProxy(e,t,n){return new Proxy({},{get:(r,i)=>{if(typeof i==`symbol`)return;let a=i;return e.push(a),n(a,t)}})}getDepGraph(){return new Map(this.depGraph)}recordDeps(e,t){this.depGraph.set(e,t)}clearDepGraph(...e){for(let t of e)this.depGraph.delete(t)}clearAllDepGraph(){this.depGraph.clear()}};function f(e){return typeof e==`object`&&!!e&&`onInit`in e&&typeof e.onInit==`function`}function p(e){return typeof e==`object`&&!!e&&`onDestroy`in e&&typeof e.onDestroy==`function`}var m=class{validateConfig(e){for(let[r,i]of Object.entries(e)){if(l.includes(r))throw new n(r,l);if(typeof i!=`function`)throw new t(r,typeof i)}}suggestKey(e,t){let n,r=1/0;for(let i of t){let t=g(e,i);t<r&&(r=t,n=i)}if(!n)return;let i=Math.max(e.length,n.length);return 1-r/i>=.5?n:void 0}};function h(...e){let t=new Map,n=[];for(let r of e)for(let e of Object.keys(r)){let r=(t.get(e)??0)+1;t.set(e,r),r===2&&n.push(e)}return n}function g(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array(r+1),a=Array(r+1);for(let e=0;e<=r;e++)i[e]=e;for(let o=1;o<=n;o++){a[0]=o;for(let n=1;n<=r;n++){let r=e[o-1]===t[n-1]?0:1;a[n]=Math.min(i[n]+1,a[n-1]+1,i[n-1]+r)}[i,a]=[a,i]}return i[r]}const _=Symbol.for(`inwire:transient`);function v(e){let t=(t=>e(t));return t[_]=!0,t}function y(e){return typeof e==`function`&&_ in e&&e[_]===!0}var b=class{factories;cache;warnings=[];validator=new m;initCalled;deferOnInit=!1;parent;name;cycleDetector;dependencyTracker;constructor(e){this.factories=e.factories,this.cache=e.cache??new Map,this.parent=e.parent,this.name=e.name,this.initCalled=e.initCalled?new Set(e.initCalled):new Set,this.cycleDetector=e.cycleDetector,this.dependencyTracker=e.dependencyTracker}getName(){return this.name}resolve(e,t=[]){let n=this.factories.get(e);if(n&&!y(n)&&this.cache.has(e))return this.cache.get(e);if(!n){if(this.parent)return this.parent.resolve(e,t);let n=this.getAllRegisteredKeys();throw new r(e,t,n,this.validator.suggestKey(e,n))}if(this.cycleDetector.isResolving(e))throw new i(e,[...t]);this.cycleDetector.enter(e);let l=[...t,e];try{let t=[],r=n(this.dependencyTracker.createTrackingProxy(t,l,(e,t)=>this.resolve(e,t)));if(r===void 0)throw new a(e,l);if(this.dependencyTracker.recordDeps(e,t),!y(n))for(let n of t){let t=this.getFactory(n);t&&y(t)&&this.warnings.push(new s(e,n))}if(y(n)||this.cache.set(e,r),!this.deferOnInit&&!this.initCalled.has(e)&&f(r)){this.initCalled.add(e);let t=r.onInit();t instanceof Promise&&t.catch(t=>{this.warnings.push(new c(e,t))})}return r}catch(t){throw t instanceof i||t instanceof r||t instanceof a||t instanceof o?t:new o(e,l,t)}finally{this.cycleDetector.leave(e)}}isResolved(e){return this.cache.has(e)}getDepGraph(){return this.dependencyTracker.getDepGraph()}getResolvedKeys(){return[...this.cache.keys()]}getFactories(){return this.factories}getCache(){return this.cache}getWarnings(){return[...this.warnings]}getAllRegisteredKeys(){let e=new Set(this.factories.keys());if(this.parent)for(let t of this.parent.getAllRegisteredKeys())e.add(t);return[...e]}setDeferOnInit(e){this.deferOnInit=e}async callOnInit(e){if(this.initCalled.has(e)||!this.cache.has(e))return;let t=this.cache.get(e);f(t)&&await t.onInit(),this.initCalled.add(e)}clearInitState(...e){for(let t of e)this.initCalled.delete(t)}clearAllInitState(){this.initCalled.clear()}clearDepGraph(...e){this.dependencyTracker.clearDepGraph(...e)}clearAllDepGraph(){this.dependencyTracker.clearAllDepGraph()}clearWarnings(){this.warnings.length=0}clearWarningsForKeys(...e){let t=new Set(e),n=this.warnings.filter(e=>e.type===`async_init_error`?!t.has(e.details.key):e.type===`scope_mismatch`?!t.has(e.details.singleton)&&!t.has(e.details.transient):!0);this.warnings.length=0,this.warnings.push(...n)}getInitCalled(){return this.initCalled}getFactory(e){return this.factories.get(e)??this.parent?.getFactory(e)}},x=class{constructor(e){this.resolver=e}async dispose(){let e=this.resolver.getCache(),t=[...e.entries()].reverse(),n=[];for(let[,e]of t)if(p(e))try{await e.onDestroy()}catch(e){n.push(e)}if(e.clear(),this.resolver.clearAllInitState(),this.resolver.clearAllDepGraph(),this.resolver.clearWarnings(),n.length===1)throw n[0];if(n.length>1)throw AggregateError(n,`dispose() encountered ${n.length} errors`)}},S=class{constructor(e){this.resolver=e}inspect(){let e={};for(let[t,n]of this.resolver.getFactories())e[t]={key:t,resolved:this.resolver.isResolved(t),deps:this.resolver.getDepGraph().get(t)??[],scope:y(n)?`transient`:`singleton`};let t=this.resolver.getName();return t?{name:t,providers:e}:{providers:e}}describe(e){let t=this.resolver.getFactories().get(e);return t?{key:e,resolved:this.resolver.isResolved(e),deps:this.resolver.getDepGraph().get(e)??[],scope:y(t)?`transient`:`singleton`}:{key:e,resolved:!1,deps:[],scope:`singleton`}}health(){let e=[...this.resolver.getFactories().keys()],t=this.resolver.getResolvedKeys(),n=new Set(t),r=this.resolver.getWarnings().map(e=>({type:e.type,message:e.message,details:e.details}));return{totalProviders:e.length,resolved:t,unresolved:e.filter(e=>!n.has(e)),warnings:r}}toString(){let e=[];for(let[t]of this.resolver.getFactories()){let n=this.resolver.isResolved(t),r=this.resolver.getDepGraph().get(t),i=r&&r.length>0?` -> [${r.join(`, `)}]`:``,a=n?`(resolved)`:`(pending)`;e.push(`${t}${i} ${a}`)}let t=this.resolver.getName();return`${t?`Scope(${t})`:`Container`} { ${e.join(`, `)} }`}};function C(e,t){let n=new Map,r=new Map;for(let e of t)n.set(e,0);for(let i of t){let a=e.get(i)??[];for(let e of a)if(t.has(e)){n.set(i,(n.get(i)??0)+1);let t=r.get(e)??[];t.push(i),r.set(e,t)}}let i=[],a=[...t].filter(e=>n.get(e)===0);for(;a.length>0;){i.push(a);let e=[];for(let t of a)for(let i of r.get(t)??[]){let t=(n.get(i)??1)-1;n.set(i,t),t===0&&e.push(i)}a=e}if(i.reduce((e,t)=>e+t.length,0)<t.size){let e=new Set(i.flat()),n=[...t].filter(t=>!e.has(t));throw Error(`Incomplete topological sort: [${n.join(`, `)}] could not be ordered. This may indicate a cycle in the dependency graph.`)}return i}var w=class{constructor(e){this.resolver=e}async preload(...e){let t=e.length>0?e:[...this.resolver.getFactories().keys()],n=new Set(this.resolver.getCache().keys());this.resolver.setDeferOnInit(!0);try{for(let e of t)this.resolver.resolve(e)}catch(e){let t=this.resolver.getCache();for(let e of t.keys())n.has(e)||t.delete(e);throw e}finally{this.resolver.setDeferOnInit(!1)}let r=this.resolver.getDepGraph(),i=new Set,a=e=>{if(!i.has(e)){i.add(e);for(let t of r.get(e)??[])a(t)}};for(let e of t)a(e);let o=C(r,i),s=[];for(let e of o){let t=await Promise.allSettled(e.map(e=>this.resolver.callOnInit(e)));for(let e of t)e.status===`rejected`&&s.push(e.reason)}if(s.length===1)throw s[0];if(s.length>1)throw AggregateError(s,`preload() encountered ${s.length} onInit errors`)}};const T=new m;function E(e,t){let n=new S(e),r=new w(e),i=new x(e),a={scope:(n,r)=>{T.validateConfig(n);let i=new Map;for(let[e,t]of Object.entries(n))i.set(e,t);return E(new b({factories:i,parent:e,name:r?.name,cycleDetector:new u,dependencyTracker:new d}),t)},extend:n=>{T.validateConfig(n);let r=new Map(e.getFactories());for(let[e,t]of Object.entries(n))r.set(e,t);return E(new b({factories:r,cache:new Map(e.getCache()),initCalled:e.getInitCalled(),cycleDetector:new u,dependencyTracker:new d}),t)},module:e=>{if(!t)throw Error(`module() is not available`);let n=e(t());return a.extend(n._toRecord())},preload:(...e)=>r.preload(...e),reset:(...t)=>{let n=e.getCache();if(t.length===0)n.clear(),e.clearAllInitState(),e.clearAllDepGraph(),e.clearWarnings();else{for(let e of t)n.delete(e);e.clearInitState(...t),e.clearDepGraph(...t),e.clearWarningsForKeys(...t)}},inspect:()=>n.inspect(),describe:e=>n.describe(e),health:()=>n.health(),toString:()=>n.toString(),dispose:()=>i.dispose()};return new Proxy({},{get(t,r){if(typeof r==`symbol`)return r===Symbol.toPrimitive||r===Symbol.toStringTag?()=>n.toString():void 0;let i=r;return i in a?a[i]:e.resolve(i)},has(t,n){if(typeof n==`symbol`)return!1;let r=n;return r in a||e.getFactories().has(r)||e.getAllRegisteredKeys().includes(r)},ownKeys(){return[...e.getAllRegisteredKeys(),...Object.keys(a)]},getOwnPropertyDescriptor(t,n){if(typeof n==`symbol`)return;let r=n;if(r in a||e.getFactories().has(r)||e.getAllRegisteredKeys().includes(r))return{configurable:!0,enumerable:!(r in a),writable:!1}}})}var D=class e{factories=new Map;add(e,t){return this.validateKey(e),typeof t==`function`?this.factories.set(e,t):this.factories.set(e,()=>t),this}addTransient(e,t){return this.validateKey(e),this.factories.set(e,v(t)),this}addModule(e){return e(this)}_toRecord(){return Object.fromEntries(this.factories)}build(){return E(new b({factories:new Map(this.factories),cycleDetector:new u,dependencyTracker:new d}),()=>new e)}validateKey(e){if(l.includes(e))throw new n(e,l)}};function O(){return new D}export{c as AsyncInitErrorWarning,i as CircularDependencyError,D as ContainerBuilder,t as ContainerConfigError,e as ContainerError,o as FactoryError,r as ProviderNotFoundError,n as ReservedKeyError,s as ScopeMismatchWarning,a as UndefinedReturnError,O as container,h as detectDuplicateKeys,v as transient};
|
|
3
|
+
`),this.details={singleton:e,transient:t}}},c=class{type=`async_init_error`;message;hint;details;constructor(e,t){let n=t instanceof Error?t.message:String(t);this.message=`onInit() for '${e}' rejected: ${n}`,this.hint=`Use preload('${e}') to await and handle async init errors.`,this.details={key:e,error:n}}};const l=[`scope`,`extend`,`module`,`preload`,`reset`,`inspect`,`describe`,`health`,`dispose`,`toString`];var u=class{resolving=new Set;enter(e){this.resolving.add(e)}leave(e){this.resolving.delete(e)}isResolving(e){return this.resolving.has(e)}},d=class{depGraph=new Map;createTrackingProxy(e,t,n){return new Proxy({},{get:(r,i)=>{if(typeof i==`symbol`)return;let a=i;return e.push(a),n(a,t)}})}getDepGraph(){return new Map(this.depGraph)}recordDeps(e,t){this.depGraph.set(e,t)}clearDepGraph(...e){for(let t of e)this.depGraph.delete(t)}clearAllDepGraph(){this.depGraph.clear()}};function f(e){return typeof e==`object`&&!!e&&`onInit`in e&&typeof e.onInit==`function`}function p(e){return typeof e==`object`&&!!e&&`onDestroy`in e&&typeof e.onDestroy==`function`}var m=class{validateConfig(e){for(let[r,i]of Object.entries(e)){if(l.includes(r))throw new n(r,l);if(typeof i!=`function`)throw new t(r,typeof i)}}suggestKey(e,t){let n,r=1/0;for(let i of t){let t=g(e,i);t<r&&(r=t,n=i)}if(!n)return;let i=Math.max(e.length,n.length);return 1-r/i>=.5?n:void 0}};function h(...e){let t=new Map,n=[];for(let r of e)for(let e of Object.keys(r)){let r=(t.get(e)??0)+1;t.set(e,r),r===2&&n.push(e)}return n}function g(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array(r+1),a=Array(r+1);for(let e=0;e<=r;e++)i[e]=e;for(let o=1;o<=n;o++){a[0]=o;for(let n=1;n<=r;n++){let r=e[o-1]===t[n-1]?0:1;a[n]=Math.min(i[n]+1,a[n-1]+1,i[n-1]+r)}[i,a]=[a,i]}return i[r]}const _=Symbol.for(`inwire:transient`);function v(e){let t=(t=>e(t));return t[_]=!0,t}function y(e){return typeof e==`function`&&_ in e&&e[_]===!0}var b=class{factories;cache;warnings=[];validator=new m;initCalled;deferOnInit=!1;parent;name;cycleDetector;dependencyTracker;constructor(e){this.factories=e.factories,this.cache=e.cache??new Map,this.parent=e.parent,this.name=e.name,this.initCalled=e.initCalled?new Set(e.initCalled):new Set,this.cycleDetector=e.cycleDetector,this.dependencyTracker=e.dependencyTracker}getName(){return this.name}resolve(e,t=[]){let n=this.factories.get(e);if(n&&!y(n)&&this.cache.has(e))return this.cache.get(e);if(!n){if(this.parent)return this.parent.resolve(e,t);let n=this.getAllRegisteredKeys();throw new r(e,t,n,this.validator.suggestKey(e,n))}if(this.cycleDetector.isResolving(e))throw new i(e,[...t]);this.cycleDetector.enter(e);let l=[...t,e];try{let t=[],r=n(this.dependencyTracker.createTrackingProxy(t,l,(e,t)=>this.resolve(e,t)));if(r===void 0)throw new a(e,l);if(this.dependencyTracker.recordDeps(e,t),!y(n))for(let n of t){let t=this.getFactory(n);t&&y(t)&&this.warnings.push(new s(e,n))}if(y(n)||this.cache.set(e,r),!this.deferOnInit&&!this.initCalled.has(e)&&f(r)){this.initCalled.add(e);let t=r.onInit();t instanceof Promise&&t.catch(t=>{this.warnings.push(new c(e,t))})}return r}catch(t){throw t instanceof i||t instanceof r||t instanceof a||t instanceof o?t:new o(e,l,t)}finally{this.cycleDetector.leave(e)}}isResolved(e){return this.cache.has(e)}getDepGraph(){return this.dependencyTracker.getDepGraph()}getResolvedKeys(){return[...this.cache.keys()]}getFactories(){return this.factories}getCache(){return this.cache}getWarnings(){return[...this.warnings]}getAllRegisteredKeys(){let e=new Set(this.factories.keys());if(this.parent)for(let t of this.parent.getAllRegisteredKeys())e.add(t);return[...e]}setDeferOnInit(e){this.deferOnInit=e}async callOnInit(e){if(this.initCalled.has(e)||!this.cache.has(e))return;let t=this.cache.get(e);f(t)&&await t.onInit(),this.initCalled.add(e)}clearInitState(...e){for(let t of e)this.initCalled.delete(t)}clearAllInitState(){this.initCalled.clear()}clearDepGraph(...e){this.dependencyTracker.clearDepGraph(...e)}clearAllDepGraph(){this.dependencyTracker.clearAllDepGraph()}clearWarnings(){this.warnings.length=0}clearWarningsForKeys(...e){let t=new Set(e),n=this.warnings.filter(e=>e.type===`async_init_error`?!t.has(e.details.key):e.type===`scope_mismatch`?!t.has(e.details.singleton)&&!t.has(e.details.transient):!0);this.warnings.length=0,this.warnings.push(...n)}getInitCalled(){return this.initCalled}getFactory(e){return this.factories.get(e)??this.parent?.getFactory(e)}},x=class{constructor(e){this.resolver=e}async dispose(){let e=this.resolver.getCache(),t=[...e.entries()].reverse(),n=[];for(let[,e]of t)if(p(e))try{await e.onDestroy()}catch(e){n.push(e)}if(e.clear(),this.resolver.clearAllInitState(),this.resolver.clearAllDepGraph(),this.resolver.clearWarnings(),n.length===1)throw n[0];if(n.length>1)throw AggregateError(n,`dispose() encountered ${n.length} errors`)}},S=class{constructor(e){this.resolver=e}inspect(){let e={};for(let[t,n]of this.resolver.getFactories())e[t]={key:t,resolved:this.resolver.isResolved(t),deps:this.resolver.getDepGraph().get(t)??[],scope:y(n)?`transient`:`singleton`};let t=this.resolver.getName();return t?{name:t,providers:e}:{providers:e}}describe(e){let t=this.resolver.getFactories().get(e);return t?{key:e,resolved:this.resolver.isResolved(e),deps:this.resolver.getDepGraph().get(e)??[],scope:y(t)?`transient`:`singleton`}:{key:e,resolved:!1,deps:[],scope:`singleton`}}health(){let e=[...this.resolver.getFactories().keys()],t=this.resolver.getResolvedKeys(),n=new Set(t),r=this.resolver.getWarnings().map(e=>({type:e.type,message:e.message,details:e.details}));return{totalProviders:e.length,resolved:t,unresolved:e.filter(e=>!n.has(e)),warnings:r}}toString(){let e=[];for(let[t]of this.resolver.getFactories()){let n=this.resolver.isResolved(t),r=this.resolver.getDepGraph().get(t),i=r&&r.length>0?` -> [${r.join(`, `)}]`:``,a=n?`(resolved)`:`(pending)`;e.push(`${t}${i} ${a}`)}let t=this.resolver.getName();return`${t?`Scope(${t})`:`Container`} { ${e.join(`, `)} }`}};function C(e,t){let n=new Map,r=new Map;for(let e of t)n.set(e,0);for(let i of t){let a=e.get(i)??[];for(let e of a)if(t.has(e)){n.set(i,(n.get(i)??0)+1);let t=r.get(e)??[];t.push(i),r.set(e,t)}}let i=[],a=[...t].filter(e=>n.get(e)===0);for(;a.length>0;){i.push(a);let e=[];for(let t of a)for(let i of r.get(t)??[]){let t=(n.get(i)??1)-1;n.set(i,t),t===0&&e.push(i)}a=e}if(i.reduce((e,t)=>e+t.length,0)<t.size){let e=new Set(i.flat()),n=[...t].filter(t=>!e.has(t));throw Error(`Incomplete topological sort: [${n.join(`, `)}] could not be ordered. This may indicate a cycle in the dependency graph.`)}return i}var w=class{constructor(e){this.resolver=e}async preload(...e){let t=e.length>0?e:[...this.resolver.getFactories().keys()],n=new Set(this.resolver.getCache().keys());this.resolver.setDeferOnInit(!0);try{for(let e of t)this.resolver.resolve(e)}catch(e){let t=this.resolver.getCache();for(let e of t.keys())n.has(e)||t.delete(e);throw e}finally{this.resolver.setDeferOnInit(!1)}let r=this.resolver.getDepGraph(),i=new Set,a=e=>{if(!i.has(e)){i.add(e);for(let t of r.get(e)??[])a(t)}};for(let e of t)a(e);let o=C(r,i),s=[];for(let e of o){let t=await Promise.allSettled(e.map(e=>this.resolver.callOnInit(e)));for(let e of t)e.status===`rejected`&&s.push(e.reason)}if(s.length===1)throw s[0];if(s.length>1)throw AggregateError(s,`preload() encountered ${s.length} onInit errors`)}};const T=new m;function E(e,t){let n=new S(e),r=new w(e),i=new x(e),a={scope:(n,r)=>{T.validateConfig(n);let i=new Map;for(let[e,t]of Object.entries(n))i.set(e,t);return E(new b({factories:i,parent:e,name:r?.name,cycleDetector:new u,dependencyTracker:new d}),t)},extend:n=>{T.validateConfig(n);let r=new Map(e.getFactories());for(let[e,t]of Object.entries(n))r.set(e,t);return E(new b({factories:r,cache:new Map(e.getCache()),initCalled:e.getInitCalled(),cycleDetector:new u,dependencyTracker:new d}),t)},module:e=>{if(!t)throw Error(`module() is not available`);let n=e(t());return a.extend(n._toRecord())},preload:(...e)=>r.preload(...e),reset:(...t)=>{let n=e.getCache();if(t.length===0)n.clear(),e.clearAllInitState(),e.clearAllDepGraph(),e.clearWarnings();else{for(let e of t)n.delete(e);e.clearInitState(...t),e.clearDepGraph(...t),e.clearWarningsForKeys(...t)}},inspect:()=>n.inspect(),describe:e=>n.describe(e),health:()=>n.health(),toString:()=>n.toString(),dispose:()=>i.dispose()};return new Proxy({},{get(t,r){if(typeof r==`symbol`)return r===Symbol.toPrimitive||r===Symbol.toStringTag?()=>n.toString():void 0;let i=r;return i in a?a[i]:e.resolve(i)},has(t,n){if(typeof n==`symbol`)return!1;let r=n;return r in a||e.getFactories().has(r)||e.getAllRegisteredKeys().includes(r)},ownKeys(){return[...e.getAllRegisteredKeys(),...Object.keys(a)]},getOwnPropertyDescriptor(t,n){if(typeof n==`symbol`)return;let r=n;if(r in a||e.getFactories().has(r)||e.getAllRegisteredKeys().includes(r))return{configurable:!0,enumerable:!(r in a),writable:!1}}})}var D=class e{factories=new Map;add(e,t){return this.validateKey(e),typeof t==`function`?this.factories.set(e,t):this.factories.set(e,()=>t),this}addTransient(e,t){return this.validateKey(e),this.factories.set(e,v(t)),this}addModule(e){return e(this)}merge(e){for(let[t,n]of Object.entries(e._toRecord()))this.validateKey(t),this.factories.set(t,n);return this}_toRecord(){return Object.fromEntries(this.factories)}build(){return E(new b({factories:new Map(this.factories),cycleDetector:new u,dependencyTracker:new d}),()=>new e)}validateKey(e){if(l.includes(e))throw new n(e,l)}};function O(){return new D}function k(){return e=>e}export{c as AsyncInitErrorWarning,i as CircularDependencyError,D as ContainerBuilder,t as ContainerConfigError,e as ContainerError,o as FactoryError,r as ProviderNotFoundError,n as ReservedKeyError,s as ScopeMismatchWarning,a as UndefinedReturnError,O as container,k as defineModule,h as detectDuplicateKeys,v as transient};
|
|
4
4
|
//# sourceMappingURL=index.mjs.map
|
package/package.json
CHANGED