vorarbeiter
Advanced tools
Comparing version 5.0.0 to 6.0.0
@@ -17,5 +17,21 @@ export type Context = object; | ||
export type ServiceInjectorDefinition<T = unknown> = ServiceInjector<T> | ServiceInjectorFunction<T>; | ||
export declare enum ServiceType { | ||
Shared = "shared", | ||
Transient = "transient", | ||
Scoped = "scoped" | ||
} | ||
export interface ServiceTypeDefinitionShared { | ||
name: ServiceType.Shared; | ||
} | ||
export interface ServiceTypeDefinitionTransient { | ||
name: ServiceType.Transient; | ||
} | ||
export interface ServiceTypeDefinitionScoped { | ||
name: ServiceType.Scoped; | ||
contextResolver: ContextResolverDefinition; | ||
} | ||
export type ServiceTypeDefinition = ServiceTypeDefinitionShared | ServiceTypeDefinitionTransient | ServiceTypeDefinitionScoped; | ||
export interface ServiceDefinition<T = unknown> { | ||
type: ServiceTypeDefinition; | ||
factory: ServiceFactoryDefinition<T>; | ||
contextResolver: ContextResolverDefinition; | ||
injector?: ServiceInjectorDefinition<T>; | ||
@@ -41,6 +57,8 @@ } | ||
private resolveService; | ||
private resolveServiceShared; | ||
private resolveServiceTransient; | ||
private resolveServiceScoped; | ||
has(id: ServiceId): boolean; | ||
private createService; | ||
private storeService; | ||
private retrieveService; | ||
private executeInjection; | ||
private resolveContext; | ||
@@ -58,3 +76,3 @@ } | ||
private readonly factory; | ||
private contextResolver; | ||
private type; | ||
private injector?; | ||
@@ -81,9 +99,2 @@ constructor(factory: ServiceFactoryDefinition<T>); | ||
export declare const createServiceSpecBuilder: () => ServiceSpecBuilderImpl; | ||
export declare class SharedContextResolver implements ContextResolver { | ||
context: any; | ||
resolveContext(container: ServiceContainer): Context; | ||
} | ||
export declare class TransientContextResolver implements ContextResolver { | ||
resolveContext(container: ServiceContainer): Context; | ||
} | ||
export declare class UnknownServiceError extends Error { | ||
@@ -90,0 +101,0 @@ readonly id: ServiceId; |
@@ -5,2 +5,8 @@ 'use strict'; | ||
exports.ServiceType = void 0; | ||
(function (ServiceType) { | ||
ServiceType["Shared"] = "shared"; | ||
ServiceType["Transient"] = "transient"; | ||
ServiceType["Scoped"] = "scoped"; | ||
})(exports.ServiceType || (exports.ServiceType = {})); | ||
class ServiceContainerImpl { | ||
@@ -21,8 +27,43 @@ constructor(spec) { | ||
resolveService(id) { | ||
var _a; | ||
if (!this.spec.services.has(id)) { | ||
throw new UnknownServiceError(id); | ||
} | ||
return (_a = this.retrieveService(id)) !== null && _a !== void 0 ? _a : this.createService(id); | ||
const definition = this.spec.services.get(id); | ||
switch (definition.type.name) { | ||
case exports.ServiceType.Transient: | ||
return this.resolveServiceTransient(id); | ||
case exports.ServiceType.Scoped: | ||
return this.resolveServiceScoped(id); | ||
case exports.ServiceType.Shared: | ||
return this.resolveServiceShared(id); | ||
} | ||
} | ||
resolveServiceShared(id) { | ||
if (this.services.has(id)) { | ||
return this.services.get(id); | ||
} | ||
const service = this.createService(id); | ||
this.services.set(id, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
resolveServiceTransient(id) { | ||
const service = this.createService(id); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
resolveServiceScoped(id) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
const ctxMap = this.services.get(id); | ||
if (ctxMap.has(ctx)) { | ||
return ctxMap.get(ctx); | ||
} | ||
const service = this.createService(id); | ||
ctxMap.set(ctx, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
has(id) { | ||
@@ -36,27 +77,18 @@ return this.services.has(id); | ||
const definition = this.spec.services.get(id); | ||
const { factory, injector } = definition; | ||
const { factory } = definition; | ||
this.loading.add(id); | ||
const service = typeof factory === "function" ? factory(this) : factory.create(this); | ||
this.loading.delete(id); | ||
this.storeService(id, service); | ||
return service; | ||
} | ||
executeInjection(id, service) { | ||
const definition = this.spec.services.get(id); | ||
const { injector } = definition; | ||
if (injector) { | ||
typeof injector === "function" ? injector(service, this) : injector.inject(service, this); | ||
} | ||
return service; | ||
} | ||
storeService(id, service) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
this.services.get(id).set(ctx, service); | ||
} | ||
retrieveService(id) { | ||
var _a; | ||
const ctx = this.resolveContext(id); | ||
return (_a = this.services.get(id)) === null || _a === void 0 ? void 0 : _a.get(ctx); | ||
} | ||
resolveContext(id) { | ||
const definition = this.spec.services.get(id); | ||
const { contextResolver } = definition; | ||
const { contextResolver } = definition.type; | ||
return typeof contextResolver === "function" ? contextResolver(this) : contextResolver.resolveContext(this); | ||
@@ -69,14 +101,14 @@ } | ||
this.factory = factory; | ||
this.contextResolver = new SharedContextResolver(); | ||
this.shared(); | ||
} | ||
shared() { | ||
this.scoped(new SharedContextResolver()); | ||
this.type = { name: exports.ServiceType.Shared }; | ||
return this; | ||
} | ||
transient() { | ||
this.scoped(new TransientContextResolver()); | ||
this.type = { name: exports.ServiceType.Transient }; | ||
return this; | ||
} | ||
scoped(contextResolver) { | ||
this.contextResolver = contextResolver; | ||
this.type = { name: exports.ServiceType.Scoped, contextResolver }; | ||
return this; | ||
@@ -90,4 +122,4 @@ } | ||
return { | ||
type: this.type, | ||
factory: this.factory, | ||
contextResolver: this.contextResolver, | ||
injector: this.injector | ||
@@ -123,15 +155,2 @@ }; | ||
const createServiceSpecBuilder = () => new ServiceSpecBuilderImpl(); | ||
class SharedContextResolver { | ||
constructor() { | ||
this.context = Object.create(null); | ||
} | ||
resolveContext(container) { | ||
return this.context; | ||
} | ||
} | ||
class TransientContextResolver { | ||
resolveContext(container) { | ||
return Object.create(null); | ||
} | ||
} | ||
class UnknownServiceError extends Error { | ||
@@ -157,4 +176,2 @@ constructor(id) { | ||
exports.ServiceSpecBuilderImpl = ServiceSpecBuilderImpl; | ||
exports.SharedContextResolver = SharedContextResolver; | ||
exports.TransientContextResolver = TransientContextResolver; | ||
exports.UnknownServiceError = UnknownServiceError; | ||
@@ -161,0 +178,0 @@ exports.createServiceContainer = createServiceContainer; |
@@ -1,2 +0,2 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});class e{constructor(e){this.spec=e,this.services=new Map,this.loading=new Set;let t=this.resolveService.bind(this);this.spec.middlewares.forEach((e=>{t=e(t)})),this.resolveService=t}get(e){return this.resolveService(e)}resolveService(e){var t;if(!this.spec.services.has(e))throw new n(e);return null!==(t=this.retrieveService(e))&&void 0!==t?t:this.createService(e)}has(e){return this.services.has(e)}createService(e){if(this.loading.has(e))throw new c(e,[...this.loading.values(),e]);const t=this.spec.services.get(e),{factory:r,injector:s}=t;this.loading.add(e);const i="function"==typeof r?r(this):r.create(this);return this.loading.delete(e),this.storeService(e,i),s&&("function"==typeof s?s(i,this):s.inject(i,this)),i}storeService(e,t){const r=this.resolveContext(e);this.services.has(e)||this.services.set(e,new WeakMap),this.services.get(e).set(r,t)}retrieveService(e){var t;const r=this.resolveContext(e);return null===(t=this.services.get(e))||void 0===t?void 0:t.get(r)}resolveContext(e){const t=this.spec.services.get(e),{contextResolver:r}=t;return"function"==typeof r?r(this):r.resolveContext(this)}}class t{constructor(e){this.factory=e,this.contextResolver=new s}shared(){return this.scoped(new s),this}transient(){return this.scoped(new i),this}scoped(e){return this.contextResolver=e,this}withInjector(e){return this.injector=e,this}getServiceDefinition(){return{factory:this.factory,contextResolver:this.contextResolver,injector:this.injector}}}class r{constructor(){this.defBuilders=new Map,this.middlewares=[]}set(e,r){const s=new t(r);return this.defBuilders.set(e,s),s}addMiddleware(...e){return this.middlewares.push(...e),this}getServiceSpec(){const e=new Map;return this.defBuilders.forEach(((t,r)=>{e.set(r,t.getServiceDefinition())})),{services:e,middlewares:this.middlewares}}}class s{constructor(){this.context=Object.create(null)}resolveContext(e){return this.context}}class i{resolveContext(e){return Object.create(null)}}class n extends Error{constructor(e){super(`unknown service "${String(e)}"`),this.id=e,this.name="UnknownServiceError"}}class c extends Error{constructor(e,t){super(`circular dependency detected: ${t.map(String).join(" -> ")}`),this.id=e,this.referenceChain=t,this.name="ServiceCircularReferenceError"}}exports.ServiceCircularReferenceError=c,exports.ServiceContainerImpl=e,exports.ServiceDefinitionBuilderImpl=t,exports.ServiceSpecBuilderImpl=r,exports.SharedContextResolver=s,exports.TransientContextResolver=i,exports.UnknownServiceError=n,exports.createServiceContainer=t=>new e(t),exports.createServiceSpecBuilder=()=>new r; | ||
"use strict";var e;Object.defineProperty(exports,"__esModule",{value:!0}),exports.ServiceType=void 0,(e=exports.ServiceType||(exports.ServiceType={})).Shared="shared",e.Transient="transient",e.Scoped="scoped";class t{constructor(e){this.spec=e,this.services=new Map,this.loading=new Set;let t=this.resolveService.bind(this);this.spec.middlewares.forEach((e=>{t=e(t)})),this.resolveService=t}get(e){return this.resolveService(e)}resolveService(e){if(!this.spec.services.has(e))throw new i(e);switch(this.spec.services.get(e).type.name){case exports.ServiceType.Transient:return this.resolveServiceTransient(e);case exports.ServiceType.Scoped:return this.resolveServiceScoped(e);case exports.ServiceType.Shared:return this.resolveServiceShared(e)}}resolveServiceShared(e){if(this.services.has(e))return this.services.get(e);const t=this.createService(e);return this.services.set(e,t),this.executeInjection(e,t),t}resolveServiceTransient(e){const t=this.createService(e);return this.executeInjection(e,t),t}resolveServiceScoped(e){const t=this.resolveContext(e);this.services.has(e)||this.services.set(e,new WeakMap);const r=this.services.get(e);if(r.has(t))return r.get(t);const s=this.createService(e);return r.set(t,s),this.executeInjection(e,s),s}has(e){return this.services.has(e)}createService(e){if(this.loading.has(e))throw new c(e,[...this.loading.values(),e]);const t=this.spec.services.get(e),{factory:r}=t;this.loading.add(e);const s="function"==typeof r?r(this):r.create(this);return this.loading.delete(e),s}executeInjection(e,t){const r=this.spec.services.get(e),{injector:s}=r;s&&("function"==typeof s?s(t,this):s.inject(t,this))}resolveContext(e){const t=this.spec.services.get(e),{contextResolver:r}=t.type;return"function"==typeof r?r(this):r.resolveContext(this)}}class r{constructor(e){this.factory=e,this.shared()}shared(){return this.type={name:exports.ServiceType.Shared},this}transient(){return this.type={name:exports.ServiceType.Transient},this}scoped(e){return this.type={name:exports.ServiceType.Scoped,contextResolver:e},this}withInjector(e){return this.injector=e,this}getServiceDefinition(){return{type:this.type,factory:this.factory,injector:this.injector}}}class s{constructor(){this.defBuilders=new Map,this.middlewares=[]}set(e,t){const s=new r(t);return this.defBuilders.set(e,s),s}addMiddleware(...e){return this.middlewares.push(...e),this}getServiceSpec(){const e=new Map;return this.defBuilders.forEach(((t,r)=>{e.set(r,t.getServiceDefinition())})),{services:e,middlewares:this.middlewares}}}class i extends Error{constructor(e){super(`unknown service "${String(e)}"`),this.id=e,this.name="UnknownServiceError"}}class c extends Error{constructor(e,t){super(`circular dependency detected: ${t.map(String).join(" -> ")}`),this.id=e,this.referenceChain=t,this.name="ServiceCircularReferenceError"}}exports.ServiceCircularReferenceError=c,exports.ServiceContainerImpl=t,exports.ServiceDefinitionBuilderImpl=r,exports.ServiceSpecBuilderImpl=s,exports.UnknownServiceError=i,exports.createServiceContainer=e=>new t(e),exports.createServiceSpecBuilder=()=>new s; | ||
//# sourceMappingURL=vorarbeiter.cjs.min.js.map |
@@ -0,1 +1,7 @@ | ||
var ServiceType; | ||
(function (ServiceType) { | ||
ServiceType["Shared"] = "shared"; | ||
ServiceType["Transient"] = "transient"; | ||
ServiceType["Scoped"] = "scoped"; | ||
})(ServiceType || (ServiceType = {})); | ||
class ServiceContainerImpl { | ||
@@ -16,8 +22,43 @@ constructor(spec) { | ||
resolveService(id) { | ||
var _a; | ||
if (!this.spec.services.has(id)) { | ||
throw new UnknownServiceError(id); | ||
} | ||
return (_a = this.retrieveService(id)) !== null && _a !== void 0 ? _a : this.createService(id); | ||
const definition = this.spec.services.get(id); | ||
switch (definition.type.name) { | ||
case ServiceType.Transient: | ||
return this.resolveServiceTransient(id); | ||
case ServiceType.Scoped: | ||
return this.resolveServiceScoped(id); | ||
case ServiceType.Shared: | ||
return this.resolveServiceShared(id); | ||
} | ||
} | ||
resolveServiceShared(id) { | ||
if (this.services.has(id)) { | ||
return this.services.get(id); | ||
} | ||
const service = this.createService(id); | ||
this.services.set(id, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
resolveServiceTransient(id) { | ||
const service = this.createService(id); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
resolveServiceScoped(id) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
const ctxMap = this.services.get(id); | ||
if (ctxMap.has(ctx)) { | ||
return ctxMap.get(ctx); | ||
} | ||
const service = this.createService(id); | ||
ctxMap.set(ctx, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
has(id) { | ||
@@ -31,27 +72,18 @@ return this.services.has(id); | ||
const definition = this.spec.services.get(id); | ||
const { factory, injector } = definition; | ||
const { factory } = definition; | ||
this.loading.add(id); | ||
const service = typeof factory === "function" ? factory(this) : factory.create(this); | ||
this.loading.delete(id); | ||
this.storeService(id, service); | ||
return service; | ||
} | ||
executeInjection(id, service) { | ||
const definition = this.spec.services.get(id); | ||
const { injector } = definition; | ||
if (injector) { | ||
typeof injector === "function" ? injector(service, this) : injector.inject(service, this); | ||
} | ||
return service; | ||
} | ||
storeService(id, service) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
this.services.get(id).set(ctx, service); | ||
} | ||
retrieveService(id) { | ||
var _a; | ||
const ctx = this.resolveContext(id); | ||
return (_a = this.services.get(id)) === null || _a === void 0 ? void 0 : _a.get(ctx); | ||
} | ||
resolveContext(id) { | ||
const definition = this.spec.services.get(id); | ||
const { contextResolver } = definition; | ||
const { contextResolver } = definition.type; | ||
return typeof contextResolver === "function" ? contextResolver(this) : contextResolver.resolveContext(this); | ||
@@ -64,14 +96,14 @@ } | ||
this.factory = factory; | ||
this.contextResolver = new SharedContextResolver(); | ||
this.shared(); | ||
} | ||
shared() { | ||
this.scoped(new SharedContextResolver()); | ||
this.type = { name: ServiceType.Shared }; | ||
return this; | ||
} | ||
transient() { | ||
this.scoped(new TransientContextResolver()); | ||
this.type = { name: ServiceType.Transient }; | ||
return this; | ||
} | ||
scoped(contextResolver) { | ||
this.contextResolver = contextResolver; | ||
this.type = { name: ServiceType.Scoped, contextResolver }; | ||
return this; | ||
@@ -85,4 +117,4 @@ } | ||
return { | ||
type: this.type, | ||
factory: this.factory, | ||
contextResolver: this.contextResolver, | ||
injector: this.injector | ||
@@ -118,15 +150,2 @@ }; | ||
const createServiceSpecBuilder = () => new ServiceSpecBuilderImpl(); | ||
class SharedContextResolver { | ||
constructor() { | ||
this.context = Object.create(null); | ||
} | ||
resolveContext(container) { | ||
return this.context; | ||
} | ||
} | ||
class TransientContextResolver { | ||
resolveContext(container) { | ||
return Object.create(null); | ||
} | ||
} | ||
class UnknownServiceError extends Error { | ||
@@ -148,3 +167,3 @@ constructor(id) { | ||
export { ServiceCircularReferenceError, ServiceContainerImpl, ServiceDefinitionBuilderImpl, ServiceSpecBuilderImpl, SharedContextResolver, TransientContextResolver, UnknownServiceError, createServiceContainer, createServiceSpecBuilder }; | ||
export { ServiceCircularReferenceError, ServiceContainerImpl, ServiceDefinitionBuilderImpl, ServiceSpecBuilderImpl, ServiceType, UnknownServiceError, createServiceContainer, createServiceSpecBuilder }; | ||
//# sourceMappingURL=vorarbeiter.esm.js.map |
@@ -1,2 +0,2 @@ | ||
class e{constructor(e){this.spec=e,this.services=new Map,this.loading=new Set;let t=this.resolveService.bind(this);this.spec.middlewares.forEach((e=>{t=e(t)})),this.resolveService=t}get(e){return this.resolveService(e)}resolveService(e){var t;if(!this.spec.services.has(e))throw new o(e);return null!==(t=this.retrieveService(e))&&void 0!==t?t:this.createService(e)}has(e){return this.services.has(e)}createService(e){if(this.loading.has(e))throw new h(e,[...this.loading.values(),e]);const t=this.spec.services.get(e),{factory:s,injector:r}=t;this.loading.add(e);const i="function"==typeof s?s(this):s.create(this);return this.loading.delete(e),this.storeService(e,i),r&&("function"==typeof r?r(i,this):r.inject(i,this)),i}storeService(e,t){const s=this.resolveContext(e);this.services.has(e)||this.services.set(e,new WeakMap),this.services.get(e).set(s,t)}retrieveService(e){var t;const s=this.resolveContext(e);return null===(t=this.services.get(e))||void 0===t?void 0:t.get(s)}resolveContext(e){const t=this.spec.services.get(e),{contextResolver:s}=t;return"function"==typeof s?s(this):s.resolveContext(this)}}const t=t=>new e(t);class s{constructor(e){this.factory=e,this.contextResolver=new n}shared(){return this.scoped(new n),this}transient(){return this.scoped(new c),this}scoped(e){return this.contextResolver=e,this}withInjector(e){return this.injector=e,this}getServiceDefinition(){return{factory:this.factory,contextResolver:this.contextResolver,injector:this.injector}}}class r{constructor(){this.defBuilders=new Map,this.middlewares=[]}set(e,t){const r=new s(t);return this.defBuilders.set(e,r),r}addMiddleware(...e){return this.middlewares.push(...e),this}getServiceSpec(){const e=new Map;return this.defBuilders.forEach(((t,s)=>{e.set(s,t.getServiceDefinition())})),{services:e,middlewares:this.middlewares}}}const i=()=>new r;class n{constructor(){this.context=Object.create(null)}resolveContext(e){return this.context}}class c{resolveContext(e){return Object.create(null)}}class o extends Error{constructor(e){super(`unknown service "${String(e)}"`),this.id=e,this.name="UnknownServiceError"}}class h extends Error{constructor(e,t){super(`circular dependency detected: ${t.map(String).join(" -> ")}`),this.id=e,this.referenceChain=t,this.name="ServiceCircularReferenceError"}}export{h as ServiceCircularReferenceError,e as ServiceContainerImpl,s as ServiceDefinitionBuilderImpl,r as ServiceSpecBuilderImpl,n as SharedContextResolver,c as TransientContextResolver,o as UnknownServiceError,t as createServiceContainer,i as createServiceSpecBuilder}; | ||
var e;!function(e){e.Shared="shared",e.Transient="transient",e.Scoped="scoped"}(e||(e={}));class t{constructor(e){this.spec=e,this.services=new Map,this.loading=new Set;let t=this.resolveService.bind(this);this.spec.middlewares.forEach((e=>{t=e(t)})),this.resolveService=t}get(e){return this.resolveService(e)}resolveService(t){if(!this.spec.services.has(t))throw new c(t);switch(this.spec.services.get(t).type.name){case e.Transient:return this.resolveServiceTransient(t);case e.Scoped:return this.resolveServiceScoped(t);case e.Shared:return this.resolveServiceShared(t)}}resolveServiceShared(e){if(this.services.has(e))return this.services.get(e);const t=this.createService(e);return this.services.set(e,t),this.executeInjection(e,t),t}resolveServiceTransient(e){const t=this.createService(e);return this.executeInjection(e,t),t}resolveServiceScoped(e){const t=this.resolveContext(e);this.services.has(e)||this.services.set(e,new WeakMap);const s=this.services.get(e);if(s.has(t))return s.get(t);const r=this.createService(e);return s.set(t,r),this.executeInjection(e,r),r}has(e){return this.services.has(e)}createService(e){if(this.loading.has(e))throw new o(e,[...this.loading.values(),e]);const t=this.spec.services.get(e),{factory:s}=t;this.loading.add(e);const r="function"==typeof s?s(this):s.create(this);return this.loading.delete(e),r}executeInjection(e,t){const s=this.spec.services.get(e),{injector:r}=s;r&&("function"==typeof r?r(t,this):r.inject(t,this))}resolveContext(e){const t=this.spec.services.get(e),{contextResolver:s}=t.type;return"function"==typeof s?s(this):s.resolveContext(this)}}const s=e=>new t(e);class r{constructor(e){this.factory=e,this.shared()}shared(){return this.type={name:e.Shared},this}transient(){return this.type={name:e.Transient},this}scoped(t){return this.type={name:e.Scoped,contextResolver:t},this}withInjector(e){return this.injector=e,this}getServiceDefinition(){return{type:this.type,factory:this.factory,injector:this.injector}}}class i{constructor(){this.defBuilders=new Map,this.middlewares=[]}set(e,t){const s=new r(t);return this.defBuilders.set(e,s),s}addMiddleware(...e){return this.middlewares.push(...e),this}getServiceSpec(){const e=new Map;return this.defBuilders.forEach(((t,s)=>{e.set(s,t.getServiceDefinition())})),{services:e,middlewares:this.middlewares}}}const n=()=>new i;class c extends Error{constructor(e){super(`unknown service "${String(e)}"`),this.id=e,this.name="UnknownServiceError"}}class o extends Error{constructor(e,t){super(`circular dependency detected: ${t.map(String).join(" -> ")}`),this.id=e,this.referenceChain=t,this.name="ServiceCircularReferenceError"}}export{o as ServiceCircularReferenceError,t as ServiceContainerImpl,r as ServiceDefinitionBuilderImpl,i as ServiceSpecBuilderImpl,e as ServiceType,c as UnknownServiceError,s as createServiceContainer,n as createServiceSpecBuilder}; | ||
//# sourceMappingURL=vorarbeiter.esm.min.js.map |
@@ -7,2 +7,8 @@ (function (global, factory) { | ||
exports.ServiceType = void 0; | ||
(function (ServiceType) { | ||
ServiceType["Shared"] = "shared"; | ||
ServiceType["Transient"] = "transient"; | ||
ServiceType["Scoped"] = "scoped"; | ||
})(exports.ServiceType || (exports.ServiceType = {})); | ||
class ServiceContainerImpl { | ||
@@ -23,8 +29,43 @@ constructor(spec) { | ||
resolveService(id) { | ||
var _a; | ||
if (!this.spec.services.has(id)) { | ||
throw new UnknownServiceError(id); | ||
} | ||
return (_a = this.retrieveService(id)) !== null && _a !== void 0 ? _a : this.createService(id); | ||
const definition = this.spec.services.get(id); | ||
switch (definition.type.name) { | ||
case exports.ServiceType.Transient: | ||
return this.resolveServiceTransient(id); | ||
case exports.ServiceType.Scoped: | ||
return this.resolveServiceScoped(id); | ||
case exports.ServiceType.Shared: | ||
return this.resolveServiceShared(id); | ||
} | ||
} | ||
resolveServiceShared(id) { | ||
if (this.services.has(id)) { | ||
return this.services.get(id); | ||
} | ||
const service = this.createService(id); | ||
this.services.set(id, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
resolveServiceTransient(id) { | ||
const service = this.createService(id); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
resolveServiceScoped(id) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
const ctxMap = this.services.get(id); | ||
if (ctxMap.has(ctx)) { | ||
return ctxMap.get(ctx); | ||
} | ||
const service = this.createService(id); | ||
ctxMap.set(ctx, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
has(id) { | ||
@@ -38,27 +79,18 @@ return this.services.has(id); | ||
const definition = this.spec.services.get(id); | ||
const { factory, injector } = definition; | ||
const { factory } = definition; | ||
this.loading.add(id); | ||
const service = typeof factory === "function" ? factory(this) : factory.create(this); | ||
this.loading.delete(id); | ||
this.storeService(id, service); | ||
return service; | ||
} | ||
executeInjection(id, service) { | ||
const definition = this.spec.services.get(id); | ||
const { injector } = definition; | ||
if (injector) { | ||
typeof injector === "function" ? injector(service, this) : injector.inject(service, this); | ||
} | ||
return service; | ||
} | ||
storeService(id, service) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
this.services.get(id).set(ctx, service); | ||
} | ||
retrieveService(id) { | ||
var _a; | ||
const ctx = this.resolveContext(id); | ||
return (_a = this.services.get(id)) === null || _a === void 0 ? void 0 : _a.get(ctx); | ||
} | ||
resolveContext(id) { | ||
const definition = this.spec.services.get(id); | ||
const { contextResolver } = definition; | ||
const { contextResolver } = definition.type; | ||
return typeof contextResolver === "function" ? contextResolver(this) : contextResolver.resolveContext(this); | ||
@@ -71,14 +103,14 @@ } | ||
this.factory = factory; | ||
this.contextResolver = new SharedContextResolver(); | ||
this.shared(); | ||
} | ||
shared() { | ||
this.scoped(new SharedContextResolver()); | ||
this.type = { name: exports.ServiceType.Shared }; | ||
return this; | ||
} | ||
transient() { | ||
this.scoped(new TransientContextResolver()); | ||
this.type = { name: exports.ServiceType.Transient }; | ||
return this; | ||
} | ||
scoped(contextResolver) { | ||
this.contextResolver = contextResolver; | ||
this.type = { name: exports.ServiceType.Scoped, contextResolver }; | ||
return this; | ||
@@ -92,4 +124,4 @@ } | ||
return { | ||
type: this.type, | ||
factory: this.factory, | ||
contextResolver: this.contextResolver, | ||
injector: this.injector | ||
@@ -125,15 +157,2 @@ }; | ||
const createServiceSpecBuilder = () => new ServiceSpecBuilderImpl(); | ||
class SharedContextResolver { | ||
constructor() { | ||
this.context = Object.create(null); | ||
} | ||
resolveContext(container) { | ||
return this.context; | ||
} | ||
} | ||
class TransientContextResolver { | ||
resolveContext(container) { | ||
return Object.create(null); | ||
} | ||
} | ||
class UnknownServiceError extends Error { | ||
@@ -159,4 +178,2 @@ constructor(id) { | ||
exports.ServiceSpecBuilderImpl = ServiceSpecBuilderImpl; | ||
exports.SharedContextResolver = SharedContextResolver; | ||
exports.TransientContextResolver = TransientContextResolver; | ||
exports.UnknownServiceError = UnknownServiceError; | ||
@@ -163,0 +180,0 @@ exports.createServiceContainer = createServiceContainer; |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vorarbeiter={})}(this,(function(e){"use strict";class t{constructor(e){this.spec=e,this.services=new Map,this.loading=new Set;let t=this.resolveService.bind(this);this.spec.middlewares.forEach((e=>{t=e(t)})),this.resolveService=t}get(e){return this.resolveService(e)}resolveService(e){var t;if(!this.spec.services.has(e))throw new c(e);return null!==(t=this.retrieveService(e))&&void 0!==t?t:this.createService(e)}has(e){return this.services.has(e)}createService(e){if(this.loading.has(e))throw new o(e,[...this.loading.values(),e]);const t=this.spec.services.get(e),{factory:r,injector:s}=t;this.loading.add(e);const i="function"==typeof r?r(this):r.create(this);return this.loading.delete(e),this.storeService(e,i),s&&("function"==typeof s?s(i,this):s.inject(i,this)),i}storeService(e,t){const r=this.resolveContext(e);this.services.has(e)||this.services.set(e,new WeakMap),this.services.get(e).set(r,t)}retrieveService(e){var t;const r=this.resolveContext(e);return null===(t=this.services.get(e))||void 0===t?void 0:t.get(r)}resolveContext(e){const t=this.spec.services.get(e),{contextResolver:r}=t;return"function"==typeof r?r(this):r.resolveContext(this)}}class r{constructor(e){this.factory=e,this.contextResolver=new i}shared(){return this.scoped(new i),this}transient(){return this.scoped(new n),this}scoped(e){return this.contextResolver=e,this}withInjector(e){return this.injector=e,this}getServiceDefinition(){return{factory:this.factory,contextResolver:this.contextResolver,injector:this.injector}}}class s{constructor(){this.defBuilders=new Map,this.middlewares=[]}set(e,t){const s=new r(t);return this.defBuilders.set(e,s),s}addMiddleware(...e){return this.middlewares.push(...e),this}getServiceSpec(){const e=new Map;return this.defBuilders.forEach(((t,r)=>{e.set(r,t.getServiceDefinition())})),{services:e,middlewares:this.middlewares}}}class i{constructor(){this.context=Object.create(null)}resolveContext(e){return this.context}}class n{resolveContext(e){return Object.create(null)}}class c extends Error{constructor(e){super(`unknown service "${String(e)}"`),this.id=e,this.name="UnknownServiceError"}}class o extends Error{constructor(e,t){super(`circular dependency detected: ${t.map(String).join(" -> ")}`),this.id=e,this.referenceChain=t,this.name="ServiceCircularReferenceError"}}e.ServiceCircularReferenceError=o,e.ServiceContainerImpl=t,e.ServiceDefinitionBuilderImpl=r,e.ServiceSpecBuilderImpl=s,e.SharedContextResolver=i,e.TransientContextResolver=n,e.UnknownServiceError=c,e.createServiceContainer=e=>new t(e),e.createServiceSpecBuilder=()=>new s,Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vorarbeiter={})}(this,(function(e){"use strict";var t;e.ServiceType=void 0,(t=e.ServiceType||(e.ServiceType={})).Shared="shared",t.Transient="transient",t.Scoped="scoped";class r{constructor(e){this.spec=e,this.services=new Map,this.loading=new Set;let t=this.resolveService.bind(this);this.spec.middlewares.forEach((e=>{t=e(t)})),this.resolveService=t}get(e){return this.resolveService(e)}resolveService(t){if(!this.spec.services.has(t))throw new c(t);switch(this.spec.services.get(t).type.name){case e.ServiceType.Transient:return this.resolveServiceTransient(t);case e.ServiceType.Scoped:return this.resolveServiceScoped(t);case e.ServiceType.Shared:return this.resolveServiceShared(t)}}resolveServiceShared(e){if(this.services.has(e))return this.services.get(e);const t=this.createService(e);return this.services.set(e,t),this.executeInjection(e,t),t}resolveServiceTransient(e){const t=this.createService(e);return this.executeInjection(e,t),t}resolveServiceScoped(e){const t=this.resolveContext(e);this.services.has(e)||this.services.set(e,new WeakMap);const r=this.services.get(e);if(r.has(t))return r.get(t);const s=this.createService(e);return r.set(t,s),this.executeInjection(e,s),s}has(e){return this.services.has(e)}createService(e){if(this.loading.has(e))throw new n(e,[...this.loading.values(),e]);const t=this.spec.services.get(e),{factory:r}=t;this.loading.add(e);const s="function"==typeof r?r(this):r.create(this);return this.loading.delete(e),s}executeInjection(e,t){const r=this.spec.services.get(e),{injector:s}=r;s&&("function"==typeof s?s(t,this):s.inject(t,this))}resolveContext(e){const t=this.spec.services.get(e),{contextResolver:r}=t.type;return"function"==typeof r?r(this):r.resolveContext(this)}}class s{constructor(e){this.factory=e,this.shared()}shared(){return this.type={name:e.ServiceType.Shared},this}transient(){return this.type={name:e.ServiceType.Transient},this}scoped(t){return this.type={name:e.ServiceType.Scoped,contextResolver:t},this}withInjector(e){return this.injector=e,this}getServiceDefinition(){return{type:this.type,factory:this.factory,injector:this.injector}}}class i{constructor(){this.defBuilders=new Map,this.middlewares=[]}set(e,t){const r=new s(t);return this.defBuilders.set(e,r),r}addMiddleware(...e){return this.middlewares.push(...e),this}getServiceSpec(){const e=new Map;return this.defBuilders.forEach(((t,r)=>{e.set(r,t.getServiceDefinition())})),{services:e,middlewares:this.middlewares}}}class c extends Error{constructor(e){super(`unknown service "${String(e)}"`),this.id=e,this.name="UnknownServiceError"}}class n extends Error{constructor(e,t){super(`circular dependency detected: ${t.map(String).join(" -> ")}`),this.id=e,this.referenceChain=t,this.name="ServiceCircularReferenceError"}}e.ServiceCircularReferenceError=n,e.ServiceContainerImpl=r,e.ServiceDefinitionBuilderImpl=s,e.ServiceSpecBuilderImpl=i,e.UnknownServiceError=c,e.createServiceContainer=e=>new r(e),e.createServiceSpecBuilder=()=>new i,Object.defineProperty(e,"__esModule",{value:!0})})); | ||
//# sourceMappingURL=vorarbeiter.umd.min.js.map |
@@ -0,1 +1,7 @@ | ||
export var ServiceType; | ||
(function (ServiceType) { | ||
ServiceType["Shared"] = "shared"; | ||
ServiceType["Transient"] = "transient"; | ||
ServiceType["Scoped"] = "scoped"; | ||
})(ServiceType || (ServiceType = {})); | ||
export class ServiceContainerImpl { | ||
@@ -16,8 +22,43 @@ constructor(spec) { | ||
resolveService(id) { | ||
var _a; | ||
if (!this.spec.services.has(id)) { | ||
throw new UnknownServiceError(id); | ||
} | ||
return (_a = this.retrieveService(id)) !== null && _a !== void 0 ? _a : this.createService(id); | ||
const definition = this.spec.services.get(id); | ||
switch (definition.type.name) { | ||
case ServiceType.Transient: | ||
return this.resolveServiceTransient(id); | ||
case ServiceType.Scoped: | ||
return this.resolveServiceScoped(id); | ||
case ServiceType.Shared: | ||
return this.resolveServiceShared(id); | ||
} | ||
} | ||
resolveServiceShared(id) { | ||
if (this.services.has(id)) { | ||
return this.services.get(id); | ||
} | ||
const service = this.createService(id); | ||
this.services.set(id, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
resolveServiceTransient(id) { | ||
const service = this.createService(id); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
resolveServiceScoped(id) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
const ctxMap = this.services.get(id); | ||
if (ctxMap.has(ctx)) { | ||
return ctxMap.get(ctx); | ||
} | ||
const service = this.createService(id); | ||
ctxMap.set(ctx, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
has(id) { | ||
@@ -31,27 +72,18 @@ return this.services.has(id); | ||
const definition = this.spec.services.get(id); | ||
const { factory, injector } = definition; | ||
const { factory } = definition; | ||
this.loading.add(id); | ||
const service = typeof factory === "function" ? factory(this) : factory.create(this); | ||
this.loading.delete(id); | ||
this.storeService(id, service); | ||
return service; | ||
} | ||
executeInjection(id, service) { | ||
const definition = this.spec.services.get(id); | ||
const { injector } = definition; | ||
if (injector) { | ||
typeof injector === "function" ? injector(service, this) : injector.inject(service, this); | ||
} | ||
return service; | ||
} | ||
storeService(id, service) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
this.services.get(id).set(ctx, service); | ||
} | ||
retrieveService(id) { | ||
var _a; | ||
const ctx = this.resolveContext(id); | ||
return (_a = this.services.get(id)) === null || _a === void 0 ? void 0 : _a.get(ctx); | ||
} | ||
resolveContext(id) { | ||
const definition = this.spec.services.get(id); | ||
const { contextResolver } = definition; | ||
const { contextResolver } = definition.type; | ||
return typeof contextResolver === "function" ? contextResolver(this) : contextResolver.resolveContext(this); | ||
@@ -64,14 +96,14 @@ } | ||
this.factory = factory; | ||
this.contextResolver = new SharedContextResolver(); | ||
this.shared(); | ||
} | ||
shared() { | ||
this.scoped(new SharedContextResolver()); | ||
this.type = { name: ServiceType.Shared }; | ||
return this; | ||
} | ||
transient() { | ||
this.scoped(new TransientContextResolver()); | ||
this.type = { name: ServiceType.Transient }; | ||
return this; | ||
} | ||
scoped(contextResolver) { | ||
this.contextResolver = contextResolver; | ||
this.type = { name: ServiceType.Scoped, contextResolver }; | ||
return this; | ||
@@ -85,4 +117,4 @@ } | ||
return { | ||
type: this.type, | ||
factory: this.factory, | ||
contextResolver: this.contextResolver, | ||
injector: this.injector | ||
@@ -118,15 +150,2 @@ }; | ||
export const createServiceSpecBuilder = () => new ServiceSpecBuilderImpl(); | ||
export class SharedContextResolver { | ||
constructor() { | ||
this.context = Object.create(null); | ||
} | ||
resolveContext(container) { | ||
return this.context; | ||
} | ||
} | ||
export class TransientContextResolver { | ||
resolveContext(container) { | ||
return Object.create(null); | ||
} | ||
} | ||
export class UnknownServiceError extends Error { | ||
@@ -133,0 +152,0 @@ constructor(id) { |
{ | ||
"name": "vorarbeiter", | ||
"version": "5.0.0", | ||
"version": "6.0.0", | ||
"homepage": "https://github.com/slavamuravey/vorarbeiter", | ||
@@ -5,0 +5,0 @@ "description": "A simple service container", |
131
src/index.ts
@@ -27,5 +27,29 @@ export type Context = object; | ||
export enum ServiceType { | ||
Shared = "shared", | ||
Transient = "transient", | ||
Scoped = "scoped" | ||
} | ||
export interface ServiceTypeDefinitionShared { | ||
name: ServiceType.Shared; | ||
} | ||
export interface ServiceTypeDefinitionTransient { | ||
name: ServiceType.Transient; | ||
} | ||
export interface ServiceTypeDefinitionScoped { | ||
name: ServiceType.Scoped; | ||
contextResolver: ContextResolverDefinition; | ||
} | ||
export type ServiceTypeDefinition = | ||
| ServiceTypeDefinitionShared | ||
| ServiceTypeDefinitionTransient | ||
| ServiceTypeDefinitionScoped; | ||
export interface ServiceDefinition<T = unknown> { | ||
type: ServiceTypeDefinition; | ||
factory: ServiceFactoryDefinition<T>; | ||
contextResolver: ContextResolverDefinition; | ||
injector?: ServiceInjectorDefinition<T>; | ||
@@ -51,3 +75,3 @@ } | ||
export class ServiceContainerImpl implements ServiceContainer { | ||
private services = new Map<ServiceId, WeakMap<Context, unknown>>(); | ||
private services = new Map<ServiceId, WeakMap<Context, unknown> | unknown>(); | ||
private loading = new Set<ServiceId>(); | ||
@@ -72,5 +96,50 @@ | ||
return this.retrieveService<T>(id) ?? this.createService<T>(id); | ||
const definition = this.spec.services.get(id) as ServiceDefinition<T>; | ||
switch (definition.type.name) { | ||
case ServiceType.Transient: | ||
return this.resolveServiceTransient(id); | ||
case ServiceType.Scoped: | ||
return this.resolveServiceScoped(id); | ||
case ServiceType.Shared: | ||
return this.resolveServiceShared(id); | ||
} | ||
} | ||
private resolveServiceShared<T>(id: ServiceId): T { | ||
if (this.services.has(id)) { | ||
return this.services.get(id) as T; | ||
} | ||
const service = this.createService<T>(id); | ||
this.services.set(id, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
private resolveServiceTransient<T>(id: ServiceId): T { | ||
const service = this.createService<T>(id); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
private resolveServiceScoped<T>(id: ServiceId): T { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
const ctxMap = this.services.get(id) as WeakMap<Context, T>; | ||
if (ctxMap.has(ctx)) { | ||
return ctxMap.get(ctx)!; | ||
} | ||
const service = this.createService<T>(id); | ||
ctxMap.set(ctx, service); | ||
this.executeInjection(id, service); | ||
return service; | ||
} | ||
has(id: ServiceId): boolean { | ||
@@ -85,3 +154,3 @@ return this.services.has(id); | ||
const definition = this.spec.services.get(id) as ServiceDefinition<T>; | ||
const { factory, injector } = definition; | ||
const { factory } = definition; | ||
@@ -92,30 +161,16 @@ this.loading.add(id); | ||
this.storeService<T>(id, service); | ||
return service; | ||
} | ||
private executeInjection<T>(id: ServiceId, service: T) { | ||
const definition = this.spec.services.get(id) as ServiceDefinition<T>; | ||
const { injector } = definition; | ||
if (injector) { | ||
typeof injector === "function" ? injector(service, this) : injector.inject(service, this); | ||
} | ||
return service; | ||
} | ||
private storeService<T>(id: ServiceId, service: T) { | ||
const ctx = this.resolveContext(id); | ||
if (!this.services.has(id)) { | ||
this.services.set(id, new WeakMap()); | ||
} | ||
this.services.get(id)!.set(ctx, service); | ||
} | ||
private retrieveService<T>(id: ServiceId): T | undefined { | ||
const ctx = this.resolveContext(id); | ||
return (this.services.get(id) as WeakMap<Context, T>)?.get(ctx); | ||
} | ||
private resolveContext(id: ServiceId): Context { | ||
const definition = this.spec.services.get(id)!; | ||
const { contextResolver } = definition; | ||
const { contextResolver } = definition.type as ServiceTypeDefinitionScoped; | ||
@@ -137,9 +192,11 @@ return typeof contextResolver === "function" ? contextResolver(this) : contextResolver.resolveContext(this); | ||
export class ServiceDefinitionBuilderImpl<T> implements ServiceDefinitionBuilder<T> { | ||
private contextResolver: ContextResolverDefinition = new SharedContextResolver(); | ||
private type!: ServiceTypeDefinition; | ||
private injector?: ServiceInjectorDefinition<T>; | ||
constructor(private readonly factory: ServiceFactoryDefinition<T>) {} | ||
constructor(private readonly factory: ServiceFactoryDefinition<T>) { | ||
this.shared(); | ||
} | ||
shared() { | ||
this.scoped(new SharedContextResolver()); | ||
this.type = { name: ServiceType.Shared }; | ||
return this; | ||
@@ -149,3 +206,3 @@ } | ||
transient() { | ||
this.scoped(new TransientContextResolver()); | ||
this.type = { name: ServiceType.Transient }; | ||
return this; | ||
@@ -155,3 +212,3 @@ } | ||
scoped(contextResolver: ContextResolverDefinition) { | ||
this.contextResolver = contextResolver; | ||
this.type = { name: ServiceType.Scoped, contextResolver }; | ||
return this; | ||
@@ -167,4 +224,4 @@ } | ||
return { | ||
type: this.type, | ||
factory: this.factory, | ||
contextResolver: this.contextResolver, | ||
injector: this.injector | ||
@@ -212,16 +269,2 @@ }; | ||
export class SharedContextResolver implements ContextResolver { | ||
context = Object.create(null); | ||
resolveContext(container: ServiceContainer): Context { | ||
return this.context; | ||
} | ||
} | ||
export class TransientContextResolver implements ContextResolver { | ||
resolveContext(container: ServiceContainer): Context { | ||
return Object.create(null); | ||
} | ||
} | ||
export class UnknownServiceError extends Error { | ||
@@ -228,0 +271,0 @@ constructor(public readonly id: ServiceId) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
128537
1203