This commit is contained in:
crusader 2018-01-01 21:42:46 +09:00
parent 88469945b0
commit b7f366be76
22 changed files with 214 additions and 169 deletions

View File

@ -2,7 +2,9 @@ import {
Class,
Method,
} from '@overflow/commons/core/reflect';
import { ClassType, PropertyKeyType } from '@overflow/commons/core/type';
import {
ClassType, PropertyKeyType, TypeUtil,
} from '@overflow/commons/core/type';
import { ApplicationContext } from './context';
import {
ConfigurationAnnotation,
@ -65,11 +67,12 @@ export class Application {
private createContext(): ApplicationContext {
let clazz: Class = Class.forClassType(this._primaryClass);
let ans = TypeUtil.ancestorsOf(this._primaryClass);
let wa: WebApplicationAnnotation = clazz.getOwnAnnotation(WebApplicationAnnotation);
if (undefined === wa) {
throw new Error(`Class is not WebApplication type. add @WebApplication annotation to class[${this._primaryClass.name}]`);
}
this._applicationContext = new ApplicationContext(wa.attributes.injectables);
this.registerJSONSources(wa.attributes.jsonSources);

View File

@ -14,27 +14,24 @@ import {
} from '@overflow/commons/di/decorators';
export interface ConfigurationAnnotationAttributes {
name?: string[];
name?: string;
}
@Injectable()
export class ConfigurationAnnotation implements Annotation {
public readonly attributes: ConfigurationAnnotationAttributes;
export class ConfigurationAnnotation extends Annotation {
public readonly attributes: ConfigurationAnnotationAttributes = {
};
public constructor(name: string | ConfigurationAnnotationAttributes) {
super();
if (undefined === name) {
this.attributes = {
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: [<string>name],
};
this.attributes.name = <string>name;
} else {
this.attributes = <ConfigurationAnnotationAttributes>name;
this.copyAttributes(this.attributes, <ConfigurationAnnotationAttributes>name);
}
}

View File

@ -16,24 +16,20 @@ export interface InstanceAnnotationAttributes {
name?: InstanceNameType;
}
export class InstanceAnnotation implements Annotation {
public readonly attributes: InstanceAnnotationAttributes;
export class InstanceAnnotation extends Annotation {
public readonly attributes: InstanceAnnotationAttributes = {
};
public constructor(name: InstanceNameType | InstanceNameType[] | InstanceAnnotationAttributes) {
super();
if (undefined === name) {
this.attributes = {
name: null,
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: <InstanceNameType>name,
};
this.attributes.name = <InstanceNameType>name;
} else {
this.attributes = <InstanceAnnotationAttributes>name;
this.copyAttributes(this.attributes, <InstanceAnnotationAttributes>name);
}
}

View File

@ -7,7 +7,16 @@ import {
PropertyKeyType,
} from '@overflow/commons/core/type';
export class RunnerAnnotation implements Annotation {
export interface RunnerAnnotationAttributes {
}
export class RunnerAnnotation extends Annotation {
public readonly attributes: RunnerAnnotationAttributes = {
};
public constructor() {
super();
}
public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType,
descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void {

View File

@ -14,11 +14,13 @@ export interface WebApplicationAnnotationAttributes {
configurations?: ClassType[];
}
export class WebApplicationAnnotation implements Annotation {
public readonly attributes: WebApplicationAnnotationAttributes;
export class WebApplicationAnnotation extends Annotation {
public readonly attributes: WebApplicationAnnotationAttributes = {
};
public constructor(attributes: WebApplicationAnnotationAttributes) {
this.attributes = attributes;
super();
this.copyAttributes(this.attributes, attributes);
}
public classDecorator<TFunction extends Function>(target: TFunction): TFunction | void {

View File

@ -4,7 +4,9 @@ import {
} from '@overflow/commons/core/type';
import {AnnotatedElement} from './annotated_element';
import {Annotation} from './annotation';
import {
Annotation,
} from './annotation';
export abstract class AccessibleObject implements AnnotatedElement {
private _annotations: Map<ClassType, Annotation>;

View File

@ -1,17 +1,30 @@
import {
MetadataKeyType,
PropertyKeyType,
NotSupportedDecoratorError,
TypeUtil,
} from '@overflow/commons/core/type';
export interface Annotation {
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 Annotation {
protected copyAttributes<AttributesType>(destination: AttributesType, source: AttributesType): void {
for (const key in source) {
if (source.hasOwnProperty(key)) {
destination[key] = source[key];
}
}
}
export default Annotation;
public classDecorator<TFunction extends Function>(target: TFunction): TFunction | void {
throw new NotSupportedDecoratorError();
}
public propertyDecorator(target: Object, propertyKey: PropertyKeyType): void {
throw new NotSupportedDecoratorError();
}
public methodDecorator<T>(target: Object, propertyKey: PropertyKeyType,
descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void {
throw new NotSupportedDecoratorError();
}
public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
throw new NotSupportedDecoratorError();
}
}

View File

@ -3,10 +3,13 @@ import {
DecoratorType,
MetadataKeyType,
Metadata,
NotSupportedDecoratorError,
TypeUtil,
} from '@overflow/commons/core/type';
import {Annotation} from './annotation';
import {
Annotation,
} from './annotation';
import {Class} from './class';
import {Constructor} from './constructor';
import {Field} from './field';
@ -35,38 +38,43 @@ export class Decorator {
switch(decoratorType) {
case DecoratorType.CLASS:
if (typeof(annotation.classDecorator) === 'undefined') {
throw new Error(`Cannot apply @${name} decorator on Class.`);
}
try {
cons = clazz._defineConstructor(Metadata.getOwnParamTypes(target));
clazz._addAnnotation(annotation);
return annotation.classDecorator.call(annotation, target);
case DecoratorType.PROPERTY:
if (typeof(annotation.propertyDecorator) === 'undefined') {
throw new Error(`Cannot apply @${name} decorator on Property.`);
} catch (e) {
if (e instanceof NotSupportedDecoratorError) {
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Class.`);
}
throw e;
}
case DecoratorType.PROPERTY:
try {
field = clazz._defineField(propertyKey, Metadata.getOwnType(target, propertyKey));
field._addAnnotation(annotation);
return annotation.propertyDecorator.call(annotation, target, propertyKey);
case DecoratorType.METHOD:
if (typeof(annotation.methodDecorator) === 'undefined') {
throw new Error(`Cannot apply @${name} decorator on Method.`);
} catch (e) {
if (e instanceof NotSupportedDecoratorError) {
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Property.`);
}
throw e;
}
case DecoratorType.METHOD:
try {
method = clazz._defineMethod(propertyKey,
Metadata.getOwnParamTypes(target, propertyKey),
Metadata.getOwnReturnType(target, propertyKey));
method._addAnnotation(annotation);
return annotation.methodDecorator.call(annotation, target, propertyKey, descriptorOrParameterIndex);
case DecoratorType.PARAMETER:
if (typeof(annotation.parameterDecorator) === 'undefined') {
throw new Error(`Cannot apply @${name} decorator on Parameter.`);
} catch (e) {
if (e instanceof NotSupportedDecoratorError) {
throw new NotSupportedDecoratorError(`Cannot apply @${name} decorator on Method.`);
}
throw e;
}
case DecoratorType.PARAMETER:
try {
if (undefined === propertyKey) {
cons = clazz.getConstructor();
parameter = cons.getParameter(descriptorOrParameterIndex);
@ -79,8 +87,14 @@ export class Decorator {
parameter._addAnnotation(annotation);
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;
}
default:
throw new Error(`Cannot determine decorator[@${name}] type.`);
throw new NotSupportedDecoratorError(`Cannot determine decorator[@${name}] type.`);
}
};
};

View File

@ -0,0 +1,6 @@
export class NotSupportedDecoratorError extends Error {
public constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
}

View File

@ -1,3 +1,4 @@
export * from './error';
export * from './metadata';
export * from './type';
export * from './util';

View File

@ -16,23 +16,22 @@ export interface InjectAnnotationAttributes {
name?: InstanceNameType;
}
export class InjectAnnotation implements Annotation {
public readonly attributes: InjectAnnotationAttributes;
export class InjectAnnotation extends Annotation {
public readonly attributes: InjectAnnotationAttributes = {
public constructor(name: InstanceNameType | InstanceNameType[] | InjectAnnotationAttributes) {
};
public constructor(name: InstanceNameType | InjectAnnotationAttributes) {
super();
if (undefined === name) {
this.attributes = {
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: <InstanceNameType>name,
};
this.attributes.name = <InstanceNameType>name;
} else {
this.attributes = <InjectAnnotationAttributes>name;
this.copyAttributes(this.attributes, <InjectAnnotationAttributes>name);
}
}
@ -40,7 +39,7 @@ export class InjectAnnotation implements Annotation {
console.log('Inject');
}
public propertyDecorator?(target: Object, propertyKey: PropertyKeyType): void {
public propertyDecorator(target: Object, propertyKey: PropertyKeyType): void {
console.log('Inject');
}
@ -49,7 +48,7 @@ export class InjectAnnotation implements Annotation {
console.log('Inject');
}
public parameterDecorator?(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
console.log('Inject');
}

View File

@ -16,23 +16,23 @@ export interface InjectableAnnotationAttributes {
name?: InstanceNameType[];
}
export class InjectableAnnotation implements Annotation {
public readonly attributes: InjectableAnnotationAttributes;
export class InjectableAnnotation extends Annotation {
public readonly attributes: InjectableAnnotationAttributes = {
};
public constructor(name: InstanceNameType | InstanceNameType[] | InjectableAnnotationAttributes) {
super();
if (undefined === name) {
this.attributes = {
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: [<InstanceNameType>name],
};
this.attributes.name = [<InstanceNameType>name];
} else if (TypeUtil.isArray(name)) {
this.attributes.name = <InstanceNameType[]>name;
} else {
this.attributes = <InjectableAnnotationAttributes>name;
this.copyAttributes(this.attributes, <InjectableAnnotationAttributes>name);
}
}

View File

@ -12,23 +12,21 @@ export interface PostConstructAnnotationAttributes {
name?: string[];
}
export class PostConstructAnnotation implements Annotation {
public readonly attributes: PostConstructAnnotationAttributes;
export class PostConstructAnnotation extends Annotation {
public readonly attributes: PostConstructAnnotationAttributes = {
};
public constructor(name: string | string[] | PostConstructAnnotationAttributes) {
super();
if (undefined === name) {
this.attributes = {
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: [<string>name],
};
this.attributes.name = [<string>name];
} else {
this.attributes = <PostConstructAnnotationAttributes>name;
this.copyAttributes(this.attributes, <PostConstructAnnotationAttributes>name);
}
}

View File

@ -12,23 +12,21 @@ export interface PreDestroyAnnotationAttributes {
name?: string[];
}
export class PreDestroyAnnotation implements Annotation {
public readonly attributes: PreDestroyAnnotationAttributes;
export class PreDestroyAnnotation extends Annotation {
public readonly attributes: PreDestroyAnnotationAttributes = {
};
public constructor(name: string | string[] | PreDestroyAnnotationAttributes) {
super();
if (undefined === name) {
this.attributes = {
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: [<string>name],
};
this.attributes.name = [<string>name];
} else {
this.attributes = <PreDestroyAnnotationAttributes>name;
this.copyAttributes(this.attributes, <PreDestroyAnnotationAttributes>name);
}
}

View File

@ -16,23 +16,21 @@ export interface ResourceAnnotationAttributes {
name?: InstanceNameType;
}
export class ResourceAnnotation implements Annotation {
public readonly attributes: ResourceAnnotationAttributes;
export class ResourceAnnotation extends Annotation {
public readonly attributes: ResourceAnnotationAttributes = {
name: undefined,
};
public constructor(name: InstanceNameType | ResourceAnnotationAttributes) {
super();
if (undefined === name) {
this.attributes = {
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: <InstanceNameType>name,
};
this.attributes.name = <InstanceNameType>name;
} else {
this.attributes = <ResourceAnnotationAttributes>name;
this.copyAttributes(this.attributes, <ResourceAnnotationAttributes>name);
}
}
@ -40,7 +38,7 @@ export class ResourceAnnotation implements Annotation {
console.log('Resource');
}
public propertyDecorator?(target: Object, propertyKey: PropertyKeyType): void {
public propertyDecorator(target: Object, propertyKey: PropertyKeyType): void {
console.log('Resource');
}
@ -49,7 +47,7 @@ export class ResourceAnnotation implements Annotation {
console.log('Resource');
}
public parameterDecorator?(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
console.log('Resource');
}
}

View File

@ -12,29 +12,29 @@ export interface ValueAnnotationAttributes {
value: string;
}
export class ValueAnnotation implements Annotation {
public readonly attributes: ValueAnnotationAttributes;
export class ValueAnnotation extends Annotation {
public readonly attributes: ValueAnnotationAttributes = {
value: undefined,
};
public constructor(value: string | ValueAnnotationAttributes) {
super();
if (undefined === value) {
throw new Error(`value attribute must be specified.`);
}
if (TypeUtil.isString(value)) {
this.attributes = {
value: <string>value,
};
this.attributes.value = <string>value;
} else {
this.attributes = <ValueAnnotationAttributes>value;
this.copyAttributes(this.attributes, <ValueAnnotationAttributes>value);
}
}
public propertyDecorator?(target: Object, propertyKey: PropertyKeyType): void {
public propertyDecorator(target: Object, propertyKey: PropertyKeyType): void {
console.log('Value');
}
public parameterDecorator?(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void {
console.log('Value');
}
}

View File

@ -12,25 +12,23 @@ export interface ActionMappingAnnotationAttributes {
value: string[];
}
export class ActionMappingAnnotation implements Annotation {
public readonly attributes: ActionMappingAnnotationAttributes;
export class ActionMappingAnnotation extends Annotation {
public readonly attributes: ActionMappingAnnotationAttributes = {
value: undefined,
};
public constructor(value: string | string[] | ActionMappingAnnotationAttributes) {
super();
if (undefined === value) {
throw new Error(`value attribute must be specified.`);
}
if (TypeUtil.isString(value)) {
this.attributes = {
value: [<string>value],
};
this.attributes.value = [<string>value];
} else if (TypeUtil.isArray(value)) {
this.attributes = {
value: <string[]>value,
};
this.attributes.value = <string[]>value;
} else {
this.attributes = <ActionMappingAnnotationAttributes>value;
this.copyAttributes(this.attributes, <ActionMappingAnnotationAttributes>value);
}
}

View File

@ -12,23 +12,21 @@ export interface ReducerAnnotationAttributes {
name?: string;
}
export class ReducerAnnotation implements Annotation {
public readonly attributes: ReducerAnnotationAttributes;
export class ReducerAnnotation extends Annotation {
public readonly attributes: ReducerAnnotationAttributes = {
};
public constructor(name: string | ReducerAnnotationAttributes) {
super();
if (undefined === name) {
this.attributes = {
name: '',
};
return;
}
if (TypeUtil.isString(name)) {
this.attributes = {
name: <string>name,
};
this.attributes.name = <string>name;
} else {
this.attributes = <ReducerAnnotationAttributes>name;
this.copyAttributes(this.attributes, <ReducerAnnotationAttributes>name);
}
}

View File

@ -12,20 +12,21 @@ export interface RestAPIAnnotationAttributes {
entryPath: string;
}
export class RestAPIAnnotation implements Annotation {
public readonly attributes: RestAPIAnnotationAttributes;
export class RestAPIAnnotation extends Annotation {
public readonly attributes: RestAPIAnnotationAttributes = {
entryPath: undefined,
};
public constructor(entryPath: string | RestAPIAnnotationAttributes) {
super();
if (undefined === entryPath) {
throw new Error(`entryPath attribute must be specified.`);
}
if (TypeUtil.isString(entryPath)) {
this.attributes = {
entryPath: <string>entryPath,
};
this.attributes.entryPath = <string>entryPath;
} else {
this.attributes = <RestAPIAnnotationAttributes>entryPath;
this.copyAttributes(this.attributes, <RestAPIAnnotationAttributes>entryPath);
}
}

View File

@ -12,20 +12,21 @@ export interface RpcAPIAnnotationAttributes {
method: string;
}
export class RpcAPIAnnotation implements Annotation {
public readonly attributes: RpcAPIAnnotationAttributes;
export class RpcAPIAnnotation extends Annotation {
public readonly attributes: RpcAPIAnnotationAttributes = {
method: undefined,
};
public constructor(method: string | RpcAPIAnnotationAttributes) {
super();
if (undefined === method) {
throw new Error(`method attribute must be specified.`);
}
if (TypeUtil.isString(method)) {
this.attributes = {
method: <string>method,
};
this.attributes.method = <string>method;
} else {
this.attributes = <RpcAPIAnnotationAttributes>method;
this.copyAttributes(this.attributes, <RpcAPIAnnotationAttributes>method);
}
}

View File

@ -59,11 +59,14 @@ declare global {
const module: { hot: any };
}
class A {
}
class B extends A {
abstract class B {
public abstract b(): void;
}
// abstract class C {
// public abstract c(): void;
// }
@WebApplication({
injectables: injectables,
jsonSources: jsonSources,
@ -74,10 +77,18 @@ class B extends A {
WebAppConfiguration,
],
})
class WebAppApplication extends B {
class WebAppApplication implements B {
private static isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false;
private static useReduxDevTools:boolean = window.devToolsExtension && !WebAppApplication.isProduction ? true : false;
public b(): void {
//
}
public c(): void {
//
}
@Resource()
private containerPromise: Promise<HTMLElement>;
private container: HTMLElement;

View File

@ -1,7 +1,7 @@
import { ClassType } from '@overflow/commons/core/type';
import {
Injectable, Inject, Resource,
Injectable, Inject, Resource, InjectableAnnotation,
} from '@overflow/commons/di/decorators';
import {DispatcherReducer} from '@overflow/commons/redux';