UNPKG

@platform/http

Version:
155 lines (154 loc) 5.04 kB
import { IS_PROD } from './constants'; import { Mime, value as valueUtil } from './libs'; export function stringify(data, errorMessage) { try { return data ? JSON.stringify(data) : ''; } catch (err) { let message = errorMessage(); message = !IS_PROD ? `${message} ${err.message}` : message; throw new Error(message); } } export function parseJson(args) { const text = args.text; try { return (typeof text === 'string' && valueUtil.isJson(args.text) ? JSON.parse(text) : text); } catch (error) { const body = text ? text : '<empty>'; const msg = `Failed while parsing JSON for '${args.url}'.\nParse Error: ${error.message}\nBody: ${body}`; throw new Error(msg); } } export function toRawHeaders(input) { const obj = Object.assign({}, (input || {})); Object.keys(obj).forEach(key => { obj[key] = obj[key].toString(); }); return new Headers(obj); } export function fromRawHeaders(input) { const hasEntries = typeof input.entries === 'function'; const obj = hasEntries ? walkHeaderEntries(input) : (input || {})._headers || {}; return Object.keys(obj).reduce((acc, key) => { const value = Array.isArray(obj[key]) ? obj[key][0] : obj[key]; acc[key] = valueUtil.toType(value); return acc; }, {}); } const walkHeaderEntries = (input) => { var _a; const res = {}; const entries = input.entries(); let next; do { next = entries.next(); if (next.value) { const [key, value] = next.value; res[key] = value; } } while (!((_a = next) === null || _a === void 0 ? void 0 : _a.done)); return res; }; export function headerValue(key, headers = {}) { key = key.trim().toLowerCase(); const match = Object.keys(headers) .filter(k => k.trim().toLowerCase() === key) .find(k => headers[k]) || ''; return match ? headers[match] : ''; } export function isFormData(headers = {}) { const contentType = headerValue('content-type', headers); return contentType.includes('multipart/form-data'); } export function isStream(value) { var _a; const stream = value; return typeof ((_a = stream) === null || _a === void 0 ? void 0 : _a.pipe) === 'function'; } export const response = { async fromPayload(payload, modifications = {}) { const { status, statusText = '' } = payload; const data = payload.data || modifications.data; let head = payload.headers || modifications.headers || {}; if (data && !headerValue('content-type', head)) { head = Object.assign(Object.assign({}, head), { 'content-type': isStream(data) ? 'application/octet-stream' : 'application/json' }); } const contentType = headerValue('content-type', head); const isBinary = Mime.isBinary(contentType); const toText = (data) => { if (!data) { return ''; } if (typeof data === 'string') { return data; } return stringify(data, () => `Failed while serializing data to JSON within [text] method.`); }; const toJson = (data) => { return data && !isBinary ? data : ''; }; let text = ''; let json = ''; const res = { status, statusText, headers: toRawHeaders(head), body: isBinary ? data : null, async text() { return text || (text = toText(data)); }, async json() { return json || (json = toJson(data)); }, }; return response.fromFetch(res); }, async fromFetch(res) { const { status } = res; const ok = status.toString()[0] === '2'; const body = res.body || undefined; const statusText = res.statusText ? res.statusText : ok ? 'OK' : ''; const headers = fromRawHeaders(res.headers); const contentType = response.toContentType(headers); const text = contentType.is.text ? await res.text() : ''; const json = contentType.is.json ? await res.json() : ''; const result = { ok, status, statusText, headers, contentType, body, text, json, }; return result; }, toContentType(headers) { const mime = headerValue('content-type', headers); const res = { mime, is: { get json() { return Mime.isJson(mime); }, get text() { return Mime.isText(mime); }, get binary() { return Mime.isBinary(mime); }, }, toString() { return mime; }, }; return res; }, };