@loopback/metadata
Version:
Utilities to help developers implement TypeScript decorators, define/merge metadata, and inspect metadata
298 lines (297 loc) • 13.2 kB
TypeScript
import { DecoratorType, MetadataKey, MetadataMap } from './types';
/**
* Options for a decorator
*/
export interface DecoratorOptions {
/**
* Controls if inherited metadata will be honored. Default to `true`.
*/
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 of the decorator for debugging purpose, such as `@inject`
*/
decoratorName?: string;
[name: string]: any;
}
/**
* Base factory class for decorator functions
*
* @example
* ```
* function classDecorator(spec: MySpec): ClassDecorator {
* return ClassDecoratorFactory.createDecorator('my-key', spec);
* }
* ```
* or
* ```
* function classDecorator(spec: MySpec): ClassDecorator {
* const factory: ClassDecoratorFactory<MySpec>('my-key', spec);
* return factory.create();
* }
* ```
* These functions above declare `@classDecorator` that can be used as follows:
* ```
* @classDecorator({x: 1})
* class MyController {}
* ```
*/
export declare class DecoratorFactory<T, // Type of the metadata spec for individual class/method/property/parameter
M extends T | MetadataMap<T> | MetadataMap<T[]>, // Type of the metadata
D extends DecoratorType> {
protected key: string;
protected spec: T;
protected options: DecoratorOptions;
protected decoratorName: string;
/**
* A constant to reference the target of a decoration
*/
static TARGET: string;
/**
* 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
* `{allowInheritance: true}` if not provided
*/
constructor(key: string, spec: T, options?: DecoratorOptions);
protected allowInheritance(): boolean;
/**
* Inherit metadata from base classes. By default, this method merges base
* metadata into the spec if `allowInheritance` is set to `true`. To customize
* the behavior, this method can be overridden by sub classes.
*
* @param inheritedMetadata - Metadata from base classes for the member
*/
protected inherit(inheritedMetadata: T | undefined | null): T;
/**
* 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
*/
static getTargetName(target: Object, member?: string | symbol, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): string;
/**
* Get the number of parameters for a given constructor or method
* @param target - Class or the prototype
* @param member - Method name
*/
static getNumberOfParameters(target: Object, member?: string): number;
/**
* Set a reference to the target class or prototype for a given spec if
* it's an object
* @param spec - Metadata spec
* @param target - Target of the decoration. It is a class or the prototype of
* a class.
*/
withTarget(spec: T, target: Object): T;
/**
* Get the optional decoration target of a given spec
* @param spec - Metadata spec
*/
getTarget(spec: T): any;
/**
* This method is called by the default implementation of the decorator
* function to merge the spec argument from the decoration with the inherited
* metadata for a class, all properties, all methods, or all method
* parameters that are decorated by this decorator.
*
* It MUST be overridden by subclasses to process inherited metadata.
*
* @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
*/
protected mergeWithInherited(inheritedMetadata: M, target: Object, member?: string | symbol, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): M;
/**
* This method is called by the default implementation of the decorator
* function to merge the spec argument from the decoration with the own
* metadata for a class, all properties, all methods, or all method
* parameters that are decorated by this decorator.
*
* It MUST be overridden by subclasses to process own metadata.
*
* @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
*/
protected mergeWithOwn(ownMetadata: M, target: Object, member?: string | symbol, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): M;
/**
* 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): Error;
/**
* Create a decorator function of the given type. Each sub class MUST
* implement this method.
*/
create(): D;
/**
* Base implementation of the decorator function
* @param target - Decorator target
* @param member - Optional property or method
* @param descriptorOrIndex - Optional method descriptor or parameter index
*/
protected decorate(target: Object, member?: string | symbol, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): void;
/**
* Create a decorator function
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
protected static _createDecorator<S, MT extends S | MetadataMap<S> | MetadataMap<S[]>, DT extends DecoratorType>(key: MetadataKey<S, DT>, spec: S, options?: DecoratorOptions): DT;
private static _cloneableTypes;
static cloneDeep<V>(val: Readonly<V>): V;
}
/**
* Factory for class decorators
*/
export declare class ClassDecoratorFactory<T> extends DecoratorFactory<T, T, ClassDecorator> {
protected mergeWithInherited(inheritedMetadata: T, target: Object, member?: string, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): T;
protected mergeWithOwn(ownMetadata: T, target: Object, member?: string, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): T;
create(): ClassDecorator;
/**
* Create a class decorator function
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<S>(key: MetadataKey<S, ClassDecorator>, spec: S, options?: DecoratorOptions): ClassDecorator;
}
/**
* Factory for property decorators
*/
export declare class PropertyDecoratorFactory<T> extends DecoratorFactory<T, MetadataMap<T>, PropertyDecorator> {
protected mergeWithInherited(inheritedMetadata: MetadataMap<T>, target: Object, propertyName?: string, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): MetadataMap<T>;
protected mergeWithOwn(ownMetadata: MetadataMap<T>, target: Object, propertyName?: string, descriptorOrParameterIndex?: TypedPropertyDescriptor<any> | number): MetadataMap<T>;
create(): PropertyDecorator;
/**
* Create a property decorator function
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<S>(key: MetadataKey<S, PropertyDecorator>, spec: S, options?: DecoratorOptions): PropertyDecorator;
}
/**
* Factory for method decorators
*/
export declare class MethodDecoratorFactory<T> extends DecoratorFactory<T, MetadataMap<T>, MethodDecorator> {
protected mergeWithInherited(inheritedMetadata: MetadataMap<T>, target: Object, methodName?: string, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T>;
protected mergeWithOwn(ownMetadata: MetadataMap<T>, target: Object, methodName?: string, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T>;
create(): MethodDecorator;
/**
* Create a method decorator function
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<S>(key: MetadataKey<S, MethodDecorator>, spec: S, options?: DecoratorOptions): MethodDecorator;
}
/**
* Factory for parameter decorators
*/
export declare class ParameterDecoratorFactory<T> extends DecoratorFactory<T, MetadataMap<T[]>, ParameterDecorator> {
private getOrInitMetadata;
protected mergeWithInherited(inheritedMetadata: MetadataMap<T[]>, target: Object, methodName?: string, parameterIndex?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;
protected mergeWithOwn(ownMetadata: MetadataMap<T[]>, target: Object, methodName?: string, parameterIndex?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;
create(): ParameterDecorator;
/**
* Create a parameter decorator function
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<S>(key: MetadataKey<S, ParameterDecorator>, spec: S, options?: DecoratorOptions): ParameterDecorator;
}
/**
* Factory for method level parameter decorator.
*
* @example
* For example, the following code uses `@param` to declare two parameters for
* `greet()`.
* ```ts
* class MyController {
* @param('name') // Parameter 0
* @param('msg') // Parameter 1
* greet() {}
* }
* ```
*/
export declare class MethodParameterDecoratorFactory<T> extends DecoratorFactory<T, MetadataMap<T[]>, MethodDecorator> {
/**
* Find the corresponding parameter index for the decoration
* @param target
* @param methodName
* @param methodDescriptor
*/
private getParameterIndex;
protected mergeWithInherited(inheritedMetadata: MetadataMap<T[]>, target: Object, methodName?: string, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;
protected mergeWithOwn(ownMetadata: MetadataMap<T[]>, target: Object, methodName?: string, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;
create(): MethodDecorator;
/**
* Create a method decorator function
* @param key - Metadata key
* @param spec - Metadata object from the decorator function
* @param options - Options for the decorator
*/
static createDecorator<S>(key: MetadataKey<S, MethodDecorator>, spec: S, options?: DecoratorOptions): MethodDecorator;
}
/**
* 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 declare class MethodMultiDecoratorFactory<T> extends MethodDecoratorFactory<T[]> {
protected mergeWithInherited(inheritedMetadata: MetadataMap<T[]>, target: Object, methodName?: string): MetadataMap<T[]>;
protected mergeWithOwn(ownMetadata: MetadataMap<T[]>, target: Object, methodName?: string, methodDescriptor?: TypedPropertyDescriptor<any> | number): MetadataMap<T[]>;
private _mergeArray;
}