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 0.3.1 to 0.4.0

19

CHANGELOG.md

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

<a name="0.4.0"></a>
# [0.4.0](https://github.com/strongloop/loopback-next/compare/@loopback/metadata@0.3.1...@loopback/metadata@0.4.0) (2018-03-29)
### Bug Fixes
* **metadata:** refine clone of decoration spec ([544052e](https://github.com/strongloop/loopback-next/commit/544052e))
### BREAKING CHANGES
* **metadata:** instances of user-defined classes are not cloned any more.
See https://github.com/strongloop/loopback-next/issues/1182. The root
cause is that DataSource instances are cloned incorrectly.
<a name="0.3.1"></a>

@@ -8,0 +27,0 @@ ## [0.3.1](https://github.com/strongloop/loopback-next/compare/@loopback/metadata@0.3.0...@loopback/metadata@0.3.1) (2018-03-23)

3

dist/src/decorator-factory.d.ts

@@ -160,3 +160,4 @@ /**

protected static _createDecorator<T, M extends T | MetadataMap<T> | MetadataMap<T[]>, D extends DecoratorType>(key: string, spec: T, options?: DecoratorOptions): D;
static cloneDeep<T>(val: T): T;
private static _cloneableTypes;
static cloneDeep<V>(val: Readonly<V>): V;
}

@@ -163,0 +164,0 @@ /**

@@ -140,2 +140,4 @@ "use strict";

enumerable: false,
// Make sure it won't be redefined on the same object
configurable: false,
});

@@ -240,10 +242,10 @@ }

return _.cloneDeepWith(val, v => {
// Do not clone functions
if (typeof v === 'function')
if (typeof v !== 'object')
return v;
if (v &&
typeof v.constructor === 'function' &&
v.constructor.prototype === v) {
// Do not clone class prototype
if (v == null)
return v;
if (v.constructor != null &&
!DecoratorFactory._cloneableTypes.includes(v.constructor)) {
// Do not clone instances of classes/constructors, such as Date
return v;
}

@@ -258,2 +260,22 @@ return undefined;

DecoratorFactory.TARGET = '__decoratorTarget';
// See https://github.com/lodash/lodash/blob/master/.internal/baseClone.js
DecoratorFactory._cloneableTypes = [
Object,
Array,
Set,
Map,
RegExp,
Date,
Buffer,
ArrayBuffer,
Float32Array,
Float64Array,
Int8Array,
Int16Array,
Int32Array,
Uint8Array,
Uint8ClampedArray,
Uint16Array,
Uint32Array,
];
exports.DecoratorFactory = DecoratorFactory;

@@ -260,0 +282,0 @@ /**

{
"name": "@loopback/metadata",
"version": "0.3.1",
"version": "0.4.0",
"description": "LoopBack's metadata utilities for reflection and decoration",

@@ -28,4 +28,4 @@ "engines": {

"devDependencies": {
"@loopback/build": "^0.3.3",
"@loopback/testlab": "^0.4.1",
"@loopback/build": "^0.4.0",
"@loopback/testlab": "^0.5.0",
"@types/debug": "^0.0.30",

@@ -32,0 +32,0 @@ "@types/lodash": "^4.14.106"

# @loopback/metadata
This module contains utilities to help developers implement [TypeScript decorators](https://www.typescriptlang.org/docs/handbook/decorators.html), define/merge
metadata, and inspect metadata.
This module contains utilities to help developers implement
[TypeScript decorators](https://www.typescriptlang.org/docs/handbook/decorators.html),
define/merge metadata, and inspect metadata.
* Reflector: Wrapper of
- Reflector: Wrapper of
[reflect-metadata](https://github.com/rbuckton/reflect-metadata)
* Decorator factories: A set of factories for class/method/property/parameter
- Decorator factories: A set of factories for class/method/property/parameter
decorators to apply metadata to a given class and its static or instance
members.
* MetadataInspector: High level APIs to inspect a class and/or its members to
- MetadataInspector: High level APIs to inspect a class and/or its members to
get metadata applied by decorators.

@@ -139,3 +140,4 @@

Now we can use `@myParameterDecorator` to add metadata to a parameter as follows:
Now we can use `@myParameterDecorator` to add metadata to a parameter as
follows:

@@ -187,4 +189,4 @@ ```ts

Now we can use `@myMethodParameterDecorator` to add metadata to a parameter
as follows:
Now we can use `@myMethodParameterDecorator` to add metadata to a parameter as
follows:

@@ -195,6 +197,3 @@ ```ts

@myMethodParameterDecorator({name: 'y'})
myMethod(
x: number,
y: number,
) {}
myMethod(x: number, y: number) {}
}

@@ -216,7 +215,8 @@ ```

- allowInheritance: Controls if inherited metadata will be honored. Default to `true`.
- 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`.
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`.

@@ -227,102 +227,102 @@ ### Customize inheritance of metadata

1. If the metadata is an object, we merge the `spec` argument from the decorator
function into the inherited value from base classes. For metadata of array and
other primitive types, the `spec` argument is used if provided.
1. If the metadata is an object, we merge the `spec` argument from the
decorator function into the inherited value from base classes. For metadata
of array and other primitive types, the `spec` argument is used if provided.
- We can override `inherit` method of the decorator factory to customize
how to resolve `spec` against the inherited metadata. For example:
- We can override `inherit` method of the decorator factory to customize how
to resolve `spec` against the inherited metadata. For example:
```ts
protected inherit(inheritedMetadata: T | undefined | null): T {
// Ignore the inherited metadata
return this.spec;
}
```
```ts
protected inherit(inheritedMetadata: T | undefined | null): T {
// Ignore the inherited metadata
return this.spec;
}
```
2. Method/property/parameter level metadata is applied to the class or its
prototype as a map keyed method/property names. We think this approach is better
than keeping metadata at method/property level as it's not easy to inspect a
class to find static/instance methods and properties with decorations. The
metadata for a class is illustrated below:
prototype as a map keyed method/property names. We think this approach is
better than keeping metadata at method/property level as it's not easy to
inspect a class to find static/instance methods and properties with
decorations. The metadata for a class is illustrated below:
- MyClass (the constructor function itself)
- MyClass (the constructor function itself)
```ts
{
// Class level metadata
'my-class-decorator-key': MyClassMetadata,
// Static method (including the constructor) parameter metadata
'my-static-parameter-decorator-key': {
'': [MyConstructorParameterMetadata], // Constructor parameter metadata
'myStaticMethod1': [MyStaticMethodParameterMetadata],
'myStaticMethod2': [MyStaticMethodParameterMetadata],
},
// Static method metadata
'my-static-method-decorator-key': {
'myStaticMethod1': MyStaticMethodMetadata,
'myStaticMethod2': MyStaticMethodMetadata,
},
// Static property metadata
'my-static-property-decorator-key': {
'myStaticMethod1': MyStaticPropertyMetadata,
'myStaticMethod1': MyStaticPropertyMetadata,
}
}
```
```ts
{
// Class level metadata
'my-class-decorator-key': MyClassMetadata,
// Static method (including the constructor) parameter metadata
'my-static-parameter-decorator-key': {
'': [MyConstructorParameterMetadata], // Constructor parameter metadata
'myStaticMethod1': [MyStaticMethodParameterMetadata],
'myStaticMethod2': [MyStaticMethodParameterMetadata],
},
// Static method metadata
'my-static-method-decorator-key': {
'myStaticMethod1': MyStaticMethodMetadata,
'myStaticMethod2': MyStaticMethodMetadata,
},
// Static property metadata
'my-static-property-decorator-key': {
'myStaticMethod1': MyStaticPropertyMetadata,
'myStaticMethod1': MyStaticPropertyMetadata,
}
}
```
- MyClass.prototype
- MyClass.prototype
```ts
{
// Instance method parameter metadata
'my-instance-parameter-decorator-key': {
'myMethod1': [MyMethodParameterMetadata],
'myMethod2': [MyMethodParameterMetadata],
},
// Instance method metadata
'my-instance-method-decorator-key': {
'myMethod1': MyMethodMetadata,
'myMethod2': MyMethodMetadata,
},
// Instance property metadata
'my-instance-property-decorator-key': {
'myProperty1': MyPropertyMetadata,
'myProperty2': MyPropertyMetadata,
}
}
```
```ts
{
// Instance method parameter metadata
'my-instance-parameter-decorator-key': {
'myMethod1': [MyMethodParameterMetadata],
'myMethod2': [MyMethodParameterMetadata],
},
// Instance method metadata
'my-instance-method-decorator-key': {
'myMethod1': MyMethodMetadata,
'myMethod2': MyMethodMetadata,
},
// Instance property metadata
'my-instance-property-decorator-key': {
'myProperty1': MyPropertyMetadata,
'myProperty2': MyPropertyMetadata,
}
}
```
The following methods in `DecoratorFactory` allow subclasses to customize how
to merge the `spec` with existing metadata for a class, methods, properties, and
method parameters. Please note `M` is a map for methods/properties/parameters.
The following methods in `DecoratorFactory` allow subclasses to customize how to
merge the `spec` with existing metadata for a class, methods, properties, and
method parameters. Please note `M` is a map for methods/properties/parameters.
```ts
protected mergeWithInherited(
inheritedMetadata: M,
target: Object,
member?: string | symbol,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
): M {
// ...
}
```ts
protected mergeWithInherited(
inheritedMetadata: M,
target: Object,
member?: string | symbol,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
): M {
// ...
}
protected mergeWithOwn(
ownMetadata: M,
target: Object,
member?: string | symbol,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
): M {
// ...
}
```
protected mergeWithOwn(
ownMetadata: M,
target: Object,
member?: string | symbol,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
): M {
// ...
}
```
3. The default implementation throws errors if the same decorator function is applied
to a given target member (class/method/property/parameter) more than once.
For example, the following usage will report an error at runtime.
3. The default implementation throws errors if the same decorator function is
applied to a given target member (class/method/property/parameter) more than
once. For example, the following usage will report an error at runtime.
```ts
@myClassDecorator({name: 'my-controller'})
@myClassDecorator({name: 'your-controller'})
class MyController {}
```
```ts
@myClassDecorator({name: 'my-controller'})
@myClassDecorator({name: 'your-controller'})
class MyController {}
```

@@ -345,3 +345,3 @@ ### Inspect metadata

## Inspect own metadata of a class
### Inspect own metadata of a class

@@ -399,23 +399,22 @@ ```ts

const allParamsForMyMethod =
MetadataInspector.getAllParameterMetaData<MyParameterMetadata>(
'my-parameter-decorator-key',
MyController.prototype, // Use MyController for static methods,
'myMethod',
);
const allParamsForMyMethod = MetadataInspector.getAllParameterMetaData<
MyParameterMetadata
>(
'my-parameter-decorator-key',
MyController.prototype, // Use MyController for static methods,
'myMethod',
);
const firstParamForMyMethod =
MetadataInspector.getMyParameterMetaData<MyParameterMetadata>(
'my-parameter-decorator-key',
MyController.prototype, // Use MyController for static methods
'myMethod',
0, // parameter index
);
const firstParamForMyMethod = MetadataInspector.getMyParameterMetaData<
MyParameterMetadata
>(
'my-parameter-decorator-key',
MyController.prototype, // Use MyController for static methods
'myMethod',
0, // parameter index
);
const allParamsForConstructor =
MetadataInspector.getAllParameterMetaData<MyParameterMetadata>(
'my-parameter-decorator-key',
MyController,
'',
);
const allParamsForConstructor = MetadataInspector.getAllParameterMetaData<
MyParameterMetadata
>('my-parameter-decorator-key', MyController, '');
```

@@ -446,5 +445,5 @@

```sh
npm install --save @loopback/metadata
```
$ npm install --save @loopback/metadata
```

@@ -451,0 +450,0 @@ ## Contributions

@@ -193,2 +193,4 @@ // Copyright IBM Corp. 2017,2018. All Rights Reserved.

enumerable: false,
// Make sure it won't be redefined on the same object
configurable: false,
});

@@ -318,13 +320,33 @@ }

static cloneDeep<T>(val: T): T {
// See https://github.com/lodash/lodash/blob/master/.internal/baseClone.js
private static _cloneableTypes = [
Object,
Array,
Set,
Map,
RegExp,
Date,
Buffer,
ArrayBuffer,
Float32Array,
Float64Array,
Int8Array,
Int16Array,
Int32Array,
Uint8Array,
Uint8ClampedArray,
Uint16Array,
Uint32Array,
];
static cloneDeep<V>(val: Readonly<V>): V {
if (typeof val !== 'object') return val;
return _.cloneDeepWith(val, v => {
// Do not clone functions
if (typeof v === 'function') return v;
if (typeof v !== 'object') return v;
if (v == null) return v;
if (
v &&
typeof v.constructor === 'function' &&
v.constructor.prototype === v
v.constructor != null &&
!DecoratorFactory._cloneableTypes.includes(v.constructor)
) {
// Do not clone class prototype
// Do not clone instances of classes/constructors, such as Date
return v;

@@ -331,0 +353,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

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