@datafuel/sdk 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/core.ts","../src/models.ts","../src/client.ts"],"sourcesContent":["/**\n * TypeScript client for the DataFuel scraping API.\n *\n * ```ts\n * import { DataFuel } from \"@datafuel/sdk\";\n *\n * const df = new DataFuel(); // reads DATAFUEL_API_KEY\n * console.log(await df.markdown(\"https://example.com\"));\n * ```\n *\n * Pick the call by the shape of the work:\n *\n * | You have | Call | Waits? |\n * |---|---|---|\n * | One URL | `scrape` / `markdown` | yes |\n * | A site, need its URL list | `map` | yes |\n * | A start URL, many pages | `crawl` / `startCrawl` | `crawl` does |\n * | A list of known URLs | `runJob` / `createJob` | `runJob` does |\n * | A question for an AI engine | `ask` | yes |\n * | A Google search | `search` | yes |\n * | Many prompts or searches | `runAskJob` / `runSearchJob` | yes |\n * | Earlier jobs, tasks, usage | `listJobs` / `listTasks` / `analytics` / `transactions` | yes |\n *\n * Start with plain `scrape`. Turn on `jsRendering` only when the page comes\n * back empty: it is slower and costs five times the credits on a Basic proxy.\n * `map` a section before you `crawl` it — one credit, and it tells you how big\n * the section is.\n */\n\nexport { DataFuel } from \"./client.js\";\nexport type { ClientOptions } from \"./client.js\";\nexport { DEFAULT_BASE_URL, VERSION } from \"./core.js\";\nexport type { AskOptions, CrawlOptions, MapOptions, SearchOptions } from \"./core.js\";\nexport {\n APIError,\n Blocked,\n DataFuelError,\n EngineUnavailable,\n Forbidden,\n IdempotencyKeyReused,\n InsufficientCredits,\n InvalidAttributes,\n JobNotCancellable,\n ModuleUnavailable,\n NoApiKey,\n NotFound,\n RateLimited,\n TaskFailed,\n TransportError,\n Unauthorized,\n Unavailable,\n WaitTimeout,\n} from \"./errors.js\";\nexport type { ErrorCode } from \"./errors.js\";\nexport { Capabilities, CrawlPage, isDone, Result } from \"./models.js\";\nexport type {\n AI,\n Analytics,\n AnalyticsCounts,\n AnalyticsOptions,\n BalanceSplit,\n CallOptions,\n CancelResult,\n Capability,\n CrawlResult,\n CrawlResultsPage,\n CrawlStatus,\n Engine,\n Format,\n JobResults,\n JobsPage,\n JobStatus,\n JobSummary,\n JsInstruction,\n JsInstructionArg,\n Link,\n ListOptions,\n ListTasksOptions,\n Payload,\n Profile,\n Proxy,\n ProxyCountry,\n ProxyLocation,\n ProxyType,\n ScrapeOptions,\n PreviousPeriod,\n SiteMap,\n Status,\n StatusCodeBreakdown,\n TasksPage,\n TaskSummary,\n TaskType,\n Transaction,\n TransactionOperation,\n TransactionsOptions,\n TransactionsPage,\n TransactionSum,\n} from \"./models.js\";\n","/**\n * Errors this package throws.\n *\n * Two families, as in the Go and Python SDKs:\n *\n * - {@link APIError} and its subclasses — the API refused the request.\n * - {@link TaskFailed} / {@link Blocked} — the API accepted the task but the\n * page could not be scraped. Failed tasks are refunded.\n */\n\nimport type { Result } from \"./models.js\";\n\n/** Base class for every error this package throws. */\nexport class DataFuelError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/** No key was passed and DATAFUEL_API_KEY is empty. Thrown before any request. */\nexport class NoApiKey extends DataFuelError {}\n\n/** The request never got an answer: DNS, connection, abort, read timeout. */\nexport class TransportError extends DataFuelError {}\n\n/** The `code` of an API error. The API may add codes; unknown ones pass through. */\nexport type ErrorCode =\n | \"UNAUTHORIZED\"\n | \"INVALID_API_KEY\"\n | \"FORBIDDEN\"\n | \"INSUFFICIENT_CREDITS\"\n | \"RATE_LIMIT_EXCEEDED\"\n | \"CONCURRENCY_LIMIT_REACHED\"\n | \"INVALID_REQUEST_BODY\"\n | \"INVALID_ATTRIBUTES\"\n | \"MISSING_TARGET\"\n | \"UNSUPPORTED_TASK_TYPE\"\n | \"JOB_REQUIRES_MULTIPLE_TARGETS\"\n | \"INVALID_IDEMPOTENCY_KEY\"\n | \"IDEMPOTENCY_KEY_REUSED\"\n | \"INVALID_TASK_ID\"\n | \"INVALID_JOB_ID\"\n | \"TASK_NOT_FOUND\"\n | \"JOB_NOT_FOUND\"\n | \"CRAWL_NOT_FOUND\"\n | \"JOB_NOT_CANCELLABLE\"\n | \"INVALID_CRAWL_PATTERN\"\n | \"CRAWL_UNSUPPORTED_OPTION\"\n | \"INVALID_CURSOR\"\n | \"INVALID_QUERY_PARAM\"\n | \"INVALID_PROXY_TYPE\"\n | \"INVALID_COUNTRY\"\n | \"INVALID_DATE_FORMAT\"\n | \"INVALID_DATE_RANGE\"\n | \"INVALID_INTERVAL\"\n | \"MODULE_UNAVAILABLE\"\n | \"ENGINE_UNAVAILABLE\"\n | \"API_KEY_RESET_FAILED\"\n | \"TASK_RESULT_TIMEOUT\"\n | \"INTERNAL_ERROR\"\n | (string & {});\n\n/** A non-2xx answer from the API itself. */\nexport class APIError extends DataFuelError {\n readonly status: number;\n readonly code: ErrorCode;\n /** Seconds the API asked us to wait, from Retry-After. 0 when absent. */\n readonly retryAfter: number;\n\n constructor(status: number, code: string, message: string, retryAfter = 0) {\n super(code ? `${message} (${status} ${code})` : `${message} (${status})`);\n this.status = status;\n this.code = code;\n this.retryAfter = retryAfter;\n }\n}\n\n/** 401: the API key is missing or invalid. */\nexport class Unauthorized extends APIError {}\n/** 403 FORBIDDEN: the account is inactive. */\nexport class Forbidden extends APIError {}\n/** 404: unknown id, or one that belongs to another account. */\nexport class NotFound extends APIError {}\n/** 429: the account's request rate or concurrency limit was reached. */\nexport class RateLimited extends APIError {}\n/** 402: not enough credits for this task. */\nexport class InsufficientCredits extends APIError {}\n/** 400 INVALID_ATTRIBUTES: the attributes do not match the task type. */\nexport class InvalidAttributes extends APIError {}\n/** 422: the key was already used for a different request. */\nexport class IdempotencyKeyReused extends APIError {}\n/** 409 JOB_NOT_CANCELLABLE: the job or crawl already finished. */\nexport class JobNotCancellable extends APIError {}\n/** 503: an operator switched something off, or a dependency is down. The message carries the reason. */\nexport class Unavailable extends APIError {}\n/** 503 MODULE_UNAVAILABLE: this task type is switched off. Nothing was charged. */\nexport class ModuleUnavailable extends Unavailable {}\n/** 503 ENGINE_UNAVAILABLE: this LLM engine is switched off. Nothing was charged. */\nexport class EngineUnavailable extends Unavailable {}\n\n/**\n * The task was accepted but could not be completed. Refunded.\n *\n * `result` carries the envelope: `statusCode`, `blocked`, `protection`, `error`.\n */\nexport class TaskFailed extends DataFuelError {\n readonly result: Result;\n\n constructor(result: Result) {\n const detail = result.error ?? result.payload?.error_detail ?? \"no detail\";\n super(`task failed: ${detail}`);\n this.result = result;\n }\n\n /** Anti-bot vendor recognised on the target, when there was one. */\n get protection(): string | undefined {\n return this.result.protection;\n }\n}\n\n/**\n * The target refused or challenged the request (403/429/503, anti-bot wall).\n *\n * Refunded. Retry with `jsRendering: true` or a Premium proxy.\n */\nexport class Blocked extends TaskFailed {}\n\n/**\n * A wait ran out of time. The work keeps running and billing server-side.\n *\n * `id` picks it back up (`waitCrawl`, `jobResults`, or a re-send under the same\n * idempotency key); `status` is the last one seen, when there was one.\n */\nexport class WaitTimeout extends DataFuelError {\n readonly id: string | undefined;\n readonly status: unknown;\n\n constructor(message: string, id?: string, status?: unknown) {\n super(message);\n this.id = id;\n this.status = status;\n }\n}\n\nconst BY_CODE: Record<string, new (s: number, c: string, m: string, r?: number) => APIError> = {\n MODULE_UNAVAILABLE: ModuleUnavailable,\n ENGINE_UNAVAILABLE: EngineUnavailable,\n INSUFFICIENT_CREDITS: InsufficientCredits,\n INVALID_ATTRIBUTES: InvalidAttributes,\n IDEMPOTENCY_KEY_REUSED: IdempotencyKeyReused,\n INVALID_API_KEY: Unauthorized,\n FORBIDDEN: Forbidden,\n JOB_NOT_CANCELLABLE: JobNotCancellable,\n};\n\nconst BY_STATUS: Record<number, new (s: number, c: string, m: string, r?: number) => APIError> = {\n 401: Unauthorized,\n 402: InsufficientCredits,\n 403: Forbidden,\n 404: NotFound,\n 409: JobNotCancellable,\n 422: IdempotencyKeyReused,\n 429: RateLimited,\n 503: Unavailable,\n};\n\n/** Map an error answer onto the narrowest class that fits. */\nexport function apiError(status: number, body: unknown, retryAfter = 0): APIError {\n let code = \"\";\n let message = \"\";\n if (body !== null && typeof body === \"object\") {\n const record = body as Record<string, unknown>;\n code = typeof record.code === \"string\" ? record.code : \"\";\n message = typeof record.message === \"string\" ? record.message : \"\";\n } else if (typeof body === \"string\" && body.length > 0 && body.length <= 300) {\n message = body;\n }\n const Cls = BY_CODE[code] ?? BY_STATUS[status] ?? APIError;\n return new Cls(status, code, message || `HTTP ${status}`, retryAfter);\n}\n","/**\n * Request building and answer classification. Pure functions, no I/O.\n *\n * Every decision lives here — which envelope a module needs, where the sticky\n * session keys go, how `ai` expands, whether an answer is retryable — so the\n * client only moves bytes.\n */\n\nimport { APIError, Unavailable } from \"./errors.js\";\nimport type {\n AI,\n AnalyticsOptions,\n Engine,\n ListOptions,\n ListTasksOptions,\n Proxy,\n ScrapeOptions,\n TransactionsOptions,\n} from \"./models.js\";\n\nexport const DEFAULT_BASE_URL = \"https://scraping-api.datafuel.ai/api/v1\";\n\n/** Kept in step with package.json by a test; see test/hardening.test.ts. */\nexport const VERSION = \"0.3.0\";\n\n/** How long a synchronous call waits for a result before giving up. */\nexport const DEFAULT_TIMEOUT_MS = 180_000;\n/** Gap between two attempts at a task the API is still processing. */\nexport const STILL_PROCESSING_DELAY_MS = 2_000;\nexport const STILL_PROCESSING = \"TASK_STILL_PROCESSING\";\n/** The API rejects a longer key with 400; catching it here saves the round trip. */\nexport const MAX_IDEMPOTENCY_KEY = 255;\n\n/** One HTTP call, ready for the client to send. */\nexport class Request {\n constructor(\n readonly method: string,\n readonly path: string,\n readonly params?: Record<string, string>,\n readonly body?: Record<string, unknown>,\n readonly idempotencyKey?: string,\n readonly auth: boolean = true,\n ) {}\n\n /** GETs are safe by nature, writes because they carry an idempotency key. */\n get retryable(): boolean {\n return this.method === \"GET\" || this.idempotencyKey !== undefined;\n }\n\n /**\n * Method and path only. The body can hold an LLM key or a cookie header, so\n * neither logging nor JSON.stringify may spill it.\n */\n toString(): string {\n return `<Request ${this.method} ${this.path}>`;\n }\n\n toJSON(): string {\n return this.toString();\n }\n\n [Symbol.for(\"nodejs.util.inspect.custom\")](): string {\n return this.toString();\n }\n}\n\n/**\n * Escape an id before it becomes part of a URL path.\n *\n * An id is caller data. Unescaped, a stray `/` or `?` in one would move the\n * request to a different endpoint.\n */\nexport function pathSegment(value: string): string {\n return encodeURIComponent(value);\n}\n\nexport function newIdempotencyKey(): string {\n return crypto.randomUUID();\n}\n\n/** The headers every call carries. The idempotency key sits beside the API key. */\nexport function headers(\n apiKey: string,\n userAgent: string,\n request: Request,\n): Record<string, string> {\n const out: Record<string, string> = {\n Accept: \"application/json\",\n \"User-Agent\": userAgent,\n };\n if (apiKey) out[\"X-API-Key\"] = apiKey;\n if (request.body !== undefined) out[\"Content-Type\"] = \"application/json\";\n if (request.idempotencyKey !== undefined) out[\"Idempotency-Key\"] = request.idempotencyKey;\n return out;\n}\n\n/** The API takes multi-field extractors as a JSON object string. */\nfunction selector(value: string | Record<string, string>): string {\n return typeof value === \"string\" ? value : JSON.stringify(value);\n}\n\nfunction aiAttributes(ai: AI): Record<string, unknown> {\n const out: Record<string, unknown> = { result_use_ai: true };\n if (ai.prompt) out.result_ai_prompt = ai.prompt;\n if (ai.format !== undefined) out.result_ai_format = ai.format;\n if (ai.provider) out.ai_provider = ai.provider;\n if (ai.model) out.ai_model = ai.model;\n if (ai.apiKey) out.ai_api_key = ai.apiKey;\n return out;\n}\n\n/**\n * Catch a half-filled AI key before it costs a request. The API does not check\n * these, so a missing one would be spent on a scrape whose AI step then fails.\n */\nexport function validateAI(ai: AI): void {\n const given = {\n provider: ai.provider !== undefined,\n model: ai.model !== undefined,\n apiKey: ai.apiKey !== undefined,\n };\n const present = Object.values(given).filter(Boolean).length;\n if (present > 0 && present < 3) {\n const missing = Object.entries(given)\n .filter(([, ok]) => !ok)\n .map(([name]) => name)\n .join(\", \");\n throw new TypeError(`ai needs provider, model and apiKey together; missing: ${missing}`);\n }\n}\n\n/**\n * Flatten the page options into the API's `attributes` object.\n *\n * Unset options are left out of the body entirely, never sent as null.\n */\nexport function scrapeAttributes(options: ScrapeOptions = {}): Record<string, unknown> {\n const attrs: Record<string, unknown> = {};\n if (options.format) attrs.result_format = options.format;\n if (options.jsRendering) attrs.js_rendering = true;\n if (options.waitFor) attrs.wait_for_selector = options.waitFor;\n if (options.waitForTimeoutMs) attrs.wait_for_selector_timeout_ms = options.waitForTimeoutMs;\n if (options.jsInstructions) attrs.js_instructions = options.jsInstructions;\n if (options.blockResource) attrs.block_resource = options.blockResource;\n if (options.mainContentOnly) attrs.main_content_only = true;\n if (options.includeImages !== undefined) attrs.include_images = options.includeImages;\n if (options.extract) attrs.extract_selector = selector(options.extract);\n if (options.extractRegex) attrs.extract_regex = selector(options.extractRegex);\n if (options.template) attrs.result_template = options.template;\n if (options.method) attrs.method = options.method;\n if (options.body) attrs.body = options.body;\n if (options.contentType) attrs.content_type = options.contentType;\n if (options.headers) attrs.headers = options.headers;\n if (options.headerOrder) attrs.header_order = options.headerOrder;\n if (options.cookies) attrs.cookie_string = options.cookies;\n if (options.userAgent) attrs.user_agent = options.userAgent;\n if (options.userAgentType) attrs.user_agent_type = options.userAgentType;\n if (options.ai) {\n validateAI(options.ai);\n Object.assign(attrs, aiAttributes(options.ai));\n }\n return attrs;\n}\n\n/** The proxy fields that travel in the request envelope. */\nexport function proxyEnvelope(proxy: Proxy | undefined): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (!proxy) return out;\n if (proxy.type) out.proxy_type = proxy.type;\n if (proxy.country) out.proxy_country = proxy.country;\n if (proxy.city) out.proxy_city = proxy.city;\n if (proxy.state) out.proxy_state = proxy.state;\n if (proxy.asn) out.proxy_asn = proxy.asn;\n return out;\n}\n\n/** The sticky-session fields, which travel in `attributes`. */\nexport function proxySession(proxy: Proxy | undefined): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (!proxy) return out;\n if (proxy.sessionId) out.proxy_session_id = proxy.sessionId;\n if (proxy.ttl) out.proxy_ttl = proxy.ttl;\n return out;\n}\n\n/** The body every write shares. */\nexport function envelope(\n taskType: string,\n attributes: Record<string, unknown>,\n extra: { proxy?: Proxy | undefined; multithreaded?: boolean | undefined } = {},\n): Record<string, unknown> {\n const body: Record<string, unknown> = { type: taskType, ...proxyEnvelope(extra.proxy) };\n if (extra.multithreaded !== undefined) body.multithreaded = extra.multithreaded;\n body.attributes = attributes;\n return body;\n}\n\nexport function key(explicit: string | undefined): string {\n if (explicit !== undefined && explicit.length > MAX_IDEMPOTENCY_KEY) {\n throw new TypeError(`idempotencyKey is longer than ${MAX_IDEMPOTENCY_KEY} characters`);\n }\n return explicit ?? newIdempotencyKey();\n}\n\nexport function buildScrape(\n url: string,\n options: ScrapeOptions,\n proxy: Proxy | undefined,\n idempotencyKey: string,\n): Request {\n const attrs = { ...scrapeAttributes(options), url, ...proxySession(proxy) };\n return new Request(\n \"POST\",\n \"/task\",\n undefined,\n envelope(\"unlocker\", attrs, { proxy }),\n idempotencyKey,\n );\n}\n\nexport function buildJob(\n urls: string[],\n options: ScrapeOptions,\n proxy: Proxy | undefined,\n sequential: boolean,\n idempotencyKey: string,\n): Request {\n const attrs = { ...scrapeAttributes(options), urls: [...urls], ...proxySession(proxy) };\n return new Request(\n \"POST\",\n \"/job\",\n undefined,\n envelope(\"unlocker\", attrs, { proxy, multithreaded: !sequential }),\n idempotencyKey,\n );\n}\n\n/** Options for the llm_scraping module, which reads its proxy country here. */\nexport interface AskOptions {\n engine: Engine | string;\n websearch?: boolean;\n followUp?: string;\n country?: string;\n location?: string;\n format?: string;\n}\n\nexport function askAttributes(\n promptField: string,\n prompt: string | string[],\n options: AskOptions,\n): Record<string, unknown> {\n const attrs: Record<string, unknown> = { [promptField]: prompt, engine: options.engine };\n if (options.websearch) attrs.websearch = true;\n if (options.followUp) attrs.follow_up_prompt = options.followUp;\n if (options.country) attrs.proxy_country = options.country;\n if (options.location) attrs.location = options.location;\n if (options.format) attrs.result_format = options.format;\n return attrs;\n}\n\nexport function buildAsk(prompt: string, options: AskOptions, idempotencyKey: string): Request {\n const attrs = askAttributes(\"prompt\", prompt, options);\n return new Request(\"POST\", \"/task\", undefined, envelope(\"llm_scraping\", attrs), idempotencyKey);\n}\n\nexport function buildAskJob(\n prompts: string[],\n options: AskOptions,\n sequential: boolean,\n idempotencyKey: string,\n): Request {\n const attrs = askAttributes(\"prompts\", [...prompts], options);\n return new Request(\n \"POST\",\n \"/job\",\n undefined,\n envelope(\"llm_scraping\", attrs, { multithreaded: !sequential }),\n idempotencyKey,\n );\n}\n\n/** Options for `map`. */\nexport interface MapOptions {\n /** Keep only links whose URL or title contains this. */\n search?: string;\n /** Map only this sitemap, from a previous `SiteMap.sitemaps`. */\n sitemap?: string;\n /** Default 5000, capped at 10000. */\n limit?: number;\n includeSubdomains?: boolean;\n ignoreSitemap?: boolean;\n sitemapOnly?: boolean;\n userAgent?: string;\n userAgentType?: string;\n}\n\nexport function buildMap(\n url: string,\n options: MapOptions,\n proxy: Proxy | undefined,\n idempotencyKey: string,\n): Request {\n const attrs: Record<string, unknown> = { url };\n if (options.search) attrs.search = options.search;\n if (options.sitemap) attrs.sitemap = options.sitemap;\n if (options.limit) attrs.limit = options.limit;\n if (options.includeSubdomains) attrs.include_subdomains = true;\n if (options.ignoreSitemap) attrs.ignore_sitemap = true;\n if (options.sitemapOnly) attrs.sitemap_only = true;\n if (options.userAgent) attrs.user_agent = options.userAgent;\n if (options.userAgentType) attrs.user_agent_type = options.userAgentType;\n Object.assign(attrs, proxySession(proxy));\n return new Request(\"POST\", \"/map\", undefined, envelope(\"map\", attrs, { proxy }), idempotencyKey);\n}\n\n/** Options for `crawl`, on top of the page options applied to every page. */\nexport interface CrawlOptions extends ScrapeOptions {\n /** Default 100, max 10000. The hard budget of the crawl. */\n maxPages?: number;\n /** Default 3, max 10. The start URL is depth 0. */\n maxDepth?: number;\n /** RE2 on path?query; when set only matches are followed. */\n includePaths?: string[];\n /** RE2 on path?query; exclude wins. */\n excludePaths?: string[];\n includeSubdomains?: boolean;\n allowBackwardLinks?: boolean;\n /** Pages in flight, default 5. */\n concurrency?: number;\n}\n\nexport function buildCrawl(\n url: string,\n options: CrawlOptions,\n proxy: Proxy | undefined,\n idempotencyKey: string,\n): Request {\n if (options.ai) {\n throw new TypeError(\"crawl does not support ai: the API rejects result_use_ai on crawls\");\n }\n const attrs: Record<string, unknown> = { ...scrapeAttributes(options), url };\n if (options.maxPages) attrs.max_pages = options.maxPages;\n if (options.maxDepth) attrs.max_depth = options.maxDepth;\n if (options.concurrency) attrs.concurrency = options.concurrency;\n if (options.includePaths?.length) attrs.include_paths = [...options.includePaths];\n if (options.excludePaths?.length) attrs.exclude_paths = [...options.excludePaths];\n if (options.includeSubdomains) attrs.include_subdomains = true;\n if (options.allowBackwardLinks) attrs.allow_backward_links = true;\n Object.assign(attrs, proxySession(proxy));\n return new Request(\n \"POST\",\n \"/crawl\",\n undefined,\n envelope(\"crawl\", attrs, { proxy }),\n idempotencyKey,\n );\n}\n\n/** Options for `search`, the Google SERP module. Proxy type is not used. */\nexport interface SearchOptions {\n /** Google `gl`, e.g. \"us\". */\n country?: string;\n /** Google `hl`, e.g. \"en\". */\n language?: string;\n /** Canonical location name. Give at most one of location, uule, lat/lon. */\n location?: string;\n /** 1-based, default 1. */\n page?: number;\n /** e.g. \"google.de\". */\n googleDomain?: string;\n uule?: string;\n lat?: number;\n lon?: number;\n /** Metres around lat/lon or location, max 1000. */\n radius?: number;\n cr?: string;\n lr?: string;\n tbs?: string;\n safe?: \"active\" | \"off\";\n nfpr?: boolean;\n filter?: boolean;\n uds?: string;\n kgmid?: string;\n si?: string;\n ludocid?: string;\n lsig?: string;\n ibp?: string;\n /** Exit country of the request. */\n proxyCountry?: string;\n /** Default json. */\n format?: \"json\" | \"html\" | \"markdown\";\n}\n\nexport function searchAttributes(\n queryField: string,\n query: string | string[],\n options: SearchOptions,\n): Record<string, unknown> {\n const attrs: Record<string, unknown> = { [queryField]: query };\n const strings: [keyof SearchOptions, string][] = [\n [\"country\", \"country\"],\n [\"language\", \"language\"],\n [\"location\", \"location\"],\n [\"googleDomain\", \"google_domain\"],\n [\"uule\", \"uule\"],\n [\"cr\", \"cr\"],\n [\"lr\", \"lr\"],\n [\"tbs\", \"tbs\"],\n [\"safe\", \"safe\"],\n [\"uds\", \"uds\"],\n [\"kgmid\", \"kgmid\"],\n [\"si\", \"si\"],\n [\"ludocid\", \"ludocid\"],\n [\"lsig\", \"lsig\"],\n [\"ibp\", \"ibp\"],\n [\"proxyCountry\", \"proxy_country\"],\n [\"format\", \"result_format\"],\n ];\n for (const [option, attribute] of strings) {\n if (options[option]) attrs[attribute] = options[option];\n }\n if (options.page) attrs.page = options.page;\n if (options.radius) attrs.radius = options.radius;\n if (options.lat !== undefined) attrs.lat = options.lat;\n if (options.lon !== undefined) attrs.lon = options.lon;\n if (options.nfpr !== undefined) attrs.nfpr = options.nfpr;\n if (options.filter !== undefined) attrs.filter = options.filter;\n return attrs;\n}\n\nexport function buildSearch(\n query: string,\n options: SearchOptions,\n idempotencyKey: string,\n): Request {\n const attrs = searchAttributes(\"query\", query, options);\n return new Request(\"POST\", \"/task\", undefined, envelope(\"serp\", attrs), idempotencyKey);\n}\n\nexport function buildSearchJob(\n queries: string[],\n options: SearchOptions,\n sequential: boolean,\n idempotencyKey: string,\n): Request {\n const attrs = searchAttributes(\"queries\", [...queries], options);\n return new Request(\n \"POST\",\n \"/job\",\n undefined,\n envelope(\"serp\", attrs, { multithreaded: !sequential }),\n idempotencyKey,\n );\n}\n\nexport function crawlResultsRequest(crawlId: string, cursor?: string, limit?: number): Request {\n const params: Record<string, string> = {};\n if (cursor) params.cursor = cursor;\n if (limit) params.limit = String(limit);\n return new Request(\n \"GET\",\n `/crawl/${pathSegment(crawlId)}/results`,\n Object.keys(params).length > 0 ? params : undefined,\n );\n}\n\n/** A Date as its UTC day, which is what the API's date filters take. */\nexport function day(value: string | Date): string {\n return typeof value === \"string\" ? value : value.toISOString().slice(0, 10);\n}\n\nfunction query(\n entries: [string, string | number | Date | undefined][],\n): Record<string, string> | undefined {\n const params: Record<string, string> = {};\n for (const [name, value] of entries) {\n if (value === undefined || value === \"\") continue;\n params[name] = value instanceof Date ? day(value) : String(value);\n }\n return Object.keys(params).length > 0 ? params : undefined;\n}\n\nfunction listRequest(path: string, options: ListOptions, jobId?: string): Request {\n const params = query([\n [\"status\", options.status],\n [\"type\", options.type],\n [\"job_id\", jobId],\n [\"start_date\", options.startDate],\n [\"end_date\", options.endDate],\n [\"limit\", options.limit],\n [\"cursor\", options.cursor],\n ]);\n return new Request(\"GET\", path, params);\n}\n\nexport function listJobsRequest(options: ListOptions): Request {\n return listRequest(\"/job\", options);\n}\n\nexport function listTasksRequest(options: ListTasksOptions): Request {\n return listRequest(\"/task\", options, options.jobId);\n}\n\nexport function transactionsRequest(options: TransactionsOptions): Request {\n const params = query([\n [\"operation\", options.operation],\n [\"start_date\", options.startDate],\n [\"end_date\", options.endDate],\n [\"page\", options.page],\n [\"limit\", options.limit],\n ]);\n return new Request(\"GET\", \"/users/@me/transactions\", params);\n}\n\nexport function analyticsRequest(options: AnalyticsOptions): Request {\n const params = query([\n [\"start_date\", options.startDate],\n [\"end_date\", options.endDate],\n [\"interval\", options.interval],\n [\"module\", options.module],\n ]);\n return new Request(\"GET\", \"/task/analytics/dashboard\", params);\n}\n\n/** Whether the API answered \"the task is still running\" instead of a result. */\nexport function stillProcessing(body: unknown): boolean {\n return (\n body !== null &&\n typeof body === \"object\" &&\n (body as Record<string, unknown>).code === STILL_PROCESSING\n );\n}\n\n/** Go's retry policy: transport errors, 429, 502, 503, 504 — nothing else. */\nexport function shouldRetry(error: unknown): boolean {\n if (error instanceof Unavailable) {\n // A deliberate switch-off is a 503 too, but retrying it only adds load: it\n // stays off until an operator turns it back on.\n if (error.code === \"MODULE_UNAVAILABLE\" || error.code === \"ENGINE_UNAVAILABLE\") return false;\n }\n if (error instanceof APIError) return [429, 502, 503, 504].includes(error.status);\n return true; // transport error\n}\n\n/** 500ms, 1s, 2s, 4s, then 8s flat — halved and randomized. Retry-After wins. */\nexport function backoff(attempt: number, retryAfterSeconds = 0): number {\n if (retryAfterSeconds > 0) return Math.min(retryAfterSeconds * 1000, 30_000);\n const base = 500 * 2 ** Math.min(attempt, 4);\n return base / 2 + Math.random() * (base / 2);\n}\n\n/** Gap before re-sending a task the API is still processing. */\nexport function pollDelay(attempt: number): number {\n return Math.max(STILL_PROCESSING_DELAY_MS, backoff(attempt));\n}\n","/** Request options and response shapes. */\n\nimport { Blocked, DataFuelError, TaskFailed } from \"./errors.js\";\n\n/** State of a task, job or crawl. Unknown states are treated as not final. */\nexport type Status =\n | \"created\"\n | \"pending\"\n | \"processing\"\n | \"completed\"\n | \"completed_with_errors\"\n | \"failed\"\n | \"cancelled\";\n\nconst TERMINAL = new Set([\"completed\", \"completed_with_errors\", \"failed\", \"cancelled\"]);\n\n/** Whether a state is final. */\nexport function isDone(status: string | undefined): boolean {\n return status !== undefined && TERMINAL.has(status);\n}\n\n/**\n * Shape of the scraped content.\n *\n * `html` raw page (API default), `markdown` cleaned text (best for LLMs),\n * `json` schema.org / JSON-LD, `png` / `jpeg` full-page screenshot.\n */\nexport type Format = \"html\" | \"markdown\" | \"json\" | \"png\" | \"jpeg\";\n\n/** AI assistant `ask` can query. Engines can be switched off at runtime. */\nexport type Engine = \"openai\" | \"gemini\" | \"google_ai_mode\" | \"perplexity\" | \"copilot\";\n\n/** Proxy plan. Matched case-insensitively; deployments may define others. */\nexport type ProxyType = \"Basic\" | \"Premium\" | (string & {});\n\n/** The exit the request leaves from. Every field optional: the account default. */\nexport interface Proxy {\n type?: ProxyType;\n /** ISO 3166-1 alpha-2, e.g. \"US\". */\n country?: string;\n city?: string;\n state?: string;\n asn?: string;\n /**\n * Sticky session: the same exit across requests, `ttl` in seconds. Read by\n * `scrape`, `map`, URL jobs and crawls, and sent in attributes rather than\n * the envelope.\n */\n sessionId?: string;\n ttl?: number;\n}\n\n/**\n * Post-process the page with an LLM, using your own key.\n *\n * Not supported on crawls: the API rejects `result_use_ai` there.\n */\nexport interface AI {\n /** What to extract. */\n prompt?: string;\n /** Example JSON object the output must follow. */\n format?: unknown;\n provider?: \"openai\" | \"anthropic\" | \"google\";\n model?: string;\n apiKey?: string;\n}\n\n/** Page options, shared by `scrape`, jobs and crawls. */\nexport interface ScrapeOptions {\n format?: Format;\n /**\n * Render the page in a real browser: slower, five times the credits on a\n * Basic proxy. Leave it off unless the page comes back empty without it.\n */\n jsRendering?: boolean;\n waitFor?: string;\n waitForTimeoutMs?: number;\n /** An object keyed by action, e.g. `{ click: \"#more\" }`. `df.jsInstructions()` lists them. */\n jsInstructions?: unknown;\n blockResource?: string;\n /** Markdown only: always render just the `<main>` / `<article>` container. */\n mainContentOnly?: boolean;\n /** Markdown only: `false` drops images and saves tokens. */\n includeImages?: boolean;\n /**\n * Extract only matching elements: field name to CSS selector. Append\n * ` @attr` to read an attribute, e.g. `{ links: \"a @href\" }`.\n */\n extract?: string | Record<string, string>;\n /** The same with RE2 patterns on the raw HTML. */\n extractRegex?: string | Record<string, string>;\n /**\n * Built-in extractors, comma separated: images, links, headings,\n * phone_numbers, emails, meta_tags, tables, schema_org, all.\n */\n template?: string;\n method?: string;\n body?: string;\n contentType?: string;\n headers?: Record<string, string>;\n headerOrder?: string[];\n cookies?: string;\n userAgent?: string;\n /** chrome, firefox, safari, edge. */\n userAgentType?: string;\n ai?: AI;\n}\n\n/** Options every call accepts. */\nexport interface CallOptions {\n proxy?: Proxy;\n /** Generated per request when omitted. Max 255 characters. */\n idempotencyKey?: string;\n /** Overrides the client's timeout for this call. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/** The raw `result` object of a task. */\nexport interface Payload {\n data?: unknown;\n status?: Status;\n error_detail?: string;\n status_code?: number;\n}\n\n/**\n * One scraped target with its metadata.\n *\n * Read the metadata before the content: a 200 can be an error page,\n * `redirected` means `finalUrl` is not what you asked for, and a 404 still\n * completes and bills.\n */\nexport class Result {\n readonly id: string | undefined;\n readonly status: Status | undefined;\n /** HTTP status the target answered. */\n readonly statusCode: number | undefined;\n readonly finalUrl: string | undefined;\n readonly redirected: boolean;\n /** Charged for this task, 0 when it failed. */\n readonly creditsUsed: number;\n readonly durationMs: number | undefined;\n readonly blocked: boolean;\n /** Anti-bot vendor recognised when blocked. */\n readonly protection: string | undefined;\n readonly error: string | undefined;\n /** The raw `result` object. Prefer `text`, `data` and `image`. */\n readonly payload: Payload | undefined;\n /** Everything the API sent, including fields this SDK does not know yet. */\n readonly raw: Record<string, unknown>;\n\n constructor(raw: Record<string, unknown>) {\n this.raw = raw;\n this.id = str(raw.id);\n this.status = str(raw.status) as Status | undefined;\n this.statusCode = num(raw.status_code);\n this.finalUrl = str(raw.final_url);\n this.redirected = raw.redirected === true;\n this.creditsUsed = num(raw.credits_used) ?? 0;\n this.durationMs = num(raw.duration_ms);\n this.blocked = raw.blocked === true;\n this.protection = str(raw.protection);\n this.error = str(raw.error);\n this.payload =\n raw.result !== null && typeof raw.result === \"object\" ? (raw.result as Payload) : undefined;\n }\n\n /** Effective state: the envelope's, else the payload's, else inferred. */\n get state(): string {\n if (this.status) return this.status;\n if (this.payload?.status) return this.payload.status;\n if (this.payload?.data !== undefined && this.payload.data !== null) return \"completed\";\n return \"pending\";\n }\n\n /** Whether the task has not finished yet (job and crawl results list stubs). */\n get pending(): boolean {\n return !isDone(this.state);\n }\n\n /** Whether the task completed and the target was not blocked. */\n get ok(): boolean {\n return this.state === \"completed\" && !this.blocked;\n }\n\n /** The structured output: format json, extract, template, AI. */\n get data(): unknown {\n return this.payload?.data;\n }\n\n /** Content of an html or markdown result; the raw JSON for structured ones. */\n get text(): string {\n const value = this.data;\n if (value === undefined || value === null) return \"\";\n return typeof value === \"string\" ? value : JSON.stringify(value);\n }\n\n /** Bytes of a png or jpeg screenshot. Throws when the result is not one. */\n get image(): Uint8Array {\n try {\n return Uint8Array.from(atob(this.text), (char) => char.charCodeAt(0));\n } catch (cause) {\n throw new DataFuelError(\"result is not a png or jpeg screenshot\", { cause });\n }\n }\n\n /** `data`, or throw when the task carried none. */\n requireData(): unknown {\n if (this.data === undefined || this.data === null) {\n throw new DataFuelError(`result has no data (status ${this.state})`);\n }\n return this.data;\n }\n\n /** Throw TaskFailed, or Blocked, when this task failed. Refunded either way. */\n raiseForStatus(): void {\n if (this.state === \"failed\") {\n throw this.blocked ? new Blocked(this) : new TaskFailed(this);\n }\n }\n}\n\n/** One crawled page: where it was found, plus the scrape result. */\nexport class CrawlPage extends Result {\n readonly url: string;\n readonly depth: number;\n readonly taskId: string | undefined;\n\n constructor(raw: Record<string, unknown>) {\n super(raw);\n this.url = str(raw.url) ?? \"\";\n this.depth = num(raw.depth) ?? 0;\n this.taskId = str(raw.task_id);\n }\n}\n\n/** One discovered URL. */\nexport interface Link {\n url: string;\n /** \"sitemap\" or \"page\". */\n source: string;\n /** Page links only. */\n title?: string;\n /** Sitemap links only. */\n lastmod?: string;\n}\n\n/**\n * What `map` found.\n *\n * `reason` says why `links` is empty: page_blocked, page_error,\n * page_unreachable, no_links_on_page (try scrape with jsRendering), no_sitemap,\n * sitemap_no_entries, search_no_match.\n */\nexport interface SiteMap {\n url: string;\n links: Link[];\n total: number;\n /** `limit` or the time budget cut the list. */\n truncated: boolean;\n sitemaps: string[];\n page_status_code: number;\n reason?: string;\n credits: number;\n /** Envelope of the underlying task. */\n task: Result;\n}\n\n/** Progress of a crawl. */\nexport interface CrawlStatus {\n status: Status;\n /** Empty while the crawl still grows: max_pages, max_depth_exhausted, insufficient_credits, cancelled. */\n stop_reason?: string;\n pages: { discovered: number; enqueued: number; done: number; failed: number; skipped: number };\n depth_reached: number;\n /**\n * Charged at queue time; refunds of failed pages are not subtracted. Sum\n * `creditsUsed` over the pages for the net figure.\n */\n total_cost: number;\n /** Whether the crawl reached a final state. */\n done: boolean;\n /** RFC 3339. */\n created_at?: string;\n updated_at?: string;\n}\n\n/** One page of crawl results. */\nexport interface CrawlResultsPage {\n pages: CrawlPage[];\n /** Absent on the last page. */\n nextCursor?: string;\n}\n\n/** A finished crawl: why it stopped and what it found. */\nexport interface CrawlResult {\n id: string;\n status: CrawlStatus;\n pages: CrawlPage[];\n}\n\n/** Progress of a job. */\nexport interface JobStatus {\n status: Status;\n tasks_count: number;\n tasks_done: number;\n tasks_remaining: number;\n total_cost: number;\n done: boolean;\n}\n\n/** A cancelled job or crawl: its final progress and what was refunded. */\nexport interface CancelResult extends JobStatus {\n refunded_tasks: number;\n refunded_credits: number;\n}\n\n/** Every task of a job. A job completes even when some of its tasks failed. */\nexport interface JobResults {\n id: string;\n tasks_count: number;\n tasks_failed: number;\n tasks_complete: number;\n tasks: Result[];\n}\n\n/** A task type, as the list and analytics filters take it. */\nexport type TaskType = \"unlocker\" | \"llm_scraping\" | \"serp\" | \"map\" | \"crawl\" | (string & {});\n\n/** Filters shared by {@link DataFuel.listJobs} and {@link DataFuel.listTasks}. */\nexport interface ListOptions {\n status?: Status;\n type?: TaskType;\n /** Created on or after this day (UTC). A Date is sent as its UTC day. */\n startDate?: string | Date;\n /** Created on or before this day (UTC, inclusive). */\n endDate?: string | Date;\n /** Items per page. API default 50, max 200. */\n limit?: number;\n /** `nextCursor` of the previous page. */\n cursor?: string;\n}\n\n/** {@link ListOptions} plus the job or crawl the tasks belong to. */\nexport interface ListTasksOptions extends ListOptions {\n jobId?: string;\n}\n\n/** A job or crawl in a list, with the same counters as {@link JobStatus}. */\nexport interface JobSummary extends JobStatus {\n id: string;\n /** `crawl` for a crawl, otherwise the task type of the batch. */\n type: TaskType;\n /** RFC 3339. */\n created_at: string;\n updated_at: string;\n}\n\n/** One page of jobs, newest first. */\nexport interface JobsPage {\n jobs: JobSummary[];\n /** Absent on the last page. */\n nextCursor?: string;\n}\n\n/** A task in a list. It has no result: fetch that with {@link DataFuel.getTask}. */\nexport interface TaskSummary {\n id: string;\n /** `null` for a task created on its own rather than by a job or crawl. */\n job_id: string | null;\n type: TaskType;\n status: Status;\n /** Absent for `llm_scraping` and `serp`. */\n url?: string;\n /** Charged when queued; a failed task is refunded. */\n credit_cost: number;\n /** RFC 3339. */\n created_at: string;\n processed_at?: string;\n failed_at?: string;\n}\n\n/** One page of tasks, newest first. */\nexport interface TasksPage {\n tasks: TaskSummary[];\n /** Absent on the last page. */\n nextCursor?: string;\n}\n\n/** What moved credits on the account. */\nexport type TransactionOperation =\n | \"plan_assignment\"\n | \"purchase\"\n | \"usage\"\n | \"refund\"\n | \"topup\"\n | \"expiry\"\n | \"adjustment\"\n | (string & {});\n\n/** Filters and paging for {@link DataFuel.transactions}. */\nexport interface TransactionsOptions {\n operation?: TransactionOperation;\n startDate?: string | Date;\n endDate?: string | Date;\n /** 1-based. API default 1. */\n page?: number;\n /** API default 10, max 200. */\n limit?: number;\n}\n\n/** One credit movement. `amount` is negative for usage and expiry. */\nexport interface Transaction {\n id: number;\n amount: number;\n /** The part of `amount` that moved plan credits, same sign; the rest moved pay-as-you-go credits. */\n plan_amount?: number;\n operation: TransactionOperation;\n /** What `reference_id` points to, e.g. `task_id` or `job_id`. */\n reference_type: string;\n reference_id: string;\n /** The balance right after this movement. */\n balance_after?: number;\n /** RFC 3339. */\n created_at: string;\n}\n\n/** Total of one operation over the whole filtered range, not just the page. */\nexport interface TransactionSum {\n operation: TransactionOperation;\n total: number;\n count: number;\n}\n\n/** One page of credit movements, newest first. */\nexport interface TransactionsPage {\n transactions: Transaction[];\n /** Movements matching the filters across all pages. */\n total_count: number;\n sums: TransactionSum[];\n}\n\n/** Range and grouping for {@link DataFuel.analytics}. */\nexport interface AnalyticsOptions {\n /** API default 30 days ago. The range may span at most 365 days. */\n startDate?: string | Date;\n /** Inclusive. API default today. */\n endDate?: string | Date;\n /** Time series bucket. API default `daily`. */\n interval?: \"hourly\" | \"daily\" | \"weekly\" | \"monthly\";\n /** Restrict to one task type. */\n module?: TaskType;\n}\n\n/** Task counts and net credits of one slice. Failed tasks are refunded and count 0 credits. */\nexport interface AnalyticsCounts {\n total: number;\n completed: number;\n failed: number;\n credits_used: number;\n}\n\n/** Tasks by the HTTP status the target answered. `status_code` 0 means no answer (timeout, DNS). */\nexport interface StatusCodeBreakdown {\n status_code: number;\n count: number;\n completed: number;\n failed: number;\n credits_used: number;\n avg_credits_per_request: number;\n}\n\n/** The same figures for the equally long period before, and the change in percent. */\nexport interface PreviousPeriod {\n credits_used: number;\n fulfilled_requests: number;\n failed_requests: number;\n failed_percentage: number;\n efficiency_score: number;\n credits_used_change: number;\n fulfilled_requests_change: number;\n failed_requests_change: number;\n efficiency_score_change: number;\n}\n\n/** Usage over a date range. Percentages are 0-100. */\nexport interface Analytics {\n summary: {\n total_tasks: number;\n credits_used: number;\n fulfilled_requests: number;\n failed_requests: number;\n failed_percentage: number;\n success_rate: number;\n efficiency_score: number;\n avg_credits_per_request: number;\n avg_duration_ms: number;\n previous_period?: PreviousPeriod | null;\n };\n timeseries: (AnalyticsCounts & { period: string })[];\n by_module: (AnalyticsCounts & {\n module: string;\n success_rate: number;\n avg_credits_per_request: number;\n avg_duration_ms: number;\n status_codes: StatusCodeBreakdown[];\n })[];\n top_targets: (AnalyticsCounts & { target: string })[];\n by_status_code: StatusCodeBreakdown[];\n}\n\n/**\n * Credits by pool. Plan credits are spent first, roll over when the plan renews and\n * expire if it is not renewed. Pay-as-you-go credits come from credit packs, are spent\n * after plan credits and never expire.\n */\nexport interface BalanceSplit {\n /** Total spendable credits: `plan_balance` plus `payg_balance`. */\n balance: number;\n plan_balance: number;\n payg_balance: number;\n}\n\n/** The account behind the API key. */\nexport interface Profile {\n email: string;\n username: string;\n current_concurrency: number;\n concurrency_limit: number;\n /** Total spendable credits: `plan_credit_balance` plus `payg_credit_balance`. */\n credit_balance: number;\n /** Spent first; expire if the plan is not renewed. */\n plan_credit_balance?: number;\n /** Spent after plan credits; never expire. */\n payg_credit_balance?: number;\n monthly_credit_limit: number;\n}\n\n/** One argument of a browser action. */\nexport interface JsInstructionArg {\n name: string;\n type: string;\n values?: string[];\n required: boolean;\n}\n\n/** One browser action `jsInstructions` accepts. */\nexport interface JsInstruction {\n action: string;\n description: string;\n /** Shape of the value: scalar, array or object. */\n value: string;\n args: JsInstructionArg[];\n /** Whether it can target an element inside an iframe. */\n iframe: boolean;\n example: unknown;\n}\n\n/** A named proxy location: a city, or an ASN. */\nexport interface ProxyLocation {\n code: string;\n name: string;\n}\n\n/** A proxy country with its regions and their cities. */\nexport interface ProxyCountry {\n code: string;\n name: string;\n regions: { code: string; name: string; cities: ProxyLocation[] }[];\n}\n\n/** One task type or LLM engine, and whether it accepts new work. */\nexport interface Capability {\n name: string;\n enabled: boolean;\n /** Operator's note when switched off. */\n reason?: string;\n}\n\n/** What the API accepts right now. */\nexport class Capabilities {\n readonly modules: Capability[];\n readonly engines: Capability[];\n\n constructor(raw: Record<string, unknown>) {\n this.modules = Array.isArray(raw.modules) ? (raw.modules as Capability[]) : [];\n this.engines = Array.isArray(raw.engines) ? (raw.engines as Capability[]) : [];\n }\n\n /** Whether a task type accepts work. Unknown names report false. */\n moduleEnabled(name: string): boolean {\n return this.modules.some((item) => item.name === name && item.enabled);\n }\n\n /** Whether an LLM engine accepts work. Unknown names report false. */\n engineEnabled(name: Engine | string): boolean {\n return this.engines.some((item) => item.name === name && item.enabled);\n }\n}\n\nfunction str(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\nfunction num(value: unknown): number | undefined {\n return typeof value === \"number\" ? value : undefined;\n}\n","/** The client. It only moves bytes; `core` decides what goes on the wire. */\n\nimport * as core from \"./core.js\";\nimport type { AskOptions, CrawlOptions, MapOptions, SearchOptions } from \"./core.js\";\nimport { apiError, DataFuelError, NoApiKey, TransportError, WaitTimeout } from \"./errors.js\";\nimport type {\n Analytics,\n AnalyticsOptions,\n BalanceSplit,\n CallOptions,\n CancelResult,\n Capability,\n CrawlResult,\n CrawlResultsPage,\n CrawlStatus,\n JobResults,\n JobsPage,\n JobStatus,\n JobSummary,\n JsInstruction,\n ListOptions,\n ListTasksOptions,\n Profile,\n ProxyCountry,\n ProxyLocation,\n ScrapeOptions,\n SiteMap,\n TasksPage,\n TaskSummary,\n TransactionsOptions,\n TransactionsPage,\n} from \"./models.js\";\nimport { Capabilities, CrawlPage, isDone, Result } from \"./models.js\";\n\n/** How to build the client. */\nexport interface ClientOptions {\n /** Falls back to `process.env.DATAFUEL_API_KEY`. */\n apiKey?: string;\n baseUrl?: string;\n /** Milliseconds. `null` disables the bound; scrape blocks until the page is ready. */\n timeoutMs?: number | null;\n /** Retries after a network error or a 429/502/503/504 answer. Default 2. */\n maxRetries?: number;\n /** How often `waitJob` and `waitCrawl` poll. Default 2000ms. */\n pollIntervalMs?: number;\n /** Prefixes the SDK User-Agent with your application's. */\n userAgent?: string;\n /** Swap the fetch implementation, e.g. in tests. */\n fetch?: typeof globalThis.fetch;\n}\n\ntype Send = CallOptions & { timeoutMs?: number; signal?: AbortSignal };\n\n/**\n * Client for the DataFuel scraping API.\n *\n * ```ts\n * const df = new DataFuel(); // reads DATAFUEL_API_KEY\n * const markdown = await df.markdown(\"https://example.com\");\n * ```\n *\n * Pick the call by the shape of the work: one URL is {@link scrape}, a site's\n * URL list is {@link map}, many pages from a start URL is {@link crawl}, a list\n * of known URLs is {@link runJob}, a question for an AI engine is {@link ask}, a\n * Google search is {@link search}.\n *\n * Every write carries an `Idempotency-Key`, generated per request, so a retry\n * attaches to the task already running instead of charging twice.\n */\nexport class DataFuel {\n readonly baseUrl: string;\n readonly timeoutMs: number | null;\n readonly maxRetries: number;\n readonly pollIntervalMs: number;\n readonly userAgent: string;\n private readonly apiKey: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n\n constructor(options: ClientOptions | string = {}) {\n const opts: ClientOptions = typeof options === \"string\" ? { apiKey: options } : options;\n this.apiKey = opts.apiKey ?? envApiKey() ?? \"\";\n this.baseUrl = (opts.baseUrl ?? core.DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeoutMs = opts.timeoutMs === undefined ? core.DEFAULT_TIMEOUT_MS : opts.timeoutMs;\n this.maxRetries = Math.max(opts.maxRetries ?? 2, 0);\n // A non-positive interval would poll in a tight loop against the API.\n this.pollIntervalMs =\n opts.pollIntervalMs !== undefined && opts.pollIntervalMs > 0 ? opts.pollIntervalMs : 2_000;\n const sdk = `datafuel-js/${core.VERSION}`;\n this.userAgent = opts.userAgent ? `${opts.userAgent} ${sdk}` : sdk;\n // Bound: a detached fetch throws \"Illegal invocation\" in browsers and\n // workers, even though Node tolerates it.\n this.fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n // --- transport ---------------------------------------------------------\n\n /** Pause between attempts. Overridable so tests need not wait in real time. */\n protected sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private async send(request: core.Request, opts: Send = {}): Promise<unknown> {\n if (!this.apiKey && request.auth) {\n throw new NoApiKey(\"no API key: pass one to the client or set DATAFUEL_API_KEY\");\n }\n const url = new URL(this.baseUrl + request.path);\n for (const [name, value] of Object.entries(request.params ?? {})) {\n url.searchParams.set(name, value);\n }\n const init: RequestInit = {\n method: request.method,\n headers: core.headers(this.apiKey, this.userAgent, request),\n // Redirects stay off: a redirect to another host would carry X-API-Key\n // to it, since fetch does not strip custom headers.\n redirect: \"manual\",\n };\n if (request.body !== undefined) init.body = JSON.stringify(request.body);\n\n for (let attempt = 0; ; attempt++) {\n let error: unknown;\n try {\n const signal = this.signalFor(opts);\n // Detached on purpose: calling `this.fetchImpl(...)` would invoke it as\n // a method of the client, and a fetch bound to another receiver (or\n // none) throws \"Illegal invocation\".\n const send = this.fetchImpl;\n const response = await send(url, signal ? { ...init, signal } : init);\n return await parse(response);\n } catch (caught) {\n if (isAbort(caught)) {\n throw new TransportError(\"the request was aborted or timed out\", { cause: caught });\n }\n error =\n caught instanceof DataFuelError\n ? caught\n : new TransportError(String(caught), {\n cause: caught,\n });\n }\n const retryAfter =\n error instanceof Object && \"retryAfter\" in error ? Number(error.retryAfter) : 0;\n if (attempt >= this.maxRetries || !request.retryable || !core.shouldRetry(error)) throw error;\n await this.sleep(core.backoff(attempt, retryAfter));\n }\n }\n\n private signalFor(opts: Send): AbortSignal | undefined {\n const budget = opts.timeoutMs ?? this.timeoutMs;\n const timeout =\n budget === null || budget === undefined ? undefined : AbortSignal.timeout(budget);\n if (timeout && opts.signal) return AbortSignal.any([timeout, opts.signal]);\n return timeout ?? opts.signal;\n }\n\n /**\n * Send a task and wait for its result.\n *\n * On a 202 the API is still working: the identical request goes out again\n * under the identical idempotency key, so it attaches to the running task\n * rather than starting a second one.\n */\n private async runTask(request: core.Request, opts: Send): Promise<Result> {\n const budget = opts.timeoutMs ?? this.timeoutMs ?? core.DEFAULT_TIMEOUT_MS;\n const deadline = Date.now() + budget;\n let body: unknown;\n for (let attempt = 0; ; attempt++) {\n body = await this.send(request, opts);\n if (!core.stillProcessing(body)) break;\n const delay = core.pollDelay(attempt);\n if (Date.now() + delay >= deadline) {\n throw new WaitTimeout(\n \"the task is still processing; re-send under the same idempotency key to pick it up\",\n request.idempotencyKey,\n );\n }\n await this.sleep(delay);\n }\n const result = new Result(record(body));\n result.raiseForStatus();\n return result;\n }\n\n // --- pages -------------------------------------------------------------\n\n /**\n * Fetch one URL and wait for the result.\n *\n * Throws {@link Blocked} when the target refused the request and\n * {@link TaskFailed} otherwise; both carry `.result`.\n */\n async scrape(url: string, options: ScrapeOptions & CallOptions = {}): Promise<Result> {\n const request = core.buildScrape(url, options, options.proxy, core.key(options.idempotencyKey));\n return this.runTask(request, options);\n }\n\n /** The one-liner: the page as LLM-ready markdown, images dropped. */\n async markdown(url: string, options: ScrapeOptions & CallOptions = {}): Promise<string> {\n const result = await this.scrape(url, { ...options, format: \"markdown\", includeImages: false });\n return result.text;\n }\n\n /**\n * Return a task by id, e.g. one created by a job or a crawl.\n *\n * A task that is still running comes back with `pending` true.\n */\n async getTask(taskId: string, options: CallOptions = {}): Promise<Result> {\n const body = await this.send(\n new core.Request(\"GET\", `/task/${core.pathSegment(taskId)}`),\n options,\n );\n if (core.stillProcessing(body)) return new Result({ id: taskId, status: \"processing\" });\n const result = new Result(record(body));\n result.raiseForStatus();\n return result;\n }\n\n /** Send a prompt to an AI engine and return its answer. */\n async ask(prompt: string, options: AskOptions & CallOptions): Promise<Result> {\n const request = core.buildAsk(prompt, options, core.key(options.idempotencyKey));\n return this.runTask(request, options);\n }\n\n /** Run a Google search and return the results page, parsed to JSON by default. */\n async search(query: string, options: SearchOptions & CallOptions = {}): Promise<Result> {\n const request = core.buildSearch(query, options, core.key(options.idempotencyKey));\n return this.runTask(request, options);\n }\n\n /**\n * List the URLs of a site without scraping them.\n *\n * One credit per call on a Basic proxy, however many links come back. Use it\n * before a crawl to see how big a section is.\n */\n async map(url: string, options: MapOptions & CallOptions = {}): Promise<SiteMap> {\n const request = core.buildMap(url, options, options.proxy, core.key(options.idempotencyKey));\n const task = await this.runTask(request, options);\n const data = record(task.requireData()) as unknown as SiteMap;\n return { ...data, links: data.links ?? [], sitemaps: data.sitemaps ?? [], task };\n }\n\n // --- crawl -------------------------------------------------------------\n\n /**\n * Queue a crawl and return its id immediately.\n *\n * Follows links from the start URL and scrapes every page. Pages are charged\n * like single scrapes when they are queued; failed and blocked pages are\n * refunded. Unset limits use the API defaults: 100 pages, depth 3, 5 in flight.\n */\n async startCrawl(url: string, options: CrawlOptions & CallOptions = {}): Promise<string> {\n const request = core.buildCrawl(url, options, options.proxy, core.key(options.idempotencyKey));\n return strField(await this.send(request, options), \"job_id\");\n }\n\n /**\n * Stop a crawl. Queued pages are refunded, pages in flight finish and bill.\n * Throws {@link JobNotCancellable} when it already finished.\n */\n async cancelCrawl(crawlId: string, options: CallOptions = {}): Promise<CancelResult> {\n return cancelResult(\n await this.send(\n new core.Request(\"POST\", `/crawl/${core.pathSegment(crawlId)}/cancel`),\n options,\n ),\n );\n }\n\n /** Return the progress of a crawl. */\n async getCrawl(crawlId: string, options: CallOptions = {}): Promise<CrawlStatus> {\n const body = record(\n await this.send(new core.Request(\"GET\", `/crawl/${core.pathSegment(crawlId)}`), options),\n );\n const raw = body as unknown as Partial<CrawlStatus>;\n return {\n ...raw,\n status: raw.status as CrawlStatus[\"status\"],\n // Counters the caller reads unconditionally must exist even on a thin answer.\n pages: {\n discovered: 0,\n enqueued: 0,\n done: 0,\n failed: 0,\n skipped: 0,\n ...(raw.pages ?? {}),\n },\n depth_reached: raw.depth_reached ?? 0,\n total_cost: raw.total_cost ?? 0,\n done: isDone(raw.status),\n };\n }\n\n /** One page of results, in discovery order. `limit` unset uses the API default. */\n async crawlResults(\n crawlId: string,\n options: CallOptions & { cursor?: string; limit?: number } = {},\n ): Promise<CrawlResultsPage> {\n const body = record(\n await this.send(core.crawlResultsRequest(crawlId, options.cursor, options.limit), options),\n );\n const pages = Array.isArray(body.pages) ? body.pages : [];\n const next = typeof body.next_cursor === \"string\" ? body.next_cursor : undefined;\n return {\n pages: pages.map((page) => new CrawlPage(record(page))),\n ...(next ? { nextCursor: next } : {}),\n };\n }\n\n /**\n * Walk every page of a crawl, fetching result pages as needed.\n *\n * Readable while the crawl runs; unfinished pages report `pending`.\n */\n async *crawlPages(\n crawlId: string,\n options: CallOptions & { limit?: number } = {},\n ): AsyncGenerator<CrawlPage> {\n let cursor: string | undefined;\n const seen = new Set<string>();\n for (;;) {\n const batch = await this.crawlResults(crawlId, { ...options, ...(cursor ? { cursor } : {}) });\n yield* batch.pages;\n cursor = batch.nextCursor;\n if (!cursor) return;\n if (seen.has(cursor)) {\n throw new DataFuelError(\"the API repeated a crawl cursor; stopping to avoid a loop\");\n }\n seen.add(cursor);\n }\n }\n\n /** Poll until the crawl is done. Without `timeoutMs` it waits indefinitely. */\n async waitCrawl(crawlId: string, options: CallOptions = {}): Promise<CrawlStatus> {\n // The timeout bounds the whole wait, not each poll.\n const { timeoutMs, ...perPoll } = options;\n const deadline = timeoutMs === undefined ? null : Date.now() + timeoutMs;\n for (;;) {\n const status = await this.getCrawl(crawlId, perPoll);\n if (status.done) return status;\n if (deadline !== null && Date.now() + this.pollIntervalMs >= deadline) {\n throw new WaitTimeout(`crawl ${crawlId} is still running`, crawlId, status);\n }\n await this.sleep(this.pollIntervalMs);\n }\n }\n\n /**\n * Start a crawl, wait for it, and return every page.\n *\n * Check `stop_reason`: `insufficient_credits` means it ended early. For large\n * crawls prefer {@link startCrawl} + {@link waitCrawl} + {@link crawlPages},\n * which stream instead of holding every page in memory. On {@link WaitTimeout}\n * the error carries the id: the crawl keeps running and billing.\n */\n async crawl(url: string, options: CrawlOptions & CallOptions = {}): Promise<CrawlResult> {\n const id = await this.startCrawl(url, options);\n const status = await this.waitCrawl(id, options);\n const pages: CrawlPage[] = [];\n for await (const page of this.crawlPages(id, options)) pages.push(page);\n return { id, status, pages };\n }\n\n // --- jobs --------------------------------------------------------------\n\n /**\n * Queue a batch of known URLs and return the job id.\n *\n * Cheaper and more predictable than a crawl when you already have the URLs.\n * `sequential` runs them one after the other; the default runs them\n * concurrently, bounded by the account's concurrency limit.\n */\n async createJob(\n urls: string[],\n options: ScrapeOptions & CallOptions & { sequential?: boolean } = {},\n ): Promise<string> {\n const request = core.buildJob(\n urls,\n options,\n options.proxy,\n options.sequential ?? false,\n core.key(options.idempotencyKey),\n );\n return strField(await this.send(request, options), \"id\");\n }\n\n /** Queue a batch of prompts for an AI engine and return the job id. */\n async createAskJob(\n prompts: string[],\n options: AskOptions & CallOptions & { sequential?: boolean },\n ): Promise<string> {\n const request = core.buildAskJob(\n prompts,\n options,\n options.sequential ?? false,\n core.key(options.idempotencyKey),\n );\n return strField(await this.send(request, options), \"id\");\n }\n\n /** Queue a batch of Google searches and return the job id. */\n async createSearchJob(\n queries: string[],\n options: SearchOptions & CallOptions & { sequential?: boolean } = {},\n ): Promise<string> {\n const request = core.buildSearchJob(\n queries,\n options,\n options.sequential ?? false,\n core.key(options.idempotencyKey),\n );\n return strField(await this.send(request, options), \"id\");\n }\n\n /** Return the progress of a job. */\n async getJob(jobId: string, options: CallOptions = {}): Promise<JobStatus> {\n return jobStatus(\n await this.send(new core.Request(\"GET\", `/job/${core.pathSegment(jobId)}`), options),\n );\n }\n\n /**\n * Stop a job. Queued tasks are refunded, tasks in flight finish and bill.\n * Throws {@link JobNotCancellable} when it already finished.\n */\n async cancelJob(jobId: string, options: CallOptions = {}): Promise<CancelResult> {\n return cancelResult(\n await this.send(new core.Request(\"POST\", `/job/${core.pathSegment(jobId)}/cancel`), options),\n );\n }\n\n /**\n * Return the per-task results of a job.\n *\n * A job completes even when some of its tasks failed: check `task.ok` or call\n * `task.raiseForStatus()` per task.\n */\n async jobResults(jobId: string, options: CallOptions = {}): Promise<JobResults> {\n const body = record(\n await this.send(new core.Request(\"GET\", `/job/${core.pathSegment(jobId)}/results`), options),\n );\n const tasks = Array.isArray(body.tasks_result) ? body.tasks_result : [];\n return {\n id: jobId,\n tasks_count: Number(body.tasks_count ?? 0),\n tasks_failed: Number(body.tasks_failed ?? 0),\n tasks_complete: Number(body.tasks_complete ?? 0),\n tasks: tasks.map((task) => new Result(record(task))),\n };\n }\n\n /** One page of your jobs and crawls, newest first. Pass `nextCursor` back as `cursor`. */\n async listJobs(options: ListOptions & CallOptions = {}): Promise<JobsPage> {\n const body = record(await this.send(core.listJobsRequest(options), options));\n const next = typeof body.next_cursor === \"string\" ? body.next_cursor : undefined;\n return {\n jobs: array(body.jobs).map((raw) => {\n const job = record(raw) as unknown as JobSummary;\n return { ...job, ...jobStatus(job) };\n }),\n ...(next ? { nextCursor: next } : {}),\n };\n }\n\n /**\n * One page of your tasks, newest first, including those of jobs and crawls.\n * Items carry no result: fetch it with {@link getTask}.\n */\n async listTasks(options: ListTasksOptions & CallOptions = {}): Promise<TasksPage> {\n const body = record(await this.send(core.listTasksRequest(options), options));\n const next = typeof body.next_cursor === \"string\" ? body.next_cursor : undefined;\n return {\n tasks: array(body.tasks).map((raw) => {\n const task = record(raw) as unknown as TaskSummary;\n return { ...task, job_id: task.job_id ?? null };\n }),\n ...(next ? { nextCursor: next } : {}),\n };\n }\n\n /** Poll until the job is done. Without `timeoutMs` it waits indefinitely. */\n async waitJob(jobId: string, options: CallOptions = {}): Promise<JobStatus> {\n // The timeout bounds the whole wait, not each poll.\n const { timeoutMs, ...perPoll } = options;\n const deadline = timeoutMs === undefined ? null : Date.now() + timeoutMs;\n for (;;) {\n const status = await this.getJob(jobId, perPoll);\n if (status.done) return status;\n if (deadline !== null && Date.now() + this.pollIntervalMs >= deadline) {\n throw new WaitTimeout(`job ${jobId} is still running`, jobId, status);\n }\n await this.sleep(this.pollIntervalMs);\n }\n }\n\n /** Create a job, wait for it, and return its results. */\n async runJob(\n urls: string[],\n options: ScrapeOptions & CallOptions & { sequential?: boolean } = {},\n ): Promise<JobResults> {\n const id = await this.createJob(urls, options);\n await this.waitJob(id, options);\n return this.jobResults(id, options);\n }\n\n /** Create a prompt job, wait for it, and return its results. */\n async runAskJob(\n prompts: string[],\n options: AskOptions & CallOptions & { sequential?: boolean },\n ): Promise<JobResults> {\n const id = await this.createAskJob(prompts, options);\n await this.waitJob(id, options);\n return this.jobResults(id, options);\n }\n\n /** Create a search job, wait for it, and return its results. */\n async runSearchJob(\n queries: string[],\n options: SearchOptions & CallOptions & { sequential?: boolean } = {},\n ): Promise<JobResults> {\n const id = await this.createSearchJob(queries, options);\n await this.waitJob(id, options);\n return this.jobResults(id, options);\n }\n\n // --- account -----------------------------------------------------------\n\n /** Which task types and LLM engines are switched on right now. Needs no key. */\n async capabilities(options: CallOptions = {}): Promise<Capabilities> {\n const request = new core.Request(\n \"GET\",\n \"/config/capabilities\",\n undefined,\n undefined,\n undefined,\n false,\n );\n return new Capabilities(record(await this.send(request, options)));\n }\n\n /** The browser actions `jsInstructions` accepts, with their arguments. Needs no key. */\n async jsInstructions(options: CallOptions = {}): Promise<JsInstruction[]> {\n const request = new core.Request(\n \"GET\",\n \"/config/js-instructions\",\n undefined,\n undefined,\n undefined,\n false,\n );\n const body = record(await this.send(request, options));\n return Array.isArray(body.instructions) ? (body.instructions as JsInstruction[]) : [];\n }\n\n /** Countries, regions and cities a proxy type can exit from. */\n async proxyLocations(\n options: CallOptions & { proxyType?: string } = {},\n ): Promise<ProxyCountry[]> {\n const params = options.proxyType ? { proxy_type: options.proxyType } : undefined;\n return list(\n await this.send(new core.Request(\"GET\", \"/config/proxy/locations\", params), options),\n ) as ProxyCountry[];\n }\n\n /** ASNs a proxy type can exit from in one country (ISO 3166-1 alpha-2). */\n async proxyAsns(\n country: string,\n options: CallOptions & { proxyType?: string } = {},\n ): Promise<ProxyLocation[]> {\n const params: Record<string, string> = { country };\n if (options.proxyType) params.proxy_type = options.proxyType;\n return list(\n await this.send(new core.Request(\"GET\", \"/config/proxy/asn\", params), options),\n ) as ProxyLocation[];\n }\n\n /** Remaining credits: plan and pay-as-you-go together. */\n async balance(options: CallOptions = {}): Promise<number> {\n const body = await this.send(new core.Request(\"GET\", \"/users/@me/balance\"), options);\n return intField(body, \"balance\");\n }\n\n /** Remaining credits by pool: plan credits (spent first) and pay-as-you-go credits. */\n async balanceSplit(options: CallOptions = {}): Promise<BalanceSplit> {\n const body = await this.send(new core.Request(\"GET\", \"/users/@me/balance\"), options);\n return {\n balance: intField(body, \"balance\"),\n plan_balance: intField(body, \"plan_balance\"),\n payg_balance: intField(body, \"payg_balance\"),\n };\n }\n\n /**\n * Credit movements, newest first: plan assignments, credit pack purchases, usage, refunds, expiry.\n * `sums` totals each operation over the whole range, not just this page.\n */\n async transactions(options: TransactionsOptions & CallOptions = {}): Promise<TransactionsPage> {\n const body = record(await this.send(core.transactionsRequest(options), options));\n return {\n transactions: array(body.transactions) as TransactionsPage[\"transactions\"],\n total_count: Number(body.total_count ?? 0),\n sums: array(body.sums) as TransactionsPage[\"sums\"],\n };\n }\n\n /** Usage over a date range: totals, a time series and breakdowns. Default: the last 30 days. */\n async analytics(options: AnalyticsOptions & CallOptions = {}): Promise<Analytics> {\n const body = record(await this.send(core.analyticsRequest(options), options));\n return {\n ...(body as unknown as Analytics),\n timeseries: array(body.timeseries) as Analytics[\"timeseries\"],\n by_module: array(body.by_module) as Analytics[\"by_module\"],\n top_targets: array(body.top_targets) as Analytics[\"top_targets\"],\n by_status_code: array(body.by_status_code) as Analytics[\"by_status_code\"],\n };\n }\n\n /** The account behind the API key. */\n async me(options: CallOptions = {}): Promise<Profile> {\n const body = await this.send(new core.Request(\"GET\", \"/users/@me\"), options);\n return record(body) as unknown as Profile;\n }\n\n /**\n * Revoke the current key and return the new one.\n *\n * This is the only time the new key is shown. The client keeps using the\n * revoked one: store the new key and build a new client with it.\n */\n async resetApiKey(options: CallOptions = {}): Promise<string> {\n const body = await this.send(new core.Request(\"POST\", \"/users/@me/api-key/reset\"), options);\n return strField(body, \"api_key\");\n }\n}\n\nexport type { Capability };\n\n/** The API key from the environment, on runtimes that have one. */\nfunction envApiKey(): string | undefined {\n return typeof process !== \"undefined\" ? process.env?.DATAFUEL_API_KEY : undefined;\n}\n\nasync function parse(response: Response): Promise<unknown> {\n const text = await response.text();\n let body: unknown;\n if (text.length > 0) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n if (!response.ok) {\n const header = response.headers.get(\"Retry-After\");\n const retryAfter = header !== null && !Number.isNaN(Number(header)) ? Number(header) : 0;\n throw apiError(response.status, body, retryAfter);\n }\n return body;\n}\n\nfunction isAbort(error: unknown): boolean {\n return error instanceof Error && (error.name === \"AbortError\" || error.name === \"TimeoutError\");\n}\n\n/** Turn a surprise answer into a DataFuelError rather than a TypeError later. */\nfunction record(body: unknown): Record<string, unknown> {\n if (body === null || typeof body !== \"object\" || Array.isArray(body)) {\n throw new DataFuelError(`unexpected answer from the API: ${JSON.stringify(body) ?? \"empty\"}`);\n }\n return body as Record<string, unknown>;\n}\n\nfunction list(body: unknown): unknown[] {\n if (!Array.isArray(body)) {\n throw new DataFuelError(`unexpected answer from the API: ${JSON.stringify(body) ?? \"empty\"}`);\n }\n return body;\n}\n\nfunction array(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction jobStatus(body: unknown): JobStatus {\n const raw = record(body) as unknown as Partial<JobStatus>;\n return {\n status: raw.status as JobStatus[\"status\"],\n tasks_count: raw.tasks_count ?? 0,\n tasks_done: raw.tasks_done ?? 0,\n tasks_remaining: raw.tasks_remaining ?? 0,\n total_cost: raw.total_cost ?? 0,\n done: isDone(raw.status),\n };\n}\n\nfunction cancelResult(body: unknown): CancelResult {\n const raw = record(body) as unknown as Partial<CancelResult>;\n return {\n ...jobStatus(body),\n refunded_tasks: raw.refunded_tasks ?? 0,\n refunded_credits: raw.refunded_credits ?? 0,\n };\n}\n\nfunction field(body: unknown, name: string): unknown {\n const value = record(body)[name];\n if (value === undefined || value === null) {\n throw new DataFuelError(`unexpected answer from the API: no ${name} field`);\n }\n return value;\n}\n\nfunction strField(body: unknown, name: string): string {\n return String(field(body, name));\n}\n\nfunction intField(body: unknown, name: string): number {\n const value = Number(field(body, name));\n if (Number.isNaN(value)) {\n throw new DataFuelError(`unexpected answer from the API: ${name} is not a number`);\n }\n return value;\n}\n"],"mappings":"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","names":["record","query","query"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/core.ts","../src/models.ts","../src/client.ts"],"sourcesContent":["/**\n * TypeScript client for the DataFuel scraping API.\n *\n * ```ts\n * import { DataFuel } from \"@datafuel/sdk\";\n *\n * const df = new DataFuel(); // reads DATAFUEL_API_KEY\n * console.log(await df.markdown(\"https://example.com\"));\n * ```\n *\n * Pick the call by the shape of the work:\n *\n * | You have | Call | Waits? |\n * |---|---|---|\n * | One URL | `scrape` / `markdown` | yes |\n * | A site, need its URL list | `map` | yes |\n * | A start URL, many pages | `crawl` / `startCrawl` | `crawl` does |\n * | A list of known URLs | `runJob` / `createJob` | `runJob` does |\n * | A question for an AI engine | `ask` | yes |\n * | A Google search | `search` | yes |\n * | Many prompts or searches | `runAskJob` / `runSearchJob` | yes |\n * | Earlier jobs, tasks, usage | `listJobs` / `listTasks` / `analytics` / `transactions` | yes |\n *\n * Start with plain `scrape`. Turn on `jsRendering` only when the page comes\n * back empty: it is slower and costs five times the credits on a Basic proxy.\n * `map` a section before you `crawl` it — one credit, and it tells you how big\n * the section is.\n */\n\nexport { DataFuel } from \"./client.js\";\nexport type { ClientOptions } from \"./client.js\";\nexport { DEFAULT_BASE_URL, VERSION } from \"./core.js\";\nexport type { AskOptions, CrawlOptions, MapOptions, SearchOptions } from \"./core.js\";\nexport {\n AlreadyExists,\n APIError,\n Blocked,\n DataFuelError,\n EngineUnavailable,\n Forbidden,\n IdempotencyKeyReused,\n InsufficientCredits,\n InvalidAttributes,\n JobNotCancellable,\n ModuleUnavailable,\n NoApiKey,\n NotFound,\n RateLimited,\n TaskFailed,\n TransportError,\n Unauthorized,\n Unavailable,\n WaitTimeout,\n} from \"./errors.js\";\nexport type { ErrorCode } from \"./errors.js\";\nexport { Capabilities, CrawlPage, isDone, Result } from \"./models.js\";\nexport type {\n AI,\n AIProvider,\n Analytics,\n AnalyticsCounts,\n AnalyticsOptions,\n BalanceSplit,\n CallOptions,\n CancelResult,\n Capability,\n CrawlResult,\n CrawlResultsPage,\n CrawlStatus,\n Engine,\n Format,\n Health,\n JobResults,\n JobsPage,\n JobStatus,\n JobSummary,\n JsInstruction,\n JsInstructionArg,\n Link,\n ListOptions,\n ListTasksOptions,\n Payload,\n Profile,\n ProtectionCheck,\n Proxy,\n ProxyCountry,\n ProxyLocation,\n ProxyType,\n ScrapeOptions,\n PreviousPeriod,\n SiteMap,\n Status,\n StatusCodeBreakdown,\n TasksPage,\n TaskSummary,\n TaskType,\n Transaction,\n TransactionOperation,\n TransactionsOptions,\n TransactionsPage,\n TransactionSum,\n} from \"./models.js\";\n","/**\n * Errors this package throws.\n *\n * Two families, as in the Go and Python SDKs:\n *\n * - {@link APIError} and its subclasses — the API refused the request.\n * - {@link TaskFailed} / {@link Blocked} — the API accepted the task but the\n * page could not be scraped. Failed tasks are refunded.\n */\n\nimport type { Result } from \"./models.js\";\n\n/** Base class for every error this package throws. */\nexport class DataFuelError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/** No key was passed and DATAFUEL_API_KEY is empty. Thrown before any request. */\nexport class NoApiKey extends DataFuelError {}\n\n/** The request never got an answer: DNS, connection, abort, read timeout. */\nexport class TransportError extends DataFuelError {}\n\n/** The `code` of an API error. The API may add codes; unknown ones pass through. */\nexport type ErrorCode =\n | \"UNAUTHORIZED\"\n | \"INVALID_API_KEY\"\n | \"FORBIDDEN\"\n | \"INSUFFICIENT_CREDITS\"\n | \"RATE_LIMIT_EXCEEDED\"\n | \"CONCURRENCY_LIMIT_REACHED\"\n | \"INVALID_REQUEST_BODY\"\n | \"INVALID_ATTRIBUTES\"\n | \"MISSING_TARGET\"\n | \"UNSUPPORTED_TASK_TYPE\"\n | \"JOB_REQUIRES_MULTIPLE_TARGETS\"\n | \"INVALID_IDEMPOTENCY_KEY\"\n | \"IDEMPOTENCY_KEY_REUSED\"\n | \"INVALID_TASK_ID\"\n | \"INVALID_JOB_ID\"\n | \"TASK_NOT_FOUND\"\n | \"JOB_NOT_FOUND\"\n | \"CRAWL_NOT_FOUND\"\n | \"JOB_NOT_CANCELLABLE\"\n | \"TASK_ALREADY_EXISTS\"\n | \"JOB_ALREADY_EXISTS\"\n | \"URL_LENGTH_CANNOT_BE_ZERO\"\n | \"ANALYTICS_FETCH_FAILED\"\n | \"INVALID_CRAWL_PATTERN\"\n | \"CRAWL_UNSUPPORTED_OPTION\"\n | \"INVALID_CURSOR\"\n | \"INVALID_QUERY_PARAM\"\n | \"INVALID_PROXY_TYPE\"\n | \"INVALID_COUNTRY\"\n | \"INVALID_DATE_FORMAT\"\n | \"INVALID_DATE_RANGE\"\n | \"INVALID_INTERVAL\"\n | \"MODULE_UNAVAILABLE\"\n | \"ENGINE_UNAVAILABLE\"\n | \"API_KEY_RESET_FAILED\"\n | \"TASK_RESULT_TIMEOUT\"\n | \"INTERNAL_ERROR\"\n | (string & {});\n\n/** A non-2xx answer from the API itself. */\nexport class APIError extends DataFuelError {\n readonly status: number;\n readonly code: ErrorCode;\n /** Seconds the API asked us to wait, from Retry-After. 0 when absent. */\n readonly retryAfter: number;\n\n constructor(status: number, code: string, message: string, retryAfter = 0) {\n super(code ? `${message} (${status} ${code})` : `${message} (${status})`);\n this.status = status;\n this.code = code;\n this.retryAfter = retryAfter;\n }\n}\n\n/** 401: the API key is missing or invalid. */\nexport class Unauthorized extends APIError {}\n/** 403 FORBIDDEN: the account is inactive. */\nexport class Forbidden extends APIError {}\n/** 404: unknown id, or one that belongs to another account. */\nexport class NotFound extends APIError {}\n/** 429: the account's request rate or concurrency limit was reached. */\nexport class RateLimited extends APIError {}\n/** 402: not enough credits for this task. */\nexport class InsufficientCredits extends APIError {}\n/** 400 INVALID_ATTRIBUTES: the attributes do not match the task type. */\nexport class InvalidAttributes extends APIError {}\n/** 422: the key was already used for a different request. */\nexport class IdempotencyKeyReused extends APIError {}\n/** 409 JOB_NOT_CANCELLABLE: the job or crawl already finished. */\nexport class JobNotCancellable extends APIError {}\n/**\n * 409 TASK_ALREADY_EXISTS / JOB_ALREADY_EXISTS: the create collided with an\n * existing task or job and is not an idempotent replay. Nothing was charged;\n * send the request again.\n */\nexport class AlreadyExists extends APIError {}\n/** 503: an operator switched something off, or a dependency is down. The message carries the reason. */\nexport class Unavailable extends APIError {}\n/** 503 MODULE_UNAVAILABLE: this task type is switched off. Nothing was charged. */\nexport class ModuleUnavailable extends Unavailable {}\n/** 503 ENGINE_UNAVAILABLE: this LLM engine is switched off. Nothing was charged. */\nexport class EngineUnavailable extends Unavailable {}\n\n/**\n * The task was accepted but could not be completed. Refunded.\n *\n * `result` carries the envelope: `statusCode`, `blocked`, `protection`, `error`.\n */\nexport class TaskFailed extends DataFuelError {\n readonly result: Result;\n\n constructor(result: Result) {\n const detail = result.error ?? result.payload?.error_detail ?? \"no detail\";\n super(`task failed: ${detail}`);\n this.result = result;\n }\n\n /** Anti-bot vendor recognised on the target, when there was one. */\n get protection(): string | undefined {\n return this.result.protection;\n }\n}\n\n/**\n * The target refused or challenged the request (403/429/503, anti-bot wall).\n *\n * Refunded. Retry with `jsRendering: true` or a Premium proxy.\n */\nexport class Blocked extends TaskFailed {}\n\n/**\n * A wait ran out of time. The work keeps running and billing server-side.\n *\n * `id` picks it back up (`waitCrawl`, `jobResults`, or a re-send under the same\n * idempotency key); `status` is the last one seen, when there was one.\n */\nexport class WaitTimeout extends DataFuelError {\n readonly id: string | undefined;\n readonly status: unknown;\n\n constructor(message: string, id?: string, status?: unknown) {\n super(message);\n this.id = id;\n this.status = status;\n }\n}\n\nconst BY_CODE: Record<string, new (s: number, c: string, m: string, r?: number) => APIError> = {\n MODULE_UNAVAILABLE: ModuleUnavailable,\n ENGINE_UNAVAILABLE: EngineUnavailable,\n INSUFFICIENT_CREDITS: InsufficientCredits,\n INVALID_ATTRIBUTES: InvalidAttributes,\n IDEMPOTENCY_KEY_REUSED: IdempotencyKeyReused,\n INVALID_API_KEY: Unauthorized,\n FORBIDDEN: Forbidden,\n JOB_NOT_CANCELLABLE: JobNotCancellable,\n TASK_ALREADY_EXISTS: AlreadyExists,\n JOB_ALREADY_EXISTS: AlreadyExists,\n};\n\nconst BY_STATUS: Record<number, new (s: number, c: string, m: string, r?: number) => APIError> = {\n 401: Unauthorized,\n 402: InsufficientCredits,\n 403: Forbidden,\n 404: NotFound,\n 422: IdempotencyKeyReused,\n 429: RateLimited,\n 503: Unavailable,\n};\n\n/** Map an error answer onto the narrowest class that fits. */\nexport function apiError(status: number, body: unknown, retryAfter = 0): APIError {\n let code = \"\";\n let message = \"\";\n if (body !== null && typeof body === \"object\") {\n const record = body as Record<string, unknown>;\n code = typeof record.code === \"string\" ? record.code : \"\";\n message = typeof record.message === \"string\" ? record.message : \"\";\n } else if (typeof body === \"string\" && body.length > 0 && body.length <= 300) {\n message = body;\n }\n const Cls = BY_CODE[code] ?? BY_STATUS[status] ?? APIError;\n return new Cls(status, code, message || `HTTP ${status}`, retryAfter);\n}\n","/**\n * Request building and answer classification. Pure functions, no I/O.\n *\n * Every decision lives here — which envelope a module needs, where the sticky\n * session keys go, how `ai` expands, whether an answer is retryable — so the\n * client only moves bytes.\n */\n\nimport { APIError, Unavailable } from \"./errors.js\";\nimport type {\n AI,\n AnalyticsOptions,\n Engine,\n ListOptions,\n ListTasksOptions,\n Proxy,\n ScrapeOptions,\n TransactionsOptions,\n} from \"./models.js\";\n\nexport const DEFAULT_BASE_URL = \"https://scraping-api.datafuel.ai/api/v1\";\n\n/** Kept in step with package.json by a test; see test/hardening.test.ts. */\nexport const VERSION = \"0.4.0\";\n\n/** How long a synchronous call waits for a result before giving up. */\nexport const DEFAULT_TIMEOUT_MS = 180_000;\n/** Gap between two attempts at a task the API is still processing. */\nexport const STILL_PROCESSING_DELAY_MS = 2_000;\nexport const STILL_PROCESSING = \"TASK_STILL_PROCESSING\";\n/** The API rejects a longer key with 400; catching it here saves the round trip. */\nexport const MAX_IDEMPOTENCY_KEY = 255;\n\n/** One HTTP call, ready for the client to send. */\nexport class Request {\n constructor(\n readonly method: string,\n readonly path: string,\n readonly params?: Record<string, string>,\n readonly body?: Record<string, unknown> | unknown[],\n readonly idempotencyKey?: string,\n readonly auth: boolean = true,\n /** A 503 that carries a health report is an answer, not an error. */\n readonly degradedOk: boolean = false,\n ) {}\n\n /** GETs are safe by nature, writes because they carry an idempotency key. */\n get retryable(): boolean {\n return this.method === \"GET\" || this.idempotencyKey !== undefined;\n }\n\n /**\n * Method and path only. The body can hold an LLM key or a cookie header, so\n * neither logging nor JSON.stringify may spill it.\n */\n toString(): string {\n return `<Request ${this.method} ${this.path}>`;\n }\n\n toJSON(): string {\n return this.toString();\n }\n\n [Symbol.for(\"nodejs.util.inspect.custom\")](): string {\n return this.toString();\n }\n}\n\n/**\n * Escape an id before it becomes part of a URL path.\n *\n * An id is caller data. Unescaped, a stray `/` or `?` in one would move the\n * request to a different endpoint.\n */\nexport function pathSegment(value: string): string {\n return encodeURIComponent(value);\n}\n\nexport function newIdempotencyKey(): string {\n return crypto.randomUUID();\n}\n\n/** The headers every call carries. The idempotency key sits beside the API key. */\nexport function headers(\n apiKey: string,\n userAgent: string,\n request: Request,\n): Record<string, string> {\n const out: Record<string, string> = {\n Accept: \"application/json\",\n \"User-Agent\": userAgent,\n };\n if (apiKey) out[\"X-API-Key\"] = apiKey;\n if (request.body !== undefined) out[\"Content-Type\"] = \"application/json\";\n if (request.idempotencyKey !== undefined) out[\"Idempotency-Key\"] = request.idempotencyKey;\n return out;\n}\n\n/** The API takes multi-field extractors as a JSON object string. */\nfunction selector(value: string | Record<string, string>): string {\n return typeof value === \"string\" ? value : JSON.stringify(value);\n}\n\nfunction aiAttributes(ai: AI): Record<string, unknown> {\n const out: Record<string, unknown> = { result_use_ai: true };\n if (ai.prompt) out.result_ai_prompt = ai.prompt;\n if (ai.format !== undefined) out.result_ai_format = ai.format;\n if (ai.provider) out.ai_provider = ai.provider;\n if (ai.model) out.ai_model = ai.model;\n if (ai.apiKey) out.ai_api_key = ai.apiKey;\n return out;\n}\n\n/** The API answers 400 INVALID_ATTRIBUTES without a provider; say so before sending. */\nexport function validateAI(ai: AI): void {\n if (!ai.provider) {\n throw new TypeError(\"ai needs a provider; aiProviders() lists the ones the API supports\");\n }\n}\n\n/**\n * Flatten the page options into the API's `attributes` object.\n *\n * Unset options are left out of the body entirely, never sent as null.\n */\nexport function scrapeAttributes(options: ScrapeOptions = {}): Record<string, unknown> {\n const attrs: Record<string, unknown> = {};\n if (options.format) attrs.result_format = options.format;\n if (options.jsRendering) attrs.js_rendering = true;\n if (options.waitFor) attrs.wait_for_selector = options.waitFor;\n if (options.waitForTimeoutMs) attrs.wait_for_selector_timeout_ms = options.waitForTimeoutMs;\n if (options.jsInstructions) attrs.js_instructions = options.jsInstructions;\n if (options.blockResource?.length) {\n attrs.block_resource =\n typeof options.blockResource === \"string\"\n ? options.blockResource\n : [...options.blockResource];\n }\n if (options.mainContentOnly) attrs.main_content_only = true;\n if (options.includeImages !== undefined) attrs.include_images = options.includeImages;\n if (options.extract) attrs.extract_selector = selector(options.extract);\n if (options.extractRegex) attrs.extract_regex = selector(options.extractRegex);\n if (options.template) attrs.result_template = options.template;\n if (options.method) attrs.method = options.method;\n if (options.body) attrs.body = options.body;\n if (options.contentType) attrs.content_type = options.contentType;\n if (options.headers) attrs.headers = options.headers;\n if (options.headerOrder) attrs.header_order = options.headerOrder;\n if (options.cookies) attrs.cookie_string = options.cookies;\n if (options.userAgent) attrs.user_agent = options.userAgent;\n if (options.userAgentType) attrs.user_agent_type = options.userAgentType;\n if (options.ai) {\n validateAI(options.ai);\n Object.assign(attrs, aiAttributes(options.ai));\n }\n return attrs;\n}\n\n/** The proxy fields that travel in the request envelope. */\nexport function proxyEnvelope(proxy: Proxy | undefined): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (!proxy) return out;\n if (proxy.type) out.proxy_type = proxy.type;\n if (proxy.country) out.proxy_country = proxy.country;\n if (proxy.city) out.proxy_city = proxy.city;\n if (proxy.state) out.proxy_state = proxy.state;\n if (proxy.asn) out.proxy_asn = proxy.asn;\n return out;\n}\n\n/** The sticky-session fields, which travel in `attributes`. */\nexport function proxySession(proxy: Proxy | undefined): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (!proxy) return out;\n if (proxy.sessionId) out.proxy_session_id = proxy.sessionId;\n if (proxy.ttl) out.proxy_ttl = proxy.ttl;\n return out;\n}\n\n/** The body every write shares. */\nexport function envelope(\n taskType: string,\n attributes: Record<string, unknown>,\n extra: { proxy?: Proxy | undefined; multithreaded?: boolean | undefined } = {},\n): Record<string, unknown> {\n const body: Record<string, unknown> = { type: taskType, ...proxyEnvelope(extra.proxy) };\n if (extra.multithreaded !== undefined) body.multithreaded = extra.multithreaded;\n body.attributes = attributes;\n return body;\n}\n\nexport function key(explicit: string | undefined): string {\n if (explicit !== undefined && explicit.length > MAX_IDEMPOTENCY_KEY) {\n throw new TypeError(`idempotencyKey is longer than ${MAX_IDEMPOTENCY_KEY} characters`);\n }\n return explicit ?? newIdempotencyKey();\n}\n\nexport function buildScrape(\n url: string,\n options: ScrapeOptions,\n proxy: Proxy | undefined,\n idempotencyKey: string,\n): Request {\n const attrs = { ...scrapeAttributes(options), url, ...proxySession(proxy) };\n return new Request(\n \"POST\",\n \"/task\",\n undefined,\n envelope(\"unlocker\", attrs, { proxy }),\n idempotencyKey,\n );\n}\n\nexport function buildJob(\n urls: string[],\n options: ScrapeOptions,\n proxy: Proxy | undefined,\n sequential: boolean,\n idempotencyKey: string,\n): Request {\n const attrs = { ...scrapeAttributes(options), urls: [...urls], ...proxySession(proxy) };\n return new Request(\n \"POST\",\n \"/job\",\n undefined,\n envelope(\"unlocker\", attrs, { proxy, multithreaded: !sequential }),\n idempotencyKey,\n );\n}\n\n/** Options for the llm_scraping module, which reads its proxy country here. */\nexport interface AskOptions {\n engine: Engine | string;\n websearch?: boolean;\n followUp?: string;\n country?: string;\n location?: string;\n format?: string;\n}\n\nexport function askAttributes(\n promptField: string,\n prompt: string | string[],\n options: AskOptions,\n): Record<string, unknown> {\n const attrs: Record<string, unknown> = { [promptField]: prompt, engine: options.engine };\n if (options.websearch) attrs.websearch = true;\n if (options.followUp) attrs.follow_up_prompt = options.followUp;\n if (options.country) attrs.proxy_country = options.country;\n if (options.location) attrs.location = options.location;\n if (options.format) attrs.result_format = options.format;\n return attrs;\n}\n\nexport function buildAsk(prompt: string, options: AskOptions, idempotencyKey: string): Request {\n const attrs = askAttributes(\"prompt\", prompt, options);\n return new Request(\"POST\", \"/task\", undefined, envelope(\"llm_scraping\", attrs), idempotencyKey);\n}\n\nexport function buildAskJob(\n prompts: string[],\n options: AskOptions,\n sequential: boolean,\n idempotencyKey: string,\n): Request {\n const attrs = askAttributes(\"prompts\", [...prompts], options);\n return new Request(\n \"POST\",\n \"/job\",\n undefined,\n envelope(\"llm_scraping\", attrs, { multithreaded: !sequential }),\n idempotencyKey,\n );\n}\n\n/** Options for `map`. */\nexport interface MapOptions {\n /** Keep only links whose URL or title contains this. */\n search?: string;\n /** Map only this sitemap, from a previous `SiteMap.sitemaps`. */\n sitemap?: string;\n /** Default 5000, capped at 10000. */\n limit?: number;\n includeSubdomains?: boolean;\n ignoreSitemap?: boolean;\n sitemapOnly?: boolean;\n userAgent?: string;\n userAgentType?: string;\n}\n\nexport function buildMap(\n url: string,\n options: MapOptions,\n proxy: Proxy | undefined,\n idempotencyKey: string,\n): Request {\n const attrs: Record<string, unknown> = { url };\n if (options.search) attrs.search = options.search;\n if (options.sitemap) attrs.sitemap = options.sitemap;\n if (options.limit) attrs.limit = options.limit;\n if (options.includeSubdomains) attrs.include_subdomains = true;\n if (options.ignoreSitemap) attrs.ignore_sitemap = true;\n if (options.sitemapOnly) attrs.sitemap_only = true;\n if (options.userAgent) attrs.user_agent = options.userAgent;\n if (options.userAgentType) attrs.user_agent_type = options.userAgentType;\n Object.assign(attrs, proxySession(proxy));\n return new Request(\"POST\", \"/map\", undefined, envelope(\"map\", attrs, { proxy }), idempotencyKey);\n}\n\n/** Options for `crawl`, on top of the page options applied to every page. */\nexport interface CrawlOptions extends ScrapeOptions {\n /** Default 100, max 10000. The hard budget of the crawl. */\n maxPages?: number;\n /** Default 3, max 10. The start URL is depth 0. */\n maxDepth?: number;\n /** RE2 on path?query; when set only matches are followed. */\n includePaths?: string[];\n /** RE2 on path?query; exclude wins. */\n excludePaths?: string[];\n includeSubdomains?: boolean;\n allowBackwardLinks?: boolean;\n /** Pages in flight, default 5. */\n concurrency?: number;\n}\n\nexport function buildCrawl(\n url: string,\n options: CrawlOptions,\n proxy: Proxy | undefined,\n idempotencyKey: string,\n): Request {\n if (options.ai) {\n throw new TypeError(\"crawl does not support ai: the API rejects result_use_ai on crawls\");\n }\n const attrs: Record<string, unknown> = { ...scrapeAttributes(options), url };\n if (options.maxPages) attrs.max_pages = options.maxPages;\n if (options.maxDepth) attrs.max_depth = options.maxDepth;\n if (options.concurrency) attrs.concurrency = options.concurrency;\n if (options.includePaths?.length) attrs.include_paths = [...options.includePaths];\n if (options.excludePaths?.length) attrs.exclude_paths = [...options.excludePaths];\n if (options.includeSubdomains) attrs.include_subdomains = true;\n if (options.allowBackwardLinks) attrs.allow_backward_links = true;\n Object.assign(attrs, proxySession(proxy));\n return new Request(\n \"POST\",\n \"/crawl\",\n undefined,\n envelope(\"crawl\", attrs, { proxy }),\n idempotencyKey,\n );\n}\n\n/** Options for `search`, the Google SERP module. Proxy type is not used. */\nexport interface SearchOptions {\n /** Google `gl`, e.g. \"us\". */\n country?: string;\n /** Google `hl`, e.g. \"en\". */\n language?: string;\n /** Canonical location name. Give at most one of location, uule, lat/lon. */\n location?: string;\n /** 1-based, default 1. */\n page?: number;\n /** e.g. \"google.de\". */\n googleDomain?: string;\n uule?: string;\n lat?: number;\n lon?: number;\n /** Metres around lat/lon or location, max 1000. */\n radius?: number;\n cr?: string;\n lr?: string;\n tbs?: string;\n safe?: \"active\" | \"off\";\n nfpr?: boolean;\n filter?: boolean;\n uds?: string;\n kgmid?: string;\n si?: string;\n ludocid?: string;\n lsig?: string;\n ibp?: string;\n /**\n * Accepted but not used yet: searches leave through DataFuel's own pool.\n * Target a market with `country` and `language`.\n */\n proxyCountry?: string;\n /** Default json. */\n format?: \"json\" | \"html\" | \"markdown\";\n}\n\nexport function searchAttributes(\n queryField: string,\n query: string | string[],\n options: SearchOptions,\n): Record<string, unknown> {\n const attrs: Record<string, unknown> = { [queryField]: query };\n const strings: [keyof SearchOptions, string][] = [\n [\"country\", \"country\"],\n [\"language\", \"language\"],\n [\"location\", \"location\"],\n [\"googleDomain\", \"google_domain\"],\n [\"uule\", \"uule\"],\n [\"cr\", \"cr\"],\n [\"lr\", \"lr\"],\n [\"tbs\", \"tbs\"],\n [\"safe\", \"safe\"],\n [\"uds\", \"uds\"],\n [\"kgmid\", \"kgmid\"],\n [\"si\", \"si\"],\n [\"ludocid\", \"ludocid\"],\n [\"lsig\", \"lsig\"],\n [\"ibp\", \"ibp\"],\n [\"proxyCountry\", \"proxy_country\"],\n [\"format\", \"result_format\"],\n ];\n for (const [option, attribute] of strings) {\n if (options[option]) attrs[attribute] = options[option];\n }\n if (options.page) attrs.page = options.page;\n if (options.radius) attrs.radius = options.radius;\n if (options.lat !== undefined) attrs.lat = options.lat;\n if (options.lon !== undefined) attrs.lon = options.lon;\n if (options.nfpr !== undefined) attrs.nfpr = options.nfpr;\n if (options.filter !== undefined) attrs.filter = options.filter;\n return attrs;\n}\n\nexport function buildSearch(\n query: string,\n options: SearchOptions,\n idempotencyKey: string,\n): Request {\n const attrs = searchAttributes(\"query\", query, options);\n return new Request(\"POST\", \"/task\", undefined, envelope(\"serp\", attrs), idempotencyKey);\n}\n\nexport function buildSearchJob(\n queries: string[],\n options: SearchOptions,\n sequential: boolean,\n idempotencyKey: string,\n): Request {\n const attrs = searchAttributes(\"queries\", [...queries], options);\n return new Request(\n \"POST\",\n \"/job\",\n undefined,\n envelope(\"serp\", attrs, { multithreaded: !sequential }),\n idempotencyKey,\n );\n}\n\nexport function crawlResultsRequest(crawlId: string, cursor?: string, limit?: number): Request {\n const params: Record<string, string> = {};\n if (cursor) params.cursor = cursor;\n if (limit) params.limit = String(limit);\n return new Request(\n \"GET\",\n `/crawl/${pathSegment(crawlId)}/results`,\n Object.keys(params).length > 0 ? params : undefined,\n );\n}\n\nexport function healthRequest(deep: boolean): Request {\n return new Request(\n \"GET\",\n \"/healthz\",\n deep ? { deep: \"1\" } : undefined,\n undefined,\n undefined,\n false,\n true,\n );\n}\n\n/** A Date as its UTC day, which is what the API's date filters take. */\nexport function day(value: string | Date): string {\n return typeof value === \"string\" ? value : value.toISOString().slice(0, 10);\n}\n\nfunction query(\n entries: [string, string | number | Date | undefined][],\n): Record<string, string> | undefined {\n const params: Record<string, string> = {};\n for (const [name, value] of entries) {\n if (value === undefined || value === \"\") continue;\n params[name] = value instanceof Date ? day(value) : String(value);\n }\n return Object.keys(params).length > 0 ? params : undefined;\n}\n\nfunction listRequest(path: string, options: ListOptions, jobId?: string): Request {\n const params = query([\n [\"status\", options.status],\n [\"type\", options.type],\n [\"job_id\", jobId],\n [\"start_date\", options.startDate],\n [\"end_date\", options.endDate],\n [\"limit\", options.limit],\n [\"cursor\", options.cursor],\n ]);\n return new Request(\"GET\", path, params);\n}\n\nexport function listJobsRequest(options: ListOptions): Request {\n return listRequest(\"/job\", options);\n}\n\nexport function listTasksRequest(options: ListTasksOptions): Request {\n return listRequest(\"/task\", options, options.jobId);\n}\n\nexport function transactionsRequest(options: TransactionsOptions): Request {\n const params = query([\n [\"operation\", options.operation],\n [\"start_date\", options.startDate],\n [\"end_date\", options.endDate],\n [\"page\", options.page],\n [\"limit\", options.limit],\n ]);\n return new Request(\"GET\", \"/users/@me/transactions\", params);\n}\n\nexport function analyticsRequest(options: AnalyticsOptions): Request {\n const params = query([\n [\"start_date\", options.startDate],\n [\"end_date\", options.endDate],\n [\"interval\", options.interval],\n [\"module\", options.module],\n ]);\n return new Request(\"GET\", \"/task/analytics/dashboard\", params);\n}\n\n/** Whether the API answered \"the task is still running\" instead of a result. */\nexport function stillProcessing(body: unknown): boolean {\n return (\n body !== null &&\n typeof body === \"object\" &&\n (body as Record<string, unknown>).code === STILL_PROCESSING\n );\n}\n\n/** Go's retry policy: transport errors, 429, 502, 503, 504 — nothing else. */\nexport function shouldRetry(error: unknown): boolean {\n if (error instanceof Unavailable) {\n // A deliberate switch-off is a 503 too, but retrying it only adds load: it\n // stays off until an operator turns it back on.\n if (error.code === \"MODULE_UNAVAILABLE\" || error.code === \"ENGINE_UNAVAILABLE\") return false;\n }\n if (error instanceof APIError) return [429, 502, 503, 504].includes(error.status);\n return true; // transport error\n}\n\n/** 500ms, 1s, 2s, 4s, then 8s flat — halved and randomized. Retry-After wins. */\nexport function backoff(attempt: number, retryAfterSeconds = 0): number {\n if (retryAfterSeconds > 0) return Math.min(retryAfterSeconds * 1000, 30_000);\n const base = 500 * 2 ** Math.min(attempt, 4);\n return base / 2 + Math.random() * (base / 2);\n}\n\n/** Gap before re-sending a task the API is still processing. */\nexport function pollDelay(attempt: number): number {\n return Math.max(STILL_PROCESSING_DELAY_MS, backoff(attempt));\n}\n","/** Request options and response shapes. */\n\nimport { Blocked, DataFuelError, TaskFailed } from \"./errors.js\";\n\n/** State of a task, job or crawl. Unknown states are treated as not final. */\nexport type Status =\n | \"created\"\n | \"pending\"\n | \"processing\"\n | \"completed\"\n | \"completed_with_errors\"\n | \"failed\"\n | \"cancelled\";\n\nconst TERMINAL = new Set([\"completed\", \"completed_with_errors\", \"failed\", \"cancelled\"]);\n\n/** Whether a state is final. */\nexport function isDone(status: string | undefined): boolean {\n return status !== undefined && TERMINAL.has(status);\n}\n\n/**\n * Shape of the scraped content.\n *\n * `html` raw page (API default), `markdown` cleaned text (best for LLMs),\n * `json` schema.org / JSON-LD, `png` / `jpeg` full-page screenshot.\n */\nexport type Format = \"html\" | \"markdown\" | \"json\" | \"png\" | \"jpeg\";\n\n/** AI assistant `ask` can query. Engines can be switched off at runtime. */\nexport type Engine = \"openai\" | \"gemini\" | \"google_ai_mode\" | \"perplexity\" | \"copilot\";\n\n/** Proxy plan. Matched case-insensitively; deployments may define others. */\nexport type ProxyType = \"Basic\" | \"Premium\" | (string & {});\n\n/** The exit the request leaves from. Every field optional: the account default. */\nexport interface Proxy {\n type?: ProxyType;\n /** ISO 3166-1 alpha-2, e.g. \"US\". */\n country?: string;\n city?: string;\n state?: string;\n asn?: string;\n /**\n * Sticky session: the same exit across requests, `ttl` in seconds. Read by\n * `scrape`, `map`, URL jobs and crawls, and sent in attributes rather than\n * the envelope.\n */\n sessionId?: string;\n ttl?: number;\n}\n\n/**\n * Post-process the page with an LLM, using your own key.\n *\n * Not supported on crawls: the API rejects `result_use_ai` there.\n */\nexport interface AI {\n /** What to extract. */\n prompt?: string;\n /** Example JSON object the output must follow. */\n format?: unknown;\n /** Required. One of the providers `df.aiProviders()` lists; the API answers 400 INVALID_ATTRIBUTES without it. */\n provider?: string;\n /** One of the models `df.aiProviders()` lists for `provider`. Omit for the provider's default. */\n model?: string;\n apiKey?: string;\n}\n\n/** Page options, shared by `scrape`, jobs and crawls. */\nexport interface ScrapeOptions {\n format?: Format;\n /**\n * Render the page in a real browser: slower, five times the credits on a\n * Basic proxy. Leave it off unless the page comes back empty without it.\n */\n jsRendering?: boolean;\n waitFor?: string;\n waitForTimeoutMs?: number;\n /**\n * Browser actions run after load: an array of single-action objects, run in\n * order, e.g. `[{ click: \"#more\" }, { wait_ms: 1000 }, { click: \"#more\" }]`.\n * An object keyed by action is still accepted, but its order is not\n * guaranteed and an action cannot repeat. `df.jsInstructions()` lists them.\n */\n jsInstructions?: unknown;\n /** Resource types the browser must not load: one, e.g. `\"Image\"`, or several. */\n blockResource?: string | string[];\n /** Markdown only: always render just the `<main>` / `<article>` container. */\n mainContentOnly?: boolean;\n /** Markdown only: `false` drops images and saves tokens. */\n includeImages?: boolean;\n /**\n * Extract only matching elements: field name to CSS selector. Append\n * ` @attr` to read an attribute, e.g. `{ links: \"a @href\" }`.\n */\n extract?: string | Record<string, string>;\n /** The same with RE2 patterns on the raw HTML. */\n extractRegex?: string | Record<string, string>;\n /**\n * Built-in extractors, comma separated: images, links, headings,\n * phone_numbers, emails, meta_tags, tables, schema_org, all.\n */\n template?: string;\n method?: string;\n body?: string;\n contentType?: string;\n headers?: Record<string, string>;\n headerOrder?: string[];\n cookies?: string;\n userAgent?: string;\n /** chrome, firefox, safari, edge. */\n userAgentType?: string;\n ai?: AI;\n}\n\n/** Options every call accepts. */\nexport interface CallOptions {\n proxy?: Proxy;\n /** Generated per request when omitted. Max 255 characters. */\n idempotencyKey?: string;\n /** Overrides the client's timeout for this call. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/** The raw `result` object of a task. */\nexport interface Payload {\n data?: unknown;\n status?: Status;\n error_detail?: string;\n status_code?: number;\n}\n\n/**\n * One scraped target with its metadata.\n *\n * Read the metadata before the content: a 200 can be an error page,\n * `redirected` means `finalUrl` is not what you asked for, and a 404 still\n * completes and bills.\n */\nexport class Result {\n readonly id: string | undefined;\n readonly status: Status | undefined;\n /** HTTP status the target answered. */\n readonly statusCode: number | undefined;\n readonly finalUrl: string | undefined;\n readonly redirected: boolean;\n /** Charged for this task, 0 when it failed. */\n readonly creditsUsed: number;\n readonly durationMs: number | undefined;\n readonly blocked: boolean;\n /** Anti-bot vendor recognised when blocked. */\n readonly protection: string | undefined;\n readonly error: string | undefined;\n /** The raw `result` object. Prefer `text`, `data` and `image`. */\n readonly payload: Payload | undefined;\n /** Everything the API sent, including fields this SDK does not know yet. */\n readonly raw: Record<string, unknown>;\n\n constructor(raw: Record<string, unknown>) {\n this.raw = raw;\n this.id = str(raw.id);\n this.status = str(raw.status) as Status | undefined;\n this.statusCode = num(raw.status_code);\n this.finalUrl = str(raw.final_url);\n this.redirected = raw.redirected === true;\n this.creditsUsed = num(raw.credits_used) ?? 0;\n this.durationMs = num(raw.duration_ms);\n this.blocked = raw.blocked === true;\n this.protection = str(raw.protection);\n this.error = str(raw.error);\n this.payload =\n raw.result !== null && typeof raw.result === \"object\" ? (raw.result as Payload) : undefined;\n }\n\n /** Effective state: the envelope's, else the payload's, else inferred. */\n get state(): string {\n if (this.status) return this.status;\n if (this.payload?.status) return this.payload.status;\n if (this.payload?.data !== undefined && this.payload.data !== null) return \"completed\";\n return \"pending\";\n }\n\n /** Whether the task has not finished yet (job and crawl results list stubs). */\n get pending(): boolean {\n return !isDone(this.state);\n }\n\n /** Whether the task completed and the target was not blocked. */\n get ok(): boolean {\n return this.state === \"completed\" && !this.blocked;\n }\n\n /** The structured output: format json, extract, template, AI. */\n get data(): unknown {\n return this.payload?.data;\n }\n\n /** Content of an html or markdown result; the raw JSON for structured ones. */\n get text(): string {\n const value = this.data;\n if (value === undefined || value === null) return \"\";\n return typeof value === \"string\" ? value : JSON.stringify(value);\n }\n\n /** Bytes of a png or jpeg screenshot. Throws when the result is not one. */\n get image(): Uint8Array {\n try {\n return Uint8Array.from(atob(this.text), (char) => char.charCodeAt(0));\n } catch (cause) {\n throw new DataFuelError(\"result is not a png or jpeg screenshot\", { cause });\n }\n }\n\n /** `data`, or throw when the task carried none. */\n requireData(): unknown {\n if (this.data === undefined || this.data === null) {\n throw new DataFuelError(`result has no data (status ${this.state})`);\n }\n return this.data;\n }\n\n /** Throw TaskFailed, or Blocked, when this task failed. Refunded either way. */\n raiseForStatus(): void {\n if (this.state === \"failed\") {\n throw this.blocked ? new Blocked(this) : new TaskFailed(this);\n }\n }\n}\n\n/** One crawled page: where it was found, plus the scrape result. */\nexport class CrawlPage extends Result {\n readonly url: string;\n readonly depth: number;\n readonly taskId: string | undefined;\n\n constructor(raw: Record<string, unknown>) {\n super(raw);\n this.url = str(raw.url) ?? \"\";\n this.depth = num(raw.depth) ?? 0;\n this.taskId = str(raw.task_id);\n }\n}\n\n/** One discovered URL. */\nexport interface Link {\n url: string;\n /** \"sitemap\" or \"page\". */\n source: string;\n /** Page links only. */\n title?: string;\n /** Sitemap links only. */\n lastmod?: string;\n}\n\n/**\n * What `map` found.\n *\n * `reason` says why `links` is empty: page_blocked, page_error,\n * page_unreachable, no_links_on_page (try scrape with jsRendering), no_sitemap,\n * sitemap_no_entries, search_no_match.\n */\nexport interface SiteMap {\n url: string;\n links: Link[];\n total: number;\n /** `limit` or the time budget cut the list. */\n truncated: boolean;\n sitemaps: string[];\n page_status_code: number;\n reason?: string;\n credits: number;\n /** Envelope of the underlying task. */\n task: Result;\n}\n\n/** Progress of a crawl. */\nexport interface CrawlStatus {\n status: Status;\n /** Empty while the crawl still grows: max_pages, max_depth_exhausted, insufficient_credits, cancelled. */\n stop_reason?: string;\n pages: { discovered: number; enqueued: number; done: number; failed: number; skipped: number };\n depth_reached: number;\n /**\n * Charged at queue time; refunds of failed pages are not subtracted. Sum\n * `creditsUsed` over the pages for the net figure.\n */\n total_cost: number;\n /** Whether the crawl reached a final state. */\n done: boolean;\n /** RFC 3339. */\n created_at?: string;\n updated_at?: string;\n}\n\n/** One page of crawl results. */\nexport interface CrawlResultsPage {\n pages: CrawlPage[];\n /** Absent on the last page. */\n nextCursor?: string;\n}\n\n/** A finished crawl: why it stopped and what it found. */\nexport interface CrawlResult {\n id: string;\n status: CrawlStatus;\n pages: CrawlPage[];\n}\n\n/** Progress of a job. */\nexport interface JobStatus {\n status: Status;\n tasks_count: number;\n tasks_done: number;\n tasks_remaining: number;\n total_cost: number;\n done: boolean;\n}\n\n/** A cancelled job or crawl: its final progress and what was refunded. */\nexport interface CancelResult extends JobStatus {\n refunded_tasks: number;\n refunded_credits: number;\n}\n\n/** Every task of a job. A job completes even when some of its tasks failed. */\nexport interface JobResults {\n id: string;\n tasks_count: number;\n tasks_failed: number;\n tasks_complete: number;\n tasks: Result[];\n}\n\n/** A task type, as the list and analytics filters take it. */\nexport type TaskType = \"unlocker\" | \"llm_scraping\" | \"serp\" | \"map\" | \"crawl\" | (string & {});\n\n/** Filters shared by {@link DataFuel.listJobs} and {@link DataFuel.listTasks}. */\nexport interface ListOptions {\n status?: Status;\n type?: TaskType;\n /** Created on or after this day (UTC). A Date is sent as its UTC day. */\n startDate?: string | Date;\n /** Created on or before this day (UTC, inclusive). */\n endDate?: string | Date;\n /** Items per page. API default 50, max 200. */\n limit?: number;\n /** `nextCursor` of the previous page. */\n cursor?: string;\n}\n\n/** {@link ListOptions} plus the job or crawl the tasks belong to. */\nexport interface ListTasksOptions extends ListOptions {\n jobId?: string;\n}\n\n/** A job or crawl in a list, with the same counters as {@link JobStatus}. */\nexport interface JobSummary extends JobStatus {\n id: string;\n /** `crawl` for a crawl, otherwise the task type of the batch. */\n type: TaskType;\n /** RFC 3339. */\n created_at: string;\n updated_at: string;\n}\n\n/** One page of jobs, newest first. */\nexport interface JobsPage {\n jobs: JobSummary[];\n /** Absent on the last page. */\n nextCursor?: string;\n}\n\n/** A task in a list. It has no result: fetch that with {@link DataFuel.getTask}. */\nexport interface TaskSummary {\n id: string;\n /** `null` for a task created on its own rather than by a job or crawl. */\n job_id: string | null;\n type: TaskType;\n status: Status;\n /** Absent for `llm_scraping` and `serp`. */\n url?: string;\n /** Charged when queued; a failed task is refunded. */\n credit_cost: number;\n /** RFC 3339. */\n created_at: string;\n processed_at?: string;\n failed_at?: string;\n}\n\n/** One page of tasks, newest first. */\nexport interface TasksPage {\n tasks: TaskSummary[];\n /** Absent on the last page. */\n nextCursor?: string;\n}\n\n/** What moved credits on the account. */\nexport type TransactionOperation =\n | \"plan_assignment\"\n | \"purchase\"\n | \"usage\"\n | \"refund\"\n | \"topup\"\n | \"expiry\"\n | \"adjustment\"\n | (string & {});\n\n/** Filters and paging for {@link DataFuel.transactions}. */\nexport interface TransactionsOptions {\n operation?: TransactionOperation;\n startDate?: string | Date;\n endDate?: string | Date;\n /** 1-based. API default 1. */\n page?: number;\n /** API default 10, max 200. */\n limit?: number;\n}\n\n/** One credit movement. `amount` is negative for usage and expiry. */\nexport interface Transaction {\n id: number;\n amount: number;\n /** The part of `amount` that moved plan credits, same sign; the rest moved pay-as-you-go credits. */\n plan_amount?: number;\n operation: TransactionOperation;\n /** What `reference_id` points to, e.g. `task_id` or `job_id`. */\n reference_type: string;\n reference_id: string;\n /** The balance right after this movement. */\n balance_after?: number;\n /** RFC 3339. */\n created_at: string;\n}\n\n/** Total of one operation over the whole filtered range, not just the page. */\nexport interface TransactionSum {\n operation: TransactionOperation;\n total: number;\n count: number;\n}\n\n/** One page of credit movements, newest first. */\nexport interface TransactionsPage {\n transactions: Transaction[];\n /** Movements matching the filters across all pages. */\n total_count: number;\n sums: TransactionSum[];\n}\n\n/** Range and grouping for {@link DataFuel.analytics}. */\nexport interface AnalyticsOptions {\n /** API default 30 days ago. The range may span at most 365 days. */\n startDate?: string | Date;\n /** Inclusive. API default today. */\n endDate?: string | Date;\n /** Time series bucket. API default `daily`. */\n interval?: \"hourly\" | \"daily\" | \"weekly\" | \"monthly\";\n /** Restrict to one task type. */\n module?: TaskType;\n}\n\n/** Task counts and net credits of one slice. Failed tasks are refunded and count 0 credits. */\nexport interface AnalyticsCounts {\n total: number;\n completed: number;\n failed: number;\n credits_used: number;\n}\n\n/** Tasks by the HTTP status the target answered. `status_code` 0 means no answer (timeout, DNS). */\nexport interface StatusCodeBreakdown {\n status_code: number;\n count: number;\n completed: number;\n failed: number;\n credits_used: number;\n avg_credits_per_request: number;\n}\n\n/** The same figures for the equally long period before, and the change in percent. */\nexport interface PreviousPeriod {\n credits_used: number;\n fulfilled_requests: number;\n failed_requests: number;\n failed_percentage: number;\n efficiency_score: number;\n credits_used_change: number;\n fulfilled_requests_change: number;\n failed_requests_change: number;\n efficiency_score_change: number;\n}\n\n/** Usage over a date range. Percentages are 0-100. */\nexport interface Analytics {\n summary: {\n total_tasks: number;\n credits_used: number;\n fulfilled_requests: number;\n failed_requests: number;\n failed_percentage: number;\n success_rate: number;\n efficiency_score: number;\n avg_credits_per_request: number;\n avg_duration_ms: number;\n previous_period?: PreviousPeriod | null;\n };\n timeseries: (AnalyticsCounts & { period: string })[];\n by_module: (AnalyticsCounts & {\n module: string;\n success_rate: number;\n avg_credits_per_request: number;\n avg_duration_ms: number;\n status_codes: StatusCodeBreakdown[];\n })[];\n top_targets: (AnalyticsCounts & { target: string })[];\n by_status_code: StatusCodeBreakdown[];\n}\n\n/**\n * Credits by pool. Plan credits are spent first, roll over when the plan renews and\n * expire if it is not renewed. Pay-as-you-go credits come from credit packs, are spent\n * after plan credits and never expire.\n */\nexport interface BalanceSplit {\n /** Total spendable credits: `plan_balance` plus `payg_balance`. */\n balance: number;\n plan_balance: number;\n payg_balance: number;\n}\n\n/** The account behind the API key. */\nexport interface Profile {\n email: string;\n username: string;\n current_concurrency: number;\n concurrency_limit: number;\n /** Total spendable credits: `plan_credit_balance` plus `payg_credit_balance`. */\n credit_balance: number;\n /** Spent first; expire if the plan is not renewed. */\n plan_credit_balance?: number;\n /** Spent after plan credits; never expire. */\n payg_credit_balance?: number;\n monthly_credit_limit: number;\n}\n\n/** One argument of a browser action. */\nexport interface JsInstructionArg {\n name: string;\n type: string;\n values?: string[];\n required: boolean;\n}\n\n/** One browser action `jsInstructions` accepts. */\nexport interface JsInstruction {\n action: string;\n description: string;\n /** Shape of the value: scalar, array or object. */\n value: string;\n args: JsInstructionArg[];\n /** Whether it can target an element inside an iframe. */\n iframe: boolean;\n example: unknown;\n}\n\n/** An LLM provider `ai.provider` accepts, with the models `ai.model` accepts for it. */\nexport interface AIProvider {\n name: string;\n models: string[];\n}\n\n/** The anti-bot protection in front of one host and path, from `checkProtection`. */\nexport interface ProtectionCheck {\n host: string;\n path: string;\n /** cloudflare, cloudflare_5sec, akamai, imperva, perimeterx or unprotected. */\n protection_type: string;\n}\n\n/** The state of the API. `checks` is filled by a deep check only, keyed by dependency. */\nexport interface Health {\n status: \"ok\" | \"degraded\" | (string & {});\n checks?: Record<string, { status: \"ok\" | \"fail\" | (string & {}); latency_ms: number }>;\n /** Whether the API can serve requests. */\n ok: boolean;\n}\n\n/** A named proxy location: a city, or an ASN. */\nexport interface ProxyLocation {\n code: string;\n name: string;\n}\n\n/** A proxy country with its regions and their cities. */\nexport interface ProxyCountry {\n code: string;\n name: string;\n regions: { code: string; name: string; cities: ProxyLocation[] }[];\n}\n\n/** One task type or LLM engine, and whether it accepts new work. */\nexport interface Capability {\n name: string;\n enabled: boolean;\n /** Operator's note when switched off. */\n reason?: string;\n}\n\n/** What the API accepts right now. */\nexport class Capabilities {\n readonly modules: Capability[];\n readonly engines: Capability[];\n\n constructor(raw: Record<string, unknown>) {\n this.modules = Array.isArray(raw.modules) ? (raw.modules as Capability[]) : [];\n this.engines = Array.isArray(raw.engines) ? (raw.engines as Capability[]) : [];\n }\n\n /** Whether a task type accepts work. Unknown names report false. */\n moduleEnabled(name: string): boolean {\n return this.modules.some((item) => item.name === name && item.enabled);\n }\n\n /** Whether an LLM engine accepts work. Unknown names report false. */\n engineEnabled(name: Engine | string): boolean {\n return this.engines.some((item) => item.name === name && item.enabled);\n }\n}\n\nfunction str(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\nfunction num(value: unknown): number | undefined {\n return typeof value === \"number\" ? value : undefined;\n}\n","/** The client. It only moves bytes; `core` decides what goes on the wire. */\n\nimport * as core from \"./core.js\";\nimport type { AskOptions, CrawlOptions, MapOptions, SearchOptions } from \"./core.js\";\nimport { apiError, DataFuelError, NoApiKey, TransportError, WaitTimeout } from \"./errors.js\";\nimport type {\n AIProvider,\n Analytics,\n AnalyticsOptions,\n BalanceSplit,\n CallOptions,\n CancelResult,\n Capability,\n CrawlResult,\n CrawlResultsPage,\n CrawlStatus,\n Health,\n JobResults,\n JobsPage,\n JobStatus,\n JobSummary,\n JsInstruction,\n ListOptions,\n ListTasksOptions,\n Profile,\n ProtectionCheck,\n ProxyCountry,\n ProxyLocation,\n ScrapeOptions,\n SiteMap,\n TasksPage,\n TaskSummary,\n TransactionsOptions,\n TransactionsPage,\n} from \"./models.js\";\nimport { Capabilities, CrawlPage, isDone, Result } from \"./models.js\";\n\n/** How to build the client. */\nexport interface ClientOptions {\n /** Falls back to `process.env.DATAFUEL_API_KEY`. */\n apiKey?: string;\n baseUrl?: string;\n /** Milliseconds. `null` disables the bound; scrape blocks until the page is ready. */\n timeoutMs?: number | null;\n /** Retries after a network error or a 429/502/503/504 answer. Default 2. */\n maxRetries?: number;\n /** How often `waitJob` and `waitCrawl` poll. Default 2000ms. */\n pollIntervalMs?: number;\n /** Prefixes the SDK User-Agent with your application's. */\n userAgent?: string;\n /** Swap the fetch implementation, e.g. in tests. */\n fetch?: typeof globalThis.fetch;\n}\n\ntype Send = CallOptions & { timeoutMs?: number; signal?: AbortSignal };\n\n/**\n * Client for the DataFuel scraping API.\n *\n * ```ts\n * const df = new DataFuel(); // reads DATAFUEL_API_KEY\n * const markdown = await df.markdown(\"https://example.com\");\n * ```\n *\n * Pick the call by the shape of the work: one URL is {@link scrape}, a site's\n * URL list is {@link map}, many pages from a start URL is {@link crawl}, a list\n * of known URLs is {@link runJob}, a question for an AI engine is {@link ask}, a\n * Google search is {@link search}.\n *\n * Every write carries an `Idempotency-Key`, generated per request, so a retry\n * attaches to the task already running instead of charging twice.\n */\nexport class DataFuel {\n readonly baseUrl: string;\n readonly timeoutMs: number | null;\n readonly maxRetries: number;\n readonly pollIntervalMs: number;\n readonly userAgent: string;\n private readonly apiKey: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n\n constructor(options: ClientOptions | string = {}) {\n const opts: ClientOptions = typeof options === \"string\" ? { apiKey: options } : options;\n this.apiKey = opts.apiKey ?? envApiKey() ?? \"\";\n this.baseUrl = (opts.baseUrl ?? core.DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeoutMs = opts.timeoutMs === undefined ? core.DEFAULT_TIMEOUT_MS : opts.timeoutMs;\n this.maxRetries = Math.max(opts.maxRetries ?? 2, 0);\n // A non-positive interval would poll in a tight loop against the API.\n this.pollIntervalMs =\n opts.pollIntervalMs !== undefined && opts.pollIntervalMs > 0 ? opts.pollIntervalMs : 2_000;\n const sdk = `datafuel-js/${core.VERSION}`;\n this.userAgent = opts.userAgent ? `${opts.userAgent} ${sdk}` : sdk;\n // Bound: a detached fetch throws \"Illegal invocation\" in browsers and\n // workers, even though Node tolerates it.\n this.fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n // --- transport ---------------------------------------------------------\n\n /** Pause between attempts. Overridable so tests need not wait in real time. */\n protected sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private async send(request: core.Request, opts: Send = {}): Promise<unknown> {\n if (!this.apiKey && request.auth) {\n throw new NoApiKey(\"no API key: pass one to the client or set DATAFUEL_API_KEY\");\n }\n const url = new URL(this.baseUrl + request.path);\n for (const [name, value] of Object.entries(request.params ?? {})) {\n url.searchParams.set(name, value);\n }\n const init: RequestInit = {\n method: request.method,\n headers: core.headers(this.apiKey, this.userAgent, request),\n // Redirects stay off: a redirect to another host would carry X-API-Key\n // to it, since fetch does not strip custom headers.\n redirect: \"manual\",\n };\n if (request.body !== undefined) init.body = JSON.stringify(request.body);\n\n for (let attempt = 0; ; attempt++) {\n let error: unknown;\n try {\n const signal = this.signalFor(opts);\n // Detached on purpose: calling `this.fetchImpl(...)` would invoke it as\n // a method of the client, and a fetch bound to another receiver (or\n // none) throws \"Illegal invocation\".\n const send = this.fetchImpl;\n const response = await send(url, signal ? { ...init, signal } : init);\n return await parse(response, request.degradedOk);\n } catch (caught) {\n if (isAbort(caught)) {\n throw new TransportError(\"the request was aborted or timed out\", { cause: caught });\n }\n error =\n caught instanceof DataFuelError\n ? caught\n : new TransportError(String(caught), {\n cause: caught,\n });\n }\n const retryAfter =\n error instanceof Object && \"retryAfter\" in error ? Number(error.retryAfter) : 0;\n if (attempt >= this.maxRetries || !request.retryable || !core.shouldRetry(error)) throw error;\n await this.sleep(core.backoff(attempt, retryAfter));\n }\n }\n\n private signalFor(opts: Send): AbortSignal | undefined {\n const budget = opts.timeoutMs ?? this.timeoutMs;\n const timeout =\n budget === null || budget === undefined ? undefined : AbortSignal.timeout(budget);\n if (timeout && opts.signal) return AbortSignal.any([timeout, opts.signal]);\n return timeout ?? opts.signal;\n }\n\n /**\n * Send a task and wait for its result.\n *\n * On a 202 the API is still working: the identical request goes out again\n * under the identical idempotency key, so it attaches to the running task\n * rather than starting a second one.\n */\n private async runTask(request: core.Request, opts: Send): Promise<Result> {\n const budget = opts.timeoutMs ?? this.timeoutMs ?? core.DEFAULT_TIMEOUT_MS;\n const deadline = Date.now() + budget;\n let body: unknown;\n for (let attempt = 0; ; attempt++) {\n body = await this.send(request, opts);\n if (!core.stillProcessing(body)) break;\n const delay = core.pollDelay(attempt);\n if (Date.now() + delay >= deadline) {\n throw new WaitTimeout(\n \"the task is still processing; re-send under the same idempotency key to pick it up\",\n request.idempotencyKey,\n );\n }\n await this.sleep(delay);\n }\n const result = new Result(record(body));\n result.raiseForStatus();\n return result;\n }\n\n // --- pages -------------------------------------------------------------\n\n /**\n * Fetch one URL and wait for the result.\n *\n * Throws {@link Blocked} when the target refused the request and\n * {@link TaskFailed} otherwise; both carry `.result`.\n */\n async scrape(url: string, options: ScrapeOptions & CallOptions = {}): Promise<Result> {\n const request = core.buildScrape(url, options, options.proxy, core.key(options.idempotencyKey));\n return this.runTask(request, options);\n }\n\n /** The one-liner: the page as LLM-ready markdown, images dropped. */\n async markdown(url: string, options: ScrapeOptions & CallOptions = {}): Promise<string> {\n const result = await this.scrape(url, { ...options, format: \"markdown\", includeImages: false });\n return result.text;\n }\n\n /**\n * Return a task by id, e.g. one created by a job or a crawl.\n *\n * A task that is still running comes back with `pending` true.\n */\n async getTask(taskId: string, options: CallOptions = {}): Promise<Result> {\n const body = await this.send(\n new core.Request(\"GET\", `/task/${core.pathSegment(taskId)}`),\n options,\n );\n if (core.stillProcessing(body)) return new Result({ id: taskId, status: \"processing\" });\n const result = new Result(record(body));\n result.raiseForStatus();\n return result;\n }\n\n /** Send a prompt to an AI engine and return its answer. */\n async ask(prompt: string, options: AskOptions & CallOptions): Promise<Result> {\n const request = core.buildAsk(prompt, options, core.key(options.idempotencyKey));\n return this.runTask(request, options);\n }\n\n /** Run a Google search and return the results page, parsed to JSON by default. */\n async search(query: string, options: SearchOptions & CallOptions = {}): Promise<Result> {\n const request = core.buildSearch(query, options, core.key(options.idempotencyKey));\n return this.runTask(request, options);\n }\n\n /**\n * List the URLs of a site without scraping them.\n *\n * One credit per call on a Basic proxy, however many links come back. Use it\n * before a crawl to see how big a section is.\n */\n async map(url: string, options: MapOptions & CallOptions = {}): Promise<SiteMap> {\n const request = core.buildMap(url, options, options.proxy, core.key(options.idempotencyKey));\n const task = await this.runTask(request, options);\n const data = record(task.requireData()) as unknown as SiteMap;\n return { ...data, links: data.links ?? [], sitemaps: data.sitemaps ?? [], task };\n }\n\n // --- crawl -------------------------------------------------------------\n\n /**\n * Queue a crawl and return its id immediately.\n *\n * Follows links from the start URL and scrapes every page. Pages are charged\n * like single scrapes when they are queued; failed and blocked pages are\n * refunded. Unset limits use the API defaults: 100 pages, depth 3, 5 in flight.\n */\n async startCrawl(url: string, options: CrawlOptions & CallOptions = {}): Promise<string> {\n const request = core.buildCrawl(url, options, options.proxy, core.key(options.idempotencyKey));\n return strField(await this.send(request, options), \"job_id\");\n }\n\n /**\n * Stop a crawl. Queued pages are refunded, pages in flight finish and bill.\n * Throws {@link JobNotCancellable} when it already finished.\n */\n async cancelCrawl(crawlId: string, options: CallOptions = {}): Promise<CancelResult> {\n return cancelResult(\n await this.send(\n new core.Request(\"POST\", `/crawl/${core.pathSegment(crawlId)}/cancel`),\n options,\n ),\n );\n }\n\n /** Return the progress of a crawl. */\n async getCrawl(crawlId: string, options: CallOptions = {}): Promise<CrawlStatus> {\n const body = record(\n await this.send(new core.Request(\"GET\", `/crawl/${core.pathSegment(crawlId)}`), options),\n );\n const raw = body as unknown as Partial<CrawlStatus>;\n return {\n ...raw,\n status: raw.status as CrawlStatus[\"status\"],\n // Counters the caller reads unconditionally must exist even on a thin answer.\n pages: {\n discovered: 0,\n enqueued: 0,\n done: 0,\n failed: 0,\n skipped: 0,\n ...(raw.pages ?? {}),\n },\n depth_reached: raw.depth_reached ?? 0,\n total_cost: raw.total_cost ?? 0,\n done: isDone(raw.status),\n };\n }\n\n /** One page of results, in discovery order. `limit` unset uses the API default. */\n async crawlResults(\n crawlId: string,\n options: CallOptions & { cursor?: string; limit?: number } = {},\n ): Promise<CrawlResultsPage> {\n const body = record(\n await this.send(core.crawlResultsRequest(crawlId, options.cursor, options.limit), options),\n );\n const pages = Array.isArray(body.pages) ? body.pages : [];\n const next = typeof body.next_cursor === \"string\" ? body.next_cursor : undefined;\n return {\n pages: pages.map((page) => new CrawlPage(record(page))),\n ...(next ? { nextCursor: next } : {}),\n };\n }\n\n /**\n * Walk every page of a crawl, fetching result pages as needed.\n *\n * Readable while the crawl runs; unfinished pages report `pending`.\n */\n async *crawlPages(\n crawlId: string,\n options: CallOptions & { limit?: number } = {},\n ): AsyncGenerator<CrawlPage> {\n let cursor: string | undefined;\n const seen = new Set<string>();\n for (;;) {\n const batch = await this.crawlResults(crawlId, { ...options, ...(cursor ? { cursor } : {}) });\n yield* batch.pages;\n cursor = batch.nextCursor;\n if (!cursor) return;\n if (seen.has(cursor)) {\n throw new DataFuelError(\"the API repeated a crawl cursor; stopping to avoid a loop\");\n }\n seen.add(cursor);\n }\n }\n\n /** Poll until the crawl is done. Without `timeoutMs` it waits indefinitely. */\n async waitCrawl(crawlId: string, options: CallOptions = {}): Promise<CrawlStatus> {\n // The timeout bounds the whole wait, not each poll.\n const { timeoutMs, ...perPoll } = options;\n const deadline = timeoutMs === undefined ? null : Date.now() + timeoutMs;\n for (;;) {\n const status = await this.getCrawl(crawlId, perPoll);\n if (status.done) return status;\n if (deadline !== null && Date.now() + this.pollIntervalMs >= deadline) {\n throw new WaitTimeout(`crawl ${crawlId} is still running`, crawlId, status);\n }\n await this.sleep(this.pollIntervalMs);\n }\n }\n\n /**\n * Start a crawl, wait for it, and return every page.\n *\n * Check `stop_reason`: `insufficient_credits` means it ended early. For large\n * crawls prefer {@link startCrawl} + {@link waitCrawl} + {@link crawlPages},\n * which stream instead of holding every page in memory. On {@link WaitTimeout}\n * the error carries the id: the crawl keeps running and billing.\n */\n async crawl(url: string, options: CrawlOptions & CallOptions = {}): Promise<CrawlResult> {\n const id = await this.startCrawl(url, options);\n const status = await this.waitCrawl(id, options);\n const pages: CrawlPage[] = [];\n for await (const page of this.crawlPages(id, options)) pages.push(page);\n return { id, status, pages };\n }\n\n // --- jobs --------------------------------------------------------------\n\n /**\n * Queue a batch of known URLs and return the job id.\n *\n * Cheaper and more predictable than a crawl when you already have the URLs.\n * `sequential` runs them one after the other; the default runs them\n * concurrently, bounded by the account's concurrency limit.\n */\n async createJob(\n urls: string[],\n options: ScrapeOptions & CallOptions & { sequential?: boolean } = {},\n ): Promise<string> {\n const request = core.buildJob(\n urls,\n options,\n options.proxy,\n options.sequential ?? false,\n core.key(options.idempotencyKey),\n );\n return strField(await this.send(request, options), \"id\");\n }\n\n /** Queue a batch of prompts for an AI engine and return the job id. */\n async createAskJob(\n prompts: string[],\n options: AskOptions & CallOptions & { sequential?: boolean },\n ): Promise<string> {\n const request = core.buildAskJob(\n prompts,\n options,\n options.sequential ?? false,\n core.key(options.idempotencyKey),\n );\n return strField(await this.send(request, options), \"id\");\n }\n\n /** Queue a batch of Google searches and return the job id. */\n async createSearchJob(\n queries: string[],\n options: SearchOptions & CallOptions & { sequential?: boolean } = {},\n ): Promise<string> {\n const request = core.buildSearchJob(\n queries,\n options,\n options.sequential ?? false,\n core.key(options.idempotencyKey),\n );\n return strField(await this.send(request, options), \"id\");\n }\n\n /** Return the progress of a job. */\n async getJob(jobId: string, options: CallOptions = {}): Promise<JobStatus> {\n return jobStatus(\n await this.send(new core.Request(\"GET\", `/job/${core.pathSegment(jobId)}`), options),\n );\n }\n\n /**\n * Stop a job. Queued tasks are refunded, tasks in flight finish and bill.\n * Throws {@link JobNotCancellable} when it already finished.\n */\n async cancelJob(jobId: string, options: CallOptions = {}): Promise<CancelResult> {\n return cancelResult(\n await this.send(new core.Request(\"POST\", `/job/${core.pathSegment(jobId)}/cancel`), options),\n );\n }\n\n /**\n * Return the per-task results of a job.\n *\n * A job completes even when some of its tasks failed: check `task.ok` or call\n * `task.raiseForStatus()` per task.\n */\n async jobResults(jobId: string, options: CallOptions = {}): Promise<JobResults> {\n const body = record(\n await this.send(new core.Request(\"GET\", `/job/${core.pathSegment(jobId)}/results`), options),\n );\n const tasks = Array.isArray(body.tasks_result) ? body.tasks_result : [];\n return {\n id: jobId,\n tasks_count: Number(body.tasks_count ?? 0),\n tasks_failed: Number(body.tasks_failed ?? 0),\n tasks_complete: Number(body.tasks_complete ?? 0),\n tasks: tasks.map((task) => new Result(record(task))),\n };\n }\n\n /** One page of your jobs and crawls, newest first. Pass `nextCursor` back as `cursor`. */\n async listJobs(options: ListOptions & CallOptions = {}): Promise<JobsPage> {\n const body = record(await this.send(core.listJobsRequest(options), options));\n const next = typeof body.next_cursor === \"string\" ? body.next_cursor : undefined;\n return {\n jobs: array(body.jobs).map((raw) => {\n const job = record(raw) as unknown as JobSummary;\n return { ...job, ...jobStatus(job) };\n }),\n ...(next ? { nextCursor: next } : {}),\n };\n }\n\n /**\n * One page of your tasks, newest first, including those of jobs and crawls.\n * Items carry no result: fetch it with {@link getTask}.\n */\n async listTasks(options: ListTasksOptions & CallOptions = {}): Promise<TasksPage> {\n const body = record(await this.send(core.listTasksRequest(options), options));\n const next = typeof body.next_cursor === \"string\" ? body.next_cursor : undefined;\n return {\n tasks: array(body.tasks).map((raw) => {\n const task = record(raw) as unknown as TaskSummary;\n return { ...task, job_id: task.job_id ?? null };\n }),\n ...(next ? { nextCursor: next } : {}),\n };\n }\n\n /** Poll until the job is done. Without `timeoutMs` it waits indefinitely. */\n async waitJob(jobId: string, options: CallOptions = {}): Promise<JobStatus> {\n // The timeout bounds the whole wait, not each poll.\n const { timeoutMs, ...perPoll } = options;\n const deadline = timeoutMs === undefined ? null : Date.now() + timeoutMs;\n for (;;) {\n const status = await this.getJob(jobId, perPoll);\n if (status.done) return status;\n if (deadline !== null && Date.now() + this.pollIntervalMs >= deadline) {\n throw new WaitTimeout(`job ${jobId} is still running`, jobId, status);\n }\n await this.sleep(this.pollIntervalMs);\n }\n }\n\n /** Create a job, wait for it, and return its results. */\n async runJob(\n urls: string[],\n options: ScrapeOptions & CallOptions & { sequential?: boolean } = {},\n ): Promise<JobResults> {\n const id = await this.createJob(urls, options);\n await this.waitJob(id, options);\n return this.jobResults(id, options);\n }\n\n /** Create a prompt job, wait for it, and return its results. */\n async runAskJob(\n prompts: string[],\n options: AskOptions & CallOptions & { sequential?: boolean },\n ): Promise<JobResults> {\n const id = await this.createAskJob(prompts, options);\n await this.waitJob(id, options);\n return this.jobResults(id, options);\n }\n\n /** Create a search job, wait for it, and return its results. */\n async runSearchJob(\n queries: string[],\n options: SearchOptions & CallOptions & { sequential?: boolean } = {},\n ): Promise<JobResults> {\n const id = await this.createSearchJob(queries, options);\n await this.waitJob(id, options);\n return this.jobResults(id, options);\n }\n\n // --- account -----------------------------------------------------------\n\n /** Which task types and LLM engines are switched on right now. Needs no key. */\n async capabilities(options: CallOptions = {}): Promise<Capabilities> {\n const request = new core.Request(\n \"GET\",\n \"/config/capabilities\",\n undefined,\n undefined,\n undefined,\n false,\n );\n return new Capabilities(record(await this.send(request, options)));\n }\n\n /** The browser actions `jsInstructions` accepts, with their arguments. Needs no key. */\n async jsInstructions(options: CallOptions = {}): Promise<JsInstruction[]> {\n const request = new core.Request(\n \"GET\",\n \"/config/js-instructions\",\n undefined,\n undefined,\n undefined,\n false,\n );\n const body = record(await this.send(request, options));\n return Array.isArray(body.instructions) ? (body.instructions as JsInstruction[]) : [];\n }\n\n /** The LLM providers and models `ai` accepts. Needs no key. */\n async aiProviders(options: CallOptions = {}): Promise<AIProvider[]> {\n const request = new core.Request(\n \"GET\",\n \"/config/ai-providers\",\n undefined,\n undefined,\n undefined,\n false,\n );\n const body = record(await this.send(request, options));\n return Array.isArray(body.providers) ? (body.providers as AIProvider[]) : [];\n }\n\n /**\n * Whether the API is up. `deep` also checks the dependencies it needs to\n * serve scrapes. A degraded report is returned, not thrown: read `ok`.\n * Needs no key.\n */\n async health(options: CallOptions & { deep?: boolean } = {}): Promise<Health> {\n const body = record(await this.send(core.healthRequest(options.deep ?? false), options));\n return { ...(body as unknown as Health), ok: body.status === \"ok\" };\n }\n\n /**\n * Which anti-bot protection sits in front of each URL. Nothing is scraped\n * and nothing is charged; invalid URLs are skipped.\n */\n async checkProtection(urls: string[], options: CallOptions = {}): Promise<ProtectionCheck[]> {\n return list(\n await this.send(new core.Request(\"POST\", \"/filter/check\", undefined, [...urls]), options),\n ) as ProtectionCheck[];\n }\n\n /** Countries, regions and cities a proxy type can exit from. */\n async proxyLocations(\n options: CallOptions & { proxyType?: string } = {},\n ): Promise<ProxyCountry[]> {\n const params = options.proxyType ? { proxy_type: options.proxyType } : undefined;\n return list(\n await this.send(new core.Request(\"GET\", \"/config/proxy/locations\", params), options),\n ) as ProxyCountry[];\n }\n\n /** ASNs a proxy type can exit from in one country (ISO 3166-1 alpha-2). */\n async proxyAsns(\n country: string,\n options: CallOptions & { proxyType?: string } = {},\n ): Promise<ProxyLocation[]> {\n const params: Record<string, string> = { country };\n if (options.proxyType) params.proxy_type = options.proxyType;\n return list(\n await this.send(new core.Request(\"GET\", \"/config/proxy/asn\", params), options),\n ) as ProxyLocation[];\n }\n\n /** Remaining credits: plan and pay-as-you-go together. */\n async balance(options: CallOptions = {}): Promise<number> {\n const body = await this.send(new core.Request(\"GET\", \"/users/@me/balance\"), options);\n return intField(body, \"balance\");\n }\n\n /** Remaining credits by pool: plan credits (spent first) and pay-as-you-go credits. */\n async balanceSplit(options: CallOptions = {}): Promise<BalanceSplit> {\n const body = await this.send(new core.Request(\"GET\", \"/users/@me/balance\"), options);\n return {\n balance: intField(body, \"balance\"),\n plan_balance: intField(body, \"plan_balance\"),\n payg_balance: intField(body, \"payg_balance\"),\n };\n }\n\n /**\n * Credit movements, newest first: plan assignments, credit pack purchases, usage, refunds, expiry.\n * `sums` totals each operation over the whole range, not just this page.\n */\n async transactions(options: TransactionsOptions & CallOptions = {}): Promise<TransactionsPage> {\n const body = record(await this.send(core.transactionsRequest(options), options));\n return {\n transactions: array(body.transactions) as TransactionsPage[\"transactions\"],\n total_count: Number(body.total_count ?? 0),\n sums: array(body.sums) as TransactionsPage[\"sums\"],\n };\n }\n\n /** Usage over a date range: totals, a time series and breakdowns. Default: the last 30 days. */\n async analytics(options: AnalyticsOptions & CallOptions = {}): Promise<Analytics> {\n const body = record(await this.send(core.analyticsRequest(options), options));\n return {\n ...(body as unknown as Analytics),\n timeseries: array(body.timeseries) as Analytics[\"timeseries\"],\n by_module: array(body.by_module) as Analytics[\"by_module\"],\n top_targets: array(body.top_targets) as Analytics[\"top_targets\"],\n by_status_code: array(body.by_status_code) as Analytics[\"by_status_code\"],\n };\n }\n\n /** The account behind the API key. */\n async me(options: CallOptions = {}): Promise<Profile> {\n const body = await this.send(new core.Request(\"GET\", \"/users/@me\"), options);\n return record(body) as unknown as Profile;\n }\n\n /**\n * Revoke the current key and return the new one.\n *\n * This is the only time the new key is shown. The client keeps using the\n * revoked one: store the new key and build a new client with it.\n */\n async resetApiKey(options: CallOptions = {}): Promise<string> {\n const body = await this.send(new core.Request(\"POST\", \"/users/@me/api-key/reset\"), options);\n return strField(body, \"api_key\");\n }\n}\n\nexport type { Capability };\n\n/** The API key from the environment, on runtimes that have one. */\nfunction envApiKey(): string | undefined {\n return typeof process !== \"undefined\" ? process.env?.DATAFUEL_API_KEY : undefined;\n}\n\nasync function parse(response: Response, degradedOk = false): Promise<unknown> {\n const text = await response.text();\n let body: unknown;\n if (text.length > 0) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n if (degradedOk && response.status === 503 && isHealthReport(body)) return body;\n if (!response.ok) {\n const header = response.headers.get(\"Retry-After\");\n const retryAfter = header !== null && !Number.isNaN(Number(header)) ? Number(header) : 0;\n throw apiError(response.status, body, retryAfter);\n }\n return body;\n}\n\nfunction isHealthReport(body: unknown): boolean {\n return body !== null && typeof body === \"object\" && \"status\" in body;\n}\n\nfunction isAbort(error: unknown): boolean {\n return error instanceof Error && (error.name === \"AbortError\" || error.name === \"TimeoutError\");\n}\n\n/** Turn a surprise answer into a DataFuelError rather than a TypeError later. */\nfunction record(body: unknown): Record<string, unknown> {\n if (body === null || typeof body !== \"object\" || Array.isArray(body)) {\n throw new DataFuelError(`unexpected answer from the API: ${JSON.stringify(body) ?? \"empty\"}`);\n }\n return body as Record<string, unknown>;\n}\n\nfunction list(body: unknown): unknown[] {\n if (!Array.isArray(body)) {\n throw new DataFuelError(`unexpected answer from the API: ${JSON.stringify(body) ?? \"empty\"}`);\n }\n return body;\n}\n\nfunction array(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction jobStatus(body: unknown): JobStatus {\n const raw = record(body) as unknown as Partial<JobStatus>;\n return {\n status: raw.status as JobStatus[\"status\"],\n tasks_count: raw.tasks_count ?? 0,\n tasks_done: raw.tasks_done ?? 0,\n tasks_remaining: raw.tasks_remaining ?? 0,\n total_cost: raw.total_cost ?? 0,\n done: isDone(raw.status),\n };\n}\n\nfunction cancelResult(body: unknown): CancelResult {\n const raw = record(body) as unknown as Partial<CancelResult>;\n return {\n ...jobStatus(body),\n refunded_tasks: raw.refunded_tasks ?? 0,\n refunded_credits: raw.refunded_credits ?? 0,\n };\n}\n\nfunction field(body: unknown, name: string): unknown {\n const value = record(body)[name];\n if (value === undefined || value === null) {\n throw new DataFuelError(`unexpected answer from the API: no ${name} field`);\n }\n return value;\n}\n\nfunction strField(body: unknown, name: string): string {\n return String(field(body, name));\n}\n\nfunction intField(body: unknown, name: string): number {\n const value = Number(field(body, name));\n if (Number.isNaN(value)) {\n throw new DataFuelError(`unexpected answer from the API: ${name} is not a number`);\n }\n return value;\n}\n"],"mappings":"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","names":["record","query","query"]}