UNPKG

fetch-to-curl-ts

Version:
132 lines (131 loc) 5.3 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()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchToCurl = void 0; const headers_1 = require("./headers"); const web_1 = require("node:stream/web"); const method_1 = require("./method"); const node_stream_1 = require("node:stream"); const node_assert_1 = __importDefault(require("node:assert")); const getHeaderString = (name, val) => `-H "${name}: ${`${val}`.replace(/(\\|")/g, "\\$1")}"`; const normalizeHeaders = (headers) => (0, headers_1.toTupleArray)(headers).reduce((acc, [key, value]) => { if (key.toLocaleLowerCase() === "accept-encoding") { acc.isEncoding = true; } acc.headers.push([key, value]); return acc; }, { headers: [], isEncoding: false, }); const escapeBody = (body) => typeof body === "string" ? body.replace(/'/g, `'\\''`) : body; const generateBody = (body) => typeof body === "object" ? escapeBody(JSON.stringify(body)) : typeof body === "string" ? escapeBody(body) : (() => { throw new Error(`Invalid body type: ${typeof body}`); })(); const buildCurl = (requestInfo, requestInit, serialized) => { var _a; const [url, options] = typeof requestInfo === "string" || requestInfo instanceof URL ? [requestInfo.toString(), requestInit !== null && requestInit !== void 0 ? requestInit : {}] : [ (requestInfo || {}).url, requestInfo, ]; const { body } = options; const serializedBody = serialized === null || serialized === void 0 ? void 0 : serialized.body; const formattedBody = serializedBody ? serializedBody : body ? generateBody(body) : undefined; const { headers, isEncoding } = normalizeHeaders(options.headers || {}); return [ "curl", // URL `'${url}'`, // Method "-X", (0, method_1.getMethod)((_a = options.method) !== null && _a !== void 0 ? _a : method_1.HTTP_METHODS.GET), // Headers ...headers.map(([k, v]) => getHeaderString(k, v)), // Body ...(formattedBody ? ["--data-binary", `'${formattedBody}'`] : []), // Flags isEncoding ? " --compressed" : undefined, ] .filter(Boolean) .join(" "); }; const webStreamToString = (stream) => __awaiter(void 0, void 0, void 0, function* () { const reader = stream.getReader(); let result = yield reader.read(); let body = ""; while (!result.done) { body += new TextDecoder().decode(result.value, { stream: true }); result = yield reader.read(); } return body; }); const nodeStreamToString = (stream) => __awaiter(void 0, void 0, void 0, function* () { let body = ""; stream.on("data", (chunk) => { body += chunk; }); (0, node_assert_1.default)(!stream.readableEnded, "Stream has already ended"); return new Promise((res, reject) => { stream.on("error", reject); stream.on("end", () => { return res(body); }); }); }); const fromRequest = (request) => __awaiter(void 0, void 0, void 0, function* () { const serializedBody = yield maybeSerializeBody(request.body); return buildCurl(request, undefined, { body: serializedBody }); }); const fetchToCurl = (requestInfo, requestInit) => __awaiter(void 0, void 0, void 0, function* () { if (isRequestLike(requestInfo)) { return fromRequest(requestInfo); } if (!requestInit) { return buildCurl(requestInfo, requestInit); } const serializedBody = yield maybeSerializeBody(requestInit.body, requestInit); return buildCurl(requestInfo, requestInit, { body: serializedBody }); }); exports.fetchToCurl = fetchToCurl; /** * @warn If there is a backing requestInit, it must be passed, otherwise, * the underlying stream will be consumed and break the actual requestInit * requesting serialiation. */ const maybeSerializeBody = (initStream, requestInit) => __awaiter(void 0, void 0, void 0, function* () { if (initStream instanceof node_stream_1.Readable) { return nodeStreamToString(initStream); } if (initStream instanceof web_1.ReadableStream) { const [s1, s2] = initStream.tee(); if (requestInit) { requestInit.body = s2; } return webStreamToString(s1); } }); const isRequestLike = (requestInfo) => !!requestInfo && "url" && typeof requestInfo === "object" && "url" in requestInfo;