{"version":3,"sources":["../src/errors.ts","../src/shared-types.ts","../src/http.ts","../src/resources/addresses.ts","../src/resources/devices.ts","../src/resources/geocode.ts","../src/resources/regions.ts","../src/resources/routing.ts","../src/resources/webhooks.ts","../src/resources/zones.ts","../src/client.ts","../src/geo.ts","../src/guards.ts","../src/session.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n\tWheraboutsApiErrorPayload,\n\tWheraboutsErrorCode,\n\tWheraboutsFieldError,\n} from \"./shared-types.ts\";\n\nexport class WheraboutsApiError extends Error {\n\treadonly code: WheraboutsErrorCode | \"unknown_error\";\n\treadonly payload: WheraboutsApiErrorPayload | null;\n\treadonly status: number;\n\t/** Correlation id from the `X-Request-Id` header or error body, if present. */\n\treadonly requestId: string | null;\n\t/** Documentation link for this error, if the API provided one. */\n\treadonly docUrl: string | null;\n\t/** Field-level validation detail, if the API provided any. */\n\treadonly fields: WheraboutsFieldError[] | null;\n\n\tconstructor(options: {\n\t\tcode?: WheraboutsApiError[\"code\"];\n\t\tdocUrl?: string | null;\n\t\tfields?: WheraboutsFieldError[] | null;\n\t\tmessage: string;\n\t\tpayload?: WheraboutsApiErrorPayload | null;\n\t\trequestId?: string | null;\n\t\tstatus: number;\n\t}) {\n\t\tsuper(options.message);\n\t\tthis.name = \"WheraboutsApiError\";\n\t\tthis.status = options.status;\n\t\tthis.code = options.code ?? \"unknown_error\";\n\t\tthis.payload = options.payload ?? null;\n\t\tthis.requestId = options.requestId ?? null;\n\t\tthis.docUrl = options.docUrl ?? null;\n\t\tthis.fields = options.fields ?? null;\n\t}\n}\n","export const WHERABOUTS_API_VERSION = \"v1\" as const;\nexport const WHERABOUTS_SDK_VERSION = \"0.4.3\" as const;\n\n/**\n * Error codes the API may return. The server currently emits a subset; the full\n * union is declared for forward-compatibility with the Phase 2 error envelope\n * (see docs/CONTRACT.md §4). Unknown codes fall back to `unknown_error`.\n */\nexport type WheraboutsErrorCode =\n\t| \"bad_request\"\n\t| \"conflict\"\n\t| \"forbidden\"\n\t| \"internal_error\"\n\t| \"not_found\"\n\t| \"rate_limited\"\n\t| \"timeout\"\n\t| \"unauthorized\"\n\t| \"unprocessable\";\n\nexport interface WheraboutsFieldError {\n\tmessage: string;\n\tpath: string;\n}\n\nexport interface RequestLogEvent {\n\tdurationMs: number;\n\tmethod: string;\n\tpath: string;\n\trequestId?: string;\n\tstatus: number;\n}\n\nexport interface WheraboutsApiErrorPayload {\n\terror: {\n\t\tcode: WheraboutsErrorCode;\n\t\tmessage: string;\n\t\t/** Correlation id; also sent as the `X-Request-Id` response header. */\n\t\trequest_id?: string;\n\t\t/** Link to documentation for this error code. */\n\t\tdoc_url?: string;\n\t\t/** Field-level validation detail (validation errors only). */\n\t\tfields?: WheraboutsFieldError[];\n\t};\n}\n\nexport interface WheraboutsClientConfig {\n\t/**\n\t * Publishable/secret API key sent as `Authorization: Bearer <apiKey>`.\n\t *\n\t * Optional: when omitted, no `Authorization` header is sent. This supports\n\t * the recommended browser pattern of proxying requests through your own\n\t * backend (via a custom `baseUrl`/`fetch`) so the real key never reaches the\n\t * client — the proxy attaches the key server-side.\n\t */\n\tapiKey?: string;\n\tbaseUrl?: string;\n\tfetch?: typeof fetch;\n\theaders?: Record<string, string>;\n\t/** Called after every request. Use for debugging or observability. */\n\tlogger?: (event: RequestLogEvent) => void;\n\t/** Max automatic retries for transient failures. Default 2. */\n\tmaxRetries?: number;\n\t/** Per-request timeout in milliseconds. Default 30000. */\n\ttimeoutMs?: number;\n}\n\n/**\n * Per-call overrides. Every resource method accepts an optional trailing\n * `options` argument of this shape.\n */\nexport interface CallOptions {\n\t/** Extra headers merged over (not replacing) the client headers. */\n\theaders?: Record<string, string>;\n\t/** Idempotency key for write requests. Auto-generated on writes if omitted. */\n\tidempotencyKey?: string;\n\t/** Override the client's `maxRetries` for this call. */\n\tmaxRetries?: number;\n\t/** Abort signal — aborting rejects the call (and is not retried). */\n\tsignal?: AbortSignal;\n\t/** Override the client's `timeoutMs` for this call. */\n\ttimeoutMs?: number;\n}\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n\nexport interface RequestOptions extends CallOptions {\n\tbody?: unknown;\n\tmethod: HttpMethod;\n\tpath: string;\n\tquery?: Record<string, number | string | undefined>;\n}\n\nexport type Requester = <T>(opts: RequestOptions) => Promise<T>;\n","import { WheraboutsApiError } from \"./errors.ts\";\nimport {\n\ttype HttpMethod,\n\ttype Requester,\n\ttype RequestOptions,\n\tWHERABOUTS_API_VERSION,\n\tWHERABOUTS_SDK_VERSION,\n\ttype WheraboutsApiErrorPayload,\n\ttype WheraboutsClientConfig,\n} from \"./shared-types.ts\";\n\nconst DEFAULT_BASE_URL = \"https://api.wherabouts.com\";\nconst DEFAULT_MAX_RETRIES = 2;\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst BACKOFF_BASE_MS = 200;\nconst BACKOFF_CAP_MS = 5000;\nconst RETRYABLE_STATUSES = new Set([408, 425, 429, 500, 502, 503, 504]);\nconst WRITE_METHODS = new Set<HttpMethod>([\"POST\", \"PUT\"]);\n\nconst createBaseHeaders = (config: WheraboutsClientConfig): Headers => {\n\tconst headers = new Headers(config.headers);\n\theaders.set(\"accept\", \"application/json\");\n\t// Only attach auth when a key is configured. Omitting it enables the proxy\n\t// pattern (the consumer's backend injects the real key), and avoids sending a\n\t// literal \"Bearer undefined\" when no key is provided.\n\tif (config.apiKey) {\n\t\theaders.set(\"authorization\", `Bearer ${config.apiKey}`);\n\t}\n\theaders.set(\n\t\t\"x-wherabouts-sdk\",\n\t\t`js-ts/${WHERABOUTS_SDK_VERSION} api/${WHERABOUTS_API_VERSION}`\n\t);\n\treturn headers;\n};\n\nconst generateIdempotencyKey = (): string => {\n\tconst cryptoObj = globalThis.crypto;\n\tif (cryptoObj?.randomUUID) {\n\t\treturn cryptoObj.randomUUID();\n\t}\n\t// Fallback for runtimes without crypto.randomUUID.\n\treturn `${Date.now().toString(16)}-${Math.random().toString(16).slice(2)}`;\n};\n\nconst buildRequestHeaders = (\n\tbaseHeaders: Headers,\n\topts: RequestOptions\n): Headers => {\n\tconst headers = new Headers(baseHeaders);\n\tif (opts.headers) {\n\t\tfor (const [key, value] of Object.entries(opts.headers)) {\n\t\t\theaders.set(key, value);\n\t\t}\n\t}\n\tif (opts.body !== undefined) {\n\t\theaders.set(\"content-type\", \"application/json\");\n\t}\n\t// Writes carry an Idempotency-Key so retries are safe (docs/CONTRACT.md §6).\n\tif (WRITE_METHODS.has(opts.method)) {\n\t\theaders.set(\n\t\t\t\"idempotency-key\",\n\t\t\topts.idempotencyKey ?? generateIdempotencyKey()\n\t\t);\n\t} else if (opts.idempotencyKey) {\n\t\theaders.set(\"idempotency-key\", opts.idempotencyKey);\n\t}\n\treturn headers;\n};\n\nconst readRequestId = (response: Response): string | null =>\n\tresponse.headers.get(\"x-request-id\") ??\n\tresponse.headers.get(\"x-wherabouts-request-id\");\n\nconst parseApiError = async (\n\tresponse: Response\n): Promise<WheraboutsApiError> => {\n\tlet payload: WheraboutsApiErrorPayload | null = null;\n\ttry {\n\t\tpayload = (await response.json()) as WheraboutsApiErrorPayload;\n\t} catch {\n\t\tpayload = null;\n\t}\n\tconst message =\n\t\tpayload?.error.message ??\n\t\t`Wherabouts request failed with status ${response.status}`;\n\treturn new WheraboutsApiError({\n\t\tstatus: response.status,\n\t\tmessage,\n\t\tcode: payload?.error.code ?? \"unknown_error\",\n\t\tpayload,\n\t\trequestId: payload?.error.request_id ?? readRequestId(response),\n\t\tdocUrl: payload?.error.doc_url ?? null,\n\t\tfields: payload?.error.fields ?? null,\n\t});\n};\n\n/** Parse a `Retry-After` header (delta-seconds or HTTP-date) to milliseconds. */\nconst parseRetryAfter = (value: string | null): number | null => {\n\tif (!value) {\n\t\treturn null;\n\t}\n\tconst seconds = Number(value);\n\tif (Number.isFinite(seconds)) {\n\t\treturn Math.max(0, seconds * 1000);\n\t}\n\tconst dateMs = Date.parse(value);\n\tif (Number.isNaN(dateMs)) {\n\t\treturn null;\n\t}\n\treturn Math.max(0, dateMs - Date.now());\n};\n\n/** Exponential backoff with full jitter, capped. */\nconst computeBackoff = (attempt: number): number => {\n\tconst exponential = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * 2 ** attempt);\n\treturn Math.random() * exponential;\n};\n\nconst sleep = (ms: number, signal?: AbortSignal): Promise<void> =>\n\tnew Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(signal.reason ?? new Error(\"Aborted\"));\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timer);\n\t\t\treject(signal?.reason ?? new Error(\"Aborted\"));\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n\nconst buildRequestUrl = (\n\tpath: string,\n\tbaseUrl: URL,\n\tquery: RequestOptions[\"query\"]\n): URL => {\n\tconst url = new URL(path, baseUrl);\n\tif (query) {\n\t\tfor (const [key, value] of Object.entries(query)) {\n\t\t\tif (value !== undefined) {\n\t\t\t\turl.searchParams.set(key, String(value));\n\t\t\t}\n\t\t}\n\t}\n\treturn url;\n};\n\n// Wires a caller's AbortSignal into the per-attempt controller and returns an\n// unlink cleanup. Keeping this out of the retry loop keeps its complexity down.\nconst linkAbort = (\n\tcontroller: AbortController,\n\tcallerSignal: AbortSignal | undefined\n): (() => void) => {\n\tif (!callerSignal) {\n\t\treturn () => {\n\t\t\t// no caller signal to unlink\n\t\t};\n\t}\n\tconst onCallerAbort = () => controller.abort();\n\tif (callerSignal.aborted) {\n\t\tcontroller.abort();\n\t} else {\n\t\tcallerSignal.addEventListener(\"abort\", onCallerAbort, { once: true });\n\t}\n\treturn () => callerSignal.removeEventListener(\"abort\", onCallerAbort);\n};\n\n// Decides what to do with a thrown request error: retry after `waitMs`, or\n// stop and surface `error`. Extracted so the retry loop stays under the\n// cognitive-complexity limit. `attempt` is the pre-increment value, so `waitMs`\n// (computeBackoff(attempt)) matches the original computeBackoff(attempt - 1)\n// taken after the caller increments.\ntype RetryDecision =\n\t| { retry: true; waitMs: number }\n\t| { retry: false; error: unknown };\n\nconst classifyRequestError = (\n\terror: unknown,\n\tctx: {\n\t\tcallerSignal: AbortSignal | undefined;\n\t\ttimedOut: boolean;\n\t\tattempt: number;\n\t\tmaxRetries: number;\n\t\ttimeoutMs: number;\n\t}\n): RetryDecision => {\n\t// Caller aborted — never retry; propagate their intent.\n\tif (ctx.callerSignal?.aborted) {\n\t\treturn { retry: false, error };\n\t}\n\t// Our timeout fired — treat like a transient failure.\n\tif (ctx.timedOut) {\n\t\tif (ctx.attempt < ctx.maxRetries) {\n\t\t\treturn { retry: true, waitMs: computeBackoff(ctx.attempt) };\n\t\t}\n\t\treturn {\n\t\t\tretry: false,\n\t\t\terror: new WheraboutsApiError({\n\t\t\t\tstatus: 0,\n\t\t\t\tcode: \"timeout\",\n\t\t\t\tmessage: `Request timed out after ${ctx.timeoutMs}ms.`,\n\t\t\t}),\n\t\t};\n\t}\n\t// A parsed API error (non-retryable status) — surface as-is.\n\tif (error instanceof WheraboutsApiError) {\n\t\treturn { retry: false, error };\n\t}\n\t// Network/transport error — retry if budget remains.\n\tif (ctx.attempt < ctx.maxRetries) {\n\t\treturn { retry: true, waitMs: computeBackoff(ctx.attempt) };\n\t}\n\treturn { retry: false, error };\n};\n\n// Decides whether a non-OK response should be retried. Returns the (capped)\n// wait when retryable; otherwise the caller throws the parsed API error.\nconst classifyResponse = (\n\tresponse: Response,\n\tctx: { attempt: number; maxRetries: number }\n): { retry: true; waitMs: number } | { retry: false } => {\n\tif (RETRYABLE_STATUSES.has(response.status) && ctx.attempt < ctx.maxRetries) {\n\t\tconst wait =\n\t\t\tparseRetryAfter(response.headers.get(\"retry-after\")) ??\n\t\t\tcomputeBackoff(ctx.attempt);\n\t\treturn { retry: true, waitMs: Math.min(wait, BACKOFF_CAP_MS) };\n\t}\n\treturn { retry: false };\n};\n\nconst readResponseBody = async <T>(response: Response): Promise<T> => {\n\tif (response.status === 204) {\n\t\treturn undefined as T;\n\t}\n\tconst text = await response.text();\n\treturn (text ? JSON.parse(text) : undefined) as T;\n};\n\ninterface AttemptContext {\n\tattempt: number;\n\tbody: string | undefined;\n\tcallerSignal: AbortSignal | undefined;\n\tconfig: WheraboutsClientConfig;\n\tfetchImpl: typeof globalThis.fetch;\n\theaders: Headers;\n\tmaxRetries: number;\n\tmethod: HttpMethod;\n\tpath: string;\n\tstartTime: number;\n\ttimeoutMs: number;\n\turl: URL;\n}\n\ntype AttemptOutcome<T> =\n\t| { done: true; value: T }\n\t| { done: false; waitMs: number };\n\n// One request attempt: sets up the timeout/abort controller, performs the fetch,\n// and returns either a terminal value or a retry signal (the loop owns waiting\n// and the attempt counter). Throws on non-retryable failures.\nconst runAttempt = async <T>(\n\tctx: AttemptContext\n): Promise<AttemptOutcome<T>> => {\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst timeoutId = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, ctx.timeoutMs);\n\tconst unlinkAbort = linkAbort(controller, ctx.callerSignal);\n\n\ttry {\n\t\tconst response = await ctx.fetchImpl(ctx.url, {\n\t\t\tmethod: ctx.method,\n\t\t\theaders: ctx.headers,\n\t\t\tbody: ctx.body,\n\t\t\tsignal: controller.signal,\n\t\t});\n\n\t\tctx.config.logger?.({\n\t\t\tmethod: ctx.method,\n\t\t\tpath: ctx.path,\n\t\t\tstatus: response.status,\n\t\t\tdurationMs: Date.now() - ctx.startTime,\n\t\t\trequestId: readRequestId(response) ?? undefined,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst decision = classifyResponse(response, {\n\t\t\t\tattempt: ctx.attempt,\n\t\t\t\tmaxRetries: ctx.maxRetries,\n\t\t\t});\n\t\t\tif (decision.retry) {\n\t\t\t\treturn { done: false, waitMs: decision.waitMs };\n\t\t\t}\n\t\t\tthrow await parseApiError(response);\n\t\t}\n\n\t\treturn { done: true, value: await readResponseBody<T>(response) };\n\t} catch (error) {\n\t\tconst decision = classifyRequestError(error, {\n\t\t\tcallerSignal: ctx.callerSignal,\n\t\t\ttimedOut,\n\t\t\tattempt: ctx.attempt,\n\t\t\tmaxRetries: ctx.maxRetries,\n\t\t\ttimeoutMs: ctx.timeoutMs,\n\t\t});\n\t\tif (decision.retry) {\n\t\t\treturn { done: false, waitMs: decision.waitMs };\n\t\t}\n\t\tthrow decision.error;\n\t} finally {\n\t\tclearTimeout(timeoutId);\n\t\tunlinkAbort();\n\t}\n};\n\nexport const createRequester = (config: WheraboutsClientConfig): Requester => {\n\tconst resolvedFetch = config.fetch ?? globalThis.fetch;\n\tif (!resolvedFetch) {\n\t\tthrow new Error(\n\t\t\t\"A fetch implementation is required to create the SDK client.\"\n\t\t);\n\t}\n\t// Bind the fetch implementation to globalThis. Internally it is invoked as a\n\t// property of the request context (`ctx.fetchImpl(...)`), which is a method\n\t// call and would otherwise set `this` to that context object. The browser's\n\t// native `fetch` requires `this` to be the global (window/WorkerGlobalScope)\n\t// and throws `TypeError: Illegal invocation` otherwise — so unbound usage\n\t// breaks every request in the browser (Node's fetch tolerates it, hiding the\n\t// bug in tests/SSR). Binding is harmless for user-supplied fetch functions.\n\tconst fetchImpl = resolvedFetch.bind(globalThis);\n\tconst baseUrl = new URL(config.baseUrl ?? DEFAULT_BASE_URL);\n\tconst baseHeaders = createBaseHeaders(config);\n\n\treturn async <T>(opts: RequestOptions): Promise<T> => {\n\t\tconst url = buildRequestUrl(opts.path, baseUrl, opts.query);\n\n\t\tconst headers = buildRequestHeaders(baseHeaders, opts);\n\t\tconst hasBody = opts.body !== undefined;\n\t\tconst body = hasBody ? JSON.stringify(opts.body) : undefined;\n\t\tconst maxRetries =\n\t\t\topts.maxRetries ?? config.maxRetries ?? DEFAULT_MAX_RETRIES;\n\t\tconst timeoutMs = opts.timeoutMs ?? config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\t\t// GET/PUT/DELETE are idempotent; POST is only retry-safe with a key (always\n\t\t// set for writes above), so every request here is retryable by method.\n\t\tconst callerSignal = opts.signal;\n\t\tconst startTime = Date.now();\n\n\t\tlet attempt = 0;\n\t\t// Retry loop: each attempt returns a terminal value or a retry signal with\n\t\t// the backoff to wait. The per-attempt mechanics live in runAttempt.\n\t\twhile (true) {\n\t\t\tconst outcome = await runAttempt<T>({\n\t\t\t\tfetchImpl,\n\t\t\t\turl,\n\t\t\t\tmethod: opts.method,\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tpath: opts.path,\n\t\t\t\tconfig,\n\t\t\t\ttimeoutMs,\n\t\t\t\tcallerSignal,\n\t\t\t\tattempt,\n\t\t\t\tmaxRetries,\n\t\t\t\tstartTime,\n\t\t\t});\n\t\t\tif (outcome.done) {\n\t\t\t\treturn outcome.value;\n\t\t\t}\n\t\t\tattempt++;\n\t\t\tawait sleep(outcome.waitMs, callerSignal);\n\t\t}\n\t};\n};\n","import type { CallOptions, Requester } from \"../shared-types.ts\";\n\nexport interface AddressSuggestion {\n\tcountry: string;\n\tformattedAddress: string;\n\tid: number;\n\tlatitude: number;\n\tlocality: string;\n\tlongitude: number;\n\tpostcode: string;\n\tstate: string;\n\tstreetAddress: string;\n}\n\nexport interface AddressRecord {\n\tbuildingName: string | null;\n\tconfidence: number | null;\n\tcountry: string;\n\tflatNumber: string | null;\n\tflatType: string | null;\n\tgnafPid: string | null;\n\tid: number;\n\tlatitude: number;\n\tlevelNumber: string | null;\n\tlevelType: string | null;\n\tlocality: string;\n\tlongitude: number;\n\tnumberFirst: string | null;\n\tnumberLast: string | null;\n\tpostcode: string;\n\tstate: string;\n\tstreetName: string;\n\tstreetSuffix: string | null;\n\tstreetType: string | null;\n}\n\nexport interface NearbyAddress {\n\tbuildingName: string | null;\n\tcountry: string;\n\tdistance: number;\n\tflatNumber: string | null;\n\tflatType: string | null;\n\tid: number;\n\tlatitude: number;\n\tlocality: string;\n\tlongitude: number;\n\tnumberFirst: string | null;\n\tnumberLast: string | null;\n\tpostcode: string;\n\tstate: string;\n\tstreetName: string;\n\tstreetType: string | null;\n}\n\nexport interface ReverseGeocodeAddress {\n\tconfidence: number | null;\n\tcountry: string;\n\tformattedAddress: string;\n\tid: number;\n\tlatitude: number;\n\tlocality: string;\n\tlongitude: number;\n\tpostcode: string;\n\tstate: string;\n\tstreetAddress: string;\n}\n\nexport interface AutocompleteParams {\n\tcountry?: string;\n\t/** Latitude for proximity boosting (pair with `lng`). */\n\tlat?: number;\n\tlimit?: number;\n\t/** Longitude for proximity boosting (pair with `lat`). Sent to the API as `lon`. */\n\tlng?: number;\n\tq: string;\n\t/**\n\t * Groups a run of keystrokes for one search into a single billable session.\n\t * Generate one stable token per search (e.g. on focus), reuse it across\n\t * keystrokes, and discard it after a result is selected. See `newSessionToken()`.\n\t */\n\tsessionToken?: string;\n\tstate?: string;\n}\n\nexport interface NearbyParams {\n\tcountry?: string;\n\tlat: number;\n\tlimit?: number;\n\tlng: number;\n\tradius?: number;\n}\n\nexport interface ReverseParams {\n\tlat: number;\n\tlng: number;\n}\n\nexport interface AutocompleteResponse {\n\tcount: number;\n\tresults: AddressSuggestion[];\n}\n\nexport interface NearbyResponse {\n\tcount: number;\n\tquery: {\n\t\tlat: number;\n\t\tlng: number;\n\t\tradius: number;\n\t};\n\tresults: NearbyAddress[];\n}\n\nexport interface ReverseResponse {\n\taddress: ReverseGeocodeAddress;\n\tdistance: number;\n\tquery: {\n\t\tlat: number;\n\t\tlng: number;\n\t};\n}\n\nexport interface AddressesResource {\n\tautocomplete(\n\t\tparams: AutocompleteParams,\n\t\toptions?: CallOptions\n\t): Promise<AutocompleteResponse>;\n\tgetById(id: number, options?: CallOptions): Promise<AddressRecord>;\n\tnearby(params: NearbyParams, options?: CallOptions): Promise<NearbyResponse>;\n\treverse(\n\t\tparams: ReverseParams,\n\t\toptions?: CallOptions\n\t): Promise<ReverseResponse>;\n}\n\nexport const createAddresses = (request: Requester): AddressesResource => ({\n\tautocomplete: (params, options) =>\n\t\trequest<AutocompleteResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/addresses/autocomplete\",\n\t\t\tquery: {\n\t\t\t\tq: params.q,\n\t\t\t\tcountry: params.country,\n\t\t\t\tstate: params.state,\n\t\t\t\tlimit: params.limit,\n\t\t\t\t// API uses `lat`/`lon` for autocomplete proximity (nearby uses `lng`).\n\t\t\t\tlat: params.lat,\n\t\t\t\tlon: params.lng,\n\t\t\t\tsessionToken: params.sessionToken,\n\t\t\t},\n\t\t\t...options,\n\t\t}),\n\tgetById: (id, options) =>\n\t\trequest<AddressRecord>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: `/api/v1/addresses/${id}`,\n\t\t\t...options,\n\t\t}),\n\tnearby: (params, options) =>\n\t\trequest<NearbyResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/addresses/nearby\",\n\t\t\tquery: {\n\t\t\t\tlat: params.lat,\n\t\t\t\tlng: params.lng,\n\t\t\t\tradius: params.radius,\n\t\t\t\tlimit: params.limit,\n\t\t\t\tcountry: params.country,\n\t\t\t},\n\t\t\t...options,\n\t\t}),\n\treverse: (params, options) =>\n\t\trequest<ReverseResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/addresses/reverse\",\n\t\t\tquery: { lat: params.lat, lng: params.lng },\n\t\t\t...options,\n\t\t}),\n});\n","import type { CallOptions, Requester } from \"../shared-types.ts\";\n\nexport interface BoundaryCrossing {\n\tevent: \"entry\" | \"exit\";\n\tzoneId: number;\n\tzoneName: string;\n}\n\nexport interface PushLocationBody {\n\tlat: number;\n\tlng: number;\n}\n\nexport interface PushLocationResponse {\n\tcrossings: BoundaryCrossing[];\n\tzones: number[];\n}\n\nexport interface DeviceZonesResponse {\n\tdeviceId: string;\n\tlatitude: number | null;\n\tlongitude: number | null;\n\tupdatedAt: string | null;\n\tzoneIds: number[];\n}\n\nexport interface DevicesResource {\n\tpushLocation(\n\t\tdeviceId: string,\n\t\tbody: PushLocationBody,\n\t\toptions?: CallOptions\n\t): Promise<PushLocationResponse>;\n\tzones(deviceId: string, options?: CallOptions): Promise<DeviceZonesResponse>;\n}\n\nexport const createDevices = (request: Requester): DevicesResource => ({\n\tpushLocation: (deviceId, body, options) =>\n\t\trequest<PushLocationResponse>({\n\t\t\tmethod: \"POST\",\n\t\t\tpath: `/api/v1/devices/${deviceId}/location`,\n\t\t\tbody,\n\t\t\t...options,\n\t\t}),\n\tzones: (deviceId, options) =>\n\t\trequest<DeviceZonesResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: `/api/v1/devices/${deviceId}/zones`,\n\t\t\t...options,\n\t\t}),\n});\n","import type { CallOptions, Requester } from \"../shared-types.ts\";\n\n// ---------------------------------------------------------------------------\n// Forward geocode types\n// ---------------------------------------------------------------------------\n\n/**\n * Params for forward geocoding. Provide `q` for unstructured free-text search,\n * OR `street` + `locality` (plus optional `state`, `postcode`, `country`) for\n * structured mode. Set `structured: \"true\"` when using structured fields.\n */\nexport interface ForwardGeocodeParams {\n\t/** ISO 3166-1 alpha-2 country code, e.g. \"AU\". */\n\tcountry?: string;\n\t/** Suburb / locality (structured mode). */\n\tlocality?: string;\n\t/** Postcode / ZIP. */\n\tpostcode?: string;\n\t/** Free-text address query (unstructured mode). */\n\tq?: string;\n\t/** State abbreviation, e.g. \"NSW\". */\n\tstate?: string;\n\t/** Street address (structured mode). */\n\tstreet?: string;\n\t/** Pass `\"true\"` to enable structured mode. */\n\tstructured?: \"true\" | \"false\";\n}\n\nexport interface GeocodeAddress {\n\tcountry: string;\n\tformattedAddress: string;\n\tid: number;\n\tlatitude: number;\n\tlocality: string;\n\tlongitude: number;\n\tpostcode: string;\n\tstate: string;\n\t/** Combined street line, e.g. \"34 BOXGROVE AVENUE\". */\n\tstreetAddress: string;\n\t/** G-NAF street name without type, e.g. \"BOXGROVE\". */\n\tstreetName: string | null;\n\t/** Street number or \"first-last\" range, e.g. \"34\". */\n\tstreetNumber: string | null;\n\t/** G-NAF street type, e.g. \"AVENUE\". */\n\tstreetType: string | null;\n}\n\nexport interface ForwardGeocodeResponse {\n\taddress: GeocodeAddress;\n\tmatchType: \"structured\" | \"fuzzy\";\n}\n\n// ---------------------------------------------------------------------------\n// Batch geocode types\n// ---------------------------------------------------------------------------\n\nexport interface BatchSubmitBody {\n\taddresses: string[];\n}\n\nexport interface BatchSubmitResponse {\n\tinputCount: number;\n\tjobId: string;\n\tstatus: \"pending\" | \"processing\";\n}\n\nexport interface BatchJobStatus {\n\tcompletedAt: string | null;\n\tdownloadUrl: string | null;\n\terror: string | null;\n\tinputCount: number;\n\tjobId: string;\n\tprocessedCount: number | null;\n\tstatus: \"pending\" | \"processing\" | \"completed\" | \"failed\";\n}\n\nexport interface BatchResultsResponse {\n\tcount: number;\n\tresults: unknown[];\n}\n\n// ---------------------------------------------------------------------------\n// Resource factory\n// ---------------------------------------------------------------------------\n\nexport interface GeocodeResource {\n\tbatch: {\n\t\tsubmit(\n\t\t\tbody: BatchSubmitBody,\n\t\t\toptions?: CallOptions\n\t\t): Promise<BatchSubmitResponse>;\n\t\tpoll(jobId: string, options?: CallOptions): Promise<BatchJobStatus>;\n\t\tresults(\n\t\t\tjobId: string,\n\t\t\toptions?: CallOptions\n\t\t): Promise<BatchResultsResponse>;\n\t};\n\tforward(\n\t\tparams: ForwardGeocodeParams,\n\t\toptions?: CallOptions\n\t): Promise<ForwardGeocodeResponse>;\n}\n\nexport const createGeocode = (request: Requester): GeocodeResource => ({\n\tforward: (params, options) =>\n\t\trequest<ForwardGeocodeResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/addresses/geocode\",\n\t\t\tquery: {\n\t\t\t\tq: params.q,\n\t\t\t\tstructured: params.structured,\n\t\t\t\tstreet: params.street,\n\t\t\t\tlocality: params.locality,\n\t\t\t\tstate: params.state,\n\t\t\t\tpostcode: params.postcode,\n\t\t\t\tcountry: params.country,\n\t\t\t},\n\t\t\t...options,\n\t\t}),\n\tbatch: {\n\t\tsubmit: (body, options) =>\n\t\t\trequest<BatchSubmitResponse>({\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tpath: \"/api/v1/geocode/batch\",\n\t\t\t\tbody,\n\t\t\t\t...options,\n\t\t\t}),\n\t\tpoll: (jobId, options) =>\n\t\t\trequest<BatchJobStatus>({\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tpath: `/api/v1/geocode/batch/${jobId}`,\n\t\t\t\t...options,\n\t\t\t}),\n\t\tresults: (jobId, options) =>\n\t\t\trequest<BatchResultsResponse>({\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tpath: `/api/v1/geocode/batch/${jobId}/results`,\n\t\t\t\t...options,\n\t\t\t}),\n\t},\n});\n","import type { CallOptions, Requester } from \"../shared-types.ts\";\n\nexport interface RegionsClassifyParams {\n\tlat: number;\n\tlayers?: string;\n\tlng: number;\n}\n\nexport interface RegionMatch {\n\tcode: string;\n\tname: string;\n}\n\nexport interface RegionsClassifyResponse {\n\tquery: { lat: number; lng: number };\n\tregions: Record<string, RegionMatch>;\n}\n\nexport interface RegionsResource {\n\tclassify(\n\t\tparams: RegionsClassifyParams,\n\t\toptions?: CallOptions\n\t): Promise<RegionsClassifyResponse>;\n}\n\nexport const createRegions = (request: Requester): RegionsResource => ({\n\tclassify: (params, options) =>\n\t\trequest<RegionsClassifyResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/regions\",\n\t\t\tquery: { lat: params.lat, lng: params.lng, layers: params.layers },\n\t\t\t...options,\n\t\t}),\n});\n","import type { CallOptions, Requester } from \"../shared-types.ts\";\n\nexport type RoutingProfile = \"driving\" | \"walking\" | \"cycling\";\n\nexport interface LatLng {\n\tlat: number;\n\tlng: number;\n}\n\nexport interface DirectionsParams {\n\tfrom?: string;\n\tfromAddressId?: number;\n\tprofile?: RoutingProfile;\n\tto?: string;\n\ttoAddressId?: number;\n}\n\nexport interface DirectionsGeometry {\n\tcoordinates: [number, number][];\n\ttype: \"LineString\";\n}\n\nexport interface IsochronePolygon {\n\tcoordinates: [number, number][][];\n\ttype: \"Polygon\";\n}\n\nexport interface DirectionsResponse {\n\tdistance_m: number;\n\tduration_s: number;\n\tgeometry: DirectionsGeometry;\n\tquery: {\n\t\tfrom: { lat: number; lng: number };\n\t\tprofile: string;\n\t\tto: { lat: number; lng: number };\n\t};\n}\n\n// --- matrix (GET) -----------------------------------------------------------\n\nexport interface MatrixParams {\n\t/** Delimited `\"lat,lng|lat,lng|<addressId>\"` (≤25 points). */\n\tdestinations: string;\n\tprofile?: RoutingProfile;\n\t/** Delimited `\"lat,lng|lat,lng|<addressId>\"` (≤25 points). */\n\tsources: string;\n}\n\nexport interface MatrixResponse {\n\tdestinations: LatLng[];\n\t/** Row-major distances in metres; unreachable cells are `null`. */\n\tdistances: (number | null)[][];\n\t/** Row-major durations in seconds; unreachable cells are `null`. */\n\tdurations: (number | null)[][];\n\tquery: { profile: string };\n\tsources: LatLng[];\n}\n\n// --- isochrone (GET) --------------------------------------------------------\n\nexport interface IsochroneParams {\n\t/** Travel-distance budget in metres (provide exactly one of duration/distance). */\n\tdistanceMeters?: number;\n\t/** Travel-time budget in seconds (provide exactly one of duration/distance). */\n\tdurationSeconds?: number;\n\t/** Also return the ABS regions the isochrone overlaps. */\n\tincludeRegions?: boolean;\n\t/** CSV of region layers to filter the overlap (e.g. `\"sa2,lga\"`). */\n\tlayers?: string;\n\t/** `\"lat,lng\"` or a G-NAF address id (as a string). */\n\torigin?: string;\n\t/** Convenience: a G-NAF address id; mapped to `origin` when `origin` is unset. */\n\toriginAddressId?: number;\n\tprofile?: RoutingProfile;\n}\n\nexport interface IsochroneResponse {\n\tpolygon: IsochronePolygon;\n\tquery: {\n\t\torigin: LatLng;\n\t\tprofile: string;\n\t\tdurationSeconds?: number;\n\t\tdistanceMeters?: number;\n\t};\n\tregions?: Record<string, { code: string; name: string }>;\n}\n\n// --- match (POST) -----------------------------------------------------------\n\nexport interface MatchPoint extends LatLng {\n\t/** GPS accuracy in metres. */\n\tradius?: number;\n\t/** UNIX seconds; all-or-none across points, strictly increasing. */\n\ttimestamp?: number;\n}\n\nexport interface MatchParams {\n\tcoordinates: MatchPoint[];\n\tgaps?: \"split\" | \"ignore\";\n\tprofile?: RoutingProfile;\n\ttidy?: boolean;\n}\n\nexport interface Matching {\n\tconfidence: number;\n\tdistance_m: number;\n\tduration_s: number;\n\tgeometry: DirectionsGeometry;\n}\n\nexport interface Tracepoint {\n\tlocation: [number, number];\n\tmatchings_index: number;\n\twaypoint_index: number;\n}\n\nexport interface MatchResponse {\n\tmatchings: Matching[];\n\tquery: { profile: string };\n\t/** One entry per input point; `null` where OSRM dropped it as an outlier. */\n\ttracepoints: (Tracepoint | null)[];\n}\n\n// --- optimize (POST) --------------------------------------------------------\n\nexport interface OptimizeWaypoint {\n\taddressId?: number;\n\tlat?: number;\n\tlng?: number;\n}\n\nexport interface OptimizeParams {\n\tdestination?: \"any\" | \"last\";\n\tprofile?: RoutingProfile;\n\troundtrip?: boolean;\n\tsource?: \"any\" | \"first\";\n\twaypoints: OptimizeWaypoint[];\n}\n\nexport interface OptimizeTrip {\n\tdistance_m: number;\n\tduration_s: number;\n\tgeometry: DirectionsGeometry;\n}\n\nexport interface OptimizeResponse {\n\tquery: { profile: string; roundtrip: boolean };\n\ttrips: OptimizeTrip[];\n\t/** Each input waypoint with its resolved coords and optimised tour position. */\n\twaypoints: { input_index: number; coords: LatLng; order: number | null }[];\n}\n\nexport interface RoutingResource {\n\tdirections(\n\t\tparams: DirectionsParams,\n\t\toptions?: CallOptions\n\t): Promise<DirectionsResponse>;\n\tisochrone(\n\t\tparams: IsochroneParams,\n\t\toptions?: CallOptions\n\t): Promise<IsochroneResponse>;\n\tmatch(params: MatchParams, options?: CallOptions): Promise<MatchResponse>;\n\tmatrix(params: MatrixParams, options?: CallOptions): Promise<MatrixResponse>;\n\toptimize(\n\t\tparams: OptimizeParams,\n\t\toptions?: CallOptions\n\t): Promise<OptimizeResponse>;\n}\n\nexport const createRouting = (request: Requester): RoutingResource => ({\n\tdirections: (params, options) =>\n\t\trequest<DirectionsResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/routing/directions\",\n\t\t\tquery: {\n\t\t\t\tfrom: params.from,\n\t\t\t\tto: params.to,\n\t\t\t\tfromAddressId: params.fromAddressId,\n\t\t\t\ttoAddressId: params.toAddressId,\n\t\t\t\tprofile: params.profile,\n\t\t\t},\n\t\t\t...options,\n\t\t}),\n\n\tmatrix: (params, options) =>\n\t\trequest<MatrixResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/routing/matrix\",\n\t\t\tquery: {\n\t\t\t\tsources: params.sources,\n\t\t\t\tdestinations: params.destinations,\n\t\t\t\tprofile: params.profile,\n\t\t\t},\n\t\t\t...options,\n\t\t}),\n\n\tisochrone: (params, options) =>\n\t\trequest<IsochroneResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/routing/isochrone\",\n\t\t\tquery: {\n\t\t\t\torigin:\n\t\t\t\t\tparams.origin ??\n\t\t\t\t\t(params.originAddressId === undefined\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: String(params.originAddressId)),\n\t\t\t\tprofile: params.profile,\n\t\t\t\tdurationSeconds: params.durationSeconds,\n\t\t\t\tdistanceMeters: params.distanceMeters,\n\t\t\t\tincludeRegions:\n\t\t\t\t\tparams.includeRegions === undefined\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: String(params.includeRegions),\n\t\t\t\tlayers: params.layers,\n\t\t\t},\n\t\t\t...options,\n\t\t}),\n\n\tmatch: (params, options) =>\n\t\trequest<MatchResponse>({\n\t\t\tmethod: \"POST\",\n\t\t\tpath: \"/api/v1/routing/match\",\n\t\t\tbody: {\n\t\t\t\tprofile: params.profile,\n\t\t\t\tcoordinates: params.coordinates,\n\t\t\t\tgaps: params.gaps,\n\t\t\t\ttidy: params.tidy,\n\t\t\t},\n\t\t\t...options,\n\t\t}),\n\n\toptimize: (params, options) =>\n\t\trequest<OptimizeResponse>({\n\t\t\tmethod: \"POST\",\n\t\t\tpath: \"/api/v1/routing/optimize\",\n\t\t\tbody: {\n\t\t\t\tprofile: params.profile,\n\t\t\t\twaypoints: params.waypoints,\n\t\t\t\troundtrip: params.roundtrip,\n\t\t\t\tsource: params.source,\n\t\t\t\tdestination: params.destination,\n\t\t\t},\n\t\t\t...options,\n\t\t}),\n});\n","import type { CallOptions, Requester } from \"../shared-types.ts\";\n\nexport type WebhookEvent = \"entry\" | \"exit\";\n\nexport interface CreateWebhookBody {\n\tevents?: WebhookEvent[];\n\turl: string;\n\tzoneId?: number;\n}\n\nexport interface WebhookSubscription {\n\tactive: boolean;\n\tcreatedAt: string;\n\tevents: WebhookEvent[];\n\tid: number;\n\turl: string;\n\tzoneId: number | null;\n}\n\nexport interface CreateWebhookResponse extends WebhookSubscription {\n\tsecret: string;\n}\n\nexport interface WebhookListItem extends WebhookSubscription {\n\tfailing: boolean;\n}\n\nexport interface ListWebhooksResponse {\n\tcount: number;\n\tresults: WebhookListItem[];\n}\n\nexport interface DeleteWebhookResponse {\n\tdeleted: true;\n\tid: number;\n}\n\nexport interface ReactivateWebhookResponse {\n\tid: number;\n\treactivated: true;\n}\n\n/** Shape of the JSON body POSTed to your webhook endpoint when a device enters a zone. */\nexport interface WebhookEntryPayload {\n\tdevice: { id: string; lat: number; lng: number };\n\tevent: \"entry\";\n\ttimestamp: string;\n\tzone: { id: number; name: string };\n}\n\n/** Shape of the JSON body POSTed to your webhook endpoint when a device exits a zone. */\nexport interface WebhookExitPayload {\n\tdevice: { id: string; lat: number; lng: number };\n\tevent: \"exit\";\n\ttimestamp: string;\n\tzone: { id: number; name: string };\n}\n\n/** Discriminated union of all inbound webhook event payloads. */\nexport type WebhookEventPayload = WebhookEntryPayload | WebhookExitPayload;\n\nexport interface WebhooksResource {\n\tcreate(\n\t\tbody: CreateWebhookBody,\n\t\toptions?: CallOptions\n\t): Promise<CreateWebhookResponse>;\n\tdelete(id: number, options?: CallOptions): Promise<DeleteWebhookResponse>;\n\tlist(options?: CallOptions): Promise<ListWebhooksResponse>;\n\treactivate(\n\t\tid: number,\n\t\toptions?: CallOptions\n\t): Promise<ReactivateWebhookResponse>;\n}\n\nexport const createWebhooks = (request: Requester): WebhooksResource => ({\n\tcreate: (body, options) =>\n\t\trequest<CreateWebhookResponse>({\n\t\t\tmethod: \"POST\",\n\t\t\tpath: \"/api/v1/webhooks\",\n\t\t\tbody,\n\t\t\t...options,\n\t\t}),\n\tlist: (options) =>\n\t\trequest<ListWebhooksResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/webhooks\",\n\t\t\t...options,\n\t\t}),\n\tdelete: (id, options) =>\n\t\trequest<DeleteWebhookResponse>({\n\t\t\tmethod: \"DELETE\",\n\t\t\tpath: `/api/v1/webhooks/${id}`,\n\t\t\t...options,\n\t\t}),\n\treactivate: (id, options) =>\n\t\trequest<ReactivateWebhookResponse>({\n\t\t\tmethod: \"POST\",\n\t\t\tpath: `/api/v1/webhooks/${id}/reactivate`,\n\t\t\t...options,\n\t\t}),\n});\n","import type { CallOptions, Requester } from \"../shared-types.ts\";\n\n// --- Types ---\n\nexport interface ZoneRecord {\n\tcreatedAt: string;\n\tdescription: string | null;\n\tid: number;\n\tmetadata: Record<string, unknown> | null;\n\tname: string;\n\tprojectId: string;\n\tupdatedAt: string;\n}\n\nexport interface ZoneWithGeometry extends ZoneRecord {\n\tgeometry: {\n\t\ttype: string;\n\t\tcoordinates: number[][][];\n\t};\n}\n\n// --- GeoJSON Polygon geometry ---\n\nexport interface GeoJsonPolygon {\n\tcoordinates: number[][][];\n\ttype: \"Polygon\";\n}\n\n// --- Param interfaces ---\n\nexport interface ZoneListParams {\n\tlimit?: number;\n\tpage?: number;\n}\n\nexport interface ZoneContainsParams {\n\tlat: number;\n\tlng: number;\n}\n\nexport interface ZoneAddressesParams {\n\tlimit?: number;\n\tpage?: number;\n}\n\nexport interface ZoneCreateBody {\n\tdescription?: string;\n\tgeometry: GeoJsonPolygon;\n\tmetadata?: Record<string, unknown>;\n\tname: string;\n}\n\nexport interface ZoneUpdateBody {\n\tdescription?: string;\n\tgeometry?: GeoJsonPolygon;\n\tmetadata?: Record<string, unknown>;\n\tname?: string;\n}\n\n// --- Response interfaces ---\n\nexport interface ZoneListResponse {\n\tcount: number;\n\tpage: number;\n\tzones: ZoneRecord[];\n}\n\nexport interface ZoneDeleteResponse {\n\tsuccess: true;\n}\n\nexport interface ZoneContainsResponse {\n\tcount: number;\n\tquery: { lat: number; lng: number };\n\tzones: ZoneRecord[];\n}\n\nexport interface ZoneAddressesResponse {\n\tcount: number;\n\tquery: { id: number; limit: number; page: number };\n\tresults: Array<{\n\t\tbuildingName: string | null;\n\t\tcountry: string;\n\t\tflatNumber: string | null;\n\t\tflatType: string | null;\n\t\tid: number;\n\t\tlatitude: number;\n\t\tlocality: string;\n\t\tlongitude: number;\n\t\tnumberFirst: string | null;\n\t\tnumberLast: string | null;\n\t\tpostcode: string;\n\t\tstate: string;\n\t\tstreetName: string;\n\t\tstreetType: string | null;\n\t}>;\n\ttruncated: boolean;\n}\n\n// --- Resource interface ---\n\nexport interface ZonesResource {\n\taddresses(\n\t\tid: number,\n\t\tparams?: ZoneAddressesParams,\n\t\toptions?: CallOptions\n\t): Promise<ZoneAddressesResponse>;\n\tcontains(\n\t\tparams: ZoneContainsParams,\n\t\toptions?: CallOptions\n\t): Promise<ZoneContainsResponse>;\n\tcreate(body: ZoneCreateBody, options?: CallOptions): Promise<ZoneRecord>;\n\tdelete(id: number, options?: CallOptions): Promise<ZoneDeleteResponse>;\n\tget(id: number, options?: CallOptions): Promise<ZoneWithGeometry>;\n\tlist(\n\t\tparams?: ZoneListParams,\n\t\toptions?: CallOptions\n\t): Promise<ZoneListResponse>;\n\tpaginate(\n\t\tparams?: ZoneListParams,\n\t\toptions?: CallOptions\n\t): AsyncGenerator<ZoneRecord[], void, unknown>;\n\tupdate(\n\t\tid: number,\n\t\tbody: ZoneUpdateBody,\n\t\toptions?: CallOptions\n\t): Promise<ZoneRecord>;\n}\n\n// --- Factory ---\n\nexport const createZones = (request: Requester): ZonesResource => ({\n\tcreate: (body, options) =>\n\t\trequest<ZoneRecord>({\n\t\t\tmethod: \"POST\",\n\t\t\tpath: \"/api/v1/zones\",\n\t\t\tbody,\n\t\t\t...options,\n\t\t}),\n\n\tlist: (params, options) =>\n\t\trequest<ZoneListResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/zones\",\n\t\t\tquery: { page: params?.page, limit: params?.limit },\n\t\t\t...options,\n\t\t}),\n\n\tasync *paginate(params, options) {\n\t\tlet page = 1;\n\t\tconst limit = params?.limit ?? 50;\n\t\twhile (true) {\n\t\t\tconst res = await request<ZoneListResponse>({\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tpath: \"/api/v1/zones\",\n\t\t\t\tquery: { page, limit },\n\t\t\t\t...options,\n\t\t\t});\n\t\t\tif (res.zones.length === 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tyield res.zones;\n\t\t\tif (res.zones.length < limit) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tpage++;\n\t\t}\n\t},\n\n\tget: (id, options) =>\n\t\trequest<ZoneWithGeometry>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: `/api/v1/zones/${id}`,\n\t\t\t...options,\n\t\t}),\n\n\tupdate: (id, body, options) =>\n\t\trequest<ZoneRecord>({\n\t\t\tmethod: \"PUT\",\n\t\t\tpath: `/api/v1/zones/${id}`,\n\t\t\tbody,\n\t\t\t...options,\n\t\t}),\n\n\tdelete: (id, options) =>\n\t\trequest<ZoneDeleteResponse>({\n\t\t\tmethod: \"DELETE\",\n\t\t\tpath: `/api/v1/zones/${id}`,\n\t\t\t...options,\n\t\t}),\n\n\tcontains: (params, options) =>\n\t\trequest<ZoneContainsResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: \"/api/v1/zones/contains\",\n\t\t\tquery: { lat: params.lat, lng: params.lng },\n\t\t\t...options,\n\t\t}),\n\n\taddresses: (id, params, options) =>\n\t\trequest<ZoneAddressesResponse>({\n\t\t\tmethod: \"GET\",\n\t\t\tpath: `/api/v1/zones/${id}/addresses`,\n\t\t\tquery: { page: params?.page, limit: params?.limit },\n\t\t\t...options,\n\t\t}),\n});\n","import { createRequester } from \"./http.ts\";\nimport {\n\ttype AddressesResource,\n\tcreateAddresses,\n} from \"./resources/addresses.ts\";\nimport { createDevices, type DevicesResource } from \"./resources/devices.ts\";\nimport { createGeocode, type GeocodeResource } from \"./resources/geocode.ts\";\nimport { createRegions, type RegionsResource } from \"./resources/regions.ts\";\nimport { createRouting, type RoutingResource } from \"./resources/routing.ts\";\nimport { createWebhooks, type WebhooksResource } from \"./resources/webhooks.ts\";\nimport { createZones, type ZonesResource } from \"./resources/zones.ts\";\nimport type { WheraboutsClientConfig } from \"./shared-types.ts\";\n\nexport interface WheraboutsClient {\n\taddresses: AddressesResource;\n\tdevices: DevicesResource;\n\tgeocode: GeocodeResource;\n\tregions: RegionsResource;\n\trouting: RoutingResource;\n\twebhooks: WebhooksResource;\n\tzones: ZonesResource;\n}\n\nexport const createWheraboutsClient = (\n\tconfig: WheraboutsClientConfig\n): WheraboutsClient => {\n\tconst request = createRequester(config);\n\treturn {\n\t\taddresses: createAddresses(request),\n\t\tgeocode: createGeocode(request),\n\t\tzones: createZones(request),\n\t\tdevices: createDevices(request),\n\t\twebhooks: createWebhooks(request),\n\t\tregions: createRegions(request),\n\t\trouting: createRouting(request),\n\t};\n};\n","// Dependency-free geo convenience helpers. Wherabouts records expose flat\n// `latitude`/`longitude`; map UIs and GeoJSON want different shapes. These save\n// consumers from reshaping by hand (mirrors use-places-autocomplete's\n// getLatLng/getZipCode utilities).\n\nexport interface LatLng {\n\tlat: number;\n\tlng: number;\n}\n\ninterface HasCoords {\n\tlatitude: number;\n\tlongitude: number;\n}\n\n/** `{ latitude, longitude }` → `{ lat, lng }` (e.g. for Leaflet/Google Maps). */\nexport function getLatLng(point: HasCoords): LatLng {\n\treturn { lat: point.latitude, lng: point.longitude };\n}\n\n/** `{ latitude, longitude }` → `[lng, lat]` (GeoJSON / MapLibre coordinate order). */\nexport function toLngLat(point: HasCoords): [number, number] {\n\treturn [point.longitude, point.latitude];\n}\n\n// Resolve ISO 3166-1 country codes to display names via the platform Intl data —\n// full international coverage with zero maintenance. Lazily constructed and\n// cached per locale so repeated calls are cheap.\nconst regionDisplayCache = new Map<string, Intl.DisplayNames | null>();\n\nfunction regionDisplayNames(locale: string): Intl.DisplayNames | null {\n\tconst cached = regionDisplayCache.get(locale);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\tconst instance =\n\t\ttypeof Intl !== \"undefined\" && \"DisplayNames\" in Intl\n\t\t\t? new Intl.DisplayNames([locale], { type: \"region\" })\n\t\t\t: null;\n\tregionDisplayCache.set(locale, instance);\n\treturn instance;\n}\n\n/**\n * ISO 3166-1 country code → display name (e.g. `\"US\"` → `\"United States\"`,\n * `\"IS\"` → `\"Iceland\"`). Falls back to the raw code when `Intl.DisplayNames`\n * is unavailable or the code is malformed. Defaults to English; pass a BCP-47\n * `locale` for localized names.\n */\nexport function countryName(code: string, locale = \"en\"): string {\n\tif (!code) {\n\t\treturn code;\n\t}\n\ttry {\n\t\treturn regionDisplayNames(locale)?.of(code.toUpperCase()) ?? code;\n\t} catch {\n\t\t// of() throws RangeError on malformed codes — keep the raw value.\n\t\treturn code;\n\t}\n}\n\nconst EARTH_RADIUS_M = 6_371_000;\nconst DEG = Math.PI / 180;\n\n/**\n * Great-circle distance in metres between two points (haversine). Handy for\n * client-side \"how far is this result\" without a round-trip.\n */\nexport function distanceMeters(a: HasCoords, b: HasCoords): number {\n\tconst dLat = (b.latitude - a.latitude) * DEG;\n\tconst dLng = (b.longitude - a.longitude) * DEG;\n\tconst lat1 = a.latitude * DEG;\n\tconst lat2 = b.latitude * DEG;\n\tconst h =\n\t\tMath.sin(dLat / 2) ** 2 +\n\t\tMath.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) ** 2;\n\treturn Math.round(2 * EARTH_RADIUS_M * Math.asin(Math.sqrt(h)));\n}\n","import { WheraboutsApiError } from \"./errors.ts\";\n\n/**\n * Narrow an unknown thrown value to `WheraboutsApiError`. Uses `instanceof`\n * with a `name`-based fallback so it still works if two copies of the SDK are\n * loaded (e.g. duplicate dep versions), where `instanceof` can fail.\n */\nexport function isWheraboutsApiError(\n\terror: unknown\n): error is WheraboutsApiError {\n\tif (error instanceof WheraboutsApiError) {\n\t\treturn true;\n\t}\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t(error as { name?: unknown }).name === \"WheraboutsApiError\" &&\n\t\ttypeof (error as { status?: unknown }).status === \"number\"\n\t);\n}\n\n/** True when the error is a rate-limit response (HTTP 429 / `rate_limited`). */\nexport function isRateLimitError(error: unknown): error is WheraboutsApiError {\n\treturn (\n\t\tisWheraboutsApiError(error) &&\n\t\t(error.status === 429 || error.code === \"rate_limited\")\n\t);\n}\n\n/** True when the error is a client-side validation/bad-request (HTTP 4xx). */\nexport function isClientError(error: unknown): error is WheraboutsApiError {\n\treturn (\n\t\tisWheraboutsApiError(error) && error.status >= 400 && error.status < 500\n\t);\n}\n","/**\n * Generate a session token for grouping a run of autocomplete keystrokes into\n * one billable search (cf. Google Places session tokens). Create one per search\n * (e.g. on input focus), pass it on every `addresses.autocomplete` call for that\n * search, and discard it once the user selects a result.\n *\n * Uses `crypto.randomUUID()` where available, with a non-cryptographic fallback\n * (a token only needs to be unique per search, not unguessable).\n */\nexport function newSessionToken(): string {\n\tconst c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n\tif (c && typeof c.randomUUID === \"function\") {\n\t\treturn c.randomUUID();\n\t}\n\treturn `wst_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n}\n"]}