import { AfterInterceptor, BeforeInterceptor, HttpConfig, HttpData, HttpEventHandler, HttpMethod, HttpResult, RequestOptions, StreamRequestOptions } from "./Http.types.mjs"; import { CancellableAsyncIterable, CancellablePromise } from "./cancellable.mjs"; //#region ../http/src/Http.d.ts declare class Http { private readonly config; private readonly beforeInterceptors; private readonly afterInterceptors; private readonly eventHandlers; /** * In-flight GET entries keyed by URL+params. Each entry tracks the shared underlying * promise, the shared AbortController, and a ref-count of active callers. * When the last caller cancels, the shared fetch is aborted. */ private readonly inFlight; constructor(config?: HttpConfig); /** Return a new Http instance that inherits this config merged with overrides. */ extend(overrides: HttpConfig): Http; getConfig(): Readonly; before(interceptor: BeforeInterceptor): this; after(interceptor: AfterInterceptor): this; on(event: string, handler: HttpEventHandler): this; off(event: string, handler: HttpEventHandler): this; private emit; get(path: string, options?: RequestOptions): CancellablePromise>; post(path: string, data?: HttpData, options?: RequestOptions): CancellablePromise>; put(path: string, data?: HttpData, options?: RequestOptions): CancellablePromise>; patch(path: string, options?: RequestOptions): CancellablePromise>; delete(path: string, options?: RequestOptions): CancellablePromise>; head(path: string, options?: RequestOptions): CancellablePromise>; options(path: string, options?: RequestOptions): CancellablePromise>; /** * Send a request with any HTTP method — the escape hatch for non-standard verbs. * All convenience methods delegate here. * * GET requests are deduplicated **in the browser**: concurrent calls with the same URL * share a single underlying fetch, and each caller gets its own CancellablePromise. * Outside a browser deduplication is off by default — see `HttpConfig.dedupe`. */ request(method: HttpMethod | string, path: string, data?: HttpData, options?: RequestOptions): CancellablePromise>; /** * Remove a single cache entry by key. * Pass the same key used in `options.cacheKey`, or the auto-generated key: * `http::`. */ invalidate(key: string): Promise; /** * Remove all cache entries. Requires the driver to implement `clear()`. */ invalidateAll(): Promise; /** * Run multiple requests concurrently and collect every result in order. * Cancelling the returned handle cancels all requests in the batch. * * Unlike `Promise.all`, individual requests still resolve to `{data, error}` * even when one fails — they never throw. The batch itself resolves when * all inner requests settle. * * @example * const results = await http.all([ * http.get('/users'), * http.get('/posts'), * ]); * const [usersResult, postsResult] = results; */ all(requests: CancellablePromise[]): CancellablePromise; /** * Run multiple requests concurrently and return the result of whichever * settles first. All other in-flight requests are cancelled immediately. * * Useful for mirror/fallback endpoints where you want the fastest response. * * @example * const { data } = await http.race([ * http.get('/cdn-us/data'), * http.get('/cdn-eu/data'), * ]); */ race(requests: CancellablePromise[]): CancellablePromise; /** * Open a streaming connection and yield parsed chunks as an async iterable. * * Supports Server-Sent Events (SSE) and newline-delimited JSON (NDJSON). * For SSE, automatically reconnects on disconnect and sends `Last-Event-ID` * so the server can resume. Use `.cancel()` to abort from outside the loop. * * The stream **never throws** — errors are stored in `.error` instead. * Check `stream.error` after the `for await` loop. * * @example * const stream = http.stream('/chat', { method: 'POST', data: { messages } }); * for await (const chunk of stream) { * setContent(c => c + chunk.content); * } * if (stream.error) showError(stream.error.message); */ stream(path: string, options?: StreamRequestOptions): CancellableAsyncIterable; /** * Build the final OutgoingRequest: URL, headers, auth, before-interceptors. * Shared by both regular requests and streaming. */ private buildOutgoingRequest; private execute; private executeWithRetry; private executeSingle; private errorResult; /** * Run all after-interceptors on `result`, providing each with a `replay()` context. * * `replay()` re-fires the original request from scratch (fresh auth, before-interceptors). * When `isReplay` is true, `replay()` is a no-op that returns the current result — this * prevents infinite loops when a token-refresh interceptor would otherwise call replay() * on the already-replayed request. */ private runAfterInterceptors; private shouldRetry; /** * Whether this GET should join the in-flight dedup pool. * * Per-request wins over instance config, which wins over the environment default: * on in a browser (one user per instance), off everywhere else. */ private shouldDedupe; /** * Resolve the key that decides which concurrent GETs share one underlying fetch. * * Precedence: explicit per-request key → `config.dedupeKey(url, params)` → URL + params. * * The last two are derived from URL + params only — they never see headers, cookies or * auth, so they cannot tell two *users* apart. That is fine in a browser and unsafe on a * server, so outside a browser an explicit per-request key is mandatory. We refuse rather * than guess which header carries identity: a guess would miss custom schemes (a tenant * header, a signed cookie) while looking safe, which is worse than failing loudly. */ private resolveDedupeKey; /** * Build the `RequestInit` for a fetch call. * * Caller-supplied `fetchInit` is spread FIRST so that keys the library doesn't model — * Next.js' `next: { revalidate, tags }`, runtime-specific flags — reach fetch, while the * fields the library manages are written last and win. `method`/`headers`/`body`/`signal` * always win (overriding them would bypass interceptors and auth, or break cancellation * and timeouts); the optional ones win only when actually configured, so an unset option * doesn't erase a deliberate `fetchInit` value. * * @param keepalive Whether `keepalive` participates at all. Streaming never applies it — * it caps the body at 64 KB and exists for unload beacons, so a globally * configured `keepalive: true` must not reach a long-lived stream. */ private buildFetchInit; /** * The fallback cache key, used only when neither `options.cacheKey` nor * `cache.generateKey` was supplied. * * URL + params has the same blind spot as the default dedup key: it cannot tell two * callers apart, so on a server an authenticated response could be handed to a different * user. The cache is opt-in, so reaching here outside a browser means someone enabled it * without saying how entries are scoped — refuse instead of caching per-user data under a * shared key. */ private defaultCacheKey; private resolveCacheConfig; private resolveRetryConfig; } //#endregion export { Http }; //# sourceMappingURL=Http.d.mts.map