/** * Imperative HTTP client with Axios-like API, interceptors, retry, timeout, * cancellation, and progress tracking — built on the native Fetch API. * * @module bquery/reactive */ import { type BqueryFetchParseAs } from '../platform/config'; /** Configuration for automatic request retries. */ export interface RetryConfig { /** Maximum number of retry attempts (default: 3). */ count: number; /** Delay in ms between retries, or a function receiving the attempt index. */ delay?: number | ((attempt: number) => number); /** Predicate deciding whether to retry a given error. Defaults to network / 5xx errors. */ retryOn?: (error: HttpError, attempt: number) => boolean; /** Called before each retry attempt with the error and 1-indexed attempt number. */ onRetry?: (error: HttpError, attempt: number) => void; } /** Progress information emitted during upload or download. */ export interface HttpProgressEvent { /** Bytes transferred so far. */ loaded: number; /** Total bytes if known, otherwise 0. */ total: number; /** Percentage between 0 and 100, or `undefined` when total is unknown. */ percent: number | undefined; } /** Full request configuration accepted by the HTTP client. */ export interface HttpRequestConfig extends Omit { /** Request URL (resolved against `baseUrl`). */ url?: string; /** Base URL prepended to relative request URLs. */ baseUrl?: string; /** Request headers. */ headers?: HeadersInit; /** Query parameters appended to the URL. */ query?: Record; /** Request body — plain objects/arrays are JSON-serialised automatically. */ body?: BodyInit | Record | unknown[] | null; /** Request timeout in milliseconds. 0 means no timeout (default). */ timeout?: number; /** Response parsing strategy. */ parseAs?: BqueryFetchParseAs; /** Custom status validation. Returns `true` for acceptable statuses. Default: `status >= 200 && status < 300`. */ validateStatus?: (status: number) => boolean; /** Custom fetch implementation for testing or adapters. */ fetcher?: typeof fetch; /** External `AbortSignal` for request cancellation. */ signal?: AbortSignal; /** Retry configuration. Pass a number for simple retry count, or a `RetryConfig` object. */ retry?: number | RetryConfig; /** Called repeatedly as response body chunks arrive. */ onDownloadProgress?: (event: HttpProgressEvent) => void; } /** Structured HTTP response returned by every client method. */ export interface HttpResponse { /** Parsed response data. */ data: T; /** HTTP status code. */ status: number; /** HTTP status text. */ statusText: string; /** Response headers. */ headers: Headers; /** Resolved request configuration used for this call. */ config: HttpRequestConfig; } /** Error subclass thrown on failed HTTP requests with rich metadata. */ export declare class HttpError extends Error { /** HTTP response (available when the server replied). */ response?: HttpResponse; /** Resolved request configuration. */ config: HttpRequestConfig; /** Original error code string (e.g. `'TIMEOUT'`, `'ABORT'`, `'NETWORK'`). */ code: string; constructor(message: string, config: HttpRequestConfig, code: string, response?: HttpResponse); } /** Single interceptor handler pair. */ export interface Interceptor { fulfilled?: (value: T) => T | Promise; rejected?: (error: unknown) => unknown; } /** Manager for adding and removing interceptors. */ export interface InterceptorManager { /** Register an interceptor. Returns a numeric id for later removal via `eject()`. */ use(fulfilled?: (value: T) => T | Promise, rejected?: (error: unknown) => unknown): number; /** Remove a previously registered interceptor by id. */ eject(id: number): void; /** Remove all interceptors. */ clear(): void; } /** Imperative HTTP client with interceptors and convenience method shortcuts. */ export interface HttpClient { /** Send a request using the provided configuration. */ request(config: HttpRequestConfig): Promise>; /** Send a GET request. */ get(url: string, config?: HttpRequestConfig): Promise>; /** Send a POST request. */ post(url: string, body?: HttpRequestConfig['body'], config?: HttpRequestConfig): Promise>; /** Send a PUT request. */ put(url: string, body?: HttpRequestConfig['body'], config?: HttpRequestConfig): Promise>; /** Send a PATCH request. */ patch(url: string, body?: HttpRequestConfig['body'], config?: HttpRequestConfig): Promise>; /** Send a DELETE request. */ delete(url: string, config?: HttpRequestConfig): Promise>; /** Send a HEAD request. */ head(url: string, config?: HttpRequestConfig): Promise>; /** Send an OPTIONS request. */ options(url: string, config?: HttpRequestConfig): Promise>; /** Request and response interceptors. */ interceptors: { request: InterceptorManager; response: InterceptorManager; }; /** The merged default configuration used by this client. */ defaults: HttpRequestConfig; } /** * Create a preconfigured HTTP client instance with interceptors. * * @param defaults - Default request configuration merged into every request * @returns An `HttpClient` with `.get()`, `.post()`, `.put()`, `.patch()`, `.delete()`, `.head()`, `.options()` * * @example * ```ts * import { createHttp } from '@bquery/bquery/reactive'; * * const api = createHttp({ * baseUrl: 'https://api.example.com', * headers: { authorization: 'Bearer token' }, * timeout: 10_000, * }); * * api.interceptors.request.use((config) => { * config.headers = { ...Object.fromEntries(new Headers(config.headers)), 'x-req-id': crypto.randomUUID() }; * return config; * }); * * const { data } = await api.get('/users'); * ``` */ export declare function createHttp(defaults?: HttpRequestConfig): HttpClient; /** * Default HTTP client instance using global bQuery fetch config. * * @example * ```ts * import { http } from '@bquery/bquery/reactive'; * * const { data } = await http.get('/api/users'); * const { data: created } = await http.post('/api/users', { name: 'Ada' }); * ``` */ export declare const http: HttpClient; /** Options for `createRequestQueue()`. */ export interface RequestQueueOptions { /** Maximum number of concurrent in-flight requests (default: 6). */ concurrency?: number; } /** Return value of `createRequestQueue()`. */ export interface RequestQueue { /** Enqueue a request. Returns a promise that resolves when the request completes. */ add: (execute: () => Promise>) => Promise>; /** Number of requests currently being processed. */ readonly pending: number; /** Number of requests waiting in the queue. */ readonly size: number; /** Remove all pending (not yet started) requests from the queue. Their promises will reject. */ clear: () => void; } /** * Create a request queue with a concurrency limit. * * Useful for rate-limiting parallel HTTP requests (e.g. browser connection limits, * API throttling) while maintaining a simple promise-based interface. * * @param options - Queue configuration * @returns A `RequestQueue` with `.add()`, `.clear()`, `.pending`, and `.size` * * @example * ```ts * import { createRequestQueue, createHttp } from '@bquery/bquery/reactive'; * * const api = createHttp({ baseUrl: 'https://api.example.com' }); * const queue = createRequestQueue({ concurrency: 3 }); * * // These will run at most 3 at a time * const results = await Promise.all( * ids.map(id => queue.add(() => api.get(`/items/${id}`))) * ); * ``` */ export declare function createRequestQueue(options?: RequestQueueOptions): RequestQueue; //# sourceMappingURL=http.d.ts.map