Socket
Socket
Sign inDemoInstall

@loopback/metadata

Package Overview
Dependencies
Maintainers
17
Versions
166
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@loopback/metadata - npm Package Compare versions

Comparing version 4.0.0-alpha.2 to 4.0.0-alpha.3

17

CHANGELOG.md

@@ -6,2 +6,19 @@ # Change Log

<a name="4.0.0-alpha.3"></a>
# [4.0.0-alpha.3](https://github.com/strongloop/loopback-next/compare/@loopback/metadata@4.0.0-alpha.2...@loopback/metadata@4.0.0-alpha.3) (2017-12-21)
### Bug Fixes
* **metadata:** fix method-level parameter decorators ([c5127d4](https://github.com/strongloop/loopback-next/commit/c5127d4))
* **metadata:** keep class prototypes untouched during clone ([195e421](https://github.com/strongloop/loopback-next/commit/195e421))
### Features
* **metadata:** Add a flag to keep args of decorators safe ([3782192](https://github.com/strongloop/loopback-next/commit/3782192))
<a name="4.0.0-alpha.2"></a>

@@ -8,0 +25,0 @@ # 4.0.0-alpha.2 (2017-12-15)

24

dist/src/decorator-factory.d.ts

@@ -12,5 +12,14 @@ /**

/**
* Inheritance will be honored
* Controls if inherited metadata will be honored. Default to `true`.
*/
allowsInheritance?: boolean;
allowInheritance?: boolean;
/**
* Controls if the value of `spec` argument will be cloned. Sometimes we
* use shared spec for the decoration, but the decorator function might need
* to mutate the object. Cloning the input spec makes it safe to use the same
* spec (`template`) to decorate different members.
*
* Default to `true`.
*/
cloneInputSpec?: boolean;
[name: string]: any;

@@ -217,5 +226,10 @@ }

export declare class MethodParameterDecoratorFactory<T> extends DecoratorFactory<T, MetadataMap<T[]>, MethodDecorator> {
protected mergeWithInherited(inheritedMetadata: MetadataMap<T[]>, target: Object, methodName?: string | symbol, methodDescriptor?: TypedPropertyDescriptor<any> | number): {
[x: string]: T[];
};
/**
* Find the corresponding parameter index for the decoration
* @param target
* @param methodName
* @param methodDescriptor
*/
private getParameterIndex(target, methodName?, methodDescriptor?);
protected mergeWithInherited(inheritedMetadata: MetadataMap<T[]>, target: Object, methodName?: string | symbol, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;
protected mergeWithOwn(ownMetadata: MetadataMap<T[]>, target: Object, methodName?: string | symbol, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;

@@ -222,0 +236,0 @@ create(): MethodDecorator;

@@ -45,6 +45,9 @@ "use strict";

this.options = options;
this.options = Object.assign({ allowInheritance: true }, options);
this.options = Object.assign({ allowInheritance: true, cloneInputSpec: true }, options);
if (this.options.cloneInputSpec) {
this.spec = DecoratorFactory.cloneDeep(spec);
}
}
allowInheritance() {
return this.options && this.options.allowInheritance;
return !!(this.options && this.options.allowInheritance);
}

@@ -229,5 +232,4 @@ /**

static cloneDeep(val) {
if (val === undefined) {
return {};
}
if (typeof val !== 'object')
return val;
return _.cloneDeepWith(val, v => {

@@ -237,2 +239,8 @@ // Do not clone functions

return v;
if (v &&
typeof v.constructor === 'function' &&
v.constructor.prototype === v) {
// Do not clone class prototype
return v;
}
return undefined;

@@ -280,2 +288,3 @@ });

mergeWithInherited(inheritedMetadata, target, propertyName, descriptorOrIndex) {
inheritedMetadata = inheritedMetadata || {};
const propertyMeta = this.withTarget(this.inherit(inheritedMetadata[propertyName]), target);

@@ -286,4 +295,3 @@ inheritedMetadata[propertyName] = propertyMeta;

mergeWithOwn(ownMetadata, target, propertyName, descriptorOrParameterIndex) {
if (ownMetadata == null)
ownMetadata = {};
ownMetadata = ownMetadata || {};
if (ownMetadata[propertyName] != null) {

@@ -315,2 +323,3 @@ const targetName = this.getTargetName(target, propertyName);

mergeWithInherited(inheritedMetadata, target, methodName, methodDescriptor) {
inheritedMetadata = inheritedMetadata || {};
const methodMeta = this.withTarget(this.inherit(inheritedMetadata[methodName]), target);

@@ -321,4 +330,3 @@ inheritedMetadata[methodName] = methodMeta;

mergeWithOwn(ownMetadata, target, methodName, methodDescriptor) {
if (ownMetadata == null)
ownMetadata = {};
ownMetadata = ownMetadata || {};
const methodMeta = ownMetadata[methodName];

@@ -362,2 +370,3 @@ if (this.getTarget(methodMeta) === target) {

mergeWithInherited(inheritedMetadata, target, methodName, parameterIndex) {
inheritedMetadata = inheritedMetadata || {};
const methodMeta = this.getOrInitMetadata(inheritedMetadata, target, methodName);

@@ -369,4 +378,3 @@ const index = parameterIndex;

mergeWithOwn(ownMetadata, target, methodName, parameterIndex) {
if (ownMetadata == null)
ownMetadata = {};
ownMetadata = ownMetadata || {};
// Find the method metadata

@@ -409,11 +417,43 @@ const methodMeta = this.getOrInitMetadata(ownMetadata, target, methodName);

class MethodParameterDecoratorFactory extends DecoratorFactory {
/**
* Find the corresponding parameter index for the decoration
* @param target
* @param methodName
* @param methodDescriptor
*/
getParameterIndex(target, methodName, methodDescriptor) {
const numOfParams = this.getNumberOfParameters(target, methodName);
// Fetch the cached parameter index
let index = reflect_1.Reflector.getOwnMetadata(this.key + ':index', target, methodName);
// Default to the last parameter
if (index == null)
index = numOfParams - 1;
if (index < 0) {
// Excessive decorations than the number of parameters detected
const method = this.getTargetName(target, methodName, methodDescriptor);
throw new Error(`The decorator is used more than ${numOfParams} time(s) on ${method}`);
}
return index;
}
mergeWithInherited(inheritedMetadata, target, methodName, methodDescriptor) {
return { [methodName]: [this.spec] };
inheritedMetadata = inheritedMetadata || {};
const index = this.getParameterIndex(target, methodName, methodDescriptor);
const inheritedParams = inheritedMetadata[methodName] || new Array(index + 1).fill(undefined);
if (inheritedParams.length) {
// First time applied to a method. This is the last parameter of the method
inheritedParams[index] = this.withTarget(this.inherit(inheritedParams[index]), target);
}
// Cache the index to help us position the next parameter
reflect_1.Reflector.defineMetadata(this.key + ':index', index - 1, target, methodName);
inheritedMetadata[methodName] = inheritedParams;
return inheritedMetadata;
}
mergeWithOwn(ownMetadata, target, methodName, methodDescriptor) {
if (ownMetadata == null)
ownMetadata = {};
let params = ownMetadata[methodName];
params = [this.spec].concat(params);
ownMetadata = ownMetadata || {};
const index = this.getParameterIndex(target, methodName, methodDescriptor);
let params = ownMetadata[methodName] || new Array(index + 1).fill(undefined);
params[index] = this.withTarget(this.inherit(params[index]), target);
ownMetadata[methodName] = params;
// Cache the index to help us position the next parameter
reflect_1.Reflector.defineMetadata(this.key + ':index', index - 1, target, methodName);
return ownMetadata;

@@ -420,0 +460,0 @@ }

@@ -12,5 +12,14 @@ /**

/**
* Inheritance will be honored
* Controls if inherited metadata will be honored. Default to `true`.
*/
allowsInheritance?: boolean;
allowInheritance?: boolean;
/**
* Controls if the value of `spec` argument will be cloned. Sometimes we
* use shared spec for the decoration, but the decorator function might need
* to mutate the object. Cloning the input spec makes it safe to use the same
* spec (`template`) to decorate different members.
*
* Default to `true`.
*/
cloneInputSpec?: boolean;
[name: string]: any;

@@ -217,5 +226,10 @@ }

export declare class MethodParameterDecoratorFactory<T> extends DecoratorFactory<T, MetadataMap<T[]>, MethodDecorator> {
protected mergeWithInherited(inheritedMetadata: MetadataMap<T[]>, target: Object, methodName?: string | symbol, methodDescriptor?: TypedPropertyDescriptor<any> | number): {
[x: string]: T[];
};
/**
* Find the corresponding parameter index for the decoration
* @param target
* @param methodName
* @param methodDescriptor
*/
private getParameterIndex(target, methodName?, methodDescriptor?);
protected mergeWithInherited(inheritedMetadata: MetadataMap<T[]>, target: Object, methodName?: string | symbol, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;
protected mergeWithOwn(ownMetadata: MetadataMap<T[]>, target: Object, methodName?: string | symbol, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;

@@ -222,0 +236,0 @@ create(): MethodDecorator;

@@ -45,6 +45,9 @@ "use strict";

this.options = options;
this.options = Object.assign({ allowInheritance: true }, options);
this.options = Object.assign({ allowInheritance: true, cloneInputSpec: true }, options);
if (this.options.cloneInputSpec) {
this.spec = DecoratorFactory.cloneDeep(spec);
}
}
allowInheritance() {
return this.options && this.options.allowInheritance;
return !!(this.options && this.options.allowInheritance);
}

@@ -229,5 +232,4 @@ /**

static cloneDeep(val) {
if (val === undefined) {
return {};
}
if (typeof val !== 'object')
return val;
return _.cloneDeepWith(val, v => {

@@ -237,2 +239,8 @@ // Do not clone functions

return v;
if (v &&
typeof v.constructor === 'function' &&
v.constructor.prototype === v) {
// Do not clone class prototype
return v;
}
return undefined;

@@ -280,2 +288,3 @@ });

mergeWithInherited(inheritedMetadata, target, propertyName, descriptorOrIndex) {
inheritedMetadata = inheritedMetadata || {};
const propertyMeta = this.withTarget(this.inherit(inheritedMetadata[propertyName]), target);

@@ -286,4 +295,3 @@ inheritedMetadata[propertyName] = propertyMeta;

mergeWithOwn(ownMetadata, target, propertyName, descriptorOrParameterIndex) {
if (ownMetadata == null)
ownMetadata = {};
ownMetadata = ownMetadata || {};
if (ownMetadata[propertyName] != null) {

@@ -315,2 +323,3 @@ const targetName = this.getTargetName(target, propertyName);

mergeWithInherited(inheritedMetadata, target, methodName, methodDescriptor) {
inheritedMetadata = inheritedMetadata || {};
const methodMeta = this.withTarget(this.inherit(inheritedMetadata[methodName]), target);

@@ -321,4 +330,3 @@ inheritedMetadata[methodName] = methodMeta;

mergeWithOwn(ownMetadata, target, methodName, methodDescriptor) {
if (ownMetadata == null)
ownMetadata = {};
ownMetadata = ownMetadata || {};
const methodMeta = ownMetadata[methodName];

@@ -362,2 +370,3 @@ if (this.getTarget(methodMeta) === target) {

mergeWithInherited(inheritedMetadata, target, methodName, parameterIndex) {
inheritedMetadata = inheritedMetadata || {};
const methodMeta = this.getOrInitMetadata(inheritedMetadata, target, methodName);

@@ -369,4 +378,3 @@ const index = parameterIndex;

mergeWithOwn(ownMetadata, target, methodName, parameterIndex) {
if (ownMetadata == null)
ownMetadata = {};
ownMetadata = ownMetadata || {};
// Find the method metadata

@@ -409,11 +417,43 @@ const methodMeta = this.getOrInitMetadata(ownMetadata, target, methodName);

class MethodParameterDecoratorFactory extends DecoratorFactory {
/**
* Find the corresponding parameter index for the decoration
* @param target
* @param methodName
* @param methodDescriptor
*/
getParameterIndex(target, methodName, methodDescriptor) {
const numOfParams = this.getNumberOfParameters(target, methodName);
// Fetch the cached parameter index
let index = reflect_1.Reflector.getOwnMetadata(this.key + ':index', target, methodName);
// Default to the last parameter
if (index == null)
index = numOfParams - 1;
if (index < 0) {
// Excessive decorations than the number of parameters detected
const method = this.getTargetName(target, methodName, methodDescriptor);
throw new Error(`The decorator is used more than ${numOfParams} time(s) on ${method}`);
}
return index;
}
mergeWithInherited(inheritedMetadata, target, methodName, methodDescriptor) {
return { [methodName]: [this.spec] };
inheritedMetadata = inheritedMetadata || {};
const index = this.getParameterIndex(target, methodName, methodDescriptor);
const inheritedParams = inheritedMetadata[methodName] || new Array(index + 1).fill(undefined);
if (inheritedParams.length) {
// First time applied to a method. This is the last parameter of the method
inheritedParams[index] = this.withTarget(this.inherit(inheritedParams[index]), target);
}
// Cache the index to help us position the next parameter
reflect_1.Reflector.defineMetadata(this.key + ':index', index - 1, target, methodName);
inheritedMetadata[methodName] = inheritedParams;
return inheritedMetadata;
}
mergeWithOwn(ownMetadata, target, methodName, methodDescriptor) {
if (ownMetadata == null)
ownMetadata = {};
let params = ownMetadata[methodName];
params = [this.spec].concat(params);
ownMetadata = ownMetadata || {};
const index = this.getParameterIndex(target, methodName, methodDescriptor);
let params = ownMetadata[methodName] || new Array(index + 1).fill(undefined);
params[index] = this.withTarget(this.inherit(params[index]), target);
ownMetadata[methodName] = params;
// Cache the index to help us position the next parameter
reflect_1.Reflector.defineMetadata(this.key + ':index', index - 1, target, methodName);
return ownMetadata;

@@ -420,0 +460,0 @@ }

{
"name": "@loopback/metadata",
"version": "4.0.0-alpha.2",
"version": "4.0.0-alpha.3",
"description": "LoopBack's metadata utilities for reflection and decoration",

@@ -15,3 +15,3 @@ "engines": {

"build:apidocs": "lb-apidocs",
"clean": "rm -rf loopback-metadata*.tgz dist* package",
"clean": "lb-clean loopback-metadata*.tgz dist dist6 package api-docs",
"prepare": "npm run build && npm run build:apidocs",

@@ -32,3 +32,3 @@ "pretest": "npm run build:current",

"@loopback/build": "^4.0.0-alpha.6",
"@loopback/testlab": "^4.0.0-alpha.15",
"@loopback/testlab": "^4.0.0-alpha.17",
"@types/debug": "0.0.30",

@@ -35,0 +35,0 @@ "@types/lodash": "^4.14.87"

@@ -207,2 +207,13 @@ # @loopback/metadata

## Decorator options
An object of type `DecoratorOptions` can be passed in to create decorator
functions. There are two flags for the options:
- allowInheritance: Controls if inherited metadata will be honored. Default to `true`.
- cloneInputSpec: Controls if the value of `spec` argument will be cloned.
Sometimes we use shared spec for the decoration, but the decorator function
might need to mutate the object. Cloning the input spec makes it safe to use
the same spec (`template`) to decorate different members. Default to `true`.
## Customize inheritance of metadata

@@ -209,0 +220,0 @@

@@ -25,5 +25,14 @@ // Copyright IBM Corp. 2013,2017. All Rights Reserved.

/**
* Inheritance will be honored
* Controls if inherited metadata will be honored. Default to `true`.
*/
allowsInheritance?: boolean;
allowInheritance?: boolean;
/**
* Controls if the value of `spec` argument will be cloned. Sometimes we
* use shared spec for the decoration, but the decorator function might need
* to mutate the object. Cloning the input spec makes it safe to use the same
* spec (`template`) to decorate different members.
*
* Default to `true`.
*/
cloneInputSpec?: boolean;
[name: string]: any;

@@ -85,7 +94,13 @@ }

) {
this.options = Object.assign({allowInheritance: true}, options);
this.options = Object.assign(
{allowInheritance: true, cloneInputSpec: true},
options,
);
if (this.options.cloneInputSpec) {
this.spec = DecoratorFactory.cloneDeep(spec);
}
}
protected allowInheritance(): boolean {
return this.options && this.options.allowInheritance;
return !!(this.options && this.options.allowInheritance);
}

@@ -296,8 +311,14 @@

static cloneDeep<T>(val: T): T {
if (val === undefined) {
return {} as T;
}
if (typeof val !== 'object') return val;
return _.cloneDeepWith(val, v => {
// Do not clone functions
if (typeof v === 'function') return v;
if (
v &&
typeof v.constructor === 'function' &&
v.constructor.prototype === v
) {
// Do not clone class prototype
return v;
}
return undefined;

@@ -369,2 +390,3 @@ });

) {
inheritedMetadata = inheritedMetadata || {};
const propertyMeta: T = this.withTarget(

@@ -384,3 +406,3 @@ <T>this.inherit(inheritedMetadata[propertyName!]),

) {
if (ownMetadata == null) ownMetadata = {};
ownMetadata = ownMetadata || {};
if (ownMetadata[propertyName!] != null) {

@@ -430,2 +452,3 @@ const targetName = this.getTargetName(target, propertyName);

) {
inheritedMetadata = inheritedMetadata || {};
const methodMeta = this.withTarget(

@@ -445,3 +468,3 @@ <T>this.inherit(inheritedMetadata[methodName!]),

) {
if (ownMetadata == null) ownMetadata = {};
ownMetadata = ownMetadata || {};
const methodMeta = ownMetadata[methodName!];

@@ -513,2 +536,3 @@ if (this.getTarget(methodMeta) === target) {

) {
inheritedMetadata = inheritedMetadata || {};
const methodMeta = this.getOrInitMetadata(

@@ -533,3 +557,3 @@ inheritedMetadata,

) {
if (ownMetadata == null) ownMetadata = {};
ownMetadata = ownMetadata || {};
// Find the method metadata

@@ -591,2 +615,32 @@ const methodMeta = this.getOrInitMetadata(ownMetadata, target, methodName);

> {
/**
* Find the corresponding parameter index for the decoration
* @param target
* @param methodName
* @param methodDescriptor
*/
private getParameterIndex(
target: Object,
methodName?: string | symbol,
methodDescriptor?: TypedPropertyDescriptor<any> | number,
) {
const numOfParams = this.getNumberOfParameters(target, methodName);
// Fetch the cached parameter index
let index = Reflector.getOwnMetadata(
this.key + ':index',
target,
methodName,
);
// Default to the last parameter
if (index == null) index = numOfParams - 1;
if (index < 0) {
// Excessive decorations than the number of parameters detected
const method = this.getTargetName(target, methodName, methodDescriptor);
throw new Error(
`The decorator is used more than ${numOfParams} time(s) on ${method}`,
);
}
return index;
}
protected mergeWithInherited(

@@ -598,3 +652,23 @@ inheritedMetadata: MetadataMap<T[]>,

) {
return {[methodName!]: [this.spec]};
inheritedMetadata = inheritedMetadata || {};
const index = this.getParameterIndex(target, methodName, methodDescriptor);
const inheritedParams =
inheritedMetadata[methodName!] || new Array(index + 1).fill(undefined);
if (inheritedParams.length) {
// First time applied to a method. This is the last parameter of the method
inheritedParams[index] = this.withTarget(
<T>this.inherit(inheritedParams[index]),
target,
);
}
// Cache the index to help us position the next parameter
Reflector.defineMetadata(
this.key + ':index',
index - 1,
target,
methodName,
);
inheritedMetadata[methodName!] = inheritedParams;
return inheritedMetadata;
}

@@ -608,6 +682,16 @@

) {
if (ownMetadata == null) ownMetadata = {};
let params = ownMetadata[methodName!];
params = [this.spec].concat(params);
ownMetadata = ownMetadata || {};
const index = this.getParameterIndex(target, methodName, methodDescriptor);
let params =
ownMetadata[methodName!] || new Array(index + 1).fill(undefined);
params[index] = this.withTarget(<T>this.inherit(params[index]), target);
ownMetadata[methodName!] = params;
// Cache the index to help us position the next parameter
Reflector.defineMetadata(
this.key + ':index',
index - 1,
target,
methodName,
);
return ownMetadata;

@@ -614,0 +698,0 @@ }

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc