/** * Types Resolver - Fetches TypeScript type definitions for npm packages. * * This is a platform-independent implementation that works anywhere with fetch(). * (Browser, Node 18+, Bun, Deno, Cloudflare Workers) * * Design principles: * 1. Single responsibility: resolve package → types. No VFS writing. * 2. CDN-agnostic interface with esm.sh implementation * 3. Transparent @types fallback (caller doesn't need to know) * 4. Subpaths resolved on-demand, not pre-fetched * 5. Caching is external/injectable (platform-specific cache implementations) */ import type { ITypesResolver } from "../types"; import type { ICache } from "./persistor"; /** * Resolved type definitions for a package. */ export interface ResolvedTypes { /** * The package name (may differ from request if @types fallback was used) */ packageName: string; /** * The resolved version */ version: string; /** * Map of relative file paths to content. * Paths are relative to the package root (e.g., "index.d.ts", "utils.d.ts") */ files: Record; /** * Whether types came from @types/* package */ fromTypesPackage: boolean; /** * Peer type dependencies detected from `export * from 'external-package'` statements. * These packages should also have their types installed for complete type resolution. */ peerTypeDeps?: Array<{ packageName: string; version: string; }>; } export interface EsmTypesResolverOptions { /** * Base URL for esm.sh (default: "https://esm.sh") */ baseUrl?: string; /** * External cache for resolved types. If not provided, no caching is done. * This allows sharing cache across resolver instances. * * Key format: `${packageName}@${version}` or `${packageName}@${version}/${subpath}` */ cache?: ICache; /** * Whether to try @types/* packages as fallback when main package * doesn't have bundled types. Default: true */ tryTypesPackages?: boolean; } /** * Types resolver using esm.sh CDN. * * Platform-independent - works anywhere with fetch(). * * Resolution strategy: * 1. Fetch package from esm.sh, check X-TypeScript-Types header * 2. If no types, try @types/{package} as fallback * 3. Fetch .d.ts files and any /// dependencies * * @example * ```ts * const resolver = new EsmTypesResolver(); * * // Resolve types for a package * const types = await resolver.resolve("lodash", "4.17.21"); * // types.files: { "index.d.ts": "...", "common.d.ts": "..." } * * // Resolve subpath types * const clientTypes = await resolver.resolve("react-dom/client", "18.2.0"); * ``` */ export declare class EsmTypesResolver implements ITypesResolver { private baseUrl; private cache; private tryTypesPackages; private lastRequestCount; constructor(options?: EsmTypesResolverOptions); /** * Get the number of HTTP requests made during the last resolveTypes call. */ getLastRequestCount(): number; /** * Resolve type definitions for a package. * * @param specifier - Package specifier with optional subpath (e.g., "react", "react-dom/client") * @param version - Optional version constraint * @returns Map of file paths to content, or empty object if no types found */ resolveTypes(specifier: string, version?: string): Promise>; /** * Resolve just the version for a package (lightweight HEAD request). * Used by install() to get the resolved version without fetching all types. */ resolveVersion(specifier: string, version?: string): Promise<{ packageName: string; version: string; } | null>; /** * Resolve with full metadata (useful for advanced use cases). */ resolve(specifier: string, version?: string): Promise; /** * Resolve types with proper cache handling. * * For versioned requests: check cache immediately with that version. * For unversioned requests: do a cheap HEAD request to get the resolved version, * then check cache with that version before doing expensive type fetching. */ private tryResolveWithCache; /** Maximum retry attempts for transient errors (npm rate limits can be persistent) */ private static readonly MAX_RETRIES; /** Base delay for exponential backoff (ms) - higher for npm rate limiting */ private static readonly RETRY_BASE_DELAY_MS; /** * Lightweight HEAD request to get package metadata without fetching types. * Returns the resolved version and types URL. * Includes retry logic for transient errors (5xx, network issues). * * For @types/* packages, uses unpkg instead of esm.sh since esm.sh * cannot serve pure TypeScript definition packages (they have no JS). */ private fetchPackageHead; /** * Fetch package metadata for @types/* packages using jsdelivr. * These packages can't be served by esm.sh (they're pure .d.ts files). * We use jsdelivr because it has proper CORS support for browser environments. */ private fetchTypesPackageHead; /** Maximum concurrent fetches to avoid overwhelming the server */ private static readonly MAX_CONCURRENT_FETCHES; /** * Fetch a URL with retry logic for transient errors. */ private fetchWithRetry; /** * Fetch a .d.ts file and any files it references via: * - /// directives * - ES module imports/exports (import from "./...", export * from "./...") * * Uses parallel fetching with batching for performance. * * Also detects external package dependencies (export * from 'other-package') * and returns them as peer type dependencies. */ private fetchTypesRecursively; /** * Extract the resolved version from the response. */ private extractVersion; } //# sourceMappingURL=esm-types-resolver.d.ts.map