Socket
Socket
Sign inDemoInstall

@loopback/metadata

Package Overview
Dependencies
Maintainers
11
Versions
165
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.0.0-alpha.10 to 4.0.0

dist/decorator-factory.d.ts

23

dist/index.d.ts

@@ -1,1 +0,22 @@

export * from './src';
/**
* A package with utilities to help developers implement
* {@link https://www.typescriptlang.org/docs/handbook/decorators.html |TypeScript decorators},
* define/merge metadata, and inspect metadata.
*
* @remarks
* Utilities:
*
* - Reflector: Wrapper of
* {@link https://github.com/rbuckton/reflect-metadata | reflect-metadata}.
* - 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
* get metadata applied by decorators.
*
* @packageDocumentation
*/
export * from './decorator-factory';
export * from './inspector';
export * from './reflect';
export * from './types';

31

dist/index.js
"use strict";
// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Copyright IBM Corp. 2017,2020. All Rights Reserved.
// Node module: @loopback/metadata
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
// DO NOT EDIT THIS FILE
// Add any aditional (re)exports to src/index.ts instead.
__export(require("./src"));
const tslib_1 = require("tslib");
/**
* A package with utilities to help developers implement
* {@link https://www.typescriptlang.org/docs/handbook/decorators.html |TypeScript decorators},
* define/merge metadata, and inspect metadata.
*
* @remarks
* Utilities:
*
* - Reflector: Wrapper of
* {@link https://github.com/rbuckton/reflect-metadata | reflect-metadata}.
* - 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
* get metadata applied by decorators.
*
* @packageDocumentation
*/
(0, tslib_1.__exportStar)(require("./decorator-factory"), exports);
(0, tslib_1.__exportStar)(require("./inspector"), exports);
(0, tslib_1.__exportStar)(require("./reflect"), exports);
(0, tslib_1.__exportStar)(require("./types"), exports);
//# sourceMappingURL=index.js.map
{
"name": "@loopback/metadata",
"version": "4.0.0-alpha.10",
"description": "LoopBack's metadata utilities for reflection and decoration",
"description": "Utilities to help developers implement TypeScript decorators, define/merge metadata, and inspect metadata",
"version": "4.0.0",
"keywords": [
"LoopBack",
"Decorators",
"Reflect"
],
"license": "MIT",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": "IBM Corp.",
"copyright.owner": "IBM Corp.",
"repository": {
"type": "git",
"url": "https://github.com/loopbackio/loopback-next.git",
"directory": "packages/metadata"
},
"engines": {
"node": ">=8"
"node": "12 || 14 || 16 || 17"
},
"scripts": {
"acceptance": "lb-mocha \"DIST/test/acceptance/**/*.js\"",
"build": "lb-tsc es2017",
"build:apidocs": "lb-apidocs",
"clean": "lb-clean loopback-metadata*.tgz dist package api-docs",
"prepublishOnly": "npm run build && npm run build:apidocs",
"acceptance": "lb-mocha \"dist/__tests__/acceptance/**/*.js\"",
"build": "lb-tsc",
"clean": "lb-clean loopback-metadata*.tgz dist *.tsbuildinfo package",
"pretest": "npm run build",
"test": "lb-mocha \"DIST/test/unit/**/*.js\" \"DIST/test/acceptance/**/*.js\"",
"unit": "lb-mocha \"DIST/test/unit/**/*.js\"",
"test": "lb-mocha \"dist/__tests__/**/*.js\"",
"unit": "lb-mocha \"dist/__tests__/unit/**/*.js\"",
"verify": "npm pack && tar xf loopback-metadata*.tgz && tree package && npm run clean"
},
"author": "IBM",
"copyright.owner": "IBM Corp.",
"license": "MIT",
"dependencies": {
"debug": "^3.1.0",
"lodash": "^4.17.4",
"reflect-metadata": "^0.1.10"
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@loopback/build": "^4.0.0-alpha.13",
"@loopback/testlab": "^4.0.0-alpha.24",
"@types/debug": "^0.0.30",
"@types/lodash": "^4.14.96"
},
"keywords": [
"LoopBack",
"Decorators",
"Reflect"
],
"files": [
"README.md",
"index.js",
"index.d.ts",
"dist/src",
"api-docs",
"src"
"dist",
"src",
"!*/__tests__"
],
"publishConfig": {
"access": "public"
"dependencies": {
"debug": "^4.3.2",
"lodash": "^4.17.21",
"reflect-metadata": "^0.1.13",
"tslib": "^2.3.1"
},
"repository": {
"type": "git",
"url": "https://github.com/strongloop/loopback-next.git"
}
"devDependencies": {
"@loopback/build": "^8.0.0",
"@loopback/eslint-config": "^12.0.0",
"@loopback/testlab": "^4.0.0",
"@types/debug": "^4.1.7",
"@types/lodash": "^4.14.176",
"@types/node": "^10.17.60"
},
"gitHead": "00a62f630c19341ce399cec3a45563b1ead6e3b8"
}
# @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.
# Usage
## Basic Use
## To create a class decorator
### To create a class decorator

@@ -30,2 +31,3 @@ ```ts

spec,
{decoratorName: '@myClassDecorator'},
);

@@ -35,3 +37,3 @@ }

Alternativley, we can instantiate the factory and create a decorator:
Alternatively, we can instantiate the factory and create a decorator:

@@ -55,3 +57,3 @@ ```ts

## To create a method decorator
### To create a method decorator

@@ -91,5 +93,113 @@ ```ts

## To create a property decorator
### To create a decorator that can be used multiple times on a single method
Instead of a single immutable object to be merged, the
`MethodMultiDecoratorFactory` reduced parameters into a flat array of items.
When fetching the metadata later, you will receive it as an array.
```ts
import {MethodMultiDecoratorFactory} from '@loopback/metadata';
function myMultiMethodDecorator(spec: object): MethodDecorator {
return MethodMultiDecoratorFactory.createDecorator<object>(
'metadata-key-for-my-method-multi-decorator',
spec,
);
}
```
Now, you can use it multiple times on a method:
```ts
class MyController {
@myMultiMethodDecorator({x: 1})
@myMultiMethodDecorator({y: 2})
@myMultiMethodDecorator({z: 3})
public point() {}
}
class MyOtherController {
@myMultiMethodDecorator([{x: 1}, {y: 2}, {z: 3}])
public point() {}
}
```
And when you access this data:
```ts
const arrayOfSpecs = MetadataInspector.getMethodMetadata<object>(
'metadata-key-for-my-method-multi-decorator',
constructor.prototype,
op,
);
// [{z: 3}, {y: 2}, {x: 1}]
```
Typescript
[applies decorators in reverse order](https://www.typescriptlang.org/docs/handbook/decorators.html)
per class, from the parent down. The metadata array resurned by `getOwnMetadata`
will be in this order:
```ts
class Parent {
@myMultiMethodDecorator('A') // second
@myMultiMethodDecorator('B') // first
public greet() {}
}
class Child extends Parent {
@myMultiMethodDecorator(['C', 'D']) // [third, fourth]
public greet() {}
}
class Grandchild extends Child {
@myMultiMethodDecorator('E') // sixth
@myMultiMethodDecorator('F') // fifth
public greet() {}
}
// getMethodMetadata = ['B', 'A', 'C', 'D', 'F', 'E']
```
You can also create a decorator that takes an object that can contain an array:
```ts
interface Point {
x?: number;
y?: number;
z?: number;
}
interface GeometryMetadata {
points: Point[];
}
function geometry(...points: Point[]): MethodDecorator {
return MethodMultiDecoratorFactory.createDecorator<GeometryMetadata>(
'metadata-key-for-my-method-multi-decorator',
points,
);
}
class MyGeoController {
@geometry({x: 1})
@geometry({x: 2}, {y: 3})
@geometry({z: 5})
public abstract() {}
}
const arrayOfSpecs = MetadataInspector.getMethodMetadata<GeometryMetadata>(
'metadata-key-for-my-method-multi-decorator',
constructor.prototype,
op,
);
// [
// { points: [{x: 1}]},
// { points: [{x:2}, {y:3}]},
// { points: [{z: 5}]},
// ]
```
### To create a property decorator
```ts
import {PropertyDecoratorFactory} from '@loopback/metadata';

@@ -102,3 +212,3 @@

function myPropertydDecorator(spec: MyPropertyMetadata): PropertyDecorator {
function myPropertyDecorator(spec: MyPropertyMetadata): PropertyDecorator {
return PropertyDecoratorFactory.createDecorator<MyPropertyMetadata>(

@@ -126,3 +236,3 @@ 'metadata-key-for-my-property-decorator',

## To create a parameter decorator
### To create a parameter decorator

@@ -137,3 +247,3 @@ ```ts

function myParameterdDecorator(spec: MyParameterMetadata): ParameterDecorator {
function myParameterDecorator(spec: MyParameterMetadata): ParameterDecorator {
return ParameterDecoratorFactory.createDecorator<MyParameterMetadata>(

@@ -146,3 +256,4 @@ 'metadata-key-for-my-parameter-decorator',

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:

@@ -152,20 +263,14 @@ ```ts

constructor(
@myParameterDecorator({name: 'logging-prefix'})
public prefix: string,
@myParameterDecorator({name: 'logging-level'})
public level: number,
@myParameterDecorator({name: 'logging-prefix'}) public prefix: string,
@myParameterDecorator({name: 'logging-level'}) public level: number,
) {}
myMethod(
@myParameterDecorator({name: 'x'})
x: number,
@myParameterDecorator({name: 'y'})
y: number,
@myParameterDecorator({name: 'x'}) x: number,
@myParameterDecorator({name: 'y'}) y: number,
) {}
static myStaticMethod(
@myParameterDecorator({name: 'a'})
a: string,
@myParameterDecorator({name: 'b'})
b: string,
@myParameterDecorator({name: 'a'}) a: string,
@myParameterDecorator({name: 'b'}) b: string,
) {}

@@ -175,3 +280,3 @@ }

## To create method decorator for parameters
### To create method decorator for parameters

@@ -196,4 +301,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:

@@ -204,6 +309,4 @@ ```ts

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

@@ -214,8 +317,8 @@

1. Method decorators cannot be applied to a constructor
2. Method decorators depends on the positions to match parameters
1. Method decorators cannot be applied to a constructor
2. Method decorators depends on the positions to match parameters
We recommend that `ParameterDecorator` be used instead.
## Decorator options
### Decorator options

@@ -225,114 +328,117 @@ An object of type `DecoratorOptions` can be passed in to create decorator

- 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`.
- decoratorName: Name for the decorator such as `@inject` for error and
debugging messages.
## Customize inheritance of metadata
### Customize inheritance of metadata
By default, the decorator factories allow inheritance with the following rules:
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:
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:
- MyClass (the constructor function itself)
```ts
{
// Class level metadata
'my-class-decorator-key': MyClassMetadata,
// Static method (including the construtor) 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,
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,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
): M {
// ...
}
```
3. The default implemention 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 {}
```
## Inspect metadata
### Inspect metadata

@@ -342,3 +448,3 @@ `MetadataInspector` provides API to inspect metadata from a class and its

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

@@ -354,3 +460,3 @@ ```ts

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

@@ -369,3 +475,3 @@ ```ts

## Inspect metadata of a method
### Inspect metadata of a method

@@ -387,3 +493,3 @@ ```ts

## Inspect metadata of a property
### Inspect metadata of a property

@@ -405,3 +511,3 @@ ```ts

## Inspect metadata of method parameters
### Inspect metadata of method parameters

@@ -434,5 +540,24 @@ ```ts

## Inspect design-time metadata of properties/methods
### Use strong-typed metadata access key
You can use MetadataAccessor to provide type checks for metadata access via
keys. For example,
```ts
const CLASS_KEY = MetadataAccessor.create<MyClassMetadata, ClassDecorator>(
'my-class-decorator-key',
);
// Create a class decorator with the key
const myClassDecorator = ClassDecoratorFactory.createDecorator(CLASS_KEY);
// Inspect a class with the key
const myClassMeta = MetadataInspector.getClassMetaData(CLASS_KEY, MyController);
```
Please note MetadataKey can be an instance of MetadataAccessor or a string.
### Inspect design-time metadata of properties/methods
```ts
import {MetadataInspector} from '@loopback/metadata';

@@ -458,12 +583,10 @@

```sh
npm install --save @loopback/metadata
```
$ npm install --save @loopback/metadata
```
## Contributions
IBM/StrongLoop is an active supporter of open source and welcomes contributions
to our projects as well as those of the Node.js community in general. For more
information on how to contribute please refer to the
[Contribution Guide](https://loopback.io/doc/en/contrib/index.html).
- [Guidelines](https://github.com/loopbackio/loopback-next/blob/master/docs/CONTRIBUTING.md)
- [Join the team](https://github.com/loopbackio/loopback-next/issues/110)

@@ -477,3 +600,3 @@ ## Tests

See
[all contributors](https://github.com/strongloop/loopback-next/graphs/contributors).
[all contributors](https://github.com/loopbackio/loopback-next/graphs/contributors).

@@ -480,0 +603,0 @@ ## License

@@ -1,2 +0,2 @@

// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Copyright IBM Corp. 2017,2020. All Rights Reserved.
// Node module: @loopback/metadata

@@ -6,17 +6,11 @@ // This file is licensed under the MIT License.

import debugModule from 'debug';
import _ from 'lodash';
import {Reflector} from './reflect';
import * as _ from 'lodash';
import * as debugModule from 'debug';
import {DecoratorType, MetadataKey, MetadataMap} from './types';
const debug = debugModule('loopback:metadata:decorator');
// tslint:disable:no-any
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* An object mapping keys to corresponding metadata
*/
export interface MetadataMap<T> {
[propertyOrMethodName: string]: T;
}
/**
* Options for a decorator

@@ -38,2 +32,8 @@ */

cloneInputSpec?: boolean;
/**
* Name of the decorator for debugging purpose, such as `@inject`
*/
decoratorName?: string;
[name: string]: any;

@@ -43,11 +43,2 @@ }

/**
* Decorator function types
*/
export type DecoratorType =
| ClassDecorator
| PropertyDecorator
| MethodDecorator
| ParameterDecorator;
/**
* Base factory class for decorator functions

@@ -77,4 +68,6 @@ *

M extends T | MetadataMap<T> | MetadataMap<T[]>, // Type of the metadata
D extends DecoratorType // Type of the decorator
D extends DecoratorType, // Type of the decorator
> {
protected decoratorName: string;
/**

@@ -87,5 +80,5 @@ * A constant to reference the target of a decoration

* Construct a new class decorator factory
* @param key Metadata key
* @param spec Metadata object from the decorator function
* @param options Options for the decorator. Default to
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator. Default to
* `{allowInheritance: true}` if not provided

@@ -96,8 +89,13 @@ */

protected spec: T,
protected options?: DecoratorOptions,
protected options: DecoratorOptions = {},
) {
this.options = Object.assign(
{allowInheritance: true, cloneInputSpec: true},
{
allowInheritance: true,
cloneInputSpec: true,
},
options,
);
const defaultDecoratorName = this.constructor.name.replace(/Factory$/, '');
this.decoratorName = this.options.decoratorName ?? defaultDecoratorName;
if (this.options.cloneInputSpec) {

@@ -109,3 +107,3 @@ this.spec = DecoratorFactory.cloneDeep(spec);

protected allowInheritance(): boolean {
return !!(this.options && this.options.allowInheritance);
return !!this.options?.allowInheritance;
}

@@ -118,3 +116,3 @@

*
* @param inheritedMetadata Metadata from base classes for the member
* @param inheritedMetadata - Metadata from base classes for the member
*/

@@ -124,3 +122,3 @@ protected inherit(inheritedMetadata: T | undefined | null): T {

if (inheritedMetadata == null) return this.spec;
if (this.spec == undefined) return inheritedMetadata;
if (this.spec == null) return inheritedMetadata;
if (typeof inheritedMetadata !== 'object') return this.spec;

@@ -135,16 +133,20 @@ if (Array.isArray(inheritedMetadata) || Array.isArray(this.spec)) {

/**
* Get the qualified name of a decoration target. For example:
* ```
* class MyClass
* MyClass.constructor[0] // First parameter of the constructor
* MyClass.myStaticProperty
* MyClass.myStaticMethod()
* MyClass.myStaticMethod[0] // First parameter of the myStaticMethod
* MyClass.prototype.myProperty
* MyClass.prototype.myMethod()
* MyClass.prototype.myMethod[1] // Second parameter of myMethod
* ```
* @param target Class or prototype of a class
* @param member Optional property/method name
* @param descriptorOrIndex Optional method descriptor or parameter index
* Get the qualified name of a decoration target.
*
* @remarks
*
* Example of target names:
*
* - class MyClass
* - MyClass.constructor[0] // First parameter of the constructor
* - MyClass.myStaticProperty
* - MyClass.myStaticMethod()
* - MyClass.myStaticMethod[0] // First parameter of the myStaticMethod
* - MyClass.prototype.myProperty
* - MyClass.prototype.myMethod()
* - MyClass.prototype.myMethod[1] // Second parameter of myMethod
*
* @param target - Class or prototype of a class
* @param member - Optional property/method name
* @param descriptorOrIndex - Optional method descriptor or parameter index
*/

@@ -163,10 +165,14 @@ static getTargetName(

}
if (member == null) member = 'constructor';
if (member == null || member === '') member = 'constructor';
const memberAccessor =
typeof member === 'symbol' ? '[' + member.toString() + ']' : '.' + member;
if (typeof descriptorOrIndex === 'number') {
// Parameter
name = `${name}.${member}[${descriptorOrIndex}]`;
name = `${name}${memberAccessor}[${descriptorOrIndex}]`;
} else if (descriptorOrIndex != null) {
name = `${name}.${member}()`;
name = `${name}${memberAccessor}()`;
} else {
name = `${name}.${member}`;
name = `${name}${memberAccessor}`;
}

@@ -178,7 +184,7 @@ return name;

* Get the number of parameters for a given constructor or method
* @param target Class or the prototype
* @param member Method name
* @param target - Class or the prototype
* @param member - Method name
*/
static getNumberOfParameters(target: Object, member?: string | symbol) {
if (target instanceof Function && !member) {
static getNumberOfParameters(target: Object, member?: string) {
if (typeof target === 'function' && !member) {
// constructor

@@ -188,3 +194,4 @@ return target.length;

// target[member] is a function
return (<{[methodName: string]: Function}>target)[member!].length;
const method = (<{[methodName: string]: Function}>target)[member!];
return method.length;
}

@@ -196,4 +203,4 @@ }

* it's an object
* @param spec Metadata spec
* @param target Target of the decoration. It is a class or the prototype of
* @param spec - Metadata spec
* @param target - Target of the decoration. It is a class or the prototype of
* a class.

@@ -207,2 +214,4 @@ */

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

@@ -215,3 +224,3 @@ }

* Get the optional decoration target of a given spec
* @param spec Metadata spec
* @param spec - Metadata spec
*/

@@ -235,6 +244,6 @@ getTarget(spec: T) {

*
* @param inheritedMetadata Metadata inherited from the base classes
* @param target Decoration target
* @param member Optional property or method
* @param descriptorOrIndex Optional parameter index or method descriptor
* @param inheritedMetadata - Metadata inherited from the base classes
* @param target - Decoration target
* @param member - Optional property or method
* @param descriptorOrIndex - Optional parameter index or method descriptor
*/

@@ -247,3 +256,5 @@ protected mergeWithInherited(

): M {
throw new Error('mergeWithInherited() is not implemented');
throw new Error(
`mergeWithInherited() is not implemented for ${this.decoratorName}`,
);
}

@@ -259,6 +270,6 @@

*
* @param ownMetadata Own Metadata exists locally on the target
* @param target Decoration target
* @param member Optional property or method
* @param descriptorOrIndex Optional parameter index or method descriptor
* @param ownMetadata - Own Metadata exists locally on the target
* @param target - Decoration target
* @param member - Optional property or method
* @param descriptorOrIndex - Optional parameter index or method descriptor
*/

@@ -271,6 +282,30 @@ protected mergeWithOwn(

): M {
throw new Error('mergeWithOwn() is not implemented');
throw new Error(
`mergeWithOwn() is not implemented for ${this.decoratorName}`,
);
}
/**
* Create an error to report if the decorator is applied to the target more
* than once
* @param target - Decoration target
* @param member - Optional property or method
* @param descriptorOrIndex - Optional parameter index or method descriptor
*/
protected duplicateDecorationError(
target: Object,
member?: string | symbol,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
) {
const targetName = DecoratorFactory.getTargetName(
target,
member,
descriptorOrIndex,
);
return new Error(
`${this.decoratorName} cannot be applied more than once on ${targetName}`,
);
}
/**
* Create a decorator function of the given type. Each sub class MUST

@@ -280,3 +315,3 @@ * implement this method.

create(): D {
throw new Error('create() is not implemented');
throw new Error(`create() is not implemented for ${this.decoratorName}`);
}

@@ -286,5 +321,5 @@

* Base implementation of the decorator function
* @param target Decorator target
* @param member Optional property or method
* @param descriptorOrIndex Optional method descriptor or parameter index
* @param target - Decorator target
* @param member - Optional property or method
* @param descriptorOrIndex - Optional method descriptor or parameter index
*/

@@ -326,26 +361,46 @@ protected decorate(

* Create a decorator function
* @param key Metadata key
* @param spec Metadata object from the decorator function
* @param options Options for the decorator
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
protected static _createDecorator<
T,
M extends T | MetadataMap<T> | MetadataMap<T[]>,
D extends DecoratorType
>(key: string, spec: T, options?: DecoratorOptions): D {
const inst = new this<T, M, D>(key, spec, options);
S,
MT extends S | MetadataMap<S> | MetadataMap<S[]>,
DT extends DecoratorType,
>(key: MetadataKey<S, DT>, spec: S, options?: DecoratorOptions): DT {
const inst = new this<S, MT, DT>(key.toString(), spec, options);
return inst.create();
}
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;

@@ -369,3 +424,3 @@ }

target: Object,
member?: string | symbol,
member?: string,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,

@@ -379,10 +434,7 @@ ) {

target: Object,
member?: string | symbol,
member?: string,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
) {
if (ownMetadata != null) {
throw new Error(
'Decorator cannot be applied more than once on ' +
DecoratorFactory.getTargetName(target),
);
throw this.duplicateDecorationError(target, member, descriptorOrIndex);
}

@@ -398,8 +450,12 @@ return this.withTarget(this.spec, target);

* Create a class decorator function
* @param key Metadata key
* @param spec Metadata object from the decorator function
* @param options Options for the decorator
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<T>(key: string, spec: T, options?: DecoratorOptions) {
return super._createDecorator<T, T, ClassDecorator>(key, spec, options);
static createDecorator<S>(
key: MetadataKey<S, ClassDecorator>,
spec: S,
options?: DecoratorOptions,
) {
return super._createDecorator<S, S, ClassDecorator>(key, spec, options);
}

@@ -419,3 +475,3 @@ }

target: Object,
propertyName?: string | symbol,
propertyName?: string,
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,

@@ -435,3 +491,3 @@ ) {

target: Object,
propertyName?: string | symbol,
propertyName?: string,
descriptorOrParameterIndex?: TypedPropertyDescriptor<any> | number,

@@ -441,5 +497,6 @@ ) {

if (ownMetadata[propertyName!] != null) {
const targetName = DecoratorFactory.getTargetName(target, propertyName);
throw new Error(
'Decorator cannot be applied more than once on ' + targetName,
throw this.duplicateDecorationError(
target,
propertyName,
descriptorOrParameterIndex,
);

@@ -458,8 +515,12 @@ }

* Create a property decorator function
* @param key Metadata key
* @param spec Metadata object from the decorator function
* @param options Options for the decorator
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<T>(key: string, spec: T, options?: DecoratorOptions) {
return super._createDecorator<T, MetadataMap<T>, PropertyDecorator>(
static createDecorator<S>(
key: MetadataKey<S, PropertyDecorator>,
spec: S,
options?: DecoratorOptions,
) {
return super._createDecorator<S, MetadataMap<S>, PropertyDecorator>(
key,

@@ -483,3 +544,3 @@ spec,

target: Object,
methodName?: string | symbol,
methodName?: string,
methodDescriptor?: TypedPropertyDescriptor<any> | number,

@@ -499,3 +560,3 @@ ) {

target: Object,
methodName?: string | symbol,
methodName?: string,
methodDescriptor?: TypedPropertyDescriptor<any> | number,

@@ -506,6 +567,3 @@ ) {

if (this.getTarget(methodMeta) === target) {
throw new Error(
'Decorator cannot be applied more than once on ' +
DecoratorFactory.getTargetName(target, methodName, methodDescriptor),
);
throw this.duplicateDecorationError(target, methodName, methodDescriptor);
}

@@ -527,8 +585,12 @@ // Set the method metadata

* Create a method decorator function
* @param key Metadata key
* @param spec Metadata object from the decorator function
* @param options Options for the decorator
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<T>(key: string, spec: T, options?: DecoratorOptions) {
return super._createDecorator<T, MetadataMap<T>, MethodDecorator>(
static createDecorator<S>(
key: MetadataKey<S, MethodDecorator>,
spec: S,
options?: DecoratorOptions,
) {
return super._createDecorator<S, MetadataMap<S>, MethodDecorator>(
key,

@@ -552,3 +614,3 @@ spec,

target: Object,
methodName?: string | symbol,
methodName?: string,
) {

@@ -570,3 +632,3 @@ const method = methodName ? methodName : '';

target: Object,
methodName?: string | symbol,
methodName?: string,
parameterIndex?: TypedPropertyDescriptor<any> | number,

@@ -591,3 +653,3 @@ ) {

target: Object,
methodName?: string | symbol,
methodName?: string,
parameterIndex?: TypedPropertyDescriptor<any> | number,

@@ -600,6 +662,3 @@ ) {

if (this.getTarget(methodMeta[index]) === target) {
throw new Error(
'Decorator cannot be applied more than once on ' +
DecoratorFactory.getTargetName(target, methodName, parameterIndex),
);
throw this.duplicateDecorationError(target, methodName, parameterIndex);
}

@@ -624,8 +683,12 @@ // Set the parameter metadata

* Create a parameter decorator function
* @param key Metadata key
* @param spec Metadata object from the decorator function
* @param options Options for the decorator
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<T>(key: string, spec: T, options?: DecoratorOptions) {
return super._createDecorator<T, MetadataMap<T[]>, ParameterDecorator>(
static createDecorator<S>(
key: MetadataKey<S, ParameterDecorator>,
spec: S,
options?: DecoratorOptions,
) {
return super._createDecorator<S, MetadataMap<S[]>, ParameterDecorator>(
key,

@@ -639,4 +702,7 @@ spec,

/**
* Factory for method level parameter decorator. For example, the following
* code uses `@param` to declare two parameters for `greet()`.
* Factory for method level parameter decorator.
*
* @example
* For example, the following code uses `@param` to declare two parameters for
* `greet()`.
* ```ts

@@ -663,3 +729,3 @@ * class MyController {

target: Object,
methodName?: string | symbol,
methodName?: string,
methodDescriptor?: TypedPropertyDescriptor<any> | number,

@@ -687,3 +753,3 @@ ) {

throw new Error(
`The decorator is used more than ${numOfParams} time(s) on ${method}`,
`${this.decoratorName} is used more than ${numOfParams} time(s) on ${method}`,
);

@@ -697,3 +763,3 @@ }

target: Object,
methodName?: string | symbol,
methodName?: string,
methodDescriptor?: TypedPropertyDescriptor<any> | number,

@@ -727,3 +793,3 @@ ) {

target: Object,
methodName?: string | symbol,
methodName?: string,
methodDescriptor?: TypedPropertyDescriptor<any> | number,

@@ -734,3 +800,3 @@ ) {

let params =
const params =
ownMetadata[methodName!] || new Array(index + 1).fill(undefined);

@@ -759,8 +825,12 @@ params[index] = this.withTarget(<T>this.inherit(params[index]), target);

* Create a method decorator function
* @param key Metadata key
* @param spec Metadata object from the decorator function
* @param options Options for the decorator
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<T>(key: string, spec: T, options?: DecoratorOptions) {
return super._createDecorator<T, MetadataMap<T[]>, MethodDecorator>(
static createDecorator<S>(
key: MetadataKey<S, MethodDecorator>,
spec: S,
options?: DecoratorOptions,
) {
return super._createDecorator<S, MetadataMap<S[]>, MethodDecorator>(
key,

@@ -772,1 +842,78 @@ spec,

}
/**
* Factory for an append-array of method-level decorators
* The `@response` metadata for a method is an array.
* Each item in the array should be a single value, containing
* a response code and a single spec or Model. This should allow:
*
* @example
* ```ts
* @response(200, MyFirstModel)
* @response(403, [NotAuthorizedReasonOne, NotAuthorizedReasonTwo])
* @response(404, NotFoundOne)
* @response(404, NotFoundTwo)
* @response(409, {schema: {}})
* public async myMethod() {}
* ```
*
* In the case that a ResponseObject is passed, it becomes the
* default for description/content, and if possible, further Models are
* incorporated as a `oneOf: []` array.
*
* In the case that a ReferenceObject is passed, it and it alone is used, since
* references can be external and we cannot `oneOf` their content.
*
* The factory creates and updates an array of items T[], and the getter
* provides the values as that array.
*/
export class MethodMultiDecoratorFactory<T> extends MethodDecoratorFactory<
T[]
> {
protected mergeWithInherited(
inheritedMetadata: MetadataMap<T[]>,
target: Object,
methodName?: string,
) {
inheritedMetadata = inheritedMetadata || {};
inheritedMetadata[methodName!] = this._mergeArray(
inheritedMetadata[methodName!],
this.withTarget(this.spec, target),
);
return inheritedMetadata;
}
protected mergeWithOwn(
ownMetadata: MetadataMap<T[]>,
target: Object,
methodName?: string,
methodDescriptor?: TypedPropertyDescriptor<any> | number,
) {
ownMetadata = ownMetadata || {};
ownMetadata[methodName!] = this._mergeArray(
ownMetadata[methodName!],
this.withTarget(this.spec, target),
);
return ownMetadata;
}
private _mergeArray(result: T[], methodMeta: T | T[]) {
if (!result) {
if (Array.isArray(methodMeta)) {
result = methodMeta;
} else {
result = [methodMeta];
}
} else {
if (Array.isArray(methodMeta)) {
result.push(...methodMeta);
} else {
result.push(methodMeta);
}
}
return result;
}
}

@@ -1,2 +0,2 @@

// Copyright IBM Corp. 2017. All Rights Reserved.
// Copyright IBM Corp. 2017,2020. All Rights Reserved.
// Node module: @loopback/metadata

@@ -6,4 +6,24 @@ // This file is licensed under the MIT License.

export * from './reflect';
/**
* A package with utilities to help developers implement
* {@link https://www.typescriptlang.org/docs/handbook/decorators.html |TypeScript decorators},
* define/merge metadata, and inspect metadata.
*
* @remarks
* Utilities:
*
* - Reflector: Wrapper of
* {@link https://github.com/rbuckton/reflect-metadata | reflect-metadata}.
* - 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
* get metadata applied by decorators.
*
* @packageDocumentation
*/
export * from './decorator-factory';
export * from './inspector';
export * from './reflect';
export * from './types';

@@ -1,8 +0,16 @@

// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Copyright IBM Corp. 2017,2019. All Rights Reserved.
// Node module: @loopback/metadata
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import debugModule from 'debug';
import {DecoratorFactory} from './decorator-factory';
import {NamespacedReflect, Reflector} from './reflect';
import {
DecoratorType,
DesignTimeMethodMetadata,
MetadataKey,
MetadataMap,
} from './types';
import {Reflector, NamespacedReflect} from './reflect';
import {MetadataMap} from './decorator-factory';
const debug = debugModule('loopback:metadata:inspector');

@@ -18,40 +26,2 @@ /**

/**
* Design time metadata for a method.
*
* @example
* ```ts
* class MyController
* {
* myMethod(x: string, y: number, z: MyClass): boolean {
* // ...
* return true;
* }
* }
* ```
*
* The `myMethod` above has design-time metadata as follows:
* ```ts
* {
* type: Function,
* parameterTypes: [String, Number, MyClass],
* returnType: Boolean
* }
* ```
*/
export interface DesignTimeMethodMetadata {
/**
* Type of the method itself. It is `Function`
*/
type: Function;
/**
* An array of parameter types
*/
parameterTypes: Function[];
/**
* Return type
*/
returnType: Function;
}
/**
* Options for inspection

@@ -86,14 +56,14 @@ */

* Get the metadata associated with the given key for a given class
* @param key Metadata key
* @param target Class that contains the metadata
* @param options Options for inspection
* @param key - Metadata key
* @param target - Class that contains the metadata
* @param options - Options for inspection
*/
static getClassMetadata<T>(
key: string,
key: MetadataKey<T, ClassDecorator>,
target: Function,
options?: InspectionOptions,
): T | undefined {
return options && options.ownMetadataOnly
? Reflector.getOwnMetadata(key, target)
: Reflector.getMetadata(key, target);
return options?.ownMetadataOnly
? Reflector.getOwnMetadata(key.toString(), target)
: Reflector.getMetadata(key.toString(), target);
}

@@ -103,14 +73,14 @@

* Define metadata for the given target
* @param key Metadata key
* @param value Metadata value
* @param target Target for the metadata
* @param member Optional property or method name
* @param key - Metadata key
* @param value - Metadata value
* @param target - Target for the metadata
* @param member - Optional property or method name
*/
static defineMetadata<T>(
key: string,
key: MetadataKey<T, DecoratorType>,
value: T,
target: Object,
member?: string | symbol,
member?: string,
) {
Reflector.defineMetadata(key, value, target, member);
Reflector.defineMetadata(key.toString(), value, target, member);
}

@@ -121,14 +91,14 @@

* target class or prototype
* @param key Metadata key
* @param target Class for static methods or prototype for instance methods
* @param options Options for inspection
* @param key - Metadata key
* @param target - Class for static methods or prototype for instance methods
* @param options - Options for inspection
*/
static getAllMethodMetadata<T>(
key: string,
key: MetadataKey<T, MethodDecorator>,
target: Object,
options?: InspectionOptions,
): MetadataMap<T> | undefined {
return options && options.ownMetadataOnly
? Reflector.getOwnMetadata(key, target)
: Reflector.getMetadata(key, target);
return options?.ownMetadataOnly
? Reflector.getOwnMetadata(key.toString(), target)
: Reflector.getMetadata(key.toString(), target);
}

@@ -139,20 +109,19 @@

* target class or prototype
* @param key Metadata key
* @param target Class for static methods or prototype for instance methods
* @param methodName Method name. If not present, default to '' to use
* @param key - Metadata key
* @param target - Class for static methods or prototype for instance methods
* @param methodName - Method name. If not present, default to '' to use
* the constructor
* @param options Options for inspection
* @param options - Options for inspection
*/
static getMethodMetadata<T>(
key: string,
key: MetadataKey<T, MethodDecorator>,
target: Object,
methodName?: string | symbol,
methodName?: string,
options?: InspectionOptions,
): T | undefined {
methodName = methodName || '';
const meta: MetadataMap<T> =
options && options.ownMetadataOnly
? Reflector.getOwnMetadata(key, target)
: Reflector.getMetadata(key, target);
return meta && meta[methodName];
methodName = methodName ?? '';
const meta: MetadataMap<T> = options?.ownMetadataOnly
? Reflector.getOwnMetadata(key.toString(), target)
: Reflector.getMetadata(key.toString(), target);
return meta?.[methodName];
}

@@ -163,14 +132,14 @@

* target class or prototype
* @param key Metadata key
* @param target Class for static methods or prototype for instance methods
* @param options Options for inspection
* @param key - Metadata key
* @param target - Class for static methods or prototype for instance methods
* @param options - Options for inspection
*/
static getAllPropertyMetadata<T>(
key: string,
key: MetadataKey<T, PropertyDecorator>,
target: Object,
options?: InspectionOptions,
): MetadataMap<T> | undefined {
return options && options.ownMetadataOnly
? Reflector.getOwnMetadata(key, target)
: Reflector.getMetadata(key, target);
return options?.ownMetadataOnly
? Reflector.getOwnMetadata(key.toString(), target)
: Reflector.getMetadata(key.toString(), target);
}

@@ -181,19 +150,18 @@

* target class or prototype
* @param key Metadata key
* @param target Class for static properties or prototype for instance
* @param key - Metadata key
* @param target - Class for static properties or prototype for instance
* properties
* @param propertyName Property name
* @param options Options for inspection
* @param propertyName - Property name
* @param options - Options for inspection
*/
static getPropertyMetadata<T>(
key: string,
key: MetadataKey<T, PropertyDecorator>,
target: Object,
propertyName: string | symbol,
propertyName: string,
options?: InspectionOptions,
): T | undefined {
const meta: MetadataMap<T> =
options && options.ownMetadataOnly
? Reflector.getOwnMetadata(key, target)
: Reflector.getMetadata(key, target);
return meta && meta[propertyName];
const meta: MetadataMap<T> = options?.ownMetadataOnly
? Reflector.getOwnMetadata(key.toString(), target)
: Reflector.getMetadata(key.toString(), target);
return meta?.[propertyName];
}

@@ -204,20 +172,19 @@

* given method
* @param key Metadata key
* @param target Class for static methods or prototype for instance methods
* @param methodName Method name. If not present, default to '' to use
* @param key - Metadata key
* @param target - Class for static methods or prototype for instance methods
* @param methodName - Method name. If not present, default to '' to use
* the constructor
* @param options Options for inspection
* @param options - Options for inspection
*/
static getAllParameterMetadata<T>(
key: string,
key: MetadataKey<T, ParameterDecorator>,
target: Object,
methodName?: string | symbol,
methodName?: string,
options?: InspectionOptions,
): T[] | undefined {
methodName = methodName || '';
const meta: MetadataMap<T[]> =
options && options.ownMetadataOnly
? Reflector.getOwnMetadata(key, target)
: Reflector.getMetadata(key, target);
return meta && meta[methodName];
methodName = methodName ?? '';
const meta: MetadataMap<T[]> = options?.ownMetadataOnly
? Reflector.getOwnMetadata(key.toString(), target)
: Reflector.getMetadata(key.toString(), target);
return meta?.[methodName];
}

@@ -228,13 +195,13 @@

* method by index
* @param key Metadata key
* @param target Class for static methods or prototype for instance methods
* @param methodName Method name. If not present, default to '' to use
* @param key - Metadata key
* @param target - Class for static methods or prototype for instance methods
* @param methodName - Method name. If not present, default to '' to use
* the constructor
* @param index Index of the parameter, starting with 0
* @param options Options for inspection
* @param index - Index of the parameter, starting with 0
* @param options - Options for inspection
*/
static getParameterMetadata<T>(
key: string,
key: MetadataKey<T, ParameterDecorator>,
target: Object,
methodName: string | symbol,
methodName: string,
index: number,

@@ -244,8 +211,7 @@ options?: InspectionOptions,

methodName = methodName || '';
const meta: MetadataMap<T[]> =
options && options.ownMetadataOnly
? Reflector.getOwnMetadata(key, target)
: Reflector.getMetadata(key, target);
const params = meta && meta[methodName];
return params && params[index];
const meta: MetadataMap<T[]> = options?.ownMetadataOnly
? Reflector.getOwnMetadata(key.toString(), target)
: Reflector.getMetadata(key.toString(), target);
const params = meta?.[methodName];
return params?.[index];
}

@@ -255,9 +221,13 @@

* Get TypeScript design time type for a property
* @param target Class or prototype
* @param propertyName Property name
* @param target - Class or prototype
* @param propertyName - Property name
* @returns Design time metadata. The return value is `undefined` when:
* - The property has type `undefined`, `null`
* - The TypeScript project has not enabled the compiler option `emitDecoratorMetadata`.
* - The code is written in vanilla JavaScript.
*/
static getDesignTypeForProperty(
target: Object,
propertyName: string | symbol,
): Function {
propertyName: string,
): Function | undefined {
return TSReflector.getMetadata('design:type', target, propertyName);

@@ -267,10 +237,13 @@ }

/**
* Get TypeScript design time type for a method
* @param target Class or prototype
* @param methodName Method name
* Get TypeScript design time type for a method.
* @param target - Class or prototype
* @param methodName - Method name
* @returns Design time metadata. The return value is `undefined`
* in projects that do not enable `emitDecoratorMetadata`
* in TypeScript compiler options or are written in vanilla JavaScript.
*/
static getDesignTypeForMethod(
target: Object,
methodName: string | symbol,
): DesignTimeMethodMetadata {
methodName: string,
): DesignTimeMethodMetadata | undefined {
const type = TSReflector.getMetadata('design:type', target, methodName);

@@ -287,2 +260,21 @@ const parameterTypes = TSReflector.getMetadata(

);
if (
type === undefined &&
parameterTypes === undefined &&
returnType === undefined
) {
/* istanbul ignore next */
if (debug.enabled) {
const targetName = DecoratorFactory.getTargetName(target, methodName);
debug(
'No design-time type metadata found while inspecting %s. ' +
'Did you forget to enable TypeScript compiler option `emitDecoratorMetadata`?',
targetName,
);
}
return undefined;
}
return {

@@ -289,0 +281,0 @@ type,

@@ -1,2 +0,2 @@

// Copyright IBM Corp. 2017. All Rights Reserved.
// Copyright IBM Corp. 2017,2019. All Rights Reserved.
// Node module: @loopback/metadata

@@ -8,3 +8,3 @@ // This file is licensed under the MIT License.

/* tslint:disable:no-any */
/* eslint-disable @typescript-eslint/no-explicit-any */

@@ -16,3 +16,3 @@ /*

/**
* @param namespace : namespace to bind this reflect context
* @param namespace - Namespace to bind this reflect context
*/

@@ -33,3 +33,3 @@ constructor(private namespace?: string) {}

target: Object,
propertyKey?: string | symbol,
propertyKey?: string,
) {

@@ -47,7 +47,3 @@ metadataKey = this.getMetadataKey(metadataKey);

*/
getMetadata(
metadataKey: string,
target: Object,
propertyKey?: string | symbol,
): any {
getMetadata(metadataKey: string, target: Object, propertyKey?: string): any {
metadataKey = this.getMetadataKey(metadataKey);

@@ -66,3 +62,3 @@ if (propertyKey) {

target: Object,
propertyKey?: string | symbol,
propertyKey?: string,
): any {

@@ -78,5 +74,5 @@ metadataKey = this.getMetadataKey(metadataKey);

* Check if the target has corresponding metadata
* @param metadataKey Key
* @param target Target
* @param propertyKey Optional property key
* @param metadataKey - Key
* @param target - Target
* @param propertyKey - Optional property key
*/

@@ -86,3 +82,3 @@ hasMetadata(

target: Object,
propertyKey?: string | symbol,
propertyKey?: string,
): boolean {

@@ -99,3 +95,3 @@ metadataKey = this.getMetadataKey(metadataKey);

target: Object,
propertyKey?: string | symbol,
propertyKey?: string,
): boolean {

@@ -112,3 +108,3 @@ metadataKey = this.getMetadataKey(metadataKey);

target: Object,
propertyKey?: string | symbol,
propertyKey?: string,
): boolean {

@@ -122,3 +118,3 @@ metadataKey = this.getMetadataKey(metadataKey);

getMetadataKeys(target: Object, propertyKey?: string | symbol): string[] {
getMetadataKeys(target: Object, propertyKey?: string): string[] {
let keys: string[];

@@ -144,3 +140,3 @@ if (propertyKey) {

getOwnMetadataKeys(target: Object, propertyKey?: string | symbol): string[] {
getOwnMetadataKeys(target: Object, propertyKey?: string): string[] {
let keys: string[];

@@ -167,2 +163,14 @@ if (propertyKey) {

decorate(
decorators: (PropertyDecorator | MethodDecorator)[],
target: Object,
targetKey?: string | symbol,
descriptor?: PropertyDescriptor,
): PropertyDescriptor | Function;
decorate(
decorators: ClassDecorator[],
target: Object,
): PropertyDescriptor | Function;
decorate(
decorators: (PropertyDecorator | MethodDecorator)[] | ClassDecorator[],

@@ -174,3 +182,8 @@ target: Object,

if (targetKey) {
return Reflect.decorate(decorators, target, targetKey, descriptor);
return Reflect.decorate(
<(PropertyDecorator | MethodDecorator)[]>decorators,
target,
targetKey,
descriptor,
);
} else {

@@ -181,3 +194,2 @@ return Reflect.decorate(<ClassDecorator[]>decorators, <Function>target);

/* tslint:disable-next-line:no-any */
metadata(

@@ -195,3 +207,2 @@ metadataKey: string,

/* tslint:disable-next-line:variable-name */
export const Reflector = new NamespacedReflect('loopback');

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc