69
packages/cc-server-binding/src/activation.ts
Normal file
69
packages/cc-server-binding/src/activation.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Container, interfaces as inversify_interfaces } from 'inversify'
|
||||
import { TYPE, interfaces as express_interfaces } from 'inversify-express-utils'
|
||||
import { METADATA_KEY, VAILD_TYPE } from './constants'
|
||||
import { interfaces } from './interfaces'
|
||||
import { getVaildMethodMetadata, getVaildControllerMetadata, getVaildModelMetadata } from './utils'
|
||||
|
||||
let handler = {
|
||||
apply: function(target: Function, thisArgument: Object, argumentsList: any[]) {
|
||||
let methodParams = getVaildMethodMetadata(target);
|
||||
let [req, res, next] = [...argumentsList.slice(-3)];
|
||||
try {
|
||||
// loop @Valid params
|
||||
for (const param of methodParams) {
|
||||
// get function argument value
|
||||
let origin = argumentsList[param.index]
|
||||
let props = getVaildModelMetadata(param.type);
|
||||
for (const prop of props) {
|
||||
let propValue = origin[prop.name];
|
||||
switch (prop.type) {
|
||||
case VAILD_TYPE.NOT_BLANK:
|
||||
if (!propValue) {
|
||||
throw new Error(prop.message);
|
||||
}
|
||||
break;
|
||||
case VAILD_TYPE.NOT_NULL:
|
||||
if (propValue == undefined) {
|
||||
throw new Error(prop.message);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unkonw Vaild Type!')
|
||||
}
|
||||
}
|
||||
}
|
||||
return target.apply(thisArgument, argumentsList);
|
||||
} catch (ex) {
|
||||
res.status(400).json({
|
||||
status: 400,
|
||||
message: ex.message
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function rebuildServer(container: Container) {
|
||||
// get all controller
|
||||
let controllers = container.getAll<express_interfaces.Controller>(TYPE.Controller)
|
||||
// for loop controllers and inject proxy to each method
|
||||
for (const controller of controllers) {
|
||||
container.rebind(TYPE.Controller)
|
||||
.to(controller.constructor as any)
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(controller.constructor.name)
|
||||
.onActivation((ctx: inversify_interfaces.Context, controller: express_interfaces.Controller) => {
|
||||
let prop = controller.constructor.prototype
|
||||
// funcs => { create: [ { index: 0, type: [Function: ExampleModel] } ] }
|
||||
let funcs = getVaildControllerMetadata(controller.constructor);
|
||||
//Reflect.getMetadata(METADATA_KEY.controllerParameter, controller.constructor);
|
||||
for (const func in funcs) {
|
||||
Reflect.defineMetadata(METADATA_KEY.vaildMethod, funcs[func], prop[func])
|
||||
// Define Proxy handle model vaild
|
||||
Reflect.defineProperty(prop, func, { value: new Proxy(prop[func], handler) })
|
||||
}
|
||||
return controller;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { rebuildServer }
|
||||
10
packages/cc-server-binding/src/constants.ts
Normal file
10
packages/cc-server-binding/src/constants.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export const METADATA_KEY = {
|
||||
vaildModel: "cc-server-binding:vaild-model",
|
||||
vaildMethod: "cc-server-binding:vaild-method",
|
||||
vaildController: "cc-server-binding:vaild-controller"
|
||||
};
|
||||
|
||||
export enum VAILD_TYPE {
|
||||
NOT_BLANK,
|
||||
NOT_NULL
|
||||
}
|
||||
50
packages/cc-server-binding/src/decorators.ts
Normal file
50
packages/cc-server-binding/src/decorators.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import 'reflect-metadata'
|
||||
import { METADATA_KEY, VAILD_TYPE } from './constants';
|
||||
import { getVaildControllerMetadata, getVaildModelMetadata } from './utils'
|
||||
import { interfaces } from './interfaces'
|
||||
/**
|
||||
* ParameterVaild
|
||||
*/
|
||||
export function Vaild(): ParameterDecorator {
|
||||
return (controller: Object, methodName: string, index: number): void => {
|
||||
var type = Reflect.getMetadata("design:paramtypes", controller, methodName)[index];
|
||||
let metadataList = getVaildControllerMetadata(controller.constructor);
|
||||
let parameterMetadataList = metadataList[methodName] || [];
|
||||
let parameterMetadata: interfaces.ParameterMetadata = {
|
||||
index: index,
|
||||
type: type
|
||||
};
|
||||
parameterMetadataList.unshift(parameterMetadata);
|
||||
metadataList[methodName] = parameterMetadataList;
|
||||
Reflect.defineMetadata(METADATA_KEY.vaildController, metadataList, controller.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vaild Blank String
|
||||
* @param message Error Message
|
||||
*/
|
||||
export const NotBlank: (message?: string) => PropertyDecorator = vaildDecoratorFactory(VAILD_TYPE.NOT_BLANK);
|
||||
/**
|
||||
* Vaild Null Param
|
||||
* @param message Error Message
|
||||
*/
|
||||
export const NotNull: (message?: string) => PropertyDecorator = vaildDecoratorFactory(VAILD_TYPE.NOT_NULL);
|
||||
|
||||
function vaildDecoratorFactory(type: VAILD_TYPE): () => PropertyDecorator {
|
||||
return function(message?: string): PropertyDecorator {
|
||||
return vaildProperty(type, message);
|
||||
};
|
||||
}
|
||||
|
||||
function vaildProperty(type: VAILD_TYPE, message?: string): PropertyDecorator {
|
||||
return (model: Object, propertyKey: string) => {
|
||||
let metadataList: interfaces.PropertyMetadata[] = getVaildModelMetadata(model.constructor);
|
||||
metadataList.push({
|
||||
name: propertyKey,
|
||||
message: message || `model ${model.constructor.name} property ${propertyKey} vaild failed => ${VAILD_TYPE[type]}`,
|
||||
type: type
|
||||
})
|
||||
Reflect.defineMetadata(METADATA_KEY.vaildModel, metadataList, model.constructor);
|
||||
}
|
||||
}
|
||||
4
packages/cc-server-binding/src/index.ts
Normal file
4
packages/cc-server-binding/src/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './decorators'
|
||||
export * from './constants';
|
||||
export * from './utils'
|
||||
export * from './activation'
|
||||
20
packages/cc-server-binding/src/interfaces.ts
Normal file
20
packages/cc-server-binding/src/interfaces.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { VAILD_TYPE } from './constants'
|
||||
|
||||
namespace interfaces {
|
||||
export interface MethodMetadata {
|
||||
[methodName: string]: ParameterMetadata[];
|
||||
}
|
||||
|
||||
export interface ParameterMetadata {
|
||||
index: number;
|
||||
type: NewableFunction;
|
||||
}
|
||||
|
||||
export interface PropertyMetadata {
|
||||
name: string;
|
||||
message: string;
|
||||
type: VAILD_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
export { interfaces };
|
||||
32
packages/cc-server-binding/src/utils.ts
Normal file
32
packages/cc-server-binding/src/utils.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { METADATA_KEY } from './constants'
|
||||
import { interfaces } from './interfaces'
|
||||
|
||||
function getVaildControllerMetadata(model: Object) {
|
||||
let controllerMetadata: interfaces.MethodMetadata = Reflect.getMetadata(
|
||||
METADATA_KEY.vaildController,
|
||||
model
|
||||
) || {};
|
||||
return controllerMetadata;
|
||||
}
|
||||
|
||||
function getVaildMethodMetadata(constructor: any) {
|
||||
let parameterMetadata: interfaces.ParameterMetadata[] = Reflect.getMetadata(
|
||||
METADATA_KEY.vaildMethod,
|
||||
constructor
|
||||
) || [];
|
||||
return parameterMetadata;
|
||||
}
|
||||
|
||||
function getVaildModelMetadata(model: Object) {
|
||||
let propertyMetadata: interfaces.PropertyMetadata[] = Reflect.getMetadata(
|
||||
METADATA_KEY.vaildModel,
|
||||
model
|
||||
) || [];
|
||||
return propertyMetadata;
|
||||
}
|
||||
|
||||
export {
|
||||
getVaildControllerMetadata,
|
||||
getVaildMethodMetadata,
|
||||
getVaildModelMetadata
|
||||
}
|
||||
Reference in New Issue
Block a user