@resira/sdk 0.4.6 → 0.4.8
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/CHANGELOG.md +60 -51
- package/README.md +210 -210
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -5
- package/dist/index.d.ts +93 -5
- package/dist/index.js.map +1 -1
- package/package.json +47 -47
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/routing.ts","../src/client.ts"],"names":["url"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ApiErrorBody } from \"./types.js\";\n\n// ═══════════════════════════════════════════════════════════════\n// Base error\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Base error class for all SDK errors.\n *\n * Use `instanceof` checks to distinguish error types:\n *\n * ```ts\n * try { … } catch (e) {\n * if (e instanceof ResiraRateLimitError) { … }\n * if (e instanceof ResiraApiError) { … }\n * if (e instanceof ResiraNetworkError) { … }\n * }\n * ```\n */\nexport class ResiraError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ResiraError\";\n // Fix prototype chain for instanceof to work after transpilation\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n// ═══════════════════════════════════════════════════════════════\n// API error (4xx / 5xx with a parsed body)\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Thrown when the API returns a non-2xx response with a JSON body.\n *\n * ```ts\n * err.status // 400, 404, 409, 422, 500, …\n * err.code // HTTP status text (e.g. \"Not Found\")\n * err.body // Parsed `{ error: \"…\" }` from the server\n * ```\n */\nexport class ResiraApiError extends ResiraError {\n /** HTTP status code. */\n readonly status: number;\n /** HTTP status text (e.g. `\"Bad Request\"`). */\n readonly code: string;\n /** Parsed error body from the API. */\n readonly body: ApiErrorBody;\n /** The full `Response` object (headers are still accessible). */\n readonly response: Response;\n\n constructor(status: number, code: string, body: ApiErrorBody, response: Response) {\n super(body.error || `API error ${status}`);\n this.name = \"ResiraApiError\";\n this.status = status;\n this.code = code;\n this.body = body;\n this.response = response;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n /** Whether this error is retryable (5xx or 429). */\n get retryable(): boolean {\n return this.status === 429 || this.status >= 500;\n }\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Rate limit error (429)\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Thrown when the API returns 429 Too Many Requests.\n *\n * ```ts\n * err.retryAfter // Seconds until the client should retry\n * ```\n */\nexport class ResiraRateLimitError extends ResiraApiError {\n /** Seconds to wait before retrying (from `Retry-After` header). */\n readonly retryAfter: number;\n\n constructor(body: ApiErrorBody, response: Response) {\n super(429, \"Too Many Requests\", body, response);\n this.name = \"ResiraRateLimitError\";\n this.retryAfter =\n body.retryAfter ??\n (Number.parseInt(response.headers.get(\"retry-after\") ?? \"60\", 10) ||\n 60);\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Network error (fetch failed, DNS, timeout, etc.)\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Thrown when the request never reached the server.\n *\n * This wraps the underlying `TypeError` or `DOMException` from\n * `fetch()` failures (DNS resolution, TLS, network offline, etc.).\n */\nexport class ResiraNetworkError extends ResiraError {\n /** The original error thrown by `fetch`. */\n readonly cause: unknown;\n\n constructor(message: string, cause: unknown) {\n super(message);\n this.name = \"ResiraNetworkError\";\n this.cause = cause;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import type { ResiraConfig, WeightedBaseUrl } from \"./types.js\";\n\ninterface ResolvedBaseUrl {\n url: string;\n weight: number;\n}\n\nconst DEFAULT_LOCAL_BASE_URLS: ResolvedBaseUrl[] = [\n { url: \"http://localhost:3001\", weight: 100 },\n];\n\nconst DEFAULT_PRODUCTION_BASE_URLS: ResolvedBaseUrl[] = [\n { url: \"https://api.resira.app\", weight: 100 },\n];\n\nfunction readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\") return undefined;\n return process.env?.[name];\n}\n\n\nfunction normalizeUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\");\n}\n\nfunction isPositiveNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0;\n}\n\nfunction toResolvedBaseUrl(value: string | WeightedBaseUrl): ResolvedBaseUrl | null {\n if (typeof value === \"string\") {\n const url = normalizeUrl(value);\n return url ? { url, weight: 1 } : null;\n }\n\n const url = normalizeUrl(value.url);\n if (!url) return null;\n\n return {\n url,\n weight: isPositiveNumber(value.weight) ? value.weight : 1,\n };\n}\n\nfunction parseJsonBaseUrls(value: string): ResolvedBaseUrl[] {\n const parsed = JSON.parse(value) as unknown;\n if (!Array.isArray(parsed)) return [];\n\n return parsed.flatMap((entry) => {\n const resolved =\n typeof entry === \"string\"\n ? toResolvedBaseUrl(entry)\n : entry && typeof entry === \"object\"\n ? toResolvedBaseUrl(entry as WeightedBaseUrl)\n : null;\n\n return resolved ? [resolved] : [];\n });\n}\n\nfunction parseDelimitedBaseUrls(value: string): ResolvedBaseUrl[] {\n return value\n .split(\",\")\n .flatMap((entry) => {\n const [rawUrl, rawWeight] = entry.split(\"|\");\n const url = normalizeUrl(rawUrl ?? \"\");\n if (!url) return [];\n\n const parsedWeight = rawWeight ? Number(rawWeight.trim()) : 1;\n return [{\n url,\n weight: isPositiveNumber(parsedWeight) ? parsedWeight : 1,\n }];\n });\n}\n\nfunction parseEnvBaseUrls(value: string | undefined): ResolvedBaseUrl[] {\n if (!value) return [];\n\n try {\n const parsed = parseJsonBaseUrls(value);\n if (parsed.length > 0) return parsed;\n } catch {\n // Fall back to delimiter parsing.\n }\n\n return parseDelimitedBaseUrls(value);\n}\n\nexport function resolveBaseUrls(config: ResiraConfig): ResolvedBaseUrl[] {\n if (config.baseUrl) {\n return [{ url: normalizeUrl(config.baseUrl), weight: 100 }];\n }\n\n if (config.baseUrls?.length) {\n const explicit = config.baseUrls.flatMap((entry) => {\n const resolved = toResolvedBaseUrl(entry);\n return resolved ? [resolved] : [];\n });\n\n if (explicit.length > 0) return explicit;\n }\n\n const envBaseUrls = parseEnvBaseUrls(readEnv(\"RESIRA_API_BASE_URLS\"));\n if (envBaseUrls.length > 0) {\n return envBaseUrls;\n }\n\n if (readEnv(\"NODE_ENV\") === \"development\") {\n return DEFAULT_LOCAL_BASE_URLS;\n }\n\n return DEFAULT_PRODUCTION_BASE_URLS;\n}\n\nexport function pickBaseUrl(baseUrls: ResolvedBaseUrl[]): string {\n return baseUrls[0]?.url ?? DEFAULT_PRODUCTION_BASE_URLS[0].url;\n}\n\nexport function getRoutingStats(): Record<string, never> {\n return {};\n}","import { ResiraApiError, ResiraNetworkError, ResiraRateLimitError } from \"./errors.js\";\nimport { pickBaseUrl, resolveBaseUrls } from \"./routing.js\";\nimport type {\n ApiErrorBody,\n Availability,\n AvailabilityParams,\n CheckoutSessionResponse,\n ConfirmPaymentRequest,\n ConfirmPaymentResponse,\n CreateCheckoutSessionRequest,\n CreateCheckoutSessionResponse,\n CreatePaymentIntentRequest,\n CreateReservationRequest,\n Dish,\n DishListResponse,\n DishResponse,\n ListReservationsParams,\n PaginatedReservations,\n PaymentIntentResponse,\n ProductListResponse,\n PropertyConfig,\n Reservation,\n ReservationResponse,\n ResiraConfig,\n ResourceListResponse,\n ValidatePromoCodeResponse,\n} from \"./types.js\";\n\n// ═══════════════════════════════════════════════════════════════\n// Constants\n// ═══════════════════════════════════════════════════════════════\n\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_RETRY_BASE_DELAY = 500; // ms\nconst API_PREFIX = \"/v1/public\";\n\n// ═══════════════════════════════════════════════════════════════\n// Helpers\n// ═══════════════════════════════════════════════════════════════\n\n/** Generate a random UUID v4 for idempotency keys. */\nfunction uuid(): string {\n // Use crypto.randomUUID when available (Node 19+, all modern browsers)\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n // Fallback: manual v4 UUID\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n\n/** Build a query string from a flat params object. Skips `undefined` values. */\nfunction toQueryString(params: Record<string, string | number | boolean | undefined>): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n }\n }\n return parts.length > 0 ? `?${parts.join(\"&\")}` : \"\";\n}\n\n/** Sleep for `ms` milliseconds. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Convert camelCase keys to snake_case for query parameters.\n * The API expects snake_case query params (`start_date`, `party_size`).\n */\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/** Convert an object's keys from camelCase to snake_case. */\nfunction keysToSnake(\n obj: Record<string, string | number | boolean | undefined>,\n): Record<string, string | number | boolean | undefined> {\n const result: Record<string, string | number | boolean | undefined> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[camelToSnake(key)] = value;\n }\n return result;\n}\n\n/** Convert snake_case string to camelCase. */\nfunction snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\n/** Deep-convert all keys in an object/array from camelCase to snake_case. */\nfunction deepKeysToSnake(obj: unknown): unknown {\n if (Array.isArray(obj)) return obj.map(deepKeysToSnake);\n if (obj !== null && typeof obj === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[camelToSnake(key)] = deepKeysToSnake(value);\n }\n return result;\n }\n return obj;\n}\n\n/** Deep-convert all keys in an object/array from snake_case to camelCase. */\nfunction deepKeysToCamel(obj: unknown): unknown {\n if (Array.isArray(obj)) return obj.map(deepKeysToCamel);\n if (obj !== null && typeof obj === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[snakeToCamel(key)] = deepKeysToCamel(value);\n }\n return result;\n }\n return obj;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Client\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Resira SDK client.\n *\n * ```ts\n * const resira = new Resira({\n * apiKey: \"resira_live_abc123…\",\n * baseUrl: \"https://api.example.com\", // optional\n * });\n *\n * const availability = await resira.getAvailability(\"prop-1\", {\n * startDate: \"2026-07-01\",\n * endDate: \"2026-07-07\",\n * });\n * ```\n */\nexport class Resira {\n private readonly apiKey: string;\n private readonly baseUrls: ReturnType<typeof resolveBaseUrls>;\n private readonly maxRetries: number;\n private readonly retryBaseDelay: number;\n private readonly _fetch: typeof globalThis.fetch;\n\n constructor(config: ResiraConfig) {\n if (!config.apiKey) {\n throw new Error(\"Resira: apiKey is required\");\n }\n this.apiKey = config.apiKey;\n this.baseUrls = resolveBaseUrls(config);\n this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n this.retryBaseDelay = config.retryBaseDelay ?? DEFAULT_RETRY_BASE_DELAY;\n this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /** The resolved API origin used by this client instance. */\n getBaseUrl(): string {\n return pickBaseUrl(this.baseUrls);\n }\n\n // ─────────────────────────────────────────────────────────────\n // Public API methods\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Fetch the public property configuration.\n *\n * Returns non-sensitive settings such as the Stripe publishable\n * key, deposit percentage, currency, and branding info.\n *\n * ```ts\n * const config = await resira.getConfig();\n * console.log(config.stripePublishableKey); // \"pk_test_…\"\n * ```\n */\n async getConfig(): Promise<PropertyConfig> {\n return this.request<PropertyConfig>(\"GET\", \"/config\");\n }\n\n /**\n * Validate a promo/discount code.\n *\n * Returns discount details if valid, or an error message if not.\n *\n * ```ts\n * const result = await resira.validatePromoCode(\"SUMMER20\");\n * if (result.valid) {\n * console.log(result.discountType, result.discountValue);\n * }\n * ```\n */\n async validatePromoCode(code: string): Promise<ValidatePromoCodeResponse> {\n try {\n const raw = await this.request<Record<string, unknown>>(\n \"POST\",\n \"/promo-codes/validate\",\n { code },\n );\n const data = deepKeysToCamel(raw) as Record<string, unknown>;\n return {\n valid: true,\n discountType: data.discountType as \"percent\" | \"fixed\" | undefined,\n discountValue: data.discountValue as number | undefined,\n currency: data.currency as string | undefined,\n minOrderCents: data.minOrderCents as number | undefined,\n };\n } catch (err: unknown) {\n // 4xx errors mean invalid code\n if (\n err &&\n typeof err === \"object\" &&\n \"status\" in err &&\n (err as { status: number }).status < 500\n ) {\n const apiErr = err as { body?: { error?: string } };\n return {\n valid: false,\n error: apiErr.body?.error ?? \"Invalid promo code\",\n };\n }\n throw err;\n }\n }\n\n /**\n * List all active resources for the organization.\n *\n * Returns resource cards with name, description, price, duration,\n * image, and type — suitable for building a resource picker.\n *\n * ```ts\n * const { resources } = await resira.listResources();\n * ```\n */\n async listResources(): Promise<ResourceListResponse> {\n return this.request<ResourceListResponse>(\"GET\", \"/resources\");\n }\n\n /**\n * Query availability for a resource.\n *\n * **Properties** (date-based):\n * ```ts\n * await resira.getAvailability(\"prop-1\", {\n * startDate: \"2026-07-01\",\n * endDate: \"2026-07-07\",\n * });\n * ```\n *\n * **Restaurants** (time-slot):\n * ```ts\n * await resira.getAvailability(\"table-5\", {\n * date: \"2026-07-01\",\n * partySize: 4,\n * });\n * ```\n *\n * Omit params to get all blocked dates (for calendar rendering).\n */\n async getAvailability(\n resourceId: string,\n params: AvailabilityParams = {},\n ): Promise<Availability> {\n if (!resourceId) {\n throw new Error(\"resourceId is required for getAvailability\");\n }\n const qs = toQueryString(keysToSnake(params as Record<string, string | number | undefined>));\n return this.request<Availability>(\n \"GET\",\n `/resources/${encodeURIComponent(resourceId)}/availability${qs}`,\n );\n }\n\n /**\n * Query availability for a product/service.\n *\n * Aggregates capacity across all linked equipment. If a product\n * has 2 jet skis (each capacity=1), slots show capacity: 2.\n * Both pending and confirmed reservations count as occupied.\n *\n * ```ts\n * await resira.getProductAvailability(\"prod-123\", {\n * date: \"2026-07-01\",\n * durationMinutes: 30,\n * });\n * ```\n */\n async getProductAvailability(\n productId: string,\n params: AvailabilityParams = {},\n ): Promise<Availability> {\n if (!productId) {\n throw new Error(\"productId is required for getProductAvailability\");\n }\n const qs = toQueryString(keysToSnake(params as Record<string, string | number | undefined>));\n return this.request<Availability>(\n \"GET\",\n `/products/${encodeURIComponent(productId)}/availability${qs}`,\n );\n }\n\n /**\n * Create a reservation.\n *\n * Uses `POST /v2/api/reservations` — the `resourceId` is sent in\n * the request body, **not** in the URL path.\n *\n * An `Idempotency-Key` header is automatically attached so that\n * retries (including those from exponential backoff) are safe.\n *\n * ```ts\n * const { reservation } = await resira.createReservation({\n * resourceId: \"prop-1\",\n * guestName: \"Jane Doe\",\n * guestEmail: \"jane@example.com\",\n * startDate: \"2026-07-01\",\n * endDate: \"2026-07-07\",\n * partySize: 3,\n * });\n * ```\n */\n async createReservation(\n payload: CreateReservationRequest,\n options?: { idempotencyKey?: string },\n ): Promise<ReservationResponse> {\n if (!payload.resourceId) {\n throw new Error(\"resourceId is required for createReservation\");\n }\n const idempotencyKey = options?.idempotencyKey ?? uuid();\n\n // Note: uses /v2/api prefix, not /v1/public\n const url = `${this.getBaseUrl()}/v2/api/reservations`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"Idempotency-Key\": idempotencyKey,\n };\n\n const init: RequestInit = {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n };\n\n let lastError: ResiraApiError | ResiraNetworkError | ResiraRateLimitError | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n const backoff = this.calculateBackoff(attempt, lastError);\n await sleep(backoff);\n }\n\n let response: Response;\n try {\n response = await this._fetch(url, init);\n } catch (err) {\n lastError = new ResiraNetworkError(\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\n err,\n );\n continue;\n }\n\n if (response.ok) {\n const raw = (await response.json()) as Record<string, unknown>;\n // The API may nest under \"reservation\" or \"booking\" depending on endpoint\n const resData = (raw.reservation ?? raw.booking ?? {}) as Record<string, unknown>;\n\n // Augment with request data: API response doesn't include\n // startTime/endTime/startDate/endDate/resourceId for v2 reservations\n const reservation: Reservation = {\n id: (resData.id as string) ?? \"\",\n resourceId: (resData.resourceId as string) ?? payload.resourceId,\n status: (resData.status as string) ?? \"pending\",\n startDate: (resData.startDate as string) ?? payload.startDate,\n endDate: (resData.endDate as string) ?? payload.endDate,\n startTime: (resData.startTime as string) ?? payload.startTime,\n endTime: (resData.endTime as string) ?? payload.endTime,\n startDatetime: (resData.startDatetime as string) ?? payload.startTime,\n endDatetime: (resData.endDatetime as string) ?? payload.endTime,\n guestName: (resData.guestName as string) ?? payload.guestName,\n partySize: (resData.partySize as number) ?? (resData.guests as number) ?? payload.partySize ?? 2,\n totalPrice: (resData.totalPrice as number) ?? 0,\n currency: (resData.currency as string) ?? \"EUR\",\n createdAt: (resData.createdAt as string) ?? new Date().toISOString(),\n };\n\n return { reservation };\n }\n\n let errorBody: ApiErrorBody;\n try {\n errorBody = (await response.json()) as ApiErrorBody;\n } catch {\n errorBody = { error: response.statusText || `HTTP ${response.status}` };\n }\n\n if (response.status === 429) {\n lastError = new ResiraRateLimitError(errorBody, response);\n continue;\n }\n\n if (response.status >= 500) {\n lastError = new ResiraApiError(response.status, response.statusText, errorBody, response);\n continue;\n }\n\n throw new ResiraApiError(response.status, response.statusText, errorBody, response);\n }\n\n throw lastError!;\n }\n\n /**\n * List reservations for a resource (paginated).\n *\n * ```ts\n * const page = await resira.listReservations(\"prop-1\", {\n * status: \"confirmed\",\n * page: 1,\n * limit: 50,\n * });\n * console.log(page.data); // Reservation[]\n * console.log(page.totalPages); // number\n * ```\n */\n async listReservations(\n resourceId: string,\n params: ListReservationsParams = {},\n ): Promise<PaginatedReservations> {\n const qs = toQueryString(params as Record<string, string | number | undefined>);\n return this.request<PaginatedReservations>(\n \"GET\",\n `/resources/${encodeURIComponent(resourceId)}/reservations${qs}`,\n );\n }\n\n /**\n * Get a single reservation by ID.\n *\n * ```ts\n * const { reservation } = await resira.getReservation(\"prop-1\", \"res-uuid\");\n * ```\n */\n async getReservation(\n resourceId: string,\n reservationId: string,\n ): Promise<ReservationResponse> {\n return this.request<ReservationResponse>(\n \"GET\",\n `/resources/${encodeURIComponent(resourceId)}/reservations/${encodeURIComponent(reservationId)}`,\n );\n }\n\n /**\n * List all active products/services for the organisation.\n *\n * Calls `GET /v1/public/products` which returns products with\n * pricing, duration, and linked equipment.\n *\n * Falls back to mapping resources → products if the endpoint\n * returns 404 (backend hasn't been updated yet).\n *\n * ```ts\n * const { products } = await resira.listProducts();\n * ```\n */\n async listProducts(): Promise<ProductListResponse> {\n try {\n return await this.request<ProductListResponse>(\"GET\", \"/products\");\n } catch (err: unknown) {\n // Fallback: if /products endpoint doesn't exist yet (404),\n // map resources → products shape\n if (\n err &&\n typeof err === \"object\" &&\n \"status\" in err &&\n (err as { status: number }).status === 404\n ) {\n const resourceResponse = await this.listResources();\n const products = resourceResponse.resources.map((r) => ({\n id: r.id,\n name: r.name,\n description: r.description,\n durationMinutes: r.durationMinutes ?? 60,\n priceCents: r.pricePerSession ?? 0,\n currency: r.currency ?? \"EUR\",\n imageUrl: r.imageUrl,\n active: r.active,\n sortOrder: 0,\n pricingModel: \"per_session\" as const,\n equipmentIds: [r.id],\n equipmentNames: [r.name],\n }));\n return { products, count: products.length };\n }\n throw err;\n }\n }\n\n /**\n * List all dishes with 3D model data for the organisation.\n *\n * Returns dishes with name, description, price, image, and\n * 3D model URLs for AR/preview rendering.\n *\n * ```ts\n * const { dishes } = await resira.listDishes();\n * ```\n */\n async listDishes(): Promise<DishListResponse> {\n return this.request<DishListResponse>(\"GET\", \"/dishes\");\n }\n\n /**\n * Get a single dish by ID.\n *\n * ```ts\n * const { dish } = await resira.getDish(\"dish-uuid\");\n * console.log(dish.name, dish.model?.glbUrl);\n * ```\n */\n async getDish(dishId: string): Promise<DishResponse> {\n if (!dishId) {\n throw new Error(\"dishId is required for getDish\");\n }\n return this.request<DishResponse>(\n \"GET\",\n `/dishes/${encodeURIComponent(dishId)}`,\n );\n }\n\n /**\n * Retrieve a checkout session by its token.\n *\n * Used to hydrate the checkout screen when opening the widget\n * with a pre-created session token (skip service selection).\n *\n * ```ts\n * const { session } = await resira.getCheckoutSession(\"cs_ab12cd34ef56\");\n * console.log(session.productName, session.priceCents);\n * ```\n */\n async getCheckoutSession(token: string): Promise<CheckoutSessionResponse> {\n if (!token) {\n throw new Error(\"token is required for getCheckoutSession\");\n }\n const url = `${this.getBaseUrl()}/v2/public/checkout-sessions/${encodeURIComponent(token)}`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: \"application/json\",\n };\n\n let lastError: ResiraApiError | ResiraNetworkError | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n const backoff = this.calculateBackoff(attempt, lastError);\n await sleep(backoff);\n }\n\n let response: Response;\n try {\n response = await this._fetch(url, { method: \"GET\", headers });\n } catch (err) {\n lastError = new ResiraNetworkError(\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\n err,\n );\n continue;\n }\n\n if (response.ok) {\n const raw = await response.json();\n return deepKeysToCamel(raw) as CheckoutSessionResponse;\n }\n\n let errorBody: ApiErrorBody;\n try {\n errorBody = (await response.json()) as ApiErrorBody;\n } catch {\n errorBody = { error: response.statusText || `HTTP ${response.status}` };\n }\n\n if (response.status === 429) {\n lastError = new ResiraRateLimitError(errorBody, response);\n continue;\n }\n if (response.status >= 500) {\n lastError = new ResiraApiError(response.status, response.statusText, errorBody, response);\n continue;\n }\n\n throw new ResiraApiError(response.status, response.statusText, errorBody, response);\n }\n\n throw lastError!;\n }\n\n /**\n * Create a new checkout session.\n *\n * External sites can create a session with product, slot, and guest\n * details, then pass the returned token to the widget to skip\n * directly to checkout.\n *\n * ```ts\n * const { sessionToken } = await resira.createCheckoutSession({\n * productId: \"prod-123\",\n * durationMinutes: 30,\n * partySize: 2,\n * date: \"2026-07-01\",\n * startTime: \"2026-07-01T10:00:00Z\",\n * endTime: \"2026-07-01T10:30:00Z\",\n * });\n * ```\n */\n async createCheckoutSession(\n payload: CreateCheckoutSessionRequest,\n options?: { idempotencyKey?: string },\n ): Promise<CreateCheckoutSessionResponse> {\n const idempotencyKey = options?.idempotencyKey ?? uuid();\n const url = `${this.getBaseUrl()}/v2/public/checkout-sessions`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"Idempotency-Key\": idempotencyKey,\n };\n\n const init: RequestInit = {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n };\n\n let lastError: ResiraApiError | ResiraNetworkError | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n const backoff = this.calculateBackoff(attempt, lastError);\n await sleep(backoff);\n }\n\n let response: Response;\n try {\n response = await this._fetch(url, init);\n } catch (err) {\n lastError = new ResiraNetworkError(\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\n err,\n );\n continue;\n }\n\n if (response.ok) {\n const raw = await response.json();\n return deepKeysToCamel(raw) as CreateCheckoutSessionResponse;\n }\n\n let errorBody: ApiErrorBody;\n try {\n errorBody = (await response.json()) as ApiErrorBody;\n } catch {\n errorBody = { error: response.statusText || `HTTP ${response.status}` };\n }\n\n if (response.status === 429) {\n lastError = new ResiraRateLimitError(errorBody, response);\n continue;\n }\n if (response.status >= 500) {\n lastError = new ResiraApiError(response.status, response.statusText, errorBody, response);\n continue;\n }\n\n throw new ResiraApiError(response.status, response.statusText, errorBody, response);\n }\n\n throw lastError!;\n }\n\n /**\n * Create a Stripe payment intent for a booking.\n *\n * The server creates the payment intent, calculates the amount,\n * and returns a `clientSecret` to confirm payment on the frontend\n * using Stripe Elements.\n *\n * ```ts\n * const { clientSecret, amountNow, amountAtVenue } =\n * await resira.createPaymentIntent({\n * productId: \"prod-123\",\n * resourceId: \"res-456\",\n * partySize: 2,\n * startDate: \"2026-07-01\",\n * startTime: \"2026-07-01T10:00:00Z\",\n * endTime: \"2026-07-01T11:00:00Z\",\n * guestName: \"Jane Doe\",\n * guestEmail: \"jane@example.com\",\n * });\n * ```\n */\n async createPaymentIntent(\n payload: CreatePaymentIntentRequest,\n options?: { idempotencyKey?: string },\n ): Promise<PaymentIntentResponse> {\n const idempotencyKey = options?.idempotencyKey ?? uuid();\n const raw = await this.request<Record<string, unknown>>(\n \"POST\",\n \"/payments/create-intent\",\n payload,\n { \"Idempotency-Key\": idempotencyKey },\n );\n // Normalize response keys to camelCase\n const data = deepKeysToCamel(raw) as Record<string, unknown>;\n // Map backend field names to SDK field names:\n // backend: amountDue, totalPrice\n // SDK: amountNow, totalAmount, amountAtVenue\n const totalAmount = (data.totalAmount as number) ?? (data.totalPrice as number) ?? 0;\n const amountNow = (data.amountNow as number) ?? (data.amountDue as number) ?? totalAmount;\n const amountAtVenue = (data.amountAtVenue as number) ?? (totalAmount - amountNow);\n return {\n clientSecret: data.clientSecret as string,\n paymentIntentId: data.paymentIntentId as string,\n amountNow,\n amountAtVenue,\n totalAmount,\n currency: (data.currency as string) ?? \"EUR\",\n paymentOption: data.paymentOption as string | undefined,\n reservationId: data.reservationId as string | undefined,\n discountAmount: (data.discountAmount as number) ?? undefined,\n originalPrice: (data.originalPrice as number) ?? undefined,\n promoCodeApplied: (data.promoCodeApplied as string) ?? undefined,\n };\n }\n\n /**\n * Confirm that a payment was successful after the guest\n * completes the Stripe payment flow.\n *\n * This transitions the reservation from `pending` to `confirmed`.\n *\n * ```ts\n * const { reservation, paymentStatus } =\n * await resira.confirmPayment({\n * paymentIntentId: \"pi_xxx\",\n * reservationId: \"res-uuid\",\n * });\n * ```\n */\n async confirmPayment(\n payload: ConfirmPaymentRequest,\n ): Promise<ConfirmPaymentResponse> {\n const raw = await this.request<Record<string, unknown>>(\n \"POST\",\n \"/payments/confirm\",\n payload,\n );\n // Normalize response keys to camelCase in case backend returns snake_case\n return deepKeysToCamel(raw) as ConfirmPaymentResponse;\n }\n\n // ─────────────────────────────────────────────────────────────\n // Internal HTTP layer\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Execute an HTTP request with retry logic and error normalization.\n *\n * - Attaches `Authorization: Bearer <apiKey>` on every request.\n * - Retries on 429 and 5xx with exponential backoff + jitter.\n * - Parses error bodies and throws typed error classes.\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<T> {\n const url = `${this.getBaseUrl()}${API_PREFIX}${path}`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: \"application/json\",\n ...extraHeaders,\n };\n\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const init: RequestInit = {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n };\n\n let lastError: ResiraApiError | ResiraNetworkError | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n // ── Wait before retry ────────────────────────────────\n if (attempt > 0) {\n const backoff = this.calculateBackoff(attempt, lastError);\n await sleep(backoff);\n }\n\n // ── Execute the request ──────────────────────────────\n let response: Response;\n try {\n response = await this._fetch(url, init);\n } catch (err) {\n lastError = new ResiraNetworkError(\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\n err,\n );\n // Network errors are always retryable\n continue;\n }\n\n // ── Success ──────────────────────────────────────────\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n // ── Parse error body ─────────────────────────────────\n let errorBody: ApiErrorBody;\n try {\n errorBody = (await response.json()) as ApiErrorBody;\n } catch {\n errorBody = { error: response.statusText || `HTTP ${response.status}` };\n }\n\n // ── Rate limit ───────────────────────────────────────\n if (response.status === 429) {\n lastError = new ResiraRateLimitError(errorBody, response);\n // Always retry 429s (up to maxRetries)\n continue;\n }\n\n // ── Server error (5xx) — retryable ───────────────────\n if (response.status >= 500) {\n lastError = new ResiraApiError(\n response.status,\n response.statusText,\n errorBody,\n response,\n );\n continue;\n }\n\n // ── Client error (4xx) — NOT retryable ───────────────\n throw new ResiraApiError(\n response.status,\n response.statusText,\n errorBody,\n response,\n );\n }\n\n // All retries exhausted — throw the last error\n throw lastError!;\n }\n\n /**\n * Calculate backoff delay in milliseconds for a given retry attempt.\n *\n * Uses exponential backoff with full jitter:\n * delay = random(0, base * 2^attempt)\n *\n * For 429 responses, respects the `Retry-After` header as a minimum.\n */\n private calculateBackoff(\n attempt: number,\n lastError?: ResiraApiError | ResiraNetworkError,\n ): number {\n const exponential = this.retryBaseDelay * 2 ** (attempt - 1);\n const jittered = Math.random() * exponential;\n\n // If the server told us to wait, use that as the floor\n if (lastError instanceof ResiraRateLimitError) {\n const serverDelay = lastError.retryAfter * 1000;\n return Math.max(serverDelay, jittered);\n }\n\n return jittered;\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/routing.ts","../src/client.ts"],"names":["url"],"mappings":";;;AAmBO,IAAM,WAAA,GAAN,cAA0B,KAAA,CAAM;AAAA,EACrC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAEZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AACF;AAeO,IAAM,cAAA,GAAN,cAA6B,WAAA,CAAY;AAAA,EAU9C,WAAA,CAAY,MAAA,EAAgB,IAAA,EAAc,IAAA,EAAoB,QAAA,EAAoB;AAChF,IAAA,KAAA,CAAM,IAAA,CAAK,KAAA,IAAS,CAAA,UAAA,EAAa,MAAM,CAAA,CAAE,CAAA;AACzC,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,IAAI,SAAA,GAAqB;AACvB,IAAA,OAAO,IAAA,CAAK,MAAA,KAAW,GAAA,IAAO,IAAA,CAAK,MAAA,IAAU,GAAA;AAAA,EAC/C;AACF;AAaO,IAAM,oBAAA,GAAN,cAAmC,cAAA,CAAe;AAAA,EAIvD,WAAA,CAAY,MAAoB,QAAA,EAAoB;AAClD,IAAA,KAAA,CAAM,GAAA,EAAK,mBAAA,EAAqB,IAAA,EAAM,QAAQ,CAAA;AAC9C,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AACZ,IAAA,IAAA,CAAK,UAAA,GACH,IAAA,CAAK,UAAA,KACJ,MAAA,CAAO,QAAA,CAAS,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA,IAAK,IAAA,EAAM,EAAE,CAAA,IAChE,EAAA,CAAA;AACF,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AACF;AAYO,IAAM,kBAAA,GAAN,cAAiC,WAAA,CAAY;AAAA,EAIlD,WAAA,CAAY,SAAiB,KAAA,EAAgB;AAC3C,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AACZ,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AACF;;;AC1GA,IAAM,uBAAA,GAA6C;AAAA,EACjD,EAAE,GAAA,EAAK,uBAAA,EAAyB,MAAA,EAAQ,GAAA;AAC1C,CAAA;AAEA,IAAM,4BAAA,GAAkD;AAAA,EACtD,EAAE,GAAA,EAAK,wBAAA,EAA0B,MAAA,EAAQ,GAAA;AAC3C,CAAA;AAEA,SAAS,QAAQ,IAAA,EAAkC;AACjD,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,EAAa,OAAO,MAAA;AAC3C,EAAA,OAAO,OAAA,CAAQ,MAAM,IAAI,CAAA;AAC3B;AAGA,SAAS,aAAa,GAAA,EAAqB;AACzC,EAAA,OAAO,GAAA,CAAI,IAAA,EAAK,CAAE,OAAA,CAAQ,QAAQ,EAAE,CAAA;AACtC;AAEA,SAAS,iBAAiB,KAAA,EAAiC;AACzD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,QAAA,CAAS,KAAK,KAAK,KAAA,GAAQ,CAAA;AACxE;AAEA,SAAS,kBAAkB,KAAA,EAAyD;AAClF,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAMA,IAAAA,GAAM,aAAa,KAAK,CAAA;AAC9B,IAAA,OAAOA,OAAM,EAAE,GAAA,EAAAA,IAAAA,EAAK,MAAA,EAAQ,GAAE,GAAI,IAAA;AAAA,EACpC;AAEA,EAAA,MAAM,GAAA,GAAM,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA;AAClC,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AAEjB,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,QAAQ,gBAAA,CAAiB,KAAA,CAAM,MAAM,CAAA,GAAI,MAAM,MAAA,GAAS;AAAA,GAC1D;AACF;AAEA,SAAS,kBAAkB,KAAA,EAAkC;AAC3D,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AAC/B,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,SAAU,EAAC;AAEpC,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,KAAU;AAC/B,IAAA,MAAM,QAAA,GACJ,OAAO,KAAA,KAAU,QAAA,GACb,iBAAA,CAAkB,KAAK,CAAA,GACvB,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,GACxB,iBAAA,CAAkB,KAAwB,CAAA,GAC1C,IAAA;AAER,IAAA,OAAO,QAAA,GAAW,CAAC,QAAQ,CAAA,GAAI,EAAC;AAAA,EAClC,CAAC,CAAA;AACH;AAEA,SAAS,uBAAuB,KAAA,EAAkC;AAChE,EAAA,OAAO,MACJ,KAAA,CAAM,GAAG,CAAA,CACT,OAAA,CAAQ,CAAC,KAAA,KAAU;AAClB,IAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,KAAA,CAAM,MAAM,GAAG,CAAA;AAC3C,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,MAAA,IAAU,EAAE,CAAA;AACrC,IAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAC;AAElB,IAAA,MAAM,eAAe,SAAA,GAAY,MAAA,CAAO,SAAA,CAAU,IAAA,EAAM,CAAA,GAAI,CAAA;AAC5D,IAAA,OAAO,CAAC;AAAA,MACN,GAAA;AAAA,MACA,MAAA,EAAQ,gBAAA,CAAiB,YAAY,CAAA,GAAI,YAAA,GAAe;AAAA,KACzD,CAAA;AAAA,EACH,CAAC,CAAA;AACL;AAEA,SAAS,iBAAiB,KAAA,EAA8C;AACtE,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAC;AAEpB,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,kBAAkB,KAAK,CAAA;AACtC,IAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,MAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,OAAO,uBAAuB,KAAK,CAAA;AACrC;AAEO,SAAS,gBAAgB,MAAA,EAAyC;AACvE,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAO,CAAC,EAAE,GAAA,EAAK,YAAA,CAAa,OAAO,OAAO,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAK,CAAA;AAAA,EAC5D;AAEA,EAAA,IAAI,MAAA,CAAO,UAAU,MAAA,EAAQ;AAC3B,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,CAAC,KAAA,KAAU;AAClD,MAAA,MAAM,QAAA,GAAW,kBAAkB,KAAK,CAAA;AACxC,MAAA,OAAO,QAAA,GAAW,CAAC,QAAQ,CAAA,GAAI,EAAC;AAAA,IAClC,CAAC,CAAA;AAED,IAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,OAAO,QAAA;AAAA,EAClC;AAEA,EAAA,MAAM,WAAA,GAAc,gBAAA,CAAiB,OAAA,CAAQ,sBAAsB,CAAC,CAAA;AACpE,EAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC1B,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAA,CAAQ,UAAU,CAAA,KAAM,aAAA,EAAe;AACzC,IAAA,OAAO,uBAAA;AAAA,EACT;AAEA,EAAA,OAAO,4BAAA;AACT;AAEO,SAAS,YAAY,QAAA,EAAqC;AAC/D,EAAA,OAAO,SAAS,CAAC,CAAA,EAAG,GAAA,IAAO,4BAAA,CAA6B,CAAC,CAAA,CAAE,GAAA;AAC7D;AAEO,SAAS,eAAA,GAAyC;AACvD,EAAA,OAAO,EAAC;AACV;;;ACzFA,IAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAM,wBAAA,GAA2B,GAAA;AACjC,IAAM,UAAA,GAAa,YAAA;AAOnB,SAAS,IAAA,GAAe;AAEtB,EAAA,IAAI,OAAO,UAAA,CAAW,MAAA,EAAQ,UAAA,KAAe,UAAA,EAAY;AACvD,IAAA,OAAO,UAAA,CAAW,OAAO,UAAA,EAAW;AAAA,EACtC;AAEA,EAAA,OAAO,sCAAA,CAAuC,OAAA,CAAQ,OAAA,EAAS,CAAC,CAAA,KAAM;AACpE,IAAA,MAAM,CAAA,GAAK,IAAA,CAAK,MAAA,EAAO,GAAI,EAAA,GAAM,CAAA;AACjC,IAAA,OAAA,CAAQ,MAAM,GAAA,GAAM,CAAA,GAAK,IAAI,CAAA,GAAO,CAAA,EAAK,SAAS,EAAE,CAAA;AAAA,EACtD,CAAC,CAAA;AACH;AAGA,SAAS,cAAc,MAAA,EAAuE;AAC5F,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACjD,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,kBAAA,CAAmB,GAAG,CAAC,CAAA,CAAA,EAAI,kBAAA,CAAmB,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,IAC9E;AAAA,EACF;AACA,EAAA,OAAO,KAAA,CAAM,SAAS,CAAA,GAAI,CAAA,CAAA,EAAI,MAAM,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,GAAK,EAAA;AACpD;AAGA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;AAMA,SAAS,aAAa,GAAA,EAAqB;AACzC,EAAA,OAAO,GAAA,CAAI,QAAQ,QAAA,EAAU,CAAC,WAAW,CAAA,CAAA,EAAI,MAAA,CAAO,WAAA,EAAa,CAAA,CAAE,CAAA;AACrE;AAGA,SAAS,YACP,GAAA,EACuD;AACvD,EAAA,MAAM,SAAgE,EAAC;AACvE,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AAC9C,IAAA,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,GAAI,KAAA;AAAA,EAC9B;AACA,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,aAAa,GAAA,EAAqB;AACzC,EAAA,OAAO,GAAA,CAAI,QAAQ,WAAA,EAAa,CAAC,GAAG,MAAA,KAAW,MAAA,CAAO,aAAa,CAAA;AACrE;AAgBA,SAAS,gBAAgB,GAAA,EAAuB;AAC9C,EAAA,IAAI,MAAM,OAAA,CAAQ,GAAG,GAAG,OAAO,GAAA,CAAI,IAAI,eAAe,CAAA;AACtD,EAAA,IAAI,GAAA,KAAQ,IAAA,IAAQ,OAAO,GAAA,KAAQ,QAAA,EAAU;AAC3C,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,GAA8B,CAAA,EAAG;AACzE,MAAA,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,GAAI,gBAAgB,KAAK,CAAA;AAAA,IACnD;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,GAAA;AACT;AAqBO,IAAM,SAAN,MAAa;AAAA,EAOlB,YAAY,MAAA,EAAsB;AAChC,IAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AACA,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,QAAA,GAAW,gBAAgB,MAAM,CAAA;AACtC,IAAA,IAAA,CAAK,UAAA,GAAa,OAAO,UAAA,IAAc,mBAAA;AACvC,IAAA,IAAA,CAAK,cAAA,GAAiB,OAAO,cAAA,IAAkB,wBAAA;AAC/C,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,KAAA,IAAS,UAAA,CAAW,KAAA,CAAM,KAAK,UAAU,CAAA;AAAA,EAChE;AAAA;AAAA,EAGA,UAAA,GAAqB;AACnB,IAAA,OAAO,WAAA,CAAY,KAAK,QAAQ,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,SAAA,GAAqC;AACzC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAwB,KAAA,EAAO,SAAS,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,kBAAkB,IAAA,EAAkD;AACxE,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA;AAAA,QACrB,MAAA;AAAA,QACA,uBAAA;AAAA,QACA,EAAE,IAAA;AAAK,OACT;AACA,MAAA,MAAM,IAAA,GAAO,gBAAgB,GAAG,CAAA;AAChC,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,IAAA;AAAA,QACP,cAAc,IAAA,CAAK,YAAA;AAAA,QACnB,eAAe,IAAA,CAAK,aAAA;AAAA,QACpB,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,eAAe,IAAA,CAAK;AAAA,OACtB;AAAA,IACF,SAAS,GAAA,EAAc;AAErB,MAAA,IACE,GAAA,IACA,OAAO,GAAA,KAAQ,QAAA,IACf,YAAY,GAAA,IACX,GAAA,CAA2B,SAAS,GAAA,EACrC;AACA,QAAA,MAAM,MAAA,GAAS,GAAA;AACf,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,KAAA;AAAA,UACP,KAAA,EAAO,MAAA,CAAO,IAAA,EAAM,KAAA,IAAS;AAAA,SAC/B;AAAA,MACF;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,aAAA,GAA+C;AACnD,IAAA,OAAO,IAAA,CAAK,OAAA,CAA8B,KAAA,EAAO,YAAY,CAAA;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,MAAM,eAAA,CACJ,UAAA,EACA,MAAA,GAA6B,EAAC,EACP;AACvB,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,MAAM,4CAA4C,CAAA;AAAA,IAC9D;AACA,IAAA,MAAM,EAAA,GAAK,aAAA,CAAc,WAAA,CAAY,MAAqD,CAAC,CAAA;AAC3F,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,KAAA;AAAA,MACA,CAAA,WAAA,EAAc,kBAAA,CAAmB,UAAU,CAAC,gBAAgB,EAAE,CAAA;AAAA,KAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,sBAAA,CACJ,SAAA,EACA,MAAA,GAA6B,EAAC,EACP;AACvB,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,IACpE;AACA,IAAA,MAAM,EAAA,GAAK,aAAA,CAAc,WAAA,CAAY,MAAqD,CAAC,CAAA;AAC3F,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,KAAA;AAAA,MACA,CAAA,UAAA,EAAa,kBAAA,CAAmB,SAAS,CAAC,gBAAgB,EAAE,CAAA;AAAA,KAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,iBAAA,CACJ,OAAA,EACA,OAAA,EAC8B;AAC9B,IAAA,IAAI,CAAC,QAAQ,UAAA,EAAY;AACvB,MAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,IAChE;AACA,IAAA,MAAM,cAAA,GAAiB,OAAA,EAAS,cAAA,IAAkB,IAAA,EAAK;AAGvD,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,UAAA,EAAY,CAAA,oBAAA,CAAA;AAEhC,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,MACpC,MAAA,EAAQ,kBAAA;AAAA,MACR,cAAA,EAAgB,kBAAA;AAAA,MAChB,iBAAA,EAAmB;AAAA,KACrB;AAEA,IAAA,MAAM,IAAA,GAAoB;AAAA,MACxB,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC9B;AAEA,IAAA,IAAI,SAAA;AAEJ,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,IAAA,CAAK,YAAY,OAAA,EAAA,EAAW;AAC3D,MAAA,IAAI,UAAU,CAAA,EAAG;AACf,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,gBAAA,CAAiB,OAAA,EAAS,SAAS,CAAA;AACxD,QAAA,MAAM,MAAM,OAAO,CAAA;AAAA,MACrB;AAEA,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,GAAA,EAAK,IAAI,CAAA;AAAA,MACxC,SAAS,GAAA,EAAK;AACZ,QAAA,SAAA,GAAY,IAAI,kBAAA;AAAA,UACd,2BAA2B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,UAC3E;AAAA,SACF;AACA,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,SAAS,EAAA,EAAI;AACf,QAAA,MAAM,GAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,QAAA,MAAM,OAAA,GAAW,GAAA,CAAI,WAAA,IAAe,GAAA,CAAI,WAAW,EAAC;AAIpD,QAAA,MAAM,WAAA,GAA2B;AAAA,UAC/B,EAAA,EAAK,QAAQ,EAAA,IAAiB,EAAA;AAAA,UAC9B,UAAA,EAAa,OAAA,CAAQ,UAAA,IAAyB,OAAA,CAAQ,UAAA;AAAA,UACtD,MAAA,EAAS,QAAQ,MAAA,IAAqB,SAAA;AAAA,UACtC,SAAA,EAAY,OAAA,CAAQ,SAAA,IAAwB,OAAA,CAAQ,SAAA;AAAA,UACpD,OAAA,EAAU,OAAA,CAAQ,OAAA,IAAsB,OAAA,CAAQ,OAAA;AAAA,UAChD,SAAA,EAAY,OAAA,CAAQ,SAAA,IAAwB,OAAA,CAAQ,SAAA;AAAA,UACpD,OAAA,EAAU,OAAA,CAAQ,OAAA,IAAsB,OAAA,CAAQ,OAAA;AAAA,UAChD,aAAA,EAAgB,OAAA,CAAQ,aAAA,IAA4B,OAAA,CAAQ,SAAA;AAAA,UAC5D,WAAA,EAAc,OAAA,CAAQ,WAAA,IAA0B,OAAA,CAAQ,OAAA;AAAA,UACxD,SAAA,EAAY,OAAA,CAAQ,SAAA,IAAwB,OAAA,CAAQ,SAAA;AAAA,UACpD,WAAY,OAAA,CAAQ,SAAA,IAAyB,OAAA,CAAQ,MAAA,IAAqB,QAAQ,SAAA,IAAa,CAAA;AAAA,UAC/F,UAAA,EAAa,QAAQ,UAAA,IAAyB,CAAA;AAAA,UAC9C,QAAA,EAAW,QAAQ,QAAA,IAAuB,KAAA;AAAA,UAC1C,WAAY,OAAA,CAAQ,SAAA,IAAA,iBAAwB,IAAI,IAAA,IAAO,WAAA;AAAY,SACrE;AAEA,QAAA,OAAO,EAAE,WAAA,EAAY;AAAA,MACvB;AAEA,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI;AACF,QAAA,SAAA,GAAa,MAAM,SAAS,IAAA,EAAK;AAAA,MACnC,CAAA,CAAA,MAAQ;AACN,QAAA,SAAA,GAAY,EAAE,KAAA,EAAO,QAAA,CAAS,cAAc,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA,EAAG;AAAA,MACxE;AAEA,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,QAAA,SAAA,GAAY,IAAI,oBAAA,CAAqB,SAAA,EAAW,QAAQ,CAAA;AACxD,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,QAAA,CAAS,UAAU,GAAA,EAAK;AAC1B,QAAA,SAAA,GAAY,IAAI,cAAA,CAAe,QAAA,CAAS,QAAQ,QAAA,CAAS,UAAA,EAAY,WAAW,QAAQ,CAAA;AACxF,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAI,cAAA,CAAe,QAAA,CAAS,QAAQ,QAAA,CAAS,UAAA,EAAY,WAAW,QAAQ,CAAA;AAAA,IACpF;AAEA,IAAA,MAAM,SAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,gBAAA,CACJ,UAAA,EACA,MAAA,GAAiC,EAAC,EACF;AAChC,IAAA,MAAM,EAAA,GAAK,cAAc,MAAqD,CAAA;AAC9E,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,KAAA;AAAA,MACA,CAAA,WAAA,EAAc,kBAAA,CAAmB,UAAU,CAAC,gBAAgB,EAAE,CAAA;AAAA,KAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cAAA,CACJ,UAAA,EACA,aAAA,EAC8B;AAC9B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,KAAA;AAAA,MACA,cAAc,kBAAA,CAAmB,UAAU,CAAC,CAAA,cAAA,EAAiB,kBAAA,CAAmB,aAAa,CAAC,CAAA;AAAA,KAChG;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,YAAA,GAA6C;AACjD,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,OAAA,CAA6B,KAAA,EAAO,WAAW,CAAA;AAAA,IACnE,SAAS,GAAA,EAAc;AAGrB,MAAA,IACE,GAAA,IACA,OAAO,GAAA,KAAQ,QAAA,IACf,YAAY,GAAA,IACX,GAAA,CAA2B,WAAW,GAAA,EACvC;AACA,QAAA,MAAM,gBAAA,GAAmB,MAAM,IAAA,CAAK,aAAA,EAAc;AAClD,QAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,UACtD,IAAI,CAAA,CAAE,EAAA;AAAA,UACN,MAAM,CAAA,CAAE,IAAA;AAAA,UACR,aAAa,CAAA,CAAE,WAAA;AAAA,UACf,eAAA,EAAiB,EAAE,eAAA,IAAmB,EAAA;AAAA,UACtC,UAAA,EAAY,EAAE,eAAA,IAAmB,CAAA;AAAA,UACjC,QAAA,EAAU,EAAE,QAAA,IAAY,KAAA;AAAA,UACxB,UAAU,CAAA,CAAE,QAAA;AAAA,UACZ,QAAQ,CAAA,CAAE,MAAA;AAAA,UACV,SAAA,EAAW,CAAA;AAAA,UACX,YAAA,EAAc,aAAA;AAAA,UACd,YAAA,EAAc,CAAC,CAAA,CAAE,EAAE,CAAA;AAAA,UACnB,cAAA,EAAgB,CAAC,CAAA,CAAE,IAAI;AAAA,SACzB,CAAE,CAAA;AACF,QAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,QAAA,CAAS,MAAA,EAAO;AAAA,MAC5C;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,UAAA,GAAwC;AAC5C,IAAA,OAAO,IAAA,CAAK,OAAA,CAA0B,KAAA,EAAO,SAAS,CAAA;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QAAQ,MAAA,EAAuC;AACnD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,IAClD;AACA,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,KAAA;AAAA,MACA,CAAA,QAAA,EAAW,kBAAA,CAAmB,MAAM,CAAC,CAAA;AAAA,KACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,mBAAmB,KAAA,EAAiD;AACxE,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,IAC5D;AACA,IAAA,MAAM,GAAA,GAAM,GAAG,IAAA,CAAK,UAAA,EAAY,CAAA,6BAAA,EAAgC,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AAEzF,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,MACpC,MAAA,EAAQ;AAAA,KACV;AAEA,IAAA,IAAI,SAAA;AAEJ,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,IAAA,CAAK,YAAY,OAAA,EAAA,EAAW;AAC3D,MAAA,IAAI,UAAU,CAAA,EAAG;AACf,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,gBAAA,CAAiB,OAAA,EAAS,SAAS,CAAA;AACxD,QAAA,MAAM,MAAM,OAAO,CAAA;AAAA,MACrB;AAEA,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,MAAM,KAAK,MAAA,CAAO,GAAA,EAAK,EAAE,MAAA,EAAQ,KAAA,EAAO,SAAS,CAAA;AAAA,MAC9D,SAAS,GAAA,EAAK;AACZ,QAAA,SAAA,GAAY,IAAI,kBAAA;AAAA,UACd,2BAA2B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,UAC3E;AAAA,SACF;AACA,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,SAAS,EAAA,EAAI;AACf,QAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,IAAA,EAAK;AAChC,QAAA,OAAO,gBAAgB,GAAG,CAAA;AAAA,MAC5B;AAEA,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI;AACF,QAAA,SAAA,GAAa,MAAM,SAAS,IAAA,EAAK;AAAA,MACnC,CAAA,CAAA,MAAQ;AACN,QAAA,SAAA,GAAY,EAAE,KAAA,EAAO,QAAA,CAAS,cAAc,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA,EAAG;AAAA,MACxE;AAEA,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,QAAA,SAAA,GAAY,IAAI,oBAAA,CAAqB,SAAA,EAAW,QAAQ,CAAA;AACxD,QAAA;AAAA,MACF;AACA,MAAA,IAAI,QAAA,CAAS,UAAU,GAAA,EAAK;AAC1B,QAAA,SAAA,GAAY,IAAI,cAAA,CAAe,QAAA,CAAS,QAAQ,QAAA,CAAS,UAAA,EAAY,WAAW,QAAQ,CAAA;AACxF,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAI,cAAA,CAAe,QAAA,CAAS,QAAQ,QAAA,CAAS,UAAA,EAAY,WAAW,QAAQ,CAAA;AAAA,IACpF;AAEA,IAAA,MAAM,SAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,qBAAA,CACJ,OAAA,EACA,OAAA,EACwC;AACxC,IAAA,MAAM,cAAA,GAAiB,OAAA,EAAS,cAAA,IAAkB,IAAA,EAAK;AACvD,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,UAAA,EAAY,CAAA,4BAAA,CAAA;AAEhC,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,MACpC,MAAA,EAAQ,kBAAA;AAAA,MACR,cAAA,EAAgB,kBAAA;AAAA,MAChB,iBAAA,EAAmB;AAAA,KACrB;AAEA,IAAA,MAAM,IAAA,GAAoB;AAAA,MACxB,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC9B;AAEA,IAAA,IAAI,SAAA;AAEJ,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,IAAA,CAAK,YAAY,OAAA,EAAA,EAAW;AAC3D,MAAA,IAAI,UAAU,CAAA,EAAG;AACf,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,gBAAA,CAAiB,OAAA,EAAS,SAAS,CAAA;AACxD,QAAA,MAAM,MAAM,OAAO,CAAA;AAAA,MACrB;AAEA,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,GAAA,EAAK,IAAI,CAAA;AAAA,MACxC,SAAS,GAAA,EAAK;AACZ,QAAA,SAAA,GAAY,IAAI,kBAAA;AAAA,UACd,2BAA2B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,UAC3E;AAAA,SACF;AACA,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,SAAS,EAAA,EAAI;AACf,QAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,IAAA,EAAK;AAChC,QAAA,OAAO,gBAAgB,GAAG,CAAA;AAAA,MAC5B;AAEA,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI;AACF,QAAA,SAAA,GAAa,MAAM,SAAS,IAAA,EAAK;AAAA,MACnC,CAAA,CAAA,MAAQ;AACN,QAAA,SAAA,GAAY,EAAE,KAAA,EAAO,QAAA,CAAS,cAAc,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA,EAAG;AAAA,MACxE;AAEA,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,QAAA,SAAA,GAAY,IAAI,oBAAA,CAAqB,SAAA,EAAW,QAAQ,CAAA;AACxD,QAAA;AAAA,MACF;AACA,MAAA,IAAI,QAAA,CAAS,UAAU,GAAA,EAAK;AAC1B,QAAA,SAAA,GAAY,IAAI,cAAA,CAAe,QAAA,CAAS,QAAQ,QAAA,CAAS,UAAA,EAAY,WAAW,QAAQ,CAAA;AACxF,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAI,cAAA,CAAe,QAAA,CAAS,QAAQ,QAAA,CAAS,UAAA,EAAY,WAAW,QAAQ,CAAA;AAAA,IACpF;AAEA,IAAA,MAAM,SAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,MAAM,mBAAA,CACJ,OAAA,EACA,OAAA,EACgC;AAChC,IAAA,MAAM,cAAA,GAAiB,OAAA,EAAS,cAAA,IAAkB,IAAA,EAAK;AACvD,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA;AAAA,MACrB,MAAA;AAAA,MACA,yBAAA;AAAA,MACA,OAAA;AAAA,MACA,EAAE,mBAAmB,cAAA;AAAe,KACtC;AAEA,IAAA,MAAM,IAAA,GAAO,gBAAgB,GAAG,CAAA;AAIhC,IAAA,MAAM,WAAA,GAAe,IAAA,CAAK,WAAA,IAA2B,IAAA,CAAK,UAAA,IAAyB,CAAA;AACnF,IAAA,MAAM,SAAA,GAAa,IAAA,CAAK,SAAA,IAAyB,IAAA,CAAK,SAAA,IAAwB,WAAA;AAC9E,IAAA,MAAM,aAAA,GAAiB,IAAA,CAAK,aAAA,IAA6B,WAAA,GAAc,SAAA;AACvE,IAAA,OAAO;AAAA,MACL,cAAc,IAAA,CAAK,YAAA;AAAA,MACnB,iBAAiB,IAAA,CAAK,eAAA;AAAA,MACtB,SAAA;AAAA,MACA,aAAA;AAAA,MACA,WAAA;AAAA,MACA,QAAA,EAAW,KAAK,QAAA,IAAuB,KAAA;AAAA,MACvC,eAAe,IAAA,CAAK,aAAA;AAAA,MACpB,eAAe,IAAA,CAAK,aAAA;AAAA,MACpB,cAAA,EAAiB,KAAK,cAAA,IAA6B,MAAA;AAAA,MACnD,aAAA,EAAgB,KAAK,aAAA,IAA4B,MAAA;AAAA,MACjD,gBAAA,EAAmB,KAAK,gBAAA,IAA+B;AAAA,KACzD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,eACJ,OAAA,EACiC;AACjC,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA;AAAA,MACrB,MAAA;AAAA,MACA,mBAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,gBAAgB,GAAG,CAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAc,OAAA,CACZ,MAAA,EACA,IAAA,EACA,MACA,YAAA,EACY;AACZ,IAAA,MAAM,GAAA,GAAM,GAAG,IAAA,CAAK,UAAA,EAAY,CAAA,EAAG,UAAU,GAAG,IAAI,CAAA,CAAA;AAEpD,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,MACpC,MAAA,EAAQ,kBAAA;AAAA,MACR,GAAG;AAAA,KACL;AAEA,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAAA,IAC5B;AAEA,IAAA,MAAM,IAAA,GAAoB;AAAA,MACxB,MAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAM,IAAA,KAAS,MAAA,GAAY,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GAAI;AAAA,KACpD;AAEA,IAAA,IAAI,SAAA;AAEJ,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,IAAA,CAAK,YAAY,OAAA,EAAA,EAAW;AAE3D,MAAA,IAAI,UAAU,CAAA,EAAG;AACf,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,gBAAA,CAAiB,OAAA,EAAS,SAAS,CAAA;AACxD,QAAA,MAAM,MAAM,OAAO,CAAA;AAAA,MACrB;AAGA,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,GAAA,EAAK,IAAI,CAAA;AAAA,MACxC,SAAS,GAAA,EAAK;AACZ,QAAA,SAAA,GAAY,IAAI,kBAAA;AAAA,UACd,2BAA2B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,UAC3E;AAAA,SACF;AAEA,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,SAAS,EAAA,EAAI;AACf,QAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,MAC9B;AAGA,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI;AACF,QAAA,SAAA,GAAa,MAAM,SAAS,IAAA,EAAK;AAAA,MACnC,CAAA,CAAA,MAAQ;AACN,QAAA,SAAA,GAAY,EAAE,KAAA,EAAO,QAAA,CAAS,cAAc,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA,EAAG;AAAA,MACxE;AAGA,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,QAAA,SAAA,GAAY,IAAI,oBAAA,CAAqB,SAAA,EAAW,QAAQ,CAAA;AAExD,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,QAAA,CAAS,UAAU,GAAA,EAAK;AAC1B,QAAA,SAAA,GAAY,IAAI,cAAA;AAAA,UACd,QAAA,CAAS,MAAA;AAAA,UACT,QAAA,CAAS,UAAA;AAAA,UACT,SAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,IAAI,cAAA;AAAA,QACR,QAAA,CAAS,MAAA;AAAA,QACT,QAAA,CAAS,UAAA;AAAA,QACT,SAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAGA,IAAA,MAAM,SAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,gBAAA,CACN,SACA,SAAA,EACQ;AACR,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,cAAA,GAAiB,CAAA,KAAM,OAAA,GAAU,CAAA,CAAA;AAC1D,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,EAAO,GAAI,WAAA;AAGjC,IAAA,IAAI,qBAAqB,oBAAA,EAAsB;AAC7C,MAAA,MAAM,WAAA,GAAc,UAAU,UAAA,GAAa,GAAA;AAC3C,MAAA,OAAO,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,QAAQ,CAAA;AAAA,IACvC;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAEF","file":"index.cjs","sourcesContent":["import type { ApiErrorBody } from \"./types.js\";\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// Base error\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Base error class for all SDK errors.\r\n *\r\n * Use `instanceof` checks to distinguish error types:\r\n *\r\n * ```ts\r\n * try { … } catch (e) {\r\n * if (e instanceof ResiraRateLimitError) { … }\r\n * if (e instanceof ResiraApiError) { … }\r\n * if (e instanceof ResiraNetworkError) { … }\r\n * }\r\n * ```\r\n */\r\nexport class ResiraError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"ResiraError\";\r\n // Fix prototype chain for instanceof to work after transpilation\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// API error (4xx / 5xx with a parsed body)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Thrown when the API returns a non-2xx response with a JSON body.\r\n *\r\n * ```ts\r\n * err.status // 400, 404, 409, 422, 500, …\r\n * err.code // HTTP status text (e.g. \"Not Found\")\r\n * err.body // Parsed `{ error: \"…\" }` from the server\r\n * ```\r\n */\r\nexport class ResiraApiError extends ResiraError {\r\n /** HTTP status code. */\r\n readonly status: number;\r\n /** HTTP status text (e.g. `\"Bad Request\"`). */\r\n readonly code: string;\r\n /** Parsed error body from the API. */\r\n readonly body: ApiErrorBody;\r\n /** The full `Response` object (headers are still accessible). */\r\n readonly response: Response;\r\n\r\n constructor(status: number, code: string, body: ApiErrorBody, response: Response) {\r\n super(body.error || `API error ${status}`);\r\n this.name = \"ResiraApiError\";\r\n this.status = status;\r\n this.code = code;\r\n this.body = body;\r\n this.response = response;\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n\r\n /** Whether this error is retryable (5xx or 429). */\r\n get retryable(): boolean {\r\n return this.status === 429 || this.status >= 500;\r\n }\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// Rate limit error (429)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Thrown when the API returns 429 Too Many Requests.\r\n *\r\n * ```ts\r\n * err.retryAfter // Seconds until the client should retry\r\n * ```\r\n */\r\nexport class ResiraRateLimitError extends ResiraApiError {\r\n /** Seconds to wait before retrying (from `Retry-After` header). */\r\n readonly retryAfter: number;\r\n\r\n constructor(body: ApiErrorBody, response: Response) {\r\n super(429, \"Too Many Requests\", body, response);\r\n this.name = \"ResiraRateLimitError\";\r\n this.retryAfter =\r\n body.retryAfter ??\r\n (Number.parseInt(response.headers.get(\"retry-after\") ?? \"60\", 10) ||\r\n 60);\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// Network error (fetch failed, DNS, timeout, etc.)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Thrown when the request never reached the server.\r\n *\r\n * This wraps the underlying `TypeError` or `DOMException` from\r\n * `fetch()` failures (DNS resolution, TLS, network offline, etc.).\r\n */\r\nexport class ResiraNetworkError extends ResiraError {\r\n /** The original error thrown by `fetch`. */\r\n readonly cause: unknown;\r\n\r\n constructor(message: string, cause: unknown) {\r\n super(message);\r\n this.name = \"ResiraNetworkError\";\r\n this.cause = cause;\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n","import type { ResiraConfig, WeightedBaseUrl } from \"./types.js\";\r\n\r\ninterface ResolvedBaseUrl {\r\n url: string;\r\n weight: number;\r\n}\r\n\r\nconst DEFAULT_LOCAL_BASE_URLS: ResolvedBaseUrl[] = [\r\n { url: \"http://localhost:3001\", weight: 100 },\r\n];\r\n\r\nconst DEFAULT_PRODUCTION_BASE_URLS: ResolvedBaseUrl[] = [\r\n { url: \"https://api.resira.app\", weight: 100 },\r\n];\r\n\r\nfunction readEnv(name: string): string | undefined {\r\n if (typeof process === \"undefined\") return undefined;\r\n return process.env?.[name];\r\n}\r\n\r\n\r\nfunction normalizeUrl(url: string): string {\r\n return url.trim().replace(/\\/+$/, \"\");\r\n}\r\n\r\nfunction isPositiveNumber(value: unknown): value is number {\r\n return typeof value === \"number\" && Number.isFinite(value) && value > 0;\r\n}\r\n\r\nfunction toResolvedBaseUrl(value: string | WeightedBaseUrl): ResolvedBaseUrl | null {\r\n if (typeof value === \"string\") {\r\n const url = normalizeUrl(value);\r\n return url ? { url, weight: 1 } : null;\r\n }\r\n\r\n const url = normalizeUrl(value.url);\r\n if (!url) return null;\r\n\r\n return {\r\n url,\r\n weight: isPositiveNumber(value.weight) ? value.weight : 1,\r\n };\r\n}\r\n\r\nfunction parseJsonBaseUrls(value: string): ResolvedBaseUrl[] {\r\n const parsed = JSON.parse(value) as unknown;\r\n if (!Array.isArray(parsed)) return [];\r\n\r\n return parsed.flatMap((entry) => {\r\n const resolved =\r\n typeof entry === \"string\"\r\n ? toResolvedBaseUrl(entry)\r\n : entry && typeof entry === \"object\"\r\n ? toResolvedBaseUrl(entry as WeightedBaseUrl)\r\n : null;\r\n\r\n return resolved ? [resolved] : [];\r\n });\r\n}\r\n\r\nfunction parseDelimitedBaseUrls(value: string): ResolvedBaseUrl[] {\r\n return value\r\n .split(\",\")\r\n .flatMap((entry) => {\r\n const [rawUrl, rawWeight] = entry.split(\"|\");\r\n const url = normalizeUrl(rawUrl ?? \"\");\r\n if (!url) return [];\r\n\r\n const parsedWeight = rawWeight ? Number(rawWeight.trim()) : 1;\r\n return [{\r\n url,\r\n weight: isPositiveNumber(parsedWeight) ? parsedWeight : 1,\r\n }];\r\n });\r\n}\r\n\r\nfunction parseEnvBaseUrls(value: string | undefined): ResolvedBaseUrl[] {\r\n if (!value) return [];\r\n\r\n try {\r\n const parsed = parseJsonBaseUrls(value);\r\n if (parsed.length > 0) return parsed;\r\n } catch {\r\n // Fall back to delimiter parsing.\r\n }\r\n\r\n return parseDelimitedBaseUrls(value);\r\n}\r\n\r\nexport function resolveBaseUrls(config: ResiraConfig): ResolvedBaseUrl[] {\r\n if (config.baseUrl) {\r\n return [{ url: normalizeUrl(config.baseUrl), weight: 100 }];\r\n }\r\n\r\n if (config.baseUrls?.length) {\r\n const explicit = config.baseUrls.flatMap((entry) => {\r\n const resolved = toResolvedBaseUrl(entry);\r\n return resolved ? [resolved] : [];\r\n });\r\n\r\n if (explicit.length > 0) return explicit;\r\n }\r\n\r\n const envBaseUrls = parseEnvBaseUrls(readEnv(\"RESIRA_API_BASE_URLS\"));\r\n if (envBaseUrls.length > 0) {\r\n return envBaseUrls;\r\n }\r\n\r\n if (readEnv(\"NODE_ENV\") === \"development\") {\r\n return DEFAULT_LOCAL_BASE_URLS;\r\n }\r\n\r\n return DEFAULT_PRODUCTION_BASE_URLS;\r\n}\r\n\r\nexport function pickBaseUrl(baseUrls: ResolvedBaseUrl[]): string {\r\n return baseUrls[0]?.url ?? DEFAULT_PRODUCTION_BASE_URLS[0].url;\r\n}\r\n\r\nexport function getRoutingStats(): Record<string, never> {\r\n return {};\r\n}","import { ResiraApiError, ResiraNetworkError, ResiraRateLimitError } from \"./errors.js\";\r\nimport { pickBaseUrl, resolveBaseUrls } from \"./routing.js\";\r\nimport type {\r\n ApiErrorBody,\r\n Availability,\r\n AvailabilityParams,\r\n CheckoutSessionResponse,\r\n ConfirmPaymentRequest,\r\n ConfirmPaymentResponse,\r\n CreateCheckoutSessionRequest,\r\n CreateCheckoutSessionResponse,\r\n CreatePaymentIntentRequest,\r\n CreateReservationRequest,\r\n Dish,\r\n DishListResponse,\r\n DishResponse,\r\n ListReservationsParams,\r\n PaginatedReservations,\r\n PaymentIntentResponse,\r\n ProductListResponse,\r\n PropertyConfig,\r\n Reservation,\r\n ReservationResponse,\r\n ResiraConfig,\r\n ResourceListResponse,\r\n ValidatePromoCodeResponse,\r\n} from \"./types.js\";\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// Constants\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nconst DEFAULT_MAX_RETRIES = 3;\r\nconst DEFAULT_RETRY_BASE_DELAY = 500; // ms\r\nconst API_PREFIX = \"/v1/public\";\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// Helpers\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\n/** Generate a random UUID v4 for idempotency keys. */\r\nfunction uuid(): string {\r\n // Use crypto.randomUUID when available (Node 19+, all modern browsers)\r\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\r\n return globalThis.crypto.randomUUID();\r\n }\r\n // Fallback: manual v4 UUID\r\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\r\n const r = (Math.random() * 16) | 0;\r\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\r\n });\r\n}\r\n\r\n/** Build a query string from a flat params object. Skips `undefined` values. */\r\nfunction toQueryString(params: Record<string, string | number | boolean | undefined>): string {\r\n const parts: string[] = [];\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value !== undefined && value !== null) {\r\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\r\n }\r\n }\r\n return parts.length > 0 ? `?${parts.join(\"&\")}` : \"\";\r\n}\r\n\r\n/** Sleep for `ms` milliseconds. */\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/**\r\n * Convert camelCase keys to snake_case for query parameters.\r\n * The API expects snake_case query params (`start_date`, `party_size`).\r\n */\r\nfunction camelToSnake(str: string): string {\r\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\r\n}\r\n\r\n/** Convert an object's keys from camelCase to snake_case. */\r\nfunction keysToSnake(\r\n obj: Record<string, string | number | boolean | undefined>,\r\n): Record<string, string | number | boolean | undefined> {\r\n const result: Record<string, string | number | boolean | undefined> = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n result[camelToSnake(key)] = value;\r\n }\r\n return result;\r\n}\r\n\r\n/** Convert snake_case string to camelCase. */\r\nfunction snakeToCamel(str: string): string {\r\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\r\n}\r\n\r\n/** Deep-convert all keys in an object/array from camelCase to snake_case. */\r\nfunction deepKeysToSnake(obj: unknown): unknown {\r\n if (Array.isArray(obj)) return obj.map(deepKeysToSnake);\r\n if (obj !== null && typeof obj === \"object\") {\r\n const result: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\r\n result[camelToSnake(key)] = deepKeysToSnake(value);\r\n }\r\n return result;\r\n }\r\n return obj;\r\n}\r\n\r\n/** Deep-convert all keys in an object/array from snake_case to camelCase. */\r\nfunction deepKeysToCamel(obj: unknown): unknown {\r\n if (Array.isArray(obj)) return obj.map(deepKeysToCamel);\r\n if (obj !== null && typeof obj === \"object\") {\r\n const result: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\r\n result[snakeToCamel(key)] = deepKeysToCamel(value);\r\n }\r\n return result;\r\n }\r\n return obj;\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// Client\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Resira SDK client.\r\n *\r\n * ```ts\r\n * const resira = new Resira({\r\n * apiKey: \"resira_live_abc123…\",\r\n * baseUrl: \"https://api.example.com\", // optional\r\n * });\r\n *\r\n * const availability = await resira.getAvailability(\"prop-1\", {\r\n * startDate: \"2026-07-01\",\r\n * endDate: \"2026-07-07\",\r\n * });\r\n * ```\r\n */\r\nexport class Resira {\r\n private readonly apiKey: string;\r\n private readonly baseUrls: ReturnType<typeof resolveBaseUrls>;\r\n private readonly maxRetries: number;\r\n private readonly retryBaseDelay: number;\r\n private readonly _fetch: typeof globalThis.fetch;\r\n\r\n constructor(config: ResiraConfig) {\r\n if (!config.apiKey) {\r\n throw new Error(\"Resira: apiKey is required\");\r\n }\r\n this.apiKey = config.apiKey;\r\n this.baseUrls = resolveBaseUrls(config);\r\n this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\r\n this.retryBaseDelay = config.retryBaseDelay ?? DEFAULT_RETRY_BASE_DELAY;\r\n this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);\r\n }\r\n\r\n /** The resolved API origin used by this client instance. */\r\n getBaseUrl(): string {\r\n return pickBaseUrl(this.baseUrls);\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Public API methods\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Fetch the public property configuration.\r\n *\r\n * Returns non-sensitive settings such as the Stripe publishable\r\n * key, deposit percentage, currency, and branding info.\r\n *\r\n * ```ts\r\n * const config = await resira.getConfig();\r\n * console.log(config.stripePublishableKey); // \"pk_test_…\"\r\n * ```\r\n */\r\n async getConfig(): Promise<PropertyConfig> {\r\n return this.request<PropertyConfig>(\"GET\", \"/config\");\r\n }\r\n\r\n /**\r\n * Validate a promo/discount code.\r\n *\r\n * Returns discount details if valid, or an error message if not.\r\n *\r\n * ```ts\r\n * const result = await resira.validatePromoCode(\"SUMMER20\");\r\n * if (result.valid) {\r\n * console.log(result.discountType, result.discountValue);\r\n * }\r\n * ```\r\n */\r\n async validatePromoCode(code: string): Promise<ValidatePromoCodeResponse> {\r\n try {\r\n const raw = await this.request<Record<string, unknown>>(\r\n \"POST\",\r\n \"/promo-codes/validate\",\r\n { code },\r\n );\r\n const data = deepKeysToCamel(raw) as Record<string, unknown>;\r\n return {\r\n valid: true,\r\n discountType: data.discountType as \"percent\" | \"fixed\" | undefined,\r\n discountValue: data.discountValue as number | undefined,\r\n currency: data.currency as string | undefined,\r\n minOrderCents: data.minOrderCents as number | undefined,\r\n };\r\n } catch (err: unknown) {\r\n // 4xx errors mean invalid code\r\n if (\r\n err &&\r\n typeof err === \"object\" &&\r\n \"status\" in err &&\r\n (err as { status: number }).status < 500\r\n ) {\r\n const apiErr = err as { body?: { error?: string } };\r\n return {\r\n valid: false,\r\n error: apiErr.body?.error ?? \"Invalid promo code\",\r\n };\r\n }\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * List all active resources for the organization.\r\n *\r\n * Returns resource cards with name, description, price, duration,\r\n * image, and type — suitable for building a resource picker.\r\n *\r\n * ```ts\r\n * const { resources } = await resira.listResources();\r\n * ```\r\n */\r\n async listResources(): Promise<ResourceListResponse> {\r\n return this.request<ResourceListResponse>(\"GET\", \"/resources\");\r\n }\r\n\r\n /**\r\n * Query availability for a resource.\r\n *\r\n * **Properties** (date-based):\r\n * ```ts\r\n * await resira.getAvailability(\"prop-1\", {\r\n * startDate: \"2026-07-01\",\r\n * endDate: \"2026-07-07\",\r\n * });\r\n * ```\r\n *\r\n * **Restaurants** (time-slot):\r\n * ```ts\r\n * await resira.getAvailability(\"table-5\", {\r\n * date: \"2026-07-01\",\r\n * partySize: 4,\r\n * });\r\n * ```\r\n *\r\n * Omit params to get all blocked dates (for calendar rendering).\r\n */\r\n async getAvailability(\r\n resourceId: string,\r\n params: AvailabilityParams = {},\r\n ): Promise<Availability> {\r\n if (!resourceId) {\r\n throw new Error(\"resourceId is required for getAvailability\");\r\n }\r\n const qs = toQueryString(keysToSnake(params as Record<string, string | number | undefined>));\r\n return this.request<Availability>(\r\n \"GET\",\r\n `/resources/${encodeURIComponent(resourceId)}/availability${qs}`,\r\n );\r\n }\r\n\r\n /**\r\n * Query availability for a product/service.\r\n *\r\n * Aggregates capacity across all linked equipment. If a product\r\n * has 2 jet skis (each capacity=1), slots show capacity: 2.\r\n * Both pending and confirmed reservations count as occupied.\r\n *\r\n * ```ts\r\n * await resira.getProductAvailability(\"prod-123\", {\r\n * date: \"2026-07-01\",\r\n * durationMinutes: 30,\r\n * });\r\n * ```\r\n */\r\n async getProductAvailability(\r\n productId: string,\r\n params: AvailabilityParams = {},\r\n ): Promise<Availability> {\r\n if (!productId) {\r\n throw new Error(\"productId is required for getProductAvailability\");\r\n }\r\n const qs = toQueryString(keysToSnake(params as Record<string, string | number | undefined>));\r\n return this.request<Availability>(\r\n \"GET\",\r\n `/products/${encodeURIComponent(productId)}/availability${qs}`,\r\n );\r\n }\r\n\r\n /**\r\n * Create a reservation.\r\n *\r\n * Uses `POST /v2/api/reservations` — the `resourceId` is sent in\r\n * the request body, **not** in the URL path.\r\n *\r\n * An `Idempotency-Key` header is automatically attached so that\r\n * retries (including those from exponential backoff) are safe.\r\n *\r\n * ```ts\r\n * const { reservation } = await resira.createReservation({\r\n * resourceId: \"prop-1\",\r\n * guestName: \"Jane Doe\",\r\n * guestEmail: \"jane@example.com\",\r\n * startDate: \"2026-07-01\",\r\n * endDate: \"2026-07-07\",\r\n * partySize: 3,\r\n * });\r\n * ```\r\n */\r\n async createReservation(\r\n payload: CreateReservationRequest,\r\n options?: { idempotencyKey?: string },\r\n ): Promise<ReservationResponse> {\r\n if (!payload.resourceId) {\r\n throw new Error(\"resourceId is required for createReservation\");\r\n }\r\n const idempotencyKey = options?.idempotencyKey ?? uuid();\r\n\r\n // Note: uses /v2/api prefix, not /v1/public\r\n const url = `${this.getBaseUrl()}/v2/api/reservations`;\r\n\r\n const headers: Record<string, string> = {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n Accept: \"application/json\",\r\n \"Content-Type\": \"application/json\",\r\n \"Idempotency-Key\": idempotencyKey,\r\n };\r\n\r\n const init: RequestInit = {\r\n method: \"POST\",\r\n headers,\r\n body: JSON.stringify(payload),\r\n };\r\n\r\n let lastError: ResiraApiError | ResiraNetworkError | ResiraRateLimitError | undefined;\r\n\r\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\r\n if (attempt > 0) {\r\n const backoff = this.calculateBackoff(attempt, lastError);\r\n await sleep(backoff);\r\n }\r\n\r\n let response: Response;\r\n try {\r\n response = await this._fetch(url, init);\r\n } catch (err) {\r\n lastError = new ResiraNetworkError(\r\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\r\n err,\r\n );\r\n continue;\r\n }\r\n\r\n if (response.ok) {\r\n const raw = (await response.json()) as Record<string, unknown>;\r\n // The API may nest under \"reservation\" or \"booking\" depending on endpoint\r\n const resData = (raw.reservation ?? raw.booking ?? {}) as Record<string, unknown>;\r\n\r\n // Augment with request data: API response doesn't include\r\n // startTime/endTime/startDate/endDate/resourceId for v2 reservations\r\n const reservation: Reservation = {\r\n id: (resData.id as string) ?? \"\",\r\n resourceId: (resData.resourceId as string) ?? payload.resourceId,\r\n status: (resData.status as string) ?? \"pending\",\r\n startDate: (resData.startDate as string) ?? payload.startDate,\r\n endDate: (resData.endDate as string) ?? payload.endDate,\r\n startTime: (resData.startTime as string) ?? payload.startTime,\r\n endTime: (resData.endTime as string) ?? payload.endTime,\r\n startDatetime: (resData.startDatetime as string) ?? payload.startTime,\r\n endDatetime: (resData.endDatetime as string) ?? payload.endTime,\r\n guestName: (resData.guestName as string) ?? payload.guestName,\r\n partySize: (resData.partySize as number) ?? (resData.guests as number) ?? payload.partySize ?? 2,\r\n totalPrice: (resData.totalPrice as number) ?? 0,\r\n currency: (resData.currency as string) ?? \"EUR\",\r\n createdAt: (resData.createdAt as string) ?? new Date().toISOString(),\r\n };\r\n\r\n return { reservation };\r\n }\r\n\r\n let errorBody: ApiErrorBody;\r\n try {\r\n errorBody = (await response.json()) as ApiErrorBody;\r\n } catch {\r\n errorBody = { error: response.statusText || `HTTP ${response.status}` };\r\n }\r\n\r\n if (response.status === 429) {\r\n lastError = new ResiraRateLimitError(errorBody, response);\r\n continue;\r\n }\r\n\r\n if (response.status >= 500) {\r\n lastError = new ResiraApiError(response.status, response.statusText, errorBody, response);\r\n continue;\r\n }\r\n\r\n throw new ResiraApiError(response.status, response.statusText, errorBody, response);\r\n }\r\n\r\n throw lastError!;\r\n }\r\n\r\n /**\r\n * List reservations for a resource (paginated).\r\n *\r\n * ```ts\r\n * const page = await resira.listReservations(\"prop-1\", {\r\n * status: \"confirmed\",\r\n * page: 1,\r\n * limit: 50,\r\n * });\r\n * console.log(page.data); // Reservation[]\r\n * console.log(page.totalPages); // number\r\n * ```\r\n */\r\n async listReservations(\r\n resourceId: string,\r\n params: ListReservationsParams = {},\r\n ): Promise<PaginatedReservations> {\r\n const qs = toQueryString(params as Record<string, string | number | undefined>);\r\n return this.request<PaginatedReservations>(\r\n \"GET\",\r\n `/resources/${encodeURIComponent(resourceId)}/reservations${qs}`,\r\n );\r\n }\r\n\r\n /**\r\n * Get a single reservation by ID.\r\n *\r\n * ```ts\r\n * const { reservation } = await resira.getReservation(\"prop-1\", \"res-uuid\");\r\n * ```\r\n */\r\n async getReservation(\r\n resourceId: string,\r\n reservationId: string,\r\n ): Promise<ReservationResponse> {\r\n return this.request<ReservationResponse>(\r\n \"GET\",\r\n `/resources/${encodeURIComponent(resourceId)}/reservations/${encodeURIComponent(reservationId)}`,\r\n );\r\n }\r\n\r\n /**\r\n * List all active products/services for the organisation.\r\n *\r\n * Calls `GET /v1/public/products` which returns products with\r\n * pricing, duration, and linked equipment.\r\n *\r\n * Falls back to mapping resources → products if the endpoint\r\n * returns 404 (backend hasn't been updated yet).\r\n *\r\n * ```ts\r\n * const { products } = await resira.listProducts();\r\n * ```\r\n */\r\n async listProducts(): Promise<ProductListResponse> {\r\n try {\r\n return await this.request<ProductListResponse>(\"GET\", \"/products\");\r\n } catch (err: unknown) {\r\n // Fallback: if /products endpoint doesn't exist yet (404),\r\n // map resources → products shape\r\n if (\r\n err &&\r\n typeof err === \"object\" &&\r\n \"status\" in err &&\r\n (err as { status: number }).status === 404\r\n ) {\r\n const resourceResponse = await this.listResources();\r\n const products = resourceResponse.resources.map((r) => ({\r\n id: r.id,\r\n name: r.name,\r\n description: r.description,\r\n durationMinutes: r.durationMinutes ?? 60,\r\n priceCents: r.pricePerSession ?? 0,\r\n currency: r.currency ?? \"EUR\",\r\n imageUrl: r.imageUrl,\r\n active: r.active,\r\n sortOrder: 0,\r\n pricingModel: \"per_session\" as const,\r\n equipmentIds: [r.id],\r\n equipmentNames: [r.name],\r\n }));\r\n return { products, count: products.length };\r\n }\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * List all dishes with 3D model data for the organisation.\r\n *\r\n * Returns dishes with name, description, price, image, and\r\n * 3D model URLs for AR/preview rendering.\r\n *\r\n * ```ts\r\n * const { dishes } = await resira.listDishes();\r\n * ```\r\n */\r\n async listDishes(): Promise<DishListResponse> {\r\n return this.request<DishListResponse>(\"GET\", \"/dishes\");\r\n }\r\n\r\n /**\r\n * Get a single dish by ID.\r\n *\r\n * ```ts\r\n * const { dish } = await resira.getDish(\"dish-uuid\");\r\n * console.log(dish.name, dish.model?.glbUrl);\r\n * ```\r\n */\r\n async getDish(dishId: string): Promise<DishResponse> {\r\n if (!dishId) {\r\n throw new Error(\"dishId is required for getDish\");\r\n }\r\n return this.request<DishResponse>(\r\n \"GET\",\r\n `/dishes/${encodeURIComponent(dishId)}`,\r\n );\r\n }\r\n\r\n /**\r\n * Retrieve a checkout session by its token.\r\n *\r\n * Used to hydrate the checkout screen when opening the widget\r\n * with a pre-created session token (skip service selection).\r\n *\r\n * ```ts\r\n * const { session } = await resira.getCheckoutSession(\"cs_ab12cd34ef56\");\r\n * console.log(session.productName, session.priceCents);\r\n * ```\r\n */\r\n async getCheckoutSession(token: string): Promise<CheckoutSessionResponse> {\r\n if (!token) {\r\n throw new Error(\"token is required for getCheckoutSession\");\r\n }\r\n const url = `${this.getBaseUrl()}/v2/public/checkout-sessions/${encodeURIComponent(token)}`;\r\n\r\n const headers: Record<string, string> = {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n Accept: \"application/json\",\r\n };\r\n\r\n let lastError: ResiraApiError | ResiraNetworkError | undefined;\r\n\r\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\r\n if (attempt > 0) {\r\n const backoff = this.calculateBackoff(attempt, lastError);\r\n await sleep(backoff);\r\n }\r\n\r\n let response: Response;\r\n try {\r\n response = await this._fetch(url, { method: \"GET\", headers });\r\n } catch (err) {\r\n lastError = new ResiraNetworkError(\r\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\r\n err,\r\n );\r\n continue;\r\n }\r\n\r\n if (response.ok) {\r\n const raw = await response.json();\r\n return deepKeysToCamel(raw) as CheckoutSessionResponse;\r\n }\r\n\r\n let errorBody: ApiErrorBody;\r\n try {\r\n errorBody = (await response.json()) as ApiErrorBody;\r\n } catch {\r\n errorBody = { error: response.statusText || `HTTP ${response.status}` };\r\n }\r\n\r\n if (response.status === 429) {\r\n lastError = new ResiraRateLimitError(errorBody, response);\r\n continue;\r\n }\r\n if (response.status >= 500) {\r\n lastError = new ResiraApiError(response.status, response.statusText, errorBody, response);\r\n continue;\r\n }\r\n\r\n throw new ResiraApiError(response.status, response.statusText, errorBody, response);\r\n }\r\n\r\n throw lastError!;\r\n }\r\n\r\n /**\r\n * Create a new checkout session.\r\n *\r\n * External sites can create a session with product, slot, and guest\r\n * details, then pass the returned token to the widget to skip\r\n * directly to checkout.\r\n *\r\n * ```ts\r\n * const { sessionToken } = await resira.createCheckoutSession({\r\n * productId: \"prod-123\",\r\n * durationMinutes: 30,\r\n * partySize: 2,\r\n * date: \"2026-07-01\",\r\n * startTime: \"2026-07-01T10:00:00Z\",\r\n * endTime: \"2026-07-01T10:30:00Z\",\r\n * });\r\n * ```\r\n */\r\n async createCheckoutSession(\r\n payload: CreateCheckoutSessionRequest,\r\n options?: { idempotencyKey?: string },\r\n ): Promise<CreateCheckoutSessionResponse> {\r\n const idempotencyKey = options?.idempotencyKey ?? uuid();\r\n const url = `${this.getBaseUrl()}/v2/public/checkout-sessions`;\r\n\r\n const headers: Record<string, string> = {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n Accept: \"application/json\",\r\n \"Content-Type\": \"application/json\",\r\n \"Idempotency-Key\": idempotencyKey,\r\n };\r\n\r\n const init: RequestInit = {\r\n method: \"POST\",\r\n headers,\r\n body: JSON.stringify(payload),\r\n };\r\n\r\n let lastError: ResiraApiError | ResiraNetworkError | undefined;\r\n\r\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\r\n if (attempt > 0) {\r\n const backoff = this.calculateBackoff(attempt, lastError);\r\n await sleep(backoff);\r\n }\r\n\r\n let response: Response;\r\n try {\r\n response = await this._fetch(url, init);\r\n } catch (err) {\r\n lastError = new ResiraNetworkError(\r\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\r\n err,\r\n );\r\n continue;\r\n }\r\n\r\n if (response.ok) {\r\n const raw = await response.json();\r\n return deepKeysToCamel(raw) as CreateCheckoutSessionResponse;\r\n }\r\n\r\n let errorBody: ApiErrorBody;\r\n try {\r\n errorBody = (await response.json()) as ApiErrorBody;\r\n } catch {\r\n errorBody = { error: response.statusText || `HTTP ${response.status}` };\r\n }\r\n\r\n if (response.status === 429) {\r\n lastError = new ResiraRateLimitError(errorBody, response);\r\n continue;\r\n }\r\n if (response.status >= 500) {\r\n lastError = new ResiraApiError(response.status, response.statusText, errorBody, response);\r\n continue;\r\n }\r\n\r\n throw new ResiraApiError(response.status, response.statusText, errorBody, response);\r\n }\r\n\r\n throw lastError!;\r\n }\r\n\r\n /**\r\n * Create a Stripe payment intent for a booking.\r\n *\r\n * The server creates the payment intent, calculates the amount,\r\n * and returns a `clientSecret` to confirm payment on the frontend\r\n * using Stripe Elements.\r\n *\r\n * ```ts\r\n * const { clientSecret, amountNow, amountAtVenue } =\r\n * await resira.createPaymentIntent({\r\n * productId: \"prod-123\",\r\n * resourceId: \"res-456\",\r\n * partySize: 2,\r\n * startDate: \"2026-07-01\",\r\n * startTime: \"2026-07-01T10:00:00Z\",\r\n * endTime: \"2026-07-01T11:00:00Z\",\r\n * guestName: \"Jane Doe\",\r\n * guestEmail: \"jane@example.com\",\r\n * });\r\n * ```\r\n */\r\n async createPaymentIntent(\r\n payload: CreatePaymentIntentRequest,\r\n options?: { idempotencyKey?: string },\r\n ): Promise<PaymentIntentResponse> {\r\n const idempotencyKey = options?.idempotencyKey ?? uuid();\r\n const raw = await this.request<Record<string, unknown>>(\r\n \"POST\",\r\n \"/payments/create-intent\",\r\n payload,\r\n { \"Idempotency-Key\": idempotencyKey },\r\n );\r\n // Normalize response keys to camelCase\r\n const data = deepKeysToCamel(raw) as Record<string, unknown>;\r\n // Map backend field names to SDK field names:\r\n // backend: amountDue, totalPrice\r\n // SDK: amountNow, totalAmount, amountAtVenue\r\n const totalAmount = (data.totalAmount as number) ?? (data.totalPrice as number) ?? 0;\r\n const amountNow = (data.amountNow as number) ?? (data.amountDue as number) ?? totalAmount;\r\n const amountAtVenue = (data.amountAtVenue as number) ?? (totalAmount - amountNow);\r\n return {\r\n clientSecret: data.clientSecret as string,\r\n paymentIntentId: data.paymentIntentId as string,\r\n amountNow,\r\n amountAtVenue,\r\n totalAmount,\r\n currency: (data.currency as string) ?? \"EUR\",\r\n paymentOption: data.paymentOption as string | undefined,\r\n reservationId: data.reservationId as string | undefined,\r\n discountAmount: (data.discountAmount as number) ?? undefined,\r\n originalPrice: (data.originalPrice as number) ?? undefined,\r\n promoCodeApplied: (data.promoCodeApplied as string) ?? undefined,\r\n };\r\n }\r\n\r\n /**\r\n * Confirm that a payment was successful after the guest\r\n * completes the Stripe payment flow.\r\n *\r\n * This transitions the reservation from `pending` to `confirmed`.\r\n *\r\n * ```ts\r\n * const { reservation, paymentStatus } =\r\n * await resira.confirmPayment({\r\n * paymentIntentId: \"pi_xxx\",\r\n * reservationId: \"res-uuid\",\r\n * });\r\n * ```\r\n */\r\n async confirmPayment(\r\n payload: ConfirmPaymentRequest,\r\n ): Promise<ConfirmPaymentResponse> {\r\n const raw = await this.request<Record<string, unknown>>(\r\n \"POST\",\r\n \"/payments/confirm\",\r\n payload,\r\n );\r\n // Normalize response keys to camelCase in case backend returns snake_case\r\n return deepKeysToCamel(raw) as ConfirmPaymentResponse;\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Internal HTTP layer\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Execute an HTTP request with retry logic and error normalization.\r\n *\r\n * - Attaches `Authorization: Bearer <apiKey>` on every request.\r\n * - Retries on 429 and 5xx with exponential backoff + jitter.\r\n * - Parses error bodies and throws typed error classes.\r\n */\r\n private async request<T>(\r\n method: string,\r\n path: string,\r\n body?: unknown,\r\n extraHeaders?: Record<string, string>,\r\n ): Promise<T> {\r\n const url = `${this.getBaseUrl()}${API_PREFIX}${path}`;\r\n\r\n const headers: Record<string, string> = {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n Accept: \"application/json\",\r\n ...extraHeaders,\r\n };\r\n\r\n if (body !== undefined) {\r\n headers[\"Content-Type\"] = \"application/json\";\r\n }\r\n\r\n const init: RequestInit = {\r\n method,\r\n headers,\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n };\r\n\r\n let lastError: ResiraApiError | ResiraNetworkError | undefined;\r\n\r\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\r\n // ── Wait before retry ────────────────────────────────\r\n if (attempt > 0) {\r\n const backoff = this.calculateBackoff(attempt, lastError);\r\n await sleep(backoff);\r\n }\r\n\r\n // ── Execute the request ──────────────────────────────\r\n let response: Response;\r\n try {\r\n response = await this._fetch(url, init);\r\n } catch (err) {\r\n lastError = new ResiraNetworkError(\r\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\r\n err,\r\n );\r\n // Network errors are always retryable\r\n continue;\r\n }\r\n\r\n // ── Success ──────────────────────────────────────────\r\n if (response.ok) {\r\n return (await response.json()) as T;\r\n }\r\n\r\n // ── Parse error body ─────────────────────────────────\r\n let errorBody: ApiErrorBody;\r\n try {\r\n errorBody = (await response.json()) as ApiErrorBody;\r\n } catch {\r\n errorBody = { error: response.statusText || `HTTP ${response.status}` };\r\n }\r\n\r\n // ── Rate limit ───────────────────────────────────────\r\n if (response.status === 429) {\r\n lastError = new ResiraRateLimitError(errorBody, response);\r\n // Always retry 429s (up to maxRetries)\r\n continue;\r\n }\r\n\r\n // ── Server error (5xx) — retryable ───────────────────\r\n if (response.status >= 500) {\r\n lastError = new ResiraApiError(\r\n response.status,\r\n response.statusText,\r\n errorBody,\r\n response,\r\n );\r\n continue;\r\n }\r\n\r\n // ── Client error (4xx) — NOT retryable ───────────────\r\n throw new ResiraApiError(\r\n response.status,\r\n response.statusText,\r\n errorBody,\r\n response,\r\n );\r\n }\r\n\r\n // All retries exhausted — throw the last error\r\n throw lastError!;\r\n }\r\n\r\n /**\r\n * Calculate backoff delay in milliseconds for a given retry attempt.\r\n *\r\n * Uses exponential backoff with full jitter:\r\n * delay = random(0, base * 2^attempt)\r\n *\r\n * For 429 responses, respects the `Retry-After` header as a minimum.\r\n */\r\n private calculateBackoff(\r\n attempt: number,\r\n lastError?: ResiraApiError | ResiraNetworkError,\r\n ): number {\r\n const exponential = this.retryBaseDelay * 2 ** (attempt - 1);\r\n const jittered = Math.random() * exponential;\r\n\r\n // If the server told us to wait, use that as the floor\r\n if (lastError instanceof ResiraRateLimitError) {\r\n const serverDelay = lastError.retryAfter * 1000;\r\n return Math.max(serverDelay, jittered);\r\n }\r\n\r\n return jittered;\r\n }\r\n\r\n}\r\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -247,14 +247,29 @@ interface DurationPrice {
|
|
|
247
247
|
durationMinutes: number;
|
|
248
248
|
/** Price in the smallest currency unit (cents). */
|
|
249
249
|
priceCents: number;
|
|
250
|
+
/** Human-readable label (e.g. "Half Day", "Full Day"). */
|
|
251
|
+
label?: string;
|
|
252
|
+
/** Whether fuel is included in this duration tier. */
|
|
253
|
+
fuelIncluded?: boolean;
|
|
250
254
|
}
|
|
251
255
|
/** A rider-tier with its own set of duration-price pairs. */
|
|
252
256
|
interface RiderTierPrice {
|
|
253
|
-
/**
|
|
254
|
-
riders
|
|
255
|
-
/**
|
|
257
|
+
/** Exact number of riders this tier applies to (mutually exclusive with min/maxRiders). */
|
|
258
|
+
riders?: number;
|
|
259
|
+
/** Range start — minimum riders for this tier. */
|
|
260
|
+
minRiders?: number;
|
|
261
|
+
/** Range end — maximum riders for this tier. */
|
|
262
|
+
maxRiders?: number;
|
|
263
|
+
/** Duration-price options for this rider count/range. */
|
|
256
264
|
durationPricing: DurationPrice[];
|
|
257
265
|
}
|
|
266
|
+
/** A single image entry for a product (same schema as ResourceImage). */
|
|
267
|
+
interface ProductImage {
|
|
268
|
+
/** CDN URL of the image. */
|
|
269
|
+
url: string;
|
|
270
|
+
/** Per-image display preferences. */
|
|
271
|
+
displaySettings?: ResourceImageDisplaySettings;
|
|
272
|
+
}
|
|
258
273
|
/** A bookable product/service as returned by the public API. */
|
|
259
274
|
interface Product {
|
|
260
275
|
/** Unique product identifier. */
|
|
@@ -269,8 +284,10 @@ interface Product {
|
|
|
269
284
|
priceCents: number;
|
|
270
285
|
/** ISO 4217 currency code (e.g. `"EUR"`). */
|
|
271
286
|
currency: string;
|
|
272
|
-
/** Optional image URL. */
|
|
287
|
+
/** Optional primary image URL (first image or legacy single image). */
|
|
273
288
|
imageUrl?: string;
|
|
289
|
+
/** All images for this product (ordered). The first is the cover image. */
|
|
290
|
+
images?: ProductImage[];
|
|
274
291
|
/** Optional calendar/display color for this service, usually configured in admin settings. */
|
|
275
292
|
serviceColor?: string;
|
|
276
293
|
/** Whether the product is active. */
|
|
@@ -279,6 +296,16 @@ interface Product {
|
|
|
279
296
|
sortOrder?: number;
|
|
280
297
|
/** Pricing model: flat rate per session or per person. */
|
|
281
298
|
pricingModel: PricingModel;
|
|
299
|
+
/** Machine-readable category key (e.g. `"jet_skis"`). */
|
|
300
|
+
category?: string;
|
|
301
|
+
/** Display name for the category (e.g. `"Jet Skis"`). */
|
|
302
|
+
categoryName?: string;
|
|
303
|
+
/** Sort order for category display. */
|
|
304
|
+
categorySortOrder?: number;
|
|
305
|
+
/** Short description of the category. */
|
|
306
|
+
categoryDescription?: string;
|
|
307
|
+
/** Hex color for category card accent. */
|
|
308
|
+
categoryColor?: string;
|
|
282
309
|
/** IDs of linked equipment/resources. */
|
|
283
310
|
equipmentIds: string[];
|
|
284
311
|
/** Equipment names (resolved by the server). */
|
|
@@ -293,12 +320,73 @@ interface Product {
|
|
|
293
320
|
variants?: ProductVariant[];
|
|
294
321
|
/** Available slot durations in minutes (returned by v2 API). */
|
|
295
322
|
slotDurations?: number[];
|
|
323
|
+
/** Whether fuel is included in the base price. */
|
|
324
|
+
fuelIncluded?: boolean;
|
|
325
|
+
/** Whether a skipper/captain is included. */
|
|
326
|
+
skipperIncluded?: boolean;
|
|
327
|
+
/** Optional skipper add-on price in cents per hour. */
|
|
328
|
+
skipperAddOnCentsPerHour?: number;
|
|
329
|
+
/** Operating hours window. */
|
|
330
|
+
operatingHours?: {
|
|
331
|
+
start: string;
|
|
332
|
+
end: string;
|
|
333
|
+
};
|
|
334
|
+
/** Seasonal availability months. */
|
|
335
|
+
seasonalAvailability?: {
|
|
336
|
+
startMonth: number;
|
|
337
|
+
endMonth: number;
|
|
338
|
+
};
|
|
339
|
+
/** Minimum age restriction. */
|
|
340
|
+
ageRestriction?: {
|
|
341
|
+
min: number;
|
|
342
|
+
};
|
|
343
|
+
/** Minimum booking duration in minutes. */
|
|
344
|
+
minBookingDurationMinutes?: number;
|
|
345
|
+
/** Maximum booking duration in minutes. */
|
|
346
|
+
maxBookingDurationMinutes?: number;
|
|
347
|
+
/** Whether champagne is included. */
|
|
348
|
+
includesChampagne?: boolean;
|
|
349
|
+
/** Available departure times (e.g. `["06:00","07:00"]`). */
|
|
350
|
+
departureTimes?: string[];
|
|
351
|
+
/** Minimum age for drivers (e.g. 21 for Scorpion). */
|
|
352
|
+
driverMinAge?: number;
|
|
353
|
+
/** Licence restriction note. */
|
|
354
|
+
licenceRestriction?: string;
|
|
355
|
+
/** Fuel included max duration in minutes. */
|
|
356
|
+
fuelIncludedMaxMinutes?: number;
|
|
357
|
+
/** AR model URL (full quality). */
|
|
358
|
+
arModelUrl?: string;
|
|
359
|
+
/** AR model URL (optimized). */
|
|
360
|
+
arModelUrlOptimized?: string;
|
|
361
|
+
/** AR model URL (low quality). */
|
|
362
|
+
arModelUrlLow?: string;
|
|
296
363
|
}
|
|
297
364
|
/** Response wrapper for product listing. */
|
|
298
365
|
interface ProductListResponse {
|
|
299
366
|
products: Product[];
|
|
367
|
+
/** Category summaries for grouping products on the public site. */
|
|
368
|
+
categories?: ProductCategory[];
|
|
300
369
|
count: number;
|
|
301
370
|
}
|
|
371
|
+
/** Category summary returned alongside products for public display grouping. */
|
|
372
|
+
interface ProductCategory {
|
|
373
|
+
/** Machine-readable category key (e.g. `"jet_skis"`). */
|
|
374
|
+
category: string;
|
|
375
|
+
/** Display name (e.g. `"Jet Skis"`). */
|
|
376
|
+
name: string;
|
|
377
|
+
/** Short description. */
|
|
378
|
+
description: string;
|
|
379
|
+
/** Hex color for category card accent. */
|
|
380
|
+
color: string;
|
|
381
|
+
/** Sort order for display. */
|
|
382
|
+
sortOrder: number;
|
|
383
|
+
/** Number of products in this category. */
|
|
384
|
+
productCount: number;
|
|
385
|
+
/** Lowest price among products in this category (in cents). */
|
|
386
|
+
startingPriceCents: number;
|
|
387
|
+
/** Currency code (e.g. `"EUR"`). */
|
|
388
|
+
currency: string;
|
|
389
|
+
}
|
|
302
390
|
/** Request body for creating a payment intent. */
|
|
303
391
|
interface CreatePaymentIntentRequest {
|
|
304
392
|
/** Product ID being booked. */
|
|
@@ -898,4 +986,4 @@ declare class ResiraNetworkError extends ResiraError {
|
|
|
898
986
|
constructor(message: string, cause: unknown);
|
|
899
987
|
}
|
|
900
988
|
|
|
901
|
-
export { type ApiErrorBody, type Availability, type AvailabilityParams, type CheckoutConfig, type CheckoutSession, type CheckoutSessionResponse, type ConfirmPaymentRequest, type ConfirmPaymentResponse, type CreateCheckoutSessionRequest, type CreateCheckoutSessionResponse, type CreatePaymentIntentRequest, type CreateReservationRequest, type DateAvailability, type Dish, type DishListResponse, type DishModel, type DishResponse, type DurationPrice, type ListReservationsParams, type PaginatedReservations, type PaymentIntentResponse, type PricingModel, type Product, type ProductListResponse, type ProductVariant, type PromoCode, type PropertyConfig, type PublicResource, type RefundRule, type Reservation, type ReservationResponse, Resira, ResiraApiError, type ResiraConfig, ResiraError, ResiraNetworkError, ResiraRateLimitError, type ResourceImage, type ResourceImageDisplaySettings, type ResourceListResponse, type RiderTierPrice, type TimeSlotAvailability, type ValidatePromoCodeResponse, type WeightedBaseUrl, getRoutingStats };
|
|
989
|
+
export { type ApiErrorBody, type Availability, type AvailabilityParams, type CheckoutConfig, type CheckoutSession, type CheckoutSessionResponse, type ConfirmPaymentRequest, type ConfirmPaymentResponse, type CreateCheckoutSessionRequest, type CreateCheckoutSessionResponse, type CreatePaymentIntentRequest, type CreateReservationRequest, type DateAvailability, type Dish, type DishListResponse, type DishModel, type DishResponse, type DurationPrice, type ListReservationsParams, type PaginatedReservations, type PaymentIntentResponse, type PricingModel, type Product, type ProductCategory, type ProductImage, type ProductListResponse, type ProductVariant, type PromoCode, type PropertyConfig, type PublicResource, type RefundRule, type Reservation, type ReservationResponse, Resira, ResiraApiError, type ResiraConfig, ResiraError, ResiraNetworkError, ResiraRateLimitError, type ResourceImage, type ResourceImageDisplaySettings, type ResourceListResponse, type RiderTierPrice, type TimeSlotAvailability, type ValidatePromoCodeResponse, type WeightedBaseUrl, getRoutingStats };
|
package/dist/index.d.ts
CHANGED
|
@@ -247,14 +247,29 @@ interface DurationPrice {
|
|
|
247
247
|
durationMinutes: number;
|
|
248
248
|
/** Price in the smallest currency unit (cents). */
|
|
249
249
|
priceCents: number;
|
|
250
|
+
/** Human-readable label (e.g. "Half Day", "Full Day"). */
|
|
251
|
+
label?: string;
|
|
252
|
+
/** Whether fuel is included in this duration tier. */
|
|
253
|
+
fuelIncluded?: boolean;
|
|
250
254
|
}
|
|
251
255
|
/** A rider-tier with its own set of duration-price pairs. */
|
|
252
256
|
interface RiderTierPrice {
|
|
253
|
-
/**
|
|
254
|
-
riders
|
|
255
|
-
/**
|
|
257
|
+
/** Exact number of riders this tier applies to (mutually exclusive with min/maxRiders). */
|
|
258
|
+
riders?: number;
|
|
259
|
+
/** Range start — minimum riders for this tier. */
|
|
260
|
+
minRiders?: number;
|
|
261
|
+
/** Range end — maximum riders for this tier. */
|
|
262
|
+
maxRiders?: number;
|
|
263
|
+
/** Duration-price options for this rider count/range. */
|
|
256
264
|
durationPricing: DurationPrice[];
|
|
257
265
|
}
|
|
266
|
+
/** A single image entry for a product (same schema as ResourceImage). */
|
|
267
|
+
interface ProductImage {
|
|
268
|
+
/** CDN URL of the image. */
|
|
269
|
+
url: string;
|
|
270
|
+
/** Per-image display preferences. */
|
|
271
|
+
displaySettings?: ResourceImageDisplaySettings;
|
|
272
|
+
}
|
|
258
273
|
/** A bookable product/service as returned by the public API. */
|
|
259
274
|
interface Product {
|
|
260
275
|
/** Unique product identifier. */
|
|
@@ -269,8 +284,10 @@ interface Product {
|
|
|
269
284
|
priceCents: number;
|
|
270
285
|
/** ISO 4217 currency code (e.g. `"EUR"`). */
|
|
271
286
|
currency: string;
|
|
272
|
-
/** Optional image URL. */
|
|
287
|
+
/** Optional primary image URL (first image or legacy single image). */
|
|
273
288
|
imageUrl?: string;
|
|
289
|
+
/** All images for this product (ordered). The first is the cover image. */
|
|
290
|
+
images?: ProductImage[];
|
|
274
291
|
/** Optional calendar/display color for this service, usually configured in admin settings. */
|
|
275
292
|
serviceColor?: string;
|
|
276
293
|
/** Whether the product is active. */
|
|
@@ -279,6 +296,16 @@ interface Product {
|
|
|
279
296
|
sortOrder?: number;
|
|
280
297
|
/** Pricing model: flat rate per session or per person. */
|
|
281
298
|
pricingModel: PricingModel;
|
|
299
|
+
/** Machine-readable category key (e.g. `"jet_skis"`). */
|
|
300
|
+
category?: string;
|
|
301
|
+
/** Display name for the category (e.g. `"Jet Skis"`). */
|
|
302
|
+
categoryName?: string;
|
|
303
|
+
/** Sort order for category display. */
|
|
304
|
+
categorySortOrder?: number;
|
|
305
|
+
/** Short description of the category. */
|
|
306
|
+
categoryDescription?: string;
|
|
307
|
+
/** Hex color for category card accent. */
|
|
308
|
+
categoryColor?: string;
|
|
282
309
|
/** IDs of linked equipment/resources. */
|
|
283
310
|
equipmentIds: string[];
|
|
284
311
|
/** Equipment names (resolved by the server). */
|
|
@@ -293,12 +320,73 @@ interface Product {
|
|
|
293
320
|
variants?: ProductVariant[];
|
|
294
321
|
/** Available slot durations in minutes (returned by v2 API). */
|
|
295
322
|
slotDurations?: number[];
|
|
323
|
+
/** Whether fuel is included in the base price. */
|
|
324
|
+
fuelIncluded?: boolean;
|
|
325
|
+
/** Whether a skipper/captain is included. */
|
|
326
|
+
skipperIncluded?: boolean;
|
|
327
|
+
/** Optional skipper add-on price in cents per hour. */
|
|
328
|
+
skipperAddOnCentsPerHour?: number;
|
|
329
|
+
/** Operating hours window. */
|
|
330
|
+
operatingHours?: {
|
|
331
|
+
start: string;
|
|
332
|
+
end: string;
|
|
333
|
+
};
|
|
334
|
+
/** Seasonal availability months. */
|
|
335
|
+
seasonalAvailability?: {
|
|
336
|
+
startMonth: number;
|
|
337
|
+
endMonth: number;
|
|
338
|
+
};
|
|
339
|
+
/** Minimum age restriction. */
|
|
340
|
+
ageRestriction?: {
|
|
341
|
+
min: number;
|
|
342
|
+
};
|
|
343
|
+
/** Minimum booking duration in minutes. */
|
|
344
|
+
minBookingDurationMinutes?: number;
|
|
345
|
+
/** Maximum booking duration in minutes. */
|
|
346
|
+
maxBookingDurationMinutes?: number;
|
|
347
|
+
/** Whether champagne is included. */
|
|
348
|
+
includesChampagne?: boolean;
|
|
349
|
+
/** Available departure times (e.g. `["06:00","07:00"]`). */
|
|
350
|
+
departureTimes?: string[];
|
|
351
|
+
/** Minimum age for drivers (e.g. 21 for Scorpion). */
|
|
352
|
+
driverMinAge?: number;
|
|
353
|
+
/** Licence restriction note. */
|
|
354
|
+
licenceRestriction?: string;
|
|
355
|
+
/** Fuel included max duration in minutes. */
|
|
356
|
+
fuelIncludedMaxMinutes?: number;
|
|
357
|
+
/** AR model URL (full quality). */
|
|
358
|
+
arModelUrl?: string;
|
|
359
|
+
/** AR model URL (optimized). */
|
|
360
|
+
arModelUrlOptimized?: string;
|
|
361
|
+
/** AR model URL (low quality). */
|
|
362
|
+
arModelUrlLow?: string;
|
|
296
363
|
}
|
|
297
364
|
/** Response wrapper for product listing. */
|
|
298
365
|
interface ProductListResponse {
|
|
299
366
|
products: Product[];
|
|
367
|
+
/** Category summaries for grouping products on the public site. */
|
|
368
|
+
categories?: ProductCategory[];
|
|
300
369
|
count: number;
|
|
301
370
|
}
|
|
371
|
+
/** Category summary returned alongside products for public display grouping. */
|
|
372
|
+
interface ProductCategory {
|
|
373
|
+
/** Machine-readable category key (e.g. `"jet_skis"`). */
|
|
374
|
+
category: string;
|
|
375
|
+
/** Display name (e.g. `"Jet Skis"`). */
|
|
376
|
+
name: string;
|
|
377
|
+
/** Short description. */
|
|
378
|
+
description: string;
|
|
379
|
+
/** Hex color for category card accent. */
|
|
380
|
+
color: string;
|
|
381
|
+
/** Sort order for display. */
|
|
382
|
+
sortOrder: number;
|
|
383
|
+
/** Number of products in this category. */
|
|
384
|
+
productCount: number;
|
|
385
|
+
/** Lowest price among products in this category (in cents). */
|
|
386
|
+
startingPriceCents: number;
|
|
387
|
+
/** Currency code (e.g. `"EUR"`). */
|
|
388
|
+
currency: string;
|
|
389
|
+
}
|
|
302
390
|
/** Request body for creating a payment intent. */
|
|
303
391
|
interface CreatePaymentIntentRequest {
|
|
304
392
|
/** Product ID being booked. */
|
|
@@ -898,4 +986,4 @@ declare class ResiraNetworkError extends ResiraError {
|
|
|
898
986
|
constructor(message: string, cause: unknown);
|
|
899
987
|
}
|
|
900
988
|
|
|
901
|
-
export { type ApiErrorBody, type Availability, type AvailabilityParams, type CheckoutConfig, type CheckoutSession, type CheckoutSessionResponse, type ConfirmPaymentRequest, type ConfirmPaymentResponse, type CreateCheckoutSessionRequest, type CreateCheckoutSessionResponse, type CreatePaymentIntentRequest, type CreateReservationRequest, type DateAvailability, type Dish, type DishListResponse, type DishModel, type DishResponse, type DurationPrice, type ListReservationsParams, type PaginatedReservations, type PaymentIntentResponse, type PricingModel, type Product, type ProductListResponse, type ProductVariant, type PromoCode, type PropertyConfig, type PublicResource, type RefundRule, type Reservation, type ReservationResponse, Resira, ResiraApiError, type ResiraConfig, ResiraError, ResiraNetworkError, ResiraRateLimitError, type ResourceImage, type ResourceImageDisplaySettings, type ResourceListResponse, type RiderTierPrice, type TimeSlotAvailability, type ValidatePromoCodeResponse, type WeightedBaseUrl, getRoutingStats };
|
|
989
|
+
export { type ApiErrorBody, type Availability, type AvailabilityParams, type CheckoutConfig, type CheckoutSession, type CheckoutSessionResponse, type ConfirmPaymentRequest, type ConfirmPaymentResponse, type CreateCheckoutSessionRequest, type CreateCheckoutSessionResponse, type CreatePaymentIntentRequest, type CreateReservationRequest, type DateAvailability, type Dish, type DishListResponse, type DishModel, type DishResponse, type DurationPrice, type ListReservationsParams, type PaginatedReservations, type PaymentIntentResponse, type PricingModel, type Product, type ProductCategory, type ProductImage, type ProductListResponse, type ProductVariant, type PromoCode, type PropertyConfig, type PublicResource, type RefundRule, type Reservation, type ReservationResponse, Resira, ResiraApiError, type ResiraConfig, ResiraError, ResiraNetworkError, ResiraRateLimitError, type ResourceImage, type ResourceImageDisplaySettings, type ResourceListResponse, type RiderTierPrice, type TimeSlotAvailability, type ValidatePromoCodeResponse, type WeightedBaseUrl, getRoutingStats };
|