@js-injection/service-provider 1.0.0-alpha.1 → 1.0.0-alpha.2

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/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var h=class extends Error{constructor(e){super(`Circular dependency detected: ${e}`),this.name="CircularDependencyError"}},p=class extends Error{constructor(e){super(`Service not registered for identifier: ${e}`),this.name="ServiceNotFoundError"}},l=class extends Error{constructor(e){super(e),this.name="RegistrationError"}},m=class extends Error{constructor(){super("ServiceProvider has been disposed and cannot resolve services."),this.name="ServiceProviderDisposedError"}},f=class extends Error{constructor(e){super(`Service "${e}" requires asynchronous disposal but a synchronous dispose was called. Please use await disposeAsync() instead.`),this.name="AsyncDisposalError"}};var v=new WeakMap;function c(y){let e=v.get(y);return e||(e=Symbol(y.name||"AnonymousClass"),v.set(y,e)),e}var u=class y{constructor(e,t,s,n=!1){this.name=e;this.definitions=t;this.parent=s;this.isAsyncScope=n}instances=new Map;resolving=new Set;path=[];disposed=!1;createScope(e="scope"){let t=this.parent||this;return new y(e,this.definitions,t,!1)}createAsyncScope(e="async-scope"){let t=this.parent||this;return new y(e,this.definitions,t,!0)}getService(e){if(this.disposed)throw new m;let t=this.getKey(e);if(this.parent&&this.definitions[t]?.lifetime==="singleton")return this.parent.getService(t);let s=this.definitions[t];if(!s){let i=typeof e=="string"||typeof e=="symbol"?String(e):e.name||String(e);throw new p(i)}let n=s.uid;if(this.instances.has(n))return this.instances.get(n);if(this.resolving.has(n)){let i=this.path.map(r=>typeof r=="symbol"?r.description||String(r):r).concat(typeof t=="symbol"?t.description||String(t):t).join(" -> ");throw new h(i)}this.resolving.add(n),this.path.push(t);try{return s.kind==="value"?this.resolveValue(n,s.value):Array.isArray(s.type)?this.resolveArray(n,s.type):s.kind==="function"&&s.func?this.resolveFunc(n,s.func,s.params):s.factory?this.resolveFactory(n,s.factory):this.resolveClass(n,s.type,s.params)}finally{this.resolving.delete(n),this.path.pop()}}dispose(){if(this.disposed)return;if(this.isAsyncScope)throw new f(this.name);this.disposed=!0;let e=Array.from(this.instances.entries()).reverse();for(let[t,s]of e)if(s&&typeof s.dispose=="function"){if(s.dispose()instanceof Promise)throw new f(typeof t=="symbol"&&t.description||String(t))}else if(s&&typeof s.disposeAsync=="function")throw new f(typeof t=="symbol"&&t.description||String(t));this.instances.clear()}async disposeAsync(){if(this.disposed)return;this.disposed=!0;let e=Array.from(this.instances.values()).reverse();for(let t of e)if(t&&typeof t.disposeAsync=="function")await t.disposeAsync();else if(t&&typeof t.dispose=="function"){let s=t.dispose();s instanceof Promise&&await s}this.instances.clear()}resolveValue(e,t){return this.instances.set(e,t),t}resolveArray(e,t){let s=t.map(n=>this.getService(n));return this.instances.set(e,s),s}resolveFactory(e,t){let s=this.createContainerProxy(),n=t(s,this);return this.instances.set(e,n),n}resolveFunc(e,t,s){let i=(s||[]).map(o=>{let a=this.tryGetKey(o);return a?this.getService(a):o}),r=t(...i);return this.instances.set(e,r),r}resolveClass(e,t,s){let i=(s||[]).map(o=>{let a=this.tryGetKey(o);return a?this.getService(a):o}),r=new t(...i);return this.instances.set(e,r),r}createContainerProxy(){return new Proxy({},{get:(e,t)=>{if(!(typeof t!="string"&&typeof t!="symbol"))return this.getService(t)}})}getKey(e){if(typeof e=="string"||typeof e=="symbol")return e;let t=this.tryGetKey(e);if(t)return t;let s=Array.isArray(e)?`[${e.map(n=>n.name).join(", ")}]`:e.name||String(e);throw new p(s)}tryGetKey(e){if(typeof e=="string"||typeof e=="symbol"){if(e in this.definitions)return e;if(typeof e=="string"){let t=Reflect.ownKeys(this.definitions).find(s=>{let n=this.definitions[s];return n.kind==="service"&&!Array.isArray(n.type)&&n.type?.name===e});if(t)return t}return}if(typeof e=="function"||Array.isArray(e)){let t=c(e);if(t in this.definitions)return t;let s=Reflect.ownKeys(this.definitions).find(n=>{let i=this.definitions[n];return i.kind==="service"&&i.type===e});if(s)return s}}};var K=class{definitions={};typeMap;constructor(){this.typeMap={}}addSingletonFactory(e,t){let s,n,i=!1;if(typeof e=="string"||typeof e=="symbol")s=e,n=this.typeMap[s],i=!0;else{let a=this.resolveKeyAndType(e);s=a.key,n=a.type}let r=i?s:c(n),o={kind:"service",lifetime:"singleton",uid:r,type:n,factory:t};return this.definitions[s]=o,s!==r&&(this.definitions[r]=o),this}addServiceProvider(e){return this.addSingletonFactory(e,(t,s)=>s)}addScopedFactory(e,t){let s,n,i=!1;if(typeof e=="string"||typeof e=="symbol")s=e,n=this.typeMap[s],i=!0;else{let a=this.resolveKeyAndType(e);s=a.key,n=a.type}let r=i?s:c(n),o={kind:"service",lifetime:"scoped",uid:r,type:n,factory:t};return this.definitions[s]=o,s!==r&&(this.definitions[r]=o),this}addSingletonClass(e,...t){let{key:s,type:n}=this.resolveKeyAndType(e),i=c(n),r={kind:"service",lifetime:"singleton",uid:i,type:n,params:t};return this.definitions[s]=r,this.definitions[i]=r,this}addScopedClass(e,...t){let{key:s,type:n}=this.resolveKeyAndType(e),i=c(n),r={kind:"service",lifetime:"scoped",uid:i,type:n,params:t};return this.definitions[s]=r,this.definitions[i]=r,this}addSingletonArray(e,...t){let s={kind:"service",lifetime:"singleton",uid:e,type:t};this.typeMap[e]=t,this.definitions[e]=s;let n=t;for(let i of n){if(Reflect.ownKeys(this.typeMap).find(g=>this.typeMap[g]===i))continue;let o=i.name;if(!o)throw new l(`Class in array "${String(e)}" is missing a name and cannot be auto-registered.`);let a=c(i),d={kind:"service",lifetime:"singleton",uid:a,type:i,params:[]};this.typeMap[o]=i,this.definitions[o]=d,this.definitions[a]=d}return this}addScopedArray(e,...t){let s={kind:"service",lifetime:"scoped",uid:e,type:t};this.typeMap[e]=t,this.definitions[e]=s;let n=t;for(let i of n){if(Reflect.ownKeys(this.typeMap).find(g=>this.typeMap[g]===i))continue;let o=i.name;if(!o)throw new l(`Class in array "${String(e)}" is missing a name and cannot be auto-registered.`);let a=c(i),d={kind:"service",lifetime:"scoped",uid:a,type:i,params:[]};this.typeMap[o]=i,this.definitions[o]=d,this.definitions[a]=d}return this}addSingletonFunc(e,t,...s){return this.definitions[e]={kind:"function",lifetime:"singleton",uid:e,func:t,params:s},this}addScopedFunc(e,t,...s){return this.definitions[e]={kind:"function",lifetime:"scoped",uid:e,func:t,params:s},this}addSingletonValue(e,t){return this.definitions[e]={kind:"value",lifetime:"singleton",uid:e,value:t},this}addScopedValue(e,t){return this.definitions[e]={kind:"value",lifetime:"scoped",uid:e,value:t},this}resolveKeyAndType(e){let t,s=Reflect.ownKeys(this.typeMap).find(n=>this.typeMap[n]===e);return s?t=s:(t=e.name||c(e),this.typeMap[t]=e),{key:t,type:e}}build(e="root"){for(let t of Reflect.ownKeys(this.definitions)){let s=this.definitions[t];if(!(s.kind!=="service"||!Array.isArray(s.type)))for(let n of s.type){let i=n.name,r=this.definitions[i];if(r&&r.params&&r.params.length===0&&n.length>0)throw new l(`Class "${i}" in array "${String(t)}" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`)}}return new u(e,this.definitions)}};export{f as AsyncDisposalError,h as CircularDependencyError,l as RegistrationError,K as ServiceCollection,p as ServiceNotFoundError,u as ServiceProvider,m as ServiceProviderDisposedError};
1
+ var u=class extends Error{constructor(e){super(`Circular dependency detected: ${e}`),this.name="CircularDependencyError"}},p=class extends Error{constructor(e){super(`Service not registered for identifier: ${e}`),this.name="ServiceNotFoundError"}},l=class extends Error{constructor(e){super(e),this.name="RegistrationError"}},h=class extends Error{constructor(){super("ServiceProvider has been disposed and cannot resolve services."),this.name="ServiceProviderDisposedError"}},f=class extends Error{constructor(e){super(`Service "${e}" requires asynchronous disposal but a synchronous dispose was called. Please use await disposeAsync() instead.`),this.name="AsyncDisposalError"}};var v=new WeakMap;function c(y){let e=v.get(y);return e||(e=Symbol(y.name||"AnonymousClass"),v.set(y,e)),e}var m=class y{constructor(e,t,s,n=!1){this.name=e;this.definitions=t;this.parent=s;this.isAsyncScope=n}instances=new Map;resolving=new Set;path=[];disposed=!1;createScope(e="scope"){let t=this.parent||this;return new y(e,this.definitions,t,!1)}createAsyncScope(e="async-scope"){let t=this.parent||this;return new y(e,this.definitions,t,!0)}getService(e){if(this.disposed)throw new h;let t=this.getKey(e);if(this.parent&&this.definitions[t]?.lifetime==="singleton")return this.parent.getService(t);let s=this.definitions[t];if(!s){let i=typeof e=="string"||typeof e=="symbol"?String(e):e.name||String(e);throw new p(i)}let n=s.uid;if(this.instances.has(n))return this.instances.get(n);if(this.resolving.has(n)){let i=this.path.map(r=>typeof r=="symbol"?r.description||String(r):r).concat(typeof t=="symbol"?t.description||String(t):t).join(" -> ");throw new u(i)}this.resolving.add(n),this.path.push(t);try{return s.kind==="value"?this.resolveValue(n,s.value):Array.isArray(s.type)?this.resolveArray(n,s.type):s.kind==="function"&&s.func?this.resolveFunc(n,s.func,s.params):s.factory?this.resolveFactory(n,s.factory):this.resolveClass(n,s.type,s.params)}finally{this.resolving.delete(n),this.path.pop()}}dispose(){if(this.disposed)return;if(this.isAsyncScope)throw new f(this.name);this.disposed=!0;let e=Array.from(this.instances.entries()).reverse();for(let[t,s]of e)if(s&&typeof s.dispose=="function"){if(s.dispose()instanceof Promise)throw new f(typeof t=="symbol"&&t.description||String(t))}else if(s&&typeof s.disposeAsync=="function")throw new f(typeof t=="symbol"&&t.description||String(t));this.instances.clear()}async disposeAsync(){if(this.disposed)return;this.disposed=!0;let e=Array.from(this.instances.values()).reverse();for(let t of e)if(t&&typeof t.disposeAsync=="function")await t.disposeAsync();else if(t&&typeof t.dispose=="function"){let s=t.dispose();s instanceof Promise&&await s}this.instances.clear()}resolveValue(e,t){return this.instances.set(e,t),t}resolveArray(e,t){let s=t.map(n=>this.getService(n));return this.instances.set(e,s),s}resolveFactory(e,t){let s=this.createContainerProxy(),n=t(s,this);return this.instances.set(e,n),n}resolveFunc(e,t,s){let i=(s||[]).map(o=>{let a=this.tryGetKey(o);return a?this.getService(a):o}),r=t(...i);return this.instances.set(e,r),r}resolveClass(e,t,s){let i=(s||[]).map(o=>{let a=this.tryGetKey(o);return a?this.getService(a):o}),r=new t(...i);return this.instances.set(e,r),r}createContainerProxy(){return new Proxy({},{get:(e,t)=>{if(!(typeof t!="string"&&typeof t!="symbol"))return this.getService(t)}})}getKey(e){if(typeof e=="string"||typeof e=="symbol")return e;let t=this.tryGetKey(e);if(t)return t;let s=Array.isArray(e)?`[${e.map(n=>n.name).join(", ")}]`:e.name||String(e);throw new p(s)}tryGetKey(e){if(typeof e=="string"||typeof e=="symbol"){if(e in this.definitions)return e;if(typeof e=="string"){let t=Reflect.ownKeys(this.definitions).find(s=>{let n=this.definitions[s];return n.kind==="service"&&!Array.isArray(n.type)&&n.type?.name===e});if(t)return t}return}if(typeof e=="function"||Array.isArray(e)){let t=c(e);if(t in this.definitions)return t;let s=Reflect.ownKeys(this.definitions).find(n=>{let i=this.definitions[n];return i.kind==="service"&&i.type===e});if(s)return s}}};var K=class{definitions={};typeMap;constructor(){this.typeMap={}}addSingletonFactory(e,t){let s,n,i=!1;if(typeof e=="string"||typeof e=="symbol")s=e,n=this.typeMap[s],i=!0;else{let a=this.resolveKeyAndType(e);s=a.key,n=a.type}let r=i?s:c(n),o={kind:"service",lifetime:"singleton",uid:r,type:n,factory:t};return this.definitions[s]=o,s!==r&&(this.definitions[r]=o),this}addServiceProvider(e){return this.addSingletonFactory(e,(t,s)=>s)}addScopedFactory(e,t){let s,n,i=!1;if(typeof e=="string"||typeof e=="symbol")s=e,n=this.typeMap[s],i=!0;else{let a=this.resolveKeyAndType(e);s=a.key,n=a.type}let r=i?s:c(n),o={kind:"service",lifetime:"scoped",uid:r,type:n,factory:t};return this.definitions[s]=o,s!==r&&(this.definitions[r]=o),this}addSingletonClass(e,...t){let{key:s,type:n}=this.resolveKeyAndType(e),i=c(n),r={kind:"service",lifetime:"singleton",uid:i,type:n,params:t};return this.definitions[s]=r,this.definitions[i]=r,this}addScopedClass(e,...t){let{key:s,type:n}=this.resolveKeyAndType(e),i=c(n),r={kind:"service",lifetime:"scoped",uid:i,type:n,params:t};return this.definitions[s]=r,this.definitions[i]=r,this}addSingletonGroup(e,...t){let s={kind:"service",lifetime:"singleton",uid:e,type:t};this.typeMap[e]=t,this.definitions[e]=s;let n=t;for(let i of n){if(Reflect.ownKeys(this.typeMap).find(g=>this.typeMap[g]===i))continue;let o=i.name;if(!o)throw new l(`Class in group "${String(e)}" is missing a name and cannot be auto-registered.`);let a=c(i),d={kind:"service",lifetime:"singleton",uid:a,type:i,params:[]};this.typeMap[o]=i,this.definitions[o]=d,this.definitions[a]=d}return this}addScopedGroup(e,...t){let s={kind:"service",lifetime:"scoped",uid:e,type:t};this.typeMap[e]=t,this.definitions[e]=s;let n=t;for(let i of n){if(Reflect.ownKeys(this.typeMap).find(g=>this.typeMap[g]===i))continue;let o=i.name;if(!o)throw new l(`Class in group "${String(e)}" is missing a name and cannot be auto-registered.`);let a=c(i),d={kind:"service",lifetime:"scoped",uid:a,type:i,params:[]};this.typeMap[o]=i,this.definitions[o]=d,this.definitions[a]=d}return this}addSingletonFunc(e,t,...s){return this.definitions[e]={kind:"function",lifetime:"singleton",uid:e,func:t,params:s},this}addScopedFunc(e,t,...s){return this.definitions[e]={kind:"function",lifetime:"scoped",uid:e,func:t,params:s},this}addSingletonValue(e,t){return this.definitions[e]={kind:"value",lifetime:"singleton",uid:e,value:t},this}addScopedValue(e,t){return this.definitions[e]={kind:"value",lifetime:"scoped",uid:e,value:t},this}resolveKeyAndType(e){let t,s=Reflect.ownKeys(this.typeMap).find(n=>this.typeMap[n]===e);return s?t=s:(t=e.name||c(e),this.typeMap[t]=e),{key:t,type:e}}build(e="root"){for(let t of Reflect.ownKeys(this.definitions)){let s=this.definitions[t];if(!(s.kind!=="service"||!Array.isArray(s.type)))for(let n of s.type){let i=n.name,r=this.definitions[i];if(r&&r.params&&r.params.length===0&&n.length>0)throw new l(`Class "${i}" in group "${String(t)}" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`)}}return new m(e,this.definitions)}};export{f as AsyncDisposalError,u as CircularDependencyError,l as RegistrationError,K as ServiceCollection,p as ServiceNotFoundError,m as ServiceProvider,h as ServiceProviderDisposedError};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/errors.ts", "../src/registry.ts", "../src/service-provider.ts", "../src/service-collection.ts"],
4
- "sourcesContent": ["/**\n * Thrown when a circular dependency is detected.\n */\nexport class CircularDependencyError extends Error {\n constructor(path: string) {\n super(`Circular dependency detected: ${path}`);\n this.name = 'CircularDependencyError';\n }\n}\n\n/**\n * Thrown when a service cannot be resolved.\n */\nexport class ServiceNotFoundError extends Error {\n constructor(identifier: string) {\n super(`Service not registered for identifier: ${identifier}`);\n this.name = 'ServiceNotFoundError';\n }\n}\n\n/**\n * Thrown when a registration is invalid.\n */\nexport class RegistrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RegistrationError';\n }\n}\n\n/**\n * Thrown when a service provider has been disposed.\n */\nexport class ServiceProviderDisposedError extends Error {\n constructor() {\n super('ServiceProvider has been disposed and cannot resolve services.');\n this.name = 'ServiceProviderDisposedError';\n }\n}\n\n/**\n * Thrown when a synchronous dispose is called on a scope containing services that require asynchronous disposal.\n */\nexport class AsyncDisposalError extends Error {\n constructor(serviceKey: string) {\n super(`Service \"${serviceKey}\" requires asynchronous disposal but a synchronous dispose was called. Please use await disposeAsync() instead.`);\n this.name = 'AsyncDisposalError';\n }\n}\n", "import type { Class } from './types.js';\r\n\r\nconst classKeyRegistry = new WeakMap<Class, symbol>();\r\n\r\n/**\r\n * Resolves a stable Symbol for a given class constructor.\r\n * This is used to ensure that DI resolution remains stable even after minification.\r\n * @param type The class constructor.\r\n */\r\nexport function getStableKey(type: Class): symbol {\r\n let key = classKeyRegistry.get(type);\r\n if (!key) {\r\n key = Symbol(type.name || 'AnonymousClass');\r\n classKeyRegistry.set(type, key);\r\n }\r\n return key;\r\n}\r\n", "import {\n AsyncDisposalError,\n CircularDependencyError,\n ServiceNotFoundError,\n ServiceProviderDisposedError,\n} from './errors.js';\nimport { getStableKey } from './registry.js';\nimport type {\n Class,\n ConcreteClass,\n ImplementationFactory,\n IServiceProvider,\n MapToInstance,\n ResolvedTypeMap,\n ServiceDefinitionMap,\n TypeMap,\n} from './types.js';\n\nexport class ServiceProvider<T extends TypeMap> implements IServiceProvider<T> {\n private instances = new Map<string | symbol, any>();\n private resolving = new Set<string | symbol>();\n private path: (string | symbol)[] = [];\n private disposed = false;\n\n /**\n * @param name The name of the service provider.\n * @param definitions The service definitions map.\n * @param parent The parent service provider, if any.\n * @param isAsyncScope Whether this is an asynchronous scope.\n */\n constructor(\n public readonly name: string,\n private definitions: ServiceDefinitionMap,\n private parent?: ServiceProvider<T>,\n private readonly isAsyncScope: boolean = false\n ) { }\n\n /**\n * Creates a new scoped ServiceProvider.\n * @param name The name of the scope.\n * @example\n * const scope = di.createScope('request-scope');\n */\n createScope(name: string = 'scope'): IServiceProvider<T> {\n const root = this.parent || this;\n return new ServiceProvider<T>(name, this.definitions, root, false);\n }\n\n /**\n * Creates a new scoped ServiceProvider that supports asynchronous disposal.\n * @param name The name of the scope.\n * @example\n * const scope = di.createAsyncScope('worker-scope');\n */\n createAsyncScope(name: string = 'async-scope'): IServiceProvider<T> {\n const root = this.parent || this;\n return new ServiceProvider<T>(name, this.definitions, root, true);\n }\n\n /**\n * Resolves a service by its key.\n * @param key The key to resolve.\n * @example\n * const logger = di.getService('Logger');\n */\n getService<K extends keyof T & (string | symbol)>(key: K): MapToInstance<T[K]>;\n\n /**\n * Resolves a service by its Class type.\n * @param type The class type to resolve.\n * @example\n * const logger = di.getService(Logger);\n */\n getService<C extends Class>(type: C): InstanceType<C>;\n\n getService<K extends keyof T & (string | symbol)>(keyOrType: K | T[K]): MapToInstance<T[K]> {\n if (this.disposed) {\n throw new ServiceProviderDisposedError();\n }\n\n const key = this.getKey(keyOrType);\n\n if (this.parent && this.definitions[key]?.lifetime === 'singleton') {\n return this.parent.getService(key as any);\n }\n\n const item = this.definitions[key];\n if (!item) {\n const name = (typeof keyOrType === 'string' || typeof keyOrType === 'symbol')\n ? String(keyOrType)\n : (keyOrType as any).name || String(keyOrType);\n throw new ServiceNotFoundError(name);\n }\n\n const uid = item.uid;\n\n if (this.instances.has(uid)) {\n return this.instances.get(uid);\n }\n\n if (this.resolving.has(uid)) {\n const pathStr = this.path.map(k => (typeof k === 'symbol' ? k.description || String(k) : k)).concat(typeof key === 'symbol' ? key.description || String(key) : key).join(' -> ');\n throw new CircularDependencyError(pathStr);\n }\n\n this.resolving.add(uid);\n this.path.push(key);\n\n try {\n if (item.kind === 'value') return this.resolveValue(uid, item.value);\n\n if (Array.isArray(item.type)) return this.resolveArray(uid, item.type);\n\n if (item.kind === 'function' && item.func) return this.resolveFunc(uid, item.func, item.params);\n\n if (item.factory) return this.resolveFactory(uid, item.factory);\n\n return this.resolveClass(uid, item.type as Class, item.params);\n } finally {\n this.resolving.delete(uid);\n this.path.pop();\n }\n }\n\n /**\n * Synchronously disposes of all resolved services.\n * Throws AsyncDisposalError if this is an async scope or if any service disposal returns a Promise.\n */\n dispose(): void {\n if (this.disposed) return;\n\n if (this.isAsyncScope) {\n throw new AsyncDisposalError(this.name);\n }\n\n this.disposed = true;\n\n const entries = Array.from(this.instances.entries()).reverse();\n\n for (const [uid, inst] of entries) {\n if (inst && typeof inst.dispose === 'function') {\n const result = inst.dispose();\n if (result instanceof Promise) {\n throw new AsyncDisposalError(typeof uid === 'symbol' ? uid.description || String(uid) : String(uid));\n }\n } else if (inst && typeof inst.disposeAsync === 'function') {\n throw new AsyncDisposalError(typeof uid === 'symbol' ? uid.description || String(uid) : String(uid));\n }\n }\n\n this.instances.clear();\n }\n\n /**\n * Asynchronously disposes of all resolved services.\n */\n async disposeAsync(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n\n const entries = Array.from(this.instances.values()).reverse();\n\n for (const inst of entries) {\n if (inst && typeof inst.disposeAsync === 'function') {\n await inst.disposeAsync();\n } else if (inst && typeof inst.dispose === 'function') {\n const result = inst.dispose();\n if (result instanceof Promise) {\n await result;\n }\n }\n }\n\n this.instances.clear();\n }\n\n /**\n * Resolves a singleton value.\n * @param uid The unique ID of the value.\n * @param value The value to resolve.\n */\n private resolveValue(uid: string | symbol, value: any): any {\n this.instances.set(uid, value);\n return value;\n }\n\n /**\n * Resolves an array of services.\n * @param uid The unique ID of the service array.\n * @param types The class types to resolve for the array.\n */\n private resolveArray(uid: string | symbol, types: Class[]): any {\n const instances = types.map((cls) => {\n const inst = this.getService(cls);\n return inst;\n });\n\n this.instances.set(uid, instances);\n return instances;\n }\n\n /**\n * Resolves a service via a factory.\n * @param uid The unique ID of the service.\n * @param factory The factory to use for resolution.\n */\n private resolveFactory(uid: string | symbol, factory: ImplementationFactory<any, any>): any {\n const container = this.createContainerProxy();\n const result = factory(container, this);\n this.instances.set(uid, result);\n return result;\n }\n\n /**\n * Resolves a service via a function.\n * @param uid The unique ID of the service.\n * @param func The function to use for resolution.\n * @param params The arguments for the function.\n */\n private resolveFunc(uid: string | symbol, func: (...args: any[]) => any, params?: any[]): any {\n const rawParams = params || [];\n const resolvedParams = rawParams.map((param) => {\n const paramKey = this.tryGetKey(param);\n const inst = paramKey ? this.getService(paramKey) : param;\n return inst;\n });\n\n const result = func(...resolvedParams);\n this.instances.set(uid, result);\n return result;\n }\n\n /**\n * Resolves a service via its class type.\n * @param uid The unique ID of the service.\n * @param type The class type to instantiate.\n * @param params The constructor arguments.\n */\n private resolveClass(uid: string | symbol, type: Class, params?: any[]): any {\n const rawParams = params || [];\n const resolvedParams = rawParams.map((param) => {\n const paramKey = this.tryGetKey(param);\n const inst = paramKey ? this.getService(paramKey) : param;\n return inst;\n });\n\n const instance = new (type as ConcreteClass)(...resolvedParams);\n this.instances.set(uid, instance);\n return instance;\n }\n\n /**\n * Creates a proxy for the type map to allow resolving services by property access.\n */\n private createContainerProxy(): ResolvedTypeMap<T> {\n return new Proxy({} as ResolvedTypeMap<T>, {\n get: (_, prop) => {\n if (typeof prop !== 'string' && typeof prop !== 'symbol') return undefined;\n return this.getService(prop as any);\n }\n });\n }\n\n /**\n * Gets the key for a given key or class type.\n * @param keyOrType The key or class type.\n */\n private getKey<K extends keyof T & (string | symbol)>(keyOrType: K | T[K]): string | symbol {\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') return keyOrType;\n\n const key = this.tryGetKey(keyOrType);\n if (key) return key;\n\n const name = Array.isArray(keyOrType)\n ? `[${keyOrType.map((c: any) => (c as any).name).join(', ')}]`\n : (keyOrType as any).name || String(keyOrType);\n throw new ServiceNotFoundError(name);\n }\n\n /**\n * Attempts to get the key for a given key or class type without throwing.\n * @param keyOrType The key or class type.\n */\n private tryGetKey(keyOrType: any): string | symbol | undefined {\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n if (keyOrType in this.definitions) return keyOrType;\n \n // Fallback for string names (backward compatibility)\n if (typeof keyOrType === 'string') {\n const entry = Reflect.ownKeys(this.definitions).find((k) => {\n const v = this.definitions[k as any];\n return v.kind === 'service' && !Array.isArray(v.type) && (v.type as any)?.name === keyOrType;\n });\n if (entry) return entry as string | symbol;\n }\n return undefined;\n }\n\n if (typeof keyOrType === 'function' || Array.isArray(keyOrType)) {\n // Check the stable registry first (minification proof)\n const stableKey = getStableKey(keyOrType as any);\n if (stableKey in this.definitions) return stableKey;\n\n // Fallback to searching by reference (for explicit symbols or non-auto registrations)\n const entry = Reflect.ownKeys(this.definitions).find((k) => {\n const v = this.definitions[k as any];\n return v.kind === 'service' && v.type === keyOrType;\n });\n if (entry) return entry as string | symbol;\n }\n\n return undefined;\n }\n}\n", "import {\n RegistrationError,\n} from './errors.js';\nimport { getStableKey } from './registry.js';\nimport { ServiceProvider } from './service-provider.js';\nimport type {\n Class,\n ClassArgs,\n FilterKeys,\n FilterValueKeys,\n FilterFuncKeys,\n FuncArgs,\n ImplementationFactory,\n MapToInstance,\n ServiceDefinitionMap,\n TypeMap,\n ServiceDefinition\n} from './types.js';\n\n/**\n * Fluent builder for service collections using a lookup map.\n */\nexport class ServiceCollection<T extends TypeMap> {\n private definitions: ServiceDefinitionMap = {};\n private typeMap: T;\n\n /**\n * Initializes a new instance of the ServiceCollection class.\n */\n constructor() {\n this.typeMap = {} as T;\n }\n\n /**\n * Adds a singleton service using a factory function.\n * Key is derived from the class.\n * @param type The class to register.\n * @param factory The factory function to create the service instance.\n * @example\n * .addSingletonFactory(UserRepo, (c) => new UserRepo(c.UserService))\n */\n addSingletonFactory<Key extends keyof T & (string | symbol), C extends Class>(\n type: C,\n factory: ImplementationFactory<T, InstanceType<C>>\n ): this;\n\n /**\n * Adds a singleton service using a factory function and a key.\n * @param key The key to register the service under.\n * @param factory The factory function to create the service instance.\n * @example\n * .addSingletonFactory(\"UserRepo\", (c) => new UserRepo(c.UserService))\n */\n addSingletonFactory<Key extends keyof T & (string | symbol)>(\n key: Key,\n factory: ImplementationFactory<T, MapToInstance<T[Key]>>\n ): this;\n\n addSingletonFactory<Key extends keyof T & (string | symbol)>(\n keyOrType: Key | Class,\n factory: ImplementationFactory<T, any>\n ): this {\n let key: string | symbol;\n let type: any;\n let isExplicitKey = false;\n\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n key = keyOrType;\n type = this.typeMap[key];\n isExplicitKey = true;\n } else {\n const resolved = this.resolveKeyAndType<Key>(keyOrType as any);\n key = resolved.key;\n type = resolved.type;\n }\n\n const uid = isExplicitKey ? key : getStableKey(type);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type, factory };\n this.definitions[key] = def;\n if (key !== uid) this.definitions[uid] = def;\n\n return this;\n }\n\n /**\n * Registers the ServiceProvider itself as a service.\n * This allows services to depend on the ServiceProvider to resolve other services dynamically.\n * @param key The key to register the ServiceProvider under.\n * @example\n * .addServiceProvider(\"ServiceProvider\")\n */\n addServiceProvider<Key extends keyof T & (string | symbol)>(key: Key) {\n return this.addSingletonFactory(key as any, (_, sp) => sp)\n }\n\n /**\n * Adds a scoped service using a factory function.\n * Key is derived from the class.\n * @param type The class to register.\n * @param factory The factory function to create the service instance.\n * @example\n * .addScopedFactory(UserRepo, (c) => new UserRepo(c.UserService))\n */\n addScopedFactory<Key extends keyof T & (string | symbol), C extends Class>(\n type: C,\n factory: ImplementationFactory<T, InstanceType<C>>\n ): this;\n\n /**\n * Adds a scoped service using a factory function and a key.\n * @param key The key to register the service under.\n * @param factory The factory function to create the service instance.\n * @example\n * .addScopedFactory(\"UserRepo\", (c) => new UserRepo(c.UserService))\n */\n addScopedFactory<Key extends keyof T & (string | symbol)>(\n key: Key,\n factory: ImplementationFactory<T, MapToInstance<T[Key]>>\n ): this;\n\n addScopedFactory<Key extends keyof T & (string | symbol)>(\n keyOrType: Key | Class,\n factory: ImplementationFactory<T, any>\n ): this {\n let key: string | symbol;\n let type: any;\n let isExplicitKey = false;\n\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n key = keyOrType;\n type = this.typeMap[key];\n isExplicitKey = true;\n } else {\n const resolved = this.resolveKeyAndType<Key>(keyOrType as any);\n key = resolved.key;\n type = resolved.type;\n }\n\n const uid = isExplicitKey ? key : getStableKey(type);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type, factory };\n this.definitions[key] = def;\n if (key !== uid) this.definitions[uid] = def;\n\n return this;\n }\n\n /**\n * Adds a singleton service using constructor injection.\n * Key is derived from the container map based on the Class.\n * @param type The class to register.\n * @param params The constructor arguments.\n * @example\n * .addSingletonClass(UserService, \"admin\", \"password\")\n */\n addSingletonClass<C extends Class>(\n type: C,\n ...params: ClassArgs<C, keyof T & (string | symbol)>\n ): this {\n const { key, type: typeRef } = this.resolveKeyAndType(type as any);\n const uid = getStableKey(typeRef);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type: typeRef, params };\n this.definitions[key] = def;\n this.definitions[uid] = def;\n return this;\n }\n\n /**\n * Adds a scoped service using constructor injection.\n * Key is derived from the container map based on the Class.\n * @param type The class to register.\n * @param params The constructor arguments.\n * @example\n * .addScopedClass(UserService, \"admin\", \"password\")\n */\n addScopedClass<C extends Class>(\n type: C,\n ...params: ClassArgs<C, keyof T & (string | symbol)>\n ): this {\n const { key, type: typeRef } = this.resolveKeyAndType(type as any);\n const uid = getStableKey(typeRef);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type: typeRef, params };\n this.definitions[key] = def;\n this.definitions[uid] = def;\n return this;\n }\n\n /**\n * Adds an array of singleton services.\n * Automatically registers individual classes if not already registered.\n * @param key The key for the service array.\n * @param types The classes to register in the array.\n * @example\n * .addSingletonArray(\"MessageCommand\", HelloCommand, ByeCommand)\n */\n addSingletonArray<\n Key extends FilterKeys<T, any[]>,\n C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]\n >(\n key: Key,\n ...types: C\n ): this {\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid: key, type: types };\n (this.typeMap as any)[key] = types;\n this.definitions[key] = def;\n\n // Auto-register individual classes if not already registered\n const typeArray = types as Class[];\n for (const type of typeArray) {\n const foundKey = Reflect.ownKeys(this.typeMap).find(k => this.typeMap[k as any] === type);\n if (foundKey) continue;\n\n const name = type.name;\n if (!name) {\n throw new RegistrationError(`Class in array \"${String(key)}\" is missing a name and cannot be auto-registered.`);\n }\n\n const uid = getStableKey(type);\n const classDef: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type, params: [] };\n (this.typeMap as any)[name] = type;\n this.definitions[name] = classDef;\n this.definitions[uid] = classDef;\n }\n\n return this;\n }\n\n /**\n * Adds an array of scoped services.\n * Automatically registers individual classes as scoped if not already registered.\n * @param key The key for the service array.\n * @param types The classes to register in the array.\n * @example\n * .addScopedArray(\"MessageCommand\", HelloCommand, ByeCommand)\n */\n addScopedArray<\n Key extends FilterKeys<T, any[]>,\n C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]\n >(\n key: Key,\n ...types: C\n ): this {\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid: key, type: types };\n (this.typeMap as any)[key] = types;\n this.definitions[key] = def;\n\n // Auto-register individual classes if not already registered\n const typeArray = types as Class[];\n for (const type of typeArray) {\n const foundKey = Reflect.ownKeys(this.typeMap).find(k => this.typeMap[k as any] === type);\n if (foundKey) continue;\n\n const name = type.name;\n if (!name) {\n throw new RegistrationError(`Class in array \"${String(key)}\" is missing a name and cannot be auto-registered.`);\n }\n\n const uid = getStableKey(type);\n const classDef: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type, params: [] };\n (this.typeMap as any)[name] = type;\n this.definitions[name] = classDef;\n this.definitions[uid] = classDef;\n }\n\n return this;\n }\n\n /**\n * Adds a singleton service using a function.\n * @param key The key for the service.\n * @param func The function to register.\n * @param params The function arguments.\n * @example\n * .addSingletonFunc(\"Logger\", createLogger, \"Config\")\n */\n addSingletonFunc<Key extends FilterFuncKeys<T>, F extends (...args: any[]) => T[Key]>(\n key: Key,\n func: F,\n ...params: FuncArgs<F, T>\n ): this {\n this.definitions[key] = { kind: 'function', lifetime: 'singleton', uid: key, func, params };\n return this;\n }\n\n /**\n * Adds a scoped service using a function.\n * @param key The key for the service.\n * @param func The function to register.\n * @param params The function arguments.\n * @example\n * .addScopedFunc(\"Logger\", createLogger, \"Config\")\n */\n addScopedFunc<Key extends FilterFuncKeys<T>, F extends (...args: any[]) => T[Key]>(\n key: Key,\n func: F,\n ...params: FuncArgs<F, T>\n ): this {\n this.definitions[key] = { kind: 'function', lifetime: 'scoped', uid: key, func, params };\n return this;\n }\n\n /**\n * Adds a singleton value.\n * @param key The key for the value.\n * @param value The value to register.\n * @example\n * .addSingletonValue(\"connectionString\", \"test connection string\")\n */\n addSingletonValue<Key extends FilterValueKeys<T>>(\n key: Key,\n value: T[Key]\n ): this {\n this.definitions[key] = { kind: 'value', lifetime: 'singleton', uid: key, value };\n return this;\n }\n\n /**\n * Adds a scoped value.\n * @param key The key for the value.\n * @param value The value to register.\n * @example\n * .addScopedValue(\"connectionString\", \"test connection string\")\n */\n addScopedValue<Key extends FilterValueKeys<T>>(\n key: Key,\n value: T[Key]\n ): this {\n this.definitions[key] = { kind: 'value', lifetime: 'scoped', uid: key, value };\n return this;\n }\n\n /**\n * Resolves the string key and Class reference for a given type.\n * If the type is already mapped in the TypeMap, the existing key is used.\n * Otherwise, it auto-registers the type using its class name as the key.\n * @param type The class reference to resolve.\n * @throws RegistrationError if the class name cannot be determined (e.g. anonymous class).\n * @example\n * const { key, type } = this.resolveKeyAndType(UserService);\n */\n private resolveKeyAndType<Key extends keyof T & (string | symbol)>(type: T[Key] & Class): { key: Key, type: T[Key] } {\n let key: Key;\n\n const foundKey = Reflect.ownKeys(this.typeMap).find(\n (k) => this.typeMap[k as any] === type\n );\n if (foundKey) {\n key = foundKey as Key;\n } else {\n // Auto-register using class name for backward compatibility\n key = (type.name || getStableKey(type)) as any as Key;\n (this.typeMap as any)[key] = type;\n }\n\n return { key, type };\n }\n\n /**\n * Builds the ServiceProvider.\n * @param name The name of the service provider.\n * @example\n * const di = new ServiceCollection<LocalMap>()\n * .addSingletonClass(MyService)\n * .build();\n */\n build(name: string = 'root'): ServiceProvider<T> {\n // Validate all registered services\n for (const key of Reflect.ownKeys(this.definitions)) {\n const item = this.definitions[key as any];\n if (item.kind !== 'service' || !Array.isArray(item.type)) continue;\n\n // This is an array of services\n for (const type of item.type as Class[]) {\n const name = type.name;\n const definitionsItem = this.definitions[name];\n\n // Check if this class was auto-registered (params is empty array) but requires arguments\n if (definitionsItem && definitionsItem.params && definitionsItem.params.length === 0 && type.length > 0) {\n throw new RegistrationError(`Class \"${name}\" in array \"${String(key)}\" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`);\n }\n }\n }\n\n return new ServiceProvider<T>(name, this.definitions);\n }\n}\n"],
4
+ "sourcesContent": ["/**\n * Thrown when a circular dependency is detected.\n */\nexport class CircularDependencyError extends Error {\n constructor(path: string) {\n super(`Circular dependency detected: ${path}`);\n this.name = 'CircularDependencyError';\n }\n}\n\n/**\n * Thrown when a service cannot be resolved.\n */\nexport class ServiceNotFoundError extends Error {\n constructor(identifier: string) {\n super(`Service not registered for identifier: ${identifier}`);\n this.name = 'ServiceNotFoundError';\n }\n}\n\n/**\n * Thrown when a registration is invalid.\n */\nexport class RegistrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RegistrationError';\n }\n}\n\n/**\n * Thrown when a service provider has been disposed.\n */\nexport class ServiceProviderDisposedError extends Error {\n constructor() {\n super('ServiceProvider has been disposed and cannot resolve services.');\n this.name = 'ServiceProviderDisposedError';\n }\n}\n\n/**\n * Thrown when a synchronous dispose is called on a scope containing services that require asynchronous disposal.\n */\nexport class AsyncDisposalError extends Error {\n constructor(serviceKey: string) {\n super(`Service \"${serviceKey}\" requires asynchronous disposal but a synchronous dispose was called. Please use await disposeAsync() instead.`);\n this.name = 'AsyncDisposalError';\n }\n}\n", "import type { Class } from './types.js';\r\n\r\nconst classKeyRegistry = new WeakMap<Class, symbol>();\r\n\r\n/**\r\n * Resolves a stable Symbol for a given class constructor.\r\n * This is used to ensure that DI resolution remains stable even after minification.\r\n * @param type The class constructor.\r\n */\r\nexport function getStableKey(type: Class): symbol {\r\n let key = classKeyRegistry.get(type);\r\n if (!key) {\r\n key = Symbol(type.name || 'AnonymousClass');\r\n classKeyRegistry.set(type, key);\r\n }\r\n return key;\r\n}\r\n", "import {\n AsyncDisposalError,\n CircularDependencyError,\n ServiceNotFoundError,\n ServiceProviderDisposedError,\n} from './errors.js';\nimport { getStableKey } from './registry.js';\nimport type {\n Class,\n ConcreteClass,\n ImplementationFactory,\n IServiceProvider,\n MapToInstance,\n ResolvedTypeMap,\n ServiceDefinitionMap,\n TypeMap,\n} from './types.js';\n\nexport class ServiceProvider<T extends TypeMap> implements IServiceProvider<T> {\n private instances = new Map<string | symbol, any>();\n private resolving = new Set<string | symbol>();\n private path: (string | symbol)[] = [];\n private disposed = false;\n\n /**\n * @param name The name of the service provider.\n * @param definitions The service definitions map.\n * @param parent The parent service provider, if any.\n * @param isAsyncScope Whether this is an asynchronous scope.\n */\n constructor(\n public readonly name: string,\n private definitions: ServiceDefinitionMap,\n private parent?: ServiceProvider<T>,\n private readonly isAsyncScope: boolean = false\n ) { }\n\n /**\n * Creates a new scoped ServiceProvider.\n * @param name The name of the scope.\n * @example\n * const scope = di.createScope('request-scope');\n */\n createScope(name: string = 'scope'): IServiceProvider<T> {\n const root = this.parent || this;\n return new ServiceProvider<T>(name, this.definitions, root, false);\n }\n\n /**\n * Creates a new scoped ServiceProvider that supports asynchronous disposal.\n * @param name The name of the scope.\n * @example\n * const scope = di.createAsyncScope('worker-scope');\n */\n createAsyncScope(name: string = 'async-scope'): IServiceProvider<T> {\n const root = this.parent || this;\n return new ServiceProvider<T>(name, this.definitions, root, true);\n }\n\n /**\n * Resolves a service by its key.\n * @param key The key to resolve.\n * @example\n * const logger = di.getService('Logger');\n */\n getService<K extends keyof T & (string | symbol)>(key: K): MapToInstance<T[K]>;\n\n /**\n * Resolves a service by its Class type.\n * @param type The class type to resolve.\n * @example\n * const logger = di.getService(Logger);\n */\n getService<C extends Class>(type: C): InstanceType<C>;\n\n getService<K extends keyof T & (string | symbol)>(keyOrType: K | T[K]): MapToInstance<T[K]> {\n if (this.disposed) {\n throw new ServiceProviderDisposedError();\n }\n\n const key = this.getKey(keyOrType);\n\n if (this.parent && this.definitions[key]?.lifetime === 'singleton') {\n return this.parent.getService(key as any);\n }\n\n const item = this.definitions[key];\n if (!item) {\n const name = (typeof keyOrType === 'string' || typeof keyOrType === 'symbol')\n ? String(keyOrType)\n : (keyOrType as any).name || String(keyOrType);\n throw new ServiceNotFoundError(name);\n }\n\n const uid = item.uid;\n\n if (this.instances.has(uid)) {\n return this.instances.get(uid);\n }\n\n if (this.resolving.has(uid)) {\n const pathStr = this.path.map(k => (typeof k === 'symbol' ? k.description || String(k) : k)).concat(typeof key === 'symbol' ? key.description || String(key) : key).join(' -> ');\n throw new CircularDependencyError(pathStr);\n }\n\n this.resolving.add(uid);\n this.path.push(key);\n\n try {\n if (item.kind === 'value') return this.resolveValue(uid, item.value);\n\n if (Array.isArray(item.type)) return this.resolveArray(uid, item.type);\n\n if (item.kind === 'function' && item.func) return this.resolveFunc(uid, item.func, item.params);\n\n if (item.factory) return this.resolveFactory(uid, item.factory);\n\n return this.resolveClass(uid, item.type as Class, item.params);\n } finally {\n this.resolving.delete(uid);\n this.path.pop();\n }\n }\n\n /**\n * Synchronously disposes of all resolved services.\n * Throws AsyncDisposalError if this is an async scope or if any service disposal returns a Promise.\n */\n dispose(): void {\n if (this.disposed) return;\n\n if (this.isAsyncScope) {\n throw new AsyncDisposalError(this.name);\n }\n\n this.disposed = true;\n\n const entries = Array.from(this.instances.entries()).reverse();\n\n for (const [uid, inst] of entries) {\n if (inst && typeof inst.dispose === 'function') {\n const result = inst.dispose();\n if (result instanceof Promise) {\n throw new AsyncDisposalError(typeof uid === 'symbol' ? uid.description || String(uid) : String(uid));\n }\n } else if (inst && typeof inst.disposeAsync === 'function') {\n throw new AsyncDisposalError(typeof uid === 'symbol' ? uid.description || String(uid) : String(uid));\n }\n }\n\n this.instances.clear();\n }\n\n /**\n * Asynchronously disposes of all resolved services.\n */\n async disposeAsync(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n\n const entries = Array.from(this.instances.values()).reverse();\n\n for (const inst of entries) {\n if (inst && typeof inst.disposeAsync === 'function') {\n await inst.disposeAsync();\n } else if (inst && typeof inst.dispose === 'function') {\n const result = inst.dispose();\n if (result instanceof Promise) {\n await result;\n }\n }\n }\n\n this.instances.clear();\n }\n\n /**\n * Resolves a singleton value.\n * @param uid The unique ID of the value.\n * @param value The value to resolve.\n */\n private resolveValue(uid: string | symbol, value: any): any {\n this.instances.set(uid, value);\n return value;\n }\n\n /**\n * Resolves an array of services.\n * @param uid The unique ID of the service array.\n * @param types The class types to resolve for the array.\n */\n private resolveArray(uid: string | symbol, types: Class[]): any {\n const instances = types.map((cls) => {\n const inst = this.getService(cls);\n return inst;\n });\n\n this.instances.set(uid, instances);\n return instances;\n }\n\n /**\n * Resolves a service via a factory.\n * @param uid The unique ID of the service.\n * @param factory The factory to use for resolution.\n */\n private resolveFactory(uid: string | symbol, factory: ImplementationFactory<any, any>): any {\n const container = this.createContainerProxy();\n const result = factory(container, this);\n this.instances.set(uid, result);\n return result;\n }\n\n /**\n * Resolves a service via a function.\n * @param uid The unique ID of the service.\n * @param func The function to use for resolution.\n * @param params The arguments for the function.\n */\n private resolveFunc(uid: string | symbol, func: (...args: any[]) => any, params?: any[]): any {\n const rawParams = params || [];\n const resolvedParams = rawParams.map((param) => {\n const paramKey = this.tryGetKey(param);\n const inst = paramKey ? this.getService(paramKey) : param;\n return inst;\n });\n\n const result = func(...resolvedParams);\n this.instances.set(uid, result);\n return result;\n }\n\n /**\n * Resolves a service via its class type.\n * @param uid The unique ID of the service.\n * @param type The class type to instantiate.\n * @param params The constructor arguments.\n */\n private resolveClass(uid: string | symbol, type: Class, params?: any[]): any {\n const rawParams = params || [];\n const resolvedParams = rawParams.map((param) => {\n const paramKey = this.tryGetKey(param);\n const inst = paramKey ? this.getService(paramKey) : param;\n return inst;\n });\n\n const instance = new (type as ConcreteClass)(...resolvedParams);\n this.instances.set(uid, instance);\n return instance;\n }\n\n /**\n * Creates a proxy for the type map to allow resolving services by property access.\n */\n private createContainerProxy(): ResolvedTypeMap<T> {\n return new Proxy({} as ResolvedTypeMap<T>, {\n get: (_, prop) => {\n if (typeof prop !== 'string' && typeof prop !== 'symbol') return undefined;\n return this.getService(prop as any);\n }\n });\n }\n\n /**\n * Gets the key for a given key or class type.\n * @param keyOrType The key or class type.\n */\n private getKey<K extends keyof T & (string | symbol)>(keyOrType: K | T[K]): string | symbol {\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') return keyOrType;\n\n const key = this.tryGetKey(keyOrType);\n if (key) return key;\n\n const name = Array.isArray(keyOrType)\n ? `[${keyOrType.map((c: any) => (c as any).name).join(', ')}]`\n : (keyOrType as any).name || String(keyOrType);\n throw new ServiceNotFoundError(name);\n }\n\n /**\n * Attempts to get the key for a given key or class type without throwing.\n * @param keyOrType The key or class type.\n */\n private tryGetKey(keyOrType: any): string | symbol | undefined {\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n if (keyOrType in this.definitions) return keyOrType;\n \n // Fallback for string names (backward compatibility)\n if (typeof keyOrType === 'string') {\n const entry = Reflect.ownKeys(this.definitions).find((k) => {\n const v = this.definitions[k as any];\n return v.kind === 'service' && !Array.isArray(v.type) && (v.type as any)?.name === keyOrType;\n });\n if (entry) return entry as string | symbol;\n }\n return undefined;\n }\n\n if (typeof keyOrType === 'function' || Array.isArray(keyOrType)) {\n // Check the stable registry first (minification proof)\n const stableKey = getStableKey(keyOrType as any);\n if (stableKey in this.definitions) return stableKey;\n\n // Fallback to searching by reference (for explicit symbols or non-auto registrations)\n const entry = Reflect.ownKeys(this.definitions).find((k) => {\n const v = this.definitions[k as any];\n return v.kind === 'service' && v.type === keyOrType;\n });\n if (entry) return entry as string | symbol;\n }\n\n return undefined;\n }\n}\n", "import {\n RegistrationError,\n} from './errors.js';\nimport { getStableKey } from './registry.js';\nimport { ServiceProvider } from './service-provider.js';\nimport type {\n Class,\n ClassArgs,\n FilterKeys,\n FilterValueKeys,\n FilterFuncKeys,\n FuncArgs,\n ImplementationFactory,\n MapToInstance,\n ServiceDefinitionMap,\n TypeMap,\n ServiceDefinition\n} from './types.js';\n\n/**\n * Fluent builder for service collections using a lookup map.\n */\nexport class ServiceCollection<T extends TypeMap> {\n private definitions: ServiceDefinitionMap = {};\n private typeMap: T;\n\n /**\n * Initializes a new instance of the ServiceCollection class.\n */\n constructor() {\n this.typeMap = {} as T;\n }\n\n /**\n * Adds a singleton service using a factory function.\n * Key is derived from the class.\n * @param type The class to register.\n * @param factory The factory function to create the service instance.\n * @example\n * .addSingletonFactory(UserRepo, (c) => new UserRepo(c.UserService))\n */\n addSingletonFactory<Key extends keyof T & (string | symbol), C extends Class>(\n type: C,\n factory: ImplementationFactory<T, InstanceType<C>>\n ): this;\n\n /**\n * Adds a singleton service using a factory function and a key.\n * @param key The key to register the service under.\n * @param factory The factory function to create the service instance.\n * @example\n * .addSingletonFactory(\"UserRepo\", (c) => new UserRepo(c.UserService))\n */\n addSingletonFactory<Key extends keyof T & (string | symbol)>(\n key: Key,\n factory: ImplementationFactory<T, MapToInstance<T[Key]>>\n ): this;\n\n addSingletonFactory<Key extends keyof T & (string | symbol)>(\n keyOrType: Key | Class,\n factory: ImplementationFactory<T, any>\n ): this {\n let key: string | symbol;\n let type: any;\n let isExplicitKey = false;\n\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n key = keyOrType;\n type = this.typeMap[key];\n isExplicitKey = true;\n } else {\n const resolved = this.resolveKeyAndType<Key>(keyOrType as any);\n key = resolved.key;\n type = resolved.type;\n }\n\n const uid = isExplicitKey ? key : getStableKey(type);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type, factory };\n this.definitions[key] = def;\n if (key !== uid) this.definitions[uid] = def;\n\n return this;\n }\n\n /**\n * Registers the ServiceProvider itself as a service.\n * This allows services to depend on the ServiceProvider to resolve other services dynamically.\n * @param key The key to register the ServiceProvider under.\n * @example\n * .addServiceProvider(\"ServiceProvider\")\n */\n addServiceProvider<Key extends keyof T & (string | symbol)>(key: Key) {\n return this.addSingletonFactory(key as any, (_, sp) => sp)\n }\n\n /**\n * Adds a scoped service using a factory function.\n * Key is derived from the class.\n * @param type The class to register.\n * @param factory The factory function to create the service instance.\n * @example\n * .addScopedFactory(UserRepo, (c) => new UserRepo(c.UserService))\n */\n addScopedFactory<Key extends keyof T & (string | symbol), C extends Class>(\n type: C,\n factory: ImplementationFactory<T, InstanceType<C>>\n ): this;\n\n /**\n * Adds a scoped service using a factory function and a key.\n * @param key The key to register the service under.\n * @param factory The factory function to create the service instance.\n * @example\n * .addScopedFactory(\"UserRepo\", (c) => new UserRepo(c.UserService))\n */\n addScopedFactory<Key extends keyof T & (string | symbol)>(\n key: Key,\n factory: ImplementationFactory<T, MapToInstance<T[Key]>>\n ): this;\n\n addScopedFactory<Key extends keyof T & (string | symbol)>(\n keyOrType: Key | Class,\n factory: ImplementationFactory<T, any>\n ): this {\n let key: string | symbol;\n let type: any;\n let isExplicitKey = false;\n\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n key = keyOrType;\n type = this.typeMap[key];\n isExplicitKey = true;\n } else {\n const resolved = this.resolveKeyAndType<Key>(keyOrType as any);\n key = resolved.key;\n type = resolved.type;\n }\n\n const uid = isExplicitKey ? key : getStableKey(type);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type, factory };\n this.definitions[key] = def;\n if (key !== uid) this.definitions[uid] = def;\n\n return this;\n }\n\n /**\n * Adds a singleton service using constructor injection.\n * Key is derived from the container map based on the Class.\n * @param type The class to register.\n * @param params The constructor arguments.\n * @example\n * .addSingletonClass(UserService, \"admin\", \"password\")\n */\n addSingletonClass<C extends Class>(\n type: C,\n ...params: ClassArgs<C, keyof T & (string | symbol)>\n ): this {\n const { key, type: typeRef } = this.resolveKeyAndType(type as any);\n const uid = getStableKey(typeRef);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type: typeRef, params };\n this.definitions[key] = def;\n this.definitions[uid] = def;\n return this;\n }\n\n /**\n * Adds a scoped service using constructor injection.\n * Key is derived from the container map based on the Class.\n * @param type The class to register.\n * @param params The constructor arguments.\n * @example\n * .addScopedClass(UserService, \"admin\", \"password\")\n */\n addScopedClass<C extends Class>(\n type: C,\n ...params: ClassArgs<C, keyof T & (string | symbol)>\n ): this {\n const { key, type: typeRef } = this.resolveKeyAndType(type as any);\n const uid = getStableKey(typeRef);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type: typeRef, params };\n this.definitions[key] = def;\n this.definitions[uid] = def;\n return this;\n }\n\n /**\n * Adds a group (array) of singleton services.\n * Automatically registers individual classes as singletons if not already registered.\n * @param key The key for the service group.\n * @param types The classes to register in the group.\n * @example\n * .addSingletonGroup(\"MessageCommand\", HelloCommand, ByeCommand)\n */\n addSingletonGroup<\n Key extends FilterKeys<T, any[]>,\n C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]\n >(\n key: Key,\n ...types: C\n ): this {\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid: key, type: types };\n (this.typeMap as any)[key] = types;\n this.definitions[key] = def;\n\n // Auto-register individual classes if not already registered\n const typeArray = types as Class[];\n for (const type of typeArray) {\n const foundKey = Reflect.ownKeys(this.typeMap).find(k => this.typeMap[k as any] === type);\n if (foundKey) continue;\n\n const name = type.name;\n if (!name) {\n throw new RegistrationError(`Class in group \"${String(key)}\" is missing a name and cannot be auto-registered.`);\n }\n\n const uid = getStableKey(type);\n const classDef: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type, params: [] };\n (this.typeMap as any)[name] = type;\n this.definitions[name] = classDef;\n this.definitions[uid] = classDef;\n }\n\n return this;\n }\n\n /**\n * Adds a group (array) of scoped services.\n * Automatically registers individual classes as scoped if not already registered.\n * @param key The key for the service group.\n * @param types The classes to register in the group.\n * @example\n * .addScopedGroup(\"MessageCommand\", HelloCommand, ByeCommand)\n */\n addScopedGroup<\n Key extends FilterKeys<T, any[]>,\n C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]\n >(\n key: Key,\n ...types: C\n ): this {\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid: key, type: types };\n (this.typeMap as any)[key] = types;\n this.definitions[key] = def;\n\n // Auto-register individual classes if not already registered\n const typeArray = types as Class[];\n for (const type of typeArray) {\n const foundKey = Reflect.ownKeys(this.typeMap).find(k => this.typeMap[k as any] === type);\n if (foundKey) continue;\n\n const name = type.name;\n if (!name) {\n throw new RegistrationError(`Class in group \"${String(key)}\" is missing a name and cannot be auto-registered.`);\n }\n\n const uid = getStableKey(type);\n const classDef: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type, params: [] };\n (this.typeMap as any)[name] = type;\n this.definitions[name] = classDef;\n this.definitions[uid] = classDef;\n }\n\n return this;\n }\n\n /**\n * Adds a singleton service using a function.\n * @param key The key for the service.\n * @param func The function to register.\n * @param params The function arguments.\n * @example\n * .addSingletonFunc(\"Logger\", createLogger, \"Config\")\n */\n addSingletonFunc<Key extends FilterFuncKeys<T>, F extends (...args: any[]) => T[Key]>(\n key: Key,\n func: F,\n ...params: FuncArgs<F, T>\n ): this {\n this.definitions[key] = { kind: 'function', lifetime: 'singleton', uid: key, func, params };\n return this;\n }\n\n /**\n * Adds a scoped service using a function.\n * @param key The key for the service.\n * @param func The function to register.\n * @param params The function arguments.\n * @example\n * .addScopedFunc(\"Logger\", createLogger, \"Config\")\n */\n addScopedFunc<Key extends FilterFuncKeys<T>, F extends (...args: any[]) => T[Key]>(\n key: Key,\n func: F,\n ...params: FuncArgs<F, T>\n ): this {\n this.definitions[key] = { kind: 'function', lifetime: 'scoped', uid: key, func, params };\n return this;\n }\n\n /**\n * Adds a singleton value.\n * @param key The key for the value.\n * @param value The value to register.\n * @example\n * .addSingletonValue(\"connectionString\", \"test connection string\")\n */\n addSingletonValue<Key extends FilterValueKeys<T>>(\n key: Key,\n value: T[Key]\n ): this {\n this.definitions[key] = { kind: 'value', lifetime: 'singleton', uid: key, value };\n return this;\n }\n\n /**\n * Adds a scoped value.\n * @param key The key for the value.\n * @param value The value to register.\n * @example\n * .addScopedValue(\"connectionString\", \"test connection string\")\n */\n addScopedValue<Key extends FilterValueKeys<T>>(\n key: Key,\n value: T[Key]\n ): this {\n this.definitions[key] = { kind: 'value', lifetime: 'scoped', uid: key, value };\n return this;\n }\n\n /**\n * Resolves the string key and Class reference for a given type.\n * If the type is already mapped in the TypeMap, the existing key is used.\n * Otherwise, it auto-registers the type using its class name as the key.\n * @param type The class reference to resolve.\n * @throws RegistrationError if the class name cannot be determined (e.g. anonymous class).\n * @example\n * const { key, type } = this.resolveKeyAndType(UserService);\n */\n private resolveKeyAndType<Key extends keyof T & (string | symbol)>(type: T[Key] & Class): { key: Key, type: T[Key] } {\n let key: Key;\n\n const foundKey = Reflect.ownKeys(this.typeMap).find(\n (k) => this.typeMap[k as any] === type\n );\n if (foundKey) {\n key = foundKey as Key;\n } else {\n // Auto-register using class name for backward compatibility\n key = (type.name || getStableKey(type)) as any as Key;\n (this.typeMap as any)[key] = type;\n }\n\n return { key, type };\n }\n\n /**\n * Builds the ServiceProvider.\n * @param name The name of the service provider.\n * @example\n * const di = new ServiceCollection<LocalMap>()\n * .addSingletonClass(MyService)\n * .build();\n */\n build(name: string = 'root'): ServiceProvider<T> {\n // Validate all registered services\n for (const key of Reflect.ownKeys(this.definitions)) {\n const item = this.definitions[key as any];\n if (item.kind !== 'service' || !Array.isArray(item.type)) continue;\n\n // This is an array of services\n for (const type of item.type as Class[]) {\n const name = type.name;\n const definitionsItem = this.definitions[name];\n\n // Check if this class was auto-registered (params is empty array) but requires arguments\n if (definitionsItem && definitionsItem.params && definitionsItem.params.length === 0 && type.length > 0) {\n throw new RegistrationError(`Class \"${name}\" in group \"${String(key)}\" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`);\n }\n }\n }\n\n return new ServiceProvider<T>(name, this.definitions);\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["CircularDependencyError", "path", "ServiceNotFoundError", "identifier", "RegistrationError", "message", "ServiceProviderDisposedError", "AsyncDisposalError", "serviceKey", "classKeyRegistry", "getStableKey", "type", "key", "ServiceProvider", "_ServiceProvider", "name", "definitions", "parent", "isAsyncScope", "root", "keyOrType", "ServiceProviderDisposedError", "key", "item", "ServiceNotFoundError", "uid", "pathStr", "k", "CircularDependencyError", "AsyncDisposalError", "entries", "inst", "result", "value", "types", "instances", "cls", "factory", "container", "func", "params", "resolvedParams", "param", "paramKey", "type", "instance", "_", "prop", "c", "entry", "v", "stableKey", "getStableKey", "ServiceCollection", "keyOrType", "factory", "key", "type", "isExplicitKey", "resolved", "uid", "getStableKey", "def", "_", "sp", "params", "typeRef", "types", "typeArray", "k", "name", "RegistrationError", "classDef", "func", "value", "foundKey", "item", "definitionsItem", "ServiceProvider"]
7
7
  }
package/dist/legacy.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var v=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var x=(o,e)=>{for(var t in e)v(o,t,{get:e[t],enumerable:!0})},w=(o,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of b(e))!T.call(o,n)&&n!==t&&v(o,n,{get:()=>e[n],enumerable:!(s=C(e,n))||s.enumerable});return o};var F=o=>w(v({},"__esModule",{value:!0}),o);var A={};x(A,{AsyncDisposalError:()=>f,CircularDependencyError:()=>h,RegistrationError:()=>l,ServiceCollection:()=>K,ServiceNotFoundError:()=>p,ServiceProvider:()=>u,ServiceProviderDisposedError:()=>m});module.exports=F(A);var h=class extends Error{constructor(e){super(`Circular dependency detected: ${e}`),this.name="CircularDependencyError"}},p=class extends Error{constructor(e){super(`Service not registered for identifier: ${e}`),this.name="ServiceNotFoundError"}},l=class extends Error{constructor(e){super(e),this.name="RegistrationError"}},m=class extends Error{constructor(){super("ServiceProvider has been disposed and cannot resolve services."),this.name="ServiceProviderDisposedError"}},f=class extends Error{constructor(e){super(`Service "${e}" requires asynchronous disposal but a synchronous dispose was called. Please use await disposeAsync() instead.`),this.name="AsyncDisposalError"}};var S=new WeakMap;function c(o){let e=S.get(o);return e||(e=Symbol(o.name||"AnonymousClass"),S.set(o,e)),e}var u=class o{constructor(e,t,s,n=!1){this.name=e;this.definitions=t;this.parent=s;this.isAsyncScope=n}instances=new Map;resolving=new Set;path=[];disposed=!1;createScope(e="scope"){let t=this.parent||this;return new o(e,this.definitions,t,!1)}createAsyncScope(e="async-scope"){let t=this.parent||this;return new o(e,this.definitions,t,!0)}getService(e){if(this.disposed)throw new m;let t=this.getKey(e);if(this.parent&&this.definitions[t]?.lifetime==="singleton")return this.parent.getService(t);let s=this.definitions[t];if(!s){let i=typeof e=="string"||typeof e=="symbol"?String(e):e.name||String(e);throw new p(i)}let n=s.uid;if(this.instances.has(n))return this.instances.get(n);if(this.resolving.has(n)){let i=this.path.map(r=>typeof r=="symbol"?r.description||String(r):r).concat(typeof t=="symbol"?t.description||String(t):t).join(" -> ");throw new h(i)}this.resolving.add(n),this.path.push(t);try{return s.kind==="value"?this.resolveValue(n,s.value):Array.isArray(s.type)?this.resolveArray(n,s.type):s.kind==="function"&&s.func?this.resolveFunc(n,s.func,s.params):s.factory?this.resolveFactory(n,s.factory):this.resolveClass(n,s.type,s.params)}finally{this.resolving.delete(n),this.path.pop()}}dispose(){if(this.disposed)return;if(this.isAsyncScope)throw new f(this.name);this.disposed=!0;let e=Array.from(this.instances.entries()).reverse();for(let[t,s]of e)if(s&&typeof s.dispose=="function"){if(s.dispose()instanceof Promise)throw new f(typeof t=="symbol"&&t.description||String(t))}else if(s&&typeof s.disposeAsync=="function")throw new f(typeof t=="symbol"&&t.description||String(t));this.instances.clear()}async disposeAsync(){if(this.disposed)return;this.disposed=!0;let e=Array.from(this.instances.values()).reverse();for(let t of e)if(t&&typeof t.disposeAsync=="function")await t.disposeAsync();else if(t&&typeof t.dispose=="function"){let s=t.dispose();s instanceof Promise&&await s}this.instances.clear()}resolveValue(e,t){return this.instances.set(e,t),t}resolveArray(e,t){let s=t.map(n=>this.getService(n));return this.instances.set(e,s),s}resolveFactory(e,t){let s=this.createContainerProxy(),n=t(s,this);return this.instances.set(e,n),n}resolveFunc(e,t,s){let i=(s||[]).map(a=>{let y=this.tryGetKey(a);return y?this.getService(y):a}),r=t(...i);return this.instances.set(e,r),r}resolveClass(e,t,s){let i=(s||[]).map(a=>{let y=this.tryGetKey(a);return y?this.getService(y):a}),r=new t(...i);return this.instances.set(e,r),r}createContainerProxy(){return new Proxy({},{get:(e,t)=>{if(!(typeof t!="string"&&typeof t!="symbol"))return this.getService(t)}})}getKey(e){if(typeof e=="string"||typeof e=="symbol")return e;let t=this.tryGetKey(e);if(t)return t;let s=Array.isArray(e)?`[${e.map(n=>n.name).join(", ")}]`:e.name||String(e);throw new p(s)}tryGetKey(e){if(typeof e=="string"||typeof e=="symbol"){if(e in this.definitions)return e;if(typeof e=="string"){let t=Reflect.ownKeys(this.definitions).find(s=>{let n=this.definitions[s];return n.kind==="service"&&!Array.isArray(n.type)&&n.type?.name===e});if(t)return t}return}if(typeof e=="function"||Array.isArray(e)){let t=c(e);if(t in this.definitions)return t;let s=Reflect.ownKeys(this.definitions).find(n=>{let i=this.definitions[n];return i.kind==="service"&&i.type===e});if(s)return s}}};var K=class{definitions={};typeMap;constructor(){this.typeMap={}}addSingletonFactory(e,t){let s,n,i=!1;if(typeof e=="string"||typeof e=="symbol")s=e,n=this.typeMap[s],i=!0;else{let y=this.resolveKeyAndType(e);s=y.key,n=y.type}let r=i?s:c(n),a={kind:"service",lifetime:"singleton",uid:r,type:n,factory:t};return this.definitions[s]=a,s!==r&&(this.definitions[r]=a),this}addServiceProvider(e){return this.addSingletonFactory(e,(t,s)=>s)}addScopedFactory(e,t){let s,n,i=!1;if(typeof e=="string"||typeof e=="symbol")s=e,n=this.typeMap[s],i=!0;else{let y=this.resolveKeyAndType(e);s=y.key,n=y.type}let r=i?s:c(n),a={kind:"service",lifetime:"scoped",uid:r,type:n,factory:t};return this.definitions[s]=a,s!==r&&(this.definitions[r]=a),this}addSingletonClass(e,...t){let{key:s,type:n}=this.resolveKeyAndType(e),i=c(n),r={kind:"service",lifetime:"singleton",uid:i,type:n,params:t};return this.definitions[s]=r,this.definitions[i]=r,this}addScopedClass(e,...t){let{key:s,type:n}=this.resolveKeyAndType(e),i=c(n),r={kind:"service",lifetime:"scoped",uid:i,type:n,params:t};return this.definitions[s]=r,this.definitions[i]=r,this}addSingletonArray(e,...t){let s={kind:"service",lifetime:"singleton",uid:e,type:t};this.typeMap[e]=t,this.definitions[e]=s;let n=t;for(let i of n){if(Reflect.ownKeys(this.typeMap).find(g=>this.typeMap[g]===i))continue;let a=i.name;if(!a)throw new l(`Class in array "${String(e)}" is missing a name and cannot be auto-registered.`);let y=c(i),d={kind:"service",lifetime:"singleton",uid:y,type:i,params:[]};this.typeMap[a]=i,this.definitions[a]=d,this.definitions[y]=d}return this}addScopedArray(e,...t){let s={kind:"service",lifetime:"scoped",uid:e,type:t};this.typeMap[e]=t,this.definitions[e]=s;let n=t;for(let i of n){if(Reflect.ownKeys(this.typeMap).find(g=>this.typeMap[g]===i))continue;let a=i.name;if(!a)throw new l(`Class in array "${String(e)}" is missing a name and cannot be auto-registered.`);let y=c(i),d={kind:"service",lifetime:"scoped",uid:y,type:i,params:[]};this.typeMap[a]=i,this.definitions[a]=d,this.definitions[y]=d}return this}addSingletonFunc(e,t,...s){return this.definitions[e]={kind:"function",lifetime:"singleton",uid:e,func:t,params:s},this}addScopedFunc(e,t,...s){return this.definitions[e]={kind:"function",lifetime:"scoped",uid:e,func:t,params:s},this}addSingletonValue(e,t){return this.definitions[e]={kind:"value",lifetime:"singleton",uid:e,value:t},this}addScopedValue(e,t){return this.definitions[e]={kind:"value",lifetime:"scoped",uid:e,value:t},this}resolveKeyAndType(e){let t,s=Reflect.ownKeys(this.typeMap).find(n=>this.typeMap[n]===e);return s?t=s:(t=e.name||c(e),this.typeMap[t]=e),{key:t,type:e}}build(e="root"){for(let t of Reflect.ownKeys(this.definitions)){let s=this.definitions[t];if(!(s.kind!=="service"||!Array.isArray(s.type)))for(let n of s.type){let i=n.name,r=this.definitions[i];if(r&&r.params&&r.params.length===0&&n.length>0)throw new l(`Class "${i}" in array "${String(t)}" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`)}}return new u(e,this.definitions)}};0&&(module.exports={AsyncDisposalError,CircularDependencyError,RegistrationError,ServiceCollection,ServiceNotFoundError,ServiceProvider,ServiceProviderDisposedError});
1
+ "use strict";var v=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var x=(o,e)=>{for(var t in e)v(o,t,{get:e[t],enumerable:!0})},w=(o,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of b(e))!T.call(o,n)&&n!==t&&v(o,n,{get:()=>e[n],enumerable:!(s=C(e,n))||s.enumerable});return o};var F=o=>w(v({},"__esModule",{value:!0}),o);var A={};x(A,{AsyncDisposalError:()=>f,CircularDependencyError:()=>u,RegistrationError:()=>l,ServiceCollection:()=>K,ServiceNotFoundError:()=>p,ServiceProvider:()=>m,ServiceProviderDisposedError:()=>h});module.exports=F(A);var u=class extends Error{constructor(e){super(`Circular dependency detected: ${e}`),this.name="CircularDependencyError"}},p=class extends Error{constructor(e){super(`Service not registered for identifier: ${e}`),this.name="ServiceNotFoundError"}},l=class extends Error{constructor(e){super(e),this.name="RegistrationError"}},h=class extends Error{constructor(){super("ServiceProvider has been disposed and cannot resolve services."),this.name="ServiceProviderDisposedError"}},f=class extends Error{constructor(e){super(`Service "${e}" requires asynchronous disposal but a synchronous dispose was called. Please use await disposeAsync() instead.`),this.name="AsyncDisposalError"}};var S=new WeakMap;function c(o){let e=S.get(o);return e||(e=Symbol(o.name||"AnonymousClass"),S.set(o,e)),e}var m=class o{constructor(e,t,s,n=!1){this.name=e;this.definitions=t;this.parent=s;this.isAsyncScope=n}instances=new Map;resolving=new Set;path=[];disposed=!1;createScope(e="scope"){let t=this.parent||this;return new o(e,this.definitions,t,!1)}createAsyncScope(e="async-scope"){let t=this.parent||this;return new o(e,this.definitions,t,!0)}getService(e){if(this.disposed)throw new h;let t=this.getKey(e);if(this.parent&&this.definitions[t]?.lifetime==="singleton")return this.parent.getService(t);let s=this.definitions[t];if(!s){let i=typeof e=="string"||typeof e=="symbol"?String(e):e.name||String(e);throw new p(i)}let n=s.uid;if(this.instances.has(n))return this.instances.get(n);if(this.resolving.has(n)){let i=this.path.map(r=>typeof r=="symbol"?r.description||String(r):r).concat(typeof t=="symbol"?t.description||String(t):t).join(" -> ");throw new u(i)}this.resolving.add(n),this.path.push(t);try{return s.kind==="value"?this.resolveValue(n,s.value):Array.isArray(s.type)?this.resolveArray(n,s.type):s.kind==="function"&&s.func?this.resolveFunc(n,s.func,s.params):s.factory?this.resolveFactory(n,s.factory):this.resolveClass(n,s.type,s.params)}finally{this.resolving.delete(n),this.path.pop()}}dispose(){if(this.disposed)return;if(this.isAsyncScope)throw new f(this.name);this.disposed=!0;let e=Array.from(this.instances.entries()).reverse();for(let[t,s]of e)if(s&&typeof s.dispose=="function"){if(s.dispose()instanceof Promise)throw new f(typeof t=="symbol"&&t.description||String(t))}else if(s&&typeof s.disposeAsync=="function")throw new f(typeof t=="symbol"&&t.description||String(t));this.instances.clear()}async disposeAsync(){if(this.disposed)return;this.disposed=!0;let e=Array.from(this.instances.values()).reverse();for(let t of e)if(t&&typeof t.disposeAsync=="function")await t.disposeAsync();else if(t&&typeof t.dispose=="function"){let s=t.dispose();s instanceof Promise&&await s}this.instances.clear()}resolveValue(e,t){return this.instances.set(e,t),t}resolveArray(e,t){let s=t.map(n=>this.getService(n));return this.instances.set(e,s),s}resolveFactory(e,t){let s=this.createContainerProxy(),n=t(s,this);return this.instances.set(e,n),n}resolveFunc(e,t,s){let i=(s||[]).map(a=>{let y=this.tryGetKey(a);return y?this.getService(y):a}),r=t(...i);return this.instances.set(e,r),r}resolveClass(e,t,s){let i=(s||[]).map(a=>{let y=this.tryGetKey(a);return y?this.getService(y):a}),r=new t(...i);return this.instances.set(e,r),r}createContainerProxy(){return new Proxy({},{get:(e,t)=>{if(!(typeof t!="string"&&typeof t!="symbol"))return this.getService(t)}})}getKey(e){if(typeof e=="string"||typeof e=="symbol")return e;let t=this.tryGetKey(e);if(t)return t;let s=Array.isArray(e)?`[${e.map(n=>n.name).join(", ")}]`:e.name||String(e);throw new p(s)}tryGetKey(e){if(typeof e=="string"||typeof e=="symbol"){if(e in this.definitions)return e;if(typeof e=="string"){let t=Reflect.ownKeys(this.definitions).find(s=>{let n=this.definitions[s];return n.kind==="service"&&!Array.isArray(n.type)&&n.type?.name===e});if(t)return t}return}if(typeof e=="function"||Array.isArray(e)){let t=c(e);if(t in this.definitions)return t;let s=Reflect.ownKeys(this.definitions).find(n=>{let i=this.definitions[n];return i.kind==="service"&&i.type===e});if(s)return s}}};var K=class{definitions={};typeMap;constructor(){this.typeMap={}}addSingletonFactory(e,t){let s,n,i=!1;if(typeof e=="string"||typeof e=="symbol")s=e,n=this.typeMap[s],i=!0;else{let y=this.resolveKeyAndType(e);s=y.key,n=y.type}let r=i?s:c(n),a={kind:"service",lifetime:"singleton",uid:r,type:n,factory:t};return this.definitions[s]=a,s!==r&&(this.definitions[r]=a),this}addServiceProvider(e){return this.addSingletonFactory(e,(t,s)=>s)}addScopedFactory(e,t){let s,n,i=!1;if(typeof e=="string"||typeof e=="symbol")s=e,n=this.typeMap[s],i=!0;else{let y=this.resolveKeyAndType(e);s=y.key,n=y.type}let r=i?s:c(n),a={kind:"service",lifetime:"scoped",uid:r,type:n,factory:t};return this.definitions[s]=a,s!==r&&(this.definitions[r]=a),this}addSingletonClass(e,...t){let{key:s,type:n}=this.resolveKeyAndType(e),i=c(n),r={kind:"service",lifetime:"singleton",uid:i,type:n,params:t};return this.definitions[s]=r,this.definitions[i]=r,this}addScopedClass(e,...t){let{key:s,type:n}=this.resolveKeyAndType(e),i=c(n),r={kind:"service",lifetime:"scoped",uid:i,type:n,params:t};return this.definitions[s]=r,this.definitions[i]=r,this}addSingletonGroup(e,...t){let s={kind:"service",lifetime:"singleton",uid:e,type:t};this.typeMap[e]=t,this.definitions[e]=s;let n=t;for(let i of n){if(Reflect.ownKeys(this.typeMap).find(g=>this.typeMap[g]===i))continue;let a=i.name;if(!a)throw new l(`Class in group "${String(e)}" is missing a name and cannot be auto-registered.`);let y=c(i),d={kind:"service",lifetime:"singleton",uid:y,type:i,params:[]};this.typeMap[a]=i,this.definitions[a]=d,this.definitions[y]=d}return this}addScopedGroup(e,...t){let s={kind:"service",lifetime:"scoped",uid:e,type:t};this.typeMap[e]=t,this.definitions[e]=s;let n=t;for(let i of n){if(Reflect.ownKeys(this.typeMap).find(g=>this.typeMap[g]===i))continue;let a=i.name;if(!a)throw new l(`Class in group "${String(e)}" is missing a name and cannot be auto-registered.`);let y=c(i),d={kind:"service",lifetime:"scoped",uid:y,type:i,params:[]};this.typeMap[a]=i,this.definitions[a]=d,this.definitions[y]=d}return this}addSingletonFunc(e,t,...s){return this.definitions[e]={kind:"function",lifetime:"singleton",uid:e,func:t,params:s},this}addScopedFunc(e,t,...s){return this.definitions[e]={kind:"function",lifetime:"scoped",uid:e,func:t,params:s},this}addSingletonValue(e,t){return this.definitions[e]={kind:"value",lifetime:"singleton",uid:e,value:t},this}addScopedValue(e,t){return this.definitions[e]={kind:"value",lifetime:"scoped",uid:e,value:t},this}resolveKeyAndType(e){let t,s=Reflect.ownKeys(this.typeMap).find(n=>this.typeMap[n]===e);return s?t=s:(t=e.name||c(e),this.typeMap[t]=e),{key:t,type:e}}build(e="root"){for(let t of Reflect.ownKeys(this.definitions)){let s=this.definitions[t];if(!(s.kind!=="service"||!Array.isArray(s.type)))for(let n of s.type){let i=n.name,r=this.definitions[i];if(r&&r.params&&r.params.length===0&&n.length>0)throw new l(`Class "${i}" in group "${String(t)}" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`)}}return new m(e,this.definitions)}};0&&(module.exports={AsyncDisposalError,CircularDependencyError,RegistrationError,ServiceCollection,ServiceNotFoundError,ServiceProvider,ServiceProviderDisposedError});
2
2
  //# sourceMappingURL=legacy.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/errors.ts", "../src/registry.ts", "../src/service-provider.ts", "../src/service-collection.ts"],
4
- "sourcesContent": ["export * from './errors.js';\nexport * from './service-collection.js';\nexport * from './service-provider.js';\nexport * from './types.js';\n", "/**\n * Thrown when a circular dependency is detected.\n */\nexport class CircularDependencyError extends Error {\n constructor(path: string) {\n super(`Circular dependency detected: ${path}`);\n this.name = 'CircularDependencyError';\n }\n}\n\n/**\n * Thrown when a service cannot be resolved.\n */\nexport class ServiceNotFoundError extends Error {\n constructor(identifier: string) {\n super(`Service not registered for identifier: ${identifier}`);\n this.name = 'ServiceNotFoundError';\n }\n}\n\n/**\n * Thrown when a registration is invalid.\n */\nexport class RegistrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RegistrationError';\n }\n}\n\n/**\n * Thrown when a service provider has been disposed.\n */\nexport class ServiceProviderDisposedError extends Error {\n constructor() {\n super('ServiceProvider has been disposed and cannot resolve services.');\n this.name = 'ServiceProviderDisposedError';\n }\n}\n\n/**\n * Thrown when a synchronous dispose is called on a scope containing services that require asynchronous disposal.\n */\nexport class AsyncDisposalError extends Error {\n constructor(serviceKey: string) {\n super(`Service \"${serviceKey}\" requires asynchronous disposal but a synchronous dispose was called. Please use await disposeAsync() instead.`);\n this.name = 'AsyncDisposalError';\n }\n}\n", "import type { Class } from './types.js';\r\n\r\nconst classKeyRegistry = new WeakMap<Class, symbol>();\r\n\r\n/**\r\n * Resolves a stable Symbol for a given class constructor.\r\n * This is used to ensure that DI resolution remains stable even after minification.\r\n * @param type The class constructor.\r\n */\r\nexport function getStableKey(type: Class): symbol {\r\n let key = classKeyRegistry.get(type);\r\n if (!key) {\r\n key = Symbol(type.name || 'AnonymousClass');\r\n classKeyRegistry.set(type, key);\r\n }\r\n return key;\r\n}\r\n", "import {\n AsyncDisposalError,\n CircularDependencyError,\n ServiceNotFoundError,\n ServiceProviderDisposedError,\n} from './errors.js';\nimport { getStableKey } from './registry.js';\nimport type {\n Class,\n ConcreteClass,\n ImplementationFactory,\n IServiceProvider,\n MapToInstance,\n ResolvedTypeMap,\n ServiceDefinitionMap,\n TypeMap,\n} from './types.js';\n\nexport class ServiceProvider<T extends TypeMap> implements IServiceProvider<T> {\n private instances = new Map<string | symbol, any>();\n private resolving = new Set<string | symbol>();\n private path: (string | symbol)[] = [];\n private disposed = false;\n\n /**\n * @param name The name of the service provider.\n * @param definitions The service definitions map.\n * @param parent The parent service provider, if any.\n * @param isAsyncScope Whether this is an asynchronous scope.\n */\n constructor(\n public readonly name: string,\n private definitions: ServiceDefinitionMap,\n private parent?: ServiceProvider<T>,\n private readonly isAsyncScope: boolean = false\n ) { }\n\n /**\n * Creates a new scoped ServiceProvider.\n * @param name The name of the scope.\n * @example\n * const scope = di.createScope('request-scope');\n */\n createScope(name: string = 'scope'): IServiceProvider<T> {\n const root = this.parent || this;\n return new ServiceProvider<T>(name, this.definitions, root, false);\n }\n\n /**\n * Creates a new scoped ServiceProvider that supports asynchronous disposal.\n * @param name The name of the scope.\n * @example\n * const scope = di.createAsyncScope('worker-scope');\n */\n createAsyncScope(name: string = 'async-scope'): IServiceProvider<T> {\n const root = this.parent || this;\n return new ServiceProvider<T>(name, this.definitions, root, true);\n }\n\n /**\n * Resolves a service by its key.\n * @param key The key to resolve.\n * @example\n * const logger = di.getService('Logger');\n */\n getService<K extends keyof T & (string | symbol)>(key: K): MapToInstance<T[K]>;\n\n /**\n * Resolves a service by its Class type.\n * @param type The class type to resolve.\n * @example\n * const logger = di.getService(Logger);\n */\n getService<C extends Class>(type: C): InstanceType<C>;\n\n getService<K extends keyof T & (string | symbol)>(keyOrType: K | T[K]): MapToInstance<T[K]> {\n if (this.disposed) {\n throw new ServiceProviderDisposedError();\n }\n\n const key = this.getKey(keyOrType);\n\n if (this.parent && this.definitions[key]?.lifetime === 'singleton') {\n return this.parent.getService(key as any);\n }\n\n const item = this.definitions[key];\n if (!item) {\n const name = (typeof keyOrType === 'string' || typeof keyOrType === 'symbol')\n ? String(keyOrType)\n : (keyOrType as any).name || String(keyOrType);\n throw new ServiceNotFoundError(name);\n }\n\n const uid = item.uid;\n\n if (this.instances.has(uid)) {\n return this.instances.get(uid);\n }\n\n if (this.resolving.has(uid)) {\n const pathStr = this.path.map(k => (typeof k === 'symbol' ? k.description || String(k) : k)).concat(typeof key === 'symbol' ? key.description || String(key) : key).join(' -> ');\n throw new CircularDependencyError(pathStr);\n }\n\n this.resolving.add(uid);\n this.path.push(key);\n\n try {\n if (item.kind === 'value') return this.resolveValue(uid, item.value);\n\n if (Array.isArray(item.type)) return this.resolveArray(uid, item.type);\n\n if (item.kind === 'function' && item.func) return this.resolveFunc(uid, item.func, item.params);\n\n if (item.factory) return this.resolveFactory(uid, item.factory);\n\n return this.resolveClass(uid, item.type as Class, item.params);\n } finally {\n this.resolving.delete(uid);\n this.path.pop();\n }\n }\n\n /**\n * Synchronously disposes of all resolved services.\n * Throws AsyncDisposalError if this is an async scope or if any service disposal returns a Promise.\n */\n dispose(): void {\n if (this.disposed) return;\n\n if (this.isAsyncScope) {\n throw new AsyncDisposalError(this.name);\n }\n\n this.disposed = true;\n\n const entries = Array.from(this.instances.entries()).reverse();\n\n for (const [uid, inst] of entries) {\n if (inst && typeof inst.dispose === 'function') {\n const result = inst.dispose();\n if (result instanceof Promise) {\n throw new AsyncDisposalError(typeof uid === 'symbol' ? uid.description || String(uid) : String(uid));\n }\n } else if (inst && typeof inst.disposeAsync === 'function') {\n throw new AsyncDisposalError(typeof uid === 'symbol' ? uid.description || String(uid) : String(uid));\n }\n }\n\n this.instances.clear();\n }\n\n /**\n * Asynchronously disposes of all resolved services.\n */\n async disposeAsync(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n\n const entries = Array.from(this.instances.values()).reverse();\n\n for (const inst of entries) {\n if (inst && typeof inst.disposeAsync === 'function') {\n await inst.disposeAsync();\n } else if (inst && typeof inst.dispose === 'function') {\n const result = inst.dispose();\n if (result instanceof Promise) {\n await result;\n }\n }\n }\n\n this.instances.clear();\n }\n\n /**\n * Resolves a singleton value.\n * @param uid The unique ID of the value.\n * @param value The value to resolve.\n */\n private resolveValue(uid: string | symbol, value: any): any {\n this.instances.set(uid, value);\n return value;\n }\n\n /**\n * Resolves an array of services.\n * @param uid The unique ID of the service array.\n * @param types The class types to resolve for the array.\n */\n private resolveArray(uid: string | symbol, types: Class[]): any {\n const instances = types.map((cls) => {\n const inst = this.getService(cls);\n return inst;\n });\n\n this.instances.set(uid, instances);\n return instances;\n }\n\n /**\n * Resolves a service via a factory.\n * @param uid The unique ID of the service.\n * @param factory The factory to use for resolution.\n */\n private resolveFactory(uid: string | symbol, factory: ImplementationFactory<any, any>): any {\n const container = this.createContainerProxy();\n const result = factory(container, this);\n this.instances.set(uid, result);\n return result;\n }\n\n /**\n * Resolves a service via a function.\n * @param uid The unique ID of the service.\n * @param func The function to use for resolution.\n * @param params The arguments for the function.\n */\n private resolveFunc(uid: string | symbol, func: (...args: any[]) => any, params?: any[]): any {\n const rawParams = params || [];\n const resolvedParams = rawParams.map((param) => {\n const paramKey = this.tryGetKey(param);\n const inst = paramKey ? this.getService(paramKey) : param;\n return inst;\n });\n\n const result = func(...resolvedParams);\n this.instances.set(uid, result);\n return result;\n }\n\n /**\n * Resolves a service via its class type.\n * @param uid The unique ID of the service.\n * @param type The class type to instantiate.\n * @param params The constructor arguments.\n */\n private resolveClass(uid: string | symbol, type: Class, params?: any[]): any {\n const rawParams = params || [];\n const resolvedParams = rawParams.map((param) => {\n const paramKey = this.tryGetKey(param);\n const inst = paramKey ? this.getService(paramKey) : param;\n return inst;\n });\n\n const instance = new (type as ConcreteClass)(...resolvedParams);\n this.instances.set(uid, instance);\n return instance;\n }\n\n /**\n * Creates a proxy for the type map to allow resolving services by property access.\n */\n private createContainerProxy(): ResolvedTypeMap<T> {\n return new Proxy({} as ResolvedTypeMap<T>, {\n get: (_, prop) => {\n if (typeof prop !== 'string' && typeof prop !== 'symbol') return undefined;\n return this.getService(prop as any);\n }\n });\n }\n\n /**\n * Gets the key for a given key or class type.\n * @param keyOrType The key or class type.\n */\n private getKey<K extends keyof T & (string | symbol)>(keyOrType: K | T[K]): string | symbol {\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') return keyOrType;\n\n const key = this.tryGetKey(keyOrType);\n if (key) return key;\n\n const name = Array.isArray(keyOrType)\n ? `[${keyOrType.map((c: any) => (c as any).name).join(', ')}]`\n : (keyOrType as any).name || String(keyOrType);\n throw new ServiceNotFoundError(name);\n }\n\n /**\n * Attempts to get the key for a given key or class type without throwing.\n * @param keyOrType The key or class type.\n */\n private tryGetKey(keyOrType: any): string | symbol | undefined {\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n if (keyOrType in this.definitions) return keyOrType;\n \n // Fallback for string names (backward compatibility)\n if (typeof keyOrType === 'string') {\n const entry = Reflect.ownKeys(this.definitions).find((k) => {\n const v = this.definitions[k as any];\n return v.kind === 'service' && !Array.isArray(v.type) && (v.type as any)?.name === keyOrType;\n });\n if (entry) return entry as string | symbol;\n }\n return undefined;\n }\n\n if (typeof keyOrType === 'function' || Array.isArray(keyOrType)) {\n // Check the stable registry first (minification proof)\n const stableKey = getStableKey(keyOrType as any);\n if (stableKey in this.definitions) return stableKey;\n\n // Fallback to searching by reference (for explicit symbols or non-auto registrations)\n const entry = Reflect.ownKeys(this.definitions).find((k) => {\n const v = this.definitions[k as any];\n return v.kind === 'service' && v.type === keyOrType;\n });\n if (entry) return entry as string | symbol;\n }\n\n return undefined;\n }\n}\n", "import {\n RegistrationError,\n} from './errors.js';\nimport { getStableKey } from './registry.js';\nimport { ServiceProvider } from './service-provider.js';\nimport type {\n Class,\n ClassArgs,\n FilterKeys,\n FilterValueKeys,\n FilterFuncKeys,\n FuncArgs,\n ImplementationFactory,\n MapToInstance,\n ServiceDefinitionMap,\n TypeMap,\n ServiceDefinition\n} from './types.js';\n\n/**\n * Fluent builder for service collections using a lookup map.\n */\nexport class ServiceCollection<T extends TypeMap> {\n private definitions: ServiceDefinitionMap = {};\n private typeMap: T;\n\n /**\n * Initializes a new instance of the ServiceCollection class.\n */\n constructor() {\n this.typeMap = {} as T;\n }\n\n /**\n * Adds a singleton service using a factory function.\n * Key is derived from the class.\n * @param type The class to register.\n * @param factory The factory function to create the service instance.\n * @example\n * .addSingletonFactory(UserRepo, (c) => new UserRepo(c.UserService))\n */\n addSingletonFactory<Key extends keyof T & (string | symbol), C extends Class>(\n type: C,\n factory: ImplementationFactory<T, InstanceType<C>>\n ): this;\n\n /**\n * Adds a singleton service using a factory function and a key.\n * @param key The key to register the service under.\n * @param factory The factory function to create the service instance.\n * @example\n * .addSingletonFactory(\"UserRepo\", (c) => new UserRepo(c.UserService))\n */\n addSingletonFactory<Key extends keyof T & (string | symbol)>(\n key: Key,\n factory: ImplementationFactory<T, MapToInstance<T[Key]>>\n ): this;\n\n addSingletonFactory<Key extends keyof T & (string | symbol)>(\n keyOrType: Key | Class,\n factory: ImplementationFactory<T, any>\n ): this {\n let key: string | symbol;\n let type: any;\n let isExplicitKey = false;\n\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n key = keyOrType;\n type = this.typeMap[key];\n isExplicitKey = true;\n } else {\n const resolved = this.resolveKeyAndType<Key>(keyOrType as any);\n key = resolved.key;\n type = resolved.type;\n }\n\n const uid = isExplicitKey ? key : getStableKey(type);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type, factory };\n this.definitions[key] = def;\n if (key !== uid) this.definitions[uid] = def;\n\n return this;\n }\n\n /**\n * Registers the ServiceProvider itself as a service.\n * This allows services to depend on the ServiceProvider to resolve other services dynamically.\n * @param key The key to register the ServiceProvider under.\n * @example\n * .addServiceProvider(\"ServiceProvider\")\n */\n addServiceProvider<Key extends keyof T & (string | symbol)>(key: Key) {\n return this.addSingletonFactory(key as any, (_, sp) => sp)\n }\n\n /**\n * Adds a scoped service using a factory function.\n * Key is derived from the class.\n * @param type The class to register.\n * @param factory The factory function to create the service instance.\n * @example\n * .addScopedFactory(UserRepo, (c) => new UserRepo(c.UserService))\n */\n addScopedFactory<Key extends keyof T & (string | symbol), C extends Class>(\n type: C,\n factory: ImplementationFactory<T, InstanceType<C>>\n ): this;\n\n /**\n * Adds a scoped service using a factory function and a key.\n * @param key The key to register the service under.\n * @param factory The factory function to create the service instance.\n * @example\n * .addScopedFactory(\"UserRepo\", (c) => new UserRepo(c.UserService))\n */\n addScopedFactory<Key extends keyof T & (string | symbol)>(\n key: Key,\n factory: ImplementationFactory<T, MapToInstance<T[Key]>>\n ): this;\n\n addScopedFactory<Key extends keyof T & (string | symbol)>(\n keyOrType: Key | Class,\n factory: ImplementationFactory<T, any>\n ): this {\n let key: string | symbol;\n let type: any;\n let isExplicitKey = false;\n\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n key = keyOrType;\n type = this.typeMap[key];\n isExplicitKey = true;\n } else {\n const resolved = this.resolveKeyAndType<Key>(keyOrType as any);\n key = resolved.key;\n type = resolved.type;\n }\n\n const uid = isExplicitKey ? key : getStableKey(type);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type, factory };\n this.definitions[key] = def;\n if (key !== uid) this.definitions[uid] = def;\n\n return this;\n }\n\n /**\n * Adds a singleton service using constructor injection.\n * Key is derived from the container map based on the Class.\n * @param type The class to register.\n * @param params The constructor arguments.\n * @example\n * .addSingletonClass(UserService, \"admin\", \"password\")\n */\n addSingletonClass<C extends Class>(\n type: C,\n ...params: ClassArgs<C, keyof T & (string | symbol)>\n ): this {\n const { key, type: typeRef } = this.resolveKeyAndType(type as any);\n const uid = getStableKey(typeRef);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type: typeRef, params };\n this.definitions[key] = def;\n this.definitions[uid] = def;\n return this;\n }\n\n /**\n * Adds a scoped service using constructor injection.\n * Key is derived from the container map based on the Class.\n * @param type The class to register.\n * @param params The constructor arguments.\n * @example\n * .addScopedClass(UserService, \"admin\", \"password\")\n */\n addScopedClass<C extends Class>(\n type: C,\n ...params: ClassArgs<C, keyof T & (string | symbol)>\n ): this {\n const { key, type: typeRef } = this.resolveKeyAndType(type as any);\n const uid = getStableKey(typeRef);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type: typeRef, params };\n this.definitions[key] = def;\n this.definitions[uid] = def;\n return this;\n }\n\n /**\n * Adds an array of singleton services.\n * Automatically registers individual classes if not already registered.\n * @param key The key for the service array.\n * @param types The classes to register in the array.\n * @example\n * .addSingletonArray(\"MessageCommand\", HelloCommand, ByeCommand)\n */\n addSingletonArray<\n Key extends FilterKeys<T, any[]>,\n C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]\n >(\n key: Key,\n ...types: C\n ): this {\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid: key, type: types };\n (this.typeMap as any)[key] = types;\n this.definitions[key] = def;\n\n // Auto-register individual classes if not already registered\n const typeArray = types as Class[];\n for (const type of typeArray) {\n const foundKey = Reflect.ownKeys(this.typeMap).find(k => this.typeMap[k as any] === type);\n if (foundKey) continue;\n\n const name = type.name;\n if (!name) {\n throw new RegistrationError(`Class in array \"${String(key)}\" is missing a name and cannot be auto-registered.`);\n }\n\n const uid = getStableKey(type);\n const classDef: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type, params: [] };\n (this.typeMap as any)[name] = type;\n this.definitions[name] = classDef;\n this.definitions[uid] = classDef;\n }\n\n return this;\n }\n\n /**\n * Adds an array of scoped services.\n * Automatically registers individual classes as scoped if not already registered.\n * @param key The key for the service array.\n * @param types The classes to register in the array.\n * @example\n * .addScopedArray(\"MessageCommand\", HelloCommand, ByeCommand)\n */\n addScopedArray<\n Key extends FilterKeys<T, any[]>,\n C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]\n >(\n key: Key,\n ...types: C\n ): this {\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid: key, type: types };\n (this.typeMap as any)[key] = types;\n this.definitions[key] = def;\n\n // Auto-register individual classes if not already registered\n const typeArray = types as Class[];\n for (const type of typeArray) {\n const foundKey = Reflect.ownKeys(this.typeMap).find(k => this.typeMap[k as any] === type);\n if (foundKey) continue;\n\n const name = type.name;\n if (!name) {\n throw new RegistrationError(`Class in array \"${String(key)}\" is missing a name and cannot be auto-registered.`);\n }\n\n const uid = getStableKey(type);\n const classDef: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type, params: [] };\n (this.typeMap as any)[name] = type;\n this.definitions[name] = classDef;\n this.definitions[uid] = classDef;\n }\n\n return this;\n }\n\n /**\n * Adds a singleton service using a function.\n * @param key The key for the service.\n * @param func The function to register.\n * @param params The function arguments.\n * @example\n * .addSingletonFunc(\"Logger\", createLogger, \"Config\")\n */\n addSingletonFunc<Key extends FilterFuncKeys<T>, F extends (...args: any[]) => T[Key]>(\n key: Key,\n func: F,\n ...params: FuncArgs<F, T>\n ): this {\n this.definitions[key] = { kind: 'function', lifetime: 'singleton', uid: key, func, params };\n return this;\n }\n\n /**\n * Adds a scoped service using a function.\n * @param key The key for the service.\n * @param func The function to register.\n * @param params The function arguments.\n * @example\n * .addScopedFunc(\"Logger\", createLogger, \"Config\")\n */\n addScopedFunc<Key extends FilterFuncKeys<T>, F extends (...args: any[]) => T[Key]>(\n key: Key,\n func: F,\n ...params: FuncArgs<F, T>\n ): this {\n this.definitions[key] = { kind: 'function', lifetime: 'scoped', uid: key, func, params };\n return this;\n }\n\n /**\n * Adds a singleton value.\n * @param key The key for the value.\n * @param value The value to register.\n * @example\n * .addSingletonValue(\"connectionString\", \"test connection string\")\n */\n addSingletonValue<Key extends FilterValueKeys<T>>(\n key: Key,\n value: T[Key]\n ): this {\n this.definitions[key] = { kind: 'value', lifetime: 'singleton', uid: key, value };\n return this;\n }\n\n /**\n * Adds a scoped value.\n * @param key The key for the value.\n * @param value The value to register.\n * @example\n * .addScopedValue(\"connectionString\", \"test connection string\")\n */\n addScopedValue<Key extends FilterValueKeys<T>>(\n key: Key,\n value: T[Key]\n ): this {\n this.definitions[key] = { kind: 'value', lifetime: 'scoped', uid: key, value };\n return this;\n }\n\n /**\n * Resolves the string key and Class reference for a given type.\n * If the type is already mapped in the TypeMap, the existing key is used.\n * Otherwise, it auto-registers the type using its class name as the key.\n * @param type The class reference to resolve.\n * @throws RegistrationError if the class name cannot be determined (e.g. anonymous class).\n * @example\n * const { key, type } = this.resolveKeyAndType(UserService);\n */\n private resolveKeyAndType<Key extends keyof T & (string | symbol)>(type: T[Key] & Class): { key: Key, type: T[Key] } {\n let key: Key;\n\n const foundKey = Reflect.ownKeys(this.typeMap).find(\n (k) => this.typeMap[k as any] === type\n );\n if (foundKey) {\n key = foundKey as Key;\n } else {\n // Auto-register using class name for backward compatibility\n key = (type.name || getStableKey(type)) as any as Key;\n (this.typeMap as any)[key] = type;\n }\n\n return { key, type };\n }\n\n /**\n * Builds the ServiceProvider.\n * @param name The name of the service provider.\n * @example\n * const di = new ServiceCollection<LocalMap>()\n * .addSingletonClass(MyService)\n * .build();\n */\n build(name: string = 'root'): ServiceProvider<T> {\n // Validate all registered services\n for (const key of Reflect.ownKeys(this.definitions)) {\n const item = this.definitions[key as any];\n if (item.kind !== 'service' || !Array.isArray(item.type)) continue;\n\n // This is an array of services\n for (const type of item.type as Class[]) {\n const name = type.name;\n const definitionsItem = this.definitions[name];\n\n // Check if this class was auto-registered (params is empty array) but requires arguments\n if (definitionsItem && definitionsItem.params && definitionsItem.params.length === 0 && type.length > 0) {\n throw new RegistrationError(`Class \"${name}\" in array \"${String(key)}\" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`);\n }\n }\n }\n\n return new ServiceProvider<T>(name, this.definitions);\n }\n}\n"],
4
+ "sourcesContent": ["export * from './errors.js';\nexport * from './service-collection.js';\nexport * from './service-provider.js';\nexport * from './types.js';\n", "/**\n * Thrown when a circular dependency is detected.\n */\nexport class CircularDependencyError extends Error {\n constructor(path: string) {\n super(`Circular dependency detected: ${path}`);\n this.name = 'CircularDependencyError';\n }\n}\n\n/**\n * Thrown when a service cannot be resolved.\n */\nexport class ServiceNotFoundError extends Error {\n constructor(identifier: string) {\n super(`Service not registered for identifier: ${identifier}`);\n this.name = 'ServiceNotFoundError';\n }\n}\n\n/**\n * Thrown when a registration is invalid.\n */\nexport class RegistrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RegistrationError';\n }\n}\n\n/**\n * Thrown when a service provider has been disposed.\n */\nexport class ServiceProviderDisposedError extends Error {\n constructor() {\n super('ServiceProvider has been disposed and cannot resolve services.');\n this.name = 'ServiceProviderDisposedError';\n }\n}\n\n/**\n * Thrown when a synchronous dispose is called on a scope containing services that require asynchronous disposal.\n */\nexport class AsyncDisposalError extends Error {\n constructor(serviceKey: string) {\n super(`Service \"${serviceKey}\" requires asynchronous disposal but a synchronous dispose was called. Please use await disposeAsync() instead.`);\n this.name = 'AsyncDisposalError';\n }\n}\n", "import type { Class } from './types.js';\r\n\r\nconst classKeyRegistry = new WeakMap<Class, symbol>();\r\n\r\n/**\r\n * Resolves a stable Symbol for a given class constructor.\r\n * This is used to ensure that DI resolution remains stable even after minification.\r\n * @param type The class constructor.\r\n */\r\nexport function getStableKey(type: Class): symbol {\r\n let key = classKeyRegistry.get(type);\r\n if (!key) {\r\n key = Symbol(type.name || 'AnonymousClass');\r\n classKeyRegistry.set(type, key);\r\n }\r\n return key;\r\n}\r\n", "import {\n AsyncDisposalError,\n CircularDependencyError,\n ServiceNotFoundError,\n ServiceProviderDisposedError,\n} from './errors.js';\nimport { getStableKey } from './registry.js';\nimport type {\n Class,\n ConcreteClass,\n ImplementationFactory,\n IServiceProvider,\n MapToInstance,\n ResolvedTypeMap,\n ServiceDefinitionMap,\n TypeMap,\n} from './types.js';\n\nexport class ServiceProvider<T extends TypeMap> implements IServiceProvider<T> {\n private instances = new Map<string | symbol, any>();\n private resolving = new Set<string | symbol>();\n private path: (string | symbol)[] = [];\n private disposed = false;\n\n /**\n * @param name The name of the service provider.\n * @param definitions The service definitions map.\n * @param parent The parent service provider, if any.\n * @param isAsyncScope Whether this is an asynchronous scope.\n */\n constructor(\n public readonly name: string,\n private definitions: ServiceDefinitionMap,\n private parent?: ServiceProvider<T>,\n private readonly isAsyncScope: boolean = false\n ) { }\n\n /**\n * Creates a new scoped ServiceProvider.\n * @param name The name of the scope.\n * @example\n * const scope = di.createScope('request-scope');\n */\n createScope(name: string = 'scope'): IServiceProvider<T> {\n const root = this.parent || this;\n return new ServiceProvider<T>(name, this.definitions, root, false);\n }\n\n /**\n * Creates a new scoped ServiceProvider that supports asynchronous disposal.\n * @param name The name of the scope.\n * @example\n * const scope = di.createAsyncScope('worker-scope');\n */\n createAsyncScope(name: string = 'async-scope'): IServiceProvider<T> {\n const root = this.parent || this;\n return new ServiceProvider<T>(name, this.definitions, root, true);\n }\n\n /**\n * Resolves a service by its key.\n * @param key The key to resolve.\n * @example\n * const logger = di.getService('Logger');\n */\n getService<K extends keyof T & (string | symbol)>(key: K): MapToInstance<T[K]>;\n\n /**\n * Resolves a service by its Class type.\n * @param type The class type to resolve.\n * @example\n * const logger = di.getService(Logger);\n */\n getService<C extends Class>(type: C): InstanceType<C>;\n\n getService<K extends keyof T & (string | symbol)>(keyOrType: K | T[K]): MapToInstance<T[K]> {\n if (this.disposed) {\n throw new ServiceProviderDisposedError();\n }\n\n const key = this.getKey(keyOrType);\n\n if (this.parent && this.definitions[key]?.lifetime === 'singleton') {\n return this.parent.getService(key as any);\n }\n\n const item = this.definitions[key];\n if (!item) {\n const name = (typeof keyOrType === 'string' || typeof keyOrType === 'symbol')\n ? String(keyOrType)\n : (keyOrType as any).name || String(keyOrType);\n throw new ServiceNotFoundError(name);\n }\n\n const uid = item.uid;\n\n if (this.instances.has(uid)) {\n return this.instances.get(uid);\n }\n\n if (this.resolving.has(uid)) {\n const pathStr = this.path.map(k => (typeof k === 'symbol' ? k.description || String(k) : k)).concat(typeof key === 'symbol' ? key.description || String(key) : key).join(' -> ');\n throw new CircularDependencyError(pathStr);\n }\n\n this.resolving.add(uid);\n this.path.push(key);\n\n try {\n if (item.kind === 'value') return this.resolveValue(uid, item.value);\n\n if (Array.isArray(item.type)) return this.resolveArray(uid, item.type);\n\n if (item.kind === 'function' && item.func) return this.resolveFunc(uid, item.func, item.params);\n\n if (item.factory) return this.resolveFactory(uid, item.factory);\n\n return this.resolveClass(uid, item.type as Class, item.params);\n } finally {\n this.resolving.delete(uid);\n this.path.pop();\n }\n }\n\n /**\n * Synchronously disposes of all resolved services.\n * Throws AsyncDisposalError if this is an async scope or if any service disposal returns a Promise.\n */\n dispose(): void {\n if (this.disposed) return;\n\n if (this.isAsyncScope) {\n throw new AsyncDisposalError(this.name);\n }\n\n this.disposed = true;\n\n const entries = Array.from(this.instances.entries()).reverse();\n\n for (const [uid, inst] of entries) {\n if (inst && typeof inst.dispose === 'function') {\n const result = inst.dispose();\n if (result instanceof Promise) {\n throw new AsyncDisposalError(typeof uid === 'symbol' ? uid.description || String(uid) : String(uid));\n }\n } else if (inst && typeof inst.disposeAsync === 'function') {\n throw new AsyncDisposalError(typeof uid === 'symbol' ? uid.description || String(uid) : String(uid));\n }\n }\n\n this.instances.clear();\n }\n\n /**\n * Asynchronously disposes of all resolved services.\n */\n async disposeAsync(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n\n const entries = Array.from(this.instances.values()).reverse();\n\n for (const inst of entries) {\n if (inst && typeof inst.disposeAsync === 'function') {\n await inst.disposeAsync();\n } else if (inst && typeof inst.dispose === 'function') {\n const result = inst.dispose();\n if (result instanceof Promise) {\n await result;\n }\n }\n }\n\n this.instances.clear();\n }\n\n /**\n * Resolves a singleton value.\n * @param uid The unique ID of the value.\n * @param value The value to resolve.\n */\n private resolveValue(uid: string | symbol, value: any): any {\n this.instances.set(uid, value);\n return value;\n }\n\n /**\n * Resolves an array of services.\n * @param uid The unique ID of the service array.\n * @param types The class types to resolve for the array.\n */\n private resolveArray(uid: string | symbol, types: Class[]): any {\n const instances = types.map((cls) => {\n const inst = this.getService(cls);\n return inst;\n });\n\n this.instances.set(uid, instances);\n return instances;\n }\n\n /**\n * Resolves a service via a factory.\n * @param uid The unique ID of the service.\n * @param factory The factory to use for resolution.\n */\n private resolveFactory(uid: string | symbol, factory: ImplementationFactory<any, any>): any {\n const container = this.createContainerProxy();\n const result = factory(container, this);\n this.instances.set(uid, result);\n return result;\n }\n\n /**\n * Resolves a service via a function.\n * @param uid The unique ID of the service.\n * @param func The function to use for resolution.\n * @param params The arguments for the function.\n */\n private resolveFunc(uid: string | symbol, func: (...args: any[]) => any, params?: any[]): any {\n const rawParams = params || [];\n const resolvedParams = rawParams.map((param) => {\n const paramKey = this.tryGetKey(param);\n const inst = paramKey ? this.getService(paramKey) : param;\n return inst;\n });\n\n const result = func(...resolvedParams);\n this.instances.set(uid, result);\n return result;\n }\n\n /**\n * Resolves a service via its class type.\n * @param uid The unique ID of the service.\n * @param type The class type to instantiate.\n * @param params The constructor arguments.\n */\n private resolveClass(uid: string | symbol, type: Class, params?: any[]): any {\n const rawParams = params || [];\n const resolvedParams = rawParams.map((param) => {\n const paramKey = this.tryGetKey(param);\n const inst = paramKey ? this.getService(paramKey) : param;\n return inst;\n });\n\n const instance = new (type as ConcreteClass)(...resolvedParams);\n this.instances.set(uid, instance);\n return instance;\n }\n\n /**\n * Creates a proxy for the type map to allow resolving services by property access.\n */\n private createContainerProxy(): ResolvedTypeMap<T> {\n return new Proxy({} as ResolvedTypeMap<T>, {\n get: (_, prop) => {\n if (typeof prop !== 'string' && typeof prop !== 'symbol') return undefined;\n return this.getService(prop as any);\n }\n });\n }\n\n /**\n * Gets the key for a given key or class type.\n * @param keyOrType The key or class type.\n */\n private getKey<K extends keyof T & (string | symbol)>(keyOrType: K | T[K]): string | symbol {\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') return keyOrType;\n\n const key = this.tryGetKey(keyOrType);\n if (key) return key;\n\n const name = Array.isArray(keyOrType)\n ? `[${keyOrType.map((c: any) => (c as any).name).join(', ')}]`\n : (keyOrType as any).name || String(keyOrType);\n throw new ServiceNotFoundError(name);\n }\n\n /**\n * Attempts to get the key for a given key or class type without throwing.\n * @param keyOrType The key or class type.\n */\n private tryGetKey(keyOrType: any): string | symbol | undefined {\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n if (keyOrType in this.definitions) return keyOrType;\n \n // Fallback for string names (backward compatibility)\n if (typeof keyOrType === 'string') {\n const entry = Reflect.ownKeys(this.definitions).find((k) => {\n const v = this.definitions[k as any];\n return v.kind === 'service' && !Array.isArray(v.type) && (v.type as any)?.name === keyOrType;\n });\n if (entry) return entry as string | symbol;\n }\n return undefined;\n }\n\n if (typeof keyOrType === 'function' || Array.isArray(keyOrType)) {\n // Check the stable registry first (minification proof)\n const stableKey = getStableKey(keyOrType as any);\n if (stableKey in this.definitions) return stableKey;\n\n // Fallback to searching by reference (for explicit symbols or non-auto registrations)\n const entry = Reflect.ownKeys(this.definitions).find((k) => {\n const v = this.definitions[k as any];\n return v.kind === 'service' && v.type === keyOrType;\n });\n if (entry) return entry as string | symbol;\n }\n\n return undefined;\n }\n}\n", "import {\n RegistrationError,\n} from './errors.js';\nimport { getStableKey } from './registry.js';\nimport { ServiceProvider } from './service-provider.js';\nimport type {\n Class,\n ClassArgs,\n FilterKeys,\n FilterValueKeys,\n FilterFuncKeys,\n FuncArgs,\n ImplementationFactory,\n MapToInstance,\n ServiceDefinitionMap,\n TypeMap,\n ServiceDefinition\n} from './types.js';\n\n/**\n * Fluent builder for service collections using a lookup map.\n */\nexport class ServiceCollection<T extends TypeMap> {\n private definitions: ServiceDefinitionMap = {};\n private typeMap: T;\n\n /**\n * Initializes a new instance of the ServiceCollection class.\n */\n constructor() {\n this.typeMap = {} as T;\n }\n\n /**\n * Adds a singleton service using a factory function.\n * Key is derived from the class.\n * @param type The class to register.\n * @param factory The factory function to create the service instance.\n * @example\n * .addSingletonFactory(UserRepo, (c) => new UserRepo(c.UserService))\n */\n addSingletonFactory<Key extends keyof T & (string | symbol), C extends Class>(\n type: C,\n factory: ImplementationFactory<T, InstanceType<C>>\n ): this;\n\n /**\n * Adds a singleton service using a factory function and a key.\n * @param key The key to register the service under.\n * @param factory The factory function to create the service instance.\n * @example\n * .addSingletonFactory(\"UserRepo\", (c) => new UserRepo(c.UserService))\n */\n addSingletonFactory<Key extends keyof T & (string | symbol)>(\n key: Key,\n factory: ImplementationFactory<T, MapToInstance<T[Key]>>\n ): this;\n\n addSingletonFactory<Key extends keyof T & (string | symbol)>(\n keyOrType: Key | Class,\n factory: ImplementationFactory<T, any>\n ): this {\n let key: string | symbol;\n let type: any;\n let isExplicitKey = false;\n\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n key = keyOrType;\n type = this.typeMap[key];\n isExplicitKey = true;\n } else {\n const resolved = this.resolveKeyAndType<Key>(keyOrType as any);\n key = resolved.key;\n type = resolved.type;\n }\n\n const uid = isExplicitKey ? key : getStableKey(type);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type, factory };\n this.definitions[key] = def;\n if (key !== uid) this.definitions[uid] = def;\n\n return this;\n }\n\n /**\n * Registers the ServiceProvider itself as a service.\n * This allows services to depend on the ServiceProvider to resolve other services dynamically.\n * @param key The key to register the ServiceProvider under.\n * @example\n * .addServiceProvider(\"ServiceProvider\")\n */\n addServiceProvider<Key extends keyof T & (string | symbol)>(key: Key) {\n return this.addSingletonFactory(key as any, (_, sp) => sp)\n }\n\n /**\n * Adds a scoped service using a factory function.\n * Key is derived from the class.\n * @param type The class to register.\n * @param factory The factory function to create the service instance.\n * @example\n * .addScopedFactory(UserRepo, (c) => new UserRepo(c.UserService))\n */\n addScopedFactory<Key extends keyof T & (string | symbol), C extends Class>(\n type: C,\n factory: ImplementationFactory<T, InstanceType<C>>\n ): this;\n\n /**\n * Adds a scoped service using a factory function and a key.\n * @param key The key to register the service under.\n * @param factory The factory function to create the service instance.\n * @example\n * .addScopedFactory(\"UserRepo\", (c) => new UserRepo(c.UserService))\n */\n addScopedFactory<Key extends keyof T & (string | symbol)>(\n key: Key,\n factory: ImplementationFactory<T, MapToInstance<T[Key]>>\n ): this;\n\n addScopedFactory<Key extends keyof T & (string | symbol)>(\n keyOrType: Key | Class,\n factory: ImplementationFactory<T, any>\n ): this {\n let key: string | symbol;\n let type: any;\n let isExplicitKey = false;\n\n if (typeof keyOrType === 'string' || typeof keyOrType === 'symbol') {\n key = keyOrType;\n type = this.typeMap[key];\n isExplicitKey = true;\n } else {\n const resolved = this.resolveKeyAndType<Key>(keyOrType as any);\n key = resolved.key;\n type = resolved.type;\n }\n\n const uid = isExplicitKey ? key : getStableKey(type);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type, factory };\n this.definitions[key] = def;\n if (key !== uid) this.definitions[uid] = def;\n\n return this;\n }\n\n /**\n * Adds a singleton service using constructor injection.\n * Key is derived from the container map based on the Class.\n * @param type The class to register.\n * @param params The constructor arguments.\n * @example\n * .addSingletonClass(UserService, \"admin\", \"password\")\n */\n addSingletonClass<C extends Class>(\n type: C,\n ...params: ClassArgs<C, keyof T & (string | symbol)>\n ): this {\n const { key, type: typeRef } = this.resolveKeyAndType(type as any);\n const uid = getStableKey(typeRef);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type: typeRef, params };\n this.definitions[key] = def;\n this.definitions[uid] = def;\n return this;\n }\n\n /**\n * Adds a scoped service using constructor injection.\n * Key is derived from the container map based on the Class.\n * @param type The class to register.\n * @param params The constructor arguments.\n * @example\n * .addScopedClass(UserService, \"admin\", \"password\")\n */\n addScopedClass<C extends Class>(\n type: C,\n ...params: ClassArgs<C, keyof T & (string | symbol)>\n ): this {\n const { key, type: typeRef } = this.resolveKeyAndType(type as any);\n const uid = getStableKey(typeRef);\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type: typeRef, params };\n this.definitions[key] = def;\n this.definitions[uid] = def;\n return this;\n }\n\n /**\n * Adds a group (array) of singleton services.\n * Automatically registers individual classes as singletons if not already registered.\n * @param key The key for the service group.\n * @param types The classes to register in the group.\n * @example\n * .addSingletonGroup(\"MessageCommand\", HelloCommand, ByeCommand)\n */\n addSingletonGroup<\n Key extends FilterKeys<T, any[]>,\n C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]\n >(\n key: Key,\n ...types: C\n ): this {\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid: key, type: types };\n (this.typeMap as any)[key] = types;\n this.definitions[key] = def;\n\n // Auto-register individual classes if not already registered\n const typeArray = types as Class[];\n for (const type of typeArray) {\n const foundKey = Reflect.ownKeys(this.typeMap).find(k => this.typeMap[k as any] === type);\n if (foundKey) continue;\n\n const name = type.name;\n if (!name) {\n throw new RegistrationError(`Class in group \"${String(key)}\" is missing a name and cannot be auto-registered.`);\n }\n\n const uid = getStableKey(type);\n const classDef: ServiceDefinition<any> = { kind: 'service', lifetime: 'singleton', uid, type, params: [] };\n (this.typeMap as any)[name] = type;\n this.definitions[name] = classDef;\n this.definitions[uid] = classDef;\n }\n\n return this;\n }\n\n /**\n * Adds a group (array) of scoped services.\n * Automatically registers individual classes as scoped if not already registered.\n * @param key The key for the service group.\n * @param types The classes to register in the group.\n * @example\n * .addScopedGroup(\"MessageCommand\", HelloCommand, ByeCommand)\n */\n addScopedGroup<\n Key extends FilterKeys<T, any[]>,\n C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]\n >(\n key: Key,\n ...types: C\n ): this {\n const def: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid: key, type: types };\n (this.typeMap as any)[key] = types;\n this.definitions[key] = def;\n\n // Auto-register individual classes if not already registered\n const typeArray = types as Class[];\n for (const type of typeArray) {\n const foundKey = Reflect.ownKeys(this.typeMap).find(k => this.typeMap[k as any] === type);\n if (foundKey) continue;\n\n const name = type.name;\n if (!name) {\n throw new RegistrationError(`Class in group \"${String(key)}\" is missing a name and cannot be auto-registered.`);\n }\n\n const uid = getStableKey(type);\n const classDef: ServiceDefinition<any> = { kind: 'service', lifetime: 'scoped', uid, type, params: [] };\n (this.typeMap as any)[name] = type;\n this.definitions[name] = classDef;\n this.definitions[uid] = classDef;\n }\n\n return this;\n }\n\n /**\n * Adds a singleton service using a function.\n * @param key The key for the service.\n * @param func The function to register.\n * @param params The function arguments.\n * @example\n * .addSingletonFunc(\"Logger\", createLogger, \"Config\")\n */\n addSingletonFunc<Key extends FilterFuncKeys<T>, F extends (...args: any[]) => T[Key]>(\n key: Key,\n func: F,\n ...params: FuncArgs<F, T>\n ): this {\n this.definitions[key] = { kind: 'function', lifetime: 'singleton', uid: key, func, params };\n return this;\n }\n\n /**\n * Adds a scoped service using a function.\n * @param key The key for the service.\n * @param func The function to register.\n * @param params The function arguments.\n * @example\n * .addScopedFunc(\"Logger\", createLogger, \"Config\")\n */\n addScopedFunc<Key extends FilterFuncKeys<T>, F extends (...args: any[]) => T[Key]>(\n key: Key,\n func: F,\n ...params: FuncArgs<F, T>\n ): this {\n this.definitions[key] = { kind: 'function', lifetime: 'scoped', uid: key, func, params };\n return this;\n }\n\n /**\n * Adds a singleton value.\n * @param key The key for the value.\n * @param value The value to register.\n * @example\n * .addSingletonValue(\"connectionString\", \"test connection string\")\n */\n addSingletonValue<Key extends FilterValueKeys<T>>(\n key: Key,\n value: T[Key]\n ): this {\n this.definitions[key] = { kind: 'value', lifetime: 'singleton', uid: key, value };\n return this;\n }\n\n /**\n * Adds a scoped value.\n * @param key The key for the value.\n * @param value The value to register.\n * @example\n * .addScopedValue(\"connectionString\", \"test connection string\")\n */\n addScopedValue<Key extends FilterValueKeys<T>>(\n key: Key,\n value: T[Key]\n ): this {\n this.definitions[key] = { kind: 'value', lifetime: 'scoped', uid: key, value };\n return this;\n }\n\n /**\n * Resolves the string key and Class reference for a given type.\n * If the type is already mapped in the TypeMap, the existing key is used.\n * Otherwise, it auto-registers the type using its class name as the key.\n * @param type The class reference to resolve.\n * @throws RegistrationError if the class name cannot be determined (e.g. anonymous class).\n * @example\n * const { key, type } = this.resolveKeyAndType(UserService);\n */\n private resolveKeyAndType<Key extends keyof T & (string | symbol)>(type: T[Key] & Class): { key: Key, type: T[Key] } {\n let key: Key;\n\n const foundKey = Reflect.ownKeys(this.typeMap).find(\n (k) => this.typeMap[k as any] === type\n );\n if (foundKey) {\n key = foundKey as Key;\n } else {\n // Auto-register using class name for backward compatibility\n key = (type.name || getStableKey(type)) as any as Key;\n (this.typeMap as any)[key] = type;\n }\n\n return { key, type };\n }\n\n /**\n * Builds the ServiceProvider.\n * @param name The name of the service provider.\n * @example\n * const di = new ServiceCollection<LocalMap>()\n * .addSingletonClass(MyService)\n * .build();\n */\n build(name: string = 'root'): ServiceProvider<T> {\n // Validate all registered services\n for (const key of Reflect.ownKeys(this.definitions)) {\n const item = this.definitions[key as any];\n if (item.kind !== 'service' || !Array.isArray(item.type)) continue;\n\n // This is an array of services\n for (const type of item.type as Class[]) {\n const name = type.name;\n const definitionsItem = this.definitions[name];\n\n // Check if this class was auto-registered (params is empty array) but requires arguments\n if (definitionsItem && definitionsItem.params && definitionsItem.params.length === 0 && type.length > 0) {\n throw new RegistrationError(`Class \"${name}\" in group \"${String(key)}\" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`);\n }\n }\n }\n\n return new ServiceProvider<T>(name, this.definitions);\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["index_exports", "__export", "AsyncDisposalError", "CircularDependencyError", "RegistrationError", "ServiceCollection", "ServiceNotFoundError", "ServiceProvider", "ServiceProviderDisposedError", "__toCommonJS", "CircularDependencyError", "path", "ServiceNotFoundError", "identifier", "RegistrationError", "message", "ServiceProviderDisposedError", "AsyncDisposalError", "serviceKey", "classKeyRegistry", "getStableKey", "type", "key", "ServiceProvider", "_ServiceProvider", "name", "definitions", "parent", "isAsyncScope", "root", "keyOrType", "ServiceProviderDisposedError", "key", "item", "ServiceNotFoundError", "uid", "pathStr", "k", "CircularDependencyError", "AsyncDisposalError", "entries", "inst", "result", "value", "types", "instances", "cls", "factory", "container", "func", "params", "resolvedParams", "param", "paramKey", "type", "instance", "_", "prop", "c", "entry", "v", "stableKey", "getStableKey", "ServiceCollection", "keyOrType", "factory", "key", "type", "isExplicitKey", "resolved", "uid", "getStableKey", "def", "_", "sp", "params", "typeRef", "types", "typeArray", "k", "name", "RegistrationError", "classDef", "func", "value", "foundKey", "item", "definitionsItem", "ServiceProvider"]
7
7
  }
@@ -71,23 +71,23 @@ export declare class ServiceCollection<T extends TypeMap> {
71
71
  */
72
72
  addScopedClass<C extends Class>(type: C, ...params: ClassArgs<C, keyof T & (string | symbol)>): this;
73
73
  /**
74
- * Adds an array of singleton services.
75
- * Automatically registers individual classes if not already registered.
76
- * @param key The key for the service array.
77
- * @param types The classes to register in the array.
74
+ * Adds a group (array) of singleton services.
75
+ * Automatically registers individual classes as singletons if not already registered.
76
+ * @param key The key for the service group.
77
+ * @param types The classes to register in the group.
78
78
  * @example
79
- * .addSingletonArray("MessageCommand", HelloCommand, ByeCommand)
79
+ * .addSingletonGroup("MessageCommand", HelloCommand, ByeCommand)
80
80
  */
81
- addSingletonArray<Key extends FilterKeys<T, any[]>, C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]>(key: Key, ...types: C): this;
81
+ addSingletonGroup<Key extends FilterKeys<T, any[]>, C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]>(key: Key, ...types: C): this;
82
82
  /**
83
- * Adds an array of scoped services.
83
+ * Adds a group (array) of scoped services.
84
84
  * Automatically registers individual classes as scoped if not already registered.
85
- * @param key The key for the service array.
86
- * @param types The classes to register in the array.
85
+ * @param key The key for the service group.
86
+ * @param types The classes to register in the group.
87
87
  * @example
88
- * .addScopedArray("MessageCommand", HelloCommand, ByeCommand)
88
+ * .addScopedGroup("MessageCommand", HelloCommand, ByeCommand)
89
89
  */
90
- addScopedArray<Key extends FilterKeys<T, any[]>, C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]>(key: Key, ...types: C): this;
90
+ addScopedGroup<Key extends FilterKeys<T, any[]>, C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]>(key: Key, ...types: C): this;
91
91
  /**
92
92
  * Adds a singleton service using a function.
93
93
  * @param key The key for the service.
@@ -36,11 +36,11 @@ export interface IServiceProvider<T extends TypeMap> {
36
36
  /**
37
37
  * Creates a new scoped ServiceProvider.
38
38
  */
39
- createScope(): IServiceProvider<T>;
39
+ createScope(name?: string): IServiceProvider<T>;
40
40
  /**
41
41
  * Creates a new scoped ServiceProvider that supports asynchronous disposal.
42
42
  */
43
- createAsyncScope(): IServiceProvider<T>;
43
+ createAsyncScope(name?: string): IServiceProvider<T>;
44
44
  /**
45
45
  * Resolves a service by its key.
46
46
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
@@ -3,177 +3,214 @@
3
3
  Quick reference for the Type-Safe Dependency Injection container.
4
4
 
5
5
  ## Table of Contents
6
- 1. [Setup & TypeMap](#1-setup--typemap)
7
- 2. [Class Registration](#2-class-registration)
8
- 3. [Factory Registration](#3-factory-registration)
9
- 4. [Function Registration](#4-function-registration)
10
- 5. [Array Registration](#5-array-registration)
11
- 6. [Value Registration](#6-value-registration)
12
- 7. [Service Retrieval](#7-service-retrieval)
13
- 8. [Scopes](#8-scopes)
14
- 9. [Disposal](#9-disposal)
6
+ 1. [Core Concepts](#core-concepts)
7
+ - [The TypeMap](#1-the-typemap)
8
+ - [Working with Interfaces](#2-working-with-interfaces)
9
+ 2. [Registration Examples](#registration-examples)
10
+ - [Class Registration](#class-registration)
11
+ - [Interface & Key Registration](#interface--key-registration)
12
+ - [Factory Registration (Sync & Async)](#factory-registration-sync--async)
13
+ - [Function Registration (Sync & Async)](#function-registration-sync--async)
14
+ - [Group Registration (Multiple Implementations)](#group-registration-multiple-implementations)
15
+ 3. [Scopes & Lifecycle](#scopes--lifecycle)
16
+ - [Scoped Services](#scoped-services)
17
+ - [Disposal](#disposal)
15
18
 
16
19
  ---
17
20
 
18
- ## 1. Setup & TypeMap
19
- The `TypeMap` defines the contract of your container.
21
+ ## Core Concepts
20
22
 
21
- ```typescript
22
- import { ServiceCollection } from '@js-injection/service-provider';
23
+ ### 1. The TypeMap
24
+ The `TypeMap` is the central contract for your container. It maps **keys** (strings or symbols) to their **resolved instance types**. This ensures full type safety when resolving services.
23
25
 
24
- interface MyMap {
25
- logger: ILogger;
26
- database: Database;
27
- userService: UserService;
28
- apiClient: ApiClient;
29
- config: Config;
30
- plugins: Plugin[];
31
- generateId: () => string;
32
- }
33
- ```
26
+ ### 2. Working with Interfaces
27
+ In TypeScript, interfaces do not exist at runtime, so you cannot use them as keys directly. Instead, you map a **string/symbol key** to an **interface type** in the `TypeMap`, then register a **concrete class** to that key.
34
28
 
35
29
  ---
36
30
 
37
- ## 2. Class Registration
31
+ ## Registration Examples
32
+
33
+ ### Class Registration
38
34
  Standard constructor injection. Dependencies are automatically resolved.
39
35
 
40
36
  ```typescript
41
- class Logger implements ILogger {
42
- log(msg: string) { console.log(msg); }
43
- }
37
+ import { ServiceCollection } from '@js-injection/service-provider';
44
38
 
45
- class UserService {
46
- constructor(public logger: ILogger) {}
47
- }
39
+ // 1. Define Services
40
+ class Logger { log(msg: string) { console.log(msg); } }
41
+ class UserService { constructor(public logger: Logger) {} }
48
42
 
49
- class ApiClient {
50
- constructor(public logger: ILogger) {}
43
+ // 2. Define TypeMap
44
+ interface MyMap {
45
+ Logger: Logger;
46
+ UserService: UserService;
51
47
  }
52
48
 
53
- const sp = new ServiceCollection<MyMap>()
54
- // Singleton (one instance global)
49
+ // 3. Build & Resolve
50
+ const container = new ServiceCollection<MyMap>()
55
51
  .addSingletonClass(Logger)
56
52
  .addSingletonClass(UserService, Logger)
57
- // Scoped (one instance per scope)
58
- .addScopedClass(ApiClient)
59
- // Build the service provider
60
53
  .build();
54
+
55
+ const userService = container.getService(UserService);
61
56
  ```
62
57
 
63
- ---
58
+ ### Interface & Key Registration
59
+ Mapping an interface to a concrete implementation using a string key.
60
+
61
+ ```typescript
62
+ import { ServiceCollection } from '@js-injection/service-provider';
64
63
 
65
- ## 3. Factory Registration
66
- Use factories for complex logic or when you need access to the container.
64
+ // 1. Define Interface & Implementation
65
+ interface ILogger { log(msg: string): void; }
66
+ class ConsoleLogger implements ILogger { log(msg: string) { console.log(msg); } }
67
+
68
+ // 2. Define TypeMap (Key -> Interface)
69
+ interface MyMap {
70
+ logger: ILogger;
71
+ }
72
+
73
+ // 3. Build & Resolve
74
+ const container = new ServiceCollection<MyMap>()
75
+ .addSingletonClass('logger', ConsoleLogger)
76
+ .build();
77
+
78
+ // Resolution Options:
79
+
80
+ // A. Resolve by Key (returns ILogger interface type)
81
+ const logger = container.getService('logger');
82
+
83
+ // B. Resolve by Concrete Class (returns ConsoleLogger instance type)
84
+ const consoleLogger = container.getService(ConsoleLogger);
85
+ ```
86
+
87
+ ### Factory Registration (Sync & Async)
88
+ Use factories for complex logic or when you need dynamic resolution from the container.
67
89
 
68
90
  ```typescript
69
- class Database {
70
- constructor(public connectionString: string) {}
91
+ import { ServiceCollection } from '@js-injection/service-provider';
92
+
93
+ class Database { constructor(public url: string) {} }
94
+
95
+ interface MyMap {
96
+ db: Database;
97
+ asyncDb: Promise<Database>;
98
+ config: { url: string };
71
99
  }
72
100
 
73
- const sp = new ServiceCollection<MyMap>()
74
- // Singleton Factory
75
- .addSingletonFactory(Database, (container) => {
76
- const connectionString = container.config.dbUrl;
77
- return new Database(connectionString);
101
+ const container = new ServiceCollection<MyMap>()
102
+ .addSingletonValue('config', { url: 'postgres://localhost' })
103
+ // A. Synchronous Factory
104
+ .addSingletonFactory('db', (c) => new Database(c.config.url))
105
+ // B. Asynchronous Factory
106
+ .addSingletonFactory('asyncDb', async (c) => {
107
+ const db = new Database(c.config.url);
108
+ await db.connect(); // hypothetical async operation
109
+ return db;
78
110
  })
79
- // Scoped Factory
80
- .addScopedFactory('apiClient', (container, sp) => {
81
- return new ApiClient(container.logger);
82
- })
83
- // Build the service provider
84
111
  .build();
85
- ```
86
112
 
87
- ---
113
+ const db = container.getService('db');
114
+ const asyncDb = await container.getService('asyncDb'); // Use 'await' for promises
115
+ ```
88
116
 
89
- ## 4. Function Registration
90
- Register a function as a service. Arguments are auto-injected.
117
+ ### Function Registration (Sync & Async)
118
+ Register a plain function as a service. Arguments are auto-injected from the container.
91
119
 
92
120
  ```typescript
93
- function createIdGenerator(prefix: string) {
94
- return () => `${prefix}-${Math.random()}`;
121
+ import { ServiceCollection } from '@js-injection/service-provider';
122
+
123
+ // 1. Define Functions
124
+ const createId = (prefix: string) => () => `${prefix}-${Math.random()}`;
125
+ const fetchConfig = async (url: string) => {
126
+ const res = await fetch(url);
127
+ return res.json();
95
128
  }
96
129
 
97
- // Arguments can be literal values or other services
98
- const sp = new ServiceCollection<MyMap>()
99
- .addSingletonFunc('generateId', createIdGenerator, 'APP')
100
- // Build the service provider
130
+ // 2. Define TypeMap
131
+ interface MyMap {
132
+ generateId: () => string;
133
+ config: Promise<any>;
134
+ }
135
+
136
+ // 3. Build & Resolve
137
+ const container = new ServiceCollection<MyMap>()
138
+ .addSingletonValue('configUrl', 'https://api.example.com/config')
139
+ .addSingletonFunc('generateId', createId, 'APP')
140
+ .addSingletonFunc('config', fetchConfig, 'configUrl')
101
141
  .build();
102
- ```
103
142
 
104
- ---
143
+ const generateId = container.getService('generateId');
144
+ const config = await container.getService('config'); // Use 'await' for promises
145
+ ```
105
146
 
106
- ## 5. Array Registration
107
- Map multiple implementations to a single key. Returns an array.
147
+ ### Group Registration (Multiple Implementations)
148
+ Map multiple implementations to a single key. Useful for plugins or middleware.
108
149
 
109
150
  ```typescript
151
+ import { ServiceCollection } from '@js-injection/service-provider';
152
+
110
153
  interface Plugin { name: string; }
111
154
  class AuthPlugin implements Plugin { name = 'auth'; }
112
155
  class LogPlugin implements Plugin { name = 'log'; }
113
156
 
114
- // Individual classes are auto-registered if needed
115
- const sp = new ServiceCollection<MyMap>()
116
- .addSingletonArray('plugins', AuthPlugin, LogPlugin)
117
- // Build the service provider
157
+ interface MyMap {
158
+ plugins: Plugin[];
159
+ }
160
+
161
+ const container = new ServiceCollection<MyMap>()
162
+ .addSingletonGroup('plugins', AuthPlugin, LogPlugin)
118
163
  .build();
119
164
 
120
- // Retrieval
121
- const plugins = sp.getService('plugins'); // [AuthPlugin, LogPlugin]
165
+ const plugins = container.getService('plugins'); // [AuthPlugin, LogPlugin]
122
166
  ```
123
167
 
124
168
  ---
125
169
 
126
- ## 6. Value Registration
127
- Register constant values or configuration objects.
170
+ ## Scopes & Lifecycle
128
171
 
129
- ```typescript
130
- interface Config { dbUrl: string; }
131
- const config: Config = { dbUrl: 'postgres://localhost:5432' };
172
+ ### Scoped Services
173
+ Scoped services are created once per scope (e.g., per web request).
132
174
 
133
- const sp = new ServiceCollection<MyMap>()
134
- .addSingletonValue('config', config)
135
- // Build the service provider
136
- .build();
137
- ```
175
+ ```typescript
176
+ import { ServiceCollection } from '@js-injection/service-provider';
138
177
 
139
- ---
178
+ class RequestContext { id = Math.random(); }
140
179
 
141
- ## 7. Service Retrieval
142
- Resolve services from the built provider.
180
+ interface MyMap {
181
+ ctx: RequestContext;
182
+ }
143
183
 
144
- ```typescript
145
- const sp = new ServiceCollection<MyMap>().build();
184
+ const root = new ServiceCollection<MyMap>()
185
+ .addScopedClass('ctx', RequestContext)
186
+ .build();
146
187
 
147
- // 1. Resolve by Class (returns Implementation type)
148
- const userService = sp.getService(UserService);
188
+ // Each scope gets its own instance
189
+ const scope1 = root.createScope();
190
+ const scope2 = root.createScope();
149
191
 
150
- // 2. Resolve by Key (returns Interface type from TypeMap)
151
- const logger = sp.getService('logger');
192
+ const ctx1 = scope1.getService('ctx');
193
+ const ctx2 = scope2.getService('ctx'); // ctx1 !== ctx2
152
194
  ```
153
195
 
154
- ---
155
-
156
- ## 8. Scopes
157
- Create child containers for unit-of-work isolation.
196
+ ### Disposal
197
+ Clean up resources by implementing `dispose()` or `disposeAsync()`.
158
198
 
159
199
  ```typescript
160
- // Standard Scope
161
- const scope = sp.createScope();
162
- const scopedSvc = scope.getService(ApiClient);
200
+ import { ServiceCollection } from '@js-injection/service-provider';
163
201
 
164
- // Async Scope (supports async disposal)
165
- const asyncScope = sp.createAsyncScope();
166
- ```
202
+ class Database {
203
+ async disposeAsync() { /* close connections */ }
204
+ }
167
205
 
168
- ---
206
+ interface MyMap { db: Database; }
169
207
 
170
- ## 9. Disposal
171
- Clean up resources for `IDisposable` and `IAsyncDisposable` services.
208
+ const container = new ServiceCollection<MyMap>()
209
+ .addSingletonClass(Database)
210
+ .build();
172
211
 
173
- ```typescript
174
- // Synchronous (throws if any service is async)
175
- sp.dispose();
212
+ container.getService(Database);
176
213
 
177
- // Asynchronous (recommended)
178
- await sp.disposeAsync();
214
+ // Asynchronously dispose of all resolved services
215
+ await container.disposeAsync();
179
216
  ```
package/package.json CHANGED
@@ -1,9 +1,15 @@
1
1
  {
2
2
  "name": "@js-injection/service-provider",
3
- "version": "1.0.0-alpha.1",
4
- "description": "",
3
+ "version": "1.0.0-alpha.2",
4
+ "description": "A lightweight, type-safe dependency injection container",
5
+ "keywords": [
6
+ "dependency-injection",
7
+ "di",
8
+ "ioc",
9
+ "service-provider"
10
+ ],
5
11
  "license": "ISC",
6
- "author": "",
12
+ "author": "Peter Flannery",
7
13
  "repository": {
8
14
  "type": "git",
9
15
  "url": "git+https://gitlab.com/js-injection/service-provider.git"
@@ -18,6 +24,7 @@
18
24
  "type": "module",
19
25
  "types": "./dist/types/src/index.d.ts",
20
26
  "main": "./dist/legacy.cjs",
27
+ "module": "./dist/index.js",
21
28
  "imports": {
22
29
  "#src/*": "./out/src/*"
23
30
  },
@@ -34,7 +41,7 @@
34
41
  "esbuild": "0.27.4",
35
42
  "js-build-tasks": "1.0.0-rc.18",
36
43
  "mocha": "11.7.5",
37
- "mocha-ui-esm": "1.0.0-beta.17",
44
+ "mocha-ui-esm": "1.0.0-beta.19",
38
45
  "rimraf": "6.1.3",
39
46
  "source-map-support": "0.5.21",
40
47
  "typescript": "5.9.3"
@@ -185,14 +185,14 @@ export class ServiceCollection<T extends TypeMap> {
185
185
  }
186
186
 
187
187
  /**
188
- * Adds an array of singleton services.
189
- * Automatically registers individual classes if not already registered.
190
- * @param key The key for the service array.
191
- * @param types The classes to register in the array.
188
+ * Adds a group (array) of singleton services.
189
+ * Automatically registers individual classes as singletons if not already registered.
190
+ * @param key The key for the service group.
191
+ * @param types The classes to register in the group.
192
192
  * @example
193
- * .addSingletonArray("MessageCommand", HelloCommand, ByeCommand)
193
+ * .addSingletonGroup("MessageCommand", HelloCommand, ByeCommand)
194
194
  */
195
- addSingletonArray<
195
+ addSingletonGroup<
196
196
  Key extends FilterKeys<T, any[]>,
197
197
  C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]
198
198
  >(
@@ -211,7 +211,7 @@ export class ServiceCollection<T extends TypeMap> {
211
211
 
212
212
  const name = type.name;
213
213
  if (!name) {
214
- throw new RegistrationError(`Class in array "${String(key)}" is missing a name and cannot be auto-registered.`);
214
+ throw new RegistrationError(`Class in group "${String(key)}" is missing a name and cannot be auto-registered.`);
215
215
  }
216
216
 
217
217
  const uid = getStableKey(type);
@@ -225,14 +225,14 @@ export class ServiceCollection<T extends TypeMap> {
225
225
  }
226
226
 
227
227
  /**
228
- * Adds an array of scoped services.
228
+ * Adds a group (array) of scoped services.
229
229
  * Automatically registers individual classes as scoped if not already registered.
230
- * @param key The key for the service array.
231
- * @param types The classes to register in the array.
230
+ * @param key The key for the service group.
231
+ * @param types The classes to register in the group.
232
232
  * @example
233
- * .addScopedArray("MessageCommand", HelloCommand, ByeCommand)
233
+ * .addScopedGroup("MessageCommand", HelloCommand, ByeCommand)
234
234
  */
235
- addScopedArray<
235
+ addScopedGroup<
236
236
  Key extends FilterKeys<T, any[]>,
237
237
  C extends (new (...args: any[]) => MapToInstance<T[Key]>[number])[]
238
238
  >(
@@ -251,7 +251,7 @@ export class ServiceCollection<T extends TypeMap> {
251
251
 
252
252
  const name = type.name;
253
253
  if (!name) {
254
- throw new RegistrationError(`Class in array "${String(key)}" is missing a name and cannot be auto-registered.`);
254
+ throw new RegistrationError(`Class in group "${String(key)}" is missing a name and cannot be auto-registered.`);
255
255
  }
256
256
 
257
257
  const uid = getStableKey(type);
@@ -375,7 +375,7 @@ export class ServiceCollection<T extends TypeMap> {
375
375
 
376
376
  // Check if this class was auto-registered (params is empty array) but requires arguments
377
377
  if (definitionsItem && definitionsItem.params && definitionsItem.params.length === 0 && type.length > 0) {
378
- throw new RegistrationError(`Class "${name}" in array "${String(key)}" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`);
378
+ throw new RegistrationError(`Class "${name}" in group "${String(key)}" requires constructor arguments and must be registered independently using addSingletonClass or addScopedClass.`);
379
379
  }
380
380
  }
381
381
  }
package/src/types.ts CHANGED
@@ -51,12 +51,12 @@ export interface IServiceProvider<T extends TypeMap> {
51
51
  /**
52
52
  * Creates a new scoped ServiceProvider.
53
53
  */
54
- createScope(): IServiceProvider<T>;
54
+ createScope(name?: string): IServiceProvider<T>;
55
55
 
56
56
  /**
57
57
  * Creates a new scoped ServiceProvider that supports asynchronous disposal.
58
58
  */
59
- createAsyncScope(): IServiceProvider<T>;
59
+ createAsyncScope(name?: string): IServiceProvider<T>;
60
60
 
61
61
  /**
62
62
  * Resolves a service by its key.