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