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.

296 lines 17.9 kB
import {} from '../legacy/smartrequest.interfaces.js'; import { request } from '../legacy/smartrequest.request.js'; import * as plugins from '../legacy/smartrequest.plugins.js'; import { PaginationStrategy } from './types/pagination.js'; import { createPaginatedResponse } from './features/pagination.js'; /** * Modern fluent client for making HTTP requests */ export class SmartRequestClient { constructor() { this._options = {}; this._responseType = 'json'; this._timeoutMs = 60000; this._retries = 0; this._queryParams = {}; } /** * Create a new SmartRequestClient instance */ static create() { return new SmartRequestClient(); } /** * Set the URL for the request */ url(url) { this._url = url; return this; } /** * Set the HTTP method */ method(method) { this._options.method = method; return this; } /** * Set JSON body for the request */ json(data) { if (!this._options.headers) { this._options.headers = {}; } this._options.headers['Content-Type'] = 'application/json'; this._options.requestBody = data; return this; } /** * Set form data for the request */ formData(data) { const form = new plugins.formData(); for (const item of data) { if (Buffer.isBuffer(item.value)) { form.append(item.name, item.value, { filename: item.filename || 'file', contentType: item.contentType || 'application/octet-stream' }); } else { form.append(item.name, item.value); } } if (!this._options.headers) { this._options.headers = {}; } this._options.headers = { ...this._options.headers, ...form.getHeaders() }; this._options.requestBody = form; return this; } /** * Set request timeout in milliseconds */ timeout(ms) { this._timeoutMs = ms; this._options.timeout = ms; this._options.hardDataCuttingTimeout = ms; return this; } /** * Set number of retry attempts */ retry(count) { this._retries = count; return this; } /** * Set HTTP headers */ headers(headers) { if (!this._options.headers) { this._options.headers = {}; } this._options.headers = { ...this._options.headers, ...headers }; return this; } /** * Set a single HTTP header */ header(name, value) { if (!this._options.headers) { this._options.headers = {}; } this._options.headers[name] = value; return this; } /** * Set query parameters */ query(params) { this._queryParams = { ...this._queryParams, ...params }; return this; } /** * Set response type */ responseType(type) { this._responseType = type; if (type === 'binary' || type === 'stream') { this._options.autoJsonParse = false; } return this; } /** * Configure pagination for requests */ pagination(config) { this._paginationConfig = config; return this; } /** * Configure offset-based pagination (page & limit) */ withOffsetPagination(config = {}) { this._paginationConfig = { strategy: PaginationStrategy.OFFSET, pageParam: config.pageParam || 'page', limitParam: config.limitParam || 'limit', startPage: config.startPage || 1, pageSize: config.pageSize || 20, totalPath: config.totalPath || 'total' }; // Add initial pagination parameters this.query({ [this._paginationConfig.pageParam]: String(this._paginationConfig.startPage), [this._paginationConfig.limitParam]: String(this._paginationConfig.pageSize) }); return this; } /** * Configure cursor-based pagination */ withCursorPagination(config = {}) { this._paginationConfig = { strategy: PaginationStrategy.CURSOR, cursorParam: config.cursorParam || 'cursor', cursorPath: config.cursorPath || 'nextCursor', hasMorePath: config.hasMorePath || 'hasMore' }; return this; } /** * Configure Link header-based pagination */ withLinkPagination() { this._paginationConfig = { strategy: PaginationStrategy.LINK_HEADER }; return this; } /** * Configure custom pagination */ withCustomPagination(config) { this._paginationConfig = { strategy: PaginationStrategy.CUSTOM, hasNextPage: config.hasNextPage, getNextPageParams: config.getNextPageParams }; return this; } /** * Make a GET request */ async get() { return this.execute('GET'); } /** * Make a POST request */ async post() { return this.execute('POST'); } /** * Make a PUT request */ async put() { return this.execute('PUT'); } /** * Make a DELETE request */ async delete() { return this.execute('DELETE'); } /** * Make a PATCH request */ async patch() { return this.execute('PATCH'); } /** * Get paginated response */ async getPaginated() { if (!this._paginationConfig) { throw new Error('Pagination not configured. Call one of the pagination methods first.'); } // Default to GET if no method specified if (!this._options.method) { this._options.method = 'GET'; } const response = await this.execute(); return createPaginatedResponse(response, this._paginationConfig, this._queryParams, (nextPageParams) => { // Create a new client with the same configuration but updated query params const nextClient = new SmartRequestClient(); Object.assign(nextClient, this); nextClient._queryParams = nextPageParams; return nextClient.getPaginated(); }); } /** * Get all pages at once (use with caution for large datasets) */ async getAllPages() { const firstPage = await this.getPaginated(); return firstPage.getAllPages(); } /** * Execute the HTTP request */ async execute(method) { if (method) { this._options.method = method; } this._options.queryParams = this._queryParams; // Handle retry logic let lastError; for (let attempt = 0; attempt <= this._retries; attempt++) { try { if (this._responseType === 'stream') { return await request(this._url, this._options, true); } else if (this._responseType === 'binary') { const response = await request(this._url, this._options, true); // Handle binary response const dataPromise = plugins.smartpromise.defer(); const chunks = []; response.on('data', (chunk) => chunks.push(chunk)); response.on('end', () => { const buffer = Buffer.concat(chunks); response.body = buffer; dataPromise.resolve(); }); await dataPromise.promise; return response; } else { // Handle JSON or text response return await request(this._url, this._options); } } catch (error) { lastError = error; // If this is the last attempt, throw the error if (attempt === this._retries) { throw lastError; } // Otherwise, wait before retrying await new Promise(resolve => setTimeout(resolve, 1000)); } } // This should never be reached due to the throw in the loop above throw lastError; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRyZXF1ZXN0Y2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbW9kZXJuL3NtYXJ0cmVxdWVzdGNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQTZCLE1BQU0sc0NBQXNDLENBQUM7QUFDakYsT0FBTyxFQUFFLE9BQU8sRUFBaUMsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzRixPQUFPLEtBQUssT0FBTyxNQUFNLG1DQUFtQyxDQUFDO0FBRzdELE9BQU8sRUFFTCxrQkFBa0IsRUFLbkIsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUVuRTs7R0FFRztBQUNILE1BQU0sT0FBTyxrQkFBa0I7SUFBL0I7UUFFVSxhQUFRLEdBQXlCLEVBQUUsQ0FBQztRQUNwQyxrQkFBYSxHQUFpQixNQUFNLENBQUM7UUFDckMsZUFBVSxHQUFXLEtBQUssQ0FBQztRQUMzQixhQUFRLEdBQVcsQ0FBQyxDQUFDO1FBQ3JCLGlCQUFZLEdBQTJCLEVBQUUsQ0FBQztJQXNVcEQsQ0FBQztJQW5VQzs7T0FFRztJQUNILE1BQU0sQ0FBQyxNQUFNO1FBQ1gsT0FBTyxJQUFJLGtCQUFrQixFQUFLLENBQUM7SUFDckMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsR0FBRyxDQUFDLEdBQVc7UUFDYixJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztRQUNoQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxNQUFrQjtRQUN2QixJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDOUIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLENBQUMsSUFBUztRQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQzNCLElBQUks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