/** * Lightweight API client factory with caching, retry, and rate limiting. * * Instead of an abstract class with 7 virtual methods, this uses a config * object to create a client. Each module calls createClient() once. * * Features: * - Disk-backed TTL cache (survives MCP server restarts) * - Timeout (30s default) * - Retry with exponential backoff (429, 502, 503, 504) * - Token-bucket rate limiting * - Auth via query param, header, or request body */ export interface ClientConfig { baseUrl: string; name: string; /** Auth configuration — how to attach credentials to requests */ auth?: { /** Where to inject credentials: query string, request header, or POST body */ type: "query" | "header" | "body"; /** * Maps param/header names to env var names. Values are read from process.env at request time. * If the env var is unset, that param is silently omitted (graceful degradation). * * Examples: * Single key: envParams: { api_key: "FRED_API_KEY" } * Key + email: envParams: { key: "AQS_API_KEY", email: "AQS_EMAIL" } * Bearer token: envParams: { Authorization: "HUD_USER_TOKEN" } (with prefix: "Bearer ") */ envParams: Record; /** Static params included on every authenticated request (e.g. { file_type: "json" } for FRED) */ extraParams?: Record; /** For header auth: prefix prepended to the first envParams value (e.g. "Bearer ") */ prefix?: string; }; /** Rate limiting */ rateLimit?: { perSecond: number; burst: number; }; /** Default headers on every request (e.g. User-Agent for SEC) */ defaultHeaders?: Record; /** Cache TTL in ms (default: 5 min). Government data often updates daily/weekly — set * higher for infrequent data: 1 hour = 3_600_000, 1 day = 86_400_000. Set 0 to disable. */ cacheTtlMs?: number; /** Timeout in ms (default: 30000) */ timeoutMs?: number; /** Max retries for transient errors (429, 502, 503, 504). Default: 2. * Increase for notoriously flaky upstream APIs (e.g. FBI CDE). */ maxRetries?: number; /** Custom error detector — some APIs return 200 OK with errors in the body */ checkError?: (data: unknown) => string | null; } /** Param values: string, number, string[] (for repeated keys like facets[series][]), or undefined to skip */ export type ParamValue = string | number | string[] | undefined; export type Params = Record; /** * Shorthand for building query param objects. Drops `undefined`, `null`, and `""`. * Booleans become `"true"`/`"false"`. Arrays pass through (for repeated keys like `facets[series][]`). * * @example * const { fromDateTime, toDateTime } = opts; * const params = qp({ limit: opts.limit ?? 20, fromDateTime, toDateTime }); * * // rename a key + set a default * const params = qp({ limit: 50, p_zip: opts.zip, sort: opts.sort ?? "desc" }); */ export declare function qp(obj: Record): Params; export interface ApiClient { get(path: string, params?: Params): Promise; post(path: string, body?: Record, params?: Params): Promise; clearCache(): void; } export declare class TokenBucket { private readonly max; private readonly rate; private tokens; private lastRefill; private readonly queue; private timer; constructor(max: number, rate: number); /** Refill tokens based on elapsed time since the last refill. */ private refill; /** Wait until a token is available, respecting FIFO order. */ acquire(): Promise; /** Number of callers currently waiting for a token. */ get pending(): number; /** Ensure a drain timer is running to release queued callers. */ private scheduleDrain; } export declare function createClient(config: ClientConfig): ApiClient; //# sourceMappingURL=client.d.ts.map