feat: add cc-server-binding
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
parent
8e56d471a7
commit
6c61f14907
4
packages/cc-server-binding/.gitignore
vendored
Normal file
4
packages/cc-server-binding/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/node_modules
|
||||||
|
/dist
|
||||||
|
/package-lock.json
|
||||||
|
/yarn.lock
|
11
packages/cc-server-binding/README.md
Normal file
11
packages/cc-server-binding/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# `cc-server-binding`
|
||||||
|
|
||||||
|
> TODO: description
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
const ccServerBinding = require('cc-server-binding');
|
||||||
|
|
||||||
|
// TODO: DEMONSTRATE API
|
||||||
|
```
|
33
packages/cc-server-binding/package.json
Normal file
33
packages/cc-server-binding/package.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "cc-server-binding",
|
||||||
|
"version": "0.2.5",
|
||||||
|
"description": "> TODO: description",
|
||||||
|
"author": "MiaoWoo <admin@yumc.pw>",
|
||||||
|
"homepage": "https://github.com/502647092/cc-server-parent#readme",
|
||||||
|
"license": "ISC",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://repo.yumc.pw/repository/npm/"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/502647092/cc-server-parent.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "npx ts-node src/index.ts",
|
||||||
|
"build": "rimraf dist && npx tsc",
|
||||||
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"reflect-metadata": "^0.1.13"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"mocha": "^6.1.4",
|
||||||
|
"rimraf": "^2.6.3",
|
||||||
|
"typescript": "^3.5.1"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/502647092/cc-server-parent/issues"
|
||||||
|
}
|
||||||
|
}
|
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
|
||||||
|
}
|
7
packages/cc-server-binding/tsconfig.json
Normal file
7
packages/cc-server-binding/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"outDir": "dist"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user