UNPKG

lugger

Version:

Lugger is an automation framework running on customizable Typescript DSL

186 lines (166 loc) 8 kB
// DSL SKIP import { CallContextEvent, CCE, dedent, getRuntime, PostfixReturn, dslIfaceGuard } from "ts-dsl"; import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios"; import Express from 'express'; import { Request, Response } from 'express'; import { Server } from "http"; import { promise, _, TaggedTemplateSelfChain } from 'ts-basis'; import { HttpError, HttpFinalizerExpress } from "./http.model"; // ==================================================== // Facade // ==================================================== type ExpressServer = Express.Express & { server?: Server, start?: () => ExpressServer, stop?: () => ExpressServer }; class httpModel { static get<T = any, D = any>(config: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static get<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static get<T = any, D = any>(strArr: TemplateStringsArray, ...args: any[]): TaggedTemplateSelfChain<PostfixReturn<AxiosResponse<T>>>; static get(...args) { dslIfaceGuard('lugger:http:get', __filename); return null; } static post<T = any, D = any>(config: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static post<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static post(...args) { dslIfaceGuard('lugger:http:post', __filename); return null; } static put<T = any, D = any>(config: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static put<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static put(...args) { dslIfaceGuard('lugger:http:put', __filename); return null; } static delete<T = any, D = any>(config: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static delete<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static delete(...args) { dslIfaceGuard('lugger:http:delete', __filename); return null; } static options<T = any, D = any>(config: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static options<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static options(...args) { dslIfaceGuard('lugger:http:options', __filename); return null; } static getContent<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>): PostfixReturn<AxiosResponse<T>>; static getContent<T = any, D = any>(strArr: TemplateStringsArray, ...args: any[]): TaggedTemplateSelfChain<PostfixReturn<AxiosResponse<T>>>; static getContent(...args) { dslIfaceGuard('lugger:http:getContent', __filename); return null; } static server<T = any, D = any>(port: number, type?: 'express'): PostfixReturn<ExpressServer>; static server(...args) { dslIfaceGuard('lugger:http:server', __filename); return null; } static finalizer = class { static express = HttpFinalizerExpress; }; } export const http = httpModel as (typeof httpModel & (<T = any, D = any>(url: string, config?: AxiosRequestConfig<any>) => PostfixReturn<AxiosResponse<T>>)); // ==================================================== // Implemenation // ==================================================== function httpModel__(cce: CallContextEvent, ...args) { const { url, config } = getHttpRequestArgs(args); return getRuntime().scopedExec( cce, 'lugger:http:http', { data: { url, config } }, async (resolve, reject, scopeContext) => { try { return resolve(await axios.get(url, config)); } catch (e) { reject(convertAxiosError(e)); } }); } (httpModel__ as any).get = (cce: CallContextEvent, ...args) => { const { url, config } = getHttpRequestArgs(args); return getRuntime().scopedExec( cce, 'lugger:http:http.get', { data: { url, config } }, async (resolve, reject, scopeContext) => { try { resolve(await axios.get(url, config)); } catch (e) { reject(convertAxiosError(e)); } }); } (httpModel__ as any).head = (cce: CallContextEvent, ...args) => { const { url, config } = getHttpRequestArgs(args); return getRuntime().scopedExec( cce, 'lugger:http:http.head', { data: { url, config } }, async (resolve, reject, scopeContext) => { try { resolve(await axios.head(url, config)); } catch (e) { reject(convertAxiosError(e)); } }); } (httpModel__ as any).post = (cce: CallContextEvent, ...args) => { const { url, config } = getHttpRequestArgs(args); return getRuntime().scopedExec( cce, 'lugger:http:http.post', { data: { url, config } }, async (resolve, reject, scopeContext) => { try { resolve(await axios.post(url, config.data, config)); } catch (e) { reject(convertAxiosError(e)); } }); } (httpModel__ as any).put = (cce: CallContextEvent, ...args) => { const { url, config } = getHttpRequestArgs(args); return getRuntime().scopedExec( cce, 'lugger:http:http.put', { data: { url, config } }, async (resolve, reject, scopeContext) => { try { resolve(await axios.put(url, config.data, config)); } catch (e) { reject(convertAxiosError(e)); } }); } (httpModel__ as any).patch = (cce: CallContextEvent, ...args) => { const { url, config } = getHttpRequestArgs(args); return getRuntime().scopedExec( cce, 'lugger:http:http.patch', { data: { url, config } }, async (resolve, reject, scopeContext) => { try { resolve(await axios.patch(url, config.data, config)); } catch (e) { reject(convertAxiosError(e)); } }); } (httpModel__ as any).delete = (cce: CallContextEvent, ...args) => { const { url, config } = getHttpRequestArgs(args); return getRuntime().scopedExec( cce, 'lugger:http:http.delete', { data: { url, config } }, async (resolve, reject, scopeContext) => { try { resolve(await axios.delete(url, config)); } catch (e) { reject(convertAxiosError(e)); } }); } (httpModel__ as any).finalizer = { express: (cce: CallContextEvent, ...args: any[]) => { return HttpFinalizerExpress(args[0], args[1]); } }; (httpModel__ as any).server = (cce: CallContextEvent, ...args) => { const port = parseInt(args[0], 10); let type: 'express' = args[1]; if (!type) { type = 'express'; } return getRuntime().scopedExec( cce, 'lugger:http:http.server', { data: { port } }, async (resolve, reject, scopeContext) => { try { if (type === 'express') { const app = Express(); (app as any).start = () => { return promise(resolve2 => { (app as any).server = app.listen(port, () => { resolve2(app); }); }); }; (app as any).stop = () => { return promise(async (resolve2, reject2) => { if (!(app as any).server) { return reject2(new Error(`cannot stop a server that has never started.`)); } ((app as any).server as Server).close(e => { if (e) { return reject2(e); } return resolve(app); }); return resolve2(); }); }; return resolve(app); } } catch (e) { reject(e); } }); } export const http__ = httpModel__ as any as (typeof http); function getHttpRequestArgs(args: any[]) { const arg0 = args[0]; if (typeof arg0 === 'string') { return { url: arg0 as string, config: (args[1] ? args[1] : {}) as AxiosRequestConfig, } } else { return { url: arg0.url as string, config: arg0 as AxiosRequestConfig, } } } function convertAxiosError(axiosE: AxiosError): HttpError { const e = new Error(`[${axiosE.code}] ${axiosE.message}`) as HttpError; e.codeName = axiosE.code; e.code = axiosE.response?.status; e.getResponse = () => axiosE.response; e.getOriginalError = () => axiosE; return e; } function couldBeJSON(data: string) { data = data.trim(); return ( (data.startsWith('{') && data.startsWith('}')) || (data.startsWith('[') && data.startsWith(']')) ); }