/** * @author Olsi Rrjolli */ import { deserialize } from 'json-typescript-mapper'; import 'reflect-metadata'; import { isUndefined } from 'util'; import { IController, IAwsRequestEvent } from '../types/index'; import { httpMethod, controllerMetaKey } from '../constants/constants'; import ValidationError from '../exceptions/ValidationError'; /** * Generate the metakey for the reflection * The Resource Path * @param httpMethod * The http method (GET, POST ...) * @param path * @returns {string} * return metakey to set the reflection id */ export const generateMetaKey = (httpMethod: string, path: string = ''): string => { return httpMethod + path; }; /** * Generate the metakey for the reflection * The Resource Path * @param httpMethod * The http method (GET, POST ...) * @param path * The path * @param resource * The resource * @returns {string} * return metakey to set the reflection id */ export const generateResourceMetaKey = (httpMethod: string, resource: string, path: string = ''): string => { return httpMethod + resource + path; }; /** * Get the method as function * @param controller * The Controller which will contain the method * @param toCallenMethodName * The Method name which selected * @return Function * The method as Function */ export const getMethod = (controller: IController, toCallenMethodName: string): Function => { return Reflect.get(controller, toCallenMethodName).bind(controller); }; /** * Get the method name * @param requestEvent * The AWS Request Event * @param controller * The Controller which will contain the Method. * @return {any} * The method name */ export const getMethodName = (requestEvent: IAwsRequestEvent, controller: IController): string => { return Reflect.getMetadata(generateMetaKey(requestEvent.httpMethod, requestEvent.resource), controller.constructor); }; /** * Get the method meta data * @param toCallMethod * The method that contains the MetaData * @param toCallController * The Controller which contains the method * @return {any} * The metadata as arraz */ export const getMethodMetadata = (toCallMethod: string, toCallController: IController): Array => { return Reflect.getMetadata(toCallMethod, toCallController, toCallMethod); }; /** * Check if execution method exist in the Controller * @param requestEvent * The Request Event * @param controller * The controller * @return {boolean} * true if method exist, otherwise false */ export const isMethodExistInController = (requestEvent: IAwsRequestEvent, controller: IController): boolean => { return !isUndefined(getMethodName(requestEvent, controller)); }; /** * Get the method metadata for example for the params and query parameter * @param controller * The controller for the target * @return {any} * Metadata as array; can be empty */ export const getControllerMetadata = (controller: IController): Array => { return Reflect.getMetadataKeys(controller.constructor); }; /** * Get the method metadata for example for the params and query parameter * @param controller * The controller for the target * @return {any} * Metadata as array; can be empty */ export const getModelForController = (controller: IController): any => { return Reflect.getOwnMetadata(controllerMetaKey.MODEL_KEY, controller.constructor); }; /** * Get the arguments for the callen method from requestEvent * @param awsRequestEvent * The request Event * @param toCallMethodName * the method from getting the arguments * @param toCallController * The controller which contains the execution method * @returns {string} * return arguments for the method */ export const parseArguments = (awsRequestEvent: IAwsRequestEvent, toCallMethodName: string, toCallController: IController): Array => { const methodMetaData = getMethodMetadata(toCallMethodName, toCallController); const model = getModelForController(toCallController); const args = new Array(); let bodyIndex = 0; if (methodMetaData) { // Get Path & Query Params for the to callen method if they set methodMetaData.forEach((metaData) => { bodyIndex = metaData.index === bodyIndex ? ++bodyIndex : bodyIndex; if (awsRequestEvent.pathParameters && awsRequestEvent.pathParameters !== null) { args[metaData.index] = awsRequestEvent.pathParameters[metaData.paramName]; } if (awsRequestEvent.queryStringParameters && awsRequestEvent.queryStringParameters !== null) { args[metaData.index] = awsRequestEvent.queryStringParameters[metaData.queryName]; } }); } if (!awsRequestEvent.body && (awsRequestEvent.httpMethod === httpMethod.POST || awsRequestEvent.httpMethod === httpMethod.PUT)) { throw new ValidationError('Invalid data', [{ field: 'body', message: 'body is required' }]); } args[bodyIndex] = model ? deserialize(model, JSON.parse(awsRequestEvent.body)) : JSON.parse(awsRequestEvent.body); return args; };