Compare commits

..

No commits in common. "master" and "v0.0.2" have entirely different histories.

18 changed files with 74 additions and 311 deletions

View File

@ -2,10 +2,5 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="0.0.4"></a>
## [0.0.4](https://git.loafle.net/overflow/core-js/compare/v0.0.2...v0.0.4) (2018-09-05)
<a name="0.0.2"></a> <a name="0.0.2"></a>
## 0.0.2 (2018-09-05) ## 0.0.2 (2018-09-05)

View File

@ -1,6 +1,6 @@
{ {
"name": "@overflow/core-js", "name": "@overflow/core-js",
"version": "0.0.11", "version": "0.0.2",
"description": "TypeScript library setup for multiple compilation targets using tsc and webpack", "description": "TypeScript library setup for multiple compilation targets using tsc and webpack",
"main": "./bundles/index.umd.js", "main": "./bundles/index.umd.js",
"module": "./esm5/index.js", "module": "./esm5/index.js",
@ -55,7 +55,9 @@
"maxSubjectLength": 120 "maxSubjectLength": 120
} }
}, },
"peerDependencies": {}, "peerDependencies": {
"tslib": ">=1.9.0"
},
"dependencies": { "dependencies": {
"reflect-metadata": "^0.1.12" "reflect-metadata": "^0.1.12"
}, },
@ -95,4 +97,4 @@
"validate-commit-msg": "^2.14.0", "validate-commit-msg": "^2.14.0",
"webpack-config-utils": "^2.3.0" "webpack-config-utils": "^2.3.0"
} }
} }

View File

@ -4,17 +4,3 @@ export class IllegalArgumentError extends Error {
Object.setPrototypeOf(this, new.target.prototype); Object.setPrototypeOf(this, new.target.prototype);
} }
} }
export class NotSupportedDecoratorError extends Error {
public constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
}
export class NotDecoratedClassError extends Error {
public constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
}

View File

@ -5,7 +5,7 @@ export interface Type<T> extends Function {
} }
export declare type IdentityType<T> = T | symbol; export declare type IdentityType<T> = T | symbol;
export declare type PropertyKeyType = IdentityType<string>; export declare type PropertyKeyType = IdentityType<string | number>;
export declare type MetadataKeyType = IdentityType<string>; export declare type MetadataKeyType = IdentityType<string>;
export enum PrimitiveType { export enum PrimitiveType {
@ -14,12 +14,3 @@ export enum PrimitiveType {
NUMBER = 'number', NUMBER = 'number',
BOOLEAN = 'boolean', BOOLEAN = 'boolean',
} }
export enum DecoratorType {
CLASS = 'Clazz',
PROPERTY = 'Property',
METHOD = 'Method',
PARAMETER = 'Parameter',
}
export type DecoratorParametersType = [any, string | symbol, number | PropertyDescriptor | undefined];

View File

@ -1,22 +0,0 @@
import {
PropertyKeyType,
} from '../core';
import {
Annotation,
} from '../reflect';
export interface Decorator<Attribute = {}> {
classDecorator?: <TFunction extends Function>(target: TFunction) => TFunction | void;
propertyDecorator?: (target: Object, propertyKey: PropertyKeyType) => void;
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<Attribute> {
public constructor(attribute?: Attribute) {
super(attribute);
}
}

View File

@ -1,164 +0,0 @@
import {
DecoratorParametersType,
DecoratorType,
NotSupportedDecoratorError,
PropertyKeyType, Type,
} from '../core';
import {
Class,
Constructor,
Field,
Metadata,
Method,
Parameter,
} from '../reflect';
import {
TypeUtil,
} from '../util';
import { Decorator } from './Decorator';
export class DecoratorHelper {
public static register<Attribute = {}>(DecoratorClass: Type<Decorator<Attribute>>, attribute?: Attribute) {
const annotation: Decorator<Attribute> = new DecoratorClass(attribute);
const name: string = DecoratorClass.name;
return function (...decoratorArgs: any[]) {
return DecoratorHelper.registerAnnotation(name, annotation, decoratorArgs);
};
}
public static create<Attribute = {}>(DecoratorClass: Type<Decorator<Attribute>>) {
return function (attribute?: Attribute) {
const annotation: Decorator<Attribute> = new DecoratorClass(attribute);
const name: string = DecoratorClass.name;
return function (...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(TypeUtil.getType(target));
let field: Field;
let method: Method;
let parameter: Parameter | undefined;
let cons: Constructor | null = null;
switch (decoratorType) {
case DecoratorType.CLASS:
try {
cons = clazz._defineConstructor(Metadata.getOwnParamTypes(target));
clazz._addAnnotation(annotation);
if (annotation instanceof Decorator && undefined !== annotation.classDecorator) {
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 && undefined !== annotation.propertyDecorator) {
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 && undefined !== annotation.methodDecorator) {
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);
}
if (undefined !== parameter) {
parameter._addAnnotation(annotation);
}
if (annotation instanceof Decorator && undefined !== annotation.parameterDecorator) {
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),
];
}
}

View File

@ -1,2 +0,0 @@
export * from './Decorator';
export * from './DecoratorHelper';

View File

@ -1,4 +1,3 @@
export * from './core'; export * from './core';
export * from './decorator';
export * from './reflect'; export * from './reflect';
export * from './util'; export * from './util';

View File

@ -21,7 +21,7 @@ export abstract class AccessibleObject implements AnnotatedElement {
} }
public isAnnotationPresent<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): boolean { public isAnnotationPresent<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): boolean {
return undefined !== this.getAnnotation(annotationClass); return null !== this.getAnnotation(annotationClass);
} }
public getOwnAnnotation<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType | undefined { public getOwnAnnotation<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType | undefined {

View File

@ -1,4 +1,4 @@
export class Annotation<Attribute = {}> { export abstract class Annotation<Attribute = {}> {
public readonly attribute: Attribute | undefined; public readonly attribute: Attribute | undefined;
public constructor(attribute?: Attribute) { public constructor(attribute?: Attribute) {

View File

@ -38,9 +38,11 @@ export class Class extends AccessibleObject {
SystemClassRegistry.set(type, clazz); SystemClassRegistry.set(type, clazz);
} }
if (undefined === clazz._constructor) { if (null === clazz._constructor) {
const parameterTypes = Metadata.getOwnParamTypes(type); const parameterTypes = Metadata.getOwnParamTypes(type);
clazz._constructor = new Constructor(clazz, parameterTypes); if (undefined !== parameterTypes) {
clazz._constructor = new Constructor(clazz, parameterTypes);
}
} }
return clazz; return clazz;
@ -122,6 +124,9 @@ export class Class extends AccessibleObject {
const fields: Map<PropertyKeyType, Field> = new Map(); const fields: Map<PropertyKeyType, Field> = new Map();
const types = TypeUtil.ancestorsOf(this._type); const types = TypeUtil.ancestorsOf(this._type);
if (null === types || 0 === types.length) {
return fields;
}
for (let i = 0; i < types.length; i++) { for (let i = 0; i < types.length; i++) {
const tType = types[i]; const tType = types[i];
const tClazz = Class.forType(tType); const tClazz = Class.forType(tType);
@ -155,6 +160,9 @@ export class Class extends AccessibleObject {
const methods: Map<PropertyKeyType, Method> = new Map(); const methods: Map<PropertyKeyType, Method> = new Map();
const types = TypeUtil.ancestorsOf(this._type); const types = TypeUtil.ancestorsOf(this._type);
if (null === types || 0 === types.length) {
return methods;
}
for (let i = 0; i < types.length; i++) { for (let i = 0; i < types.length; i++) {
const tClazzType = types[i]; const tClazzType = types[i];
const tClazz = Class.forType(tClazzType); const tClazz = Class.forType(tClazzType);
@ -180,6 +188,9 @@ export class Class extends AccessibleObject {
const annotations: Map<Type<any>, Annotation> = new Map(); const annotations: Map<Type<any>, Annotation> = new Map();
const types = TypeUtil.ancestorsOf(this._type); const types = TypeUtil.ancestorsOf(this._type);
if (null === types || 0 === types.length) {
return annotations;
}
for (let i = 0; i < types.length; i++) { for (let i = 0; i < types.length; i++) {
const tClazzType = types[i]; const tClazzType = types[i];
const tClazz = Class.forType(tClazzType); const tClazz = Class.forType(tClazzType);

View File

@ -5,8 +5,6 @@
import { Class } from './Class'; import { Class } from './Class';
import { Executable } from './Executable'; import { Executable } from './Executable';
const CONSTRUCTOR_NAME = 'constructor';
export class Constructor extends Executable { export class Constructor extends Executable {
// private _rawConstructor: Function; // private _rawConstructor: Function;
@ -21,3 +19,5 @@ export class Constructor extends Executable {
return new (ctor.bind.apply(ctor, [null].concat(args)))(); return new (ctor.bind.apply(ctor, [null].concat(args)))();
} }
} }
const CONSTRUCTOR_NAME = 'constructor';

View File

@ -49,6 +49,10 @@ export abstract class Executable extends AccessibleObject implements Member {
* getParameterCount * getParameterCount
*/ */
public getParameterCount(): number { public getParameterCount(): number {
if (null === this._parameters) {
return 0;
}
return this._parameters.length; return this._parameters.length;
} }
/** /**
@ -61,6 +65,9 @@ export abstract class Executable extends AccessibleObject implements Member {
* getParameter * getParameter
*/ */
public getParameter(index: number): Parameter | undefined { public getParameter(index: number): Parameter | undefined {
if (null === this._parameters) {
return undefined;
}
if (0 > index || this._parameters.length <= index) { if (0 > index || this._parameters.length <= index) {
return undefined; return undefined;
} }

View File

@ -5,31 +5,6 @@ import {
import { TypeUtil } from '../util/TypeUtil'; import { TypeUtil } from '../util/TypeUtil';
/**
* Metadata key
* @private
* @type {string}
*/
const DESIGN_PARAM_TYPES = 'design:paramtypes';
/**
* Metadata key
* @private
* @type {string}
*/
const DESIGN_TYPE = 'design:type';
/**
* Metadata key
* @private
* @type {string}
*/
const DESIGN_RETURN_TYPE = 'design:returntype';
/**
* Properties collections
* @private
* @type {string}
*/
const PROPERTIES: Map<MetadataKeyType, any[]> = new Map<MetadataKeyType, any[]>();
export class Metadata { export class Metadata {
/** /**
* Gets the metadata value for the provided metadata key on the target object or its prototype chain. * Gets the metadata value for the provided metadata key on the target object or its prototype chain.
@ -529,3 +504,28 @@ export class Metadata {
return Reflect.getOwnMetadata(DESIGN_PARAM_TYPES, target, propertyKey); return Reflect.getOwnMetadata(DESIGN_PARAM_TYPES, target, propertyKey);
} }
} }
/**
* Metadata key
* @private
* @type {string}
*/
const DESIGN_PARAM_TYPES = 'design:paramtypes';
/**
* Metadata key
* @private
* @type {string}
*/
const DESIGN_TYPE = 'design:type';
/**
* Metadata key
* @private
* @type {string}
*/
const DESIGN_RETURN_TYPE = 'design:returntype';
/**
* Properties collections
* @private
* @type {string}
*/
const PROPERTIES: Map<MetadataKeyType, any[]> = new Map<MetadataKeyType, any[]>();

View File

@ -1,32 +0,0 @@
import { Method } from '../reflect';
export abstract class ReflectionUtil {
public static getParamTypes(method: Method): any[] {
if (0 === method.getParameterCount()) {
return [];
}
const parameters = method.getParameters();
if (undefined === parameters) {
return [];
}
const results: any[] = [];
for (let indexI = 0; indexI < parameters.length; indexI++) {
const paramType = parameters[indexI].getType();
results.push(paramType);
}
return results;
}
public static getParamTypeStrings(method: Method): string[] {
const paramTypes = ReflectionUtil.getParamTypes(method);
const results: string[] = [];
paramTypes.forEach(paramType => {
results.push(paramType.name);
});
return results;
}
}

View File

@ -4,10 +4,6 @@ import {
Type, Type,
} from '../core'; } from '../core';
const COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
const DEFAULT_PARAMS = /=[^,]+/mg;
const FAT_ARROWS = /=>.*$/mg;
export class TypeUtil { export class TypeUtil {
/** /**
* Get the provide constructor. * Get the provide constructor.
@ -155,7 +151,7 @@ export class TypeUtil {
* @returns {boolean} * @returns {boolean}
*/ */
public static isMethod(target: any, propertyKey: PropertyKeyType): boolean { public static isMethod(target: any, propertyKey: PropertyKeyType): boolean {
if (typeof target.propertyKey === 'undefined') { if (typeof(target[propertyKey]) === undefined) {
return false; return false;
} }
@ -393,27 +389,26 @@ export class TypeUtil {
* @param {number} time * @param {number} time
* @returns {Promise<any>} * @returns {Promise<any>}
*/ */
public static promiseTimeout(promise: Promise<any>, timeout = 1000): Promise<{ ok: boolean, response?: any }> { public static promiseTimeout(promise: Promise<any>, time = 1000): Promise<{ ok: boolean, response: any }> {
let _hTimeout: any; const timeout = (p: Promise<any>, t: number) => new Promise((resolve) => {
p.then((response) => {
resolve();
return response;
});
setTimeout(() => resolve({ ok: false }), t);
});
promise = promise.then((response) => ({ ok: true, response }));
return Promise.race([ return Promise.race([
promise, promise,
new Promise((resolve, reject) => { timeout(promise, time),
promise.then(response => {
clearTimeout(_hTimeout);
resolve();
return { ok: true, response };
}).catch(reason => {
clearTimeout(_hTimeout);
reject(reason);
});
_hTimeout = setTimeout(() => {
resolve({ ok: false });
}, timeout);
}),
]); ]);
} }
} }
const COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
const DEFAULT_PARAMS = /=[^,]+/mg;
const FAT_ARROWS = /=>.*$/mg;

View File

@ -1,4 +1,3 @@
export * from './AnnotationUtil'; export * from './AnnotationUtil';
export * from './ReflectionUtil';
export * from './Registry'; export * from './Registry';
export * from './TypeUtil'; export * from './TypeUtil';

View File

@ -4,8 +4,6 @@
"module": "esnext", "module": "esnext",
"target": "es5", "target": "es5",
"types": [ "types": [
"jest",
"node",
"reflect-metadata", "reflect-metadata",
], ],
"lib": [ "lib": [