ing
This commit is contained in:
parent
529d717588
commit
13721a3814
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -752,9 +752,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tslint-config-prettier": {
|
"tslint-config-prettier": {
|
||||||
"version": "1.12.0",
|
"version": "1.13.0",
|
||||||
"resolved": "https://nexus.loafle.net/repository/npm-all/tslint-config-prettier/-/tslint-config-prettier-1.12.0.tgz",
|
"resolved": "https://nexus.loafle.net/repository/npm-all/tslint-config-prettier/-/tslint-config-prettier-1.13.0.tgz",
|
||||||
"integrity": "sha512-7zugK8NWpoDPYT6UNGLDGpQOhk0CSodjkyrTNiHOCjwIAleYKlyQunxpsSXBIoGEs/kFVppd6YzZeQZtrJnyRg==",
|
"integrity": "sha512-assE77K7K8Q9j8CVIHiU3d1uoKc8N5v7UPpkQ9IE8BEPWkvSYR37lDuYekDlAMFqR1IpD6CrS+uOJLl6pw7Wdw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"tslint-config-standard": {
|
"tslint-config-standard": {
|
||||||
|
|
131
src/Decorator.ts
131
src/Decorator.ts
|
@ -1,24 +1,131 @@
|
||||||
import {
|
import {
|
||||||
|
Type,
|
||||||
PropertyKeyType,
|
PropertyKeyType,
|
||||||
} from '@loafer/core';
|
} from '@loafer/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Annotation,
|
Annotation,
|
||||||
|
Class,
|
||||||
|
Constructor,
|
||||||
|
Field,
|
||||||
|
Method,
|
||||||
|
Parameter,
|
||||||
|
Metadata,
|
||||||
} from '@loafer/core/reflect';
|
} from '@loafer/core/reflect';
|
||||||
|
|
||||||
export interface Decorator<Attribute = {}> {
|
import {
|
||||||
classDecorator?: <TFunction extends Function>(target: TFunction) => TFunction | void;
|
TypeUtil,
|
||||||
propertyDecorator?: (target: Object, propertyKey: PropertyKeyType) => void;
|
} from '@loafer/core/util/TypeUtil';
|
||||||
methodDecorator?: <T>(target: Object, propertyKey: PropertyKeyType,
|
|
||||||
descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
|
|
||||||
parameterDecorator?: (target: Object, propertyKey: PropertyKeyType, parameterIndex: number) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class Decorator<Attribute = {}> extends Annotation {
|
import { DecoratorType, DecoratorParametersType } from './type';
|
||||||
public readonly attribute: Attribute;
|
import { NotSupportedDecoratorError } from './error';
|
||||||
|
|
||||||
public constructor(attribute?: Attribute) {
|
export class Decorator {
|
||||||
super();
|
|
||||||
this.attribute = attribute;
|
public static register<T extends Annotation>(AnnotationClass: Type<Annotation>, _annotation: T, ...decoratorArgs: any[]) {
|
||||||
|
const annotation: Annotation = Object.assign(new AnnotationClass(), _annotation);
|
||||||
|
|
||||||
|
const name: string = AnnotationClass.name;
|
||||||
|
|
||||||
|
const decoratorType: DecoratorType = Decorator.getDecoratorType(decoratorArgs);
|
||||||
|
|
||||||
|
const [target, propertyKey, descriptorOrParameterIndex] = decoratorArgs;
|
||||||
|
|
||||||
|
const clazz: Class = Class._defineClass(TypeUtil.getType(target));
|
||||||
|
let field: Field = null;
|
||||||
|
let method: Method = null;
|
||||||
|
let parameter: Parameter = null;
|
||||||
|
let cons: Constructor = null;
|
||||||
|
|
||||||
|
switch (decoratorType) {
|
||||||
|
case DecoratorType.CLASS:
|
||||||
|
try {
|
||||||
|
cons = clazz._defineConstructor(Metadata.getOwnParamTypes(target));
|
||||||
|
clazz._addAnnotation(annotation);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof NotSupportedDecoratorError) {
|
||||||
|
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Class.`);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DecoratorType.PROPERTY:
|
||||||
|
try {
|
||||||
|
field = clazz._defineField(propertyKey, Metadata.getOwnType(target, propertyKey));
|
||||||
|
field._addAnnotation(annotation);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof NotSupportedDecoratorError) {
|
||||||
|
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Property.`);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DecoratorType.METHOD:
|
||||||
|
try {
|
||||||
|
method = clazz._defineMethod(propertyKey,
|
||||||
|
Metadata.getOwnParamTypes(target, propertyKey),
|
||||||
|
Metadata.getOwnReturnType(target, propertyKey));
|
||||||
|
method._addAnnotation(annotation);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof NotSupportedDecoratorError) {
|
||||||
|
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Method.`);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DecoratorType.PARAMETER:
|
||||||
|
try {
|
||||||
|
if (undefined === propertyKey) {
|
||||||
|
cons = clazz.getConstructor();
|
||||||
|
parameter = cons.getParameter(descriptorOrParameterIndex);
|
||||||
|
} else {
|
||||||
|
method = clazz._defineMethod(propertyKey,
|
||||||
|
Metadata.getOwnParamTypes(target, propertyKey),
|
||||||
|
Metadata.getOwnReturnType(target, propertyKey));
|
||||||
|
parameter = method.getParameter(descriptorOrParameterIndex);
|
||||||
|
}
|
||||||
|
parameter._addAnnotation(annotation);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof NotSupportedDecoratorError) {
|
||||||
|
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Parameter.`);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedDecoratorError(`Cannot determine decorator[@${name}] type.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {any[]} args
|
||||||
|
* @returns {DecoratorType}
|
||||||
|
*/
|
||||||
|
public static getDecoratorType(args: any[]): DecoratorType {
|
||||||
|
const [, propertyKey, descriptor] = args;
|
||||||
|
|
||||||
|
if (typeof descriptor === 'number') {
|
||||||
|
return DecoratorType.PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyKey && descriptor === undefined || descriptor && (descriptor.get || descriptor.set)) {
|
||||||
|
return DecoratorType.PROPERTY;
|
||||||
|
}
|
||||||
|
return (descriptor && descriptor.value) ? DecoratorType.METHOD : DecoratorType.CLASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @param {string} propertyKey
|
||||||
|
* @returns {DecoratorParametersType}
|
||||||
|
*/
|
||||||
|
public static decoratorArgs(target: any, propertyKey: PropertyKeyType): DecoratorParametersType {
|
||||||
|
return [
|
||||||
|
target,
|
||||||
|
propertyKey,
|
||||||
|
TypeUtil.descriptorOf(target, propertyKey),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
import {
|
|
||||||
Type,
|
|
||||||
PropertyKeyType,
|
|
||||||
} from '@loafer/core';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Annotation,
|
|
||||||
Class,
|
|
||||||
Constructor,
|
|
||||||
Field,
|
|
||||||
Method,
|
|
||||||
Parameter,
|
|
||||||
Metadata,
|
|
||||||
} from '@loafer/core/reflect';
|
|
||||||
|
|
||||||
import {
|
|
||||||
TypeUtil,
|
|
||||||
} from '@loafer/core/util/TypeUtil';
|
|
||||||
|
|
||||||
import { Decorator } from './Decorator';
|
|
||||||
import { DecoratorType, DecoratorParametersType } from './type';
|
|
||||||
import { NotSupportedDecoratorError } from './error';
|
|
||||||
|
|
||||||
export class DecoratorHelper {
|
|
||||||
|
|
||||||
public static register<AnnotationType extends Annotation>(annotation: AnnotationType, ...decoratorArgs: any[]) {
|
|
||||||
const annotationClass = Metadata.getType(annotation);
|
|
||||||
const name: string = annotationClass.name;
|
|
||||||
|
|
||||||
DecoratorHelper.registerAnnotation(name, annotation, decoratorArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static create = <Attribute = {}>(DecoratorClass: Type<Decorator<Attribute>>) => {
|
|
||||||
return (attribute: Attribute) => {
|
|
||||||
const annotation: Decorator<Attribute> = new DecoratorClass(attribute);
|
|
||||||
const name: string = DecoratorClass.name;
|
|
||||||
|
|
||||||
return (...decoratorArgs: any[]) => {
|
|
||||||
return DecoratorHelper.registerAnnotation(name, annotation, decoratorArgs);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static registerAnnotation(name: string, annotation: any, decoratorArgs: any[]) {
|
|
||||||
const decoratorType: DecoratorType = DecoratorHelper.getDecoratorType(decoratorArgs);
|
|
||||||
|
|
||||||
const [target, propertyKey, descriptorOrParameterIndex] = decoratorArgs;
|
|
||||||
|
|
||||||
const clazz: Class = Class._defineClass(Metadata.getType(target));
|
|
||||||
let field: Field = null;
|
|
||||||
let method: Method = null;
|
|
||||||
let parameter: Parameter = null;
|
|
||||||
let cons: Constructor = null;
|
|
||||||
|
|
||||||
switch (decoratorType) {
|
|
||||||
case DecoratorType.CLASS:
|
|
||||||
try {
|
|
||||||
cons = clazz._defineConstructor(Metadata.getOwnParamTypes(target));
|
|
||||||
clazz._addAnnotation(annotation);
|
|
||||||
if (annotation instanceof Decorator) {
|
|
||||||
return annotation.classDecorator.call(annotation, target);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof NotSupportedDecoratorError) {
|
|
||||||
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Class.`);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DecoratorType.PROPERTY:
|
|
||||||
try {
|
|
||||||
field = clazz._defineField(propertyKey, Metadata.getOwnType(target, propertyKey));
|
|
||||||
field._addAnnotation(annotation);
|
|
||||||
if (annotation instanceof Decorator) {
|
|
||||||
return annotation.propertyDecorator.call(annotation, target, propertyKey);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof NotSupportedDecoratorError) {
|
|
||||||
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Property.`);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DecoratorType.METHOD:
|
|
||||||
try {
|
|
||||||
method = clazz._defineMethod(propertyKey,
|
|
||||||
Metadata.getOwnParamTypes(target, propertyKey),
|
|
||||||
Metadata.getOwnReturnType(target, propertyKey));
|
|
||||||
method._addAnnotation(annotation);
|
|
||||||
|
|
||||||
if (annotation instanceof Decorator) {
|
|
||||||
return annotation.methodDecorator.call(annotation, target, propertyKey, descriptorOrParameterIndex);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof NotSupportedDecoratorError) {
|
|
||||||
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Method.`);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DecoratorType.PARAMETER:
|
|
||||||
try {
|
|
||||||
if (undefined === propertyKey) {
|
|
||||||
cons = clazz.getConstructor();
|
|
||||||
parameter = cons.getParameter(descriptorOrParameterIndex);
|
|
||||||
} else {
|
|
||||||
method = clazz._defineMethod(propertyKey,
|
|
||||||
Metadata.getOwnParamTypes(target, propertyKey),
|
|
||||||
Metadata.getOwnReturnType(target, propertyKey));
|
|
||||||
parameter = method.getParameter(descriptorOrParameterIndex);
|
|
||||||
}
|
|
||||||
parameter._addAnnotation(annotation);
|
|
||||||
|
|
||||||
if (annotation instanceof Decorator) {
|
|
||||||
return annotation.parameterDecorator.call(annotation, target, propertyKey, descriptorOrParameterIndex);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof NotSupportedDecoratorError) {
|
|
||||||
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Parameter.`);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new NotSupportedDecoratorError(`Cannot determine decorator[@${name}] type.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {any[]} args
|
|
||||||
* @returns {DecoratorType}
|
|
||||||
*/
|
|
||||||
public static getDecoratorType(args: any[]): DecoratorType {
|
|
||||||
const [, propertyKey, descriptor] = args;
|
|
||||||
|
|
||||||
if (typeof descriptor === 'number') {
|
|
||||||
return DecoratorType.PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertyKey && descriptor === undefined || descriptor && (descriptor.get || descriptor.set)) {
|
|
||||||
return DecoratorType.PROPERTY;
|
|
||||||
}
|
|
||||||
return (descriptor && descriptor.value) ? DecoratorType.METHOD : DecoratorType.CLASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
* @param {string} propertyKey
|
|
||||||
* @returns {DecoratorParametersType}
|
|
||||||
*/
|
|
||||||
public static decoratorArgs(target: any, propertyKey: PropertyKeyType): DecoratorParametersType {
|
|
||||||
return [
|
|
||||||
target,
|
|
||||||
propertyKey,
|
|
||||||
TypeUtil.descriptorOf(target, propertyKey),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,3 @@
|
||||||
export * from './Decorator';
|
export * from './Decorator';
|
||||||
export * from './DecoratorHelper';
|
|
||||||
export * from './error';
|
export * from './error';
|
||||||
export * from './type';
|
export * from './type';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user