/** * Vertical-agnostic live availability-search fan-out. * * Parallel `searchAvailability` across an operator's sourced connections and * owned search handlers, with per-connection timeouts, partial-success * handling, and a ranked merge into one `AvailabilityCandidate` list. The * non-flight counterpart of `fanOutFlightSearch` * (`@voyant-travel/flights`), built on the catalog source-adapter contract. * * Owned and sourced supply land in the same ranked list; one slow/erroring * source is flagged in `perConnection`, never fatal. * * See `docs/architecture/dynamic-packaging-rfc.md` §2 (Gap 1) and §4. */ import type { AvailabilityCandidate, AvailabilitySearchRequest, SourceAdapter, SourceAdapterContext } from "@voyant-travel/catalog-contracts"; import type { OwnedAvailabilitySearchHandler, OwnedSearchContext } from "./owned-search-handler.js"; /** Per-source outcome, returned alongside merged candidates for partial-success UX. */ export type AvailabilityConnectionStatus = "ok" | "partial" | "empty" | "unsupported" | "timeout" | "error" | "capability_missing" | "vertical_skipped"; export interface AvailabilityConnectionResult { /** Connection id (sourced) or entity module (owned). */ source: string; kind: "sourced" | "owned"; status: AvailabilityConnectionStatus; count: number; latencyMs: number; errorMessage?: string; /** * Per-source pagination token. A merged cursor can't represent N sources, * so paging is per-connection: re-run the fan-out for just this source with * `request.cursor = nextCursor` to fetch its next page. */ nextCursor?: string; } export interface FanOutAvailabilityResult { /** Merged + ranked candidates across every responding source. */ candidates: AvailabilityCandidate[]; perConnection: AvailabilityConnectionResult[]; } export interface FanOutAvailabilitySearchOptions { /** Sourced adapters to fan out across. Gated by `supportsAvailabilitySearch`. */ adapters?: ReadonlyArray<{ connectionId: string; adapter: SourceAdapter; context?: Partial; }>; /** Owned search handlers — owned inventory as a search source. */ ownedHandlers?: ReadonlyArray<{ handler: OwnedAvailabilitySearchHandler; context: OwnedSearchContext; }>; request: AvailabilitySearchRequest; /** * Per-source hard timeout. Default 5000ms. One slow source is reported as * `timeout`; the rest return on time. */ perConnectionTimeoutMs?: number; /** Optional cap on the merged candidate count (the search still runs in full). */ limit?: number; } /** * Fan out an availability search across sourced connections + owned handlers, * parallelized with a per-source timeout, then merge and rank by price. * * Partial-success semantics: sources that time out / error / lack the * capability are flagged in `perConnection`; the fan-out still returns * whatever responding sources produced. */ export declare function fanOutAvailabilitySearch(options: FanOutAvailabilitySearchOptions): Promise;