scavio 0.18.1 → 0.19.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.
- package/README.md +49 -3
- package/dist/index.cjs +78 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +143 -1
- package/dist/index.d.ts +143 -1
- package/dist/index.js +77 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/retry.ts","../src/http.ts","../src/rate-limiter.ts","../src/namespaces/amazon.ts","../src/namespaces/google.ts","../src/namespaces/reddit.ts","../src/namespaces/tiktok.ts","../src/namespaces/tiktok-shop.ts","../src/namespaces/instagram.ts","../src/namespaces/walmart.ts","../src/namespaces/youtube.ts","../src/namespaces/x.ts","../src/namespaces/linkedin.ts","../src/namespaces/threads.ts","../src/namespaces/kuaishou.ts","../src/namespaces/ebay.ts","../src/namespaces/target.ts","../src/namespaces/home-depot.ts","../src/namespaces/zillow.ts","../src/namespaces/redfin.ts","../src/namespaces/booking.ts","../src/namespaces/airbnb.ts","../src/namespaces/tripadvisor.ts","../src/namespaces/yelp.ts","../src/namespaces/indeed.ts","../src/namespaces/glassdoor.ts","../src/namespaces/app-store.ts","../src/namespaces/google-play.ts","../src/namespaces/g2.ts","../src/namespaces/capterra.ts","../src/namespaces/sec.ts","../src/namespaces/companies-house.ts","../src/namespaces/google-ads.ts","../src/namespaces/meta-ads.ts","../src/namespaces/costco.ts","../src/client.ts"],"sourcesContent":["export class ScavioError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ScavioError\";\n }\n}\n\nexport class MissingAPIKeyError extends ScavioError {\n constructor() {\n super(\n \"No API key provided. Pass apiKey or set the SCAVIO_API_KEY \" +\n \"environment variable. Get your free key at https://dashboard.scavio.dev\",\n );\n this.name = \"MissingAPIKeyError\";\n }\n}\n\n/** The request could not reach the API (DNS, connection reset, TLS, ...). */\nexport class ScavioConnectionError extends ScavioError {\n constructor(message = \"Connection error\") {\n super(message);\n this.name = \"ScavioConnectionError\";\n }\n}\n\n/** The request did not complete within the configured timeout. */\nexport class ScavioTimeoutError extends ScavioError {\n constructor(message = \"Request timed out\") {\n super(message);\n this.name = \"ScavioTimeoutError\";\n }\n}\n\nexport class InvalidAPIKeyError extends ScavioError {\n public readonly statusCode = 401;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(message = \"Invalid API key\", responseBody?: Record<string, unknown>) {\n super(message);\n this.name = \"InvalidAPIKeyError\";\n this.responseBody = responseBody;\n }\n}\n\nexport class InsufficientCreditsError extends ScavioError {\n public readonly statusCode = 402;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(message = \"Insufficient credits\", responseBody?: Record<string, unknown>) {\n super(message);\n this.name = \"InsufficientCreditsError\";\n this.responseBody = responseBody;\n }\n}\n\n/**\n * The request body failed validation. Raised for HTTP 400 and for HTTP 422,\n * which is what Threads and Kuaishou return when an identifier is missing or\n * conflicting - those routes have no 400. `statusCode` reports whichever the\n * API actually sent.\n */\nexport class BadRequestError extends ScavioError {\n public readonly statusCode: number;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(\n message = \"Bad request\",\n responseBody?: Record<string, unknown>,\n statusCode = 400,\n ) {\n super(message);\n this.name = \"BadRequestError\";\n this.responseBody = responseBody;\n this.statusCode = statusCode;\n }\n}\n\nexport class NotFoundError extends ScavioError {\n public readonly statusCode = 404;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(message = \"Not found\", responseBody?: Record<string, unknown>) {\n super(message);\n this.name = \"NotFoundError\";\n this.responseBody = responseBody;\n }\n}\n\nexport class RateLimitError extends ScavioError {\n public readonly statusCode = 429;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(message = \"Rate limit exceeded\", responseBody?: Record<string, unknown>) {\n super(message);\n this.name = \"RateLimitError\";\n this.responseBody = responseBody;\n }\n}\n\nexport class ScavioAPIError extends ScavioError {\n public readonly statusCode: number;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(\n statusCode: number,\n message: string,\n responseBody?: Record<string, unknown>,\n ) {\n super(`API error ${statusCode}: ${message}`);\n this.name = \"ScavioAPIError\";\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n }\n}\n","/**\n * Retry policy: exponential backoff with full jitter and Retry-After support.\n * Mirrors the Python SDK's RetryConfig.\n */\n\n/** Statuses that are safe to retry: rate limiting plus transient upstream errors. */\nexport const DEFAULT_RETRY_STATUSES: ReadonlySet<number> = new Set([\n 429, 500, 502, 503, 504,\n]);\n\nexport interface RetryConfig {\n /** Additional attempts after the first request. 0 disables retries. */\n maxRetries: number;\n /** Base backoff in seconds; attempt n waits up to baseDelay * 2**n before jitter. */\n baseDelay: number;\n /** Upper bound (seconds) on any single backoff wait. */\n maxDelay: number;\n /** HTTP status codes that trigger a retry. */\n retryStatuses: ReadonlySet<number>;\n}\n\nexport function makeRetryConfig(maxRetries: number): RetryConfig {\n return {\n maxRetries,\n baseDelay: 0.5,\n maxDelay: 8.0,\n retryStatuses: DEFAULT_RETRY_STATUSES,\n };\n}\n\nexport function shouldRetryStatus(\n config: RetryConfig,\n statusCode: number,\n attempt: number,\n): boolean {\n return attempt < config.maxRetries && config.retryStatuses.has(statusCode);\n}\n\nexport function shouldRetryException(\n config: RetryConfig,\n attempt: number,\n): boolean {\n return attempt < config.maxRetries;\n}\n\n/**\n * Seconds to sleep before the next attempt. Honors a Retry-After value when\n * present; otherwise uses exponential backoff with full jitter.\n */\nexport function backoff(\n config: RetryConfig,\n attempt: number,\n retryAfter?: number,\n): number {\n if (retryAfter !== undefined) {\n return Math.min(Math.max(retryAfter, 0), config.maxDelay);\n }\n const capped = Math.min(config.maxDelay, config.baseDelay * 2 ** attempt);\n return Math.random() * capped;\n}\n\n/** Parse a Retry-After header (delta-seconds or HTTP-date) to seconds. */\nexport function parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n const trimmed = header.trim();\n const asNumber = Number(trimmed);\n if (!Number.isNaN(asNumber) && trimmed !== \"\") {\n return asNumber;\n }\n const asDate = Date.parse(trimmed);\n if (!Number.isNaN(asDate)) {\n return Math.max((asDate - Date.now()) / 1000, 0);\n }\n return undefined;\n}\n","import {\n BadRequestError,\n InsufficientCreditsError,\n InvalidAPIKeyError,\n NotFoundError,\n RateLimitError,\n ScavioAPIError,\n ScavioConnectionError,\n ScavioTimeoutError,\n} from \"./errors.js\";\nimport type { RateLimiter } from \"./rate-limiter.js\";\nimport {\n backoff,\n makeRetryConfig,\n parseRetryAfter,\n shouldRetryException,\n shouldRetryStatus,\n type RetryConfig,\n} from \"./retry.js\";\n\nexport const BASE_URL = \"https://api.scavio.dev\";\nexport const DEFAULT_TIMEOUT = 30_000;\nexport const DEFAULT_MAX_RETRIES = 2;\n\n// Injected from package.json at build time (tsup and vitest `define`), so the\n// version string can never drift from the published package.\ndeclare const __SCAVIO_JS_VERSION__: string;\n\nexport const SDK_VERSION: string =\n typeof __SCAVIO_JS_VERSION__ === \"string\" ? __SCAVIO_JS_VERSION__ : \"0.0.0\";\n\nexport const USER_AGENT = `scavio-js/${SDK_VERSION}`;\n\n// Browsers refuse (or silently drop) a script-set User-Agent, so it is only\n// sent from server runtimes. X-Client-Source identifies the SDK everywhere.\nexport function isServerRuntime(): boolean {\n const g = globalThis as {\n process?: { versions?: { node?: string } };\n window?: unknown;\n document?: unknown;\n };\n if (typeof g.window !== \"undefined\" && typeof g.document !== \"undefined\") {\n return false;\n }\n return typeof g.process?.versions?.node === \"string\";\n}\n\nexport function buildHeaders(apiKey: string): Record<string, string> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n \"X-Client-Source\": \"scavio-js\",\n };\n if (isServerRuntime()) {\n headers[\"User-Agent\"] = USER_AGENT;\n }\n return headers;\n}\n\nfunction stripUndefined(\n obj: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\nfunction handleError(statusCode: number, body: Record<string, unknown>): never {\n let error = body.error ?? \"Unknown error\";\n if (typeof error === \"object\" && error !== null && \"message\" in error) {\n error = (error as { message: string }).message;\n }\n const msg = String(error);\n const responseBody = Object.keys(body).length > 0 ? body : undefined;\n\n // 422 is Threads' and Kuaishou's validation status - those routes have no\n // 400 - so it maps to BadRequestError too and a caller catching one class\n // handles validation failures on every platform.\n if (statusCode === 400 || statusCode === 422) {\n throw new BadRequestError(msg, responseBody, statusCode);\n }\n if (statusCode === 401) throw new InvalidAPIKeyError(msg, responseBody);\n if (statusCode === 402) throw new InsufficientCreditsError(msg, responseBody);\n if (statusCode === 404) throw new NotFoundError(msg, responseBody);\n if (statusCode === 429) throw new RateLimitError(msg, responseBody);\n throw new ScavioAPIError(statusCode, msg, responseBody);\n}\n\nfunction sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, seconds * 1000));\n}\n\nfunction isAbortError(err: unknown): boolean {\n return (\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\")\n );\n}\n\nfunction getHeader(response: Response, name: string): string | null {\n const headers = response.headers;\n if (headers && typeof headers.get === \"function\") {\n return headers.get(name);\n }\n return null;\n}\n\nexport async function request(options: {\n method: \"GET\" | \"POST\";\n path: string;\n apiKey: string;\n baseUrl: string;\n timeout: number;\n rateLimiter: RateLimiter;\n body?: Record<string, unknown>;\n maxRetries?: number;\n}): Promise<Record<string, unknown>> {\n const url = `${options.baseUrl}${options.path}`;\n const headers = buildHeaders(options.apiKey);\n const retry: RetryConfig = makeRetryConfig(\n options.maxRetries ?? DEFAULT_MAX_RETRIES,\n );\n\n let attempt = 0;\n\n for (;;) {\n await options.rateLimiter.wait();\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), options.timeout);\n\n let response: Response;\n try {\n const fetchOptions: RequestInit = {\n method: options.method,\n headers,\n signal: controller.signal,\n };\n\n if (options.method === \"POST\" && options.body) {\n fetchOptions.body = JSON.stringify(stripUndefined(options.body));\n }\n\n response = await fetch(url, fetchOptions);\n } catch (err) {\n clearTimeout(timeoutId);\n const timedOut = isAbortError(err);\n if (shouldRetryException(retry, attempt)) {\n await sleep(backoff(retry, attempt));\n attempt += 1;\n continue;\n }\n const msg = err instanceof Error ? err.message : String(err);\n if (timedOut) {\n throw new ScavioTimeoutError(msg);\n }\n throw new ScavioConnectionError(msg);\n } finally {\n clearTimeout(timeoutId);\n }\n\n if (response.ok) {\n return (await response.json()) as Record<string, unknown>;\n }\n\n if (shouldRetryStatus(retry, response.status, attempt)) {\n const retryAfter = parseRetryAfter(getHeader(response, \"Retry-After\"));\n await sleep(backoff(retry, attempt, retryAfter));\n attempt += 1;\n continue;\n }\n\n let body: Record<string, unknown> = {};\n try {\n body = (await response.json()) as Record<string, unknown>;\n } catch {\n // ignore parse failures\n }\n handleError(response.status, body);\n }\n}\n","export class RateLimiter {\n private readonly maxPerSecond: number;\n private readonly timestamps: number[] = [];\n private pending: Promise<void> = Promise.resolve();\n\n constructor(maxPerSecond: number) {\n this.maxPerSecond = maxPerSecond;\n }\n\n async wait(): Promise<void> {\n const ticket = this.pending.then(() => this.acquire());\n this.pending = ticket;\n return ticket;\n }\n\n private async acquire(): Promise<void> {\n this.cleanup();\n if (this.timestamps.length >= this.maxPerSecond) {\n const sleepMs = 1000 - (Date.now() - this.timestamps[0]!);\n if (sleepMs > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, sleepMs));\n }\n this.cleanup();\n }\n this.timestamps.push(Date.now());\n }\n\n private cleanup(): void {\n const now = Date.now();\n while (this.timestamps.length > 0 && now - this.timestamps[0]! >= 1000) {\n this.timestamps.shift();\n }\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/**\n * Amazon moved to a new upstream in 2026-07 and the API now returns a\n * normalized shape instead of the old raw provider payload. Nine options went\n * with the old provider: language, currency, device, sort_by, pages,\n * category_id, merchant_id, zip_code and autoselect_variant. They are removed\n * rather than kept as no-ops - notably `sort_by`, which the marketplace was\n * verified to ignore entirely (every sort value returned the same unordered\n * set). Sending a retired option anyway still returns 200, with a top-level\n * `warnings` array naming what was ignored.\n *\n * `country` is the canonical marketplace selector; `domain` and `start_page`\n * remain as deprecated aliases because published SDK versions send them.\n */\nexport interface AmazonSearchOptions {\n /** Product search query (1-500 characters). */\n query: string;\n /** Marketplace country code (ISO 3166-1 alpha-2, e.g. 'us', 'gb', 'de'). Defaults to 'us'. */\n country?: string;\n /** @deprecated Amazon domain suffix ('com', 'co.uk'). Use `country` instead. */\n domain?: string;\n /** Results page, 1-based. One page per call, 1 credit each. */\n page?: number;\n /** @deprecated Alias for `page`. */\n start_page?: number;\n [key: string]: unknown;\n}\n\nexport interface AmazonProductOptions {\n /** Amazon ASIN (e.g. 'B09XS7JWHH'). Sent to the API as 'query'. */\n asin: string;\n /** Marketplace country code (ISO 3166-1 alpha-2, e.g. 'us', 'gb', 'de'). Defaults to 'us'. */\n country?: string;\n /** @deprecated Amazon domain suffix ('com', 'co.uk'). Use `country` instead. */\n domain?: string;\n [key: string]: unknown;\n}\n\nexport interface AmazonOffersOptions {\n /** Amazon ASIN (e.g. 'B09XS7JWHH'). Sent to the API as 'query'. */\n asin: string;\n /** Marketplace country code (ISO 3166-1 alpha-2, e.g. 'us', 'gb', 'de'). Defaults to 'us'. */\n country?: string;\n /** @deprecated Amazon domain suffix ('com', 'co.uk'). Use `country` instead. */\n domain?: string;\n [key: string]: unknown;\n}\n\nexport class AmazonNamespace {\n constructor(private client: Scavio) {}\n\n async search(\n options: AmazonSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/amazon/search\", options);\n }\n\n async product(\n options: AmazonProductOptions,\n ): Promise<Record<string, unknown>> {\n const { asin, ...rest } = options;\n return this.client._post(\"/api/v1/amazon/product\", {\n query: asin,\n ...rest,\n });\n }\n\n /** Every seller offer for one ASIN: price, seller, condition, shipping, and\n * which offer holds the buy box. Page 1 only. */\n async offers(options: AmazonOffersOptions): Promise<Record<string, unknown>> {\n const { asin, ...rest } = options;\n return this.client._post(\"/api/v1/amazon/offers\", {\n query: asin,\n ...rest,\n });\n }\n\n /** Supported Amazon marketplaces, as `domains` and `countries`. `languages`\n * and `currencies` remain in the payload but are always empty: neither is a\n * request parameter any more. */\n async options(): Promise<Record<string, unknown>> {\n return this.client._get(\"/api/v1/amazon/options\");\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/**\n * Google endpoints (scrape.do engine, /api/v2/google). A faithful passthrough\n * that returns Google's full response. Every endpoint costs 1 credit. Any\n * additional scrape.do parameter can be added to the options object.\n * See https://scavio.dev/docs/search-api.\n */\n\nexport interface GoogleSearchOptions {\n /** Search query (1-500 characters). */\n query: string;\n /** Device to emulate. */\n device?: \"desktop\" | \"mobile\";\n /** Result offset: 0 = page 1, 10 = page 2, ... up to 990. */\n start?: number;\n /** Include the raw Google HTML in the response. */\n include_html?: boolean;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Canonical location name; auto-encoded to a UULE string. */\n location?: string;\n /** Pre-encoded UULE location string (takes priority over location). */\n uule?: string;\n /** Language restrict (e.g. 'lang_en'). */\n lr?: string;\n /** Country restrict (e.g. 'countryUS'). */\n cr?: string;\n /** SafeSearch filter. */\n safe?: \"active\";\n /** Disable spelling correction / auto-fixes when true. */\n nfpr?: boolean;\n /** '0' disables the omitted/similar-results filter. */\n filter?: \"0\" | \"1\";\n /** Restrict results to a recent time window. */\n time_period?:\n | \"last_hour\"\n | \"last_day\"\n | \"last_week\"\n | \"last_month\"\n | \"last_year\";\n /** Resolve a deferred AI Overview (server default true). */\n resolve_ai_overview?: boolean;\n [key: string]: unknown;\n}\n\nexport interface GoogleAiModeOptions {\n /** Question or prompt (1-500 characters). */\n query: string;\n /** Device to emulate. */\n device?: \"desktop\" | \"mobile\";\n /** Include the raw Google HTML in the response. */\n include_html?: boolean;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Canonical location name; auto-encoded to a UULE string. */\n location?: string;\n /** Pre-encoded UULE location string (takes priority over location). */\n uule?: string;\n /** SafeSearch filter. */\n safe?: \"active\";\n [key: string]: unknown;\n}\n\nexport interface GoogleMapsSearchOptions {\n /** Search query (1-500 characters). */\n query: string;\n /** Result offset; must be a multiple of 20 (0, 20, 40, ...). */\n start?: number;\n /** Map center as '@lat,lng,zoomz'; controls where results come from. */\n ll?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleMapsPlaceOptions {\n /** Place ID (ChIJ...). */\n place_id?: string;\n /** Numeric CID. */\n data_cid?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleMapsReviewsOptions {\n /** Data ID (0xHEX:0xHEX). */\n data_id?: string;\n /** Place ID (ChIJ...). */\n place_id?: string;\n /** Reviews per page (1-20). */\n num?: number;\n /** Pagination cursor from a prior response. */\n next_page_token?: string;\n /** Sort order. */\n sort_by?: \"relevance\" | \"newest\" | \"highest_rating\" | \"lowest_rating\";\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleShoppingOptions {\n /** Product search query (1-500 characters). */\n query: string;\n /** Device to emulate. */\n device?: \"desktop\" | \"mobile\";\n /** Result offset. */\n start?: number;\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n /** 0 = relevance, 1 = price ascending, 2 = price descending. */\n sort_by?: number;\n /** Only items with free shipping. */\n free_shipping?: boolean;\n /** Only items on sale. */\n on_sale?: boolean;\n /** Opaque Google Shopping filter token. */\n shoprs?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Canonical location name; auto-encoded to a UULE string. */\n location?: string;\n /** Pre-encoded UULE location string (takes priority over location). */\n uule?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleShoppingProductOptions {\n /** Durable product catalog id. */\n catalog_id?: string;\n /** Product query; required when catalog_id is set. */\n query?: string;\n /** Immersive product page token. */\n immersive_product_page_token?: string;\n /** Alias for immersive_product_page_token. */\n page_token?: string;\n /** Product id. */\n product_id?: string;\n /** Device to emulate. */\n device?: \"desktop\" | \"mobile\" | \"tablet\";\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Seller sort order. */\n sort_by?: \"base_price\" | \"total_price\" | \"promotion\" | \"seller_rating\";\n /** Load all available stores. */\n load_all_stores?: boolean;\n /** Fetch additional stores. */\n more_stores?: boolean;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Canonical location name; auto-encoded to a UULE string. */\n location?: string;\n /** Pre-encoded UULE location string (takes priority over location). */\n uule?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleShoppingStoresOptions {\n /** Durable product catalog id. */\n catalog_id: string;\n /** Pagination cursor from shopping_product. */\n next_page_token: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleFlightsOptions {\n /** Departure IATA code(s); comma-separated allowed. */\n departure_id: string;\n /** Arrival IATA code(s); comma-separated allowed. */\n arrival_id: string;\n /** Outbound date (YYYY-MM-DD). */\n outbound_date: string;\n /** 1 = round trip, 2 = one way, 3 = multi-city. */\n type?: number;\n /** Return date (YYYY-MM-DD); required when type=1. */\n return_date?: string;\n /** Number of adults (1-9). */\n adults?: number;\n /** Number of children (0-9). */\n children?: number;\n /** Infants in seat (0-4). */\n infants_in_seat?: number;\n /** Infants on lap (0-4). */\n infants_on_lap?: number;\n /** 1 = economy, 2 = premium, 3 = business, 4 = first. */\n travel_class?: number;\n /** 0 = any, 1 = nonstop, 2 = <=1 stop, 3 = <=2 stops. */\n stops?: number;\n /** 1 = top, 2 = price, 3 = departure, 4 = arrival, 5 = duration, 6 = emissions. */\n sort_by?: number;\n /** Comma-separated airline codes/alliances to include. */\n include_airlines?: string;\n /** Comma-separated airline codes/alliances to exclude. */\n exclude_airlines?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Currency code (ISO 4217, e.g. 'USD'). */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleHotelsOptions {\n /** Search query; use a '<City> hotels' form. */\n query: string;\n /** Check-in date (YYYY-MM-DD). */\n check_in_date: string;\n /** Check-out date (YYYY-MM-DD). */\n check_out_date: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Currency code (ISO 4217, e.g. 'USD'). */\n currency?: string;\n /** 3 = lowest price, 8 = highest rating, 13 = most reviewed. */\n sort_by?: number;\n /** Minimum nightly price. */\n min_price?: number;\n /** Maximum nightly price. */\n max_price?: number;\n /** 7 = 3.5+, 8 = 4.0+, 9 = 4.5+. */\n rating?: number;\n /** Comma-separated star ratings (2-5). */\n hotel_class?: string;\n /** Comma-separated amenity ids. */\n amenities?: string;\n /** Comma-separated property-type ids (e.g. '12' for vacation rentals). */\n property_types?: string;\n /** Only properties with free cancellation. */\n free_cancellation?: boolean;\n /** Only eco-certified properties. */\n eco_certified?: boolean;\n /** Only properties with special offers. */\n special_offers?: boolean;\n /** Pagination cursor from a prior response. */\n next_page_token?: string;\n /** Number of properties to return (1-20). */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface GoogleHotelsDetailOptions {\n /** Property detail token from a hotels listing. */\n detail_token: string;\n /** Check-in date (YYYY-MM-DD). */\n check_in_date: string;\n /** Check-out date (YYYY-MM-DD). */\n check_out_date: string;\n /** Currency code (ISO 4217, e.g. 'USD'). */\n currency?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleNewsOptions {\n /** Keyword search. */\n query?: string;\n /** Browse a news topic. */\n topic_token?: string;\n /** Browse a topic section. */\n section_token?: string;\n /** Fetch full coverage of a story. */\n story_token?: string;\n /** Browse a publication. */\n publication_token?: string;\n /** Knowledge Graph entity id. */\n kgmid?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Sort order: 0 = relevance, 1 = date (only with query or kgmid). */\n so?: number;\n [key: string]: unknown;\n}\n\nexport interface GoogleTrendsOptions {\n /** Search term(s); comma-separated for comparisons. */\n query: string;\n /** Location code (e.g. 'US', 'GB', 'US-CA'). */\n geo?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Time range (e.g. 'today 12-m', 'now 7-d'). */\n date?: string;\n /** Timezone offset in minutes. */\n tz?: string;\n /** Which trends dataset to return. */\n data_type?:\n | \"TIMESERIES\"\n | \"GEO_MAP\"\n | \"GEO_MAP_0\"\n | \"RELATED_QUERIES\"\n | \"RELATED_TOPICS\";\n /** Category id. */\n cat?: string;\n /** Google property filter. */\n gprop?: \"images\" | \"news\" | \"youtube\" | \"froogle\";\n /** Resolution for GEO_MAP data. */\n region?: \"COUNTRY\" | \"REGION\" | \"DMA\" | \"CITY\";\n [key: string]: unknown;\n}\n\nexport interface GoogleTrendingOptions {\n /** Country code (e.g. 'US'). */\n geo: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Trending window: 4, 24, 48, or 168. */\n hours?: number;\n /** Category id (0-20). */\n cat?: number;\n /** Sort order. */\n sort?: \"relevance\" | \"search_volume\" | \"recency\" | \"title\";\n /** Filter by trend status. */\n status?: \"all\" | \"active\";\n [key: string]: unknown;\n}\n\nexport class GoogleNamespace {\n constructor(private client: Scavio) {}\n\n /** Google SERP search (includes the AI Overview when Google returns one). */\n async search(options: GoogleSearchOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google\", options);\n }\n\n /** Google AI Mode answer. */\n async aiMode(options: GoogleAiModeOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/ai-mode\", options);\n }\n\n /** Google Maps local results. */\n async mapsSearch(options: GoogleMapsSearchOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/maps/search\", options);\n }\n\n /** Google Maps place details. Provide place_id or data_cid. */\n async mapsPlace(options: GoogleMapsPlaceOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/maps/place\", options);\n }\n\n /** Google Maps reviews. Provide data_id or place_id. */\n async mapsReviews(options: GoogleMapsReviewsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/maps/reviews\", options);\n }\n\n /** Google Shopping search results. */\n async shopping(options: GoogleShoppingOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/shopping\", options);\n }\n\n /** Google Shopping product. Pass catalog_id + query for full details and sellers. */\n async shoppingProduct(\n options: GoogleShoppingProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/shopping/product\", options);\n }\n\n /** Google Shopping product sellers (continuation of shoppingProduct). */\n async shoppingStores(\n options: GoogleShoppingStoresOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/shopping/product/stores\", options);\n }\n\n /** Google Flights. */\n async flights(options: GoogleFlightsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/flights\", options);\n }\n\n /** Google Hotels search. */\n async hotels(options: GoogleHotelsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/hotels\", options);\n }\n\n /** Google Hotels property details (from a hotels listing detail_token). */\n async hotelsDetail(\n options: GoogleHotelsDetailOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/hotels/detail\", options);\n }\n\n /** Google News. Provide query or a topic/story/publication token. */\n async news(options: GoogleNewsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/news\", options);\n }\n\n /** Google Trends data. */\n async trends(options: GoogleTrendsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/trends\", options);\n }\n\n /** Google Trending Now for a country. */\n async trending(options: GoogleTrendingOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/trending\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/** Comment / feed sort orders. */\nexport type RedditSort = \"HOT\" | \"NEW\" | \"TOP\" | \"BEST\" | \"CONTROVERSIAL\";\n/** Subreddit feed sort orders. */\nexport type RedditFeedSort =\n | \"BEST\"\n | \"HOT\"\n | \"NEW\"\n | \"TOP\"\n | \"CONTROVERSIAL\"\n | \"RISING\";\n\n/**\n * Search takes only `query` and `cursor`. There is no result-type or sort\n * filter upstream: anything else is dropped server-side.\n */\nexport interface RedditSearchOptions {\n /** Search query (1-500 characters). */\n query: string;\n /** Pagination cursor from a prior response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditSearchSuggestionsOptions {\n /** Search query (1-500 characters). */\n query: string;\n [key: string]: unknown;\n}\n\nexport interface RedditPostOptions {\n /** Post fullname (t3_...) or bare id. */\n post_id?: string;\n /** Full Reddit post URL. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditPostCommentsOptions {\n /** Post fullname (t3_...). */\n post_id: string;\n /** Comment sort order (default 'TOP'). */\n sort?: RedditSort;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditCommentRepliesOptions {\n /** Post fullname (t3_...). */\n post_id: string;\n /** reply_cursor from a comment in the comments endpoint. */\n cursor: string;\n /** Comment sort order (default 'TOP'). */\n sort?: RedditSort;\n [key: string]: unknown;\n}\n\nexport interface RedditSubredditOptions {\n /** Subreddit name (without r/). */\n subreddit: string;\n [key: string]: unknown;\n}\n\nexport interface RedditSubredditPostsOptions {\n /** Subreddit name (without r/). */\n subreddit: string;\n /** Feed sort order (default 'HOT'). */\n sort?: RedditFeedSort;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditUserOptions {\n /** Redditor username (without u/). */\n username: string;\n [key: string]: unknown;\n}\n\nexport interface RedditUserFeedOptions {\n /** Redditor username (without u/). */\n username: string;\n /** Sort order (default 'NEW'). */\n sort?: RedditSort;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditPopularOptions {\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport class RedditNamespace {\n constructor(private client: Scavio) {}\n\n /** Returns `data.results` plus `next_cursor` / `has_more` (not `data.posts`). */\n async search(\n options: RedditSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/search\", options);\n }\n\n async searchSuggestions(\n options: RedditSearchSuggestionsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/search/suggestions\", options);\n }\n\n /**\n * Returns a flat post object under `data` (post_id, title, text, url,\n * subreddit, author, score, ...). Comments are a separate call.\n */\n async post(options: RedditPostOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/post\", options);\n }\n\n async postComments(\n options: RedditPostCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/post/comments\", options);\n }\n\n async commentReplies(\n options: RedditCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/post/comments/replies\", options);\n }\n\n async subreddit(\n options: RedditSubredditOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/subreddit\", options);\n }\n\n async subredditPosts(\n options: RedditSubredditPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/subreddit/posts\", options);\n }\n\n async user(options: RedditUserOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/user\", options);\n }\n\n async userPosts(\n options: RedditUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/user/posts\", options);\n }\n\n async userComments(\n options: RedditUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/user/comments\", options);\n }\n\n async popular(\n options: RedditPopularOptions = {},\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/popular\", options);\n }\n\n async trending(): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/trending\", {});\n }\n}\n","import type { Scavio } from \"../client.js\";\n\nexport interface TikTokProfileOptions {\n /** TikTok @username (without the @). */\n username?: string;\n /** TikTok sec_user_id. */\n sec_user_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TikTokUserPostsOptions {\n /** TikTok sec_user_id. */\n sec_user_id: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-30). */\n count?: number;\n /** '0' = latest, '1' = popular. */\n sort_type?: \"0\" | \"1\";\n [key: string]: unknown;\n}\n\nexport interface TikTokVideoOptions {\n /** TikTok video id. */\n video_id: string;\n [key: string]: unknown;\n}\n\nexport interface TikTokVideoCommentsOptions {\n /** TikTok video id. */\n video_id: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-50). */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokCommentRepliesOptions {\n /** TikTok video id. */\n video_id: string;\n /** Parent comment id. */\n comment_id: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-50). */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokSearchVideosOptions {\n /** Search keyword (1-500 characters). */\n keyword: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-30). */\n count?: number;\n /** '0' = relevance, '1' = most likes. */\n sort_type?: \"0\" | \"1\";\n /** Age filter in days: 0 = all time, 1, 7, 30, 90, 180. */\n publish_time?: \"0\" | \"1\" | \"7\" | \"30\" | \"90\" | \"180\";\n [key: string]: unknown;\n}\n\nexport interface TikTokSearchUsersOptions {\n /** Search keyword (1-500 characters). */\n keyword: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-30). */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokHashtagOptions {\n /** Hashtag name (without the #). */\n hashtag_name?: string;\n /** Hashtag id. */\n hashtag_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TikTokHashtagVideosOptions {\n /** Hashtag id. */\n hashtag_id: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-30). */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokUserFollowersOptions {\n /** TikTok sec_user_id. */\n sec_user_id: string;\n /** Results per page (1-20). */\n count?: number;\n /** Pagination token from a prior response. */\n page_token?: string;\n /** Minimum timestamp cursor. */\n min_time?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokUserFollowingsOptions {\n /** TikTok sec_user_id. */\n sec_user_id: string;\n /** Results per page (1-20). */\n count?: number;\n /** Pagination token from a prior response. */\n page_token?: string;\n /** Minimum timestamp cursor. */\n min_time?: number;\n [key: string]: unknown;\n}\n\nexport class TikTokNamespace {\n constructor(private client: Scavio) {}\n\n async profile(\n options: TikTokProfileOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/profile\", options);\n }\n\n async userPosts(\n options: TikTokUserPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/user/posts\", options);\n }\n\n async video(\n options: TikTokVideoOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/video\", options);\n }\n\n async videoComments(\n options: TikTokVideoCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/video/comments\", options);\n }\n\n async commentReplies(\n options: TikTokCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/video/comments/replies\", options);\n }\n\n async searchVideos(\n options: TikTokSearchVideosOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/search/videos\", options);\n }\n\n async searchUsers(\n options: TikTokSearchUsersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/search/users\", options);\n }\n\n async hashtag(\n options: TikTokHashtagOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/hashtag\", options);\n }\n\n async hashtagVideos(\n options: TikTokHashtagVideosOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/hashtag/videos\", options);\n }\n\n async userFollowers(\n options: TikTokUserFollowersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/user/followers\", options);\n }\n\n async userFollowings(\n options: TikTokUserFollowingsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/user/followings\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/** Marketplace regions served by suggestions, product, reviews, and shop products. */\nexport type TikTokShopRegion =\n | \"US\"\n | \"GB\"\n | \"SG\"\n | \"MY\"\n | \"PH\"\n | \"TH\"\n | \"VN\"\n | \"ID\";\n\n/** Marketplace regions served by category listings. */\nexport type TikTokShopListingRegion = \"US\" | \"GB\";\n\n/** Review ordering: 'relevant' is text-complete and image-heavy, 'recent' is fresher but text-sparse. */\nexport type TikTokShopReviewSort = \"relevant\" | \"recent\";\n\nexport interface TikTokShopSearchOptions {\n /** Search query (1-200 characters). US catalog only. */\n search: string;\n /** Opaque cursor from a prior response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopSuggestionsOptions {\n /** Partial query to expand (1-100 characters). */\n search: string;\n /** Marketplace region (default 'US'). */\n region?: TikTokShopRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopProductOptions {\n /** TikTok Shop product id (6-25 digits). */\n product_id: string;\n /** Marketplace region (default 'US'). */\n region?: TikTokShopRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopProductReviewsOptions {\n /** TikTok Shop product id (6-25 digits). */\n product_id: string;\n /** 1-based page number (1-500, default 1). */\n page?: number;\n /** Reviews per page (1-200, default 20). */\n page_size?: number;\n /** 'relevant' (default) is text-complete and image-heavy; 'recent' is fresher but far more text-sparse. */\n sort?: TikTokShopReviewSort;\n /** Only reviews with this star rating (1-5). */\n rating?: number;\n /** Only reviews with a photo or video (default false). */\n has_media?: boolean;\n /** Only verified purchases (default false). */\n verified_only?: boolean;\n /** Marketplace region (default 'US'). */\n region?: TikTokShopRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopCategoryProductsOptions {\n /** Category id from tiktokShop.categories(); level 1 or 2 both work. */\n category_id: string;\n /** Opaque cursor from a prior response's next_cursor. */\n cursor?: string;\n /** Marketplace region, 'US' or 'GB' only (default 'US'). */\n region?: TikTokShopListingRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopShopProductsOptions {\n /** TikTok Shop seller id (also called seller_id elsewhere on TikTok). */\n shop_id: string;\n /** Opaque cursor from a prior response's next_cursor. */\n cursor?: string;\n /** Marketplace region (default 'US'). */\n region?: TikTokShopRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopResolveOptions {\n /** A TikTok Shop product or store URL, affiliate share link, or vt.tiktok.com short link. */\n url: string;\n [key: string]: unknown;\n}\n\nexport class TikTokShopNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search TikTok Shop products by keyword (US catalog), up to 30 per page with\n * exact prices, ratings, and shop details. Paginate with next_cursor and dedupe\n * by product_id across pages.\n *\n * This is one of the three endpoints that return exact prices; tiktokShop.product()\n * does not return a price. A product_id returned here is not guaranteed to resolve\n * on tiktokShop.product() - only about 44% do.\n */\n async search(\n options: TikTokShopSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/search\", options);\n }\n\n /**\n * Keyword autocomplete and expansion for a partial query, across 8 marketplace\n * regions. Suggestions are not guaranteed prefix matches: a misspelling returns\n * typo corrections, and results can include brand and shop names.\n */\n async searchSuggestions(\n options: TikTokShopSuggestionsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/search/suggestions\", options);\n }\n\n /**\n * Full product detail: description, images, variants with stock, shipping, shop\n * profile, category path, and top reviews.\n *\n * Two limits worth knowing before you build on this:\n *\n * 1. It resolves only about 44% of the product ids returned by tiktokShop.search().\n * Upstream has no detail data for the rest, so an HTTP 404 is a normal outcome,\n * not an error. Skip the item rather than retrying - retries do not help and no\n * other region carries it. Search to product is not a reliable pipeline.\n *\n * This method throws `NotFoundError` on that 404 (there is no `data` field in\n * the response body to test), so a loop over search ids must catch it or it\n * dies on the first miss:\n *\n * ```ts\n * import { NotFoundError } from \"scavio\";\n *\n * for (const productId of productIds) {\n * try {\n * const detail = await client.tiktokShop.product({ product_id: productId });\n * } catch (e) {\n * if (e instanceof NotFoundError) continue; // no detail upstream; skip\n * throw e;\n * }\n * }\n * ```\n *\n * tiktokShop.productReviews() often works for ids product() cannot resolve: of\n * 8 such ids tested, 8 returned HTTP 200 and 7 carried at least one review, so\n * it is a useful fallback source of product detail.\n * 2. It does NOT return a price. Upstream masks the price on the product page.\n * Exact prices come from tiktokShop.search(), tiktokShop.shopProducts(), and\n * tiktokShop.categoryProducts().\n */\n async product(\n options: TikTokShopProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/product\", options);\n }\n\n /**\n * Paginated product reviews with text, images, star histogram, and\n * verified-purchase flags, up to 200 per call. total_reviews drifts between calls\n * and must not be used to compute a page count; page with has_more instead.\n */\n async productReviews(\n options: TikTokShopProductReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/product/reviews\", options);\n }\n\n /**\n * The global TikTok Shop category tree: 28 top-level categories, 240 nodes, two\n * levels deep. Category ids are identical in every region and names are always\n * English.\n */\n async categories(): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/categories\", {});\n }\n\n /**\n * Products listed under a category id from tiktokShop.categories(), with exact\n * prices. Page size is inconsistent upstream (15 to 20 per page), so always\n * paginate with next_cursor rather than assuming a fixed page size. Category\n * listings are shallow: after a few pages the source stops returning new products\n * and has_more turns false, which is the end of the listing rather than an error.\n */\n async categoryProducts(\n options: TikTokShopCategoryProductsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/category/products\", options);\n }\n\n /**\n * A shop's product catalog, 30 per page, with exact prices. Shop follower count,\n * location, and shop-level rating are not available here; call\n * tiktokShop.product() for the full shop profile.\n */\n async shopProducts(\n options: TikTokShopShopProductsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/shop/products\", options);\n }\n\n /**\n * Resolve any TikTok Shop URL or share link to a product_id or shop_id, ready to\n * pass to the other methods. Accepts canonical product and store pages,\n * tiktok.com/view links, affiliate share links, and vt.tiktok.com short links.\n */\n async resolve(\n options: TikTokShopResolveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/resolve\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/**\n * Instagram endpoints (/api/v1/instagram). Credit cost varies by endpoint,\n * in three tiers:\n * - 2: `userPosts`\n * - 8: `post`, `commentReplies`\n * - 10: everything else (`profile`, `userReels`, `userTagged`, `userStories`,\n * `postComments`, `searchUsers`, `searchHashtags`, `userFollowers`,\n * `userFollowings`)\n * See https://scavio.dev/docs/instagram-api.\n */\n\nexport interface InstagramProfileOptions {\n /** Instagram username (without the @). */\n username?: string;\n /** Instagram numeric user id. */\n user_id?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramUserFeedOptions {\n /** Instagram username (without the @). */\n username?: string;\n /** Instagram numeric user id. */\n user_id?: string;\n /** Results per page (1-50). */\n count?: number;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramStoriesOptions {\n /** Instagram username (without the @). */\n username?: string;\n /** Instagram numeric user id. */\n user_id?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramPostOptions {\n /** Full Instagram post URL. */\n url?: string;\n /** Instagram media id. */\n media_id?: string;\n /** Instagram shortcode (from the post URL). */\n shortcode?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramPostCommentsOptions {\n /** Instagram shortcode (from the post URL). */\n shortcode?: string;\n /** Full Instagram post URL. */\n url?: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n /** Comment sort order. */\n sort_order?: \"popular\" | \"newest\";\n [key: string]: unknown;\n}\n\nexport interface InstagramCommentRepliesOptions {\n /** Instagram media id. */\n media_id: string;\n /** Parent comment id. */\n comment_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramSearchOptions {\n /** Search keyword (1-500 characters). */\n keyword: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramFollowOptions {\n /** Instagram username (without the @). */\n username?: string;\n /** Instagram numeric user id. */\n user_id?: string;\n /** Results per page (1-100). */\n count?: number;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport class InstagramNamespace {\n constructor(private client: Scavio) {}\n\n async profile(\n options: InstagramProfileOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/profile\", options);\n }\n\n async userPosts(\n options: InstagramUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/posts\", options);\n }\n\n async userReels(\n options: InstagramUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/reels\", options);\n }\n\n async userTagged(\n options: InstagramUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/tagged\", options);\n }\n\n async userStories(\n options: InstagramStoriesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/stories\", options);\n }\n\n async post(\n options: InstagramPostOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/post\", options);\n }\n\n async postComments(\n options: InstagramPostCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/post/comments\", options);\n }\n\n async commentReplies(\n options: InstagramCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/post/comments/replies\", options);\n }\n\n async searchUsers(\n options: InstagramSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/search/users\", options);\n }\n\n async searchHashtags(\n options: InstagramSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/search/hashtags\", options);\n }\n\n async userFollowers(\n options: InstagramFollowOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/followers\", options);\n }\n\n async userFollowings(\n options: InstagramFollowOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/followings\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Walmart: search, product, reviews, category, offers, seller, sellerProducts\n// and stores.\n//\n// `device` is the only retired param. It is no longer typed here; sending it\n// anyway does not fail the request - the response carries a `warnings[]` array\n// explaining that it was ignored.\n//\n// STORE TARGETING (search and product): pass `delivery_zip` and `store_id`\n// TOGETHER to get one store's assortment and availability. Works on walmart.com\n// and walmart.ca (a Canadian postal code such as \"M5V 2T6\" with domain \"ca\").\n// Get `store_id` from `stores()` for a ZIP or postal code, on the same domain.\n// The store actually used is echoed in `data.location`. A store-targeted call\n// costs 2 credits and takes 10-60 seconds; a store_id that does not exist\n// returns 400. walmart.com.mx does not support store targeting.\n//\n// CREDITS ARE BODY-PRICED: search and category cost 1 credit on domain \"com\" or\n// \"ca\" and 2 on \"com.mx\"; a store-targeted search or product costs 2. Product,\n// reviews, offers, seller, sellerProducts and stores are otherwise 1.\n\nexport interface WalmartSearchOptions {\n /** Product search query (1-500 characters). */\n query: string;\n /**\n * Walmart storefront. Price-bearing: \"com\" and \"ca\" cost 1 credit,\n * \"com.mx\" costs 2. Defaults to \"com\".\n */\n domain?: \"com\" | \"ca\" | \"com.mx\";\n /** Result page, 1-indexed. */\n page?: number;\n /** @deprecated Alias for `page`. Use `page`. */\n start_page?: number;\n /** Result sort order (default \"best_match\"). */\n sort_by?:\n | \"best_match\"\n | \"price_low\"\n | \"price_high\"\n | \"best_seller\"\n | \"rating_high\"\n | \"new\";\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n /**\n * Delivery speed filter. \"2_days\" is deliberately unsupported (it leaks\n * 3-4 day items) and there is no \"anytime\" - omit the param instead.\n */\n fulfillment_speed?: \"today\" | \"tomorrow\";\n /** Fulfillment type filter. */\n fulfillment_type?: \"in_store\";\n /**\n * Shopper's postal code for store targeting: a 5-digit US ZIP, or a Canadian\n * postal code (\"M5V 2T6\") with domain \"ca\". Must be sent together with\n * `store_id`. Store-targeted calls cost 2 credits.\n */\n delivery_zip?: string;\n /**\n * Walmart store to target, from `stores()` on the same domain. Must be sent\n * together with `delivery_zip`. Supported on domain \"com\" and \"ca\".\n */\n store_id?: string | number;\n [key: string]: unknown;\n}\n\nexport interface WalmartProductOptions {\n /** Walmart item id (usItemId), e.g. \"13544111159\". */\n product_id: string;\n /**\n * Walmart storefront, \"com\" (default) or \"ca\". \"ca\" is only available\n * together with `delivery_zip` + `store_id`.\n */\n domain?: \"com\" | \"ca\";\n /**\n * Shopper's postal code for store targeting: a 5-digit US ZIP, or a Canadian\n * postal code with domain \"ca\". Must be sent together with `store_id`.\n */\n delivery_zip?: string;\n /**\n * Walmart store to target, from `stores()` on the same domain. Must be sent\n * together with `delivery_zip`.\n */\n store_id?: string | number;\n [key: string]: unknown;\n}\n\nexport interface WalmartStoresOptions {\n /**\n * A 5-digit US ZIP, or a Canadian postal code (\"M5V 2T6\" or \"M5V2T6\") with\n * domain \"ca\".\n */\n zipcode: string;\n /** \"com\" (walmart.com, default) or \"ca\" (walmart.ca). */\n domain?: \"com\" | \"ca\";\n [key: string]: unknown;\n}\n\n/** One store returned by `stores()`. */\nexport interface WalmartStore {\n store_id: string | null;\n name: string | null;\n type: string | null;\n node_type: string | null;\n distance_miles: number | null;\n address: {\n line1: string | null;\n line2: string | null;\n city: string | null;\n state: string | null;\n zipcode: string | null;\n country: string | null;\n };\n latitude: number | null;\n longitude: number | null;\n open_24_hours: boolean | null;\n hours: {\n day: string | null;\n start: string | null;\n end: string | null;\n closed: boolean | null;\n }[];\n pickup_types: string[];\n}\n\n/** The `data` object of a `stores()` response. */\nexport interface WalmartStoresData {\n /** The ZIP or postal code searched, normalized (\"M5V 2T6\"). */\n zipcode: string;\n domain: \"com\" | \"ca\";\n count: number;\n /** Nearest first. */\n stores: WalmartStore[];\n}\n\nexport interface WalmartStoresResponse {\n data: WalmartStoresData;\n response_time: number;\n credits_used: number;\n credits_remaining: number;\n warnings?: string[];\n [key: string]: unknown;\n}\n\nexport interface WalmartReviewsOptions {\n /** Walmart item id (usItemId). */\n product_id: string;\n /** Result page, 1-indexed. 10 reviews per page. */\n page?: number;\n /** Review sort order. */\n sort?:\n | \"relevancy\"\n | \"submission-desc\"\n | \"submission-asc\"\n | \"rating-desc\"\n | \"rating-asc\"\n | \"helpful-desc\";\n [key: string]: unknown;\n}\n\nexport interface WalmartCategoryOptions {\n /**\n * Category id: either a leaf id (\"1095191\") or a full underscore path\n * (\"3944_133251_1095191\").\n */\n category_id: string;\n /**\n * Walmart storefront. Price-bearing: \"com\" and \"ca\" cost 1 credit,\n * \"com.mx\" costs 2. Defaults to \"com\".\n */\n domain?: \"com\" | \"ca\" | \"com.mx\";\n /** Result page, 1-indexed. */\n page?: number;\n /** Trims the returned list after fetching. Does NOT reduce the credit cost. */\n limit?: number;\n /** Result sort order (default \"best_match\"). */\n sort_by?:\n | \"best_match\"\n | \"price_low\"\n | \"price_high\"\n | \"best_seller\"\n | \"rating_high\"\n | \"new\";\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n /**\n * Delivery speed filter. \"2_days\" is deliberately unsupported (it leaks\n * 3-4 day items) and there is no \"anytime\" - omit the param instead.\n */\n fulfillment_speed?: \"today\" | \"tomorrow\";\n [key: string]: unknown;\n}\n\nexport interface WalmartOffersOptions {\n /** Walmart item id (usItemId). */\n product_id: string;\n [key: string]: unknown;\n}\n\nexport interface WalmartSellerOptions {\n /**\n * NUMERIC catalog seller id, the `seller_catalog_id` field returned by\n * product/offers. The GUID form of seller_id returns 404.\n */\n seller_id: string;\n [key: string]: unknown;\n}\n\nexport interface WalmartSellerProductsOptions {\n /**\n * NUMERIC catalog seller id (`seller_catalog_id`). The GUID form returns 404.\n */\n seller_id: string;\n [key: string]: unknown;\n}\n\nexport class WalmartNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Structured Walmart search results: `products[]`, `products_count` and the\n * resolved `location`. Page through with `page` (1-indexed).\n *\n * Pass `delivery_zip` + `store_id` to get one store's results (walmart.com\n * and walmart.ca); `data.location` confirms the store.\n *\n * Costs 1 credit for `domain` \"com\" or \"ca\", 2 credits for \"com.mx\", and 2\n * credits when store-targeted.\n */\n async search(\n options: WalmartSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/search\", options);\n }\n\n /**\n * Full product detail: price, rating, images, specifications, availability\n * and seller.\n *\n * Pass `delivery_zip` + `store_id` for one store's price and availability.\n * `domain: \"ca\"` is available only together with a store target.\n *\n * Costs 1 credit, or 2 when store-targeted. A store that does not carry the\n * item returns 404.\n */\n async product(\n options: WalmartProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/product\", options);\n }\n\n /**\n * Customer reviews with ratings, text, author, date and the rating\n * breakdown. 10 reviews per page; advance with `page`.\n *\n * Costs 1 credit.\n */\n async reviews(\n options: WalmartReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/reviews\", options);\n }\n\n /**\n * Products within a category, in the same product shape as `search()`.\n * Page through with `page`; `limit` only trims the response.\n *\n * Costs 1 credit for `domain` \"com\" or \"ca\", 2 credits for \"com.mx\".\n */\n async category(\n options: WalmartCategoryOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/category\", options);\n }\n\n /**\n * Seller offer for a product: price, seller, condition and buy-box flag.\n * Returns the BUY-BOX SELLER ONLY, not the full offer list.\n *\n * Costs 1 credit.\n */\n async offers(\n options: WalmartOffersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/offers\", options);\n }\n\n /**\n * Marketplace seller storefront: name, rating, review count, Pro Seller\n * badge and business details.\n *\n * Costs 1 credit. `seller_id` must be the numeric catalog seller id.\n */\n async seller(\n options: WalmartSellerOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/seller\", options);\n }\n\n /**\n * A seller's catalog. Roughly the first 40 items are server-rendered and\n * that is all this returns - there is no pagination. `total_count` reports\n * the seller's real catalog size, which is usually far larger.\n *\n * Costs 1 credit. `seller_id` must be the numeric catalog seller id.\n */\n async sellerProducts(\n options: WalmartSellerProductsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/seller-products\", options);\n }\n\n /**\n * Walmart stores near a US ZIP (or a Canadian postal code with `domain: \"ca\"`),\n * nearest first, with `store_id`, address, distance, coordinates and hours.\n * Use a `store_id` with `delivery_zip` on `search()` or `product()`, on the\n * same domain, to target that store.\n *\n * Costs 1 credit.\n */\n async stores(options: WalmartStoresOptions): Promise<WalmartStoresResponse> {\n return (await this.client._post(\n \"/api/v1/walmart/stores\",\n options,\n )) as unknown as WalmartStoresResponse;\n }\n}\n","import type { Scavio } from \"../client.js\";\n\nexport interface YouTubeSearchOptions {\n /** Search query (1-500 characters). Sent to the API as 'search'. */\n query: string;\n /** Filter by upload date. */\n upload_date?: \"last_hour\" | \"today\" | \"this_week\" | \"this_month\" | \"this_year\";\n /** Filter by result type. */\n type?: \"video\" | \"channel\" | \"playlist\" | \"movie\";\n /** short (<4 min), medium (4-20 min), long (>20 min). */\n duration?: \"short\" | \"medium\" | \"long\";\n /** Sort order. */\n sort_by?: \"relevance\" | \"date\" | \"view_count\" | \"rating\";\n /**\n * Feature filters, e.g. [\"hd\", \"4k\", \"subtitles\", \"creative_commons\",\n * \"live\", \"360\", \"3d\", \"hdr\", \"vr180\"].\n */\n features?: string[];\n /** Pagination cursor from a prior response. */\n cursor?: string;\n /** HD videos only. */\n hd?: boolean;\n /** Videos with subtitles/CC only. */\n subtitles?: boolean;\n /** Creative Commons licensed only. */\n creative_commons?: boolean;\n /** Live videos only. */\n live?: boolean;\n /** HDR videos only. */\n hdr?: boolean;\n /** VR180 videos only. */\n vr180?: boolean;\n /** 4K videos only. Sent to the API as '4k'. */\n fourK?: boolean;\n /** 360-degree videos only. Sent to the API as '360'. */\n video_360?: boolean;\n /** 3D videos only. Sent to the API as '3d'. */\n video_3d?: boolean;\n [key: string]: unknown;\n}\n\nexport interface YouTubeShortsOptions {\n /** Search query (1-500 characters). Sent to the API as 'search'. */\n query: string;\n /** Sort order. */\n sort_by?: \"relevance\" | \"date\" | \"view_count\" | \"rating\";\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeSuggestionsOptions {\n /** Search query (1-500 characters). Sent to the API as 'search'. */\n query: string;\n /** Language code for suggestions (default 'en'). */\n language?: string;\n /** Region code for suggestions (default 'US'). */\n region?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeVideoOptions {\n /** YouTube video id (e.g. 'dQw4w9WgXcQ') or a full watch URL. */\n video_id: string;\n [key: string]: unknown;\n}\n\n/** @deprecated Use YouTubeVideoOptions with youtube.video(). */\nexport interface YouTubeMetadataOptions {\n /** YouTube video id (e.g. 'dQw4w9WgXcQ') or a full watch URL. */\n video_id: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeCommentsOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeCommentRepliesOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n /** Reply cursor from a parent comment's 'reply_cursor'. */\n reply_cursor: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeTranscriptOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n /** Caption language code (default 'en'). */\n language?: string;\n /** 'text' for plain transcript, 'srt' for timed subtitles (default 'text'). */\n format?: \"text\" | \"srt\";\n [key: string]: unknown;\n}\n\nexport interface YouTubeRelatedOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelSearchOptions {\n /** Search query (1-500 characters). Sent to the API as 'search'. */\n query: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelOptions {\n /** YouTube channel id, @handle, or channel URL. */\n channel_id: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelVideosOptions {\n /** YouTube channel id. */\n channel_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelShortsOptions {\n /** YouTube channel id. */\n channel_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelCommunityOptions {\n /** YouTube channel id. */\n channel_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelResolveOptions {\n /** A channel @handle or channel URL to resolve to a channel id. */\n channel: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeStreamsOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n [key: string]: unknown;\n}\n\nexport class YouTubeNamespace {\n constructor(private client: Scavio) {}\n\n async search(\n options: YouTubeSearchOptions,\n ): Promise<Record<string, unknown>> {\n const { query, fourK, video_360, video_3d, ...rest } = options;\n const body: Record<string, unknown> = {\n search: query,\n ...rest,\n };\n if (fourK !== undefined) body[\"4k\"] = fourK;\n if (video_360 !== undefined) body[\"360\"] = video_360;\n if (video_3d !== undefined) body[\"3d\"] = video_3d;\n return this.client._post(\"/api/v1/youtube/search\", body);\n }\n\n async shorts(\n options: YouTubeShortsOptions,\n ): Promise<Record<string, unknown>> {\n const { query, ...rest } = options;\n return this.client._post(\"/api/v1/youtube/shorts\", {\n search: query,\n ...rest,\n });\n }\n\n async suggestions(\n options: YouTubeSuggestionsOptions,\n ): Promise<Record<string, unknown>> {\n const { query, ...rest } = options;\n return this.client._post(\"/api/v1/youtube/suggestions\", {\n search: query,\n ...rest,\n });\n }\n\n async video(\n options: YouTubeVideoOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/video\", options);\n }\n\n /** @deprecated Use youtube.video(). Alias kept for backward compatibility. */\n async metadata(\n options: YouTubeMetadataOptions,\n ): Promise<Record<string, unknown>> {\n return this.video(options);\n }\n\n async comments(\n options: YouTubeCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/comments\", options);\n }\n\n async commentReplies(\n options: YouTubeCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/comments/replies\", options);\n }\n\n async transcript(\n options: YouTubeTranscriptOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/transcript\", options);\n }\n\n async related(\n options: YouTubeRelatedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/related\", options);\n }\n\n async channelSearch(\n options: YouTubeChannelSearchOptions,\n ): Promise<Record<string, unknown>> {\n const { query, ...rest } = options;\n return this.client._post(\"/api/v1/youtube/channel/search\", {\n search: query,\n ...rest,\n });\n }\n\n async channel(\n options: YouTubeChannelOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel\", options);\n }\n\n async channelVideos(\n options: YouTubeChannelVideosOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel/videos\", options);\n }\n\n async channelShorts(\n options: YouTubeChannelShortsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel/shorts\", options);\n }\n\n async channelCommunity(\n options: YouTubeChannelCommunityOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel/community\", options);\n }\n\n async channelResolve(\n options: YouTubeChannelResolveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel/resolve\", options);\n }\n\n async streams(\n options: YouTubeStreamsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/streams\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\nexport interface XSearchOptions {\n /** Search query (1-500 characters). */\n search: string;\n /** Result category (default 'Top'). */\n search_type?: \"Top\" | \"Latest\" | \"People\" | \"Photos\" | \"Videos\";\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface XTweetOptions {\n /** Tweet id. */\n tweet_id: string;\n [key: string]: unknown;\n}\n\nexport interface XTweetCommentsOptions {\n /** Tweet id. */\n tweet_id: string;\n /** 'top' (ranked) or 'latest' (chronological); default 'top'. */\n rank?: \"top\" | \"latest\";\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface XTweetRetweetersOptions {\n /** Tweet id. */\n tweet_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface XUserOptions {\n /** An X handle (without the @). */\n screen_name: string;\n [key: string]: unknown;\n}\n\nexport interface XUserFeedOptions {\n /** An X handle (without the @). */\n screen_name: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface XTrendingOptions {\n /** Country name (default 'UnitedStates'). */\n country?: string;\n [key: string]: unknown;\n}\n\nexport class XNamespace {\n constructor(private client: Scavio) {}\n\n async search(\n options: XSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/search\", options);\n }\n\n async tweet(\n options: XTweetOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/tweet\", options);\n }\n\n async tweetComments(\n options: XTweetCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/tweet/comments\", options);\n }\n\n async tweetRetweeters(\n options: XTweetRetweetersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/tweet/retweeters\", options);\n }\n\n async user(\n options: XUserOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user\", options);\n }\n\n async userTweets(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/tweets\", options);\n }\n\n async userReplies(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/replies\", options);\n }\n\n async userMedia(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/media\", options);\n }\n\n async userFollowers(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/followers\", options);\n }\n\n async userFollowings(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/followings\", options);\n }\n\n async trending(\n options: XTrendingOptions = {},\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/trending\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// The provider retired the `linkedin/web/*` namespace these were built on. Live\n// endpoints now run on `web_v2`, which is URL-native: public params are\n// unchanged (the permalink is built server-side) and `url` is accepted\n// everywhere as a direct alternative. Params web_v2 has no equivalent for (the\n// include_* flags, the member urn) are gone. Pagination is back as of the\n// provider's 2026-07-31 release: list endpoints take an opaque `cursor` and\n// return `next_cursor`, and personPosts gained a `type` feed selector.\n//\n// Five endpoints have no upstream left and always return HTTP 410 unbilled:\n// personContact, companyPeople, companyJobs, searchPeople, searchPosts. They are\n// kept so existing code fails loudly rather than with a TypeError.\n\n/** A member reference: a vanity handle, or a full profile URL. */\nexport interface LinkedInPersonOptions {\n /** Public identifier (vanity handle), e.g. \"williamhgates\". */\n username?: string;\n /** Full LinkedIn profile URL, as an alternative to username. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInPersonPostsRequest extends LinkedInPersonOptions {\n /** Which feed: the member's own posts (default), posts they commented on, or posts they reacted to. */\n type?: \"posts\" | \"comments\" | \"reactions\";\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n}\n\n/** A company reference: a universal name (slug), or a full company URL. */\nexport interface LinkedInCompanyOptions {\n /** Company universal name (slug), e.g. \"microsoft\". */\n company?: string;\n /** Full LinkedIn company URL, as an alternative to company. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInCompanyPostsRequest extends LinkedInCompanyOptions {\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n}\n\n// The person/company option shapes were reworked when the urn and count params\n// lost their upstream. These aliases keep the old type names importable so\n// existing TypeScript code still compiles.\n/** @deprecated Use {@link LinkedInPersonOptions}. */\nexport type LinkedInPersonRefOptions = LinkedInPersonOptions;\n/** @deprecated Use {@link LinkedInPersonPostsRequest}. */\nexport type LinkedInPersonPostsOptions = LinkedInPersonPostsRequest;\n/** @deprecated Use {@link LinkedInCompanyPostsRequest}. */\nexport type LinkedInCompanyPostsOptions = LinkedInCompanyPostsRequest;\n\nexport interface LinkedInSearchJobsOptions {\n /** Search keyword. */\n search: string;\n /** Geographic filter; omit to search everywhere. */\n location?: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInJobOptions {\n /** Job listing id. */\n job_id?: string;\n /** Full LinkedIn job URL, as an alternative to job_id. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInPostOptions {\n /** Post id or activity urn. */\n post_id?: string;\n /** Full LinkedIn post URL, as an alternative to post_id. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInPostCommentsOptions extends LinkedInPostOptions {\n /** 1-based page number. Page size varies, so page until a page comes back empty. */\n page?: number;\n}\n\n/** @deprecated Retired upstream; always returns HTTP 410. */\nexport interface LinkedInPersonContactOptions {\n username?: string;\n [key: string]: unknown;\n}\n\n/** @deprecated Retired upstream; always returns HTTP 410. */\nexport interface LinkedInCompanyRefOptions {\n company_id?: string;\n company?: string;\n [key: string]: unknown;\n}\n\n/** @deprecated Retired upstream; always returns HTTP 410. */\nexport interface LinkedInSearchPeopleOptions {\n search?: string;\n title?: string;\n company?: string;\n school?: string;\n location?: string;\n [key: string]: unknown;\n}\n\n/** @deprecated Retired upstream; always returns HTTP 410. */\nexport interface LinkedInSearchPostsOptions {\n search?: string;\n [key: string]: unknown;\n}\n\nexport class LinkedInNamespace {\n constructor(private client: Scavio) {}\n\n /** Full profile: about text, experience, education, honours and links. */\n async person(\n options: LinkedInPersonOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/person\", options);\n }\n\n /** The about-only slice of the profile payload. */\n async personAbout(\n options: LinkedInPersonOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/person/about\", options);\n }\n\n /**\n * A member's posts, or the posts they commented on or reacted to via `type`.\n * 50 per page; pass the previous response's `next_cursor` to advance.\n */\n async personPosts(\n options: LinkedInPersonPostsRequest,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/person/posts\", options);\n }\n\n /** Company profile, including locations and featured employees. */\n async company(\n options: LinkedInCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/company\", options);\n }\n\n /** Recent company posts, 50 per page; advance with `next_cursor`. */\n async companyPosts(\n options: LinkedInCompanyPostsRequest,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/company/posts\", options);\n }\n\n /**\n * Job search, 25 per page; advance with `next_cursor`. Upstream rotates its\n * result set, so pages overlap slightly - dedupe by job id.\n */\n async searchJobs(\n options: LinkedInSearchJobsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/search/jobs\", options);\n }\n\n /** Full detail for one job listing, including the hiring company. */\n async job(\n options: LinkedInJobOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/job\", options);\n }\n\n /** Full detail for one post, including its top visible comments. */\n async post(\n options: LinkedInPostOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/post\", options);\n }\n\n /** Comments with their replies. Page size varies - keep paging until empty. */\n async postComments(\n options: LinkedInPostCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/post/comments\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed.\n */\n async personContact(\n options: LinkedInPersonContactOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/person/contact\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed. `company()` returns `featured_employees`, a small sample of\n * staff profiles.\n */\n async companyPeople(\n options: LinkedInCompanyRefOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/company/people\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed. Use `searchJobs()` with the company name as the search term.\n */\n async companyJobs(\n options: LinkedInCompanyRefOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/company/jobs\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed.\n */\n async searchPeople(\n options: LinkedInSearchPeopleOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/search/people\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed.\n */\n async searchPosts(\n options: LinkedInSearchPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/search/posts\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Threads is body-priced. The upstream handle lookup is dead, so addressing a\n// user by `username` buys a second upstream call: 2 credits by `user_id`,\n// 4 credits by `username`. Only profile, userPosts and userReplies are\n// username-keyed - post, postComments and searchUsers are always 2 credits.\n// Resolve a handle once with searchUsers() or profile(), keep the returned\n// user_id, and every later call stays on the cheap path.\n//\n// There is NO Threads content search. Only people search exists\n// (searchUsers). Nothing here searches posts.\n//\n// Error codes differ from the scrape.do platforms: 404 when no user matches,\n// 422 when the identifier is missing or conflicting, 502 upstream. There is no\n// 400 and no 503.\n\n/** A user reference: the cheap numeric id, or the handle at double the cost. */\nexport interface ThreadsProfileOptions {\n /**\n * Numeric user id, e.g. \"63625256886\". The cheap path: 2 credits.\n */\n user_id?: string;\n /**\n * Handle without the leading @ (1-60 characters). Costs 2 extra credits\n * because the id has to be resolved upstream first - prefer `user_id`.\n */\n username?: string;\n [key: string]: unknown;\n}\n\nexport interface ThreadsUserPostsOptions extends ThreadsProfileOptions {\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n}\n\nexport interface ThreadsUserRepliesOptions extends ThreadsProfileOptions {\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n}\n\n/** A post reference: the post id, or its threads.net URL. */\nexport interface ThreadsPostOptions {\n /** Post id. */\n post_id?: string;\n /** Full threads.net post URL, as an alternative to post_id. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface ThreadsPostCommentsOptions {\n /** Post id. This endpoint takes the id only - no URL, no username. */\n post_id: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface ThreadsSearchUsersOptions {\n /** Name or handle to search for (1-200 characters). */\n query: string;\n [key: string]: unknown;\n}\n\nexport class ThreadsNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Profile details for a Threads user. Pass `user_id` or `username`;\n * sending neither returns 422 and no match returns 404.\n *\n * Costs 2 credits by `user_id`, 4 credits by `username`.\n */\n async profile(\n options: ThreadsProfileOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/profile\", options);\n }\n\n /**\n * A user's Threads posts. Advance with the previous response's\n * `next_cursor`. Pass `user_id` or `username`.\n *\n * Costs 2 credits by `user_id`, 4 credits by `username` - and that surcharge\n * applies to every page, so resolve the id once before paging.\n */\n async userPosts(\n options: ThreadsUserPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/user/posts\", options);\n }\n\n /**\n * A user's replies. Advance with the previous response's `next_cursor`.\n * Pass `user_id` or `username`.\n *\n * Costs 2 credits by `user_id`, 4 credits by `username` - and that surcharge\n * applies to every page, so resolve the id once before paging.\n */\n async userReplies(\n options: ThreadsUserRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/user/replies\", options);\n }\n\n /**\n * A single post, addressed by `post_id` or by its threads.net `url`.\n * Sending neither returns 422.\n *\n * Costs 2 credits.\n */\n async post(\n options: ThreadsPostOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/post\", options);\n }\n\n /**\n * Replies to a post. Advance with the previous response's `next_cursor`.\n *\n * Costs 2 credits - this endpoint is never username-keyed, so there is no\n * handle surcharge.\n */\n async postComments(\n options: ThreadsPostCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/post/comments\", options);\n }\n\n /**\n * Threads profiles matching a name or handle. This is people search, and it\n * is the only search Threads exposes - there is no content/post search.\n * Use it to turn a handle into the `user_id` every other method prefers.\n *\n * Costs 2 credits. Single response, no pagination.\n */\n async searchUsers(\n options: ThreadsSearchUsersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/search/users\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Kuaishou (China) - kuaishou.com. This is NOT Kwai international: kwai.com\n// ids and links are not served upstream and come back as an empty envelope,\n// so keep kwai.com URLs out of every call here.\n//\n// CREDITS ARE PER-ENDPOINT, not a platform constant. profile costs 10,\n// video costs 2, videosBatch costs 40, the four search endpoints cost 10 each,\n// and everything else costs 1. Each method's own cost is on its JSDoc - read\n// it before looping, because the spread between the cheapest and the dearest\n// call is 40x.\n//\n// videosBatch is hard-capped at 20 photo ids for that reason.\n//\n// Errors: Kuaishou hides upstream failures inside HTTP 200 bodies; the API\n// detects those and surfaces them as 502. A missing or invalid identifier is\n// 422. There is no 400, no 404 and no 503 on this platform.\n\nexport interface KuaishouProfileOptions {\n /** Kuaishou numeric user id, e.g. \"5518803932\". */\n user_id: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouUserPostsOptions {\n /** Kuaishou numeric user id. */\n user_id: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouUserLiveOptions {\n /** Kuaishou numeric user id. */\n user_id: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouUserResolveOptions {\n /**\n * A kuaishou.com or v.kuaishou.com link, e.g.\n * \"https://v.kuaishou.com/KcdKDwFp\". Kwai international (kwai.com) links\n * are not supported.\n */\n share_link: string;\n [key: string]: unknown;\n}\n\n/** A video reference: the photo id, or a Kuaishou URL. One of the two. */\nexport interface KuaishouVideoOptions {\n /** Photo (video) id, e.g. \"3xtdqvdnqd3psuc\". */\n photo_id?: string;\n /** A kuaishou.com or v.kuaishou.com video URL, as an alternative to photo_id. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouVideoCommentsOptions {\n /** Photo (video) id. This endpoint takes the id only - no URL. */\n photo_id: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouCommentRepliesOptions {\n /** Photo (video) id the root comment sits on. */\n photo_id: string;\n /** Id of the root comment whose replies you want. */\n root_comment_id: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n /** Replies per page, 1-50. */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface KuaishouVideosBatchOptions {\n /** Photo (video) ids, 1-20 per call. More than 20 is rejected. */\n photo_ids: string[];\n [key: string]: unknown;\n}\n\nexport interface KuaishouSearchOptions {\n /** Search keyword (1-200 characters). */\n keyword: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouSearchVideosOptions {\n /** Search keyword (1-200 characters). */\n keyword: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouSearchUsersOptions {\n /** Search keyword (1-200 characters). */\n keyword: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouSearchLiveOptions {\n /** Search keyword (1-200 characters). */\n keyword: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouTagFeedOptions {\n /** Hashtag text, without the leading # (1-200 characters). */\n tag: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouTrendingOptions {\n /** Which leaderboard to read (default \"hot\"). */\n board?: \"hot\" | \"live\" | \"shopping\" | \"brand\" | \"music\";\n [key: string]: unknown;\n}\n\nexport class KuaishouNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Profile details for a Kuaishou user, addressed by numeric `user_id`.\n *\n * Costs 10 credits - the dearest single-object call on the platform. If you\n * only have a share link, resolve it with `userResolve()` (1 credit) first.\n */\n async profile(\n options: KuaishouProfileOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/profile\", options);\n }\n\n /**\n * A user's top posts. Advance with the previous response's `next_cursor`.\n *\n * Costs 1 credit per page.\n */\n async userPosts(\n options: KuaishouUserPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/user/posts\", options);\n }\n\n /**\n * A user's current live-stream status.\n *\n * Costs 1 credit.\n */\n async userLive(\n options: KuaishouUserLiveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/user/live\", options);\n }\n\n /**\n * Turns a Kuaishou share link into a `user_id` you can feed to the other\n * user endpoints. kuaishou.com and v.kuaishou.com links only - kwai.com is\n * not supported.\n *\n * Costs 1 credit.\n */\n async userResolve(\n options: KuaishouUserResolveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/user/resolve\", options);\n }\n\n /**\n * A single video, addressed by `photo_id` or by its Kuaishou `url`.\n * Sending neither returns 422.\n *\n * Costs 2 credits.\n */\n async video(\n options: KuaishouVideoOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/video\", options);\n }\n\n /**\n * Comments on a video. Advance with the previous response's `next_cursor`.\n *\n * Costs 1 credit per page.\n */\n async videoComments(\n options: KuaishouVideoCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/video/comments\", options);\n }\n\n /**\n * Replies under a root comment. Advance with the previous response's\n * `next_cursor`; `count` (1-50) sizes the page.\n *\n * Costs 1 credit per page.\n */\n async commentReplies(\n options: KuaishouCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/video/sub-comments\", options);\n }\n\n /**\n * Several videos in one call, up to 20 photo ids (a hard cap - a longer\n * `photo_ids` array is rejected).\n *\n * Costs 40 credits per call, flat, whether you send 1 id or 20 - so batch\n * to the cap. For a single video `video()` costs 2.\n */\n async videosBatch(\n options: KuaishouVideosBatchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/videos/batch\", options);\n }\n\n /**\n * Mixed-result search across Kuaishou. Advance with the previous response's\n * `next_cursor`.\n *\n * Costs 10 credits per page.\n */\n async search(\n options: KuaishouSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/search\", options);\n }\n\n /**\n * Video search results. Advance with the previous response's `next_cursor`.\n *\n * Costs 10 credits per page.\n */\n async searchVideos(\n options: KuaishouSearchVideosOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/search/videos\", options);\n }\n\n /**\n * User search results. Advance with the previous response's `next_cursor`.\n *\n * Costs 10 credits per page.\n */\n async searchUsers(\n options: KuaishouSearchUsersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/search/users\", options);\n }\n\n /**\n * Live-stream search results. Advance with the previous response's\n * `next_cursor`.\n *\n * Costs 10 credits per page.\n */\n async searchLive(\n options: KuaishouSearchLiveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/search/live\", options);\n }\n\n /**\n * Posts under a hashtag. Advance with the previous response's `next_cursor`.\n *\n * Costs 1 credit per page - the cheap way to pull volume, versus 10 for\n * `search()`.\n */\n async tagFeed(\n options: KuaishouTagFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/tag/feed\", options);\n }\n\n /**\n * Leaderboards: hot, live, shopping, brand or music. Defaults to \"hot\".\n *\n * Costs 1 credit.\n */\n async trending(\n options: KuaishouTrendingOptions = {},\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/trending\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// eBay is 1 credit flat on all three endpoints.\n//\n// `seller` (the method) is a PROFILE endpoint - it returns the storefront card\n// and cannot enumerate a catalogue. To page a seller's inventory, call\n// search() with the `seller` option set and no `query` at all.\n//\n// `sold: true` searches completed listings that actually sold, which is the\n// price-research surface. eBay publishes no headline count on that view, so\n// `total_results` comes back null there.\n\nexport interface EbaySearchOptions {\n /**\n * Search keywords (1-500 characters). Optional, but either `query` or\n * `seller` must be present or the request is rejected.\n */\n query?: string;\n /**\n * Scope results to one seller's username. Usable with NO `query` to page\n * that seller's whole catalogue - this, not seller(), is how you enumerate\n * inventory.\n */\n seller?: string;\n /** Result page, 1-indexed. */\n page?: number;\n /** Result sort order (default \"best_match\"). */\n sort_by?:\n | \"best_match\"\n | \"ending_soonest\"\n | \"newly_listed\"\n | \"price_low\"\n | \"price_high\";\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n /**\n * Item condition. \"refurbished\" is eBay's parent condition, not one of its\n * three graded tiers.\n */\n condition?: \"new\" | \"open_box\" | \"refurbished\" | \"used\" | \"for_parts\";\n /** Listing format filter. */\n buying_format?: \"auction\" | \"buy_it_now\" | \"best_offer\";\n /** Free-shipping listings only. */\n free_shipping?: boolean;\n /**\n * Search completed listings that SOLD rather than live inventory.\n * `total_results` is null on this view - eBay publishes no headline count.\n */\n sold?: boolean;\n /**\n * eBay category id. Must be numeric: an unrecognised id is not an error,\n * it silently returns the UNFILTERED set under a 200.\n */\n category_id?: string;\n /**\n * Results per page. eBay accepts only 60, 120 or 240 and silently falls\n * back to 60 for anything else. Defaults to 60.\n */\n per_page?: 60 | 120 | 240;\n [key: string]: unknown;\n}\n\nexport interface EbayProductOptions {\n /**\n * eBay item number, or a full ebay.com/itm/... URL. Tracking params on a\n * pasted URL are discarded.\n */\n item_id: string;\n [key: string]: unknown;\n}\n\nexport interface EbaySellerOptions {\n /** eBay username as it appears in ebay.com/usr/<name>. */\n seller: string;\n [key: string]: unknown;\n}\n\nexport class EbayNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Structured eBay listing results: price, condition, bids, shipping, seller,\n * feedback, plus `count` and `total_results`.\n *\n * Either `query` or `seller` is required. Set `sold: true` to search\n * completed listings that actually sold - on that view `total_results` is\n * always null because eBay publishes no headline count for it.\n *\n * Paged with `page`; `per_page` accepts only 60, 120 or 240 and silently\n * falls back to 60 for any other value.\n *\n * Costs 1 credit.\n */\n async search(\n options: EbaySearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/ebay/search\", options);\n }\n\n /**\n * One eBay listing in full: price, condition, images, item specifics,\n * shipping, returns, auction state and seller.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async product(\n options: EbayProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/ebay/product\", options);\n }\n\n /**\n * A seller's profile card: store name, feedback score and percentage, items\n * sold, followers, location and categories.\n *\n * PROFILE ONLY - it cannot list what the seller is selling. For inventory,\n * call search({ seller }) with no query and page through it.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async seller(\n options: EbaySellerOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/ebay/seller\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Target is 1 credit flat on all four endpoints.\n//\n// LATENCY, not price, is what to plan for: Target's own API refuses proxy\n// pools and is reached through a headless browser. Typical wall time is\n// ~4s for product, ~9s for search, ~37s for category and ~40s for reviews,\n// and a retried 502 has been seen at 105s. Raise the client `timeout` before\n// calling category() or reviews().\n//\n// reviews() returns 8 review BODIES maximum whatever the product's\n// review_count says. `limit` only trims that set - there is no page or offset.\n//\n// `seller_id` / `seller_name` are null on first-party stock, which is most of\n// Target. Null there means \"sold by Target\", not missing data; only Target\n// Plus marketplace rows name a vendor.\n//\n// Unlike Walmart, `store_id` is a real request param here - prices and\n// availability are the caller's choice.\n\nexport interface TargetSearchOptions {\n /** Search keywords (1-500 characters). */\n keyword: string;\n /** Result page, 1-indexed. */\n page?: number;\n /** Results per page, 1-28 (default 24). Target rejects anything above 28. */\n count?: number;\n /** Result sort order (default \"relevance\"). */\n sort?:\n | \"relevance\"\n | \"featured\"\n | \"price_low\"\n | \"price_high\"\n | \"rating_high\"\n | \"best_seller\"\n | \"newest\";\n /** Numeric Target store id used for pricing and availability (default \"3991\"). */\n store_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TargetCategoryOptions {\n /** Category id: the segment after `N-` in a target.com /c/ URL. */\n category_id: string;\n /** Result page, 1-indexed. */\n page?: number;\n /** Results per page, 1-28 (default 24). Target rejects anything above 28. */\n count?: number;\n /** Result sort order (default \"relevance\"). */\n sort?:\n | \"relevance\"\n | \"featured\"\n | \"price_low\"\n | \"price_high\"\n | \"rating_high\"\n | \"best_seller\"\n | \"newest\";\n /** Numeric Target store id used for pricing and availability (default \"3991\"). */\n store_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TargetProductOptions {\n /**\n * Target TCIN. A child tcin is answered by its variation parent, with the\n * child itself present in `variants`.\n */\n tcin: string;\n /** Numeric Target store id used for pricing and availability (default \"3991\"). */\n store_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TargetReviewsOptions {\n /** Target TCIN. */\n tcin: string;\n /**\n * TRIMS the returned bodies only. Target publishes 8 reviews anonymously\n * and offers no paging, so this cannot reach a 9th review.\n */\n limit?: number;\n /** Numeric Target store id used for pricing and availability (default \"3991\"). */\n store_id?: string;\n [key: string]: unknown;\n}\n\nexport class TargetNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Target.com: prices, ratings, badges and promotions.\n *\n * Paged with `page` + `count` (1-28, default 24). `seller_id` and\n * `seller_name` are null on first-party rows, which means \"sold by Target\".\n *\n * Costs 1 credit. Typically ~9s - it runs through a headless browser.\n */\n async search(\n options: TargetSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/target/search\", options);\n }\n\n /**\n * Products in a Target category: the same shape as search() plus the\n * category breadcrumb.\n *\n * Paged with `page` + `count` (1-28, default 24).\n *\n * Costs 1 credit. The slowest endpoint here at ~37s - set a generous client\n * timeout before calling it.\n */\n async category(\n options: TargetCategoryOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/target/category\", options);\n }\n\n /**\n * Target product details by TCIN: price, rating, images, specifications,\n * variants, return policy and fulfillment.\n *\n * `store_id` is a real request param here - the price and availability you\n * get back are the store you asked for.\n *\n * Costs 1 credit. Typically ~4s. Single response, no pagination.\n */\n async product(\n options: TargetProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/target/product\", options);\n }\n\n /**\n * Target reviews with the rating breakdown, per-attribute averages and\n * guest photos.\n *\n * Returns 8 review BODIES MAXIMUM regardless of the product's review_count.\n * `limit` only trims that set; there is no page or offset param, so the\n * aggregate distribution is the full-population signal here, not the bodies.\n *\n * Costs 1 credit. Typically ~40s.\n */\n async reviews(\n options: TargetReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/target/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Home Depot is 2 credits flat on all three endpoints - it sits on the\n// premium per-domain proxy table, so it is the priciest of the retail\n// namespaces.\n//\n// Search page size is FIXED at 12 with no way to change it. Paging is the\n// only way to read further, and there is no per-page option to type.\n//\n// `sort_by` is a CLOSED enum on purpose. Home Depot does not fall back on an\n// unknown sort - it answers 200 with an empty page that still bills. \"Newest\"\n// (arrivaldate) is deliberately absent: it works on category pages and is\n// rejected on keyword search.\n//\n// Unknown item ids and out-of-range pages come back upstream as billed 200\n// shells; the API restates them as 404.\n\nexport interface HomeDepotSearchOptions {\n /** Search keywords (1-500 characters). */\n query: string;\n /** Result page, 1-indexed. Page size is fixed at 12 products. */\n page?: number;\n /**\n * Result sort order (default \"best_match\"). Closed set - an unrecognised\n * value is not ignored, it produces an empty billed page.\n */\n sort_by?: \"best_match\" | \"top_sellers\" | \"top_rated\" | \"price_low\" | \"price_high\";\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n [key: string]: unknown;\n}\n\nexport interface HomeDepotProductOptions {\n /**\n * Home Depot item id, or a full homedepot.com/p/... URL. Tracking params on\n * a pasted URL are discarded.\n */\n item_id: string;\n [key: string]: unknown;\n}\n\nexport interface HomeDepotReviewsOptions {\n /** Home Depot item id. */\n item_id: string;\n /**\n * Result page, 1-indexed. 30 reviews per page. `total_pages` is the last\n * page that exists - asking past it returns 404.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class HomeDepotNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Home Depot: price and promotions, brand and model, ratings,\n * badges, and per-store pickup/delivery.\n *\n * Page size is FIXED at 12 products and cannot be raised - page through\n * with `page` to read further.\n *\n * Costs 2 credits.\n */\n async search(\n options: HomeDepotSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/homedepot/search\", options);\n }\n\n /**\n * Full item detail: pricing and promotions, images and videos, the spec\n * table, dimensions, bullets, documents and return policy.\n *\n * Carries only a 10-review PREVIEW - reviews() is the paginated surface.\n * An unknown item id comes back as 404.\n *\n * Costs 2 credits. Single response, no pagination.\n */\n async product(\n options: HomeDepotProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/homedepot/product\", options);\n }\n\n /**\n * One page of full review bodies with the rating distribution,\n * per-attribute ratings, photos and seller responses.\n *\n * 30 reviews per page. `total_pages` is the last page that exists; a page\n * beyond it is a 404, not an empty result.\n *\n * Costs 2 credits.\n */\n async reviews(\n options: HomeDepotReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/homedepot/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Zillow is 1 credit flat on all three endpoints.\n//\n// A bare ZIP works ALONE but cannot be combined with a filter or a sort:\n// on that request shape Zillow resolves the region by geolocation and answers\n// about another city entirely. Pass the city name when you are filtering.\n//\n// On listing_status \"for_rent\", min_price / max_price mean MONTHLY RENT -\n// Zillow files rent under its payment filter, not its price filter.\n//\n// A region Zillow cannot resolve is a 404, not an empty result set.\n//\n// agentReviews() is named for what it addresses. The path is /zillow/reviews\n// but the subject is an AGENT profile keyed by screen name, never a property.\n\nexport interface ZillowSearchOptions {\n /**\n * Region to search: a Zillow slug, a human form (\"Austin, TX\"), a ZIP, or a\n * pasted Zillow search URL. A bare ZIP works only on its own - combined\n * with any filter or sort, Zillow geolocates instead and answers about a\n * different city, so use the city name there.\n */\n location: string;\n /** Which market to read (default \"for_sale\"). */\n listing_status?: \"for_sale\" | \"for_rent\" | \"sold\";\n /** Result page, 1-indexed. */\n page?: number;\n /**\n * Result sort order. Sorts that rank against a signed-in profile\n * (saved / featured / personalised) are deliberately absent - these\n * requests are never signed in.\n */\n sort?:\n | \"relevance\"\n | \"recommended\"\n | \"newest\"\n | \"price_low\"\n | \"price_high\"\n | \"payment_low\"\n | \"payment_high\"\n | \"beds\"\n | \"baths\"\n | \"sqft\"\n | \"lot_size\"\n | \"zestimate_low\"\n | \"zestimate_high\"\n | \"recent_change\";\n /**\n * Minimum price. On listing_status \"for_rent\" this is MONTHLY RENT, not\n * sale price.\n */\n min_price?: number;\n /**\n * Maximum price. On listing_status \"for_rent\" this is MONTHLY RENT, not\n * sale price.\n */\n max_price?: number;\n /** Minimum bedrooms. */\n beds_min?: number;\n /** Maximum bedrooms. */\n beds_max?: number;\n /** Minimum bathrooms. Half-baths allowed (1.5). */\n baths_min?: number;\n /** Maximum bathrooms. Half-baths allowed (1.5). */\n baths_max?: number;\n /** Minimum living area in square feet. */\n sqft_min?: number;\n /** Maximum living area in square feet. */\n sqft_max?: number;\n /** Minimum lot size in square feet. */\n lot_size_min?: number;\n /** Maximum lot size in square feet. */\n lot_size_max?: number;\n /** Earliest year built. */\n year_built_min?: number;\n /** Latest year built. */\n year_built_max?: number;\n /** Maximum monthly HOA fee. */\n max_hoa?: number;\n /** Property type filter. */\n home_type?:\n | \"houses\"\n | \"townhomes\"\n | \"multi_family\"\n | \"condos\"\n | \"apartments\"\n | \"manufactured\"\n | \"lots_land\";\n /**\n * Listed within: days as \"1\" | \"7\" | \"14\" | \"30\" | \"90\", or months as\n * \"6m\" | \"12m\" | \"24m\" | \"36m\". Closed enum - an unrecognised value is not\n * an error, it silently returns the UNFILTERED set under a 200.\n */\n days_on_zillow?: \"1\" | \"7\" | \"14\" | \"30\" | \"90\" | \"6m\" | \"12m\" | \"24m\" | \"36m\";\n /** Keyword filter applied to the listing text (1-200 characters). */\n keywords?: string;\n /** Pool only. */\n has_pool?: boolean;\n /** Garage only. */\n has_garage?: boolean;\n /** Air conditioning only. */\n has_air_conditioning?: boolean;\n /** Waterfront only. */\n is_waterfront?: boolean;\n /** Basement only. */\n has_basement?: boolean;\n /** New construction only. */\n is_new_construction?: boolean;\n /** Listings with an open house scheduled. */\n has_open_house?: boolean;\n /** Price-reduced listings only. */\n price_reduced?: boolean;\n /** Listings with a 3D tour. */\n is_3d_tour?: boolean;\n [key: string]: unknown;\n}\n\nexport interface ZillowPropertyOptions {\n /**\n * A zpid, a /homedetails/ URL, or a zillow.com/apartments/ building URL.\n * Rental buildings have no caller-visible zpid - search() returns\n * coordinates in that slot - so pass the /apartments/ URL for those.\n */\n zpid: string;\n [key: string]: unknown;\n}\n\nexport interface ZillowAgentReviewsOptions {\n /**\n * The agent's zillow.com/profile/<name>/ screen name, or a full profile\n * URL. Screen names may contain spaces.\n */\n screen_name: string;\n [key: string]: unknown;\n}\n\nexport class ZillowNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Listings in a region: price, beds, baths, living area, Zestimate,\n * coordinates, images and days on market.\n *\n * Paged with `page`. A bare ZIP works alone but not alongside a filter or a\n * sort - use the city name when filtering. On listing_status \"for_rent\",\n * min_price / max_price are MONTHLY RENT. A region Zillow cannot resolve is\n * a 404, not an empty list.\n *\n * Costs 1 credit.\n */\n async search(\n options: ZillowSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/zillow/search\", options);\n }\n\n /**\n * Full listing detail: price and price history, Zestimate, tax history,\n * description, RESO facts, rooms, schools, open houses, photos and\n * attribution. Rental buildings return floor plans, amenities and unit\n * counts instead.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async property(\n options: ZillowPropertyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/zillow/property\", options);\n }\n\n /**\n * An AGENT's profile and reviews: rating, review count, bodies with\n * sub-ratings, specialties, languages, licenses, service areas and sales\n * counts.\n *\n * This addresses an agent by screen name, NOT a property. Zillow\n * server-renders the first five reviews only: `count` is what came back,\n * `total_review_count` is what the agent actually has, and there is no way\n * to page to the rest.\n *\n * Costs 1 credit.\n */\n async agentReviews(\n options: ZillowAgentReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/zillow/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Redfin is 1 credit flat on all three endpoints. property() and market()\n// read the property / region PAGE, whose inlined request cache replaces the\n// ~40 upstream calls the page itself made - which is why they cost the same\n// as search().\n//\n// CITY NAMES ARE NOT ACCEPTED on `location`. Redfin's own name lookup is the\n// single path its edge blocks us from, so pass a redfin.com region URL\n// (/city/, /neighborhood/, /county/, /zipcode/), a bare 5-digit ZIP, or\n// `region_id` + `region_type` TOGETHER - the transport falls back to\n// `location` unless it has both halves.\n//\n// `region_id` is NOT a ZIP code. They are different number spaces, and a ZIP\n// passed as a region id resolves to another city rather than failing.\n//\n// Every numeric filter is truncated into Redfin's gis query, so FRACTIONAL\n// bounds are rejected rather than silently floored (1.5 baths would have\n// become 1).\n//\n// `days_on_market` comes back NULL on search() - Redfin's mainHouseInfo\n// carries no `dom` key. Do not build on that field.\n//\n// Two filter pairs are mutually exclusive by construction:\n// `max_days_on_market` + `min_days_on_market` (Redfin expresses both through\n// one param), and `sold_within_days` outside `listing_status: \"sold\"`.\n\nexport interface RedfinSearchOptions {\n /**\n * A redfin.com region URL (/city/, /neighborhood/, /county/, /zipcode/) or\n * a bare 5-digit ZIP, up to 500 characters. CITY NAMES ARE NOT ACCEPTED.\n * Required unless `region_id` AND `region_type` are both given.\n */\n location?: string;\n /**\n * Redfin's internal region id. NOT a ZIP code - a ZIP here resolves to a\n * different city instead of failing. Must be paired with `region_type`.\n */\n region_id?: number;\n /**\n * What `region_id` refers to: 1 neighborhood, 2 ZIP, 5 county, 6 city.\n * Must be paired with `region_id`.\n */\n region_type?: 1 | 2 | 5 | 6;\n /** Which market to read (default \"for_sale\"). */\n listing_status?: \"for_sale\" | \"sold\" | \"for_rent\";\n /**\n * Sold-listing lookback in days (default 90). REJECTED unless\n * `listing_status` is \"sold\" - it only widens whatever listing_status\n * already chose.\n */\n sold_within_days?: number;\n /** Result page, 1-indexed. */\n page?: number;\n /** Listings per page, 1-350 (default 100). */\n limit?: number;\n /** Result sort order (default \"recommended\"). */\n sort?:\n | \"recommended\"\n | \"price_low\"\n | \"price_high\"\n | \"newest\"\n | \"oldest\"\n | \"sqft_low\"\n | \"sqft_high\"\n | \"price_per_sqft_low\"\n | \"price_per_sqft_high\";\n /**\n * Minimum price. On `listing_status: \"for_rent\"` this is MONTHLY RENT, not\n * sale price.\n */\n min_price?: number;\n /**\n * Maximum price. On `listing_status: \"for_rent\"` this is MONTHLY RENT, not\n * sale price.\n */\n max_price?: number;\n /** Minimum bedrooms. Whole numbers only. */\n beds_min?: number;\n /** Maximum bedrooms. Whole numbers only. */\n beds_max?: number;\n /**\n * Minimum bathrooms. WHOLE baths only - a fractional value such as 1.5 is\n * rejected, not rounded.\n */\n baths_min?: number;\n /** Minimum living area in square feet. Whole numbers only. */\n sqft_min?: number;\n /** Maximum living area in square feet. Whole numbers only. */\n sqft_max?: number;\n /** Minimum lot size in square feet. Whole numbers only. */\n lot_size_min?: number;\n /** Earliest year built. */\n year_built_min?: number;\n /** Latest year built. */\n year_built_max?: number;\n /** Maximum monthly HOA fee. */\n max_hoa?: number;\n /**\n * Property class. Redfin's uipt code 7 is deliberately absent - its meaning\n * could not be confirmed and a guess would silently search a different\n * class.\n */\n property_type?:\n | \"house\"\n | \"condo\"\n | \"townhouse\"\n | \"multi_family\"\n | \"land\"\n | \"other\"\n | \"co_op\";\n /** Listings with a pool only. */\n has_pool?: boolean;\n /**\n * Maximum days on market. Cannot be combined with `min_days_on_market` -\n * Redfin expresses both through ONE param, so the transport would send the\n * max and drop the min.\n */\n max_days_on_market?: number;\n /**\n * Minimum days on market. Cannot be combined with `max_days_on_market`.\n */\n min_days_on_market?: number;\n [key: string]: unknown;\n}\n\nexport interface RedfinPropertyOptions {\n /**\n * A Redfin property id, or any redfin.com listing URL carrying one (up to\n * 500 characters).\n */\n property_id: string;\n [key: string]: unknown;\n}\n\nexport interface RedfinMarketOptions {\n /**\n * A redfin.com region URL (/city/, /neighborhood/, /county/, /zipcode/) or\n * a bare 5-digit ZIP, up to 500 characters. CITY NAMES ARE NOT ACCEPTED.\n * Required unless `region_id` AND `region_type` are both given.\n */\n location?: string;\n /**\n * Redfin's internal region id. NOT a ZIP code. Must be paired with\n * `region_type`.\n */\n region_id?: number;\n /**\n * What `region_id` refers to: 1 neighborhood, 2 ZIP, 5 county, 6 city.\n * Must be paired with `region_id`.\n */\n region_type?: 1 | 2 | 5 | 6;\n [key: string]: unknown;\n}\n\nexport class RedfinNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Redfin listings: price, price per sqft, beds, baths, living area, lot\n * size, year built, coordinates, listing remarks and full photo galleries.\n *\n * Pass `location` (a redfin.com region URL or a bare ZIP - city NAMES are\n * not accepted) or `region_id` AND `region_type` together. Paged with\n * `page` + `limit`, up to 350 listings per page.\n *\n * `days_on_market` comes back NULL on every row: Redfin's mainHouseInfo has\n * no `dom` key. Fractional numeric filters are rejected, not rounded.\n * `sold_within_days` requires `listing_status: \"sold\"`, and\n * `max_days_on_market` / `min_days_on_market` cannot be combined.\n *\n * Costs 1 credit.\n */\n async search(\n options: RedfinSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/redfin/search\", options);\n }\n\n /**\n * One Redfin listing in full: price, Redfin Estimate and rental estimate,\n * complete MLS fact sheet, price and tax history, listing agents, open\n * houses, schools, climate risk, walkability and location scores, sun\n * exposure, monthly weather, permits, zoning, comparable sales and photos.\n *\n * Reads the property PAGE, whose inlined request cache replaces the ~40\n * upstream calls that page made - which is why it is the same price as\n * search().\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async property(\n options: RedfinPropertyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/redfin/property\", options);\n }\n\n /**\n * Housing-market stats for a region: median list and sale price, price per\n * sqft, sale-to-list ratio, average offers and days on market, YoY\n * movement, Redfin's 0-100 compete score, live inventory by property type,\n * median price and active listings per bedroom count, plus Redfin agent\n * presence and aggregate rating.\n *\n * Pass `location` (city NAMES are not accepted) or `region_id` AND\n * `region_type` together.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async market(\n options: RedfinMarketOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/redfin/market\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Booking.com is 1 credit flat on all three endpoints.\n//\n// `checkin` and `checkout` must be sent TOGETHER on every endpoint. Booking\n// ignores a lone checkin and prices a default range of its own, so the\n// response comes back with real prices for dates nobody asked for.\n//\n// hotel() and reviews() take dates for the same reason search does: Booking\n// prices a STAY, not a property. Omit them and you get prices for a two-night\n// window Booking chose; the response echoes whichever dates were used.\n//\n// `currency` defaults to USD in the transport. Without it Booking prices off\n// the proxy exit and two identical requests disagree.\n//\n// A search with neither `destination` nor `dest_id` would land on Booking's\n// HOMEPAGE - a billed request that returns nothing - so it is rejected at the\n// edge instead. `dest_type` is likewise rejected without `dest_id`, because\n// Booking silently ignores it on its own.\n//\n// Chain the `url` a search row returns into hotel() / reviews(). A bare page\n// slug with the wrong `country_code` is a real 404 that scrape.do BILLS.\n\nexport interface BookingSearchOptions {\n /**\n * Free-text destination, 1-200 characters (\"Paris\", \"Lisbon, Portugal\").\n * Either `destination` or `dest_id` is required.\n */\n destination?: string;\n /**\n * Numeric Booking destination id. Either `destination` or `dest_id` is\n * required.\n */\n dest_id?: string;\n /**\n * What `dest_id` refers to. Rejected without `dest_id` - Booking silently\n * ignores it on its own.\n */\n dest_type?:\n | \"city\"\n | \"region\"\n | \"country\"\n | \"district\"\n | \"landmark\"\n | \"airport\"\n | \"hotel\";\n /** Result page, 1-indexed. 25 properties per page. */\n page?: number;\n /** Result sort order (default \"popularity\"). */\n sort_by?:\n | \"popularity\"\n | \"price_low\"\n | \"price_high\"\n | \"stars_high\"\n | \"stars_low\"\n | \"stars_and_price\"\n | \"distance\"\n | \"review_score\";\n /** Minimum price PER NIGHT, in `currency`. Must be <= `max_price`. */\n min_price?: number;\n /** Maximum price PER NIGHT, in `currency`. */\n max_price?: number;\n /** Star ratings to keep, 1-5 each, up to 5 values. OR'd together. */\n stars?: number[];\n /**\n * Minimum guest review score. A CLOSED set - Booking silently drops an\n * arbitrary threshold, so only \"6\", \"7\", \"8\" and \"9\" are accepted.\n */\n min_review_score?: \"6\" | \"7\" | \"8\" | \"9\";\n /**\n * Accommodation type by name, or a raw numeric Booking accommodation-type\n * id.\n */\n property_type?:\n | \"apartments\"\n | \"hostels\"\n | \"hotels\"\n | \"motels\"\n | \"resorts\"\n | \"bed_and_breakfasts\"\n | \"villas\"\n | \"campgrounds\"\n | \"vacation_homes\"\n | \"lodges\"\n | \"homestays\"\n | number;\n /** Free-cancellation rates only. */\n free_cancellation?: boolean;\n /** No-prepayment rates only. */\n no_prepayment?: boolean;\n /** Breakfast-included rates only. */\n breakfast_included?: boolean;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `checkout` and\n * before it.\n */\n checkin?: string;\n /** Check-out date, YYYY-MM-DD. Must be sent together with `checkin`. */\n checkout?: string;\n /** Adults in the party (default 2). */\n adults?: number;\n /** Child AGES, 0-17 each, up to 10 values. Ages, not a count. */\n children_ages?: number[];\n /** Rooms to price (default 1). */\n rooms?: number;\n /**\n * ISO 4217 currency, 3 letters (default \"USD\"). Leave it set - without a\n * currency Booking prices off the proxy exit.\n */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface BookingHotelOptions {\n /**\n * booking.com property URL or the bare page slug, 1-500 characters. Query\n * params are discarded. Chaining the `url` from a search row is cheapest -\n * a bare slug with the wrong `country_code` is a BILLED 404.\n */\n hotel: string;\n /** Two-letter country code (default \"us\"). Only consulted for a bare slug. */\n country_code?: string;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `checkout` and\n * before it. Omitting both prices a two-night window Booking chose.\n */\n checkin?: string;\n /** Check-out date, YYYY-MM-DD. Must be sent together with `checkin`. */\n checkout?: string;\n /** Adults in the party (default 2). */\n adults?: number;\n /** Child AGES, 0-17 each, up to 10 values. Ages, not a count. */\n children_ages?: number[];\n /** Rooms to price (default 1). */\n rooms?: number;\n /** ISO 4217 currency, 3 letters (default \"USD\"). */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface BookingReviewsOptions {\n /**\n * booking.com property URL or the bare page slug, 1-500 characters. Query\n * params are discarded.\n */\n hotel: string;\n /** Two-letter country code (default \"us\"). Only consulted for a bare slug. */\n country_code?: string;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `checkout` and\n * before it.\n */\n checkin?: string;\n /** Check-out date, YYYY-MM-DD. Must be sent together with `checkin`. */\n checkout?: string;\n /** Adults in the party (default 2). */\n adults?: number;\n /** Child AGES, 0-17 each, up to 10 values. Ages, not a count. */\n children_ages?: number[];\n /** Rooms to price (default 1). */\n rooms?: number;\n /** ISO 4217 currency, 3 letters (default \"USD\"). */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport class BookingNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Booking.com properties for a destination and stay: live nightly\n * price, review score, star rating, location, room type and deal badges.\n *\n * Either `destination` or `dest_id` is required - without one the request\n * would land on Booking's homepage, so it is rejected instead of billed.\n * `dest_type` requires `dest_id`.\n *\n * Paged with `page`, 25 properties per page. `checkin` and `checkout` must\n * be sent together or Booking prices a range of its own choosing.\n *\n * Each row carries a `url` - chain it into hotel() rather than rebuilding a\n * slug, which risks a BILLED 404 on the wrong `country_code`.\n *\n * Costs 1 credit.\n */\n async search(\n options: BookingSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/booking/search\", options);\n }\n\n /**\n * One Booking.com property in full: rooms and rate plans, facilities, house\n * rules, check-in windows, policies, images, location and review scores -\n * priced for the stay you ask for.\n *\n * Takes dates because Booking prices a STAY. Omit them and the response\n * carries prices for a two-night window Booking picked; the response echoes\n * whichever dates were used.\n *\n * Single response, no pagination.\n *\n * Costs 1 credit.\n */\n async hotel(\n options: BookingHotelOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/booking/hotel\", options);\n }\n\n /**\n * Booking.com guest reviews with the score breakdown by category and\n * Booking's own praise/complaint summary.\n *\n * NO PAGE PARAM - do not invent one. `total_count` is the property's whole\n * review history; `count` is what this response holds.\n *\n * Costs 1 credit.\n */\n async reviews(\n options: BookingReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/booking/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Airbnb is 1 credit flat on all three endpoints.\n//\n// PRICES ARE SEARCH-ONLY. listing() carries NO nightly rate under any\n// parameters - with or without dates, and even under render. Read prices off\n// search() rows.\n//\n// The RATING BREAKDOWN is the mirror image: the six category ratings, the\n// five-bucket star distribution and Airbnb's AI-synthesised review tags live\n// on listing(), which server-renders them - NOT on reviews().\n//\n// `check_in` and `check_out` must be sent together. A dateless search defaults\n// to +30 days / 5 nights AND A/Bs both the window and the prices - one URL was\n// seen splitting 3/3 across two windows with a first-row price of $680 / $802\n// / $2,238. The response flags this as `dates_are_defaulted`, so pass dates\n// whenever the price matters.\n//\n// `currency` defaults to USD in the transport; without it Airbnb prices off\n// the proxy exit and two identical requests disagree.\n//\n// `room_type` and amenity NAMES are validated before the scrape, because an\n// unrecognised value makes Airbnb return the UNFILTERED set under a 200.\n//\n// Search is 18 listings per page and `cursor` WINS over `page`, so sending\n// both is rejected.\n\nexport interface AirbnbSearchOptions {\n /**\n * City, region, ZIP, or a pasted airbnb.com/s/ URL, 1-200 characters. A\n * location Airbnb cannot resolve is a 404, not an empty result.\n */\n location: string;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `check_out` and\n * before it. Omitted, the transport defaults to +30 days and the response\n * sets `dates_are_defaulted`.\n */\n check_in?: string;\n /**\n * Check-out date, YYYY-MM-DD. Must be sent together with `check_in`.\n * Omitted, it defaults to `check_in` + 5 nights.\n */\n check_out?: string;\n /** Adults in the party. */\n adults?: number;\n /** Children, ages 2-12. */\n children?: number;\n /** Infants. */\n infants?: number;\n /** Pets. */\n pets?: number;\n /**\n * Minimum price for the WHOLE STAY, not per night. Must be <= `max_price`.\n */\n min_price?: number;\n /** Maximum price for the WHOLE STAY, not per night. */\n max_price?: number;\n /** Room type. A closed set - an unrecognised value is rejected up front. */\n room_type?: \"entire_home\" | \"private_room\" | \"shared_room\" | \"hotel_room\";\n /** Minimum bedrooms. */\n min_bedrooms?: number;\n /** Minimum beds. */\n min_beds?: number;\n /** Minimum bathrooms. */\n min_bathrooms?: number;\n /** Superhost listings only. */\n superhost?: boolean;\n /** Instant Book listings only. */\n instant_book?: boolean;\n /** Guest Favourite listings only. */\n guest_favorite?: boolean;\n /** Free-cancellation listings only. */\n free_cancellation?: boolean;\n /**\n * Comma-separated amenity filter, 1-200 characters. Either the named\n * vocabulary - \"wifi\", \"air_conditioning\", \"pool\", \"kitchen\",\n * \"free_parking\", \"washer\", \"self_check_in\", \"tv\" - or raw numeric Airbnb\n * amenity ids. An unrecognised NAME is rejected before the scrape, because\n * Airbnb would otherwise answer the UNFILTERED set under a 200.\n */\n amenities?: string;\n /**\n * ISO 4217 currency (default \"USD\"). Leave it set - without a currency\n * Airbnb prices off the proxy exit.\n */\n currency?: string;\n /**\n * Result page, 1-indexed. 18 listings per page. Cannot be combined with\n * `cursor`.\n */\n page?: number;\n /**\n * `next_cursor` from a previous response, 1-500 characters. Wins over\n * `page`, so sending both is rejected.\n */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface AirbnbListingOptions {\n /**\n * Airbnb listing id or a full /rooms/ URL, 1-500 characters. Query params\n * are discarded - they carry someone else's dates.\n */\n listing_id: string;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `check_out` and\n * before it. Dates do NOT produce a price here - the room page has none.\n */\n check_in?: string;\n /** Check-out date, YYYY-MM-DD. Must be sent together with `check_in`. */\n check_out?: string;\n /** Adults in the party. */\n adults?: number;\n /** Children, ages 2-12. */\n children?: number;\n /** Infants. */\n infants?: number;\n /** Pets. */\n pets?: number;\n /** ISO 4217 currency (default \"USD\"). */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface AirbnbReviewsOptions {\n /** Airbnb listing id or a full /rooms/ URL, 1-500 characters. */\n listing_id: string;\n /** ISO 4217 currency (default \"USD\"). */\n currency?: string;\n /**\n * Reviews per response, 1-50 (default 30). Send it explicitly - upstream\n * falls back to a fixed 7 rows when no limit is given.\n */\n limit?: number;\n /** Row offset into the review list (default 0). */\n offset?: number;\n [key: string]: unknown;\n}\n\nexport class AirbnbNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Airbnb stays: stay-total and per-night price with the full\n * discount ledger, rating and review count, bedrooms/beds/baths,\n * coordinates, badges, images and `dates_are_defaulted`.\n *\n * This is the ONLY endpoint that carries a price - listing() has no nightly\n * rate field at all.\n *\n * Paged with `page` (18 listings per page) XOR `cursor`; `cursor` wins, so\n * sending both is rejected. `min_price` / `max_price` are WHOLE-STAY totals,\n * not per night.\n *\n * Pass `check_in` + `check_out` together whenever price matters: a dateless\n * search defaults to +30 days / 5 nights and A/Bs both the window and the\n * prices, which the response flags as `dates_are_defaulted`.\n *\n * Costs 1 credit.\n */\n async search(\n options: AirbnbSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/airbnb/search\", options);\n }\n\n /**\n * One Airbnb listing in full: description, property and room type, capacity\n * and room counts, the complete grouped amenity list (including the\n * amenities the place does NOT have), host profile and stats, house rules\n * with parsed check-in/out times, cancellation policy, sleeping\n * arrangements, photo tour, every image, and the RATING BREAKDOWN - six\n * category ratings, the five-bucket star distribution and Airbnb's\n * AI-synthesised review tags.\n *\n * NO NIGHTLY PRICE. The room page carries no rate under any parameters,\n * with or without dates. Prices come from search() only.\n *\n * Single response, no pagination.\n *\n * Costs 1 credit.\n */\n async listing(\n options: AirbnbListingOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/airbnb/listing\", options);\n }\n\n /**\n * Airbnb review BODIES with per-review rating, date, and reviewer name,\n * photo and location.\n *\n * Paged with `limit` (1-50, default 30) + `offset`. Send `limit`\n * explicitly - upstream returns a fixed 7 rows when none is given.\n *\n * `count` is the listing's TOTAL review count; `returned` is how many rows\n * this page holds. The rating breakdown is NOT here - it lives on\n * listing().\n *\n * Costs 1 credit.\n */\n async reviews(\n options: AirbnbReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/airbnb/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Tripadvisor is 2 credits flat on all four endpoints.\n//\n// START WITH locations(). Every other endpoint is keyed by ids that exist\n// only inside Tripadvisor's own URLs, so a caller holding a place NAME has no\n// other entry point. A GEO row from locations() answers `geo_id` for search();\n// a business row answers the `geo_id` + `location_id` pair that location() and\n// reviews() take.\n//\n// Page 1 of a location's reviews already rides along inside location() - call\n// reviews() only to page PAST it.\n//\n// Review page size differs by family: 15 per page for restaurants, 10 for\n// hotels and attractions. Keep `category` matched to the location's own type\n// on any page past the first. Consecutive pages can REPEAT one review at the\n// boundary - de-duplicate on review_id when concatenating.\n//\n// Search renders 30 locations per page and a page beyond the last is a 404,\n// not an empty result. An unknown location id is answered upstream with a 200\n// city listing (billed) that the transport restates as a 404.\n\nexport interface TripadvisorLocationsOptions {\n /** Place or business NAME to resolve, 1-120 characters. */\n query: string;\n /**\n * How many matches to return, 1-20 (default 12). This only SIZES the\n * response - it is not a page param.\n */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface TripadvisorSearchOptions {\n /**\n * Tripadvisor geo id. Accepts 30196, g30196, or a URL carrying one. Either\n * `geo_id` or `url` is required.\n */\n geo_id?: string;\n /** Which listing family to read (default \"restaurants\"). */\n category?: \"restaurants\" | \"hotels\" | \"attractions\";\n /**\n * Result page, 1-indexed. 30 locations per page; a page beyond the last is\n * a 404, not an empty result.\n */\n page?: number;\n /**\n * Full tripadvisor.com listing URL, 1-500 characters. The host is checked by\n * the transport (subdomain-aware, covers country sites). Either `geo_id` or\n * `url` is required.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface TripadvisorLocationOptions {\n /**\n * Tripadvisor location id. Accepts 1899234, d1899234, or a full _Review\n * URL. Either `location_id` or `url` is required.\n */\n location_id?: string;\n /**\n * Tripadvisor geo id. Required by the transport when a bare d-id is sent -\n * the pair comes straight off a locations() business row.\n */\n geo_id?: string;\n /** Which listing family the location belongs to (default \"restaurants\"). */\n category?: \"restaurants\" | \"hotels\" | \"attractions\";\n /**\n * Full tripadvisor.com listing URL, 1-500 characters. Either `location_id`\n * or `url` is required.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface TripadvisorReviewsOptions {\n /**\n * Tripadvisor location id. Accepts 1899234, d1899234, or a full _Review\n * URL. Either `location_id` or `url` is required.\n */\n location_id?: string;\n /** Tripadvisor geo id for the location. */\n geo_id?: string;\n /**\n * Which listing family the location belongs to (default \"restaurants\").\n * Page size follows this, so it must match the location's own type on any\n * page past the first.\n */\n category?: \"restaurants\" | \"hotels\" | \"attractions\";\n /**\n * Full tripadvisor.com listing URL, 1-500 characters. Either `location_id`\n * or `url` is required.\n */\n url?: string;\n /**\n * Result page, 1-indexed. 15 per page for restaurants, 10 for hotels and\n * attractions. Past the last page is a 404.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class TripadvisorNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Resolve a place or business NAME to the Tripadvisor\n * geo_id / location_id pairs every other endpoint needs.\n *\n * A GEO row answers `geo_id` for search(); a business row answers the\n * `geo_id` + `location_id` pair location() and reviews() take. Those ids\n * exist only inside Tripadvisor's own URLs, so this is the only entry point\n * from a name.\n *\n * `limit` (1-20, default 12) sizes the response; there is no pagination.\n *\n * Costs 2 credits.\n */\n async locations(\n options: TripadvisorLocationsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tripadvisor/locations\", options);\n }\n\n /**\n * Restaurants, hotels or attractions in a Tripadvisor geo, Tripadvisor-\n * ranked: rating, review count, price band, address, coordinates, phone,\n * hours and Travelers' Choice badge. Each row carries the location_id +\n * geo_id pair the detail endpoints take.\n *\n * `geo_id` or `url` is required - get `geo_id` from locations().\n *\n * Paged with `page`, 30 locations per page. A page beyond the last is a\n * 404, not an empty result.\n *\n * Costs 2 credits.\n */\n async search(\n options: TripadvisorSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tripadvisor/search\", options);\n }\n\n /**\n * One Tripadvisor location in full: rating, review histogram and per-aspect\n * sub-ratings, city ranking, price band, cuisines, amenities, address,\n * coordinates, contact, photos, and the FIRST PAGE OF REVIEWS.\n *\n * `location_id` or `url` is required, and the transport additionally\n * requires a geo when a bare d-id is sent.\n *\n * Page 1 of the reviews is already here - call reviews() only to page PAST\n * it. An unknown location id is a 404 (upstream answers a billed city\n * listing that the transport restates).\n *\n * Costs 2 credits.\n */\n async location(\n options: TripadvisorLocationOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tripadvisor/location\", options);\n }\n\n /**\n * A page of Tripadvisor reviews: rating, trip date and type, reviewer home\n * town and contribution count, and any management response.\n *\n * `location_id` or `url` is required. Page size follows `category` - 15 per\n * page for restaurants, 10 for hotels and attractions - so keep it matched\n * to the location's own type on any page past the first.\n *\n * Consecutive pages can REPEAT one review at the boundary; de-duplicate on\n * review_id when concatenating.\n *\n * Costs 2 credits.\n */\n async reviews(\n options: TripadvisorReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tripadvisor/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Yelp is 2 credits flat on all three endpoints - it sits on the premium\n// per-domain proxy table.\n//\n// REVIEWS PAGE 1 IS REDUNDANT. business() already returns the first page of\n// reviews at no extra cost, and reviews({ page: 1 }) re-fetches the exact same\n// document for another 2 credits. Start at page 2.\n//\n// `location` is effectively REQUIRED on search: Yelp geolocates a\n// location-less search off the proxy exit, so the same request can answer\n// about a different metro run to run.\n//\n// Yelp fixes the page size at 10 for both search and reviews, and a page past\n// the last review is a 404, not an empty result.\n//\n// `sort` is a CLOSED enum on both endpoints because Yelp ignores an\n// unrecognised sortby and serves default ranking under a 200 - a billed\n// premium scrape for a sort that never ran.\n//\n// popular_items on business() has a stub-shell state: rows arrive with every\n// field null but `identifier`. Those rows are dropped and\n// popular_items_omitted flags it.\n\nexport interface YelpSearchOptions {\n /**\n * What to search for (1-200 characters), e.g. \"coffee\". Required together\n * with `location` unless `url` is given.\n */\n term?: string;\n /**\n * Where to search (1-200 characters), e.g. \"Austin, TX\". Effectively\n * REQUIRED - without it Yelp geolocates off the proxy exit and the same\n * request answers about a different metro run to run.\n */\n location?: string;\n /** Result page, 1-indexed. Yelp fixes the page size at 10. */\n page?: number;\n /**\n * Result sort order (default \"recommended\"). Closed set - Yelp ignores an\n * unrecognised value and serves default ranking under a billed 200.\n */\n sort?: \"recommended\" | \"rating\" | \"review_count\";\n /** Price bands to include, 1 ($) to 4 ($$$$). 1-4 entries. */\n price?: Array<1 | 2 | 3 | 4>;\n /** Businesses open at request time only. */\n open_now?: boolean;\n /**\n * Raw Yelp filter aliases (RestaurantsDelivery, GoodForKids,\n * WheelchairAccessible), max 20. Deliberate PASSTHROUGH, not an enum -\n * Yelp's vocabulary runs ~117 values per vertical, and an alias it does not\n * know is ignored upstream so results come back unfiltered.\n */\n attributes?: string[];\n /**\n * A full yelp.com/search URL as an alternative to term + location\n * (1-1000 characters).\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface YelpBusinessOptions {\n /**\n * Yelp alias (desnudo-coffee-austin-2), opaque encid, or a yelp.com/biz URL\n * (1-500 characters). Either this or `url` is required.\n */\n business_id?: string;\n /** A yelp.com/biz URL (1-1000 characters). Either this or `business_id` is required. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface YelpReviewsOptions {\n /**\n * Yelp alias, opaque encid, or a yelp.com/biz URL (1-500 characters).\n * Either this or `url` is required.\n */\n business_id?: string;\n /** A yelp.com/biz URL (1-1000 characters). Either this or `business_id` is required. */\n url?: string;\n /**\n * Result page, 1-indexed, 10 reviews per page. PAGE 1 IS REDUNDANT with\n * business() and costs another 2 credits - start at page 2. A page past the\n * last review is a 404, not an empty result.\n */\n page?: number;\n /**\n * Review sort order (default \"relevance\"). Closed set - an unrecognised\n * value is served as default ranking under a billed 200.\n */\n sort?: \"relevance\" | \"newest\" | \"oldest\" | \"rating_high\" | \"rating_low\" | \"elites\";\n /** Keep only reviews at this star rating. Changes filtered_review_count, not review_count. */\n rating?: 1 | 2 | 3 | 4 | 5;\n [key: string]: unknown;\n}\n\nexport class YelpNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Businesses in Yelp's ranked order: rating, review count, price band,\n * categories, address, contact rails, hours, photos and a review snippet.\n * Each row carries both business_id and alias, either of which addresses\n * business(). `count` is the 10-row page, `total_results` is Yelp's headline\n * count.\n *\n * `term` + `location` or `url` is required, and `location` is effectively\n * mandatory - Yelp geolocates a location-less search off the proxy exit.\n * Paged with `page`; the page size is fixed at 10.\n *\n * Costs 2 credits.\n */\n async search(\n options: YelpSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/yelp/search\", options);\n }\n\n /**\n * One business in full: rating and per-star histogram, review count, price\n * band, categories, address and coordinates, phone, website and menu links,\n * hours and holidays, amenities, photos and videos, popular items, health\n * inspections, Q&A, licences and claim status - PLUS the first page of\n * reviews at no extra cost.\n *\n * Because those reviews ride along, calling reviews({ page: 1 }) after this\n * buys the same document twice. Yelp's recommendation software hides some\n * reviews entirely; those are never returned and are counted in\n * not_recommended_review_count here. popular_items rows can arrive as stub\n * shells with every field null but `identifier` - those are dropped and\n * popular_items_omitted flags it.\n *\n * `business_id` or `url` is required. Costs 2 credits. Single response, no\n * pagination.\n */\n async business(\n options: YelpBusinessOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/yelp/business\", options);\n }\n\n /**\n * A page of reviews: rating, full text, language, author profile and\n * expertise counts, attached photos, reaction counts and owner response.\n *\n * START AT PAGE 2 - page 1 re-fetches the document business() already\n * returned and costs another 2 credits. 10 reviews per page, and a page past\n * the last review is a 404, not an empty result. `rating` changes\n * filtered_review_count, not review_count.\n *\n * `business_id` or `url` is required. Costs 2 credits.\n */\n async reviews(\n options: YelpReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/yelp/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Indeed is 2 credits flat on all four endpoints.\n//\n// `radius` and `max_age_days` are CLOSED sets. Indeed IGNORES any other value\n// and answers the unfiltered set, so a request for a 7-mile radius is billed\n// as a search covering fifty. The unions here are the whole accepted\n// vocabulary: radius 0/5/10/15/25/35/50/100 (upstream default 50) and\n// max_age_days 1/3/7/14.\n//\n// `min_salary` filters on INDEED'S OWN ESTIMATE for the role, not a posted\n// figure, so postings that publish no salary at all still match.\n//\n// A location-only search - no `query` - is valid and returns every posting in\n// a metro.\n//\n// Search is 10 postings per page; company reviews are 20 per page. An unknown\n// job key or company slug is a real 404 that scrape.do BILLS.\n\nexport interface IndeedSearchOptions {\n /**\n * Search keywords, 1-500 characters. Optional: either `query` or `location`\n * must be present.\n */\n query?: string;\n /**\n * City+state, postal code, state, country or \"Remote\", 1-200 characters.\n * Usable with NO `query` at all - that returns every posting in the metro.\n */\n location?: string;\n /** Result page, 1-indexed. 10 postings per page. */\n page?: number;\n /**\n * Search radius in miles. A CLOSED set (upstream default 50) - Indeed\n * ignores anything else and bills a wider search than you asked for.\n */\n radius?: 0 | 5 | 10 | 15 | 25 | 35 | 50 | 100;\n /**\n * Maximum posting age in days. A CLOSED set - Indeed ignores anything else\n * and returns the unfiltered set.\n */\n max_age_days?: 1 | 3 | 7 | 14;\n /** Employment type filter. */\n job_type?: \"full_time\" | \"part_time\" | \"contract\" | \"temporary\" | \"internship\";\n /**\n * Minimum salary. Filters on INDEED'S OWN ESTIMATE for the role, not a\n * posted figure, so postings publishing no salary still match.\n */\n min_salary?: number;\n /** Remote postings only. */\n remote?: boolean;\n [key: string]: unknown;\n}\n\nexport interface IndeedJobOptions {\n /**\n * 16-hex Indeed job key, or any indeed.com URL carrying jk= (/viewjob,\n * /rc/clk, /pagead/clk).\n */\n job_id: string;\n [key: string]: unknown;\n}\n\nexport interface IndeedCompanyOptions {\n /**\n * indeed.com/cmp/<slug> slug or a full profile URL, 1-200 characters. Slugs\n * are untidy - e.g. \"Tata-Consultancy-Services-(tcs)\".\n */\n company: string;\n [key: string]: unknown;\n}\n\nexport interface IndeedCompanyReviewsOptions {\n /**\n * indeed.com/cmp/<slug> slug or a full profile URL, 1-200 characters.\n */\n company: string;\n /** Result page, 1-indexed. 20 reviews per page. */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class IndeedNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Indeed job postings: title, employer, rating, location, salary\n * range, job type, benefits, posting age and apply route.\n *\n * Either `query` or `location` is required; a location-only search is valid\n * and returns every posting in the metro.\n *\n * Paged with `page`, 10 postings per page. `radius` and `max_age_days` are\n * closed sets - Indeed silently ignores an off-list value and bills the\n * unfiltered search. `min_salary` filters on Indeed's own ESTIMATE for the\n * role, not a posted figure.\n *\n * Costs 2 credits.\n */\n async search(\n options: IndeedSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/indeed/search\", options);\n }\n\n /**\n * One Indeed posting in full: description text and HTML, structured salary,\n * employment types, benefits, geocoded address, employer rating, applicant\n * count and the original ATS link.\n *\n * Single response, no pagination. An unknown job key is a real 404 that\n * scrape.do BILLS - take `job_id` from a search row.\n *\n * Costs 2 credits.\n */\n async job(\n options: IndeedJobOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/indeed/job\", options);\n }\n\n /**\n * Indeed employer profile: description, industry, HQ, size, revenue, CEO\n * approval, overall and per-category ratings, reported salaries, open roles\n * and locations.\n *\n * Single response, no pagination. An unknown company slug is a real 404\n * that scrape.do BILLS.\n *\n * Costs 2 credits.\n */\n async company(\n options: IndeedCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/indeed/company\", options);\n }\n\n /**\n * Indeed employee reviews with per-category ratings, pros/cons, reviewer\n * job title and location, plus aggregated sentiment and topic / location /\n * job-title breakdowns.\n *\n * Paged with `page`, 20 reviews per page.\n *\n * Costs 2 credits.\n */\n async companyReviews(\n options: IndeedCompanyReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/indeed/company/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Glassdoor is 1 credit flat on all four endpoints.\n//\n// START WITH companies(). company(), reviews() and salaries() all address an\n// employer_id that exists only inside Glassdoor's /Overview/ URLs, and\n// companies() is the only way to get one from a company name.\n//\n// THEN CHAIN ON `url`. company() returns reviews_url and salaries_url; passing\n// those back as `url` halves the upstream work, because addressing reviews or\n// salaries by employer_id costs two upstream fetches (the /Reviews/ and\n// /Salary/ slugs are case-sensitive and have to be read off the profile\n// first). The customer price is 1 credit either way.\n//\n// reviews() IS CAPPED AT THREE REVIEWS per response by Glassdoor's login wall.\n// There is deliberately no `page` param - move the window with `category` and\n// `employment_status`, and read filtered_review_count to see how many match.\n//\n// `category` and `employment_status` are CLOSED enums because Glassdoor\n// ignores an unknown filter value and serves the unfiltered set under a 200.\n//\n// SLOW AND FLAKY: this domain needs a rendered fetch and the pool is degraded.\n// Per-call success is ~87%. Typical wall time is ~3-47s for company, ~75s for\n// reviews and ~41s for salaries, and a call that fails outright can take ~172s\n// before its 502. Raise the client `timeout` before using this namespace.\n\nexport interface GlassdoorCompaniesOptions {\n /** Company name to resolve (1-120 characters). */\n query: string;\n [key: string]: unknown;\n}\n\nexport interface GlassdoorCompanyOptions {\n /**\n * Glassdoor employer id. MUST BE A STRING - a JSON number is rejected.\n * Accepts 1699, E1699 or IE1699. Either this or `url` is required.\n */\n employer_id?: string;\n /**\n * Company name (1-200 characters). COSMETIC ONLY: the profile resolves on\n * employer_id alone, this is ignored entirely when `url` is set, and it does\n * NOT satisfy the employer_id-or-url requirement.\n */\n company?: string;\n /**\n * Any glassdoor.com employer URL (/Overview/, /Reviews/ or /Salary/).\n * Non-glassdoor.com hosts are rejected. Either this or `employer_id` is\n * required.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface GlassdoorReviewsOptions {\n /**\n * Glassdoor employer id as a STRING (1699, E1699 or IE1699). Either this or\n * `url` is required. Addressing by employer_id costs two upstream fetches -\n * pass reviews_url from company() as `url` instead.\n */\n employer_id?: string;\n /** Company name (1-200 characters). Cosmetic; does not satisfy the identifier requirement. */\n company?: string;\n /**\n * Pass back the reviews_url that company() returned to skip the resolve\n * fetch. Either this or `employer_id` is required.\n */\n url?: string;\n /**\n * Restrict to reviews about one axis. Closed set - Glassdoor ignores an\n * unknown value and returns the UNFILTERED set under a 200.\n */\n category?:\n | \"career_development\"\n | \"compensation\"\n | \"culture\"\n | \"diversity_and_inclusion\"\n | \"management\"\n | \"work_life_balance\";\n /**\n * Restrict to reviewers of one employment type. Closed set - an unknown\n * value is silently unfiltered. FREELANCE is absent because it was never\n * confirmed to change the result set.\n */\n employment_status?: \"full_time\" | \"part_time\" | \"contract\" | \"intern\";\n [key: string]: unknown;\n}\n\nexport interface GlassdoorSalariesOptions {\n /**\n * Glassdoor employer id as a STRING (1699, E1699 or IE1699). Either this or\n * `url` is required. Addressing by employer_id costs two upstream fetches -\n * pass salaries_url from company() as `url` instead.\n */\n employer_id?: string;\n /** Company name (1-200 characters). Cosmetic; does not satisfy the identifier requirement. */\n company?: string;\n /**\n * Pass back the salaries_url that company() returned to skip the resolve\n * fetch. Either this or `employer_id` is required.\n */\n url?: string;\n /**\n * Result page, 1-indexed. 10 job titles per page; `page_count` on the\n * response is how many pages exist.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class GlassdoorNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Search Glassdoor for a company by NAME and resolve it to the\n * employer_id every other method needs, ranked by Glassdoor and\n * de-duplicated.\n *\n * company(), reviews() and salaries() all key off an employer_id that exists\n * only inside Glassdoor's /Overview/ URLs, so this lookup is the entry\n * point.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async companies(\n options: GlassdoorCompaniesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/glassdoor/companies\", options);\n }\n\n /**\n * Employer profile: description, mission, industry, sector, HQ, size band,\n * revenue band, stock symbol, year founded, overall and per-category\n * ratings, star distribution, CEO approval, awards, FAQ, the five\n * server-rendered reviews, AND reviews_url / salaries_url.\n *\n * THE CHAINING ENDPOINT: pass reviews_url / salaries_url back as `url` on\n * reviews() and salaries() to halve the upstream fetches. `employer_id` or\n * `url` is required - `company` is cosmetic and does not satisfy it.\n *\n * Costs 1 credit. Single response, no pagination. Typically ~3-47s.\n */\n async company(\n options: GlassdoorCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/glassdoor/company\", options);\n }\n\n /**\n * Full reviews with per-axis scores, pros, cons, advice, job title,\n * location, employment status and employer response - plus complete rating\n * statistics, star distribution, aggregate pro/con highlight terms and\n * per-job-title review counts.\n *\n * HARD CAP OF THREE REVIEW BODIES per response: that is Glassdoor's login\n * wall, not a limit option. There is deliberately NO `page` param. Move the\n * window with `category` and `employment_status` and read\n * filtered_review_count to see how many match; the aggregate statistics are\n * the full-population signal here, not the bodies.\n *\n * `employer_id` or `url` is required. Costs 1 credit. Typically ~75s.\n */\n async reviews(\n options: GlassdoorReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/glassdoor/reviews\", options);\n }\n\n /**\n * Salaries by job title: base-pay and total-pay percentiles P10-P90 with\n * medians called out, sample counts, currency, pay period and last-reported\n * date.\n *\n * These are Glassdoor's ESTIMATES for the title, not individual reported\n * salaries. Paged with `page` at 10 job titles per page; `page_count` on the\n * response is how many pages exist.\n *\n * `employer_id` or `url` is required. Costs 1 credit. Typically ~41s.\n */\n async salaries(\n options: GlassdoorSalariesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/glassdoor/salaries\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// The Apple App Store is 1 credit flat on all three endpoints - it runs on\n// Apple's official iTunes JSON API, which is the cheapest surface here.\n//\n// SEARCH HAS NO PAGINATION. `limit` (1-200) is the only lever on volume; every\n// offset spelling is silently ignored. Raise the limit, never reach for a page\n// param.\n//\n// app() accepts BOTH a numeric App Store id and a bundle id (auto-detected,\n// identical payload). reviews() is NUMERIC ONLY - the RSS feed has no\n// bundle-id form.\n//\n// `country` decides price, currency, localised title and whether the app is\n// sold there at all. Anything that is not two letters falls back to US, so\n// \"usa\" silently buys a US result set.\n//\n// An id Apple cannot resolve is a BILLED 404: Apple charges for the 200 that\n// carries an empty result list. reviews() cannot 404 at all - an unknown id\n// and a real app with zero reviews return the same empty feed.\n//\n// Mac rows carry NO iPad or Apple TV screenshots, advisories, features,\n// supported devices or Game Center flag - those come back empty rather than\n// absent.\n//\n// The transport's `attribute` param is deliberately not exposed:\n// softwareDeveloper is valid upstream but has no effect, and plain search\n// already matches the developer field.\n\nexport interface AppStoreSearchOptions {\n /**\n * Search term (1-500 characters). Matches app name, keyword OR publisher\n * name - searching a developer returns their catalogue.\n */\n term: string;\n /**\n * Number of apps to return, 1-200 (default 25). THE ONLY LEVER on result\n * volume: there is no pagination and every offset spelling is ignored.\n */\n limit?: number;\n /**\n * Two-letter storefront code (default \"us\"). Decides price, currency,\n * localised title and whether the app is sold there at all. Anything that is\n * not exactly two letters falls back to US.\n */\n country?: string;\n /** Which catalogue to search (default \"software\", i.e. iPhone apps). */\n entity?: \"software\" | \"ipad_software\" | \"mac_software\";\n /**\n * Five-letter locale for the returned text, e.g. \"en_us\". Independent of\n * `country`: the storefront sets the price, this sets the words.\n */\n lang?: string;\n [key: string]: unknown;\n}\n\nexport interface AppStoreAppOptions {\n /**\n * App Store id OR bundle id (notion.id, com.burbn.instagram), auto-detected\n * and returning an identical payload. 1-255 characters matching\n * ^[A-Za-z0-9][A-Za-z0-9._-]*$ - a pasted apps.apple.com URL is rejected\n * with a free 400.\n */\n app_id: string;\n /**\n * Two-letter storefront code (default \"us\"). Decides price, currency,\n * localised title and availability. Anything not exactly two letters falls\n * back to US.\n */\n country?: string;\n [key: string]: unknown;\n}\n\nexport interface AppStoreReviewsOptions {\n /**\n * NUMERIC App Store id only - the reviews RSS feed has no bundle-id form,\n * unlike app().\n */\n app_id: string;\n /**\n * Two-letter storefront code (default \"us\"). Each storefront has its own\n * 500-review ceiling, so a different country is how you read past page 10.\n */\n country?: string;\n /**\n * Result page, 1-10 (default 1), 50 reviews each. HARD STOP AT PAGE 10 -\n * 500 reviews per storefront is Apple's anonymous ceiling.\n */\n page?: number;\n /**\n * Review sort order (default \"most_recent\"). Under \"most_recent\" almost\n * every review is too new to have been voted on and the vote fields come\n * back as ZEROES; \"most_helpful\" returns them densely populated.\n */\n sort?: \"most_recent\" | \"most_helpful\";\n [key: string]: unknown;\n}\n\nexport class AppStoreNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Up to 200 fully-shaped App Store apps - the same 43-field row as app() -\n * which makes this a bulk metadata fetch as well as a search, and a\n * publisher lookup when the term is a developer name.\n *\n * NO PAGINATION. `limit` (1-200, default 25) is the only lever on volume;\n * every offset spelling is silently ignored. Mac rows carry no iPad or Apple\n * TV screenshots, advisories, features, supported devices or Game Center\n * flag.\n *\n * Costs 1 credit.\n */\n async search(\n options: AppStoreSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/appstore/search\", options);\n }\n\n /**\n * Full listing: title, description, developer and seller identity, price and\n * currency, all-time and current-version ratings, version and release notes,\n * genres, content rating and advisories, icons at three sizes, screenshots,\n * download size, minimum OS, languages, supported devices, Game Center and\n * VPP flags.\n *\n * Takes a numeric App Store id or a bundle id interchangeably. An id Apple\n * cannot resolve is a BILLED 404 - Apple charges for the empty result list.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async app(\n options: AppStoreAppOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/appstore/app\", options);\n }\n\n /**\n * A page of reviews: star rating, title, full text, author, and the APP\n * VERSION the review was written against.\n *\n * NUMERIC APP IDS ONLY here. Paged 1-10 at 50 reviews each and hard-stopped\n * at page 10 - 500 reviews per storefront is Apple's anonymous ceiling, so\n * ask a different `country` to reach further. This endpoint CANNOT 404: an\n * unknown id and a real app with zero reviews return the same empty feed.\n * Under sort \"most_recent\" the vote fields are zeroes.\n *\n * Costs 1 credit.\n */\n async reviews(\n options: AppStoreReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/appstore/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Google Play is 2 credits flat on all three endpoints. It sits on the premium\n// per-domain proxy table and is NOT priced like the `google` namespace, which\n// is part of why it is a separate namespace.\n//\n// SEARCH HAS NO PAGINATION - Play serves one shelf of ~30 apps and there is no\n// page or cursor to ask for more.\n//\n// `hl` changes the STOREFRONT, not just the strings: at hl=pt-BR the title,\n// description, install formatting and content rating all move with it. Play\n// silently falls back to English/US on values it does not serve.\n//\n// The reviews `cursor` is opaque, SINGLE-USE, and encodes the sort as well as\n// the position - send it back with the SAME `sort` it came from. A cursor past\n// the last review is a 404, not an empty page.\n//\n// app() already returns the 20 reviews Play server-renders; reviews() is for\n// paging past them or sorting differently. The reviews RPC answering a 200\n// with an empty payload is a BILLED 404 - premium price paid to learn the\n// package has no reviews or does not exist.\n//\n// Games are folded into the apps vertical. Books and films use a different\n// card shape entirely and are not covered.\n\nexport interface GooglePlaySearchOptions {\n /** Search query (1-200 characters). */\n query: string;\n /**\n * Interface language (2-20 characters, default \"en\"). Changes the\n * STOREFRONT, not only the strings - title, description, install formatting\n * and content rating all move with it. Play falls back to English on values\n * it does not serve.\n */\n hl?: string;\n /** Country code (2-10 characters, default \"us\"). */\n gl?: string;\n [key: string]: unknown;\n}\n\nexport interface GooglePlayAppOptions {\n /**\n * Android package name (com.spotify.music) or any play.google.com URL\n * carrying one in its id param. 1-500 characters.\n */\n app_id: string;\n /**\n * Interface language (2-20 characters, default \"en\"). Changes the storefront\n * as well as the strings.\n */\n hl?: string;\n /** Country code (2-10 characters, default \"us\"). */\n gl?: string;\n [key: string]: unknown;\n}\n\nexport interface GooglePlayReviewsOptions {\n /**\n * Android package name or any play.google.com URL carrying one in its id\n * param. 1-500 characters.\n */\n app_id: string;\n /**\n * Review sort order (default \"newest\"). The cursor encodes this value, so\n * changing `sort` mid-pagination invalidates the cursor.\n */\n sort?: \"relevance\" | \"newest\" | \"rating\";\n /**\n * Reviews per page, 1-200 (default 50). Capped at 200 on our side; Play\n * honours more, but a single page that large is megabytes for one call.\n */\n count?: number;\n /**\n * next_cursor from a prior response (1-4000 characters). OPAQUE and\n * SINGLE-USE, and it encodes the sort as well as the position - send it back\n * with the SAME `sort` it came from. A cursor past the last review is a 404,\n * not an empty page.\n */\n cursor?: string;\n /** Interface language (2-20 characters, default \"en\"). */\n hl?: string;\n /** Country code (2-10 characters, default \"us\"). */\n gl?: string;\n [key: string]: unknown;\n}\n\nexport class GooglePlayNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Ranked apps: package name, title, developer, rating, install count, price\n * and IAP range, content rating, icon and screenshots. A branded query\n * returns the hero card as result 1 projected to the same row shape, plus\n * Play's related-query rail.\n *\n * NO PAGINATION - one shelf of ~30 apps, with no page or cursor param.\n * `hl` moves the whole storefront, not just the language of the strings.\n *\n * Costs 2 credits.\n */\n async search(\n options: GooglePlaySearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleplay/search\", options);\n }\n\n /**\n * Full store listing: installs including the REAL count Play publishes but\n * never renders, rating and star histogram, description, developer identity\n * and legal contact, price and IAPs, categories and gameplay tags,\n * screenshots and trailer, version and Android requirement, release and\n * update dates, changelog, full permission tree, Data safety table, the 20\n * server-rendered reviews, and the similar-apps and more-by-developer rails.\n *\n * Those 20 reviews ride along at no extra cost - use reviews() only to page\n * past them or to sort differently.\n *\n * Costs 2 credits. Single response, no pagination.\n */\n async app(\n options: GooglePlayAppOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleplay/app\", options);\n }\n\n /**\n * A page of reviews: star score, full text, author, thumbs-up count,\n * developer reply, and the APP VERSION the reviewer was running.\n *\n * Paged with `cursor` -> next_cursor. The cursor is opaque and SINGLE-USE\n * and encodes the sort as well as the position, so send it back with the\n * same `sort` it came from; a cursor past the last review is a 404, not an\n * empty page. `count` is capped at 200. An empty payload here is a BILLED\n * 404 - the premium price is paid to learn the package has no reviews or\n * does not exist.\n *\n * Costs 2 credits.\n */\n async reviews(\n options: GooglePlayReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleplay/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// G2, the B2B software review site. 5 credits flat on all three endpoints -\n// the only 5-credit platform we serve, because g2.com bills 25 upstream\n// credits per call with neither render nor super asked for.\n//\n// A BOT WALL OR HOLLOW SHELL ARRIVES AS A BILLED 502: the upstream fetch is a\n// real HTTP 200 that was charged in full, so the call is billed for a page we\n// could not parse. Retry policy is deliberately conservative for that reason -\n// do not wrap these calls in an aggressive retry loop of your own.\n//\n// Every filter is a CLOSED ENUM on purpose. G2 silently accepts an unknown\n// sort (answering 200 in some unstated ordering, so the sort never ran) and an\n// unknown filter value MATCHES NOTHING - a bogus company size returns\n// \"Reviews (0)\", which reads as \"this product has no enterprise reviews\".\n//\n// product() carries NO review text: G2 loads review bodies in a separate\n// frame. Call reviews() for text, per-star counts and facet counts.\n\nexport interface G2SearchOptions {\n /** Search term (1-200 characters). Required unless `url` is given. */\n query?: string;\n /** Result page, 1-indexed. 20 per page unless `limit` says otherwise. */\n page?: number;\n /**\n * Results per page (1-100, default 20). Capped at 100 on our side so a\n * single request cannot ask for a multi-megabyte page on a 60s deadline;\n * G2 itself keeps paginating at any size.\n */\n limit?: number;\n /** Result sort order (default \"relevance\"). */\n sort?: \"relevance\" | \"popular\" | \"alphabetical\" | \"rating\";\n /** Products at or above this star rating. */\n rating?: 1 | 2 | 3 | 4 | 5;\n /**\n * Full g2.com/search URL, as an alternative to `query`. The host is checked\n * by the transport.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface G2ProductOptions {\n /**\n * A G2 slug (\"notion\") or the numeric G2 id (\"82623\") AS A STRING - both\n * resolve on the same upstream path. Required unless `url` is given.\n */\n product_id?: string;\n /** Full g2.com product URL, as an alternative to `product_id`. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface G2ReviewsOptions {\n /**\n * A G2 slug (\"notion\") or the numeric G2 id (\"82623\") as a string.\n * Required unless `url` is given.\n */\n product_id?: string;\n /** Full g2.com reviews URL, as an alternative to `product_id`. */\n url?: string;\n /** Result page, 1-indexed. Fixed at 10 reviews per page. */\n page?: number;\n /** Review sort order (default \"relevance\"). */\n sort?: \"relevance\" | \"newest\" | \"most_helpful\" | \"rating_high\" | \"rating_low\";\n /**\n * Star bucket. HALF-STAR-INCLUSIVE: 1 returns 0, 0.5 and 1-star reviews.\n */\n rating?: 1 | 2 | 3 | 4 | 5;\n /** Reviewer's company size: SB <=50, MM 51-1000, Ent >1000. */\n company_size?: \"small_business\" | \"mid_market\" | \"enterprise\";\n /** Reviewer's role. */\n role?:\n | \"user\"\n | \"administrator\"\n | \"executive_sponsor\"\n | \"internal_consultant\"\n | \"consultant\"\n | \"agency\"\n | \"industry_analyst\";\n /** Reviewer's region. */\n region?:\n | \"north_america\"\n | \"europe\"\n | \"asia\"\n | \"latin_america\"\n | \"anz\"\n | \"middle_east\"\n | \"africa\";\n /**\n * Full-text search within the reviews (1-200 characters). Narrows the list\n * AND every facet count.\n */\n query?: string;\n [key: string]: unknown;\n}\n\nexport class G2Namespace {\n constructor(private client: Scavio) {}\n\n /**\n * Ranked B2B software products on G2: star rating, review count, vendor,\n * categories, seller description and logo. Every row carries `product_id`\n * and `slug` to feed product() and reviews().\n *\n * Paged with `page` and `limit` (1-100, default 20). `total_results` is\n * G2's Products-tab headline and is CAPPED AT 10000, so treat a 10000 as a\n * floor rather than a count; `total_by_type` breaks the same query across\n * products, sellers, categories and discussions.\n *\n * Pass `query` or `url`.\n *\n * Costs 5 credits.\n */\n async search(\n options: G2SearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/g2/search\", options);\n }\n\n /**\n * A full G2 software profile: rating with per-star histogram, review count,\n * vendor, description and seller website, pricing editions with parsed\n * amounts, feature groups, categories and breadcrumbs, supported languages,\n * integrations, alternatives, head-to-head comparisons, media, community\n * discussions and G2's AI-derived pros and cons.\n *\n * CARRIES NO REVIEW TEXT. G2 loads review bodies in a separate frame, so\n * this endpoint returns none at all - call reviews() for text.\n *\n * Pass `product_id` (slug or numeric id as a string) or `url`.\n *\n * Costs 5 credits. Single response, no pagination.\n */\n async product(\n options: G2ProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/g2/product\", options);\n }\n\n /**\n * A page of G2 reviews: rating, title, likes and dislikes, problems solved,\n * reviewer job title, industry and company size, validated and incentivized\n * flags - PLUS what the profile page has no form of: exact per-star counts,\n * pros and cons with per-theme counts, and company-size / role / industry /\n * region / category facets with counts.\n *\n * Fixed at 10 reviews per page; advance with `page`. This paginates well\n * past the 10 pages G2's own widget links to.\n *\n * `rating` buckets are HALF-STAR-INCLUSIVE (1 returns 0, 0.5 and 1-star).\n * Every filter is a closed enum because an unrecognised value matches\n * nothing upstream and comes back as an empty, plausible-looking result set.\n *\n * Pass `product_id` or `url`.\n *\n * Costs 5 credits.\n */\n async reviews(\n options: G2ReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/g2/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Capterra, the B2B software review site. 2 credits flat on all three\n// endpoints (a premium per-domain upstream table).\n//\n// SEARCH DOES NOT PAGINATE. Capterra fixes the result set at 20 and ?page=2\n// returns identical rows, so there is deliberately NO page param on search().\n//\n// `slug` behaves differently on the two product-keyed endpoints: it is\n// COSMETIC on product() (/p/186596/Zzzjunk/ returns Notion's profile\n// byte-for-byte) but LOAD-BEARING on reviews(), where it is case-sensitive\n// upstream and a wrong one silently serves PAGE ONE under a billed 200. Pass\n// back the `slug` or `reviews_url` you got from search() or product().\n//\n// `product_id` must be a STRING everywhere - a JSON number is rejected.\n\nexport interface CapterraSearchOptions {\n /**\n * Search term (1-200 characters). Required unless `url` is given: a\n * term-less search serves a fixed popular-products list that has nothing to\n * do with the caller.\n */\n query?: string;\n /**\n * Full capterra.com search URL, as an alternative to `query`. The host is\n * checked by the transport, which also covers capterra.co.uk and\n * capterra.com.br.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface CapterraProductOptions {\n /**\n * The number in /p/186596/Notion/, AS A STRING - a JSON number is rejected.\n * Required unless `url` is given.\n */\n product_id?: string;\n /** Product slug. COSMETIC on this endpoint - any value returns the same profile. */\n slug?: string;\n /** Full capterra.com product URL, as an alternative to `product_id`. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface CapterraReviewsOptions {\n /**\n * The number in /p/186596/Notion/, as a string. Required unless `url` is\n * given.\n */\n product_id?: string;\n /**\n * Product slug. LOAD-BEARING here, unlike on product(): it is case-sensitive\n * upstream and a wrong one silently serves PAGE ONE under a billed 200.\n * Pass back the slug from search() or product().\n */\n slug?: string;\n /**\n * Full capterra.com reviews URL. Passing back `reviews_url` from product()\n * is the reliable way to page.\n */\n url?: string;\n /**\n * Result page, 1-100. 25 reviews per page. There is no page past 100\n * whatever the review count says.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class CapterraNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * 20 ranked Capterra software products: name, vendor description, rating,\n * review count, logo and the paid-placement flag. Every row carries\n * `product_id` and `slug` to feed product() and reviews().\n *\n * NO PAGINATION. Capterra fixes the result set at 20 and page 2 returns the\n * identical rows, so there is deliberately no page param - narrow the query\n * instead.\n *\n * Pass `query` or `url`.\n *\n * Costs 2 credits.\n */\n async search(\n options: CapterraSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/capterra/search\", options);\n }\n\n /**\n * A full Capterra profile: rating with per-star histogram and the four\n * scored criteria, likelihood to recommend, review sentiment and topics, the\n * complete pricing table with every plan and its features, every rated\n * feature, every integration, AI-derived pros and cons with the quoted\n * review, FAQs, screenshots, badges and awards, competitor comparisons and\n * alternatives, and the buyer profile by company size / industry / job\n * function - PLUS the 25 most recent reviews, which ride along at no extra\n * cost.\n *\n * `vendor` IS ALWAYS NULL here: Capterra does not publish it as structured\n * data on the product page. The reviews name the vendor per review.\n *\n * Pass `product_id` (a string) or `url`. `slug` is cosmetic on this\n * endpoint.\n *\n * Costs 2 credits. Single response, no pagination.\n */\n async product(\n options: CapterraProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/capterra/product\", options);\n }\n\n /**\n * A page of Capterra reviews: overall score plus five per-criterion scores,\n * title, pros, cons, advice, usage duration, incentivized flag, alternatives\n * considered and what the reviewer switched from, reviewer job title /\n * industry / company size, and the vendor response - plus a richer\n * competitor list than the profile carries, each alternative with its own\n * rating histogram and starting price.\n *\n * 25 reviews per page, CAPPED AT PAGE 100. Past it Capterra answers 200 with\n * PAGE ONE and the page quietly dropped from the canonical, so nothing\n * signals the cap but repeated rows. Page 1 is already inside product(), so\n * use this to page past it.\n *\n * Pass `product_id` or `url`. `slug` is load-bearing here and case-sensitive\n * upstream - a wrong one silently serves page one.\n *\n * Costs 2 credits.\n */\n async reviews(\n options: CapterraReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/capterra/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// SEC EDGAR is 1 credit flat on all six endpoints - it sits on the SEC's own\n// free JSON API.\n//\n// LOOKUP FIRST. Callers hold a ticker (AAPL); EDGAR is keyed by CIK\n// (0000320193). Call lookup() to resolve one before anything else. Both the\n// `cik` and `ticker` fields accept either spelling, which softens the problem\n// without removing it.\n//\n// XBRL concept tags are CASE-SENSITIVE: \"netincomeloss\" is a 404 upstream,\n// not a match. Call facts() to list what a filer actually reports, then\n// concept() to pull that tag's history.\n//\n// `form` matching differs by endpoint on purpose: on filings() it matches the\n// form AND its root form, so \"10-K\" also returns 10-K/A amendments; on\n// concept() it is an EXACT match, so \"10-K\" EXCLUDES 10-K/A.\n//\n// EDGAR's \"recent\" filings block is not a fixed window - a decade for a quiet\n// filer, about a year for a prolific one. filings({ include_history: true })\n// reaches back further and is the one call that can buy up to 10 upstream\n// fetches while still costing ONE credit.\n//\n// Full-text search coverage STARTS IN 2001, and `page` is capped at 100\n// (100 documents per page) because the index refuses a result window past\n// 10,000.\n\nexport interface SECLookupOptions {\n /** Ticker, company name, or a fragment (1-200 characters). */\n query: string;\n /**\n * How many matches to return, 1-100 (default 10). This SIZES the response,\n * it is not a page param - there is no pagination here.\n */\n limit?: number;\n /**\n * Restrict to one listing exchange. Matched case-insensitively. Filers\n * listed with NO exchange are excluded by ANY value.\n */\n exchange?: \"NASDAQ\" | \"NYSE\" | \"OTC\" | \"CBOE\";\n [key: string]: unknown;\n}\n\nexport interface SECCompanyOptions {\n /**\n * CIK in any spelling: 320193, 0000320193 or CIK0000320193. A ticker is\n * accepted here too. Either `cik` or `ticker` is required.\n */\n cik?: string;\n /**\n * Ticker, dotted or dashed (BRK.B / BRK-B). WINS over `cik` when both are\n * given. Either `cik` or `ticker` is required.\n */\n ticker?: string;\n [key: string]: unknown;\n}\n\nexport interface SECFilingsOptions {\n /**\n * CIK in any spelling; a ticker is accepted here too. Either `cik` or\n * `ticker` is required.\n */\n cik?: string;\n /**\n * Ticker, dotted or dashed. WINS over `cik` when both are given. Either\n * `cik` or `ticker` is required.\n */\n ticker?: string;\n /**\n * Form filter: \"10-K\", [\"10-K\", \"10-Q\"] or \"10-K,8-K\". Matched against the\n * form AND its root form, so \"10-K\" also returns 10-K/A amendments - ask\n * for \"10-K/A\" to get only amendments. Up to 25 forms.\n */\n form?: string | string[];\n /** Earliest filing date, YYYY-MM-DD. */\n date_from?: string;\n /** Latest filing date, YYYY-MM-DD. */\n date_to?: string;\n /** Result page, 1-indexed. */\n page?: number;\n /** Filings per page, 1-500 (default 50). */\n limit?: number;\n /**\n * Reach past EDGAR's \"recent\" block into up to 10 archived shards. Still\n * ONE credit. `history_truncated` in the response flags a filer that had\n * more shards than the cap.\n */\n include_history?: boolean;\n [key: string]: unknown;\n}\n\nexport interface SECConceptOptions {\n /**\n * CIK in any spelling; a ticker is accepted here too. Either `cik` or\n * `ticker` is required.\n */\n cik?: string;\n /**\n * Ticker, dotted or dashed. WINS over `cik` when both are given. Either\n * `cik` or `ticker` is required.\n */\n ticker?: string;\n /**\n * XBRL tag, e.g. \"NetIncomeLoss\" (1-120 characters, letters then\n * alphanumerics). CASE-SENSITIVE - \"netincomeloss\" is a 404 upstream, not a\n * match. Use facts() to discover the tags a filer actually reports.\n */\n concept: string;\n /** Taxonomy: us-gaap, dei, ifrs-full, srt (default \"us-gaap\"). */\n taxonomy?: string;\n /** Unit filter, e.g. \"USD\" vs \"USD/shares\". */\n unit?: string;\n /**\n * Form filter. EXACT match here, so \"10-K\" EXCLUDES 10-K/A - the opposite\n * of filings().\n */\n form?: string;\n /**\n * How many values to return, 1-2000 (default 250). This SIZES the response,\n * it is not a page param.\n */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface SECFactsOptions {\n /**\n * CIK in any spelling; a ticker is accepted here too. Either `cik` or\n * `ticker` is required.\n */\n cik?: string;\n /**\n * Ticker, dotted or dashed. WINS over `cik` when both are given. Either\n * `cik` or `ticker` is required.\n */\n ticker?: string;\n /** Restrict to one taxonomy, e.g. \"us-gaap\" or \"dei\". */\n taxonomy?: string;\n /**\n * Case-insensitive substring matched against the tag name and its label\n * (1-200 characters).\n */\n query?: string;\n /**\n * How many concepts to return, 1-2000 (default 250). This SIZES the\n * response, it is not a page param.\n */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface SECSearchOptions {\n /**\n * Full-text query (1-500 characters). A quoted phrase is an exact match;\n * bare words are a bag of terms. OPTIONAL - a cik, ticker, form or date\n * filter on its own is a valid search.\n */\n query?: string;\n /** One CIK or up to 25. Tickers are accepted here too. */\n cik?: string | string[];\n /** One ticker or up to 25. */\n ticker?: string | string[];\n /** One form or up to 25, e.g. \"8-K\" or [\"10-K\", \"10-Q\"]. */\n form?: string | string[];\n /** Earliest filing date, YYYY-MM-DD. Coverage starts in 2001. */\n date_from?: string;\n /** Latest filing date, YYYY-MM-DD. */\n date_to?: string;\n /**\n * EDGAR's own two-character location codes - \"CA\", \"NY\", and alphanumeric\n * codes for foreign jurisdictions. One or up to 25.\n */\n location?: string | string[];\n /** Result order (default \"relevance\"). */\n sort?: \"relevance\" | \"newest\" | \"oldest\";\n /**\n * Result page, 1-indexed, CAPPED AT 100. 100 documents per page - the index\n * refuses a result window past 10,000.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class SECNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Resolves a company name or ticker to the CIK every other SEC\n * EDGAR endpoint is keyed by: matching filers with symbol, listing\n * exchange, and ready-made submissions / company-facts / EDGAR URLs, tiered\n * by match quality (each row carries its tier as `match`).\n *\n * `limit` sizes the response; there is no pagination. `exchange` is a\n * closed set matched case-insensitively, and filers listed with no exchange\n * are excluded by ANY value.\n *\n * Costs 1 credit.\n */\n async lookup(\n options: SECLookupOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/lookup\", options);\n }\n\n /**\n * Filer profile: legal and former names, SIC industry, filer category, EIN,\n * LEI, state of incorporation, fiscal year end, business and mailing\n * addresses, every ticker with its exchange, which forms it files and how\n * often, plus a preview of its 10 most recent filings.\n *\n * Either `cik` or `ticker` is required; `ticker` wins when both are given.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async company(\n options: SECCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/company\", options);\n }\n\n /**\n * A page of one filer's filings: accession number, form and root form,\n * filing and period dates, 8-K item codes, and direct links to the primary\n * document, filing index and attachment directory.\n *\n * Either `cik` or `ticker` is required. Paged with `page` + `limit`.\n * `form` matches the form AND its root form, so \"10-K\" also returns 10-K/A.\n * EDGAR's \"recent\" block is not a fixed window - a decade for a quiet\n * filer, about a year for a prolific one; `include_history` reaches back\n * through up to 10 archived shards and sets `history_truncated` when the\n * filer had more.\n *\n * Costs 1 credit - including with `include_history`, which is the one call\n * that can buy more than one upstream fetch.\n */\n async filings(\n options: SECFilingsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/filings\", options);\n }\n\n /**\n * Every value a filer reported for one XBRL concept, newest period first,\n * with the form and filing each number came from. Restatements are KEPT,\n * not collapsed; `latest` disambiguates a quarter from its year-to-date\n * twin using the SEC's comparability flag.\n *\n * Either `cik` or `ticker` is required. The `concept` tag is CASE-SENSITIVE\n * - \"netincomeloss\" is a 404 upstream, not a match; call facts() to find\n * the real tag. `form` is an EXACT match here, so \"10-K\" excludes 10-K/A.\n * `limit` sizes the response; there is no pagination.\n *\n * Costs 1 credit.\n */\n async concept(\n options: SECConceptOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/concept\", options);\n }\n\n /**\n * The index of every XBRL concept a filer reports - tag, label,\n * description, units and most recent value - across us-gaap, dei and any\n * other taxonomy it uses. This is how you find what to ask concept() for.\n *\n * Either `cik` or `ticker` is required. `limit` sizes the response; there\n * is no pagination.\n *\n * Costs 1 credit.\n */\n async facts(\n options: SECFactsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/facts\", options);\n }\n\n /**\n * EDGAR full-text search: each hit is the matching DOCUMENT with its URL,\n * form, filing date and filer identity, plus facets breaking the whole\n * result set down by company, form, industry and state.\n *\n * Coverage STARTS IN 2001 - nothing earlier is indexed. Accepts NO query at\n * all: a cik, ticker, form or date filter on its own is a valid search.\n * Paged with `page`, capped at 100 (100 documents per page) because the\n * index refuses a result window past 10,000.\n *\n * Costs 1 credit.\n */\n async search(\n options: SECSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/search\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Companies House (UK) is 1 credit flat on all four endpoints - it sits on\n// the official UK register.\n//\n// SEARCH FIRST. Everything else is keyed by `company_number`, so search() is\n// how you get one. Search matches CURRENT AND FORMER names.\n//\n// `company_number` is deliberately loose: the register 404s on /company/445790\n// and /company/sc090312 for companies that exist, so the number is zero-padded\n// and upper-cased for you. Registry prefixes supported: SC (Scotland),\n// NI (Northern Ireland), OC/SO/NC (LLPs), FC (overseas), BR (UK\n// establishment), CE (charitable incorporated organisation).\n//\n// Paging differs by endpoint. search() is CAPPED AT PAGE 50: the register\n// serves a 1000-result WINDOW per term whatever hit count it prints - it\n// claims 10,000 for a broad term, then answers page 51 with HTTP 416.\n// officers() and filingHistory() have NO upper page bound; past the last page\n// the register answers an ordinary 200 with an empty list, indistinguishable\n// from a company with no officers or no filings.\n\nexport interface CompaniesHouseSearchOptions {\n /** Company name or fragment (1-200 characters, non-blank). */\n query: string;\n /**\n * Result page, 1-indexed (default 1). 20 results per page, CAPPED AT 50 -\n * the register only serves the first 1000 matches for a term.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport interface CompaniesHouseCompanyOptions {\n /**\n * UK company number, 1-20 characters, e.g. \"00445790\" or \"SC090312\". Loose\n * on purpose - it is zero-padded and upper-cased for you, so \"445790\" and\n * \"sc090312\" both work. Prefixes: SC, NI, OC/SO/NC, FC, BR, CE.\n */\n company_number: string;\n [key: string]: unknown;\n}\n\nexport interface CompaniesHouseOfficersOptions {\n /**\n * UK company number, zero-padded and upper-cased for you.\n */\n company_number: string;\n /**\n * Result page, 1-indexed (default 1). 35 officers per page, no upper bound\n * - past the last page the register answers 200 with an empty list.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport interface CompaniesHouseFilingHistoryOptions {\n /**\n * UK company number, zero-padded and upper-cased for you.\n */\n company_number: string;\n /**\n * Result page, 1-indexed (default 1). No upper bound - past the last page\n * the register answers 200 with an empty list.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class CompaniesHouseNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Searches the UK register by name and returns the\n * `company_number` every other endpoint is keyed by, plus name, status,\n * incorporation or dissolution date, registered office address and matched\n * former names.\n *\n * Matches CURRENT AND FORMER names. Paged with `page`, 20 results per page,\n * CAPPED AT PAGE 50 - the register serves a 1000-result window per term\n * whatever hit count it prints, and answers page 51 with HTTP 416.\n *\n * Costs 1 credit.\n */\n async search(\n options: CompaniesHouseSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/companieshouse/search\", options);\n }\n\n /**\n * Full register entry: status, type, incorporation and dissolution dates,\n * registered office, SIC codes, previous names, accounts and\n * confirmation-statement due dates with overdue flags, and whether it has\n * charges, insolvency history, officers or UK establishments. FC companies\n * return home registry / legal form / governing law, BR returns the parent,\n * CE returns the charity number.\n *\n * `company_number` is zero-padded and upper-cased for you, so a number off\n * a letterhead or out of a spreadsheet that ate its leading zeros still\n * resolves.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async company(\n options: CompaniesHouseCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/companieshouse/company\", options);\n }\n\n /**\n * Officers current and resigned: name, role, appointment and resignation\n * dates, correspondence address, nationality, country of residence,\n * month-and-year date of birth, and identity-verification status.\n *\n * Paged with `page`, 35 officers per page, NO upper bound - past the last\n * page the register answers an ordinary 200 with an empty list, identical\n * to a company with no officers.\n *\n * `officers_count` is EVERY appointment ever made and `resignations_count`\n * how many ended, so the active count is the difference. There is no\n * server-side active/resigned filter - filter on each officer's `status` in\n * the response.\n *\n * Costs 1 credit.\n */\n async officers(\n options: CompaniesHouseOfficersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/companieshouse/officers\", options);\n }\n\n /**\n * Filings, most recent first: date, filing type code (AA, CS01, SH03),\n * description, register annotations and child documents, and a link to the\n * filed PDF with its page count.\n *\n * A filing the register has not finished processing carries a\n * `processing_note` instead of a document.\n *\n * Paged with `page`, NO upper bound - past the last page it is an ordinary\n * 200 with an empty list.\n *\n * Costs 1 credit.\n */\n async filingHistory(\n options: CompaniesHouseFilingHistoryOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/companieshouse/filing-history\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Google Ads Transparency Center. 1 credit flat on all three endpoints.\n//\n// START WITH advertisers(). It is the lookup that turns a brand name or a\n// domain into the advertiser_id that search() and creative() are keyed by.\n//\n// IMPRESSIONS AND REACH ARE EEA-ONLY. They are DSA-compelled, so Google\n// publishes them only where the law requires: impressions_min, impressions_max\n// and first_shown come back NULL on US creatives. That is not a bug and not a\n// gap in the parse - point your examples at an EEA region.\n//\n// The three format sets are DISJOINT: an advertiser's text, image and video\n// ads share no creatives, so a format filter is a partition, not a narrowing.\n//\n// Totals are RANGES, never exact: an advertiser's headline ad count is\n// total_ads_min / total_ads_max, and a creative's impression bucket can carry\n// a lower bound, an upper bound, or one alone.\n\nexport interface GoogleAdsAdvertisersOptions {\n /** Brand name or domain to resolve (1-200 characters). */\n query: string;\n /**\n * ISO alpha-2 country (US, GB, DE) or a Google geo criteria id as a string.\n * DEFAULTS TO THE UNITED STATES, not worldwide - the lookup runs against one\n * country's index at a time, so an advertiser who runs no US ads comes back as\n * an empty list. Set it to a country the advertiser actually advertises in.\n */\n region?: string;\n /**\n * Rows per arm (1-20, default 10). Advertisers and domains are capped\n * SEPARATELY, so a name query can return up to twice this many rows.\n */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface GoogleAdsSearchOptions {\n /**\n * Bare host, www host or full URL; reduced to the registrable host. THE ONLY\n * WAY to get the `domain` field back on each row. Required unless\n * `advertiser_id` is given.\n */\n domain?: string;\n /**\n * Google advertiser id, e.g. \"AR16735076323512287233\". The shape is checked\n * before any request is made, so a typo costs nothing. Required unless\n * `domain` is given.\n */\n advertiser_id?: string;\n /**\n * ISO alpha-2 country (US, GB, DE) or a Google geo criteria id as a string.\n * Scopes the deep links on every row - the same advertiser can share ZERO\n * creatives between two countries. Default: worldwide.\n */\n region?: string;\n /** Creative format. The three sets are DISJOINT. Default: all formats. */\n format?: \"text\" | \"image\" | \"video\";\n /** Google surface the ad ran on. Default: all surfaces. */\n platform?: \"play\" | \"maps\" | \"search\" | \"shopping\" | \"youtube\";\n /** Ad topic (default \"all\"). */\n topic?: \"all\" | \"political\";\n /**\n * Rows per page (1-100, default 40). 100 is a HARD UPSTREAM CEILING, not our\n * policy: Google answers a larger request with ZERO rows rather than an\n * error.\n */\n limit?: number;\n /**\n * `next_cursor` from the previous response (1-4000 characters). Re-send the\n * SAME filters alongside it. Null once the advertiser is exhausted.\n */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleAdsCreativeOptions {\n /** Google advertiser id, e.g. \"AR16735076323512287233\". */\n advertiser_id: string;\n /**\n * Creative id. MUST belong to the `advertiser_id` sent with it - the lookup\n * is keyed by the pair and a mismatch is a 404.\n */\n creative_id: string;\n [key: string]: unknown;\n}\n\nexport class GoogleAdsNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Resolves a brand name or a domain to the `advertiser_id` that\n * search() and creative() are keyed by.\n *\n * Returns two row kinds in one list: `advertiser` rows carry the id, the\n * verified name, the verification country and the total ad count AS A RANGE\n * (total_ads_min / total_ads_max - Google never publishes an exact figure);\n * `domain` rows carry a website. A name query returns both kinds, a\n * domain-shaped query returns domains only.\n *\n * NO PAGINATION - this is an autocomplete, roughly 20 rows per arm, and\n * `limit` caps each arm separately.\n *\n * Costs 1 credit.\n */\n async advertisers(\n options: GoogleAdsAdvertisersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleads/advertisers\", options);\n }\n\n /**\n * Every ad Google is running for one advertiser: the creative (archived\n * image, rich-media bundle, Google's renderer link, dimensions), advertiser\n * id and name, format, first and last seen dates, days actually run, plus\n * total_ads_min / total_ads_max.\n *\n * Cursor-paginated: read `next_cursor` off the response and send it back as\n * `cursor` WITH THE SAME FILTERS, up to 100 rows per page. `next_cursor` is\n * null once exhausted. A `limit` above 100 is not an error - Google answers\n * it with ZERO rows.\n *\n * The three `format` sets are disjoint, and `domain` is dropped from every\n * row when the query is by `advertiser_id`, so query by domain if you need\n * that field. The headline total is a RANGE, never an exact count.\n *\n * Pass `domain` or `advertiser_id`.\n *\n * Costs 1 credit per page.\n */\n async search(\n options: GoogleAdsSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleads/search\", options);\n }\n\n /**\n * One creative in full, and the ONLY endpoint carrying its history: every\n * size variation of the asset, the impression bucket, the per-region\n * breakdown with first and last shown dates and a per-surface impression\n * split inside each region, the format, Google's category label, and the\n * funder disclosure on political ads.\n *\n * IMPRESSIONS AND REACH ARE EEA-ONLY: impressions_min, impressions_max and\n * first_shown are NULL on US creatives because Google publishes reach only\n * where the DSA compels it. A bucket row can carry a lower bound, an upper\n * bound, or one alone.\n *\n * Keyed by the `advertiser_id` + `creative_id` PAIR - a mismatched pair is a\n * 404, not an empty response.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async creative(\n options: GoogleAdsCreativeOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleads/creative\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Meta Ad Library (Facebook and Instagram ads). 1 credit flat on all three\n// endpoints.\n//\n// THE PATHS ARE /api/v1/meta-ads/* - HYPHENATED. The route key and namespace\n// are metaAds, but the URL segment is meta-ads. Never derive one from the\n// other.\n//\n// FULL CURSOR PAGINATION on search() and advertiser(): page 1 is 30 ads, then\n// 10 per page. Walk `has_next_page` to scrape a whole query or a whole\n// advertiser. The cursor is an opaque self-contained blob, so paging is\n// stateless - and THE OTHER FILTERS ARE IGNORED when a cursor is present,\n// because the cursor already carries them. Each page is another credit, so\n// depth costs roughly 10 ads per credit past the first 30.\n//\n// Spend, reach, impressions and the paid-for-by disclosure are NULL on\n// COMMERCIAL ads. Only political/issue ads carry them - set\n// ad_type: \"political_and_issue_ads\" to surface them. Expected, not a bug.\n//\n// Logged-out public data only: nothing here touches a login or the\n// token-gated graph.facebook.com/ads_archive API.\n\nexport interface MetaAdsSearchOptions {\n /** Search term (1-200 characters). */\n query: string;\n /** Two-letter country code (default \"US\"). */\n country?: string;\n /** Whether to include ads that have stopped running (default \"all\"). */\n active_status?: \"all\" | \"active\" | \"inactive\";\n /**\n * Ad category (default \"all\"). \"political_and_issue_ads\" is the only way to\n * get spend, reach, impressions and the paid-for-by disclosure back.\n */\n ad_type?: \"all\" | \"political_and_issue_ads\";\n /** Creative media filter. Default: no media filter. */\n media_type?: \"all\" | \"image\" | \"video\" | \"meme\" | \"image_and_meme\" | \"none\";\n /** How the query terms are matched (default \"keyword_unordered\"). */\n search_type?: \"keyword_unordered\" | \"keyword_exact_phrase\";\n /**\n * `next_cursor` from the previous response. Page 1 is 30 ads, then 10 per\n * page. EVERY OTHER FILTER IS IGNORED when this is present - the cursor\n * already carries them.\n */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface MetaAdsAdvertiserOptions {\n /** The advertiser's numeric Facebook Page id (3-25 digits, as a string). */\n page_id: string;\n /** Two-letter country code (default \"US\"). */\n country?: string;\n /** Whether to include ads that have stopped running (default \"all\"). */\n active_status?: \"all\" | \"active\" | \"inactive\";\n /**\n * Ad category (default \"all\"). \"political_and_issue_ads\" is the only way to\n * get spend, reach, impressions and the paid-for-by disclosure back.\n */\n ad_type?: \"all\" | \"political_and_issue_ads\";\n /** Creative media filter. Default: no media filter. */\n media_type?: \"all\" | \"image\" | \"video\" | \"meme\" | \"image_and_meme\" | \"none\";\n /**\n * `next_cursor` from the previous response. Page 1 is 30 ads, then 10 per\n * page. EVERY OTHER FILTER IS IGNORED when this is present.\n */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface MetaAdsAdOptions {\n /** The ad's archive id (3-25 digits, as a string). */\n ad_archive_id: string;\n [key: string]: unknown;\n}\n\nexport class MetaAdsNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search the Meta Ad Library. Page 1 returns 30 ads with the full creative:\n * page name, ad copy, headline, CTA, images and videos, the platforms each\n * ran on, and run dates - plus `total_results`, `total_is_capped`,\n * `has_next_page` and `next_cursor`.\n *\n * Cursor-paginated the whole way down: 30 ads on page 1, then 10 per page.\n * Walk `has_next_page` to pull an entire query. THE OTHER FILTERS ARE\n * IGNORED once `cursor` is set, because the cursor carries them itself.\n *\n * `total_results` CAPS AT 50000 with `total_is_capped: true` - Meta only\n * reports \">50,000\", so never present it as an exact count. Spend, reach,\n * impressions and the paid-for-by disclosure are null unless\n * `ad_type` is \"political_and_issue_ads\".\n *\n * Costs 1 credit PER PAGE, so depth costs roughly 10 ads per credit past the\n * first 30.\n */\n async search(\n options: MetaAdsSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/meta-ads/search\", options);\n }\n\n /**\n * Every ad a Facebook Page is running, addressed by its numeric page id.\n * Page 1 returns 30 ads with the same creative detail as search(), then 10\n * per page off `next_cursor`; walk `has_next_page` to pull the advertiser's\n * whole library.\n *\n * The other filters are ignored once `cursor` is set. Spend, reach,\n * impressions and the paid-for-by disclosure are null on commercial ads -\n * only political/issue ads carry them.\n *\n * Costs 1 credit per page.\n */\n async advertiser(\n options: MetaAdsAdvertiserOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/meta-ads/advertiser\", options);\n }\n\n /**\n * One ad in full by archive id: creative, advertiser, run dates, platforms\n * and any political disclosure.\n *\n * Spend, reach and impressions are null unless the ad is a political/issue\n * ad.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async ad(\n options: MetaAdsAdOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/meta-ads/ad\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Costco: 13 endpoints, all POST /api/v1/costco/<method>.\n//\n// country is \"us\" (costco.com, default) or \"ca\" (costco.ca) everywhere except\n// coupons (US only). search, product and warehouses also take the\n// international sites (uk, au, mx, jp, kr, tw), which support keyword, sort and\n// paging only - no warehouse prices and no gas.\n//\n// Warehouse numbers (e.g. \"1062\") come from warehouses(). Passing one as\n// warehouse_id on search, category or deals adds that warehouse's in-store\n// price, stock status and price code to every result.\n//\n// Most endpoints cost 1 credit. The multi-warehouse ones scale with the body:\n// prices (2 credits at 10 warehouses), availability (1 per 5 warehouses),\n// warehouses (2 with country \"ca\") and gas (2 by location on ca; by\n// warehouse_ids, 1 per 5 on us and 2 per warehouse on ca).\n\n/** costco.com (\"us\", default) or costco.ca (\"ca\"). */\nexport type CostcoNaCountry = \"us\" | \"ca\";\n\n/**\n * Costco site. \"us\" (default) and \"ca\" support every filter; the other six\n * support keyword, sort and paging only.\n */\nexport type CostcoCountry = CostcoNaCountry | \"uk\" | \"au\" | \"mx\" | \"jp\" | \"kr\" | \"tw\";\n\nexport type CostcoSortBy = \"best_match\" | \"price_low\" | \"price_high\" | \"top_rated\" | \"newest\";\n\nexport type CostcoDealType =\n | \"new\"\n | \"while_supplies_last\"\n | \"treasure_hunt\"\n | \"member_favorites\"\n | \"online_only\"\n | \"on_sale\";\n\nexport type CostcoPriceCode = \"clearance\" | \"manager_markdown\" | \"special_buy\";\n\n/** Filters shared by search, category and deals (us and ca). */\nexport interface CostcoListingFilters {\n /**\n * Costco warehouse number (e.g. \"1062\"). Adds that warehouse's in-store\n * price, stock status and price code to every result; omit for online\n * prices only.\n */\n warehouse_id?: string;\n /** Result order (default \"best_match\"). Costco broadens matching under any other sort. */\n sort_by?: CostcoSortBy;\n /** Brand names to keep, up to 20 (e.g. [\"Kirkland Signature\"]). */\n brands?: string[];\n /** Minimum online price, inclusive. */\n min_price?: number;\n /** Maximum online price, inclusive. */\n max_price?: number;\n /** Minimum average star rating (1-5). */\n min_rating?: number;\n /** Only items with an active discount. */\n on_sale?: boolean;\n /** Hide out-of-stock items. */\n in_stock?: boolean;\n /** Only items sold and in stock at warehouse_id (requires warehouse_id). */\n in_warehouse?: boolean;\n /** Results page, 1-based (1-500). */\n page?: number;\n /** Results per page (1-120, default 24). */\n page_size?: number;\n}\n\nexport interface CostcoSearchOptions extends CostcoListingFilters {\n /** Keywords, or a Costco item number (1-200 characters). */\n query: string;\n country?: CostcoCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoCategoryOptions extends CostcoListingFilters {\n /** Category slug from categories() (e.g. \"televisions\"), or a costco.com category URL. */\n category: string;\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoCategoriesOptions {\n /**\n * Numeric Costco category id (e.g. \"30001\"). Omit for the top-level\n * departments; pass one for its full subcategory tree.\n */\n category_id?: string;\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoProductOptions {\n /** Costco item number or product id, or a costco.com product URL. Pass this or item_ids. */\n item_id?: string;\n /** Up to 20 ids in one call (us and ca only). */\n item_ids?: string[];\n country?: CostcoCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoPricesOptions {\n /** Costco item number or product id. Pass this or item_ids. */\n item_id?: string;\n /** Up to 20 ids in one call. */\n item_ids?: string[];\n /**\n * Warehouses to price (1-10, e.g. [\"1062\", \"1107\"]). The online price is\n * always included.\n */\n warehouse_ids: string[];\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoAvailabilityOptions {\n /** Costco item number or product id, or a costco.com product URL. */\n item_number: string;\n /** Warehouses to check (1-10). 1 credit per 5 warehouses. */\n warehouse_ids: string[];\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoReviewsOptions {\n /** Costco product id (the product_id field from search or product). */\n product_id: string;\n /** Review order (default \"newest\"). */\n sort_by?: \"newest\" | \"oldest\" | \"highest_rating\" | \"lowest_rating\" | \"most_helpful\";\n /** Only reviews with this star rating (1-5). */\n rating?: number;\n /** Results page, 1-based (1-500). */\n page?: number;\n /** Reviews per page (1-100, default 25). */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface CostcoWarehousesOptions {\n /** US zip code. Pass zip, or latitude and longitude. */\n zip?: string;\n latitude?: number;\n longitude?: number;\n country?: CostcoCountry;\n /** Nearest warehouses to return (1-50, default 10). */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface CostcoGasOptions {\n /** US zip code. Pass zip, latitude and longitude, or warehouse_ids. */\n zip?: string;\n latitude?: number;\n longitude?: number;\n /** Specific warehouses instead of a location (1-10). */\n warehouse_ids?: string[];\n country?: CostcoNaCountry;\n /** Nearest stations to return (1-50). */\n limit?: number;\n [key: string]: unknown;\n}\n\n/** coupons takes no parameters. */\nexport interface CostcoCouponsOptions {\n [key: string]: unknown;\n}\n\nexport interface CostcoDealsOptions extends CostcoListingFilters {\n /** Deal feed. */\n type: CostcoDealType;\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoClearanceOptions {\n /** Costco warehouse number to scan, from warehouses() (e.g. \"1062\"). */\n warehouse_id: string;\n /** Keywords to scan. Pass query or category. */\n query?: string;\n /** Category slug to scan instead of a query. */\n category?: string;\n /** Result pages of 120 to scan (1-5, default 3). */\n pages?: number;\n /**\n * Markdown codes to keep. Default clearance (.97) and manager_markdown\n * (.00/.88); add special_buy for .49/.79/.89 endings, which are common on\n * regular grocery prices.\n */\n price_codes?: CostcoPriceCode[];\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoAutocompleteOptions {\n /** Partial search text (1-100 characters). */\n query: string;\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport class CostcoNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Costco by keyword or item number: online price and original price,\n * ratings, member-only and stock flags, promotions and facets. Pass\n * `warehouse_id` to add that warehouse's in-store price and stock to every\n * result.\n *\n * Costs 1 credit.\n */\n async search(options: CostcoSearchOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/search\", options);\n }\n\n /**\n * Products in a Costco category, with the same sort, filters and\n * per-warehouse pricing as search().\n *\n * Costs 1 credit.\n */\n async category(options: CostcoCategoryOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/category\", options);\n }\n\n /**\n * The Costco department list, or the full subcategory tree under one\n * department when `category_id` is set.\n *\n * Costs 1 credit.\n */\n async categories(options: CostcoCategoriesOptions = {}): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/categories\", options);\n }\n\n /**\n * Full details for up to 20 items: description, features, specifications,\n * variants, member-only and purchase limits, delivery fee, and promotions\n * with start and end dates. Pass `item_id` or `item_ids`.\n *\n * Costs 1 credit.\n */\n async product(options: CostcoProductOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/product\", options);\n }\n\n /**\n * Online price versus in-warehouse price for up to 20 items across up to 10\n * warehouses, with each location's discount, final price, promotion dates\n * and price code.\n *\n * Costs 1 credit for up to 9 warehouses and 2 credits for 10.\n */\n async prices(options: CostcoPricesOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/prices\", options);\n }\n\n /**\n * In-warehouse stock status for one item at up to 10 warehouses, plus\n * pickup and same-day delivery availability. A status, never a quantity.\n *\n * Costs 1 credit per 5 warehouses.\n */\n async availability(options: CostcoAvailabilityOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/availability\", options);\n }\n\n /**\n * Customer reviews for a Costco product with the rating distribution and\n * recommend count; sort, star filter and up to 100 reviews per page.\n *\n * Costs 1 credit.\n */\n async reviews(options: CostcoReviewsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/reviews\", options);\n }\n\n /**\n * Costco warehouses near a US zip code or coordinates, nearest first:\n * warehouse_id, address, hours, departments, services, and gas station hours\n * and prices.\n *\n * Costs 1 credit, or 2 with country \"ca\".\n */\n async warehouses(options: CostcoWarehousesOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/warehouses\", options);\n }\n\n /**\n * Current regular, premium and diesel prices at Costco gas stations near a\n * location, or at specific warehouses.\n *\n * Costs 1 credit by location (2 with country \"ca\"); by `warehouse_ids`,\n * 1 credit per 5 warehouses on us and 2 credits per warehouse on ca.\n */\n async gas(options: CostcoGasOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/gas\", options);\n }\n\n /**\n * The current Costco member coupon book (US): every offer with its item\n * number, discount, final price, warehouse/online scope, limits and the\n * book's valid dates. Takes no parameters.\n *\n * Costs 1 credit.\n */\n async coupons(options: CostcoCouponsOptions = {}): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/coupons\", options);\n }\n\n /**\n * Costco deal feeds: new items, while supplies last, treasure hunt, member\n * favorites, online-only and everything on sale, with the same filters and\n * optional per-warehouse pricing as search().\n *\n * Costs 1 credit.\n */\n async deals(options: CostcoDealsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/deals\", options);\n }\n\n /**\n * Markdown finder for one warehouse: scans a query or category and keeps\n * the items whose in-warehouse price ends in a markdown code - .97\n * clearance and .00/.88 manager markdown by default, .49/.79/.89 special\n * buys on request. The codes are the member-community decode; Costco does\n * not publish them. Only items Costco lists online are covered.\n *\n * Costs 1 credit.\n */\n async clearance(options: CostcoClearanceOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/clearance\", options);\n }\n\n /**\n * Costco search-box suggestions for a partial query.\n *\n * Costs 1 credit.\n */\n async autocomplete(options: CostcoAutocompleteOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/autocomplete\", options);\n }\n}\n","import { MissingAPIKeyError, ScavioError } from \"./errors.js\";\nimport { BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT, request } from \"./http.js\";\nimport { RateLimiter } from \"./rate-limiter.js\";\nimport { AmazonNamespace } from \"./namespaces/amazon.js\";\nimport type { GoogleSearchOptions } from \"./namespaces/google.js\";\nimport { GoogleNamespace } from \"./namespaces/google.js\";\nimport { RedditNamespace } from \"./namespaces/reddit.js\";\nimport { TikTokNamespace } from \"./namespaces/tiktok.js\";\nimport { TikTokShopNamespace } from \"./namespaces/tiktok-shop.js\";\nimport { InstagramNamespace } from \"./namespaces/instagram.js\";\nimport { WalmartNamespace } from \"./namespaces/walmart.js\";\nimport { YouTubeNamespace } from \"./namespaces/youtube.js\";\nimport { XNamespace } from \"./namespaces/x.js\";\nimport { LinkedInNamespace } from \"./namespaces/linkedin.js\";\nimport { ThreadsNamespace } from \"./namespaces/threads.js\";\nimport { KuaishouNamespace } from \"./namespaces/kuaishou.js\";\nimport { EbayNamespace } from \"./namespaces/ebay.js\";\nimport { TargetNamespace } from \"./namespaces/target.js\";\nimport { HomeDepotNamespace } from \"./namespaces/home-depot.js\";\nimport { ZillowNamespace } from \"./namespaces/zillow.js\";\nimport { RedfinNamespace } from \"./namespaces/redfin.js\";\nimport { BookingNamespace } from \"./namespaces/booking.js\";\nimport { AirbnbNamespace } from \"./namespaces/airbnb.js\";\nimport { TripadvisorNamespace } from \"./namespaces/tripadvisor.js\";\nimport { YelpNamespace } from \"./namespaces/yelp.js\";\nimport { IndeedNamespace } from \"./namespaces/indeed.js\";\nimport { GlassdoorNamespace } from \"./namespaces/glassdoor.js\";\nimport { AppStoreNamespace } from \"./namespaces/app-store.js\";\nimport { GooglePlayNamespace } from \"./namespaces/google-play.js\";\nimport { G2Namespace } from \"./namespaces/g2.js\";\nimport { CapterraNamespace } from \"./namespaces/capterra.js\";\nimport { SECNamespace } from \"./namespaces/sec.js\";\nimport { CompaniesHouseNamespace } from \"./namespaces/companies-house.js\";\nimport { GoogleAdsNamespace } from \"./namespaces/google-ads.js\";\nimport { MetaAdsNamespace } from \"./namespaces/meta-ads.js\";\nimport { CostcoNamespace } from \"./namespaces/costco.js\";\n\n/**\n * Default client-side rate limit, safe on every plan including free.\n */\nexport const DEFAULT_MAX_REQUESTS_PER_SECOND = 1;\n\n/**\n * Highest client-side rate limit accepted, matching the largest plan limit.\n */\nexport const MAX_REQUESTS_PER_SECOND = 50;\n\nexport interface ScavioConfig {\n apiKey?: string;\n baseUrl?: string;\n timeout?: number;\n maxRequestsPerSecond?: number;\n /**\n * Additional retry attempts after the first request on transient failures\n * (HTTP 429/500/502/503/504 and network/timeout errors). Defaults to 2.\n * Set to 0 to disable retries.\n */\n maxRetries?: number;\n}\n\n/**\n * Options for the top-level `extract()` method.\n *\n * Extract is a CORE endpoint, not a platform: it reads any URL, so it hangs\n * off the client itself rather than a namespace.\n */\nexport interface ExtractOptions {\n /**\n * Page to read. http(s) only; a bare host is upgraded to https. Loopback,\n * private, link-local and cloud-metadata hosts are rejected with a 400.\n * 1-2048 characters.\n */\n url: string;\n /**\n * Output format (default \"markdown\").\n *\n * - \"html\": the raw page, unmodified.\n * - \"markdown\": readability extraction - boilerplate stripped.\n * - \"text\": that markdown flattened to plain text.\n */\n format?: \"html\" | \"markdown\" | \"text\";\n /**\n * Fetch tier, and THE PRICE-BEARING PARAM (default \"normal\").\n *\n * - \"normal\": plain datacenter fetch - 1 credit.\n * - \"advanced\": headless browser render, for JS-built pages - 1 credit.\n * - \"ultra\": residential proxy, for hard bot walls - 2 credits.\n */\n mode?: \"normal\" | \"advanced\" | \"ultra\";\n [key: string]: unknown;\n}\n\nexport class Scavio {\n readonly google: GoogleNamespace;\n readonly amazon: AmazonNamespace;\n readonly walmart: WalmartNamespace;\n readonly youtube: YouTubeNamespace;\n readonly reddit: RedditNamespace;\n readonly tiktok: TikTokNamespace;\n readonly tiktokShop: TikTokShopNamespace;\n readonly instagram: InstagramNamespace;\n readonly x: XNamespace;\n readonly linkedin: LinkedInNamespace;\n readonly threads: ThreadsNamespace;\n readonly kuaishou: KuaishouNamespace;\n readonly ebay: EbayNamespace;\n readonly target: TargetNamespace;\n readonly homeDepot: HomeDepotNamespace;\n readonly zillow: ZillowNamespace;\n readonly redfin: RedfinNamespace;\n readonly booking: BookingNamespace;\n readonly airbnb: AirbnbNamespace;\n readonly tripadvisor: TripadvisorNamespace;\n readonly yelp: YelpNamespace;\n readonly indeed: IndeedNamespace;\n readonly glassdoor: GlassdoorNamespace;\n readonly appStore: AppStoreNamespace;\n readonly googlePlay: GooglePlayNamespace;\n readonly g2: G2Namespace;\n readonly capterra: CapterraNamespace;\n readonly sec: SECNamespace;\n readonly companiesHouse: CompaniesHouseNamespace;\n readonly googleAds: GoogleAdsNamespace;\n readonly metaAds: MetaAdsNamespace;\n readonly costco: CostcoNamespace;\n\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n private readonly rateLimiter: RateLimiter;\n\n constructor(config?: ScavioConfig) {\n this.apiKey = config?.apiKey ?? process.env.SCAVIO_API_KEY ?? \"\";\n if (!this.apiKey) {\n throw new MissingAPIKeyError();\n }\n\n this.baseUrl = (config?.baseUrl ?? BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = config?.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = config?.maxRetries ?? DEFAULT_MAX_RETRIES;\n\n const rps = config?.maxRequestsPerSecond ?? DEFAULT_MAX_REQUESTS_PER_SECOND;\n if (rps < 1 || rps > MAX_REQUESTS_PER_SECOND) {\n throw new ScavioError(\n `maxRequestsPerSecond must be between 1 and ${MAX_REQUESTS_PER_SECOND}`,\n );\n }\n this.rateLimiter = new RateLimiter(rps);\n\n this.google = new GoogleNamespace(this);\n this.amazon = new AmazonNamespace(this);\n this.walmart = new WalmartNamespace(this);\n this.youtube = new YouTubeNamespace(this);\n this.reddit = new RedditNamespace(this);\n this.tiktok = new TikTokNamespace(this);\n this.tiktokShop = new TikTokShopNamespace(this);\n this.instagram = new InstagramNamespace(this);\n this.x = new XNamespace(this);\n this.linkedin = new LinkedInNamespace(this);\n this.threads = new ThreadsNamespace(this);\n this.kuaishou = new KuaishouNamespace(this);\n this.ebay = new EbayNamespace(this);\n this.target = new TargetNamespace(this);\n this.homeDepot = new HomeDepotNamespace(this);\n this.zillow = new ZillowNamespace(this);\n this.redfin = new RedfinNamespace(this);\n this.booking = new BookingNamespace(this);\n this.airbnb = new AirbnbNamespace(this);\n this.tripadvisor = new TripadvisorNamespace(this);\n this.yelp = new YelpNamespace(this);\n this.indeed = new IndeedNamespace(this);\n this.glassdoor = new GlassdoorNamespace(this);\n this.appStore = new AppStoreNamespace(this);\n this.googlePlay = new GooglePlayNamespace(this);\n this.g2 = new G2Namespace(this);\n this.capterra = new CapterraNamespace(this);\n this.sec = new SECNamespace(this);\n this.companiesHouse = new CompaniesHouseNamespace(this);\n this.googleAds = new GoogleAdsNamespace(this);\n this.metaAds = new MetaAdsNamespace(this);\n this.costco = new CostcoNamespace(this);\n }\n\n /** @internal */\n async _post(\n path: string,\n body: object,\n ): Promise<Record<string, unknown>> {\n return request({\n method: \"POST\",\n path,\n apiKey: this.apiKey,\n baseUrl: this.baseUrl,\n timeout: this.timeout,\n maxRetries: this.maxRetries,\n rateLimiter: this.rateLimiter,\n body: body as Record<string, unknown>,\n });\n }\n\n /** @internal */\n async _get(path: string): Promise<Record<string, unknown>> {\n return request({\n method: \"GET\",\n path,\n apiKey: this.apiKey,\n baseUrl: this.baseUrl,\n timeout: this.timeout,\n maxRetries: this.maxRetries,\n rateLimiter: this.rateLimiter,\n });\n }\n\n async search(\n options: GoogleSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.google.search(options);\n }\n\n /**\n * Read ANY web page and get it back as readability Markdown (the default),\n * plain text, or raw HTML. Returns `{ url, format, mode, content,\n * content_length }`.\n *\n * This is a core endpoint, not a platform, so it lives on the client itself:\n * `scavio.extract({ url })`, never `scavio.extract.extract()`.\n *\n * Credits are a function of `mode`, not a flat per-call constant:\n * \"normal\" costs 1, \"advanced\" costs 1, \"ultra\" costs 2. Billing happens\n * only on a successful extraction - a dead link, bot wall or timeout costs\n * nothing.\n *\n * Start on \"normal\". Move to \"advanced\" when the page builds its content in\n * the browser, and to \"ultra\" only when a bot wall blocks the other two.\n *\n * @example\n * const page = await scavio.extract({ url: \"https://example.com/pricing\" });\n * console.log(page.content);\n */\n async extract(options: ExtractOptions): Promise<Record<string, unknown>> {\n return this._post(\"/api/v1/extract\", options);\n }\n\n async getUsage(): Promise<Record<string, unknown>> {\n return this._get(\"/api/v1/usage\");\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/retry.ts","../src/http.ts","../src/rate-limiter.ts","../src/namespaces/amazon.ts","../src/namespaces/google.ts","../src/namespaces/reddit.ts","../src/namespaces/tiktok.ts","../src/namespaces/tiktok-shop.ts","../src/namespaces/instagram.ts","../src/namespaces/walmart.ts","../src/namespaces/youtube.ts","../src/namespaces/x.ts","../src/namespaces/linkedin.ts","../src/namespaces/threads.ts","../src/namespaces/kuaishou.ts","../src/namespaces/ebay.ts","../src/namespaces/target.ts","../src/namespaces/home-depot.ts","../src/namespaces/zillow.ts","../src/namespaces/redfin.ts","../src/namespaces/booking.ts","../src/namespaces/airbnb.ts","../src/namespaces/tripadvisor.ts","../src/namespaces/yelp.ts","../src/namespaces/indeed.ts","../src/namespaces/glassdoor.ts","../src/namespaces/app-store.ts","../src/namespaces/google-play.ts","../src/namespaces/g2.ts","../src/namespaces/capterra.ts","../src/namespaces/sec.ts","../src/namespaces/companies-house.ts","../src/namespaces/google-ads.ts","../src/namespaces/meta-ads.ts","../src/namespaces/costco.ts","../src/namespaces/trustpilot.ts","../src/client.ts"],"sourcesContent":["export class ScavioError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ScavioError\";\n }\n}\n\nexport class MissingAPIKeyError extends ScavioError {\n constructor() {\n super(\n \"No API key provided. Pass apiKey or set the SCAVIO_API_KEY \" +\n \"environment variable. Get your free key at https://dashboard.scavio.dev\",\n );\n this.name = \"MissingAPIKeyError\";\n }\n}\n\n/** The request could not reach the API (DNS, connection reset, TLS, ...). */\nexport class ScavioConnectionError extends ScavioError {\n constructor(message = \"Connection error\") {\n super(message);\n this.name = \"ScavioConnectionError\";\n }\n}\n\n/** The request did not complete within the configured timeout. */\nexport class ScavioTimeoutError extends ScavioError {\n constructor(message = \"Request timed out\") {\n super(message);\n this.name = \"ScavioTimeoutError\";\n }\n}\n\nexport class InvalidAPIKeyError extends ScavioError {\n public readonly statusCode = 401;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(message = \"Invalid API key\", responseBody?: Record<string, unknown>) {\n super(message);\n this.name = \"InvalidAPIKeyError\";\n this.responseBody = responseBody;\n }\n}\n\nexport class InsufficientCreditsError extends ScavioError {\n public readonly statusCode = 402;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(message = \"Insufficient credits\", responseBody?: Record<string, unknown>) {\n super(message);\n this.name = \"InsufficientCreditsError\";\n this.responseBody = responseBody;\n }\n}\n\n/**\n * The request body failed validation. Raised for HTTP 400 and for HTTP 422,\n * which is what Threads and Kuaishou return when an identifier is missing or\n * conflicting - those routes have no 400. `statusCode` reports whichever the\n * API actually sent.\n */\nexport class BadRequestError extends ScavioError {\n public readonly statusCode: number;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(\n message = \"Bad request\",\n responseBody?: Record<string, unknown>,\n statusCode = 400,\n ) {\n super(message);\n this.name = \"BadRequestError\";\n this.responseBody = responseBody;\n this.statusCode = statusCode;\n }\n}\n\nexport class NotFoundError extends ScavioError {\n public readonly statusCode = 404;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(message = \"Not found\", responseBody?: Record<string, unknown>) {\n super(message);\n this.name = \"NotFoundError\";\n this.responseBody = responseBody;\n }\n}\n\nexport class RateLimitError extends ScavioError {\n public readonly statusCode = 429;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(message = \"Rate limit exceeded\", responseBody?: Record<string, unknown>) {\n super(message);\n this.name = \"RateLimitError\";\n this.responseBody = responseBody;\n }\n}\n\nexport class ScavioAPIError extends ScavioError {\n public readonly statusCode: number;\n public readonly responseBody?: Record<string, unknown>;\n\n constructor(\n statusCode: number,\n message: string,\n responseBody?: Record<string, unknown>,\n ) {\n super(`API error ${statusCode}: ${message}`);\n this.name = \"ScavioAPIError\";\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n }\n}\n","/**\n * Retry policy: exponential backoff with full jitter and Retry-After support.\n * Mirrors the Python SDK's RetryConfig.\n */\n\n/** Statuses that are safe to retry: rate limiting plus transient upstream errors. */\nexport const DEFAULT_RETRY_STATUSES: ReadonlySet<number> = new Set([\n 429, 500, 502, 503, 504,\n]);\n\nexport interface RetryConfig {\n /** Additional attempts after the first request. 0 disables retries. */\n maxRetries: number;\n /** Base backoff in seconds; attempt n waits up to baseDelay * 2**n before jitter. */\n baseDelay: number;\n /** Upper bound (seconds) on any single backoff wait. */\n maxDelay: number;\n /** HTTP status codes that trigger a retry. */\n retryStatuses: ReadonlySet<number>;\n}\n\nexport function makeRetryConfig(maxRetries: number): RetryConfig {\n return {\n maxRetries,\n baseDelay: 0.5,\n maxDelay: 8.0,\n retryStatuses: DEFAULT_RETRY_STATUSES,\n };\n}\n\nexport function shouldRetryStatus(\n config: RetryConfig,\n statusCode: number,\n attempt: number,\n): boolean {\n return attempt < config.maxRetries && config.retryStatuses.has(statusCode);\n}\n\nexport function shouldRetryException(\n config: RetryConfig,\n attempt: number,\n): boolean {\n return attempt < config.maxRetries;\n}\n\n/**\n * Seconds to sleep before the next attempt. Honors a Retry-After value when\n * present; otherwise uses exponential backoff with full jitter.\n */\nexport function backoff(\n config: RetryConfig,\n attempt: number,\n retryAfter?: number,\n): number {\n if (retryAfter !== undefined) {\n return Math.min(Math.max(retryAfter, 0), config.maxDelay);\n }\n const capped = Math.min(config.maxDelay, config.baseDelay * 2 ** attempt);\n return Math.random() * capped;\n}\n\n/** Parse a Retry-After header (delta-seconds or HTTP-date) to seconds. */\nexport function parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n const trimmed = header.trim();\n const asNumber = Number(trimmed);\n if (!Number.isNaN(asNumber) && trimmed !== \"\") {\n return asNumber;\n }\n const asDate = Date.parse(trimmed);\n if (!Number.isNaN(asDate)) {\n return Math.max((asDate - Date.now()) / 1000, 0);\n }\n return undefined;\n}\n","import {\n BadRequestError,\n InsufficientCreditsError,\n InvalidAPIKeyError,\n NotFoundError,\n RateLimitError,\n ScavioAPIError,\n ScavioConnectionError,\n ScavioTimeoutError,\n} from \"./errors.js\";\nimport type { RateLimiter } from \"./rate-limiter.js\";\nimport {\n backoff,\n makeRetryConfig,\n parseRetryAfter,\n shouldRetryException,\n shouldRetryStatus,\n type RetryConfig,\n} from \"./retry.js\";\n\nexport const BASE_URL = \"https://api.scavio.dev\";\nexport const DEFAULT_TIMEOUT = 30_000;\nexport const DEFAULT_MAX_RETRIES = 2;\n\n// Injected from package.json at build time (tsup and vitest `define`), so the\n// version string can never drift from the published package.\ndeclare const __SCAVIO_JS_VERSION__: string;\n\nexport const SDK_VERSION: string =\n typeof __SCAVIO_JS_VERSION__ === \"string\" ? __SCAVIO_JS_VERSION__ : \"0.0.0\";\n\nexport const USER_AGENT = `scavio-js/${SDK_VERSION}`;\n\n// Browsers refuse (or silently drop) a script-set User-Agent, so it is only\n// sent from server runtimes. X-Client-Source identifies the SDK everywhere.\nexport function isServerRuntime(): boolean {\n const g = globalThis as {\n process?: { versions?: { node?: string } };\n window?: unknown;\n document?: unknown;\n };\n if (typeof g.window !== \"undefined\" && typeof g.document !== \"undefined\") {\n return false;\n }\n return typeof g.process?.versions?.node === \"string\";\n}\n\nexport function buildHeaders(apiKey: string): Record<string, string> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n \"X-Client-Source\": \"scavio-js\",\n };\n if (isServerRuntime()) {\n headers[\"User-Agent\"] = USER_AGENT;\n }\n return headers;\n}\n\nfunction stripUndefined(\n obj: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\nfunction handleError(statusCode: number, body: Record<string, unknown>): never {\n let error = body.error ?? \"Unknown error\";\n if (typeof error === \"object\" && error !== null && \"message\" in error) {\n error = (error as { message: string }).message;\n }\n const msg = String(error);\n const responseBody = Object.keys(body).length > 0 ? body : undefined;\n\n // 422 is Threads' and Kuaishou's validation status - those routes have no\n // 400 - so it maps to BadRequestError too and a caller catching one class\n // handles validation failures on every platform.\n if (statusCode === 400 || statusCode === 422) {\n throw new BadRequestError(msg, responseBody, statusCode);\n }\n if (statusCode === 401) throw new InvalidAPIKeyError(msg, responseBody);\n if (statusCode === 402) throw new InsufficientCreditsError(msg, responseBody);\n if (statusCode === 404) throw new NotFoundError(msg, responseBody);\n if (statusCode === 429) throw new RateLimitError(msg, responseBody);\n throw new ScavioAPIError(statusCode, msg, responseBody);\n}\n\nfunction sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, seconds * 1000));\n}\n\nfunction isAbortError(err: unknown): boolean {\n return (\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\")\n );\n}\n\nfunction getHeader(response: Response, name: string): string | null {\n const headers = response.headers;\n if (headers && typeof headers.get === \"function\") {\n return headers.get(name);\n }\n return null;\n}\n\nexport async function request(options: {\n method: \"GET\" | \"POST\";\n path: string;\n apiKey: string;\n baseUrl: string;\n timeout: number;\n rateLimiter: RateLimiter;\n body?: Record<string, unknown>;\n maxRetries?: number;\n}): Promise<Record<string, unknown>> {\n const url = `${options.baseUrl}${options.path}`;\n const headers = buildHeaders(options.apiKey);\n const retry: RetryConfig = makeRetryConfig(\n options.maxRetries ?? DEFAULT_MAX_RETRIES,\n );\n\n let attempt = 0;\n\n for (;;) {\n await options.rateLimiter.wait();\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), options.timeout);\n\n let response: Response;\n try {\n const fetchOptions: RequestInit = {\n method: options.method,\n headers,\n signal: controller.signal,\n };\n\n if (options.method === \"POST\" && options.body) {\n fetchOptions.body = JSON.stringify(stripUndefined(options.body));\n }\n\n response = await fetch(url, fetchOptions);\n } catch (err) {\n clearTimeout(timeoutId);\n const timedOut = isAbortError(err);\n if (shouldRetryException(retry, attempt)) {\n await sleep(backoff(retry, attempt));\n attempt += 1;\n continue;\n }\n const msg = err instanceof Error ? err.message : String(err);\n if (timedOut) {\n throw new ScavioTimeoutError(msg);\n }\n throw new ScavioConnectionError(msg);\n } finally {\n clearTimeout(timeoutId);\n }\n\n if (response.ok) {\n return (await response.json()) as Record<string, unknown>;\n }\n\n if (shouldRetryStatus(retry, response.status, attempt)) {\n const retryAfter = parseRetryAfter(getHeader(response, \"Retry-After\"));\n await sleep(backoff(retry, attempt, retryAfter));\n attempt += 1;\n continue;\n }\n\n let body: Record<string, unknown> = {};\n try {\n body = (await response.json()) as Record<string, unknown>;\n } catch {\n // ignore parse failures\n }\n handleError(response.status, body);\n }\n}\n","export class RateLimiter {\n private readonly maxPerSecond: number;\n private readonly timestamps: number[] = [];\n private pending: Promise<void> = Promise.resolve();\n\n constructor(maxPerSecond: number) {\n this.maxPerSecond = maxPerSecond;\n }\n\n async wait(): Promise<void> {\n const ticket = this.pending.then(() => this.acquire());\n this.pending = ticket;\n return ticket;\n }\n\n private async acquire(): Promise<void> {\n this.cleanup();\n if (this.timestamps.length >= this.maxPerSecond) {\n const sleepMs = 1000 - (Date.now() - this.timestamps[0]!);\n if (sleepMs > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, sleepMs));\n }\n this.cleanup();\n }\n this.timestamps.push(Date.now());\n }\n\n private cleanup(): void {\n const now = Date.now();\n while (this.timestamps.length > 0 && now - this.timestamps[0]! >= 1000) {\n this.timestamps.shift();\n }\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/**\n * Amazon moved to a new upstream in 2026-07 and the API now returns a\n * normalized shape instead of the old raw provider payload. Nine options went\n * with the old provider: language, currency, device, sort_by, pages,\n * category_id, merchant_id, zip_code and autoselect_variant. They are removed\n * rather than kept as no-ops - notably `sort_by`, which the marketplace was\n * verified to ignore entirely (every sort value returned the same unordered\n * set). Sending a retired option anyway still returns 200, with a top-level\n * `warnings` array naming what was ignored.\n *\n * `country` is the canonical marketplace selector; `domain` and `start_page`\n * remain as deprecated aliases because published SDK versions send them.\n */\nexport interface AmazonSearchOptions {\n /** Product search query (1-500 characters). */\n query: string;\n /** Marketplace country code (ISO 3166-1 alpha-2, e.g. 'us', 'gb', 'de'). Defaults to 'us'. */\n country?: string;\n /** @deprecated Amazon domain suffix ('com', 'co.uk'). Use `country` instead. */\n domain?: string;\n /** Results page, 1-based. One page per call, 1 credit each. */\n page?: number;\n /** @deprecated Alias for `page`. */\n start_page?: number;\n [key: string]: unknown;\n}\n\nexport interface AmazonProductOptions {\n /** Amazon ASIN (e.g. 'B09XS7JWHH'). Sent to the API as 'query'. */\n asin: string;\n /** Marketplace country code (ISO 3166-1 alpha-2, e.g. 'us', 'gb', 'de'). Defaults to 'us'. */\n country?: string;\n /** @deprecated Amazon domain suffix ('com', 'co.uk'). Use `country` instead. */\n domain?: string;\n [key: string]: unknown;\n}\n\nexport interface AmazonOffersOptions {\n /** Amazon ASIN (e.g. 'B09XS7JWHH'). Sent to the API as 'query'. */\n asin: string;\n /** Marketplace country code (ISO 3166-1 alpha-2, e.g. 'us', 'gb', 'de'). Defaults to 'us'. */\n country?: string;\n /** @deprecated Amazon domain suffix ('com', 'co.uk'). Use `country` instead. */\n domain?: string;\n [key: string]: unknown;\n}\n\nexport class AmazonNamespace {\n constructor(private client: Scavio) {}\n\n async search(\n options: AmazonSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/amazon/search\", options);\n }\n\n async product(\n options: AmazonProductOptions,\n ): Promise<Record<string, unknown>> {\n const { asin, ...rest } = options;\n return this.client._post(\"/api/v1/amazon/product\", {\n query: asin,\n ...rest,\n });\n }\n\n /** Every seller offer for one ASIN: price, seller, condition, shipping, and\n * which offer holds the buy box. Page 1 only. */\n async offers(options: AmazonOffersOptions): Promise<Record<string, unknown>> {\n const { asin, ...rest } = options;\n return this.client._post(\"/api/v1/amazon/offers\", {\n query: asin,\n ...rest,\n });\n }\n\n /** Supported Amazon marketplaces, as `domains` and `countries`. `languages`\n * and `currencies` remain in the payload but are always empty: neither is a\n * request parameter any more. */\n async options(): Promise<Record<string, unknown>> {\n return this.client._get(\"/api/v1/amazon/options\");\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/**\n * Google endpoints (scrape.do engine, /api/v2/google). A faithful passthrough\n * that returns Google's full response. Every endpoint costs 1 credit. Any\n * additional scrape.do parameter can be added to the options object.\n * See https://scavio.dev/docs/search-api.\n */\n\nexport interface GoogleSearchOptions {\n /** Search query (1-500 characters). */\n query: string;\n /** Device to emulate. */\n device?: \"desktop\" | \"mobile\";\n /** Result offset: 0 = page 1, 10 = page 2, ... up to 990. */\n start?: number;\n /** Include the raw Google HTML in the response. */\n include_html?: boolean;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Canonical location name; auto-encoded to a UULE string. */\n location?: string;\n /** Pre-encoded UULE location string (takes priority over location). */\n uule?: string;\n /** Language restrict (e.g. 'lang_en'). */\n lr?: string;\n /** Country restrict (e.g. 'countryUS'). */\n cr?: string;\n /** SafeSearch filter. */\n safe?: \"active\";\n /** Disable spelling correction / auto-fixes when true. */\n nfpr?: boolean;\n /** '0' disables the omitted/similar-results filter. */\n filter?: \"0\" | \"1\";\n /** Restrict results to a recent time window. */\n time_period?:\n | \"last_hour\"\n | \"last_day\"\n | \"last_week\"\n | \"last_month\"\n | \"last_year\";\n /** Resolve a deferred AI Overview (server default true). */\n resolve_ai_overview?: boolean;\n [key: string]: unknown;\n}\n\nexport interface GoogleAiModeOptions {\n /** Question or prompt (1-500 characters). */\n query: string;\n /** Device to emulate. */\n device?: \"desktop\" | \"mobile\";\n /** Include the raw Google HTML in the response. */\n include_html?: boolean;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Canonical location name; auto-encoded to a UULE string. */\n location?: string;\n /** Pre-encoded UULE location string (takes priority over location). */\n uule?: string;\n /** SafeSearch filter. */\n safe?: \"active\";\n [key: string]: unknown;\n}\n\nexport interface GoogleMapsSearchOptions {\n /** Search query (1-500 characters). */\n query: string;\n /** Result offset; must be a multiple of 20 (0, 20, 40, ...). */\n start?: number;\n /** Map center as '@lat,lng,zoomz'; controls where results come from. */\n ll?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleMapsPlaceOptions {\n /** Place ID (ChIJ...). */\n place_id?: string;\n /** Numeric CID. */\n data_cid?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleMapsReviewsOptions {\n /** Data ID (0xHEX:0xHEX). */\n data_id?: string;\n /** Place ID (ChIJ...). */\n place_id?: string;\n /** Reviews per page (1-20). */\n num?: number;\n /** Pagination cursor from a prior response. */\n next_page_token?: string;\n /** Sort order. */\n sort_by?: \"relevance\" | \"newest\" | \"highest_rating\" | \"lowest_rating\";\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleShoppingOptions {\n /** Product search query (1-500 characters). */\n query: string;\n /** Device to emulate. */\n device?: \"desktop\" | \"mobile\";\n /** Result offset. */\n start?: number;\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n /** 0 = relevance, 1 = price ascending, 2 = price descending. */\n sort_by?: number;\n /** Only items with free shipping. */\n free_shipping?: boolean;\n /** Only items on sale. */\n on_sale?: boolean;\n /** Opaque Google Shopping filter token. */\n shoprs?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Canonical location name; auto-encoded to a UULE string. */\n location?: string;\n /** Pre-encoded UULE location string (takes priority over location). */\n uule?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleShoppingProductOptions {\n /** Durable product catalog id. */\n catalog_id?: string;\n /** Product query; required when catalog_id is set. */\n query?: string;\n /** Immersive product page token. */\n immersive_product_page_token?: string;\n /** Alias for immersive_product_page_token. */\n page_token?: string;\n /** Product id. */\n product_id?: string;\n /** Device to emulate. */\n device?: \"desktop\" | \"mobile\" | \"tablet\";\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Seller sort order. */\n sort_by?: \"base_price\" | \"total_price\" | \"promotion\" | \"seller_rating\";\n /** Load all available stores. */\n load_all_stores?: boolean;\n /** Fetch additional stores. */\n more_stores?: boolean;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Canonical location name; auto-encoded to a UULE string. */\n location?: string;\n /** Pre-encoded UULE location string (takes priority over location). */\n uule?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleShoppingStoresOptions {\n /** Durable product catalog id. */\n catalog_id: string;\n /** Pagination cursor from shopping_product. */\n next_page_token: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleFlightsOptions {\n /** Departure IATA code(s); comma-separated allowed. */\n departure_id: string;\n /** Arrival IATA code(s); comma-separated allowed. */\n arrival_id: string;\n /** Outbound date (YYYY-MM-DD). */\n outbound_date: string;\n /** 1 = round trip, 2 = one way, 3 = multi-city. */\n type?: number;\n /** Return date (YYYY-MM-DD); required when type=1. */\n return_date?: string;\n /** Number of adults (1-9). */\n adults?: number;\n /** Number of children (0-9). */\n children?: number;\n /** Infants in seat (0-4). */\n infants_in_seat?: number;\n /** Infants on lap (0-4). */\n infants_on_lap?: number;\n /** 1 = economy, 2 = premium, 3 = business, 4 = first. */\n travel_class?: number;\n /** 0 = any, 1 = nonstop, 2 = <=1 stop, 3 = <=2 stops. */\n stops?: number;\n /** 1 = top, 2 = price, 3 = departure, 4 = arrival, 5 = duration, 6 = emissions. */\n sort_by?: number;\n /** Comma-separated airline codes/alliances to include. */\n include_airlines?: string;\n /** Comma-separated airline codes/alliances to exclude. */\n exclude_airlines?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Currency code (ISO 4217, e.g. 'USD'). */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleHotelsOptions {\n /** Search query; use a '<City> hotels' form. */\n query: string;\n /** Check-in date (YYYY-MM-DD). */\n check_in_date: string;\n /** Check-out date (YYYY-MM-DD). */\n check_out_date: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Currency code (ISO 4217, e.g. 'USD'). */\n currency?: string;\n /** 3 = lowest price, 8 = highest rating, 13 = most reviewed. */\n sort_by?: number;\n /** Minimum nightly price. */\n min_price?: number;\n /** Maximum nightly price. */\n max_price?: number;\n /** 7 = 3.5+, 8 = 4.0+, 9 = 4.5+. */\n rating?: number;\n /** Comma-separated star ratings (2-5). */\n hotel_class?: string;\n /** Comma-separated amenity ids. */\n amenities?: string;\n /** Comma-separated property-type ids (e.g. '12' for vacation rentals). */\n property_types?: string;\n /** Only properties with free cancellation. */\n free_cancellation?: boolean;\n /** Only eco-certified properties. */\n eco_certified?: boolean;\n /** Only properties with special offers. */\n special_offers?: boolean;\n /** Pagination cursor from a prior response. */\n next_page_token?: string;\n /** Number of properties to return (1-20). */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface GoogleHotelsDetailOptions {\n /** Property detail token from a hotels listing. */\n detail_token: string;\n /** Check-in date (YYYY-MM-DD). */\n check_in_date: string;\n /** Check-out date (YYYY-MM-DD). */\n check_out_date: string;\n /** Currency code (ISO 4217, e.g. 'USD'). */\n currency?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleNewsOptions {\n /** Keyword search. */\n query?: string;\n /** Browse a news topic. */\n topic_token?: string;\n /** Browse a topic section. */\n section_token?: string;\n /** Fetch full coverage of a story. */\n story_token?: string;\n /** Browse a publication. */\n publication_token?: string;\n /** Knowledge Graph entity id. */\n kgmid?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Country of the search (ISO 3166-1 alpha-2, e.g. 'us'). */\n gl?: string;\n /** Regional Google domain (e.g. 'google.co.uk'). */\n google_domain?: string;\n /** Sort order: 0 = relevance, 1 = date (only with query or kgmid). */\n so?: number;\n [key: string]: unknown;\n}\n\nexport interface GoogleTrendsOptions {\n /** Search term(s); comma-separated for comparisons. */\n query: string;\n /** Location code (e.g. 'US', 'GB', 'US-CA'). */\n geo?: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Time range (e.g. 'today 12-m', 'now 7-d'). */\n date?: string;\n /** Timezone offset in minutes. */\n tz?: string;\n /** Which trends dataset to return. */\n data_type?:\n | \"TIMESERIES\"\n | \"GEO_MAP\"\n | \"GEO_MAP_0\"\n | \"RELATED_QUERIES\"\n | \"RELATED_TOPICS\";\n /** Category id. */\n cat?: string;\n /** Google property filter. */\n gprop?: \"images\" | \"news\" | \"youtube\" | \"froogle\";\n /** Resolution for GEO_MAP data. */\n region?: \"COUNTRY\" | \"REGION\" | \"DMA\" | \"CITY\";\n [key: string]: unknown;\n}\n\nexport interface GoogleTrendingOptions {\n /** Country code (e.g. 'US'). */\n geo: string;\n /** UI language (ISO 639-1, e.g. 'en'). */\n hl?: string;\n /** Trending window: 4, 24, 48, or 168. */\n hours?: number;\n /** Category id (0-20). */\n cat?: number;\n /** Sort order. */\n sort?: \"relevance\" | \"search_volume\" | \"recency\" | \"title\";\n /** Filter by trend status. */\n status?: \"all\" | \"active\";\n [key: string]: unknown;\n}\n\nexport class GoogleNamespace {\n constructor(private client: Scavio) {}\n\n /** Google SERP search (includes the AI Overview when Google returns one). */\n async search(options: GoogleSearchOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google\", options);\n }\n\n /** Google AI Mode answer. */\n async aiMode(options: GoogleAiModeOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/ai-mode\", options);\n }\n\n /** Google Maps local results. */\n async mapsSearch(options: GoogleMapsSearchOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/maps/search\", options);\n }\n\n /** Google Maps place details. Provide place_id or data_cid. */\n async mapsPlace(options: GoogleMapsPlaceOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/maps/place\", options);\n }\n\n /** Google Maps reviews. Provide data_id or place_id. */\n async mapsReviews(options: GoogleMapsReviewsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/maps/reviews\", options);\n }\n\n /** Google Shopping search results. */\n async shopping(options: GoogleShoppingOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/shopping\", options);\n }\n\n /** Google Shopping product. Pass catalog_id + query for full details and sellers. */\n async shoppingProduct(\n options: GoogleShoppingProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/shopping/product\", options);\n }\n\n /** Google Shopping product sellers (continuation of shoppingProduct). */\n async shoppingStores(\n options: GoogleShoppingStoresOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/shopping/product/stores\", options);\n }\n\n /** Google Flights. */\n async flights(options: GoogleFlightsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/flights\", options);\n }\n\n /** Google Hotels search. */\n async hotels(options: GoogleHotelsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/hotels\", options);\n }\n\n /** Google Hotels property details (from a hotels listing detail_token). */\n async hotelsDetail(\n options: GoogleHotelsDetailOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/hotels/detail\", options);\n }\n\n /** Google News. Provide query or a topic/story/publication token. */\n async news(options: GoogleNewsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/news\", options);\n }\n\n /** Google Trends data. */\n async trends(options: GoogleTrendsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/trends\", options);\n }\n\n /** Google Trending Now for a country. */\n async trending(options: GoogleTrendingOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v2/google/trending\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/** Comment / feed sort orders. */\nexport type RedditSort = \"HOT\" | \"NEW\" | \"TOP\" | \"BEST\" | \"CONTROVERSIAL\";\n/** Subreddit feed sort orders. */\nexport type RedditFeedSort =\n | \"BEST\"\n | \"HOT\"\n | \"NEW\"\n | \"TOP\"\n | \"CONTROVERSIAL\"\n | \"RISING\";\n\n/**\n * Search takes only `query` and `cursor`. There is no result-type or sort\n * filter upstream: anything else is dropped server-side.\n */\nexport interface RedditSearchOptions {\n /** Search query (1-500 characters). */\n query: string;\n /** Pagination cursor from a prior response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditSearchSuggestionsOptions {\n /** Search query (1-500 characters). */\n query: string;\n [key: string]: unknown;\n}\n\nexport interface RedditPostOptions {\n /** Post fullname (t3_...) or bare id. */\n post_id?: string;\n /** Full Reddit post URL. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditPostCommentsOptions {\n /** Post fullname (t3_...). */\n post_id: string;\n /** Comment sort order (default 'TOP'). */\n sort?: RedditSort;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditCommentRepliesOptions {\n /** Post fullname (t3_...). */\n post_id: string;\n /** reply_cursor from a comment in the comments endpoint. */\n cursor: string;\n /** Comment sort order (default 'TOP'). */\n sort?: RedditSort;\n [key: string]: unknown;\n}\n\nexport interface RedditSubredditOptions {\n /** Subreddit name (without r/). */\n subreddit: string;\n [key: string]: unknown;\n}\n\nexport interface RedditSubredditPostsOptions {\n /** Subreddit name (without r/). */\n subreddit: string;\n /** Feed sort order (default 'HOT'). */\n sort?: RedditFeedSort;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditUserOptions {\n /** Redditor username (without u/). */\n username: string;\n [key: string]: unknown;\n}\n\nexport interface RedditUserFeedOptions {\n /** Redditor username (without u/). */\n username: string;\n /** Sort order (default 'NEW'). */\n sort?: RedditSort;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface RedditPopularOptions {\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport class RedditNamespace {\n constructor(private client: Scavio) {}\n\n /** Returns `data.results` plus `next_cursor` / `has_more` (not `data.posts`). */\n async search(\n options: RedditSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/search\", options);\n }\n\n async searchSuggestions(\n options: RedditSearchSuggestionsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/search/suggestions\", options);\n }\n\n /**\n * Returns a flat post object under `data` (post_id, title, text, url,\n * subreddit, author, score, ...). Comments are a separate call.\n */\n async post(options: RedditPostOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/post\", options);\n }\n\n async postComments(\n options: RedditPostCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/post/comments\", options);\n }\n\n async commentReplies(\n options: RedditCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/post/comments/replies\", options);\n }\n\n async subreddit(\n options: RedditSubredditOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/subreddit\", options);\n }\n\n async subredditPosts(\n options: RedditSubredditPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/subreddit/posts\", options);\n }\n\n async user(options: RedditUserOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/user\", options);\n }\n\n async userPosts(\n options: RedditUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/user/posts\", options);\n }\n\n async userComments(\n options: RedditUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/user/comments\", options);\n }\n\n async popular(\n options: RedditPopularOptions = {},\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/popular\", options);\n }\n\n async trending(): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/reddit/trending\", {});\n }\n}\n","import type { Scavio } from \"../client.js\";\n\nexport interface TikTokProfileOptions {\n /** TikTok @username (without the @). */\n username?: string;\n /** TikTok sec_user_id. */\n sec_user_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TikTokUserPostsOptions {\n /** TikTok sec_user_id. */\n sec_user_id: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-30). */\n count?: number;\n /** '0' = latest, '1' = popular. */\n sort_type?: \"0\" | \"1\";\n [key: string]: unknown;\n}\n\nexport interface TikTokVideoOptions {\n /** TikTok video id. */\n video_id: string;\n [key: string]: unknown;\n}\n\nexport interface TikTokVideoCommentsOptions {\n /** TikTok video id. */\n video_id: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-50). */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokCommentRepliesOptions {\n /** TikTok video id. */\n video_id: string;\n /** Parent comment id. */\n comment_id: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-50). */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokSearchVideosOptions {\n /** Search keyword (1-500 characters). */\n keyword: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-30). */\n count?: number;\n /** '0' = relevance, '1' = most likes. */\n sort_type?: \"0\" | \"1\";\n /** Age filter in days: 0 = all time, 1, 7, 30, 90, 180. */\n publish_time?: \"0\" | \"1\" | \"7\" | \"30\" | \"90\" | \"180\";\n [key: string]: unknown;\n}\n\nexport interface TikTokSearchUsersOptions {\n /** Search keyword (1-500 characters). */\n keyword: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-30). */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokHashtagOptions {\n /** Hashtag name (without the #). */\n hashtag_name?: string;\n /** Hashtag id. */\n hashtag_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TikTokHashtagVideosOptions {\n /** Hashtag id. */\n hashtag_id: string;\n /** Pagination cursor (default '0'). */\n cursor?: string;\n /** Results per page (1-30). */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokUserFollowersOptions {\n /** TikTok sec_user_id. */\n sec_user_id: string;\n /** Results per page (1-20). */\n count?: number;\n /** Pagination token from a prior response. */\n page_token?: string;\n /** Minimum timestamp cursor. */\n min_time?: number;\n [key: string]: unknown;\n}\n\nexport interface TikTokUserFollowingsOptions {\n /** TikTok sec_user_id. */\n sec_user_id: string;\n /** Results per page (1-20). */\n count?: number;\n /** Pagination token from a prior response. */\n page_token?: string;\n /** Minimum timestamp cursor. */\n min_time?: number;\n [key: string]: unknown;\n}\n\nexport class TikTokNamespace {\n constructor(private client: Scavio) {}\n\n async profile(\n options: TikTokProfileOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/profile\", options);\n }\n\n async userPosts(\n options: TikTokUserPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/user/posts\", options);\n }\n\n async video(\n options: TikTokVideoOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/video\", options);\n }\n\n async videoComments(\n options: TikTokVideoCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/video/comments\", options);\n }\n\n async commentReplies(\n options: TikTokCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/video/comments/replies\", options);\n }\n\n async searchVideos(\n options: TikTokSearchVideosOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/search/videos\", options);\n }\n\n async searchUsers(\n options: TikTokSearchUsersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/search/users\", options);\n }\n\n async hashtag(\n options: TikTokHashtagOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/hashtag\", options);\n }\n\n async hashtagVideos(\n options: TikTokHashtagVideosOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/hashtag/videos\", options);\n }\n\n async userFollowers(\n options: TikTokUserFollowersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/user/followers\", options);\n }\n\n async userFollowings(\n options: TikTokUserFollowingsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok/user/followings\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/** Marketplace regions served by suggestions, product, reviews, and shop products. */\nexport type TikTokShopRegion =\n | \"US\"\n | \"GB\"\n | \"SG\"\n | \"MY\"\n | \"PH\"\n | \"TH\"\n | \"VN\"\n | \"ID\";\n\n/** Marketplace regions served by category listings. */\nexport type TikTokShopListingRegion = \"US\" | \"GB\";\n\n/** Review ordering: 'relevant' is text-complete and image-heavy, 'recent' is fresher but text-sparse. */\nexport type TikTokShopReviewSort = \"relevant\" | \"recent\";\n\nexport interface TikTokShopSearchOptions {\n /** Search query (1-200 characters). US catalog only. */\n search: string;\n /** Opaque cursor from a prior response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopSuggestionsOptions {\n /** Partial query to expand (1-100 characters). */\n search: string;\n /** Marketplace region (default 'US'). */\n region?: TikTokShopRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopProductOptions {\n /** TikTok Shop product id (6-25 digits). */\n product_id: string;\n /** Marketplace region (default 'US'). */\n region?: TikTokShopRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopProductReviewsOptions {\n /** TikTok Shop product id (6-25 digits). */\n product_id: string;\n /** 1-based page number (1-500, default 1). */\n page?: number;\n /** Reviews per page (1-200, default 20). */\n page_size?: number;\n /** 'relevant' (default) is text-complete and image-heavy; 'recent' is fresher but far more text-sparse. */\n sort?: TikTokShopReviewSort;\n /** Only reviews with this star rating (1-5). */\n rating?: number;\n /** Only reviews with a photo or video (default false). */\n has_media?: boolean;\n /** Only verified purchases (default false). */\n verified_only?: boolean;\n /** Marketplace region (default 'US'). */\n region?: TikTokShopRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopCategoryProductsOptions {\n /** Category id from tiktokShop.categories(); level 1 or 2 both work. */\n category_id: string;\n /** Opaque cursor from a prior response's next_cursor. */\n cursor?: string;\n /** Marketplace region, 'US' or 'GB' only (default 'US'). */\n region?: TikTokShopListingRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopShopProductsOptions {\n /** TikTok Shop seller id (also called seller_id elsewhere on TikTok). */\n shop_id: string;\n /** Opaque cursor from a prior response's next_cursor. */\n cursor?: string;\n /** Marketplace region (default 'US'). */\n region?: TikTokShopRegion;\n [key: string]: unknown;\n}\n\nexport interface TikTokShopResolveOptions {\n /** A TikTok Shop product or store URL, affiliate share link, or vt.tiktok.com short link. */\n url: string;\n [key: string]: unknown;\n}\n\nexport class TikTokShopNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search TikTok Shop products by keyword (US catalog), up to 30 per page with\n * exact prices, ratings, and shop details. Paginate with next_cursor and dedupe\n * by product_id across pages.\n *\n * This is one of the three endpoints that return exact prices; tiktokShop.product()\n * does not return a price. A product_id returned here is not guaranteed to resolve\n * on tiktokShop.product() - only about 44% do.\n */\n async search(\n options: TikTokShopSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/search\", options);\n }\n\n /**\n * Keyword autocomplete and expansion for a partial query, across 8 marketplace\n * regions. Suggestions are not guaranteed prefix matches: a misspelling returns\n * typo corrections, and results can include brand and shop names.\n */\n async searchSuggestions(\n options: TikTokShopSuggestionsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/search/suggestions\", options);\n }\n\n /**\n * Full product detail: description, images, variants with stock, shipping, shop\n * profile, category path, and top reviews.\n *\n * Two limits worth knowing before you build on this:\n *\n * 1. It resolves only about 44% of the product ids returned by tiktokShop.search().\n * Upstream has no detail data for the rest, so an HTTP 404 is a normal outcome,\n * not an error. Skip the item rather than retrying - retries do not help and no\n * other region carries it. Search to product is not a reliable pipeline.\n *\n * This method throws `NotFoundError` on that 404 (there is no `data` field in\n * the response body to test), so a loop over search ids must catch it or it\n * dies on the first miss:\n *\n * ```ts\n * import { NotFoundError } from \"scavio\";\n *\n * for (const productId of productIds) {\n * try {\n * const detail = await client.tiktokShop.product({ product_id: productId });\n * } catch (e) {\n * if (e instanceof NotFoundError) continue; // no detail upstream; skip\n * throw e;\n * }\n * }\n * ```\n *\n * tiktokShop.productReviews() often works for ids product() cannot resolve: of\n * 8 such ids tested, 8 returned HTTP 200 and 7 carried at least one review, so\n * it is a useful fallback source of product detail.\n * 2. It does NOT return a price. Upstream masks the price on the product page.\n * Exact prices come from tiktokShop.search(), tiktokShop.shopProducts(), and\n * tiktokShop.categoryProducts().\n */\n async product(\n options: TikTokShopProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/product\", options);\n }\n\n /**\n * Paginated product reviews with text, images, star histogram, and\n * verified-purchase flags, up to 200 per call. total_reviews drifts between calls\n * and must not be used to compute a page count; page with has_more instead.\n */\n async productReviews(\n options: TikTokShopProductReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/product/reviews\", options);\n }\n\n /**\n * The global TikTok Shop category tree: 28 top-level categories, 240 nodes, two\n * levels deep. Category ids are identical in every region and names are always\n * English.\n */\n async categories(): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/categories\", {});\n }\n\n /**\n * Products listed under a category id from tiktokShop.categories(), with exact\n * prices. Page size is inconsistent upstream (15 to 20 per page), so always\n * paginate with next_cursor rather than assuming a fixed page size. Category\n * listings are shallow: after a few pages the source stops returning new products\n * and has_more turns false, which is the end of the listing rather than an error.\n */\n async categoryProducts(\n options: TikTokShopCategoryProductsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/category/products\", options);\n }\n\n /**\n * A shop's product catalog, 30 per page, with exact prices. Shop follower count,\n * location, and shop-level rating are not available here; call\n * tiktokShop.product() for the full shop profile.\n */\n async shopProducts(\n options: TikTokShopShopProductsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/shop/products\", options);\n }\n\n /**\n * Resolve any TikTok Shop URL or share link to a product_id or shop_id, ready to\n * pass to the other methods. Accepts canonical product and store pages,\n * tiktok.com/view links, affiliate share links, and vt.tiktok.com short links.\n */\n async resolve(\n options: TikTokShopResolveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tiktok-shop/resolve\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n/**\n * Instagram endpoints (/api/v1/instagram). Credit cost varies by endpoint,\n * in three tiers:\n * - 2: `userPosts`\n * - 8: `post`, `commentReplies`\n * - 10: everything else (`profile`, `userReels`, `userTagged`, `userStories`,\n * `postComments`, `searchUsers`, `searchHashtags`, `userFollowers`,\n * `userFollowings`)\n * See https://scavio.dev/docs/instagram-api.\n */\n\nexport interface InstagramProfileOptions {\n /** Instagram username (without the @). */\n username?: string;\n /** Instagram numeric user id. */\n user_id?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramUserFeedOptions {\n /** Instagram username (without the @). */\n username?: string;\n /** Instagram numeric user id. */\n user_id?: string;\n /** Results per page (1-50). */\n count?: number;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramStoriesOptions {\n /** Instagram username (without the @). */\n username?: string;\n /** Instagram numeric user id. */\n user_id?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramPostOptions {\n /** Full Instagram post URL. */\n url?: string;\n /** Instagram media id. */\n media_id?: string;\n /** Instagram shortcode (from the post URL). */\n shortcode?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramPostCommentsOptions {\n /** Instagram shortcode (from the post URL). */\n shortcode?: string;\n /** Full Instagram post URL. */\n url?: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n /** Comment sort order. */\n sort_order?: \"popular\" | \"newest\";\n [key: string]: unknown;\n}\n\nexport interface InstagramCommentRepliesOptions {\n /** Instagram media id. */\n media_id: string;\n /** Parent comment id. */\n comment_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramSearchOptions {\n /** Search keyword (1-500 characters). */\n keyword: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface InstagramFollowOptions {\n /** Instagram username (without the @). */\n username?: string;\n /** Instagram numeric user id. */\n user_id?: string;\n /** Results per page (1-100). */\n count?: number;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport class InstagramNamespace {\n constructor(private client: Scavio) {}\n\n async profile(\n options: InstagramProfileOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/profile\", options);\n }\n\n async userPosts(\n options: InstagramUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/posts\", options);\n }\n\n async userReels(\n options: InstagramUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/reels\", options);\n }\n\n async userTagged(\n options: InstagramUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/tagged\", options);\n }\n\n async userStories(\n options: InstagramStoriesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/stories\", options);\n }\n\n async post(\n options: InstagramPostOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/post\", options);\n }\n\n async postComments(\n options: InstagramPostCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/post/comments\", options);\n }\n\n async commentReplies(\n options: InstagramCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/post/comments/replies\", options);\n }\n\n async searchUsers(\n options: InstagramSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/search/users\", options);\n }\n\n async searchHashtags(\n options: InstagramSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/search/hashtags\", options);\n }\n\n async userFollowers(\n options: InstagramFollowOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/followers\", options);\n }\n\n async userFollowings(\n options: InstagramFollowOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/instagram/user/followings\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Walmart: search, product, reviews, category, offers, seller, sellerProducts\n// and stores.\n//\n// `device` is the only retired param. It is no longer typed here; sending it\n// anyway does not fail the request - the response carries a `warnings[]` array\n// explaining that it was ignored.\n//\n// STORE TARGETING (search and product): pass `delivery_zip` and `store_id`\n// TOGETHER to get one store's assortment and availability. Works on walmart.com\n// and walmart.ca (a Canadian postal code such as \"M5V 2T6\" with domain \"ca\").\n// Get `store_id` from `stores()` for a ZIP or postal code, on the same domain.\n// The store actually used is echoed in `data.location`. A store-targeted call\n// costs 2 credits and takes 10-60 seconds; a store_id that does not exist\n// returns 400. walmart.com.mx does not support store targeting.\n//\n// CREDITS ARE BODY-PRICED: search and category cost 1 credit on domain \"com\" or\n// \"ca\" and 2 on \"com.mx\"; a store-targeted search or product costs 2. Product,\n// reviews, offers, seller, sellerProducts and stores are otherwise 1.\n\nexport interface WalmartSearchOptions {\n /** Product search query (1-500 characters). */\n query: string;\n /**\n * Walmart storefront. Price-bearing: \"com\" and \"ca\" cost 1 credit,\n * \"com.mx\" costs 2. Defaults to \"com\".\n */\n domain?: \"com\" | \"ca\" | \"com.mx\";\n /** Result page, 1-indexed. */\n page?: number;\n /** @deprecated Alias for `page`. Use `page`. */\n start_page?: number;\n /** Result sort order (default \"best_match\"). */\n sort_by?:\n | \"best_match\"\n | \"price_low\"\n | \"price_high\"\n | \"best_seller\"\n | \"rating_high\"\n | \"new\";\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n /**\n * Delivery speed filter. \"2_days\" is deliberately unsupported (it leaks\n * 3-4 day items) and there is no \"anytime\" - omit the param instead.\n */\n fulfillment_speed?: \"today\" | \"tomorrow\";\n /** Fulfillment type filter. */\n fulfillment_type?: \"in_store\";\n /**\n * Shopper's postal code for store targeting: a 5-digit US ZIP, or a Canadian\n * postal code (\"M5V 2T6\") with domain \"ca\". Must be sent together with\n * `store_id`. Store-targeted calls cost 2 credits.\n */\n delivery_zip?: string;\n /**\n * Walmart store to target, from `stores()` on the same domain. Must be sent\n * together with `delivery_zip`. Supported on domain \"com\" and \"ca\".\n */\n store_id?: string | number;\n [key: string]: unknown;\n}\n\nexport interface WalmartProductOptions {\n /** Walmart item id (usItemId), e.g. \"13544111159\". */\n product_id: string;\n /**\n * Walmart storefront, \"com\" (default) or \"ca\". \"ca\" is only available\n * together with `delivery_zip` + `store_id`.\n */\n domain?: \"com\" | \"ca\";\n /**\n * Shopper's postal code for store targeting: a 5-digit US ZIP, or a Canadian\n * postal code with domain \"ca\". Must be sent together with `store_id`.\n */\n delivery_zip?: string;\n /**\n * Walmart store to target, from `stores()` on the same domain. Must be sent\n * together with `delivery_zip`.\n */\n store_id?: string | number;\n [key: string]: unknown;\n}\n\nexport interface WalmartStoresOptions {\n /**\n * A 5-digit US ZIP, or a Canadian postal code (\"M5V 2T6\" or \"M5V2T6\") with\n * domain \"ca\".\n */\n zipcode: string;\n /** \"com\" (walmart.com, default) or \"ca\" (walmart.ca). */\n domain?: \"com\" | \"ca\";\n [key: string]: unknown;\n}\n\n/** One store returned by `stores()`. */\nexport interface WalmartStore {\n store_id: string | null;\n name: string | null;\n type: string | null;\n node_type: string | null;\n distance_miles: number | null;\n address: {\n line1: string | null;\n line2: string | null;\n city: string | null;\n state: string | null;\n zipcode: string | null;\n country: string | null;\n };\n latitude: number | null;\n longitude: number | null;\n open_24_hours: boolean | null;\n hours: {\n day: string | null;\n start: string | null;\n end: string | null;\n closed: boolean | null;\n }[];\n pickup_types: string[];\n}\n\n/** The `data` object of a `stores()` response. */\nexport interface WalmartStoresData {\n /** The ZIP or postal code searched, normalized (\"M5V 2T6\"). */\n zipcode: string;\n domain: \"com\" | \"ca\";\n count: number;\n /** Nearest first. */\n stores: WalmartStore[];\n}\n\nexport interface WalmartStoresResponse {\n data: WalmartStoresData;\n response_time: number;\n credits_used: number;\n credits_remaining: number;\n warnings?: string[];\n [key: string]: unknown;\n}\n\nexport interface WalmartReviewsOptions {\n /** Walmart item id (usItemId). */\n product_id: string;\n /** Result page, 1-indexed. 10 reviews per page. */\n page?: number;\n /** Review sort order. */\n sort?:\n | \"relevancy\"\n | \"submission-desc\"\n | \"submission-asc\"\n | \"rating-desc\"\n | \"rating-asc\"\n | \"helpful-desc\";\n [key: string]: unknown;\n}\n\nexport interface WalmartCategoryOptions {\n /**\n * Category id: either a leaf id (\"1095191\") or a full underscore path\n * (\"3944_133251_1095191\").\n */\n category_id: string;\n /**\n * Walmart storefront. Price-bearing: \"com\" and \"ca\" cost 1 credit,\n * \"com.mx\" costs 2. Defaults to \"com\".\n */\n domain?: \"com\" | \"ca\" | \"com.mx\";\n /** Result page, 1-indexed. */\n page?: number;\n /** Trims the returned list after fetching. Does NOT reduce the credit cost. */\n limit?: number;\n /** Result sort order (default \"best_match\"). */\n sort_by?:\n | \"best_match\"\n | \"price_low\"\n | \"price_high\"\n | \"best_seller\"\n | \"rating_high\"\n | \"new\";\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n /**\n * Delivery speed filter. \"2_days\" is deliberately unsupported (it leaks\n * 3-4 day items) and there is no \"anytime\" - omit the param instead.\n */\n fulfillment_speed?: \"today\" | \"tomorrow\";\n [key: string]: unknown;\n}\n\nexport interface WalmartOffersOptions {\n /** Walmart item id (usItemId). */\n product_id: string;\n [key: string]: unknown;\n}\n\nexport interface WalmartSellerOptions {\n /**\n * NUMERIC catalog seller id, the `seller_catalog_id` field returned by\n * product/offers. The GUID form of seller_id returns 404.\n */\n seller_id: string;\n [key: string]: unknown;\n}\n\nexport interface WalmartSellerProductsOptions {\n /**\n * NUMERIC catalog seller id (`seller_catalog_id`). The GUID form returns 404.\n */\n seller_id: string;\n [key: string]: unknown;\n}\n\nexport class WalmartNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Structured Walmart search results: `products[]`, `products_count` and the\n * resolved `location`. Page through with `page` (1-indexed).\n *\n * Pass `delivery_zip` + `store_id` to get one store's results (walmart.com\n * and walmart.ca); `data.location` confirms the store.\n *\n * Costs 1 credit for `domain` \"com\" or \"ca\", 2 credits for \"com.mx\", and 2\n * credits when store-targeted.\n */\n async search(\n options: WalmartSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/search\", options);\n }\n\n /**\n * Full product detail: price, rating, images, specifications, availability\n * and seller.\n *\n * Pass `delivery_zip` + `store_id` for one store's price and availability.\n * `domain: \"ca\"` is available only together with a store target.\n *\n * Costs 1 credit, or 2 when store-targeted. A store that does not carry the\n * item returns 404.\n */\n async product(\n options: WalmartProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/product\", options);\n }\n\n /**\n * Customer reviews with ratings, text, author, date and the rating\n * breakdown. 10 reviews per page; advance with `page`.\n *\n * Costs 1 credit.\n */\n async reviews(\n options: WalmartReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/reviews\", options);\n }\n\n /**\n * Products within a category, in the same product shape as `search()`.\n * Page through with `page`; `limit` only trims the response.\n *\n * Costs 1 credit for `domain` \"com\" or \"ca\", 2 credits for \"com.mx\".\n */\n async category(\n options: WalmartCategoryOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/category\", options);\n }\n\n /**\n * Seller offer for a product: price, seller, condition and buy-box flag.\n * Returns the BUY-BOX SELLER ONLY, not the full offer list.\n *\n * Costs 1 credit.\n */\n async offers(\n options: WalmartOffersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/offers\", options);\n }\n\n /**\n * Marketplace seller storefront: name, rating, review count, Pro Seller\n * badge and business details.\n *\n * Costs 1 credit. `seller_id` must be the numeric catalog seller id.\n */\n async seller(\n options: WalmartSellerOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/seller\", options);\n }\n\n /**\n * A seller's catalog. Roughly the first 40 items are server-rendered and\n * that is all this returns - there is no pagination. `total_count` reports\n * the seller's real catalog size, which is usually far larger.\n *\n * Costs 1 credit. `seller_id` must be the numeric catalog seller id.\n */\n async sellerProducts(\n options: WalmartSellerProductsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/walmart/seller-products\", options);\n }\n\n /**\n * Walmart stores near a US ZIP (or a Canadian postal code with `domain: \"ca\"`),\n * nearest first, with `store_id`, address, distance, coordinates and hours.\n * Use a `store_id` with `delivery_zip` on `search()` or `product()`, on the\n * same domain, to target that store.\n *\n * Costs 1 credit.\n */\n async stores(options: WalmartStoresOptions): Promise<WalmartStoresResponse> {\n return (await this.client._post(\n \"/api/v1/walmart/stores\",\n options,\n )) as unknown as WalmartStoresResponse;\n }\n}\n","import type { Scavio } from \"../client.js\";\n\nexport interface YouTubeSearchOptions {\n /** Search query (1-500 characters). Sent to the API as 'search'. */\n query: string;\n /** Filter by upload date. */\n upload_date?: \"last_hour\" | \"today\" | \"this_week\" | \"this_month\" | \"this_year\";\n /** Filter by result type. */\n type?: \"video\" | \"channel\" | \"playlist\" | \"movie\";\n /** short (<4 min), medium (4-20 min), long (>20 min). */\n duration?: \"short\" | \"medium\" | \"long\";\n /** Sort order. */\n sort_by?: \"relevance\" | \"date\" | \"view_count\" | \"rating\";\n /**\n * Feature filters, e.g. [\"hd\", \"4k\", \"subtitles\", \"creative_commons\",\n * \"live\", \"360\", \"3d\", \"hdr\", \"vr180\"].\n */\n features?: string[];\n /** Pagination cursor from a prior response. */\n cursor?: string;\n /** HD videos only. */\n hd?: boolean;\n /** Videos with subtitles/CC only. */\n subtitles?: boolean;\n /** Creative Commons licensed only. */\n creative_commons?: boolean;\n /** Live videos only. */\n live?: boolean;\n /** HDR videos only. */\n hdr?: boolean;\n /** VR180 videos only. */\n vr180?: boolean;\n /** 4K videos only. Sent to the API as '4k'. */\n fourK?: boolean;\n /** 360-degree videos only. Sent to the API as '360'. */\n video_360?: boolean;\n /** 3D videos only. Sent to the API as '3d'. */\n video_3d?: boolean;\n [key: string]: unknown;\n}\n\nexport interface YouTubeShortsOptions {\n /** Search query (1-500 characters). Sent to the API as 'search'. */\n query: string;\n /** Sort order. */\n sort_by?: \"relevance\" | \"date\" | \"view_count\" | \"rating\";\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeSuggestionsOptions {\n /** Search query (1-500 characters). Sent to the API as 'search'. */\n query: string;\n /** Language code for suggestions (default 'en'). */\n language?: string;\n /** Region code for suggestions (default 'US'). */\n region?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeVideoOptions {\n /** YouTube video id (e.g. 'dQw4w9WgXcQ') or a full watch URL. */\n video_id: string;\n [key: string]: unknown;\n}\n\n/** @deprecated Use YouTubeVideoOptions with youtube.video(). */\nexport interface YouTubeMetadataOptions {\n /** YouTube video id (e.g. 'dQw4w9WgXcQ') or a full watch URL. */\n video_id: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeCommentsOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeCommentRepliesOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n /** Reply cursor from a parent comment's 'reply_cursor'. */\n reply_cursor: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeTranscriptOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n /** Caption language code (default 'en'). */\n language?: string;\n /** 'text' for plain transcript, 'srt' for timed subtitles (default 'text'). */\n format?: \"text\" | \"srt\";\n [key: string]: unknown;\n}\n\nexport interface YouTubeRelatedOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelSearchOptions {\n /** Search query (1-500 characters). Sent to the API as 'search'. */\n query: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelOptions {\n /** YouTube channel id, @handle, or channel URL. */\n channel_id: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelVideosOptions {\n /** YouTube channel id. */\n channel_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelShortsOptions {\n /** YouTube channel id. */\n channel_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelCommunityOptions {\n /** YouTube channel id. */\n channel_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeChannelResolveOptions {\n /** A channel @handle or channel URL to resolve to a channel id. */\n channel: string;\n [key: string]: unknown;\n}\n\nexport interface YouTubeStreamsOptions {\n /** YouTube video id or a full watch URL. */\n video_id: string;\n [key: string]: unknown;\n}\n\nexport class YouTubeNamespace {\n constructor(private client: Scavio) {}\n\n async search(\n options: YouTubeSearchOptions,\n ): Promise<Record<string, unknown>> {\n const { query, fourK, video_360, video_3d, ...rest } = options;\n const body: Record<string, unknown> = {\n search: query,\n ...rest,\n };\n if (fourK !== undefined) body[\"4k\"] = fourK;\n if (video_360 !== undefined) body[\"360\"] = video_360;\n if (video_3d !== undefined) body[\"3d\"] = video_3d;\n return this.client._post(\"/api/v1/youtube/search\", body);\n }\n\n async shorts(\n options: YouTubeShortsOptions,\n ): Promise<Record<string, unknown>> {\n const { query, ...rest } = options;\n return this.client._post(\"/api/v1/youtube/shorts\", {\n search: query,\n ...rest,\n });\n }\n\n async suggestions(\n options: YouTubeSuggestionsOptions,\n ): Promise<Record<string, unknown>> {\n const { query, ...rest } = options;\n return this.client._post(\"/api/v1/youtube/suggestions\", {\n search: query,\n ...rest,\n });\n }\n\n async video(\n options: YouTubeVideoOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/video\", options);\n }\n\n /** @deprecated Use youtube.video(). Alias kept for backward compatibility. */\n async metadata(\n options: YouTubeMetadataOptions,\n ): Promise<Record<string, unknown>> {\n return this.video(options);\n }\n\n async comments(\n options: YouTubeCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/comments\", options);\n }\n\n async commentReplies(\n options: YouTubeCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/comments/replies\", options);\n }\n\n async transcript(\n options: YouTubeTranscriptOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/transcript\", options);\n }\n\n async related(\n options: YouTubeRelatedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/related\", options);\n }\n\n async channelSearch(\n options: YouTubeChannelSearchOptions,\n ): Promise<Record<string, unknown>> {\n const { query, ...rest } = options;\n return this.client._post(\"/api/v1/youtube/channel/search\", {\n search: query,\n ...rest,\n });\n }\n\n async channel(\n options: YouTubeChannelOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel\", options);\n }\n\n async channelVideos(\n options: YouTubeChannelVideosOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel/videos\", options);\n }\n\n async channelShorts(\n options: YouTubeChannelShortsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel/shorts\", options);\n }\n\n async channelCommunity(\n options: YouTubeChannelCommunityOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel/community\", options);\n }\n\n async channelResolve(\n options: YouTubeChannelResolveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/channel/resolve\", options);\n }\n\n async streams(\n options: YouTubeStreamsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/youtube/streams\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\nexport interface XSearchOptions {\n /** Search query (1-500 characters). */\n search: string;\n /** Result category (default 'Top'). */\n search_type?: \"Top\" | \"Latest\" | \"People\" | \"Photos\" | \"Videos\";\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface XTweetOptions {\n /** Tweet id. */\n tweet_id: string;\n [key: string]: unknown;\n}\n\nexport interface XTweetCommentsOptions {\n /** Tweet id. */\n tweet_id: string;\n /** 'top' (ranked) or 'latest' (chronological); default 'top'. */\n rank?: \"top\" | \"latest\";\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface XTweetRetweetersOptions {\n /** Tweet id. */\n tweet_id: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface XUserOptions {\n /** An X handle (without the @). */\n screen_name: string;\n [key: string]: unknown;\n}\n\nexport interface XUserFeedOptions {\n /** An X handle (without the @). */\n screen_name: string;\n /** Pagination cursor from a prior response. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface XTrendingOptions {\n /** Country name (default 'UnitedStates'). */\n country?: string;\n [key: string]: unknown;\n}\n\nexport class XNamespace {\n constructor(private client: Scavio) {}\n\n async search(\n options: XSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/search\", options);\n }\n\n async tweet(\n options: XTweetOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/tweet\", options);\n }\n\n async tweetComments(\n options: XTweetCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/tweet/comments\", options);\n }\n\n async tweetRetweeters(\n options: XTweetRetweetersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/tweet/retweeters\", options);\n }\n\n async user(\n options: XUserOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user\", options);\n }\n\n async userTweets(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/tweets\", options);\n }\n\n async userReplies(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/replies\", options);\n }\n\n async userMedia(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/media\", options);\n }\n\n async userFollowers(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/followers\", options);\n }\n\n async userFollowings(\n options: XUserFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/user/followings\", options);\n }\n\n async trending(\n options: XTrendingOptions = {},\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/x/trending\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// The provider retired the `linkedin/web/*` namespace these were built on. Live\n// endpoints now run on `web_v2`, which is URL-native: public params are\n// unchanged (the permalink is built server-side) and `url` is accepted\n// everywhere as a direct alternative. Params web_v2 has no equivalent for (the\n// include_* flags, the member urn) are gone. Pagination is back as of the\n// provider's 2026-07-31 release: list endpoints take an opaque `cursor` and\n// return `next_cursor`, and personPosts gained a `type` feed selector.\n//\n// Five endpoints have no upstream left and always return HTTP 410 unbilled:\n// personContact, companyPeople, companyJobs, searchPeople, searchPosts. They are\n// kept so existing code fails loudly rather than with a TypeError.\n\n/** A member reference: a vanity handle, or a full profile URL. */\nexport interface LinkedInPersonOptions {\n /** Public identifier (vanity handle), e.g. \"williamhgates\". */\n username?: string;\n /** Full LinkedIn profile URL, as an alternative to username. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInPersonPostsRequest extends LinkedInPersonOptions {\n /** Which feed: the member's own posts (default), posts they commented on, or posts they reacted to. */\n type?: \"posts\" | \"comments\" | \"reactions\";\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n}\n\n/** A company reference: a universal name (slug), or a full company URL. */\nexport interface LinkedInCompanyOptions {\n /** Company universal name (slug), e.g. \"microsoft\". */\n company?: string;\n /** Full LinkedIn company URL, as an alternative to company. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInCompanyPostsRequest extends LinkedInCompanyOptions {\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n}\n\n// The person/company option shapes were reworked when the urn and count params\n// lost their upstream. These aliases keep the old type names importable so\n// existing TypeScript code still compiles.\n/** @deprecated Use {@link LinkedInPersonOptions}. */\nexport type LinkedInPersonRefOptions = LinkedInPersonOptions;\n/** @deprecated Use {@link LinkedInPersonPostsRequest}. */\nexport type LinkedInPersonPostsOptions = LinkedInPersonPostsRequest;\n/** @deprecated Use {@link LinkedInCompanyPostsRequest}. */\nexport type LinkedInCompanyPostsOptions = LinkedInCompanyPostsRequest;\n\nexport interface LinkedInSearchJobsOptions {\n /** Search keyword. */\n search: string;\n /** Geographic filter; omit to search everywhere. */\n location?: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInJobOptions {\n /** Job listing id. */\n job_id?: string;\n /** Full LinkedIn job URL, as an alternative to job_id. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInPostOptions {\n /** Post id or activity urn. */\n post_id?: string;\n /** Full LinkedIn post URL, as an alternative to post_id. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface LinkedInPostCommentsOptions extends LinkedInPostOptions {\n /** 1-based page number. Page size varies, so page until a page comes back empty. */\n page?: number;\n}\n\n/** @deprecated Retired upstream; always returns HTTP 410. */\nexport interface LinkedInPersonContactOptions {\n username?: string;\n [key: string]: unknown;\n}\n\n/** @deprecated Retired upstream; always returns HTTP 410. */\nexport interface LinkedInCompanyRefOptions {\n company_id?: string;\n company?: string;\n [key: string]: unknown;\n}\n\n/** @deprecated Retired upstream; always returns HTTP 410. */\nexport interface LinkedInSearchPeopleOptions {\n search?: string;\n title?: string;\n company?: string;\n school?: string;\n location?: string;\n [key: string]: unknown;\n}\n\n/** @deprecated Retired upstream; always returns HTTP 410. */\nexport interface LinkedInSearchPostsOptions {\n search?: string;\n [key: string]: unknown;\n}\n\nexport class LinkedInNamespace {\n constructor(private client: Scavio) {}\n\n /** Full profile: about text, experience, education, honours and links. */\n async person(\n options: LinkedInPersonOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/person\", options);\n }\n\n /** The about-only slice of the profile payload. */\n async personAbout(\n options: LinkedInPersonOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/person/about\", options);\n }\n\n /**\n * A member's posts, or the posts they commented on or reacted to via `type`.\n * 50 per page; pass the previous response's `next_cursor` to advance.\n */\n async personPosts(\n options: LinkedInPersonPostsRequest,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/person/posts\", options);\n }\n\n /** Company profile, including locations and featured employees. */\n async company(\n options: LinkedInCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/company\", options);\n }\n\n /** Recent company posts, 50 per page; advance with `next_cursor`. */\n async companyPosts(\n options: LinkedInCompanyPostsRequest,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/company/posts\", options);\n }\n\n /**\n * Job search, 25 per page; advance with `next_cursor`. Upstream rotates its\n * result set, so pages overlap slightly - dedupe by job id.\n */\n async searchJobs(\n options: LinkedInSearchJobsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/search/jobs\", options);\n }\n\n /** Full detail for one job listing, including the hiring company. */\n async job(\n options: LinkedInJobOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/job\", options);\n }\n\n /** Full detail for one post, including its top visible comments. */\n async post(\n options: LinkedInPostOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/post\", options);\n }\n\n /** Comments with their replies. Page size varies - keep paging until empty. */\n async postComments(\n options: LinkedInPostCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/post/comments\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed.\n */\n async personContact(\n options: LinkedInPersonContactOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/person/contact\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed. `company()` returns `featured_employees`, a small sample of\n * staff profiles.\n */\n async companyPeople(\n options: LinkedInCompanyRefOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/company/people\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed. Use `searchJobs()` with the company name as the search term.\n */\n async companyJobs(\n options: LinkedInCompanyRefOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/company/jobs\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed.\n */\n async searchPeople(\n options: LinkedInSearchPeopleOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/search/people\", options);\n }\n\n /**\n * @deprecated Retired by the upstream provider. Always returns HTTP 410 and is\n * never billed.\n */\n async searchPosts(\n options: LinkedInSearchPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/linkedin/search/posts\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Threads is body-priced. The upstream handle lookup is dead, so addressing a\n// user by `username` buys a second upstream call: 2 credits by `user_id`,\n// 4 credits by `username`. Only profile, userPosts and userReplies are\n// username-keyed - post, postComments and searchUsers are always 2 credits.\n// Resolve a handle once with searchUsers() or profile(), keep the returned\n// user_id, and every later call stays on the cheap path.\n//\n// There is NO Threads content search. Only people search exists\n// (searchUsers). Nothing here searches posts.\n//\n// Error codes differ from the scrape.do platforms: 404 when no user matches,\n// 422 when the identifier is missing or conflicting, 502 upstream. There is no\n// 400 and no 503.\n\n/** A user reference: the cheap numeric id, or the handle at double the cost. */\nexport interface ThreadsProfileOptions {\n /**\n * Numeric user id, e.g. \"63625256886\". The cheap path: 2 credits.\n */\n user_id?: string;\n /**\n * Handle without the leading @ (1-60 characters). Costs 2 extra credits\n * because the id has to be resolved upstream first - prefer `user_id`.\n */\n username?: string;\n [key: string]: unknown;\n}\n\nexport interface ThreadsUserPostsOptions extends ThreadsProfileOptions {\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n}\n\nexport interface ThreadsUserRepliesOptions extends ThreadsProfileOptions {\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n}\n\n/** A post reference: the post id, or its threads.net URL. */\nexport interface ThreadsPostOptions {\n /** Post id. */\n post_id?: string;\n /** Full threads.net post URL, as an alternative to post_id. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface ThreadsPostCommentsOptions {\n /** Post id. This endpoint takes the id only - no URL, no username. */\n post_id: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface ThreadsSearchUsersOptions {\n /** Name or handle to search for (1-200 characters). */\n query: string;\n [key: string]: unknown;\n}\n\nexport class ThreadsNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Profile details for a Threads user. Pass `user_id` or `username`;\n * sending neither returns 422 and no match returns 404.\n *\n * Costs 2 credits by `user_id`, 4 credits by `username`.\n */\n async profile(\n options: ThreadsProfileOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/profile\", options);\n }\n\n /**\n * A user's Threads posts. Advance with the previous response's\n * `next_cursor`. Pass `user_id` or `username`.\n *\n * Costs 2 credits by `user_id`, 4 credits by `username` - and that surcharge\n * applies to every page, so resolve the id once before paging.\n */\n async userPosts(\n options: ThreadsUserPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/user/posts\", options);\n }\n\n /**\n * A user's replies. Advance with the previous response's `next_cursor`.\n * Pass `user_id` or `username`.\n *\n * Costs 2 credits by `user_id`, 4 credits by `username` - and that surcharge\n * applies to every page, so resolve the id once before paging.\n */\n async userReplies(\n options: ThreadsUserRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/user/replies\", options);\n }\n\n /**\n * A single post, addressed by `post_id` or by its threads.net `url`.\n * Sending neither returns 422.\n *\n * Costs 2 credits.\n */\n async post(\n options: ThreadsPostOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/post\", options);\n }\n\n /**\n * Replies to a post. Advance with the previous response's `next_cursor`.\n *\n * Costs 2 credits - this endpoint is never username-keyed, so there is no\n * handle surcharge.\n */\n async postComments(\n options: ThreadsPostCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/post/comments\", options);\n }\n\n /**\n * Threads profiles matching a name or handle. This is people search, and it\n * is the only search Threads exposes - there is no content/post search.\n * Use it to turn a handle into the `user_id` every other method prefers.\n *\n * Costs 2 credits. Single response, no pagination.\n */\n async searchUsers(\n options: ThreadsSearchUsersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/threads/search/users\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Kuaishou (China) - kuaishou.com. This is NOT Kwai international: kwai.com\n// ids and links are not served upstream and come back as an empty envelope,\n// so keep kwai.com URLs out of every call here.\n//\n// CREDITS ARE PER-ENDPOINT, not a platform constant. profile costs 10,\n// video costs 2, videosBatch costs 40, the four search endpoints cost 10 each,\n// and everything else costs 1. Each method's own cost is on its JSDoc - read\n// it before looping, because the spread between the cheapest and the dearest\n// call is 40x.\n//\n// videosBatch is hard-capped at 20 photo ids for that reason.\n//\n// Errors: Kuaishou hides upstream failures inside HTTP 200 bodies; the API\n// detects those and surfaces them as 502. A missing or invalid identifier is\n// 422. There is no 400, no 404 and no 503 on this platform.\n\nexport interface KuaishouProfileOptions {\n /** Kuaishou numeric user id, e.g. \"5518803932\". */\n user_id: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouUserPostsOptions {\n /** Kuaishou numeric user id. */\n user_id: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouUserLiveOptions {\n /** Kuaishou numeric user id. */\n user_id: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouUserResolveOptions {\n /**\n * A kuaishou.com or v.kuaishou.com link, e.g.\n * \"https://v.kuaishou.com/KcdKDwFp\". Kwai international (kwai.com) links\n * are not supported.\n */\n share_link: string;\n [key: string]: unknown;\n}\n\n/** A video reference: the photo id, or a Kuaishou URL. One of the two. */\nexport interface KuaishouVideoOptions {\n /** Photo (video) id, e.g. \"3xtdqvdnqd3psuc\". */\n photo_id?: string;\n /** A kuaishou.com or v.kuaishou.com video URL, as an alternative to photo_id. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouVideoCommentsOptions {\n /** Photo (video) id. This endpoint takes the id only - no URL. */\n photo_id: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouCommentRepliesOptions {\n /** Photo (video) id the root comment sits on. */\n photo_id: string;\n /** Id of the root comment whose replies you want. */\n root_comment_id: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n /** Replies per page, 1-50. */\n count?: number;\n [key: string]: unknown;\n}\n\nexport interface KuaishouVideosBatchOptions {\n /** Photo (video) ids, 1-20 per call. More than 20 is rejected. */\n photo_ids: string[];\n [key: string]: unknown;\n}\n\nexport interface KuaishouSearchOptions {\n /** Search keyword (1-200 characters). */\n keyword: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouSearchVideosOptions {\n /** Search keyword (1-200 characters). */\n keyword: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouSearchUsersOptions {\n /** Search keyword (1-200 characters). */\n keyword: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouSearchLiveOptions {\n /** Search keyword (1-200 characters). */\n keyword: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouTagFeedOptions {\n /** Hashtag text, without the leading # (1-200 characters). */\n tag: string;\n /** Opaque cursor from a previous response's next_cursor. */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface KuaishouTrendingOptions {\n /** Which leaderboard to read (default \"hot\"). */\n board?: \"hot\" | \"live\" | \"shopping\" | \"brand\" | \"music\";\n [key: string]: unknown;\n}\n\nexport class KuaishouNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Profile details for a Kuaishou user, addressed by numeric `user_id`.\n *\n * Costs 10 credits - the dearest single-object call on the platform. If you\n * only have a share link, resolve it with `userResolve()` (1 credit) first.\n */\n async profile(\n options: KuaishouProfileOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/profile\", options);\n }\n\n /**\n * A user's top posts. Advance with the previous response's `next_cursor`.\n *\n * Costs 1 credit per page.\n */\n async userPosts(\n options: KuaishouUserPostsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/user/posts\", options);\n }\n\n /**\n * A user's current live-stream status.\n *\n * Costs 1 credit.\n */\n async userLive(\n options: KuaishouUserLiveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/user/live\", options);\n }\n\n /**\n * Turns a Kuaishou share link into a `user_id` you can feed to the other\n * user endpoints. kuaishou.com and v.kuaishou.com links only - kwai.com is\n * not supported.\n *\n * Costs 1 credit.\n */\n async userResolve(\n options: KuaishouUserResolveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/user/resolve\", options);\n }\n\n /**\n * A single video, addressed by `photo_id` or by its Kuaishou `url`.\n * Sending neither returns 422.\n *\n * Costs 2 credits.\n */\n async video(\n options: KuaishouVideoOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/video\", options);\n }\n\n /**\n * Comments on a video. Advance with the previous response's `next_cursor`.\n *\n * Costs 1 credit per page.\n */\n async videoComments(\n options: KuaishouVideoCommentsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/video/comments\", options);\n }\n\n /**\n * Replies under a root comment. Advance with the previous response's\n * `next_cursor`; `count` (1-50) sizes the page.\n *\n * Costs 1 credit per page.\n */\n async commentReplies(\n options: KuaishouCommentRepliesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/video/sub-comments\", options);\n }\n\n /**\n * Several videos in one call, up to 20 photo ids (a hard cap - a longer\n * `photo_ids` array is rejected).\n *\n * Costs 40 credits per call, flat, whether you send 1 id or 20 - so batch\n * to the cap. For a single video `video()` costs 2.\n */\n async videosBatch(\n options: KuaishouVideosBatchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/videos/batch\", options);\n }\n\n /**\n * Mixed-result search across Kuaishou. Advance with the previous response's\n * `next_cursor`.\n *\n * Costs 10 credits per page.\n */\n async search(\n options: KuaishouSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/search\", options);\n }\n\n /**\n * Video search results. Advance with the previous response's `next_cursor`.\n *\n * Costs 10 credits per page.\n */\n async searchVideos(\n options: KuaishouSearchVideosOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/search/videos\", options);\n }\n\n /**\n * User search results. Advance with the previous response's `next_cursor`.\n *\n * Costs 10 credits per page.\n */\n async searchUsers(\n options: KuaishouSearchUsersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/search/users\", options);\n }\n\n /**\n * Live-stream search results. Advance with the previous response's\n * `next_cursor`.\n *\n * Costs 10 credits per page.\n */\n async searchLive(\n options: KuaishouSearchLiveOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/search/live\", options);\n }\n\n /**\n * Posts under a hashtag. Advance with the previous response's `next_cursor`.\n *\n * Costs 1 credit per page - the cheap way to pull volume, versus 10 for\n * `search()`.\n */\n async tagFeed(\n options: KuaishouTagFeedOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/tag/feed\", options);\n }\n\n /**\n * Leaderboards: hot, live, shopping, brand or music. Defaults to \"hot\".\n *\n * Costs 1 credit.\n */\n async trending(\n options: KuaishouTrendingOptions = {},\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/kuaishou/trending\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// eBay is 1 credit flat on all three endpoints.\n//\n// `seller` (the method) is a PROFILE endpoint - it returns the storefront card\n// and cannot enumerate a catalogue. To page a seller's inventory, call\n// search() with the `seller` option set and no `query` at all.\n//\n// `sold: true` searches completed listings that actually sold, which is the\n// price-research surface. eBay publishes no headline count on that view, so\n// `total_results` comes back null there.\n\nexport interface EbaySearchOptions {\n /**\n * Search keywords (1-500 characters). Optional, but either `query` or\n * `seller` must be present or the request is rejected.\n */\n query?: string;\n /**\n * Scope results to one seller's username. Usable with NO `query` to page\n * that seller's whole catalogue - this, not seller(), is how you enumerate\n * inventory.\n */\n seller?: string;\n /** Result page, 1-indexed. */\n page?: number;\n /** Result sort order (default \"best_match\"). */\n sort_by?:\n | \"best_match\"\n | \"ending_soonest\"\n | \"newly_listed\"\n | \"price_low\"\n | \"price_high\";\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n /**\n * Item condition. \"refurbished\" is eBay's parent condition, not one of its\n * three graded tiers.\n */\n condition?: \"new\" | \"open_box\" | \"refurbished\" | \"used\" | \"for_parts\";\n /** Listing format filter. */\n buying_format?: \"auction\" | \"buy_it_now\" | \"best_offer\";\n /** Free-shipping listings only. */\n free_shipping?: boolean;\n /**\n * Search completed listings that SOLD rather than live inventory.\n * `total_results` is null on this view - eBay publishes no headline count.\n */\n sold?: boolean;\n /**\n * eBay category id. Must be numeric: an unrecognised id is not an error,\n * it silently returns the UNFILTERED set under a 200.\n */\n category_id?: string;\n /**\n * Results per page. eBay accepts only 60, 120 or 240 and silently falls\n * back to 60 for anything else. Defaults to 60.\n */\n per_page?: 60 | 120 | 240;\n [key: string]: unknown;\n}\n\nexport interface EbayProductOptions {\n /**\n * eBay item number, or a full ebay.com/itm/... URL. Tracking params on a\n * pasted URL are discarded.\n */\n item_id: string;\n [key: string]: unknown;\n}\n\nexport interface EbaySellerOptions {\n /** eBay username as it appears in ebay.com/usr/<name>. */\n seller: string;\n [key: string]: unknown;\n}\n\nexport class EbayNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Structured eBay listing results: price, condition, bids, shipping, seller,\n * feedback, plus `count` and `total_results`.\n *\n * Either `query` or `seller` is required. Set `sold: true` to search\n * completed listings that actually sold - on that view `total_results` is\n * always null because eBay publishes no headline count for it.\n *\n * Paged with `page`; `per_page` accepts only 60, 120 or 240 and silently\n * falls back to 60 for any other value.\n *\n * Costs 1 credit.\n */\n async search(\n options: EbaySearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/ebay/search\", options);\n }\n\n /**\n * One eBay listing in full: price, condition, images, item specifics,\n * shipping, returns, auction state and seller.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async product(\n options: EbayProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/ebay/product\", options);\n }\n\n /**\n * A seller's profile card: store name, feedback score and percentage, items\n * sold, followers, location and categories.\n *\n * PROFILE ONLY - it cannot list what the seller is selling. For inventory,\n * call search({ seller }) with no query and page through it.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async seller(\n options: EbaySellerOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/ebay/seller\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Target is 1 credit flat on all four endpoints.\n//\n// LATENCY, not price, is what to plan for: Target's own API refuses proxy\n// pools and is reached through a headless browser. Typical wall time is\n// ~4s for product, ~9s for search, ~37s for category and ~40s for reviews,\n// and a retried 502 has been seen at 105s. Raise the client `timeout` before\n// calling category() or reviews().\n//\n// reviews() returns 8 review BODIES maximum whatever the product's\n// review_count says. `limit` only trims that set - there is no page or offset.\n//\n// `seller_id` / `seller_name` are null on first-party stock, which is most of\n// Target. Null there means \"sold by Target\", not missing data; only Target\n// Plus marketplace rows name a vendor.\n//\n// Unlike Walmart, `store_id` is a real request param here - prices and\n// availability are the caller's choice.\n\nexport interface TargetSearchOptions {\n /** Search keywords (1-500 characters). */\n keyword: string;\n /** Result page, 1-indexed. */\n page?: number;\n /** Results per page, 1-28 (default 24). Target rejects anything above 28. */\n count?: number;\n /** Result sort order (default \"relevance\"). */\n sort?:\n | \"relevance\"\n | \"featured\"\n | \"price_low\"\n | \"price_high\"\n | \"rating_high\"\n | \"best_seller\"\n | \"newest\";\n /** Numeric Target store id used for pricing and availability (default \"3991\"). */\n store_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TargetCategoryOptions {\n /** Category id: the segment after `N-` in a target.com /c/ URL. */\n category_id: string;\n /** Result page, 1-indexed. */\n page?: number;\n /** Results per page, 1-28 (default 24). Target rejects anything above 28. */\n count?: number;\n /** Result sort order (default \"relevance\"). */\n sort?:\n | \"relevance\"\n | \"featured\"\n | \"price_low\"\n | \"price_high\"\n | \"rating_high\"\n | \"best_seller\"\n | \"newest\";\n /** Numeric Target store id used for pricing and availability (default \"3991\"). */\n store_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TargetProductOptions {\n /**\n * Target TCIN. A child tcin is answered by its variation parent, with the\n * child itself present in `variants`.\n */\n tcin: string;\n /** Numeric Target store id used for pricing and availability (default \"3991\"). */\n store_id?: string;\n [key: string]: unknown;\n}\n\nexport interface TargetReviewsOptions {\n /** Target TCIN. */\n tcin: string;\n /**\n * TRIMS the returned bodies only. Target publishes 8 reviews anonymously\n * and offers no paging, so this cannot reach a 9th review.\n */\n limit?: number;\n /** Numeric Target store id used for pricing and availability (default \"3991\"). */\n store_id?: string;\n [key: string]: unknown;\n}\n\nexport class TargetNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Target.com: prices, ratings, badges and promotions.\n *\n * Paged with `page` + `count` (1-28, default 24). `seller_id` and\n * `seller_name` are null on first-party rows, which means \"sold by Target\".\n *\n * Costs 1 credit. Typically ~9s - it runs through a headless browser.\n */\n async search(\n options: TargetSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/target/search\", options);\n }\n\n /**\n * Products in a Target category: the same shape as search() plus the\n * category breadcrumb.\n *\n * Paged with `page` + `count` (1-28, default 24).\n *\n * Costs 1 credit. The slowest endpoint here at ~37s - set a generous client\n * timeout before calling it.\n */\n async category(\n options: TargetCategoryOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/target/category\", options);\n }\n\n /**\n * Target product details by TCIN: price, rating, images, specifications,\n * variants, return policy and fulfillment.\n *\n * `store_id` is a real request param here - the price and availability you\n * get back are the store you asked for.\n *\n * Costs 1 credit. Typically ~4s. Single response, no pagination.\n */\n async product(\n options: TargetProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/target/product\", options);\n }\n\n /**\n * Target reviews with the rating breakdown, per-attribute averages and\n * guest photos.\n *\n * Returns 8 review BODIES MAXIMUM regardless of the product's review_count.\n * `limit` only trims that set; there is no page or offset param, so the\n * aggregate distribution is the full-population signal here, not the bodies.\n *\n * Costs 1 credit. Typically ~40s.\n */\n async reviews(\n options: TargetReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/target/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Home Depot is 2 credits flat on all three endpoints - it sits on the\n// premium per-domain proxy table, so it is the priciest of the retail\n// namespaces.\n//\n// Search page size is FIXED at 12 with no way to change it. Paging is the\n// only way to read further, and there is no per-page option to type.\n//\n// `sort_by` is a CLOSED enum on purpose. Home Depot does not fall back on an\n// unknown sort - it answers 200 with an empty page that still bills. \"Newest\"\n// (arrivaldate) is deliberately absent: it works on category pages and is\n// rejected on keyword search.\n//\n// Unknown item ids and out-of-range pages come back upstream as billed 200\n// shells; the API restates them as 404.\n\nexport interface HomeDepotSearchOptions {\n /** Search keywords (1-500 characters). */\n query: string;\n /** Result page, 1-indexed. Page size is fixed at 12 products. */\n page?: number;\n /**\n * Result sort order (default \"best_match\"). Closed set - an unrecognised\n * value is not ignored, it produces an empty billed page.\n */\n sort_by?: \"best_match\" | \"top_sellers\" | \"top_rated\" | \"price_low\" | \"price_high\";\n /** Minimum price filter. */\n min_price?: number;\n /** Maximum price filter. */\n max_price?: number;\n [key: string]: unknown;\n}\n\nexport interface HomeDepotProductOptions {\n /**\n * Home Depot item id, or a full homedepot.com/p/... URL. Tracking params on\n * a pasted URL are discarded.\n */\n item_id: string;\n [key: string]: unknown;\n}\n\nexport interface HomeDepotReviewsOptions {\n /** Home Depot item id. */\n item_id: string;\n /**\n * Result page, 1-indexed. 30 reviews per page. `total_pages` is the last\n * page that exists - asking past it returns 404.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class HomeDepotNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Home Depot: price and promotions, brand and model, ratings,\n * badges, and per-store pickup/delivery.\n *\n * Page size is FIXED at 12 products and cannot be raised - page through\n * with `page` to read further.\n *\n * Costs 2 credits.\n */\n async search(\n options: HomeDepotSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/homedepot/search\", options);\n }\n\n /**\n * Full item detail: pricing and promotions, images and videos, the spec\n * table, dimensions, bullets, documents and return policy.\n *\n * Carries only a 10-review PREVIEW - reviews() is the paginated surface.\n * An unknown item id comes back as 404.\n *\n * Costs 2 credits. Single response, no pagination.\n */\n async product(\n options: HomeDepotProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/homedepot/product\", options);\n }\n\n /**\n * One page of full review bodies with the rating distribution,\n * per-attribute ratings, photos and seller responses.\n *\n * 30 reviews per page. `total_pages` is the last page that exists; a page\n * beyond it is a 404, not an empty result.\n *\n * Costs 2 credits.\n */\n async reviews(\n options: HomeDepotReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/homedepot/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Zillow is 1 credit flat on all three endpoints.\n//\n// A bare ZIP works ALONE but cannot be combined with a filter or a sort:\n// on that request shape Zillow resolves the region by geolocation and answers\n// about another city entirely. Pass the city name when you are filtering.\n//\n// On listing_status \"for_rent\", min_price / max_price mean MONTHLY RENT -\n// Zillow files rent under its payment filter, not its price filter.\n//\n// A region Zillow cannot resolve is a 404, not an empty result set.\n//\n// agentReviews() is named for what it addresses. The path is /zillow/reviews\n// but the subject is an AGENT profile keyed by screen name, never a property.\n\nexport interface ZillowSearchOptions {\n /**\n * Region to search: a Zillow slug, a human form (\"Austin, TX\"), a ZIP, or a\n * pasted Zillow search URL. A bare ZIP works only on its own - combined\n * with any filter or sort, Zillow geolocates instead and answers about a\n * different city, so use the city name there.\n */\n location: string;\n /** Which market to read (default \"for_sale\"). */\n listing_status?: \"for_sale\" | \"for_rent\" | \"sold\";\n /** Result page, 1-indexed. */\n page?: number;\n /**\n * Result sort order. Sorts that rank against a signed-in profile\n * (saved / featured / personalised) are deliberately absent - these\n * requests are never signed in.\n */\n sort?:\n | \"relevance\"\n | \"recommended\"\n | \"newest\"\n | \"price_low\"\n | \"price_high\"\n | \"payment_low\"\n | \"payment_high\"\n | \"beds\"\n | \"baths\"\n | \"sqft\"\n | \"lot_size\"\n | \"zestimate_low\"\n | \"zestimate_high\"\n | \"recent_change\";\n /**\n * Minimum price. On listing_status \"for_rent\" this is MONTHLY RENT, not\n * sale price.\n */\n min_price?: number;\n /**\n * Maximum price. On listing_status \"for_rent\" this is MONTHLY RENT, not\n * sale price.\n */\n max_price?: number;\n /** Minimum bedrooms. */\n beds_min?: number;\n /** Maximum bedrooms. */\n beds_max?: number;\n /** Minimum bathrooms. Half-baths allowed (1.5). */\n baths_min?: number;\n /** Maximum bathrooms. Half-baths allowed (1.5). */\n baths_max?: number;\n /** Minimum living area in square feet. */\n sqft_min?: number;\n /** Maximum living area in square feet. */\n sqft_max?: number;\n /** Minimum lot size in square feet. */\n lot_size_min?: number;\n /** Maximum lot size in square feet. */\n lot_size_max?: number;\n /** Earliest year built. */\n year_built_min?: number;\n /** Latest year built. */\n year_built_max?: number;\n /** Maximum monthly HOA fee. */\n max_hoa?: number;\n /** Property type filter. */\n home_type?:\n | \"houses\"\n | \"townhomes\"\n | \"multi_family\"\n | \"condos\"\n | \"apartments\"\n | \"manufactured\"\n | \"lots_land\";\n /**\n * Listed within: days as \"1\" | \"7\" | \"14\" | \"30\" | \"90\", or months as\n * \"6m\" | \"12m\" | \"24m\" | \"36m\". Closed enum - an unrecognised value is not\n * an error, it silently returns the UNFILTERED set under a 200.\n */\n days_on_zillow?: \"1\" | \"7\" | \"14\" | \"30\" | \"90\" | \"6m\" | \"12m\" | \"24m\" | \"36m\";\n /** Keyword filter applied to the listing text (1-200 characters). */\n keywords?: string;\n /** Pool only. */\n has_pool?: boolean;\n /** Garage only. */\n has_garage?: boolean;\n /** Air conditioning only. */\n has_air_conditioning?: boolean;\n /** Waterfront only. */\n is_waterfront?: boolean;\n /** Basement only. */\n has_basement?: boolean;\n /** New construction only. */\n is_new_construction?: boolean;\n /** Listings with an open house scheduled. */\n has_open_house?: boolean;\n /** Price-reduced listings only. */\n price_reduced?: boolean;\n /** Listings with a 3D tour. */\n is_3d_tour?: boolean;\n [key: string]: unknown;\n}\n\nexport interface ZillowPropertyOptions {\n /**\n * A zpid, a /homedetails/ URL, or a zillow.com/apartments/ building URL.\n * Rental buildings have no caller-visible zpid - search() returns\n * coordinates in that slot - so pass the /apartments/ URL for those.\n */\n zpid: string;\n [key: string]: unknown;\n}\n\nexport interface ZillowAgentReviewsOptions {\n /**\n * The agent's zillow.com/profile/<name>/ screen name, or a full profile\n * URL. Screen names may contain spaces.\n */\n screen_name: string;\n [key: string]: unknown;\n}\n\nexport class ZillowNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Listings in a region: price, beds, baths, living area, Zestimate,\n * coordinates, images and days on market.\n *\n * Paged with `page`. A bare ZIP works alone but not alongside a filter or a\n * sort - use the city name when filtering. On listing_status \"for_rent\",\n * min_price / max_price are MONTHLY RENT. A region Zillow cannot resolve is\n * a 404, not an empty list.\n *\n * Costs 1 credit.\n */\n async search(\n options: ZillowSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/zillow/search\", options);\n }\n\n /**\n * Full listing detail: price and price history, Zestimate, tax history,\n * description, RESO facts, rooms, schools, open houses, photos and\n * attribution. Rental buildings return floor plans, amenities and unit\n * counts instead.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async property(\n options: ZillowPropertyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/zillow/property\", options);\n }\n\n /**\n * An AGENT's profile and reviews: rating, review count, bodies with\n * sub-ratings, specialties, languages, licenses, service areas and sales\n * counts.\n *\n * This addresses an agent by screen name, NOT a property. Zillow\n * server-renders the first five reviews only: `count` is what came back,\n * `total_review_count` is what the agent actually has, and there is no way\n * to page to the rest.\n *\n * Costs 1 credit.\n */\n async agentReviews(\n options: ZillowAgentReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/zillow/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Redfin is 1 credit flat on all three endpoints. property() and market()\n// read the property / region PAGE, whose inlined request cache replaces the\n// ~40 upstream calls the page itself made - which is why they cost the same\n// as search().\n//\n// CITY NAMES ARE NOT ACCEPTED on `location`. Redfin's own name lookup is the\n// single path its edge blocks us from, so pass a redfin.com region URL\n// (/city/, /neighborhood/, /county/, /zipcode/), a bare 5-digit ZIP, or\n// `region_id` + `region_type` TOGETHER - the transport falls back to\n// `location` unless it has both halves.\n//\n// `region_id` is NOT a ZIP code. They are different number spaces, and a ZIP\n// passed as a region id resolves to another city rather than failing.\n//\n// Every numeric filter is truncated into Redfin's gis query, so FRACTIONAL\n// bounds are rejected rather than silently floored (1.5 baths would have\n// become 1).\n//\n// `days_on_market` comes back NULL on search() - Redfin's mainHouseInfo\n// carries no `dom` key. Do not build on that field.\n//\n// Two filter pairs are mutually exclusive by construction:\n// `max_days_on_market` + `min_days_on_market` (Redfin expresses both through\n// one param), and `sold_within_days` outside `listing_status: \"sold\"`.\n\nexport interface RedfinSearchOptions {\n /**\n * A redfin.com region URL (/city/, /neighborhood/, /county/, /zipcode/) or\n * a bare 5-digit ZIP, up to 500 characters. CITY NAMES ARE NOT ACCEPTED.\n * Required unless `region_id` AND `region_type` are both given.\n */\n location?: string;\n /**\n * Redfin's internal region id. NOT a ZIP code - a ZIP here resolves to a\n * different city instead of failing. Must be paired with `region_type`.\n */\n region_id?: number;\n /**\n * What `region_id` refers to: 1 neighborhood, 2 ZIP, 5 county, 6 city.\n * Must be paired with `region_id`.\n */\n region_type?: 1 | 2 | 5 | 6;\n /** Which market to read (default \"for_sale\"). */\n listing_status?: \"for_sale\" | \"sold\" | \"for_rent\";\n /**\n * Sold-listing lookback in days (default 90). REJECTED unless\n * `listing_status` is \"sold\" - it only widens whatever listing_status\n * already chose.\n */\n sold_within_days?: number;\n /** Result page, 1-indexed. */\n page?: number;\n /** Listings per page, 1-350 (default 100). */\n limit?: number;\n /** Result sort order (default \"recommended\"). */\n sort?:\n | \"recommended\"\n | \"price_low\"\n | \"price_high\"\n | \"newest\"\n | \"oldest\"\n | \"sqft_low\"\n | \"sqft_high\"\n | \"price_per_sqft_low\"\n | \"price_per_sqft_high\";\n /**\n * Minimum price. On `listing_status: \"for_rent\"` this is MONTHLY RENT, not\n * sale price.\n */\n min_price?: number;\n /**\n * Maximum price. On `listing_status: \"for_rent\"` this is MONTHLY RENT, not\n * sale price.\n */\n max_price?: number;\n /** Minimum bedrooms. Whole numbers only. */\n beds_min?: number;\n /** Maximum bedrooms. Whole numbers only. */\n beds_max?: number;\n /**\n * Minimum bathrooms. WHOLE baths only - a fractional value such as 1.5 is\n * rejected, not rounded.\n */\n baths_min?: number;\n /** Minimum living area in square feet. Whole numbers only. */\n sqft_min?: number;\n /** Maximum living area in square feet. Whole numbers only. */\n sqft_max?: number;\n /** Minimum lot size in square feet. Whole numbers only. */\n lot_size_min?: number;\n /** Earliest year built. */\n year_built_min?: number;\n /** Latest year built. */\n year_built_max?: number;\n /** Maximum monthly HOA fee. */\n max_hoa?: number;\n /**\n * Property class. Redfin's uipt code 7 is deliberately absent - its meaning\n * could not be confirmed and a guess would silently search a different\n * class.\n */\n property_type?:\n | \"house\"\n | \"condo\"\n | \"townhouse\"\n | \"multi_family\"\n | \"land\"\n | \"other\"\n | \"co_op\";\n /** Listings with a pool only. */\n has_pool?: boolean;\n /**\n * Maximum days on market. Cannot be combined with `min_days_on_market` -\n * Redfin expresses both through ONE param, so the transport would send the\n * max and drop the min.\n */\n max_days_on_market?: number;\n /**\n * Minimum days on market. Cannot be combined with `max_days_on_market`.\n */\n min_days_on_market?: number;\n [key: string]: unknown;\n}\n\nexport interface RedfinPropertyOptions {\n /**\n * A Redfin property id, or any redfin.com listing URL carrying one (up to\n * 500 characters).\n */\n property_id: string;\n [key: string]: unknown;\n}\n\nexport interface RedfinMarketOptions {\n /**\n * A redfin.com region URL (/city/, /neighborhood/, /county/, /zipcode/) or\n * a bare 5-digit ZIP, up to 500 characters. CITY NAMES ARE NOT ACCEPTED.\n * Required unless `region_id` AND `region_type` are both given.\n */\n location?: string;\n /**\n * Redfin's internal region id. NOT a ZIP code. Must be paired with\n * `region_type`.\n */\n region_id?: number;\n /**\n * What `region_id` refers to: 1 neighborhood, 2 ZIP, 5 county, 6 city.\n * Must be paired with `region_id`.\n */\n region_type?: 1 | 2 | 5 | 6;\n [key: string]: unknown;\n}\n\nexport class RedfinNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Redfin listings: price, price per sqft, beds, baths, living area, lot\n * size, year built, coordinates, listing remarks and full photo galleries.\n *\n * Pass `location` (a redfin.com region URL or a bare ZIP - city NAMES are\n * not accepted) or `region_id` AND `region_type` together. Paged with\n * `page` + `limit`, up to 350 listings per page.\n *\n * `days_on_market` comes back NULL on every row: Redfin's mainHouseInfo has\n * no `dom` key. Fractional numeric filters are rejected, not rounded.\n * `sold_within_days` requires `listing_status: \"sold\"`, and\n * `max_days_on_market` / `min_days_on_market` cannot be combined.\n *\n * Costs 1 credit.\n */\n async search(\n options: RedfinSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/redfin/search\", options);\n }\n\n /**\n * One Redfin listing in full: price, Redfin Estimate and rental estimate,\n * complete MLS fact sheet, price and tax history, listing agents, open\n * houses, schools, climate risk, walkability and location scores, sun\n * exposure, monthly weather, permits, zoning, comparable sales and photos.\n *\n * Reads the property PAGE, whose inlined request cache replaces the ~40\n * upstream calls that page made - which is why it is the same price as\n * search().\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async property(\n options: RedfinPropertyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/redfin/property\", options);\n }\n\n /**\n * Housing-market stats for a region: median list and sale price, price per\n * sqft, sale-to-list ratio, average offers and days on market, YoY\n * movement, Redfin's 0-100 compete score, live inventory by property type,\n * median price and active listings per bedroom count, plus Redfin agent\n * presence and aggregate rating.\n *\n * Pass `location` (city NAMES are not accepted) or `region_id` AND\n * `region_type` together.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async market(\n options: RedfinMarketOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/redfin/market\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Booking.com is 1 credit flat on all three endpoints.\n//\n// `checkin` and `checkout` must be sent TOGETHER on every endpoint. Booking\n// ignores a lone checkin and prices a default range of its own, so the\n// response comes back with real prices for dates nobody asked for.\n//\n// hotel() and reviews() take dates for the same reason search does: Booking\n// prices a STAY, not a property. Omit them and you get prices for a two-night\n// window Booking chose; the response echoes whichever dates were used.\n//\n// `currency` defaults to USD in the transport. Without it Booking prices off\n// the proxy exit and two identical requests disagree.\n//\n// A search with neither `destination` nor `dest_id` would land on Booking's\n// HOMEPAGE - a billed request that returns nothing - so it is rejected at the\n// edge instead. `dest_type` is likewise rejected without `dest_id`, because\n// Booking silently ignores it on its own.\n//\n// Chain the `url` a search row returns into hotel() / reviews(). A bare page\n// slug with the wrong `country_code` is a real 404 that scrape.do BILLS.\n\nexport interface BookingSearchOptions {\n /**\n * Free-text destination, 1-200 characters (\"Paris\", \"Lisbon, Portugal\").\n * Either `destination` or `dest_id` is required.\n */\n destination?: string;\n /**\n * Numeric Booking destination id. Either `destination` or `dest_id` is\n * required.\n */\n dest_id?: string;\n /**\n * What `dest_id` refers to. Rejected without `dest_id` - Booking silently\n * ignores it on its own.\n */\n dest_type?:\n | \"city\"\n | \"region\"\n | \"country\"\n | \"district\"\n | \"landmark\"\n | \"airport\"\n | \"hotel\";\n /** Result page, 1-indexed. 25 properties per page. */\n page?: number;\n /** Result sort order (default \"popularity\"). */\n sort_by?:\n | \"popularity\"\n | \"price_low\"\n | \"price_high\"\n | \"stars_high\"\n | \"stars_low\"\n | \"stars_and_price\"\n | \"distance\"\n | \"review_score\";\n /** Minimum price PER NIGHT, in `currency`. Must be <= `max_price`. */\n min_price?: number;\n /** Maximum price PER NIGHT, in `currency`. */\n max_price?: number;\n /** Star ratings to keep, 1-5 each, up to 5 values. OR'd together. */\n stars?: number[];\n /**\n * Minimum guest review score. A CLOSED set - Booking silently drops an\n * arbitrary threshold, so only \"6\", \"7\", \"8\" and \"9\" are accepted.\n */\n min_review_score?: \"6\" | \"7\" | \"8\" | \"9\";\n /**\n * Accommodation type by name, or a raw numeric Booking accommodation-type\n * id.\n */\n property_type?:\n | \"apartments\"\n | \"hostels\"\n | \"hotels\"\n | \"motels\"\n | \"resorts\"\n | \"bed_and_breakfasts\"\n | \"villas\"\n | \"campgrounds\"\n | \"vacation_homes\"\n | \"lodges\"\n | \"homestays\"\n | number;\n /** Free-cancellation rates only. */\n free_cancellation?: boolean;\n /** No-prepayment rates only. */\n no_prepayment?: boolean;\n /** Breakfast-included rates only. */\n breakfast_included?: boolean;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `checkout` and\n * before it.\n */\n checkin?: string;\n /** Check-out date, YYYY-MM-DD. Must be sent together with `checkin`. */\n checkout?: string;\n /** Adults in the party (default 2). */\n adults?: number;\n /** Child AGES, 0-17 each, up to 10 values. Ages, not a count. */\n children_ages?: number[];\n /** Rooms to price (default 1). */\n rooms?: number;\n /**\n * ISO 4217 currency, 3 letters (default \"USD\"). Leave it set - without a\n * currency Booking prices off the proxy exit.\n */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface BookingHotelOptions {\n /**\n * booking.com property URL or the bare page slug, 1-500 characters. Query\n * params are discarded. Chaining the `url` from a search row is cheapest -\n * a bare slug with the wrong `country_code` is a BILLED 404.\n */\n hotel: string;\n /** Two-letter country code (default \"us\"). Only consulted for a bare slug. */\n country_code?: string;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `checkout` and\n * before it. Omitting both prices a two-night window Booking chose.\n */\n checkin?: string;\n /** Check-out date, YYYY-MM-DD. Must be sent together with `checkin`. */\n checkout?: string;\n /** Adults in the party (default 2). */\n adults?: number;\n /** Child AGES, 0-17 each, up to 10 values. Ages, not a count. */\n children_ages?: number[];\n /** Rooms to price (default 1). */\n rooms?: number;\n /** ISO 4217 currency, 3 letters (default \"USD\"). */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface BookingReviewsOptions {\n /**\n * booking.com property URL or the bare page slug, 1-500 characters. Query\n * params are discarded.\n */\n hotel: string;\n /** Two-letter country code (default \"us\"). Only consulted for a bare slug. */\n country_code?: string;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `checkout` and\n * before it.\n */\n checkin?: string;\n /** Check-out date, YYYY-MM-DD. Must be sent together with `checkin`. */\n checkout?: string;\n /** Adults in the party (default 2). */\n adults?: number;\n /** Child AGES, 0-17 each, up to 10 values. Ages, not a count. */\n children_ages?: number[];\n /** Rooms to price (default 1). */\n rooms?: number;\n /** ISO 4217 currency, 3 letters (default \"USD\"). */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport class BookingNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Booking.com properties for a destination and stay: live nightly\n * price, review score, star rating, location, room type and deal badges.\n *\n * Either `destination` or `dest_id` is required - without one the request\n * would land on Booking's homepage, so it is rejected instead of billed.\n * `dest_type` requires `dest_id`.\n *\n * Paged with `page`, 25 properties per page. `checkin` and `checkout` must\n * be sent together or Booking prices a range of its own choosing.\n *\n * Each row carries a `url` - chain it into hotel() rather than rebuilding a\n * slug, which risks a BILLED 404 on the wrong `country_code`.\n *\n * Costs 1 credit.\n */\n async search(\n options: BookingSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/booking/search\", options);\n }\n\n /**\n * One Booking.com property in full: rooms and rate plans, facilities, house\n * rules, check-in windows, policies, images, location and review scores -\n * priced for the stay you ask for.\n *\n * Takes dates because Booking prices a STAY. Omit them and the response\n * carries prices for a two-night window Booking picked; the response echoes\n * whichever dates were used.\n *\n * Single response, no pagination.\n *\n * Costs 1 credit.\n */\n async hotel(\n options: BookingHotelOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/booking/hotel\", options);\n }\n\n /**\n * Booking.com guest reviews with the score breakdown by category and\n * Booking's own praise/complaint summary.\n *\n * NO PAGE PARAM - do not invent one. `total_count` is the property's whole\n * review history; `count` is what this response holds.\n *\n * Costs 1 credit.\n */\n async reviews(\n options: BookingReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/booking/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Airbnb is 1 credit flat on all three endpoints.\n//\n// PRICES ARE SEARCH-ONLY. listing() carries NO nightly rate under any\n// parameters - with or without dates, and even under render. Read prices off\n// search() rows.\n//\n// The RATING BREAKDOWN is the mirror image: the six category ratings, the\n// five-bucket star distribution and Airbnb's AI-synthesised review tags live\n// on listing(), which server-renders them - NOT on reviews().\n//\n// `check_in` and `check_out` must be sent together. A dateless search defaults\n// to +30 days / 5 nights AND A/Bs both the window and the prices - one URL was\n// seen splitting 3/3 across two windows with a first-row price of $680 / $802\n// / $2,238. The response flags this as `dates_are_defaulted`, so pass dates\n// whenever the price matters.\n//\n// `currency` defaults to USD in the transport; without it Airbnb prices off\n// the proxy exit and two identical requests disagree.\n//\n// `room_type` and amenity NAMES are validated before the scrape, because an\n// unrecognised value makes Airbnb return the UNFILTERED set under a 200.\n//\n// Search is 18 listings per page and `cursor` WINS over `page`, so sending\n// both is rejected.\n\nexport interface AirbnbSearchOptions {\n /**\n * City, region, ZIP, or a pasted airbnb.com/s/ URL, 1-200 characters. A\n * location Airbnb cannot resolve is a 404, not an empty result.\n */\n location: string;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `check_out` and\n * before it. Omitted, the transport defaults to +30 days and the response\n * sets `dates_are_defaulted`.\n */\n check_in?: string;\n /**\n * Check-out date, YYYY-MM-DD. Must be sent together with `check_in`.\n * Omitted, it defaults to `check_in` + 5 nights.\n */\n check_out?: string;\n /** Adults in the party. */\n adults?: number;\n /** Children, ages 2-12. */\n children?: number;\n /** Infants. */\n infants?: number;\n /** Pets. */\n pets?: number;\n /**\n * Minimum price for the WHOLE STAY, not per night. Must be <= `max_price`.\n */\n min_price?: number;\n /** Maximum price for the WHOLE STAY, not per night. */\n max_price?: number;\n /** Room type. A closed set - an unrecognised value is rejected up front. */\n room_type?: \"entire_home\" | \"private_room\" | \"shared_room\" | \"hotel_room\";\n /** Minimum bedrooms. */\n min_bedrooms?: number;\n /** Minimum beds. */\n min_beds?: number;\n /** Minimum bathrooms. */\n min_bathrooms?: number;\n /** Superhost listings only. */\n superhost?: boolean;\n /** Instant Book listings only. */\n instant_book?: boolean;\n /** Guest Favourite listings only. */\n guest_favorite?: boolean;\n /** Free-cancellation listings only. */\n free_cancellation?: boolean;\n /**\n * Comma-separated amenity filter, 1-200 characters. Either the named\n * vocabulary - \"wifi\", \"air_conditioning\", \"pool\", \"kitchen\",\n * \"free_parking\", \"washer\", \"self_check_in\", \"tv\" - or raw numeric Airbnb\n * amenity ids. An unrecognised NAME is rejected before the scrape, because\n * Airbnb would otherwise answer the UNFILTERED set under a 200.\n */\n amenities?: string;\n /**\n * ISO 4217 currency (default \"USD\"). Leave it set - without a currency\n * Airbnb prices off the proxy exit.\n */\n currency?: string;\n /**\n * Result page, 1-indexed. 18 listings per page. Cannot be combined with\n * `cursor`.\n */\n page?: number;\n /**\n * `next_cursor` from a previous response, 1-500 characters. Wins over\n * `page`, so sending both is rejected.\n */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface AirbnbListingOptions {\n /**\n * Airbnb listing id or a full /rooms/ URL, 1-500 characters. Query params\n * are discarded - they carry someone else's dates.\n */\n listing_id: string;\n /**\n * Check-in date, YYYY-MM-DD. Must be sent together with `check_out` and\n * before it. Dates do NOT produce a price here - the room page has none.\n */\n check_in?: string;\n /** Check-out date, YYYY-MM-DD. Must be sent together with `check_in`. */\n check_out?: string;\n /** Adults in the party. */\n adults?: number;\n /** Children, ages 2-12. */\n children?: number;\n /** Infants. */\n infants?: number;\n /** Pets. */\n pets?: number;\n /** ISO 4217 currency (default \"USD\"). */\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface AirbnbReviewsOptions {\n /** Airbnb listing id or a full /rooms/ URL, 1-500 characters. */\n listing_id: string;\n /** ISO 4217 currency (default \"USD\"). */\n currency?: string;\n /**\n * Reviews per response, 1-50 (default 30). Send it explicitly - upstream\n * falls back to a fixed 7 rows when no limit is given.\n */\n limit?: number;\n /** Row offset into the review list (default 0). */\n offset?: number;\n [key: string]: unknown;\n}\n\nexport class AirbnbNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Airbnb stays: stay-total and per-night price with the full\n * discount ledger, rating and review count, bedrooms/beds/baths,\n * coordinates, badges, images and `dates_are_defaulted`.\n *\n * This is the ONLY endpoint that carries a price - listing() has no nightly\n * rate field at all.\n *\n * Paged with `page` (18 listings per page) XOR `cursor`; `cursor` wins, so\n * sending both is rejected. `min_price` / `max_price` are WHOLE-STAY totals,\n * not per night.\n *\n * Pass `check_in` + `check_out` together whenever price matters: a dateless\n * search defaults to +30 days / 5 nights and A/Bs both the window and the\n * prices, which the response flags as `dates_are_defaulted`.\n *\n * Costs 1 credit.\n */\n async search(\n options: AirbnbSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/airbnb/search\", options);\n }\n\n /**\n * One Airbnb listing in full: description, property and room type, capacity\n * and room counts, the complete grouped amenity list (including the\n * amenities the place does NOT have), host profile and stats, house rules\n * with parsed check-in/out times, cancellation policy, sleeping\n * arrangements, photo tour, every image, and the RATING BREAKDOWN - six\n * category ratings, the five-bucket star distribution and Airbnb's\n * AI-synthesised review tags.\n *\n * NO NIGHTLY PRICE. The room page carries no rate under any parameters,\n * with or without dates. Prices come from search() only.\n *\n * Single response, no pagination.\n *\n * Costs 1 credit.\n */\n async listing(\n options: AirbnbListingOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/airbnb/listing\", options);\n }\n\n /**\n * Airbnb review BODIES with per-review rating, date, and reviewer name,\n * photo and location.\n *\n * Paged with `limit` (1-50, default 30) + `offset`. Send `limit`\n * explicitly - upstream returns a fixed 7 rows when none is given.\n *\n * `count` is the listing's TOTAL review count; `returned` is how many rows\n * this page holds. The rating breakdown is NOT here - it lives on\n * listing().\n *\n * Costs 1 credit.\n */\n async reviews(\n options: AirbnbReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/airbnb/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Tripadvisor is 2 credits flat on all four endpoints.\n//\n// START WITH locations(). Every other endpoint is keyed by ids that exist\n// only inside Tripadvisor's own URLs, so a caller holding a place NAME has no\n// other entry point. A GEO row from locations() answers `geo_id` for search();\n// a business row answers the `geo_id` + `location_id` pair that location() and\n// reviews() take.\n//\n// Page 1 of a location's reviews already rides along inside location() - call\n// reviews() only to page PAST it.\n//\n// Review page size differs by family: 15 per page for restaurants, 10 for\n// hotels and attractions. Keep `category` matched to the location's own type\n// on any page past the first. Consecutive pages can REPEAT one review at the\n// boundary - de-duplicate on review_id when concatenating.\n//\n// Search renders 30 locations per page and a page beyond the last is a 404,\n// not an empty result. An unknown location id is answered upstream with a 200\n// city listing (billed) that the transport restates as a 404.\n\nexport interface TripadvisorLocationsOptions {\n /** Place or business NAME to resolve, 1-120 characters. */\n query: string;\n /**\n * How many matches to return, 1-20 (default 12). This only SIZES the\n * response - it is not a page param.\n */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface TripadvisorSearchOptions {\n /**\n * Tripadvisor geo id. Accepts 30196, g30196, or a URL carrying one. Either\n * `geo_id` or `url` is required.\n */\n geo_id?: string;\n /** Which listing family to read (default \"restaurants\"). */\n category?: \"restaurants\" | \"hotels\" | \"attractions\";\n /**\n * Result page, 1-indexed. 30 locations per page; a page beyond the last is\n * a 404, not an empty result.\n */\n page?: number;\n /**\n * Full tripadvisor.com listing URL, 1-500 characters. The host is checked by\n * the transport (subdomain-aware, covers country sites). Either `geo_id` or\n * `url` is required.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface TripadvisorLocationOptions {\n /**\n * Tripadvisor location id. Accepts 1899234, d1899234, or a full _Review\n * URL. Either `location_id` or `url` is required.\n */\n location_id?: string;\n /**\n * Tripadvisor geo id. Required by the transport when a bare d-id is sent -\n * the pair comes straight off a locations() business row.\n */\n geo_id?: string;\n /** Which listing family the location belongs to (default \"restaurants\"). */\n category?: \"restaurants\" | \"hotels\" | \"attractions\";\n /**\n * Full tripadvisor.com listing URL, 1-500 characters. Either `location_id`\n * or `url` is required.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface TripadvisorReviewsOptions {\n /**\n * Tripadvisor location id. Accepts 1899234, d1899234, or a full _Review\n * URL. Either `location_id` or `url` is required.\n */\n location_id?: string;\n /** Tripadvisor geo id for the location. */\n geo_id?: string;\n /**\n * Which listing family the location belongs to (default \"restaurants\").\n * Page size follows this, so it must match the location's own type on any\n * page past the first.\n */\n category?: \"restaurants\" | \"hotels\" | \"attractions\";\n /**\n * Full tripadvisor.com listing URL, 1-500 characters. Either `location_id`\n * or `url` is required.\n */\n url?: string;\n /**\n * Result page, 1-indexed. 15 per page for restaurants, 10 for hotels and\n * attractions. Past the last page is a 404.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class TripadvisorNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Resolve a place or business NAME to the Tripadvisor\n * geo_id / location_id pairs every other endpoint needs.\n *\n * A GEO row answers `geo_id` for search(); a business row answers the\n * `geo_id` + `location_id` pair location() and reviews() take. Those ids\n * exist only inside Tripadvisor's own URLs, so this is the only entry point\n * from a name.\n *\n * `limit` (1-20, default 12) sizes the response; there is no pagination.\n *\n * Costs 2 credits.\n */\n async locations(\n options: TripadvisorLocationsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tripadvisor/locations\", options);\n }\n\n /**\n * Restaurants, hotels or attractions in a Tripadvisor geo, Tripadvisor-\n * ranked: rating, review count, price band, address, coordinates, phone,\n * hours and Travelers' Choice badge. Each row carries the location_id +\n * geo_id pair the detail endpoints take.\n *\n * `geo_id` or `url` is required - get `geo_id` from locations().\n *\n * Paged with `page`, 30 locations per page. A page beyond the last is a\n * 404, not an empty result.\n *\n * Costs 2 credits.\n */\n async search(\n options: TripadvisorSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tripadvisor/search\", options);\n }\n\n /**\n * One Tripadvisor location in full: rating, review histogram and per-aspect\n * sub-ratings, city ranking, price band, cuisines, amenities, address,\n * coordinates, contact, photos, and the FIRST PAGE OF REVIEWS.\n *\n * `location_id` or `url` is required, and the transport additionally\n * requires a geo when a bare d-id is sent.\n *\n * Page 1 of the reviews is already here - call reviews() only to page PAST\n * it. An unknown location id is a 404 (upstream answers a billed city\n * listing that the transport restates).\n *\n * Costs 2 credits.\n */\n async location(\n options: TripadvisorLocationOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tripadvisor/location\", options);\n }\n\n /**\n * A page of Tripadvisor reviews: rating, trip date and type, reviewer home\n * town and contribution count, and any management response.\n *\n * `location_id` or `url` is required. Page size follows `category` - 15 per\n * page for restaurants, 10 for hotels and attractions - so keep it matched\n * to the location's own type on any page past the first.\n *\n * Consecutive pages can REPEAT one review at the boundary; de-duplicate on\n * review_id when concatenating.\n *\n * Costs 2 credits.\n */\n async reviews(\n options: TripadvisorReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/tripadvisor/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Yelp is 2 credits flat on all three endpoints - it sits on the premium\n// per-domain proxy table.\n//\n// REVIEWS PAGE 1 IS REDUNDANT. business() already returns the first page of\n// reviews at no extra cost, and reviews({ page: 1 }) re-fetches the exact same\n// document for another 2 credits. Start at page 2.\n//\n// `location` is effectively REQUIRED on search: Yelp geolocates a\n// location-less search off the proxy exit, so the same request can answer\n// about a different metro run to run.\n//\n// Yelp fixes the page size at 10 for both search and reviews, and a page past\n// the last review is a 404, not an empty result.\n//\n// `sort` is a CLOSED enum on both endpoints because Yelp ignores an\n// unrecognised sortby and serves default ranking under a 200 - a billed\n// premium scrape for a sort that never ran.\n//\n// popular_items on business() has a stub-shell state: rows arrive with every\n// field null but `identifier`. Those rows are dropped and\n// popular_items_omitted flags it.\n\nexport interface YelpSearchOptions {\n /**\n * What to search for (1-200 characters), e.g. \"coffee\". Required together\n * with `location` unless `url` is given.\n */\n term?: string;\n /**\n * Where to search (1-200 characters), e.g. \"Austin, TX\". Effectively\n * REQUIRED - without it Yelp geolocates off the proxy exit and the same\n * request answers about a different metro run to run.\n */\n location?: string;\n /** Result page, 1-indexed. Yelp fixes the page size at 10. */\n page?: number;\n /**\n * Result sort order (default \"recommended\"). Closed set - Yelp ignores an\n * unrecognised value and serves default ranking under a billed 200.\n */\n sort?: \"recommended\" | \"rating\" | \"review_count\";\n /** Price bands to include, 1 ($) to 4 ($$$$). 1-4 entries. */\n price?: Array<1 | 2 | 3 | 4>;\n /** Businesses open at request time only. */\n open_now?: boolean;\n /**\n * Raw Yelp filter aliases (RestaurantsDelivery, GoodForKids,\n * WheelchairAccessible), max 20. Deliberate PASSTHROUGH, not an enum -\n * Yelp's vocabulary runs ~117 values per vertical, and an alias it does not\n * know is ignored upstream so results come back unfiltered.\n */\n attributes?: string[];\n /**\n * A full yelp.com/search URL as an alternative to term + location\n * (1-1000 characters).\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface YelpBusinessOptions {\n /**\n * Yelp alias (desnudo-coffee-austin-2), opaque encid, or a yelp.com/biz URL\n * (1-500 characters). Either this or `url` is required.\n */\n business_id?: string;\n /** A yelp.com/biz URL (1-1000 characters). Either this or `business_id` is required. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface YelpReviewsOptions {\n /**\n * Yelp alias, opaque encid, or a yelp.com/biz URL (1-500 characters).\n * Either this or `url` is required.\n */\n business_id?: string;\n /** A yelp.com/biz URL (1-1000 characters). Either this or `business_id` is required. */\n url?: string;\n /**\n * Result page, 1-indexed, 10 reviews per page. PAGE 1 IS REDUNDANT with\n * business() and costs another 2 credits - start at page 2. A page past the\n * last review is a 404, not an empty result.\n */\n page?: number;\n /**\n * Review sort order (default \"relevance\"). Closed set - an unrecognised\n * value is served as default ranking under a billed 200.\n */\n sort?: \"relevance\" | \"newest\" | \"oldest\" | \"rating_high\" | \"rating_low\" | \"elites\";\n /** Keep only reviews at this star rating. Changes filtered_review_count, not review_count. */\n rating?: 1 | 2 | 3 | 4 | 5;\n [key: string]: unknown;\n}\n\nexport class YelpNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Businesses in Yelp's ranked order: rating, review count, price band,\n * categories, address, contact rails, hours, photos and a review snippet.\n * Each row carries both business_id and alias, either of which addresses\n * business(). `count` is the 10-row page, `total_results` is Yelp's headline\n * count.\n *\n * `term` + `location` or `url` is required, and `location` is effectively\n * mandatory - Yelp geolocates a location-less search off the proxy exit.\n * Paged with `page`; the page size is fixed at 10.\n *\n * Costs 2 credits.\n */\n async search(\n options: YelpSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/yelp/search\", options);\n }\n\n /**\n * One business in full: rating and per-star histogram, review count, price\n * band, categories, address and coordinates, phone, website and menu links,\n * hours and holidays, amenities, photos and videos, popular items, health\n * inspections, Q&A, licences and claim status - PLUS the first page of\n * reviews at no extra cost.\n *\n * Because those reviews ride along, calling reviews({ page: 1 }) after this\n * buys the same document twice. Yelp's recommendation software hides some\n * reviews entirely; those are never returned and are counted in\n * not_recommended_review_count here. popular_items rows can arrive as stub\n * shells with every field null but `identifier` - those are dropped and\n * popular_items_omitted flags it.\n *\n * `business_id` or `url` is required. Costs 2 credits. Single response, no\n * pagination.\n */\n async business(\n options: YelpBusinessOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/yelp/business\", options);\n }\n\n /**\n * A page of reviews: rating, full text, language, author profile and\n * expertise counts, attached photos, reaction counts and owner response.\n *\n * START AT PAGE 2 - page 1 re-fetches the document business() already\n * returned and costs another 2 credits. 10 reviews per page, and a page past\n * the last review is a 404, not an empty result. `rating` changes\n * filtered_review_count, not review_count.\n *\n * `business_id` or `url` is required. Costs 2 credits.\n */\n async reviews(\n options: YelpReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/yelp/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Indeed is 2 credits flat on all four endpoints.\n//\n// `radius` and `max_age_days` are CLOSED sets. Indeed IGNORES any other value\n// and answers the unfiltered set, so a request for a 7-mile radius is billed\n// as a search covering fifty. The unions here are the whole accepted\n// vocabulary: radius 0/5/10/15/25/35/50/100 (upstream default 50) and\n// max_age_days 1/3/7/14.\n//\n// `min_salary` filters on INDEED'S OWN ESTIMATE for the role, not a posted\n// figure, so postings that publish no salary at all still match.\n//\n// A location-only search - no `query` - is valid and returns every posting in\n// a metro.\n//\n// Search is 10 postings per page; company reviews are 20 per page. An unknown\n// job key or company slug is a real 404 that scrape.do BILLS.\n\nexport interface IndeedSearchOptions {\n /**\n * Search keywords, 1-500 characters. Optional: either `query` or `location`\n * must be present.\n */\n query?: string;\n /**\n * City+state, postal code, state, country or \"Remote\", 1-200 characters.\n * Usable with NO `query` at all - that returns every posting in the metro.\n */\n location?: string;\n /** Result page, 1-indexed. 10 postings per page. */\n page?: number;\n /**\n * Search radius in miles. A CLOSED set (upstream default 50) - Indeed\n * ignores anything else and bills a wider search than you asked for.\n */\n radius?: 0 | 5 | 10 | 15 | 25 | 35 | 50 | 100;\n /**\n * Maximum posting age in days. A CLOSED set - Indeed ignores anything else\n * and returns the unfiltered set.\n */\n max_age_days?: 1 | 3 | 7 | 14;\n /** Employment type filter. */\n job_type?: \"full_time\" | \"part_time\" | \"contract\" | \"temporary\" | \"internship\";\n /**\n * Minimum salary. Filters on INDEED'S OWN ESTIMATE for the role, not a\n * posted figure, so postings publishing no salary still match.\n */\n min_salary?: number;\n /** Remote postings only. */\n remote?: boolean;\n [key: string]: unknown;\n}\n\nexport interface IndeedJobOptions {\n /**\n * 16-hex Indeed job key, or any indeed.com URL carrying jk= (/viewjob,\n * /rc/clk, /pagead/clk).\n */\n job_id: string;\n [key: string]: unknown;\n}\n\nexport interface IndeedCompanyOptions {\n /**\n * indeed.com/cmp/<slug> slug or a full profile URL, 1-200 characters. Slugs\n * are untidy - e.g. \"Tata-Consultancy-Services-(tcs)\".\n */\n company: string;\n [key: string]: unknown;\n}\n\nexport interface IndeedCompanyReviewsOptions {\n /**\n * indeed.com/cmp/<slug> slug or a full profile URL, 1-200 characters.\n */\n company: string;\n /** Result page, 1-indexed. 20 reviews per page. */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class IndeedNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Indeed job postings: title, employer, rating, location, salary\n * range, job type, benefits, posting age and apply route.\n *\n * Either `query` or `location` is required; a location-only search is valid\n * and returns every posting in the metro.\n *\n * Paged with `page`, 10 postings per page. `radius` and `max_age_days` are\n * closed sets - Indeed silently ignores an off-list value and bills the\n * unfiltered search. `min_salary` filters on Indeed's own ESTIMATE for the\n * role, not a posted figure.\n *\n * Costs 2 credits.\n */\n async search(\n options: IndeedSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/indeed/search\", options);\n }\n\n /**\n * One Indeed posting in full: description text and HTML, structured salary,\n * employment types, benefits, geocoded address, employer rating, applicant\n * count and the original ATS link.\n *\n * Single response, no pagination. An unknown job key is a real 404 that\n * scrape.do BILLS - take `job_id` from a search row.\n *\n * Costs 2 credits.\n */\n async job(\n options: IndeedJobOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/indeed/job\", options);\n }\n\n /**\n * Indeed employer profile: description, industry, HQ, size, revenue, CEO\n * approval, overall and per-category ratings, reported salaries, open roles\n * and locations.\n *\n * Single response, no pagination. An unknown company slug is a real 404\n * that scrape.do BILLS.\n *\n * Costs 2 credits.\n */\n async company(\n options: IndeedCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/indeed/company\", options);\n }\n\n /**\n * Indeed employee reviews with per-category ratings, pros/cons, reviewer\n * job title and location, plus aggregated sentiment and topic / location /\n * job-title breakdowns.\n *\n * Paged with `page`, 20 reviews per page.\n *\n * Costs 2 credits.\n */\n async companyReviews(\n options: IndeedCompanyReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/indeed/company/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Glassdoor is 1 credit flat on all four endpoints.\n//\n// START WITH companies(). company(), reviews() and salaries() all address an\n// employer_id that exists only inside Glassdoor's /Overview/ URLs, and\n// companies() is the only way to get one from a company name.\n//\n// THEN CHAIN ON `url`. company() returns reviews_url and salaries_url; passing\n// those back as `url` halves the upstream work, because addressing reviews or\n// salaries by employer_id costs two upstream fetches (the /Reviews/ and\n// /Salary/ slugs are case-sensitive and have to be read off the profile\n// first). The customer price is 1 credit either way.\n//\n// reviews() IS CAPPED AT THREE REVIEWS per response by Glassdoor's login wall.\n// There is deliberately no `page` param - move the window with `category` and\n// `employment_status`, and read filtered_review_count to see how many match.\n//\n// `category` and `employment_status` are CLOSED enums because Glassdoor\n// ignores an unknown filter value and serves the unfiltered set under a 200.\n//\n// SLOW AND FLAKY: this domain needs a rendered fetch and the pool is degraded.\n// Per-call success is ~87%. Typical wall time is ~3-47s for company, ~75s for\n// reviews and ~41s for salaries, and a call that fails outright can take ~172s\n// before its 502. Raise the client `timeout` before using this namespace.\n\nexport interface GlassdoorCompaniesOptions {\n /** Company name to resolve (1-120 characters). */\n query: string;\n [key: string]: unknown;\n}\n\nexport interface GlassdoorCompanyOptions {\n /**\n * Glassdoor employer id. MUST BE A STRING - a JSON number is rejected.\n * Accepts 1699, E1699 or IE1699. Either this or `url` is required.\n */\n employer_id?: string;\n /**\n * Company name (1-200 characters). COSMETIC ONLY: the profile resolves on\n * employer_id alone, this is ignored entirely when `url` is set, and it does\n * NOT satisfy the employer_id-or-url requirement.\n */\n company?: string;\n /**\n * Any glassdoor.com employer URL (/Overview/, /Reviews/ or /Salary/).\n * Non-glassdoor.com hosts are rejected. Either this or `employer_id` is\n * required.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface GlassdoorReviewsOptions {\n /**\n * Glassdoor employer id as a STRING (1699, E1699 or IE1699). Either this or\n * `url` is required. Addressing by employer_id costs two upstream fetches -\n * pass reviews_url from company() as `url` instead.\n */\n employer_id?: string;\n /** Company name (1-200 characters). Cosmetic; does not satisfy the identifier requirement. */\n company?: string;\n /**\n * Pass back the reviews_url that company() returned to skip the resolve\n * fetch. Either this or `employer_id` is required.\n */\n url?: string;\n /**\n * Restrict to reviews about one axis. Closed set - Glassdoor ignores an\n * unknown value and returns the UNFILTERED set under a 200.\n */\n category?:\n | \"career_development\"\n | \"compensation\"\n | \"culture\"\n | \"diversity_and_inclusion\"\n | \"management\"\n | \"work_life_balance\";\n /**\n * Restrict to reviewers of one employment type. Closed set - an unknown\n * value is silently unfiltered. FREELANCE is absent because it was never\n * confirmed to change the result set.\n */\n employment_status?: \"full_time\" | \"part_time\" | \"contract\" | \"intern\";\n [key: string]: unknown;\n}\n\nexport interface GlassdoorSalariesOptions {\n /**\n * Glassdoor employer id as a STRING (1699, E1699 or IE1699). Either this or\n * `url` is required. Addressing by employer_id costs two upstream fetches -\n * pass salaries_url from company() as `url` instead.\n */\n employer_id?: string;\n /** Company name (1-200 characters). Cosmetic; does not satisfy the identifier requirement. */\n company?: string;\n /**\n * Pass back the salaries_url that company() returned to skip the resolve\n * fetch. Either this or `employer_id` is required.\n */\n url?: string;\n /**\n * Result page, 1-indexed. 10 job titles per page; `page_count` on the\n * response is how many pages exist.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class GlassdoorNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Search Glassdoor for a company by NAME and resolve it to the\n * employer_id every other method needs, ranked by Glassdoor and\n * de-duplicated.\n *\n * company(), reviews() and salaries() all key off an employer_id that exists\n * only inside Glassdoor's /Overview/ URLs, so this lookup is the entry\n * point.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async companies(\n options: GlassdoorCompaniesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/glassdoor/companies\", options);\n }\n\n /**\n * Employer profile: description, mission, industry, sector, HQ, size band,\n * revenue band, stock symbol, year founded, overall and per-category\n * ratings, star distribution, CEO approval, awards, FAQ, the five\n * server-rendered reviews, AND reviews_url / salaries_url.\n *\n * THE CHAINING ENDPOINT: pass reviews_url / salaries_url back as `url` on\n * reviews() and salaries() to halve the upstream fetches. `employer_id` or\n * `url` is required - `company` is cosmetic and does not satisfy it.\n *\n * Costs 1 credit. Single response, no pagination. Typically ~3-47s.\n */\n async company(\n options: GlassdoorCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/glassdoor/company\", options);\n }\n\n /**\n * Full reviews with per-axis scores, pros, cons, advice, job title,\n * location, employment status and employer response - plus complete rating\n * statistics, star distribution, aggregate pro/con highlight terms and\n * per-job-title review counts.\n *\n * HARD CAP OF THREE REVIEW BODIES per response: that is Glassdoor's login\n * wall, not a limit option. There is deliberately NO `page` param. Move the\n * window with `category` and `employment_status` and read\n * filtered_review_count to see how many match; the aggregate statistics are\n * the full-population signal here, not the bodies.\n *\n * `employer_id` or `url` is required. Costs 1 credit. Typically ~75s.\n */\n async reviews(\n options: GlassdoorReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/glassdoor/reviews\", options);\n }\n\n /**\n * Salaries by job title: base-pay and total-pay percentiles P10-P90 with\n * medians called out, sample counts, currency, pay period and last-reported\n * date.\n *\n * These are Glassdoor's ESTIMATES for the title, not individual reported\n * salaries. Paged with `page` at 10 job titles per page; `page_count` on the\n * response is how many pages exist.\n *\n * `employer_id` or `url` is required. Costs 1 credit. Typically ~41s.\n */\n async salaries(\n options: GlassdoorSalariesOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/glassdoor/salaries\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// The Apple App Store is 1 credit flat on all three endpoints - it runs on\n// Apple's official iTunes JSON API, which is the cheapest surface here.\n//\n// SEARCH HAS NO PAGINATION. `limit` (1-200) is the only lever on volume; every\n// offset spelling is silently ignored. Raise the limit, never reach for a page\n// param.\n//\n// app() accepts BOTH a numeric App Store id and a bundle id (auto-detected,\n// identical payload). reviews() is NUMERIC ONLY - the RSS feed has no\n// bundle-id form.\n//\n// `country` decides price, currency, localised title and whether the app is\n// sold there at all. Anything that is not two letters falls back to US, so\n// \"usa\" silently buys a US result set.\n//\n// An id Apple cannot resolve is a BILLED 404: Apple charges for the 200 that\n// carries an empty result list. reviews() cannot 404 at all - an unknown id\n// and a real app with zero reviews return the same empty feed.\n//\n// Mac rows carry NO iPad or Apple TV screenshots, advisories, features,\n// supported devices or Game Center flag - those come back empty rather than\n// absent.\n//\n// The transport's `attribute` param is deliberately not exposed:\n// softwareDeveloper is valid upstream but has no effect, and plain search\n// already matches the developer field.\n\nexport interface AppStoreSearchOptions {\n /**\n * Search term (1-500 characters). Matches app name, keyword OR publisher\n * name - searching a developer returns their catalogue.\n */\n term: string;\n /**\n * Number of apps to return, 1-200 (default 25). THE ONLY LEVER on result\n * volume: there is no pagination and every offset spelling is ignored.\n */\n limit?: number;\n /**\n * Two-letter storefront code (default \"us\"). Decides price, currency,\n * localised title and whether the app is sold there at all. Anything that is\n * not exactly two letters falls back to US.\n */\n country?: string;\n /** Which catalogue to search (default \"software\", i.e. iPhone apps). */\n entity?: \"software\" | \"ipad_software\" | \"mac_software\";\n /**\n * Five-letter locale for the returned text, e.g. \"en_us\". Independent of\n * `country`: the storefront sets the price, this sets the words.\n */\n lang?: string;\n [key: string]: unknown;\n}\n\nexport interface AppStoreAppOptions {\n /**\n * App Store id OR bundle id (notion.id, com.burbn.instagram), auto-detected\n * and returning an identical payload. 1-255 characters matching\n * ^[A-Za-z0-9][A-Za-z0-9._-]*$ - a pasted apps.apple.com URL is rejected\n * with a free 400.\n */\n app_id: string;\n /**\n * Two-letter storefront code (default \"us\"). Decides price, currency,\n * localised title and availability. Anything not exactly two letters falls\n * back to US.\n */\n country?: string;\n [key: string]: unknown;\n}\n\nexport interface AppStoreReviewsOptions {\n /**\n * NUMERIC App Store id only - the reviews RSS feed has no bundle-id form,\n * unlike app().\n */\n app_id: string;\n /**\n * Two-letter storefront code (default \"us\"). Each storefront has its own\n * 500-review ceiling, so a different country is how you read past page 10.\n */\n country?: string;\n /**\n * Result page, 1-10 (default 1), 50 reviews each. HARD STOP AT PAGE 10 -\n * 500 reviews per storefront is Apple's anonymous ceiling.\n */\n page?: number;\n /**\n * Review sort order (default \"most_recent\"). Under \"most_recent\" almost\n * every review is too new to have been voted on and the vote fields come\n * back as ZEROES; \"most_helpful\" returns them densely populated.\n */\n sort?: \"most_recent\" | \"most_helpful\";\n [key: string]: unknown;\n}\n\nexport class AppStoreNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Up to 200 fully-shaped App Store apps - the same 43-field row as app() -\n * which makes this a bulk metadata fetch as well as a search, and a\n * publisher lookup when the term is a developer name.\n *\n * NO PAGINATION. `limit` (1-200, default 25) is the only lever on volume;\n * every offset spelling is silently ignored. Mac rows carry no iPad or Apple\n * TV screenshots, advisories, features, supported devices or Game Center\n * flag.\n *\n * Costs 1 credit.\n */\n async search(\n options: AppStoreSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/appstore/search\", options);\n }\n\n /**\n * Full listing: title, description, developer and seller identity, price and\n * currency, all-time and current-version ratings, version and release notes,\n * genres, content rating and advisories, icons at three sizes, screenshots,\n * download size, minimum OS, languages, supported devices, Game Center and\n * VPP flags.\n *\n * Takes a numeric App Store id or a bundle id interchangeably. An id Apple\n * cannot resolve is a BILLED 404 - Apple charges for the empty result list.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async app(\n options: AppStoreAppOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/appstore/app\", options);\n }\n\n /**\n * A page of reviews: star rating, title, full text, author, and the APP\n * VERSION the review was written against.\n *\n * NUMERIC APP IDS ONLY here. Paged 1-10 at 50 reviews each and hard-stopped\n * at page 10 - 500 reviews per storefront is Apple's anonymous ceiling, so\n * ask a different `country` to reach further. This endpoint CANNOT 404: an\n * unknown id and a real app with zero reviews return the same empty feed.\n * Under sort \"most_recent\" the vote fields are zeroes.\n *\n * Costs 1 credit.\n */\n async reviews(\n options: AppStoreReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/appstore/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Google Play is 2 credits flat on all three endpoints. It sits on the premium\n// per-domain proxy table and is NOT priced like the `google` namespace, which\n// is part of why it is a separate namespace.\n//\n// SEARCH HAS NO PAGINATION - Play serves one shelf of ~30 apps and there is no\n// page or cursor to ask for more.\n//\n// `hl` changes the STOREFRONT, not just the strings: at hl=pt-BR the title,\n// description, install formatting and content rating all move with it. Play\n// silently falls back to English/US on values it does not serve.\n//\n// The reviews `cursor` is opaque, SINGLE-USE, and encodes the sort as well as\n// the position - send it back with the SAME `sort` it came from. A cursor past\n// the last review is a 404, not an empty page.\n//\n// app() already returns the 20 reviews Play server-renders; reviews() is for\n// paging past them or sorting differently. The reviews RPC answering a 200\n// with an empty payload is a BILLED 404 - premium price paid to learn the\n// package has no reviews or does not exist.\n//\n// Games are folded into the apps vertical. Books and films use a different\n// card shape entirely and are not covered.\n\nexport interface GooglePlaySearchOptions {\n /** Search query (1-200 characters). */\n query: string;\n /**\n * Interface language (2-20 characters, default \"en\"). Changes the\n * STOREFRONT, not only the strings - title, description, install formatting\n * and content rating all move with it. Play falls back to English on values\n * it does not serve.\n */\n hl?: string;\n /** Country code (2-10 characters, default \"us\"). */\n gl?: string;\n [key: string]: unknown;\n}\n\nexport interface GooglePlayAppOptions {\n /**\n * Android package name (com.spotify.music) or any play.google.com URL\n * carrying one in its id param. 1-500 characters.\n */\n app_id: string;\n /**\n * Interface language (2-20 characters, default \"en\"). Changes the storefront\n * as well as the strings.\n */\n hl?: string;\n /** Country code (2-10 characters, default \"us\"). */\n gl?: string;\n [key: string]: unknown;\n}\n\nexport interface GooglePlayReviewsOptions {\n /**\n * Android package name or any play.google.com URL carrying one in its id\n * param. 1-500 characters.\n */\n app_id: string;\n /**\n * Review sort order (default \"newest\"). The cursor encodes this value, so\n * changing `sort` mid-pagination invalidates the cursor.\n */\n sort?: \"relevance\" | \"newest\" | \"rating\";\n /**\n * Reviews per page, 1-200 (default 50). Capped at 200 on our side; Play\n * honours more, but a single page that large is megabytes for one call.\n */\n count?: number;\n /**\n * next_cursor from a prior response (1-4000 characters). OPAQUE and\n * SINGLE-USE, and it encodes the sort as well as the position - send it back\n * with the SAME `sort` it came from. A cursor past the last review is a 404,\n * not an empty page.\n */\n cursor?: string;\n /** Interface language (2-20 characters, default \"en\"). */\n hl?: string;\n /** Country code (2-10 characters, default \"us\"). */\n gl?: string;\n [key: string]: unknown;\n}\n\nexport class GooglePlayNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Ranked apps: package name, title, developer, rating, install count, price\n * and IAP range, content rating, icon and screenshots. A branded query\n * returns the hero card as result 1 projected to the same row shape, plus\n * Play's related-query rail.\n *\n * NO PAGINATION - one shelf of ~30 apps, with no page or cursor param.\n * `hl` moves the whole storefront, not just the language of the strings.\n *\n * Costs 2 credits.\n */\n async search(\n options: GooglePlaySearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleplay/search\", options);\n }\n\n /**\n * Full store listing: installs including the REAL count Play publishes but\n * never renders, rating and star histogram, description, developer identity\n * and legal contact, price and IAPs, categories and gameplay tags,\n * screenshots and trailer, version and Android requirement, release and\n * update dates, changelog, full permission tree, Data safety table, the 20\n * server-rendered reviews, and the similar-apps and more-by-developer rails.\n *\n * Those 20 reviews ride along at no extra cost - use reviews() only to page\n * past them or to sort differently.\n *\n * Costs 2 credits. Single response, no pagination.\n */\n async app(\n options: GooglePlayAppOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleplay/app\", options);\n }\n\n /**\n * A page of reviews: star score, full text, author, thumbs-up count,\n * developer reply, and the APP VERSION the reviewer was running.\n *\n * Paged with `cursor` -> next_cursor. The cursor is opaque and SINGLE-USE\n * and encodes the sort as well as the position, so send it back with the\n * same `sort` it came from; a cursor past the last review is a 404, not an\n * empty page. `count` is capped at 200. An empty payload here is a BILLED\n * 404 - the premium price is paid to learn the package has no reviews or\n * does not exist.\n *\n * Costs 2 credits.\n */\n async reviews(\n options: GooglePlayReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleplay/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// G2, the B2B software review site. 5 credits flat on all three endpoints -\n// the only 5-credit platform we serve, because g2.com bills 25 upstream\n// credits per call with neither render nor super asked for.\n//\n// A BOT WALL OR HOLLOW SHELL ARRIVES AS A BILLED 502: the upstream fetch is a\n// real HTTP 200 that was charged in full, so the call is billed for a page we\n// could not parse. Retry policy is deliberately conservative for that reason -\n// do not wrap these calls in an aggressive retry loop of your own.\n//\n// Every filter is a CLOSED ENUM on purpose. G2 silently accepts an unknown\n// sort (answering 200 in some unstated ordering, so the sort never ran) and an\n// unknown filter value MATCHES NOTHING - a bogus company size returns\n// \"Reviews (0)\", which reads as \"this product has no enterprise reviews\".\n//\n// product() carries NO review text: G2 loads review bodies in a separate\n// frame. Call reviews() for text, per-star counts and facet counts.\n\nexport interface G2SearchOptions {\n /** Search term (1-200 characters). Required unless `url` is given. */\n query?: string;\n /** Result page, 1-indexed. 20 per page unless `limit` says otherwise. */\n page?: number;\n /**\n * Results per page (1-100, default 20). Capped at 100 on our side so a\n * single request cannot ask for a multi-megabyte page on a 60s deadline;\n * G2 itself keeps paginating at any size.\n */\n limit?: number;\n /** Result sort order (default \"relevance\"). */\n sort?: \"relevance\" | \"popular\" | \"alphabetical\" | \"rating\";\n /** Products at or above this star rating. */\n rating?: 1 | 2 | 3 | 4 | 5;\n /**\n * Full g2.com/search URL, as an alternative to `query`. The host is checked\n * by the transport.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface G2ProductOptions {\n /**\n * A G2 slug (\"notion\") or the numeric G2 id (\"82623\") AS A STRING - both\n * resolve on the same upstream path. Required unless `url` is given.\n */\n product_id?: string;\n /** Full g2.com product URL, as an alternative to `product_id`. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface G2ReviewsOptions {\n /**\n * A G2 slug (\"notion\") or the numeric G2 id (\"82623\") as a string.\n * Required unless `url` is given.\n */\n product_id?: string;\n /** Full g2.com reviews URL, as an alternative to `product_id`. */\n url?: string;\n /** Result page, 1-indexed. Fixed at 10 reviews per page. */\n page?: number;\n /** Review sort order (default \"relevance\"). */\n sort?: \"relevance\" | \"newest\" | \"most_helpful\" | \"rating_high\" | \"rating_low\";\n /**\n * Star bucket. HALF-STAR-INCLUSIVE: 1 returns 0, 0.5 and 1-star reviews.\n */\n rating?: 1 | 2 | 3 | 4 | 5;\n /** Reviewer's company size: SB <=50, MM 51-1000, Ent >1000. */\n company_size?: \"small_business\" | \"mid_market\" | \"enterprise\";\n /** Reviewer's role. */\n role?:\n | \"user\"\n | \"administrator\"\n | \"executive_sponsor\"\n | \"internal_consultant\"\n | \"consultant\"\n | \"agency\"\n | \"industry_analyst\";\n /** Reviewer's region. */\n region?:\n | \"north_america\"\n | \"europe\"\n | \"asia\"\n | \"latin_america\"\n | \"anz\"\n | \"middle_east\"\n | \"africa\";\n /**\n * Full-text search within the reviews (1-200 characters). Narrows the list\n * AND every facet count.\n */\n query?: string;\n [key: string]: unknown;\n}\n\nexport class G2Namespace {\n constructor(private client: Scavio) {}\n\n /**\n * Ranked B2B software products on G2: star rating, review count, vendor,\n * categories, seller description and logo. Every row carries `product_id`\n * and `slug` to feed product() and reviews().\n *\n * Paged with `page` and `limit` (1-100, default 20). `total_results` is\n * G2's Products-tab headline and is CAPPED AT 10000, so treat a 10000 as a\n * floor rather than a count; `total_by_type` breaks the same query across\n * products, sellers, categories and discussions.\n *\n * Pass `query` or `url`.\n *\n * Costs 5 credits.\n */\n async search(\n options: G2SearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/g2/search\", options);\n }\n\n /**\n * A full G2 software profile: rating with per-star histogram, review count,\n * vendor, description and seller website, pricing editions with parsed\n * amounts, feature groups, categories and breadcrumbs, supported languages,\n * integrations, alternatives, head-to-head comparisons, media, community\n * discussions and G2's AI-derived pros and cons.\n *\n * CARRIES NO REVIEW TEXT. G2 loads review bodies in a separate frame, so\n * this endpoint returns none at all - call reviews() for text.\n *\n * Pass `product_id` (slug or numeric id as a string) or `url`.\n *\n * Costs 5 credits. Single response, no pagination.\n */\n async product(\n options: G2ProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/g2/product\", options);\n }\n\n /**\n * A page of G2 reviews: rating, title, likes and dislikes, problems solved,\n * reviewer job title, industry and company size, validated and incentivized\n * flags - PLUS what the profile page has no form of: exact per-star counts,\n * pros and cons with per-theme counts, and company-size / role / industry /\n * region / category facets with counts.\n *\n * Fixed at 10 reviews per page; advance with `page`. This paginates well\n * past the 10 pages G2's own widget links to.\n *\n * `rating` buckets are HALF-STAR-INCLUSIVE (1 returns 0, 0.5 and 1-star).\n * Every filter is a closed enum because an unrecognised value matches\n * nothing upstream and comes back as an empty, plausible-looking result set.\n *\n * Pass `product_id` or `url`.\n *\n * Costs 5 credits.\n */\n async reviews(\n options: G2ReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/g2/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Capterra, the B2B software review site. 2 credits flat on all three\n// endpoints (a premium per-domain upstream table).\n//\n// SEARCH DOES NOT PAGINATE. Capterra fixes the result set at 20 and ?page=2\n// returns identical rows, so there is deliberately NO page param on search().\n//\n// `slug` behaves differently on the two product-keyed endpoints: it is\n// COSMETIC on product() (/p/186596/Zzzjunk/ returns Notion's profile\n// byte-for-byte) but LOAD-BEARING on reviews(), where it is case-sensitive\n// upstream and a wrong one silently serves PAGE ONE under a billed 200. Pass\n// back the `slug` or `reviews_url` you got from search() or product().\n//\n// `product_id` must be a STRING everywhere - a JSON number is rejected.\n\nexport interface CapterraSearchOptions {\n /**\n * Search term (1-200 characters). Required unless `url` is given: a\n * term-less search serves a fixed popular-products list that has nothing to\n * do with the caller.\n */\n query?: string;\n /**\n * Full capterra.com search URL, as an alternative to `query`. The host is\n * checked by the transport, which also covers capterra.co.uk and\n * capterra.com.br.\n */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface CapterraProductOptions {\n /**\n * The number in /p/186596/Notion/, AS A STRING - a JSON number is rejected.\n * Required unless `url` is given.\n */\n product_id?: string;\n /** Product slug. COSMETIC on this endpoint - any value returns the same profile. */\n slug?: string;\n /** Full capterra.com product URL, as an alternative to `product_id`. */\n url?: string;\n [key: string]: unknown;\n}\n\nexport interface CapterraReviewsOptions {\n /**\n * The number in /p/186596/Notion/, as a string. Required unless `url` is\n * given.\n */\n product_id?: string;\n /**\n * Product slug. LOAD-BEARING here, unlike on product(): it is case-sensitive\n * upstream and a wrong one silently serves PAGE ONE under a billed 200.\n * Pass back the slug from search() or product().\n */\n slug?: string;\n /**\n * Full capterra.com reviews URL. Passing back `reviews_url` from product()\n * is the reliable way to page.\n */\n url?: string;\n /**\n * Result page, 1-100. 25 reviews per page. There is no page past 100\n * whatever the review count says.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class CapterraNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * 20 ranked Capterra software products: name, vendor description, rating,\n * review count, logo and the paid-placement flag. Every row carries\n * `product_id` and `slug` to feed product() and reviews().\n *\n * NO PAGINATION. Capterra fixes the result set at 20 and page 2 returns the\n * identical rows, so there is deliberately no page param - narrow the query\n * instead.\n *\n * Pass `query` or `url`.\n *\n * Costs 2 credits.\n */\n async search(\n options: CapterraSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/capterra/search\", options);\n }\n\n /**\n * A full Capterra profile: rating with per-star histogram and the four\n * scored criteria, likelihood to recommend, review sentiment and topics, the\n * complete pricing table with every plan and its features, every rated\n * feature, every integration, AI-derived pros and cons with the quoted\n * review, FAQs, screenshots, badges and awards, competitor comparisons and\n * alternatives, and the buyer profile by company size / industry / job\n * function - PLUS the 25 most recent reviews, which ride along at no extra\n * cost.\n *\n * `vendor` IS ALWAYS NULL here: Capterra does not publish it as structured\n * data on the product page. The reviews name the vendor per review.\n *\n * Pass `product_id` (a string) or `url`. `slug` is cosmetic on this\n * endpoint.\n *\n * Costs 2 credits. Single response, no pagination.\n */\n async product(\n options: CapterraProductOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/capterra/product\", options);\n }\n\n /**\n * A page of Capterra reviews: overall score plus five per-criterion scores,\n * title, pros, cons, advice, usage duration, incentivized flag, alternatives\n * considered and what the reviewer switched from, reviewer job title /\n * industry / company size, and the vendor response - plus a richer\n * competitor list than the profile carries, each alternative with its own\n * rating histogram and starting price.\n *\n * 25 reviews per page, CAPPED AT PAGE 100. Past it Capterra answers 200 with\n * PAGE ONE and the page quietly dropped from the canonical, so nothing\n * signals the cap but repeated rows. Page 1 is already inside product(), so\n * use this to page past it.\n *\n * Pass `product_id` or `url`. `slug` is load-bearing here and case-sensitive\n * upstream - a wrong one silently serves page one.\n *\n * Costs 2 credits.\n */\n async reviews(\n options: CapterraReviewsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/capterra/reviews\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// SEC EDGAR is 1 credit flat on all six endpoints - it sits on the SEC's own\n// free JSON API.\n//\n// LOOKUP FIRST. Callers hold a ticker (AAPL); EDGAR is keyed by CIK\n// (0000320193). Call lookup() to resolve one before anything else. Both the\n// `cik` and `ticker` fields accept either spelling, which softens the problem\n// without removing it.\n//\n// XBRL concept tags are CASE-SENSITIVE: \"netincomeloss\" is a 404 upstream,\n// not a match. Call facts() to list what a filer actually reports, then\n// concept() to pull that tag's history.\n//\n// `form` matching differs by endpoint on purpose: on filings() it matches the\n// form AND its root form, so \"10-K\" also returns 10-K/A amendments; on\n// concept() it is an EXACT match, so \"10-K\" EXCLUDES 10-K/A.\n//\n// EDGAR's \"recent\" filings block is not a fixed window - a decade for a quiet\n// filer, about a year for a prolific one. filings({ include_history: true })\n// reaches back further and is the one call that can buy up to 10 upstream\n// fetches while still costing ONE credit.\n//\n// Full-text search coverage STARTS IN 2001, and `page` is capped at 100\n// (100 documents per page) because the index refuses a result window past\n// 10,000.\n\nexport interface SECLookupOptions {\n /** Ticker, company name, or a fragment (1-200 characters). */\n query: string;\n /**\n * How many matches to return, 1-100 (default 10). This SIZES the response,\n * it is not a page param - there is no pagination here.\n */\n limit?: number;\n /**\n * Restrict to one listing exchange. Matched case-insensitively. Filers\n * listed with NO exchange are excluded by ANY value.\n */\n exchange?: \"NASDAQ\" | \"NYSE\" | \"OTC\" | \"CBOE\";\n [key: string]: unknown;\n}\n\nexport interface SECCompanyOptions {\n /**\n * CIK in any spelling: 320193, 0000320193 or CIK0000320193. A ticker is\n * accepted here too. Either `cik` or `ticker` is required.\n */\n cik?: string;\n /**\n * Ticker, dotted or dashed (BRK.B / BRK-B). WINS over `cik` when both are\n * given. Either `cik` or `ticker` is required.\n */\n ticker?: string;\n [key: string]: unknown;\n}\n\nexport interface SECFilingsOptions {\n /**\n * CIK in any spelling; a ticker is accepted here too. Either `cik` or\n * `ticker` is required.\n */\n cik?: string;\n /**\n * Ticker, dotted or dashed. WINS over `cik` when both are given. Either\n * `cik` or `ticker` is required.\n */\n ticker?: string;\n /**\n * Form filter: \"10-K\", [\"10-K\", \"10-Q\"] or \"10-K,8-K\". Matched against the\n * form AND its root form, so \"10-K\" also returns 10-K/A amendments - ask\n * for \"10-K/A\" to get only amendments. Up to 25 forms.\n */\n form?: string | string[];\n /** Earliest filing date, YYYY-MM-DD. */\n date_from?: string;\n /** Latest filing date, YYYY-MM-DD. */\n date_to?: string;\n /** Result page, 1-indexed. */\n page?: number;\n /** Filings per page, 1-500 (default 50). */\n limit?: number;\n /**\n * Reach past EDGAR's \"recent\" block into up to 10 archived shards. Still\n * ONE credit. `history_truncated` in the response flags a filer that had\n * more shards than the cap.\n */\n include_history?: boolean;\n [key: string]: unknown;\n}\n\nexport interface SECConceptOptions {\n /**\n * CIK in any spelling; a ticker is accepted here too. Either `cik` or\n * `ticker` is required.\n */\n cik?: string;\n /**\n * Ticker, dotted or dashed. WINS over `cik` when both are given. Either\n * `cik` or `ticker` is required.\n */\n ticker?: string;\n /**\n * XBRL tag, e.g. \"NetIncomeLoss\" (1-120 characters, letters then\n * alphanumerics). CASE-SENSITIVE - \"netincomeloss\" is a 404 upstream, not a\n * match. Use facts() to discover the tags a filer actually reports.\n */\n concept: string;\n /** Taxonomy: us-gaap, dei, ifrs-full, srt (default \"us-gaap\"). */\n taxonomy?: string;\n /** Unit filter, e.g. \"USD\" vs \"USD/shares\". */\n unit?: string;\n /**\n * Form filter. EXACT match here, so \"10-K\" EXCLUDES 10-K/A - the opposite\n * of filings().\n */\n form?: string;\n /**\n * How many values to return, 1-2000 (default 250). This SIZES the response,\n * it is not a page param.\n */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface SECFactsOptions {\n /**\n * CIK in any spelling; a ticker is accepted here too. Either `cik` or\n * `ticker` is required.\n */\n cik?: string;\n /**\n * Ticker, dotted or dashed. WINS over `cik` when both are given. Either\n * `cik` or `ticker` is required.\n */\n ticker?: string;\n /** Restrict to one taxonomy, e.g. \"us-gaap\" or \"dei\". */\n taxonomy?: string;\n /**\n * Case-insensitive substring matched against the tag name and its label\n * (1-200 characters).\n */\n query?: string;\n /**\n * How many concepts to return, 1-2000 (default 250). This SIZES the\n * response, it is not a page param.\n */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface SECSearchOptions {\n /**\n * Full-text query (1-500 characters). A quoted phrase is an exact match;\n * bare words are a bag of terms. OPTIONAL - a cik, ticker, form or date\n * filter on its own is a valid search.\n */\n query?: string;\n /** One CIK or up to 25. Tickers are accepted here too. */\n cik?: string | string[];\n /** One ticker or up to 25. */\n ticker?: string | string[];\n /** One form or up to 25, e.g. \"8-K\" or [\"10-K\", \"10-Q\"]. */\n form?: string | string[];\n /** Earliest filing date, YYYY-MM-DD. Coverage starts in 2001. */\n date_from?: string;\n /** Latest filing date, YYYY-MM-DD. */\n date_to?: string;\n /**\n * EDGAR's own two-character location codes - \"CA\", \"NY\", and alphanumeric\n * codes for foreign jurisdictions. One or up to 25.\n */\n location?: string | string[];\n /** Result order (default \"relevance\"). */\n sort?: \"relevance\" | \"newest\" | \"oldest\";\n /**\n * Result page, 1-indexed, CAPPED AT 100. 100 documents per page - the index\n * refuses a result window past 10,000.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class SECNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Resolves a company name or ticker to the CIK every other SEC\n * EDGAR endpoint is keyed by: matching filers with symbol, listing\n * exchange, and ready-made submissions / company-facts / EDGAR URLs, tiered\n * by match quality (each row carries its tier as `match`).\n *\n * `limit` sizes the response; there is no pagination. `exchange` is a\n * closed set matched case-insensitively, and filers listed with no exchange\n * are excluded by ANY value.\n *\n * Costs 1 credit.\n */\n async lookup(\n options: SECLookupOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/lookup\", options);\n }\n\n /**\n * Filer profile: legal and former names, SIC industry, filer category, EIN,\n * LEI, state of incorporation, fiscal year end, business and mailing\n * addresses, every ticker with its exchange, which forms it files and how\n * often, plus a preview of its 10 most recent filings.\n *\n * Either `cik` or `ticker` is required; `ticker` wins when both are given.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async company(\n options: SECCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/company\", options);\n }\n\n /**\n * A page of one filer's filings: accession number, form and root form,\n * filing and period dates, 8-K item codes, and direct links to the primary\n * document, filing index and attachment directory.\n *\n * Either `cik` or `ticker` is required. Paged with `page` + `limit`.\n * `form` matches the form AND its root form, so \"10-K\" also returns 10-K/A.\n * EDGAR's \"recent\" block is not a fixed window - a decade for a quiet\n * filer, about a year for a prolific one; `include_history` reaches back\n * through up to 10 archived shards and sets `history_truncated` when the\n * filer had more.\n *\n * Costs 1 credit - including with `include_history`, which is the one call\n * that can buy more than one upstream fetch.\n */\n async filings(\n options: SECFilingsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/filings\", options);\n }\n\n /**\n * Every value a filer reported for one XBRL concept, newest period first,\n * with the form and filing each number came from. Restatements are KEPT,\n * not collapsed; `latest` disambiguates a quarter from its year-to-date\n * twin using the SEC's comparability flag.\n *\n * Either `cik` or `ticker` is required. The `concept` tag is CASE-SENSITIVE\n * - \"netincomeloss\" is a 404 upstream, not a match; call facts() to find\n * the real tag. `form` is an EXACT match here, so \"10-K\" excludes 10-K/A.\n * `limit` sizes the response; there is no pagination.\n *\n * Costs 1 credit.\n */\n async concept(\n options: SECConceptOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/concept\", options);\n }\n\n /**\n * The index of every XBRL concept a filer reports - tag, label,\n * description, units and most recent value - across us-gaap, dei and any\n * other taxonomy it uses. This is how you find what to ask concept() for.\n *\n * Either `cik` or `ticker` is required. `limit` sizes the response; there\n * is no pagination.\n *\n * Costs 1 credit.\n */\n async facts(\n options: SECFactsOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/facts\", options);\n }\n\n /**\n * EDGAR full-text search: each hit is the matching DOCUMENT with its URL,\n * form, filing date and filer identity, plus facets breaking the whole\n * result set down by company, form, industry and state.\n *\n * Coverage STARTS IN 2001 - nothing earlier is indexed. Accepts NO query at\n * all: a cik, ticker, form or date filter on its own is a valid search.\n * Paged with `page`, capped at 100 (100 documents per page) because the\n * index refuses a result window past 10,000.\n *\n * Costs 1 credit.\n */\n async search(\n options: SECSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/sec/search\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Companies House (UK) is 1 credit flat on all four endpoints - it sits on\n// the official UK register.\n//\n// SEARCH FIRST. Everything else is keyed by `company_number`, so search() is\n// how you get one. Search matches CURRENT AND FORMER names.\n//\n// `company_number` is deliberately loose: the register 404s on /company/445790\n// and /company/sc090312 for companies that exist, so the number is zero-padded\n// and upper-cased for you. Registry prefixes supported: SC (Scotland),\n// NI (Northern Ireland), OC/SO/NC (LLPs), FC (overseas), BR (UK\n// establishment), CE (charitable incorporated organisation).\n//\n// Paging differs by endpoint. search() is CAPPED AT PAGE 50: the register\n// serves a 1000-result WINDOW per term whatever hit count it prints - it\n// claims 10,000 for a broad term, then answers page 51 with HTTP 416.\n// officers() and filingHistory() have NO upper page bound; past the last page\n// the register answers an ordinary 200 with an empty list, indistinguishable\n// from a company with no officers or no filings.\n\nexport interface CompaniesHouseSearchOptions {\n /** Company name or fragment (1-200 characters, non-blank). */\n query: string;\n /**\n * Result page, 1-indexed (default 1). 20 results per page, CAPPED AT 50 -\n * the register only serves the first 1000 matches for a term.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport interface CompaniesHouseCompanyOptions {\n /**\n * UK company number, 1-20 characters, e.g. \"00445790\" or \"SC090312\". Loose\n * on purpose - it is zero-padded and upper-cased for you, so \"445790\" and\n * \"sc090312\" both work. Prefixes: SC, NI, OC/SO/NC, FC, BR, CE.\n */\n company_number: string;\n [key: string]: unknown;\n}\n\nexport interface CompaniesHouseOfficersOptions {\n /**\n * UK company number, zero-padded and upper-cased for you.\n */\n company_number: string;\n /**\n * Result page, 1-indexed (default 1). 35 officers per page, no upper bound\n * - past the last page the register answers 200 with an empty list.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport interface CompaniesHouseFilingHistoryOptions {\n /**\n * UK company number, zero-padded and upper-cased for you.\n */\n company_number: string;\n /**\n * Result page, 1-indexed (default 1). No upper bound - past the last page\n * the register answers 200 with an empty list.\n */\n page?: number;\n [key: string]: unknown;\n}\n\nexport class CompaniesHouseNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Searches the UK register by name and returns the\n * `company_number` every other endpoint is keyed by, plus name, status,\n * incorporation or dissolution date, registered office address and matched\n * former names.\n *\n * Matches CURRENT AND FORMER names. Paged with `page`, 20 results per page,\n * CAPPED AT PAGE 50 - the register serves a 1000-result window per term\n * whatever hit count it prints, and answers page 51 with HTTP 416.\n *\n * Costs 1 credit.\n */\n async search(\n options: CompaniesHouseSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/companieshouse/search\", options);\n }\n\n /**\n * Full register entry: status, type, incorporation and dissolution dates,\n * registered office, SIC codes, previous names, accounts and\n * confirmation-statement due dates with overdue flags, and whether it has\n * charges, insolvency history, officers or UK establishments. FC companies\n * return home registry / legal form / governing law, BR returns the parent,\n * CE returns the charity number.\n *\n * `company_number` is zero-padded and upper-cased for you, so a number off\n * a letterhead or out of a spreadsheet that ate its leading zeros still\n * resolves.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async company(\n options: CompaniesHouseCompanyOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/companieshouse/company\", options);\n }\n\n /**\n * Officers current and resigned: name, role, appointment and resignation\n * dates, correspondence address, nationality, country of residence,\n * month-and-year date of birth, and identity-verification status.\n *\n * Paged with `page`, 35 officers per page, NO upper bound - past the last\n * page the register answers an ordinary 200 with an empty list, identical\n * to a company with no officers.\n *\n * `officers_count` is EVERY appointment ever made and `resignations_count`\n * how many ended, so the active count is the difference. There is no\n * server-side active/resigned filter - filter on each officer's `status` in\n * the response.\n *\n * Costs 1 credit.\n */\n async officers(\n options: CompaniesHouseOfficersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/companieshouse/officers\", options);\n }\n\n /**\n * Filings, most recent first: date, filing type code (AA, CS01, SH03),\n * description, register annotations and child documents, and a link to the\n * filed PDF with its page count.\n *\n * A filing the register has not finished processing carries a\n * `processing_note` instead of a document.\n *\n * Paged with `page`, NO upper bound - past the last page it is an ordinary\n * 200 with an empty list.\n *\n * Costs 1 credit.\n */\n async filingHistory(\n options: CompaniesHouseFilingHistoryOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/companieshouse/filing-history\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Google Ads Transparency Center. 1 credit flat on all three endpoints.\n//\n// START WITH advertisers(). It is the lookup that turns a brand name or a\n// domain into the advertiser_id that search() and creative() are keyed by.\n//\n// IMPRESSIONS AND REACH ARE EEA-ONLY. They are DSA-compelled, so Google\n// publishes them only where the law requires: impressions_min, impressions_max\n// and first_shown come back NULL on US creatives. That is not a bug and not a\n// gap in the parse - point your examples at an EEA region.\n//\n// The three format sets are DISJOINT: an advertiser's text, image and video\n// ads share no creatives, so a format filter is a partition, not a narrowing.\n//\n// Totals are RANGES, never exact: an advertiser's headline ad count is\n// total_ads_min / total_ads_max, and a creative's impression bucket can carry\n// a lower bound, an upper bound, or one alone.\n\nexport interface GoogleAdsAdvertisersOptions {\n /** Brand name or domain to resolve (1-200 characters). */\n query: string;\n /**\n * ISO alpha-2 country (US, GB, DE) or a Google geo criteria id as a string.\n * DEFAULTS TO THE UNITED STATES, not worldwide - the lookup runs against one\n * country's index at a time, so an advertiser who runs no US ads comes back as\n * an empty list. Set it to a country the advertiser actually advertises in.\n */\n region?: string;\n /**\n * Rows per arm (1-20, default 10). Advertisers and domains are capped\n * SEPARATELY, so a name query can return up to twice this many rows.\n */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface GoogleAdsSearchOptions {\n /**\n * Bare host, www host or full URL; reduced to the registrable host. THE ONLY\n * WAY to get the `domain` field back on each row. Required unless\n * `advertiser_id` is given.\n */\n domain?: string;\n /**\n * Google advertiser id, e.g. \"AR16735076323512287233\". The shape is checked\n * before any request is made, so a typo costs nothing. Required unless\n * `domain` is given.\n */\n advertiser_id?: string;\n /**\n * ISO alpha-2 country (US, GB, DE) or a Google geo criteria id as a string.\n * Scopes the deep links on every row - the same advertiser can share ZERO\n * creatives between two countries. Default: worldwide.\n */\n region?: string;\n /** Creative format. The three sets are DISJOINT. Default: all formats. */\n format?: \"text\" | \"image\" | \"video\";\n /** Google surface the ad ran on. Default: all surfaces. */\n platform?: \"play\" | \"maps\" | \"search\" | \"shopping\" | \"youtube\";\n /** Ad topic (default \"all\"). */\n topic?: \"all\" | \"political\";\n /**\n * Rows per page (1-100, default 40). 100 is a HARD UPSTREAM CEILING, not our\n * policy: Google answers a larger request with ZERO rows rather than an\n * error.\n */\n limit?: number;\n /**\n * `next_cursor` from the previous response (1-4000 characters). Re-send the\n * SAME filters alongside it. Null once the advertiser is exhausted.\n */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface GoogleAdsCreativeOptions {\n /** Google advertiser id, e.g. \"AR16735076323512287233\". */\n advertiser_id: string;\n /**\n * Creative id. MUST belong to the `advertiser_id` sent with it - the lookup\n * is keyed by the pair and a mismatch is a 404.\n */\n creative_id: string;\n [key: string]: unknown;\n}\n\nexport class GoogleAdsNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * START HERE. Resolves a brand name or a domain to the `advertiser_id` that\n * search() and creative() are keyed by.\n *\n * Returns two row kinds in one list: `advertiser` rows carry the id, the\n * verified name, the verification country and the total ad count AS A RANGE\n * (total_ads_min / total_ads_max - Google never publishes an exact figure);\n * `domain` rows carry a website. A name query returns both kinds, a\n * domain-shaped query returns domains only.\n *\n * NO PAGINATION - this is an autocomplete, roughly 20 rows per arm, and\n * `limit` caps each arm separately.\n *\n * Costs 1 credit.\n */\n async advertisers(\n options: GoogleAdsAdvertisersOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleads/advertisers\", options);\n }\n\n /**\n * Every ad Google is running for one advertiser: the creative (archived\n * image, rich-media bundle, Google's renderer link, dimensions), advertiser\n * id and name, format, first and last seen dates, days actually run, plus\n * total_ads_min / total_ads_max.\n *\n * Cursor-paginated: read `next_cursor` off the response and send it back as\n * `cursor` WITH THE SAME FILTERS, up to 100 rows per page. `next_cursor` is\n * null once exhausted. A `limit` above 100 is not an error - Google answers\n * it with ZERO rows.\n *\n * The three `format` sets are disjoint, and `domain` is dropped from every\n * row when the query is by `advertiser_id`, so query by domain if you need\n * that field. The headline total is a RANGE, never an exact count.\n *\n * Pass `domain` or `advertiser_id`.\n *\n * Costs 1 credit per page.\n */\n async search(\n options: GoogleAdsSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleads/search\", options);\n }\n\n /**\n * One creative in full, and the ONLY endpoint carrying its history: every\n * size variation of the asset, the impression bucket, the per-region\n * breakdown with first and last shown dates and a per-surface impression\n * split inside each region, the format, Google's category label, and the\n * funder disclosure on political ads.\n *\n * IMPRESSIONS AND REACH ARE EEA-ONLY: impressions_min, impressions_max and\n * first_shown are NULL on US creatives because Google publishes reach only\n * where the DSA compels it. A bucket row can carry a lower bound, an upper\n * bound, or one alone.\n *\n * Keyed by the `advertiser_id` + `creative_id` PAIR - a mismatched pair is a\n * 404, not an empty response.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async creative(\n options: GoogleAdsCreativeOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/googleads/creative\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Meta Ad Library (Facebook and Instagram ads). 1 credit flat on all three\n// endpoints.\n//\n// THE PATHS ARE /api/v1/meta-ads/* - HYPHENATED. The route key and namespace\n// are metaAds, but the URL segment is meta-ads. Never derive one from the\n// other.\n//\n// FULL CURSOR PAGINATION on search() and advertiser(): page 1 is 30 ads, then\n// 10 per page. Walk `has_next_page` to scrape a whole query or a whole\n// advertiser. The cursor is an opaque self-contained blob, so paging is\n// stateless - and THE OTHER FILTERS ARE IGNORED when a cursor is present,\n// because the cursor already carries them. Each page is another credit, so\n// depth costs roughly 10 ads per credit past the first 30.\n//\n// Spend, reach, impressions and the paid-for-by disclosure are NULL on\n// COMMERCIAL ads. Only political/issue ads carry them - set\n// ad_type: \"political_and_issue_ads\" to surface them. Expected, not a bug.\n//\n// Logged-out public data only: nothing here touches a login or the\n// token-gated graph.facebook.com/ads_archive API.\n\nexport interface MetaAdsSearchOptions {\n /** Search term (1-200 characters). */\n query: string;\n /** Two-letter country code (default \"US\"). */\n country?: string;\n /** Whether to include ads that have stopped running (default \"all\"). */\n active_status?: \"all\" | \"active\" | \"inactive\";\n /**\n * Ad category (default \"all\"). \"political_and_issue_ads\" is the only way to\n * get spend, reach, impressions and the paid-for-by disclosure back.\n */\n ad_type?: \"all\" | \"political_and_issue_ads\";\n /** Creative media filter. Default: no media filter. */\n media_type?: \"all\" | \"image\" | \"video\" | \"meme\" | \"image_and_meme\" | \"none\";\n /** How the query terms are matched (default \"keyword_unordered\"). */\n search_type?: \"keyword_unordered\" | \"keyword_exact_phrase\";\n /**\n * `next_cursor` from the previous response. Page 1 is 30 ads, then 10 per\n * page. EVERY OTHER FILTER IS IGNORED when this is present - the cursor\n * already carries them.\n */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface MetaAdsAdvertiserOptions {\n /** The advertiser's numeric Facebook Page id (3-25 digits, as a string). */\n page_id: string;\n /** Two-letter country code (default \"US\"). */\n country?: string;\n /** Whether to include ads that have stopped running (default \"all\"). */\n active_status?: \"all\" | \"active\" | \"inactive\";\n /**\n * Ad category (default \"all\"). \"political_and_issue_ads\" is the only way to\n * get spend, reach, impressions and the paid-for-by disclosure back.\n */\n ad_type?: \"all\" | \"political_and_issue_ads\";\n /** Creative media filter. Default: no media filter. */\n media_type?: \"all\" | \"image\" | \"video\" | \"meme\" | \"image_and_meme\" | \"none\";\n /**\n * `next_cursor` from the previous response. Page 1 is 30 ads, then 10 per\n * page. EVERY OTHER FILTER IS IGNORED when this is present.\n */\n cursor?: string;\n [key: string]: unknown;\n}\n\nexport interface MetaAdsAdOptions {\n /** The ad's archive id (3-25 digits, as a string). */\n ad_archive_id: string;\n [key: string]: unknown;\n}\n\nexport class MetaAdsNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search the Meta Ad Library. Page 1 returns 30 ads with the full creative:\n * page name, ad copy, headline, CTA, images and videos, the platforms each\n * ran on, and run dates - plus `total_results`, `total_is_capped`,\n * `has_next_page` and `next_cursor`.\n *\n * Cursor-paginated the whole way down: 30 ads on page 1, then 10 per page.\n * Walk `has_next_page` to pull an entire query. THE OTHER FILTERS ARE\n * IGNORED once `cursor` is set, because the cursor carries them itself.\n *\n * `total_results` CAPS AT 50000 with `total_is_capped: true` - Meta only\n * reports \">50,000\", so never present it as an exact count. Spend, reach,\n * impressions and the paid-for-by disclosure are null unless\n * `ad_type` is \"political_and_issue_ads\".\n *\n * Costs 1 credit PER PAGE, so depth costs roughly 10 ads per credit past the\n * first 30.\n */\n async search(\n options: MetaAdsSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/meta-ads/search\", options);\n }\n\n /**\n * Every ad a Facebook Page is running, addressed by its numeric page id.\n * Page 1 returns 30 ads with the same creative detail as search(), then 10\n * per page off `next_cursor`; walk `has_next_page` to pull the advertiser's\n * whole library.\n *\n * The other filters are ignored once `cursor` is set. Spend, reach,\n * impressions and the paid-for-by disclosure are null on commercial ads -\n * only political/issue ads carry them.\n *\n * Costs 1 credit per page.\n */\n async advertiser(\n options: MetaAdsAdvertiserOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/meta-ads/advertiser\", options);\n }\n\n /**\n * One ad in full by archive id: creative, advertiser, run dates, platforms\n * and any political disclosure.\n *\n * Spend, reach and impressions are null unless the ad is a political/issue\n * ad.\n *\n * Costs 1 credit. Single response, no pagination.\n */\n async ad(\n options: MetaAdsAdOptions,\n ): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/meta-ads/ad\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Costco: 13 endpoints, all POST /api/v1/costco/<method>.\n//\n// country is \"us\" (costco.com, default) or \"ca\" (costco.ca) everywhere except\n// coupons (US only). search, product and warehouses also take the\n// international sites (uk, au, mx, jp, kr, tw), which support keyword, sort and\n// paging only - no warehouse prices and no gas.\n//\n// Warehouse numbers (e.g. \"1062\") come from warehouses(). Passing one as\n// warehouse_id on search, category or deals adds that warehouse's in-store\n// price, stock status and price code to every result.\n//\n// Most endpoints cost 1 credit. The multi-warehouse ones scale with the body:\n// prices (2 credits at 10 warehouses), availability (1 per 5 warehouses),\n// warehouses (2 with country \"ca\") and gas (2 by location on ca; by\n// warehouse_ids, 1 per 5 on us and 2 per warehouse on ca).\n\n/** costco.com (\"us\", default) or costco.ca (\"ca\"). */\nexport type CostcoNaCountry = \"us\" | \"ca\";\n\n/**\n * Costco site. \"us\" (default) and \"ca\" support every filter; the other six\n * support keyword, sort and paging only.\n */\nexport type CostcoCountry = CostcoNaCountry | \"uk\" | \"au\" | \"mx\" | \"jp\" | \"kr\" | \"tw\";\n\nexport type CostcoSortBy = \"best_match\" | \"price_low\" | \"price_high\" | \"top_rated\" | \"newest\";\n\nexport type CostcoDealType =\n | \"new\"\n | \"while_supplies_last\"\n | \"treasure_hunt\"\n | \"member_favorites\"\n | \"online_only\"\n | \"on_sale\";\n\nexport type CostcoPriceCode = \"clearance\" | \"manager_markdown\" | \"special_buy\";\n\n/** Filters shared by search, category and deals (us and ca). */\nexport interface CostcoListingFilters {\n /**\n * Costco warehouse number (e.g. \"1062\"). Adds that warehouse's in-store\n * price, stock status and price code to every result; omit for online\n * prices only.\n */\n warehouse_id?: string;\n /** Result order (default \"best_match\"). Costco broadens matching under any other sort. */\n sort_by?: CostcoSortBy;\n /** Brand names to keep, up to 20 (e.g. [\"Kirkland Signature\"]). */\n brands?: string[];\n /** Minimum online price, inclusive. */\n min_price?: number;\n /** Maximum online price, inclusive. */\n max_price?: number;\n /** Minimum average star rating (1-5). */\n min_rating?: number;\n /** Only items with an active discount. */\n on_sale?: boolean;\n /** Hide out-of-stock items. */\n in_stock?: boolean;\n /** Only items sold and in stock at warehouse_id (requires warehouse_id). */\n in_warehouse?: boolean;\n /** Results page, 1-based (1-500). */\n page?: number;\n /** Results per page (1-120, default 24). */\n page_size?: number;\n}\n\nexport interface CostcoSearchOptions extends CostcoListingFilters {\n /** Keywords, or a Costco item number (1-200 characters). */\n query: string;\n country?: CostcoCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoCategoryOptions extends CostcoListingFilters {\n /** Category slug from categories() (e.g. \"televisions\"), or a costco.com category URL. */\n category: string;\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoCategoriesOptions {\n /**\n * Numeric Costco category id (e.g. \"30001\"). Omit for the top-level\n * departments; pass one for its full subcategory tree.\n */\n category_id?: string;\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoProductOptions {\n /** Costco item number or product id, or a costco.com product URL. Pass this or item_ids. */\n item_id?: string;\n /** Up to 20 ids in one call (us and ca only). */\n item_ids?: string[];\n country?: CostcoCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoPricesOptions {\n /** Costco item number or product id. Pass this or item_ids. */\n item_id?: string;\n /** Up to 20 ids in one call. */\n item_ids?: string[];\n /**\n * Warehouses to price (1-10, e.g. [\"1062\", \"1107\"]). The online price is\n * always included.\n */\n warehouse_ids: string[];\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoAvailabilityOptions {\n /** Costco item number or product id, or a costco.com product URL. */\n item_number: string;\n /** Warehouses to check (1-10). 1 credit per 5 warehouses. */\n warehouse_ids: string[];\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoReviewsOptions {\n /** Costco product id (the product_id field from search or product). */\n product_id: string;\n /** Review order (default \"newest\"). */\n sort_by?: \"newest\" | \"oldest\" | \"highest_rating\" | \"lowest_rating\" | \"most_helpful\";\n /** Only reviews with this star rating (1-5). */\n rating?: number;\n /** Results page, 1-based (1-500). */\n page?: number;\n /** Reviews per page (1-100, default 25). */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface CostcoWarehousesOptions {\n /** US zip code. Pass zip, or latitude and longitude. */\n zip?: string;\n latitude?: number;\n longitude?: number;\n country?: CostcoCountry;\n /** Nearest warehouses to return (1-50, default 10). */\n limit?: number;\n [key: string]: unknown;\n}\n\nexport interface CostcoGasOptions {\n /** US zip code. Pass zip, latitude and longitude, or warehouse_ids. */\n zip?: string;\n latitude?: number;\n longitude?: number;\n /** Specific warehouses instead of a location (1-10). */\n warehouse_ids?: string[];\n country?: CostcoNaCountry;\n /** Nearest stations to return (1-50). */\n limit?: number;\n [key: string]: unknown;\n}\n\n/** coupons takes no parameters. */\nexport interface CostcoCouponsOptions {\n [key: string]: unknown;\n}\n\nexport interface CostcoDealsOptions extends CostcoListingFilters {\n /** Deal feed. */\n type: CostcoDealType;\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoClearanceOptions {\n /** Costco warehouse number to scan, from warehouses() (e.g. \"1062\"). */\n warehouse_id: string;\n /** Keywords to scan. Pass query or category. */\n query?: string;\n /** Category slug to scan instead of a query. */\n category?: string;\n /** Result pages of 120 to scan (1-5, default 3). */\n pages?: number;\n /**\n * Markdown codes to keep. Default clearance (.97) and manager_markdown\n * (.00/.88); add special_buy for .49/.79/.89 endings, which are common on\n * regular grocery prices.\n */\n price_codes?: CostcoPriceCode[];\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport interface CostcoAutocompleteOptions {\n /** Partial search text (1-100 characters). */\n query: string;\n country?: CostcoNaCountry;\n [key: string]: unknown;\n}\n\nexport class CostcoNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Costco by keyword or item number: online price and original price,\n * ratings, member-only and stock flags, promotions and facets. Pass\n * `warehouse_id` to add that warehouse's in-store price and stock to every\n * result.\n *\n * Costs 1 credit.\n */\n async search(options: CostcoSearchOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/search\", options);\n }\n\n /**\n * Products in a Costco category, with the same sort, filters and\n * per-warehouse pricing as search().\n *\n * Costs 1 credit.\n */\n async category(options: CostcoCategoryOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/category\", options);\n }\n\n /**\n * The Costco department list, or the full subcategory tree under one\n * department when `category_id` is set.\n *\n * Costs 1 credit.\n */\n async categories(options: CostcoCategoriesOptions = {}): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/categories\", options);\n }\n\n /**\n * Full details for up to 20 items: description, features, specifications,\n * variants, member-only and purchase limits, delivery fee, and promotions\n * with start and end dates. Pass `item_id` or `item_ids`.\n *\n * Costs 1 credit.\n */\n async product(options: CostcoProductOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/product\", options);\n }\n\n /**\n * Online price versus in-warehouse price for up to 20 items across up to 10\n * warehouses, with each location's discount, final price, promotion dates\n * and price code.\n *\n * Costs 1 credit for up to 9 warehouses and 2 credits for 10.\n */\n async prices(options: CostcoPricesOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/prices\", options);\n }\n\n /**\n * In-warehouse stock status for one item at up to 10 warehouses, plus\n * pickup and same-day delivery availability. A status, never a quantity.\n *\n * Costs 1 credit per 5 warehouses.\n */\n async availability(options: CostcoAvailabilityOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/availability\", options);\n }\n\n /**\n * Customer reviews for a Costco product with the rating distribution and\n * recommend count; sort, star filter and up to 100 reviews per page.\n *\n * Costs 1 credit.\n */\n async reviews(options: CostcoReviewsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/reviews\", options);\n }\n\n /**\n * Costco warehouses near a US zip code or coordinates, nearest first:\n * warehouse_id, address, hours, departments, services, and gas station hours\n * and prices.\n *\n * Costs 1 credit, or 2 with country \"ca\".\n */\n async warehouses(options: CostcoWarehousesOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/warehouses\", options);\n }\n\n /**\n * Current regular, premium and diesel prices at Costco gas stations near a\n * location, or at specific warehouses.\n *\n * Costs 1 credit by location (2 with country \"ca\"); by `warehouse_ids`,\n * 1 credit per 5 warehouses on us and 2 credits per warehouse on ca.\n */\n async gas(options: CostcoGasOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/gas\", options);\n }\n\n /**\n * The current Costco member coupon book (US): every offer with its item\n * number, discount, final price, warehouse/online scope, limits and the\n * book's valid dates. Takes no parameters.\n *\n * Costs 1 credit.\n */\n async coupons(options: CostcoCouponsOptions = {}): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/coupons\", options);\n }\n\n /**\n * Costco deal feeds: new items, while supplies last, treasure hunt, member\n * favorites, online-only and everything on sale, with the same filters and\n * optional per-warehouse pricing as search().\n *\n * Costs 1 credit.\n */\n async deals(options: CostcoDealsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/deals\", options);\n }\n\n /**\n * Markdown finder for one warehouse: scans a query or category and keeps\n * the items whose in-warehouse price ends in a markdown code - .97\n * clearance and .00/.88 manager markdown by default, .49/.79/.89 special\n * buys on request. The codes are the member-community decode; Costco does\n * not publish them. Only items Costco lists online are covered.\n *\n * Costs 1 credit.\n */\n async clearance(options: CostcoClearanceOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/clearance\", options);\n }\n\n /**\n * Costco search-box suggestions for a partial query.\n *\n * Costs 1 credit.\n */\n async autocomplete(options: CostcoAutocompleteOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/costco/autocomplete\", options);\n }\n}\n","import type { Scavio } from \"../client.js\";\n\n// Trustpilot: 6 endpoints, all POST /api/v1/trustpilot/<method>, 2 credits each.\n//\n// business() and reviews() take exactly one of domain or url. reviews() serves\n// up to 10 pages of 20 (200 reviews) per filter combination; slice by stars,\n// language, date_range, topics or search to reach more. An unknown business,\n// review or category returns a 404 and is billed.\n\nexport type TrustpilotReviewsDateRange = \"last30days\" | \"last3months\" | \"last6months\" | \"last12months\";\nexport type TrustpilotReviewsSort = \"recency\" | \"relevance\";\nexport type TrustpilotCategorySort = \"most_relevant\" | \"reviews_count\" | \"latest_review\";\nexport type TrustpilotStars = 1 | 2 | 3 | 4 | 5;\n\nexport interface TrustpilotSearchOptions {\n /** Business name, keyword or category (1-200 characters). */\n query: string;\n /** 2-letter country code to search in (default \"US\"). */\n country?: string;\n /** Results page, 1-based (1-1000). */\n page?: number;\n /** Businesses per page (1-100, default 20). */\n page_size?: number;\n [key: string]: unknown;\n}\n\n/** A business address: pass exactly one of domain or url. */\nexport interface TrustpilotBusinessAddress {\n /** The business's website domain as listed on Trustpilot (e.g. \"www.amazon.com\"). */\n domain?: string;\n /** A trustpilot.com/review/<domain> page URL, from any Trustpilot country site. */\n url?: string;\n}\n\nexport interface TrustpilotBusinessOptions extends TrustpilotBusinessAddress {\n /**\n * 2-letter language code (default \"en\"). The 20 included reviews are this\n * language's newest, and the AI summary and topics come back in it when\n * Trustpilot has them for that language (null / empty otherwise). The rating\n * distribution and review-language breakdown cover every language.\n */\n language?: string;\n [key: string]: unknown;\n}\n\nexport interface TrustpilotReviewsOptions extends TrustpilotBusinessAddress {\n /** Reviews page, 1-10 (20 per page). */\n page?: number;\n /** Only reviews with these star ratings (e.g. [1, 2]). */\n stars?: TrustpilotStars[];\n /** Review language (2-letter code) or \"all\" (default \"all\"). */\n language?: string;\n /** Only reviews published in this window. */\n date_range?: TrustpilotReviewsDateRange;\n /** Review order (default \"recency\"). */\n sort?: TrustpilotReviewsSort;\n /** Only verified reviews. */\n verified_only?: boolean;\n /** Only reviews the business replied to. */\n with_replies?: boolean;\n /** Topic ids from business()'s topics, up to 10 (e.g. [\"delivery_service\"]). */\n topics?: string[];\n /** Only reviews containing this text (1-100 characters). */\n search?: string;\n [key: string]: unknown;\n}\n\nexport interface TrustpilotCategoriesOptions {\n /** Find categories by name (1-100 characters). Omit for the full tree. */\n query?: string;\n /** 2-letter country code for the name lookup (default \"US\"). */\n country?: string;\n [key: string]: unknown;\n}\n\nexport interface TrustpilotCategoryOptions {\n /** Category id from categories() (e.g. \"vpn_service\"). */\n category_id: string;\n /** 2-letter country code (default \"US\"). */\n country?: string;\n /** Result order (default \"most_relevant\"). */\n sort?: TrustpilotCategorySort;\n /**\n * Minimum star rating: 3, 4 or 4.5. Trustpilot rounds TrustScore to stars,\n * so 4 includes TrustScore 3.8 and up.\n */\n min_trust_score?: 3 | 4 | 4.5;\n /** Only businesses that have claimed their Trustpilot profile. */\n claimed_only?: boolean;\n /** Results page, 1-based (20 businesses per page). */\n page?: number;\n [key: string]: unknown;\n}\n\nexport interface TrustpilotReviewOptions {\n /** 24-character review id, as returned in review_id by business() or reviews(). */\n review_id: string;\n [key: string]: unknown;\n}\n\nexport class TrustpilotNamespace {\n constructor(private client: Scavio) {}\n\n /**\n * Search Trustpilot businesses by keyword in one country: TrustScore, star\n * rating, review count, categories, website, and the email, phone and\n * address the business published. Up to 100 businesses per page.\n *\n * Costs 2 credits.\n */\n async search(options: TrustpilotSearchOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/trustpilot/search\", options);\n }\n\n /**\n * A Trustpilot business profile: TrustScore, rating distribution, review\n * languages, categories, contact details, claimed and verification status,\n * reply rate and reply speed on negative reviews, consumer alerts, the AI\n * review summary and topics, similar businesses, and the 20 newest reviews\n * in the chosen language. Pass exactly one of domain or url.\n *\n * Costs 2 credits.\n */\n async business(options: TrustpilotBusinessOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/trustpilot/business\", options);\n }\n\n /**\n * One page of 20 Trustpilot reviews for a business, filtered by stars,\n * language, date range, topics, text search, verified-only and\n * with-replies, sorted by recency or relevance. Returns total_filtered, so a\n * date range doubles as review velocity. Up to 10 pages (200 reviews) per\n * filter combination. Pass exactly one of domain or url.\n *\n * Costs 2 credits.\n */\n async reviews(options: TrustpilotReviewsOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/trustpilot/reviews\", options);\n }\n\n /**\n * The full Trustpilot category tree (top-level categories and their\n * subcategories), or categories matching a name. Every category_id works\n * with category().\n *\n * Costs 2 credits.\n */\n async categories(options: TrustpilotCategoriesOptions = {}): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/trustpilot/categories\", options);\n }\n\n /**\n * Businesses ranked in a Trustpilot category for one country, with\n * TrustScore, review count, location, website, email and phone. Sort by\n * relevance, review count or latest review, set a minimum star rating, or\n * keep claimed profiles only. 20 per page.\n *\n * Costs 2 credits.\n */\n async category(options: TrustpilotCategoryOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/trustpilot/category\", options);\n }\n\n /**\n * One Trustpilot review by id: rating, title, full text, dates,\n * verification, the reviewer's public profile summary, the business reply,\n * and the business it is about.\n *\n * Costs 2 credits.\n */\n async review(options: TrustpilotReviewOptions): Promise<Record<string, unknown>> {\n return this.client._post(\"/api/v1/trustpilot/review\", options);\n }\n}\n","import { MissingAPIKeyError, ScavioError } from \"./errors.js\";\nimport { BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT, request } from \"./http.js\";\nimport { RateLimiter } from \"./rate-limiter.js\";\nimport { AmazonNamespace } from \"./namespaces/amazon.js\";\nimport type { GoogleSearchOptions } from \"./namespaces/google.js\";\nimport { GoogleNamespace } from \"./namespaces/google.js\";\nimport { RedditNamespace } from \"./namespaces/reddit.js\";\nimport { TikTokNamespace } from \"./namespaces/tiktok.js\";\nimport { TikTokShopNamespace } from \"./namespaces/tiktok-shop.js\";\nimport { InstagramNamespace } from \"./namespaces/instagram.js\";\nimport { WalmartNamespace } from \"./namespaces/walmart.js\";\nimport { YouTubeNamespace } from \"./namespaces/youtube.js\";\nimport { XNamespace } from \"./namespaces/x.js\";\nimport { LinkedInNamespace } from \"./namespaces/linkedin.js\";\nimport { ThreadsNamespace } from \"./namespaces/threads.js\";\nimport { KuaishouNamespace } from \"./namespaces/kuaishou.js\";\nimport { EbayNamespace } from \"./namespaces/ebay.js\";\nimport { TargetNamespace } from \"./namespaces/target.js\";\nimport { HomeDepotNamespace } from \"./namespaces/home-depot.js\";\nimport { ZillowNamespace } from \"./namespaces/zillow.js\";\nimport { RedfinNamespace } from \"./namespaces/redfin.js\";\nimport { BookingNamespace } from \"./namespaces/booking.js\";\nimport { AirbnbNamespace } from \"./namespaces/airbnb.js\";\nimport { TripadvisorNamespace } from \"./namespaces/tripadvisor.js\";\nimport { YelpNamespace } from \"./namespaces/yelp.js\";\nimport { IndeedNamespace } from \"./namespaces/indeed.js\";\nimport { GlassdoorNamespace } from \"./namespaces/glassdoor.js\";\nimport { AppStoreNamespace } from \"./namespaces/app-store.js\";\nimport { GooglePlayNamespace } from \"./namespaces/google-play.js\";\nimport { G2Namespace } from \"./namespaces/g2.js\";\nimport { CapterraNamespace } from \"./namespaces/capterra.js\";\nimport { SECNamespace } from \"./namespaces/sec.js\";\nimport { CompaniesHouseNamespace } from \"./namespaces/companies-house.js\";\nimport { GoogleAdsNamespace } from \"./namespaces/google-ads.js\";\nimport { MetaAdsNamespace } from \"./namespaces/meta-ads.js\";\nimport { CostcoNamespace } from \"./namespaces/costco.js\";\nimport { TrustpilotNamespace } from \"./namespaces/trustpilot.js\";\n\n/**\n * Default client-side rate limit, safe on every plan including free.\n */\nexport const DEFAULT_MAX_REQUESTS_PER_SECOND = 1;\n\n/**\n * Highest client-side rate limit accepted, matching the largest plan limit.\n */\nexport const MAX_REQUESTS_PER_SECOND = 50;\n\nexport interface ScavioConfig {\n apiKey?: string;\n baseUrl?: string;\n timeout?: number;\n maxRequestsPerSecond?: number;\n /**\n * Additional retry attempts after the first request on transient failures\n * (HTTP 429/500/502/503/504 and network/timeout errors). Defaults to 2.\n * Set to 0 to disable retries.\n */\n maxRetries?: number;\n}\n\n/**\n * Options for the top-level `extract()` method.\n *\n * Extract is a CORE endpoint, not a platform: it reads any URL, so it hangs\n * off the client itself rather than a namespace.\n */\nexport interface ExtractOptions {\n /**\n * Page to read. http(s) only; a bare host is upgraded to https. Loopback,\n * private, link-local and cloud-metadata hosts are rejected with a 400.\n * 1-2048 characters.\n */\n url: string;\n /**\n * Output format (default \"markdown\").\n *\n * - \"html\": the raw page, unmodified.\n * - \"markdown\": readability extraction - boilerplate stripped.\n * - \"text\": that markdown flattened to plain text.\n */\n format?: \"html\" | \"markdown\" | \"text\";\n /**\n * Fetch tier, and THE PRICE-BEARING PARAM (default \"normal\").\n *\n * - \"normal\": plain datacenter fetch - 1 credit.\n * - \"advanced\": headless browser render, for JS-built pages - 1 credit.\n * - \"ultra\": residential proxy, for hard bot walls - 2 credits.\n */\n mode?: \"normal\" | \"advanced\" | \"ultra\";\n [key: string]: unknown;\n}\n\nexport class Scavio {\n readonly google: GoogleNamespace;\n readonly amazon: AmazonNamespace;\n readonly walmart: WalmartNamespace;\n readonly youtube: YouTubeNamespace;\n readonly reddit: RedditNamespace;\n readonly tiktok: TikTokNamespace;\n readonly tiktokShop: TikTokShopNamespace;\n readonly instagram: InstagramNamespace;\n readonly x: XNamespace;\n readonly linkedin: LinkedInNamespace;\n readonly threads: ThreadsNamespace;\n readonly kuaishou: KuaishouNamespace;\n readonly ebay: EbayNamespace;\n readonly target: TargetNamespace;\n readonly homeDepot: HomeDepotNamespace;\n readonly zillow: ZillowNamespace;\n readonly redfin: RedfinNamespace;\n readonly booking: BookingNamespace;\n readonly airbnb: AirbnbNamespace;\n readonly tripadvisor: TripadvisorNamespace;\n readonly yelp: YelpNamespace;\n readonly indeed: IndeedNamespace;\n readonly glassdoor: GlassdoorNamespace;\n readonly appStore: AppStoreNamespace;\n readonly googlePlay: GooglePlayNamespace;\n readonly g2: G2Namespace;\n readonly capterra: CapterraNamespace;\n readonly sec: SECNamespace;\n readonly companiesHouse: CompaniesHouseNamespace;\n readonly googleAds: GoogleAdsNamespace;\n readonly metaAds: MetaAdsNamespace;\n readonly costco: CostcoNamespace;\n readonly trustpilot: TrustpilotNamespace;\n\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n private readonly rateLimiter: RateLimiter;\n\n constructor(config?: ScavioConfig) {\n this.apiKey = config?.apiKey ?? process.env.SCAVIO_API_KEY ?? \"\";\n if (!this.apiKey) {\n throw new MissingAPIKeyError();\n }\n\n this.baseUrl = (config?.baseUrl ?? BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = config?.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = config?.maxRetries ?? DEFAULT_MAX_RETRIES;\n\n const rps = config?.maxRequestsPerSecond ?? DEFAULT_MAX_REQUESTS_PER_SECOND;\n if (rps < 1 || rps > MAX_REQUESTS_PER_SECOND) {\n throw new ScavioError(\n `maxRequestsPerSecond must be between 1 and ${MAX_REQUESTS_PER_SECOND}`,\n );\n }\n this.rateLimiter = new RateLimiter(rps);\n\n this.google = new GoogleNamespace(this);\n this.amazon = new AmazonNamespace(this);\n this.walmart = new WalmartNamespace(this);\n this.youtube = new YouTubeNamespace(this);\n this.reddit = new RedditNamespace(this);\n this.tiktok = new TikTokNamespace(this);\n this.tiktokShop = new TikTokShopNamespace(this);\n this.instagram = new InstagramNamespace(this);\n this.x = new XNamespace(this);\n this.linkedin = new LinkedInNamespace(this);\n this.threads = new ThreadsNamespace(this);\n this.kuaishou = new KuaishouNamespace(this);\n this.ebay = new EbayNamespace(this);\n this.target = new TargetNamespace(this);\n this.homeDepot = new HomeDepotNamespace(this);\n this.zillow = new ZillowNamespace(this);\n this.redfin = new RedfinNamespace(this);\n this.booking = new BookingNamespace(this);\n this.airbnb = new AirbnbNamespace(this);\n this.tripadvisor = new TripadvisorNamespace(this);\n this.yelp = new YelpNamespace(this);\n this.indeed = new IndeedNamespace(this);\n this.glassdoor = new GlassdoorNamespace(this);\n this.appStore = new AppStoreNamespace(this);\n this.googlePlay = new GooglePlayNamespace(this);\n this.g2 = new G2Namespace(this);\n this.capterra = new CapterraNamespace(this);\n this.sec = new SECNamespace(this);\n this.companiesHouse = new CompaniesHouseNamespace(this);\n this.googleAds = new GoogleAdsNamespace(this);\n this.metaAds = new MetaAdsNamespace(this);\n this.costco = new CostcoNamespace(this);\n this.trustpilot = new TrustpilotNamespace(this);\n }\n\n /** @internal */\n async _post(\n path: string,\n body: object,\n ): Promise<Record<string, unknown>> {\n return request({\n method: \"POST\",\n path,\n apiKey: this.apiKey,\n baseUrl: this.baseUrl,\n timeout: this.timeout,\n maxRetries: this.maxRetries,\n rateLimiter: this.rateLimiter,\n body: body as Record<string, unknown>,\n });\n }\n\n /** @internal */\n async _get(path: string): Promise<Record<string, unknown>> {\n return request({\n method: \"GET\",\n path,\n apiKey: this.apiKey,\n baseUrl: this.baseUrl,\n timeout: this.timeout,\n maxRetries: this.maxRetries,\n rateLimiter: this.rateLimiter,\n });\n }\n\n async search(\n options: GoogleSearchOptions,\n ): Promise<Record<string, unknown>> {\n return this.google.search(options);\n }\n\n /**\n * Read ANY web page and get it back as readability Markdown (the default),\n * plain text, or raw HTML. Returns `{ url, format, mode, content,\n * content_length }`.\n *\n * This is a core endpoint, not a platform, so it lives on the client itself:\n * `scavio.extract({ url })`, never `scavio.extract.extract()`.\n *\n * Credits are a function of `mode`, not a flat per-call constant:\n * \"normal\" costs 1, \"advanced\" costs 1, \"ultra\" costs 2. Billing happens\n * only on a successful extraction - a dead link, bot wall or timeout costs\n * nothing.\n *\n * Start on \"normal\". Move to \"advanced\" when the page builds its content in\n * the browser, and to \"ultra\" only when a bot wall blocks the other two.\n *\n * @example\n * const page = await scavio.extract({ url: \"https://example.com/pricing\" });\n * console.log(page.content);\n */\n async extract(options: ExtractOptions): Promise<Record<string, unknown>> {\n return this._post(\"/api/v1/extract\", options);\n }\n\n async getUsage(): Promise<Record<string, unknown>> {\n return this._get(\"/api/v1/usage\");\n }\n}\n"],"mappings":";AAAO,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,qBAAN,cAAiC,YAAY;AAAA,EAClD,cAAc;AACZ;AAAA,MACE;AAAA,IAEF;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,wBAAN,cAAoC,YAAY;AAAA,EACrD,YAAY,UAAU,oBAAoB;AACxC,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,qBAAN,cAAiC,YAAY;AAAA,EAClD,YAAY,UAAU,qBAAqB;AACzC,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,qBAAN,cAAiC,YAAY;AAAA,EAClC,aAAa;AAAA,EACb;AAAA,EAEhB,YAAY,UAAU,mBAAmB,cAAwC;AAC/E,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,eAAe;AAAA,EACtB;AACF;AAEO,IAAM,2BAAN,cAAuC,YAAY;AAAA,EACxC,aAAa;AAAA,EACb;AAAA,EAEhB,YAAY,UAAU,wBAAwB,cAAwC;AACpF,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,eAAe;AAAA,EACtB;AACF;AAQO,IAAM,kBAAN,cAA8B,YAAY;AAAA,EAC/B;AAAA,EACA;AAAA,EAEhB,YACE,UAAU,eACV,cACA,aAAa,KACb;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,eAAe;AACpB,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,gBAAN,cAA4B,YAAY;AAAA,EAC7B,aAAa;AAAA,EACb;AAAA,EAEhB,YAAY,UAAU,aAAa,cAAwC;AACzE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,eAAe;AAAA,EACtB;AACF;AAEO,IAAM,iBAAN,cAA6B,YAAY;AAAA,EAC9B,aAAa;AAAA,EACb;AAAA,EAEhB,YAAY,UAAU,uBAAuB,cAAwC;AACnF,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,eAAe;AAAA,EACtB;AACF;AAEO,IAAM,iBAAN,cAA6B,YAAY;AAAA,EAC9B;AAAA,EACA;AAAA,EAEhB,YACE,YACA,SACA,cACA;AACA,UAAM,aAAa,UAAU,KAAK,OAAO,EAAE;AAC3C,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,eAAe;AAAA,EACtB;AACF;;;AC3GO,IAAM,yBAA8C,oBAAI,IAAI;AAAA,EACjE;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AACtB,CAAC;AAaM,SAAS,gBAAgB,YAAiC;AAC/D,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV,eAAe;AAAA,EACjB;AACF;AAEO,SAAS,kBACd,QACA,YACA,SACS;AACT,SAAO,UAAU,OAAO,cAAc,OAAO,cAAc,IAAI,UAAU;AAC3E;AAEO,SAAS,qBACd,QACA,SACS;AACT,SAAO,UAAU,OAAO;AAC1B;AAMO,SAAS,QACd,QACA,SACA,YACQ;AACR,MAAI,eAAe,QAAW;AAC5B,WAAO,KAAK,IAAI,KAAK,IAAI,YAAY,CAAC,GAAG,OAAO,QAAQ;AAAA,EAC1D;AACA,QAAM,SAAS,KAAK,IAAI,OAAO,UAAU,OAAO,YAAY,KAAK,OAAO;AACxE,SAAO,KAAK,OAAO,IAAI;AACzB;AAGO,SAAS,gBAAgB,QAA2C;AACzE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,UAAU,OAAO,KAAK;AAC5B,QAAM,WAAW,OAAO,OAAO;AAC/B,MAAI,CAAC,OAAO,MAAM,QAAQ,KAAK,YAAY,IAAI;AAC7C,WAAO;AAAA,EACT;AACA,QAAM,SAAS,KAAK,MAAM,OAAO;AACjC,MAAI,CAAC,OAAO,MAAM,MAAM,GAAG;AACzB,WAAO,KAAK,KAAK,SAAS,KAAK,IAAI,KAAK,KAAM,CAAC;AAAA,EACjD;AACA,SAAO;AACT;;;ACtDO,IAAM,WAAW;AACjB,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAM5B,IAAM,cACX,OAA4C,WAAwB;AAE/D,IAAM,aAAa,aAAa,WAAW;AAI3C,SAAS,kBAA2B;AACzC,QAAM,IAAI;AAKV,MAAI,OAAO,EAAE,WAAW,eAAe,OAAO,EAAE,aAAa,aAAa;AACxE,WAAO;AAAA,EACT;AACA,SAAO,OAAO,EAAE,SAAS,UAAU,SAAS;AAC9C;AAEO,SAAS,aAAa,QAAwC;AACnE,QAAM,UAAkC;AAAA,IACtC,eAAe,UAAU,MAAM;AAAA,IAC/B,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,EACrB;AACA,MAAI,gBAAgB,GAAG;AACrB,YAAQ,YAAY,IAAI;AAAA,EAC1B;AACA,SAAO;AACT;AAEA,SAAS,eACP,KACyB;AACzB,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,QAAI,UAAU,QAAW;AACvB,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,YAAoB,MAAsC;AAC7E,MAAI,QAAQ,KAAK,SAAS;AAC1B,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,aAAa,OAAO;AACrE,YAAS,MAA8B;AAAA,EACzC;AACA,QAAM,MAAM,OAAO,KAAK;AACxB,QAAM,eAAe,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,OAAO;AAK3D,MAAI,eAAe,OAAO,eAAe,KAAK;AAC5C,UAAM,IAAI,gBAAgB,KAAK,cAAc,UAAU;AAAA,EACzD;AACA,MAAI,eAAe,IAAK,OAAM,IAAI,mBAAmB,KAAK,YAAY;AACtE,MAAI,eAAe,IAAK,OAAM,IAAI,yBAAyB,KAAK,YAAY;AAC5E,MAAI,eAAe,IAAK,OAAM,IAAI,cAAc,KAAK,YAAY;AACjE,MAAI,eAAe,IAAK,OAAM,IAAI,eAAe,KAAK,YAAY;AAClE,QAAM,IAAI,eAAe,YAAY,KAAK,YAAY;AACxD;AAEA,SAAS,MAAM,SAAgC;AAC7C,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,UAAU,GAAI,CAAC;AACrE;AAEA,SAAS,aAAa,KAAuB;AAC3C,SACE,eAAe,UACd,IAAI,SAAS,gBAAgB,IAAI,SAAS;AAE/C;AAEA,SAAS,UAAU,UAAoB,MAA6B;AAClE,QAAM,UAAU,SAAS;AACzB,MAAI,WAAW,OAAO,QAAQ,QAAQ,YAAY;AAChD,WAAO,QAAQ,IAAI,IAAI;AAAA,EACzB;AACA,SAAO;AACT;AAEA,eAAsB,QAAQ,SASO;AACnC,QAAM,MAAM,GAAG,QAAQ,OAAO,GAAG,QAAQ,IAAI;AAC7C,QAAM,UAAU,aAAa,QAAQ,MAAM;AAC3C,QAAM,QAAqB;AAAA,IACzB,QAAQ,cAAc;AAAA,EACxB;AAEA,MAAI,UAAU;AAEd,aAAS;AACP,UAAM,QAAQ,YAAY,KAAK;AAE/B,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,QAAQ,OAAO;AAEtE,QAAI;AACJ,QAAI;AACF,YAAM,eAA4B;AAAA,QAChC,QAAQ,QAAQ;AAAA,QAChB;AAAA,QACA,QAAQ,WAAW;AAAA,MACrB;AAEA,UAAI,QAAQ,WAAW,UAAU,QAAQ,MAAM;AAC7C,qBAAa,OAAO,KAAK,UAAU,eAAe,QAAQ,IAAI,CAAC;AAAA,MACjE;AAEA,iBAAW,MAAM,MAAM,KAAK,YAAY;AAAA,IAC1C,SAAS,KAAK;AACZ,mBAAa,SAAS;AACtB,YAAM,WAAW,aAAa,GAAG;AACjC,UAAI,qBAAqB,OAAO,OAAO,GAAG;AACxC,cAAM,MAAM,QAAQ,OAAO,OAAO,CAAC;AACnC,mBAAW;AACX;AAAA,MACF;AACA,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAI,UAAU;AACZ,cAAM,IAAI,mBAAmB,GAAG;AAAA,MAClC;AACA,YAAM,IAAI,sBAAsB,GAAG;AAAA,IACrC,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAEA,QAAI,SAAS,IAAI;AACf,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAEA,QAAI,kBAAkB,OAAO,SAAS,QAAQ,OAAO,GAAG;AACtD,YAAM,aAAa,gBAAgB,UAAU,UAAU,aAAa,CAAC;AACrE,YAAM,MAAM,QAAQ,OAAO,SAAS,UAAU,CAAC;AAC/C,iBAAW;AACX;AAAA,IACF;AAEA,QAAI,OAAgC,CAAC;AACrC,QAAI;AACF,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,QAAQ;AAAA,IAER;AACA,gBAAY,SAAS,QAAQ,IAAI;AAAA,EACnC;AACF;;;ACxLO,IAAM,cAAN,MAAkB;AAAA,EACN;AAAA,EACA,aAAuB,CAAC;AAAA,EACjC,UAAyB,QAAQ,QAAQ;AAAA,EAEjD,YAAY,cAAsB;AAChC,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,MAAM,OAAsB;AAC1B,UAAM,SAAS,KAAK,QAAQ,KAAK,MAAM,KAAK,QAAQ,CAAC;AACrD,SAAK,UAAU;AACf,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,UAAyB;AACrC,SAAK,QAAQ;AACb,QAAI,KAAK,WAAW,UAAU,KAAK,cAAc;AAC/C,YAAM,UAAU,OAAQ,KAAK,IAAI,IAAI,KAAK,WAAW,CAAC;AACtD,UAAI,UAAU,GAAG;AACf,cAAM,IAAI,QAAc,CAAC,YAAY,WAAW,SAAS,OAAO,CAAC;AAAA,MACnE;AACA,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,WAAW,KAAK,KAAK,IAAI,CAAC;AAAA,EACjC;AAAA,EAEQ,UAAgB;AACtB,UAAM,MAAM,KAAK,IAAI;AACrB,WAAO,KAAK,WAAW,SAAS,KAAK,MAAM,KAAK,WAAW,CAAC,KAAM,KAAM;AACtE,WAAK,WAAW,MAAM;AAAA,IACxB;AAAA,EACF;AACF;;;ACgBO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA,EAEpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA,EAEA,MAAM,QACJ,SACkC;AAClC,UAAM,EAAE,MAAM,GAAG,KAAK,IAAI;AAC1B,WAAO,KAAK,OAAO,MAAM,0BAA0B;AAAA,MACjD,OAAO;AAAA,MACP,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA;AAAA;AAAA,EAIA,MAAM,OAAO,SAAgE;AAC3E,UAAM,EAAE,MAAM,GAAG,KAAK,IAAI;AAC1B,WAAO,KAAK,OAAO,MAAM,yBAAyB;AAAA,MAChD,OAAO;AAAA,MACP,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAA4C;AAChD,WAAO,KAAK,OAAO,KAAK,wBAAwB;AAAA,EAClD;AACF;;;ACyQO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA,EAGpB,MAAM,OAAO,SAAgE;AAC3E,WAAO,KAAK,OAAO,MAAM,kBAAkB,OAAO;AAAA,EACpD;AAAA;AAAA,EAGA,MAAM,OAAO,SAAgE;AAC3E,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAM,WAAW,SAAoE;AACnF,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AAAA;AAAA,EAGA,MAAM,UAAU,SAAmE;AACjF,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA,EAGA,MAAM,YAAY,SAAqE;AACrF,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA;AAAA,EAGA,MAAM,SAAS,SAAkE;AAC/E,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAM,gBACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mCAAmC,OAAO;AAAA,EACrE;AAAA;AAAA,EAGA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0CAA0C,OAAO;AAAA,EAC5E;AAAA;AAAA,EAGA,MAAM,QAAQ,SAAiE;AAC7E,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAM,OAAO,SAAgE;AAC3E,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA;AAAA,EAGA,MAAM,KAAK,SAA8D;AACvE,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AAAA;AAAA,EAGA,MAAM,OAAO,SAAgE;AAC3E,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAM,SAAS,SAAkE;AAC/E,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AACF;;;AC1UO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA,EAGpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA,EAEA,MAAM,kBACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,qCAAqC,OAAO;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,SAA8D;AACvE,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AAAA,EAEA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,wCAAwC,OAAO;AAAA,EAC1E;AAAA,EAEA,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA,EAEA,MAAM,KAAK,SAA8D;AACvE,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AAAA,EAEA,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA,EAEA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,QACJ,UAAgC,CAAC,GACC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA,EAEA,MAAM,WAA6C;AACjD,WAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC,CAAC;AAAA,EACxD;AACF;;;ACtDO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA,EAEpB,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA,EAEA,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA,EAEA,MAAM,MACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,wBAAwB,OAAO;AAAA,EAC1D;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yCAAyC,OAAO;AAAA,EAC3E;AAAA,EAEA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA,EAEA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AACF;;;AC/FO,IAAM,sBAAN,MAA0B;AAAA,EAC/B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kBACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0CAA0C,OAAO;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqCA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uCAAuC,OAAO;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAA+C;AACnD,WAAO,KAAK,OAAO,MAAM,kCAAkC,CAAC,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yCAAyC,OAAO;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,qCAAqC,OAAO;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AACF;;;ACxHO,IAAM,qBAAN,MAAyB;AAAA,EAC9B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA,EAEpB,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA,EAEA,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,WACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA,EAEA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA,EAEA,MAAM,KACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA,EAEA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mCAAmC,OAAO;AAAA,EACrE;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2CAA2C,OAAO;AAAA,EAC7E;AAAA,EAEA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,qCAAqC,OAAO;AAAA,EACvE;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,oCAAoC,OAAO;AAAA,EACtE;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,qCAAqC,OAAO;AAAA,EACvE;AACF;;;ACmDO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mCAAmC,OAAO;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OAAO,SAA+D;AAC1E,WAAQ,MAAM,KAAK,OAAO;AAAA,MACxB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACxKO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA,EAEpB,MAAM,OACJ,SACkC;AAClC,UAAM,EAAE,OAAO,OAAO,WAAW,UAAU,GAAG,KAAK,IAAI;AACvD,UAAM,OAAgC;AAAA,MACpC,QAAQ;AAAA,MACR,GAAG;AAAA,IACL;AACA,QAAI,UAAU,OAAW,MAAK,IAAI,IAAI;AACtC,QAAI,cAAc,OAAW,MAAK,KAAK,IAAI;AAC3C,QAAI,aAAa,OAAW,MAAK,IAAI,IAAI;AACzC,WAAO,KAAK,OAAO,MAAM,0BAA0B,IAAI;AAAA,EACzD;AAAA,EAEA,MAAM,OACJ,SACkC;AAClC,UAAM,EAAE,OAAO,GAAG,KAAK,IAAI;AAC3B,WAAO,KAAK,OAAO,MAAM,0BAA0B;AAAA,MACjD,QAAQ;AAAA,MACR,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YACJ,SACkC;AAClC,UAAM,EAAE,OAAO,GAAG,KAAK,IAAI;AAC3B,WAAO,KAAK,OAAO,MAAM,+BAA+B;AAAA,MACtD,QAAQ;AAAA,MACR,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B;AAAA,EAEA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,oCAAoC,OAAO;AAAA,EACtE;AAAA,EAEA,MAAM,WACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AAAA,EAEA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,UAAM,EAAE,OAAO,GAAG,KAAK,IAAI;AAC3B,WAAO,KAAK,OAAO,MAAM,kCAAkC;AAAA,MACzD,QAAQ;AAAA,MACR,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA,EAEA,MAAM,iBACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,qCAAqC,OAAO;AAAA,EACvE;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mCAAmC,OAAO;AAAA,EACrE;AAAA,EAEA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AACF;;;AC/NO,IAAM,aAAN,MAAiB;AAAA,EACtB,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA,EAEpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,oBAAoB,OAAO;AAAA,EACtD;AAAA,EAEA,MAAM,MACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mBAAmB,OAAO;AAAA,EACrD;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA,EAEA,MAAM,gBACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AAAA,EAEA,MAAM,KACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kBAAkB,OAAO;AAAA,EACpD;AAAA,EAEA,MAAM,WACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA,EAEA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA,EAEA,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,wBAAwB,OAAO;AAAA,EAC1D;AAAA,EAEA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA,EAEA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA,EAEA,MAAM,SACJ,UAA4B,CAAC,GACK;AAClC,WAAO,KAAK,OAAO,MAAM,sBAAsB,OAAO;AAAA,EACxD;AACF;;;ACVO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA,EAGpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA,EAGA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA;AAAA,EAGA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA;AAAA,EAGA,MAAM,IACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,wBAAwB,OAAO;AAAA,EAC1D;AAAA;AAAA,EAGA,MAAM,KACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mCAAmC,OAAO;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mCAAmC,OAAO;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AACF;;;AC7KO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpB,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,wBAAwB,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AACF;;;ACXO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpB,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mCAAmC,OAAO;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uCAAuC,OAAO;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SACJ,UAAmC,CAAC,GACF;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AACF;;;ACxNO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAepB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,wBAAwB,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AACF;;;ACzCO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AACF;;;AC9FO,IAAM,qBAAN,MAAyB;AAAA,EAC9B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AACF;;;ACoCO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAapB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,aACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AACF;;;ACjCO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AACF;;;AChDO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,MACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AACF;;;ACnFO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AACF;;;ACzGO,IAAM,uBAAN,MAA2B;AAAA,EAChC,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAepB,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,gCAAgC,OAAO;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AACF;;;ACrFO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAepB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,wBAAwB,OAAO;AAAA,EAC1D;AACF;;;AC5EO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,IACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,sBAAsB,OAAO;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,eACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AACF;;;AC1CO,IAAM,qBAAN,MAAyB;AAAA,EAC9B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAapB,MAAM,UACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AACF;;;ACrFO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,IACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,wBAAwB,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AACF;;;ACpEO,IAAM,sBAAN,MAA0B;AAAA,EAC/B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAapB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,IACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AACF;;;AC9CO,IAAM,cAAN,MAAkB;AAAA,EACvB,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,qBAAqB,OAAO;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,sBAAsB,OAAO;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,sBAAsB,OAAO;AAAA,EACxD;AACF;;;AC7FO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAepB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AACF;;;AC4CO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,sBAAsB,OAAO;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,MACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,qBAAqB,OAAO;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,sBAAsB,OAAO;AAAA,EACxD;AACF;;;ACjOO,IAAM,0BAAN,MAA8B;AAAA,EACnC,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,QACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,kCAAkC,OAAO;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,mCAAmC,OAAO;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,cACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,yCAAyC,OAAO;AAAA,EAC3E;AACF;;;AC9DO,IAAM,qBAAN,MAAyB;AAAA,EAC9B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBpB,MAAM,YACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,SACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AACF;;;AClFO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBpB,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,WACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,GACJ,SACkC;AAClC,WAAO,KAAK,OAAO,MAAM,uBAAuB,OAAO;AAAA,EACzD;AACF;;;ACkEO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUpB,MAAM,OAAO,SAAgE;AAC3E,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAAS,SAAkE;AAC/E,WAAO,KAAK,OAAO,MAAM,2BAA2B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,UAAmC,CAAC,GAAqC;AACxF,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,SAAiE;AAC7E,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,SAAgE;AAC3E,WAAO,KAAK,OAAO,MAAM,yBAAyB,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,SAAsE;AACvF,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAQ,SAAiE;AAC7E,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAW,SAAoE;AACnF,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAI,SAA6D;AACrE,WAAO,KAAK,OAAO,MAAM,sBAAsB,OAAO;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,UAAgC,CAAC,GAAqC;AAClF,WAAO,KAAK,OAAO,MAAM,0BAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAM,SAA+D;AACzE,WAAO,KAAK,OAAO,MAAM,wBAAwB,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,UAAU,SAAmE;AACjF,WAAO,KAAK,OAAO,MAAM,4BAA4B,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAa,SAAsE;AACvF,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AACF;;;ACnPO,IAAM,sBAAN,MAA0B;AAAA,EAC/B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,MAAM,OAAO,SAAoE;AAC/E,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,SAAS,SAAsE;AACnF,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QAAQ,SAAqE;AACjF,WAAO,KAAK,OAAO,MAAM,8BAA8B,OAAO;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAW,UAAuC,CAAC,GAAqC;AAC5F,WAAO,KAAK,OAAO,MAAM,iCAAiC,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,SAAS,SAAsE;AACnF,WAAO,KAAK,OAAO,MAAM,+BAA+B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,SAAoE;AAC/E,WAAO,KAAK,OAAO,MAAM,6BAA6B,OAAO;AAAA,EAC/D;AACF;;;ACpIO,IAAM,kCAAkC;AAKxC,IAAM,0BAA0B;AA+ChC,IAAM,SAAN,MAAa;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAAuB;AACjC,SAAK,SAAS,QAAQ,UAAU,QAAQ,IAAI,kBAAkB;AAC9D,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,mBAAmB;AAAA,IAC/B;AAEA,SAAK,WAAW,QAAQ,WAAW,UAAU,QAAQ,QAAQ,EAAE;AAC/D,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,aAAa,QAAQ,cAAc;AAExC,UAAM,MAAM,QAAQ,wBAAwB;AAC5C,QAAI,MAAM,KAAK,MAAM,yBAAyB;AAC5C,YAAM,IAAI;AAAA,QACR,8CAA8C,uBAAuB;AAAA,MACvE;AAAA,IACF;AACA,SAAK,cAAc,IAAI,YAAY,GAAG;AAEtC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,UAAU,IAAI,iBAAiB,IAAI;AACxC,SAAK,UAAU,IAAI,iBAAiB,IAAI;AACxC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,aAAa,IAAI,oBAAoB,IAAI;AAC9C,SAAK,YAAY,IAAI,mBAAmB,IAAI;AAC5C,SAAK,IAAI,IAAI,WAAW,IAAI;AAC5B,SAAK,WAAW,IAAI,kBAAkB,IAAI;AAC1C,SAAK,UAAU,IAAI,iBAAiB,IAAI;AACxC,SAAK,WAAW,IAAI,kBAAkB,IAAI;AAC1C,SAAK,OAAO,IAAI,cAAc,IAAI;AAClC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,YAAY,IAAI,mBAAmB,IAAI;AAC5C,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,UAAU,IAAI,iBAAiB,IAAI;AACxC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,cAAc,IAAI,qBAAqB,IAAI;AAChD,SAAK,OAAO,IAAI,cAAc,IAAI;AAClC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,YAAY,IAAI,mBAAmB,IAAI;AAC5C,SAAK,WAAW,IAAI,kBAAkB,IAAI;AAC1C,SAAK,aAAa,IAAI,oBAAoB,IAAI;AAC9C,SAAK,KAAK,IAAI,YAAY,IAAI;AAC9B,SAAK,WAAW,IAAI,kBAAkB,IAAI;AAC1C,SAAK,MAAM,IAAI,aAAa,IAAI;AAChC,SAAK,iBAAiB,IAAI,wBAAwB,IAAI;AACtD,SAAK,YAAY,IAAI,mBAAmB,IAAI;AAC5C,SAAK,UAAU,IAAI,iBAAiB,IAAI;AACxC,SAAK,SAAS,IAAI,gBAAgB,IAAI;AACtC,SAAK,aAAa,IAAI,oBAAoB,IAAI;AAAA,EAChD;AAAA;AAAA,EAGA,MAAM,MACJ,MACA,MACkC;AAClC,WAAO,QAAQ;AAAA,MACb,QAAQ;AAAA,MACR;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,KAAK,MAAgD;AACzD,WAAO,QAAQ;AAAA,MACb,QAAQ;AAAA,MACR;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OACJ,SACkC;AAClC,WAAO,KAAK,OAAO,OAAO,OAAO;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,QAAQ,SAA2D;AACvE,WAAO,KAAK,MAAM,mBAAmB,OAAO;AAAA,EAC9C;AAAA,EAEA,MAAM,WAA6C;AACjD,WAAO,KAAK,KAAK,eAAe;AAAA,EAClC;AACF;","names":[]}
|