@furystack/inject
Advanced tools
Comparing version 1.0.9 to 2.0.0
@@ -1,8 +0,21 @@ | ||
import "reflect-metadata"; | ||
import { Constructable } from "./Types/Constructable"; | ||
export interface InjectableOptions { | ||
import 'reflect-metadata'; | ||
import { Constructable } from './Types/Constructable'; | ||
/** | ||
* Options for the injectable instance | ||
*/ | ||
export interface IInjectableOptions { | ||
/** | ||
* Enables or disables resolving the dependencies from the constructor (true by default) | ||
*/ | ||
ResolveDependencies: boolean; | ||
} | ||
export declare const defaultInjectableOptions: InjectableOptions; | ||
export declare const Injectable: (options?: Partial<InjectableOptions> | undefined) => <T extends Constructable<any>>(ctor: T) => void; | ||
/** | ||
* The default options for the injectable classes | ||
*/ | ||
export declare const defaultInjectableOptions: IInjectableOptions; | ||
/** | ||
* Decorator method for tagging a class as injectable | ||
* @param options The options object | ||
*/ | ||
export declare const Injectable: (options?: Partial<IInjectableOptions> | undefined) => <T extends Constructable<any>>(ctor: T) => void; | ||
//# sourceMappingURL=Injectable.d.ts.map |
@@ -5,17 +5,26 @@ "use strict"; | ||
const Injector_1 = require("./Injector"); | ||
/** | ||
* The default options for the injectable classes | ||
*/ | ||
exports.defaultInjectableOptions = { | ||
ResolveDependencies: true, | ||
}; | ||
/** | ||
* Decorator method for tagging a class as injectable | ||
* @param options The options object | ||
*/ | ||
exports.Injectable = (options) => { | ||
return (ctor) => { | ||
const meta = Reflect.getMetadata("design:paramtypes", ctor); | ||
const meta = Reflect.getMetadata('design:paramtypes', ctor); | ||
const metaValue = { | ||
Dependencies: meta && meta.map((param) => { | ||
return param; | ||
}) || [], | ||
Dependencies: (meta && | ||
meta.map(param => { | ||
return param; | ||
})) || | ||
[], | ||
Options: { ...exports.defaultInjectableOptions, ...options }, | ||
}; | ||
Injector_1.Injector.Default.meta.set(ctor, metaValue); | ||
Injector_1.Injector.meta.set(ctor, metaValue); | ||
}; | ||
}; | ||
//# sourceMappingURL=Injectable.js.map |
@@ -1,20 +0,62 @@ | ||
import { Disposable } from "@sensenet/client-utils"; | ||
import { Constructable } from "./Types/Constructable"; | ||
import { Disposable } from '@sensenet/client-utils'; | ||
import { Constructable } from './Types/Constructable'; | ||
/** | ||
* Container for injectable instances | ||
*/ | ||
export declare class Injector implements Disposable { | ||
/** | ||
* Disposes the Injector object and all its disposable injectables | ||
*/ | ||
dispose(): Promise<void>; | ||
/** | ||
* Options object for an injector instance | ||
*/ | ||
options: { | ||
parent: Injector; | ||
owner: any; | ||
parent?: Injector; | ||
owner?: any; | ||
}; | ||
static Default: Injector; | ||
meta: Map<Constructable<any>, { | ||
/** | ||
* Static class metadata map, filled by the @Injectable() decorator | ||
*/ | ||
static meta: Map<Constructable<any>, { | ||
Dependencies: Array<Constructable<any>>; | ||
Options: import("./Injectable").InjectableOptions; | ||
Options: import('./Injectable').IInjectableOptions; | ||
}>; | ||
private cachedSingletons; | ||
Remove: <T>(ctor: Constructable<T>) => boolean; | ||
GetInstance<T>(ctor: Constructable<T>, local?: boolean, dependencies?: Array<Constructable<T>>): T; | ||
SetInstance<T>(instance: T, key?: Constructable<any>): void; | ||
constructor(options?: Partial<Injector["options"]>); | ||
remove: <T>(ctor: Constructable<T>) => boolean; | ||
/** | ||
* | ||
* @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; | ||
/** | ||
* Sets explicitliy an instance for a key in the store | ||
* @param instance The created instance | ||
* @param key The class key to be persisted (optional, calls back to the instance's constructor) | ||
*/ | ||
setExplicitInstance<T>(instance: T, key?: Constructable<any>): void; | ||
/** | ||
* 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 | ||
* @param options Additional injector options | ||
*/ | ||
createChild(options?: Partial<Injector['options']>): Injector; | ||
} | ||
//# sourceMappingURL=Injector.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* Container for injectable instances | ||
*/ | ||
class Injector { | ||
constructor(options) { | ||
this.options = { | ||
parent: Injector.Default, | ||
owner: null, | ||
}; | ||
this.meta = new Map(); | ||
constructor() { | ||
/** | ||
* Options object for an injector instance | ||
*/ | ||
this.options = {}; | ||
this.cachedSingletons = new Map(); | ||
this.Remove = (ctor) => this.cachedSingletons.delete(ctor); | ||
this.options = { ...this.options, ...options }; | ||
this.remove = (ctor) => this.cachedSingletons.delete(ctor); | ||
} | ||
/** | ||
* Disposes the Injector object and all its disposable injectables | ||
*/ | ||
async dispose() { | ||
/** */ | ||
const singletons = Array.from(this.cachedSingletons.entries()).map((e) => e[1]); | ||
const singletons = Array.from(this.cachedSingletons.entries()).map(e => e[1]); | ||
const disposeRequests = singletons | ||
.filter((s) => s !== this) | ||
.filter(s => s !== this) | ||
.map(async (s) => { | ||
@@ -26,3 +30,9 @@ if (s.dispose) { | ||
} | ||
GetInstance(ctor, local = false, dependencies = []) { | ||
/** | ||
* | ||
* @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 = []) { | ||
if (ctor === this.constructor) { | ||
@@ -37,28 +47,68 @@ return this; | ||
} | ||
const fromParent = !local && this.options.parent && this.options.parent.GetInstance(ctor); | ||
const fromParent = !local && this.options.parent && this.options.parent.getInstance(ctor); | ||
if (fromParent) { | ||
return fromParent; | ||
} | ||
const meta = Injector.Default.meta.get(ctor); | ||
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()`); | ||
.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])) | ||
? meta.Dependencies.map(dep => this.getInstance(dep, false, [...dependencies, ctor])) | ||
: []; | ||
const newInstance = new ctor(...deps); | ||
this.SetInstance(newInstance); | ||
this.setExplicitInstance(newInstance); | ||
return newInstance; | ||
} | ||
SetInstance(instance, key) { | ||
/** | ||
* Sets explicitliy an instance for a key in the store | ||
* @param instance The created instance | ||
* @param key The class key to be persisted (optional, calls back to the instance's constructor) | ||
*/ | ||
setExplicitInstance(instance, key) { | ||
if (instance.constructor === this.constructor) { | ||
throw Error("Cannot set an injector instance as injectable"); | ||
throw Error('Cannot set an injector instance as injectable'); | ||
} | ||
this.cachedSingletons.set(key || instance.constructor, 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 | ||
* @param options Additional injector options | ||
*/ | ||
createChild(options) { | ||
const i = new Injector(); | ||
i.options = i.options || options; | ||
i.options.parent = this; | ||
return i; | ||
} | ||
} | ||
Injector.Default = new Injector({ parent: undefined }); | ||
/** | ||
* Static class metadata map, filled by the @Injectable() decorator | ||
*/ | ||
Injector.meta = new Map(); | ||
exports.Injector = Injector; | ||
//# sourceMappingURL=Injector.js.map |
@@ -0,2 +1,5 @@ | ||
/** | ||
* Type that defines a type as constructable | ||
*/ | ||
export declare type Constructable<T> = (new (...args: any[]) => object) & (new (...args: any[]) => T); | ||
//# sourceMappingURL=Constructable.d.ts.map |
{ | ||
"name": "@furystack/inject", | ||
"version": "1.0.9", | ||
"version": "2.0.0", | ||
"description": "Core FuryStack package", | ||
@@ -71,3 +71,3 @@ "main": "dist/index.js", | ||
"typings": "./dist/index.d.ts", | ||
"gitHead": "625d3512cd6bfe9ea97d3dedde2023c0996970ab" | ||
"gitHead": "d0452632dfb2b8de2dcb1c47d88fff62997c738d" | ||
} |
@@ -1,24 +0,40 @@ | ||
import "reflect-metadata"; | ||
import { Injector } from "./Injector"; | ||
import { Constructable } from "./Types/Constructable"; | ||
import 'reflect-metadata' | ||
import { Injector } from './Injector' | ||
import { Constructable } from './Types/Constructable' | ||
export interface InjectableOptions { | ||
ResolveDependencies: boolean; | ||
/** | ||
* Options for the injectable instance | ||
*/ | ||
export interface IInjectableOptions { | ||
/** | ||
* Enables or disables resolving the dependencies from the constructor (true by default) | ||
*/ | ||
ResolveDependencies: boolean | ||
} | ||
export const defaultInjectableOptions: InjectableOptions = { | ||
ResolveDependencies: true, | ||
}; | ||
/** | ||
* The default options for the injectable classes | ||
*/ | ||
export const defaultInjectableOptions: IInjectableOptions = { | ||
ResolveDependencies: true, | ||
} | ||
export const Injectable = (options?: Partial<InjectableOptions>) => { | ||
return <T extends Constructable<any>>(ctor: T) => { | ||
const meta = Reflect.getMetadata("design:paramtypes", ctor); | ||
const metaValue = { | ||
Dependencies: meta && (meta as any[]).map((param) => { | ||
return param; | ||
}) || [], | ||
Options: {...defaultInjectableOptions, ...options}, | ||
}; | ||
Injector.Default.meta.set(ctor, metaValue); | ||
}; | ||
}; | ||
/** | ||
* Decorator method for tagging a class as injectable | ||
* @param options The options object | ||
*/ | ||
export const Injectable = (options?: Partial<IInjectableOptions>) => { | ||
return <T extends Constructable<any>>(ctor: T) => { | ||
const meta = Reflect.getMetadata('design:paramtypes', ctor) | ||
const metaValue = { | ||
Dependencies: | ||
(meta && | ||
(meta as any[]).map(param => { | ||
return param | ||
})) || | ||
[], | ||
Options: { ...defaultInjectableOptions, ...options }, | ||
} | ||
Injector.meta.set(ctor, metaValue) | ||
} | ||
} |
@@ -1,91 +0,132 @@ | ||
import { Disposable } from "@sensenet/client-utils"; | ||
import { Constructable } from "./Types/Constructable"; | ||
import { Disposable } from '@sensenet/client-utils' | ||
import { Constructable } from './Types/Constructable' | ||
/** | ||
* Container for injectable instances | ||
*/ | ||
export class Injector implements Disposable { | ||
/** | ||
* Disposes the Injector object and all its disposable injectables | ||
*/ | ||
public async dispose() { | ||
/** */ | ||
const singletons = Array.from(this.cachedSingletons.entries()).map( | ||
(e) => e[1], | ||
); | ||
const singletons = Array.from(this.cachedSingletons.entries()).map(e => e[1]) | ||
const disposeRequests = singletons | ||
.filter((s) => s !== this) | ||
.map(async (s) => { | ||
.filter(s => s !== this) | ||
.map(async s => { | ||
if (s.dispose) { | ||
await s.dispose(); | ||
await s.dispose() | ||
} | ||
}); | ||
await Promise.all(disposeRequests); | ||
}) | ||
await Promise.all(disposeRequests) | ||
} | ||
public options: { parent: Injector; owner: any } = { | ||
parent: Injector.Default, | ||
owner: null, | ||
}; | ||
/** | ||
* Options object for an injector instance | ||
*/ | ||
public options: { parent?: Injector; owner?: any } = {} | ||
public static Default: Injector = new Injector({ parent: undefined }); | ||
public meta: Map< | ||
/** | ||
* Static class metadata map, filled by the @Injectable() decorator | ||
*/ | ||
public static meta: Map< | ||
Constructable<any>, | ||
{ | ||
Dependencies: Array<Constructable<any>>; | ||
Options: import("./Injectable").InjectableOptions; | ||
Dependencies: Array<Constructable<any>> | ||
Options: import('./Injectable').IInjectableOptions | ||
} | ||
> = new Map(); | ||
> = new Map() | ||
private cachedSingletons: Map<Constructable<any>, any> = new Map(); | ||
private cachedSingletons: Map<Constructable<any>, any> = new Map() | ||
public Remove = <T>(ctor: Constructable<T>) => | ||
this.cachedSingletons.delete(ctor) | ||
public remove = <T>(ctor: Constructable<T>) => this.cachedSingletons.delete(ctor) | ||
public GetInstance<T>( | ||
ctor: Constructable<T>, | ||
local: boolean = false, | ||
dependencies: Array<Constructable<T>> = [], | ||
): T { | ||
/** | ||
* | ||
* @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 { | ||
if (ctor === this.constructor) { | ||
return (this as any) as T; | ||
return (this as any) as T | ||
} | ||
if (dependencies.includes(ctor)) { | ||
throw Error(`Circular dependencies found.`); | ||
throw Error(`Circular dependencies found.`) | ||
} | ||
if (this.cachedSingletons.has(ctor)) { | ||
return this.cachedSingletons.get(ctor) as T; | ||
return this.cachedSingletons.get(ctor) as T | ||
} | ||
const fromParent = | ||
!local && this.options.parent && this.options.parent.GetInstance(ctor); | ||
const fromParent = !local && this.options.parent && this.options.parent.getInstance(ctor) | ||
if (fromParent) { | ||
return fromParent; | ||
return fromParent | ||
} | ||
const meta = Injector.Default.meta.get(ctor); | ||
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()`, | ||
); | ||
.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 newInstance = new ctor(...deps); | ||
this.SetInstance(newInstance); | ||
return newInstance; | ||
? meta.Dependencies.map(dep => this.getInstance(dep, false, [...dependencies, ctor])) | ||
: [] | ||
const newInstance = new ctor(...deps) | ||
this.setExplicitInstance(newInstance) | ||
return newInstance | ||
} | ||
public SetInstance<T>(instance: T, key?: Constructable<any>) { | ||
/** | ||
* Sets explicitliy an instance for a key in the store | ||
* @param instance The created instance | ||
* @param key The class key to be persisted (optional, calls back to the instance's constructor) | ||
*/ | ||
public setExplicitInstance<T>(instance: T, key?: Constructable<any>) { | ||
if (instance.constructor === this.constructor) { | ||
throw Error("Cannot set an injector instance as injectable"); | ||
throw Error('Cannot set an injector instance as injectable') | ||
} | ||
this.cachedSingletons.set( | ||
key || (instance.constructor as Constructable<T>), | ||
instance, | ||
); | ||
this.cachedSingletons.set(key || (instance.constructor as Constructable<T>), instance) | ||
} | ||
constructor(options?: Partial<Injector["options"]>) { | ||
this.options = { ...this.options, ...options }; | ||
/** | ||
* 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 | ||
* @param options Additional injector options | ||
*/ | ||
public createChild(options?: Partial<Injector['options']>) { | ||
const i = new Injector() | ||
i.options = i.options || options | ||
i.options.parent = this | ||
return i | ||
} | ||
} |
@@ -1,1 +0,4 @@ | ||
export declare type Constructable<T> = (new (...args: any[]) => object) & (new (...args: any[]) => T); | ||
/** | ||
* Type that defines a type as constructable | ||
*/ | ||
export declare type Constructable<T> = (new (...args: any[]) => object) & (new (...args: any[]) => T) |
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
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
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
41419
406
1