// import * as request from "request"; import { IChassisContext, IOperation } from "../interfaces"; import Vars from "./Vars"; import * as _ from "lodash"; // import * as http from "http"; // import * as https from "https"; // import { URL } from "url"; import Axios from "axios"; export default class APIs { static DEBUG = false; constructor() {} public static get(context: IChassisContext, url: string): Promise { return new Promise((resolve, reject) => { Axios.get(url) .then((rep) => { resolve(rep.data); }) .catch((err) => { context.error({ code: "feature:request:get:failed", url: url, error: err ? err.toString() : "no error", }); reject(err); }); }); } public static request( context: IChassisContext, url: string, _headers?: any ): Promise { // let headers = APIs.get_headers_with_token(_headers, token); return new Promise((resolve, reject) => { // call backend API APIs.DEBUG && context.log({ code: "feature:request:api", url: url, }); // call backend API APIs.DEBUG && context.log({ code: "feature:request:api", url: url, }); Axios.get(url, { headers: _headers }) .then((rep) => { resolve(rep.data); }) .catch((err) => { context.error({ code: "feature:request:api:failed", url: url, error: err ? err.toString() : "no error", }); reject(err); }); }); } public static named_request( context: IChassisContext, api_name: string, // url: string, api: APIRequest ): Promise { return new Promise((resolve, reject) => { // call backend API APIs.DEBUG && context.log({ code: "feature:api:request", api: api_name, url: api.url, headers: api.headers, }); Axios.request({ url: api.url, headers: api.headers, params: api.params, }) .then((resp) => { try { let result = {}; APIs.DEBUG && context.log({ code: "feature:api:response", api: api_name, url: api.url, response: resp, }); result[api_name] = _.isObject(resp.data) ? resp.data : JSON.parse(resp.data); resolve(result); } catch (e) { console.error( "feature:api:json:failed: %o --> %o", e, resp ); reject(e); } }) .catch((err) => { context.error({ code: "feature:api:failed", api: api_name, url: api.url, error: err ? err.toString() : "no error", }); reject(err); }); }); } public static get_headers_with_token(headers: any, token?: string) { let _headers: any = _.extend({}, headers); if (token) { // inject Bearer Token _headers.Authorization = token; } return _headers; } /** * Collect a set of API responses as promise * * @param apis * @param opx_ctx * @param token */ public static requests( context: IChassisContext, apis: APIRequests, op_ctx: any, token?: string ): Promise { let _requests = []; // iterate over set of APIs for (let api_name in apis) { let api: APIRequest = _.extend({}, apis[api_name]); api.headers = APIs.get_headers_with_token(api.headers, token); api.params = _.extend({}, api.params); if (token) { // inject Bearer Token api.headers.authorization = token; } api.url = Vars.$$(api.url, op_ctx); let _request = this.named_request(context, api_name, api); _requests.push(_request); } return new Promise((resolve, reject) => { // concurrent "named" requests Promise.all(_requests) .then((responses) => { // merge named results let results: APIResponses = {}; for (let r in responses) { _.extend(results, responses[r]); } resolve(results); }) .catch(reject); }); } public static getOperationContext( _op: IOperation, req: any, _ctx?: any ): APIContext { let ctx = _.extend({}, _ctx, { op: { resource: _op.resource, actionId: _op.actionId, operationId: _op.operationId, }, }); return APIs.getRequestContext(req, ctx); } public static getRequestContext(req: any, _ctx?: any): APIContext { let params = _.extend({}, req.query, req.params); // merged params let ctx = _.extend( { params: {}, jwt: {}, query: {} }, _ctx, req ? { req: { path: req.path, method: req.method }, params: params, path: req.params, query: req.query, jwt: req.jwt || {}, } : {} ); // console.log("req.ctx: %o --> %o", req.params, ctx); return ctx as APIContext; } public static resource_path_to_express_path(resource: string): string { return resource .replace(new RegExp("{", "g"), ":") .replace(new RegExp("}", "g"), ""); } public static getContentType(type: string) { if (!type) return "application/json"; let ix = type.indexOf(";"); if (ix < 0) return type; return type.substring(0, ix); } public static oops(context: IChassisContext, res: any, log: any) { context.warn(log); res.status(log.statusCode || 400); res.send({ code: log.code, message: log.message || log.error || log.code, error: log.error || true, }); } public static async sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } export interface APIRequests { [name: string]: APIRequest; } export interface APIRequest { url: string; method?: string; headers?: any; params?: any; } export interface APIResponses { [name: string]: any; } export interface APIContext { req: any; op: any; jwt: any; headers?: any; params: any; query: any; }