inwire 1.2.0 → 2.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/README.md CHANGED
@@ -269,6 +269,16 @@ await app.preload('db', 'cache'); // resolve specific deps
269
269
  await app.preload(); // resolve ALL
270
270
  ```
271
271
 
272
+ `preload()` **awaits `onInit()`** on every resolved service and runs independent branches in parallel using topological sorting:
273
+
274
+ ```
275
+ Level 0: [config] ← no deps, inits first
276
+ Level 1: [db] [cache] ← depend on config, init in parallel
277
+ Level 2: [api] ← depends on db + cache, inits last
278
+ ```
279
+
280
+ Errors thrown in `onInit()` propagate to the caller — use `try/catch` around `preload()` for startup validation.
281
+
272
282
  ### Reset
273
283
 
274
284
  ```typescript
package/dist/index.d.mts CHANGED
@@ -187,7 +187,6 @@ interface ContainerWarning {
187
187
  */
188
188
  declare class ContainerBuilder<TContract extends Record<string, unknown> = Record<string, unknown>, TBuilt extends Record<string, unknown> = {}> {
189
189
  private readonly factories;
190
- private readonly transientKeys;
191
190
  /**
192
191
  * Registers a dependency — factory (lazy) or instance (eager).
193
192
  *
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}`),this.hint=r?`Did you mean '${r}'? Or add '${e}' to your container:\n createContainer({\n ...existing,\n ${e}: (c) => new Your${e[0].toUpperCase()}${e.slice(1)}(/* deps */),\n });`:`Add '${e}' to your container:\n createContainer({\n ...existing,\n ${e}: (c) => new Your${e[0].toUpperCase()}${e.slice(1)}(/* deps */),\n });`,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}}};const c=[`scope`,`extend`,`module`,`preload`,`reset`,`inspect`,`describe`,`health`,`dispose`,`toString`];function l(e){return typeof e==`object`&&!!e&&`onInit`in e&&typeof e.onInit==`function`}function u(e){return typeof e==`object`&&!!e&&`onDestroy`in e&&typeof e.onDestroy==`function`}var d=class{validateConfig(e){for(let[r,i]of Object.entries(e)){if(c.includes(r))throw new n(r,c);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=p(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 f(...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 p(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 m=Symbol.for(`inwire:transient`);function h(e){let t=(t=>e(t));return t[m]=!0,t}function g(e){return typeof e==`function`&&m in e&&e[m]===!0}var _=class{factories;cache;resolving=new Set;depGraph=new Map;warnings=[];validator=new d;parent;name;constructor(e,t,n,r){this.factories=e,this.cache=t??new Map,this.parent=n,this.name=r}getName(){return this.name}resolve(e,t=[]){let n=this.factories.get(e);if(n&&!g(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.resolving.has(e))throw new i(e,[...t]);this.resolving.add(e);let c=[...t,e];try{let t=[],r=n(this.createTrackingProxy(t,c));if(r===void 0)throw new a(e,c);if(this.depGraph.set(e,t),!g(n))for(let n of t){let t=this.getFactory(n);t&&g(t)&&this.warnings.push(new s(e,n))}if(g(n)||this.cache.set(e,r),l(r)){let e=r.onInit();e instanceof Promise&&e.catch(()=>{})}return r}catch(t){throw t instanceof i||t instanceof r||t instanceof a||t instanceof o?t:new o(e,c,t)}finally{this.resolving.delete(e)}}isResolved(e){return this.cache.has(e)}getDepGraph(){return new Map(this.depGraph)}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]}createTrackingProxy(e,t){return new Proxy({},{get:(n,r)=>{if(typeof r==`symbol`)return;let i=r;return e.push(i),this.resolve(i,t)}})}getFactory(e){return this.factories.get(e)??this.parent?.getFactory(e)}},v=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:g(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:g(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(`, `)} }`}};const y=new d;function b(e,t){let n=new v(e),r={scope:(n,r)=>{let i=new Map;for(let[e,t]of Object.entries(n))i.set(e,t);return b(new _(i,new Map,e,r?.name),t)},extend:n=>{y.validateConfig(n);let r=new Map(e.getFactories());for(let[e,t]of Object.entries(n))r.set(e,t);return b(new _(r,new Map(e.getCache())),t)},module:e=>{if(!t)throw Error(`module() is not available`);let n=e(t());return r.extend(n._toRecord())},preload:async(...t)=>{let n=t.length>0?t:[...e.getFactories().keys()];for(let t of n)e.resolve(t)},reset:(...t)=>{let n=e.getCache();for(let e of t)n.delete(e)},inspect:()=>n.inspect(),describe:e=>n.describe(e),health:()=>n.health(),toString:()=>n.toString(),dispose:async()=>{let t=e.getCache(),n=[...t.entries()].reverse();for(let[,e]of n)u(e)&&await e.onDestroy();t.clear()}};return new Proxy({},{get(t,i){if(typeof i==`symbol`)return i===Symbol.toPrimitive||i===Symbol.toStringTag?()=>n.toString():void 0;let a=i;return a in r?r[a]:e.resolve(a)},has(t,n){if(typeof n==`symbol`)return!1;let i=n;return i in r||e.getFactories().has(i)||e.getAllRegisteredKeys().includes(i)},ownKeys(){return[...e.getAllRegisteredKeys(),...Object.keys(r)]},getOwnPropertyDescriptor(t,n){if(typeof n==`symbol`)return;let i=n;if(i in r||e.getFactories().has(i)||e.getAllRegisteredKeys().includes(i))return{configurable:!0,enumerable:!(i in r),writable:!1}}})}var x=class e{factories=new Map;transientKeys=new Set;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,h(t)),this.transientKeys.add(e),this}addModule(e){return e(this)}_toRecord(){return Object.fromEntries(this.factories)}build(){return b(new _(new Map(this.factories)),()=>new e)}validateKey(e){if(c.includes(e))throw new n(e,c)}};function S(){return new x}export{i as CircularDependencyError,x as ContainerBuilder,t as ContainerConfigError,e as ContainerError,o as FactoryError,r as ProviderNotFoundError,n as ReservedKeyError,s as ScopeMismatchWarning,a as UndefinedReturnError,S as container,f as detectDuplicateKeys,h as transient};
3
+ `),this.details={singleton:e,transient:t}}};const c=[`scope`,`extend`,`module`,`preload`,`reset`,`inspect`,`describe`,`health`,`dispose`,`toString`];function l(e){return typeof e==`object`&&!!e&&`onInit`in e&&typeof e.onInit==`function`}function u(e){return typeof e==`object`&&!!e&&`onDestroy`in e&&typeof e.onDestroy==`function`}var d=class{validateConfig(e){for(let[r,i]of Object.entries(e)){if(c.includes(r))throw new n(r,c);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=p(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 f(...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 p(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 m=Symbol.for(`inwire:transient`);function h(e){let t=(t=>e(t));return t[m]=!0,t}function g(e){return typeof e==`function`&&m in e&&e[m]===!0}var _=class{factories;cache;resolving=new Set;depGraph=new Map;warnings=[];validator=new d;initCalled=new Set;deferOnInit=!1;parent;name;constructor(e,t,n,r,i){this.factories=e,this.cache=t??new Map,this.parent=n,this.name=r,i&&(this.initCalled=new Set(i))}getName(){return this.name}resolve(e,t=[]){let n=this.factories.get(e);if(n&&!g(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.resolving.has(e))throw new i(e,[...t]);this.resolving.add(e);let c=[...t,e];try{let t=[],r=n(this.createTrackingProxy(t,c));if(r===void 0)throw new a(e,c);if(this.depGraph.set(e,t),!g(n))for(let n of t){let t=this.getFactory(n);t&&g(t)&&this.warnings.push(new s(e,n))}if(g(n)||this.cache.set(e,r),!this.deferOnInit&&!this.initCalled.has(e)&&l(r)){this.initCalled.add(e);let t=r.onInit();t instanceof Promise&&t.catch(()=>{})}return r}catch(t){throw t instanceof i||t instanceof r||t instanceof a||t instanceof o?t:new o(e,c,t)}finally{this.resolving.delete(e)}}isResolved(e){return this.cache.has(e)}getDepGraph(){return new Map(this.depGraph)}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))return;this.initCalled.add(e);let t=this.cache.get(e);l(t)&&await t.onInit()}clearInitState(...e){for(let t of e)this.initCalled.delete(t)}clearAllInitState(){this.initCalled.clear()}getInitCalled(){return this.initCalled}createTrackingProxy(e,t){return new Proxy({},{get:(n,r)=>{if(typeof r==`symbol`)return;let i=r;return e.push(i),this.resolve(i,t)}})}getFactory(e){return this.factories.get(e)??this.parent?.getFactory(e)}},v=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:g(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:g(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(`, `)} }`}};const y=new d;function b(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}return i}function x(e,t){let n=new v(e),r={scope:(n,r)=>{let i=new Map;for(let[e,t]of Object.entries(n))i.set(e,t);return x(new _(i,new Map,e,r?.name),t)},extend:n=>{y.validateConfig(n);let r=new Map(e.getFactories());for(let[e,t]of Object.entries(n))r.set(e,t);return x(new _(r,new Map(e.getCache()),void 0,void 0,e.getInitCalled()),t)},module:e=>{if(!t)throw Error(`module() is not available`);let n=e(t());return r.extend(n._toRecord())},preload:async(...t)=>{let n=t.length>0?t:[...e.getFactories().keys()];e.setDeferOnInit(!0);for(let t of n)e.resolve(t);e.setDeferOnInit(!1);let r=e.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 n)a(e);let o=b(r,i);for(let t of o)await Promise.all(t.map(t=>e.callOnInit(t)))},reset:(...t)=>{let n=e.getCache();for(let e of t)n.delete(e);e.clearInitState(...t)},inspect:()=>n.inspect(),describe:e=>n.describe(e),health:()=>n.health(),toString:()=>n.toString(),dispose:async()=>{let t=e.getCache(),n=[...t.entries()].reverse();for(let[,e]of n)u(e)&&await e.onDestroy();t.clear(),e.clearAllInitState()}};return new Proxy({},{get(t,i){if(typeof i==`symbol`)return i===Symbol.toPrimitive||i===Symbol.toStringTag?()=>n.toString():void 0;let a=i;return a in r?r[a]:e.resolve(a)},has(t,n){if(typeof n==`symbol`)return!1;let i=n;return i in r||e.getFactories().has(i)||e.getAllRegisteredKeys().includes(i)},ownKeys(){return[...e.getAllRegisteredKeys(),...Object.keys(r)]},getOwnPropertyDescriptor(t,n){if(typeof n==`symbol`)return;let i=n;if(i in r||e.getFactories().has(i)||e.getAllRegisteredKeys().includes(i))return{configurable:!0,enumerable:!(i in r),writable:!1}}})}var S=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,h(t)),this}addModule(e){return e(this)}_toRecord(){return Object.fromEntries(this.factories)}build(){return x(new _(new Map(this.factories)),()=>new e)}validateKey(e){if(c.includes(e))throw new n(e,c)}};function C(){return new S}export{i as CircularDependencyError,S as ContainerBuilder,t as ContainerConfigError,e as ContainerError,o as FactoryError,r as ProviderNotFoundError,n as ReservedKeyError,s as ScopeMismatchWarning,a as UndefinedReturnError,C as container,f as detectDuplicateKeys,h as transient};
4
4
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inwire",
3
- "version": "1.2.0",
3
+ "version": "2.0.0",
4
4
  "description": "Zero-ceremony dependency injection for TypeScript. Full inference, no decorators, no tokens. Built-in introspection for AI tooling.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",