@loopback/context
Advanced tools
Comparing version 4.0.0-alpha.6 to 4.0.0-alpha.7
import 'reflect-metadata'; | ||
import { BoundValue } from './binding'; | ||
export interface Injection { | ||
bindingKey: string; | ||
metadata?: { | ||
[attribute: string]: BoundValue; | ||
}; | ||
} | ||
/** | ||
@@ -10,2 +17,4 @@ * A decorator to annotate method arguments for automatic injection | ||
* class InfoController { | ||
* @inject('authentication.user') public userName: string; | ||
* | ||
* constructor(@inject('application.name') public appName: string) { | ||
@@ -21,6 +30,20 @@ * } | ||
* | ||
* @param bindingKey What binding to use in order to resolve the value | ||
* of the annotated argument. | ||
* @param bindingKey What binding to use in order to resolve the value of the | ||
* decorated constructor parameter or property. | ||
* @param metadata Optional metadata to help the injection | ||
* | ||
*/ | ||
export declare function inject(bindingKey: string): (target: Object, propertyKey: string | symbol, parameterIndex: number) => void; | ||
export declare function describeInjectedArguments(target: Function): string[]; | ||
export declare function inject(bindingKey: string, metadata?: Object): (target: any, propertyKey?: string | symbol | undefined, propertyDescriptorOrParameterIndex?: number | TypedPropertyDescriptor<any> | undefined) => void; | ||
/** | ||
* Return an array of injection objects for constructor parameters | ||
* @param target The target class | ||
*/ | ||
export declare function describeInjectedArguments(target: Function): Injection[]; | ||
/** | ||
* Return a map of injection objects for properties | ||
* @param target The target class. Please note a property decorator function receives | ||
* the target.prototype | ||
*/ | ||
export declare function describeInjectedProperties(target: Function): { | ||
[p: string]: Injection; | ||
}; |
@@ -7,5 +7,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const assert = require("assert"); | ||
require("reflect-metadata"); | ||
const REFLECTION_KEY = 'loopback.inject'; | ||
const REFLECTION_CDI_KEY = 'loopback:inject:constructor'; | ||
const REFLECTION_PDI_KEY = 'loopback:inject:properties'; | ||
/** | ||
@@ -19,2 +19,4 @@ * A decorator to annotate method arguments for automatic injection | ||
* class InfoController { | ||
* @inject('authentication.user') public userName: string; | ||
* | ||
* constructor(@inject('application.name') public appName: string) { | ||
@@ -30,17 +32,45 @@ * } | ||
* | ||
* @param bindingKey What binding to use in order to resolve the value | ||
* of the annotated argument. | ||
* @param bindingKey What binding to use in order to resolve the value of the | ||
* decorated constructor parameter or property. | ||
* @param metadata Optional metadata to help the injection | ||
* | ||
*/ | ||
function inject(bindingKey) { | ||
return function markArgumentAsInjected(target, propertyKey, parameterIndex) { | ||
assert(parameterIndex != undefined, '@inject decorator can be used on function arguments only!'); | ||
const injectedArgs = Reflect.getOwnMetadata(REFLECTION_KEY, target, propertyKey) || []; | ||
injectedArgs[parameterIndex] = bindingKey; | ||
Reflect.defineMetadata(REFLECTION_KEY, injectedArgs, target, propertyKey); | ||
function inject(bindingKey, metadata) { | ||
// tslint:disable-next-line:no-any | ||
return function markArgumentAsInjected(target, propertyKey, propertyDescriptorOrParameterIndex) { | ||
if (typeof propertyDescriptorOrParameterIndex === 'number') { | ||
// The decorator is applied to a method parameter | ||
// Please note propertyKey is `undefined` for constructor | ||
const injectedArgs = Reflect.getOwnMetadata(REFLECTION_CDI_KEY, target, propertyKey) || []; | ||
injectedArgs[propertyDescriptorOrParameterIndex] = { bindingKey, metadata }; | ||
Reflect.defineMetadata(REFLECTION_CDI_KEY, injectedArgs, target, propertyKey); | ||
} | ||
else if (propertyKey) { | ||
// The decorator is applied to a property | ||
const injections = Reflect.getOwnMetadata(REFLECTION_PDI_KEY, target) || {}; | ||
injections[propertyKey] = { bindingKey, metadata }; | ||
Reflect.defineMetadata(REFLECTION_PDI_KEY, injections, target); | ||
} | ||
else { | ||
throw new Error('@inject can be used on properties or method parameters.'); | ||
} | ||
}; | ||
} | ||
exports.inject = inject; | ||
/** | ||
* Return an array of injection objects for constructor parameters | ||
* @param target The target class | ||
*/ | ||
function describeInjectedArguments(target) { | ||
return Reflect.getOwnMetadata(REFLECTION_KEY, target) || []; | ||
return Reflect.getOwnMetadata(REFLECTION_CDI_KEY, target) || []; | ||
} | ||
exports.describeInjectedArguments = describeInjectedArguments; | ||
/** | ||
* Return a map of injection objects for properties | ||
* @param target The target class. Please note a property decorator function receives | ||
* the target.prototype | ||
*/ | ||
function describeInjectedProperties(target) { | ||
return Reflect.getOwnMetadata(REFLECTION_PDI_KEY, target.prototype) || {}; | ||
} | ||
exports.describeInjectedProperties = describeInjectedProperties; |
@@ -27,1 +27,5 @@ import { Context } from './context'; | ||
export declare function resolveInjectedArguments(fn: Function, ctx: Context): BoundValue[] | Promise<BoundValue[]>; | ||
export declare type KV = { | ||
[p: string]: BoundValue; | ||
}; | ||
export declare function resolveInjectedProperties(fn: Function, ctx: Context): KV | Promise<KV>; |
@@ -21,8 +21,34 @@ "use strict"; | ||
const argsOrPromise = resolveInjectedArguments(ctor, ctx); | ||
const propertiesOrPromise = resolveInjectedProperties(ctor, ctx); | ||
let inst; | ||
if (isPromise_1.isPromise(argsOrPromise)) { | ||
return argsOrPromise.then(args => new ctor(...args)); | ||
// Instantiate the class asynchronously | ||
inst = argsOrPromise.then(args => new ctor(...args)); | ||
} | ||
else { | ||
return new ctor(...argsOrPromise); | ||
// Instantiate the class synchronously | ||
inst = new ctor(...argsOrPromise); | ||
} | ||
if (isPromise_1.isPromise(propertiesOrPromise)) { | ||
return propertiesOrPromise.then((props) => { | ||
if (isPromise_1.isPromise(inst)) { | ||
// Inject the properties asynchrounously | ||
return inst.then(obj => Object.assign(obj, props)); | ||
} | ||
else { | ||
// Inject the properties synchrounously | ||
return Object.assign(inst, props); | ||
} | ||
}); | ||
} | ||
else { | ||
if (isPromise_1.isPromise(inst)) { | ||
// Inject the properties asynchrounously | ||
return inst.then(obj => Object.assign(obj, propertiesOrPromise)); | ||
} | ||
else { | ||
// Inject the properties synchrounously | ||
return Object.assign(inst, propertiesOrPromise); | ||
} | ||
} | ||
} | ||
@@ -50,3 +76,3 @@ exports.instantiateClass = instantiateClass; | ||
for (let ix = 0; ix < fn.length; ix++) { | ||
const bindingKey = injectedArgs[ix]; | ||
const bindingKey = injectedArgs[ix].bindingKey; | ||
if (!bindingKey) { | ||
@@ -75,1 +101,31 @@ throw new Error(`Cannot resolve injected arguments for function ${fn.name}: ` + | ||
exports.resolveInjectedArguments = resolveInjectedArguments; | ||
function resolveInjectedProperties(fn, ctx) { | ||
const injectedProperties = inject_1.describeInjectedProperties(fn); | ||
const properties = {}; | ||
let asyncResolvers = undefined; | ||
const propertyResolver = (p) => ((v) => properties[p] = v); | ||
for (const p in injectedProperties) { | ||
const bindingKey = injectedProperties[p].bindingKey; | ||
if (!bindingKey) { | ||
throw new Error(`Cannot resolve injected property for class ${fn.name}: ` + | ||
`The property ${p} was not decorated for dependency injection.`); | ||
} | ||
const binding = ctx.getBinding(bindingKey); | ||
const valueOrPromise = binding.getValue(ctx); | ||
if (isPromise_1.isPromise(valueOrPromise)) { | ||
if (!asyncResolvers) | ||
asyncResolvers = []; | ||
asyncResolvers.push(valueOrPromise.then(propertyResolver(p))); | ||
} | ||
else { | ||
properties[p] = valueOrPromise; | ||
} | ||
} | ||
if (asyncResolvers) { | ||
return Promise.all(asyncResolvers).then(() => properties); | ||
} | ||
else { | ||
return properties; | ||
} | ||
} | ||
exports.resolveInjectedProperties = resolveInjectedProperties; |
import 'reflect-metadata'; | ||
import { BoundValue } from './binding'; | ||
export interface Injection { | ||
bindingKey: string; | ||
metadata?: { | ||
[attribute: string]: BoundValue; | ||
}; | ||
} | ||
/** | ||
@@ -10,2 +17,4 @@ * A decorator to annotate method arguments for automatic injection | ||
* class InfoController { | ||
* @inject('authentication.user') public userName: string; | ||
* | ||
* constructor(@inject('application.name') public appName: string) { | ||
@@ -21,6 +30,20 @@ * } | ||
* | ||
* @param bindingKey What binding to use in order to resolve the value | ||
* of the annotated argument. | ||
* @param bindingKey What binding to use in order to resolve the value of the | ||
* decorated constructor parameter or property. | ||
* @param metadata Optional metadata to help the injection | ||
* | ||
*/ | ||
export declare function inject(bindingKey: string): (target: Object, propertyKey: string | symbol, parameterIndex: number) => void; | ||
export declare function describeInjectedArguments(target: Function): string[]; | ||
export declare function inject(bindingKey: string, metadata?: Object): (target: any, propertyKey?: string | symbol | undefined, propertyDescriptorOrParameterIndex?: number | TypedPropertyDescriptor<any> | undefined) => void; | ||
/** | ||
* Return an array of injection objects for constructor parameters | ||
* @param target The target class | ||
*/ | ||
export declare function describeInjectedArguments(target: Function): Injection[]; | ||
/** | ||
* Return a map of injection objects for properties | ||
* @param target The target class. Please note a property decorator function receives | ||
* the target.prototype | ||
*/ | ||
export declare function describeInjectedProperties(target: Function): { | ||
[p: string]: Injection; | ||
}; |
@@ -7,5 +7,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const assert = require("assert"); | ||
require("reflect-metadata"); | ||
const REFLECTION_KEY = 'loopback.inject'; | ||
const REFLECTION_CDI_KEY = 'loopback:inject:constructor'; | ||
const REFLECTION_PDI_KEY = 'loopback:inject:properties'; | ||
/** | ||
@@ -19,2 +19,4 @@ * A decorator to annotate method arguments for automatic injection | ||
* class InfoController { | ||
* @inject('authentication.user') public userName: string; | ||
* | ||
* constructor(@inject('application.name') public appName: string) { | ||
@@ -30,17 +32,45 @@ * } | ||
* | ||
* @param bindingKey What binding to use in order to resolve the value | ||
* of the annotated argument. | ||
* @param bindingKey What binding to use in order to resolve the value of the | ||
* decorated constructor parameter or property. | ||
* @param metadata Optional metadata to help the injection | ||
* | ||
*/ | ||
function inject(bindingKey) { | ||
return function markArgumentAsInjected(target, propertyKey, parameterIndex) { | ||
assert(parameterIndex != undefined, '@inject decorator can be used on function arguments only!'); | ||
const injectedArgs = Reflect.getOwnMetadata(REFLECTION_KEY, target, propertyKey) || []; | ||
injectedArgs[parameterIndex] = bindingKey; | ||
Reflect.defineMetadata(REFLECTION_KEY, injectedArgs, target, propertyKey); | ||
function inject(bindingKey, metadata) { | ||
// tslint:disable-next-line:no-any | ||
return function markArgumentAsInjected(target, propertyKey, propertyDescriptorOrParameterIndex) { | ||
if (typeof propertyDescriptorOrParameterIndex === 'number') { | ||
// The decorator is applied to a method parameter | ||
// Please note propertyKey is `undefined` for constructor | ||
const injectedArgs = Reflect.getOwnMetadata(REFLECTION_CDI_KEY, target, propertyKey) || []; | ||
injectedArgs[propertyDescriptorOrParameterIndex] = { bindingKey, metadata }; | ||
Reflect.defineMetadata(REFLECTION_CDI_KEY, injectedArgs, target, propertyKey); | ||
} | ||
else if (propertyKey) { | ||
// The decorator is applied to a property | ||
const injections = Reflect.getOwnMetadata(REFLECTION_PDI_KEY, target) || {}; | ||
injections[propertyKey] = { bindingKey, metadata }; | ||
Reflect.defineMetadata(REFLECTION_PDI_KEY, injections, target); | ||
} | ||
else { | ||
throw new Error('@inject can be used on properties or method parameters.'); | ||
} | ||
}; | ||
} | ||
exports.inject = inject; | ||
/** | ||
* Return an array of injection objects for constructor parameters | ||
* @param target The target class | ||
*/ | ||
function describeInjectedArguments(target) { | ||
return Reflect.getOwnMetadata(REFLECTION_KEY, target) || []; | ||
return Reflect.getOwnMetadata(REFLECTION_CDI_KEY, target) || []; | ||
} | ||
exports.describeInjectedArguments = describeInjectedArguments; | ||
/** | ||
* Return a map of injection objects for properties | ||
* @param target The target class. Please note a property decorator function receives | ||
* the target.prototype | ||
*/ | ||
function describeInjectedProperties(target) { | ||
return Reflect.getOwnMetadata(REFLECTION_PDI_KEY, target.prototype) || {}; | ||
} | ||
exports.describeInjectedProperties = describeInjectedProperties; |
@@ -27,1 +27,5 @@ import { Context } from './context'; | ||
export declare function resolveInjectedArguments(fn: Function, ctx: Context): BoundValue[] | Promise<BoundValue[]>; | ||
export declare type KV = { | ||
[p: string]: BoundValue; | ||
}; | ||
export declare function resolveInjectedProperties(fn: Function, ctx: Context): KV | Promise<KV>; |
@@ -21,8 +21,34 @@ "use strict"; | ||
const argsOrPromise = resolveInjectedArguments(ctor, ctx); | ||
const propertiesOrPromise = resolveInjectedProperties(ctor, ctx); | ||
let inst; | ||
if (isPromise_1.isPromise(argsOrPromise)) { | ||
return argsOrPromise.then(args => new ctor(...args)); | ||
// Instantiate the class asynchronously | ||
inst = argsOrPromise.then(args => new ctor(...args)); | ||
} | ||
else { | ||
return new ctor(...argsOrPromise); | ||
// Instantiate the class synchronously | ||
inst = new ctor(...argsOrPromise); | ||
} | ||
if (isPromise_1.isPromise(propertiesOrPromise)) { | ||
return propertiesOrPromise.then((props) => { | ||
if (isPromise_1.isPromise(inst)) { | ||
// Inject the properties asynchrounously | ||
return inst.then(obj => Object.assign(obj, props)); | ||
} | ||
else { | ||
// Inject the properties synchrounously | ||
return Object.assign(inst, props); | ||
} | ||
}); | ||
} | ||
else { | ||
if (isPromise_1.isPromise(inst)) { | ||
// Inject the properties asynchrounously | ||
return inst.then(obj => Object.assign(obj, propertiesOrPromise)); | ||
} | ||
else { | ||
// Inject the properties synchrounously | ||
return Object.assign(inst, propertiesOrPromise); | ||
} | ||
} | ||
} | ||
@@ -50,3 +76,3 @@ exports.instantiateClass = instantiateClass; | ||
for (let ix = 0; ix < fn.length; ix++) { | ||
const bindingKey = injectedArgs[ix]; | ||
const bindingKey = injectedArgs[ix].bindingKey; | ||
if (!bindingKey) { | ||
@@ -75,1 +101,31 @@ throw new Error(`Cannot resolve injected arguments for function ${fn.name}: ` + | ||
exports.resolveInjectedArguments = resolveInjectedArguments; | ||
function resolveInjectedProperties(fn, ctx) { | ||
const injectedProperties = inject_1.describeInjectedProperties(fn); | ||
const properties = {}; | ||
let asyncResolvers = undefined; | ||
const propertyResolver = (p) => ((v) => properties[p] = v); | ||
for (const p in injectedProperties) { | ||
const bindingKey = injectedProperties[p].bindingKey; | ||
if (!bindingKey) { | ||
throw new Error(`Cannot resolve injected property for class ${fn.name}: ` + | ||
`The property ${p} was not decorated for dependency injection.`); | ||
} | ||
const binding = ctx.getBinding(bindingKey); | ||
const valueOrPromise = binding.getValue(ctx); | ||
if (isPromise_1.isPromise(valueOrPromise)) { | ||
if (!asyncResolvers) | ||
asyncResolvers = []; | ||
asyncResolvers.push(valueOrPromise.then(propertyResolver(p))); | ||
} | ||
else { | ||
properties[p] = valueOrPromise; | ||
} | ||
} | ||
if (asyncResolvers) { | ||
return Promise.all(asyncResolvers).then(() => properties); | ||
} | ||
else { | ||
return properties; | ||
} | ||
} | ||
exports.resolveInjectedProperties = resolveInjectedProperties; |
{ | ||
"name": "@loopback/context", | ||
"version": "4.0.0-alpha.6", | ||
"version": "4.0.0-alpha.7", | ||
"description": "LoopBack's container for Inversion of Control", | ||
"main": "index", | ||
"scripts": { | ||
"acceptance": "mocha --opts ../../test/mocha.opts 'test/acceptance/**/*.ts'", | ||
"build": "npm run build:lib && npm run build:lib6", | ||
"build:lib": "tsc --target es2017 --outDir lib", | ||
"build:lib6": "tsc --target es2015 --outDir lib6", | ||
"build:lib": "tsc -p tsconfig.build.json --target es2017 --outDir lib", | ||
"build:lib6": "tsc -p tsconfig.build.json --target es2015 --outDir lib6", | ||
"clean": "rm -f loopback-context*.tgz && rm -rf lib* && rm -rf package", | ||
@@ -25,3 +24,3 @@ "prepublish": "npm run build", | ||
"devDependencies": { | ||
"@loopback/testlab": "^4.0.0-alpha.3", | ||
"@loopback/testlab": "^4.0.0-alpha.4", | ||
"@types/bluebird": "^3.5.2", | ||
@@ -28,0 +27,0 @@ "bluebird": "^3.5.0", |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
43636
1205
1