@spinajs/di
Advanced tools
Comparing version 1.0.19 to 1.1.5
@@ -0,1 +1,2 @@ | ||
/// <reference types="node" /> | ||
import 'reflect-metadata'; | ||
@@ -5,6 +6,7 @@ import { TypedArray } from './array'; | ||
import { Class, Factory } from './types'; | ||
import { EventEmitter } from "events"; | ||
/** | ||
* Dependency injection container implementation | ||
*/ | ||
export declare class Container implements IContainer { | ||
export declare class Container extends EventEmitter implements IContainer { | ||
/** | ||
@@ -32,6 +34,14 @@ * Handles information about what is registered as what | ||
/** | ||
* Clears container registry and cache. | ||
* Clears container registry and cache. shorthand for container.clearCache() && container.clearRegistry() | ||
*/ | ||
clear(): void; | ||
/** | ||
* clears container registered types information | ||
*/ | ||
clearCache(): void; | ||
/** | ||
* Clears container resolved types | ||
*/ | ||
clearRegistry(): void; | ||
/** | ||
* Register class/interface to DI. | ||
@@ -50,2 +60,7 @@ * @param type - interface object to register | ||
* | ||
* Do not try to get service by factory func, it will always return null. | ||
* If you somehowe want to cache instances created by factory functions, | ||
* factory itself should do that somehow and end user should always resolve by | ||
* assigned type | ||
* | ||
* @param serviceName - name of service to get | ||
@@ -96,2 +111,3 @@ * @returns { null | T} - null if no service has been resolved at given name | ||
resolve<T>(type: TypedArray<T>, check?: boolean): T extends AsyncModule ? Promise<T[]> : T[]; | ||
private resolveArrayType; | ||
private resolveType; | ||
@@ -98,0 +114,0 @@ private _hasRegisteredType; |
@@ -12,7 +12,10 @@ "use strict"; | ||
const interfaces_1 = require("./interfaces"); | ||
const events_1 = require("events"); | ||
const exceptions_2 = require("./exceptions"); | ||
/** | ||
* Dependency injection container implementation | ||
*/ | ||
class Container { | ||
class Container extends events_1.EventEmitter { | ||
constructor(parent) { | ||
super(); | ||
this.registry = new Map(); | ||
@@ -33,7 +36,18 @@ this.cache = new Map(); | ||
/** | ||
* Clears container registry and cache. | ||
* Clears container registry and cache. shorthand for container.clearCache() && container.clearRegistry() | ||
*/ | ||
clear() { | ||
this.clearCache(); | ||
} | ||
/** | ||
* clears container registered types information | ||
*/ | ||
clearCache() { | ||
this.cache.clear(); | ||
this.cache = new Map(); | ||
} | ||
/** | ||
* Clears container resolved types | ||
*/ | ||
clearRegistry() { | ||
this.registry.clear(); | ||
@@ -102,7 +116,17 @@ this.registerSelf(); | ||
} | ||
/** | ||
* When we try to get type by factory func, always return null | ||
* It's technically an arror becouse factory func in in charge now | ||
* of managing intances of created objects (eg. creating cache) | ||
* | ||
* We do not track of any instances created by factory funcions. | ||
*/ | ||
const isFactory = !helpers_1.isConstructor(identifier[identifier.length - 1]) && _.isFunction(identifier[identifier.length - 1]); | ||
if (isFactory) { | ||
return null; | ||
} | ||
if (service instanceof array_1.TypedArray) { | ||
return identifier.map(t => _get(t.name)); | ||
} | ||
const isFactory = !helpers_1.isConstructor(identifier[0]) && _.isFunction(identifier[0]); | ||
return _get(isFactory ? (typeof service === 'string' ? service : service.name) : identifier[0].name); | ||
return _get(identifier[identifier.length - 1].name); | ||
function _get(i) { | ||
@@ -191,3 +215,3 @@ if (self.cache.has(i)) { | ||
if (isArray) { | ||
const resolved = targetType.map(r => this.resolveType(sourceType, r, opt)); | ||
const resolved = targetType.map(r => this.resolveArrayType(sourceType, r, opt)); | ||
if (resolved.some(r => r instanceof Promise)) { | ||
@@ -200,2 +224,9 @@ return Promise.all(resolved); | ||
} | ||
resolveArrayType(sourceType, targetType, options) { | ||
const tname = typeof sourceType === 'string' ? sourceType : sourceType.name; | ||
if (!this.Registry.has(tname)) { | ||
throw new exceptions_2.ResolveException(`Cannot resolve array of type ${tname}, no types are registered in container.`); | ||
} | ||
return this.resolveType(sourceType, targetType, options); | ||
} | ||
resolveType(sourceType, targetType, options) { | ||
@@ -205,6 +236,12 @@ const self = this; | ||
const isFactory = !helpers_1.isConstructor(targetType) && _.isFunction(targetType); | ||
/** | ||
* If its a factory func, always resolve as new instance | ||
*/ | ||
if (isFactory) { | ||
return _getNewInstance(targetType); | ||
} | ||
// check cache if needed | ||
if (descriptor.resolver === enums_1.ResolveType.Singleton || descriptor.resolver === enums_1.ResolveType.PerChildContainer) { | ||
if (this.has(isFactory ? sourceType : targetType, descriptor.resolver === enums_1.ResolveType.Singleton)) { | ||
return this.get(isFactory ? sourceType : targetType); | ||
if (this.has(targetType, descriptor.resolver === enums_1.ResolveType.Singleton)) { | ||
return this.get(targetType); | ||
} | ||
@@ -217,4 +254,3 @@ } | ||
return _resolve(descriptor, targetType, resolvedDependencies); | ||
}) | ||
.then(_setCache); | ||
}).then(_setCache); | ||
} | ||
@@ -229,10 +265,8 @@ else { | ||
} | ||
function _getNameOfResolvedType() { | ||
return targetType.name; | ||
} | ||
function _setCache(r) { | ||
const isFactory = !helpers_1.isConstructor(targetType) && _.isFunction(targetType); | ||
const checkParent = descriptor.resolver === enums_1.ResolveType.Singleton; | ||
const toCheck = isFactory | ||
? typeof sourceType === 'string' | ||
? sourceType | ||
: sourceType.name | ||
: targetType.name; | ||
const toCheck = _getNameOfResolvedType(); | ||
if (!self.has(toCheck, checkParent)) { | ||
@@ -272,2 +306,4 @@ self.Cache.set(toCheck, r); | ||
} | ||
reduce(t.prototype); | ||
reduce(t.__proto__); | ||
if (t[decorators_1.DI_DESCRIPTION_SYMBOL]) { | ||
@@ -277,4 +313,2 @@ descriptor.inject = descriptor.inject.concat(t[decorators_1.DI_DESCRIPTION_SYMBOL].inject); | ||
} | ||
reduce(t.prototype); | ||
reduce(t.__proto__); | ||
} | ||
@@ -337,2 +371,4 @@ } | ||
newInstance.resolveAsync(self).then(() => { | ||
self.emit(`di.resolved.${_getNameOfResolvedType()}`); | ||
}).then(() => { | ||
res(newInstance); | ||
@@ -342,4 +378,7 @@ }); | ||
} | ||
if (newInstance instanceof interfaces_1.SyncModule) { | ||
newInstance.resolve(self); | ||
else { | ||
if (newInstance instanceof interfaces_1.SyncModule) { | ||
newInstance.resolve(self); | ||
} | ||
self.emit(`di.resolved.${_getNameOfResolvedType()}`); | ||
} | ||
@@ -346,0 +385,0 @@ } |
@@ -55,25 +55,4 @@ export declare const DI_DESCRIPTION_SYMBOL: unique symbol; | ||
*/ | ||
export declare function Inject(...args: Class[]): any; | ||
export declare function Inject(...args: Array<(Class | TypedArray<any>)>): any; | ||
/** | ||
* Sets dependency injection guidelines - what to inject for specified class. If multiple instances are registered at specified type, | ||
* all of them are resolved and injected | ||
* @param args - what to inject - class definitions | ||
* @example | ||
* ```javascript | ||
* | ||
* @InjectAll(Bar) | ||
* class Foo{ | ||
* | ||
* barInstances : Bar[]; | ||
* | ||
* constructor(bars : Bar[]){ | ||
* // all Bar implementations are injected when Foo is created via DI container | ||
* this.barInstances = bar; | ||
* } | ||
* } | ||
* | ||
* ``` | ||
*/ | ||
export declare function InjectAll(...args: Class[]): any; | ||
/** | ||
* Automatically injects dependency based on reflected property type. Uses experimental typescript reflection api | ||
@@ -80,0 +59,0 @@ * If decorator is applied to array property all registered type instances are injected, otherwise only first / only that exists |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Singleton = exports.NewInstance = exports.PerChildInstance = exports.LazyInject = exports.Autoinject = exports.InjectAll = exports.Inject = exports.Injectable = exports.DI_DESCRIPTION_SYMBOL = void 0; | ||
exports.Singleton = exports.NewInstance = exports.PerChildInstance = exports.LazyInject = exports.Autoinject = exports.Inject = exports.Injectable = exports.DI_DESCRIPTION_SYMBOL = void 0; | ||
const enums_1 = require("./enums"); | ||
@@ -89,3 +89,2 @@ const root_1 = require("./root"); | ||
descriptor.inject.push({ | ||
all: false, | ||
autoinject: false, | ||
@@ -100,35 +99,2 @@ autoinjectKey: '', | ||
/** | ||
* Sets dependency injection guidelines - what to inject for specified class. If multiple instances are registered at specified type, | ||
* all of them are resolved and injected | ||
* @param args - what to inject - class definitions | ||
* @example | ||
* ```javascript | ||
* | ||
* @InjectAll(Bar) | ||
* class Foo{ | ||
* | ||
* barInstances : Bar[]; | ||
* | ||
* constructor(bars : Bar[]){ | ||
* // all Bar implementations are injected when Foo is created via DI container | ||
* this.barInstances = bar; | ||
* } | ||
* } | ||
* | ||
* ``` | ||
*/ | ||
function InjectAll(...args) { | ||
return AddDependency((descriptor) => { | ||
for (const a of args) { | ||
descriptor.inject.push({ | ||
all: true, | ||
autoinject: false, | ||
autoinjectKey: '', | ||
inject: a, | ||
}); | ||
} | ||
}); | ||
} | ||
exports.InjectAll = InjectAll; | ||
/** | ||
* Automatically injects dependency based on reflected property type. Uses experimental typescript reflection api | ||
@@ -167,6 +133,5 @@ * If decorator is applied to array property all registered type instances are injected, otherwise only first / only that exists | ||
descriptor.inject.push({ | ||
all: isArray ? true : false, | ||
autoinject: true, | ||
autoinjectKey: propertyKey, | ||
inject: isArray ? injectType : type, | ||
inject: isArray ? Array.ofType(injectType) : type, | ||
}); | ||
@@ -173,0 +138,0 @@ }); |
@@ -9,1 +9,2 @@ export * from './interfaces'; | ||
export * from './root'; | ||
export * from './exceptions'; |
@@ -21,2 +21,3 @@ "use strict"; | ||
__exportStar(require("./root"), exports); | ||
__exportStar(require("./exceptions"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -0,3 +1,5 @@ | ||
/// <reference types="node" /> | ||
import { ResolveType } from './enums'; | ||
import { Class, Factory } from './types'; | ||
import { EventEmitter } from "events"; | ||
/** | ||
@@ -26,6 +28,8 @@ * Interface to describe DI binding behaviour | ||
} | ||
export interface IContainer { | ||
export interface IContainer extends EventEmitter { | ||
Cache: Map<string, any[] | any>; | ||
Registry: Map<string, any[] | any>; | ||
clear(): void; | ||
clearRegistry(): void; | ||
clearCache(): void; | ||
register<T>(implementation: Class<T> | Factory<T>): IBind; | ||
@@ -56,3 +60,2 @@ child(): IContainer; | ||
autoinject: boolean; | ||
all: boolean; | ||
autoinjectKey: string; | ||
@@ -73,7 +76,11 @@ } | ||
*/ | ||
export declare abstract class SyncModule { | ||
abstract resolve(container: IContainer): void; | ||
export declare class Module { | ||
protected resolved: boolean; | ||
get Resolved(): boolean; | ||
} | ||
export declare abstract class AsyncModule { | ||
abstract resolveAsync(container: IContainer): Promise<void>; | ||
export declare abstract class SyncModule extends Module { | ||
resolve(_: IContainer): void; | ||
} | ||
export declare class AsyncModule extends Module { | ||
resolveAsync(_: IContainer): Promise<void>; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AsyncModule = exports.SyncModule = void 0; | ||
exports.AsyncModule = exports.SyncModule = exports.Module = void 0; | ||
/** | ||
@@ -18,8 +18,23 @@ * Interface to describe DI resolve strategies. Strategies are used do | ||
// } | ||
class SyncModule { | ||
class Module { | ||
constructor() { | ||
this.resolved = false; | ||
} | ||
get Resolved() { | ||
return this.resolved; | ||
} | ||
} | ||
exports.Module = Module; | ||
class SyncModule extends Module { | ||
resolve(_) { | ||
this.resolved = true; | ||
} | ||
} | ||
exports.SyncModule = SyncModule; | ||
class AsyncModule { | ||
class AsyncModule extends Module { | ||
async resolveAsync(_) { | ||
this.resolved = true; | ||
} | ||
} | ||
exports.AsyncModule = AsyncModule; | ||
//# sourceMappingURL=interfaces.js.map |
@@ -8,3 +8,26 @@ import { IBind, IContainer, AsyncModule } from './interfaces'; | ||
const RootContainer: IContainer; | ||
/*** | ||
* EVENT LISTENER STUFF | ||
* | ||
* Allows to use event listener stuff on root container | ||
*/ | ||
function on(event: string, listener: (...args: any) => void): IContainer; | ||
function addListener(event: string | symbol, listener: (...args: any[]) => void): IContainer; | ||
function once(event: string | symbol, listener: (...args: any[]) => void): IContainer; | ||
function removeListener(event: string | symbol, listener: (...args: any[]) => void): IContainer; | ||
function off(event: string | symbol, listener: (...args: any[]) => void): IContainer; | ||
function removeAllListeners(event?: string | symbol): IContainer; | ||
function setMaxListeners(n: number): IContainer; | ||
function getMaxListeners(): number; | ||
function listeners(event: string | symbol): Function[]; | ||
function rawListeners(event: string | symbol): Function[]; | ||
function emit(event: string | symbol, ...args: any[]): boolean; | ||
function listenerCount(type: string | symbol): number; | ||
function prependListener(event: string | symbol, listener: (...args: any[]) => void): IContainer; | ||
function prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): IContainer; | ||
function eventNames(): Array<string | symbol>; | ||
/** | ||
* =========================================================================== | ||
*/ | ||
/** | ||
* Clears root container registry and cache. | ||
@@ -14,3 +37,11 @@ */ | ||
/** | ||
* Register class/interface to DI root container. | ||
* Clears out root registry ( registered types in root container ) | ||
*/ | ||
function clearRegistry(): void; | ||
/** | ||
* Cleart ous root cache ( all resolved types ) | ||
*/ | ||
function clearCache(): void; | ||
/** | ||
* Register class/interface to DI root container. If | ||
* @param type - interface object to register | ||
@@ -17,0 +48,0 @@ * @throws { InvalidArgument } if type is null or undefined |
@@ -12,11 +12,94 @@ "use strict"; | ||
DI.RootContainer = new container_1.Container(); | ||
/*** | ||
* EVENT LISTENER STUFF | ||
* | ||
* Allows to use event listener stuff on root container | ||
*/ | ||
function on(event, listener) { | ||
return DI.RootContainer.on(event, listener); | ||
} | ||
DI.on = on; | ||
function addListener(event, listener) { | ||
return DI.RootContainer.addListener(event, listener); | ||
} | ||
DI.addListener = addListener; | ||
function once(event, listener) { | ||
return DI.RootContainer.once(event, listener); | ||
} | ||
DI.once = once; | ||
function removeListener(event, listener) { | ||
return DI.RootContainer.removeListener(event, listener); | ||
} | ||
DI.removeListener = removeListener; | ||
function off(event, listener) { | ||
return DI.RootContainer.off(event, listener); | ||
} | ||
DI.off = off; | ||
function removeAllListeners(event) { | ||
return DI.RootContainer.removeAllListeners(event); | ||
} | ||
DI.removeAllListeners = removeAllListeners; | ||
function setMaxListeners(n) { | ||
return DI.RootContainer.setMaxListeners(n); | ||
} | ||
DI.setMaxListeners = setMaxListeners; | ||
function getMaxListeners() { | ||
return DI.RootContainer.getMaxListeners(); | ||
} | ||
DI.getMaxListeners = getMaxListeners; | ||
function listeners(event) { | ||
return DI.RootContainer.listeners(event); | ||
} | ||
DI.listeners = listeners; | ||
function rawListeners(event) { | ||
return DI.RootContainer.rawListeners(event); | ||
} | ||
DI.rawListeners = rawListeners; | ||
function emit(event, ...args) { | ||
return DI.RootContainer.emit(event, ...args); | ||
} | ||
DI.emit = emit; | ||
function listenerCount(type) { | ||
return DI.RootContainer.listenerCount(type); | ||
} | ||
DI.listenerCount = listenerCount; | ||
function prependListener(event, listener) { | ||
return DI.RootContainer.prependListener(event, listener); | ||
} | ||
DI.prependListener = prependListener; | ||
function prependOnceListener(event, listener) { | ||
return DI.RootContainer.prependOnceListener(event, listener); | ||
} | ||
DI.prependOnceListener = prependOnceListener; | ||
function eventNames() { | ||
return DI.RootContainer.eventNames(); | ||
} | ||
DI.eventNames = eventNames; | ||
/** | ||
* =========================================================================== | ||
*/ | ||
/** | ||
* Clears root container registry and cache. | ||
*/ | ||
function clear() { | ||
DI.RootContainer.clear(); | ||
DI.RootContainer.clearCache(); | ||
DI.RootContainer.clearRegistry(); | ||
} | ||
DI.clear = clear; | ||
/** | ||
* Register class/interface to DI root container. | ||
* Clears out root registry ( registered types in root container ) | ||
*/ | ||
function clearRegistry() { | ||
DI.RootContainer.clearRegistry(); | ||
} | ||
DI.clearRegistry = clearRegistry; | ||
/** | ||
* Cleart ous root cache ( all resolved types ) | ||
*/ | ||
function clearCache() { | ||
DI.RootContainer.clearCache(); | ||
} | ||
DI.clearCache = clearCache; | ||
/** | ||
* Register class/interface to DI root container. If | ||
* @param type - interface object to register | ||
@@ -23,0 +106,0 @@ * @throws { InvalidArgument } if type is null or undefined |
{ | ||
"name": "@spinajs/di", | ||
"version": "1.0.19", | ||
"version": "1.1.5", | ||
"description": "lightweight di container ", | ||
@@ -11,2 +11,3 @@ "main": "lib/index.js", | ||
"build": "tsc", | ||
"build-watch": "tsc -w", | ||
"prepare": "npm run build", | ||
@@ -13,0 +14,0 @@ "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"", |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
74808
36
1348