UNPKG

typenexus

Version:

TypeNexus is a good tool for API encapsulation and management. It provides a clean and lightweight way to package TypeORM functionality, helping you build applications faster while reducing template code redundancy and type conversion work.

195 lines (194 loc) 6.9 kB
/** * Action metadata. */ export class ActionMetadata { globalOptions; /** * Action's controller. */ controllerMetadata; /** * Class on which's method this action is attached. */ target; /** * Object's method that will be executed on this action. */ method; /** * Route to be registered for the action. */ route; /** * Indicates if this action uses Body. */ isBodyUsed; /** * Indicates if this action uses Uploaded File. */ isFileUsed; /** * Indicates if this action uses Uploaded Files. */ isFilesUsed; /** * Extra options used by @Body decorator. */ bodyExtraOptions; /** * Action type represents http method used for the registered route. Can be one of the value defined in ActionTypes * class. */ type; /** * Action's parameters. */ params; /** * Action's constructor parameters. */ paramsConstructor = []; /** * Full route to this action (includes controller base route). */ fullRoute; /** * Indicates if this action uses Authorized decorator. */ isAuthorizedUsed; /** * Roles set by @Authorized decorator. */ authorizedRoles; /** * Indicates if controller of this action is json-typed. */ isJsonTyped; /** * Action's use metadatas. */ uses; /** * Http code to be used on undefined action returned content. */ undefinedResultCode; /** * Http code to be used on null action returned content. */ nullResultCode; /** * Http code to be set on successful response. */ successHttpCode; /** * Specifies redirection url for this action. */ redirect; /** * Rendered template to be used for this controller action. */ renderedTemplate; /** * Response headers to be set. */ headers; constructor(controllerMetadata, args, globalOptions) { this.globalOptions = globalOptions; this.controllerMetadata = controllerMetadata; this.route = args.route; this.target = args.target; this.method = args.method; this.type = args.type; } /** * Builds everything action metadata needs. * Action metadata can be used only after its build. */ build(responseHandlers) { const authorizedHandler = responseHandlers.find((handler) => handler.type === 'authorized'); const contentTypeHandler = responseHandlers.find((handler) => handler.type === 'content-type'); const undefinedResultHandler = responseHandlers.find((handler) => handler.type === 'on-undefined'); const nullResultHandler = responseHandlers.find((handler) => handler.type === 'on-null'); const successCodeHandler = responseHandlers.find((handler) => handler.type === 'success-code'); const redirectHandler = responseHandlers.find((handler) => handler.type === 'redirect'); const renderedTemplateHandler = responseHandlers.find((handler) => handler.type === 'rendered-template'); const bodyParam = this.params.find((param) => param.type === 'body'); if (successCodeHandler) this.successHttpCode = successCodeHandler.value; if (redirectHandler) this.redirect = redirectHandler.value; if (renderedTemplateHandler) this.renderedTemplate = renderedTemplateHandler.value; this.undefinedResultCode = undefinedResultHandler ? undefinedResultHandler.value : this.globalOptions.defaults && this.globalOptions.defaults.undefinedResultCode; this.nullResultCode = nullResultHandler ? nullResultHandler.value : this.globalOptions.defaults && this.globalOptions.defaults.nullResultCode; this.bodyExtraOptions = bodyParam ? bodyParam.extraOptions : undefined; this.isBodyUsed = !!this.params.find((param) => param.type === 'body' || param.type === 'body-param'); this.isFilesUsed = !!this.params.find((param) => param.type === 'files'); this.isFileUsed = !!this.params.find((param) => param.type === 'file'); this.isJsonTyped = contentTypeHandler !== undefined ? /json/.test(contentTypeHandler.value) : this.controllerMetadata.type === 'json'; this.fullRoute = this.buildFullRoute(); this.headers = this.buildHeaders(responseHandlers); this.isAuthorizedUsed = this.controllerMetadata.isAuthorizedUsed || !!authorizedHandler; this.authorizedRoles = (this.controllerMetadata.authorizedRoles || []).concat((authorizedHandler && authorizedHandler.value) || []); } /** * Appends base route to a given regexp route. */ static appendBaseRoute(baseRoute, route) { const prefix = `/${baseRoute}`.replace(/\/+/g, '/'); if (typeof route === 'string') return `${prefix}/${route}`.replace(/\/+/g, '/'); if (!baseRoute || baseRoute === '') return route; const fullPath = `^${prefix}${route.toString().substring(1)}?$`; return new RegExp(fullPath, route.flags); } /** * Builds full action route. */ buildFullRoute() { if (this.route instanceof RegExp) { if (this.controllerMetadata.route) { return ActionMetadata.appendBaseRoute(this.controllerMetadata.route, this.route); } return this.route; } let path = ''; if (this.controllerMetadata.route) path += this.controllerMetadata.route; if (this.route && typeof this.route === 'string') path += this.route; return path; } /** * Calls action method. * Action method is an action defined in a user controller. */ callMethod(params, paramsConstructor, action) { const controllerInstance = this.controllerMetadata.getInstance(action, paramsConstructor); return controllerInstance[this.method].apply(controllerInstance, params); } /** * Builds action response headers. */ buildHeaders(responseHandlers) { const locationHandler = responseHandlers.find((handler) => handler.type === 'location'); const contentTypeHandler = responseHandlers.find((handler) => handler.type === 'content-type'); const headerHandlers = responseHandlers.filter((handler) => handler.type === 'header'); const headers = {}; if (locationHandler) headers['Location'] = locationHandler.value; if (contentTypeHandler) headers['Content-type'] = contentTypeHandler.value; if (headerHandlers) headerHandlers.map((handler) => (headers[handler.value] = handler.secondaryValue)); return headers; } }