@furystack/inject
Advanced tools
Comparing version 2.0.0 to 3.0.0
@@ -7,6 +7,3 @@ import 'reflect-metadata'; | ||
export interface IInjectableOptions { | ||
/** | ||
* Enables or disables resolving the dependencies from the constructor (true by default) | ||
*/ | ||
ResolveDependencies: boolean; | ||
lifetime: 'transient' | 'singleton' | 'scoped'; | ||
} | ||
@@ -13,0 +10,0 @@ /** |
@@ -9,3 +9,3 @@ "use strict"; | ||
exports.defaultInjectableOptions = { | ||
ResolveDependencies: true, | ||
lifetime: 'transient', | ||
}; | ||
@@ -20,3 +20,3 @@ /** | ||
const metaValue = { | ||
Dependencies: (meta && | ||
dependencies: (meta && | ||
meta.map(param => { | ||
@@ -26,3 +26,3 @@ return param; | ||
[], | ||
Options: { ...exports.defaultInjectableOptions, ...options }, | ||
options: { ...exports.defaultInjectableOptions, ...options }, | ||
}; | ||
@@ -29,0 +29,0 @@ Injector_1.Injector.meta.set(ctor, metaValue); |
@@ -22,4 +22,4 @@ import { Disposable } from '@sensenet/client-utils'; | ||
static meta: Map<Constructable<any>, { | ||
Dependencies: Array<Constructable<any>>; | ||
Options: import('./Injectable').IInjectableOptions; | ||
dependencies: Array<Constructable<any>>; | ||
options: import('./Injectable').IInjectableOptions; | ||
}>; | ||
@@ -31,6 +31,5 @@ private cachedSingletons; | ||
* @param ctor The constructor object (e.g. IncomingMessage) | ||
* @param local Flag that forbids parent walk if the instance is not available but the injector has a parent | ||
* @param dependencies Resolved dependencies | ||
*/ | ||
getInstance<T>(ctor: Constructable<T>, local?: boolean, dependencies?: Array<Constructable<T>>): T; | ||
getInstance<T>(ctor: Constructable<T>, dependencies?: Array<Constructable<T>>): T; | ||
/** | ||
@@ -43,18 +42,2 @@ * Sets explicitliy an instance for a key in the store | ||
/** | ||
* Retrieves an instance and runs it's `setup()` method if available | ||
* @param ctor The constructor of the resource | ||
* @param args Arguments for the instance's setup() method | ||
*/ | ||
setupInstance<T extends { | ||
setup: (...args: TSetupArgs) => void; | ||
}, TSetupArgs extends any[]>(ctor: new (...args: any[]) => T, ...args: TSetupArgs): T; | ||
/** | ||
* Retrieves an instance and runs it's `setup()` method if available | ||
* @param ctor The constructor of the resource | ||
* @param args Arguments for the instance's setup() method | ||
*/ | ||
setupLocalInstance<T extends { | ||
setup: (...args: TSetupArgs) => void; | ||
}, TSetupArgs extends any[]>(ctor: new (...args: any[]) => T, ...args: TSetupArgs): T; | ||
/** | ||
* Creates a child injector instance | ||
@@ -61,0 +44,0 @@ * @param options Additional injector options |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Injectable_1 = require("./Injectable"); | ||
/** | ||
@@ -33,28 +34,43 @@ * Container for injectable instances | ||
* @param ctor The constructor object (e.g. IncomingMessage) | ||
* @param local Flag that forbids parent walk if the instance is not available but the injector has a parent | ||
* @param dependencies Resolved dependencies | ||
*/ | ||
getInstance(ctor, local = false, dependencies = []) { | ||
getInstance(ctor, dependencies = []) { | ||
if (ctor === this.constructor) { | ||
return this; | ||
} | ||
const meta = Injector.meta.get(ctor); | ||
if (!meta) { | ||
throw Error(`No metadata found for '${ctor.name}'. Dependencies: ${dependencies | ||
.map(d => d.name) | ||
.join(',')}. Be sure that it's decorated with '@Injectable()' or added explicitly with SetInstance()`); | ||
} | ||
if (dependencies.includes(ctor)) { | ||
throw Error(`Circular dependencies found.`); | ||
} | ||
if (this.cachedSingletons.has(ctor)) { | ||
if (meta.options.lifetime === 'singleton') { | ||
const invalidDeps = meta.dependencies | ||
.map(dep => ({ meta: Injector.meta.get(dep), dep })) | ||
.filter(m => m.meta && (m.meta.options.lifetime === 'scoped' || m.meta.options.lifetime === 'transient')) | ||
.map(i => i.meta && `${i.dep.name}:${i.meta.options.lifetime}`); | ||
if (invalidDeps.length) { | ||
throw Error(`Injector error: Singleton type '${ctor.name}' depends on non-singleton injectables: ${invalidDeps.join(',')}`); | ||
} | ||
} | ||
else if (meta.options.lifetime === 'scoped') { | ||
const invalidDeps = meta.dependencies | ||
.map(dep => ({ meta: Injector.meta.get(dep), dep })) | ||
.filter(m => m.meta && m.meta.options.lifetime === 'transient') | ||
.map(i => i.meta && `${i.dep.name}:${i.meta.options.lifetime}`); | ||
if (invalidDeps.length) { | ||
throw Error(`Injector error: Scoped type '${ctor.name}' depends on transient injectables: ${invalidDeps.join(',')}`); | ||
} | ||
} | ||
if (meta.options.lifetime !== 'transient' && this.cachedSingletons.has(ctor)) { | ||
return this.cachedSingletons.get(ctor); | ||
} | ||
const fromParent = !local && this.options.parent && this.options.parent.getInstance(ctor); | ||
const fromParent = meta.options.lifetime === 'singleton' && this.options.parent && this.options.parent.getInstance(ctor); | ||
if (fromParent) { | ||
return fromParent; | ||
} | ||
const meta = Injector.meta.get(ctor); | ||
if (!meta) { | ||
throw Error(`No metadata found for '${ctor.name}'. Dependencies: ${dependencies | ||
.map(d => d.name) | ||
.join(',')}. Be sure that it's decorated with '@Injectable()' or added explicitly with SetInstance()`); | ||
} | ||
const deps = meta.Options.ResolveDependencies | ||
? meta.Dependencies.map(dep => this.getInstance(dep, false, [...dependencies, ctor])) | ||
: []; | ||
const deps = meta.dependencies.map(dep => this.getInstance(dep, [...dependencies, ctor])); | ||
const newInstance = new ctor(...deps); | ||
@@ -70,30 +86,20 @@ this.setExplicitInstance(newInstance); | ||
setExplicitInstance(instance, key) { | ||
const ctor = key || instance.constructor; | ||
if (!Injector.meta.has(ctor)) { | ||
const meta = Reflect.getMetadata('design:paramtypes', ctor); | ||
Injector.meta.set(ctor, { | ||
dependencies: (meta && | ||
meta.map(param => { | ||
return param; | ||
})) || | ||
[], | ||
options: { ...Injectable_1.defaultInjectableOptions, lifetime: 'explicit' }, | ||
}); | ||
} | ||
if (instance.constructor === this.constructor) { | ||
throw Error('Cannot set an injector instance as injectable'); | ||
} | ||
this.cachedSingletons.set(key || instance.constructor, instance); | ||
this.cachedSingletons.set(ctor, instance); | ||
} | ||
/** | ||
* Retrieves an instance and runs it's `setup()` method if available | ||
* @param ctor The constructor of the resource | ||
* @param args Arguments for the instance's setup() method | ||
*/ | ||
setupInstance(ctor, ...args) { | ||
const instance = this.getInstance(ctor); | ||
instance.setup(...args); | ||
this.setExplicitInstance(instance); | ||
return instance; | ||
} | ||
/** | ||
* Retrieves an instance and runs it's `setup()` method if available | ||
* @param ctor The constructor of the resource | ||
* @param args Arguments for the instance's setup() method | ||
*/ | ||
setupLocalInstance(ctor, ...args) { | ||
const instance = this.getInstance(ctor, true); | ||
instance.setup(...args); | ||
this.setExplicitInstance(instance); | ||
return instance; | ||
} | ||
/** | ||
* Creates a child injector instance | ||
@@ -100,0 +106,0 @@ * @param options Additional injector options |
{ | ||
"name": "@furystack/inject", | ||
"version": "2.0.0", | ||
"version": "3.0.0", | ||
"description": "Core FuryStack package", | ||
@@ -54,12 +54,12 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@sensenet/client-utils": "^1.2.1", | ||
"reflect-metadata": "^0.1.12" | ||
"@sensenet/client-utils": "1.4.2", | ||
"reflect-metadata": "0.1.13" | ||
}, | ||
"devDependencies": { | ||
"@types/jest": "^23.3.11", | ||
"jest": "^23.6.0", | ||
"rimraf": "^2.6.1", | ||
"ts-jest": "^23.10.4", | ||
"tslint": "^5.11.0", | ||
"typescript": "^3.1.6" | ||
"@types/jest": "24.0.9", | ||
"jest": "24.1.0", | ||
"rimraf": "2.6.3", | ||
"ts-jest": "24.0.0", | ||
"tslint": "5.13.0", | ||
"typescript": "3.3.3333" | ||
}, | ||
@@ -72,3 +72,3 @@ "config": { | ||
"typings": "./dist/index.d.ts", | ||
"gitHead": "d0452632dfb2b8de2dcb1c47d88fff62997c738d" | ||
"gitHead": "1045d854bfd8c475b7035471d130d401417a2321" | ||
} |
@@ -9,6 +9,3 @@ import 'reflect-metadata' | ||
export interface IInjectableOptions { | ||
/** | ||
* Enables or disables resolving the dependencies from the constructor (true by default) | ||
*/ | ||
ResolveDependencies: boolean | ||
lifetime: 'transient' | 'singleton' | 'scoped' | ||
} | ||
@@ -20,3 +17,3 @@ | ||
export const defaultInjectableOptions: IInjectableOptions = { | ||
ResolveDependencies: true, | ||
lifetime: 'transient', | ||
} | ||
@@ -32,3 +29,3 @@ | ||
const metaValue = { | ||
Dependencies: | ||
dependencies: | ||
(meta && | ||
@@ -39,3 +36,3 @@ (meta as any[]).map(param => { | ||
[], | ||
Options: { ...defaultInjectableOptions, ...options }, | ||
options: { ...defaultInjectableOptions, ...options }, | ||
} | ||
@@ -42,0 +39,0 @@ Injector.meta.set(ctor, metaValue) |
import { Disposable } from '@sensenet/client-utils' | ||
import { defaultInjectableOptions } from './Injectable' | ||
import { Constructable } from './Types/Constructable' | ||
@@ -35,4 +36,4 @@ | ||
{ | ||
Dependencies: Array<Constructable<any>> | ||
Options: import('./Injectable').IInjectableOptions | ||
dependencies: Array<Constructable<any>> | ||
options: import('./Injectable').IInjectableOptions | ||
} | ||
@@ -48,30 +49,53 @@ > = new Map() | ||
* @param ctor The constructor object (e.g. IncomingMessage) | ||
* @param local Flag that forbids parent walk if the instance is not available but the injector has a parent | ||
* @param dependencies Resolved dependencies | ||
*/ | ||
public getInstance<T>(ctor: Constructable<T>, local: boolean = false, dependencies: Array<Constructable<T>> = []): T { | ||
public getInstance<T>(ctor: Constructable<T>, dependencies: Array<Constructable<T>> = []): T { | ||
if (ctor === this.constructor) { | ||
return (this as any) as T | ||
} | ||
const meta = Injector.meta.get(ctor) | ||
if (!meta) { | ||
throw Error( | ||
`No metadata found for '${ctor.name}'. Dependencies: ${dependencies | ||
.map(d => d.name) | ||
.join(',')}. Be sure that it's decorated with '@Injectable()' or added explicitly with SetInstance()`, | ||
) | ||
} | ||
if (dependencies.includes(ctor)) { | ||
throw Error(`Circular dependencies found.`) | ||
} | ||
if (this.cachedSingletons.has(ctor)) { | ||
if (meta.options.lifetime === 'singleton') { | ||
const invalidDeps = meta.dependencies | ||
.map(dep => ({ meta: Injector.meta.get(dep), dep })) | ||
.filter(m => m.meta && (m.meta.options.lifetime === 'scoped' || m.meta.options.lifetime === 'transient')) | ||
.map(i => i.meta && `${i.dep.name}:${i.meta.options.lifetime}`) | ||
if (invalidDeps.length) { | ||
throw Error( | ||
`Injector error: Singleton type '${ctor.name}' depends on non-singleton injectables: ${invalidDeps.join( | ||
',', | ||
)}`, | ||
) | ||
} | ||
} else if (meta.options.lifetime === 'scoped') { | ||
const invalidDeps = meta.dependencies | ||
.map(dep => ({ meta: Injector.meta.get(dep), dep })) | ||
.filter(m => m.meta && m.meta.options.lifetime === 'transient') | ||
.map(i => i.meta && `${i.dep.name}:${i.meta.options.lifetime}`) | ||
if (invalidDeps.length) { | ||
throw Error( | ||
`Injector error: Scoped type '${ctor.name}' depends on transient injectables: ${invalidDeps.join(',')}`, | ||
) | ||
} | ||
} | ||
if (meta.options.lifetime !== 'transient' && this.cachedSingletons.has(ctor)) { | ||
return this.cachedSingletons.get(ctor) as T | ||
} | ||
const fromParent = !local && this.options.parent && this.options.parent.getInstance(ctor) | ||
const fromParent = | ||
meta.options.lifetime === 'singleton' && this.options.parent && this.options.parent.getInstance(ctor) | ||
if (fromParent) { | ||
return fromParent | ||
} | ||
const meta = Injector.meta.get(ctor) | ||
if (!meta) { | ||
throw Error( | ||
`No metadata found for '${ctor.name}'. Dependencies: ${dependencies | ||
.map(d => d.name) | ||
.join(',')}. Be sure that it's decorated with '@Injectable()' or added explicitly with SetInstance()`, | ||
) | ||
} | ||
const deps = meta.Options.ResolveDependencies | ||
? meta.Dependencies.map(dep => this.getInstance(dep, false, [...dependencies, ctor])) | ||
: [] | ||
const deps = meta.dependencies.map(dep => this.getInstance(dep, [...dependencies, ctor])) | ||
const newInstance = new ctor(...deps) | ||
@@ -88,39 +112,22 @@ this.setExplicitInstance(newInstance) | ||
public setExplicitInstance<T>(instance: T, key?: Constructable<any>) { | ||
const ctor = key || (instance.constructor as Constructable<T>) | ||
if (!Injector.meta.has(ctor)) { | ||
const meta = Reflect.getMetadata('design:paramtypes', ctor) | ||
Injector.meta.set(ctor, { | ||
dependencies: | ||
(meta && | ||
(meta as any[]).map(param => { | ||
return param | ||
})) || | ||
[], | ||
options: { ...defaultInjectableOptions, lifetime: 'explicit' as any }, | ||
}) | ||
} | ||
if (instance.constructor === this.constructor) { | ||
throw Error('Cannot set an injector instance as injectable') | ||
} | ||
this.cachedSingletons.set(key || (instance.constructor as Constructable<T>), instance) | ||
this.cachedSingletons.set(ctor, instance) | ||
} | ||
/** | ||
* Retrieves an instance and runs it's `setup()` method if available | ||
* @param ctor The constructor of the resource | ||
* @param args Arguments for the instance's setup() method | ||
*/ | ||
public setupInstance<T extends { setup: (...args: TSetupArgs) => void }, TSetupArgs extends any[]>( | ||
ctor: new (...args: any[]) => T, | ||
...args: TSetupArgs | ||
) { | ||
const instance = this.getInstance(ctor) | ||
instance.setup(...args) | ||
this.setExplicitInstance(instance) | ||
return instance | ||
} | ||
/** | ||
* Retrieves an instance and runs it's `setup()` method if available | ||
* @param ctor The constructor of the resource | ||
* @param args Arguments for the instance's setup() method | ||
*/ | ||
public setupLocalInstance<T extends { setup: (...args: TSetupArgs) => void }, TSetupArgs extends any[]>( | ||
ctor: new (...args: any[]) => T, | ||
...args: TSetupArgs | ||
) { | ||
const instance = this.getInstance(ctor, true) | ||
instance.setup(...args) | ||
this.setExplicitInstance(instance) | ||
return instance | ||
} | ||
/** | ||
* Creates a child injector instance | ||
@@ -127,0 +134,0 @@ * @param options Additional injector options |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
42162
0
396
+ Added@sensenet/client-utils@1.4.2(transitive)
+ Addedreflect-metadata@0.1.13(transitive)
- Removed@sensenet/client-utils@1.10.0(transitive)
- Removedreflect-metadata@0.1.14(transitive)
- Removedtslib@2.8.1(transitive)
Updated@sensenet/client-utils@1.4.2
Updatedreflect-metadata@0.1.13