UNPKG

@pricething/curl

Version:

A typescript wrapper around cURL-impersonate.

135 lines (134 loc) 4.55 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RequestBuilder = void 0; const node_child_process_1 = require("node:child_process"); const node_path_1 = __importDefault(require("node:path")); const browsers_1 = require("./browsers"); const presets_1 = require("./presets"); class RequestBuilder { _url = ""; _browser; _preset; _method = "GET"; _flags = []; _headers = {}; url(url) { this._url = url; return this; } method(method) { this._method = method; return this; } /** * Add a header to the request * @param name The name of the header to set * @param value The value of the header to set * @returns The RequestBuilder instance */ header(name, value) { this._headers[name] = value; return this; } /** * Add multiple headers to the request * @param headers A record of headers to add to the request * @returns The RequestBuilder instance */ headers(headers) { this._headers = { ...this._headers, ...headers }; return this; } /** * Add a flag to the request * @param name The name of the flag to set * @param value The value of the flag to set * @returns The RequestBuilder instance */ flag(name, value) { if (value) { this._flags.push(`${name} "${value}"`); } else { this._flags.push(name); } return this; } /** * Follow redirects (sugar for this.flag("-L")) * @returns The RequestBuilder instance */ follow() { this.flag("-L"); return this; } body(body) { this.flag("-d", JSON.stringify(body)); return this; } /** * Add multiple flags to the request * @param flags A record of flags to add to the request * @returns The RequestBuilder instance */ flags(flags) { for (const [flag, value] of Object.entries(flags)) { this.flag(flag, value); } return this; } /** * Set the browser and version preset for the request. * Throws if the browser is not supported on the current platform. * @param preset The preset to use for the request * @returns The RequestBuilder instance */ preset(preset) { this._browser = (0, browsers_1.resolveBrowser)(preset.name); this._preset = presets_1.BrowserPresets[preset.name][preset.version]; return this; } /** * Send the request * @returns A promise that resolves with the response and details of the request */ async send() { const browser = this._browser ?? (0, browsers_1.getDefaultPlatformBrowser)(); const preset = this._preset ?? Object.values(presets_1.BrowserPresets[browser.name])[0]; const headers = this.buildHeaderFlags({ ...this._headers, ...preset.headers }); const flags = this.buildFlags(this._flags); const command = [node_path_1.default.join(browsers_1.BINARY_PATH, browser.binary), ...flags, ...preset.flags, ...headers, "-s", `-w "\\n%{json}"`, `-X ${this._method}`, `"${this._url}"`].join(" "); return new Promise((resolve, reject) => { (0, node_child_process_1.exec)(command, { cwd: browsers_1.BINARY_PATH }, (err, stdout, stderr) => { if (err) { reject(err); return; } if (stderr.trim().length > 0) { resolve({ response: undefined, details: undefined, stderr }); return; } const result = stdout.split("\n"); const response = result.slice(0, result.length - 1).join(""); const details = JSON.parse(result.at(-1) ?? "{}"); resolve({ response, details, stderr: undefined }); }); }); } buildFlags(flags) { const flagBlacklist = [ "-w", "-s", "-v", // TODO: potentially add a way to parse stdout with flag included "-X" ]; return flags.filter((flag) => !flagBlacklist.includes(flag)); } buildHeaderFlags(headers) { return Object.entries(headers).map(([key, value]) => `-H "${key}: ${value}"`); } } exports.RequestBuilder = RequestBuilder;