UNPKG

lemon-core

Version:
801 lines 32.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createSigV4Proxy = exports.my_sequence = exports.my_parrallel = exports.parseRange = exports.isUserAuthorized = exports.getIdentityId = exports.$event = exports.$slack = exports.$info = exports.$protocol = exports.$rand = exports.$T = void 0; /** * `helpers.ts` * - helper functions used globally in project * * * @author Steve Jung <steve@lemoncloud.io> * @date 2020-12-22 initial version * @date 2021-12-21 protocol support `//self` url. * @date 2021-12-23 optimize types of $protocol. * @date 2022-03-17 addition text processing. (S2, P) * * @copyright (C) 2021 LemonCloud Co Ltd. - All Rights Reserved. */ const cores_1 = __importDefault(require("../cores/")); const engine_1 = __importStar(require("../engine/")); const test_helper_1 = require("../common/test-helper"); const sig_v4_1 = require("../extended/libs/sig-v4"); const perf_hooks_1 = require("perf_hooks"); const tools_1 = require("../tools/tools"); const request_1 = __importDefault(require("request")); const query_string_1 = __importDefault(require("query-string")); /** * Helpers to transform data-types. */ exports.$T = { /** * transform to string w/ trim() */ S: (val, def = '') => `${val !== null && val !== void 0 ? val : def}`.trim(), /** * as string w/o white-space. */ S2: (val, def = '', delim = '') => `${val !== null && val !== void 0 ? val : def}`.replace(/\s+/g, delim), /** * transform to string[] */ SS: (val, def = []) => { if (val === null || val === undefined) return def; if (typeof val === 'string') return val ? val.split(',').map(_ => exports.$T.S(_, '').trim()) : def; if (Array.isArray(val)) return val.length > 0 ? val.map(_ => exports.$T.S(_, '').trim()) : def; return [exports.$T.S(val)]; }, /** * text to Plain text (remove html tag) */ P: (text, max = 0) => { const msg = (typeof text === 'string' ? text : `${text || ''}`) .replace(/<[^>]*>/g, ' ') //* remove html tag. .replace(/[^a-zA-Z0-9가-힣ㅋ-ㅎㅏ-ㅣ\.\?]+/g, ' ') //* remove non-char. .trim(); const len = msg.length; return max && len > max ? msg.substring(0, max) + '...' : msg; }, /** * transform to number(integer). */ N: (val, def = 0) => { const n = engine_1.$U.N(val, def); return Number.isNaN(n) ? def : n; }, /** * number array */ NN: (val, def = []) => { if (val === null || val === undefined) return def; if (typeof val === 'string') return val ? val.split(',').map(_ => exports.$T.N(_, 0)) : def; if (Array.isArray(val)) return val.length > 0 ? val.map(_ => exports.$T.N(_, 0)) : def; return [exports.$T.N(val)]; }, /** * transform to number(float) */ F: (val, def = 0) => engine_1.$U.F(val, def), /** * transform to number(float)[] */ FF: (val, def = []) => { if (val === null || val === undefined) return def; if (typeof val === 'string') return val ? val.split(',').map(_ => exports.$T.F(_, 0)) : def; if (Array.isArray(val)) return val.length > 0 ? val.map(_ => exports.$T.F(_, 0)) : def; return [exports.$T.F(val)]; }, /** * float w/ fixed len=3 */ F3: (n, e = 0.000001) => Number((n + e).toFixed(3)), /** * transform to boolean. */ B: (val, def = 0) => { if (val === null || val === undefined) return def; if (typeof val === 'boolean') return val ? 1 : 0; if (typeof val === 'string' && ['y', 'yes', 't', 'true'].includes(val.toLowerCase())) return 1; return engine_1.$U.N(val, def) && 1; }, /** * transform to Time number via string | number. */ T: (val, def = 0) => { const checkVal = `${val || ''}`.includes('-'); if (checkVal) { if (engine_1.$U.dt(val)) return engine_1.$U.dt(val).getTime(); else throw new Error(`@val[${val}] is invalid!`); } else { return engine_1.$U.dt(engine_1.$U.N(val, def)).getTime(); } }, /** * transform to Date formatted string */ D: (val, def = '') => { let s = exports.$T.S(val); let y; let m; let d; if (s.includes('-')) { [y, m, d] = s.split('-'); } else { y = s.slice(0, 4); m = s.slice(4, 6); d = s.slice(6); } s = [y, m, d] .filter(e => (e === null || e === void 0 ? void 0 : e.length) > 0) .map(e => e.padStart(2, '0')) .join('-'); if (y && y.length === 4 && !Number.isNaN(Date.parse(s))) return s; return def; }, /** * date-time format */ DT: (val, def = '2020-01-01') => { const s = exports.$T.D(val, '').split('-'); // must be valid date-format like '2000-01-02' const d = def.split('-'); return d .map((d, i) => s[i] || d || '01') .map(e => e.padStart(2, '0')) .join('-'); }, /** * Extract Text */ EX: (data, txt1, txt2) => { data = `${data || ''}`; const a = data.indexOf(txt1); const b = a >= 0 ? data.indexOf(txt2, a + txt1.length) : a; return b > a ? data.substring(a + txt1.length, b) : ''; }, /** * transform to simple-set. * @param val json object. */ simples: (val, throws = false) => { //* validate if simple-type (string | number | null | undefined) const t = typeof val; if (val === undefined) return undefined; else if (val === null || val === '') return { _: null }; else if (t === 'string' || t === 'number') return { _: val }; else if (t === 'object' && !Array.isArray(val)) { const keys = Object.keys(val); const reName = /^[a-z_][a-zA-Z0-9_\-]*$/; return keys.reduce((N, k) => { const v = val[k]; if (v === undefined) { //* NOP } else if (reName.test(k)) { const t = typeof v; if (v === null || v === '') N[k] = null; else if (t === 'string' || t === 'number') N[k] = v; else if (throws) throw new Error(`.${k}[${v}] is invalid!`); } else if (throws) throw new Error(`.${k} is invalid format!`); return N; }, {}); } else if (throws) throw new Error(`@val[${t}] is invalid!`); return {}; }, /** * catch string between txt1 and txt2 * @param data string * @param txt1 head * @param txt2 tail */ catch: (data, txt1, txt2) => { data = typeof data == 'string' ? data : `${data}`; const a = data.indexOf(txt1); const b = a >= 0 ? data.indexOf(txt2, a + txt1.length) : a; const c = b > a ? data.substring(a + txt1.length, b) : ''; return c; }, /** * merge simple-set from $org to $new * @param $org the origin set * @param $new the update set. */ merge: ($org, $new) => { if (!$new) return $org; return Object.keys($new).reduce((N, k) => { const val = $new[k]; if (val === null || val === undefined) delete N[k]; else N[k] = val; return N; }, Object.assign({}, $org)); }, /** * replace message with template. */ template: (msg, set) => { // const msg = $U.env('MSG_PHONE_CODE', '인증 번호는 [{code}] 입니다.') as string; const tmp = Object.assign({}, set); return msg.replace(/\{(\w+)\}/g, (a, b) => (tmp[b] !== undefined ? `${tmp[b]}` : `{${b}}`)); }, /** * make random-code by length * @param size length of code * @param rand flag to use random (0 => 0, 1 => max) */ makeRandomCode: (size = 6, rand) => { const flag = rand === undefined || rand === true || typeof rand == 'number' ? true : false; const min = size >= 1 ? Math.pow(10, size - 1) : 1; const max = 10 * min - 1; const val = min + (flag ? Math.floor((max - min) * (typeof rand == 'number' ? rand : Math.random())) : max - min); return { val, min, max }; }, /** * 객체 정규화 시킴. * - null 에 대해서는 특별히 처리. */ normal: (N) => Object.keys(N || {}).reduce((M, k) => { if (k.startsWith('_') || k.startsWith('$')) return M; const v = N[k]; //* `null` 은 DynamoDB에서 비어있는 문자임. M[k] = v === null ? '' : v; return M; }, {}), /** * transform list to map by `id` */ asMap: (list, id = 'id') => list.reduce((M, N) => { const key = `${N[id] || ''}`; M[key] = N; return M; }, {}), /** * compare object, and extract the only diff properties. */ diff: (A, B, onlyValid = false) => { if (!A || !B) return B; else if (typeof A !== 'object' || typeof B !== 'object') return B; return engine_1.$U .diff(A, B) .map(s => `${s || ''}`) .reduce((M, k) => { const org = A[k]; const val = B[k]; if (onlyValid) { if (val !== undefined && val !== null) { //* dynamo 에서는 null 과 '' 이 같음. if (org === null && val === '') { // NOP - due to same value. } else { M[k] = val; } } } else { M[k] = val === undefined && org !== undefined ? null : val; } return M; }, {}); }, /** * get $perf instance. * ```ts * const p = $T.perf() * const took = p.took(); */ perf: () => { return new (class MyPerfmance { constructor(t0) { this.took = () => { const t1 = perf_hooks_1.performance.now(); // start of processing const took = Math.round((t1 - this.t0) / 100) / 10; // in sec. return took; }; this.t0 = t0 || perf_hooks_1.performance.now(); // start of processing } })(); }, /** * parse `.meta` property as object. * @param meta any */ parseMeta: (meta) => { if (typeof meta === 'string' && meta) { try { if (meta.startsWith('[') && meta.endsWith(']')) { const list = JSON.parse(meta); const $ret = { list }; return $ret; } else if (meta.startsWith('{') && meta.endsWith('}')) { return JSON.parse(meta); } else { const $ret = { type: 'string', value: meta }; return $ret; } } catch (e) { const $ret = { type: 'string', value: meta, error: (0, test_helper_1.GETERR)(e) }; return $ret; } } else if (meta === null || meta === undefined) { return null; } else if (typeof meta === 'object') { return meta; } else { const type = typeof meta; const $ret = { type, value: meta }; return $ret; } }, /** * clear the undefined properties from the cloned object. * - applied only to 1st depth. * * @param N object * @param $def default if not valid object. * @returns cloned object */ onlyDefined: tools_1.onlyDefined, }; /** * random number generator */ exports.$rand = { /** * list of number[] in n-size. */ range: (n) => [...Array(n).keys()], /** * generate random number */ float: (from, to) => Math.random() * (to - from) + from, /** * generate multiple float numbers */ floats: (from, to, n) => new Array(n).fill(0).map(() => exports.$rand.float(from, to)), /** * generate an integer */ integer: (from, to) => Math.floor(exports.$rand.float(Math.ceil(from), Math.floor(to))), /** * generate multiple integers */ integers: (from, to, n) => new Array(n).fill(0).map(() => exports.$rand.integer(from, to)), }; /** * builder to support protocol-service. * @param context the current context (or service name). * @param service service name * @param options additional options. */ const $protocol = (context = {}, service, options) => { //* for backward compartibility. shift arguments if 1st context is string. const ctx = typeof context === 'string' ? {} : context; service = typeof context === 'string' ? context : service; const param = typeof context === 'string' ? service : options === null || options === void 0 ? void 0 : options.param; const body = typeof context === 'string' ? param : options === null || options === void 0 ? void 0 : options.body; if (!ctx) throw new Error(`@context (NextContext) is required!`); if (!service) throw new Error(`@service (string) is required!`); const $proto = cores_1.default.protocol.service; const isProd = (options === null || options === void 0 ? void 0 : options.isProd) !== undefined ? options === null || options === void 0 ? void 0 : options.isProd : engine_1.$U.env('NS') === 'SS' ? true : false; //TODO - `STAGE` is not changed from env.yml file @211215. // _inf(NS, 'NS =', $U.env('NS'), $engine.cores.config.config.get('NS'), process.env['NS']); // _inf(NS, 'stage =', $U.env('STAGE'), $engine.cores.config.config.get('STAGE'), process.env['STAGE']); //NOTE - STAGE is not changed. //* prod용 lambda접근을 위한 환경 구성!!!!! const $param = (p, b, x) => { const protoParam = Object.assign(Object.assign({}, $proto.fromURL(ctx, asTargetUrl(), p || param, b || body)), x); if (isProd) protoParam.stage = 'prod'; return protoParam; }; const $callback = (callback) => { if (callback) { const [path, qs] = callback.split('?'); if (path) { const [type, id, cmd] = path.split('/'); const param = query_string_1.default.parse(qs); return { type, id, cmd, param }; } } }; //* find the target protocol-url from context. const asTargetUrl = () => { if (!service.startsWith('//')) throw new Error(`@service[${service}] (string) is invalid!`); if (service.startsWith('//self/')) { const self = $proto.myProtocolURI(ctx); const [a, b] = [self.indexOf('@'), self.indexOf('#')]; const target = self.substring(a < 0 ? 'api://'.length : a + 1, b > a ? b : self.length) + service.substring('//self'.length); return `api://${target}`; } else { return `api:${service}`; } }; //* execute via protocol-service. const execute = (param, body, mode = 'POST') => $proto.execute($param(param, body, { mode })); // eslint-disable-next-line prettier/prettier const enqueue = (param, body, mode = 'POST', callback, delaySeconds = 1) => $proto.enqueue($param(param, body, { mode }), $callback(callback), delaySeconds); const notify = (param, body, mode = 'POST', callback) => $proto.notify($param(param, body, { mode }), $callback(callback)); //* returns instance. return { hello: () => `helper:protocol:${service || ''}`, asTargetUrl, execute, enqueue, notify, }; }; exports.$protocol = $protocol; /** * get the current config info */ const $info = () => { const $conf = cores_1.default.config.config; const service = $conf.getService(); const version = $conf.getVersion(); const stage = $conf.getStage(); return { service, version, stage }; }; exports.$info = $info; /** * send message to slack/public * * @param title 헤터 타이틀 * @param text object or 텍스트 내용 * @param pretext (optional) 텍스트 미리보기용. * @param params (optional) customize more options. */ const $slack = (title, text, pretext, params) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; //* about current service................. const { service, version, stage } = (0, exports.$info)(); const name = `${service}#${version}` + (stage !== 'prod' ? `/${stage}` : ''); return (0, engine_1.doReportSlack)((params === null || params === void 0 ? void 0 : params.channel) ? `!${params === null || params === void 0 ? void 0 : params.channel}` : 'public', { channel: (_a = params === null || params === void 0 ? void 0 : params.channel) !== null && _a !== void 0 ? _a : undefined, attachments: [ exports.$T.onlyDefined({ color: `${(params === null || params === void 0 ? void 0 : params.color) || '#FFB71B' || 'good'}`, title, pretext: pretext === null ? undefined : pretext !== null && pretext !== void 0 ? pretext : ((params === null || params === void 0 ? void 0 : params.scope) ? `#${name} [\`${params.scope}\`]` : undefined), text: text === null || text === undefined ? undefined : typeof text === 'string' ? text : engine_1.$U.json(text), fields: params === null || params === void 0 ? void 0 : params.fields, footer: (params === null || params === void 0 ? void 0 : params.footer) === null ? undefined : (_b = params === null || params === void 0 ? void 0 : params.footer) !== null && _b !== void 0 ? _b : `${service}/${stage}#${version}`, ts: (params === null || params === void 0 ? void 0 : params.ts) === null ? undefined : Math.floor(engine_1.$U.current_time_ms() / 1000), }), ], }, params === null || params === void 0 ? void 0 : params.context).catch(e => `#err:${(0, test_helper_1.GETERR)(e)}`); }); exports.$slack = $slack; /** * event producer builder * @param context current context * @param defEndpoint (optional) the default endpoint. */ const $event = (context, defEndpoint = '') => { const $protocol = cores_1.default.protocol; const endpoint = engine_1.$U.env('EVENT_RELAY_SNS', defEndpoint); if (!endpoint) throw new Error(`env[EVENT_RELAY_SNS] is required - $event()`); return { publish: (body) => __awaiter(void 0, void 0, void 0, function* () { return $protocol.service.broadcast(context, endpoint, body); }), }; }; exports.$event = $event; /** * authentication helper - get identity-id from context * @param context the current context */ function getIdentityId(context) { var _a; const identityId = (_a = context === null || context === void 0 ? void 0 : context.identity) === null || _a === void 0 ? void 0 : _a.identityId; if (!identityId && (context === null || context === void 0 ? void 0 : context.domain) === 'localhost') { //* use `env[LOCAL_ACCOUNT]` only if runs in local server. return engine_1.$U.env('LOCAL_ACCOUNT', ''); } return identityId; } exports.getIdentityId = getIdentityId; /** * authentication helper - check user is authorized * - 이 메서드는 AWS IAM 인증 여부만을 확인한다. * - 따라서 true를 반환한다고 하여 회원 가입이 되어있다는 의미는 아니다. * * @param context the current context * @params params (optional) to override `identity` when running local. */ function isUserAuthorized(context, params) { const identityId = getIdentityId(context); //WARN - in local server, override the identity w/ param if ((context === null || context === void 0 ? void 0 : context.domain) === 'localhost') { //!* override with optional parameter. if (context) { context.identity = Object.assign(Object.assign({}, (params !== undefined ? params : context.identity)), { identityId }); } } return !!identityId; } exports.isUserAuthorized = isUserAuthorized; /** * parse range expression * @param exp range expression (e.g. '[63100 TO 224000]' or '[* TO 150000}') */ function parseRange(exp) { const match = exp.match(/^([\[{])([0-9]+|\*) TO ([0-9]+|\*)([}\]])$/); if (match && (match[2] !== '*' || match[3] !== '*')) { const range = {}; if (match[2] !== '*') { const n = exports.$T.N(match[2]); if (match[1] === '[') range.gte = n; else if (match[1] === '{') range.gt = n; } if (match[3] !== '*') { const n = exports.$T.N(match[3]); if (match[4] === ']') range.lte = n; else if (match[4] === '}') range.lt = n; } return range; } } exports.parseRange = parseRange; /** * customized of `do_parrallel` for safe error-handling. * - use `.error` to report the internal error. * * @param list list of model. * @param func callback to process of each * @param size (optional) size of parrallel (default 10) */ const my_parrallel = (list, func, size) => __awaiter(void 0, void 0, void 0, function* () { const results = yield (0, engine_1.do_parrallel)(list, (item, i) => { const ret = (() => { try { return func(item, i); } catch (e) { return Promise.reject(e); } })(); const res = ret instanceof Promise ? ret : Promise.resolve(ret); return res.catch(e => ({ id: item.id, error: (0, test_helper_1.GETERR)(e) })); }, size); return results; }); exports.my_parrallel = my_parrallel; /** * run in sequence order * - same as `my_parrallel(list, func, 1)`; * * 주의) 내부 error를 throw 하지 않으니, list 를 전부 처리할때까지 안끝남. * * @param list list of model. * @param func callback to process of each */ const my_sequence = (list, func) => (0, exports.my_parrallel)(list, func, 1); exports.my_sequence = my_sequence; /** * create api-http-proxy with sig-v4 agent, which using endpoint as proxy server. * * # as cases. * as proxy agent: GET <endpoint>/<host?>/<path?> * as direct agent: GET <endpoint>/<id?>/<cmd?> * * @param name client-name * @param endpoint service url (or backbone proxy-url) * @param sigConfig sig-v4 client-config * @param options optional parameters */ const createSigV4Proxy = ( /** name of client */ name, /** endpoint of service */ endpoint, /** sig-v4 client-config */ sigConfig, /** (optional) parameters */ options) => { var _a, _b, _c, _d; const errScope = `createSigV4Proxy(${name !== null && name !== void 0 ? name : ''})`; if (!endpoint) throw new Error(`@endpoint (url) is required - ${errScope}`); const NS = engine_1.$U.NS(`X${name}`, 'magenta'); // NAMESPACE TO BE PRINTED. const encoder = (_a = options === null || options === void 0 ? void 0 : options.encoder) !== null && _a !== void 0 ? _a : ((name, path) => path); const relayHeaderKey = (_b = options === null || options === void 0 ? void 0 : options.relayHeaderKey) !== null && _b !== void 0 ? _b : ''; const resultKey = (_c = options === null || options === void 0 ? void 0 : options.resultKey) !== null && _c !== void 0 ? _c : ''; const verbose = (_d = options === null || options === void 0 ? void 0 : options.verbose) !== null && _d !== void 0 ? _d : false; const _log = verbose ? engine_1.default.log : () => { }; const _err = verbose ? engine_1.default.err : () => { }; const _inf = verbose ? engine_1.default.inf : () => { }; // initialize AWS SigV4 Client const sigClient = sigConfig ? (0, sig_v4_1.sigV4Client)(Object.assign(Object.assign({}, sigConfig), { endpoint })) : null; /** * class: `ApiHttpProxy` * - http proxy client via backbone's web. */ return new (class { // eslint-disable-next-line @typescript-eslint/no-empty-function constructor(headers) { this.headers = headers; this.hello = () => `http-web-proxy:${name}`; } doProxy(method, path1, path2, $param, $body, $ctx) { if (!method) throw new Error(`@method is required - ${errScope}`); if (!(endpoint === null || endpoint === void 0 ? void 0 : endpoint.startsWith('http')) && !(endpoint === null || endpoint === void 0 ? void 0 : endpoint.startsWith('https'))) throw new Error(`@endpoint[${endpoint}] is invalid - ${errScope}`); _inf(NS, `doProxy(${method})..`); const _isNa = (a) => a === undefined || a === null; _log(NS, '> endpoint =', endpoint); _isNa(path1) && _log(NS, `> host(id) =`, typeof path1, path1); _isNa(path2) && _log(NS, `> path(cmd) =`, typeof path2, path2); //* prepare request parameters // eslint-disable-next-line prettier/prettier const query_string = _isNa($param) ? '' : (typeof $param == 'object' ? query_string_1.default.stringify($param) : `${$param}`); const url = endpoint + (_isNa(path1) ? '' : `/${encoder('host', path1)}`) + (_isNa(path1) && _isNa(path2) ? '' : `/${encoder('path', path2)}`) + (!query_string ? '' : '?' + query_string); const request = request_1.default; const options = { method, uri: url, headers: Object.assign({}, this.headers), body: $body === null ? undefined : $body, json: typeof $body === 'string' ? false : true, }; if (sigClient) { const signedRequest = sigClient.signRequest({ method, path: (_isNa(path1) ? '' : `/${encoder('host', path1)}`) + (_isNa(path1) && _isNa(path2) ? '' : `/${encoder('path', path2)}`), queryParams: $param, headers: options.headers, body: $body, }); options.headers = Object.assign(Object.assign({}, options.headers), signedRequest.headers); options.uri = signedRequest.url; } //* relay HEADERS to `WEB-API` if (this.headers) { const headers = this.headers; options.headers = Object.keys(headers).reduce((H, key) => { const val = headers[key]; const name = `${relayHeaderKey}${key}`; const text = `${val}`; H[name] = text; return H; }, options.headers); } _log(NS, ' url :=', options.method, url); _log(NS, '*', options.method, url, options.json ? 'json' : 'plain'); _log(NS, '> options =', engine_1.$U.json(options)); //* returns promise return new Promise((resolve, reject) => { //* start request.. request(options, function (error, response, body) { error && _err(NS, '>>>>> requested! err=', error); if (error) return reject(error instanceof Error ? error : new Error((0, test_helper_1.GETERR)(error))); //* detect trouble. const statusCode = response.statusCode; const statusMessage = response.statusMessage; //* if not in success if (statusCode !== 200 && statusCode !== 201) { const msg = body ? (0, test_helper_1.GETERR)(body) : `${statusMessage || ''}`; if (statusCode === 400 || statusCode === 404) { const title = `${(statusCode == 404 ? '' : statusMessage) || 'NOT FOUND'}`.toUpperCase(); const message = msg.startsWith('404 NOT FOUND') ? msg : `${statusCode} ${title} - ${msg}`; return reject(new Error(message)); } statusMessage && _log(NS, `> statusMessage[${statusCode}] =`, statusMessage); body && _log(NS, `> body[${statusCode}] =`, engine_1.$U.json(body)); return reject(new Error(`${statusCode} ${statusMessage || 'FAILURE'} - ${msg}`)); } //* try to parse body. try { if (body && typeof body == 'string' && body.startsWith('{') && body.endsWith('}')) { body = JSON.parse(body); } else if (body && typeof body == 'string' && body.startsWith('[') && body.endsWith(']')) { body = JSON.parse(body); } } catch (e) { _err(NS, '!WARN! parse(body) =', e instanceof Error ? e : engine_1.$U.json(e)); } //* ok! succeeded. resolve(body); }); }).then((res) => { if (resultKey && res && res[resultKey] !== undefined) return res[resultKey]; return res; }); } })(options === null || options === void 0 ? void 0 : options.headers); }; exports.createSigV4Proxy = createSigV4Proxy; //# sourceMappingURL=helpers.js.map