UNPKG

@push.rocks/smartrequest

Version:

A module for modern HTTP/HTTPS requests with support for form data, file uploads, JSON, binary data, streams, and more.

210 lines 17.3 kB
import * as types from './types.js'; import { CoreResponse } from './response.js'; import { CoreRequest as AbstractCoreRequest } from '../core_base/request.js'; /** * Bun implementation of Core Request class using native fetch with unix socket support */ export class CoreRequest extends AbstractCoreRequest { constructor(url, options = {}, requestDataFunc = null) { super(url, options); this.timeoutId = null; this.abortController = null; this.requestDataFunc = requestDataFunc; // Check for unsupported Node.js-specific options if (options.agent) { throw new Error('Node.js specific option (agent) is not supported in Bun implementation'); } // Handle Node.js stream conversion if requestDataFunc is provided if (requestDataFunc && options.__nodeStream) { // Convert Node.js stream to web ReadableStream for Bun const nodeStream = options.__nodeStream; // Bun can handle Node.js streams via Readable.toWeb if available // Or we can create a web stream that reads from the Node stream if (typeof nodeStream.toWeb === 'function') { this.options.requestBody = nodeStream.toWeb(); } else { // Create web ReadableStream from Node.js stream this.options.requestBody = new ReadableStream({ async start(controller) { nodeStream.on('data', (chunk) => { controller.enqueue(new Uint8Array(chunk)); }); nodeStream.on('end', () => { controller.close(); }); nodeStream.on('error', (err) => { controller.error(err); }); }, }); } } // Warn if raw streaming function is provided (not supported in Bun) if (requestDataFunc && options.__rawStreamFunc) { throw new Error('Raw streaming with .raw() is not supported in Bun. Use .stream() with web ReadableStream instead.'); } } /** * Build the full URL with query parameters */ buildUrl() { // For unix sockets, we need to extract the HTTP path part if (CoreRequest.isUnixSocket(this.url)) { const { path } = CoreRequest.parseUnixSocketUrl(this.url); // Build URL for the HTTP request (the hostname doesn't matter for unix sockets) if (!this.options.queryParams || Object.keys(this.options.queryParams).length === 0) { return `http://localhost${path}`; } const url = new URL(`http://localhost${path}`); Object.entries(this.options.queryParams).forEach(([key, value]) => { url.searchParams.append(key, value); }); return url.toString(); } // Regular HTTP/HTTPS URL if (!this.options.queryParams || Object.keys(this.options.queryParams).length === 0) { return this.url; } const url = new URL(this.url); Object.entries(this.options.queryParams).forEach(([key, value]) => { url.searchParams.append(key, value); }); return url.toString(); } /** * Convert our options to fetch RequestInit with Bun-specific extensions */ buildFetchOptions() { const fetchOptions = { method: this.options.method, headers: this.options.headers, credentials: this.options.credentials, mode: this.options.mode, cache: this.options.cache, redirect: this.options.redirect, referrer: this.options.referrer, referrerPolicy: this.options.referrerPolicy, integrity: this.options.integrity, keepalive: this.options.keepAlive, signal: this.options.signal, }; // Handle unix socket if (CoreRequest.isUnixSocket(this.url)) { const { socketPath } = CoreRequest.parseUnixSocketUrl(this.url); fetchOptions.unix = socketPath; } else if (this.options.unix) { // Direct unix option was provided fetchOptions.unix = this.options.unix; } else if (this.options.socketPath) { // Legacy Node.js socketPath option - convert to Bun's unix option fetchOptions.unix = this.options.socketPath; } // Handle request body if (this.options.requestBody !== undefined) { if (typeof this.options.requestBody === 'string' || this.options.requestBody instanceof ArrayBuffer || this.options.requestBody instanceof Uint8Array || this.options.requestBody instanceof FormData || this.options.requestBody instanceof URLSearchParams || this.options.requestBody instanceof ReadableStream || // Check for Buffer (Bun supports Node.js Buffer) (typeof Buffer !== 'undefined' && this.options.requestBody instanceof Buffer)) { fetchOptions.body = this.options.requestBody; // If streaming, we need to set duplex mode if (this.options.requestBody instanceof ReadableStream) { fetchOptions.duplex = 'half'; } } else { // Convert objects to JSON fetchOptions.body = JSON.stringify(this.options.requestBody); // Set content-type if not already set if (!fetchOptions.headers) { fetchOptions.headers = { 'Content-Type': 'application/json' }; } else if (fetchOptions.headers instanceof Headers) { if (!fetchOptions.headers.has('Content-Type')) { fetchOptions.headers.set('Content-Type', 'application/json'); } } else if (typeof fetchOptions.headers === 'object' && !Array.isArray(fetchOptions.headers)) { const headersObj = fetchOptions.headers; if (!headersObj['Content-Type']) { headersObj['Content-Type'] = 'application/json'; } } } } // Handle timeout if (this.options.timeout || this.options.hardDataCuttingTimeout) { const timeout = this.options.hardDataCuttingTimeout || this.options.timeout; this.abortController = new AbortController(); this.timeoutId = setTimeout(() => { if (this.abortController) { this.abortController.abort(); } }, timeout); fetchOptions.signal = this.abortController.signal; } return fetchOptions; } /** * Fire the request and return a CoreResponse */ async fire() { const response = await this.fireCore(); return new CoreResponse(response); } /** * Fire the request and return the raw Response */ async fireCore() { const url = this.buildUrl(); const options = this.buildFetchOptions(); try { const response = await fetch(url, options); // Clear timeout on successful response this.clearTimeout(); return response; } catch (error) { // Clear timeout on error this.clearTimeout(); if (error.name === 'AbortError') { throw new Error('Request timed out'); } throw error; } } /** * Clear the timeout and abort controller */ clearTimeout() { if (this.timeoutId) { clearTimeout(this.timeoutId); this.timeoutId = null; } if (this.abortController) { this.abortController = null; } } /** * Static factory method to create and fire a request */ static async create(url, options = {}) { const request = new CoreRequest(url, options); return request.fire(); } } /** * Convenience exports for backward compatibility */ export const isUnixSocket = CoreRequest.isUnixSocket; export const parseUnixSocketUrl = CoreRequest.parseUnixSocketUrl; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvcmVfYnVuL3JlcXVlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDcEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsV0FBVyxJQUFJLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFN0U7O0dBRUc7QUFDSCxNQUFNLE9BQU8sV0FBWSxTQUFRLG1CQUdoQztJQUtDLFlBQ0UsR0FBVyxFQUNYLFVBQW9DLEVBQUUsRUFDdEMsa0JBQStDLElBQUk7UUFFbkQsS0FBSyxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztRQVRkLGNBQVMsR0FBeUMsSUFBSSxDQUFDO1FBQ3ZELG9CQUFlLEdBQTJCLElBQUksQ0FBQztRQVNyRCxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztRQUV2QyxpREFBaUQ7UUFDakQsSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLEtBQUssQ0FDYix3RUFBd0UsQ0FDekUsQ0FBQztRQUNKLENBQUM7UUFFRCxrRUFBa0U7UUFDbEUsSUFBSSxlQUFlLElBQUssT0FBZSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3JELHVEQUF1RDtZQUN2RCxNQUFNLFVBQVUsR0FBSSxPQUFlLENBQUMsWUFBWSxDQUFDO1lBRWpELGlFQUFpRTtZQUNqRSxnRUFBZ0U7WUFDaEUsSUFBSSxPQUFRLFVBQWtCLENBQUMsS0FBSyxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUNwRCxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsR0FBSSxVQUFrQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3pELENBQUM7aUJBQU0sQ0FBQztnQkFDTixnREFBZ0Q7Z0JBQ2hELElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxHQUFHLElB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