UNPKG

@scefira/dfw-nodejs

Version:
301 lines (253 loc) 9.59 kB
import DFWModule from "./DFWModule"; import { DFWScheme } from "../.."; import { Request, Response, Router, NextFunction, RequestHandler } from "express"; import axios, { AxiosRequestConfig, AxiosResponse, AxiosStatic } from "axios"; import { isString, isObject } from "util"; import SecurityManager from "./SecurityManager"; import { UploadOptions, UploadConfig } from "./UploadManager"; export type BootCallback = (dfw:DFWScheme,boot:any)=>Promise<any>; export type APIMethods = "get"|"put"|"post"|"delete"|"options"|"link"; export type APIFunction = ((dfw:DFWScheme)=>Promise<any>)|((dfw:DFWScheme)=>any); export class APIListener{ public caller:APIFunction; public config:DFWListenerConfig; constructor(f:APIFunction,cfg?:DFWListenerConfig){ this.caller = f; this.config = cfg?cfg:{}; } } export default class APIManager extends DFWModule{ private bootCallbacks:BootCallback[] = [ /** add default callback on each APIManager instance */ async (dfw,boot:DFWBoot)=>{ boot.session = { isLogged: dfw.session.isLogged, nick: dfw.session.isLogged?dfw.session.model.user!.nick:undefined, email:dfw.session.isLogged?dfw.session.model.user!.email:undefined, credentials:[], access:[] } if(dfw.session.isLogged && dfw.session.model.user){ // if is user logged, then we load the access and credentials and send it to boot state dfw.session.model.user.credentials.forEach((c)=>{ let {name,description,id} = c; boot.session.credentials.push({name,description,id}); if(c.access !== undefined){ c.access.forEach((a)=>{ let {name,description,id} = a; boot.session.credentials.push({name,description,id}); }) } }) } } ]; /** * * @param dfw */ public async touchAsync(dfw:DFWScheme){ dfw.api.bootAsync = async ()=>{ return await this.getBootAsync(dfw); } dfw.api.error = (description?:string,reference?:string)=>{ dfw.response.status(400); dfw.response.statusMessage = "ERROR"; return { "error" : description , ref: reference }; } dfw.api.success = (data?:any)=>{ return data?data:""; } dfw.api.response = (data:any)=>{ this.response(dfw,data); } dfw.api.notFound = (description?:string)=>{ dfw.response.status(404); return { "message" : description }; } } /** * * @param dfw */ public async getBootAsync(dfw:DFWScheme):Promise<any>{ let result = {}; for(let i = 0; i < this.bootCallbacks.length; i++){ await this.bootCallbacks[i](dfw,result); } return result; } /** * * @param bootc */ public addBootCallback(bootc:BootCallback){ this.bootCallbacks.push(bootc); } /** * * @param dfw */ public response(dfw:DFWScheme,data:{}){ dfw.response.json(data); } /** * fetch data to the server * @param path * @param config */ public fetch(path:string,config?:AxiosRequestConfig):Promise<AxiosResponse>{ return axios.get(path,config); } /** * add an API listener * @param path * @param f * @param method * @param router */ public addListener(path:string,f:APIFunction,cfg?:DFWListenerConfig|APIMethods){ if(this.DFWInstance.server === undefined){ console.error("> you need to start DFW express server (DFW.startServer) to add an API listener"); return; } let {method, router, middleware,...settings} = isObject(cfg)?cfg as DFWListenerConfig:{} as DFWListenerConfig; if(settings === undefined) settings = {}; if(method === undefined) method = isString(cfg)?cfg:"get"; if(router === undefined) router = this.DFWInstance.server; if(middleware === undefined) middleware = []; middleware.push(this.DFWInstance.middleware); // Validation of the rules in DFWListenerConfig if fails locks the process middleware.push((req:Request,res:Response,next:NextFunction)=>{ this.validateListenerConfigRules(req.dfw!,settings).then((status)=>{ if(status === true){ next(); } }).catch((e)=>{ this.response(req.dfw!, req.dfw!.api.error(`${e}`,"dfw")); }) }); // Third party middlewares validated if(settings.security !== undefined && settings.security.uploads){ let uploadCfg:UploadConfig = (isObject( settings.security.uploads))?settings.security.uploads as UploadConfig:{}; middleware.push(this.DFWInstance.modules.uploadManager.makeUploadMiddleware(uploadCfg)); } // Main DFW library middleware middleware.push((req:Request,res:Response,next:NextFunction)=>{ let dfw:DFWScheme = req.dfw!; f(dfw).then((data)=>{ this.response(dfw,data); }).catch((e)=>{ console.log(e); this.response(dfw, dfw.api.error(`${e}`,"api")); }); }); router![method](path,middleware) } /** * synonym of addUploadListener from UploadManager * @param path * @param dfwConfig * @param uploadConfig */ public addUploadListener(path:string,dfwConfig:DFWListenerConfig = {},uploadConfig?:UploadOptions){ if(dfwConfig.security === undefined) dfwConfig.security = {}; if(dfwConfig.security!.uploads === undefined) dfwConfig.security!.uploads = true; this.DFWInstance.modules.APIManager.addListener(path, async (dfw:DFWScheme)=>{ let file = await dfw.file.flushUploadAsync(dfw.request.files["file"] as any,uploadConfig); if(!file){ return dfw.api.error(); }else{ return dfw.api.success({ file: await this.DFWInstance.modules.uploadManager.getFileRecordDataAsync(file) }); } },Object.assign({},dfwConfig,{method:"post"})); this.DFWInstance.modules.APIManager.addListener(path, async (dfw:DFWScheme)=>{ dfw.response.set({ 'Access-Control-Allow-Methods': 'OPTIONS, POST', 'Access-Control-Allow-Headers': 'Content-Type' }); },"options"); } /** * @returns boolean true if checking is succeed or false if one rule fail */ public async validateListenerConfigRules(dfw:DFWScheme,settings:DFWListenerConfig){ if(settings.security !== undefined ){ // Modulo de seguridad if(settings.security.session !== undefined && ! await dfw.security.checkRuleAsync(SecurityManager.RULE_LOGGED_SESSION,settings.security.session)){ dfw.api.response(dfw.api.error(SecurityManager.LABEL_RULE_LOGGED_SESSION)); return false; } if(settings.security.credentials !== undefined && ! await dfw.security.checkRuleAsync(SecurityManager.RULE_CREDENTIAL,settings.security.credentials)){ dfw.api.response(dfw.api.error(SecurityManager.LABEL_RULE_CREDENTIAL)); return false; } if(settings.security.access !== undefined && ! await dfw.security.checkRuleAsync(SecurityManager.RULE_ACCESS,settings.security.access)){ dfw.api.response(dfw.api.error(SecurityManager.LABEL_RULE_ACCESS)); return false; } } return true; } //////////////////////////////////////////////////////////////////////////////// /** * Return an instance of axios */ public static axios:AxiosStatic = axios; } /** * Configuration for listener in DFW */ export interface DFWListenerConfig{ method?:APIMethods; router?:Router; middleware?:RequestHandler[]; security?:{ session?:boolean; credentials?:string|string[]; access?:string|string[]; uploads?:boolean|UploadConfig; } validation?:{ body?:string[], query?:string[], } } export type DFWBasicBoot = { session:{ isLogged:boolean, nick?:string, email?:string, credentials:{ id:number, name:string, description?:string, }[], access?:{ id:number, name:string, description?:string, }[] } } export type DFWBoot<T extends {} = DFWBasicBoot> = T & DFWBasicBoot; export interface DFWAPISchema{ /** * */ bootAsync: () => Promise<{}>; /** * */ error: (description?:string,ref?:string) => any; /** * */ success: (data?:any)=>any; /** * */ response: (data:any)=>void; /** * */ notFound: (description?:string)=>void; }