173 lines
6.8 KiB
JavaScript
173 lines
6.8 KiB
JavaScript
|
"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;
|