"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()); }); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeDefaultKy = exports.http = exports.filterHeaders = exports.wrapResponseClosure = exports.wrapRequestClosure = void 0; const error_1 = require("./error"); const ky_universal_1 = __importDefault(require("ky-universal")); const stream_1 = require("./stream"); const merge_1 = require("./merge"); const type_1 = require("./type"); const DEFAULT_KY_CONFIG = { headers: { accept: 'application/json, text/plain, */*', 'user-agent': `bee-js`, }, }; function isHttpError(e) { return (0, type_1.isObject)(e) && typeof e.response !== 'undefined'; } function isHttpRequestError(e) { return (0, type_1.isObject)(e) && typeof e.request !== 'undefined'; } function headersToObject(header) { return [...header.entries()].reduce((obj, [key, val]) => { obj[key] = val; return obj; }, {}); } function wrapRequest(request) { return { url: request.url, method: request.method.toUpperCase(), headers: headersToObject(request.headers), }; } function wrapRequestClosure(cb) { return (request) => __awaiter(this, void 0, void 0, function* () { yield cb(wrapRequest(request)); }); } exports.wrapRequestClosure = wrapRequestClosure; function wrapResponseClosure(cb) { return (request, options, response) => __awaiter(this, void 0, void 0, function* () { yield cb({ headers: headersToObject(response.headers), status: response.status, statusText: response.statusText, request: wrapRequest(request), }); }); } exports.wrapResponseClosure = wrapResponseClosure; /** * Filters out entries that has undefined value from headers object. * Modifies the original object! * * @param obj */ // eslint-disable-next-line @typescript-eslint/ban-types function filterHeaders(obj) { if (obj === undefined) { return undefined; } (0, type_1.isStrictlyObject)(obj); const typedObj = obj; for (const key in typedObj) { if (typedObj[key] === undefined) { delete typedObj[key]; } } if (Object.keys(typedObj).length === 0) { return undefined; } return typedObj; } exports.filterHeaders = filterHeaders; /** * Main utility function to make HTTP requests. * @param ky * @param config */ function http(ky, config) { return __awaiter(this, void 0, void 0, function* () { try { const { path, responseType } = config, kyConfig = __rest(config, ["path", "responseType"]); const response = (yield ky(path, Object.assign(Object.assign({}, kyConfig), { searchParams: filterHeaders(kyConfig.searchParams) }))); switch (responseType) { case 'stream': if (!response.body) { throw new error_1.BeeError('Response was expected to get data but did not get any!'); } response.data = (0, stream_1.normalizeToReadableStream)(response.body); break; case 'arraybuffer': response.data = (yield response.arrayBuffer()); break; case 'json': try { response.data = (yield response.json()); } catch (e) { throw new error_1.BeeNotAJsonError(); } break; default: break; // If responseType is not set, then no data are expected } return response; } catch (e) { // Passthrough thrown errors if (e instanceof error_1.BeeNotAJsonError) { throw e; } if (isHttpError(e)) { let message; // We store the response body here as it can be read only once in Response's lifecycle so to make it exposed // to the user in the BeeResponseError, for further analysis. const body = yield e.response.text(); try { // The response can be Bee's JSON with structure `{code, message}` lets try to parse it message = JSON.parse(body).message; } catch (e) { } if (message) { throw new error_1.BeeResponseError(e.response.status, e.response, body, config, `${e.response.statusText}: ${message}`); } else { throw new error_1.BeeResponseError(e.response.status, e.response, body, config, e.response.statusText); } } else if (isHttpRequestError(e)) { throw new error_1.BeeRequestError(e.message, config); } else { // Node 18 has native `fetch` implementation called Undici. Errors from this implementation have top level generic // message "fetch failed" with the more specific error placed into `cause` property. Instead of "fetch failed" we // expose the underlying problem. if (e.cause) { throw new error_1.BeeError(e.cause.message); } throw new error_1.BeeError(e.message); } } }); } exports.http = http; function makeDefaultKy(kyConfig) { return ky_universal_1.default.create((0, merge_1.deepMerge)(DEFAULT_KY_CONFIG, kyConfig)); } exports.makeDefaultKy = makeDefaultKy;