UNPKG

@nestia/fetcher

Version:

Fetcher library of Nestia SDK

185 lines 8.17 kB
"use strict"; 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FetcherBase = void 0; const HttpError_1 = require("../HttpError"); /** @internal */ var FetcherBase; (function (FetcherBase) { FetcherBase.request = (props) => (connection, route, input, stringify) => __awaiter(this, void 0, void 0, function* () { const result = yield _Propagate("fetch")(props)(connection, route, input, stringify); if (result.success === false) throw new HttpError_1.HttpError(route.method, route.path, result.status, result.headers, result.data); return result.data; }); FetcherBase.propagate = (props) => (connection, route, input, stringify) => __awaiter(this, void 0, void 0, function* () { return _Propagate("propagate")(props)(connection, route, input, stringify); }); /** @internal */ const _Propagate = (method) => (props) => (connection, route, input, stringify) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h, _j; //---- // REQUEST MESSAGE //---- // METHOD & HEADERS const headers = Object.assign({}, ((_a = connection.headers) !== null && _a !== void 0 ? _a : {})); if (input !== undefined) { if (((_b = route.request) === null || _b === void 0 ? void 0 : _b.type) === undefined) throw new Error(`Error on ${props.className}.fetch(): no content-type being configured.`); else if (route.request.type !== "multipart/form-data") headers["Content-Type"] = route.request.type; } else if (input === undefined && headers["Content-Type"] !== undefined) delete headers["Content-Type"]; // INIT REQUEST DATA const init = Object.assign(Object.assign({}, ((_c = connection.options) !== null && _c !== void 0 ? _c : {})), { method: route.method, headers: (() => { const output = []; for (const [key, value] of Object.entries(headers)) if (value === undefined) continue; else if (Array.isArray(value)) for (const v of value) output.push([key, String(v)]); else output.push([key, String(value)]); return output; })() }); // CONSTRUCT BODY DATA if (input !== undefined) init.body = props.encode( // BODY TRANSFORM ((_d = route.request) === null || _d === void 0 ? void 0 : _d.type) === "application/x-www-form-urlencoded" ? request_query_body(input) : ((_e = route.request) === null || _e === void 0 ? void 0 : _e.type) === "multipart/form-data" ? request_form_data_body(input) : ((_f = route.request) === null || _f === void 0 ? void 0 : _f.type) !== "text/plain" ? (stringify !== null && stringify !== void 0 ? stringify : JSON.stringify)(input) : input, headers); //---- // RESPONSE MESSAGE //---- // URL SPECIFICATION const path = connection.host[connection.host.length - 1] !== "/" && route.path[0] !== "/" ? `/${route.path}` : route.path; const url = new URL(`${connection.host}${path}`); // DO FETCH const event = { route, path, status: null, input, output: undefined, started_at: new Date(), respond_at: null, completed_at: null, }; try { // TRY FETCH const response = yield ((_g = connection.fetch) !== null && _g !== void 0 ? _g : fetch)(url.href, init); event.respond_at = new Date(); event.status = response.status; // CONSTRUCT RESULT DATA const result = { success: response.status === 200 || response.status === 201 || response.status === route.status, status: response.status, headers: response_headers_to_object(response.headers), data: undefined, }; if (result.success === false) { // WHEN FAILED result.data = yield response.text(); const type = response.headers.get("content-type"); if (method !== "fetch" && type && type.indexOf("application/json") !== -1) try { result.data = JSON.parse(result.data); } catch (_k) { } } else { // WHEN SUCCESS if (route.method === "HEAD") result.data = undefined; else if (((_h = route.response) === null || _h === void 0 ? void 0 : _h.type) === "application/json") { const text = yield response.text(); result.data = text.length ? JSON.parse(text) : undefined; } else if (((_j = route.response) === null || _j === void 0 ? void 0 : _j.type) === "application/x-www-form-urlencoded") { const query = new URLSearchParams(yield response.text()); result.data = route.parseQuery ? route.parseQuery(query) : query; } else result.data = props.decode(yield response.text(), result.headers); } event.output = result.data; return result; } catch (exp) { throw exp; } finally { event.completed_at = new Date(); if (connection.logger) try { yield connection.logger(event); } catch (_l) { } } }); })(FetcherBase || (exports.FetcherBase = FetcherBase = {})); /** @internal */ const request_query_body = (input) => { const q = new URLSearchParams(); for (const [key, value] of Object.entries(input)) if (value === undefined) continue; else if (Array.isArray(value)) value.forEach((elem) => q.append(key, String(elem))); else q.set(key, String(value)); return q; }; /** @internal */ const request_form_data_body = (input) => { const encoded = new FormData(); const append = (key) => (value) => { if (value === undefined) return; else if (typeof File === "function" && value instanceof File) encoded.append(key, value, value.name); else encoded.append(key, value); }; for (const [key, value] of Object.entries(input)) if (Array.isArray(value)) value.map(append(key)); else append(key)(value); return encoded; }; /** @internal */ const response_headers_to_object = (headers) => { const output = {}; headers.forEach((value, key) => { var _a; if (key === "set-cookie") { (_a = output[key]) !== null && _a !== void 0 ? _a : (output[key] = []); output[key].push(...value.split(";").map((str) => str.trim())); } else output[key] = value; }); return output; }; //# sourceMappingURL=FetcherBase.js.map