@nestia/fetcher
Version:
Fetcher library of Nestia SDK
185 lines • 8.17 kB
JavaScript
;
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