/** * HTTP client for the npm registry API v2. * * This module provides {@link NpmRegistryClient}, a thin wrapper around the * global `fetch` (available in Node 18+) that adds: * * - **Timeout**: each request is aborted after 10 seconds via an * `AbortController`. * - **Retry with exponential backoff**: failed requests (network errors or * non-2xx responses) are retried up to 3 times with delays of 1s, 2s, and * 4s between attempts. * - **Compression**: the `Accept-Encoding` header advertises gzip and * deflate support. * - **User-Agent**: a customisable UA header is sent on every request. * - **Typed errors**: non-success responses and unrecoverable failures are * surfaced as {@link NpmRegistryError} carrying the HTTP status code and * status text. * * The client intentionally contains **no caching** and **no rate limiting** * — those concerns are delegated to dedicated modules layered on top. * * @module registry/client */ import type { AbbreviatedVersion, PackageMetadata, SearchResult } from './types.js'; /** Default compressed tarball limit for a deep package-content scan. */ export declare const DEFAULT_MAX_TARBALL_BYTES: number; /** * HTTP client for the npm registry. * * Construct an instance once and reuse it across calls — the client holds no * per-request mutable state beyond the configured base URL and User-Agent. * All public methods are async and return parsed, typed JSON payloads. * * @example * ```ts * const client = new NpmRegistryClient(); * const meta = await client.getPackageMetadata('lodash'); * const manifest = await client.getVersionManifest('lodash', '4.17.21'); * const hits = await client.searchPackages('security', 10); * ``` */ export declare class NpmRegistryClient { /** Base URL (no trailing slash) prepended to every request path. */ private readonly baseUrl; /** User-Agent header value sent on every request. */ private readonly userAgent; /** Explicit proxy URL from constructor options (highest priority). */ private readonly proxyUrl?; /** Proxy dispatchers keyed by proxy URL, lazily created. */ private readonly proxyAgents; /** Hosts that must bypass the proxy. */ private readonly noProxyHosts; /** * @param options - Optional configuration overriding the defaults. * @param options.baseUrl - Registry base URL. Defaults to * `https://registry.npmjs.org`. A trailing slash is stripped. * @param options.userAgent - User-Agent header value. Defaults to a * string identifying `@npm-safe/core`. * @param options.proxy - Proxy URL (e.g. `http://127.0.0.1:7897`). When * omitted, the conventional environment variables are consulted. */ constructor(options?: { readonly baseUrl?: string; readonly userAgent?: string; readonly proxy?: string; }); /** * Resolve the fetch `dispatcher` to use for a request URL. * * Returns `undefined` when no proxy is configured or the hostname is in * the `NO_PROXY` list; otherwise returns a lazily created * {@link Dispatcher} for the active proxy. * * @param url - Fully-qualified request URL. * @returns A proxy dispatcher, or `undefined` to use the default fetch. */ private getDispatcher; /** * Fetch the full packument (metadata) for a package. * * Issues `GET {baseUrl}/{name}` and returns the parsed * {@link PackageMetadata} document, which includes all published versions, * dist-tags, and the readme. * * @param name - Package name (scoped names include the leading `@`). * @param options - Optional request options. `options.signal` is forwarded * to the underlying fetch as part of a combined abort signal; an external * abort settles the promise promptly with an `AbortError` `DOMException` * (no retry). * @returns The full package metadata document. * @throws {NpmRegistryError} When the request fails after all retries or * the registry returns a non-2xx status. * @throws {DOMException} With name `AbortError` when `options.signal` is * aborted. */ getPackageMetadata(name: string, options?: { readonly signal?: AbortSignal; }): Promise; /** * Fetch the abbreviated packument for a single published version. * * Issues `GET {baseUrl}/{name}/{version}` and returns the parsed * {@link AbbreviatedVersion} manifest. * * @param name - Package name (scoped names include the leading `@`). * @param version - Semver version string (e.g. `4.17.21`). * @returns The abbreviated version manifest. * @throws {NpmRegistryError} When the request fails after all retries or * the registry returns a non-2xx status. */ getVersionManifest(name: string, version: string): Promise; /** * Search the registry for packages matching a text query. * * Issues `GET {baseUrl}/-/v1/search?text={query}&size={size}` and returns * the array of {@link SearchResult} hits. The `size` parameter caps the * number of results (the registry imposes its own upper bound). * * @param query - Free-text search query. * @param options - Optional search options. `options.size` caps the number * of results (defaults to 20); `options.signal` is forwarded to the * underlying fetch as part of a combined abort signal. * @returns An array of search-result hits, ordered by relevance. * @throws {NpmRegistryError} When the request fails after all retries or * the registry returns a non-2xx status. * @throws {DOMException} With name `AbortError` when `options.signal` is * aborted. */ searchPackages(query: string, options?: { readonly size?: number; readonly signal?: AbortSignal; }): Promise; /** Download a same-origin package tarball through a bounded binary reader. */ downloadTarball(tarballUrl: string, options?: { readonly maxBytes?: number; readonly signal?: AbortSignal; }): Promise; /** * Perform a single HTTP GET against `url` with timeout and retry. * * The request is retried up to {@link MAX_ATTEMPTS} times with exponential * backoff (1s, 2s, 4s). A retry is attempted when: * * - The fetch rejects (network error, DNS failure, abort due to the owned * timeout controller). * - The response status is not in the 2xx range. * * On the final attempt the underlying error (or a new * {@link NpmRegistryError} for non-2xx responses) is rethrown. * * **Cooperative cancellation**: when `options.signal` is supplied it is * combined with the per-request timeout controller via `AbortSignal.any`. * An external abort (`options.signal` aborted) breaks the retry loop * immediately and rethrows `DOMException('The operation was aborted.', * 'AbortError')` with NO retry — the abort is never swallowed as a * retryable timeout. Only the owned timeout controller keeps the existing * wrap-as-`NpmRegistryError` + retry behaviour. * * @typeParam T - Expected shape of the parsed JSON response. * @param url - Fully-qualified URL to fetch. * @param options - Optional request options. `options.signal` is an * external abort signal forwarded by callers. * @returns The parsed JSON response body typed as `T`. * @throws {NpmRegistryError} When all attempts are exhausted or the * registry returns a non-2xx status on the final attempt. * @throws {DOMException} With name `AbortError` when `options.signal` is * aborted. */ private request; } //# sourceMappingURL=client.d.ts.map