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"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user