{"version":3,"sources":["../src/index.ts","../src/auth/token-manager.ts","../src/utils/sanitize.ts","../src/errors.ts","../src/http/retry.ts","../src/utils/case.ts","../src/http/client.ts","../src/resources/calendar.ts","../src/models/inquiry.ts","../src/http/paginate.ts","../src/utils/cache.ts","../src/resources/inquiries.ts","../src/resources/messages.ts","../src/resources/properties.ts","../src/models/reservation.ts","../src/resources/reservations.ts","../src/resources/reviews.ts","../src/resources/user.ts","../src/resources/transactions.ts","../src/resources/payouts.ts","../src/resources/knowledge-hub.ts","../src/client.ts","../src/connect/resources/auth-codes.ts","../src/connect/paginate.ts","../src/connect/resources/customers.ts","../src/connect/resources/channels.ts","../src/connect/resources/listings.ts","../src/connect/resources/reservations.ts","../src/connect/resources/messaging.ts","../src/connect/resources/reviews.ts","../src/connect/resources/transactions.ts","../src/connect/resources/payouts.ts","../src/connect/resources/resolutions.ts","../src/connect/client.ts","../src/connect/index.ts","../src/connect/webhooks/types.ts","../src/connect/webhooks/verify.ts","../src/connect/filter.ts","../src/filters/reservation-filter.ts","../src/filters/property-filter.ts","../src/filters/inquiry-filter.ts"],"sourcesContent":["export const VERSION = '0.7.2'\n\nexport { HospitableClient } from './client'\nexport type { HospitableClientConfig, ResourceCacheConfig } from './client'\n\n// Connect API — partner-facing, multi-customer integration surface.\n// Public API types (e.g. Reservation, Review, Transaction) collide with\n// Connect API types of the same name, so Connect lives under a namespace.\n// Usage:\n//   import { HospitableConnectClient, Connect } from 'hospitable'\n//   const connect = new HospitableConnectClient({ token })\n//   const filter = new Connect.ConnectFilter().where('status', 'is', ['accept'])\nexport { HospitableConnectClient } from './connect/client'\nexport type { HospitableConnectClientConfig } from './connect/client'\nexport * as Connect from './connect'\n\nexport {\n  HospitableError,\n  AuthenticationError,\n  RateLimitError,\n  NotFoundError,\n  ValidationError,\n  ForbiddenError,\n  ServerError,\n  ConfigurationError,\n  createErrorFromResponse,\n} from './errors'\n\n// Aliases mandated by AGENTS.md — existing short names are retained for\n// backward compatibility; these let consumers catch by the spec names.\n// `ForbiddenError extends AuthenticationError`, so `instanceof HospitableAuthError`\n// catches both 401 and 403 per the AGENTS.md spec.\nexport {\n  AuthenticationError as HospitableAuthError,\n  ForbiddenError as HospitableForbiddenError,\n  RateLimitError as HospitableRateLimitError,\n  NotFoundError as HospitableNotFoundError,\n  ValidationError as HospitableValidationError,\n  ServerError as HospitableServerError,\n  ConfigurationError as HospitableConfigurationError,\n} from './errors'\n\nexport * from './models/index'\n\nexport { TokenManager } from './auth'\nexport type { TokenManagerConfig } from './auth'\n\nexport { paginate, collectAll } from './http/paginate'\nexport type { PageFetcher } from './http/paginate'\n\nexport { PropertiesResource } from './resources'\nexport type { PropertyListParams } from './resources'\n\nexport { ReservationsResource } from './resources'\n\nexport { MessagesResource } from './resources'\n\nexport { CalendarResource } from './resources'\n\nexport { ReviewsResource } from './resources'\n\nexport { InquiriesResource } from './resources'\n\nexport { UserResource } from './resources'\n\nexport { TransactionsResource } from './resources'\n\nexport { PayoutsResource } from './resources'\n\nexport { KnowledgeHubResource } from './resources'\n\nexport { sanitize, MemoryCache, cacheKey } from './utils'\nexport type { CacheConfig } from './utils'\n\nexport { ReservationFilter, PropertyFilter, InquiryFilter } from './filters'\n","declare const process: { env: Record<string, string | undefined> }\n\nexport interface TokenManagerConfig {\n  token?: string\n  refreshToken?: string\n  clientId?: string\n  clientSecret?: string\n  baseURL: string\n  /**\n   * Seconds until the caller-supplied `token` expires. Only consulted when\n   * both `token` and `refreshToken` are provided (OAuth rehydrate path).\n   * Defaults to 3600 — a conservative \"fresh\" assumption. Pass the server's\n   * `expires_in` response directly if you have it; pass a small value only\n   * when you know the token is near-expiry and want to force a proactive\n   * refresh on the next request.\n   */\n  expiresIn?: number\n}\n\ninterface OAuthTokenResponse {\n  access_token: string\n  refresh_token?: string\n  expires_in: number\n  token_type: string\n}\n\nexport class TokenManager {\n  private accessToken: string | undefined\n  private refreshToken: string | undefined\n  private expiresAt: number = 0\n  private refreshPromise: Promise<void> | null = null\n\n  constructor(private readonly config: TokenManagerConfig) {\n    if (config.token !== undefined && config.token.length === 0) {\n      throw new Error('token must be a non-empty string')\n    }\n    if (config.token && !config.refreshToken && !config.clientId) {\n      this.accessToken = config.token\n      this.expiresAt = Infinity\n    } else if (config.token) {\n      this.accessToken = config.token\n      this.refreshToken = config.refreshToken\n      const ttlSeconds = config.expiresIn ?? 3600\n      this.expiresAt = Date.now() + ttlSeconds * 1000\n    } else {\n      const envPat = process.env['HOSPITABLE_API_PAT']\n      if (envPat) {\n        this.accessToken = envPat\n        this.expiresAt = Infinity\n      }\n    }\n  }\n\n  async getAuthHeader(): Promise<string> {\n    if (this.needsRefresh()) {\n      await this.ensureRefreshed()\n    }\n    /* v8 ignore next 3 */\n    if (!this.accessToken) {\n      throw new Error('No access token available. Provide token or clientId+clientSecret.')\n    }\n    return `Bearer ${this.accessToken}`\n  }\n\n  private needsRefresh(): boolean {\n    if (this.expiresAt === Infinity) return false\n    return Date.now() >= this.expiresAt - 60_000\n  }\n\n  private async ensureRefreshed(): Promise<void> {\n    if (this.refreshPromise) {\n      await this.refreshPromise\n      return\n    }\n    this.refreshPromise = this.doRefresh().finally(() => {\n      this.refreshPromise = null\n    })\n    await this.refreshPromise\n  }\n\n  private async doRefresh(): Promise<void> {\n    const { clientId, clientSecret, baseURL } = this.config\n    if (!clientId || !clientSecret) {\n      throw new Error('Cannot refresh token: clientId and clientSecret are required')\n    }\n\n    const body = this.refreshToken\n      ? new URLSearchParams({\n          grant_type: 'refresh_token',\n          refresh_token: this.refreshToken,\n          client_id: clientId,\n          client_secret: clientSecret,\n        })\n      : new URLSearchParams({\n          grant_type: 'client_credentials',\n          client_id: clientId,\n          client_secret: clientSecret,\n        })\n\n    const response = await fetch(`${baseURL}/oauth/token`, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n      body: body.toString(),\n    })\n\n    if (!response.ok) {\n      // Drain the body to free the socket, but do NOT embed it in the\n      // thrown message: OAuth error responses can echo back credentials\n      // (client_secret in error_description) or PII. Callers who log\n      // errors would leak whatever the server returned.\n      await response.text().catch(() => '')\n      throw new Error(`Token refresh failed (${response.status})`)\n    }\n\n    const data = (await response.json()) as OAuthTokenResponse\n    this.accessToken = data.access_token\n    if (data.refresh_token) this.refreshToken = data.refresh_token\n    this.expiresAt = Date.now() + data.expires_in * 1000\n  }\n\n  async handleUnauthorized(): Promise<void> {\n    this.expiresAt = 0\n    await this.ensureRefreshed()\n  }\n}\n","// Personally-identifying guest fields.\nconst PII_FIELD_PATTERN = /^(email|phone|phoneNumbers|firstName|lastName|passportNumber|fullName|dateOfBirth|guestName|displayName|hostName|senderId)$/i\n\n// Auth / credential-bearing fields. Broad substring match — `token`,\n// `secret`, `apiKey`, `api_key`, and `authorization` all match as whole\n// words or substrings of longer field names. `password` is included for\n// defense-in-depth against hypothetical future endpoints but is heavily\n// carved out by SAFE_OVERRIDES below.\nconst SENSITIVE_PATTERN = /token|secret|password|credential|apiKey|api_key|authorization/i\n\n// Business / financial identity — added when the SDK started wrapping\n// /v2/user, /v2/transactions, /v2/payouts. These fields land on response\n// bodies and would leak through debug logs or caught-error handlers that\n// stringify whole payloads.\n//\n// Deliberate omissions:\n// - `platformId` — overloaded: on payouts it's a bank-transfer reference\n//   (sensitive), on messages/reservations it's a public platform ID. Field-\n//   name-based redaction can't distinguish; document the trade-off rather\n//   than over-redact and hide useful debug info.\n// - `city`, `state`, `country`, `company` — too broad to be individually\n//   identifying. The narrow fields (streetLine*, postalCode) provide the\n//   actual PII surface.\n// - `amount`, `paidOutAmount` — amounts are sensitive but not identifying;\n//   redacting them cripples debugging flow analysis.\nconst SENSITIVE_BIZ_PATTERN = /^(taxId|tax_id|vat|bankAccount|bank_account|streetLine1|street_line1|streetLine2|street_line2|postalCode|postal_code)$/i\n\n// Known field names that LOOK sensitive by pattern match but are NOT\n// auth credentials for this SDK's threat model. Checked before the\n// SENSITIVE_PATTERN so these pass through sanitize() unchanged.\n//\n// Rationale:\n// - `wifiPassword` / `wifi_password` — the Wi-Fi password a host shares\n//   with their guest for the stay. Agents fetching\n//   `property.details.wifiPassword` to include in a check-in message\n//   need to see the real value in debug output to diagnose \"guest can't\n//   connect to wifi\" issues. Redacting it in logs forces operators to\n//   disable sanitization globally (exposing real secrets) or bypass the\n//   SDK. Precise carve-out is safer than the collateral damage.\n//\n// If a future field appears that LOOKS like a credential by name but\n// actually isn't one in practice, add it here with a code comment\n// explaining why.\nconst SAFE_OVERRIDES = /^(wifiPassword|wifi_password)$/i\n\n/**\n * Recursively masks PII and sensitive fields in an object for safe logging.\n * Does NOT mutate the original — returns a new object with masked values.\n * Only affects log output; never called on actual API payloads.\n *\n * Patterns matched:\n * - {@link PII_FIELD_PATTERN} — guest-identifying fields (email, names, phone…)\n * - {@link SENSITIVE_PATTERN} — auth/credentials (token, secret, apiKey…)\n * - {@link SENSITIVE_BIZ_PATTERN} — business/financial identity\n *   (taxId, vat, bankAccount, streetLine*, postalCode)\n *\n * Override exceptions (pass through unchanged):\n * - {@link SAFE_OVERRIDES} — explicitly-safe fields that match a sensitive\n *   pattern but are not credentials in practice (e.g. `wifiPassword`)\n *\n * The patterns check both camelCase and snake_case forms so this function is\n * safe to call on raw server responses (pre-`deepSnakeToCamel`) as well as\n * post-conversion objects.\n */\nexport function sanitize(value: unknown, depth = 0): unknown {\n  if (depth > 10) return value // prevent infinite recursion\n  if (value === null || typeof value !== 'object') return value\n  if (Array.isArray(value)) return value.map((item) => sanitize(item, depth + 1))\n\n  const result: Record<string, unknown> = {}\n  for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n    // Safe-override check runs FIRST — a field on the allowlist passes\n    // through even if it would otherwise match the sensitive pattern.\n    if (SAFE_OVERRIDES.test(key)) {\n      result[key] = sanitize(val, depth + 1)\n      continue\n    }\n    if (\n      PII_FIELD_PATTERN.test(key) ||\n      SENSITIVE_PATTERN.test(key) ||\n      SENSITIVE_BIZ_PATTERN.test(key)\n    ) {\n      result[key] = '***'\n    } else {\n      result[key] = sanitize(val, depth + 1)\n    }\n  }\n  return result\n}\n","import { sanitize } from './utils/sanitize'\n\nexport class HospitableError extends Error {\n  readonly statusCode: number\n  readonly requestId: string | undefined\n\n  constructor(message: string, statusCode: number, requestId?: string) {\n    super(message)\n    this.name = 'HospitableError'\n    this.statusCode = statusCode\n    this.requestId = requestId\n    Object.setPrototypeOf(this, new.target.prototype)\n  }\n}\n\n/**\n * Thrown on 401 and 403 responses. AGENTS.md §Error Handling spec mandates\n * a single `HospitableAuthError` covering both. `ForbiddenError` extends\n * this class so `err instanceof HospitableAuthError` catches 403 too.\n *\n * The trailing `statusCode` parameter exists so {@link ForbiddenError} can\n * reuse the same constructor without duplicating the readonly-field dance.\n * Callers should prefer {@link ForbiddenError} over `new AuthenticationError(…, 403)`.\n */\nexport class AuthenticationError extends HospitableError {\n  constructor(\n    message = 'Authentication failed',\n    requestId?: string,\n    statusCode: 401 | 403 = 401,\n  ) {\n    super(message, statusCode, requestId)\n    this.name = 'HospitableAuthError'\n  }\n}\n\nexport class RateLimitError extends HospitableError {\n  readonly retryAfter: number\n\n  constructor(retryAfter: number, requestId?: string) {\n    super(`Rate limit exceeded. Retry after ${retryAfter}s`, 429, requestId)\n    this.name = 'HospitableRateLimitError'\n    this.retryAfter = retryAfter\n  }\n}\n\nexport class NotFoundError extends HospitableError {\n  readonly resource: string | undefined\n\n  constructor(message = 'Resource not found', requestId?: string, resource?: string) {\n    super(message, 404, requestId)\n    this.name = 'HospitableNotFoundError'\n    this.resource = resource\n  }\n}\n\nexport class ValidationError extends HospitableError {\n  readonly fields: Record<string, string[]>\n\n  constructor(message: string, fields: Record<string, string[]> = {}, requestId?: string) {\n    super(message, 422, requestId)\n    this.name = 'HospitableValidationError'\n    this.fields = fields\n  }\n}\n\nexport class ForbiddenError extends AuthenticationError {\n  constructor(message = 'Forbidden', requestId?: string) {\n    super(message, requestId, 403)\n    this.name = 'HospitableForbiddenError'\n  }\n}\n\nexport class ServerError extends HospitableError {\n  readonly attempts: number\n\n  constructor(message: string, statusCode: number, attempts: number, requestId?: string) {\n    super(message, statusCode, requestId)\n    this.name = 'HospitableServerError'\n    this.attempts = attempts\n  }\n}\n\n/**\n * Thrown for client-side configuration / usage errors detected before any\n * HTTP request is made — e.g. calling `InquiryFilter.toParams()` without\n * supplying the required `properties` filter.\n *\n * Carries `statusCode = 0` to signal \"no HTTP request happened\". It still\n * extends {@link HospitableError} so agents catching the base class handle\n * it alongside runtime HTTP errors without special-casing.\n */\nexport class ConfigurationError extends HospitableError {\n  constructor(message: string) {\n    super(message, 0)\n    this.name = 'HospitableConfigurationError'\n  }\n}\n\nexport function createErrorFromResponse(\n  statusCode: number,\n  body: Record<string, unknown>,\n  requestId?: string,\n  attempts = 1,\n  retryAfterOverride?: number,\n): HospitableError {\n  const message = (body['message'] as string | undefined) ?? `HTTP ${statusCode}`\n\n  switch (statusCode) {\n    case 401:\n      return new AuthenticationError(message, requestId)\n    case 403:\n      return new ForbiddenError(message, requestId)\n    case 404:\n      return new NotFoundError(message, requestId)\n    case 400:\n    case 422: {\n      const rawErrors = (body['errors'] as Record<string, string[]> | undefined) ?? {}\n      const errors = sanitize(rawErrors) as Record<string, string[]>\n      return new ValidationError(message, errors, requestId)\n    }\n    case 429: {\n      const retryAfter =\n        retryAfterOverride ??\n        (body['retryAfter'] as number | undefined) ??\n        60\n      return new RateLimitError(retryAfter, requestId)\n    }\n    default:\n      return new ServerError(message, statusCode, attempts, requestId)\n  }\n}\n","import { HospitableError, ServerError } from '../errors'\n\nexport interface RetryConfig {\n  maxAttempts?: number\n  baseDelay?: number\n  maxDelay?: number\n  onRateLimit?: (info: { retryAfter: number; endpoint: string; attempt: number }) => void\n}\n\nconst RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504])\n\nfunction jitteredDelay(base: number, attempt: number, max: number): number {\n  const exponential = Math.min(base * Math.pow(2, attempt - 1), max)\n  const jitter = exponential * 0.25 * (Math.random() * 2 - 1)\n  return Math.max(0, exponential + jitter)\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport async function withRetry<T>(\n  fn: () => Promise<T>,\n  endpoint: string,\n  config: RetryConfig = {},\n): Promise<T> {\n  const {\n    maxAttempts = 4,\n    baseDelay = 1000,\n    maxDelay = 60_000,\n    onRateLimit,\n  } = config\n\n  let lastError: unknown\n\n  for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n    try {\n      return await fn()\n    } catch (error) {\n      lastError = error\n\n      const statusCode = getStatusCode(error)\n      if (statusCode === null || !RETRYABLE_STATUS_CODES.has(statusCode)) {\n        throw error\n      }\n\n      if (attempt === maxAttempts) {\n        break\n      }\n\n      let delay: number\n      if (statusCode === 429 && error instanceof Error) {\n        const retryAfter = extractRetryAfter(error)\n        // Cap server-supplied retryAfter to maxDelay — a hostile or\n        // misconfigured upstream could otherwise stall the consumer's\n        // process for an unbounded duration.\n        delay =\n          retryAfter > 0\n            ? Math.min(retryAfter * 1000, maxDelay)\n            : jitteredDelay(baseDelay, attempt, maxDelay)\n        onRateLimit?.({ retryAfter, endpoint, attempt })\n      } else {\n        delay = jitteredDelay(baseDelay, attempt, maxDelay)\n      }\n\n      await sleep(delay)\n    }\n  }\n\n  // Preserve the original error type when it's already one of our typed\n  // errors — agents rely on `instanceof RateLimitError` etc., so wrapping\n  // an exhausted 429 in a generic ServerError would break narrowing.\n  if (lastError instanceof HospitableError) {\n    throw lastError\n  }\n  const statusCode = getStatusCode(lastError) ?? 500\n  const message = lastError instanceof Error ? lastError.message : `Request failed after ${maxAttempts} attempts`\n  throw new ServerError(message, statusCode, maxAttempts)\n}\n\nfunction getStatusCode(error: unknown): number | null {\n  if (error != null && typeof error === 'object' && 'statusCode' in error) {\n    const code = (error as { statusCode: unknown }).statusCode\n    if (typeof code === 'number') return code\n  }\n  return null\n}\n\nfunction extractRetryAfter(error: Error): number {\n  if ('retryAfter' in error && typeof (error as { retryAfter: unknown }).retryAfter === 'number') {\n    return (error as { retryAfter: number }).retryAfter\n  }\n  return 60\n}\n","export function snakeToCamel(s: string): string {\n  return s.replace(/_(\\w)/g, (_, c: string) => c.toUpperCase())\n}\n\nexport function camelToSnake(s: string): string {\n  return s.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)\n}\n\nexport function deepSnakeToCamel(obj: unknown, depth = 0): unknown {\n  if (depth > 20) return obj\n  if (Array.isArray(obj)) return obj.map(v => deepSnakeToCamel(v, depth + 1))\n  if (obj !== null && typeof obj === 'object') {\n    return Object.fromEntries(\n      Object.entries(obj as Record<string, unknown>).map(([k, v]) => [\n        k.includes('_') ? snakeToCamel(k) : k,\n        deepSnakeToCamel(v, depth + 1),\n      ])\n    )\n  }\n  return obj\n}\n\nexport function deepCamelToSnake(obj: unknown, depth = 0): unknown {\n  if (depth > 20) return obj\n  if (Array.isArray(obj)) return obj.map(v => deepCamelToSnake(v, depth + 1))\n  if (obj !== null && typeof obj === 'object') {\n    return Object.fromEntries(\n      Object.entries(obj as Record<string, unknown>).map(([k, v]) => [\n        /[A-Z]/.test(k) ? camelToSnake(k) : k,\n        deepCamelToSnake(v, depth + 1),\n      ])\n    )\n  }\n  return obj\n}\n","import { VERSION } from '../index'\nimport { withRetry, type RetryConfig } from './retry'\nimport { sanitize } from '../utils/sanitize'\nimport { camelToSnake, deepSnakeToCamel, deepCamelToSnake } from '../utils/case'\nimport { createErrorFromResponse, type HospitableError } from '../errors'\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n\nexport interface RequestOptions {\n  method?: HttpMethod\n  params?: Record<string, string | number | boolean | string[] | undefined>\n  body?: unknown\n  headers?: Record<string, string>\n}\n\nexport interface HttpClientConfig {\n  baseURL: string\n  getAuthHeader: () => Promise<string>\n  onUnauthorized?: () => Promise<void>\n  debug?: boolean\n  retryConfig?: RetryConfig\n}\n\n/**\n * Legacy HTTP error class.\n *\n * @deprecated Exported only for backward compatibility with code that\n * imported `HttpError` directly. New code should catch\n * {@link HospitableError} and its subclasses (`NotFoundError`,\n * `AuthenticationError`, `ValidationError`, etc.) — `HttpClient` now throws\n * those at runtime.\n */\nexport class HttpError extends Error {\n  constructor(\n    readonly statusCode: number,\n    message: string,\n    readonly requestId: string | undefined,\n    readonly body: Record<string, unknown>,\n    readonly attempts: number = 1,\n  ) {\n    super(message)\n    this.name = 'HttpError'\n  }\n}\n\nfunction buildURL(base: string, path: string, params?: RequestOptions['params']): string {\n  const url = new URL(path, base)\n  if (params) {\n    for (const [key, value] of Object.entries(params)) {\n      if (value === undefined) continue\n      const snakeKey = camelToSnake(key)\n      if (Array.isArray(value)) {\n        value.forEach((v) => url.searchParams.append(`${snakeKey}[]`, v))\n      } else {\n        url.searchParams.set(snakeKey, String(value))\n      }\n    }\n  }\n  return url.toString()\n}\n\nasync function readErrorBody(response: Response): Promise<Record<string, unknown>> {\n  try {\n    const raw = await response.json()\n    return deepSnakeToCamel(raw) as Record<string, unknown>\n  } catch {\n    return {}\n  }\n}\n\nfunction errorFromResponse(\n  response: Response,\n  body: Record<string, unknown>,\n): HospitableError {\n  const requestId = response.headers.get('x-request-id') ?? undefined\n  // RFC 6585 `Retry-After` — Hospitable (like most APIs) returns rate-limit\n  // backoff guidance via this header, not a JSON body field. Lift it here so\n  // `RateLimitError.retryAfter` reflects the server's actual wait request.\n  const retryAfterHeader = response.headers.get('Retry-After')\n  const retryAfterOverride =\n    retryAfterHeader !== null && /^\\d+$/.test(retryAfterHeader)\n      ? parseInt(retryAfterHeader, 10)\n      : undefined\n  // Fall back to a status-derived message when the body omits one so the\n  // thrown error always carries something more useful than \"undefined\".\n  if (body['message'] === undefined) {\n    body = { ...body, message: `HTTP ${response.status}` }\n  }\n  return createErrorFromResponse(response.status, body, requestId, 1, retryAfterOverride)\n}\n\nexport class HttpClient {\n  constructor(private readonly config: HttpClientConfig) {}\n\n  private async parseResponse<T>(response: Response): Promise<T> {\n    if (response.status === 204) return undefined as T\n    return response.json().then(deepSnakeToCamel) as Promise<T>\n  }\n\n  async request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n    const { method = 'GET', params, body, headers: extraHeaders = {} } = options\n    const url = buildURL(this.config.baseURL, path, params)\n\n    return withRetry(\n      async () => {\n        const authHeader = await this.config.getAuthHeader()\n\n        const headers: Record<string, string> = {\n          Accept: 'application/json',\n          Authorization: authHeader,\n          'User-Agent': `hospitable-ts/${VERSION}`,\n          ...extraHeaders,\n        }\n        if (body !== undefined) {\n          headers['Content-Type'] = 'application/json'\n        }\n\n        if (this.config.debug) {\n          console.debug(`[hospitable] ${method} ${url}`)\n          if (body !== undefined) {\n            console.debug('[hospitable] body:', sanitize(body))\n          }\n        }\n\n        const response = await fetch(url, {\n          method,\n          headers,\n          ...(body !== undefined ? { body: JSON.stringify(deepCamelToSnake(body)) } : {}),\n        })\n\n        if (!response.ok) {\n          const errorBody = await readErrorBody(response)\n          if (this.config.debug) {\n            console.debug('[hospitable] error body:', sanitize(errorBody))\n          }\n          if (response.status === 401 && this.config.onUnauthorized) {\n            await this.config.onUnauthorized()\n            const freshAuth = await this.config.getAuthHeader()\n            const retryResponse = await fetch(url, {\n              method,\n              headers: { ...headers, Authorization: freshAuth },\n              ...(body !== undefined ? { body: JSON.stringify(deepCamelToSnake(body)) } : {}),\n            })\n            if (retryResponse.ok) {\n              return this.parseResponse<T>(retryResponse)\n            }\n            throw errorFromResponse(retryResponse, await readErrorBody(retryResponse))\n          }\n          throw errorFromResponse(response, errorBody)\n        }\n\n        return this.parseResponse<T>(response)\n      },\n      url,\n      this.config.retryConfig,\n    )\n  }\n\n  get<T>(path: string, params?: RequestOptions['params']): Promise<T> {\n    return this.request<T>(path, { method: 'GET', ...(params !== undefined ? { params } : {}) })\n  }\n\n  post<T>(path: string, body?: unknown): Promise<T> {\n    return this.request<T>(path, { method: 'POST', body })\n  }\n\n  put<T>(path: string, body?: unknown): Promise<T> {\n    return this.request<T>(path, { method: 'PUT', body })\n  }\n\n  patch<T>(path: string, body?: unknown): Promise<T> {\n    return this.request<T>(path, { method: 'PATCH', body })\n  }\n\n  delete<T>(path: string): Promise<T> {\n    return this.request<T>(path, { method: 'DELETE' })\n  }\n}\n","import type { HttpClient } from '../http/client'\nimport type { CalendarData, CalendarUpdate } from '../models/calendar'\n\n/**\n * Resource for reading and mutating per-property calendar state: day\n * availability, nightly price, minimum stay, and owner blocks.\n *\n * Dates are always ISO `YYYY-MM-DD`. `update` and `block` are **additive** —\n * Hospitable merges the payload with existing calendar state rather than\n * replacing it.\n *\n * @see https://developer.hospitable.com/docs/public-api-docs/w7lb6cwd1dvx6-calendar-resource\n */\nexport class CalendarResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * Fetch calendar days for a property in `[startDate, endDate]` inclusive.\n   *\n   * @see GET https://public.api.hospitable.com/v2/properties/{id}/calendar\n   */\n  async get(\n    propertyId: string,\n    startDate: string,\n    endDate: string,\n  ): Promise<CalendarData> {\n    const response = await this.http.get<{ data: CalendarData }>(\n      `/v2/properties/${encodeURIComponent(propertyId)}/calendar`,\n      { startDate, endDate },\n    )\n    return response.data\n  }\n\n  /**\n   * Apply a batch of per-day calendar updates (price, availability, minStay,\n   * check-in/out restrictions, notes). Merges additively — only the fields\n   * provided on each `CalendarUpdate` entry are modified.\n   *\n   * `options.note` sets a top-level note applied to every date in `updates`\n   * that doesn't define its own `note`. Pass `null` to clear. Max 512 chars.\n   *\n   * @see PUT https://public.api.hospitable.com/v2/properties/{id}/calendar\n   */\n  async update(\n    propertyId: string,\n    updates: CalendarUpdate[],\n    options: { note?: string | null } = {},\n  ): Promise<void> {\n    const body: { note?: string | null; dates: CalendarUpdate[] } = { dates: updates }\n    if (options.note !== undefined) body.note = options.note\n    await this.http.put<void>(\n      `/v2/properties/${encodeURIComponent(propertyId)}/calendar`,\n      body,\n    )\n  }\n\n  /**\n   * Block a date range (e.g. owner stay, maintenance).\n   *\n   * @see POST https://public.api.hospitable.com/v2/properties/{id}/calendar/block\n   */\n  async block(\n    propertyId: string,\n    startDate: string,\n    endDate: string,\n    reason?: string,\n  ): Promise<void> {\n    const body: Record<string, string> = { startDate, endDate }\n    if (reason !== undefined) body['reason'] = reason\n    await this.http.post<void>(\n      `/v2/properties/${encodeURIComponent(propertyId)}/calendar/block`,\n      body,\n    )\n  }\n\n  /**\n   * Remove a previously placed block on a date range.\n   *\n   * @see POST https://public.api.hospitable.com/v2/properties/{id}/calendar/unblock\n   */\n  async unblock(propertyId: string, startDate: string, endDate: string): Promise<void> {\n    await this.http.post<void>(\n      `/v2/properties/${encodeURIComponent(propertyId)}/calendar/unblock`,\n      {\n        startDate,\n        endDate,\n      },\n    )\n  }\n}\n","import type { Property } from './property'\nimport type { Message } from './message'\nimport type { PaginatedResponse } from './pagination'\n\nexport interface InquiryGuestCounts {\n  total: number\n  adultCount: number\n  childCount: number\n  infantCount: number\n  petCount: number\n}\n\n/**\n * Inquiry guests return only first/last name by default. Extra fields may appear\n * when `include=guest` is passed — kept optional to avoid breaking on bare responses.\n */\nexport interface InquiryGuest {\n  firstName: string\n  lastName: string\n  email?: string | null\n  phoneNumbers?: string[]\n  profilePicture?: string | null\n  language?: string\n}\n\nexport interface InquiryListing {\n  platform: string\n  platformId: string\n  platformName?: string\n  platformEmail?: string\n}\n\nexport interface InquiryUser {\n  id: string\n  email: string\n  name: string\n}\n\n/**\n * An inquiry — the pre-booking conversation/request stage.\n *\n * `inquiry.id` **is the conversation ID** — pass it directly to\n * `client.messages.list(inquiry.id)` to fetch the message thread, or to\n * `client.messages.sendForInquiry(inquiry.id, body)` to reply.\n *\n * The Hospitable API returns a single `Property` in a field awkwardly named\n * `properties` (plural-but-singular). {@link normalizeInquiry} aliases it to\n * `property` for nicer DX — both reference the same object. Prefer\n * `inquiry.property` in new code.\n */\nexport interface Inquiry {\n  id: string\n  platform: string\n  inquiryDate: string\n  arrivalDate?: string\n  departureDate?: string\n  guests: InquiryGuestCounts\n  guest: InquiryGuest\n  /**\n   * Included via `include=properties`. Singular despite the plural name — API quirk.\n   * @deprecated Prefer {@link Inquiry.property}. Both point at the same object.\n   */\n  properties?: Property\n  /** Alias for `properties`, populated by `normalizeInquiry`. Same object reference. */\n  property?: Property\n  /** Included via `include=listings`. */\n  listings?: InquiryListing[]\n  /** Included via `include=user`. */\n  user?: InquiryUser\n  /** Included via `include=messages` (only available on get-by-uuid). */\n  messages?: Message[]\n}\n\nexport type InquiryList = PaginatedResponse<Inquiry>\n\nexport type InquiryIncludeField =\n  | 'financials'\n  | 'guest'\n  | 'user'\n  | 'properties'\n  | 'listings'\n  | 'messages'\n\nexport interface InquiryListParams {\n  /** Required by the API — array of property UUIDs to query. */\n  properties: string[]\n  /** Comma-separated: any of `financials,guest,properties,listings`. */\n  include?: string\n  /** Inquiries where the last message is after the specified datetime (ISO 8601). */\n  lastMessageAt?: string\n  page?: number\n  perPage?: number\n}\n\n/**\n * Normalize an Inquiry response by aliasing the `properties` field to `property`.\n *\n * Contract:\n *  - Mutates and returns the same inquiry object (resource code relies on identity).\n *  - No-op when `properties` is undefined (happens when the include was not requested).\n *  - Does NOT overwrite an existing `property` field if already set.\n */\nexport function normalizeInquiry(inquiry: Inquiry): Inquiry {\n  if (inquiry.properties && inquiry.property === undefined) {\n    inquiry.property = inquiry.properties\n  }\n  return inquiry\n}\n","import type { PaginatedResponse } from '../models/pagination'\n\nexport interface PageFetcher<T, P extends { page?: number; perPage?: number }> {\n  (params: P): Promise<PaginatedResponse<T>>\n}\n\nexport async function* paginate<T, P extends { page?: number; perPage?: number }>(\n  fetcher: PageFetcher<T, P>,\n  params: Omit<P, 'page'>,\n): AsyncGenerator<T> {\n  let page = 1\n  let lastPage = 1\n  do {\n    const result = await fetcher({ ...params, page } as P)\n    for (const item of result.data) {\n      yield item\n    }\n    lastPage = result.meta.lastPage ?? 0\n    page++\n  } while (page <= lastPage && lastPage > 0)\n}\n\n/**\n * Drain every item from a paginated source into an array.\n *\n * Two forms are supported:\n *\n * 1. **Iterable form** — the idiomatic shape for SDK consumers:\n *    ```ts\n *    const all = await collectAll(client.reservations.iter({ startDate: '2026-01-01' }))\n *    ```\n *\n * 2. **Fetcher form** — used when driving pagination against a raw\n *    `PageFetcher` without a resource class in scope:\n *    ```ts\n *    const all = await collectAll(params => http.get('/v2/things', params), { perPage: 50 })\n *    ```\n *\n * @remarks Both forms eagerly buffer the entire result set in memory. For\n * large streams (>10k items), prefer iterating directly with `for await`\n * and processing items as they arrive.\n */\nexport function collectAll<T>(iterable: AsyncIterable<T>): Promise<T[]>\nexport function collectAll<T, P extends { page?: number; perPage?: number }>(\n  fetcher: PageFetcher<T, P>,\n  params: Omit<P, 'page'>,\n): Promise<T[]>\nexport async function collectAll<T, P extends { page?: number; perPage?: number }>(\n  source: AsyncIterable<T> | PageFetcher<T, P>,\n  params?: Omit<P, 'page'>,\n): Promise<T[]> {\n  const results: T[] = []\n  const iterable: AsyncIterable<T> =\n    typeof source === 'function'\n      ? paginate(source, params ?? ({} as Omit<P, 'page'>))\n      : source\n  for await (const item of iterable) {\n    results.push(item)\n  }\n  return results\n}\n","export interface CacheConfig {\n  enabled?: boolean\n  ttl?: number\n  maxSize?: number\n}\n\ninterface CacheEntry<T> {\n  value: T\n  expiresAt: number\n}\n\nexport class MemoryCache<T> {\n  private store = new Map<string, CacheEntry<T>>()\n  private readonly ttl: number\n  private readonly maxSize: number\n\n  constructor(config: CacheConfig = {}) {\n    this.ttl = config.ttl ?? 60_000\n    this.maxSize = config.maxSize ?? 100\n  }\n\n  get(key: string): T | undefined {\n    const entry = this.store.get(key)\n    if (!entry) return undefined\n    if (Date.now() > entry.expiresAt) {\n      this.store.delete(key)\n      return undefined\n    }\n    this.store.delete(key)\n    this.store.set(key, entry)\n    return entry.value\n  }\n\n  set(key: string, value: T): void {\n    this.store.delete(key)\n    if (this.store.size >= this.maxSize) {\n      const now = Date.now()\n      for (const [k, e] of this.store) {\n        if (now > e.expiresAt) this.store.delete(k)\n      }\n    }\n    if (this.store.size >= this.maxSize) {\n      const oldest = this.store.keys().next().value\n      if (oldest !== undefined) this.store.delete(oldest)\n    }\n    this.store.set(key, { value, expiresAt: Date.now() + this.ttl })\n  }\n\n  has(key: string): boolean {\n    const entry = this.store.get(key)\n    if (!entry) return false\n    if (Date.now() > entry.expiresAt) {\n      this.store.delete(key)\n      return false\n    }\n    return true\n  }\n\n  delete(key: string): boolean {\n    return this.store.delete(key)\n  }\n\n  clear(): void {\n    this.store.clear()\n  }\n\n  get size(): number {\n    return this.store.size\n  }\n}\n\nexport function cacheKey(prefix: string, params?: Record<string, unknown>): string {\n  if (!params || Object.keys(params).length === 0) return prefix\n  const sorted = Object.keys(params).sort().reduce<Record<string, unknown>>((acc, k) => {\n    if (params[k] !== undefined) acc[k] = params[k]\n    return acc\n  }, {})\n  return `${prefix}:${JSON.stringify(sorted)}`\n}\n","import type { HttpClient, RequestOptions } from '../http/client'\nimport type {\n  Inquiry,\n  InquiryList,\n  InquiryListParams,\n} from '../models/inquiry'\nimport { normalizeInquiry } from '../models/inquiry'\nimport { paginate } from '../http/paginate'\nimport { MemoryCache, cacheKey, type CacheConfig } from '../utils/cache'\n\nconst DEFAULT_TTL = 60_000\n\nfunction normalizeListParams(params: InquiryListParams) {\n  return {\n    page: params.page,\n    properties: params.properties,\n    include: params.include,\n    lastMessageAt: params.lastMessageAt,\n    perPage: params.perPage,\n  }\n}\n\n/**\n * Resource for the Hospitable Inquiries API — pre-booking conversations.\n *\n * Note: an inquiry's `id` is also the conversation ID, so you can pass it\n * directly to `client.messages.list(inquiry.id)` to fetch the message thread.\n *\n * @see https://developer.hospitable.com/docs/public-api-docs/9lujw5cgctxti-get-inquiries\n * @see https://developer.hospitable.com/docs/public-api-docs/yczg8erku08qw-get-inquiry-by-uuid\n */\nexport class InquiriesResource {\n  private cache: MemoryCache<unknown> | null\n\n  constructor(\n    private readonly http: HttpClient,\n    cacheConfig?: CacheConfig,\n  ) {\n    const enabled = cacheConfig?.enabled ?? false\n    this.cache = enabled\n      ? new MemoryCache({\n          ttl: cacheConfig?.ttl ?? DEFAULT_TTL,\n          ...(cacheConfig?.maxSize !== undefined ? { maxSize: cacheConfig.maxSize } : {}),\n        })\n      : null\n  }\n\n  private async fetchList(params: InquiryListParams): Promise<InquiryList> {\n    const normalized = normalizeListParams(params)\n    const response = await this.http.get<InquiryList>(\n      '/v2/inquiries',\n      normalized as RequestOptions['params'],\n    )\n    // Return a fresh wrapper rather than mutating the value returned by\n    // `http.get` — callers expect the HTTP client's return value to be\n    // treated as immutable.\n    return { ...response, data: response.data.map(normalizeInquiry) }\n  }\n\n  /**\n   * List inquiries for the given properties.\n   *\n   * `params.properties` is required by the API — enforced at the type level.\n   * Each returned inquiry is passed through {@link normalizeInquiry}, so the\n   * `property` alias is populated alongside the raw `properties` field when\n   * `include=properties` is requested.\n   *\n   * @see GET https://public.api.hospitable.com/v2/inquiries\n   */\n  async list(params: InquiryListParams): Promise<InquiryList> {\n    const normalized = normalizeListParams(params)\n    const key = cacheKey('inquiries:list', normalized as unknown as Record<string, unknown>)\n    if (this.cache) {\n      const cached = this.cache.get(key) as InquiryList | undefined\n      if (cached) return cached\n    }\n    const result = await this.fetchList(params)\n    this.cache?.set(key, result)\n    return result\n  }\n\n  /**\n   * Fetch a single inquiry by UUID (which is the conversation ID).\n   *\n   * The optional `include` parameter accepts a comma-separated list of:\n   * `financials`, `guest`, `properties`, `listings`, `messages`. Note that\n   * `messages` is only supported on this endpoint, not on {@link list}.\n   *\n   * **Envelope quirk**: unlike the list endpoint, the single-inquiry\n   * response is wrapped in `{data: Inquiry}`. The SDK unwraps it so\n   * callers always receive a bare {@link Inquiry}.\n   *\n   * @see GET https://public.api.hospitable.com/v2/inquiries/{uuid}\n   * @throws {NotFoundError} on 404 (inquiry does not exist)\n   * @throws {HospitableError} on 410 (inquiry has been deleted upstream)\n   * @throws {ServerError} on 5xx after retries are exhausted\n   */\n  async get(uuid: string, include?: string): Promise<Inquiry> {\n    const key = cacheKey('inquiries:get', { uuid, include })\n    if (this.cache) {\n      const cached = this.cache.get(key) as Inquiry | undefined\n      if (cached) return cached\n    }\n    const response = await this.http.get<{ data: Inquiry }>(\n      `/v2/inquiries/${encodeURIComponent(uuid)}`,\n      include ? { include } : undefined,\n    )\n    const normalized = normalizeInquiry(response.data)\n    this.cache?.set(key, normalized)\n    return normalized\n  }\n\n  /**\n   * Stream every inquiry matching `params`, auto-paginating through all pages.\n   *\n   * Memory-efficient — pulls one page at a time. Pass the same params you'd\n   * pass to {@link list}, minus `page` which is managed by the generator.\n   *\n   * @see GET https://public.api.hospitable.com/v2/inquiries\n   */\n  async *iter(params: Omit<InquiryListParams, 'page'>): AsyncGenerator<Inquiry> {\n    yield* paginate<Inquiry, InquiryListParams>(p => this.fetchList(p), params)\n  }\n\n  /** Drop the in-memory cache. Called automatically by the client on 401 re-auth. */\n  clearCache(): void {\n    this.cache?.clear()\n  }\n}\n","import type { HttpClient } from '../http/client'\nimport type {\n  Message,\n  MessageThread,\n  MessageTemplate,\n  MessageReceipt,\n  SendMessageOptions,\n  SendReservationMessageOptions,\n} from '../models/message'\n\n/**\n * Resource for reading and sending messages on reservations and inquiries.\n *\n * **Which send method to use?**\n *\n * | Conversation state                       | Call                                     |\n * | ---------------------------------------- | ---------------------------------------- |\n * | `reservation.id` known (booking exists)  | {@link send} — accepts `images` attachments |\n * | `inquiry.id` known, no reservation yet   | {@link sendForInquiry} — no `images`     |\n *\n * Calling the wrong endpoint returns 410 or 422. Since `inquiry.id ===\n * conversation_id`, reading a message thread works the same for both:\n * `client.messages.list(reservationOrInquiryId)`.\n *\n * Both send methods return `202 Accepted` with a `MessageReceipt` —\n * delivery happens out-of-band on the upstream channel (Airbnb, VRBO,\n * Booking.com, direct). Persist `receipt.sentReferenceId` and match it\n * against `Message.sentReferenceId` on a subsequent `list()` to confirm.\n *\n * Rate limits (both endpoints): **2/minute per target**, **50 per 5\n * minutes globally**. The retry layer handles 429 automatically.\n */\nexport class MessagesResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * List the message thread for a reservation.\n   *\n   * @see GET https://public.api.hospitable.com/v2/reservations/{uuid}/messages\n   */\n  async list(reservationId: string): Promise<MessageThread> {\n    const response = await this.http.get<{ data: Message[] }>(\n      `/v2/reservations/${encodeURIComponent(reservationId)}/messages`,\n    )\n    return {\n      reservationId,\n      messages: response.data ?? [],\n    }\n  }\n\n  /**\n   * Send a message on a reservation.\n   *\n   * Returns an async receipt with a `sentReferenceId` — the API responds with\n   * 202 Accepted and delivers asynchronously on the upstream channel. Match\n   * the `sentReferenceId` against messages fetched via {@link list} afterwards\n   * to confirm delivery landed.\n   *\n   * Rate limits: 2/minute per reservation, 50 per 5 minutes globally. The\n   * SDK's retry layer handles 429 responses automatically.\n   *\n   * @see POST https://public.api.hospitable.com/v2/reservations/{uuid}/messages\n   */\n  async send(\n    reservationId: string,\n    body: string,\n    options?: SendReservationMessageOptions,\n  ): Promise<MessageReceipt> {\n    const payload: { body: string } & SendReservationMessageOptions = { body, ...options }\n    const response = await this.http.post<{ data: MessageReceipt }>(\n      `/v2/reservations/${encodeURIComponent(reservationId)}/messages`,\n      payload,\n    )\n    return response.data\n  }\n\n  /**\n   * Send a message on an inquiry (pre-booking conversation).\n   *\n   * The `inquiryUuid` is the conversation_id — same as `inquiry.id`. Use this\n   * endpoint when a conversation exists but hasn't yet produced a reservation\n   * (i.e. the guest is still in the \"inquiry\" stage). Once it becomes a\n   * reservation, switch to {@link send} instead.\n   *\n   * Returns an async receipt with a `sentReferenceId` — match it against the\n   * `sentReferenceId` on Message resources fetched afterwards to correlate\n   * delivery on upstream channels (Airbnb, VRBO, etc).\n   *\n   * Rate limits: 2/minute per inquiry, 50 per 5 minutes globally.\n   *\n   * @see POST https://public.api.hospitable.com/v2/inquiries/{uuid}/messages\n   * @throws {HospitableError} 410 if the inquiry has been deleted upstream.\n   * @throws {RateLimitError} 429 after retries are exhausted (`.retryAfter` in seconds).\n   * @throws {ValidationError} 422 if the conversation has already become a reservation — use {@link send} instead.\n   */\n  async sendForInquiry(\n    inquiryUuid: string,\n    body: string,\n    options?: SendMessageOptions,\n  ): Promise<MessageReceipt> {\n    const payload: { body: string } & SendMessageOptions = { body, ...options }\n    const response = await this.http.post<{ data: MessageReceipt }>(\n      `/v2/inquiries/${encodeURIComponent(inquiryUuid)}/messages`,\n      payload,\n    )\n    return response.data\n  }\n\n  /**\n   * List available message templates.\n   *\n   * @see GET https://public.api.hospitable.com/v2/message-templates\n   */\n  async listTemplates(): Promise<MessageTemplate[]> {\n    const response = await this.http.get<{ data: MessageTemplate[] }>('/v2/message-templates')\n    return response.data\n  }\n\n  /**\n   * Send a message on a reservation using a message template.\n   *\n   * @see POST https://public.api.hospitable.com/v2/reservations/{uuid}/messages/template\n   */\n  async sendTemplate(\n    reservationId: string,\n    templateId: string,\n    variables: Record<string, string> = {},\n  ): Promise<Message> {\n    const response = await this.http.post<{ data: Message }>(\n      `/v2/reservations/${encodeURIComponent(reservationId)}/messages/template`,\n      { templateId, variables },\n    )\n    return response.data\n  }\n}\n","import type { HttpClient, RequestOptions } from '../http/client'\nimport type {\n  Property,\n  PropertyIcalImport,\n  PropertyImage,\n  PropertyList,\n  PropertySearchParams,\n  PropertyTag,\n  CreateIcalImportOptions,\n  UpdateIcalImportOptions,\n} from '../models/property'\nimport type { CreateQuoteParams } from '../models/quote'\nimport { paginate } from '../http/paginate'\nimport { MemoryCache, cacheKey, type CacheConfig } from '../utils/cache'\nimport { ConfigurationError } from '../errors'\n\nconst DEFAULT_TTL = 86_400_000\n\nexport interface PropertyListParams {\n  page?: number\n  perPage?: number\n  tags?: string[]\n  /**\n   * Comma-separated include fields. Valid values are members of\n   * {@link PropertyIncludeField}: `'user'`, `'listings'`, `'details'`,\n   * `'bookings'`. Unknown values are silently ignored by the API — pass\n   * only the literals to avoid typos that fail open.\n   *\n   * Example: `include: 'user,listings,details'`\n   */\n  include?: string\n}\n\n/**\n * Resource for the Hospitable Properties API.\n *\n * Properties rarely change, so this resource's default cache TTL is 24h\n * when caching is enabled. Cache is cleared automatically by the client\n * on 401 re-auth.\n *\n * @see https://developer.hospitable.com/docs/public-api-docs/1i1kr1bhpg0ku-properties-resource\n */\nexport class PropertiesResource {\n  private cache: MemoryCache<unknown> | null\n\n  constructor(\n    private readonly http: HttpClient,\n    cacheConfig?: CacheConfig,\n  ) {\n    const enabled = cacheConfig?.enabled ?? false\n    this.cache = enabled\n      ? new MemoryCache({ ttl: cacheConfig?.ttl ?? DEFAULT_TTL, ...(cacheConfig?.maxSize !== undefined ? { maxSize: cacheConfig.maxSize } : {}) })\n      : null\n  }\n\n  private fetchList(params: PropertyListParams = {}): Promise<PropertyList> {\n    return this.http.get<PropertyList>('/v2/properties', params as RequestOptions['params'])\n  }\n\n  /**\n   * List properties, optionally filtered by tags.\n   *\n   * @see GET https://public.api.hospitable.com/v2/properties\n   */\n  async list(params: PropertyListParams = {}): Promise<PropertyList> {\n    const key = cacheKey('properties:list', params as Record<string, unknown>)\n    if (this.cache) {\n      const cached = this.cache.get(key) as PropertyList | undefined\n      if (cached) return cached\n    }\n    const result = await this.fetchList(params)\n    this.cache?.set(key, result)\n    return result\n  }\n\n  /**\n   * Fetch a single property by UUID.\n   *\n   * Pass `include` as a comma-separated list of {@link PropertyIncludeField}\n   * values — `'user'`, `'listings'`, `'details'`, `'bookings'` — to\n   * side-load related data onto the response.\n   *\n   * **Envelope quirk**: unlike the list endpoint, the single-property\n   * response is wrapped in `{data: Property}`. The SDK unwraps it so\n   * callers always receive a bare {@link Property}. This is an API-side\n   * inconsistency (also present on `/v2/user`), not an SDK bug.\n   *\n   * @see GET https://public.api.hospitable.com/v2/properties/{id}\n   * @throws {NotFoundError} on 404\n   */\n  async get(id: string, include?: string): Promise<Property> {\n    const key = cacheKey('properties:get', { id, include })\n    if (this.cache) {\n      const cached = this.cache.get(key) as Property | undefined\n      if (cached) return cached\n    }\n    const response = await this.http.get<{ data: Property }>(\n      `/v2/properties/${encodeURIComponent(id)}`,\n      include ? { include } : undefined,\n    )\n    const result = response.data\n    this.cache?.set(key, result)\n    return result\n  }\n\n  /**\n   * List all tags attached to a given property. These are the structured\n   * org-level tags from the tag registry, distinct from the free-text\n   * `Property.tags` field inline on the property object.\n   *\n   * @see GET https://public.api.hospitable.com/v2/properties/{id}/tags\n   */\n  async listTags(id: string): Promise<PropertyTag[]> {\n    const key = cacheKey('properties:tags', { id })\n    if (this.cache) {\n      const cached = this.cache.get(key) as PropertyTag[] | undefined\n      if (cached) return cached\n    }\n    const response = await this.http.get<{ data: PropertyTag[] }>(\n      `/v2/properties/${encodeURIComponent(id)}/tags`,\n    )\n    this.cache?.set(key, response.data)\n    return response.data\n  }\n\n  /**\n   * Fetch all images attached to a property, ordered by display position.\n   *\n   * @see GET https://public.api.hospitable.com/v2/properties/{id}/images\n   */\n  async getImages(id: string): Promise<PropertyImage[]> {\n    // Not cached: Hospitable returns pre-signed S3 URLs (typically ~1h\n    // expiry) and the properties-resource default TTL is 24h. Caching\n    // would serve expired URLs that return 403 Forbidden with no helpful\n    // error. Callers who need the array in-memory should hold the\n    // promise themselves.\n    const response = await this.http.get<{ data: PropertyImage[] }>(\n      `/v2/properties/${encodeURIComponent(id)}/images`,\n    )\n    return response.data\n  }\n\n  /**\n   * Search for available properties matching a window and party size.\n   *\n   * All three of `startDate`, `endDate`, and `adults` are **required** by\n   * the API — the SDK passes them through as-is and the server returns 400\n   * if any are missing.\n   *\n   * Unlike {@link list}, search results are availability-filtered — only\n   * properties that can host the given dates/guests appear.\n   *\n   * @see GET https://public.api.hospitable.com/v2/properties/search\n   */\n  async search(params: PropertySearchParams): Promise<PropertyList> {\n    return this.http.get<PropertyList>(\n      '/v2/properties/search',\n      params as unknown as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * Stream every property matching `params`, auto-paginating through all pages.\n   *\n   * Memory-efficient — pulls one page at a time. Pair with\n   * `collectAll(client.properties.iter())` to drain into an array.\n   */\n  async *iter(params: Omit<PropertyListParams, 'page'> = {}): AsyncGenerator<Property> {\n    yield* paginate<Property, PropertyListParams>(p => this.fetchList(p), params)\n  }\n\n  /**\n   * Add tags to a property. The API accepts 1-10 tags per call.\n   *\n   * @see POST https://public.api.hospitable.com/v2/properties/{id}/tags\n   * @throws {ConfigurationError} when `tags` is empty or exceeds 10 items\n   */\n  async addTags(uuid: string, tags: string[]): Promise<void> {\n    if (tags.length === 0 || tags.length > 10) {\n      throw new ConfigurationError(\n        'properties.addTags: `tags` must contain 1-10 tag strings. ' +\n        'The Hospitable API rejects empty or oversized tag arrays. ' +\n        'Example: client.properties.addTags(propertyId, [\"beach\", \"pool\"]).',\n      )\n    }\n    await this.http.post<void>(\n      `/v2/properties/${encodeURIComponent(uuid)}/tags`,\n      { tags },\n    )\n    this.cache?.clear()\n  }\n\n  /**\n   * Request a price quote for a property.\n   *\n   * Requires the \"Direct\" feature on the Hospitable account. Response\n   * shape is typed as `unknown` — see {@link CreateQuoteParams} for the\n   * input contract.\n   *\n   * @returns The quote response from the API. Typed as `unknown` because\n   * the return shape couldn't be probed (account lacks \"Direct\" feature).\n   * Inspect the response object and narrow with a type guard at the call\n   * site. Expected to contain pricing breakdown fields.\n   *\n   * @see POST https://public.api.hospitable.com/v2/properties/{id}/quote\n   */\n  async createQuote(uuid: string, params: CreateQuoteParams): Promise<unknown> {\n    return this.http.post<unknown>(\n      `/v2/properties/${encodeURIComponent(uuid)}/quote`,\n      params,\n    )\n  }\n\n  /**\n   * Create an iCal import feed on a property.\n   *\n   * @see POST https://public.api.hospitable.com/v2/properties/{id}/ical-imports\n   */\n  async createIcalImport(\n    uuid: string,\n    url: string,\n    options?: CreateIcalImportOptions,\n  ): Promise<PropertyIcalImport> {\n    const response = await this.http.post<{ data: PropertyIcalImport }>(\n      `/v2/properties/${encodeURIComponent(uuid)}/ical-imports`,\n      { url, ...options },\n    )\n    return response.data\n  }\n\n  /**\n   * Update an existing iCal import feed on a property.\n   *\n   * @see PUT https://public.api.hospitable.com/v2/properties/{id}/ical-imports/{icalUuid}\n   */\n  async updateIcalImport(\n    uuid: string,\n    icalUuid: string,\n    options: UpdateIcalImportOptions = {},\n  ): Promise<PropertyIcalImport> {\n    const response = await this.http.put<{ data: PropertyIcalImport }>(\n      `/v2/properties/${encodeURIComponent(uuid)}/ical-imports/${encodeURIComponent(icalUuid)}`,\n      options,\n    )\n    return response.data\n  }\n\n  /** Drop the in-memory cache. Called automatically by the client on 401 re-auth. */\n  clearCache(): void {\n    this.cache?.clear()\n  }\n}\n","/**\n * Status of a reservation as returned by the Hospitable API.\n *\n * Values are lowercase snake_case strings. Use {@link isReservationStatus}\n * to narrow an unknown string to this type.\n *\n * ⚠️ Spelling trap: the legacy {@link Reservation.status} and\n * {@link ReservationStatusHistoryEntry} fields use British `cancelled`, while\n * the older {@link ReservationLegacyStatusHistoryEntry} (exposed on the\n * `status_history` field) uses American `canceled`. New code should read\n * {@link Reservation.reservationStatus} and avoid both legacy shapes.\n */\nexport type ReservationStatus =\n  | 'not_accepted'\n  | 'request'\n  | 'accepted'\n  | 'cancelled'\n  | 'checkpoint'\n\nexport const RESERVATION_STATUSES = [\n  'not_accepted',\n  'request',\n  'accepted',\n  'cancelled',\n  'checkpoint',\n] as const satisfies readonly ReservationStatus[]\n\n/** Type guard for {@link ReservationStatus}. */\nexport function isReservationStatus(value: unknown): value is ReservationStatus {\n  return typeof value === 'string' && (RESERVATION_STATUSES as readonly string[]).includes(value)\n}\n\n/**\n * Booking platform the reservation originated on. Kept as an open string\n * union — the upstream API may surface additional platforms (`homeaway`,\n * `custom-direct`, etc.) that agents should pass through rather than reject.\n */\nexport type ReservationPlatform = 'airbnb' | 'vrbo' | 'booking_com' | 'direct' | (string & {})\n\n/**\n * Include fields accepted by `GET /v2/reservations` and `GET /v2/reservations/{id}`.\n *\n * Empirically verified against the live API on 2026-04-11. Unknown includes\n * are silently ignored by the server — passing an invalid value won't error,\n * it just won't populate any extra fields.\n */\nexport type ReservationIncludeField =\n  | 'guest'\n  | 'user'\n  | 'financials'\n  | 'listings'\n  | 'properties'\n  | 'review'\n  | 'smartlock_code'\n\n/**\n * Selector for which date field `startDate`/`endDate` filter against.\n *\n * - `checkin` (default) — filter by `check_in` date. Use this to find\n *   reservations arriving in a window.\n * - `checkout` — filter by `check_out` date. Use this to find reservations\n *   departing in a window, or guests currently in-house.\n *\n * The API only accepts these two literal values. Other values (including\n * `checkin_or_checkout`) return 400.\n */\nexport type ReservationDateQuery = 'checkin' | 'checkout'\n\nexport interface Guest {\n  id: string\n  firstName: string\n  lastName: string\n  email: string | null\n  phoneNumbers: string[]\n  profilePicture: string | null\n  location: string | null\n  language: string\n}\n\nexport interface ReservationGuests {\n  total: number\n  adultCount: number\n  childCount: number\n  infantCount: number\n  petCount: number\n}\n\n/**\n * A single line-item on a reservation's financial breakdown. Used by\n * every entry inside the `guest` and `host` subsections of\n * {@link ReservationFinancials} — accommodation, fees, discounts, taxes,\n * adjustments, payments, and totals all share this exact shape.\n *\n * ⚠️ **`amount` can be negative** — discounts and host-side service\n * fees arrive as negative integers (e.g. `-121365` for a\n * `-$1,213.65` early-bird discount). Don't assume positivity.\n */\nexport interface ReservationFinancialLineItem {\n  /** Minor currency units (cents for USD). May be negative. */\n  amount: number\n  /** Pre-formatted display string, e.g. `\"$1,483.35\"` or `\"-$1,213.65\"`. */\n  formatted: string\n  /** Human-readable label, e.g. `\"Cleaning Fee\"`, `\"Early Bird Discount\"`. */\n  label: string\n  /**\n   * Grouping category. Values seen: `\"Accommodation\"`, `\"Guest fees\"`,\n   * `\"Guest total price\"`, `\"Host Tax\"`, `\"Service fees\"`, `\"Discounts\"`,\n   * `\"Revenue\"`. Open string union for forward compatibility.\n   */\n  category: string\n}\n\n/**\n * Guest-facing financial breakdown — what the guest is shown and charged\n * on the booking platform. Every sub-array is `[]` when no entries\n * apply; arrays are never `null`.\n */\nexport interface ReservationFinancialsGuest {\n  /** Base room rate before fees/taxes/discounts. */\n  accommodation: ReservationFinancialLineItem\n  /** Accommodation amount divided by night count, for display. */\n  averageNightlyRate: ReservationFinancialLineItem\n  /** Guest-side fees (cleaning, pet, extra-guest, etc.). */\n  fees: ReservationFinancialLineItem[]\n  /** Guest-side discounts. Amounts are negative. */\n  discounts: ReservationFinancialLineItem[]\n  /** Taxes charged to the guest (occupancy, lodging, VAT, etc.). */\n  taxes: ReservationFinancialLineItem[]\n  /** Manual adjustments applied to the guest total. */\n  adjustments: ReservationFinancialLineItem[]\n  /** Payment records (typically populated post-stay). */\n  payments: ReservationFinancialLineItem[]\n  /** Final total charged to the guest. */\n  totalPrice: ReservationFinancialLineItem\n}\n\n/**\n * Host-side financial breakdown — what the host earns after platform\n * fees. This is the \"revenue\" side of the ledger.\n */\nexport interface ReservationFinancialsHost {\n  /** Base accommodation revenue. */\n  accommodation: ReservationFinancialLineItem\n  /**\n   * Per-day rate breakdown. `null` when the stay is a single flat rate;\n   * otherwise an array with one entry per night, labeled with the date.\n   */\n  accommodationBreakdown: ReservationFinancialLineItem[] | null\n  /** Fees collected from the guest and passed through to the host. */\n  guestFees: ReservationFinancialLineItem[]\n  /** Host-side service fees charged by the platform. Amounts typically negative. */\n  hostFees: ReservationFinancialLineItem[]\n  /** Host-side discounts (promotional, loyalty, etc.). Amounts negative. */\n  discounts: ReservationFinancialLineItem[]\n  /** Manual adjustments applied to host revenue. */\n  adjustments: ReservationFinancialLineItem[]\n  /** Taxes withheld from host revenue (rare — usually guest-side). */\n  taxes: ReservationFinancialLineItem[]\n  /** Final amount the host receives after all adjustments. */\n  revenue: ReservationFinancialLineItem\n}\n\n/**\n * Full financial breakdown for a reservation. Returned when the\n * `include=financials` query parameter is passed to the reservations\n * list or get endpoint. Requires the `financials:read` OAuth2 scope on\n * the access token.\n *\n * Split into `guest` (what the guest pays) and `host` (what the host\n * receives). The two sides are reconciled via platform fees, taxes, and\n * service charges — see {@link ReservationFinancialsHost.hostFees} for\n * the platform's cut.\n *\n * @see GET https://public.api.hospitable.com/v2/reservations (include=financials)\n */\nexport interface ReservationFinancials {\n  /** ISO 4217 currency code (e.g. `\"USD\"`). */\n  currency: string\n  guest: ReservationFinancialsGuest\n  host: ReservationFinancialsHost\n}\n\n/**\n * Structured status object returned by the current API on the\n * `reservation_status` field. Carries both the current state and a full\n * history of transitions with sub-category detail the flat {@link\n * Reservation.status} string cannot express (e.g. `accepted` +\n * `early_checkin_requested`).\n *\n * Prefer this over {@link Reservation.status} / {@link Reservation.statusHistory}\n * in new code.\n */\nexport interface ReservationStatusObject {\n  current: {\n    category: ReservationStatus\n    subCategory: string | null\n  }\n  history: ReservationStatusHistoryEntry[]\n}\n\nexport interface ReservationStatusHistoryEntry {\n  category: ReservationStatus\n  subCategory: string | null\n  changedAt: string\n}\n\n/**\n * Legacy status history entry exposed on the `status_history` field.\n *\n * ⚠️ The `status` field here uses **American** spelling (`canceled`) while\n * everything else in the API uses British spelling (`cancelled`). Strict\n * equality against `'cancelled'` will silently miss matches. Migrate to\n * {@link ReservationStatusObject.history} which uses consistent British spelling.\n *\n * @deprecated Use {@link Reservation.reservationStatus}.\n */\nexport interface ReservationLegacyStatusHistoryEntry {\n  /** Human-readable label, e.g. \"Accepted\", \"Cancelled\". */\n  category: string\n  /** Raw status value — **uses American spelling** (`canceled` vs `cancelled`). */\n  status: string\n  changedAt: string\n}\n\nexport interface Reservation {\n  id: string\n  code: string\n  platform: ReservationPlatform\n  platformId: string\n  bookingDate: string\n  arrivalDate: string\n  departureDate: string\n  checkIn: string\n  checkOut: string\n  nights: number\n  stayType: string\n  ownerStay: boolean | null\n\n  /**\n   * Structured status with history. Preferred over {@link status} and\n   * {@link statusHistory} — carries sub-category detail the flat string\n   * cannot express, and uses consistent British spelling throughout.\n   */\n  reservationStatus: ReservationStatusObject\n\n  /**\n   * Legacy flat status string. Uses British spelling (`cancelled`).\n   * @deprecated Read {@link reservationStatus}.current.category instead.\n   */\n  status: ReservationStatus\n\n  /**\n   * Legacy status history array.\n   *\n   * ⚠️ **Spelling trap**: each entry's `.status` field uses **American**\n   * spelling (`canceled`) while the modern {@link ReservationStatus} union\n   * uses British spelling (`cancelled`). Strict-equality checks against\n   * `'cancelled'` would silently miss matches on raw API data.\n   *\n   * The SDK's `ReservationsResource` normalizes this on every response\n   * (via `normalizeReservation()`), so you'll actually see `'cancelled'`\n   * here when reading through the client. But if you receive a Reservation\n   * from any other source — webhook payload, cached pre-normalization,\n   * hand-constructed test fixture — the raw value may still be `'canceled'`.\n   *\n   * @deprecated Read {@link reservationStatus}.history instead — it uses\n   *   consistent British spelling upstream and includes `subCategory`\n   *   detail this legacy field can't express.\n   */\n  statusHistory: ReservationLegacyStatusHistoryEntry[]\n\n  guests: ReservationGuests\n  /** Only populated when `include=guest` is requested. */\n  guest?: Guest\n  /** Only populated when `include=user` is requested. */\n  user?: ReservationUser\n  /**\n   * Full financial breakdown. Populated only when `include=financials`\n   * is requested and the access token has the `financials:read` scope.\n   */\n  financials?: ReservationFinancials\n  /** Only populated when `include=properties` is requested. */\n  properties?: unknown[]\n  /** Only populated when `include=listings` is requested. */\n  listings?: unknown[]\n  /**\n   * Only populated when `include=review` is requested. `null` when the\n   * reservation has no review yet (e.g. still in progress, or cancelled).\n   */\n  review?: unknown | null\n  /**\n   * Smart-lock access code for the property during this reservation,\n   * typically a 4-digit numeric string. Populated only when\n   * `include=smartlock_code` is requested. `null` when the property has\n   * no smart lock configured, or the reservation doesn't have a code\n   * assigned yet (e.g. cancelled, far-future, not-accepted).\n   *\n   * This field is **not** redacted by `sanitize()` — like `wifiPassword`\n   * on a property, it's a shareable credential an agent needs to include\n   * in guest check-in messages. Don't log raw Reservation objects to\n   * stdout in contexts where bystanders might see them.\n   *\n   * Wire format: the API serializes this as `smartlock_code`\n   * (snake_case); the SDK's `deepSnakeToCamel` converts it to\n   * `smartlockCode` on the TypeScript side.\n   */\n  smartlockCode?: string | null\n\n  notes: string | null\n  conversationId: string\n  conversationLanguage: string | null\n  lastMessageAt: string | null\n  issueAlert: unknown\n}\n\n/** User/host attached to a reservation via `include=user`. */\nexport interface ReservationUser {\n  id: string\n  email: string\n  name: string\n  profilePicture: string | null\n}\n\nexport type ReservationList = import('./pagination').PaginatedResponse<Reservation>\n\n/**\n * Normalize a Reservation returned by the API so legacy fields are safe\n * to compare against modern `ReservationStatus` values.\n *\n * Specifically: the legacy `status_history[].status` field uses American\n * spelling (`canceled`), while every other status field in the API uses\n * British spelling (`cancelled`). An agent doing\n * `r.statusHistory.some(h => h.status === 'cancelled')` would silently\n * miss cancelled reservations — a business-logic bug with real financial\n * impact (charges sent to guests who canceled, \"in-house\" classification\n * of guests who canceled, etc.).\n *\n * This normalizer rewrites `canceled` → `cancelled` in place on each\n * `statusHistory` entry's `status` field. It's called by\n * `ReservationsResource.list()`, `.get()`, and `.iter()` so consumers\n * always see consistent British spelling.\n *\n * Idempotent and safe on partial / incomplete data: missing fields are\n * left alone.\n *\n * Contract:\n *  - Mutates and returns the same reservation object.\n *  - Only touches `statusHistory[].status` when the value is exactly\n *    `'canceled'` — any other value is preserved.\n */\nexport function normalizeReservation(reservation: Reservation): Reservation {\n  if (Array.isArray(reservation.statusHistory)) {\n    for (const entry of reservation.statusHistory) {\n      if (entry.status === 'canceled') {\n        entry.status = 'cancelled'\n      }\n    }\n  }\n  return reservation\n}\n\n/**\n * Who initiated the cancellation — used as the body of\n * `POST /v2/reservations/{uuid}/cancel`.\n */\nexport type CancelReservationInitiatedBy = 'host' | 'guest'\n\n/**\n * WRITE-side input shape for reservation financials. NOT the same as\n * {@link ReservationFinancials} (READ-side with nested guest/host\n * subsections). All amounts in minor currency units (cents).\n *\n * @see POST https://public.api.hospitable.com/v2/reservations\n */\nexport interface CreateReservationFinancials {\n  /** ISO 4217 currency code (e.g. `\"USD\"`). */\n  currency: string\n  /** Base accommodation amount in minor currency units. */\n  accommodation: number\n  cleaningFee?: number\n  linenFee?: number\n  managementFee?: number\n  communityFee?: number\n  petFee?: number\n  resortFee?: number\n  passThroughTaxes?: number\n  otherFees?: Array<{ label: string; amount: number }>\n}\n\n/** Guest contact info for creating a reservation. */\nexport interface CreateReservationGuest {\n  firstName: string\n  lastName: string\n  email: string\n  phone?: string\n}\n\n/** Guest headcounts for creating/updating a reservation. */\nexport interface CreateReservationGuestCounts {\n  adults: number\n  children?: number\n  infants?: number\n  pets?: number\n}\n\n/**\n * Parameters for `POST /v2/reservations` — creating a direct reservation.\n *\n * @see POST https://public.api.hospitable.com/v2/reservations\n */\nexport interface CreateReservationParams {\n  propertyId: string\n  /** ISO `YYYY-MM-DD` check-in date. */\n  checkIn: string\n  /** ISO `YYYY-MM-DD` check-out date. */\n  checkOut: string\n  guests: CreateReservationGuestCounts\n  guest: CreateReservationGuest\n  /** Two-letter language code (e.g. `\"en\"`). */\n  language: string\n  financials: CreateReservationFinancials\n  channel?: string\n  notes?: string\n  reservationCode?: string\n  include?: string\n}\n\n/**\n * Parameters for `PUT /v2/reservations/{uuid}` — updating an existing\n * reservation. Currency is not required on update (inherited from the\n * existing reservation).\n *\n * @see PUT https://public.api.hospitable.com/v2/reservations/{uuid}\n */\nexport interface UpdateReservationParams {\n  checkIn: string\n  checkOut: string\n  guests: CreateReservationGuestCounts\n  guest: CreateReservationGuest\n  language: string\n  financials: Omit<CreateReservationFinancials, 'currency'>\n  notes?: string\n  include?: string\n}\n\nexport interface ReservationListParams {\n  /**\n   * Property UUIDs to scope the search to. **Required by the API** — omit\n   * this and the server returns `400 \"The properties field is required.\"`.\n   * The SDK throws a {@link ConfigurationError} before the request is sent\n   * so agents get actionable feedback without a round trip.\n   */\n  properties: string[]\n  /** ISO `YYYY-MM-DD` — lower bound on the date field chosen by `dateQuery`. */\n  startDate?: string\n  /** ISO `YYYY-MM-DD` — upper bound on the date field chosen by `dateQuery`. */\n  endDate?: string\n  /**\n   * Which date field `startDate`/`endDate` filter against.\n   * Defaults to `checkin` on the API side if omitted.\n   */\n  dateQuery?: ReservationDateQuery\n  /**\n   * Only reservations whose last-message timestamp is on or after this value.\n   *\n   * ⚠️ Format quirk: the API expects **`YYYY-MM-DD HH:MM:SS`** (space-separated,\n   * no timezone), NOT ISO 8601. Example: `'2026-01-15 14:30:00'`.\n   */\n  lastMessageAt?: string\n  /**\n   * Filter by reservation status. Single value or array. Serialized as\n   * repeated `status[]=` query params.\n   */\n  status?: ReservationStatus | ReservationStatus[]\n  /**\n   * Comma-separated include fields. Prefer {@link ReservationIncludeField}.\n   * Unknown values are silently ignored by the API.\n   */\n  include?: string\n  page?: number\n  perPage?: number\n}\n","import type { HttpClient, RequestOptions } from '../http/client'\nimport type {\n  Reservation,\n  ReservationList,\n  ReservationListParams,\n  CancelReservationInitiatedBy,\n  CreateReservationParams,\n  UpdateReservationParams,\n} from '../models/reservation'\nimport { normalizeReservation } from '../models/reservation'\nimport type { EnrichmentField } from '../models/enrichment'\nimport { paginate } from '../http/paginate'\nimport { MemoryCache, cacheKey, type CacheConfig } from '../utils/cache'\nimport { ConfigurationError } from '../errors'\n\nconst DEFAULT_TTL = 60_000\n\n/**\n * Verify that `properties` is present and non-empty. The API requires this\n * field — throwing locally lets agents read the error message and self-correct\n * in one turn instead of round-tripping through a 400.\n *\n * Called from `list()` and `iter()` — the only two public entry points that\n * reach `fetchList()`. The private `fetchList()` trusts its callers rather\n * than re-validating, so the same guard doesn't run twice on a cache miss.\n */\nfunction assertPropertiesPresent(params: ReservationListParams): void {\n  if (!params.properties || params.properties.length === 0) {\n    throw new ConfigurationError(\n      'reservations.list: `properties` is required and must be a non-empty array of property UUIDs. ' +\n        'The Hospitable API rejects requests without this filter. ' +\n        'Example: client.reservations.list({ properties: [propertyId] }).',\n    )\n  }\n}\n\nfunction normalizeListParams(params: ReservationListParams) {\n  return {\n    page: params.page,\n    properties: params.properties,\n    startDate: params.startDate,\n    endDate: params.endDate,\n    dateQuery: params.dateQuery,\n    lastMessageAt: params.lastMessageAt,\n    status: Array.isArray(params.status) ? params.status : params.status ? [params.status] : undefined,\n    include: params.include,\n    perPage: params.perPage,\n  }\n}\n\n/**\n * Apply `normalizeReservation` to every entry in a paginated list while\n * preserving the `meta`/`links` wrapper. Returns a fresh wrapper so the\n * caller never mutates the HTTP response identity.\n */\nfunction normalizeList(list: ReservationList): ReservationList {\n  return { ...list, data: list.data.map(normalizeReservation) }\n}\n\n/**\n * Resource for the Hospitable Reservations API.\n *\n * Default cache TTL is 60 seconds when caching is enabled — reservations\n * move too quickly for long-lived caching.\n *\n * @see https://developer.hospitable.com/docs/public-api-docs/a6ba5e23bc9cb-reservations-resource\n */\nexport class ReservationsResource {\n  private cache: MemoryCache<unknown> | null\n\n  constructor(\n    private readonly http: HttpClient,\n    cacheConfig?: CacheConfig,\n  ) {\n    const enabled = cacheConfig?.enabled ?? false\n    this.cache = enabled\n      ? new MemoryCache({ ttl: cacheConfig?.ttl ?? DEFAULT_TTL, ...(cacheConfig?.maxSize !== undefined ? { maxSize: cacheConfig.maxSize } : {}) })\n      : null\n  }\n\n  /**\n   * Private fetcher used by `list()` and `iter()`. Trusts its caller to\n   * have already validated `params.properties` via `assertPropertiesPresent`\n   * — do not call this directly without validation.\n   */\n  private async fetchList(params: ReservationListParams): Promise<ReservationList> {\n    const normalized = normalizeListParams(params)\n    const raw = await this.http.get<ReservationList>(\n      '/v2/reservations',\n      normalized as RequestOptions['params'],\n    )\n    return normalizeList(raw)\n  }\n\n  /**\n   * List reservations, filtered by the supplied params.\n   *\n   * `params.properties` is required — the API returns 400 without it, so the\n   * SDK throws a {@link ConfigurationError} before making the request.\n   *\n   * Use `dateQuery` to choose whether `startDate`/`endDate` filter against\n   * `check_in` (default) or `check_out`. Swap to `'checkout'` to find\n   * reservations departing in a window or guests currently in-house — see\n   * {@link getInHouse} for the convenience wrapper.\n   *\n   * Every returned reservation passes through `normalizeReservation()` so\n   * the legacy `statusHistory[].status` field uses consistent British\n   * spelling (`'cancelled'`, not `'canceled'`) — see the type's JSDoc for\n   * the full rationale.\n   *\n   * @see {@link ReservationFilter} for a fluent builder\n   * @see GET https://public.api.hospitable.com/v2/reservations\n   * @throws {ConfigurationError} when `properties` is empty or missing\n   */\n  async list(params: ReservationListParams): Promise<ReservationList> {\n    assertPropertiesPresent(params)\n    const key = cacheKey(\n      'reservations:list',\n      normalizeListParams(params) as unknown as Record<string, unknown>,\n    )\n    if (this.cache) {\n      const cached = this.cache.get(key) as ReservationList | undefined\n      if (cached) return cached\n    }\n    const result = await this.fetchList(params)\n    this.cache?.set(key, result)\n    return result\n  }\n\n  /**\n   * Fetch a single reservation by UUID.\n   *\n   * **Envelope quirk**: unlike the list endpoint, the single-reservation\n   * response is wrapped in `{data: Reservation}`. The SDK unwraps it so\n   * callers always receive a bare {@link Reservation}. Mutating endpoints\n   * ({@link cancel}, {@link create}, {@link update}) wrap their responses\n   * the same way and unwrap identically.\n   *\n   * @see GET https://public.api.hospitable.com/v2/reservations/{id}\n   * @throws {NotFoundError} on 404\n   */\n  async get(id: string, include?: string): Promise<Reservation> {\n    const key = cacheKey('reservations:get', { id, include })\n    if (this.cache) {\n      const cached = this.cache.get(key) as Reservation | undefined\n      if (cached) return cached\n    }\n    const response = await this.http.get<{ data: Reservation }>(\n      `/v2/reservations/${encodeURIComponent(id)}`,\n      include ? { include } : undefined,\n    )\n    const result = normalizeReservation(response.data)\n    this.cache?.set(key, result)\n    return result\n  }\n\n  /**\n   * Convenience wrapper: accepted reservations arriving on or after today,\n   * for the given properties. Equivalent to\n   * `list({ properties, startDate: today, status: 'accepted', dateQuery: 'checkin' })`.\n   *\n   * Defaults `include` to `'guest,properties'` so agents get a useful\n   * payload without needing to remember the include-field list.\n   */\n  async getUpcoming(\n    propertyIds: string[],\n    options: { include?: string } = {},\n  ): Promise<ReservationList> {\n    const today = new Date().toISOString().split('T')[0]!\n    return this.list({\n      properties: propertyIds,\n      startDate: today,\n      status: 'accepted',\n      dateQuery: 'checkin',\n      include: options.include ?? 'guest,properties',\n    })\n  }\n\n  /**\n   * Convenience wrapper: guests **currently in-house** — accepted\n   * reservations that have started but not yet ended.\n   *\n   * Returns a plain `Reservation[]` rather than a paginated wrapper because\n   * this method performs a client-side filter and pagination metadata from\n   * the upstream response would be misleading (it would count reservations\n   * filtered out locally).\n   *\n   * Implementation: streams `iter()` with `dateQuery: 'checkout'` and\n   * `startDate: today` — fetching every reservation whose check-out is\n   * today or later (haven't departed yet) — and filters locally to those\n   * whose `arrivalDate` is today or earlier (already arrived).\n   *\n   * The two-filter approach is necessary because the Hospitable API only\n   * accepts a single `date_query` at a time, and \"in-house\" needs\n   * constraints on both check-in and check-out.\n   *\n   * Defaults `include` to `'guest,properties'` so agents have usable data\n   * without remembering the include-field list.\n   *\n   * ⚠️ **Timezone caveat**: \"today\" is computed from the SDK host's UTC\n   * clock (`new Date().toISOString().split('T')[0]`), not from each\n   * property's local timezone. For properties in strongly offset\n   * timezones (e.g. Hawaii at UTC-10), calling this method during the\n   * UTC-boundary window (~0:00–10:00 UTC) can misclassify a same-day\n   * turnover by one day — a guest arriving \"today\" local time may read\n   * as arriving \"yesterday\" UTC, and the filter may either include or\n   * exclude them depending on their check-out date. If your properties\n   * span multiple timezones and you need millisecond-correct boundary\n   * behavior, query `list()` directly with a timezone-aware `today`.\n   */\n  async getInHouse(\n    propertyIds: string[],\n    options: { include?: string } = {},\n  ): Promise<Reservation[]> {\n    const today = new Date().toISOString().split('T')[0]!\n    const result: Reservation[] = []\n    for await (const r of this.iter({\n      properties: propertyIds,\n      startDate: today,\n      dateQuery: 'checkout',\n      status: 'accepted',\n      include: options.include ?? 'guest,properties',\n    })) {\n      if (r.arrivalDate.slice(0, 10) <= today) result.push(r)\n    }\n    return result\n  }\n\n  /**\n   * Stream every reservation matching `params`, auto-paginating through all pages.\n   *\n   * Memory-efficient — pulls one page at a time. Pair with\n   * `collectAll(client.reservations.iter(...))` to drain into an array.\n   *\n   * @throws {ConfigurationError} when `params.properties` is empty or missing\n   */\n  async *iter(params: Omit<ReservationListParams, 'page'>): AsyncGenerator<Reservation> {\n    assertPropertiesPresent(params)\n    yield* paginate<Reservation, ReservationListParams>(p => this.fetchList(p), params)\n  }\n\n  /**\n   * Cancel a reservation.\n   *\n   * @see POST https://public.api.hospitable.com/v2/reservations/{uuid}/cancel\n   */\n  async cancel(uuid: string, initiatedBy: CancelReservationInitiatedBy): Promise<Reservation> {\n    const response = await this.http.post<{ data: Reservation }>(\n      `/v2/reservations/${encodeURIComponent(uuid)}/cancel`,\n      { initiatedBy },\n    )\n    return normalizeReservation(response.data)\n  }\n\n  /**\n   * Create a new direct reservation.\n   *\n   * @see POST https://public.api.hospitable.com/v2/reservations\n   */\n  async create(params: CreateReservationParams): Promise<Reservation> {\n    const response = await this.http.post<{ data: Reservation }>('/v2/reservations', params)\n    return normalizeReservation(response.data)\n  }\n\n  /**\n   * Update an existing reservation.\n   *\n   * @see PUT https://public.api.hospitable.com/v2/reservations/{uuid}\n   */\n  async update(uuid: string, params: UpdateReservationParams): Promise<Reservation> {\n    const response = await this.http.put<{ data: Reservation }>(\n      `/v2/reservations/${encodeURIComponent(uuid)}`,\n      params,\n    )\n    return normalizeReservation(response.data)\n  }\n\n  /**\n   * List all enrichment fields for a reservation.\n   *\n   * @see GET https://public.api.hospitable.com/v2/reservations/{uuid}/enrichment\n   */\n  async listEnrichment(uuid: string): Promise<EnrichmentField[]> {\n    const response = await this.http.get<{ data: EnrichmentField[] }>(\n      `/v2/reservations/${encodeURIComponent(uuid)}/enrichment`,\n    )\n    return response.data\n  }\n\n  /**\n   * Get a single enrichment field by key.\n   *\n   * @see GET https://public.api.hospitable.com/v2/reservations/{uuid}/enrichment/{key}\n   */\n  async getEnrichment(uuid: string, key: string): Promise<EnrichmentField> {\n    return this.http.get<EnrichmentField>(\n      `/v2/reservations/${encodeURIComponent(uuid)}/enrichment/${encodeURIComponent(key)}`,\n    )\n  }\n\n  /**\n   * Update a single enrichment field. Pass `null` to clear the value.\n   *\n   * @see PUT https://public.api.hospitable.com/v2/reservations/{uuid}/enrichment/{key}\n   */\n  async updateEnrichment(uuid: string, key: string, value: string | null): Promise<EnrichmentField> {\n    return this.http.put<EnrichmentField>(\n      `/v2/reservations/${encodeURIComponent(uuid)}/enrichment/${encodeURIComponent(key)}`,\n      { value },\n    )\n  }\n\n  /** Drop the in-memory cache. Called automatically by the client on 401 re-auth. */\n  clearCache(): void {\n    this.cache?.clear()\n  }\n}\n","import type { HttpClient, RequestOptions } from '../http/client'\nimport type { Review, ReviewList, ReviewListParams } from '../models/review'\nimport { paginate } from '../http/paginate'\n\n/**\n * Resource for listing and responding to guest reviews.\n *\n * Reviews are scoped to a property: all list/iter calls take a `propertyId`\n * as the first argument. Use `params.responded = false` to pull only the\n * reviews still awaiting a host response.\n *\n * @see https://developer.hospitable.com/docs/public-api-docs/v8ue8kuzpfgvj-reviews-resource\n */\nexport class ReviewsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(propertyId: string, params: ReviewListParams = {}): Promise<ReviewList> {\n    const normalized: RequestOptions['params'] = {}\n    if (params.responded !== undefined) normalized['responded'] = params.responded\n    if (params.include !== undefined) normalized['include'] = params.include\n    if (params.perPage !== undefined) normalized['perPage'] = params.perPage\n    if (params.page !== undefined) normalized['page'] = params.page\n    return this.http.get<ReviewList>(\n      `/v2/properties/${encodeURIComponent(propertyId)}/reviews`,\n      normalized,\n    )\n  }\n\n  /**\n   * List reviews for a property. Pass `{ responded: false }` to surface\n   * only reviews still waiting on a host response.\n   *\n   * @see GET https://public.api.hospitable.com/v2/properties/{id}/reviews\n   */\n  async list(propertyId: string, params: ReviewListParams = {}): Promise<ReviewList> {\n    return this.fetchList(propertyId, params)\n  }\n\n  /**\n   * Post a host response to a review.\n   *\n   * @see POST https://public.api.hospitable.com/v2/reviews/{id}/respond\n   */\n  async respond(id: string, responseText: string): Promise<Review> {\n    return this.http.post<Review>(\n      `/v2/reviews/${encodeURIComponent(id)}/respond`,\n      { response: responseText },\n    )\n  }\n\n  /**\n   * Stream every review matching `params` for a property, auto-paginating\n   * through all pages.\n   */\n  async *iter(propertyId: string, params: Omit<ReviewListParams, 'page'> = {}): AsyncGenerator<Review> {\n    yield* paginate<Review, ReviewListParams>(p => this.fetchList(propertyId, p), params)\n  }\n}\n","import type { HttpClient } from '../http/client'\nimport type { User } from '../models/user'\n\n/**\n * Resource for the single-user `/v2/user` endpoint.\n *\n * Returns the authenticated account's identity + business profile. This is\n * the canonical \"who am I\" call — agents can use it to discover the\n * account's company metadata, billing address, and host identity without\n * scraping it from a reservation include.\n *\n * **Envelope quirk**: unlike `/v2/properties/{id}` which returns the\n * resource object directly, `/v2/user` wraps its response in `{data: ...}`.\n * The SDK unwraps this envelope so callers get a bare {@link User} object.\n * This is an API-side inconsistency, not an SDK bug — see\n * `examples/probe-api-surface.ts` for the raw shape.\n *\n * **Not cached**: user identity changes rarely but not never (business\n * profile edits, email changes). The SDK does not cache this response; if\n * you're calling it in a hot loop, hoist the result yourself.\n *\n * @see GET https://public.api.hospitable.com/v2/user\n */\nexport class UserResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * Fetch the authenticated user's profile and business info.\n   *\n   * @see GET https://public.api.hospitable.com/v2/user\n   */\n  async get(): Promise<User> {\n    const response = await this.http.get<{ data: User }>('/v2/user')\n    return response.data\n  }\n}\n","import type { HttpClient, RequestOptions } from '../http/client'\nimport type {\n  Transaction,\n  TransactionList,\n  TransactionListParams,\n} from '../models/transaction'\nimport { paginate } from '../http/paginate'\n\n/**\n * Resource for the Hospitable Transactions API.\n *\n * Requires the `financials:read` scope on the access token.\n *\n * ⚠️ **Unbounded-query risk for agents**: unlike `reservations.list()`,\n * this endpoint does not require any mandatory filter. Calling\n * `transactions.iter()` with no params will stream the account's **entire\n * transaction history** (hundreds to thousands of rows on active\n * accounts). Always pass `startDate`/`endDate` or `properties` to scope\n * the query when building agentic workflows — a prompt-injected agent\n * that calls `iter()` without bounds will happily exfiltrate the full\n * financial history in one turn.\n *\n * @see GET https://public.api.hospitable.com/v2/transactions\n */\nexport class TransactionsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(params: TransactionListParams = {}): Promise<TransactionList> {\n    return this.http.get<TransactionList>('/v2/transactions', params as RequestOptions['params'])\n  }\n\n  /**\n   * Fetch a single transaction by UUID.\n   *\n   * @see GET https://public.api.hospitable.com/v2/transactions/{uuid}\n   * @throws {NotFoundError} on 404\n   */\n  async get(uuid: string, include?: string): Promise<Transaction> {\n    const response = await this.http.get<{ data: Transaction }>(\n      `/v2/transactions/${encodeURIComponent(uuid)}`,\n      include ? { include } : undefined,\n    )\n    return response.data\n  }\n\n  /**\n   * List financial transactions. Use `startDate`/`endDate` to scope to a\n   * reporting window.\n   *\n   * @see GET https://public.api.hospitable.com/v2/transactions\n   */\n  async list(params: TransactionListParams = {}): Promise<TransactionList> {\n    return this.fetchList(params)\n  }\n\n  /**\n   * Stream every transaction matching `params`, auto-paginating through\n   * all pages.\n   *\n   * ⚠️ **Always pass bounds.** Calling this with no params streams the\n   * entire account history — see the resource-level JSDoc. Prefer\n   * `{ startDate, endDate }` or `{ properties }` scoping, especially in\n   * agent-driven code paths.\n   */\n  async *iter(params: Omit<TransactionListParams, 'page'> = {}): AsyncGenerator<Transaction> {\n    yield* paginate<Transaction, TransactionListParams>(p => this.fetchList(p), params)\n  }\n}\n","import type { HttpClient, RequestOptions } from '../http/client'\nimport type { Payout, PayoutList, PayoutListParams } from '../models/payout'\nimport { paginate } from '../http/paginate'\n\n/**\n * Resource for the Hospitable Payouts API.\n *\n * Requires the `financials:read` scope on the access token.\n *\n * ⚠️ **Unbounded-query risk for agents**: like {@link TransactionsResource},\n * this endpoint does not require any mandatory filter. Calling\n * `payouts.iter()` with no params will stream the **entire payout\n * history** (often hundreds of rows). Scope with `startDate`/`endDate` or\n * `properties` when building agent workflows, especially if inputs may\n * be attacker-influenced.\n *\n * @see GET https://public.api.hospitable.com/v2/payouts\n */\nexport class PayoutsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(params: PayoutListParams = {}): Promise<PayoutList> {\n    return this.http.get<PayoutList>('/v2/payouts', params as RequestOptions['params'])\n  }\n\n  /**\n   * Fetch a single payout by UUID.\n   *\n   * @see GET https://public.api.hospitable.com/v2/payouts/{uuid}\n   * @throws {NotFoundError} on 404\n   */\n  async get(uuid: string, include?: string): Promise<Payout> {\n    const response = await this.http.get<{ data: Payout }>(\n      `/v2/payouts/${encodeURIComponent(uuid)}`,\n      include ? { include } : undefined,\n    )\n    return response.data\n  }\n\n  /**\n   * List payouts. Use `startDate`/`endDate` to scope to a reporting window.\n   *\n   * @see GET https://public.api.hospitable.com/v2/payouts\n   */\n  async list(params: PayoutListParams = {}): Promise<PayoutList> {\n    return this.fetchList(params)\n  }\n\n  /**\n   * Stream every payout matching `params`, auto-paginating through all pages.\n   *\n   * ⚠️ **Always pass bounds.** See resource-level JSDoc for the rationale.\n   */\n  async *iter(params: Omit<PayoutListParams, 'page'> = {}): AsyncGenerator<Payout> {\n    yield* paginate<Payout, PayoutListParams>(p => this.fetchList(p), params)\n  }\n}\n","import type { HttpClient } from '../http/client'\nimport type {\n  KnowledgeHub,\n  KnowledgeHubItem,\n  CreateKnowledgeHubItemOptions,\n  UpdateKnowledgeHubItemOptions,\n} from '../models/knowledge-hub'\n\n/**\n * Resource for the Hospitable Knowledge Hub API.\n *\n * The Knowledge Hub stores structured Q&A content that the Hospitable AI\n * draws on when composing guest replies. Content is organized by\n * property, grouped into topics, and broken into individual items.\n *\n * @see GET https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub\n */\nexport class KnowledgeHubResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * Fetch the full Knowledge Hub for a property — topics, items, and sources.\n   *\n   * @see GET https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub\n   */\n  async get(propertyUuid: string): Promise<KnowledgeHub> {\n    const response = await this.http.get<{ data: KnowledgeHub }>(\n      `/v2/properties/${encodeURIComponent(propertyUuid)}/knowledge-hub`,\n    )\n    return response.data\n  }\n\n  /**\n   * Create a new Knowledge Hub item under an existing or new topic.\n   *\n   * Pass `topicId` to append to an existing topic, or `topicName` to\n   * create a new topic and add the item under it.\n   *\n   * @see POST https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/items\n   */\n  async createItem(\n    propertyUuid: string,\n    content: string,\n    options?: CreateKnowledgeHubItemOptions,\n  ): Promise<KnowledgeHubItem> {\n    const response = await this.http.post<{ data: KnowledgeHubItem }>(\n      `/v2/properties/${encodeURIComponent(propertyUuid)}/knowledge-hub/items`,\n      { content, ...options },\n    )\n    return response.data\n  }\n\n  /**\n   * Update an existing Knowledge Hub item's content and/or topic assignment.\n   *\n   * @see PUT https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/items/{itemId}\n   */\n  async updateItem(\n    propertyUuid: string,\n    itemId: number,\n    content: string,\n    options?: UpdateKnowledgeHubItemOptions,\n  ): Promise<KnowledgeHubItem> {\n    const response = await this.http.put<{ data: KnowledgeHubItem }>(\n      `/v2/properties/${encodeURIComponent(propertyUuid)}/knowledge-hub/items/${encodeURIComponent(String(itemId))}`,\n      { content, ...options },\n    )\n    return response.data\n  }\n\n  /**\n   * Delete a Knowledge Hub item.\n   *\n   * @see DELETE https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/items/{itemId}\n   */\n  async deleteItem(propertyUuid: string, itemId: number): Promise<void> {\n    await this.http.delete<void>(\n      `/v2/properties/${encodeURIComponent(propertyUuid)}/knowledge-hub/items/${encodeURIComponent(String(itemId))}`,\n    )\n  }\n\n  /**\n   * Delete an entire Knowledge Hub topic and all its items.\n   *\n   * @see DELETE https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/topics/{topicId}\n   */\n  async deleteTopic(propertyUuid: string, topicId: number): Promise<void> {\n    await this.http.delete<void>(\n      `/v2/properties/${encodeURIComponent(propertyUuid)}/knowledge-hub/topics/${encodeURIComponent(String(topicId))}`,\n    )\n  }\n}\n","import { TokenManager } from './auth'\nimport type { TokenManagerConfig } from './auth'\nimport { HttpClient } from './http/client'\nimport type { RetryConfig } from './http/retry'\nimport type { CacheConfig } from './utils/cache'\nimport { CalendarResource } from './resources/calendar'\nimport { InquiriesResource } from './resources/inquiries'\nimport { MessagesResource } from './resources/messages'\nimport { PropertiesResource } from './resources/properties'\nimport { ReservationsResource } from './resources/reservations'\nimport { ReviewsResource } from './resources/reviews'\nimport { UserResource } from './resources/user'\nimport { TransactionsResource } from './resources/transactions'\nimport { PayoutsResource } from './resources/payouts'\nimport { KnowledgeHubResource } from './resources/knowledge-hub'\n\nexport interface ResourceCacheConfig {\n  properties?: CacheConfig\n  reservations?: CacheConfig\n  inquiries?: CacheConfig\n}\n\nexport interface HospitableClientConfig {\n  /** Personal Access Token. Also read from HOSPITABLE_API_PAT env var. */\n  token?: string\n  /** OAuth2 refresh token */\n  refreshToken?: string\n  /** OAuth2 client ID */\n  clientId?: string\n  /** OAuth2 client secret */\n  clientSecret?: string\n  /** API base URL. Defaults to https://public.api.hospitable.com */\n  baseURL?: string\n  /** Retry configuration */\n  retry?: RetryConfig\n  /** Enable debug logging */\n  debug?: boolean\n  /** Cache configuration per resource */\n  cache?: ResourceCacheConfig\n}\n\nexport class HospitableClient {\n  readonly properties: PropertiesResource\n  readonly reservations: ReservationsResource\n  readonly calendar: CalendarResource\n  readonly messages: MessagesResource\n  readonly reviews: ReviewsResource\n  readonly inquiries: InquiriesResource\n  readonly user: UserResource\n  readonly transactions: TransactionsResource\n  readonly payouts: PayoutsResource\n  readonly knowledgeHub: KnowledgeHubResource\n\n  constructor(config: HospitableClientConfig = {}) {\n    const baseURL = config.baseURL ?? 'https://public.api.hospitable.com'\n\n    const tokenConfig: TokenManagerConfig = {\n      ...(config.token !== undefined ? { token: config.token } : {}),\n      ...(config.refreshToken !== undefined ? { refreshToken: config.refreshToken } : {}),\n      ...(config.clientId !== undefined ? { clientId: config.clientId } : {}),\n      ...(config.clientSecret !== undefined ? { clientSecret: config.clientSecret } : {}),\n      baseURL,\n    }\n\n    const tokenManager = new TokenManager(tokenConfig)\n\n    const httpClient = new HttpClient({\n      baseURL,\n      getAuthHeader: () => tokenManager.getAuthHeader(),\n      onUnauthorized: async () => {\n        await tokenManager.handleUnauthorized()\n        this.properties.clearCache()\n        this.reservations.clearCache()\n        this.inquiries.clearCache()\n      },\n      ...(config.debug !== undefined ? { debug: config.debug } : {}),\n      ...(config.retry !== undefined ? { retryConfig: config.retry } : {}),\n    })\n\n    this.properties = new PropertiesResource(httpClient, config.cache?.properties)\n    this.reservations = new ReservationsResource(httpClient, config.cache?.reservations)\n    this.calendar = new CalendarResource(httpClient)\n    this.messages = new MessagesResource(httpClient)\n    this.reviews = new ReviewsResource(httpClient)\n    this.inquiries = new InquiriesResource(httpClient, config.cache?.inquiries)\n    this.user = new UserResource(httpClient)\n    this.transactions = new TransactionsResource(httpClient)\n    this.payouts = new PayoutsResource(httpClient)\n    this.knowledgeHub = new KnowledgeHubResource(httpClient)\n  }\n}\n","import type { HttpClient } from '../../http/client'\nimport type { AuthCode, CreateAuthCodeInput } from '../models/auth-code'\n\n/**\n * Resource for the Connect Auth Codes API.\n *\n * Auth codes are 5-minute magic links used to authenticate a Customer\n * into Hospitable Connect. The customer must already exist before\n * requesting a code.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class AuthCodesResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * Create an auth code for a customer. Returns the magic-link URL to\n   * send the customer to and its absolute expiry timestamp (5 minutes).\n   *\n   * @see POST https://connect.hospitable.com/api/v1/auth-codes\n   */\n  async create(input: CreateAuthCodeInput): Promise<AuthCode> {\n    const response = await this.http.post<{ data: AuthCode }>('/auth-codes', input)\n    return response.data\n  }\n}\n","import type { ConnectPaginatedResponse } from './models'\n\nexport interface ConnectPageFetcher<T, P extends { page?: number; perPage?: number }> {\n  (params: P): Promise<ConnectPaginatedResponse<T>>\n}\n\n/**\n * Page-driver for Connect list endpoints. Terminates when the API\n * returns a page with an empty `data` array or null `links.next` —\n * Connect's `meta.last_page` is only sometimes present, so we rely on\n * the resource-level link header + empty-page signal which every list\n * endpoint honors.\n */\nexport async function* paginateConnect<T, P extends { page?: number; perPage?: number }>(\n  fetcher: ConnectPageFetcher<T, P>,\n  params: Omit<P, 'page'>,\n): AsyncGenerator<T> {\n  let page = 1\n  while (true) {\n    const result = await fetcher({ ...params, page } as P)\n    for (const item of result.data) {\n      yield item\n    }\n    if (result.links.next === null || result.data.length === 0) return\n    const lastPage = result.meta.lastPage\n    if (typeof lastPage === 'number' && page >= lastPage) return\n    page++\n  }\n}\n","import type { HttpClient, RequestOptions } from '../../http/client'\nimport { paginateConnect } from '../paginate'\nimport type {\n  ConnectPaginatedResponse,\n  CreateCustomerInput,\n  Customer,\n} from '../models'\n\nexport interface CustomerListParams {\n  page?: number\n  perPage?: number\n  /** Comma-separated subset of Customer fields to return (e.g. `'id,email'`). */\n  _select?: string\n}\n\n/**\n * Resource for the Connect Customers API. A Customer is one end-user of\n * the partner application; they own Channels (OTA connections).\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class CustomersResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(params: CustomerListParams = {}): Promise<ConnectPaginatedResponse<Customer>> {\n    return this.http.get<ConnectPaginatedResponse<Customer>>(\n      '/customers',\n      params as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * List customers, paginated.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers\n   */\n  async list(params: CustomerListParams = {}): Promise<ConnectPaginatedResponse<Customer>> {\n    return this.fetchList(params)\n  }\n\n  /**\n   * Stream every customer. Memory-efficient — one page at a time.\n   */\n  async *iter(params: Omit<CustomerListParams, 'page'> = {}): AsyncGenerator<Customer> {\n    yield* paginateConnect<Customer, CustomerListParams>(p => this.fetchList(p), params)\n  }\n\n  /**\n   * Create a customer. The `id` field is partner-assigned — use any\n   * stable string (your app's user ID is the typical choice).\n   *\n   * @see POST https://connect.hospitable.com/api/v1/customers\n   */\n  async create(input: CreateCustomerInput): Promise<Customer> {\n    const response = await this.http.post<{ data: Customer }>('/customers', input)\n    return response.data\n  }\n\n  /**\n   * Fetch a single customer by id.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers/{customer}\n   * @throws {NotFoundError} on 404\n   */\n  async get(customerId: string): Promise<Customer> {\n    const response = await this.http.get<{ data: Customer }>(\n      `/customers/${encodeURIComponent(customerId)}`,\n    )\n    return response.data\n  }\n\n  /**\n   * Delete a customer and all associated channels / data.\n   *\n   * @see DELETE https://connect.hospitable.com/api/v1/customers/{customer}\n   */\n  async delete(customerId: string): Promise<void> {\n    await this.http.delete<void>(`/customers/${encodeURIComponent(customerId)}`)\n  }\n}\n","import type { HttpClient } from '../../http/client'\nimport type { Channel, Listing } from '../models'\n\n/**\n * Resource for the Connect Channels API. A Channel is an OTA connection\n * (currently Airbnb only) owned by a Customer. Channels aggregate\n * Listings and Reviews from the connected platform.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class ChannelsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  /**\n   * List all channels a customer has connected.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/channels\n   */\n  async list(customerId: string): Promise<Channel[]> {\n    const response = await this.http.get<{ data: Channel[] }>(\n      `/customers/${encodeURIComponent(customerId)}/channels`,\n    )\n    return response.data\n  }\n\n  /**\n   * Fetch a single channel by id, scoped to a customer.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/channels/{channel}\n   */\n  async get(customerId: string, channelId: string): Promise<Channel> {\n    const response = await this.http.get<{ data: Channel }>(\n      `/customers/${encodeURIComponent(customerId)}/channels/${encodeURIComponent(channelId)}`,\n    )\n    return response.data\n  }\n\n  /**\n   * Disconnect a channel from a customer.\n   *\n   * Note: this does **not** revoke the customer's authorization on the\n   * OTA itself (e.g. the Airbnb account stays linked in the guest's\n   * Airbnb app). It only severs Hospitable's sync with that channel.\n   *\n   * @see DELETE https://connect.hospitable.com/api/v1/customers/{customer}/channels/{channel}\n   */\n  async delete(customerId: string, channelId: string): Promise<void> {\n    await this.http.delete<void>(\n      `/customers/${encodeURIComponent(customerId)}/channels/${encodeURIComponent(channelId)}`,\n    )\n  }\n\n  /**\n   * List all listings published on a given channel. Excludes\n   * unpublished or draft listings on the OTA side.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/listings\n   */\n  async listListings(channelId: string): Promise<Listing[]> {\n    const response = await this.http.get<{ data: Listing[] }>(\n      `/channels/${encodeURIComponent(channelId)}/listings`,\n    )\n    return response.data\n  }\n\n  /**\n   * Fetch a single listing scoped to a channel.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/listings/{listing}\n   */\n  async getListing(channelId: string, listingId: string): Promise<Listing> {\n    const response = await this.http.get<{ data: Listing }>(\n      `/channels/${encodeURIComponent(channelId)}/listings/${encodeURIComponent(listingId)}`,\n    )\n    return response.data\n  }\n}\n","import type { HttpClient, RequestOptions } from '../../http/client'\nimport { paginateConnect } from '../paginate'\nimport { ConfigurationError } from '../../errors'\nimport type {\n  CalendarDay,\n  ConnectPaginatedResponse,\n  Listing,\n  ListingImage,\n  UpdateCalendarDay,\n} from '../models'\n\nexport interface ListingListParams {\n  page?: number\n  perPage?: number\n  _select?: string\n}\n\nexport interface CalendarRangeParams {\n  /** ISO `YYYY-MM-DD`, inclusive. */\n  startDate: string\n  /** ISO `YYYY-MM-DD`, inclusive. Up to 365 days per request. */\n  endDate: string\n}\n\n/**\n * Resource for the Connect Listings, Pricing & Availability API.\n *\n * Customer-scoped listings: what the Customer owns across every channel.\n * Use {@link ChannelsResource.listListings} when you need channel-scoped\n * listings instead.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class ListingsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(\n    customerId: string,\n    params: ListingListParams,\n  ): Promise<ConnectPaginatedResponse<Listing>> {\n    return this.http.get<ConnectPaginatedResponse<Listing>>(\n      `/customers/${encodeURIComponent(customerId)}/listings`,\n      params as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * List all listings a customer owns, across every channel.\n   * Unpublished listings are excluded.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/listings\n   */\n  async list(\n    customerId: string,\n    params: ListingListParams = {},\n  ): Promise<ConnectPaginatedResponse<Listing>> {\n    return this.fetchList(customerId, params)\n  }\n\n  /**\n   * Stream every listing for a customer. Memory-efficient — paginates\n   * one page at a time.\n   */\n  async *iter(\n    customerId: string,\n    params: Omit<ListingListParams, 'page'> = {},\n  ): AsyncGenerator<Listing> {\n    yield* paginateConnect<Listing, ListingListParams>(\n      p => this.fetchList(customerId, p),\n      params,\n    )\n  }\n\n  /**\n   * Fetch a single listing scoped to a customer.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/listings/{listing}\n   */\n  async get(customerId: string, listingId: string): Promise<Listing> {\n    const response = await this.http.get<{ data: Listing }>(\n      `/customers/${encodeURIComponent(customerId)}/listings/${encodeURIComponent(listingId)}`,\n    )\n    return response.data\n  }\n\n  /**\n   * Fetch photo gallery for a listing, ordered by `order`.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/listings/{listing}/images\n   */\n  async getImages(customerId: string, listingId: string): Promise<ListingImage[]> {\n    const response = await this.http.get<{ data: ListingImage[] }>(\n      `/customers/${encodeURIComponent(customerId)}/listings/${encodeURIComponent(listingId)}/images`,\n    )\n    return response.data\n  }\n\n  /**\n   * Fetch day-level pricing + availability for a listing.\n   *\n   * API limits: up to 540 days in the future, max 365 days per\n   * request (split into batches for wider windows).\n   *\n   * @see GET https://connect.hospitable.com/api/v1/listings/{listing}/calendar\n   * @throws {ConfigurationError} when `startDate` or `endDate` is missing\n   */\n  async getCalendar(listingId: string, params: CalendarRangeParams): Promise<CalendarDay[]> {\n    if (!params.startDate || !params.endDate) {\n      throw new ConfigurationError(\n        'listings.getCalendar: `startDate` and `endDate` (YYYY-MM-DD) are required. ' +\n          'API rejects calendar queries without an explicit window.',\n      )\n    }\n    const response = await this.http.get<{ data: CalendarDay[] }>(\n      `/listings/${encodeURIComponent(listingId)}/calendar`,\n      params as unknown as RequestOptions['params'],\n    )\n    return response.data\n  }\n\n  /**\n   * Batch-update day-level pricing and/or availability.\n   *\n   * @see PUT https://connect.hospitable.com/api/v1/listings/{listing}/calendar\n   * @throws {ConfigurationError} when `days` is empty\n   */\n  async updateCalendar(listingId: string, days: UpdateCalendarDay[]): Promise<void> {\n    if (days.length === 0) {\n      throw new ConfigurationError(\n        'listings.updateCalendar: pass at least one day. ' +\n          'The API rejects empty calendar update batches.',\n      )\n    }\n    await this.http.put<void>(\n      `/listings/${encodeURIComponent(listingId)}/calendar`,\n      { days },\n    )\n  }\n}\n","import type { HttpClient, RequestOptions } from '../../http/client'\nimport { paginateConnect } from '../paginate'\nimport type { ConnectPaginatedResponse, Reservation } from '../models'\n\nexport interface ReservationListParams {\n  page?: number\n  perPage?: number\n  _select?: string\n  /**\n   * Free-form filter bag — Connect uses `field[operator]=value` syntax\n   * (see Filters reference). Keys map 1:1 to query params, so to filter\n   * by `arrival_date[after]=2026-01-01` pass\n   * `{ 'arrival_date[after]': '2026-01-01' }`. Use `ConnectFilter` for\n   * a typed builder.\n   *\n   * Value type intentionally excludes `string[]`: Connect's filter\n   * serialization is comma-joined strings (see `ConnectFilter.where`),\n   * so arrays should be pre-joined before hitting this bag. Allowing\n   * `string[]` here also accidentally satisfied the numeric `page` /\n   * `perPage` slots at compile time, producing silent `NaN` paginator\n   * loops — see issue #49.\n   */\n  [key: string]: string | number | boolean | undefined\n}\n\n/**\n * Resource for the Connect Reservations API.\n *\n * Reservations can be queried per-listing (`listings.../reservations`)\n * or per-customer (`customers.../reservations`). The per-customer\n * variant is useful for dashboards aggregating a host's entire book;\n * per-listing is useful for per-property views.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class ReservationsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchByListing(\n    listingId: string,\n    params: ReservationListParams,\n  ): Promise<ConnectPaginatedResponse<Reservation>> {\n    return this.http.get<ConnectPaginatedResponse<Reservation>>(\n      `/listings/${encodeURIComponent(listingId)}/reservations`,\n      params as RequestOptions['params'],\n    )\n  }\n\n  private fetchByCustomer(\n    customerId: string,\n    params: ReservationListParams,\n  ): Promise<ConnectPaginatedResponse<Reservation>> {\n    return this.http.get<ConnectPaginatedResponse<Reservation>>(\n      `/customers/${encodeURIComponent(customerId)}/reservations`,\n      params as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * List reservations on a single listing.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/listings/{listing}/reservations\n   */\n  async listByListing(\n    listingId: string,\n    params: ReservationListParams = {},\n  ): Promise<ConnectPaginatedResponse<Reservation>> {\n    return this.fetchByListing(listingId, params)\n  }\n\n  /** Stream every reservation on a listing, auto-paginating. */\n  async *iterByListing(\n    listingId: string,\n    params: Omit<ReservationListParams, 'page'> = {},\n  ): AsyncGenerator<Reservation> {\n    yield* paginateConnect<Reservation, ReservationListParams>(\n      p => this.fetchByListing(listingId, p),\n      params,\n    )\n  }\n\n  /**\n   * Fetch a single reservation scoped to a listing.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/listings/{listing}/reservations/{reservation}\n   */\n  async getByListing(listingId: string, reservationId: string): Promise<Reservation> {\n    const response = await this.http.get<{ data: Reservation }>(\n      `/listings/${encodeURIComponent(listingId)}/reservations/${encodeURIComponent(reservationId)}`,\n    )\n    return response.data\n  }\n\n  /**\n   * List every reservation a customer has across all their listings.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/reservations\n   */\n  async listByCustomer(\n    customerId: string,\n    params: ReservationListParams = {},\n  ): Promise<ConnectPaginatedResponse<Reservation>> {\n    return this.fetchByCustomer(customerId, params)\n  }\n\n  /** Stream every reservation for a customer, auto-paginating. */\n  async *iterByCustomer(\n    customerId: string,\n    params: Omit<ReservationListParams, 'page'> = {},\n  ): AsyncGenerator<Reservation> {\n    yield* paginateConnect<Reservation, ReservationListParams>(\n      p => this.fetchByCustomer(customerId, p),\n      params,\n    )\n  }\n\n  /**\n   * Fetch a single reservation scoped to a customer.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/reservations/{reservation}\n   */\n  async getByCustomer(customerId: string, reservationId: string): Promise<Reservation> {\n    const response = await this.http.get<{ data: Reservation }>(\n      `/customers/${encodeURIComponent(customerId)}/reservations/${encodeURIComponent(reservationId)}`,\n    )\n    return response.data\n  }\n}\n","import type { HttpClient, RequestOptions } from '../../http/client'\nimport { paginateConnect } from '../paginate'\nimport { ConfigurationError } from '../../errors'\nimport type {\n  ConnectPaginatedResponse,\n  MessageTemplate,\n  SendMessageInput,\n} from '../models'\n\nexport interface MessageTemplateListParams {\n  page?: number\n  perPage?: number\n  _select?: string\n}\n\n/**\n * Resource for the Connect Messaging API. Messages are sent via\n * **pre-configured templates** — freeform text is not supported.\n * Configure templates in the Partner Portal, then reference them by\n * `templateId` when sending.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class MessagingResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchTemplates(\n    params: MessageTemplateListParams,\n  ): Promise<ConnectPaginatedResponse<MessageTemplate>> {\n    return this.http.get<ConnectPaginatedResponse<MessageTemplate>>(\n      '/message-templates',\n      params as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * List all message templates available to this vendor.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/message-templates\n   */\n  async listTemplates(\n    params: MessageTemplateListParams = {},\n  ): Promise<ConnectPaginatedResponse<MessageTemplate>> {\n    return this.fetchTemplates(params)\n  }\n\n  /** Stream every template, auto-paginating. */\n  async *iterTemplates(\n    params: Omit<MessageTemplateListParams, 'page'> = {},\n  ): AsyncGenerator<MessageTemplate> {\n    yield* paginateConnect<MessageTemplate, MessageTemplateListParams>(\n      p => this.fetchTemplates(p),\n      params,\n    )\n  }\n\n  /**\n   * Fetch a single template by id.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/message-templates/{template}\n   */\n  async getTemplate(templateId: string): Promise<MessageTemplate> {\n    const response = await this.http.get<{ data: MessageTemplate }>(\n      `/message-templates/${encodeURIComponent(templateId)}`,\n    )\n    return response.data\n  }\n\n  /**\n   * Send a templated message to the guest on a reservation. Placeholder\n   * values are substituted into the template body; the rendered message\n   * appears in the guest's OTA inbox.\n   *\n   * @see POST https://connect.hospitable.com/api/v1/reservations/{reservation}/messages\n   * @throws {ConfigurationError} when `templateId` is missing\n   */\n  async send(reservationId: string, input: SendMessageInput): Promise<void> {\n    if (!input.templateId) {\n      throw new ConfigurationError(\n        'messaging.send: `templateId` is required. ' +\n          'Freeform messages are not supported — configure a template in the Partner Portal.',\n      )\n    }\n    await this.http.post<void>(\n      `/reservations/${encodeURIComponent(reservationId)}/messages`,\n      input,\n    )\n  }\n}\n","import type { HttpClient, RequestOptions } from '../../http/client'\nimport { paginateConnect } from '../paginate'\nimport type { ConnectPaginatedResponse, Review } from '../models'\n\nexport interface ReviewListParams {\n  page?: number\n  perPage?: number\n  _select?: string\n  /** Free-form `field[operator]=value` filter bag. See issue #49 for the `string[]` exclusion rationale. */\n  [key: string]: string | number | boolean | undefined\n}\n\n/**\n * Resource for the Connect Reviews API. Reviews are scoped to a\n * channel — pass the channel id of the OTA account the review came\n * through.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class ReviewsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(\n    channelId: string,\n    params: ReviewListParams,\n  ): Promise<ConnectPaginatedResponse<Review>> {\n    return this.http.get<ConnectPaginatedResponse<Review>>(\n      `/channels/${encodeURIComponent(channelId)}/reviews`,\n      params as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * List reviews on a channel, paginated.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/reviews\n   */\n  async list(\n    channelId: string,\n    params: ReviewListParams = {},\n  ): Promise<ConnectPaginatedResponse<Review>> {\n    return this.fetchList(channelId, params)\n  }\n\n  /** Stream every review on a channel. */\n  async *iter(\n    channelId: string,\n    params: Omit<ReviewListParams, 'page'> = {},\n  ): AsyncGenerator<Review> {\n    yield* paginateConnect<Review, ReviewListParams>(p => this.fetchList(channelId, p), params)\n  }\n}\n","import type { HttpClient, RequestOptions } from '../../http/client'\nimport { paginateConnect } from '../paginate'\nimport type { ConnectPaginatedResponse, Transaction } from '../models'\n\nexport interface TransactionListParams {\n  page?: number\n  perPage?: number\n  _select?: string\n  /** Free-form `field[operator]=value` filter bag. See issue #49 for the `string[]` exclusion rationale. */\n  [key: string]: string | number | boolean | undefined\n}\n\n/**\n * Resource for the Connect Transactions API (beta).\n *\n * **Beta**: this surface is not GA. For customers whose Airbnb channel\n * was authorized before 2024-01-12, re-run the auth-code flow to pick\n * up transactions + payouts permissions.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class TransactionsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(\n    channelId: string,\n    params: TransactionListParams,\n  ): Promise<ConnectPaginatedResponse<Transaction>> {\n    return this.http.get<ConnectPaginatedResponse<Transaction>>(\n      `/channels/${encodeURIComponent(channelId)}/transactions`,\n      params as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * List transactions on a channel, paginated.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/transactions\n   */\n  async list(\n    channelId: string,\n    params: TransactionListParams = {},\n  ): Promise<ConnectPaginatedResponse<Transaction>> {\n    return this.fetchList(channelId, params)\n  }\n\n  /** Stream every transaction on a channel. */\n  async *iter(\n    channelId: string,\n    params: Omit<TransactionListParams, 'page'> = {},\n  ): AsyncGenerator<Transaction> {\n    yield* paginateConnect<Transaction, TransactionListParams>(\n      p => this.fetchList(channelId, p),\n      params,\n    )\n  }\n\n  /**\n   * Fetch a single transaction scoped to a channel.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/transactions/{transaction}\n   */\n  async get(channelId: string, transactionId: string): Promise<Transaction> {\n    const response = await this.http.get<{ data: Transaction }>(\n      `/channels/${encodeURIComponent(channelId)}/transactions/${encodeURIComponent(transactionId)}`,\n    )\n    return response.data\n  }\n}\n","import type { HttpClient, RequestOptions } from '../../http/client'\nimport { paginateConnect } from '../paginate'\nimport type { ConnectPaginatedResponse, Payout } from '../models'\n\nexport interface PayoutListParams {\n  page?: number\n  perPage?: number\n  _select?: string\n  /** Free-form `field[operator]=value` filter bag. See issue #49 for the `string[]` exclusion rationale. */\n  [key: string]: string | number | boolean | undefined\n}\n\n/**\n * Resource for the Connect Payouts API (beta).\n *\n * Channel-scoped. For customers whose Airbnb channel was authorized\n * before 2024-01-12, re-run the auth-code flow to pick up payout\n * permissions.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class PayoutsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(\n    channelId: string,\n    params: PayoutListParams,\n  ): Promise<ConnectPaginatedResponse<Payout>> {\n    return this.http.get<ConnectPaginatedResponse<Payout>>(\n      `/channels/${encodeURIComponent(channelId)}/payouts`,\n      params as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * List payouts on a channel, paginated.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/payouts\n   */\n  async list(\n    channelId: string,\n    params: PayoutListParams = {},\n  ): Promise<ConnectPaginatedResponse<Payout>> {\n    return this.fetchList(channelId, params)\n  }\n\n  /** Stream every payout on a channel. */\n  async *iter(\n    channelId: string,\n    params: Omit<PayoutListParams, 'page'> = {},\n  ): AsyncGenerator<Payout> {\n    yield* paginateConnect<Payout, PayoutListParams>(\n      p => this.fetchList(channelId, p),\n      params,\n    )\n  }\n\n  /**\n   * Fetch a single payout scoped to a channel.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/payouts/{payout}\n   */\n  async get(channelId: string, payoutId: string): Promise<Payout> {\n    const response = await this.http.get<{ data: Payout }>(\n      `/channels/${encodeURIComponent(channelId)}/payouts/${encodeURIComponent(payoutId)}`,\n    )\n    return response.data\n  }\n}\n","import type { HttpClient, RequestOptions } from '../../http/client'\nimport { paginateConnect } from '../paginate'\nimport type { ConnectPaginatedResponse, Resolution } from '../models'\n\nexport interface ResolutionListParams {\n  page?: number\n  perPage?: number\n  _select?: string\n  /** Free-form `field[operator]=value` filter bag. See issue #49 for the `string[]` exclusion rationale. */\n  [key: string]: string | number | boolean | undefined\n}\n\n/**\n * Resource for the Connect Resolutions API (beta).\n *\n * Resolutions are OTA-mediated disputes — security-deposit claims,\n * damage claims, refund requests. Channel-scoped. This surface is\n * **in active development**; response shapes may evolve.\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class ResolutionsResource {\n  constructor(private readonly http: HttpClient) {}\n\n  private fetchList(\n    channelId: string,\n    params: ResolutionListParams,\n  ): Promise<ConnectPaginatedResponse<Resolution>> {\n    return this.http.get<ConnectPaginatedResponse<Resolution>>(\n      `/channels/${encodeURIComponent(channelId)}/resolutions`,\n      params as RequestOptions['params'],\n    )\n  }\n\n  /**\n   * List resolutions on a channel, paginated.\n   *\n   * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/resolutions\n   */\n  async list(\n    channelId: string,\n    params: ResolutionListParams = {},\n  ): Promise<ConnectPaginatedResponse<Resolution>> {\n    return this.fetchList(channelId, params)\n  }\n\n  /** Stream every resolution on a channel. */\n  async *iter(\n    channelId: string,\n    params: Omit<ResolutionListParams, 'page'> = {},\n  ): AsyncGenerator<Resolution> {\n    yield* paginateConnect<Resolution, ResolutionListParams>(\n      p => this.fetchList(channelId, p),\n      params,\n    )\n  }\n}\n","import { HttpClient } from '../http/client'\nimport type { RetryConfig } from '../http/retry'\nimport { ConfigurationError } from '../errors'\nimport { AuthCodesResource } from './resources/auth-codes'\nimport { CustomersResource } from './resources/customers'\nimport { ChannelsResource } from './resources/channels'\nimport { ListingsResource } from './resources/listings'\nimport { ReservationsResource } from './resources/reservations'\nimport { MessagingResource } from './resources/messaging'\nimport { ReviewsResource } from './resources/reviews'\nimport { TransactionsResource } from './resources/transactions'\nimport { PayoutsResource } from './resources/payouts'\nimport { ResolutionsResource } from './resources/resolutions'\n\ndeclare const process: { env: Record<string, string | undefined> }\n\nexport interface HospitableConnectClientConfig {\n  /**\n   * Partner-portal bearer token. Also read from `HOSPITABLE_CONNECT_TOKEN`\n   * env var. Generate in partners.hospitable.com → Connect → Settings →\n   * Access tokens (shown only once — store securely).\n   */\n  token?: string\n  /** API base URL. Defaults to `https://connect.hospitable.com/api/v1`. */\n  baseURL?: string\n  /** Retry configuration. Connect rate-limits at 60 req/min per vendor. */\n  retry?: RetryConfig\n  /** Enable debug logging. */\n  debug?: boolean\n  /**\n   * Optional callback invoked when a 401 is returned by the API. Should\n   * resolve to a freshly-minted bearer token, which the SDK will swap in\n   * and use to transparently retry the failing request.\n   *\n   * Without this callback, 401s throw {@link AuthenticationError} and the\n   * caller must reconstruct the client — fine for short-lived scripts but\n   * a dead-end for long-running agent processes that rotate tokens\n   * mid-session. Supply it to cover that case.\n   *\n   * @example\n   * ```ts\n   * new HospitableConnectClient({\n   *   token: initialToken,\n   *   onTokenExpired: () => fetchFreshConnectToken(),\n   * })\n   * ```\n   */\n  onTokenExpired?: () => string | Promise<string>\n}\n\n/**\n * Client for the Hospitable Connect API — partner-facing, multi-customer\n * integration surface. Distinct from {@link HospitableClient} (Public API,\n * host-facing).\n *\n * Auth is a static bearer token minted in the Hospitable Partner Portal;\n * there is no OAuth refresh loop. By default, 401s surface as\n * {@link AuthenticationError} and are terminal — regenerate the token in\n * the portal and reconstruct the client. Supply {@link HospitableConnectClientConfig.onTokenExpired}\n * to plug in a custom refresh path (e.g. for long-running agents that\n * rotate tokens via an external system).\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class HospitableConnectClient {\n  readonly authCodes: AuthCodesResource\n  readonly customers: CustomersResource\n  readonly channels: ChannelsResource\n  readonly listings: ListingsResource\n  readonly reservations: ReservationsResource\n  readonly messaging: MessagingResource\n  readonly reviews: ReviewsResource\n  readonly transactions: TransactionsResource\n  readonly payouts: PayoutsResource\n  readonly resolutions: ResolutionsResource\n\n  constructor(config: HospitableConnectClientConfig = {}) {\n    const baseURL = config.baseURL ?? 'https://connect.hospitable.com/api/v1'\n\n    const token = config.token ?? process.env['HOSPITABLE_CONNECT_TOKEN']\n    if (!token || token.length === 0) {\n      throw new ConfigurationError(\n        'HospitableConnectClient: `token` is required. Pass it to the ' +\n          'constructor or set HOSPITABLE_CONNECT_TOKEN. Mint the token in ' +\n          'the Hospitable Partner Portal under Connect → Settings → Access tokens.',\n      )\n    }\n\n    // Hold the current token in a mutable ref so `onTokenExpired` can rotate\n    // it in place without reconstructing the client. `getAuthHeader` reads\n    // through the ref on every request.\n    let currentToken = token\n\n    const http = new HttpClient({\n      baseURL,\n      getAuthHeader: async () => `Bearer ${currentToken}`,\n      ...(config.onTokenExpired !== undefined\n        ? {\n            onUnauthorized: async () => {\n              currentToken = await config.onTokenExpired!()\n            },\n          }\n        : {}),\n      ...(config.debug !== undefined ? { debug: config.debug } : {}),\n      ...(config.retry !== undefined ? { retryConfig: config.retry } : {}),\n    })\n\n    this.authCodes = new AuthCodesResource(http)\n    this.customers = new CustomersResource(http)\n    this.channels = new ChannelsResource(http)\n    this.listings = new ListingsResource(http)\n    this.reservations = new ReservationsResource(http)\n    this.messaging = new MessagingResource(http)\n    this.reviews = new ReviewsResource(http)\n    this.transactions = new TransactionsResource(http)\n    this.payouts = new PayoutsResource(http)\n    this.resolutions = new ResolutionsResource(http)\n  }\n}\n","export { HospitableConnectClient } from './client'\nexport type { HospitableConnectClientConfig } from './client'\n\nexport * from './models'\nexport * from './resources'\nexport * from './webhooks'\n\nexport { ConnectFilter } from './filter'\nexport type { ConnectFilterOperator } from './filter'\n\nexport { paginateConnect } from './paginate'\nexport type { ConnectPageFetcher } from './paginate'\n\n// `collectAll` works on any AsyncIterable (including the generator returned\n// by `paginateConnect`), so it's re-exported here for namespace symmetry —\n// `import { Connect } from 'hospitable'` → `Connect.collectAll(...)` just works.\nexport { collectAll } from '../http/paginate'\n","import type { Channel } from '../models/channel'\nimport type { Listing } from '../models/listing'\nimport type { Payout } from '../models/payout'\nimport type { Reservation } from '../models/reservation'\nimport type { Review } from '../models/review'\nimport type { Transaction } from '../models/transaction'\nimport type { Customer } from '../models/customer'\n\n/**\n * Every Connect webhook payload shares this envelope. `id` is a ULID,\n * `created` is ISO-8601, `action` identifies the event, `version` is\n * the schema version the platform used to serialize the event, and\n * `data` carries the domain object + embedded related resources.\n *\n * Return 200 to acknowledge receipt — the platform retries on any\n * non-2xx response.\n *\n * ⚠️  **Security.** The type guards ({@link isConnectWebhookAction},\n * {@link isConnectWebhookFamily}) only narrow the shape — they do NOT\n * authenticate the sender. Anyone who discovers your webhook URL can POST\n * a forged body that passes both guards. Before trusting any incoming\n * payload, verify its HMAC signature with {@link verifyWebhookSignature}\n * using the shared secret from your Hospitable integration.\n */\nexport interface ConnectWebhookEnvelope<Action extends string, Data> {\n  id: string\n  created: string\n  action: Action\n  version: string\n  data: Data\n}\n\n/* ---------- Channel events ---------- */\n\nexport type ChannelWebhookAction = 'channel.activated'\n\nexport interface ChannelWebhookData extends Channel {\n  /**\n   * Customer who owns this channel connection. Always embedded on\n   * channel events so partners can route the payload to the right\n   * tenant without a follow-up GET.\n   */\n  customer: Customer\n}\n\nexport type ChannelWebhookPayload = ConnectWebhookEnvelope<\n  ChannelWebhookAction,\n  ChannelWebhookData\n>\n\n/* ---------- Listing events ---------- */\n\nexport type ListingWebhookAction =\n  | 'listing.created'\n  | 'listing.changed'\n  | 'listing.deactivated'\n  | 'listing.reactivated'\n\nexport interface ListingWebhookData extends Listing {\n  customer: Customer\n}\n\nexport type ListingWebhookPayload = ConnectWebhookEnvelope<\n  ListingWebhookAction,\n  ListingWebhookData\n>\n\n/* ---------- Reservation events ---------- */\n\nexport type ReservationWebhookAction = 'reservation.created' | 'reservation.changed'\n\nexport interface ReservationWebhookData extends Reservation {\n  /** Listing this reservation is against. */\n  listing: Listing\n  /** Channel the booking came through. */\n  channel: Channel\n  /** Customer who owns the channel. */\n  customer: Customer\n}\n\nexport type ReservationWebhookPayload = ConnectWebhookEnvelope<\n  ReservationWebhookAction,\n  ReservationWebhookData\n>\n\n/* ---------- Review events ---------- */\n\nexport type ReviewWebhookAction =\n  | 'review.created'\n  | 'review.submitted'\n  | 'review.published'\n  | 'review.changed'\n  | 'review.expired'\n  | 'review.response_submitted'\n\nexport type ReviewWebhookPayload = ConnectWebhookEnvelope<ReviewWebhookAction, Review>\n\n/* ---------- Payout events ---------- */\n\nexport type PayoutWebhookAction = 'payout.created' | 'payout.changed'\n\nexport type PayoutWebhookPayload = ConnectWebhookEnvelope<PayoutWebhookAction, Payout>\n\n/* ---------- Transaction events ---------- */\n\nexport type TransactionWebhookAction = 'transaction.created' | 'transaction.changed'\n\nexport interface TransactionWebhookData extends Transaction {\n  payout?: Payout\n  channel?: Channel\n  listing?: Listing\n  reservation?: Reservation\n}\n\nexport type TransactionWebhookPayload = ConnectWebhookEnvelope<\n  TransactionWebhookAction,\n  TransactionWebhookData\n>\n\n/* ---------- Discriminated union over every event ---------- */\n\nexport type ConnectWebhookPayload =\n  | ChannelWebhookPayload\n  | ListingWebhookPayload\n  | ReservationWebhookPayload\n  | ReviewWebhookPayload\n  | PayoutWebhookPayload\n  | TransactionWebhookPayload\n\nexport type ConnectWebhookAction = ConnectWebhookPayload['action']\n\n/**\n * Type guard factory — narrows a generic payload to the requested event\n * family. Use at webhook-endpoint entry points to route by event type\n * without manual `as` casts.\n *\n * @example\n * ```ts\n * if (isConnectWebhookAction(payload, 'reservation.created')) {\n *   // payload.data is typed as ReservationWebhookData here\n * }\n * ```\n */\nexport function isConnectWebhookAction<A extends ConnectWebhookAction>(\n  payload: ConnectWebhookPayload,\n  action: A,\n): payload is Extract<ConnectWebhookPayload, { action: A }> {\n  return payload.action === action\n}\n\n/**\n * Broader family guard — narrows to all events sharing a prefix.\n *\n * @example\n * ```ts\n * if (isConnectWebhookFamily(payload, 'reservation')) {\n *   // payload is ReservationWebhookPayload\n * }\n * ```\n */\nexport function isConnectWebhookFamily<\n  F extends 'channel' | 'listing' | 'reservation' | 'review' | 'payout' | 'transaction',\n>(\n  payload: ConnectWebhookPayload,\n  family: F,\n): payload is Extract<ConnectWebhookPayload, { action: `${F}.${string}` }> {\n  return payload.action.startsWith(`${family}.`)\n}\n","/**\n * Digest algorithm used to compute the HMAC. `sha256` is the default and\n * what Hospitable uses; `sha1` is supported only for legacy compatibility.\n */\nexport type WebhookSignatureAlgorithm = 'sha256' | 'sha1'\n\n/**\n * Encoding of the signature as sent in the HTTP header. Hex is the\n * Hospitable default; base64 is supported for callers who bridge from\n * other webhook providers.\n */\nexport type WebhookSignatureEncoding = 'hex' | 'base64'\n\nexport interface VerifyWebhookSignatureOptions {\n  /**\n   * The raw request body, exactly as received. Do NOT pass the parsed\n   * JSON — the byte-for-byte original is required for the HMAC to match.\n   * Most frameworks expose this as `req.rawBody`, `request.body` (when\n   * configured for raw), or the result of a `body-parser`-style raw reader.\n   *\n   * Node's `Buffer` is accepted transparently since it extends\n   * `Uint8Array`; the SDK itself doesn't depend on `@types/node`.\n   */\n  rawBody: string | Uint8Array\n  /**\n   * The signature header value received from Hospitable. If the header\n   * contains an `algo=` prefix (e.g. `sha256=abc123…`), it is stripped\n   * automatically before comparison.\n   */\n  signatureHeader: string\n  /**\n   * The shared secret configured when the webhook was registered in the\n   * Hospitable Partner Portal. Store this in an env var or secret manager\n   * — never hardcode it.\n   */\n  secret: string\n  /** Defaults to `'sha256'`. */\n  algorithm?: WebhookSignatureAlgorithm\n  /** Defaults to `'hex'`. */\n  encoding?: WebhookSignatureEncoding\n  /**\n   * Optional timestamp header value. When supplied, the signed payload is\n   * `` `${timestamp}.${rawBody}` `` — a common anti-replay scheme. Pair\n   * this with {@link toleranceSeconds} to reject stale deliveries.\n   */\n  timestamp?: string\n  /**\n   * Maximum age in seconds allowed for a timestamped payload. Signatures\n   * older than this (relative to `Date.now()`) are rejected. Only consulted\n   * when {@link timestamp} is provided. Defaults to 300 (5 minutes).\n   */\n  toleranceSeconds?: number\n}\n\n/**\n * Verify the HMAC signature on an incoming Hospitable Connect webhook.\n *\n * Hospitable signs every webhook delivery with a shared secret; verifying\n * the signature is the caller's responsibility and is mandatory for any\n * production integration — without it, an attacker who knows your webhook\n * URL can forge events and trigger arbitrary downstream behavior in your\n * tenant.\n *\n * Resolves to `true` when the signature is valid and (if supplied) the\n * timestamp is within tolerance. Resolves to `false` for any mismatch,\n * malformed input, or stale payload. Never throws for signature mismatch\n * — throwing on verification failure invites a DoS where crafted bodies\n * crash the receiver.\n *\n * Uses a constant-time comparison to prevent side-channel leaks of the\n * expected signature byte-by-byte.\n *\n * Implemented via Web Crypto (`globalThis.crypto.subtle`) so the SDK\n * stays free of `@types/node`. Works on Node 20+ (native) and in any\n * runtime that ships Web Crypto.\n *\n * @example\n * ```ts\n * // Express route handler — be sure to capture the raw body.\n * app.post('/webhooks/hospitable', express.raw({ type: 'application/json' }), async (req, res) => {\n *   const ok = await verifyWebhookSignature({\n *     rawBody: req.body,\n *     signatureHeader: req.header('X-Hospitable-Signature') ?? '',\n *     secret: process.env.HOSPITABLE_WEBHOOK_SECRET!,\n *   })\n *   if (!ok) return res.status(401).end()\n *   const payload = JSON.parse(new TextDecoder().decode(req.body))\n *   // ... handle payload ...\n *   res.status(200).end()\n * })\n * ```\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport async function verifyWebhookSignature(\n  opts: VerifyWebhookSignatureOptions,\n): Promise<boolean> {\n  const {\n    rawBody,\n    signatureHeader,\n    secret,\n    algorithm = 'sha256',\n    encoding = 'hex',\n    timestamp,\n    toleranceSeconds = 300,\n  } = opts\n\n  if (!signatureHeader || !secret) return false\n\n  if (timestamp !== undefined) {\n    const ts = Number(timestamp)\n    if (!Number.isFinite(ts)) return false\n    const ageSeconds = Math.abs(Date.now() / 1000 - ts)\n    if (ageSeconds > toleranceSeconds) return false\n  }\n\n  const bodyBytes = toBytes(rawBody)\n  const signedPayload =\n    timestamp !== undefined ? concatBytes(toBytes(`${timestamp}.`), bodyBytes) : bodyBytes\n\n  const encoder = new TextEncoder()\n  const keyMaterial = encoder.encode(secret)\n  // Cast to ArrayBuffer: TextEncoder.encode returns Uint8Array<ArrayBufferLike>\n  // in newer TS lib, but Web Crypto's BufferSource requires ArrayBuffer-backed.\n  // The underlying buffer is always ArrayBuffer (never SharedArrayBuffer) in\n  // this code path, so the cast is runtime-safe.\n  const key = await crypto.subtle.importKey(\n    'raw',\n    keyMaterial.buffer as ArrayBuffer,\n    { name: 'HMAC', hash: { name: algorithm === 'sha1' ? 'SHA-1' : 'SHA-256' } },\n    false,\n    ['sign'],\n  )\n  const expected = new Uint8Array(\n    await crypto.subtle.sign('HMAC', key, signedPayload.buffer as ArrayBuffer),\n  )\n\n  const prefixMatch = signatureHeader.match(/^[A-Za-z][A-Za-z0-9]{1,15}=(.+)$/)\n  const headerValue = prefixMatch ? prefixMatch[1]! : signatureHeader\n\n  const provided = decodeSignature(headerValue, encoding)\n  if (provided === null) return false\n  if (provided.length !== expected.length) return false\n  return constantTimeEqual(provided, expected)\n}\n\nfunction toBytes(body: string | Uint8Array): Uint8Array {\n  if (typeof body === 'string') return new TextEncoder().encode(body)\n  // Copy into a fresh, tightly-bounded Uint8Array. Node's `Buffer` is a\n  // subclass of Uint8Array but shares an underlying pool across many\n  // Buffer instances — `buf.buffer` can be much larger than the logical\n  // bytes of `buf`, with `byteOffset` / `byteLength` carving out the\n  // slice. `crypto.subtle.sign(..., buf.buffer)` would then sign the\n  // entire pool, producing a wrong HMAC. The copy here normalizes any\n  // input (Buffer or plain Uint8Array) to an exact-length ArrayBuffer.\n  const out = new Uint8Array(body.length)\n  out.set(body)\n  return out\n}\n\nfunction concatBytes(a: Uint8Array, b: Uint8Array): Uint8Array {\n  const out = new Uint8Array(a.length + b.length)\n  out.set(a, 0)\n  out.set(b, a.length)\n  return out\n}\n\nfunction decodeSignature(\n  value: string,\n  encoding: WebhookSignatureEncoding,\n): Uint8Array | null {\n  if (encoding === 'hex') {\n    if (value.length === 0 || value.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(value)) {\n      return null\n    }\n    const out = new Uint8Array(value.length / 2)\n    for (let i = 0; i < out.length; i++) {\n      out[i] = parseInt(value.slice(i * 2, i * 2 + 2), 16)\n    }\n    return out\n  }\n  // base64\n  try {\n    const binary = atob(value)\n    const out = new Uint8Array(binary.length)\n    for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i)\n    return out\n  } catch {\n    return null\n  }\n}\n\nfunction constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n  let diff = 0\n  for (let i = 0; i < a.length; i++) diff |= a[i]! ^ b[i]!\n  return diff === 0\n}\n","import { ConfigurationError } from '../errors'\n\n/**\n * Operators supported by Connect's `field[operator]=value` filter\n * syntax. Multi-value operators accept comma-separated lists; the\n * single-value ones take one value.\n */\nexport type ConnectFilterOperator =\n  /** Include values. Multi-value. */\n  | 'is'\n  /** Exclude values. Multi-value. */\n  | 'not'\n  /** `<` — single value. */\n  | 'lt'\n  /** `<=` — single value. */\n  | 'lte'\n  /** `>` — single value. */\n  | 'gt'\n  /** `>=` — single value. */\n  | 'gte'\n  /** Inclusive range. Two values. */\n  | 'between'\n  /** `<` date. Single value. */\n  | 'before'\n  /** `>` date. Single value. */\n  | 'after'\n\nconst MULTI_VALUE_OPS = new Set<ConnectFilterOperator>(['is', 'not'])\nconst SINGLE_VALUE_OPS = new Set<ConnectFilterOperator>(['lt', 'lte', 'gt', 'gte', 'before', 'after'])\n\n/**\n * Allowlisted shape for field identifiers. Letters, digits, underscore,\n * and dot (for nested paths like `financials.host`). Must start with a\n * letter or underscore.\n *\n * Enforced on every `field` argument across `where`, `sortAsc`,\n * `sortDesc`, and `select` to block two classes of defect:\n *\n * 1. **Log injection.** Without the guard, a field value containing\n *    newlines / ANSI control codes flows into `ConfigurationError.message`\n *    and then into any structured-log sink the caller uses (Sentry,\n *    CloudWatch, etc.). AI agents composing filters from LLM output\n *    are the realistic attack surface.\n * 2. **Param-key corruption.** A field containing `]` or `[` would\n *    produce a malformed `field[operator]` key that the API would reject\n *    with an unhelpful 400 deep in the request pipeline.\n *\n * The error message deliberately does NOT echo the offending `field`\n * value (that's the defect the guard is preventing).\n */\nconst FIELD_PATTERN = /^[A-Za-z_][\\w.]*$/\n\nfunction assertValidField(field: string): void {\n  if (!FIELD_PATTERN.test(field)) {\n    throw new ConfigurationError(\n      `ConnectFilter: field name must match ${FIELD_PATTERN.source} ` +\n        '(letters, digits, underscore, dot; must start with a letter or underscore).',\n    )\n  }\n}\n\n/**\n * Fluent, immutable builder for Connect list params — composes\n * `field[operator]=value` filters, `sort[asc|desc]=field`, `_select=`,\n * and pagination (page / perPage).\n *\n * Every chainable method returns a new `ConnectFilter`; branch safely\n * without mutating shared state. Terminate with {@link toParams}.\n *\n * @example\n * ```ts\n * const params = new ConnectFilter()\n *   .where('city', 'is', ['New York', 'Seattle'])\n *   .where('status', 'not', ['deny', 'cancelled'])\n *   .where('arrival_date', 'before', '2024-02-01')\n *   .sortDesc('arrival_date')\n *   .select('id', 'arrival_date', 'financials.host')\n *   .perPage(50)\n *   .toParams()\n *\n * await connect.reservations.listByCustomer(customerId, params)\n * ```\n *\n * @see https://developer.hospitable.com/docs/connect-api-docs\n */\nexport class ConnectFilter {\n  private readonly state: Record<string, string>\n\n  constructor(state: Record<string, string> = {}) {\n    this.state = state\n  }\n\n  /**\n   * Add a filter. Operator determines how `value` is stringified:\n   * `is` / `not` join arrays with commas; `between` requires exactly\n   * two values; every other operator takes a single value.\n   *\n   * @throws {ConfigurationError} when the value shape doesn't match the operator\n   */\n  where(\n    field: string,\n    operator: ConnectFilterOperator,\n    value: string | number | boolean | Array<string | number | boolean>,\n  ): ConnectFilter {\n    assertValidField(field)\n\n    const stringified = Array.isArray(value)\n      ? value.map(v => String(v)).join(',')\n      : String(value)\n\n    if (operator === 'between') {\n      const parts = Array.isArray(value) ? value : String(value).split(',')\n      if (parts.length !== 2) {\n        throw new ConfigurationError(\n          'ConnectFilter.where: `between` requires exactly two values. ' +\n            `Got ${parts.length}. Example: .where('amount', 'between', [100, 500]).`,\n        )\n      }\n    } else if (MULTI_VALUE_OPS.has(operator)) {\n      if (Array.isArray(value) && value.length === 0) {\n        throw new ConfigurationError(\n          `ConnectFilter.where: \\`${operator}\\` requires at least one value. ` +\n            'Empty arrays cause the API to reject the request.',\n        )\n      }\n    } else if (SINGLE_VALUE_OPS.has(operator)) {\n      if (Array.isArray(value)) {\n        throw new ConfigurationError(\n          `ConnectFilter.where: \\`${operator}\\` takes a single value — received an array. ` +\n            `Example: .where('<field>', '${operator}', '2024-02-01').`,\n        )\n      }\n    }\n\n    // Comma is the multi-value delimiter on `is`, `not`, and `between`.\n    // A value containing a literal comma (e.g. 'San Francisco, CA') would\n    // silently split into two values when the API parses the query string,\n    // so reject it up front rather than producing an ambiguous filter.\n    if (Array.isArray(value) && (MULTI_VALUE_OPS.has(operator) || operator === 'between')) {\n      for (const v of value) {\n        if (typeof v === 'string' && v.includes(',')) {\n          throw new ConfigurationError(\n            `ConnectFilter.where: \\`${operator}\\` values cannot contain commas — ` +\n              'comma is the multi-value delimiter in the Connect query syntax. ' +\n              'Split the value into separate filters or normalize it before passing.',\n          )\n        }\n      }\n    }\n\n    return new ConnectFilter({\n      ...this.state,\n      [`${field}[${operator}]`]: stringified,\n    })\n  }\n\n  /** Sort ascending by `field`. Replaces any prior sort. */\n  sortAsc(field: string): ConnectFilter {\n    assertValidField(field)\n    const next = this.stripSort()\n    next[`sort[asc]`] = field\n    return new ConnectFilter(next)\n  }\n\n  /** Sort descending by `field`. Replaces any prior sort. */\n  sortDesc(field: string): ConnectFilter {\n    assertValidField(field)\n    const next = this.stripSort()\n    next[`sort[desc]`] = field\n    return new ConnectFilter(next)\n  }\n\n  /** Shortcut for `sort=latest` — sorts by record creation time, newest first. */\n  sortLatest(): ConnectFilter {\n    const next = this.stripSort()\n    next['sort'] = 'latest'\n    return new ConnectFilter(next)\n  }\n\n  /** Shortcut for `sort=oldest` — sorts by record creation time, oldest first. */\n  sortOldest(): ConnectFilter {\n    const next = this.stripSort()\n    next['sort'] = 'oldest'\n    return new ConnectFilter(next)\n  }\n\n  /** Request only a subset of response fields via `_select=a,b,c`. */\n  select(...fields: string[]): ConnectFilter {\n    if (fields.length === 0) return this\n    fields.forEach(assertValidField)\n    return new ConnectFilter({ ...this.state, _select: fields.join(',') })\n  }\n\n  page(n: number): ConnectFilter {\n    return new ConnectFilter({ ...this.state, page: String(n) })\n  }\n\n  perPage(n: number): ConnectFilter {\n    return new ConnectFilter({ ...this.state, per_page: String(n) })\n  }\n\n  /** Materialize the filter into a plain params record. */\n  toParams(): Record<string, string> {\n    return { ...this.state }\n  }\n\n  private stripSort(): Record<string, string> {\n    const next: Record<string, string> = {}\n    for (const [k, v] of Object.entries(this.state)) {\n      if (k === 'sort' || k === 'sort[asc]' || k === 'sort[desc]') continue\n      next[k] = v\n    }\n    return next\n  }\n}\n","import type {\n  ReservationDateQuery,\n  ReservationIncludeField,\n  ReservationListParams,\n  ReservationStatus,\n} from '../models/reservation'\nimport { ConfigurationError } from '../errors'\n\n/**\n * Fluent, immutable builder for `client.reservations.list` params.\n *\n * Every chainable method returns a new `ReservationFilter` — safe to branch\n * filters mid-construction without mutating shared state. Terminate the\n * chain with {@link toParams}.\n *\n * @example\n * ```ts\n * const params = new ReservationFilter()\n *   .properties([propertyId])                 // required by the API\n *   .checkinAfter('2026-01-01')\n *   .checkinBefore('2026-12-31')\n *   .dateQuery('checkout')                    // optional — defaults to checkin\n *   .status(['accepted', 'request'])\n *   .include('guest', 'properties', 'review')\n *   .perPage(50)\n *   .toParams()\n *\n * await client.reservations.list(params)\n * ```\n */\nexport class ReservationFilter {\n  private readonly params: Partial<ReservationListParams>\n\n  constructor(params: Partial<ReservationListParams> = {}) {\n    this.params = params\n  }\n\n  /** Reservations with date >= this (ISO `YYYY-MM-DD`), on field chosen by {@link dateQuery}. */\n  checkinAfter(date: string): ReservationFilter {\n    return new ReservationFilter({ ...this.params, startDate: date })\n  }\n\n  /** Reservations with date <= this (ISO `YYYY-MM-DD`), on field chosen by {@link dateQuery}. */\n  checkinBefore(date: string): ReservationFilter {\n    return new ReservationFilter({ ...this.params, endDate: date })\n  }\n\n  /**\n   * Choose which date field `checkinAfter`/`checkinBefore` filter against.\n   * Defaults to `'checkin'` on the API side. Set to `'checkout'` to find\n   * guests currently in-house or departing in a window.\n   */\n  dateQuery(q: ReservationDateQuery): ReservationFilter {\n    return new ReservationFilter({ ...this.params, dateQuery: q })\n  }\n\n  /**\n   * Only reservations whose last-message timestamp is >= this value.\n   * Format: `YYYY-MM-DD HH:MM:SS` (space-separated — NOT ISO 8601).\n   */\n  lastMessageAt(timestamp: string): ReservationFilter {\n    return new ReservationFilter({ ...this.params, lastMessageAt: timestamp })\n  }\n\n  /** Narrow to one or more statuses. */\n  status(status: ReservationStatus | ReservationStatus[]): ReservationFilter {\n    return new ReservationFilter({ ...this.params, status })\n  }\n\n  /** Scope to specific property UUIDs. **Required by the API.** */\n  properties(ids: string[]): ReservationFilter {\n    return new ReservationFilter({ ...this.params, properties: ids })\n  }\n\n  /**\n   * Request one or more include fields. Pass as separate arguments:\n   * `.include('guest', 'properties', 'review')`.\n   */\n  include(...fields: ReservationIncludeField[]): ReservationFilter {\n    return new ReservationFilter({ ...this.params, include: fields.join(',') })\n  }\n\n  perPage(n: number): ReservationFilter {\n    return new ReservationFilter({ ...this.params, perPage: n })\n  }\n\n  /**\n   * Materialize the filter into a plain params object suitable for\n   * `client.reservations.list()`.\n   *\n   * @throws {ConfigurationError} when `properties` has not been supplied\n   */\n  toParams(): ReservationListParams {\n    if (!this.params.properties || this.params.properties.length === 0) {\n      throw new ConfigurationError(\n        'ReservationFilter.toParams: call .properties([...ids]) first — ' +\n          'the Hospitable API rejects reservation queries without this filter.',\n      )\n    }\n    return { ...this.params } as ReservationListParams\n  }\n}\n","import type { PropertyListParams } from '../resources/properties'\nimport type { PropertyIncludeField } from '../models/property'\n\n/**\n * Fluent, immutable builder for `client.properties.list` params.\n *\n * @example\n * ```ts\n * const params = new PropertyFilter()\n *   .tags(['tag-uuid-1', 'tag-uuid-2'])\n *   .include('user', 'listings')\n *   .perPage(100)\n *   .toParams()\n *\n * await client.properties.list(params)\n * ```\n */\nexport class PropertyFilter {\n  private readonly params: PropertyListParams\n\n  constructor(params: PropertyListParams = {}) {\n    this.params = params\n  }\n\n  /** Narrow to properties tagged with any of the given tag UUIDs. */\n  tags(tagIds: string[]): PropertyFilter {\n    return new PropertyFilter({ ...this.params, tags: tagIds })\n  }\n\n  /**\n   * Request one or more include fields. Pass as separate arguments:\n   * `.include('user', 'listings', 'details')`. Accepted values are\n   * `'user'`, `'listings'`, `'details'`, `'bookings'` — unknown values\n   * are silently ignored by the API, so TypeScript narrowing via\n   * {@link PropertyIncludeField} is the only fail-fast check.\n   */\n  include(...fields: PropertyIncludeField[]): PropertyFilter {\n    return new PropertyFilter({ ...this.params, include: fields.join(',') })\n  }\n\n  perPage(n: number): PropertyFilter {\n    return new PropertyFilter({ ...this.params, perPage: n })\n  }\n\n  /** Materialize the filter into a plain params object. */\n  toParams(): PropertyListParams {\n    return { ...this.params }\n  }\n}\n","import type { InquiryIncludeField, InquiryListParams } from '../models/inquiry'\nimport { ConfigurationError } from '../errors'\n\n/**\n * Fluent builder for inquiry list params.\n *\n * Immutable — every method returns a new `InquiryFilter`. Build up the filter then\n * call {@link toParams} or pass directly to `client.inquiries.list(filter.toParams())`.\n *\n * The underlying API requires a non-empty `properties` filter;\n * {@link toParams} throws {@link ConfigurationError} if none was supplied.\n *\n * @example\n * ```ts\n * const params = new InquiryFilter()\n *   .properties(['prop-uuid'])\n *   .include('guest', 'properties')\n *   .lastMessageAfter('2026-01-01T00:00:00Z')\n *   .perPage(50)\n *   .toParams()\n *\n * await client.inquiries.list(params)\n * ```\n */\nexport class InquiryFilter {\n  private readonly params: Partial<InquiryListParams>\n\n  constructor(params: Partial<InquiryListParams> = {}) {\n    this.params = params\n  }\n\n  properties(ids: string[]): InquiryFilter {\n    return new InquiryFilter({ ...this.params, properties: ids })\n  }\n\n  include(...fields: InquiryIncludeField[]): InquiryFilter {\n    return new InquiryFilter({ ...this.params, include: fields.join(',') })\n  }\n\n  lastMessageAfter(datetime: string): InquiryFilter {\n    return new InquiryFilter({ ...this.params, lastMessageAt: datetime })\n  }\n\n  page(n: number): InquiryFilter {\n    return new InquiryFilter({ ...this.params, page: n })\n  }\n\n  perPage(n: number): InquiryFilter {\n    return new InquiryFilter({ ...this.params, perPage: n })\n  }\n\n  /**\n   * Materialize the filter.\n   *\n   * @throws {ConfigurationError} if `.properties()` was never called or was\n   * called with an empty array — the `/v2/inquiries` endpoint requires a\n   * non-empty set of property UUIDs.\n   */\n  toParams(): InquiryListParams {\n    if (!this.params.properties || this.params.properties.length === 0) {\n      throw new ConfigurationError(\n        'InquiryFilter: `properties` is required. Call .properties([uuid, ...]) before .toParams().',\n      )\n    }\n    return { ...this.params, properties: this.params.properties }\n  }\n}\n"],"mappings":"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","names":["statusCode","DEFAULT_TTL","DEFAULT_TTL","normalizeListParams","ReservationsResource","ReviewsResource","TransactionsResource","PayoutsResource","ReservationsResource","ReviewsResource","TransactionsResource","PayoutsResource","PayoutsResource","ReservationsResource","ReviewsResource","TransactionsResource"]}