ing
This commit is contained in:
parent
3a5dc4b69f
commit
19621ef090
|
@ -29,7 +29,7 @@
|
||||||
"@ngrx/router-store": "^5.2.0",
|
"@ngrx/router-store": "^5.2.0",
|
||||||
"@ngrx/store": "^5.2.0",
|
"@ngrx/store": "^5.2.0",
|
||||||
"@ngrx/store-devtools": "^5.2.0",
|
"@ngrx/store-devtools": "^5.2.0",
|
||||||
"angular-tree-component": "^7.0.2",
|
"angular-tree-component": "^7.1.0",
|
||||||
"angularx-qrcode": "^1.0.1",
|
"angularx-qrcode": "^1.0.1",
|
||||||
"angular-l10n": "^4.1.5",
|
"angular-l10n": "^4.1.5",
|
||||||
"core-js": "^2.5.3",
|
"core-js": "^2.5.3",
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
"ngx-cookie-service": "^1.0.10",
|
"ngx-cookie-service": "^1.0.10",
|
||||||
"ngx-perfect-scrollbar": "^5.3.1",
|
"ngx-perfect-scrollbar": "^5.3.1",
|
||||||
"nvd3": "^1.8.6",
|
"nvd3": "^1.8.6",
|
||||||
|
"reflect-metadata": "^0.1.12",
|
||||||
"rxjs": "^5.5.6",
|
"rxjs": "^5.5.6",
|
||||||
"zone.js": "^0.8.20",
|
"zone.js": "^0.8.20",
|
||||||
"ip-cidr": "^1.1.2"
|
"ip-cidr": "^1.1.2"
|
||||||
|
|
6
src/@loafer/core/error.ts
Normal file
6
src/@loafer/core/error.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export class IllegalArgumentError extends Error {
|
||||||
|
public constructor(message?: string) {
|
||||||
|
super(message);
|
||||||
|
Object.setPrototypeOf(this, new.target.prototype);
|
||||||
|
}
|
||||||
|
}
|
1
src/@loafer/core/index.ts
Normal file
1
src/@loafer/core/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './type';
|
64
src/@loafer/core/reflect/AccessibleObject.ts
Normal file
64
src/@loafer/core/reflect/AccessibleObject.ts
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import {
|
||||||
|
TypeUtil,
|
||||||
|
} from '../util/TypeUtil';
|
||||||
|
|
||||||
|
import { AnnotatedElement } from './AnnotatedElement';
|
||||||
|
import { Annotation } from './Annotation';
|
||||||
|
|
||||||
|
export abstract class AccessibleObject implements AnnotatedElement {
|
||||||
|
private _annotations: Map<Type<any>, Annotation>;
|
||||||
|
|
||||||
|
protected constructor() {
|
||||||
|
this._annotations = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
public _addAnnotation<AnnotationType extends Annotation>(annotation: AnnotationType): void {
|
||||||
|
this._annotations.set(TypeUtil.getType(annotation), annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAnnotationPresent<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): boolean {
|
||||||
|
return null !== this.getAnnotation(annotationClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOwnAnnotation<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType | undefined {
|
||||||
|
return <AnnotationType>this._annotations.get(annotationClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOwnAnnotations(): Map<Type<any>, Annotation> {
|
||||||
|
return this._annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOwnAnnotationsByType<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>)
|
||||||
|
: AnnotationType[] | undefined {
|
||||||
|
if (0 === this._annotations.size) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const results: AnnotationType[] = [];
|
||||||
|
for (const classType of Array.from(this._annotations.keys())) {
|
||||||
|
if (classType === annotationClass) {
|
||||||
|
results.push(<AnnotationType>this._annotations.get(classType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 === results.length) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAnnotation<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType | undefined {
|
||||||
|
return this.getOwnAnnotation(annotationClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAnnotations(): Map<Type<any>, Annotation> {
|
||||||
|
return this.getOwnAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAnnotationsByType<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>)
|
||||||
|
: AnnotationType[] | undefined {
|
||||||
|
return this.getOwnAnnotationsByType(annotationClass);
|
||||||
|
}
|
||||||
|
}
|
17
src/@loafer/core/reflect/AnnotatedElement.ts
Normal file
17
src/@loafer/core/reflect/AnnotatedElement.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import { Annotation } from './Annotation';
|
||||||
|
|
||||||
|
export interface AnnotatedElement {
|
||||||
|
_addAnnotation<AnnotationType extends Annotation>(annotation: AnnotationType): void;
|
||||||
|
|
||||||
|
isAnnotationPresent<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): boolean;
|
||||||
|
getOwnAnnotation<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType | undefined;
|
||||||
|
getOwnAnnotations(): Map<Type<any>, Annotation>;
|
||||||
|
getOwnAnnotationsByType<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType[] | undefined;
|
||||||
|
getAnnotation<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType | undefined;
|
||||||
|
getAnnotations(): Map<Type<any>, Annotation>;
|
||||||
|
getAnnotationsByType<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType[] | undefined;
|
||||||
|
}
|
7
src/@loafer/core/reflect/Annotation.ts
Normal file
7
src/@loafer/core/reflect/Annotation.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export abstract class Annotation<Attribute = {}> {
|
||||||
|
public readonly attribute: Attribute;
|
||||||
|
|
||||||
|
public constructor(attribute?: Attribute) {
|
||||||
|
this.attribute = attribute;
|
||||||
|
}
|
||||||
|
}
|
228
src/@loafer/core/reflect/Class.ts
Normal file
228
src/@loafer/core/reflect/Class.ts
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import {
|
||||||
|
TypeUtil,
|
||||||
|
} from '../util/TypeUtil';
|
||||||
|
|
||||||
|
import { AccessibleObject } from './AccessibleObject';
|
||||||
|
import { Annotation } from './Annotation';
|
||||||
|
import { SystemClassRegistry } from './ClassRegistry';
|
||||||
|
import { Constructor } from './Constructor';
|
||||||
|
import { Field } from './Field';
|
||||||
|
import { Method } from './Method';
|
||||||
|
import { Metadata } from './Metadata';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export class Class extends AccessibleObject {
|
||||||
|
private _type: Type<any>;
|
||||||
|
private _constructor: Constructor;
|
||||||
|
private _fields: Map<PropertyKeyType, Field>;
|
||||||
|
private _methods: Map<PropertyKeyType, Method>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* forClass
|
||||||
|
*/
|
||||||
|
public static forType(type: Type<any>): Class | undefined {
|
||||||
|
return SystemClassRegistry.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _defineClass
|
||||||
|
*/
|
||||||
|
public static _defineClass(type: Type<any>): Class {
|
||||||
|
let clazz: Class = Class.forType(type);
|
||||||
|
if (undefined === clazz) {
|
||||||
|
clazz = new Class(type);
|
||||||
|
SystemClassRegistry.set(type, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === clazz._constructor) {
|
||||||
|
const parameterTypes = Metadata.getOwnParamTypes(type);
|
||||||
|
if (undefined !== parameterTypes) {
|
||||||
|
clazz._constructor = new Constructor(clazz, parameterTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(type: Type<any>) {
|
||||||
|
super();
|
||||||
|
this._type = type;
|
||||||
|
this._fields = new Map();
|
||||||
|
this._methods = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _defineField
|
||||||
|
*/
|
||||||
|
public _defineConstructor(parameterTypes: any[]): Constructor {
|
||||||
|
let cons: Constructor = this._constructor;
|
||||||
|
if (undefined === cons) {
|
||||||
|
cons = new Constructor(this, parameterTypes);
|
||||||
|
this._constructor = cons;
|
||||||
|
}
|
||||||
|
return cons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _defineField
|
||||||
|
*/
|
||||||
|
public _defineField(propertyKey: PropertyKeyType, propertyType: any): Field {
|
||||||
|
let field: Field = this._fields.get(propertyKey);
|
||||||
|
if (undefined === field) {
|
||||||
|
field = new Field(this, propertyKey, propertyType);
|
||||||
|
this._fields.set(propertyKey, field);
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _defineMethod
|
||||||
|
*/
|
||||||
|
public _defineMethod(propertyKey: PropertyKeyType, parameterTypes: any[], returnType: any): Method {
|
||||||
|
let method: Method = this._methods.get(propertyKey);
|
||||||
|
if (undefined === method) {
|
||||||
|
method = new Method(this, propertyKey, parameterTypes, returnType);
|
||||||
|
this._methods.set(propertyKey, method);
|
||||||
|
}
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getType(): Type<any> {
|
||||||
|
return this._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getConstructor(): Constructor {
|
||||||
|
if (undefined === this._constructor) {
|
||||||
|
this._constructor = new Constructor(this, undefined);
|
||||||
|
}
|
||||||
|
return this._constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOwnField(propertyKey: PropertyKeyType): Field | undefined {
|
||||||
|
return this._fields.get(propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOwnFields(): Map<PropertyKeyType, Field> {
|
||||||
|
return this._fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getField(propertyKey: PropertyKeyType): Field | undefined {
|
||||||
|
const fields = this.getFields();
|
||||||
|
|
||||||
|
return fields.get(propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getFields(): Map<PropertyKeyType, Field> {
|
||||||
|
const fields: Map<PropertyKeyType, Field> = new Map();
|
||||||
|
|
||||||
|
const types = TypeUtil.ancestorsOf(this._type);
|
||||||
|
if (null === types || 0 === types.length) {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < types.length; i++) {
|
||||||
|
const tType = types[i];
|
||||||
|
const tClazz = Class.forType(tType);
|
||||||
|
if (undefined === tClazz) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tClazz.getOwnFields().forEach((value: Field, key: PropertyKeyType, map: Map<PropertyKeyType, Field>): void => {
|
||||||
|
fields.set(key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOwnMethod(propertyKey: PropertyKeyType): Method | undefined {
|
||||||
|
return this._methods.get(propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOwnMethods(): Map<PropertyKeyType, Method> {
|
||||||
|
return this._methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMethod(propertyKey: PropertyKeyType): Method | undefined {
|
||||||
|
const methods = this.getMethods();
|
||||||
|
|
||||||
|
return methods.get(propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMethods(): Map<PropertyKeyType, Method> {
|
||||||
|
const methods: Map<PropertyKeyType, Method> = new Map();
|
||||||
|
|
||||||
|
const types = TypeUtil.ancestorsOf(this._type);
|
||||||
|
if (null === types || 0 === types.length) {
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < types.length; i++) {
|
||||||
|
const tClazzType = types[i];
|
||||||
|
const tClazz = Class.forType(tClazzType);
|
||||||
|
if (undefined === tClazz) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tClazz.getOwnMethods().forEach((value: Method, key: PropertyKeyType, map: Map<PropertyKeyType, Method>): void => {
|
||||||
|
methods.set(key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAnnotation<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>): AnnotationType | undefined {
|
||||||
|
const annotations = this.getAnnotations();
|
||||||
|
|
||||||
|
return <AnnotationType>annotations.get(annotationClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAnnotations(): Map<Type<any>, Annotation> {
|
||||||
|
const annotations: Map<Type<any>, Annotation> = new Map();
|
||||||
|
|
||||||
|
const types = TypeUtil.ancestorsOf(this._type);
|
||||||
|
if (null === types || 0 === types.length) {
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < types.length; i++) {
|
||||||
|
const tClazzType = types[i];
|
||||||
|
const tClazz = Class.forType(tClazzType);
|
||||||
|
if (undefined === tClazz) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tClazz.getOwnAnnotations().forEach((value: Annotation, key: Type<any>, map: Map<Type<any>, Annotation>): void => {
|
||||||
|
annotations.set(key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAnnotationsByType<AnnotationType extends Annotation>(annotationClass: Type<AnnotationType>)
|
||||||
|
: AnnotationType[] | undefined {
|
||||||
|
const annotations = this.getAnnotations();
|
||||||
|
if (0 === annotations.size) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const results: AnnotationType[] = [];
|
||||||
|
for (const classType of Array.from(annotations.keys())) {
|
||||||
|
if (classType === annotationClass) {
|
||||||
|
results.push(<AnnotationType>annotations.get(classType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 === results.length) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getName(): string {
|
||||||
|
return this._type.name;
|
||||||
|
}
|
||||||
|
}
|
12
src/@loafer/core/reflect/ClassRegistry.ts
Normal file
12
src/@loafer/core/reflect/ClassRegistry.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Type } from '../type';
|
||||||
|
import { Registry } from '../util/Registry';
|
||||||
|
|
||||||
|
import { Class } from './Class';
|
||||||
|
|
||||||
|
export class ClassRegistry extends Registry<Type<any>, Class> {
|
||||||
|
public constructor(parent?: ClassRegistry) {
|
||||||
|
super(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SystemClassRegistry = new ClassRegistry();
|
26
src/@loafer/core/reflect/Constructor.ts
Normal file
26
src/@loafer/core/reflect/Constructor.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import {
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import {
|
||||||
|
TypeUtil,
|
||||||
|
} from '../util/TypeUtil';
|
||||||
|
|
||||||
|
import { Class } from './Class';
|
||||||
|
import { Executable } from './Executable';
|
||||||
|
|
||||||
|
export class Constructor extends Executable {
|
||||||
|
private _rawConstructor: Function;
|
||||||
|
|
||||||
|
public constructor(declaringClazz: Class, parameterTypes?: any[]) {
|
||||||
|
super(declaringClazz, CONSTRUCTOR_NAME, parameterTypes);
|
||||||
|
this._rawConstructor = TypeUtil.getPrototype(declaringClazz.getType())[CONSTRUCTOR_NAME];
|
||||||
|
}
|
||||||
|
|
||||||
|
public newInstance(...args: any[]): any {
|
||||||
|
const ctor = this.getDeclaringClass().getType();
|
||||||
|
return new (ctor.bind.apply(ctor, [null].concat(args)))();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CONSTRUCTOR_NAME = 'constructor';
|
75
src/@loafer/core/reflect/Executable.ts
Normal file
75
src/@loafer/core/reflect/Executable.ts
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
import {
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import {
|
||||||
|
TypeUtil,
|
||||||
|
} from '../util/TypeUtil';
|
||||||
|
|
||||||
|
import { AccessibleObject } from './AccessibleObject';
|
||||||
|
import { Class } from './Class';
|
||||||
|
import { Member } from './Member';
|
||||||
|
import { Parameter } from './Parameter';
|
||||||
|
|
||||||
|
export abstract class Executable extends AccessibleObject implements Member {
|
||||||
|
private _clazz: Class;
|
||||||
|
private _name: PropertyKeyType;
|
||||||
|
private _parameters: Parameter[];
|
||||||
|
|
||||||
|
protected constructor(declaringClazz: Class, name: PropertyKeyType, parameterTypes?: any[]) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._clazz = declaringClazz;
|
||||||
|
this._name = name;
|
||||||
|
|
||||||
|
if (undefined === parameterTypes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parameterNames = TypeUtil.getParameterNames(declaringClazz.getType(), name);
|
||||||
|
this._parameters = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < parameterTypes.length; i++) {
|
||||||
|
const parameterType = parameterTypes[i];
|
||||||
|
const parameterName = parameterNames[i];
|
||||||
|
const parameter: Parameter = new Parameter(this, parameterType, parameterName, i);
|
||||||
|
this._parameters.push(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDeclaringClass(): Class {
|
||||||
|
return this._clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getName(): PropertyKeyType {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getParameterCount
|
||||||
|
*/
|
||||||
|
public getParameterCount(): number {
|
||||||
|
if (null === this._parameters) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return this._parameters.length;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* getParameters
|
||||||
|
*/
|
||||||
|
public getParameters(): Parameter[] | undefined {
|
||||||
|
return this._parameters;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* getParameter
|
||||||
|
*/
|
||||||
|
public getParameter(index: number): Parameter | undefined {
|
||||||
|
if (null === this._parameters) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (0 > index || this._parameters.length <= index) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this._parameters[index];
|
||||||
|
}
|
||||||
|
}
|
33
src/@loafer/core/reflect/Field.ts
Normal file
33
src/@loafer/core/reflect/Field.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import {
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import { AccessibleObject } from './AccessibleObject';
|
||||||
|
import { Class } from './Class';
|
||||||
|
import { Member } from './Member';
|
||||||
|
|
||||||
|
export class Field extends AccessibleObject implements Member {
|
||||||
|
private _clazz: Class;
|
||||||
|
private _name: PropertyKeyType;
|
||||||
|
private _type: any;
|
||||||
|
|
||||||
|
public constructor(declaringClazz: Class, name: PropertyKeyType, fieldType: any) {
|
||||||
|
super();
|
||||||
|
this._clazz = declaringClazz;
|
||||||
|
this._name = name;
|
||||||
|
this._type = fieldType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDeclaringClass(): Class {
|
||||||
|
return this._clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getName(): PropertyKeyType {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getType(): any {
|
||||||
|
return this._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
src/@loafer/core/reflect/Member.ts
Normal file
10
src/@loafer/core/reflect/Member.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import {
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import { Class } from './Class';
|
||||||
|
|
||||||
|
export interface Member {
|
||||||
|
getDeclaringClass(): Class;
|
||||||
|
getName(): PropertyKeyType;
|
||||||
|
}
|
521
src/@loafer/core/reflect/Metadata.ts
Normal file
521
src/@loafer/core/reflect/Metadata.ts
Normal file
|
@ -0,0 +1,521 @@
|
||||||
|
import {
|
||||||
|
MetadataKeyType,
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import { TypeUtil } from '../util/TypeUtil';
|
||||||
|
|
||||||
|
|
||||||
|
export class Metadata {
|
||||||
|
/**
|
||||||
|
* Gets the metadata value for the provided metadata key on the target object or its prototype chain.
|
||||||
|
* @param key A key used to store and retrieve metadata.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // constructor
|
||||||
|
* result = Metadata.get("custom:annotation", Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.get("custom:annotation", Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // property (on prototype)
|
||||||
|
* result = Metadata.get("custom:annotation", Example.prototype, "property");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.get("custom:annotation", Example, "staticMethod");
|
||||||
|
*
|
||||||
|
* // method (on prototype)
|
||||||
|
* result = Metadata.get("custom:annotation", Example.prototype, "method");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static get(key: MetadataKeyType, target: any, propertyKey?: PropertyKeyType): any {
|
||||||
|
return Reflect.getMetadata(key, TypeUtil.getType(target), propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata value for the provided metadata key on the target object or its prototype chain.
|
||||||
|
* @param key A key used to store and retrieve metadata.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // constructor
|
||||||
|
* result = Metadata.getOwn("custom:annotation", Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.getOwn("custom:annotation", Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // property (on prototype)
|
||||||
|
* result = Metadata.getOwn("custom:annotation", Example.prototype, "property");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.getOwn("custom:annotation", Example, "staticMethod");
|
||||||
|
*
|
||||||
|
* // method (on prototype)
|
||||||
|
* result = Metadata.getOwn("custom:annotation", Example.prototype, "method");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static getOwn(key: MetadataKeyType, target: any, propertyKey?: PropertyKeyType): any {
|
||||||
|
return Reflect.getOwnMetadata(key, TypeUtil.getType(target), propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata value for the provided metadata DESIGN_TYPE on the target object or its prototype chain.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // on contructor
|
||||||
|
* result = Metadata.getType(Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.getType(Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.getType(Example, "staticMethod");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static getType(target: any, propertyKey?: PropertyKeyType): any {
|
||||||
|
return Reflect.getMetadata(DESIGN_TYPE, target, propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata value for the provided metadata DESIGN_TYPE on the target object or its prototype chain.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // on contructor
|
||||||
|
* result = Metadata.getOwnType(Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.getOwnType(Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.getOwnType(Example, "staticMethod");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static getOwnType(target: any, propertyKey?: PropertyKeyType): any {
|
||||||
|
return Reflect.getMetadata(DESIGN_TYPE, target, propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata value for the provided metadata DESIGN_RETURN_TYPE on the target object or its prototype chain.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // on contructor
|
||||||
|
* result = Metadata.getReturnType(Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.getReturnType(Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.getReturnType(Example, "staticMethod");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static getReturnType(target: any, propertyKey?: PropertyKeyType): any {
|
||||||
|
return Reflect.getMetadata(DESIGN_RETURN_TYPE, target, propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata value for the provided metadata DESIGN_RETURN_TYPE on the target object or its prototype chain.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // on contructor
|
||||||
|
* result = Metadata.getOwnReturnType(Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.getOwnReturnType(Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.getOwnReturnType(Example, "staticMethod");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static getOwnReturnType(target: any, propertyKey?: PropertyKeyType): any {
|
||||||
|
return Reflect.getOwnMetadata(DESIGN_RETURN_TYPE, target, propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined.
|
||||||
|
* @param key A key used to store and retrieve metadata.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // constructor
|
||||||
|
* result = Metadata.has("custom:annotation", Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.has("custom:annotation", Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // property (on prototype)
|
||||||
|
* result = Metadata.has("custom:annotation", Example.prototype, "property");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.has("custom:annotation", Example, "staticMethod");
|
||||||
|
*
|
||||||
|
* // method (on prototype)
|
||||||
|
* result = Metadata.has("custom:annotation", Example.prototype, "method");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static has(key: MetadataKeyType, target: any, propertyKey?: PropertyKeyType): boolean {
|
||||||
|
return Reflect.hasMetadata(key, TypeUtil.getType(target), propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined.
|
||||||
|
* @param key A key used to store and retrieve metadata.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // constructor
|
||||||
|
* result = Metadata.has("custom:annotation", Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.hasOwn("custom:annotation", Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // property (on prototype)
|
||||||
|
* result = Metadata.hasOwn("custom:annotation", Example.prototype, "property");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.hasOwn("custom:annotation", Example, "staticMethod");
|
||||||
|
*
|
||||||
|
* // method (on prototype)
|
||||||
|
* result = Metadata.hasOwn("custom:annotation", Example.prototype, "method");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static hasOwn(key: MetadataKeyType, target: any, propertyKey?: PropertyKeyType): boolean {
|
||||||
|
return Reflect.hasOwnMetadata(key, TypeUtil.getType(target), propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the metadata entry from the target object with the provided key.
|
||||||
|
* @param key A key used to store and retrieve metadata.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns `true` if the metadata entry was found and deleted; otherwise, false.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // constructor
|
||||||
|
* result = Metadata.delete("custom:annotation", Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.delete("custom:annotation", Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // property (on prototype)
|
||||||
|
* result = Metadata.delete("custom:annotation", Example.prototype, "property");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.delete("custom:annotation", Example, "staticMethod");
|
||||||
|
*
|
||||||
|
* // method (on prototype)
|
||||||
|
* result = Metadata.delete("custom:annotation", Example.prototype, "method");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static delete(key: MetadataKeyType, target: any, propertyKey?: PropertyKeyType): boolean {
|
||||||
|
return Reflect.deleteMetadata(key, TypeUtil.getType(target), propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the metadata value for the provided metadata DESIGN_PARAM_TYPES on the target object or its prototype chain.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @param value A value that contains attached metadata.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // on contructor
|
||||||
|
* result = Metadata.setParamTypes(Example, undefined, [Object]);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.setParamTypes(Example, "staticProperty", [Object]);
|
||||||
|
*
|
||||||
|
* // property (on prototype)
|
||||||
|
* result = Metadata.setParamTypes(Example.prototype, "property", [Object]);
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.setParamTypes(Example, "staticMethod", [Object]);
|
||||||
|
*
|
||||||
|
* // method (on prototype)
|
||||||
|
* result = Metadata.setParamTypes(Example.prototype, "method", [Object]);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static setParamTypes(target: any, propertyKey: PropertyKeyType, value: any): void {
|
||||||
|
return this.set(DESIGN_PARAM_TYPES, value, target.prototype, propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all metadata for a metadataKey.
|
||||||
|
* @param metadataKey
|
||||||
|
*/
|
||||||
|
public static getTargetsFromPropertyKey = (metadataKey: MetadataKeyType): any[] =>
|
||||||
|
PROPERTIES.has(metadataKey) ? PROPERTIES.get(metadataKey) || [] : []
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a unique metadata entry on the target.
|
||||||
|
* @param key A key used to store and retrieve metadata.
|
||||||
|
* @param value A value that contains attached metadata.
|
||||||
|
* @param target The target object on which to define metadata.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // constructor
|
||||||
|
* Reflect.defineMetadata("custom:annotation", options, Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* Reflect.defineMetadata("custom:annotation", Number, Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // property (on prototype)
|
||||||
|
* Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "property");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* Reflect.defineMetadata("custom:annotation", Number, Example, "staticMethod");
|
||||||
|
*
|
||||||
|
* // method (on prototype)
|
||||||
|
* Reflect.defineMetadata("custom:annotation", Number, Example.prototype, "method");
|
||||||
|
*
|
||||||
|
* // decorator factory as metadata-producing annotation.
|
||||||
|
* function MyAnnotation(options): PropertyDecorator {
|
||||||
|
* return (target, key) => Reflect.defineMetadata("custom:annotation", options, target, key);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static set(key: MetadataKeyType, value: any, target: any, propertyKey?: PropertyKeyType): void {
|
||||||
|
|
||||||
|
const targets: any[] = PROPERTIES.has(key) ? PROPERTIES.get(key) || [] : [];
|
||||||
|
const classConstructor = TypeUtil.getType(target);
|
||||||
|
|
||||||
|
if (targets.indexOf(classConstructor) === -1) {
|
||||||
|
targets.push(classConstructor);
|
||||||
|
PROPERTIES.set(key, targets);
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflect.defineMetadata(key, value, TypeUtil.getType(target), propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata value for the provided metadata DESIGN_PARAM_TYPES on the target object or its prototype chain.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // on contructor
|
||||||
|
* result = Metadata.getParamTypes(Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.getParamTypes(Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.getParamTypes(Example, "staticMethod");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static getParamTypes(target: any, propertyKey?: PropertyKeyType): any[] {
|
||||||
|
return Reflect.getMetadata(DESIGN_PARAM_TYPES, target, propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the metadata value for the provided metadata DESIGN_PARAM_TYPES on the target object or its prototype chain.
|
||||||
|
* @param target The target object on which the metadata is defined.
|
||||||
|
* @param propertyKey The property key for the target.
|
||||||
|
* @returns The metadata value for the metadata key if found; otherwise, `undefined`.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* class Example {
|
||||||
|
* // property declarations are not part of ES6, though they are valid in TypeScript:
|
||||||
|
* // static staticProperty;
|
||||||
|
* // property;
|
||||||
|
*
|
||||||
|
* static staticMethod(p) { }
|
||||||
|
* method(p) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // on contructor
|
||||||
|
* result = Metadata.getParamTypes(Example);
|
||||||
|
*
|
||||||
|
* // property (on constructor)
|
||||||
|
* result = Metadata.getParamTypes(Example, "staticProperty");
|
||||||
|
*
|
||||||
|
* // method (on constructor)
|
||||||
|
* result = Metadata.getParamTypes(Example, "staticMethod");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static getOwnParamTypes(target: any, propertyKey?: PropertyKeyType): any[] {
|
||||||
|
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[]>();
|
29
src/@loafer/core/reflect/Method.ts
Normal file
29
src/@loafer/core/reflect/Method.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import {
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
import {
|
||||||
|
TypeUtil,
|
||||||
|
} from '../util/TypeUtil';
|
||||||
|
|
||||||
|
import { Class } from './Class';
|
||||||
|
import { Executable } from './Executable';
|
||||||
|
|
||||||
|
export class Method extends Executable {
|
||||||
|
private _returnType: any;
|
||||||
|
private _rawMethod: Function;
|
||||||
|
|
||||||
|
public constructor(declaringClazz: Class, name: PropertyKeyType, parameterTypes: any[], returnType: any) {
|
||||||
|
super(declaringClazz, name, parameterTypes);
|
||||||
|
this._returnType = returnType;
|
||||||
|
this._rawMethod = TypeUtil.getPrototype(declaringClazz.getType())[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getReturnType(): any {
|
||||||
|
return this._returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public invoke(instance: Object, ...args: any[]): any {
|
||||||
|
return this._rawMethod.apply(instance, args);
|
||||||
|
}
|
||||||
|
}
|
33
src/@loafer/core/reflect/Parameter.ts
Normal file
33
src/@loafer/core/reflect/Parameter.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { AccessibleObject } from './AccessibleObject';
|
||||||
|
import { Executable } from './Executable';
|
||||||
|
|
||||||
|
export class Parameter extends AccessibleObject {
|
||||||
|
private _executable: Executable;
|
||||||
|
private _type: any;
|
||||||
|
private _index: number;
|
||||||
|
private _name: string;
|
||||||
|
|
||||||
|
public constructor(executable: Executable, parameterType: any, name: string, index: number) {
|
||||||
|
super();
|
||||||
|
this._executable = executable;
|
||||||
|
this._type = parameterType;
|
||||||
|
this._name = name;
|
||||||
|
this._index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDeclaringExecutable(): Executable {
|
||||||
|
return this._executable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getType(): any {
|
||||||
|
return this._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getName(): string {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getIndex(): number {
|
||||||
|
return this._index;
|
||||||
|
}
|
||||||
|
}
|
12
src/@loafer/core/reflect/index.ts
Normal file
12
src/@loafer/core/reflect/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export * from './AccessibleObject';
|
||||||
|
export * from './AnnotatedElement';
|
||||||
|
export * from './Annotation';
|
||||||
|
export * from './Class';
|
||||||
|
export * from './Constructor';
|
||||||
|
|
||||||
|
export * from './Executable';
|
||||||
|
export * from './Field';
|
||||||
|
export * from './Member';
|
||||||
|
export * from './Metadata';
|
||||||
|
export * from './Method';
|
||||||
|
export * from './Parameter';
|
16
src/@loafer/core/type.ts
Normal file
16
src/@loafer/core/type.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
export declare const Type: FunctionConstructor;
|
||||||
|
export declare function isType(v: any): v is Type<any>;
|
||||||
|
export interface Type<T> extends Function {
|
||||||
|
new (...args: any[]): T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type IdentityType<T> = T | symbol;
|
||||||
|
export declare type PropertyKeyType = IdentityType<string>;
|
||||||
|
export declare type MetadataKeyType = IdentityType<string>;
|
||||||
|
|
||||||
|
export enum PrimitiveType {
|
||||||
|
ANY = 'any',
|
||||||
|
STRING = 'string',
|
||||||
|
NUMBER = 'number',
|
||||||
|
BOOLEAN = 'boolean',
|
||||||
|
}
|
39
src/@loafer/core/util/AnnotationUtil.ts
Normal file
39
src/@loafer/core/util/AnnotationUtil.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { Class, Annotation } from '../reflect';
|
||||||
|
import { Type } from '../type';
|
||||||
|
|
||||||
|
export abstract class AnnotationUtils {
|
||||||
|
public static hasAnnotation<T extends Annotation>(type: Type<any>, annotationClass: Type<T>): boolean {
|
||||||
|
const annotation = AnnotationUtils.getAnnotation(type, annotationClass);
|
||||||
|
if (undefined !== annotation) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getAnnotation<T extends Annotation>(type: Type<any>, annotationClass: Type<T>): T | undefined {
|
||||||
|
const clazz = Class.forType(type);
|
||||||
|
if (undefined === clazz) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const annotations = clazz.getAnnotations();
|
||||||
|
if (0 === annotations.size) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const annonClassType of Array.from(annotations.keys())) {
|
||||||
|
if (annonClassType === annotationClass) {
|
||||||
|
return <T>annotations.get(annonClassType);
|
||||||
|
}
|
||||||
|
const annotation = AnnotationUtils.getAnnotation(annonClassType, annotationClass);
|
||||||
|
if (undefined !== annotation) {
|
||||||
|
return annotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
66
src/@loafer/core/util/Registry.ts
Normal file
66
src/@loafer/core/util/Registry.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
export abstract class Registry<K, V> {
|
||||||
|
private _parent: Registry<K, V>;
|
||||||
|
private _map: Map<K, V>;
|
||||||
|
|
||||||
|
protected constructor(parent?: Registry<K, V>) {
|
||||||
|
this._parent = parent;
|
||||||
|
this._map = new Map<K, V>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get parent(): Registry<K, V> | undefined {
|
||||||
|
return this._parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get size(): number {
|
||||||
|
return this._map.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(key: K): V | undefined {
|
||||||
|
let v = this._map.get(key);
|
||||||
|
if (undefined === v && undefined !== this._parent) {
|
||||||
|
v = this._parent.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public has(key: K): boolean {
|
||||||
|
let exist = this._map.has(key);
|
||||||
|
if (!exist && undefined !== this._parent) {
|
||||||
|
exist = this._parent.has(key);
|
||||||
|
}
|
||||||
|
return exist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(key: K, value: V): void {
|
||||||
|
this._map.set(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public entries(): IterableIterator<[K, V]> {
|
||||||
|
return this._map.entries();
|
||||||
|
}
|
||||||
|
|
||||||
|
public keys(): IterableIterator<K> {
|
||||||
|
return this._map.keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
public values(): IterableIterator<V> {
|
||||||
|
return this._map.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear(): void {
|
||||||
|
this._map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public delete(key: K): boolean {
|
||||||
|
let result = this._map.delete(key);
|
||||||
|
if (!result && undefined !== this._parent) {
|
||||||
|
result = this._parent.delete(key);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public forEach(callback: (vlaue: V, key: K, map: Map<K, V>) => void, thisArg?: any): void {
|
||||||
|
this._map.forEach(callback, thisArg);
|
||||||
|
}
|
||||||
|
}
|
407
src/@loafer/core/util/TypeUtil.ts
Normal file
407
src/@loafer/core/util/TypeUtil.ts
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
PrimitiveType,
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '../type';
|
||||||
|
|
||||||
|
|
||||||
|
export class TypeUtil {
|
||||||
|
/**
|
||||||
|
* Get the provide constructor.
|
||||||
|
* @param target
|
||||||
|
*/
|
||||||
|
public static getContructor<T>(target: any): Type<T> {
|
||||||
|
return typeof target === 'function' ? target : target.constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the provide constructor if target is an instance.
|
||||||
|
* @param target
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
public static getType<T>(target: any): Type<T> {
|
||||||
|
return target.prototype ? target : target.constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the provide prototype if target is an instance.
|
||||||
|
* @param target
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
public static getPrototype(target: any): Object {
|
||||||
|
return typeof target === 'function' ? target.prototype : target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {symbol}
|
||||||
|
*/
|
||||||
|
public static getTypeOrSymbol(target: any): any {
|
||||||
|
return typeof target === 'symbol' ? target : TypeUtil.getType(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the given obj is a primitive.
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isPrimitiveOrPrimitiveType(target: any): boolean {
|
||||||
|
return TypeUtil.isString(target)
|
||||||
|
|| TypeUtil.isNumber(target)
|
||||||
|
|| TypeUtil.isBoolean(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {PrimitiveType}
|
||||||
|
*/
|
||||||
|
public static primitiveOf(target: any): PrimitiveType {
|
||||||
|
if (TypeUtil.isString(target)) {
|
||||||
|
return PrimitiveType.STRING;
|
||||||
|
}
|
||||||
|
if (TypeUtil.isNumber(target)) {
|
||||||
|
return PrimitiveType.NUMBER;
|
||||||
|
}
|
||||||
|
if (TypeUtil.isBoolean(target)) {
|
||||||
|
return PrimitiveType.BOOLEAN;
|
||||||
|
}
|
||||||
|
return PrimitiveType.ANY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isString(target: any): boolean {
|
||||||
|
return typeof target === 'string' || target instanceof String || target === String;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isNumber(target: any): boolean {
|
||||||
|
return typeof target === 'number' || target instanceof Number || target === Number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isBoolean(target: any): boolean {
|
||||||
|
return typeof target === 'boolean' || target instanceof Boolean || target === Boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
public static isArray(target: any): boolean {
|
||||||
|
return Array.isArray(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the clazz is an array.
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isArrayOrArrayType(target: any): boolean {
|
||||||
|
if (target === Array) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return TypeUtil.isArray(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the target.
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isCollection(target: any): boolean {
|
||||||
|
return TypeUtil.isArrayOrArrayType(target)
|
||||||
|
|| target === Map
|
||||||
|
|| target instanceof Map
|
||||||
|
|| target === Set
|
||||||
|
|| target instanceof Set
|
||||||
|
|| target === WeakMap
|
||||||
|
|| target instanceof WeakMap
|
||||||
|
|| target === WeakSet
|
||||||
|
|| target instanceof WeakSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isDate(target: any): boolean {
|
||||||
|
return target === Date || target instanceof Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isMethod(target: any, propertyKey: PropertyKeyType): boolean {
|
||||||
|
if (typeof(target[propertyKey]) === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return typeof target[propertyKey] === 'function';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isObject(target: any): boolean {
|
||||||
|
return target === Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isType(target: any): boolean {
|
||||||
|
return !TypeUtil.isPrimitiveOrPrimitiveType(target)
|
||||||
|
&& !TypeUtil.isObject(target)
|
||||||
|
&& !TypeUtil.isDate(target)
|
||||||
|
&& target !== undefined
|
||||||
|
&& !TypeUtil.isPromise(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the value is an empty string, null or undefined.
|
||||||
|
* @param value
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isEmpty(value: any): boolean {
|
||||||
|
return value === '' || value === null || value === undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get object name
|
||||||
|
*/
|
||||||
|
public static nameOf(obj: any): string {
|
||||||
|
switch (typeof obj) {
|
||||||
|
default:
|
||||||
|
return '' + obj;
|
||||||
|
case 'symbol':
|
||||||
|
return TypeUtil.nameOfSymbol(obj);
|
||||||
|
case 'function':
|
||||||
|
return TypeUtil.nameOfType(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the provide name.
|
||||||
|
* @param target
|
||||||
|
*/
|
||||||
|
public static nameOfType(target: any): string {
|
||||||
|
return typeof target === 'function'
|
||||||
|
? target.name
|
||||||
|
: target.constructor.name;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get symbol name.
|
||||||
|
* @param sym
|
||||||
|
*/
|
||||||
|
public static nameOfSymbol(sym: symbol): string {
|
||||||
|
return sym.toString().replace('Symbol(', '').replace(')', '');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param out
|
||||||
|
* @param obj
|
||||||
|
* @param {{[p: string]: (collection: any[], value: any) => any}} reducers
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
|
public static deepExtends(out: any, obj: any, reducers: { [key: string]: (collection: any[], value: any) => any } = {}): any {
|
||||||
|
|
||||||
|
if (obj === undefined || obj === null) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TypeUtil.isPrimitiveOrPrimitiveType(obj) || typeof obj === 'symbol' || typeof obj === 'function') {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TypeUtil.isArrayOrArrayType(obj)) {
|
||||||
|
out = out || [];
|
||||||
|
} else {
|
||||||
|
out = out || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultReducer = reducers.default ? reducers.default : (collection: any[], value: any) => {
|
||||||
|
collection.push(value);
|
||||||
|
return collection;
|
||||||
|
};
|
||||||
|
const set = (key: string | number, value: any) => {
|
||||||
|
if (TypeUtil.isArrayOrArrayType(obj)) {
|
||||||
|
out.push(value);
|
||||||
|
} else {
|
||||||
|
out[key] = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(obj).forEach(key => {
|
||||||
|
let value = obj[key];
|
||||||
|
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === '' && out[key] !== '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TypeUtil.isPrimitiveOrPrimitiveType(value) || typeof value === 'function') {
|
||||||
|
set(key, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TypeUtil.isArrayOrArrayType(value)) {
|
||||||
|
|
||||||
|
value = value.map((v: any) => TypeUtil.deepExtends(undefined, v));
|
||||||
|
|
||||||
|
set(key, []
|
||||||
|
.concat(out[key] || [], value)
|
||||||
|
.reduce((collection: any[], v: any) =>
|
||||||
|
reducers[key] ? reducers[key](collection, v) : defaultReducer(collection, v),
|
||||||
|
[]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object
|
||||||
|
if (TypeUtil.isArrayOrArrayType(obj)) {
|
||||||
|
set(key, TypeUtil.deepExtends(undefined, value, reducers));
|
||||||
|
} else {
|
||||||
|
set(key, TypeUtil.deepExtends(out[key], value, reducers));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (TypeUtil.isArrayOrArrayType(out)) {
|
||||||
|
out.reduce((collection: any[], value: any) => defaultReducer(collection, value), []);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public static isPromise(target: any): boolean {
|
||||||
|
return target === Promise || target instanceof Promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
|
public static getInheritedType(target: Type<any>): Type<any> {
|
||||||
|
return Object.getPrototypeOf(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @param {PropertyKeyType} propertyKey
|
||||||
|
* @returns {PropertyDescriptor}
|
||||||
|
*/
|
||||||
|
public static descriptorOf(target: any, propertyKey: PropertyKeyType): PropertyDescriptor {
|
||||||
|
return Object.getOwnPropertyDescriptor(target && target.prototype || target, propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @param {PropertyKeyType} propertyKey
|
||||||
|
* @returns {string[]}
|
||||||
|
*/
|
||||||
|
public static getParameterNames(target: any, propertyKey: PropertyKeyType): string[] {
|
||||||
|
const rawType = TypeUtil.getPrototype(target);
|
||||||
|
const fn: Function = rawType[propertyKey];
|
||||||
|
|
||||||
|
const code = fn.toString()
|
||||||
|
.replace(COMMENTS, '')
|
||||||
|
.replace(FAT_ARROWS, '')
|
||||||
|
.replace(DEFAULT_PARAMS, '');
|
||||||
|
|
||||||
|
const result = code.slice(code.indexOf('(') + 1, code.indexOf(')')).match(/([^\s,]+)/g);
|
||||||
|
|
||||||
|
return result === null
|
||||||
|
? []
|
||||||
|
: result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
|
public static ancestorsOf(target: Type<any>): Type<any>[] {
|
||||||
|
const classes: Type<any>[] = [];
|
||||||
|
|
||||||
|
let currentTarget = TypeUtil.getType(target);
|
||||||
|
|
||||||
|
while (TypeUtil.nameOf(currentTarget) !== '') {
|
||||||
|
classes.unshift(currentTarget);
|
||||||
|
currentTarget = TypeUtil.getInheritedType(currentTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @param {string} name
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
public static applyBefore(target: any, name: string, callback: Function): void {
|
||||||
|
const original = target[name];
|
||||||
|
target[name] = function (...args: any[]): any {
|
||||||
|
callback(...args);
|
||||||
|
return original.apply(this, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Promise<any>} promise
|
||||||
|
* @param {number} time
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
public static promiseTimeout(promise: Promise<any>, time: number = 1000): Promise<{ ok: boolean, response: 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([
|
||||||
|
promise,
|
||||||
|
timeout(promise, time),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
|
||||||
|
const DEFAULT_PARAMS = /=[^,]+/mg;
|
||||||
|
const FAT_ARROWS = /=>.*$/mg;
|
22
src/@loafer/decorator/Decorator.ts
Normal file
22
src/@loafer/decorator/Decorator.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '@loafer/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Annotation,
|
||||||
|
} from '@loafer/core/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);
|
||||||
|
}
|
||||||
|
}
|
107
src/@loafer/decorator/DecoratorFactory.ts
Normal file
107
src/@loafer/decorator/DecoratorFactory.ts
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
MetadataKeyType,
|
||||||
|
} 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 { DecoratorUtil } from './util';
|
||||||
|
import { DecoratorType } from './type';
|
||||||
|
import { NotSupportedDecoratorError } from './error';
|
||||||
|
|
||||||
|
|
||||||
|
export class DecoratorFactory {
|
||||||
|
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[]) => {
|
||||||
|
const decoratorType: DecoratorType = DecoratorUtil.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);
|
||||||
|
return annotation.classDecorator.call(annotation, target);
|
||||||
|
} 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);
|
||||||
|
} 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);
|
||||||
|
} 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);
|
||||||
|
} else {
|
||||||
|
method = clazz._defineMethod(propertyKey,
|
||||||
|
Metadata.getOwnParamTypes(target, propertyKey),
|
||||||
|
Metadata.getOwnReturnType(target, propertyKey));
|
||||||
|
parameter = method.getParameter(descriptorOrParameterIndex);
|
||||||
|
}
|
||||||
|
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 NotSupportedDecoratorError(`Cannot determine decorator[@${name}] type.`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/@loafer/decorator/error.ts
Normal file
13
src/@loafer/decorator/error.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
5
src/@loafer/decorator/index.ts
Normal file
5
src/@loafer/decorator/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export * from './Decorator';
|
||||||
|
export * from './DecoratorFactory';
|
||||||
|
export * from './error';
|
||||||
|
export * from './type';
|
||||||
|
export * from './util';
|
8
src/@loafer/decorator/type.ts
Normal file
8
src/@loafer/decorator/type.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
export enum DecoratorType {
|
||||||
|
CLASS = 'Clazz',
|
||||||
|
PROPERTY = 'Property',
|
||||||
|
METHOD = 'Method',
|
||||||
|
PARAMETER = 'Parameter',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DecoratorParametersType = [any, string | symbol, number | PropertyDescriptor];
|
48
src/@loafer/decorator/util.ts
Normal file
48
src/@loafer/decorator/util.ts
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import {
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '@loafer/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
TypeUtil,
|
||||||
|
} from '@loafer/core/util/TypeUtil';
|
||||||
|
|
||||||
|
|
||||||
|
import {
|
||||||
|
DecoratorType,
|
||||||
|
DecoratorParametersType,
|
||||||
|
} from './type';
|
||||||
|
|
||||||
|
export class DecoratorUtil {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @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),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,8 +11,8 @@ import 'rxjs/add/observable/throw';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RESTError,
|
RESTError,
|
||||||
RESTServerError,
|
RESTClientError,
|
||||||
} from '../error';
|
} from '../protocol';
|
||||||
|
|
||||||
export class RESTClient {
|
export class RESTClient {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -42,7 +42,7 @@ export class RESTClient {
|
||||||
.request<T>(method, Location.joinWithSlash(this._baseURL, entry), options)
|
.request<T>(method, Location.joinWithSlash(this._baseURL, entry), options)
|
||||||
.map(response => response)
|
.map(response => response)
|
||||||
.catch((error: HttpErrorResponse) => {
|
.catch((error: HttpErrorResponse) => {
|
||||||
const restError: RESTError = {
|
const restClientError: RESTClientError = {
|
||||||
request: {
|
request: {
|
||||||
method: method,
|
method: method,
|
||||||
entry: entry,
|
entry: entry,
|
||||||
|
@ -51,14 +51,14 @@ export class RESTClient {
|
||||||
response: error.error,
|
response: error.error,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.error(restError);
|
console.error(restClientError);
|
||||||
// const aryMsg = error.error.message.split('|');
|
// const aryMsg = error.error.message.split('|');
|
||||||
// const resError: RESTError = {
|
// const resError: RESTError = {
|
||||||
// code: error.error.code,
|
// code: error.error.code,
|
||||||
// message: aryMsg[0],
|
// message: aryMsg[0],
|
||||||
// data: aryMsg[1] === 'null' ? '' : aryMsg[1],
|
// data: aryMsg[1] === 'null' ? '' : aryMsg[1],
|
||||||
// };
|
// };
|
||||||
return Observable.throw(restError);
|
return Observable.throw(restClientError);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
1
src/@loafer/ng-rest/client/index.ts
Normal file
1
src/@loafer/ng-rest/client/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './RESTClient';
|
1
src/@loafer/ng-rest/core/index.ts
Normal file
1
src/@loafer/ng-rest/core/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './token';
|
3
src/@loafer/ng-rest/core/token.ts
Normal file
3
src/@loafer/ng-rest/core/token.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
|
||||||
|
export const _REST_BASE_URL = new InjectionToken('@loafer/ng-rest Internal Base URL');
|
1
src/@loafer/ng-rest/index.ts
Normal file
1
src/@loafer/ng-rest/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './ng-rest.module';
|
68
src/@loafer/ng-rest/ng-rest.module.ts
Normal file
68
src/@loafer/ng-rest/ng-rest.module.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import {
|
||||||
|
NgModule,
|
||||||
|
ModuleWithProviders,
|
||||||
|
Type,
|
||||||
|
Inject,
|
||||||
|
InjectionToken,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
_REST_BASE_URL,
|
||||||
|
} from './core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
SERVICES, RESTService,
|
||||||
|
} from './service';
|
||||||
|
|
||||||
|
export interface RESTFeatureModuleConfig {
|
||||||
|
url?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RESTRootModuleConfig {
|
||||||
|
baseURL: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RESTRootModule {
|
||||||
|
constructor(
|
||||||
|
private restService: RESTService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RESTFeatureModule {
|
||||||
|
constructor(
|
||||||
|
private restService: RESTService,
|
||||||
|
private root: RESTRootModule,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RESTModule {
|
||||||
|
static forRoot(config: RESTRootModuleConfig): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: RESTRootModule,
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: _REST_BASE_URL,
|
||||||
|
useValue: config.baseURL,
|
||||||
|
},
|
||||||
|
SERVICES,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static forFeature(config: RESTFeatureModuleConfig): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: RESTFeatureModule,
|
||||||
|
providers: [
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createSourceInstances(...instances: any[]) {
|
||||||
|
return instances;
|
||||||
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
export interface RESTError {
|
export interface RESTClientError {
|
||||||
request: {
|
request: {
|
||||||
method: string;
|
method: string;
|
||||||
entry: string;
|
entry: string;
|
||||||
options?: any;
|
options?: any;
|
||||||
};
|
};
|
||||||
response: RESTServerError;
|
response: RESTError;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RESTServerError {
|
export interface RESTError {
|
||||||
code: number;
|
code: number;
|
||||||
message: string;
|
message: string;
|
||||||
data?: any;
|
data?: any;
|
1
src/@loafer/ng-rest/protocol/index.ts
Normal file
1
src/@loafer/ng-rest/protocol/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './RESTError';
|
7
src/@loafer/ng-rest/service/index.ts
Normal file
7
src/@loafer/ng-rest/service/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export * from './rest.service';
|
||||||
|
|
||||||
|
import { RESTService } from './rest.service';
|
||||||
|
|
||||||
|
export const SERVICES = [
|
||||||
|
RESTService,
|
||||||
|
];
|
|
@ -11,16 +11,16 @@ import 'rxjs/add/operator/catch';
|
||||||
import 'rxjs/add/operator/timeout';
|
import 'rxjs/add/operator/timeout';
|
||||||
import 'rxjs/add/observable/throw';
|
import 'rxjs/add/observable/throw';
|
||||||
|
|
||||||
import { RESTClient } from 'packages/core/rest/client/RESTClient';
|
import { _REST_BASE_URL } from '../core';
|
||||||
|
import { RESTClient } from '../client';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RESTService extends RESTClient {
|
export class RESTService extends RESTClient {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject('REST_BASE_URL') _baseURL: string,
|
@Inject(_REST_BASE_URL) _baseURL: string,
|
||||||
@Inject(HttpClient) _httpClient: HttpClient,
|
@Inject(HttpClient) _httpClient: HttpClient,
|
||||||
) {
|
) {
|
||||||
super(_baseURL, _httpClient);
|
super(_baseURL, _httpClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { Subject } from 'rxjs/Subject';
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
|
||||||
|
import { RPCClientError } from '../protocol/RPCError';
|
||||||
import { RPCError } from '../error';
|
import { RPCClientRWC } from './RPCClientRWC';
|
||||||
import { RPCClientRWC } from './rwc/RPCClientRWC';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RPCClientCodec,
|
RPCClientCodec,
|
||||||
|
@ -48,6 +47,7 @@ export abstract class RPCClient {
|
||||||
this.onMessage(value);
|
this.onMessage(value);
|
||||||
},
|
},
|
||||||
(error: any) => {
|
(error: any) => {
|
||||||
|
console.error(error);
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
|
|
||||||
|
@ -113,9 +113,7 @@ export abstract class RPCClient {
|
||||||
const resCodec = this._codec.response(message);
|
const resCodec = this._codec.response(message);
|
||||||
|
|
||||||
if (resCodec.isNotification()) {
|
if (resCodec.isNotification()) {
|
||||||
const noti = resCodec.notification();
|
this.onNotification(resCodec.notification());
|
||||||
console.log(`RPC Notification: ${noti}`);
|
|
||||||
this.onNotification(noti);
|
|
||||||
} else {
|
} else {
|
||||||
this.onResponse(resCodec);
|
this.onResponse(resCodec);
|
||||||
}
|
}
|
||||||
|
@ -134,12 +132,12 @@ export abstract class RPCClient {
|
||||||
if (undefined !== result) {
|
if (undefined !== result) {
|
||||||
reqState.subject.next(result);
|
reqState.subject.next(result);
|
||||||
} else if (undefined !== error) {
|
} else if (undefined !== error) {
|
||||||
const rpcError: RPCError = {
|
const rpcClientError: RPCClientError = {
|
||||||
request: reqState.request,
|
request: reqState.request,
|
||||||
response: error,
|
response: error,
|
||||||
};
|
};
|
||||||
console.error(rpcError);
|
console.error(rpcClientError);
|
||||||
reqState.subject.error(rpcError);
|
reqState.subject.error(rpcClientError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
src/@loafer/ng-rpc/client/RPCClientRWC.ts
Normal file
11
src/@loafer/ng-rpc/client/RPCClientRWC.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
export interface RPCClientRWC {
|
||||||
|
connect(queryString?: string): void;
|
||||||
|
readResponse(): Observable<Object>;
|
||||||
|
writeRequest(data: any): void;
|
||||||
|
disconnect(): void;
|
||||||
|
connectionStatus(): Observable<boolean>;
|
||||||
|
}
|
2
src/@loafer/ng-rpc/client/index.ts
Normal file
2
src/@loafer/ng-rpc/client/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './RPCClient';
|
||||||
|
export * from './RPCClientRWC';
|
|
@ -5,18 +5,17 @@ import { map } from 'rxjs/operator/map';
|
||||||
import {
|
import {
|
||||||
RxWebsocketSubject,
|
RxWebsocketSubject,
|
||||||
RxWebsocketSubjectConfig,
|
RxWebsocketSubjectConfig,
|
||||||
} from 'packages/core/websocket/RxWebsocketSubject';
|
} from './RxWebsocketSubject';
|
||||||
|
|
||||||
import { RPCClientRWC } from '../RPCClientRWC';
|
import { RPCClientRWC } from '../../RPCClientRWC';
|
||||||
|
|
||||||
export class RPCClientWebsocketRWC extends RPCClientRWC {
|
export class RPCClientWebsocketRWC implements RPCClientRWC {
|
||||||
private _wsSocketSubject: RxWebsocketSubject<Object>;
|
private _wsSocketSubject: RxWebsocketSubject<Object>;
|
||||||
private _responseSubject: Subject<Object>;
|
private _responseSubject: Subject<Object>;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private _config: RxWebsocketSubjectConfig,
|
private _config: RxWebsocketSubjectConfig,
|
||||||
) {
|
) {
|
||||||
super();
|
|
||||||
this._wsSocketSubject = new RxWebsocketSubject<Object>(this._config);
|
this._wsSocketSubject = new RxWebsocketSubject<Object>(this._config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +36,7 @@ export class RPCClientWebsocketRWC extends RPCClientRWC {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
|
console.log('sss');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
2
src/@loafer/ng-rpc/client/rwc/websocket/index.ts
Normal file
2
src/@loafer/ng-rpc/client/rwc/websocket/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './RPCClientWebsocketRWC';
|
||||||
|
export * from './RxWebsocketSubject';
|
1
src/@loafer/ng-rpc/core/index.ts
Normal file
1
src/@loafer/ng-rpc/core/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './token';
|
8
src/@loafer/ng-rpc/core/token.ts
Normal file
8
src/@loafer/ng-rpc/core/token.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
|
||||||
|
export const RPC_CODEC = new InjectionToken('@loafer/ng-rpc RPC codec');
|
||||||
|
export const RPC_RWC = new InjectionToken('@loafer/ng-rpc RPC rwc');
|
||||||
|
|
||||||
|
export const _ROOT_SUBSCRIBERS = new InjectionToken('@loafer/ng-rpc RPC root subscribers');
|
||||||
|
export const _FEATURE_SUBSCRIBERS = new InjectionToken('@loafer/ng-rpc RPC feature subscribers');
|
||||||
|
|
1
src/@loafer/ng-rpc/decorator/index.ts
Normal file
1
src/@loafer/ng-rpc/decorator/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './rpc-subscriber.decorator';
|
26
src/@loafer/ng-rpc/decorator/rpc-subscriber.decorator.ts
Normal file
26
src/@loafer/ng-rpc/decorator/rpc-subscriber.decorator.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '@loafer/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Decorator,
|
||||||
|
DecoratorFactory,
|
||||||
|
} from '@loafer/decorator';
|
||||||
|
|
||||||
|
export interface RPCSubscriberDecoratorAttribute {
|
||||||
|
method: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RPCSubscriberDecorator extends Decorator<RPCSubscriberDecoratorAttribute> {
|
||||||
|
public constructor(config: RPCSubscriberDecoratorAttribute) {
|
||||||
|
super(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public methodDecorator = <T>(target: Object, propertyKey: PropertyKeyType,
|
||||||
|
descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void => {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RPCSubscriber = DecoratorFactory.create<RPCSubscriberDecoratorAttribute>(RPCSubscriberDecorator);
|
1
src/@loafer/ng-rpc/index.ts
Normal file
1
src/@loafer/ng-rpc/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './ng-rpc.module';
|
109
src/@loafer/ng-rpc/ng-rpc.module.ts
Normal file
109
src/@loafer/ng-rpc/ng-rpc.module.ts
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
import {
|
||||||
|
NgModule,
|
||||||
|
ModuleWithProviders,
|
||||||
|
Type,
|
||||||
|
Inject,
|
||||||
|
InjectionToken,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPC_CODEC,
|
||||||
|
RPC_RWC,
|
||||||
|
|
||||||
|
_ROOT_SUBSCRIBERS,
|
||||||
|
_FEATURE_SUBSCRIBERS,
|
||||||
|
} from './core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClientRWC,
|
||||||
|
} from './client/RPCClientRWC';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClientCodec,
|
||||||
|
} from './protocol';
|
||||||
|
|
||||||
|
import {
|
||||||
|
SERVICES, RPCService,
|
||||||
|
} from './service';
|
||||||
|
|
||||||
|
import {
|
||||||
|
SUBSCRIBERS, RPCSubscribeService,
|
||||||
|
} from './subscribe';
|
||||||
|
|
||||||
|
export interface RPCFeatureModuleConfig {
|
||||||
|
subscribers?: Type<any>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPCRootModuleConfig {
|
||||||
|
subscribers?: Type<any>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RPCRootModule {
|
||||||
|
constructor(
|
||||||
|
private rpcService: RPCService,
|
||||||
|
private rpcSubscribeService: RPCSubscribeService,
|
||||||
|
@Inject(_ROOT_SUBSCRIBERS) rootSubscribers: any[],
|
||||||
|
) {
|
||||||
|
rootSubscribers.forEach((subscriber) => {
|
||||||
|
rpcSubscribeService.addSubscriber(subscriber);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RPCFeatureModule {
|
||||||
|
constructor(
|
||||||
|
private rpcService: RPCService,
|
||||||
|
private rpcSubscribeService: RPCSubscribeService,
|
||||||
|
@Inject(_FEATURE_SUBSCRIBERS) featureSubscribersGroups: any[][],
|
||||||
|
private root: RPCRootModule,
|
||||||
|
) {
|
||||||
|
featureSubscribersGroups.forEach((featureSubscribers) => {
|
||||||
|
featureSubscribers.forEach((subscriber) => {
|
||||||
|
rpcSubscribeService.addSubscriber(subscriber);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RPCModule {
|
||||||
|
static forRoot(config: RPCRootModuleConfig): ModuleWithProviders {
|
||||||
|
const subscribers = undefined === config.subscribers ? [] : config.subscribers;
|
||||||
|
return {
|
||||||
|
ngModule: RPCRootModule,
|
||||||
|
providers: [
|
||||||
|
subscribers,
|
||||||
|
{
|
||||||
|
provide: _ROOT_SUBSCRIBERS,
|
||||||
|
deps: subscribers,
|
||||||
|
useFactory: createSourceInstances,
|
||||||
|
},
|
||||||
|
SERVICES,
|
||||||
|
SUBSCRIBERS,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static forFeature(config: RPCFeatureModuleConfig): ModuleWithProviders {
|
||||||
|
const subscribers = undefined === config.subscribers ? [] : config.subscribers;
|
||||||
|
|
||||||
|
return {
|
||||||
|
ngModule: RPCFeatureModule,
|
||||||
|
providers: [
|
||||||
|
subscribers,
|
||||||
|
{
|
||||||
|
provide: _FEATURE_SUBSCRIBERS,
|
||||||
|
multi: true,
|
||||||
|
deps: subscribers,
|
||||||
|
useFactory: createSourceInstances,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createSourceInstances(...instances: any[]) {
|
||||||
|
return instances;
|
||||||
|
}
|
20
src/@loafer/ng-rpc/protocol/RPCClientCodec.ts
Normal file
20
src/@loafer/ng-rpc/protocol/RPCClientCodec.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { RPCError } from './RPCError';
|
||||||
|
|
||||||
|
export interface RPCClientCodec {
|
||||||
|
request(method: string, args: any[], id: number): any;
|
||||||
|
response(res: any): RPCClientResponseCodec;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPCClientResponseCodec {
|
||||||
|
id(): number | undefined;
|
||||||
|
error(): RPCError | undefined;
|
||||||
|
result(): any | undefined;
|
||||||
|
|
||||||
|
isNotification(): boolean;
|
||||||
|
notification(): RPCClientNotificationCodec | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPCClientNotificationCodec {
|
||||||
|
method(): string;
|
||||||
|
params(): any | undefined;
|
||||||
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
export interface RPCError {
|
export interface RPCClientError {
|
||||||
request: {
|
request: {
|
||||||
method: string,
|
method: string,
|
||||||
params: any[],
|
params: any[],
|
||||||
};
|
};
|
||||||
response: RPCServerError;
|
response: RPCError;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error object representation when a method invocation fails.
|
* Error object representation when a method invocation fails.
|
||||||
*/
|
*/
|
||||||
export interface RPCServerError {
|
export interface RPCError {
|
||||||
/** Indicates the error type that occurred. */
|
/** Indicates the error type that occurred. */
|
||||||
code: ErrorCode;
|
code: RPCErrorCode;
|
||||||
|
|
||||||
/** A short description of the error. */
|
/** A short description of the error. */
|
||||||
message: string;
|
message: string;
|
||||||
|
@ -21,7 +21,7 @@ export interface RPCServerError {
|
||||||
}/*
|
}/*
|
||||||
|
|
||||||
/** Error codes are same as xml-rpc codes. See http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php */
|
/** Error codes are same as xml-rpc codes. See http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php */
|
||||||
export const enum ErrorCode {
|
export const enum RPCErrorCode {
|
||||||
/** Parse error Invalid JSON was received by the Server. */
|
/** Parse error Invalid JSON was received by the Server. */
|
||||||
ParseError = -32700,
|
ParseError = -32700,
|
||||||
|
|
2
src/@loafer/ng-rpc/protocol/index.ts
Normal file
2
src/@loafer/ng-rpc/protocol/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './RPCClientCodec';
|
||||||
|
export * from './RPCError';
|
|
@ -5,8 +5,8 @@ import {
|
||||||
} from '../RPCClientCodec';
|
} from '../RPCClientCodec';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RPCServerError,
|
RPCError,
|
||||||
} from '../../error';
|
} from '../RPCError';
|
||||||
|
|
||||||
export interface ClientNotification {
|
export interface ClientNotification {
|
||||||
method: string;
|
method: string;
|
||||||
|
@ -23,11 +23,11 @@ export interface ClientRequest {
|
||||||
export interface ClientResponse {
|
export interface ClientResponse {
|
||||||
jsonrpc: string;
|
jsonrpc: string;
|
||||||
result?: any;
|
result?: any;
|
||||||
error?: RPCServerError;
|
error?: RPCError;
|
||||||
id?: number;
|
id?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RPCClientJSONCodec extends RPCClientCodec {
|
export class JSONRPCClientCodec implements RPCClientCodec {
|
||||||
public request(method: string, args: any[], id?: number): any {
|
public request(method: string, args: any[], id?: number): any {
|
||||||
const params = convertParamsToStringArray(args);
|
const params = convertParamsToStringArray(args);
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ export class RPCClientJSONCodec extends RPCClientCodec {
|
||||||
result: res.result,
|
result: res.result,
|
||||||
error: res.error,
|
error: res.error,
|
||||||
};
|
};
|
||||||
return new RPCClientJSONResponseCodec(_res);
|
return new JSONRPCClientResponseCodec(_res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,15 +79,14 @@ function convertParamsToStringArray(args: any[]): string[] | undefined {
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RPCClientJSONResponseCodec extends RPCClientResponseCodec {
|
export class JSONRPCClientResponseCodec implements RPCClientResponseCodec {
|
||||||
public constructor(private _res: ClientResponse) {
|
public constructor(private _res: ClientResponse) {
|
||||||
super();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public id(): number | undefined {
|
public id(): number | undefined {
|
||||||
return this._res.id;
|
return this._res.id;
|
||||||
}
|
}
|
||||||
public error(): RPCServerError | undefined {
|
public error(): RPCError | undefined {
|
||||||
return this._res.error;
|
return this._res.error;
|
||||||
}
|
}
|
||||||
public result(): any | undefined {
|
public result(): any | undefined {
|
||||||
|
@ -109,13 +108,12 @@ export class RPCClientJSONResponseCodec extends RPCClientResponseCodec {
|
||||||
method: this._res.result.method,
|
method: this._res.result.method,
|
||||||
params: this._res.result.params,
|
params: this._res.result.params,
|
||||||
};
|
};
|
||||||
return new RPCClientJSONNotificationCodec(_noti);
|
return new JSONRPCClientNotificationCodec(_noti);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RPCClientJSONNotificationCodec extends RPCClientNotificationCodec {
|
export class JSONRPCClientNotificationCodec implements RPCClientNotificationCodec {
|
||||||
public constructor(private _noti: ClientNotification) {
|
public constructor(private _noti: ClientNotification) {
|
||||||
super();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public method(): string {
|
public method(): string {
|
1
src/@loafer/ng-rpc/protocol/json/index.ts
Normal file
1
src/@loafer/ng-rpc/protocol/json/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './JSONRPCClientCodec';
|
7
src/@loafer/ng-rpc/service/index.ts
Normal file
7
src/@loafer/ng-rpc/service/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export * from './rpc.service';
|
||||||
|
|
||||||
|
import { RPCService } from './rpc.service';
|
||||||
|
|
||||||
|
export const SERVICES = [
|
||||||
|
RPCService,
|
||||||
|
];
|
39
src/@loafer/ng-rpc/service/rpc.service.ts
Normal file
39
src/@loafer/ng-rpc/service/rpc.service.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPC_CODEC,
|
||||||
|
RPC_RWC,
|
||||||
|
} from '../core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClient,
|
||||||
|
RPCClientRWC,
|
||||||
|
} from '../client';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClientCodec,
|
||||||
|
RPCClientNotificationCodec,
|
||||||
|
} from '../protocol';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCSubscribeService,
|
||||||
|
} from '../subscribe';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RPCService extends RPCClient {
|
||||||
|
constructor(
|
||||||
|
@Inject(RPC_CODEC) rpcClientCodec: RPCClientCodec,
|
||||||
|
@Inject(RPC_RWC) rpcClientRWC: RPCClientRWC,
|
||||||
|
private rpcSubscribeService: RPCSubscribeService,
|
||||||
|
) {
|
||||||
|
super(rpcClientCodec, rpcClientRWC);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onNotification(notiCodec: RPCClientNotificationCodec): void {
|
||||||
|
this.rpcSubscribeService.notify(notiCodec);
|
||||||
|
}
|
||||||
|
}
|
7
src/@loafer/ng-rpc/subscribe/index.ts
Normal file
7
src/@loafer/ng-rpc/subscribe/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export * from './subscribe.service';
|
||||||
|
|
||||||
|
import { RPCSubscribeService } from './subscribe.service';
|
||||||
|
|
||||||
|
export const SUBSCRIBERS = [
|
||||||
|
RPCSubscribeService,
|
||||||
|
];
|
56
src/@loafer/ng-rpc/subscribe/subscribe.service.ts
Normal file
56
src/@loafer/ng-rpc/subscribe/subscribe.service.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
} from '@loafer/core';
|
||||||
|
|
||||||
|
import { TypeUtil } from '@loafer/core/util/TypeUtil';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Class,
|
||||||
|
Metadata,
|
||||||
|
} from '@loafer/core/reflect';
|
||||||
|
|
||||||
|
import { RPCSubscriberDecorator } from '../decorator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClientNotificationCodec,
|
||||||
|
} from '../protocol';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RPCSubscribeService {
|
||||||
|
private subscribers: Set<any>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
) {
|
||||||
|
this.subscribers = new Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
public addSubscriber(subscriber: Type<any>): void {
|
||||||
|
const type = TypeUtil.getType(subscriber);
|
||||||
|
|
||||||
|
if (this.subscribers.has(subscriber)) {
|
||||||
|
console.log(`Subscriber[${type.name}] has been added`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.subscribers.add(subscriber);
|
||||||
|
|
||||||
|
const clazz = Class.forType(type);
|
||||||
|
if (undefined === clazz) {
|
||||||
|
console.log(`Type[${subscriber.name}] is not decorated type`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const methods = clazz.getMethods();
|
||||||
|
methods.forEach((method, propertyKey) => {
|
||||||
|
const annon = method.getAnnotation(RPCSubscriberDecorator);
|
||||||
|
console.log(`subscriber method[${annon.attribute.method}]`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public notify(codec: RPCClientNotificationCodec): void {
|
||||||
|
console.log(`notify method[${codec.method()}] params[${codec.params()}]`);
|
||||||
|
}
|
||||||
|
}
|
17
src/app/app-rest.module.ts
Normal file
17
src/app/app-rest.module.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RESTModule } from '@loafer/ng-rest';
|
||||||
|
|
||||||
|
import { environment } from '../environments/environment';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
exports: [
|
||||||
|
RESTModule,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
RESTModule.forRoot({baseURL: environment.restBaseURL}),
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppRESTModule { }
|
36
src/app/app-rpc.module.ts
Normal file
36
src/app/app-rpc.module.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RPCModule } from '@loafer/ng-rpc';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPC_CODEC,
|
||||||
|
RPC_RWC,
|
||||||
|
} from '@loafer/ng-rpc/core';
|
||||||
|
import { JSONRPCClientCodec } from '@loafer/ng-rpc/protocol/json';
|
||||||
|
import {
|
||||||
|
RPCClientWebsocketRWC,
|
||||||
|
RxWebsocketSubjectConfig,
|
||||||
|
} from '@loafer/ng-rpc/client/rwc/websocket';
|
||||||
|
|
||||||
|
import { environment } from '../environments/environment';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
exports: [
|
||||||
|
RPCModule,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
RPCModule.forRoot({}),
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{provide: 'WEBAPP_RPC_CONFIG', useValue: environment.webappRPCConfig},
|
||||||
|
|
||||||
|
{provide: RPC_CODEC, useFactory: () => new JSONRPCClientCodec()},
|
||||||
|
{
|
||||||
|
provide: RPC_RWC,
|
||||||
|
useFactory: (config: RxWebsocketSubjectConfig) => new RPCClientWebsocketRWC(config),
|
||||||
|
deps: ['WEBAPP_RPC_CONFIG']
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppRPCModule { }
|
|
@ -9,32 +9,18 @@ import { CookieService } from 'ngx-cookie-service';
|
||||||
|
|
||||||
import { MemberModule } from 'packages/member/member.module';
|
import { MemberModule } from 'packages/member/member.module';
|
||||||
|
|
||||||
import { RPCClient } from 'packages/core/rpc/client/RPCClient';
|
|
||||||
import { RPCClientCodec } from 'packages/core/rpc/protocol/RPCClientCodec';
|
|
||||||
import { RPCClientJSONCodec } from 'packages/core/rpc/protocol/json/RPCClientJSONCodec';
|
|
||||||
|
|
||||||
import { RPCClientRWC } from 'packages/core/rpc/client/rwc/RPCClientRWC';
|
|
||||||
import { RPCClientWebsocketRWC } from 'packages/core/rpc/client/rwc/websocket/RPCClientWebsocketRWC';
|
|
||||||
import { RxWebsocketSubjectConfig } from 'packages/core/websocket/RxWebsocketSubject';
|
|
||||||
|
|
||||||
import { RESTClient } from 'packages/core/rest/client/RESTClient';
|
|
||||||
|
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppStoreModule } from './app-store.module';
|
import { AppStoreModule } from './app-store.module';
|
||||||
import { AppL10NModule } from './app-l10n.module';
|
import { AppL10NModule } from './app-l10n.module';
|
||||||
|
import { AppRPCModule } from './app-rpc.module';
|
||||||
|
import { AppRESTModule } from './app-rest.module';
|
||||||
|
|
||||||
import { MaterialModule } from 'packages/commons/material/material.module';
|
import { MaterialModule } from 'packages/commons/material/material.module';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
import { environment } from '../environments/environment';
|
|
||||||
import { RPCService } from './commons/service/rpc.service';
|
|
||||||
import { RESTService } from './commons/service/rest.service';
|
|
||||||
|
|
||||||
|
|
||||||
import { AuthGuard } from './commons/guard/auth.guard';
|
import { AuthGuard } from './commons/guard/auth.guard';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -42,27 +28,13 @@ import { AuthGuard } from './commons/guard/auth.guard';
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
AppStoreModule,
|
AppStoreModule,
|
||||||
AppL10NModule,
|
AppL10NModule,
|
||||||
|
AppRPCModule,
|
||||||
|
AppRESTModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
MemberModule,
|
MemberModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: 'REST_BASE_URL', useValue: environment.restBaseURL},
|
|
||||||
{provide: 'WEBAPP_RPC_CONFIG', useValue: environment.webappRPCConfig},
|
|
||||||
|
|
||||||
{provide: RPCClientCodec, useFactory: () => new RPCClientJSONCodec()},
|
|
||||||
{
|
|
||||||
provide: RPCClientRWC,
|
|
||||||
useFactory: (config: RxWebsocketSubjectConfig) => new RPCClientWebsocketRWC(config),
|
|
||||||
deps: ['WEBAPP_RPC_CONFIG']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: RESTClient, useClass: RESTService
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: RPCClient, useClass: RPCService
|
|
||||||
},
|
|
||||||
|
|
||||||
CookieService,
|
CookieService,
|
||||||
AuthGuard,
|
AuthGuard,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { TestBed, inject } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { RPCService } from './rpc.service';
|
|
||||||
|
|
||||||
describe('RPCService', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
providers: [RPCService]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', inject([RPCService], (service: RPCService) => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('apiService connect to server', inject([RPCService], (service: RPCService) => {
|
|
||||||
service.connect();
|
|
||||||
service.getConnectionStatus().subscribe(
|
|
||||||
(isConnected: boolean) => {
|
|
||||||
console.log('isConnected:' + isConnected);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { Injectable, Inject } from '@angular/core';
|
|
||||||
import { Store, select } from '@ngrx/store';
|
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { Subject } from 'rxjs/Subject';
|
|
||||||
|
|
||||||
import { RPCClient } from 'packages/core/rpc/client/RPCClient';
|
|
||||||
import { RPCClientCodec } from 'packages/core/rpc/protocol/RPCClientCodec';
|
|
||||||
import { RPCClientRWC } from 'packages/core/rpc/client/rwc/RPCClientRWC';
|
|
||||||
import { RPCClientNotificationCodec } from 'packages/core/rpc/protocol/RPCClientCodec';
|
|
||||||
|
|
||||||
import { notificationAction } from 'packages/core/rpc/store/notification';
|
|
||||||
|
|
||||||
import * as AppStore from '../store';
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class RPCService extends RPCClient {
|
|
||||||
constructor(
|
|
||||||
private _rpcClientCodec: RPCClientCodec,
|
|
||||||
private _rpcClientRWC: RPCClientRWC,
|
|
||||||
private store: Store<AppStore.State>,
|
|
||||||
) {
|
|
||||||
super(_rpcClientCodec, _rpcClientRWC);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected onNotification(notiCodec: RPCClientNotificationCodec): void {
|
|
||||||
this.store.dispatch(notificationAction(notiCodec.method(), notiCodec.params()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ import 'rxjs/add/operator/take';
|
||||||
|
|
||||||
import { CookieService } from 'ngx-cookie-service';
|
import { CookieService } from 'ngx-cookie-service';
|
||||||
|
|
||||||
import { RPCClient } from 'packages/core/rpc/client/RPCClient';
|
import { RPCService } from '@loafer/ng-rpc/service';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SigninSuccess,
|
SigninSuccess,
|
||||||
|
@ -29,7 +29,7 @@ export class Effects {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private actions$: Actions,
|
private actions$: Actions,
|
||||||
private rpcClient: RPCClient,
|
private rpcService: RPCService,
|
||||||
private cookieService: CookieService,
|
private cookieService: CookieService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ export class Effects {
|
||||||
|
|
||||||
const queryString = `authToken=${authToken}`;
|
const queryString = `authToken=${authToken}`;
|
||||||
|
|
||||||
this.rpcClient.connect(queryString);
|
this.rpcService.connect(queryString);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ export class Effects {
|
||||||
// console.log(`authToken: ${authToken}`);
|
// console.log(`authToken: ${authToken}`);
|
||||||
const queryString = `authToken=${authToken}`;
|
const queryString = `authToken=${authToken}`;
|
||||||
|
|
||||||
this.rpcClient.connect(queryString);
|
this.rpcService.connect(queryString);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
import { InjectionToken } from '@angular/core';
|
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
export abstract class RPCClientRWC {
|
|
||||||
public abstract connect(queryString?: string): void;
|
|
||||||
public abstract readResponse(): Observable<Object>;
|
|
||||||
public abstract writeRequest(data: any): void;
|
|
||||||
public abstract disconnect(): void;
|
|
||||||
public abstract connectionStatus(): Observable<boolean>;
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { RPCServerError } from '../error';
|
|
||||||
|
|
||||||
export abstract class RPCClientCodec {
|
|
||||||
abstract request(method: string, args: any[], id: number): any;
|
|
||||||
abstract response(res: any): RPCClientResponseCodec;
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class RPCClientResponseCodec {
|
|
||||||
abstract id(): number | undefined;
|
|
||||||
abstract error(): RPCServerError | undefined;
|
|
||||||
abstract result(): any | undefined;
|
|
||||||
|
|
||||||
abstract isNotification(): boolean;
|
|
||||||
abstract notification(): RPCClientNotificationCodec | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class RPCClientNotificationCodec {
|
|
||||||
public abstract method(): string;
|
|
||||||
public abstract params(): any | undefined;
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './notification.action';
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { Action } from '@ngrx/store';
|
|
||||||
|
|
||||||
export const NOTIFICATION_ACTION_TYPE_PREFIX = '@@NOTIFICATION';
|
|
||||||
|
|
||||||
export interface NotificationAction extends Action {
|
|
||||||
payload?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function notificationActionEnum(method: string): string {
|
|
||||||
return `[${NOTIFICATION_ACTION_TYPE_PREFIX}] ${method}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function notificationAction(method: string, params: any): Action {
|
|
||||||
const action: NotificationAction = {
|
|
||||||
type: notificationActionEnum(method),
|
|
||||||
payload: params,
|
|
||||||
};
|
|
||||||
return action;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component, OnInit, AfterContentInit } from '@angular/core';
|
import { Component, OnInit, AfterContentInit } from '@angular/core';
|
||||||
import { MatCheckboxChange } from '@angular/material';
|
import { MatCheckboxChange } from '@angular/material';
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
import {
|
import {
|
||||||
DiscoveryStartInfo,
|
DiscoveryStartInfo,
|
||||||
DiscoveryZone,
|
DiscoveryZone,
|
||||||
|
@ -59,7 +59,7 @@ export class SettingComponent implements OnInit, AfterContentInit {
|
||||||
this.started = true;
|
this.started = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error: RPCError) => {
|
(error: RPCClientError) => {
|
||||||
console.log(error.response.message);
|
console.log(error.response.message);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -68,7 +68,7 @@ export class SettingComponent implements OnInit, AfterContentInit {
|
||||||
(zone: Zone) => {
|
(zone: Zone) => {
|
||||||
this.convertTreeView(zone);
|
this.convertTreeView(zone);
|
||||||
},
|
},
|
||||||
(error: RPCError) => {
|
(error: RPCClientError) => {
|
||||||
console.log(error.response.message);
|
console.log(error.response.message);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
13
src/packages/discovery/discovery-rpc.module.ts
Normal file
13
src/packages/discovery/discovery-rpc.module.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RPCModule } from '@loafer/ng-rpc';
|
||||||
|
|
||||||
|
import {
|
||||||
|
SUBSCRIBERS,
|
||||||
|
} from './subscriber';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RPCModule.forFeature({subscribers: SUBSCRIBERS}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class DiscoveryRPCModule { }
|
|
@ -1,4 +1,4 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule, Inject } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ import { MaterialModule } from 'packages/commons/material/material.module';
|
||||||
import { InputChipModule } from 'packages/commons/component/input-chip/input-chip.module';
|
import { InputChipModule } from 'packages/commons/component/input-chip/input-chip.module';
|
||||||
|
|
||||||
import { DiscoveryStoreModule } from './discovery-store.module';
|
import { DiscoveryStoreModule } from './discovery-store.module';
|
||||||
|
import { DiscoveryRPCModule } from './discovery-rpc.module';
|
||||||
|
|
||||||
import { COMPONENTS } from './component';
|
import { COMPONENTS } from './component';
|
||||||
import { SERVICES } from './service';
|
import { SERVICES } from './service';
|
||||||
import { TreeModule } from 'angular-tree-component';
|
import { TreeModule } from 'angular-tree-component';
|
||||||
|
@ -18,6 +20,7 @@ import { TreeModule } from 'angular-tree-component';
|
||||||
InputChipModule,
|
InputChipModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
DiscoveryStoreModule,
|
DiscoveryStoreModule,
|
||||||
|
DiscoveryRPCModule,
|
||||||
TreeModule
|
TreeModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -30,4 +33,5 @@ import { TreeModule } from 'angular-tree-component';
|
||||||
SERVICES,
|
SERVICES,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class DiscoveryModule { }
|
export class DiscoveryModule {
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { RPCClient } from 'packages/core/rpc/client/RPCClient';
|
import { RPCService } from '@loafer/ng-rpc/service';
|
||||||
import {
|
import {
|
||||||
DiscoveryStartInfo,
|
DiscoveryStartInfo,
|
||||||
DiscoveryZone,
|
DiscoveryZone,
|
||||||
|
@ -17,26 +17,26 @@ import {
|
||||||
export class DiscoveryService {
|
export class DiscoveryService {
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private rpcClient: RPCClient,
|
private rpcService: RPCService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public start(dsInfo: DiscoveryStartInfo): Observable<DiscoveryStartInfo> {
|
public start(dsInfo: DiscoveryStartInfo): Observable<DiscoveryStartInfo> {
|
||||||
|
|
||||||
return this.rpcClient.call('DiscoveryService.startDiscovery', dsInfo);
|
return this.rpcService.call('DiscoveryService.startDiscovery', dsInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public discoverZone(probeID: string, discoveryZone: DiscoveryZone): void {
|
public discoverZone(probeID: string, discoveryZone: DiscoveryZone): void {
|
||||||
this.rpcClient.send('DiscoveryService.discoverZone', probeID, discoveryZone);
|
this.rpcService.send('DiscoveryService.discoverZone', probeID, discoveryZone);
|
||||||
}
|
}
|
||||||
public discoverHost(probeID: string, zone: Zone, discoveryHost: DiscoveryHost): void {
|
public discoverHost(probeID: string, zone: Zone, discoveryHost: DiscoveryHost): void {
|
||||||
this.rpcClient.send('DiscoveryService.discoverHost', probeID, zone, discoveryHost);
|
this.rpcService.send('DiscoveryService.discoverHost', probeID, zone, discoveryHost);
|
||||||
}
|
}
|
||||||
public discoverPort(probeID: string, host: Host, discoveryPort: DiscoveryPort): void {
|
public discoverPort(probeID: string, host: Host, discoveryPort: DiscoveryPort): void {
|
||||||
this.rpcClient.send('DiscoveryService.discoverPort', probeID, host, discoveryPort);
|
this.rpcService.send('DiscoveryService.discoverPort', probeID, host, discoveryPort);
|
||||||
}
|
}
|
||||||
public discoverService(probeID: string, port: Port, discoveryService: M_DiscoveryService): void {
|
public discoverService(probeID: string, port: Port, discoveryService: M_DiscoveryService): void {
|
||||||
this.rpcClient.send('DiscoveryService.discoverService', probeID, port, discoveryService);
|
this.rpcService.send('DiscoveryService.discoverService', probeID, port, discoveryService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { RPCClient } from 'packages/core/rpc/client/RPCClient';
|
import { RPCService } from '@loafer/ng-rpc/service';
|
||||||
import {
|
import {
|
||||||
DiscoveryStartInfo,
|
DiscoveryStartInfo,
|
||||||
DiscoveryZone,
|
DiscoveryZone,
|
||||||
|
@ -18,14 +18,14 @@ import { Probe } from 'packages/probe/model';
|
||||||
export class TargetDiscoveryService {
|
export class TargetDiscoveryService {
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private rpcClient: RPCClient,
|
private rpcService: RPCService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public saveAllTarget(hosts: Host[], probe: Probe): Observable<Boolean> {
|
public saveAllTarget(hosts: Host[], probe: Probe): Observable<Boolean> {
|
||||||
|
|
||||||
return this.rpcClient.call('TargetDiscoveryService.saveAllTarget', hosts, probe);
|
return this.rpcService.call('TargetDiscoveryService.saveAllTarget', hosts, probe);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { notificationActionEnum } from 'packages/core/rpc/store/notification';
|
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Zone,
|
Zone,
|
||||||
Host,
|
Host,
|
||||||
|
@ -15,10 +12,10 @@ import {
|
||||||
} from '../../model';
|
} from '../../model';
|
||||||
|
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
DiscoverZone = '[@@NOTIFICATION] DiscoveryService.discoverZone',
|
DiscoverZone = '[discovery.discovery] discoverZone',
|
||||||
DiscoverHost = '[@@NOTIFICATION] DiscoveryService.discoverHost',
|
DiscoverHost = '[discovery.discovery] discoverHost',
|
||||||
DiscoverPort = '[@@NOTIFICATION] DiscoveryService.discoverPort',
|
DiscoverPort = '[discovery.discovery] discoverPort',
|
||||||
DiscoverService = '[@@NOTIFICATION] DiscoveryService.discoverService',
|
DiscoverService = '[discovery.discovery] discoverService',
|
||||||
DiscoveredZone = '[@@NOTIFICATION] DiscoveryService.discoveredZone',
|
DiscoveredZone = '[@@NOTIFICATION] DiscoveryService.discoveredZone',
|
||||||
DiscoveredHost = '[@@NOTIFICATION] DiscoveryService.discoveredHost',
|
DiscoveredHost = '[@@NOTIFICATION] DiscoveryService.discoveredHost',
|
||||||
DiscoveredPort = '[@@NOTIFICATION] DiscoveryService.discoveredPort',
|
DiscoveredPort = '[@@NOTIFICATION] DiscoveryService.discoveredPort',
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Actions,
|
Actions,
|
||||||
ActionType,
|
ActionType,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { Zone } from '../../model';
|
import { Zone } from '../../model';
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
error: RPCError | null;
|
error: RPCClientError | null;
|
||||||
processing: boolean;
|
processing: boolean;
|
||||||
zones: Map<string, Zone> | null;
|
zones: Map<string, Zone> | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { notificationActionEnum } from 'packages/core/rpc/store/notification';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Zone,
|
Zone,
|
||||||
|
@ -36,7 +35,7 @@ export class DiscoverySaveAllTargetSuccess implements Action {
|
||||||
export class DiscoverySaveAllTargetFailure implements Action {
|
export class DiscoverySaveAllTargetFailure implements Action {
|
||||||
readonly type = ActionType.SaveAllTargetFailure;
|
readonly type = ActionType.SaveAllTargetFailure;
|
||||||
|
|
||||||
constructor(public payload: RPCError) {}
|
constructor(public payload: RPCClientError) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Actions =
|
export type Actions =
|
||||||
|
|
|
@ -14,7 +14,7 @@ import 'rxjs/add/operator/switchMap';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
import 'rxjs/add/operator/take';
|
import 'rxjs/add/operator/take';
|
||||||
|
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { DiscoveryStartInfo } from '../../model';
|
import { DiscoveryStartInfo } from '../../model';
|
||||||
import { TargetDiscoveryService } from '../../service/target-discovery.service';
|
import { TargetDiscoveryService } from '../../service/target-discovery.service';
|
||||||
|
@ -43,7 +43,7 @@ export class Effects {
|
||||||
.map(result => {
|
.map(result => {
|
||||||
return new DiscoverySaveAllTargetSuccess(result);
|
return new DiscoverySaveAllTargetSuccess(result);
|
||||||
})
|
})
|
||||||
.catch((error: RPCError) => {
|
.catch((error: RPCClientError) => {
|
||||||
console.log(error.response.message);
|
console.log(error.response.message);
|
||||||
return of(new DiscoverySaveAllTargetFailure(error));
|
return of(new DiscoverySaveAllTargetFailure(error));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Actions,
|
Actions,
|
||||||
ActionType,
|
ActionType,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { DiscoveryStartInfo } from '../../model';
|
import { DiscoveryStartInfo } from '../../model';
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
error: RPCError | null;
|
error: RPCClientError | null;
|
||||||
isPending: boolean;
|
isPending: boolean;
|
||||||
isSuccess: Boolean | null;
|
isSuccess: Boolean | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { DiscoveryStartInfo } from '../../model';
|
import { DiscoveryStartInfo } from '../../model';
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export class SettingSuccess implements Action {
|
||||||
export class SettingFailure implements Action {
|
export class SettingFailure implements Action {
|
||||||
readonly type = ActionType.SettingFailure;
|
readonly type = ActionType.SettingFailure;
|
||||||
|
|
||||||
constructor(public payload: RPCError) {}
|
constructor(public payload: RPCClientError) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SettingRedirect implements Action {
|
export class SettingRedirect implements Action {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import 'rxjs/add/operator/switchMap';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
import 'rxjs/add/operator/take';
|
import 'rxjs/add/operator/take';
|
||||||
|
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { DiscoveryStartInfo } from '../../model';
|
import { DiscoveryStartInfo } from '../../model';
|
||||||
import { DiscoveryService } from '../../service/discovery.service';
|
import { DiscoveryService } from '../../service/discovery.service';
|
||||||
|
@ -43,7 +43,7 @@ export class Effects {
|
||||||
.map(discoveryStartInfo => {
|
.map(discoveryStartInfo => {
|
||||||
return new SettingSuccess(discoveryStartInfo);
|
return new SettingSuccess(discoveryStartInfo);
|
||||||
})
|
})
|
||||||
.catch((error: RPCError) => {
|
.catch((error: RPCClientError) => {
|
||||||
console.log(error.response.message);
|
console.log(error.response.message);
|
||||||
return of(new SettingFailure(error));
|
return of(new SettingFailure(error));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Actions,
|
Actions,
|
||||||
ActionType,
|
ActionType,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { DiscoveryStartInfo } from '../../model';
|
import { DiscoveryStartInfo } from '../../model';
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
isStart: boolean;
|
isStart: boolean;
|
||||||
error: RPCError | null;
|
error: RPCClientError | null;
|
||||||
isPending: boolean;
|
isPending: boolean;
|
||||||
discoveryStartInfo: DiscoveryStartInfo | null;
|
discoveryStartInfo: DiscoveryStartInfo | null;
|
||||||
}
|
}
|
||||||
|
|
39
src/packages/discovery/subscriber/discovery.subscriber.ts
Normal file
39
src/packages/discovery/subscriber/discovery.subscriber.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { RPCSubscriber } from '@loafer/ng-rpc/decorator';
|
||||||
|
|
||||||
|
import * as DiscoveryStore from '../store/notification';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Zone,
|
||||||
|
Host,
|
||||||
|
Port,
|
||||||
|
Service,
|
||||||
|
} from '../model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DiscoverySubscriber {
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private store: Store<DiscoveryStore.State>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@RPCSubscriber({method: 'DiscoveryService.discoveredZone'})
|
||||||
|
public discoveredZone(zone: Zone): void {
|
||||||
|
this.store.dispatch(new DiscoveryStore.DiscoveredZone(zone));
|
||||||
|
}
|
||||||
|
@RPCSubscriber({method: 'DiscoveryService.discoveredHost'})
|
||||||
|
public discoveredHost(host: Host): void {
|
||||||
|
this.store.dispatch(new DiscoveryStore.DiscoveredHost(host));
|
||||||
|
}
|
||||||
|
@RPCSubscriber({method: 'DiscoveryService.discoveredPort'})
|
||||||
|
public discoveredPort(port: Port): void {
|
||||||
|
this.store.dispatch(new DiscoveryStore.DiscoveredPort(port));
|
||||||
|
}
|
||||||
|
@RPCSubscriber({method: 'DiscoveryService.discoveredService'})
|
||||||
|
public discoveredService(service: Service): void {
|
||||||
|
this.store.dispatch(new DiscoveryStore.DiscoveredService(service));
|
||||||
|
}
|
||||||
|
}
|
5
src/packages/discovery/subscriber/index.ts
Normal file
5
src/packages/discovery/subscriber/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { DiscoverySubscriber } from './discovery.subscriber';
|
||||||
|
|
||||||
|
export const SUBSCRIBERS = [
|
||||||
|
DiscoverySubscriber,
|
||||||
|
];
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component, OnInit, AfterContentInit } from '@angular/core';
|
import { Component, OnInit, AfterContentInit } from '@angular/core';
|
||||||
import { Infra, InfraHost, InfraOSApplication } from '../../model';
|
import { Infra, InfraHost, InfraOSApplication } from '../../model';
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
import { AuthSelector } from 'packages/member/store';
|
import { AuthSelector } from 'packages/member/store';
|
||||||
import * as ListStore from '../../store/list';
|
import * as ListStore from '../../store/list';
|
||||||
import { ListSelector } from '../../store';
|
import { ListSelector } from '../../store';
|
||||||
|
@ -33,7 +33,7 @@ export class MapComponent implements OnInit, AfterContentInit {
|
||||||
this.infras = page.content;
|
this.infras = page.content;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error: RPCError) => {
|
(error: RPCClientError) => {
|
||||||
console.log(error.response.message);
|
console.log(error.response.message);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
import { RPCClient } from 'packages/core/rpc/client/RPCClient';
|
import { RPCService } from '@loafer/ng-rpc/service';
|
||||||
|
|
||||||
import { Infra } from '../model';
|
import { Infra } from '../model';
|
||||||
import { Page, PageParams } from '../../../app/commons/model';
|
import { Page, PageParams } from '../../../app/commons/model';
|
||||||
|
@ -14,16 +14,16 @@ import { Probe } from '../../probe/model';
|
||||||
export class InfraService {
|
export class InfraService {
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private rpcClient: RPCClient,
|
private rpcService: RPCService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public readAllByDomain(domain: Domain, pageParams: PageParams): Observable<Page> {
|
public readAllByDomain(domain: Domain, pageParams: PageParams): Observable<Page> {
|
||||||
return this.rpcClient.call('InfraService.readAllByDomain', domain, pageParams);
|
return this.rpcService.call('InfraService.readAllByDomain', domain, pageParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readAllByProbe(probe: Probe, pageParams: PageParams): Observable<Page> {
|
public readAllByProbe(probe: Probe, pageParams: PageParams): Observable<Page> {
|
||||||
return this.rpcClient.call('InfraService.readAllByProbe', probe, pageParams);
|
return this.rpcService.call('InfraService.readAllByProbe', probe, pageParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { PageParams, Page } from 'app/commons/model';
|
import { PageParams, Page } from 'app/commons/model';
|
||||||
import { Domain } from '../../../domain/model';
|
import { Domain } from '../../../domain/model';
|
||||||
|
@ -31,7 +31,7 @@ export class ReadAllByDomainSuccess implements Action {
|
||||||
export class ReadAllByDomainFailure implements Action {
|
export class ReadAllByDomainFailure implements Action {
|
||||||
readonly type = ActionType.ReadAllByDomainFailure;
|
readonly type = ActionType.ReadAllByDomainFailure;
|
||||||
|
|
||||||
constructor(public payload: RPCError) { }
|
constructor(public payload: RPCClientError) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ReadAllByProbe implements Action {
|
export class ReadAllByProbe implements Action {
|
||||||
|
@ -49,7 +49,7 @@ export class ReadAllByProbeSuccess implements Action {
|
||||||
export class ReadAllByProbeFailure implements Action {
|
export class ReadAllByProbeFailure implements Action {
|
||||||
readonly type = ActionType.ReadAllByProbeFailure;
|
readonly type = ActionType.ReadAllByProbeFailure;
|
||||||
|
|
||||||
constructor(public payload: RPCError) { }
|
constructor(public payload: RPCClientError) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import 'rxjs/add/operator/exhaustMap';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
import 'rxjs/add/operator/take';
|
import 'rxjs/add/operator/take';
|
||||||
|
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { Infra } from '../../model';
|
import { Infra } from '../../model';
|
||||||
import { InfraService } from '../../service/infra.service';
|
import { InfraService } from '../../service/infra.service';
|
||||||
|
@ -46,7 +46,7 @@ export class Effects {
|
||||||
.map(page => {
|
.map(page => {
|
||||||
return new ReadAllByDomainSuccess(page);
|
return new ReadAllByDomainSuccess(page);
|
||||||
})
|
})
|
||||||
.catch((error: RPCError) => {
|
.catch((error: RPCClientError) => {
|
||||||
return of(new ReadAllByDomainFailure(error));
|
return of(new ReadAllByDomainFailure(error));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ export class Effects {
|
||||||
.map(page => {
|
.map(page => {
|
||||||
return new ReadAllByProbeSuccess(page);
|
return new ReadAllByProbeSuccess(page);
|
||||||
})
|
})
|
||||||
.catch((error: RPCError) => {
|
.catch((error: RPCClientError) => {
|
||||||
return of(new ReadAllByProbeFailure(error));
|
return of(new ReadAllByProbeFailure(error));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,13 @@ import {
|
||||||
MemoizedSelector,
|
MemoizedSelector,
|
||||||
} from '@ngrx/store';
|
} from '@ngrx/store';
|
||||||
|
|
||||||
import { RPCError } from 'packages/core/rpc/error';
|
import { RPCClientError } from '@loafer/ng-rpc/protocol';
|
||||||
|
|
||||||
import { Infra } from '../../model';
|
import { Infra } from '../../model';
|
||||||
import { Page } from '../../../../app/commons/model';
|
import { Page } from '../../../../app/commons/model';
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
error: RPCError | null;
|
error: RPCClientError | null;
|
||||||
isPending: boolean;
|
isPending: boolean;
|
||||||
page: Page | null;
|
page: Page | null;
|
||||||
}
|
}
|
||||||
|
|
9
src/packages/member/member-rest.module.ts
Normal file
9
src/packages/member/member-rest.module.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RESTModule } from '@loafer/ng-rest';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RESTModule.forFeature({}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class MemberRESTModule { }
|
|
@ -6,6 +6,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MaterialModule } from 'packages/commons/material/material.module';
|
import { MaterialModule } from 'packages/commons/material/material.module';
|
||||||
|
|
||||||
import { MemberStoreModule } from './member-store.module';
|
import { MemberStoreModule } from './member-store.module';
|
||||||
|
import { MemberRESTModule } from './member-rest.module';
|
||||||
|
|
||||||
import { COMPONENTS } from './component';
|
import { COMPONENTS } from './component';
|
||||||
import { SERVICES } from './service';
|
import { SERVICES } from './service';
|
||||||
|
@ -18,6 +19,7 @@ import { SERVICES } from './service';
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
MemberStoreModule,
|
MemberStoreModule,
|
||||||
|
MemberRESTModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
COMPONENTS,
|
COMPONENTS,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
import { RESTClient } from 'packages/core/rest/client/RESTClient';
|
import { RESTService } from '@loafer/ng-rest/service';
|
||||||
import { DomainMember } from 'packages/domain/model';
|
import { DomainMember } from 'packages/domain/model';
|
||||||
|
|
||||||
import { Member } from '../model';
|
import { Member } from '../model';
|
||||||
|
@ -12,7 +12,7 @@ import { Member } from '../model';
|
||||||
export class MemberService {
|
export class MemberService {
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private restClient: RESTClient,
|
private restService: RESTService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ export class MemberService {
|
||||||
signinPw: password,
|
signinPw: password,
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.restClient.request<any>('post', '/account/signin', {
|
return this.restService.request<any>('post', '/account/signin', {
|
||||||
body: body,
|
body: body,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,13 @@ export class MemberService {
|
||||||
authToken: authToken,
|
authToken: authToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.restClient.request<DomainMember>('post', '/account/signin_cookie', {
|
return this.restService.request<DomainMember>('post', '/account/signin_cookie', {
|
||||||
body: body,
|
body: body,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public signup(member: Member): Observable<Member> {
|
public signup(member: Member): Observable<Member> {
|
||||||
return this.restClient.request<Member>('post', '/account/signup', {
|
return this.restService.request<Member>('post', '/account/signup', {
|
||||||
body: member,
|
body: member,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { RESTError } from 'packages/core/rest/error';
|
import { RESTClientError } from '@loafer/ng-rest/protocol';
|
||||||
|
|
||||||
import { DomainMember } from 'packages/domain/model';
|
import { DomainMember } from 'packages/domain/model';
|
||||||
import { Member } from '../../model';
|
import { Member } from '../../model';
|
||||||
|
@ -35,7 +35,7 @@ export class SigninSuccess implements Action {
|
||||||
export class SigninFailure implements Action {
|
export class SigninFailure implements Action {
|
||||||
readonly type = ActionType.SigninFailure;
|
readonly type = ActionType.SigninFailure;
|
||||||
|
|
||||||
constructor(public payload: RESTError) {}
|
constructor(public payload: RESTClientError) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SigninRedirect implements Action {
|
export class SigninRedirect implements Action {
|
||||||
|
@ -58,7 +58,7 @@ export class SigninCookieSuccess implements Action {
|
||||||
export class SigninCookieFailure implements Action {
|
export class SigninCookieFailure implements Action {
|
||||||
readonly type = ActionType.SigninCookieFailure;
|
readonly type = ActionType.SigninCookieFailure;
|
||||||
|
|
||||||
constructor(public payload: RESTError) {}
|
constructor(public payload: RESTClientError) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Signout implements Action {
|
export class Signout implements Action {
|
||||||
|
@ -72,7 +72,7 @@ export class SignoutSuccess implements Action {
|
||||||
export class SignoutFailure implements Action {
|
export class SignoutFailure implements Action {
|
||||||
readonly type = ActionType.SignoutFailure;
|
readonly type = ActionType.SignoutFailure;
|
||||||
|
|
||||||
constructor(public payload: RESTError) {}
|
constructor(public payload: RESTClientError) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Actions =
|
export type Actions =
|
||||||
|
|
|
@ -14,7 +14,7 @@ import 'rxjs/add/operator/switchMap';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
import 'rxjs/add/operator/take';
|
import 'rxjs/add/operator/take';
|
||||||
|
|
||||||
import { RESTError } from 'packages/core/rest/error';
|
import { RESTClientError } from '@loafer/ng-rest/protocol';
|
||||||
|
|
||||||
import { DomainMember } from 'packages/domain/model';
|
import { DomainMember } from 'packages/domain/model';
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ export class Effects {
|
||||||
const domainMember = result['domainMember'];
|
const domainMember = result['domainMember'];
|
||||||
return new SigninSuccess({authToken: authToken, domainMember: domainMember});
|
return new SigninSuccess({authToken: authToken, domainMember: domainMember});
|
||||||
})
|
})
|
||||||
.catch((error: RESTError) => {
|
.catch((error: RESTClientError) => {
|
||||||
return of(new SigninFailure(error));
|
return of(new SigninFailure(error));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ export class Effects {
|
||||||
.map((domainMember: DomainMember) => {
|
.map((domainMember: DomainMember) => {
|
||||||
return new SigninCookieSuccess(domainMember);
|
return new SigninCookieSuccess(domainMember);
|
||||||
})
|
})
|
||||||
.catch((error: RESTError) => {
|
.catch((error: RESTClientError) => {
|
||||||
return of(new SigninFailure(error));
|
return of(new SigninFailure(error));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { RESTError } from 'packages/core/rest/error';
|
import { RESTClientError } from '@loafer/ng-rest/protocol';
|
||||||
import { Domain } from 'packages/domain/model';
|
import { Domain } from 'packages/domain/model';
|
||||||
import { Member } from '../../model';
|
import { Member } from '../../model';
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
signined: boolean;
|
signined: boolean;
|
||||||
error: RESTError | null;
|
error: RESTClientError | null;
|
||||||
pending: boolean;
|
pending: boolean;
|
||||||
member: Member | null;
|
member: Member | null;
|
||||||
domain: Domain | null;
|
domain: Domain | null;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { RESTError } from 'packages/core/rest/error';
|
import { RESTClientError } from '@loafer/ng-rest/protocol';
|
||||||
|
|
||||||
import { Member } from '../../model';
|
import { Member } from '../../model';
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ export class SignupSuccess implements Action {
|
||||||
export class SignupFailure implements Action {
|
export class SignupFailure implements Action {
|
||||||
readonly type = ActionType.SignupFailure;
|
readonly type = ActionType.SignupFailure;
|
||||||
|
|
||||||
constructor(public payload: RESTError) {}
|
constructor(public payload: RESTClientError) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Actions =
|
export type Actions =
|
||||||
|
|
|
@ -13,8 +13,6 @@ import 'rxjs/add/operator/exhaustMap';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
import 'rxjs/add/operator/take';
|
import 'rxjs/add/operator/take';
|
||||||
|
|
||||||
import { RESTError } from 'packages/core/rest/error';
|
|
||||||
|
|
||||||
import { Member } from '../../model';
|
import { Member } from '../../model';
|
||||||
import { MemberService } from '../../service/member.service';
|
import { MemberService } from '../../service/member.service';
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { RESTError } from 'packages/core/rest/error';
|
import { RESTClientError } from '@loafer/ng-rest/protocol';
|
||||||
|
|
||||||
import { Member } from '../../model';
|
import { Member } from '../../model';
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
error: RESTError | null;
|
error: RESTClientError | null;
|
||||||
pending: boolean;
|
pending: boolean;
|
||||||
member: Member | null;
|
member: Member | null;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user