sabre-client 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/sabre-error.ts","../src/air/grouped-itinerary.ts","../src/air/itinerary-messages.ts","../src/http/raw-request.ts","../src/air/bargain-finder-max.ts","../src/booking/booking-errors.ts","../src/air/get-seats.ts","../src/air/itinerary-flights.ts","../src/air/revalidate-itinerary.ts","../src/air/air.ts","../src/logging/redact.ts","../src/logging/logger.ts","../src/auth/token-request.ts","../src/auth/token-store.ts","../src/auth/auth-manager.ts","../src/booking/cancel-booking.ts","../src/booking/flight-details.ts","../src/booking/create-booking.ts","../src/booking/get-booking.ts","../src/booking/booking-management.ts","../src/http/retry.ts","../src/config.ts","../src/http/rest-transport.ts","../src/sabre.ts","../src/http/soap-transport.ts","../src/session/credentials.ts","../src/queue/queue-access.ts","../src/queue/queue-ref.ts","../src/queue/queue-count.ts","../src/queue/queue-list.ts","../src/queue/queue-activity.ts","../src/queue/queue-place.ts","../src/queue/queue-management.ts","../src/reservation/reservation-history.ts","../src/reservation/session-reservation.ts","../src/session/command.ts","../src/session/session.ts","../src/sabre-legacy.ts","../src/auth/credentials.ts","../src/queue/host-date.ts","../src/queue/queue-paragraph.ts","../src/queue/queue-place-remark.ts","../src/air/seat-availability-request.ts","../src/index.ts"],"sourcesContent":["// Jerarquía de errores del SDK. Ver sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md.\n\nexport interface SabreErrorOptions {\n /** Si la política de reintentos puede volver a intentar la operación. */\n retryable: boolean;\n /** Fragmento de la respuesta original sin transformar (JSON parseado o nodo XML). */\n raw?: unknown;\n cause?: unknown;\n}\n\n/**\n * Base de todos los errores del SDK.\n *\n * `raw` puede contener credenciales o datos de pasajero: no es enumerable, así que\n * no aparece en `JSON.stringify`, spreads ni serializadores de logs, pero sigue\n * accesible como `error.raw` para debugging. No lo vuelques a un logger sin sanitizar.\n */\nexport class SabreError extends Error {\n override name = 'SabreError';\n readonly retryable: boolean;\n declare readonly raw: unknown;\n\n constructor(message: string, options: SabreErrorOptions) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.retryable = options.retryable;\n Object.defineProperty(this, 'raw', {\n value: options.raw,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n }\n\n toJSON(): Record<string, unknown> {\n const fields: Record<string, unknown> = Object.fromEntries(Object.entries(this));\n return { ...fields, name: this.name, message: this.message };\n }\n}\n\nexport type SabreProtocol = 'rest' | 'soap';\n\nexport interface SabreGatewayErrorOptions extends SabreErrorOptions {\n protocol: SabreProtocol;\n /** HTTP status de la respuesta, si la hubo. */\n status?: number;\n /** Código tal cual lo devuelve el gateway (`ERR.2SG.*`, `USG_*`), si viene en el body. */\n code?: string;\n}\n\n/** Error de transporte/gateway (`ERR.2SG.*` + HTTP status en REST, `USG_*` en SOAP). */\nexport class SabreGatewayError extends SabreError {\n override name = 'SabreGatewayError';\n readonly protocol: SabreProtocol;\n readonly status: number | undefined;\n readonly code: string | undefined;\n\n constructor(message: string, options: SabreGatewayErrorOptions) {\n super(message, options);\n this.protocol = options.protocol;\n this.status = options.status;\n this.code = options.code;\n }\n}\n\n/**\n * Por qué una sesión SOAP no sirve: `'limit'` (más de 50 sesiones), `'invalid'` (uso\n * concurrente de la sesión), `'expired'` (sesión vencida) o `'blocked'` (creación de sesión\n * bloqueada para el usuario).\n */\nexport type SabreSessionErrorKind = 'limit' | 'invalid' | 'expired' | 'blocked';\n\nexport interface SabreSessionErrorOptions extends Omit<SabreGatewayErrorOptions, 'protocol'> {\n kind: SabreSessionErrorKind;\n}\n\n/**\n * Error de la sesión SOAP de `SabreLegacy`. Se distingue con `instanceof` y `kind`, sin comparar\n * mensajes. La sesión que lo lanzó queda inutilizable: las llamadas siguientes lanzan sin red.\n */\nexport class SabreSessionError extends SabreGatewayError {\n override name = 'SabreSessionError';\n readonly kind: SabreSessionErrorKind;\n\n constructor(message: string, options: SabreSessionErrorOptions) {\n super(message, { ...options, protocol: 'soap' });\n this.kind = options.kind;\n }\n}\n\nexport interface SabreOrchestrationErrorOptions extends Omit<SabreErrorOptions, 'retryable'> {\n /** `SP.PROVIDER_ERROR` o `SP.INTERNAL_ERROR`. */\n code: string;\n}\n\n/**\n * Error de servicio orquestado (`SP.*`), viaja dentro de una respuesta 200.\n * `SP.PROVIDER_ERROR` es reintentable; `SP.INTERNAL_ERROR` (y cualquier otro) no.\n */\nexport class SabreOrchestrationError extends SabreError {\n override name = 'SabreOrchestrationError';\n readonly code: string;\n\n constructor(message: string, options: SabreOrchestrationErrorOptions) {\n super(message, { ...options, retryable: options.code === 'SP.PROVIDER_ERROR' });\n this.code = options.code;\n }\n}\n\nexport interface SabreServiceErrorOptions extends Omit<SabreErrorOptions, 'retryable'> {\n /** Servicio que originó el error, p. ej. `'createBooking'`. */\n service: string;\n /** Código tal cual lo documenta Sabre, sin normalizar. */\n code: string;\n}\n\nexport interface SabreBusinessErrorOptions extends SabreServiceErrorOptions {\n /**\n * Solo para códigos que Sabre documenta como temporales en un servicio de lectura\n * (p. ej. `Transmission timeout` de Bargain Finder Max). Por defecto `false`.\n * La política de reintentos igual exige que la operación sea idempotente.\n */\n retryable?: boolean;\n /** Avisos que llegaron junto con el error (p. ej. `category: WARNING` de Create Booking). */\n warnings?: readonly SabreWarning[];\n /**\n * Otros errores que llegaron junto con este (p. ej. la causa real detrás de\n * `NO_ITEMS_CANCELLED` en Cancel Booking).\n */\n errors?: readonly SabreBusinessError[];\n}\n\n/**\n * Error del catálogo propio de un servicio. No es reintentable, salvo los códigos\n * temporales de servicios de lectura que se marcan con `retryable: true`.\n */\nexport class SabreBusinessError extends SabreError {\n override name = 'SabreBusinessError';\n readonly service: string;\n readonly code: string;\n readonly warnings: readonly SabreWarning[];\n readonly errors: readonly SabreBusinessError[];\n\n constructor(message: string, options: SabreBusinessErrorOptions) {\n super(message, { ...options, retryable: options.retryable ?? false });\n this.service = options.service;\n this.code = options.code;\n this.warnings = options.warnings ?? [];\n this.errors = options.errors ?? [];\n }\n}\n\n/**\n * Advertencia de un servicio (p. ej. `category: WARNING` de Create Booking, soft errors\n * de End Transaction): no es un fallo fatal. Nunca se reintenta automáticamente.\n */\nexport class SabreWarning extends SabreError {\n override name = 'SabreWarning';\n readonly service: string;\n readonly code: string;\n\n constructor(message: string, options: SabreServiceErrorOptions) {\n super(message, { ...options, retryable: false });\n this.service = options.service;\n this.code = options.code;\n }\n}\n","// Modelo `groupedItineraryResponse` compartido por Bargain Finder Max y Revalidate Itinerary,\n// y su desnormalizador: resuelve cada `ref` al objeto completo antes de exponerlo.\n// Ver sabre-wiki/wiki/concepts/modelo-de-itinerario.md.\n//\n// Sin schema formal: los campos salen de los ejemplos de BFM y Revalidate del wiki. Los que\n// solo aparecieron en uno de los dos van como opcionales.\nimport { SabreError } from '../errors/index.js';\n\n// ---------------------------------------------------------------------------\n// Descriptores compartidos (arrays planos indexados por `id`)\n// ---------------------------------------------------------------------------\n\nexport interface ScheduleEndpoint {\n airport: string;\n city?: string;\n /** Visto en sandbox para aeropuertos de EE. UU. */\n state?: string;\n country?: string;\n /** Hora local con offset, p. ej. `17:10:00+02:00`. */\n time: string;\n terminal?: string;\n /** Días que se suman a la fecha de salida del vuelo. Visto en sandbox (`arrival`). */\n dateAdjustment?: number;\n}\n\nexport interface ScheduleEquipment {\n code: string;\n typeForFirstLeg?: string;\n typeForLastLeg?: string;\n}\n\nexport interface ScheduleCarrier {\n marketing: string;\n marketingFlightNumber: number;\n operating?: string;\n operatingFlightNumber?: number;\n alliances?: string;\n equipment?: ScheduleEquipment;\n /**\n * Nombre del operador en un código compartido, tal cual (p. ej. `\"/AVIANCA\"`). No está en el\n * spec. Se observó en BFM y Revalidate en CERT, también cuando `operating` y\n * `operatingFlightNumber` coinciden con el comercializador (AM101 TRC→MEX, operado por\n * `\"AEROLITORAL DBA AEROMEXICO CONNECT\"`, 2026-11-05).\n */\n codeShared?: string;\n}\n\n/** Vuelo/segmento operado (`scheduleDescs[]`). */\nexport interface ScheduleDesc {\n id: number;\n /** Visto en sandbox, p. ej. `\"7\"`; significado sin confirmar. */\n dotRating?: string;\n frequency?: string;\n stopCount?: number;\n eTicketable?: boolean;\n totalMilesFlown?: number;\n /** Minutos. */\n elapsedTime?: number;\n departure: ScheduleEndpoint;\n arrival: ScheduleEndpoint;\n carrier: ScheduleCarrier;\n}\n\n/** Tramo lógico (`legDescs[]`): agrupa schedules por `ref`. */\nexport interface LegDesc {\n id: number;\n /** Minutos. */\n elapsedTime?: number;\n schedules: LegScheduleRef[];\n}\n\n/**\n * Schedule dentro de un tramo. `departureDateAdjustment`: días que se suman a la fecha del\n * tramo para la salida de este vuelo (conexión al día siguiente). Visto en sandbox, sin\n * documentar en los ejemplos de Sabre.\n */\nexport interface LegScheduleRef extends Ref {\n departureDateAdjustment?: number;\n}\n\n/** Impuesto individual (`taxDescs[]`). */\nexport interface TaxDesc {\n id: number;\n code: string;\n amount: number;\n currency: string;\n description?: string;\n publishedAmount?: number;\n publishedCurrency?: string;\n station?: string;\n country?: string;\n /** Visto en sandbox. */\n taxReissue?: { refundable?: boolean };\n}\n\n/** Resumen de impuestos por código (`taxSummaryDescs[]`). Misma forma que `TaxDesc`. */\nexport type TaxSummaryDesc = TaxDesc;\n\n/** Cargo adicional (`obFeeDescs[]`). Significado exacto de \"OB\" sin confirmar. */\nexport interface ObFeeDesc {\n id: number;\n amount: number;\n currency: string;\n}\n\nexport interface FareComponentDescSegment {\n segment: {\n stopover?: boolean;\n };\n}\n\n/** Componente de tarifa (`fareComponentDescs[]`). */\nexport interface FareComponentDesc {\n id: number;\n governingCarrier?: string;\n fareAmount?: number;\n fareCurrency?: string;\n fareBasisCode: string;\n farePassengerType?: string;\n publishedFareAmount?: number;\n publishedFareCurrency?: string;\n /** `FROM` / `TO`. */\n directionality?: string;\n applicablePricingCategories?: string;\n vendorCode?: string;\n fareTypeBitmap?: string;\n fareType?: string;\n fareTariff?: string;\n fareRule?: string;\n cabinCode?: string;\n segments?: FareComponentDescSegment[];\n // Vistos solo en Revalidate Itinerary.\n ticketDesignator?: string;\n mileageSurcharge?: number;\n mileage?: boolean;\n oneWayFare?: boolean;\n negotiatedFare?: boolean;\n privateFare?: boolean;\n notValidAfter?: string;\n /** Distinto de `directionality`; significado sin confirmar. */\n direction?: string;\n}\n\n/** Aerolínea validadora (`validatingCarrierDescs[]`). */\nexport interface ValidatingCarrierDesc {\n id: number;\n settlementMethod?: string;\n newVcxProcess?: boolean;\n default?: { code: string };\n}\n\n/** Franquicia de equipaje (`baggageAllowanceDescs[]`). */\nexport interface BaggageAllowanceDesc {\n id: number;\n pieceCount?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Piezas que no llevan referencias\n// ---------------------------------------------------------------------------\n\n/** Referencia a un descriptor por su `id`. */\nexport interface Ref {\n ref: number;\n}\n\nexport interface ItineraryMessage {\n severity: string;\n type: string;\n code: string;\n text: string;\n}\n\nexport interface LegDescription {\n departureDate: string;\n departureLocation: string;\n arrivalLocation: string;\n}\n\nexport interface CurrencyConversion {\n from: string;\n to: string;\n exchangeRateUsed: number;\n}\n\nexport interface PassengerTotalFare {\n totalFare: number;\n totalTaxAmount?: number;\n currency: string;\n baseFareAmount?: number;\n baseFareCurrency?: string;\n equivalentAmount?: number;\n equivalentCurrency?: string;\n constructionAmount?: number;\n constructionCurrency?: string;\n exchangeRateOne?: number;\n // Comisión de agencia: vistos solo en Revalidate Itinerary.\n commissionPercentage?: number;\n commissionAmount?: number;\n cat35CommissionPercentage?: number;\n cat35CommissionAmount?: number;\n cat35MarkupAmount?: number;\n commissionAmountInEquivalent?: number;\n commissionSource?: string;\n}\n\nexport interface TotalFare {\n totalPrice: number;\n totalTaxAmount?: number;\n currency: string;\n baseFareAmount?: number;\n baseFareCurrency?: string;\n constructionAmount?: number;\n constructionCurrency?: string;\n equivalentAmount?: number;\n equivalentCurrency?: string;\n}\n\n/** Disponibilidad del segmento dentro de un componente de tarifa. */\nexport interface FareComponentSegmentDetail {\n bookingCode?: string;\n cabinCode?: string;\n mealCode?: string;\n seatsAvailable?: number;\n availabilityBreak?: boolean;\n fareBreakPoint?: boolean;\n}\n\nexport interface FareMessage {\n type: string;\n code: string;\n /** Visto en sandbox de Revalidate. */\n carrier?: string;\n info: string;\n}\n\n// ---------------------------------------------------------------------------\n// Respuesta tal cual la manda Sabre (con `ref`). Interna: el SDK expone la desnormalizada.\n// ---------------------------------------------------------------------------\n\nexport interface RawFareComponent extends Ref {\n beginAirport?: string;\n endAirport?: string;\n segments?: Array<{ segment: FareComponentSegmentDetail }>;\n}\n\nexport interface RawBaggageInformation {\n provisionType?: string;\n airlineCode?: string;\n /** Índices de segmento, no referencias a descriptores. */\n segments?: Array<{ id: number }>;\n allowance?: Ref;\n}\n\nexport interface RawPassengerInfo {\n passengerType: string;\n passengerNumber?: number;\n nonRefundable?: boolean;\n fareComponents?: RawFareComponent[];\n taxes?: Ref[];\n taxSummaries?: Ref[];\n obFees?: Ref[];\n currencyConversion?: CurrencyConversion;\n passengerTotalFare?: PassengerTotalFare;\n baggageInformation?: RawBaggageInformation[];\n // Vistos solo en Revalidate Itinerary.\n fareMessages?: FareMessage[];\n fareCalcLine?: { info: string };\n}\n\nexport interface RawFare {\n mandatoryInd?: boolean;\n validatingCarrierCode?: string;\n vita?: boolean;\n eTicketable?: boolean;\n lastTicketDate?: string;\n lastTicketTime?: string;\n governingCarriers?: string;\n passengerInfoList: Array<{ passengerInfo: RawPassengerInfo }>;\n totalFare?: TotalFare;\n validatingCarriers?: Ref[];\n}\n\nexport interface RawPricingInformation {\n pricingSubsource?: string;\n /** P. ej. `ATPCO`. Visto en Revalidate y en sandbox de BFM. */\n distributionModel?: string;\n fare: RawFare;\n}\n\nexport interface RawItinerary {\n id: number;\n pricingSource?: string;\n /** Visto solo en Revalidate Itinerary. */\n currentItinerary?: boolean;\n /** Visto en sandbox de BFM; significado sin confirmar. */\n diversitySwapper?: { weighedPrice?: number };\n legs: Ref[];\n pricingInformation: RawPricingInformation[];\n}\n\nexport interface RawItineraryGroup {\n groupDescription: { legDescriptions: LegDescription[] };\n itineraries: RawItinerary[];\n}\n\n/** Contenido de `groupedItineraryResponse` tal cual llega de Sabre. */\nexport interface RawGroupedItineraryResponse {\n version: string;\n messages?: ItineraryMessage[];\n statistics?: { itineraryCount: number };\n scheduleDescs?: ScheduleDesc[];\n taxDescs?: TaxDesc[];\n taxSummaryDescs?: TaxSummaryDesc[];\n obFeeDescs?: ObFeeDesc[];\n fareComponentDescs?: FareComponentDesc[];\n validatingCarrierDescs?: ValidatingCarrierDesc[];\n baggageAllowanceDescs?: BaggageAllowanceDesc[];\n legDescs?: LegDesc[];\n itineraryGroups?: RawItineraryGroup[];\n}\n\n// ---------------------------------------------------------------------------\n// Respuesta desnormalizada (superficie pública)\n// ---------------------------------------------------------------------------\n\n/** Tramo con sus schedules resueltos. */\nexport interface Leg extends Omit<LegDesc, 'schedules'> {\n schedules: LegSchedule[];\n}\n\n/** Schedule resuelto, con lo que la referencia del tramo agrega. */\nexport type LegSchedule = ScheduleDesc & Omit<LegScheduleRef, 'ref'>;\n\n/** Segmento de un componente de tarifa: lo del descriptor más la disponibilidad del itinerario. */\nexport interface FareComponentSegment {\n segment: FareComponentDescSegment['segment'] & FareComponentSegmentDetail;\n}\n\n/** Componente de tarifa resuelto: descriptor + datos propios del itinerario. */\nexport interface FareComponent extends Omit<FareComponentDesc, 'segments'> {\n beginAirport?: string;\n endAirport?: string;\n segments?: FareComponentSegment[];\n}\n\nexport interface BaggageInformation extends Omit<RawBaggageInformation, 'allowance'> {\n allowance?: BaggageAllowanceDesc;\n}\n\nexport interface PassengerInfo\n extends Omit<RawPassengerInfo, 'fareComponents' | 'taxes' | 'taxSummaries' | 'obFees' | 'baggageInformation'> {\n fareComponents?: FareComponent[];\n taxes?: TaxDesc[];\n taxSummaries?: TaxSummaryDesc[];\n obFees?: ObFeeDesc[];\n baggageInformation?: BaggageInformation[];\n}\n\nexport interface Fare extends Omit<RawFare, 'passengerInfoList' | 'validatingCarriers'> {\n passengerInfoList: Array<{ passengerInfo: PassengerInfo }>;\n validatingCarriers?: ValidatingCarrierDesc[];\n}\n\nexport interface PricingInformation extends Omit<RawPricingInformation, 'fare'> {\n fare: Fare;\n}\n\nexport interface Itinerary extends Omit<RawItinerary, 'legs' | 'pricingInformation'> {\n legs: Leg[];\n pricingInformation: PricingInformation[];\n}\n\nexport interface ItineraryGroup {\n groupDescription: { legDescriptions: LegDescription[] };\n itineraries: Itinerary[];\n}\n\n/**\n * `groupedItineraryResponse` con cada `ref` resuelto al objeto completo. Los arrays de\n * descriptores (`scheduleDescs`, `legDescs`, …) ya no se exponen: su contenido vive\n * dentro de cada itinerario.\n */\nexport interface GroupedItineraryResponse {\n version: string;\n messages: ItineraryMessage[];\n statistics?: { itineraryCount: number };\n itineraryGroups: ItineraryGroup[];\n}\n\n// ---------------------------------------------------------------------------\n// Desnormalizador\n// ---------------------------------------------------------------------------\n\n/**\n * Resuelve cada `{ ref, ...resto }` a `{ ...descriptor, ...resto }` (sin `ref`; el `id` del\n * descriptor se conserva). En los componentes de tarifa, `segments` se fusiona elemento a\n * elemento: el descriptor aporta `stopover` y el itinerario la disponibilidad; si los dos\n * traen `segments` con distinto largo, la respuesta es malformada.\n *\n * Un `ref` sin descriptor con ese `id` es una respuesta malformada: lanza `SabreError`\n * no reintentable en vez de devolver un objeto a medias. No muta la entrada.\n */\nexport function denormalizeGroupedItineraryResponse(\n raw: RawGroupedItineraryResponse,\n service: string,\n): GroupedItineraryResponse {\n const resolver = new Resolver(raw, service);\n return {\n version: raw.version,\n messages: raw.messages ?? [],\n ...(raw.statistics === undefined ? {} : { statistics: raw.statistics }),\n itineraryGroups: (raw.itineraryGroups ?? []).map((group) => ({\n groupDescription: group.groupDescription,\n itineraries: group.itineraries.map((itinerary) => resolver.itinerary(itinerary)),\n })),\n };\n}\n\nclass Resolver {\n readonly #service: string;\n readonly #schedules: Map<number, ScheduleDesc>;\n readonly #legs: Map<number, LegDesc>;\n readonly #taxes: Map<number, TaxDesc>;\n readonly #taxSummaries: Map<number, TaxSummaryDesc>;\n readonly #obFees: Map<number, ObFeeDesc>;\n readonly #fareComponents: Map<number, FareComponentDesc>;\n readonly #validatingCarriers: Map<number, ValidatingCarrierDesc>;\n readonly #baggageAllowances: Map<number, BaggageAllowanceDesc>;\n\n constructor(raw: RawGroupedItineraryResponse, service: string) {\n this.#service = service;\n this.#schedules = byId(raw.scheduleDescs);\n this.#legs = byId(raw.legDescs);\n this.#taxes = byId(raw.taxDescs);\n this.#taxSummaries = byId(raw.taxSummaryDescs);\n this.#obFees = byId(raw.obFeeDescs);\n this.#fareComponents = byId(raw.fareComponentDescs);\n this.#validatingCarriers = byId(raw.validatingCarrierDescs);\n this.#baggageAllowances = byId(raw.baggageAllowanceDescs);\n }\n\n itinerary(itinerary: RawItinerary): Itinerary {\n return {\n ...itinerary,\n legs: itinerary.legs.map((ref) => this.#leg(ref)),\n pricingInformation: itinerary.pricingInformation.map((pricing) => ({\n ...pricing,\n fare: this.#fare(pricing.fare),\n })),\n };\n }\n\n #leg(ref: Ref): Leg {\n const leg = this.#merge(this.#legs, 'legDescs', ref);\n return { ...leg, schedules: leg.schedules.map((schedule) => this.#merge(this.#schedules, 'scheduleDescs', schedule)) };\n }\n\n #fare(fare: RawFare): Fare {\n const { validatingCarriers, ...rest } = fare;\n return {\n ...rest,\n passengerInfoList: fare.passengerInfoList.map(({ passengerInfo, ...entry }) => ({\n ...entry,\n passengerInfo: this.#passengerInfo(passengerInfo),\n })),\n ...(validatingCarriers === undefined\n ? {}\n : {\n validatingCarriers: validatingCarriers.map((ref) =>\n this.#merge(this.#validatingCarriers, 'validatingCarrierDescs', ref),\n ),\n }),\n };\n }\n\n #passengerInfo(info: RawPassengerInfo): PassengerInfo {\n const { fareComponents, taxes, taxSummaries, obFees, baggageInformation, ...rest } = info;\n const result: PassengerInfo = { ...rest };\n if (fareComponents !== undefined) result.fareComponents = fareComponents.map((ref) => this.#fareComponent(ref));\n if (taxes !== undefined) result.taxes = taxes.map((ref) => this.#merge(this.#taxes, 'taxDescs', ref));\n if (taxSummaries !== undefined) {\n result.taxSummaries = taxSummaries.map((ref) => this.#merge(this.#taxSummaries, 'taxSummaryDescs', ref));\n }\n if (obFees !== undefined) result.obFees = obFees.map((ref) => this.#merge(this.#obFees, 'obFeeDescs', ref));\n if (baggageInformation !== undefined) {\n result.baggageInformation = baggageInformation.map(({ allowance, ...bag }) => ({\n ...bag,\n ...(allowance === undefined\n ? {}\n : { allowance: this.#merge(this.#baggageAllowances, 'baggageAllowanceDescs', allowance) }),\n }));\n }\n return result;\n }\n\n #fareComponent(ref: RawFareComponent): FareComponent {\n const desc = this.#lookup(this.#fareComponents, 'fareComponentDescs', ref.ref);\n const { ref: _ref, segments: siteSegments, ...site } = ref;\n const { segments: descSegments, ...descRest } = desc;\n if (descSegments !== undefined && siteSegments !== undefined && descSegments.length !== siteSegments.length) {\n throw this.#malformed(\n `fareComponents con ${siteSegments.length} segmentos y fareComponentDescs ${ref.ref} con ${descSegments.length}`,\n );\n }\n const segments = mergeSegments(descSegments, siteSegments);\n return { ...descRest, ...site, ...(segments === undefined ? {} : { segments }) };\n }\n\n /** `{ ref, ...resto }` → `{ ...descriptor, ...resto }`. */\n #merge<T extends { id: number }>(index: Map<number, T>, kind: string, ref: Ref): T {\n const { ref: id, ...site } = ref;\n return { ...this.#lookup(index, kind, id), ...site };\n }\n\n #lookup<T>(index: Map<number, T>, kind: string, id: number): T {\n const desc = index.get(id);\n if (desc === undefined) throw this.#malformed(`ref ${id} sin descriptor en ${kind}`);\n return desc;\n }\n\n #malformed(detail: string): SabreError {\n return new SabreError(`${this.#service}: respuesta malformada, ${detail}`, { retryable: false });\n }\n}\n\nfunction byId<T extends { id: number }>(descs: T[] | undefined): Map<number, T> {\n return new Map((descs ?? []).map((desc) => [desc.id, desc]));\n}\n\nfunction mergeSegments(\n desc: FareComponentDescSegment[] | undefined,\n site: Array<{ segment: FareComponentSegmentDetail }> | undefined,\n): FareComponentSegment[] | undefined {\n if (desc === undefined && site === undefined) return undefined;\n // Los largos ya se validaron iguales cuando vienen los dos.\n const length = desc?.length ?? site?.length ?? 0;\n return Array.from({ length }, (_, i) => ({\n segment: { ...desc?.[i]?.segment, ...site?.[i]?.segment },\n }));\n}\n","// Clasificación de errores de negocio en `groupedItineraryResponse.messages[]`, compartida por\n// los servicios que responden con ese modelo (Bargain Finder Max, Revalidate Itinerary).\n// Ver sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md.\nimport { SabreBusinessError, SabreError } from '../errors/index.js';\nimport type { ItineraryMessage } from './grouped-itinerary.js';\n\n/** Entrada de catálogo: se compara por substring del `text`, sin distinguir mayúsculas. */\nexport interface ItineraryMessageCatalogEntry {\n code: string;\n retryable: boolean;\n}\n\n/**\n * Paso 3 del orden de detección: un mensaje con `severity: Error` en\n * `groupedItineraryResponse.messages[]` (respuesta 200) es un `SabreBusinessError`.\n *\n * En sandbox, los mensajes `Error` son genéricos (`No complete journey can be built…`,\n * `Error during Processing`) y el texto del catálogo llega en un mensaje `Info`\n * (`NO FLIGHT SCHEDULES FOR QUALIFIERS USED`). Por eso, cuando hay algún `Error`, el\n * catálogo se busca en el `text` de todos los mensajes.\n */\nexport function classifyItineraryMessages(\n body: unknown,\n service: string,\n catalog: ReadonlyArray<ItineraryMessageCatalogEntry>,\n): SabreError | undefined {\n const response = isObject(body) ? body.groupedItineraryResponse : undefined;\n if (!isObject(response)) {\n return new SabreError(`${service}: respuesta malformada, falta groupedItineraryResponse`, {\n retryable: false,\n raw: body,\n });\n }\n const messages = Array.isArray(response.messages) ? (response.messages as Partial<ItineraryMessage>[]) : [];\n const error = messages.find((message) => message.severity?.toLowerCase() === 'error');\n if (error === undefined) return undefined;\n\n const match = findInCatalog(messages, catalog);\n const text = match?.text ?? (typeof error.text === 'string' ? error.text : '');\n const known = match?.entry;\n const code = known?.code ?? error.code ?? text;\n return new SabreBusinessError(`${service}: ${text || code}`, {\n service,\n code,\n retryable: known?.retryable ?? false,\n raw: body,\n });\n}\n\nfunction findInCatalog(\n messages: Partial<ItineraryMessage>[],\n catalog: ReadonlyArray<ItineraryMessageCatalogEntry>,\n): { entry: ItineraryMessageCatalogEntry; text: string } | undefined {\n for (const message of messages) {\n if (typeof message.text !== 'string') continue;\n const text = message.text.toLowerCase();\n const entry = catalog.find((candidate) => text.includes(candidate.code.toLowerCase()));\n if (entry !== undefined) return { entry, text: message.text };\n }\n return undefined;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n","// Request crudo que mandó el SDK, por operación. Ver\n// sabre-wiki/wiki/proyectos/sabre-client/decisiones/request-crudo.md (ADR-029).\nimport type { SabreRawResponseCallback } from './raw-response.js';\n\n/**\n * Lo que el SDK mandó por la red en el último intento de una operación.\n *\n * ⚠️ El `body` y la `url` traen datos de pasajeros (PII): localizadores, nombres, contactos. El\n * SDK nunca los envía al logger; quien usa `onRawRequest` responde por dónde los guarda.\n */\nexport interface SabreRawRequest {\n /** El mismo valor que en `onRawResponse`, p. ej. `'booking.get'` o `'queue.access'`. */\n operation: string;\n protocol: 'rest' | 'soap';\n /** `'GET'`, `'POST'`… En SOAP, siempre `'POST'`. */\n method: string;\n /** URL completa, con query string. */\n url: string;\n /** Los headers que se mandaron, sin `Authorization` (se quita el header entero). */\n headers: Headers;\n /**\n * El texto que se mandó, o `undefined` si el request no llevaba body. En REST va tal cual. En\n * SOAP es el sobre completo, con una sola modificación: el valor de cada `BinarySecurityToken`\n * va como `[REDACTED]`.\n */\n body: string | undefined;\n /** Intentos que llegaron a llamar a `fetch`, contando los reintentos (1 si no hubo). */\n attempts: number;\n}\n\n/**\n * Se llama una sola vez por operación, con el último intento que se mandó, antes de devolver o de\n * lanzar y antes que `onRawResponse`. A diferencia de este, se llama también si ningún intento tuvo\n * respuesta HTTP (fallo de red, `AbortError`). No se llama si la operación lanza antes de mandar\n * nada, ni con las llamadas de auth: el token de OAuth y `SessionCreateRQ` (`openSession`), que\n * llevan credenciales, y `SessionCloseRQ` (`close`).\n *\n * Es síncrono y su retorno se ignora. Si lanza, el SDK lo atrapa, emite\n * `sabre.request.rawRequestHookFailed` al logger (sin el body) y la operación sigue.\n */\nexport type SabreRawRequestCallback = (raw: SabreRawRequest) => void;\n\n/** Lo que se guarda de un intento, hasta entregarlo. */\nexport type RawRequestCapture = Omit<SabreRawRequest, 'operation' | 'protocol' | 'attempts'>;\n\n/** Los headers que se entregan: una copia, sin `Authorization`. */\nexport function rawRequestHeaders(headers: HeadersInit): Headers {\n const copy = new Headers(headers);\n copy.delete('Authorization');\n return copy;\n}\n\n/**\n * Los campos de una operación REST para el transporte: `operation` y los callbacks que haya. Sin\n * callbacks, nada.\n */\nexport function rawHooks(\n options: { onRawResponse?: SabreRawResponseCallback | undefined; onRawRequest?: SabreRawRequestCallback | undefined },\n operation: string,\n): { operation?: string; onRawResponse?: SabreRawResponseCallback; onRawRequest?: SabreRawRequestCallback } {\n const { onRawResponse, onRawRequest } = options;\n if (onRawResponse === undefined && onRawRequest === undefined) return {};\n return {\n operation,\n ...(onRawResponse === undefined ? {} : { onRawResponse }),\n ...(onRawRequest === undefined ? {} : { onRawRequest }),\n };\n}\n","// Bargain Finder Max v5 (`POST /v5/offers/shop`).\n// Ver sabre-wiki/wiki/entities/bargain-finder-max.md.\nimport type { SabreError } from '../errors/index.js';\nimport type { SabreRawResponseCallback } from '../http/raw-response.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport type { RetryOptions } from '../http/retry.js';\nimport {\n denormalizeGroupedItineraryResponse,\n type GroupedItineraryResponse,\n type RawGroupedItineraryResponse,\n} from './grouped-itinerary.js';\nimport { classifyItineraryMessages, type ItineraryMessageCatalogEntry } from './itinerary-messages.js';\nimport type { OtaAirLowFareSearchRq } from './low-fare-search-request.js';\nimport { rawHooks, type SabreRawRequestCallback } from '../http/raw-request.js';\n\nexport const BARGAIN_FINDER_MAX_SERVICE = 'bargainFinderMax';\nconst PATH = '/v5/offers/shop';\n\n/** Body de Bargain Finder Max v5, tal cual lo documenta Sabre. */\nexport interface BargainFinderMaxRequest {\n OTA_AirLowFareSearchRQ: OtaAirLowFareSearchRq;\n}\n\n/** `groupedItineraryResponse` con las referencias ya resueltas. */\nexport type BargainFinderMaxResponse = GroupedItineraryResponse;\n\nexport interface RequestOptions {\n signal?: AbortSignal;\n /** Respuesta cruda del último intento HTTP. El body trae PII: ver `SabreRawResponse`. */\n onRawResponse?: SabreRawResponseCallback;\n /** Request crudo del último intento que se mandó, sin `Authorization`. Trae PII: ver `SabreRawRequest`. */\n onRawRequest?: SabreRawRequestCallback;\n /** Pisa los reintentos del cliente solo para esta request. */\n retry?: Partial<RetryOptions>;\n}\n\n/**\n * Catálogo de errores de BFM (guía oficial de errores). Se compara por substring del\n * `text` porque Sabre agrega detalle variable. Los temporales son reintentables: BFM es\n * una lectura idempotente y Sabre indica reintentar.\n */\nexport const BARGAIN_FINDER_MAX_CATALOG: ReadonlyArray<ItineraryMessageCatalogEntry> = [\n { code: 'No Availability', retryable: false },\n { code: 'NO FLIGHT SCHEDULES FOR QUALIFIERS USED', retryable: false },\n { code: 'Connection reset by peer', retryable: true },\n { code: 'Transmission timeout', retryable: true },\n { code: 'Insufficient resources', retryable: true },\n { code: 'MAX NBR COMBINATIONS EXCEEDED', retryable: true },\n];\n\nexport async function bargainFinderMax(\n transport: RestTransport,\n request: BargainFinderMaxRequest,\n options: RequestOptions = {},\n): Promise<BargainFinderMaxResponse> {\n if (typeof request !== 'object' || request === null || typeof request.OTA_AirLowFareSearchRQ !== 'object') {\n throw new TypeError('sabre-client: bargainFinderMax espera { OTA_AirLowFareSearchRQ: { ... } }');\n }\n const body = await transport.request<{ groupedItineraryResponse: RawGroupedItineraryResponse }>({\n method: 'POST',\n path: PATH,\n service: BARGAIN_FINDER_MAX_SERVICE,\n // POST, pero de solo lectura: se puede reintentar sin efectos duplicados.\n idempotent: true,\n body: request,\n classify: classifyBargainFinderMax,\n ...(options.retry === undefined ? {} : { retry: options.retry }),\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'air.bargainFinderMax'),\n });\n return denormalizeGroupedItineraryResponse(body.groupedItineraryResponse, BARGAIN_FINDER_MAX_SERVICE);\n}\n\n/** Ver `classifyItineraryMessages`. */\nexport function classifyBargainFinderMax(body: unknown): SabreError | undefined {\n return classifyItineraryMessages(body, BARGAIN_FINDER_MAX_SERVICE, BARGAIN_FINDER_MAX_CATALOG);\n}\n","// `errors[]` de la Booking Management API: mismo `Error` del spec en Create, Get y Cancel.\n// Ver sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md.\nimport { SabreBusinessError, SabreWarning } from '../errors/index.js';\n\nconst WARNING = 'WARNING';\n\n/** Elemento de `errors[]` tal cual lo manda Sabre (`Error` del spec; los avisos comparten forma). */\nexport interface BookingResponseError {\n /** `BAD_REQUEST`, `APPLICATION_ERROR`, `WARNING`, … */\n category: string;\n /** P. ej. `UNABLE_TO_BOOK_FLIGHTS`. */\n type: string;\n description?: string;\n fieldPath?: string;\n fieldName?: string;\n /** Puede traer datos del request (p. ej. un email): no se copia a los errores del SDK. */\n fieldValue?: string;\n}\n\nexport function responseErrors(response: { errors?: BookingResponseError[] }): BookingResponseError[] {\n return Array.isArray(response.errors) ? response.errors.filter(isObject) as BookingResponseError[] : [];\n}\n\nexport function isWarning(item: BookingResponseError): boolean {\n return typeof item.category === 'string' && item.category.toUpperCase() === WARNING;\n}\n\nexport function toWarning(service: string, item: BookingResponseError): SabreWarning {\n return new SabreWarning(messageOf(service, item), { service, code: codeOf(item), raw: item });\n}\n\nexport interface BusinessErrorAttachments {\n warnings?: SabreWarning[];\n errors?: SabreBusinessError[];\n retryable?: boolean;\n}\n\nexport function toBusinessError(\n service: string,\n item: BookingResponseError,\n { warnings = [], errors = [], retryable = false }: BusinessErrorAttachments = {},\n): SabreBusinessError {\n return new SabreBusinessError(messageOf(service, item), {\n service,\n code: codeOf(item),\n raw: item,\n warnings,\n errors,\n retryable,\n });\n}\n\nexport function codeOf(item: BookingResponseError): string {\n return typeof item.type === 'string' && item.type !== '' ? item.type : String(item.category);\n}\n\n/** Sin `fieldValue`, que puede traer datos del pasajero; queda en `raw`. */\nfunction messageOf(service: string, item: BookingResponseError): string {\n const where = typeof item.fieldPath === 'string' && item.fieldPath !== '' ? ` en ${item.fieldPath}` : '';\n const description = typeof item.description === 'string' && item.description !== '' ? `: ${item.description}` : '';\n return `${service}: ${String(item.category)} ${codeOf(item)}${where}${description}`;\n}\n\nexport function nonEmpty(value: unknown): value is string {\n return typeof value === 'string' && value !== '';\n}\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n","// Get Seats v3 (`POST /v3/offers/getseats/...`).\n// Ver sabre-wiki/wiki/entities/get-seats.md y sabre-wiki/wiki/sdk/get-seats-en-el-sdk.md.\nimport { isObject, nonEmpty, toBusinessError, toWarning } from '../booking/booking-errors.js';\nimport { type SabreBusinessError, SabreError, type SabreWarning } from '../errors/index.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport type { RequestOptions } from './bargain-finder-max.js';\nimport { rawHooks } from '../http/raw-request.js';\n\n/** `service` de errores y logs; distinto por endpoint para que no quede oculto (ADR, opción C). */\nexport const GET_SEATS_BY_PAYLOAD_SERVICE = 'getSeatsByPayload';\nconst BY_PAYLOAD_PATH = '/v3/offers/getseats/byReservationPayload';\nexport const GET_SEATS_BY_PNR_LOCATOR_SERVICE = 'getSeatsByPnrLocator';\nconst BY_PNR_LOCATOR_PATH = '/v3/offers/getseats/byPnrLocator';\n/** Campos del payload que no pueden ir junto con `pnrLocator`. */\nconst PAYLOAD_FIELDS = ['segments', 'passengers', 'returnSeatMapsOnlyForSegmentRefs'] as const;\n\n// ─── Request ────────────────────────────────────────────────────────────────\n\n/** `KeyValuePair` del spec. */\nexport interface SeatKeyValuePair {\n key: string;\n value: string;\n}\n\n/** `LoyaltyProgramAccount` del spec. */\nexport interface SeatLoyaltyProgramAccount {\n airlineCode?: string;\n accountNumber?: string;\n programName?: string;\n}\n\n/** `SegmentBase` del spec. Fechas `YYYY-MM-DD` y horas `HH:MM`, locales del aeropuerto. */\nexport interface SeatSegment {\n /** Identifica el segmento dentro del mensaje (`IdType`: `^[a-zA-Z_][a-zA-Z0-9_\\-.]*$`). */\n id: string;\n bookingAirlineCode: string;\n bookingFlightNumber: number;\n departureAirportCode: string;\n arrivalAirportCode: string;\n departureDate: string;\n bookingClassCode: string;\n departureTime?: string;\n arrivalDate?: string;\n arrivalTime?: string;\n operatingAirlineCode?: string;\n operatingFlightNumber?: number;\n operatingBookingClassCode?: string;\n cabinCode?: string;\n}\n\n/** `SegmentPayloadRq` del spec. */\nexport interface SeatSegmentPayloadRq extends SeatSegment {\n /** Si el segmento tiene el tag `/RCRQ`. */\n hasRecordCreateTag?: boolean;\n}\n\n/** `FareSegmentAssociation` del spec. */\nexport interface SeatFareSegmentAssociation {\n segmentRef: string;\n fareComponentRef: string;\n}\n\n/** `SpecialServiceRequest` del spec. */\nexport interface SeatSpecialServiceRequest {\n codes: string[];\n segmentRef?: string;\n}\n\n/** `PassengerBase` del spec. */\nexport interface SeatPassenger {\n id: string;\n passengerType?: string;\n givenName?: string;\n surname?: string;\n loyaltyProgramAccounts?: SeatLoyaltyProgramAccount[];\n}\n\n/** `PassengerPayloadRq` del spec. */\nexport interface SeatPassengerPayloadRq extends SeatPassenger {\n fareSegmentAssociation?: SeatFareSegmentAssociation[];\n specialServiceRequests?: SeatSpecialServiceRequest[];\n /** Pasajero con un infante sin asiento. Por defecto `false`. */\n isAccompaniedByInfant?: boolean;\n customAttributes?: SeatKeyValuePair[];\n}\n\n/** `FareDetail` del spec. */\nexport interface SeatFareDetail {\n fareType?: string;\n fareTariff?: string;\n fareRule?: string;\n fareIndicator?: number;\n fareTypeBitmap?: string;\n hasPrivateTariff?: boolean;\n}\n\n/** `FareComponent` del spec. */\nexport interface SeatFareComponent {\n fareComponentId: string;\n fareBasis: string;\n governingCarrier?: string;\n /** Número como string, p. ej. `'500.00'`. Exige `totalPriceCurrencyCode`. */\n totalPrice?: string;\n totalPriceCurrencyCode?: string;\n brandCode?: string;\n fareDetail?: SeatFareDetail;\n}\n\n/** `SeatAvailabilityByPayloadRq` del spec 3.0: la reserva armada a mano. */\nexport interface SeatAvailabilityByPayloadRq {\n /** `id` de los segmentos para los que se piden mapas. */\n returnSeatMapsOnlyForSegmentRefs: string[];\n segments: SeatSegmentPayloadRq[];\n passengers: SeatPassengerPayloadRq[];\n returnSeatOffersOnlyForPassengerRefs?: string[];\n fareComponents?: SeatFareComponent[];\n /** ISO 4217. Si falta, Sabre la elige según otros factores. */\n currencyCode?: string;\n /** `true`: mapa de check-in; `false`: mapa de reserva. */\n isCheckinMode?: boolean;\n customAttributes?: SeatKeyValuePair[];\n}\n\n/**\n * `SeatAvailabilityByPnrLocatorRq` del spec 3.0: un PNR ya creado. Sabre lo lee sin estado,\n * así que no ve los cambios sin confirmar.\n */\nexport interface SeatAvailabilityByPnrLocatorRq {\n /** Localizador del PNR (`^[A-Z]{6}$`). */\n pnrLocator: string;\n /** IDs de segmento del PNR para los que se piden mapas. */\n returnSeatMapsOnlyForSegmentIds?: string[];\n /** Name reference numbers del PNR, p. ej. `'01.01'`. */\n returnSeatOffersOnlyForPassengerNameReferenceNumbers?: string[];\n currencyCode?: string;\n isCheckinMode?: boolean;\n customAttributes?: SeatKeyValuePair[];\n}\n\n/** Entrada de `sabre.air.getSeats`: con `pnrLocator` va a `byPnrLocator`; sin él, a `byReservationPayload`. */\nexport type GetSeatsRequest = SeatAvailabilityByPayloadRq | SeatAvailabilityByPnrLocatorRq;\n\n// ─── Response ───────────────────────────────────────────────────────────────\n\n/** `FlightLeg` del spec. */\nexport interface SeatFlightLeg {\n id: string;\n departureAirportCode: string;\n arrivalAirportCode: string;\n departureScheduledDateTime?: string;\n aircraftCode?: string;\n}\n\n/** `SegmentRs` del spec. */\nexport interface SeatSegmentRs extends SeatSegment {\n isChangeOfGauge?: boolean;\n flightLegs?: SeatFlightLeg[];\n /**\n * El segmento en la reserva (p. ej. `\"10\"`). Coincide con `flights[].itemId` y\n * `allSegments[].id` de Get Booking, así que sirve para cruzar el mapa con la reserva. No está en\n * el spec 3.0: llega en `byPnrLocator` (CERT, 2026-11-04, sabre-playground #11).\n */\n reservationSegmentId?: string;\n}\n\n/** `PassengerRs` del spec. */\nexport type SeatPassengerRs = SeatPassenger;\n\n/** `TaxType` del spec. */\nexport interface SeatTax {\n taxAmount?: number | string;\n taxCode?: string;\n description?: string;\n}\n\n/**\n * `PriceBreakdown` del spec, en la moneda del `PriceDefinition`. El spec dice string, pero en\n * producción los importes llegaron como número (`1200`, 2026-10-31): se acepta cualquiera.\n */\nexport interface SeatPriceBreakdown {\n /** Con impuestos. */\n amount: number | string;\n amountWithoutTaxes?: number | string;\n taxesTotal?: number | string;\n taxes?: SeatTax[];\n isTaxExempt?: boolean;\n}\n\n/** `PriceDefinition` del spec. */\nexport interface SeatPriceDefinition {\n id: string;\n currencyCode: string;\n totalPrice: SeatPriceBreakdown;\n referenceBasePrice?: SeatPriceBreakdown;\n}\n\n/** `OfferItemDetails` del spec. */\nexport interface SeatOfferItemDetails {\n serviceDefinitionRef: string;\n /** `id` de un `PriceDefinition` del mismo mensaje: ahí está el precio del asiento. */\n priceDefinitionRef?: string;\n segmentRefs: string[];\n passengerRefs: string[];\n refundableReissuableIndicator?: 'Yes' | 'No' | 'Reuse';\n isInterlineable?: boolean;\n sectorPortionIndicator?: 'Sector' | 'Portion' | 'Journey';\n feeApplicationMethod?: string;\n purchaseByDateTime?: string;\n annotations?: SeatKeyValuePair[];\n}\n\n/** `OfferItem` del spec: ítem reservable asignado a asientos. */\nexport interface SeatOfferItem extends SeatOfferItemDetails {\n id: string;\n}\n\n/** `DisplayOnlyItem` del spec: ítem solo informativo. */\nexport interface SeatDisplayOnlyItem extends SeatOfferItemDetails {\n id: string;\n displayOnlyReason?: 'Unavailable' | 'Unable To Book' | 'Restricted' | 'Unknown';\n displayOnlySource?: string;\n displayOnlyReasonDetails?: SeatKeyValuePair[];\n}\n\n/** `ServiceDefinition` del spec. */\nexport interface SeatServiceDefinition {\n id: string;\n serviceCode?: string;\n airlineCode?: string;\n commercialName?: string;\n /** Group code de ATPCO. */\n groupCode?: string;\n emdType?: 'Standalone' | 'Flight Coupon Associated' | 'Standalone Ticket Associated' | 'Other Than Emd' | 'Eticket';\n emdTypeCode?: number;\n specialServiceCode?: string;\n reasonForIssuance?: string;\n reasonForIssuanceCode?: string;\n isCommissionable?: boolean;\n isFeeGuaranteed?: boolean;\n}\n\n/** `SeatCharacteristic` / `RowCharacteristic` del spec (PADIS 9825). */\nexport interface SeatCharacteristic {\n code: string;\n description?: string;\n}\n\n/** `SeatType` del spec. El número de asiento es `row` de la fila más `column`. */\nexport interface Seat {\n column: string;\n /** PADIS 9865: `F` libre, `O` ocupado, … */\n occupationStatusCode?: string;\n characteristics?: SeatCharacteristic[];\n isOperative?: boolean;\n /** Ítems reservables (`offerItems[].id`) del asiento. */\n offerItemRefIds?: string[];\n /** Ítems solo informativos (`displayOnlyItems[].id`) del asiento. */\n displayOnlyItemRefIds?: string[];\n}\n\n/** `SeatRow` del spec. */\nexport interface SeatRow {\n row: number;\n characteristics?: SeatCharacteristic[];\n seats: Seat[];\n}\n\n/** `CabinLayoutRowPosition` del spec. */\nexport interface SeatCabinRowPosition {\n firstRow: number;\n lastRow: number;\n}\n\n/** `Facility` del spec. */\nexport interface SeatCabinFacility {\n firstRow: number;\n lastRow: number;\n columnIds?: string[];\n orientationCode: string;\n positionCodes: string[];\n facilityTypeCode: string;\n}\n\n/**\n * Un pasillo de la cabina: entre qué filas está y entre qué columnas (p. ej. `leftFromColumn: \"D\"`,\n * `rightFromColumn: \"C\"`). No está en el spec 3.0: llega en `byPnrLocator` y en\n * `byReservationPayload`, en CERT y en producción.\n */\nexport interface SeatCabinAisle {\n firstRow: number;\n lastRow: number;\n leftFromColumn: string;\n rightFromColumn: string;\n}\n\n/** `CabinLayoutType` del spec, más `aisles`, que el spec no trae. */\nexport interface SeatCabinLayout {\n columns: Array<{ id: string; position?: string[] }>;\n rows: SeatCabinRowPosition;\n wingRowPosition?: SeatCabinRowPosition[];\n exitRowPosition?: SeatCabinRowPosition[];\n seatCount?: number;\n authorizedSeatCount?: number;\n missingRowNumbers?: number[];\n missingSeats?: string[];\n facilities?: SeatCabinFacility[];\n deckCode?: string;\n /** Los pasillos. No está en el spec 3.0 (ver `SeatCabinAisle`). */\n aisles?: SeatCabinAisle[];\n}\n\n/** `CabinCompartment` del spec. */\nexport interface SeatCabinCompartment {\n firstRow?: number;\n lastRow?: number;\n columnIds?: string[];\n cabinCode?: string;\n cabinName?: string;\n cabinLayout?: SeatCabinLayout;\n seatRows?: SeatRow[];\n}\n\n/** `SeatMap` del spec. */\nexport interface SeatMap {\n /** `id` del segmento, del request o de `segments[]` de la respuesta. */\n segmentRef: string;\n /**\n * `id` de un `flightLegs[]` del segmento. En un vuelo directo, `byPnrLocator` lo manda como\n * `null` y `byReservationPayload` no lo manda (CERT, 2026-11-04, sabre-playground #11).\n */\n flightLegRef?: string | null;\n cabinCompartments?: SeatCabinCompartment[];\n}\n\n/** `SeatAvailabilityResponse` del spec 3.0. */\nexport interface SeatAvailabilityResponse {\n /** Solo lo usa `seatOffers` (NDC); por ATPCO el asiento se reserva por número. */\n offerId?: string;\n offerExpirationDateTime?: string;\n segments: SeatSegmentRs[];\n passengers: SeatPassengerRs[];\n serviceDefinitions: SeatServiceDefinition[];\n priceDefinitions?: SeatPriceDefinition[];\n offerItems: SeatOfferItem[];\n displayOnlyItems?: SeatDisplayOnlyItem[];\n seatMaps: SeatMap[];\n}\n\n/** `Error` / `Warning` del spec: la misma forma que los de Booking Management. */\nexport interface SeatAvailabilityIssue {\n category: string;\n type: string;\n description?: string;\n fieldName?: string;\n fieldPath?: string;\n /** Puede traer datos del request: no se copia a los errores del SDK. */\n fieldValue?: string;\n}\n\n/** `SeatAvailabilityRs` tal cual llega de Sabre. */\nexport interface RawSeatAvailabilityRs {\n response?: SeatAvailabilityResponse;\n errors?: SeatAvailabilityIssue[];\n warnings?: SeatAvailabilityIssue[];\n}\n\n/**\n * Resultado de `sabre.air.getSeats`: el `SeatAvailabilityRs` del spec con `errors[]` y\n * `warnings[]` reemplazados por los del SDK.\n */\nexport interface GetSeatsResponse {\n response: SeatAvailabilityResponse;\n /** `warnings[]` de Sabre. Nunca se lanzan. */\n warnings: SabreWarning[];\n /** `errors[]` que llegaron junto con un `response`: el mapa existe, pero puede faltar algo. */\n errors: SabreBusinessError[];\n}\n\n// ─── Operación ──────────────────────────────────────────────────────────────\n\n/**\n * Get Seats: una sola función que elige el endpoint según si el request trae `pnrLocator`\n * (opción C de sabre-wiki/wiki/sdk/get-seats-en-el-sdk.md). Lectura: se puede reintentar.\n */\nexport async function getSeats(\n transport: RestTransport,\n request: GetSeatsRequest,\n options: RequestOptions = {},\n): Promise<GetSeatsResponse> {\n if (!isObject(request)) {\n throw new TypeError('sabre-client: air.getSeats espera un objeto');\n }\n if ('pnrLocator' in request) {\n // Una mezcla nunca cae en silencio en un endpoint (ADR, opción C).\n if (!nonEmpty(request.pnrLocator)) {\n throw new TypeError('sabre-client: air.getSeats con pnrLocator vacío');\n }\n const mixed = PAYLOAD_FIELDS.filter((field) => field in request);\n if (mixed.length > 0) {\n throw new TypeError(`sabre-client: air.getSeats con pnrLocator no acepta ${mixed.join(', ')}`);\n }\n return send(transport, BY_PNR_LOCATOR_PATH, GET_SEATS_BY_PNR_LOCATOR_SERVICE, request, options);\n }\n if (!Array.isArray(request.segments) || !Array.isArray(request.passengers)) {\n throw new TypeError('sabre-client: air.getSeats espera { segments: [...], passengers: [...], ... } o { pnrLocator }');\n }\n return send(transport, BY_PAYLOAD_PATH, GET_SEATS_BY_PAYLOAD_SERVICE, request, options);\n}\n\nasync function send(\n transport: RestTransport,\n path: string,\n service: string,\n request: GetSeatsRequest,\n options: RequestOptions,\n): Promise<GetSeatsResponse> {\n const body = await transport.request<RawSeatAvailabilityRs>({\n method: 'POST',\n path,\n service,\n idempotent: true,\n body: request,\n classify: (raw) => classifyGetSeats(raw, service),\n ...(options.retry === undefined ? {} : { retry: options.retry }),\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, `air.${service}`),\n });\n return {\n response: body.response!,\n warnings: issues(body.warnings).map((item) => toWarning(service, item)),\n errors: issues(body.errors).map((item) => toBusinessError(service, item)),\n };\n}\n\n/**\n * Paso 3 del orden de detección, con la política para servicios sin catálogo\n * (sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md): lo que decide si se lanza es si hay\n * `response`.\n *\n * - Hay `response`: no hay error; `errors[]` y `warnings[]` van adjuntos al resultado.\n * - No hay `response`: `SabreBusinessError` con el primer elemento de `errors[]`, y el resto\n * de los errores y los `warnings[]` adjuntos. Sin catálogo, nada es reintentable.\n */\nexport function classifyGetSeats(body: unknown, service: string): SabreError | undefined {\n if (!isObject(body)) {\n return new SabreError(`${service}: respuesta malformada, se esperaba un objeto`, { retryable: false, raw: body });\n }\n const rs = body as RawSeatAvailabilityRs;\n if (isObject(rs.response)) return undefined;\n\n const [first, ...rest] = issues(rs.errors);\n if (first !== undefined) {\n return toBusinessError(service, first, {\n warnings: issues(rs.warnings).map((item) => toWarning(service, item)),\n errors: rest.map((item) => toBusinessError(service, item)),\n });\n }\n return new SabreError(`${service}: respuesta malformada, sin response ni errors`, { retryable: false, raw: body });\n}\n\nfunction issues(list: SeatAvailabilityIssue[] | undefined): SeatAvailabilityIssue[] {\n return Array.isArray(list) ? list.filter(isObject) as SeatAvailabilityIssue[] : [];\n}\n","// Reglas para fijar los vuelos de un itinerario desnormalizado, compartidas por los\n// helpers que arman requests a partir de él (Revalidate Itinerary, Create Booking).\n// Ver sabre-wiki/wiki/concepts/modelo-de-itinerario.md.\nimport type { Itinerary, ItineraryGroup, LegSchedule } from './grouped-itinerary.js';\n\n/** Un vuelo del itinerario con su fecha de salida ya resuelta y su clase de servicio. */\nexport interface ItineraryFlight {\n /** Índice del tramo (`legs[]`) al que pertenece. */\n legIndex: number;\n schedule: LegSchedule;\n /** `YYYY-MM-DD`, hora local del aeropuerto de salida. */\n departureDate: string;\n /** `YYYY-MM-DD`, hora local del aeropuerto de llegada. */\n arrivalDate: string;\n bookingCode: string;\n}\n\n/**\n * Aplana los vuelos del itinerario en orden.\n *\n * - La clase de servicio de cada vuelo sale de `fareComponents[].segments[].bookingCode` del\n * primer pasajero de la primera cotización, en el orden de los vuelos del itinerario.\n * - Las fechas salen de `legDescriptions[].departureDate` más `departureDateAdjustment` del\n * schedule (salida) y `arrival.dateAdjustment` (llegada).\n */\nexport function itineraryFlights(group: ItineraryGroup, itinerary: Itinerary): ItineraryFlight[] {\n const { legDescriptions } = group.groupDescription;\n if (legDescriptions.length !== itinerary.legs.length) {\n throw new TypeError(\n `sabre-client: el itinerario tiene ${itinerary.legs.length} tramos y el grupo ${legDescriptions.length}`,\n );\n }\n const classes = bookingCodes(itinerary);\n const flightCount = itinerary.legs.reduce((n, leg) => n + leg.schedules.length, 0);\n if (classes.length !== flightCount) {\n throw new TypeError(\n `sabre-client: el itinerario tiene ${flightCount} vuelos y ${classes.length} clases de servicio en fareComponents`,\n );\n }\n\n let next = 0;\n return itinerary.legs.flatMap((leg, legIndex) => {\n const legDate = legDescriptions[legIndex]!.departureDate;\n return leg.schedules.map((schedule) => {\n const departureDate = addDays(legDate, schedule.departureDateAdjustment ?? 0);\n return {\n legIndex,\n schedule,\n departureDate,\n arrivalDate: addDays(departureDate, schedule.arrival.dateAdjustment ?? 0),\n bookingCode: classes[next++]!,\n };\n });\n });\n}\n\nfunction bookingCodes(itinerary: Itinerary): string[] {\n const passenger = itinerary.pricingInformation[0]?.fare.passengerInfoList[0]?.passengerInfo;\n return (passenger?.fareComponents ?? []).flatMap((component) =>\n (component.segments ?? []).map(({ segment }) => {\n if (segment.bookingCode === undefined) {\n throw new TypeError('sabre-client: un segmento de fareComponents no trae bookingCode');\n }\n return segment.bookingCode;\n }),\n );\n}\n\n/** `2026-09-11` + n días, en calendario puro (sin zona horaria). */\nfunction addDays(date: string, days: number): string {\n if (days === 0) return date;\n const [year, month, day] = date.split('-').map(Number) as [number, number, number];\n return new Date(Date.UTC(year, month - 1, day + days)).toISOString().slice(0, 10);\n}\n","// Revalidate Itinerary v5 (`POST /v5/shop/flights/revalidate`).\n// Ver sabre-wiki/wiki/entities/revalidate-itinerary.md.\nimport type { SabreError } from '../errors/index.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport { BARGAIN_FINDER_MAX_CATALOG, type BargainFinderMaxRequest, type RequestOptions } from './bargain-finder-max.js';\nimport {\n denormalizeGroupedItineraryResponse,\n type GroupedItineraryResponse,\n type Itinerary,\n type ItineraryGroup,\n type RawGroupedItineraryResponse,\n} from './grouped-itinerary.js';\nimport { type ItineraryFlight, itineraryFlights } from './itinerary-flights.js';\nimport { classifyItineraryMessages, type ItineraryMessageCatalogEntry } from './itinerary-messages.js';\nimport type {\n LowFareSearchFlight,\n LowFareSearchOriginDestination,\n OtaAirLowFareSearchRq,\n} from './low-fare-search-request.js';\nimport { rawHooks } from '../http/raw-request.js';\n\nexport const REVALIDATE_ITINERARY_SERVICE = 'revalidateItinerary';\nconst PATH = '/v5/shop/flights/revalidate';\n\n/** Body de Revalidate Itinerary v5: el mismo `OTA_AirLowFareSearchRQ` que BFM, con los vuelos fijados. */\nexport interface RevalidateItineraryRequest {\n OTA_AirLowFareSearchRQ: OtaAirLowFareSearchRq;\n}\n\n/** `groupedItineraryResponse` con las referencias ya resueltas. */\nexport type RevalidateItineraryResponse = GroupedItineraryResponse;\n\nexport async function revalidateItinerary(\n transport: RestTransport,\n request: RevalidateItineraryRequest,\n options: RequestOptions = {},\n): Promise<RevalidateItineraryResponse> {\n if (typeof request !== 'object' || request === null || typeof request.OTA_AirLowFareSearchRQ !== 'object') {\n throw new TypeError('sabre-client: revalidateItinerary espera { OTA_AirLowFareSearchRQ: { ... } }');\n }\n const body = await transport.request<{ groupedItineraryResponse: RawGroupedItineraryResponse }>({\n method: 'POST',\n path: PATH,\n service: REVALIDATE_ITINERARY_SERVICE,\n // POST, pero de solo lectura: no sostiene inventario, se puede reintentar.\n idempotent: true,\n body: request,\n classify: classifyRevalidateItinerary,\n ...(options.retry === undefined ? {} : { retry: options.retry }),\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'air.revalidateItinerary'),\n });\n return denormalizeGroupedItineraryResponse(body.groupedItineraryResponse, REVALIDATE_ITINERARY_SERVICE);\n}\n\n/**\n * Catálogo de errores de Revalidate (guía oficial de errores de Revalidate Itinerary, en la\n * documentación SOAP de BFM 7.2.0; ver sabre-wiki/wiki/entities/revalidate-itinerary.md).\n * Las cinco condiciones describen un dato que no existe (tarifa, horario o disponibilidad):\n * reintentar no cambia el resultado. En producción, `NO FARE FOR CLASS USED` llegó con\n * `code: 'PROCESS'`; el catálogo le da un `code` estable.\n *\n * Los temporales se heredan de BFM (mismo motor), con `retryable: true`.\n */\nexport const REVALIDATE_ITINERARY_CATALOG: ReadonlyArray<ItineraryMessageCatalogEntry> = [\n { code: 'NO COMBINABLE FARES FOR CLASS USED', retryable: false },\n { code: 'NO FARE FOR CLASS USED', retryable: false },\n { code: 'NO FLIGHT SCHEDULES FOR QUALIFIERS USED', retryable: false },\n { code: 'NO SUCH FLIGHT', retryable: false },\n { code: 'NO AVAILABILITY', retryable: false },\n ...BARGAIN_FINDER_MAX_CATALOG.filter((entry) => entry.retryable),\n];\n\n/** Ver `classifyItineraryMessages`. */\nexport function classifyRevalidateItinerary(body: unknown): SabreError | undefined {\n return classifyItineraryMessages(body, REVALIDATE_ITINERARY_SERVICE, REVALIDATE_ITINERARY_CATALOG);\n}\n\nexport interface RevalidateItineraryRequestSource {\n /** Request de BFM que produjo el itinerario: aporta `Version`, `POS`, pasajeros y `TPA_Extensions`. */\n search: BargainFinderMaxRequest;\n /** Grupo del itinerario: aporta la fecha de cada tramo. */\n group: ItineraryGroup;\n itinerary: Itinerary;\n}\n\n/**\n * Arma el request de Revalidate Itinerary para un itinerario devuelto por BFM, fijando cada\n * vuelo en `OriginDestinationInformation[].TPA_Extensions.Flight[]`.\n *\n * - Clases de servicio y fechas: ver `itineraryFlights`. Las horas salen de `time` sin el offset.\n * - `MaxStopsQuantity` es el máximo de conexiones de un tramo, para no rechazar itinerarios\n * con escala.\n * - `Fixed: false` y `VerificationItinCallLogic: \"L\"` se copian del ejemplo de Sabre; su\n * efecto no está documentado.\n */\nexport function buildRevalidateItineraryRequest(source: RevalidateItineraryRequestSource): RevalidateItineraryRequest {\n const { search, group, itinerary } = source;\n const flights = itineraryFlights(group, itinerary);\n\n const originDestinations = itinerary.legs.map((_leg, i): LowFareSearchOriginDestination => {\n const legFlights = flights.filter((f) => f.legIndex === i).map(flight);\n const first = legFlights[0]!;\n const last = legFlights.at(-1)!;\n return {\n Fixed: false,\n DepartureDateTime: first.DepartureDateTime,\n OriginLocation: { LocationCode: first.OriginLocation.LocationCode },\n DestinationLocation: { LocationCode: last.DestinationLocation.LocationCode },\n TPA_Extensions: { Flight: legFlights },\n };\n });\n\n const { Version, POS, TravelerInfoSummary, TPA_Extensions } = search.OTA_AirLowFareSearchRQ;\n return {\n OTA_AirLowFareSearchRQ: {\n Version,\n POS,\n OriginDestinationInformation: originDestinations,\n TravelPreferences: {\n MaxStopsQuantity: Math.max(...itinerary.legs.map((leg) => leg.schedules.length - 1)),\n TPA_Extensions: { VerificationItinCallLogic: { Value: 'L' } },\n },\n TravelerInfoSummary,\n ...(TPA_Extensions === undefined ? {} : { TPA_Extensions }),\n },\n };\n}\n\nfunction flight({ schedule, departureDate, arrivalDate, bookingCode }: ItineraryFlight): LowFareSearchFlight {\n const { carrier } = schedule;\n return {\n Type: 'A',\n Number: carrier.marketingFlightNumber,\n DepartureDateTime: `${departureDate}T${localTime(schedule.departure.time)}`,\n ArrivalDateTime: `${arrivalDate}T${localTime(schedule.arrival.time)}`,\n ClassOfService: bookingCode,\n OriginLocation: { LocationCode: schedule.departure.airport },\n DestinationLocation: { LocationCode: schedule.arrival.airport },\n Airline: {\n Marketing: carrier.marketing,\n ...(carrier.operating === undefined ? {} : { Operating: carrier.operating }),\n },\n };\n}\n\n/** `17:10:00+02:00` → `17:10:00`. */\nfunction localTime(time: string): string {\n return time.slice(0, 8);\n}\n","// Módulo de dominio `sabre.air`. Ver sabre-wiki/wiki/sdk/convenciones-de-nombres-y-versionado.md.\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n bargainFinderMax,\n type BargainFinderMaxRequest,\n type BargainFinderMaxResponse,\n type RequestOptions,\n} from './bargain-finder-max.js';\nimport { getSeats, type GetSeatsRequest, type GetSeatsResponse } from './get-seats.js';\nimport {\n revalidateItinerary,\n type RevalidateItineraryRequest,\n type RevalidateItineraryResponse,\n} from './revalidate-itinerary.js';\n\nexport class Air {\n readonly #transport: RestTransport;\n\n /** @internal Lo construye el cliente `Sabre`. */\n constructor(transport: RestTransport) {\n this.#transport = transport;\n }\n\n /**\n * Bargain Finder Max v5: busca itinerarios de menor precio. Devuelve el\n * `groupedItineraryResponse` con las referencias ya resueltas.\n */\n bargainFinderMax(request: BargainFinderMaxRequest, options?: RequestOptions): Promise<BargainFinderMaxResponse> {\n return bargainFinderMax(this.#transport, request, options);\n }\n\n /**\n * Revalidate Itinerary v5: revalida disponibilidad y precio de un itinerario ya elegido,\n * sin sostener inventario. El request se arma con `buildRevalidateItineraryRequest`.\n */\n revalidateItinerary(\n request: RevalidateItineraryRequest,\n options?: RequestOptions,\n ): Promise<RevalidateItineraryResponse> {\n return revalidateItinerary(this.#transport, request, options);\n }\n\n /**\n * Get Seats v3: mapa de asientos con disponibilidad y precio. Sin `pnrLocator` va a\n * `byReservationPayload`, armado con `buildSeatAvailabilityRequest`; con `pnrLocator`, a\n * `byPnrLocator`. Un `pnrLocator` vacío o mezclado con `segments`, `passengers` o\n * `returnSeatMapsOnlyForSegmentRefs` lanza `TypeError` sin llamar a la red.\n */\n getSeats(request: GetSeatsRequest, options?: RequestOptions): Promise<GetSeatsResponse> {\n return getSeats(this.#transport, request, options);\n }\n}\n","// Redacción obligatoria antes de que cualquier dato llegue al logger.\n// Ver sabre-wiki/wiki/sdk/configuracion-logging-y-build.md.\n\nexport const REDACTED = '[REDACTED]';\n\n/**\n * Claves cuyo valor se enmascara completo, comparadas sin distinguir mayúsculas\n * ni separadores (`client_secret`, `Client-Secret` y `clientSecret` son la misma).\n */\nconst SENSITIVE_KEYS = new Set(\n [\n // Credenciales\n 'clientSecret',\n 'password',\n 'username',\n 'authorization',\n 'binarySecurityToken',\n 'accessToken',\n 'refreshToken',\n 'token',\n // Datos de pasajero\n 'travelers',\n 'passengers',\n ].map(normalizeKey),\n);\n\nfunction normalizeKey(key: string): string {\n return key.replace(/[-_\\s]/g, '').toLowerCase();\n}\n\nexport function isSensitiveKey(key: string): boolean {\n return SENSITIVE_KEYS.has(normalizeKey(key));\n}\n\n/** Copia profunda de `value` con los campos sensibles enmascarados. No muta la entrada. */\nexport function redact(value: unknown): unknown {\n return redactValue(value, new WeakSet());\n}\n\nfunction redactValue(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null || typeof value !== 'object') return value;\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n\n if (Array.isArray(value)) return value.map((item) => redactValue(item, seen));\n if (value instanceof Headers) return redactEntries(value.entries(), seen);\n if (value instanceof Date) return value.toISOString();\n if (value instanceof Error) {\n // Los errores del SDK definen toJSON sin `raw`; para el resto, solo nombre y mensaje.\n const json = 'toJSON' in value && typeof value.toJSON === 'function' ? value.toJSON() : undefined;\n return redactValue(json ?? { name: value.name, message: value.message }, seen);\n }\n return redactEntries(Object.entries(value), seen);\n}\n\nfunction redactEntries(entries: Iterable<[string, unknown]>, seen: WeakSet<object>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, item] of entries) {\n out[key] = isSensitiveKey(key) ? REDACTED : redactValue(item, seen);\n }\n return out;\n}\n\n/**\n * Elemento `BinarySecurityToken` con cualquier prefijo (o ninguno), sin contar el\n * autocerrado. Los atributos admiten valores entre comillas con `>` adentro. El cierre\n * acepta cualquier prefijo: ante un sobre mal formado, conviene tapar de más.\n */\nconst BINARY_SECURITY_TOKEN =\n /(<(?:[A-Za-z_][\\w.-]*:)?BinarySecurityToken(?=[\\s/>])(?:[^>\"']|\"[^\"]*\"|'[^']*')*(?<!\\/)>)([\\s\\S]*?)(<\\/(?:[A-Za-z_][\\w.-]*:)?BinarySecurityToken\\s*>)/g;\n\n/**\n * Reemplaza el valor de cada `BinarySecurityToken` del sobre SOAP por `[REDACTED]`.\n *\n * Trabaja sobre el texto, sin parsear ni volver a serializar: el resto del sobre queda byte\n * a byte (indentación, orden de atributos, prefijos y `eb:MessageHeader`). Un sobre sin\n * token, o con el token vacío, vuelve idéntico. Ver sabre-wiki/wiki/sdk/respuesta-cruda-soap.md\n * (opción D).\n */\nexport function redactSoapEnvelope(envelope: string): string {\n return envelope.replace(BINARY_SECURITY_TOKEN, (match, open: string, value: string, close: string) =>\n value.trim() === '' ? match : `${open}${REDACTED}${close}`,\n );\n}\n","// Logger inyectable. Ver sabre-wiki/wiki/sdk/configuracion-logging-y-build.md.\nimport { redact } from './redact.js';\n\n/**\n * Interfaz mínima de logger, compatible con `winston` y `console`.\n * Con `pino`, que invierte el orden: `info: (m, c) => pino.info(c, m)`.\n */\nexport interface SabreLogger {\n debug(message: string, context?: Record<string, unknown>): void;\n info(message: string, context?: Record<string, unknown>): void;\n warn(message: string, context?: Record<string, unknown>): void;\n error(message: string, context?: Record<string, unknown>): void;\n}\n\nexport type SabreLogLevel = keyof SabreLogger;\n\n/** Eventos estables que emite el SDK como `message`. */\nexport type SabreLogEvent =\n | 'sabre.request.start'\n | 'sabre.request.end'\n | 'sabre.request.retry'\n | 'sabre.request.rawResponseHookFailed'\n | 'sabre.request.rawRequestHookFailed'\n | 'sabre.auth.token.refresh'\n | 'sabre.auth.token.store'\n | 'sabre.booking.seat.priced'\n | 'sabre.session.open'\n | 'sabre.session.close'\n | 'sabre.session.closeFailed'\n | 'sabre.session.keepAliveFailed'\n | 'sabre.session.command'\n | 'sabre.queue.exitTolerated'\n | 'sabre.queue.exitFailed';\n\n/** Logger interno: redacta siempre el contexto y no hace nada si no hay logger. */\nexport class EventLogger {\n readonly #logger: SabreLogger | undefined;\n\n constructor(logger?: SabreLogger) {\n this.#logger = logger;\n }\n\n emit(level: SabreLogLevel, event: SabreLogEvent, context: Record<string, unknown> = {}): void {\n if (this.#logger === undefined) return;\n try {\n this.#logger[level](event, redact(context) as Record<string, unknown>);\n } catch {\n // Un logger que falla no debe romper la request en curso.\n }\n }\n}\n","// Armado de la request de OAuth Token Create, una estrategia por versión.\n// Ver sabre-wiki/wiki/entities/oauth-token-create.md: v2 y v3 no son intercambiables.\nimport type { SabreAuthVersion, SabreCredentials, SabreCredentialsV2 } from '../config.js';\n\nexport interface TokenRequest {\n path: string;\n /** Valor del header `Authorization` (`Basic ...`). */\n authorization: string;\n body: URLSearchParams;\n}\n\n/** v3: `Basic base64(clientId:clientSecret)` y el EPR en el body con `grant_type=password`. */\nexport function buildTokenRequestV3(credentials: SabreCredentials): TokenRequest {\n return {\n path: '/v3/auth/token',\n authorization: `Basic ${base64(`${credentials.clientId}:${credentials.clientSecret}`)}`,\n body: new URLSearchParams({\n grant_type: 'password',\n username: credentials.username,\n password: credentials.password,\n }),\n };\n}\n\n/** v2: doble Base64 sobre el EPR y su password, con `grant_type=client_credentials`. */\nexport function buildTokenRequestV2(credentials: SabreCredentialsV2): TokenRequest {\n return {\n path: '/v2/auth/token',\n authorization: `Basic ${base64(`${base64(credentials.username)}:${base64(credentials.password)}`)}`,\n body: new URLSearchParams({ grant_type: 'client_credentials' }),\n };\n}\n\nexport function buildTokenRequest(\n authVersion: SabreAuthVersion,\n credentials: SabreCredentials | SabreCredentialsV2,\n): TokenRequest {\n // `resolveConfig` ya exige clientId/clientSecret cuando la versión es v3.\n return authVersion === 'v3'\n ? buildTokenRequestV3(credentials as SabreCredentials)\n : buildTokenRequestV2(credentials as SabreCredentialsV2);\n}\n\n/** Base64 de los bytes UTF-8 de `text`, solo con Web APIs (sin `Buffer`). */\nexport function base64(text: string): string {\n let binary = '';\n for (const byte of new TextEncoder().encode(text)) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n","// Almacén de token inyectable por el consumidor. Ver sabre-wiki/wiki/sdk/renovacion-token-oauth.md,\n// sección \"Decisiones de la Fase 4\" (decisión B).\nimport type { SabreAuthVersion, SabreCredentials, SabreCredentialsV2, SabreEnvironment } from '../config.js';\n\n/** Token ATK tal cual se guarda: tiempos absolutos, para que otro proceso sepa cuánto le queda. */\nexport interface StoredToken {\n accessToken: string;\n /** Momento de obtención, en ms desde epoch. */\n obtainedAt: number;\n /** Momento de expiración, en ms desde epoch. */\n expiresAt: number;\n}\n\n/**\n * Almacén de token del consumidor (archivo, Redis, KV…). El SDK no trae implementaciones.\n *\n * `key` identifica la configuración (entorno, versión de OAuth y credencial, sin secretos):\n * un mismo store puede servir a varios clientes sin mezclar sus tokens. El token es un\n * secreto: protegerlo dentro del store es responsabilidad del consumidor.\n *\n * Si `get` o `set` lanzan, el SDK sigue con su caché en memoria: el store nunca rompe una llamada.\n */\nexport interface SabreTokenStore {\n get(key: string): Promise<StoredToken | undefined>;\n set(key: string, token: StoredToken): Promise<void>;\n}\n\n/**\n * `sabre-client:<environment>:<authVersion>:<hash>`, donde `hash` son los primeros 16 bytes\n * en hex del SHA-256 del username EPR (y del clientId en v3). No contiene secretos.\n */\nexport async function tokenStoreKey(\n environment: SabreEnvironment,\n authVersion: SabreAuthVersion,\n credentials: Readonly<SabreCredentials | SabreCredentialsV2>,\n): Promise<string> {\n const identity = authVersion === 'v3' ? `${credentials.clientId}\\n${credentials.username}` : credentials.username;\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(identity));\n const hash = [...new Uint8Array(digest).slice(0, 16)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n return `sabre-client:${environment}:${authVersion}:${hash}`;\n}\n\n/** Un valor de `get` que no tenga la forma de `StoredToken` se ignora. */\nexport function isStoredToken(value: unknown): value is StoredToken {\n if (typeof value !== 'object' || value === null) return false;\n const { accessToken, obtainedAt, expiresAt } = value as Record<string, unknown>;\n return (\n typeof accessToken === 'string' &&\n accessToken !== '' &&\n typeof obtainedAt === 'number' &&\n typeof expiresAt === 'number' &&\n Number.isFinite(obtainedAt) &&\n expiresAt > obtainedAt\n );\n}\n","// Obtención del token ATK de OAuth Token Create.\n// Ver sabre-wiki/wiki/sdk/renovacion-token-oauth.md y wiki/entities/oauth-token-create.md.\nimport type { ResolvedConfig } from '../config.js';\nimport { SabreGatewayError } from '../errors/index.js';\nimport type { AuthorizationProvider, RestTransport } from '../http/rest-transport.js';\nimport { EventLogger } from '../logging/logger.js';\nimport { buildTokenRequest } from './token-request.js';\nimport { isStoredToken, type SabreTokenStore, type StoredToken, tokenStoreKey } from './token-store.js';\n\nexport const TOKEN_SERVICE = 'oauthTokenCreate';\n\n/** Margen de refresco proactivo: 1 h antes de expirar (o media vida si el token dura menos). */\nexport const REFRESH_THRESHOLD_S = 3600;\n\nexport type TokenRefreshReason = 'initial' | 'proactive' | 'reactive';\n\n/** Token ATK obtenido de OAuth Token Create. */\nexport interface AccessToken {\n accessToken: string;\n /** Vida del token en segundos, tal cual llega en `expires_in`. */\n expiresIn: number;\n /** Momento de obtención, en ms desde epoch. */\n obtainedAt: number;\n}\n\ninterface TokenResponse {\n access_token?: unknown;\n expires_in?: unknown;\n token_type?: unknown;\n}\n\nexport interface AuthManagerOptions {\n /** Solo para tests: reloj en ms. */\n now?: () => number;\n}\n\n/**\n * Cachea el token en memoria (y en `tokenStore`, si lo hay), lo renueva antes de que expire\n * y comparte una sola petición en vuelo entre requests concurrentes. Interno en v0.3.0.\n */\nexport class AuthManager {\n readonly #config: ResolvedConfig;\n readonly #transport: RestTransport;\n readonly #now: () => number;\n readonly #log: EventLogger;\n #token: AccessToken | undefined;\n #inFlight: Promise<AccessToken> | undefined;\n /** El último token cacheado fue rechazado con 401 (el próximo refresco es reactivo). */\n #invalidated = false;\n /** Token rechazado con 401: si el store todavía lo tiene, no se vuelve a usar. */\n #rejected: string | undefined;\n readonly #store: SabreTokenStore | undefined;\n #storeKey: Promise<string> | undefined;\n\n constructor(config: ResolvedConfig, transport: RestTransport, options: AuthManagerOptions = {}) {\n this.#config = config;\n this.#transport = transport;\n this.#now = options.now ?? Date.now;\n this.#log = new EventLogger(config.logger);\n this.#store = config.tokenStore;\n }\n\n /** Token vigente; pide uno nuevo si no hay o si cruzó el umbral de refresco. */\n async getToken(): Promise<string> {\n const token = this.#token;\n if (token !== undefined && !this.#needsRefresh(token)) return token.accessToken;\n const reason = token !== undefined ? 'proactive' : this.#invalidated ? 'reactive' : 'initial';\n return (await this.#refresh(reason)).accessToken;\n }\n\n /**\n * Descarta `accessToken` tras un 401 de un servicio. Si el caché ya tiene otro token\n * (otra request lo renovó), no hace nada: los 401 concurrentes comparten un refresco.\n */\n invalidate(accessToken: string): void {\n if (this.#token?.accessToken !== accessToken) return;\n this.#token = undefined;\n this.#invalidated = true;\n this.#rejected = accessToken;\n }\n\n /** Adaptador de salida para el transporte REST: `Authorization: Bearer <token>`. */\n bearerProvider(): AuthorizationProvider {\n return {\n get: async () => `Bearer ${await this.getToken()}`,\n invalidate: (authorization) => this.invalidate(authorization.replace(/^Bearer /, '')),\n };\n }\n\n #needsRefresh(token: AccessToken): boolean {\n const thresholdMs = Math.min(REFRESH_THRESHOLD_S, token.expiresIn / 2) * 1000;\n return this.#now() >= token.obtainedAt + token.expiresIn * 1000 - thresholdMs;\n }\n\n /** Una sola petición en vuelo: las llamadas concurrentes esperan la misma promesa. */\n #refresh(reason: TokenRefreshReason): Promise<AccessToken> {\n this.#inFlight ??= this.#obtain(reason).finally(() => {\n this.#inFlight = undefined;\n });\n return this.#inFlight;\n }\n\n /** Token del store si sigue vigente (otro proceso pudo renovarlo); si no, uno nuevo. */\n async #obtain(reason: TokenRefreshReason): Promise<AccessToken> {\n const stored = await this.#readStore();\n if (stored !== undefined && stored.accessToken !== this.#rejected && !this.#needsRefresh(stored)) {\n this.#token = stored;\n this.#invalidated = false;\n return stored;\n }\n\n const token = await this.fetchToken();\n this.#token = token;\n this.#invalidated = false;\n this.#rejected = undefined;\n this.#log.emit('info', 'sabre.auth.token.refresh', {\n authVersion: this.#config.authVersion,\n reason,\n expiresIn: token.expiresIn,\n });\n await this.#writeStore(token);\n return token;\n }\n\n async #readStore(): Promise<AccessToken | undefined> {\n if (this.#store === undefined) return undefined;\n try {\n const value = await this.#store.get(await this.#key());\n if (!isStoredToken(value)) return undefined;\n return {\n accessToken: value.accessToken,\n expiresIn: (value.expiresAt - value.obtainedAt) / 1000,\n obtainedAt: value.obtainedAt,\n };\n } catch (error) {\n this.#storeFailed('get', error);\n return undefined;\n }\n }\n\n async #writeStore(token: AccessToken): Promise<void> {\n if (this.#store === undefined) return;\n const stored: StoredToken = {\n accessToken: token.accessToken,\n obtainedAt: token.obtainedAt,\n expiresAt: token.obtainedAt + token.expiresIn * 1000,\n };\n try {\n await this.#store.set(await this.#key(), stored);\n } catch (error) {\n this.#storeFailed('set', error);\n }\n }\n\n #key(): Promise<string> {\n const { environment, authVersion, credentials } = this.#config;\n this.#storeKey ??= tokenStoreKey(environment, authVersion, credentials);\n return this.#storeKey;\n }\n\n /**\n * El store nunca rompe la llamada: se sigue con el caché en memoria. Del error solo se\n * loguea el nombre: el mensaje lo arma el store del consumidor y podría traer el token.\n */\n #storeFailed(operation: 'get' | 'set', error: unknown): void {\n this.#log.emit('warn', 'sabre.auth.token.store', {\n authVersion: this.#config.authVersion,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n\n /**\n * Pide un token nuevo. Los errores del endpoint (`invalid_request`/`invalid_client` 401,\n * `unauthorized` 403) salen como `SabreGatewayError` con `retryable: false`.\n */\n async fetchToken(): Promise<AccessToken> {\n const { path, authorization, body } = buildTokenRequest(this.#config.authVersion, this.#config.credentials);\n const response = await this.#transport.request<TokenResponse | undefined>({\n method: 'POST',\n path,\n service: TOKEN_SERVICE,\n // Pedir otro token no tiene efectos duplicados: 429/5xx entran en la política genérica.\n idempotent: true,\n auth: false,\n headers: { Authorization: authorization },\n body,\n });\n return this.#parse(response);\n }\n\n #parse(response: TokenResponse | undefined): AccessToken {\n const accessToken = response?.access_token;\n const expiresIn = response?.expires_in;\n if (typeof accessToken !== 'string' || accessToken === '' || typeof expiresIn !== 'number' || !(expiresIn > 0)) {\n throw new SabreGatewayError(`${TOKEN_SERVICE}: respuesta sin access_token/expires_in válidos`, {\n protocol: 'rest',\n status: 200,\n retryable: false,\n raw: response,\n });\n }\n return { accessToken, expiresIn, obtainedAt: this.#now() };\n }\n}\n","// Cancel Booking (`POST /v1/trip/orders/cancelBooking`).\n// Ver sabre-wiki/wiki/sdk/gestion-de-reserva.md y sabre-wiki/wiki/sources/cancel-booking.md.\nimport { SabreError, type SabreWarning } from '../errors/index.js';\nimport type { SabreRawResponseCallback } from '../http/raw-response.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n type BookingResponseError,\n isObject,\n isWarning,\n nonEmpty,\n responseErrors,\n toBusinessError,\n toWarning,\n} from './booking-errors.js';\nimport type { Booking } from './create-booking.js';\nimport type { BookingSource } from './get-booking.js';\nimport { rawHooks, type SabreRawRequestCallback } from '../http/raw-request.js';\n\nexport const CANCEL_BOOKING_SERVICE = 'cancelBooking';\nconst PATH = '/v1/trip/orders/cancelBooking';\n/** Llega con `category: WARNING`, pero significa que no se canceló nada (decidido en #39). */\nconst NO_ITEMS_CANCELLED = 'NO_ITEMS_CANCELLED';\nconst ITEM_LISTS = ['flights', 'hotels', 'cars', 'trains', 'cruises', 'segments'] as const;\n\n/** `HALT_ON_ERROR` (default de Sabre, con rollback) o `ALLOW_PARTIAL_CANCEL`. */\nexport type CancelBookingErrorPolicy = 'HALT_ON_ERROR' | 'ALLOW_PARTIAL_CANCEL';\n\nexport type FlightTicketOperation = 'VOID' | 'REFUND';\n\nexport type RefundDocumentsType = 'Tickets' | 'EMDs' | 'Tickets and EMDs';\n\n/** Producto a cancelar, por el `itemId` que devuelve Get Booking (p. ej. `flights[].itemId`). */\nexport interface BookingItemReference {\n itemId: string;\n}\n\n/**\n * Segmento a cancelar, por `id` o por `sequence`. Sabre desaconseja `sequence`: la posición\n * puede cambiar entre la lectura y la cancelación.\n */\nexport interface CancelSegmentReference {\n id?: string;\n sequence?: number;\n}\n\n/** `Notification` del spec: `email` o `queuePlacement`, no los dos. Se envía tal cual. */\nexport interface CancelBookingNotification {\n email?: 'DEFAULT' | 'INVOICE' | 'ETICKET' | 'ETICKET_PDF' | 'ITINERARY' | 'ITINERARY_PDF';\n queuePlacement?: Array<Record<string, unknown>>;\n}\n\n/**\n * `CancelBookingRequest` del spec v1.33. El Tier 1 usa `cancelAll` o `flights[].itemId` sobre\n * contenido ATPCO; los campos de tickets, NDC, impresoras, notificación y retención se envían\n * tal cual, sin lógica propia.\n */\nexport interface CancelBookingRequest {\n /** Localizador del PNR u Order ID (`^[A-Z0-9]{6,}$`). Único campo obligatorio. */\n confirmationId: string;\n bookingSource?: BookingSource;\n /** Cancela todos los segmentos. No se combina con las listas. */\n cancelAll?: boolean;\n flights?: BookingItemReference[];\n hotels?: BookingItemReference[];\n cars?: BookingItemReference[];\n trains?: BookingItemReference[];\n cruises?: BookingItemReference[];\n segments?: CancelSegmentReference[];\n /** Sin valor, Sabre aplica `HALT_ON_ERROR`: si algo falla, deshace lo ya cancelado. */\n errorHandlingPolicy?: CancelBookingErrorPolicy;\n /** Si es `true`, la respuesta trae el estado posterior en `booking`. */\n retrieveBooking?: boolean;\n /** Firma del cambio en el PNR. Sabre usa `LW CANCEL API` por defecto. */\n receivedFrom?: string;\n /** El contexto no se revierte al terminar. */\n targetPcc?: string;\n /** No se combina con `offerItemId`. */\n flightTicketOperation?: FlightTicketOperation;\n /** Solo NDC. No se combina con `flightTicketOperation`. */\n offerItemId?: string;\n notification?: CancelBookingNotification;\n designatePrinters?: Array<Record<string, unknown>>;\n retentionEndDate?: string;\n retentionLabel?: string;\n voidNonElectronicTickets?: boolean;\n refundDocumentsType?: RefundDocumentsType;\n}\n\nexport interface CancelBookingOptions {\n signal?: AbortSignal;\n /** Respuesta cruda del último intento HTTP. El body trae PII: ver `SabreRawResponse`. */\n onRawResponse?: SabreRawResponseCallback;\n /** Request crudo del último intento que se mandó, sin `Authorization`. Trae PII: ver `SabreRawRequest`. */\n onRawRequest?: SabreRawRequestCallback;\n}\n\n/** `CancelBookingResponse` tal cual llega de Sabre. */\nexport interface RawCancelBookingResponse {\n timestamp?: string;\n request?: CancelBookingRequest;\n booking?: Booking;\n tickets?: Array<Record<string, unknown>>;\n voidedTickets?: string[];\n refundedTickets?: string[];\n flightRefunds?: Array<Record<string, unknown>>;\n errors?: BookingResponseError[];\n}\n\n/** Cancelación con éxito: sin errores fatales y sin `NO_ITEMS_CANCELLED`. */\nexport interface CancelBookingResponse {\n timestamp?: string;\n /** Eco del request con los defaults de Sabre completados. */\n request?: CancelBookingRequest;\n /** Estado posterior de la reserva, anidado (solo con `retrieveBooking: true`). */\n booking?: Booking;\n tickets?: Array<Record<string, unknown>>;\n voidedTickets?: string[];\n refundedTickets?: string[];\n flightRefunds?: Array<Record<string, unknown>>;\n /**\n * Elementos de `errors[]` con `category: WARNING`. Con `END_TRANSACTION_PROBLEM` la\n * confirmación quedó pendiente: verifica el resultado con `sabre.booking.get`.\n */\n warnings: SabreWarning[];\n}\n\n/**\n * Cancel Booking: escritura sin reintento automático. Solo el reintento reactivo ante 401,\n * que el gateway rechaza antes de llegar al proveedor.\n */\nexport async function cancelBooking(\n transport: RestTransport,\n request: CancelBookingRequest,\n options: CancelBookingOptions = {},\n): Promise<CancelBookingResponse> {\n validateCancelBookingRequest(request);\n const body = await transport.request<RawCancelBookingResponse>({\n method: 'POST',\n path: PATH,\n service: CANCEL_BOOKING_SERVICE,\n idempotent: false,\n body: request,\n classify: classifyCancelBooking,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'booking.cancel'),\n });\n return toCancelBookingResponse(body);\n}\n\n/** Combinaciones que Sabre rechaza seguro (`INVALID_FLAGS_COMBINATION`, `CANCEL_DATA_MISSING`). */\nfunction validateCancelBookingRequest(request: CancelBookingRequest): void {\n if (!isObject(request) || !nonEmpty(request.confirmationId)) {\n throw new TypeError('sabre-client: booking.cancel espera { confirmationId: string, ... }');\n }\n const lists = ITEM_LISTS.join(', ');\n if (request.cancelAll === true) {\n if (ITEM_LISTS.some((list) => request[list] !== undefined)) {\n throw new TypeError(`sabre-client: booking.cancel no combina cancelAll con listas (${lists})`);\n }\n } else if (!ITEM_LISTS.some((list) => Array.isArray(request[list]) && request[list].length > 0)) {\n throw new TypeError(`sabre-client: booking.cancel necesita cancelAll: true o al menos una lista (${lists})`);\n }\n if (request.offerItemId !== undefined && request.flightTicketOperation !== undefined) {\n throw new TypeError('sabre-client: booking.cancel no combina offerItemId con flightTicketOperation');\n }\n}\n\n/**\n * Paso 3 del orden de detección. Éxito = ningún error que no sea `WARNING` y ningún\n * `NO_ITEMS_CANCELLED`. Si no:\n *\n * - Con `NO_ITEMS_CANCELLED`: `SabreBusinessError` con ese código; los errores que explican\n * el fallo van en `errors` y los demás avisos en `warnings`.\n * - Sin él: `SabreBusinessError` con el primer error que no sea `WARNING`, el resto en\n * `errors` y los avisos en `warnings`.\n */\nexport function classifyCancelBooking(body: unknown): SabreError | undefined {\n if (!isObject(body)) {\n return new SabreError(`${CANCEL_BOOKING_SERVICE}: respuesta malformada, se esperaba un objeto`, {\n retryable: false,\n raw: body,\n });\n }\n const items = responseErrors(body as RawCancelBookingResponse);\n const nothingCancelled = items.find(isNoItemsCancelled);\n const warnings = items.filter((item) => isWarning(item) && !isNoItemsCancelled(item)).map(warningOf);\n const fatal = items.filter((item) => !isWarning(item));\n\n if (nothingCancelled !== undefined) {\n return toBusinessError(CANCEL_BOOKING_SERVICE, nothingCancelled, { warnings, errors: fatal.map(errorOf) });\n }\n const [first, ...rest] = fatal;\n if (first === undefined) return undefined;\n return toBusinessError(CANCEL_BOOKING_SERVICE, first, { warnings, errors: rest.map(errorOf) });\n}\n\n/** Solo para respuestas con éxito (ver `classifyCancelBooking`): `errors[]` trae solo avisos. */\nfunction toCancelBookingResponse(body: RawCancelBookingResponse): CancelBookingResponse {\n const { errors: _errors, ...rest } = body;\n return { ...rest, warnings: responseErrors(body).map(warningOf) };\n}\n\nfunction isNoItemsCancelled(item: BookingResponseError): boolean {\n return item.type === NO_ITEMS_CANCELLED;\n}\n\nfunction warningOf(item: BookingResponseError): SabreWarning {\n return toWarning(CANCEL_BOOKING_SERVICE, item);\n}\n\nfunction errorOf(item: BookingResponseError) {\n return toBusinessError(CANCEL_BOOKING_SERVICE, item);\n}\n","// Armado de `flightDetails` de Create Booking desde un itinerario de BFM/Revalidate.\n// El mapeo está inferido, ninguna fuente lo documenta: ver la tabla \"Mapeo desde un\n// itinerario de BFM/Revalidate → flightDetails\" en sabre-wiki/wiki/entities/booking-management-api.md.\nimport type { GetSeatsResponse } from '../air/get-seats.js';\nimport type { Itinerary, ItineraryGroup } from '../air/grouped-itinerary.js';\nimport { itineraryFlights } from '../air/itinerary-flights.js';\nimport type { FlightDetails, FlightToBook, PassengerPricing, PriceComparison } from './create-booking-request.js';\n\n/** Patrón de `BookGenericSeat.number` en el spec de Booking Management. */\nconst SEAT_NUMBER = /^[0-9]+[A-Z]$/;\n\n/** Asiento elegido para un vuelo del itinerario. */\nexport interface BookingSeatSelection {\n /**\n * Número del vuelo en el itinerario, empezando en 1 (`1` es `flights[0]`). Misma base que\n * `travelerIndex`, para no confundirlos.\n */\n segmentIndex: number;\n /** Número del viajero en `travelers[]` de Create Booking, empezando en 1 (lo fija el spec). */\n travelerIndex: number;\n /** Fila y columna, p. ej. `13A`. */\n number: string;\n}\n\n/** Asiento elegido que tiene precio en Get Seats. Sin datos del pasajero. */\nexport interface PricedSeat {\n /** Empieza en 1, como en `BookingSeatSelection`. */\n segmentIndex: number;\n /** Vuelo comercializador, p. ej. `AA1234`. */\n flight: string;\n seat: string;\n amount: string;\n currencyCode: string;\n}\n\n/**\n * Asientos con precio de cada `FlightDetails` armado por `buildBookingFlightDetails`. El\n * helper es puro y no tiene logger: `booking.create` los busca acá y emite el `warn` con el\n * logger del cliente. Si el objeto se clona, el aviso se pierde; el request no cambia.\n */\nconst pricedSeats = new WeakMap<FlightDetails, PricedSeat[]>();\n\n/** @internal Para `booking.create`. */\nexport function pricedSeatsOf(details: FlightDetails | undefined): PricedSeat[] {\n return details === undefined ? [] : (pricedSeats.get(details) ?? []);\n}\n\nexport interface BookingFlightDetailsSource {\n /** Grupo del itinerario: aporta la fecha de cada tramo. */\n group: ItineraryGroup;\n /** Itinerario elegido, idealmente el devuelto por Revalidate Itinerary. */\n itinerary: Itinerary;\n /**\n * Umbral de precio. `desiredAmount` sale de `totalFare.totalPrice` del itinerario. El spec no\n * tiene campo de moneda: se supone la del pricing (la del PCC, salvo `currencyPricing`).\n */\n priceComparison?: Omit<PriceComparison, 'desiredAmount'>;\n /**\n * Asientos por número, para `flights[segmentIndex - 1].seats[]` (camino ATPCO; `seatOffers` es\n * solo NDC). Conviene elegir asientos sin cargo: no se sabe qué hace Sabre con uno cobrable.\n */\n seats?: BookingSeatSelection[];\n /**\n * Respuesta de `sabre.air.getSeats` para el mismo itinerario. Si un asiento elegido tiene\n * precio ahí, `booking.create` emite `sabre.booking.seat.priced` (`warn`) y reserva igual.\n */\n seatAvailability?: GetSeatsResponse;\n}\n\n/**\n * Arma `flightDetails` para reservar por el camino ATPCO un itinerario ya revalidado.\n *\n * - `flights[]`: vuelo comercializador, aeropuertos, fecha y clase con las mismas reglas que\n * Revalidate (`itineraryFlights`); `departureTime` en `HH:MM` y `flightStatusCode: 'NN'`.\n * `isMarriageGroup` no se manda: no hay fuente para él.\n * - `flightPricing[0].qualifiers`: `passengersPricing` desde `passengerInfoList` y\n * `validatingAirlineCode` desde `validatingCarrierCode` de la primera cotización.\n * - `seats`: se validan sin llamar a Sabre (`number` con el patrón del spec, vuelo y viajero\n * existentes, los dos índices empiezan en 1) y se agregan a `flights[segmentIndex - 1].seats[]`.\n * Sin `seats`, nada cambia.\n */\nexport function buildBookingFlightDetails(source: BookingFlightDetailsSource): FlightDetails {\n const { group, itinerary, priceComparison, seats = [], seatAvailability } = source;\n const flights = itineraryFlights(group, itinerary).map(\n ({ schedule, departureDate, bookingCode }): FlightToBook => ({\n flightNumber: schedule.carrier.marketingFlightNumber,\n airlineCode: schedule.carrier.marketing,\n fromAirportCode: schedule.departure.airport,\n toAirportCode: schedule.arrival.airport,\n departureDate,\n departureTime: schedule.departure.time.slice(0, 5),\n bookingClass: bookingCode,\n flightStatusCode: 'NN',\n }),\n );\n\n const fare = itinerary.pricingInformation[0]?.fare;\n if (fare === undefined) {\n throw new TypeError('sabre-client: el itinerario no trae pricingInformation');\n }\n const passengersPricing = fare.passengerInfoList.map(\n ({ passengerInfo }): PassengerPricing => ({\n passengerCode: passengerInfo.passengerType,\n numberOfpassengers: passengerInfo.passengerNumber ?? 1,\n }),\n );\n\n let priceComparisons: PriceComparison[] | undefined;\n if (priceComparison !== undefined) {\n const total = fare.totalFare?.totalPrice;\n if (total === undefined) {\n throw new TypeError('sabre-client: el itinerario no trae totalFare.totalPrice para priceComparison');\n }\n priceComparisons = [{ desiredAmount: amount(total), ...priceComparison }];\n }\n\n const travelerCount = passengersPricing.reduce((n, p) => n + (p.numberOfpassengers ?? 1), 0);\n const priced: PricedSeat[] = [];\n for (const selection of seats) {\n const flight = flights[validSeat(selection, flights.length, travelerCount)]!;\n (flight.seats ??= []).push({ number: selection.number, travelerIndex: selection.travelerIndex });\n const price = seatAvailability === undefined ? undefined : seatPrice(seatAvailability, flight, selection.number);\n if (price !== undefined) {\n priced.push({\n segmentIndex: selection.segmentIndex,\n flight: `${flight.airlineCode}${flight.flightNumber}`,\n seat: selection.number,\n ...price,\n });\n }\n }\n\n const details: FlightDetails = {\n flights,\n flightPricing: [\n {\n ...(priceComparisons === undefined ? {} : { priceComparisons }),\n qualifiers: {\n passengersPricing,\n ...(fare.validatingCarrierCode === undefined ? {} : { validatingAirlineCode: fare.validatingCarrierCode }),\n },\n },\n ],\n };\n if (priced.length > 0) pricedSeats.set(details, priced);\n return details;\n}\n\n/** Devuelve la posición en `flights[]` (`segmentIndex - 1`) si la selección es válida; si no, `TypeError`. */\nfunction validSeat(selection: BookingSeatSelection, flightCount: number, travelerCount: number): number {\n const { segmentIndex, travelerIndex, number } = selection;\n if (typeof number !== 'string' || !SEAT_NUMBER.test(number)) {\n throw new TypeError(`sabre-client: el asiento ${String(number)} no cumple ^[0-9]+[A-Z]$ (p. ej. 13A)`);\n }\n if (!Number.isInteger(segmentIndex) || segmentIndex < 1 || segmentIndex > flightCount) {\n throw new TypeError(\n `sabre-client: el asiento ${number} pide el vuelo ${segmentIndex}, y hay ${flightCount} (empieza en 1)`,\n );\n }\n if (!Number.isInteger(travelerIndex) || travelerIndex < 1 || travelerIndex > travelerCount) {\n throw new TypeError(\n `sabre-client: el asiento ${number} pide el viajero ${travelerIndex}, y hay ${travelerCount} (empieza en 1)`,\n );\n }\n return segmentIndex - 1;\n}\n\n/**\n * Precio del asiento en Get Seats, si es mayor que cero. El segmento se busca por vuelo,\n * fecha y aeropuerto de salida, no por `id`: así no depende de cómo se armó el request.\n * Ruta: `seats[].offerItemRefIds` → `offerItems[].priceDefinitionRef` → `priceDefinitions[]`.\n */\nfunction seatPrice(\n availability: GetSeatsResponse,\n flight: FlightToBook,\n number: string,\n): { amount: string; currencyCode: string } | undefined {\n const { response } = availability;\n const segmentIds = new Set(\n response.segments\n .filter(\n (s) =>\n s.bookingAirlineCode === flight.airlineCode &&\n s.bookingFlightNumber === flight.flightNumber &&\n s.departureAirportCode === flight.fromAirportCode &&\n s.departureDate === flight.departureDate,\n )\n .map((s) => s.id),\n );\n const row = Number(number.slice(0, -1));\n const column = number.slice(-1);\n const seat = response.seatMaps\n .filter((map) => segmentIds.has(map.segmentRef))\n .flatMap((map) => map.cabinCompartments ?? [])\n .flatMap((cabin) => cabin.seatRows ?? [])\n .filter((r) => r.row === row)\n .flatMap((r) => r.seats)\n .find((s) => s.column === column);\n\n for (const itemId of seat?.offerItemRefIds ?? []) {\n const item = response.offerItems.find((i) => i.id === itemId);\n const price = response.priceDefinitions?.find((p) => p.id === item?.priceDefinitionRef);\n if (price !== undefined && Number(price.totalPrice.amount) > 0) {\n // Sabre manda número aunque el spec diga string: se normaliza para el evento.\n return { amount: String(price.totalPrice.amount), currencyCode: price.currencyCode };\n }\n }\n return undefined;\n}\n\n/** `1234.5` → `'1234.5'`; el spec acepta hasta 3 decimales. */\nfunction amount(value: number): string {\n return String(Math.round(value * 1000) / 1000);\n}\n","// Create Booking (`POST /v1/trip/orders/createBooking`).\n// Ver sabre-wiki/wiki/entities/booking-management-api.md y\n// sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md (éxito parcial de Create Booking).\nimport { type SabreBusinessError, SabreError, type SabreWarning } from '../errors/index.js';\nimport type { SabreRawResponseCallback } from '../http/raw-response.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n type BookingResponseError,\n isObject,\n isWarning,\n nonEmpty,\n responseErrors,\n toBusinessError,\n toWarning,\n} from './booking-errors.js';\nimport type { Booking } from './booking-types.js';\nimport type { CreateBookingRequest } from './create-booking-request.js';\nimport { pricedSeatsOf } from './flight-details.js';\nimport { rawHooks, type SabreRawRequestCallback } from '../http/raw-request.js';\n\nexport const CREATE_BOOKING_SERVICE = 'createBooking';\nconst PATH = '/v1/trip/orders/createBooking';\n/** Aviso cuyo `description` trae el `confirmationId` de una reserva que sí se creó. */\nconst UNABLE_TO_RETRIEVE_BOOKING = 'UNABLE_TO_RETRIEVE_BOOKING';\n\nexport interface CreateBookingOptions {\n signal?: AbortSignal;\n /** Respuesta cruda del último intento HTTP. El body trae PII: ver `SabreRawResponse`. */\n onRawResponse?: SabreRawResponseCallback;\n /** Request crudo del último intento que se mandó, sin `Authorization`. Trae PII: ver `SabreRawRequest`. */\n onRawRequest?: SabreRawRequestCallback;\n}\n\n/** Elemento de `errors[]` de Create Booking. */\nexport type CreateBookingResponseError = BookingResponseError;\n\n/** `Booking` del spec v1.33, tipado completo (#158): ver `booking-types.ts`. */\nexport type { Booking };\n\n/** `CreateBookingResponse` tal cual llega de Sabre. */\nexport interface RawCreateBookingResponse {\n timestamp?: string;\n confirmationId?: string;\n booking?: Booking;\n errors?: CreateBookingResponseError[];\n request?: CreateBookingRequest;\n}\n\n/**\n * Reserva creada. Si Sabre la creó con avisos o con errores no fatales (p. ej. con\n * `errorHandlingPolicy: DO_NOT_HALT_ON_*`), no se lanza: van adjuntos aquí.\n */\nexport interface CreateBookingResponse {\n /** Localizador del PNR. */\n confirmationId: string;\n timestamp?: string;\n /** Falta, p. ej., con el aviso `UNABLE_TO_RETRIEVE_BOOKING`. */\n booking?: Booking;\n /** Copia del request enviado, si Sabre la devuelve. */\n request?: CreateBookingRequest;\n /** Elementos de `errors[]` con `category: WARNING`. */\n warnings: SabreWarning[];\n /** Elementos de `errors[]` de otras categorías que no impidieron crear la reserva. */\n errors: SabreBusinessError[];\n}\n\n/**\n * Create Booking: escritura no idempotente, sin reintento automático. Solo el reintento\n * reactivo ante 401, que el gateway rechaza antes de llegar al proveedor.\n */\nexport async function createBooking(\n transport: RestTransport,\n request: CreateBookingRequest,\n options: CreateBookingOptions = {},\n): Promise<CreateBookingResponse> {\n validateCreateBookingRequest(request);\n // Decidido en #62: un asiento con precio solo se avisa; la reserva se envía igual.\n for (const seat of pricedSeatsOf(request.flightDetails)) {\n transport.log.emit('warn', 'sabre.booking.seat.priced', { service: CREATE_BOOKING_SERVICE, ...seat });\n }\n const body = await transport.request<RawCreateBookingResponse>({\n method: 'POST',\n path: PATH,\n service: CREATE_BOOKING_SERVICE,\n idempotent: false,\n body: request,\n classify: classifyCreateBooking,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'booking.create'),\n });\n return toCreateBookingResponse(body);\n}\n\n/**\n * Reglas de la API que Sabre rechaza seguro, iguales para todas las agencias:\n * `FUTURE_TICKETING` sin `futureTicketingPolicy` vuelve como `MANDATORY_DATA_MISSING`. Solo se\n * revisa que la policy esté, no su contenido; los valores de la agencia van tal cual.\n */\nfunction validateCreateBookingRequest(request: CreateBookingRequest): void {\n if (typeof request !== 'object' || request === null) {\n throw new TypeError('sabre-client: booking.create espera un objeto CreateBookingRequest');\n }\n const agency = request.agency;\n if (agency?.ticketingPolicy === 'FUTURE_TICKETING' && agency.futureTicketingPolicy === undefined) {\n throw new TypeError(\n 'sabre-client: booking.create con agency.ticketingPolicy FUTURE_TICKETING necesita agency.futureTicketingPolicy',\n );\n }\n // `BookGenericSeat.travelerIndex` es 1-based sobre `travelers[]`.\n const travelers = Array.isArray(request.travelers) ? request.travelers.length : 0;\n for (const flight of request.flightDetails?.flights ?? []) {\n for (const seat of flight.seats ?? []) {\n if (seat.travelerIndex < 1 || seat.travelerIndex > travelers) {\n throw new TypeError(\n `sabre-client: booking.create con un asiento para el viajero ${seat.travelerIndex}, y travelers tiene ${travelers}`,\n );\n }\n }\n }\n}\n\n/**\n * Paso 3 del orden de detección. Lo que decide si se lanza es si la reserva se creó, no la\n * categoría de `errors[]`:\n *\n * - Hay reserva (`confirmationId`, `booking.bookingId` o el aviso `UNABLE_TO_RETRIEVE_BOOKING`\n * con el localizador en el `description`): no hay error, `toCreateBookingResponse` adjunta\n * avisos y errores al resultado.\n * - No hay reserva: `SabreBusinessError` con el primer error que no sea `WARNING`, y los\n * avisos adjuntos.\n */\nexport function classifyCreateBooking(body: unknown): SabreError | undefined {\n if (!isObject(body)) {\n return new SabreError(`${CREATE_BOOKING_SERVICE}: respuesta malformada, se esperaba un objeto`, {\n retryable: false,\n raw: body,\n });\n }\n const response = body as RawCreateBookingResponse;\n if (confirmationIdOf(response) !== undefined) return undefined;\n\n // La reserva existe pero no hay localizador que devolver: no es un \"no se creó\".\n if (reservationWithoutId(response)) {\n return new SabreError(\n `${CREATE_BOOKING_SERVICE}: Sabre indica que la reserva se creó, pero no devolvió su confirmationId`,\n { retryable: false, raw: body },\n );\n }\n const items = responseErrors(response);\n const fatal = items.find((item) => !isWarning(item));\n if (fatal !== undefined) return toBusinessError(CREATE_BOOKING_SERVICE, fatal, { warnings: items.filter(isWarning).map(warningOf) });\n return new SabreError(`${CREATE_BOOKING_SERVICE}: respuesta malformada, sin confirmationId ni errores fatales`, {\n retryable: false,\n raw: body,\n });\n}\n\n/** Solo para respuestas con reserva (ver `classifyCreateBooking`). */\nfunction toCreateBookingResponse(body: RawCreateBookingResponse): CreateBookingResponse {\n const items = responseErrors(body);\n return {\n confirmationId: confirmationIdOf(body)!,\n ...(body.timestamp === undefined ? {} : { timestamp: body.timestamp }),\n ...(body.booking === undefined ? {} : { booking: body.booking }),\n ...(body.request === undefined ? {} : { request: body.request }),\n warnings: items.filter(isWarning).map(warningOf),\n errors: items.filter((item) => !isWarning(item)).map((item) => toBusinessError(CREATE_BOOKING_SERVICE, item)),\n };\n}\n\nfunction confirmationIdOf(response: RawCreateBookingResponse): string | undefined {\n if (nonEmpty(response.confirmationId)) return response.confirmationId;\n if (nonEmpty(response.booking?.bookingId)) return response.booking.bookingId;\n const notRetrieved = responseErrors(response).find((item) => item.type === UNABLE_TO_RETRIEVE_BOOKING);\n return notRetrieved === undefined ? undefined : locatorIn(notRetrieved.description);\n}\n\nfunction reservationWithoutId(response: RawCreateBookingResponse): boolean {\n return response.booking !== undefined || responseErrors(response).some((item) => item.type === UNABLE_TO_RETRIEVE_BOOKING);\n}\n\n/**\n * El catálogo documenta el description como `Booking was created successfully but could not\n * be retrieved. (confirmationId)`. Se prefiere el valor entre paréntesis.\n */\nfunction locatorIn(description: string | undefined): string | undefined {\n if (description === undefined) return undefined;\n return /\\(([A-Z0-9]{6,})\\)/.exec(description)?.[1] ?? /\\b([A-Z0-9]{6,})\\b/.exec(description)?.[1];\n}\n\nfunction warningOf(item: BookingResponseError): SabreWarning {\n return toWarning(CREATE_BOOKING_SERVICE, item);\n}\n","// Get Booking (`POST /v1/trip/orders/getBooking`).\n// Ver sabre-wiki/wiki/sdk/gestion-de-reserva.md y sabre-wiki/wiki/sources/get-booking.md.\nimport { type SabreBusinessError, SabreError, type SabreWarning } from '../errors/index.js';\nimport type { SabreRawResponseCallback } from '../http/raw-response.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n type BookingResponseError,\n isObject,\n isWarning,\n nonEmpty,\n responseErrors,\n toBusinessError,\n toWarning,\n} from './booking-errors.js';\nimport type { Booking } from './create-booking.js';\nimport { rawHooks, type SabreRawRequestCallback } from '../http/raw-request.js';\n\nexport const GET_BOOKING_SERVICE = 'getBooking';\nconst PATH = '/v1/trip/orders/getBooking';\n/** Fallos de sistema que Sabre puede resolver al repetir la lectura (decidido en #39). */\nconst RETRYABLE_TYPES = new Set(['INTERNAL_SERVER_TIMEOUT', 'DOWNLINE_SERVICE_FAILURE']);\n\n/** Secciones de la respuesta (`ReturnOnlyEnum`). Además evitan llamadas downline de Sabre. */\nexport type GetBookingReturnOnly =\n | 'FLIGHTS'\n | 'FLIGHT_PENALTY'\n | 'BAGGAGE_POLICY'\n | 'JOURNEYS'\n | 'HOTELS'\n | 'HOTEL_ADDRESS'\n | 'CARS'\n | 'CAR_RENTAL_ADDRESS'\n | 'CAR_RENTAL_PENALTY'\n | 'TRAINS'\n | 'CRUISES'\n | 'ALL_SEGMENTS'\n | 'TRAVELERS'\n | 'TICKETS'\n | 'PAYMENTS'\n | 'PENALTIES'\n | 'REMARKS'\n | 'IS_CANCELABLE'\n | 'IS_TICKETED'\n | 'CONTACT_INFO'\n | 'OTHER_SERVICES'\n | 'SPECIAL_SERVICES'\n | 'FARES'\n | 'CREATION_DETAILS'\n | 'ANCILLARIES'\n | 'FORMS_OF_PAYMENT'\n | 'RETENTION_DATE'\n | 'ACCOUNTING_ITEMS'\n | 'NON_ELECTRONIC_TICKETS'\n | 'TRAVELERS_EMPLOYERS'\n | 'PROFILES';\n\n/** `BookingSourceEnum`. Por defecto `SABRE`. */\nexport type BookingSource = 'SABRE' | 'SABRE_ORDER';\n\n/** `ExtraFeatures` del spec (incluye `CommonExtraFeatures`). */\nexport interface GetBookingExtraFeatures {\n /** Solo NDC. Por defecto `true`. */\n returnEmptySeatObjects?: boolean;\n /** Por defecto `false`; más lento. */\n forceHotelUpdate?: boolean;\n returnFrequentRenter?: boolean;\n returnWalletFormsOfPayment?: boolean;\n returnFiscalId?: boolean;\n}\n\n/** `GetBookingRequest` del spec v1.33. */\nexport interface GetBookingRequest {\n /** Localizador del PNR u Order ID (`^[A-Z0-9]{6,}$`). Único campo obligatorio. */\n confirmationId: string;\n bookingSource?: BookingSource;\n /** Cambio de contexto (`^[A-Z0-9]{3,4}$`). */\n targetPcc?: string;\n /** Validación extra: si no coincide con el PNR, Sabre responde `UNAUTHORIZED_ACCESS`. */\n surname?: string;\n /** Según el spec, Sabre no los usa; solo `surname`. */\n givenName?: string;\n middleName?: string;\n /** Vacío o ausente: la reserva completa. */\n returnOnly?: GetBookingReturnOnly[];\n extraFeatures?: GetBookingExtraFeatures;\n /** Requiere el keyword `CCVIEW` en el EPR. */\n unmaskPaymentCardNumbers?: boolean;\n}\n\nexport interface GetBookingOptions {\n signal?: AbortSignal;\n /** Respuesta cruda del último intento HTTP. El body trae PII: ver `SabreRawResponse`. */\n onRawResponse?: SabreRawResponseCallback;\n /** Request crudo del último intento que se mandó, sin `Authorization`. Trae PII: ver `SabreRawRequest`. */\n onRawRequest?: SabreRawRequestCallback;\n}\n\n/** `GetBookingResponse` tal cual llega de Sabre: el `Booking` va en el primer nivel. */\nexport interface RawGetBookingResponse extends Booking {\n timestamp?: string;\n bookingSignature?: string;\n request?: GetBookingRequest;\n errors?: BookingResponseError[];\n}\n\n/**\n * Reserva leída, con el `Booking` en el primer nivel tal cual lo define Sabre (no se normaliza\n * contra Create ni Cancel, que lo anidan en `booking`). `errors[]` del original se reemplaza\n * por los errores del SDK.\n */\nexport interface GetBookingResponse extends Booking {\n bookingId: string;\n timestamp?: string;\n /** Solo viene si Sabre armó la reserva sin errores. Lo usa Modify Booking. */\n bookingSignature?: string;\n /** Copia del request enviado, si Sabre la devuelve. */\n request?: GetBookingRequest;\n /**\n * Elementos de `errors[]` con `category: WARNING`. En un PNR sin emitir es normal\n * `RESOURCE_UNAVAILABLE` por falta de fare rules.\n */\n warnings: SabreWarning[];\n /**\n * Elementos de `errors[]` de otras categorías que llegaron junto con la reserva, p. ej.\n * `UNAUTHORIZED_ACCESS` de un servicio downline: faltan secciones, pero la reserva existe.\n */\n errors: SabreBusinessError[];\n}\n\n/**\n * Get Booking: lectura idempotente. Los 429/5xx de gateway se reintentan con la política\n * genérica, y también `INTERNAL_SERVER_TIMEOUT` y `DOWNLINE_SERVICE_FAILURE`.\n */\nexport async function getBooking(\n transport: RestTransport,\n request: GetBookingRequest,\n options: GetBookingOptions = {},\n): Promise<GetBookingResponse> {\n if (!isObject(request) || !nonEmpty(request.confirmationId)) {\n throw new TypeError('sabre-client: booking.get espera { confirmationId: string, ... }');\n }\n const body = await transport.request<RawGetBookingResponse>({\n method: 'POST',\n path: PATH,\n service: GET_BOOKING_SERVICE,\n idempotent: true,\n body: request,\n classify: classifyGetBooking,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'booking.get'),\n });\n return toGetBookingResponse(body);\n}\n\n/**\n * Paso 3 del orden de detección. Lo que decide si se lanza es si hay reserva (`bookingId`):\n *\n * - Hay reserva: no hay error; `toGetBookingResponse` adjunta avisos y errores al resultado.\n * - No hay reserva: `SabreBusinessError` con el primer error que no sea `WARNING` (p. ej.\n * `BOOKING_NOT_FOUND` o `UNAUTHORIZED_ACCESS`), y los avisos adjuntos.\n */\nexport function classifyGetBooking(body: unknown): SabreError | undefined {\n if (!isObject(body)) {\n return new SabreError(`${GET_BOOKING_SERVICE}: respuesta malformada, se esperaba un objeto`, {\n retryable: false,\n raw: body,\n });\n }\n const response = body as RawGetBookingResponse;\n if (nonEmpty(response.bookingId)) return undefined;\n\n const items = responseErrors(response);\n const fatal = items.find((item) => !isWarning(item));\n if (fatal !== undefined) return errorOf(fatal, items.filter(isWarning).map(warningOf));\n return new SabreError(`${GET_BOOKING_SERVICE}: respuesta malformada, sin bookingId ni errores fatales`, {\n retryable: false,\n raw: body,\n });\n}\n\n/** Solo para respuestas con reserva (ver `classifyGetBooking`). */\nfunction toGetBookingResponse(body: RawGetBookingResponse): GetBookingResponse {\n const items = responseErrors(body);\n return {\n ...body,\n bookingId: body.bookingId!,\n warnings: items.filter(isWarning).map(warningOf),\n errors: items.filter((item) => !isWarning(item)).map((item) => errorOf(item, [])),\n };\n}\n\nfunction warningOf(item: BookingResponseError): SabreWarning {\n return toWarning(GET_BOOKING_SERVICE, item);\n}\n\nfunction errorOf(item: BookingResponseError, warnings: SabreWarning[]): SabreBusinessError {\n return toBusinessError(GET_BOOKING_SERVICE, item, { warnings, retryable: RETRYABLE_TYPES.has(item.type) });\n}\n","// Módulo de dominio `sabre.booking` (Booking Management API).\n// Ver sabre-wiki/wiki/sdk/convenciones-de-nombres-y-versionado.md.\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n cancelBooking,\n type CancelBookingOptions,\n type CancelBookingRequest,\n type CancelBookingResponse,\n} from './cancel-booking.js';\nimport type { CreateBookingRequest } from './create-booking-request.js';\nimport { createBooking, type CreateBookingOptions, type CreateBookingResponse } from './create-booking.js';\nimport { getBooking, type GetBookingOptions, type GetBookingRequest, type GetBookingResponse } from './get-booking.js';\n\nexport class BookingManagement {\n readonly #transport: RestTransport;\n\n /** @internal Lo construye el cliente `Sabre`. */\n constructor(transport: RestTransport) {\n this.#transport = transport;\n }\n\n /**\n * Create Booking: crea la reserva. Para un itinerario de BFM/Revalidate, `flightDetails` se\n * arma con `buildBookingFlightDetails`.\n *\n * Nunca se reintenta automáticamente. Si la reserva se crea con avisos o errores no fatales,\n * no lanza: los devuelve en `warnings` y `errors`. Si no se crea, lanza `SabreBusinessError`.\n * Con `agency.ticketingPolicy: 'FUTURE_TICKETING'` y sin `agency.futureTicketingPolicy`, lanza\n * `TypeError` sin llamar a la red: Sabre lo rechaza seguro. Lo mismo con un asiento cuyo\n * `travelerIndex` no está en `travelers`. Un asiento con precio en Get Seats (ver\n * `buildBookingFlightDetails`) solo emite `sabre.booking.seat.priced` en `warn`.\n */\n create(request: CreateBookingRequest, options?: CreateBookingOptions): Promise<CreateBookingResponse> {\n return createBooking(this.#transport, request, options);\n }\n\n /**\n * Get Booking: lee la reserva por `confirmationId`. El `Booking` va en el primer nivel de la\n * respuesta, a diferencia de `create`. Usa `returnOnly` para pedir solo las secciones que\n * hacen falta: además acelera la respuesta.\n *\n * Si la reserva existe, no lanza: los avisos y errores parciales van en `warnings` y\n * `errors`. Si no existe o no se pudo leer (p. ej. `BOOKING_NOT_FOUND`), lanza\n * `SabreBusinessError`. Es una lectura: se reintenta ante fallos transitorios.\n */\n get(request: GetBookingRequest, options?: GetBookingOptions): Promise<GetBookingResponse> {\n return getBooking(this.#transport, request, options);\n }\n\n /**\n * Cancel Booking: cancela la reserva entera (`cancelAll: true`) o por `itemId` (p. ej. los\n * `flights[].itemId` de `get`). Valida antes de enviar las combinaciones que Sabre rechaza y,\n * si encuentra una, lanza `TypeError` sin llamar a la red.\n *\n * Nunca se reintenta automáticamente. Lanza `SabreBusinessError` si algo falló o si Sabre\n * responde `NO_ITEMS_CANCELLED` (no se canceló nada), aunque llegue como aviso. Con\n * `END_TRANSACTION_PROBLEM` en `warnings`, la confirmación quedó pendiente: verifica con `get`.\n */\n cancel(request: CancelBookingRequest, options?: CancelBookingOptions): Promise<CancelBookingResponse> {\n return cancelBooking(this.#transport, request, options);\n }\n}\n","// Política de reintentos. Ver sabre-wiki/wiki/sdk/politica-de-reintentos-y-backoff.md.\nimport { SabreError } from '../errors/index.js';\n\nexport interface RetryOptions {\n /** Reintentos después de la primera llamada (3 → hasta 4 llamadas en total). */\n maxRetries: number;\n /** Delay base del backoff exponencial, en milisegundos. */\n baseDelayMs: number;\n}\n\nexport const DEFAULT_RETRY: Readonly<RetryOptions> = Object.freeze({ maxRetries: 3, baseDelayMs: 500 });\n\n/** Piso mínimo de espera que documenta Sabre para 429/5xx de gateway. */\nexport const MIN_RETRY_DELAY_MS = 500;\n\n/** Full jitter: aleatorio entre 0 y `baseDelayMs · 2^retry`, con piso de 500 ms. */\nexport function retryDelay(retry: number, baseDelayMs: number, random: () => number = Math.random): number {\n return Math.max(MIN_RETRY_DELAY_MS, Math.floor(random() * baseDelayMs * 2 ** retry));\n}\n\n/** Solo se reintenta un `SabreError` con `retryable: true` en una operación idempotente. */\nexport function shouldRetry(error: unknown, idempotent: boolean): boolean {\n return idempotent && error instanceof SabreError && error.retryable;\n}\n\nexport function validateRetryOptions(retry: Partial<RetryOptions>, where: string): void {\n if (retry.maxRetries !== undefined && !(Number.isInteger(retry.maxRetries) && retry.maxRetries >= 0)) {\n throw new TypeError(`sabre-client: ${where}.maxRetries debe ser un entero >= 0`);\n }\n if (retry.baseDelayMs !== undefined && !(Number.isFinite(retry.baseDelayMs) && retry.baseDelayMs >= 0)) {\n throw new TypeError(`sabre-client: ${where}.baseDelayMs debe ser un número >= 0`);\n }\n}\n\n/** Espera `ms`, o rechaza con el motivo del `signal` si se aborta antes. */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason);\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","// Config explícita del consumidor; el SDK nunca lee variables de entorno.\n// Ver sabre-wiki/wiki/sdk/configuracion-logging-y-build.md.\nimport type { SabreTokenStore } from './auth/token-store.js';\nimport { DEFAULT_RETRY, type RetryOptions, validateRetryOptions } from './http/retry.js';\nimport type { SabreLogger } from './logging/index.js';\n\nexport type SabreEnvironment = 'sandbox' | 'production';\n\nexport type SabreAuthVersion = 'v3' | 'v2';\n\n/** Credenciales para OAuth Token Create v3: Client ID/Secret más usuario EPR. */\nexport interface SabreCredentials {\n /**\n * Versión de OAuth para la que se armaron. `buildCredentials` la pone; la config la usa cuando\n * no trae su propio `authVersion`.\n */\n authVersion?: 'v3';\n clientId: string;\n clientSecret: string;\n /** Usuario EPR. */\n username: string;\n /** Contraseña EPR. */\n password: string;\n}\n\n/** Credenciales para OAuth Token Create v2: solo EPR; `clientId`/`clientSecret` se ignoran. */\nexport interface SabreCredentialsV2 {\n /**\n * Versión de OAuth para la que se armaron. `buildCredentials` la pone, y con ella la config no\n * necesita repetir `authVersion: 'v2'`.\n */\n authVersion?: 'v2';\n clientId?: string;\n clientSecret?: string;\n /** Usuario EPR. */\n username: string;\n /** Contraseña EPR. */\n password: string;\n}\n\ninterface SabreBaseConfig {\n environment: SabreEnvironment;\n logger?: SabreLogger;\n /** Reintentos por defecto del cliente; cada request puede pisarlos. */\n retry?: Partial<RetryOptions>;\n /** `fetch` a usar en lugar del global (tests, proxies, runtimes edge). */\n fetch?: typeof fetch;\n /**\n * Almacén del token para reutilizarlo entre procesos (scripts, serverless). Sin él, el\n * token se cachea solo en memoria.\n */\n tokenStore?: SabreTokenStore;\n}\n\n/** OAuth Token Create v3 (por defecto). */\nexport interface SabreConfigV3 extends SabreBaseConfig {\n authVersion?: 'v3';\n credentials: SabreCredentials;\n}\n\n/** OAuth Token Create v2. */\nexport interface SabreConfigV2 extends SabreBaseConfig {\n authVersion: 'v2';\n credentials: SabreCredentialsV2;\n}\n\n/**\n * OAuth Token Create v2 sin `authVersion` en la config: la versión sale de las credenciales,\n * como las devuelve `buildCredentials({ authVersion: 'v2', … })`.\n */\nexport interface SabreConfigV2FromCredentials extends SabreBaseConfig {\n authVersion?: never;\n credentials: SabreCredentialsV2 & { authVersion: 'v2' };\n}\n\n/**\n * Credenciales con su versión, sin saber cuál al compilar: lo que devuelve\n * `buildCredentials(options: BuildCredentialsOptions)`. Es un solo tipo y no la unión de\n * `BuiltCredentialsV3 | BuiltCredentialsV2`: con la unión, TypeScript aceptaría también un\n * `SabreCredentialsV2` sin marca, porque toma su `authVersion` opcional como discriminante. A\n * cambio, el tipo no exige `clientId`/`clientSecret` con `'v3'`: eso lo valida `resolveConfig`.\n */\nexport interface SabreCredentialsAnyVersion {\n authVersion: SabreAuthVersion;\n clientId?: string;\n clientSecret?: string;\n username: string;\n password: string;\n}\n\n/**\n * Config sin `authVersion`, con credenciales de `buildCredentials` cuya versión no se conoce al\n * compilar. La versión sale de la marca de las credenciales en runtime (Q-084, #159).\n */\nexport interface SabreConfigFromCredentials extends SabreBaseConfig {\n authVersion?: never;\n credentials: SabreCredentialsAnyVersion;\n}\n\n/**\n * Config del cliente, discriminada por `authVersion`: el de la config o, si falta, el de\n * `credentials`. Sin ninguno de los dos, es v3.\n */\nexport type SabreConfig = SabreConfigV3 | SabreConfigV2 | SabreConfigV2FromCredentials | SabreConfigFromCredentials;\n\nexport const BASE_URLS: Readonly<Record<SabreEnvironment, string>> = Object.freeze({\n sandbox: 'https://api.cert.platform.sabre.com',\n production: 'https://api.platform.sabre.com',\n});\n\n/** Endpoints SOAP de `SabreLegacy` (ver entornos-y-certificacion). */\nexport const SOAP_BASE_URLS: Readonly<Record<SabreEnvironment, string>> = Object.freeze({\n sandbox: 'https://webservices.cert.platform.sabre.com',\n production: 'https://webservices.platform.sabre.com',\n});\n\n/** Config validada y con defaults aplicados. */\nexport interface ResolvedConfig {\n credentials: Readonly<SabreCredentials | SabreCredentialsV2>;\n environment: SabreEnvironment;\n baseUrl: string;\n soapBaseUrl: string;\n authVersion: SabreAuthVersion;\n logger: SabreLogger | undefined;\n retry: Readonly<RetryOptions>;\n fetch: typeof fetch;\n tokenStore: SabreTokenStore | undefined;\n}\n\nconst LOGGER_METHODS = ['debug', 'info', 'warn', 'error'] as const;\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction requireString(value: unknown, field: string): void {\n if (typeof value !== 'string' || value.trim() === '') fail(`${field} es requerido y debe ser un string no vacío`);\n}\n\nexport function resolveConfig(config: SabreConfig): ResolvedConfig {\n if (!isObject(config)) fail('la config debe ser un objeto');\n\n const { environment } = config;\n if (environment !== 'sandbox' && environment !== 'production') {\n fail(`environment debe ser 'sandbox' o 'production' (recibido: ${JSON.stringify(environment)})`);\n }\n\n const configVersion = config.authVersion ?? undefined;\n if (configVersion !== undefined && configVersion !== 'v3' && configVersion !== 'v2') {\n fail(`authVersion debe ser 'v3' o 'v2' (recibido: ${JSON.stringify(configVersion)})`);\n }\n\n const { credentials } = config;\n if (!isObject(credentials)) fail('credentials es requerido');\n // La marca que pone `buildCredentials`: evita repetir `authVersion` en la config (#148).\n const credentialsVersion = credentials.authVersion ?? undefined;\n if (credentialsVersion !== undefined && credentialsVersion !== 'v3' && credentialsVersion !== 'v2') {\n fail(`credentials.authVersion debe ser 'v3' o 'v2' (recibido: ${JSON.stringify(credentialsVersion)})`);\n }\n if (configVersion !== undefined && credentialsVersion !== undefined && configVersion !== credentialsVersion) {\n fail(`authVersion '${configVersion}' no coincide con credentials.authVersion '${credentialsVersion}'`);\n }\n const authVersion: SabreAuthVersion = configVersion ?? credentialsVersion ?? 'v3';\n requireString(credentials.username, 'credentials.username');\n requireString(credentials.password, 'credentials.password');\n if (authVersion === 'v3') {\n requireString(credentials.clientId, 'credentials.clientId (requerido con authVersion v3)');\n requireString(credentials.clientSecret, 'credentials.clientSecret (requerido con authVersion v3)');\n }\n\n const { logger } = config;\n if (logger !== undefined) {\n if (!isObject(logger)) fail('logger debe ser un objeto con debug/info/warn/error');\n for (const method of LOGGER_METHODS) {\n if (typeof logger[method] !== 'function') fail(`logger.${method} debe ser una función`);\n }\n }\n\n if (config.retry !== undefined) {\n if (!isObject(config.retry)) fail('retry debe ser un objeto');\n validateRetryOptions(config.retry, 'retry');\n }\n\n const { tokenStore } = config;\n if (tokenStore !== undefined) {\n if (!isObject(tokenStore) || typeof tokenStore.get !== 'function' || typeof tokenStore.set !== 'function') {\n fail('tokenStore debe ser un objeto con get(key) y set(key, token)');\n }\n }\n\n const fetchImpl = config.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') fail('no hay fetch disponible: pasa config.fetch');\n\n return {\n // Ya validado arriba: con v3 trae clientId/clientSecret; la marca de versión ya se resolvió.\n credentials: Object.freeze({ ...credentials }) as SabreCredentials | SabreCredentialsV2,\n environment,\n baseUrl: BASE_URLS[environment],\n soapBaseUrl: SOAP_BASE_URLS[environment],\n authVersion,\n logger,\n retry: Object.freeze({ ...DEFAULT_RETRY, ...definedOnly(config.retry ?? {}) }),\n // Enlazado al global para evitar \"Illegal invocation\" en algunos runtimes.\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n tokenStore,\n };\n}\n\n/** Quita claves con valor `undefined` para que no pisen los defaults. */\nexport function definedOnly<T extends object>(value: T): Partial<T> {\n return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== undefined)) as Partial<T>;\n}\n","// Transporte REST del cliente `Sabre`: fetch JSON, detección de errores y reintentos.\n// Ver sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md y politica-de-reintentos-y-backoff.md.\nimport { definedOnly, type ResolvedConfig } from '../config.js';\nimport { SabreError, SabreGatewayError } from '../errors/index.js';\nimport { EventLogger } from '../logging/logger.js';\nimport { type RawRequestCapture, rawRequestHeaders, type SabreRawRequestCallback } from './raw-request.js';\nimport type { SabreRawResponse, SabreRawResponseCallback } from './raw-response.js';\nimport { type RetryOptions, retryDelay, shouldRetry, sleep, validateRetryOptions } from './retry.js';\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\n/** Status de gateway REST reintentables (ver errores-comunes-api). */\nconst RETRYABLE_STATUS = new Set([429, 500, 503, 504]);\n\n/**\n * Pasos 2–3 del orden de detección, aportados por cada servicio: recibe el body de una\n * respuesta 2xx y devuelve el error de su catálogo (orquestado, negocio o warning), o\n * `undefined` si la respuesta es data válida.\n */\nexport type ResponseClassifier = (body: unknown, response: Response) => SabreError | undefined;\n\nexport interface RestRequest {\n method: HttpMethod;\n /** Ruta relativa a la base URL, p. ej. `/v5/offers/shop`. */\n path: string;\n /** Nombre del servicio para errores y logs, p. ej. `'bargainFinderMax'`. */\n service: string;\n /**\n * Si la operación se puede repetir sin efectos duplicados. Las escrituras\n * (Create Booking, End Transaction) van en `false` y nunca se reintentan.\n */\n idempotent: boolean;\n query?: Record<string, string | number | boolean | undefined>;\n /** Se serializa como JSON, salvo `URLSearchParams`, que va como form-urlencoded. */\n body?: unknown;\n headers?: Record<string, string>;\n /** `false` para no pedir el header `Authorization` (p. ej. la propia request de token). */\n auth?: boolean;\n classify?: ResponseClassifier;\n retry?: Partial<RetryOptions>;\n signal?: AbortSignal;\n /** Método público sin `sabre.`, p. ej. `'booking.get'`. Lo reciben `onRawResponse` y `onRawRequest`. */\n operation?: string;\n onRawResponse?: SabreRawResponseCallback;\n /** No se llama si `auth` es `false` (la request de token lleva la credencial). */\n onRawRequest?: SabreRawRequestCallback;\n}\n\n/**\n * Último intento con respuesta HTTP (`last`) y último request mandado (`request`). Solo se lleva\n * si hay `onRawResponse` u `onRawRequest`.\n */\ninterface RawCapture {\n attempts: number;\n last?: { status: number; headers: Headers; body: string };\n request?: RawRequestCapture;\n}\n\n/** Fuente del header `Authorization` de los servicios (la implementa `AuthManager`). */\nexport interface AuthorizationProvider {\n /** Valor vigente del header, p. ej. `Bearer <token>`. */\n get(): Promise<string>;\n /** El gateway rechazó `authorization` con 401: descartarlo para que `get` traiga otro. */\n invalidate(authorization: string): void;\n}\n\nexport interface RestTransportOptions {\n authorization?: AuthorizationProvider;\n /** Solo para tests: fuente de aleatoriedad del jitter. */\n random?: () => number;\n /** Solo para tests: espera entre reintentos. */\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n}\n\nexport class RestTransport {\n readonly #config: ResolvedConfig;\n readonly #log: EventLogger;\n readonly #random: () => number;\n readonly #sleep: (ms: number, signal?: AbortSignal) => Promise<void>;\n #authorization: AuthorizationProvider | undefined;\n\n constructor(config: ResolvedConfig, options: RestTransportOptions = {}) {\n this.#config = config;\n this.#log = new EventLogger(config.logger);\n this.#authorization = options.authorization;\n this.#random = options.random ?? Math.random;\n this.#sleep = options.sleep ?? sleep;\n }\n\n /** @internal Para los avisos de las operaciones que no son de una request (p. ej. asientos con precio). */\n get log(): EventLogger {\n return this.#log;\n }\n\n /** Punto de enganche para `AuthManager`. */\n setAuthorizationProvider(provider: AuthorizationProvider | undefined): void {\n this.#authorization = provider;\n }\n\n async request<T>(request: RestRequest): Promise<T> {\n if (request.retry !== undefined) validateRetryOptions(request.retry, 'retry');\n const wantsRequest = request.onRawRequest !== undefined && request.auth !== false;\n const capture: RawCapture | undefined =\n request.onRawResponse === undefined && !wantsRequest ? undefined : { attempts: 0 };\n try {\n return await this.#attempts<T>(request, capture);\n } finally {\n // Antes de devolver o de lanzar: primero el último request que se mandó, aunque no haya\n // tenido respuesta, y después el último intento que tuvo respuesta HTTP.\n if (wantsRequest && capture?.request !== undefined) this.#deliverRawRequest(request, capture.request, capture.attempts);\n if (capture?.last !== undefined) this.#deliverRaw(request, { ...capture.last, attempts: capture.attempts });\n }\n }\n\n async #attempts<T>(request: RestRequest, capture: RawCapture | undefined): Promise<T> {\n const retry = { ...this.#config.retry, ...definedOnly(request.retry ?? {}) };\n\n let reauthorized = false;\n for (let attempt = 0; ; attempt++) {\n // Fuera del try: un fallo al obtener el token ya pasó por sus propios reintentos.\n const authorization = await this.#authorizationFor(request);\n try {\n return await this.#send<T>(request, attempt, authorization, capture);\n } catch (error) {\n // Refresco reactivo: un solo reintento con token nuevo, fuera del presupuesto genérico.\n // Aplica también a escrituras: el 401 del gateway rechaza la request antes del proveedor.\n if (authorization !== undefined && !reauthorized && isUnauthorized(error)) {\n reauthorized = true;\n this.#authorization?.invalidate(authorization);\n this.#log.emit('warn', 'sabre.request.retry', {\n service: request.service,\n method: request.method,\n path: request.path,\n attempt: attempt + 1,\n reason: 'unauthorized',\n error: error as SabreError,\n });\n attempt--;\n continue;\n }\n if (attempt >= retry.maxRetries || !shouldRetry(error, request.idempotent)) throw error;\n const delayMs = retryDelay(attempt, retry.baseDelayMs, this.#random);\n this.#log.emit('warn', 'sabre.request.retry', {\n service: request.service,\n method: request.method,\n path: request.path,\n attempt: attempt + 1,\n maxRetries: retry.maxRetries,\n delayMs,\n error: error as SabreError,\n });\n await this.#sleep(delayMs, request.signal);\n }\n }\n }\n\n /** Un callback que lanza no rompe la operación: Create Booking no puede perder su localizador. */\n #deliverRaw(request: RestRequest, raw: Omit<SabreRawResponse, 'operation' | 'protocol'>): void {\n const operation = request.operation ?? request.service;\n try {\n request.onRawResponse?.({ operation, protocol: 'rest', ...raw });\n } catch (error) {\n this.#log.emit('warn', 'sabre.request.rawResponseHookFailed', {\n service: request.service,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n }\n\n /** Igual que `#deliverRaw`: un callback que lanza no rompe la operación. */\n #deliverRawRequest(request: RestRequest, raw: RawRequestCapture, attempts: number): void {\n const operation = request.operation ?? request.service;\n try {\n request.onRawRequest?.({ operation, protocol: 'rest', ...raw, attempts });\n } catch (error) {\n this.#log.emit('warn', 'sabre.request.rawRequestHookFailed', {\n service: request.service,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n }\n\n async #authorizationFor(request: RestRequest): Promise<string | undefined> {\n if (request.auth === false || this.#authorization === undefined) return undefined;\n return this.#authorization.get();\n }\n\n async #send<T>(\n request: RestRequest,\n attempt: number,\n authorization: string | undefined,\n capture: RawCapture | undefined,\n ): Promise<T> {\n const url = this.#url(request);\n const headers = new Headers({ Accept: 'application/json', ...request.headers });\n const form = request.body instanceof URLSearchParams;\n if (request.body !== undefined && !headers.has('Content-Type')) {\n headers.set('Content-Type', form ? 'application/x-www-form-urlencoded' : 'application/json');\n }\n if (authorization !== undefined) headers.set('Authorization', authorization);\n\n const logContext = { service: request.service, method: request.method, path: request.path, attempt };\n this.#log.emit('debug', 'sabre.request.start', logContext);\n const startedAt = Date.now();\n\n let response: Response;\n const body = request.body === undefined ? undefined : form ? String(request.body) : JSON.stringify(request.body);\n if (capture !== undefined) {\n capture.attempts++;\n if (request.onRawRequest !== undefined && request.auth !== false) {\n capture.request = { method: request.method, url, headers: rawRequestHeaders(headers), body };\n }\n }\n try {\n response = await this.#config.fetch(url, {\n method: request.method,\n headers,\n ...(body === undefined ? {} : { body }),\n ...(request.signal === undefined ? {} : { signal: request.signal }),\n });\n } catch (cause) {\n if (isAbort(cause, request.signal)) throw cause;\n const error = new SabreGatewayError(`${request.service}: fallo de red (${describe(cause)})`, {\n protocol: 'rest',\n retryable: true,\n cause,\n });\n this.#log.emit('error', 'sabre.request.end', { ...logContext, durationMs: Date.now() - startedAt, error });\n throw error;\n }\n\n const text = await response.text();\n if (capture !== undefined) capture.last = { status: response.status, headers: response.headers, body: text };\n const parsed = parseBody(text);\n const endContext = { ...logContext, status: response.status, durationMs: Date.now() - startedAt };\n\n // Paso 1: HTTP status de gateway.\n if (!response.ok) {\n const error = gatewayError(request.service, response.status, parsed);\n this.#log.emit('error', 'sabre.request.end', { ...endContext, error });\n throw error;\n }\n\n // Pasos 2–3: catálogo propio del servicio.\n const serviceError = request.classify?.(parsed, response);\n if (serviceError !== undefined) {\n this.#log.emit('warn', 'sabre.request.end', { ...endContext, error: serviceError });\n throw serviceError;\n }\n\n // Paso 4: data.\n this.#log.emit('info', 'sabre.request.end', endContext);\n return parsed as T;\n }\n\n #url(request: RestRequest): string {\n const path = request.path.startsWith('/') ? request.path : `/${request.path}`;\n const url = new URL(path, this.#config.baseUrl);\n for (const [key, value] of Object.entries(request.query ?? {})) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n return url.toString();\n }\n}\n\n/** Body parseado como JSON; si no es JSON, el texto tal cual; vacío → `undefined`. */\nfunction parseBody(text: string): unknown {\n if (text === '') return undefined;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return text;\n }\n}\n\nfunction gatewayError(service: string, status: number, body: unknown): SabreGatewayError {\n const code = extractCode(body);\n const detail = extractDescription(body);\n return new SabreGatewayError(\n `${service}: HTTP ${status}${code === undefined ? '' : ` ${code}`}${detail === undefined ? '' : `: ${detail}`}`,\n {\n protocol: 'rest',\n status,\n retryable: RETRYABLE_STATUS.has(status),\n raw: body,\n ...(code === undefined ? {} : { code }),\n },\n );\n}\n\n/**\n * Best-effort: el campo del código `ERR.2SG.*` no está confirmado (issue de fuente #21). Se\n * prueban `errorCode`, `error` y `errors[0].code`; este último, visto en un 401 de Get Seats\n * en CERT (`{ errors: [{ code: '305', descriptionText, statusText }] }`, 2026-10-31). Si no\n * viene, `errors[0].type`: un 502 de Get Seats `byPnrLocator` en CERT lo trae así\n * (`{ errors: [{ type: 'DOWNLINE_ERROR', description }] }`, 2026-11-02, #124).\n */\nfunction extractCode(body: unknown): string | undefined {\n if (typeof body !== 'object' || body === null) return undefined;\n for (const key of ['errorCode', 'error'] as const) {\n const value = (body as Record<string, unknown>)[key];\n if (typeof value === 'string' && value !== '') return value;\n }\n return firstErrorField(body, 'code') ?? firstErrorField(body, 'type');\n}\n\n/** Detalle legible de `errors[0]`: `descriptionText` o, si no viene, `description`. */\nfunction extractDescription(body: unknown): string | undefined {\n return firstErrorField(body, 'descriptionText') ?? firstErrorField(body, 'description');\n}\n\nfunction firstErrorField(body: unknown, key: string): string | undefined {\n if (typeof body !== 'object' || body === null) return undefined;\n const errors = (body as { errors?: unknown }).errors;\n const first: unknown = Array.isArray(errors) ? errors[0] : undefined;\n if (typeof first !== 'object' || first === null) return undefined;\n const value = (first as Record<string, unknown>)[key];\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction isUnauthorized(error: unknown): boolean {\n return error instanceof SabreGatewayError && error.protocol === 'rest' && error.status === 401;\n}\n\nfunction isAbort(error: unknown, signal: AbortSignal | undefined): boolean {\n return signal?.aborted === true || (error instanceof Error && error.name === 'AbortError');\n}\n\nfunction describe(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","// Cliente REST. Ver sabre-wiki/wiki/sdk/arquitectura-clientes-transporte.md.\nimport { Air } from './air/air.js';\nimport { AuthManager } from './auth/auth-manager.js';\nimport { BookingManagement } from './booking/booking-management.js';\nimport { type ResolvedConfig, resolveConfig, type SabreConfig, type SabreEnvironment } from './config.js';\nimport { RestTransport } from './http/rest-transport.js';\n\nexport class Sabre {\n readonly #config: ResolvedConfig;\n readonly #transport: RestTransport;\n /** Servicios de Air: shopping, revalidación. */\n readonly air: Air;\n /** Booking Management: creación de reservas. */\n readonly booking: BookingManagement;\n\n constructor(config: SabreConfig) {\n this.#config = resolveConfig(config);\n this.#transport = new RestTransport(this.#config);\n // Toda request lleva `Authorization: Bearer <token>`, salvo la propia de token (`auth: false`).\n const auth = new AuthManager(this.#config, this.#transport);\n this.#transport.setAuthorizationProvider(auth.bearerProvider());\n this.air = new Air(this.#transport);\n this.booking = new BookingManagement(this.#transport);\n }\n\n get environment(): SabreEnvironment {\n return this.#config.environment;\n }\n\n get baseUrl(): string {\n return this.#config.baseUrl;\n }\n}\n","// Transporte SOAP de `SabreLegacy`: sobre armado a mano, fetch, parseo y mapeo de errores.\n// Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (puntos 4 y 6),\n// cliente-http-y-libreria-xml.md y respuesta-cruda-soap.md.\nimport { XMLParser } from 'fast-xml-parser';\nimport { definedOnly, type ResolvedConfig } from '../config.js';\nimport { SabreBusinessError, SabreGatewayError, SabreWarning } from '../errors/index.js';\nimport { EventLogger } from '../logging/logger.js';\nimport { REDACTED, redactSoapEnvelope } from '../logging/redact.js';\nimport { type RawRequestCapture, rawRequestHeaders, type SabreRawRequestCallback } from './raw-request.js';\nimport type { SabreRawResponseCallback } from './raw-response.js';\nimport { type RetryOptions, retryDelay, sleep, validateRetryOptions } from './retry.js';\n\n/**\n * Status HTTP transitorios cuando la respuesta no trae un sobre SOAP (proxy, balanceador).\n * Solo se reintentan en operaciones idempotentes.\n */\nconst TRANSIENT_STATUS = new Set([429, 500, 503, 504]);\n\n/**\n * \"Se excedió el máximo de requests concurrentes: esperar ≥ 500 ms y reintentar\". Se asume que\n * Sabre no procesó el request, así que se reintentan también en las operaciones que mueven el\n * cursor. Sin confirmar: se valida en la Fase 4.\n */\nexport const BUSY_CODES: ReadonlySet<string> = new Set(['USG_CONNECTOR_IS_BUSY', 'USG_IS_BUSY', 'USG_SERVICE_IS_BUSY']);\n\n/**\n * Los demás `USG_*` que el catálogo manda a \"esperar ≥ 500 ms y reintentar\". No dicen si el\n * request se procesó, así que solo se reintentan en operaciones idempotentes.\n * `USG_RESOURCE_UNAVAILABLE` (límite de sesiones) no está: no se reintenta.\n */\nconst TRANSIENT_CODES: ReadonlySet<string> = new Set([\n 'USG_SECURITY_ICE_ERROR',\n 'USG_SERVICE_PROVIDER_ERROR',\n 'USG_NO_RESPONSE_FROM_JMSRECEIVER_IN_TIME',\n 'SC_SERVICE_UNAVAILABLE',\n 'USG_COULD_NOT_COMPLETE_REQUEST',\n 'USG_IIOP_OBJECT_NOT_EXIST',\n 'USG_IIOP_TRANSIENT_EXCEPTION',\n 'USG_MOM_SERVICE_PROVIDER_INFRASTRUCTURE_ERROR',\n]);\n\n/** Esquema fijo que documenta Sabre: 3 reintentos con 1 s de intervalo, sin jitter. */\nexport const PREVIOUS_ENTRY_ACTIVE_RETRIES = 3;\nexport const PREVIOUS_ENTRY_ACTIVE_DELAY_MS = 1000;\nconst PREVIOUS_ENTRY_ACTIVE = /PREVIOUS ENTRY ACTIVE/i;\n\ntype RetryReason = 'busy' | 'previous-entry-active' | 'transient';\n\n/** Credencial del header `wsse:Security`. */\nexport type SoapSecurity =\n /** Token de sesión (ATH) o stateless (ATK). */\n | { binarySecurityToken: string }\n /** Credenciales de `SessionCreateRQ`. `clientId` y `clientSecret` solo van en la 2.0.0. */\n | {\n usernameToken: {\n username: string;\n password: string;\n organization: string;\n domain: string;\n clientId?: string;\n clientSecret?: string;\n };\n };\n\nexport interface SoapRequest {\n /** Nombre del servicio para errores y logs, p. ej. `'queueAccess'`. */\n service: string;\n /** `eb:Service` y `eb:Action`, p. ej. `'QueueAccessLLSRQ'`. */\n action: string;\n /** Payload del `soap-env:Body`, ya armado y escapado (ver `xmlEscape`). */\n payload: string;\n /** `eb:CPAId`: el PCC. */\n cpaId: string;\n /** `eb:ConversationId` de la sesión. */\n conversationId: string;\n security: SoapSecurity;\n /**\n * Si la operación se puede repetir sin efectos (`count`, `list`, `ping`). Las que mueven el\n * cursor de una cola van en `false`: nunca se reintentan ante un fallo de red.\n */\n idempotent: boolean;\n retry?: Partial<RetryOptions>;\n /** `true` para devolver el `BinarySecurityToken` de la respuesta (solo `SessionCreateRQ`). */\n readSecurityToken?: boolean;\n signal?: AbortSignal;\n /** Método público sin `legacy.`, p. ej. `'queue.access'`. Lo reciben `onRawResponse` y `onRawRequest`. */\n operation?: string;\n onRawResponse?: SabreRawResponseCallback;\n /**\n * No se llama con `usernameToken` (`SessionCreateRQ`): el sobre lleva `wsse:Password` y el\n * `ClientSecret`, y la regla de auth lo deja fuera (ADR-029).\n */\n onRawRequest?: SabreRawRequestCallback;\n}\n\nexport interface SoapResponse {\n /** Elemento hijo del `Body` (p. ej. `QueueAccessRS`), parseado y sin prefijos de namespace. */\n payload: Record<string, unknown>;\n /** Nombre local de ese elemento, p. ej. `'QueueAccessRS'`. */\n payloadName: string;\n /** Los `stl:Warning` de `stl:ApplicationResults`. */\n warnings: SabreWarning[];\n /** `eb:MessageId` de la respuesta, el dato que pide soporte de Sabre. */\n messageId: string | undefined;\n /** `eb:Timestamp` de la respuesta, en UTC con `Z` (ver `respondedAtOf`). */\n respondedAt: string | undefined;\n /** El sobre redactado, como `raw` de los errores que arme la operación al leer el payload. */\n raw: string;\n /** El `BinarySecurityToken` del header, solo con `readSecurityToken`. */\n securityToken: string | undefined;\n status: number;\n}\n\nexport interface SoapTransportOptions {\n /** Solo para tests: id del `eb:MessageId`. */\n messageId?: () => string;\n /** Solo para tests: reloj del `eb:Timestamp`. */\n now?: () => Date;\n /** Solo para tests: fuente de aleatoriedad del jitter. */\n random?: () => number;\n /** Solo para tests: espera entre reintentos. */\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n}\n\n/**\n * Último intento con respuesta HTTP (`last`), para entregarlo una sola vez a `onRawResponse`, y\n * último sobre mandado (`request`), para `onRawRequest`.\n */\ninterface RawCapture {\n attempts: number;\n last?: { status: number; headers: Headers; body: string };\n request?: RawRequestCapture;\n}\n\nconst SOAP_HEADERS = { 'Content-Type': 'text/xml; charset=utf-8', Accept: 'text/xml' } as const;\n\ntype XmlNode = Record<string, unknown>;\n\n/**\n * Atributos con `@`, sin prefijos de namespace y todo como string: `\"011\"` y `\"....261\"`\n * llegan tal cual, para que cada servicio decida cómo leerlos.\n */\nconst PARSER_OPTIONS = {\n ignoreAttributes: false,\n attributeNamePrefix: '@',\n removeNSPrefix: true,\n parseTagValue: false,\n parseAttributeValue: false,\n processEntities: true,\n} as const;\nconst parser = new XMLParser(PARSER_OPTIONS);\n/** Igual, pero sin recortar los textos: solo para lo que depende de los espacios. */\nconst untrimmedParser = new XMLParser({ ...PARSER_OPTIONS, trimValues: false });\n\nexport class SoapTransport {\n readonly #config: ResolvedConfig;\n readonly #log: EventLogger;\n readonly #messageId: () => string;\n readonly #now: () => Date;\n readonly #random: () => number;\n readonly #sleep: (ms: number, signal?: AbortSignal) => Promise<void>;\n\n constructor(config: ResolvedConfig, options: SoapTransportOptions = {}) {\n this.#config = config;\n this.#log = new EventLogger(config.logger);\n this.#messageId = options.messageId ?? (() => globalThis.crypto.randomUUID());\n this.#now = options.now ?? (() => new Date());\n this.#random = options.random ?? Math.random;\n this.#sleep = options.sleep ?? sleep;\n }\n\n /** @internal Para los eventos de sesión que no son una request. */\n get log(): EventLogger {\n return this.#log;\n }\n\n async request(request: SoapRequest): Promise<SoapResponse> {\n if (request.retry !== undefined) validateRetryOptions(request.retry, 'retry');\n const capture: RawCapture = { attempts: 0 };\n try {\n return await this.#attempts(request, capture);\n } finally {\n // Una sola vez por operación: primero el último sobre que se mandó, aunque no haya tenido\n // respuesta, y después el último intento que tuvo respuesta HTTP.\n if (capture.request !== undefined) this.#deliverRawRequest(request, capture.request, capture.attempts);\n if (capture.last !== undefined) this.#deliverRaw(request, { ...capture.last, attempts: capture.attempts });\n }\n }\n\n /**\n * Dos presupuestos separados: el backoff genérico (`retry.maxRetries`, para `USG_*_BUSY` y\n * los transitorios) y el esquema fijo de `PREVIOUS ENTRY ACTIVE`, que no se ajusta a la config.\n */\n async #attempts(request: SoapRequest, capture: RawCapture): Promise<SoapResponse> {\n const retry = { ...this.#config.retry, ...definedOnly(request.retry ?? {}) };\n let generic = 0;\n let previousEntryActive = 0;\n for (let attempt = 0; ; attempt++) {\n try {\n return await this.#send(request, attempt, capture);\n } catch (error) {\n const reason = retryReason(error, request.idempotent);\n let delayMs: number;\n if (reason === 'previous-entry-active' && previousEntryActive < PREVIOUS_ENTRY_ACTIVE_RETRIES) {\n previousEntryActive++;\n delayMs = PREVIOUS_ENTRY_ACTIVE_DELAY_MS;\n } else if ((reason === 'busy' || reason === 'transient') && generic < retry.maxRetries) {\n delayMs = retryDelay(generic, retry.baseDelayMs, this.#random);\n generic++;\n } else {\n throw error;\n }\n this.#log.emit('warn', 'sabre.request.retry', {\n protocol: 'soap',\n service: request.service,\n action: request.action,\n attempt: attempt + 1,\n reason,\n delayMs,\n error: error as SabreGatewayError,\n });\n await this.#sleep(delayMs, request.signal);\n }\n }\n }\n\n async #send(request: SoapRequest, attempt: number, capture: RawCapture): Promise<SoapResponse> {\n const envelope = this.#envelope(request);\n const logContext = { protocol: 'soap', service: request.service, action: request.action, attempt };\n this.#log.emit('debug', 'sabre.request.start', logContext);\n const startedAt = Date.now();\n\n let response: Response;\n capture.attempts++;\n if (wantsRawRequest(request)) {\n // eb:MessageId y eb:Timestamp se generan en cada intento: se guarda el último sobre.\n capture.request = {\n method: 'POST',\n url: this.#config.soapBaseUrl,\n headers: rawRequestHeaders(SOAP_HEADERS),\n body: redactSoapEnvelope(scrubToken(envelope, request.security)),\n };\n }\n try {\n response = await this.#config.fetch(this.#config.soapBaseUrl, {\n method: 'POST',\n headers: SOAP_HEADERS,\n body: envelope,\n ...(request.signal === undefined ? {} : { signal: request.signal }),\n });\n } catch (cause) {\n if (isAbort(cause, request.signal)) throw cause;\n const error = new SabreGatewayError(`${request.service}: fallo de red (${describe(cause)})`, {\n protocol: 'soap',\n retryable: false,\n cause,\n });\n this.#log.emit('error', 'sabre.request.end', { ...logContext, durationMs: Date.now() - startedAt, error });\n throw error;\n }\n\n const original = await response.text();\n // Todo lo que sale del transporte (raw, errores, logs) se arma desde el texto redactado.\n const text = redactSoapEnvelope(scrubToken(original, request.security));\n capture.last = { status: response.status, headers: response.headers, body: text };\n\n const document = parseEnvelope(text);\n const messageId = stringAt(document?.Header, 'MessageHeader', 'MessageData', 'MessageId');\n const endContext = {\n ...logContext,\n status: response.status,\n durationMs: Date.now() - startedAt,\n ...(messageId === undefined ? {} : { messageId }),\n };\n\n try {\n const result = this.#classify(request, response, document, text);\n this.#log.emit('info', 'sabre.request.end', { ...endContext, warnings: result.warnings.length });\n return {\n ...result,\n messageId,\n respondedAt: respondedAtOf(text),\n raw: text,\n securityToken: request.readSecurityToken === true ? readSecurityToken(original) : undefined,\n status: response.status,\n };\n } catch (error) {\n const level = error instanceof SabreBusinessError ? 'warn' : 'error';\n this.#log.emit(level, 'sabre.request.end', { ...endContext, error });\n throw error;\n }\n }\n\n /** Orden de detección: fault (gateway), luego `stl:Error` (negocio), luego data. */\n #classify(\n request: SoapRequest,\n response: Response,\n document: { Header: unknown; Body: XmlNode } | undefined,\n text: string,\n ): Pick<SoapResponse, 'payload' | 'payloadName' | 'warnings'> {\n const { service } = request;\n if (document === undefined) {\n throw new SabreGatewayError(`${service}: HTTP ${response.status}, la respuesta no es un sobre SOAP`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: text,\n });\n }\n\n // Paso 1: SOAP fault (errores de `Transport` y `Validation`, y los `USG_*` del gateway).\n const fault = asNode(document.Body.Fault);\n if (fault !== undefined) throw faultError(service, response.status, fault, text);\n\n const [payloadName, payloadValue] = firstElement(document.Body);\n const payload = asNode(payloadValue);\n if (payloadName === undefined || payload === undefined) {\n throw new SabreGatewayError(`${service}: HTTP ${response.status}, el sobre SOAP no trae payload`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: text,\n });\n }\n if (!response.ok) {\n throw new SabreGatewayError(`${service}: HTTP ${response.status}`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: text,\n });\n }\n\n // Paso 3: `stl:ApplicationResults`. Los `stl:Warning` no lanzan.\n const results = asNode(payload.ApplicationResults);\n const warnings = asArray(results?.Warning).map((node) => {\n const entry = resultEntry(node);\n return new SabreWarning(`${service}: ${entry.description}`, { service, code: entry.code, raw: text });\n });\n const errors = asArray(results?.Error).map((node) => {\n const entry = resultEntry(node);\n return new SabreBusinessError(`${service}: ${entry.description}`, {\n service,\n code: entry.code,\n raw: text,\n retryable: PREVIOUS_ENTRY_ACTIVE.test(entry.description),\n });\n });\n const [first, ...rest] = errors;\n if (first !== undefined) {\n throw new SabreBusinessError(first.message, {\n service,\n code: first.code,\n raw: text,\n retryable: first.retryable,\n warnings,\n errors: rest,\n });\n }\n\n // Paso 4: data.\n return { payload, payloadName, warnings };\n }\n\n #envelope(request: SoapRequest): string {\n const timestamp = this.#now().toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n return [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:eb=\"http://www.ebxml.org/namespaces/messageHeader\">',\n '<soap-env:Header>',\n '<eb:MessageHeader soap-env:mustUnderstand=\"1\" eb:version=\"1.0\">',\n '<eb:From><eb:PartyId/></eb:From>',\n '<eb:To><eb:PartyId/></eb:To>',\n `<eb:CPAId>${xmlEscape(request.cpaId)}</eb:CPAId>`,\n `<eb:ConversationId>${xmlEscape(request.conversationId)}</eb:ConversationId>`,\n `<eb:Service>${xmlEscape(request.action)}</eb:Service>`,\n `<eb:Action>${xmlEscape(request.action)}</eb:Action>`,\n '<eb:MessageData>',\n `<eb:MessageId>mid:${xmlEscape(this.#messageId())}</eb:MessageId>`,\n `<eb:Timestamp>${timestamp}</eb:Timestamp>`,\n '</eb:MessageData>',\n '</eb:MessageHeader>',\n securityHeader(request.security),\n '</soap-env:Header>',\n `<soap-env:Body>${request.payload}</soap-env:Body>`,\n '</soap-env:Envelope>',\n ].join('');\n }\n\n /** Un callback que lanza no rompe la operación (mismo criterio que REST). */\n #deliverRawRequest(request: SoapRequest, raw: RawRequestCapture, attempts: number): void {\n const operation = request.operation ?? request.service;\n try {\n request.onRawRequest?.({ operation, protocol: 'soap', ...raw, attempts });\n } catch (error) {\n this.#log.emit('warn', 'sabre.request.rawRequestHookFailed', {\n service: request.service,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n }\n\n /** Un callback que lanza no rompe la operación (mismo criterio que REST). */\n #deliverRaw(request: SoapRequest, raw: Required<RawCapture>['last'] & { attempts: number }): void {\n if (request.onRawResponse === undefined) return;\n const operation = request.operation ?? request.service;\n try {\n request.onRawResponse({ operation, protocol: 'soap', ...raw });\n } catch (error) {\n this.#log.emit('warn', 'sabre.request.rawResponseHookFailed', {\n service: request.service,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n }\n}\n\n/** Escapa texto para un elemento o un atributo XML. */\n/**\n * `eb:Timestamp` del header de un sobre de respuesta, en ISO 8601 UTC: Sabre lo manda sin zona\n * (`\"2026-11-06T17:34:16\"`) y en UTC (comparado con `stl:Success@timeStamp`, que trae `Z`, en\n * CERT el 2026-11-06), así que se le agrega `Z`. Con una zona explícita queda tal cual. Si no\n * viene o no tiene forma de fecha y hora, `undefined`. Ver ADR-027 (C1).\n */\nexport function respondedAtOf(raw: unknown): string | undefined {\n if (typeof raw !== 'string') return undefined;\n const header = /<(?:[\\w-]+:)?Header\\b[\\s\\S]*?<\\/(?:[\\w-]+:)?Header>/.exec(raw)?.[0];\n const value = header === undefined ? undefined : /<(?:[\\w-]+:)?Timestamp>\\s*([^<\\s]+)\\s*</.exec(header)?.[1];\n const match = value === undefined ? null : /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?)(Z|[+-]\\d{2}:\\d{2})?$/.exec(value);\n if (match === null) return undefined;\n return `${match[1]}${match[2] ?? 'Z'}`;\n}\n\n/** `{ respondedAt }` si el sobre lo trae; si no, nada (`exactOptionalPropertyTypes`). */\nexport function respondedAtField(raw: unknown): { respondedAt?: string } {\n const respondedAt = respondedAtOf(raw);\n return respondedAt === undefined ? {} : { respondedAt };\n}\n\nexport function xmlEscape(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\nfunction securityHeader(security: SoapSecurity): string {\n const open = '<wsse:Security xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2002/12/secext\">';\n if ('binarySecurityToken' in security) {\n return `${open}<wsse:BinarySecurityToken valueType=\"String\" EncodingType=\"wsse:Base64Binary\">${xmlEscape(security.binarySecurityToken)}</wsse:BinarySecurityToken></wsse:Security>`;\n }\n const token = security.usernameToken;\n return [\n open,\n '<wsse:UsernameToken>',\n `<wsse:Username>${xmlEscape(token.username)}</wsse:Username>`,\n `<wsse:Password>${xmlEscape(token.password)}</wsse:Password>`,\n `<Organization>${xmlEscape(token.organization)}</Organization>`,\n `<Domain>${xmlEscape(token.domain)}</Domain>`,\n token.clientId === undefined ? '' : `<ClientId>${xmlEscape(token.clientId)}</ClientId>`,\n token.clientSecret === undefined ? '' : `<ClientSecret>${xmlEscape(token.clientSecret)}</ClientSecret>`,\n '</wsse:UsernameToken>',\n '</wsse:Security>',\n ].join('');\n}\n\n/**\n * Tapa el token que mandó el SDK donde sea que Sabre lo repita (p. ej. dentro de un\n * `faultstring`), en texto plano o escapado. El `BinarySecurityToken` del header lo tapa\n * después `redactSoapEnvelope`.\n */\n/** `onRawRequest` solo con token de sesión: el sobre de `SessionCreateRQ` es la credencial. */\nfunction wantsRawRequest(request: SoapRequest): boolean {\n return request.onRawRequest !== undefined && 'binarySecurityToken' in request.security;\n}\n\nfunction scrubToken(text: string, security: SoapSecurity): string {\n if (!('binarySecurityToken' in security) || security.binarySecurityToken === '') return text;\n const token = security.binarySecurityToken;\n return text.split(token).join(REDACTED).split(xmlEscape(token)).join(REDACTED);\n}\n\nfunction parseEnvelope(text: string, xmlParser = parser): { Header: unknown; Body: XmlNode } | undefined {\n if (text.trim() === '') return undefined;\n let parsed: unknown;\n try {\n parsed = xmlParser.parse(text);\n } catch {\n return undefined;\n }\n const envelope = asNode(asNode(parsed)?.Envelope);\n const body = asNode(envelope?.Body);\n if (envelope === undefined || body === undefined) return undefined;\n return { Header: envelope.Header, Body: body };\n}\n\n/** Lee el token del texto original, antes de redactar. Solo para `SessionCreateRS`. */\nfunction readSecurityToken(original: string): string | undefined {\n const document = parseEnvelope(original);\n const token = stringAt(document?.Header, 'Security', 'BinarySecurityToken');\n return token === undefined || token.trim() === '' ? undefined : token.trim();\n}\n\n/**\n * `USG_*` dentro del fault, best-effort: ninguna fuente dice en qué campo viaja. Se busca en\n * `faultcode`, `faultstring` y `detail`, y si no aparece se usa el `faultcode`. Se confirma\n * con la primera sesión real (#95).\n */\nconst USG_CODE = /\\bUSG_[A-Z0-9_]+\\b/;\n\nfunction faultError(service: string, status: number, fault: XmlNode, text: string): SabreGatewayError {\n const faultcode = textOf(fault.faultcode);\n const faultstring = textOf(fault.faultstring);\n const haystack = [faultcode, faultstring, JSON.stringify(fault.detail ?? '')].join(' ');\n const code = USG_CODE.exec(haystack)?.[0] ?? faultcode;\n const detail = [faultcode, faultstring].filter((part) => part !== undefined && part !== '').join(': ');\n // `retryable: true` solo para `USG_*_BUSY` y `PREVIOUS ENTRY ACTIVE` (decisiones 4 y 5).\n const retryable = (code !== undefined && BUSY_CODES.has(code)) || PREVIOUS_ENTRY_ACTIVE.test(haystack);\n return new SabreGatewayError(`${service}: SOAP fault${detail === '' ? '' : ` ${detail}`}`, {\n protocol: 'soap',\n status,\n retryable,\n raw: text,\n ...(code === undefined || code === '' ? {} : { code }),\n });\n}\n\n/**\n * Un `stl:Error` o `stl:Warning`: `code` es el primer `Message@code`, o el primer `ShortText` si\n * no viene (las respuestas reales traen el `ERR.SWS.*` ahí, #96), o el `type`. La descripción junta\n * los textos de `Message` con el `ShortText`.\n */\nfunction resultEntry(node: unknown): { code: string; description: string } {\n const entry = asNode(node) ?? {};\n const messages: string[] = [];\n const shortTexts: string[] = [];\n let code: string | undefined;\n for (const results of asArray(entry.SystemSpecificResults)) {\n const resultsNode = asNode(results) ?? {};\n for (const message of asArray(resultsNode.Message)) {\n code ??= nonEmpty(asNode(message)?.['@code']);\n const value = textOf(message);\n if (value !== undefined && value !== '') messages.push(value);\n }\n for (const shortText of asArray(resultsNode.ShortText)) {\n const value = textOf(shortText);\n if (value !== undefined && value !== '') shortTexts.push(value);\n }\n }\n const type = nonEmpty(entry['@type']);\n const description = [\n messages.join(' / ') || type || 'sin detalle',\n ...shortTexts.filter((short) => !messages.includes(short)).map((short) => `(${short})`),\n ].join(' ');\n return { code: code ?? shortTexts[0] ?? type ?? 'UNKNOWN', description };\n}\n\n/**\n * Por qué se puede reintentar un error, según la idempotencia de la operación. Ver\n * tier-3-sesion-y-colas-soap.md (punto 5) y politica-de-reintentos-y-backoff.md.\n */\nfunction retryReason(error: unknown, idempotent: boolean): RetryReason | undefined {\n if ((error instanceof SabreBusinessError || error instanceof SabreGatewayError) && PREVIOUS_ENTRY_ACTIVE.test(error.message)) {\n return 'previous-entry-active';\n }\n if (!(error instanceof SabreGatewayError) || error.protocol !== 'soap') return undefined;\n if (error.code !== undefined && BUSY_CODES.has(error.code)) return 'busy';\n // Lo que sigue pudo haber llegado a Sabre: solo se repite si la operación es idempotente.\n if (!idempotent) return undefined;\n if (error.code !== undefined) return TRANSIENT_CODES.has(error.code) ? 'transient' : undefined;\n // Sin código: un fallo de red (sin status) o una respuesta sin sobre SOAP.\n if (error.status === undefined || TRANSIENT_STATUS.has(error.status)) return 'transient';\n return undefined;\n}\n\n/**\n * El payload del `Body` de `raw` con los textos tal cual, sin recortar espacios ni saltos de\n * línea. Para las pantallas de host (`SabreCommandLLSRS`), que van alineadas por columna: el\n * parser compartido recorta y desalinea la primera línea.\n */\nexport function untrimmedPayload(raw: string): Record<string, unknown> | undefined {\n const document = parseEnvelope(raw, untrimmedParser);\n return document === undefined ? undefined : asNode(firstElement(document.Body)[1]);\n}\n\nfunction firstElement(node: XmlNode): [string | undefined, unknown] {\n for (const [key, value] of Object.entries(node)) {\n if (!key.startsWith('@') && key !== '#text') return [key, Array.isArray(value) ? value[0] : value];\n }\n return [undefined, undefined];\n}\n\nfunction asNode(value: unknown): XmlNode | undefined {\n if (Array.isArray(value)) return asNode(value[0]);\n return typeof value === 'object' && value !== null ? (value as XmlNode) : undefined;\n}\n\nexport function asArray(value: unknown): unknown[] {\n if (value === undefined || value === null || value === '') return [];\n return Array.isArray(value) ? value : [value];\n}\n\n/** Texto de un elemento: un string, o el `#text` de un elemento con atributos. */\nexport function textOf(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n const node = asNode(value);\n const text = node?.['#text'];\n return typeof text === 'string' ? text : node === undefined ? undefined : '';\n}\n\nfunction stringAt(root: unknown, ...path: string[]): string | undefined {\n let node: unknown = root;\n for (const key of path) node = asNode(node)?.[key];\n return nonEmpty(textOf(node));\n}\n\nfunction nonEmpty(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction isAbort(error: unknown, signal: AbortSignal | undefined): boolean {\n return signal?.aborted === true || (error instanceof Error && error.name === 'AbortError');\n}\n\nfunction describe(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n","// Credenciales de `SessionCreateRQ`, sacadas del mismo `username` EPR que autentica en REST.\n// Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 1 y \"Decisiones tomadas en la\n// revisión\") y wiki/entities/oauth-token-create.md (formatos del EPR).\nimport type { SabreCredentials, SabreCredentialsV2 } from '../config.js';\n\n/** Versión de `SessionCreateRQ`: 2.0.0 con `clientId`/`clientSecret`, 1.0.0 sin ellos. */\nexport type SessionCreateVersion = '2.0.0' | '1.0.0';\n\n/** Lo que pide el `wsse:UsernameToken` de `SessionCreateRQ`, ya separado. */\nexport interface SessionCredentials {\n version: SessionCreateVersion;\n /** Usuario EPR, sin PCC ni domain. */\n username: string;\n password: string;\n /** PCC: `Organization` del `UsernameToken` y `eb:CPAId`. Default de las operaciones de cola. */\n organization: string;\n domain: string;\n /** Solo en la 2.0.0. */\n clientId?: string;\n /** Solo en la 2.0.0. */\n clientSecret?: string;\n}\n\n/** 3 o 4 caracteres alfanuméricos. */\nconst PCC = /^[A-Za-z0-9]{3,4}$/;\n\n/** Si el texto es un PCC: 3 o 4 caracteres alfanuméricos. */\nexport function isPseudoCityCode(value: unknown): value is string {\n return typeof value === 'string' && PCC.test(value);\n}\n\n/** Prefijo del EPR de OAuth v2: `V1:<user>:<PCC>:<domain>`. */\nconst V2_PREFIX = 'V1:';\n\nconst FORMATS = \"'V1:<user>:<PCC>:<domain>' (OAuth v2) o '<user>-<PCC>-<domain>' (OAuth v3)\";\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/**\n * Separa usuario, PCC y domain del `username` EPR, leyendo de derecha a izquierda: el último\n * campo es el domain, el anterior el PCC y lo que queda es el usuario. Así un usuario con `-`\n * o `:` no rompe el formato. Los mensajes de error no repiten el `username`.\n */\nexport function parseEprUsername(username: string): { username: string; organization: string; domain: string } {\n const v2 = username.startsWith(V2_PREFIX);\n const fields = (v2 ? username.slice(V2_PREFIX.length) : username).split(v2 ? ':' : '-');\n if (fields.length < 3) fail(`credentials.username debe tener el formato ${FORMATS} para abrir una sesión SOAP`);\n\n const domain = fields.pop()!;\n const organization = fields.pop()!;\n const user = fields.join(v2 ? ':' : '-');\n if (user.trim() === '' || domain.trim() === '') {\n fail(`credentials.username debe tener el formato ${FORMATS} para abrir una sesión SOAP`);\n }\n if (!PCC.test(organization)) {\n fail('el PCC de credentials.username debe tener 3 o 4 caracteres alfanuméricos');\n }\n return { username: user, organization, domain };\n}\n\n/**\n * Credenciales de sesión a partir de las de la config. La versión sale de los datos, sin\n * fallback: con `clientId` y `clientSecret`, 2.0.0; sin ninguno, 1.0.0; con uno solo, error de\n * configuración.\n */\nexport function resolveSessionCredentials(\n credentials: Readonly<SabreCredentials | SabreCredentialsV2>,\n): SessionCredentials {\n const { clientId, clientSecret, password } = credentials;\n if ((clientId === undefined) !== (clientSecret === undefined)) {\n fail('credentials.clientId y credentials.clientSecret van juntos: pasa los dos (SessionCreateRQ 2.0.0) o ninguno (1.0.0)');\n }\n const epr = parseEprUsername(credentials.username);\n if (clientId === undefined || clientSecret === undefined) return { version: '1.0.0', ...epr, password };\n\n if (typeof clientId !== 'string' || clientId.trim() === '') fail('credentials.clientId debe ser un string no vacío');\n if (typeof clientSecret !== 'string' || clientSecret.trim() === '') {\n fail('credentials.clientSecret debe ser un string no vacío');\n }\n return { version: '2.0.0', ...epr, password, clientId, clientSecret };\n}\n","// Access Queue (`QueueAccessLLSRQ` 2.1.1): entrar a una cola y navegarla. Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (puntos 2, 3 y 4) y\n// wiki/sources/access-queue-v2-1-1-design.md.\nimport { XMLParser } from 'fast-xml-parser';\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreBusinessError, SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, textOf, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport { type QueueRef, queueRefAttribute } from './queue-ref.js';\n\nexport const QUEUE_ACCESS_SERVICE = 'queueAccess';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\n/** Texto exacto del fin de cola. Es la respuesta normal cuando no queda ningún PNR. */\nexport const END_OF_DISPLAY = 'END OF DISPLAY FOR REQUESTED DATA';\n/**\n * Una cola vacía, como `stl:Error` de `access` y `list` (producción, #96). Las fuentes solo\n * mostraban `END OF DISPLAY`.\n */\nexport const QUEUE_EMPTY = 'QUEUE SELECTED WAS EMPTY';\n/** `QXI` con la sesión fuera de una cola, como `stl:Error` (producción, #96). */\nexport const OFF_QUEUE = 'CANNOT DO THIS IF OFF QUEUE';\n\n/** Por qué terminó la cola: el fin de cola de siempre o una cola vacía al entrar. */\nexport type QueueEndReason = 'end-of-display' | 'empty';\n\n/** Máximo de filtros de `selection` y de colas de `remove({ from })`, según el design 2.1.1. */\nexport const MAX_SELECTIONS = 8;\nexport const MAX_REMOVE_FROM = 3;\n\n/**\n * Un filtro al entrar a una cola: un calificador de host, p. ej. `{ function: 'AL', criteria: 'DL' }`\n * (solo los PNR de esa aerolínea). Las reglas de combinación las valida Sabre.\n */\nexport interface QueueSelection {\n function: string;\n criteria: string;\n}\n\nexport interface QueueAccessRequest {\n queue: QueueRef;\n /** PCC de la cola. Por defecto, el de la sesión. */\n pcc?: string;\n /** Hasta 8 filtros. Con selección, la cola abre solo los PNR que cumplen el criterio. */\n selection?: readonly QueueSelection[];\n}\n\n/** Una cola de la que `remove` saca el PNR actual. */\nexport interface QueueRemoveTarget {\n queue: QueueRef;\n /** Por defecto, el PCC de la sesión. */\n pcc?: string;\n}\n\nexport interface QueueRemoveRequest {\n /** De 1 a 3 colas de las que sacar el PNR actual a la vez. Sin `from`, sale de la cola en curso. */\n from?: readonly QueueRemoveTarget[];\n}\n\nexport type QueueAccessOptions = RequestOptions;\nexport type QueueNavigationOptions = RequestOptions;\n\n/** El PNR en el que quedó parada la cola. */\nexport interface QueueItem {\n /** Localizador: `Line/UniqueID@ID`. */\n locator: string;\n /**\n * `Line/DateTime`, tal cual llegó: con año en las respuestas reales (`\"2024-05-15T13:24\"`), sin\n * año en el design (`\"12-21T07:00\"`). Al entrar a una cola (`access`, `ignore`, `remove`, `place`)\n * es la **última modificación del PNR**, no la colocación en la cola: para un mismo PNR no\n * coincide con el de `list`, que sí es la colocación (producción, #96 y #155). Se devuelve tal cual.\n */\n placedAt?: string;\n /** `Line/POS/Source`: quién colocó el PNR. `agentSine` puede ser `SABRE`. */\n placedBy?: { agentSine?: string; pseudoCityCode?: string };\n /** `Line/PassengerName`. Las respuestas reales de entrar a una cola no lo traen. */\n primaryPassenger?: string;\n /** `Line/Group`. Las respuestas reales de entrar a una cola no lo traen. */\n group?: string;\n /**\n * `Paragraph/Text`: el PNR en formato de host, línea por línea y tal cual, con su sangría. Las\n * líneas vacías llegan como `\"\"`. Se interpreta con `parseQueueParagraph`.\n */\n paragraph: readonly string[];\n}\n\n/**\n * Un mensaje de la cola `S`, la de mensajes del PCC (ADR-028). No es un PNR: no trae localizador\n * ni datos de colocación, solo texto libre.\n */\nexport interface QueueMessage {\n /** `Paragraph/Text`, línea por línea y tal cual, con su sangría. */\n text: string[];\n}\n\n/**\n * Resultado de una operación que avanza en la cola. Lo que queda en pantalla se distingue por\n * `kind`: un PNR (`'pnr'`, en las colas numéricas y con nombre) o un mensaje (`'message'`, en la\n * cola `S`). El fin de cola es un resultado, no un error: `END OF DISPLAY FOR REQUESTED DATA`\n * llega como `{ done: true }`, también al entrar a una cola vacía, y deja la sesión fuera de la\n * cola.\n */\nexport type QueueStep =\n | { done: false; kind: 'pnr'; item: QueueItem; warnings: SabreWarning[]; respondedAt?: string }\n | { done: false; kind: 'message'; message: QueueMessage; warnings: SabreWarning[]; respondedAt?: string }\n | { done: true; reason: QueueEndReason; message: string; warnings: SabreWarning[]; respondedAt?: string };\n\n/** Qué acción de navegación se manda en `Navigation@Action`. */\ntype NavigationAction = 'I' | 'QR' | 'QXI';\n\nconst OPERATIONS: Record<NavigationAction, string> = { I: 'queue.ignore', QR: 'queue.remove', QXI: 'queue.exit' };\n\nfunction root(body: string): string {\n return `<QueueAccessRQ Version=\"2.1.1\" xmlns=\"${NAMESPACE}\">${body}</QueueAccessRQ>`;\n}\n\nfunction identifier(queue: QueueRef, pcc: string): string {\n return `<QueueIdentifier ${queueRefAttribute(queue)} PseudoCityCode=\"${xmlEscape(pcc)}\"/>`;\n}\n\n/** Los `Selection`, hermanos de `QueueIdentifier`. Los usan `access` y `list`. */\nexport function selectionXml(selection: readonly QueueSelection[]): string {\n return selection\n .map((filter) => `<Selection Function=\"${xmlEscape(filter.function)}\" Criteria=\"${xmlEscape(filter.criteria)}\"/>`)\n .join('');\n}\n\n/** `Q/<PCC><cola>`, con los filtros de `Selection` si los hay. */\nexport function queueAccessPayload(queue: QueueRef, pcc: string, selection: readonly QueueSelection[] = []): string {\n return root(`${identifier(queue, pcc)}${selectionXml(selection)}`);\n}\n\n/** `Navigation@Action`. Solo `QR` lleva `QueueIdentifier`: las colas de las que sacar el PNR. */\nexport function queueNavigationPayload(action: NavigationAction, from: ReadonlyArray<{ queue: QueueRef; pcc: string }> = []): string {\n return root(`<Navigation Action=\"${action}\"/>${from.map((target) => identifier(target.queue, target.pcc)).join('')}`);\n}\n\n/**\n * Las operaciones de Access Queue mueven el cursor: no se reintentan ante un fallo de red. El\n * transporte solo las repite ante `USG_*_BUSY` y `PREVIOUS ENTRY ACTIVE`.\n */\nexport function queueAccessRequest(payload: string, operation: string, options: RequestOptions): SessionRequest {\n return { service: QUEUE_ACCESS_SERVICE, action: 'QueueAccessLLSRQ', payload, idempotent: false, operation, ...options };\n}\n\nexport function navigationOperation(action: NavigationAction): string {\n return OPERATIONS[action];\n}\n\n/**\n * Parser aparte para el `Paragraph`: el del transporte recorta los espacios, y el formato de host\n * usa la sangría. Se vuelve a leer el sobre (ya redactado) sin recortar.\n */\nconst paragraphParser = new XMLParser({\n ignoreAttributes: true,\n removeNSPrefix: true,\n parseTagValue: false,\n trimValues: false,\n processEntities: true,\n isArray: (name) => name === 'Text',\n});\n\nexport type XmlNode = Record<string, unknown>;\n\nexport function node(value: unknown): XmlNode | undefined {\n if (Array.isArray(value)) return node(value[0]);\n return typeof value === 'object' && value !== null ? (value as XmlNode) : undefined;\n}\n\nexport function attribute(value: unknown, name: string): string | undefined {\n const text = node(value)?.[`@${name}`];\n return typeof text === 'string' && text.trim() !== '' ? text.trim() : undefined;\n}\n\nfunction element(value: unknown): string | undefined {\n const text = textOf(Array.isArray(value) ? value[0] : value)?.trim();\n return text === undefined || text === '' ? undefined : text;\n}\n\n/**\n * Las líneas `Text` de una respuesta, tal cual: las de `Paragraph` en `QueueAccessRS` y las del\n * primer nivel en `QueuePlaceRS`.\n */\nexport function textLines(raw: string, payloadName: 'QueueAccessRS' | 'QueuePlaceRS'): string[] {\n let parsed: unknown;\n try {\n parsed = paragraphParser.parse(raw);\n } catch {\n return [];\n }\n const payload = node(node(node(node(parsed)?.Envelope)?.Body)?.[payloadName]);\n const container = payloadName === 'QueueAccessRS' ? node(payload?.Paragraph) : payload;\n return asArray(container?.Text).map((line) => (typeof line === 'string' ? line : (textOf(line) ?? '')));\n}\n\n/** Las líneas de `Paragraph/Text` de un `QueueAccessRS`, tal cual. */\nexport function paragraphLines(raw: string): string[] {\n return textLines(raw, 'QueueAccessRS');\n}\n\n/** Si un texto de Sabre es el fin de cola, comparado por el texto exacto. */\nexport function isEndOfDisplay(text: string | undefined): boolean {\n return text?.trim() === END_OF_DISPLAY;\n}\n\n/**\n * Si un `stl:Warning` o `stl:Error` es el fin de cola. El transporte junta los `Message` con\n * `\" / \"` y agrega el `ShortText` entre paréntesis, así que se busca el texto como una de esas\n * partes, entero.\n */\nexport function isEndOfDisplayResult(error: { message: string; service: string }): boolean {\n return resultHasText(error, END_OF_DISPLAY);\n}\n\n/** Si un `stl:Warning` o `stl:Error` trae `text` como una de sus partes, entero. */\nexport function resultHasText(error: { message: string; service: string }, text: string): boolean {\n const prefix = `${error.service}: `;\n const description = error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message;\n return description\n .split(/ \\/ | \\(|\\)/)\n .some((part) => part.trim() === text);\n}\n\n/**\n * El fin de cola, si llegó como `stl:Error` de `service`: `END OF DISPLAY` o una cola vacía\n * (`QUEUE SELECTED WAS EMPTY`). Si no, `undefined`.\n */\nexport function queueEndError(error: unknown, service: string): { reason: QueueEndReason; error: SabreBusinessError } | undefined {\n if (!(error instanceof SabreBusinessError) || error.service !== service) return undefined;\n const results = [error, ...error.errors];\n if (results.some((result) => resultHasText(result, QUEUE_EMPTY))) return { reason: 'empty', error };\n if (results.some(isEndOfDisplayResult)) return { reason: 'end-of-display', error };\n return undefined;\n}\n\n/** Si el error es el de `QXI` con la sesión fuera de una cola. */\nexport function isOffQueueError(error: unknown): error is SabreBusinessError {\n return error instanceof SabreBusinessError && [error, ...error.errors].some((result) => resultHasText(result, OFF_QUEUE));\n}\n\n/** El fin de cola. `raw` es el sobre del que sale `respondedAt`: la respuesta o el `stl:Error`. */\nexport function endStep(warnings: SabreWarning[], reason: QueueEndReason = 'end-of-display', raw?: unknown): QueueStep {\n return { done: true, reason, message: reason === 'empty' ? QUEUE_EMPTY : END_OF_DISPLAY, warnings, ...respondedAtField(raw) };\n}\n\n/**\n * Lee el paso de un `QueueAccessRS`. El fin de cola llega como primera línea del `Paragraph`\n * (evidencia de `1.0.8`, y la cola `S` en CERT) o como `stl:Warning`. Con `messages` (la sesión\n * está en la cola `S`), un `Paragraph` sin `Line` es un mensaje (CERT, 2026-11-06). Fuera de la\n * `S`, un `Line` sin localizador es una respuesta que el SDK no entiende: lanza\n * `SabreGatewayError`. En la `S`, un `Line` con localizador también lanza.\n */\nexport function parseQueueStep(response: SoapResponse, { messages = false }: { messages?: boolean } = {}): QueueStep {\n const { warnings } = response;\n const paragraph = paragraphLines(response.raw);\n const firstLine = paragraph.find((line) => line.trim() !== '');\n if (isEndOfDisplay(firstLine) || warnings.some(isEndOfDisplayResult)) return endStep(warnings, 'end-of-display', response.raw);\n\n if (messages && response.payload.Line === undefined && firstLine !== undefined) {\n return { done: false, kind: 'message', message: { text: paragraph }, warnings, ...respondedAtField(response.raw) };\n }\n const fields = messages ? undefined : lineFields(response.payload.Line);\n if (fields === undefined) {\n const expected = messages ? 'sin Paragraph de mensaje ni fin de cola en la cola S' : 'sin Line/UniqueID ni fin de cola';\n throw new SabreGatewayError(`${QUEUE_ACCESS_SERVICE}: respuesta no reconocida (${expected})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n const item: QueueItem = { ...fields, paragraph };\n return { done: false, kind: 'pnr', item, warnings, ...respondedAtField(response.raw) };\n}\n\n/** Los campos de un `Line`, o `undefined` si no trae `UniqueID`. */\nexport function lineFields(value: unknown): Omit<QueueItem, 'paragraph'> | undefined {\n const line = node(value);\n const locator = attribute(line?.UniqueID, 'ID');\n if (line === undefined || locator === undefined) return undefined;\n const source = node(node(line.POS)?.Source);\n const agentSine = attribute(source, 'AgentSine');\n const pseudoCityCode = attribute(source, 'PseudoCityCode');\n const placedAt = element(line.DateTime);\n const primaryPassenger = element(line.PassengerName);\n const group = element(line.Group);\n return {\n locator,\n ...(placedAt === undefined ? {} : { placedAt }),\n ...(agentSine === undefined && pseudoCityCode === undefined\n ? {}\n : {\n placedBy: {\n ...(agentSine === undefined ? {} : { agentSine }),\n ...(pseudoCityCode === undefined ? {} : { pseudoCityCode }),\n },\n }),\n ...(primaryPassenger === undefined ? {} : { primaryPassenger }),\n ...(group === undefined ? {} : { group }),\n };\n}\n","// Referencia a una cola de PNR, la misma en la entrada y en la salida. Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 2 y decisiones de la revisión) y\n// wiki/sources/ingresar-a-una-cola.md.\nimport { xmlEscape } from '../http/soap-transport.js';\n\n/**\n * Una cola (ADR-028). Hay tres clases, y viajan por dos atributos distintos de `QueueIdentifier`:\n * - **numérica**, de 0 a 511: `400` → `Number=\"400\"`;\n * - **alfabética**, una o dos letras mayúsculas: `'S'` → `Number=\"S\"`. La `S` es la cola de\n * **mensajes** del PCC (cuenta lo mismo que `Totals Type=\"MESSAGES\"`): no tiene PNR y no se puede\n * listar;\n * - **con nombre** (tablas QN y QNB): `{ name: 'HOTELS' }` → `Name=\"HOTELS\"`.\n *\n * Lo que devuelve `queue.count` se pasa tal cual a las demás operaciones. Las colas 0–49 son del\n * sistema: el SDK no las restringe.\n */\nexport type QueueRef = number | string | { name: string };\n\n/** Primera y última cola numérica de un PCC. */\nexport const MIN_QUEUE_NUMBER = 0;\nexport const MAX_QUEUE_NUMBER = 511;\n\n/** La cola de mensajes del PCC: no tiene PNR y Sabre no la lista (`INVALID ENTRY`). */\nexport const MESSAGE_QUEUE = 'S';\n\n/**\n * Una cola alfabética: una o dos letras mayúsculas. Es una regla laxa a propósito: la documentación\n * solo muestra `S` y `A`, y no se sabe si hay colas de dos letras (ADR-028).\n */\nconst ALPHA_QUEUE = /^[A-Z]{1,2}$/;\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/** Valida una `QueueRef` de la entrada, sin red. `label` es el nombre del campo en el mensaje. */\nexport function validateQueueRef(value: unknown, label: string): asserts value is QueueRef {\n if (typeof value === 'number') {\n if (Number.isInteger(value) && value >= MIN_QUEUE_NUMBER && value <= MAX_QUEUE_NUMBER) return;\n fail(`${label} debe ser un número de cola entero de ${MIN_QUEUE_NUMBER} a ${MAX_QUEUE_NUMBER}, una cola alfabética ('S') o { name }`);\n }\n if (typeof value === 'string') {\n if (ALPHA_QUEUE.test(value)) return;\n // Cada cola tiene una sola forma: '12' no se convierte en 12, ni 's' en 'S' (ADR-028).\n if (/^\\d+$/.test(value.trim())) fail(`${label}: una cola numérica va como número (${Number(value)}), no como string`);\n fail(`${label} debe ser una cola alfabética de una o dos letras mayúsculas (p. ej. 'S')`);\n }\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const { name } = value as { name?: unknown };\n if (typeof name !== 'string' || name.trim() === '') fail(`${label}.name debe ser un string no vacío`);\n // Un { name } de una o dos letras es casi seguro una cola alfabética mal armada, p. ej. el\n // { name: 'S' } que devolvía count en la 0.4.x: Sabre lo rechaza con INVALID QUEUE NAME FORMAT.\n // Ninguna fuente confirma que no existan colas con nombre tan cortas: si aparece una, se afloja\n // esta regla, y eso no rompe la compatibilidad (ADR-028, sub-decisión ii).\n if (ALPHA_QUEUE.test(name)) fail(`${label}: '${name}' es una cola alfabética: pasa '${name}', no { name: '${name}' }`);\n return;\n }\n fail(`${label} debe ser un número de cola (0–511), una cola alfabética ('S') o { name }`);\n}\n\n/** Atributo de `QueueIdentifier`: `Number=\"12\"`, `Number=\"S\"` o `Name=\"HOTELS\"`, ya escapado. */\nexport function queueRefAttribute(queue: QueueRef): string {\n if (typeof queue === 'number') return `Number=\"${queue}\"`;\n if (typeof queue === 'string') return `Number=\"${xmlEscape(queue)}\"`;\n return `Name=\"${xmlEscape(queue.name)}\"`;\n}\n\n/** Si la cola es la de mensajes (`'S'`). */\nexport function isMessageQueue(queue: QueueRef): boolean {\n return queue === MESSAGE_QUEUE;\n}\n\n/**\n * Lee el `Number` de una respuesta (`QueueCountRS`, `QueuePlaceRS`, `QueueAnalysisRS`): `\"12\"` da\n * `12`, y `\"S\"`, `'S'`. Devuelve `undefined` si viene vacío. Un `Number` que no es ni numérico ni\n * alfabético sale tal cual, como string: es lo que mandó Sabre.\n */\nexport function toQueueRef(value: string | undefined): QueueRef | undefined {\n const text = value?.trim();\n if (text === undefined || text === '') return undefined;\n return /^\\d+$/.test(text) ? Number(text) : text;\n}\n","// Get Queue Count (`QueueCountLLSRQ` 2.2.1). Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md\n// (punto 2) y wiki/entities/queue-management.md (Get Queue Count y respuestas reales).\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport { type QueueRef, toQueueRef } from './queue-ref.js';\n\nexport const QUEUE_COUNT_SERVICE = 'queueCount';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\nexport interface QueueCountRequest {\n /** PCC cuyas colas se cuentan. Por defecto, el de la sesión. */\n pcc?: string;\n}\n\nexport type QueueCountOptions = RequestOptions;\n\n/** Una cola con mensajes o PNR. */\nexport interface QueueCount {\n queue: QueueRef;\n count: number;\n}\n\nexport interface QueueCountResponse {\n /** Las colas que trae la respuesta, en el orden de Sabre. Sabre no lista las vacías. */\n queues: QueueCount[];\n /**\n * Los `Totals` por `Type`: `MESSAGES`, `SPECIALS` y `PNRS`. Si Sabre no manda alguno, queda en\n * `undefined`.\n */\n totals: { messages?: number; specials?: number; pnrs?: number };\n /**\n * `QueueInfo@DateTime` tal cual llegó, sin año (`\"06-25T09:46\"`): la hora del host al contar.\n * Es un hecho pasado, así que el año se resuelve hacia atrás desde una fecha de referencia.\n */\n countedAt?: string;\n /** Los `stl:Warning` de la respuesta. No lanzan. */\n warnings: SabreWarning[];\n /**\n * `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC (`\"2026-11-06T17:34:16Z\"`). A\n * diferencia de las fechas del host, trae año y zona. Falta si Sabre no lo manda.\n */\n respondedAt?: string;\n}\n\nconst TOTAL_TYPES = { MESSAGES: 'messages', SPECIALS: 'specials', PNRS: 'pnrs' } as const;\n\n/** Cuerpo de `QueueCountRQ`: solo el PCC, para contar todas sus colas. */\nexport function queueCountPayload(pcc: string): string {\n return `<QueueCountRQ Version=\"2.2.1\" xmlns=\"${NAMESPACE}\"><QueueInfo><QueueIdentifier PseudoCityCode=\"${xmlEscape(pcc)}\"/></QueueInfo></QueueCountRQ>`;\n}\n\n/** `QueueCountLLSRQ` es una lectura: se reintenta ante `USG_*_BUSY`, transitorios y red. */\nexport function queueCountRequest(pcc: string, options: QueueCountOptions): SessionRequest {\n return {\n service: QUEUE_COUNT_SERVICE,\n action: 'QueueCountLLSRQ',\n payload: queueCountPayload(pcc),\n idempotent: true,\n operation: 'queue.count',\n ...options,\n };\n}\n\n/**\n * Normaliza un `Count` de Sabre a número. Llega con relleno de puntos, como en la documentación\n * (`\"....261\"`), o sin él, como en las respuestas reales (`\"6\"`). Devuelve `undefined` si no es\n * un entero con ese formato.\n */\nexport function parseHostCount(value: string | undefined): number | undefined {\n const match = /^[.\\s]*(\\d+)\\s*$/.exec(value ?? '');\n return match === null ? undefined : Number(match[1]);\n}\n\ntype XmlNode = Record<string, unknown>;\n\nfunction attribute(node: unknown, name: string): string | undefined {\n const value = (node as XmlNode | undefined)?.[`@${name}`];\n return typeof value === 'string' ? value : undefined;\n}\n\n/**\n * Lee `QueueCountRS`. Si falta una sección, queda vacía o en `undefined`. Un `Number` o un `Count`\n * que no se puede leer es una respuesta que el SDK no entiende: lanza `SabreGatewayError` antes\n * que devolver una cuenta equivocada.\n */\nexport function parseQueueCountResponse(response: SoapResponse): QueueCountResponse {\n const queues: QueueCount[] = [];\n let countedAt: string | undefined;\n for (const info of asArray(response.payload.QueueInfo)) {\n countedAt ??= nonEmpty(attribute(info, 'DateTime'));\n for (const identifier of asArray((info as XmlNode).QueueIdentifier)) {\n // `Number` trae las numéricas y las alfabéticas (\"400\", \"S\"); `Name`, las colas con nombre\n // (ADR-028). Las respuestas reales solo traen `Number`, pero se lee igual que en place.\n const number = attribute(identifier, 'Number');\n const name = nonEmpty(attribute(identifier, 'Name'));\n const queue: QueueRef | undefined = number === undefined && name !== undefined ? { name } : toQueueRef(number);\n const count = parseHostCount(attribute(identifier, 'Count'));\n if (queue === undefined || count === undefined) {\n throw malformed(`QueueIdentifier con Number=\"${number ?? ''}\" y Count=\"${attribute(identifier, 'Count') ?? ''}\"`, response);\n }\n queues.push({ queue, count });\n }\n }\n\n const totals: QueueCountResponse['totals'] = {};\n for (const total of asArray(response.payload.Totals)) {\n const key = TOTAL_TYPES[(attribute(total, 'Type') ?? '').toUpperCase() as keyof typeof TOTAL_TYPES];\n if (key === undefined) continue;\n const count = parseHostCount(attribute(total, 'Count'));\n if (count === undefined) throw malformed(`Totals ${key} con Count=\"${attribute(total, 'Count') ?? ''}\"`, response);\n totals[key] = count;\n }\n\n return {\n queues,\n totals,\n ...(countedAt === undefined ? {} : { countedAt }),\n warnings: response.warnings,\n ...respondedAtField(response.raw),\n };\n}\n\nfunction malformed(detail: string, response: SoapResponse): SabreGatewayError {\n return new SabreGatewayError(`${QUEUE_COUNT_SERVICE}: respuesta no reconocida (${detail})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n}\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n const text = value?.trim();\n return text === undefined || text === '' ? undefined : text;\n}\n","// Lista de una cola (`QueueAccessLLSRQ` 2.1.1 con `List@Ind`): sus localizadores, sin recorrerla.\n// Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 2) y\n// wiki/sources/access-queue-v2-1-1-design.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport {\n attribute,\n isEndOfDisplay,\n isEndOfDisplayResult,\n lineFields,\n paragraphLines,\n QUEUE_ACCESS_SERVICE,\n type QueueItem,\n type QueueSelection,\n selectionXml,\n} from './queue-access.js';\nimport { type QueueRef, queueRefAttribute } from './queue-ref.js';\n\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\nexport interface QueueListRequest {\n queue: QueueRef;\n /** PCC de la cola. Por defecto, el de la sesión. */\n pcc?: string;\n /** `true` para pedir también el pasajero principal de cada PNR (`Q/…/LN`). */\n primaryPassenger?: boolean;\n /**\n * Hasta 8 filtros, como en `access`, pero Sabre solo acepta `QD` (fecha de colocación en la cola,\n * p. ej. `{ function: 'QD', criteria: '05NOV' }`) o `AK` (el agente que lo colocó, PCC más firma,\n * p. ej. `{ function: 'AK', criteria: 'PCC1AAT' }`) en la lista: con otro código responde\n * `VALID SELECTION CODE FOR QUEUE LIST ARE QD OR AK` (producción, #155). El SDK lo rechaza sin red.\n */\n selection?: readonly QueueSelection[];\n}\n\n/**\n * Los únicos códigos de `Selection` que Sabre acepta en la lista (producción, #155): `QD`, la fecha\n * de colocación en la cola, y `AK`, el agente que colocó el PNR (`AK-<PCC><firma>`, según\n * wiki/sources/funciones-de-seleccion-de-colas.md). `QD` se probó en `list`; `AK` no.\n */\nexport const LIST_SELECTION_FUNCTIONS: readonly string[] = ['QD', 'AK'];\n\nexport type QueueListOptions = RequestOptions;\n\n/**\n * Un PNR de la lista: los campos de su `Line`. Su `placedAt` es la **colocación en la cola**, la\n * fecha por la que filtra `QD`. No es la misma fecha que el `placedAt` de `access`, que es la última\n * modificación del PNR (producción, #155).\n */\nexport interface QueueListEntry extends Omit<QueueItem, 'paragraph'> {\n /** `Line@Number`: la posición en la lista. */\n position?: number;\n}\n\nexport interface QueueListResponse {\n /** Los localizadores, en el orden de la cola. */\n locators: string[];\n /** Un elemento por PNR, en el mismo orden que `locators`. */\n entries: QueueListEntry[];\n /** `Paragraph/Text` tal cual: empieza con la cabecera `QUEUE LIST FOR <PCC> QUEUE <n>`. */\n paragraph: string[];\n warnings: SabreWarning[];\n /**\n * `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC (`\"2026-11-06T17:34:16Z\"`). A\n * diferencia de las fechas del host, trae año y zona. Falta si Sabre no lo manda.\n */\n respondedAt?: string;\n}\n\n/** `Q/<PCC><cola>/L`. Los `Selection` van después de `QueueIdentifier`, como en `access`. */\nexport function queueListPayload(\n queue: QueueRef,\n pcc: string,\n primaryPassenger: boolean,\n selection: readonly QueueSelection[] = [],\n): string {\n const list = primaryPassenger ? '<List Ind=\"true\" PrimaryPassenger=\"true\"/>' : '<List Ind=\"true\"/>';\n return `<QueueAccessRQ Version=\"2.1.1\" xmlns=\"${NAMESPACE}\"><QueueIdentifier ${queueRefAttribute(queue)} PseudoCityCode=\"${xmlEscape(pcc)}\">${list}</QueueIdentifier>${selectionXml(selection)}</QueueAccessRQ>`;\n}\n\n/** `list` es una lectura (decisión de la revisión): se reintenta como `count`. */\nexport function queueListRequest(payload: string, options: QueueListOptions): SessionRequest {\n return {\n service: QUEUE_ACCESS_SERVICE,\n action: 'QueueAccessLLSRQ',\n payload,\n idempotent: true,\n operation: 'queue.list',\n ...options,\n };\n}\n\nexport function emptyList(warnings: SabreWarning[], paragraph: string[] = [], raw?: unknown): QueueListResponse {\n return { locators: [], entries: [], paragraph, warnings, ...respondedAtField(raw) };\n}\n\n/**\n * Lee la lista. No pagina: Sabre devuelve la cola entera en una sola respuesta (1221 `Line` en\n * ~279 KB, producción, #155). Una cola vacía (fin de cola como primera línea o como `stl:Warning`) da una lista\n * vacía. Un `Line` sin `UniqueID` es una respuesta que el SDK no entiende: lanza\n * `SabreGatewayError`.\n */\nexport function parseQueueList(response: SoapResponse): QueueListResponse {\n const { warnings } = response;\n const paragraph = paragraphLines(response.raw);\n const firstLine = paragraph.find((line) => line.trim() !== '');\n if (isEndOfDisplay(firstLine) || warnings.some(isEndOfDisplayResult)) return emptyList(warnings, paragraph, response.raw);\n\n const entries = asArray(response.payload.Line).map((line): QueueListEntry => {\n const fields = lineFields(line);\n if (fields === undefined) {\n throw new SabreGatewayError(`${QUEUE_ACCESS_SERVICE}: respuesta no reconocida (Line sin UniqueID en la lista)`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n const number = attribute(line, 'Number');\n const position = number !== undefined && /^\\d+$/.test(number) ? Number(number) : undefined;\n return { ...(position === undefined ? {} : { position }), ...fields };\n });\n return { locators: entries.map((entry) => entry.locator), entries, paragraph, warnings, ...respondedAtField(response.raw) };\n}\n","// Get Queue Activity (`QueueAnalysisLLSRQ` 2.0.0). Ver\n// sabre-wiki/wiki/proyectos/sabre-client/decisiones/tier-4-colas-avanzadas.md (A1),\n// wiki/sources/get-queue-activity-v2-0-0-design.md y wiki/entities/queue-management.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport { parseHostCount } from './queue-count.js';\nimport { type QueueRef, toQueueRef } from './queue-ref.js';\n\nexport const QUEUE_ACTIVITY_SERVICE = 'queueAnalysis';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\nexport interface QueueActivityRequest {\n /** PCC cuyas colas se analizan. Por defecto, el de la sesión. */\n pcc?: string;\n}\n\nexport type QueueActivityOptions = RequestOptions;\n\n/**\n * Los ocho contadores de Get Queue Activity, con los nombres de Sabre. La pantalla `QA` del host los\n * muestra en columnas (`ON Q`, `REMOVD`, …). Ninguna fuente dice desde cuándo cuentan (Q-097): el\n * SDK los devuelve sin interpretar.\n */\nexport interface QueueActivityCounters {\n /** `NumMessages`: los mensajes o PNR que están hoy en la cola (`ON Q`). */\n numMessages: number;\n /** `Ended`: los terminados en la cola. */\n ended: number;\n /** `Ignored`: los ignorados (`I`). */\n ignored: number;\n /** `Moved`: los movidos a otra cola. */\n moved: number;\n /** `Removed`: los sacados de la cola (`QR`). */\n removed: number;\n /** `Transferred`: los transferidos. */\n transferred: number;\n /** `LeftMessageToContact`: con un mensaje dejado al contacto. */\n leftMessageToContact: number;\n /** `UnableToReach`: los que no se pudo contactar. */\n unableToReach: number;\n}\n\n/** Los contadores de una cola. Sabre lista también colas vacías con contadores. */\nexport interface QueueActivity extends QueueActivityCounters {\n /** La cola, como en `count`: `400`, `'S'` o `{ name }`. Se pasa tal cual a las demás operaciones. */\n queue: QueueRef;\n}\n\nexport interface QueueActivityResponse {\n /** Las colas que trae la respuesta, en el orden de Sabre. */\n queues: QueueActivity[];\n /** `Totals`: los ocho contadores sumados para el PCC. Sin `Totals`, `undefined`. */\n totals?: QueueActivityCounters;\n /**\n * `QueueInfo@DateTime` tal cual llegó, sin año (`\"11-06T11:33\"`): la hora del host al analizar.\n * Es un hecho pasado, así que el año se resuelve hacia atrás, como `countedAt`.\n */\n analyzedAt?: string;\n /** Los `stl:Warning` de la respuesta. No lanzan. */\n warnings: SabreWarning[];\n /** `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC. Falta si Sabre no lo manda. */\n respondedAt?: string;\n}\n\n/** Elemento de Sabre → contador. */\nconst COUNTERS: ReadonlyArray<[string, keyof QueueActivityCounters]> = [\n ['NumMessages', 'numMessages'],\n ['Ended', 'ended'],\n ['Ignored', 'ignored'],\n ['Moved', 'moved'],\n ['Removed', 'removed'],\n ['Transferred', 'transferred'],\n ['LeftMessageToContact', 'leftMessageToContact'],\n ['UnableToReach', 'unableToReach'],\n];\n\n/** Cuerpo de `QueueAnalysisRQ`: solo el PCC, para analizar todas sus colas (`QA/<PCC>`). */\nexport function queueActivityPayload(pcc: string): string {\n return `<QueueAnalysisRQ Version=\"2.0.0\" xmlns=\"${NAMESPACE}\"><QueueInfo><QueueIdentifier PseudoCityCode=\"${xmlEscape(pcc)}\"/></QueueInfo></QueueAnalysisRQ>`;\n}\n\n/**\n * `QueueAnalysisLLSRQ` es una lectura: se reintenta ante `USG_*_BUSY`, transitorios y red. No pide\n * duty code 9, aunque el sample lo diga (CERT y producción, Q-098).\n */\nexport function queueActivityRequest(pcc: string, options: QueueActivityOptions): SessionRequest {\n return {\n service: QUEUE_ACTIVITY_SERVICE,\n action: 'QueueAnalysisLLSRQ',\n payload: queueActivityPayload(pcc),\n idempotent: true,\n operation: 'queue.activity',\n ...options,\n };\n}\n\ntype XmlNode = Record<string, unknown>;\n\nfunction attribute(node: unknown, name: string): string | undefined {\n const value = (Array.isArray(node) ? node[0] : (node as XmlNode | undefined))?.[`@${name}`];\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n const text = value?.trim();\n return text === undefined || text === '' ? undefined : text;\n}\n\n/**\n * Lee `QueueAnalysisRS`. Un `Number` que no se puede leer, o un contador que falta o no es un\n * entero, es una respuesta que el SDK no entiende: lanza `SabreGatewayError` antes que devolver un\n * contador equivocado.\n */\nexport function parseQueueActivityResponse(response: SoapResponse): QueueActivityResponse {\n const queues: QueueActivity[] = [];\n let analyzedAt: string | undefined;\n for (const info of asArray(response.payload.QueueInfo)) {\n analyzedAt ??= nonEmpty(attribute(info, 'DateTime'));\n for (const identifier of asArray((info as XmlNode).QueueIdentifier)) {\n // `Number` trae las numéricas y las alfabéticas (\"400\", \"S\"); `Name`, las con nombre (ADR-028).\n const number = attribute(identifier, 'Number');\n const name = nonEmpty(attribute(identifier, 'Name'));\n const queue: QueueRef | undefined = number === undefined && name !== undefined ? { name } : toQueueRef(number);\n if (queue === undefined) throw malformed(`QueueIdentifier con Number=\"${number ?? ''}\"`, response);\n queues.push({ queue, ...counters(identifier, `la cola ${number ?? name}`, response) });\n }\n }\n const totalsNode = asArray(response.payload.Totals)[0];\n const totals = totalsNode === undefined ? undefined : counters(totalsNode, 'Totals', response);\n\n return {\n queues,\n ...(totals === undefined ? {} : { totals }),\n ...(analyzedAt === undefined ? {} : { analyzedAt }),\n warnings: response.warnings,\n ...respondedAtField(response.raw),\n };\n}\n\nfunction counters(node: unknown, label: string, response: SoapResponse): QueueActivityCounters {\n const result = {} as QueueActivityCounters;\n for (const [element, key] of COUNTERS) {\n const raw = attribute((node as XmlNode)[element], 'Count');\n const count = parseHostCount(raw);\n if (count === undefined) throw malformed(`${label} con ${element} Count=\"${raw ?? ''}\"`, response);\n result[key] = count;\n }\n return result;\n}\n\nfunction malformed(detail: string, response: SoapResponse): SabreGatewayError {\n return new SabreGatewayError(`${QUEUE_ACTIVITY_SERVICE}: respuesta no reconocida (${detail})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n}\n","// Place Queue Message (`QueuePlaceLLSRQ` 2.0.4): colocar PNR en colas. Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 2, \"place\"),\n// wiki/sources/place-queue-message-v2-0-4-design.md y wiki/sources/sabre-legacy-client-1-0-8.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport {\n attribute,\n endStep,\n isEndOfDisplay,\n isEndOfDisplayResult,\n node,\n type QueueStep,\n textLines,\n} from './queue-access.js';\nimport { type QueueRef, queueRefAttribute, toQueueRef } from './queue-ref.js';\n\nexport const QUEUE_PLACE_SERVICE = 'queuePlace';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\n/** Límites del design 2.0.4: hasta 10 colas y hasta 6 localizadores. */\nexport const MAX_PLACE_TO = 10;\nexport const MAX_PLACE_LOCATORS = 6;\n\n/** Rangos de PIC válidos (`PrefatoryInstructionCode`), según el artículo de selección de colas. */\nconst INSTRUCTION_CODE_RANGES: ReadonlyArray<readonly [number, number]> = [\n [0, 191],\n [200, 254],\n];\n\n/** Una cola de destino. */\nexport interface QueuePlaceTarget {\n queue: QueueRef;\n /** Por defecto, el PCC de la sesión. */\n pcc?: string;\n /**\n * Código PIC (`PrefatoryInstructionCode`): 0–191 o 200–254. **Obligatorio**, aunque el design\n * 2.0.4 lo da como opcional: sin PIC, producción rechaza el place con `INSTRUCTION NUMBER NOT IN\n * RANGE` fuera de una cola y con `NEED INSTRUCTION NUMBER` dentro (#97). Sin valor por defecto.\n */\n instructionCode: number;\n}\n\nexport interface QueuePlaceRequest {\n /** De 1 a 10 colas de destino. */\n to: readonly QueuePlaceTarget[];\n /**\n * Hasta 6 localizadores a colocar, sin tenerlos en el AAA. Solo fuera de una cola: dentro,\n * `place` coloca el PNR actual.\n */\n locators?: readonly string[];\n}\n\nexport type QueuePlaceOptions = RequestOptions;\n\n/** Una colocación que confirma Sabre (`QueueInfo`). */\nexport interface QueuePlacement {\n queue?: QueueRef;\n pcc?: string;\n locator?: string;\n /** `QueueInfo@DateTime` tal cual, sin año (`\"12-21T12:00\"`). */\n placedAt?: string;\n}\n\n/** Lo que devuelve `place` fuera de una cola: no avanza nada. */\nexport interface QueuePlaceResult {\n /** Las colocaciones de `QueueInfo`, si Sabre las manda. */\n placements: QueuePlacement[];\n /** Las líneas `Text`, tal cual (p. ej. `\"OK 1030 NMIUTF\"`). */\n text: string[];\n warnings: SabreWarning[];\n /**\n * `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC (`\"2026-11-06T17:34:16Z\"`). A\n * diferencia de las fechas del host, trae año y zona. Falta si Sabre no lo manda.\n */\n respondedAt?: string;\n}\n\n/**\n * Lo que devuelve `place`: un `QueueStep` dentro de una cola, y un `QueuePlaceResult` fuera. Se\n * distinguen con `'done' in result`. Con `locators`, el tipo ya es `QueuePlaceResult`.\n */\nexport type QueuePlaceResponse = QueueStep | QueuePlaceResult;\n\n/** Destino ya validado, con el PCC resuelto. */\nexport interface ResolvedPlaceTarget {\n queue: QueueRef;\n pcc: string;\n instructionCode?: number;\n}\n\n/** Si un PIC está en los rangos válidos. */\nexport function isInstructionCode(value: unknown): value is number {\n return (\n typeof value === 'number' &&\n Number.isInteger(value) &&\n INSTRUCTION_CODE_RANGES.some(([min, max]) => value >= min && value <= max)\n );\n}\n\nexport function queuePlacePayload(to: readonly ResolvedPlaceTarget[], locators: readonly string[] = []): string {\n const identifiers = to\n .map((target) => {\n const pic = target.instructionCode === undefined ? '' : ` PrefatoryInstructionCode=\"${target.instructionCode}\"`;\n return `<QueueIdentifier ${queueRefAttribute(target.queue)}${pic} PseudoCityCode=\"${xmlEscape(target.pcc)}\"/>`;\n })\n .join('');\n const ids = locators.map((locator) => `<UniqueID ID=\"${xmlEscape(locator)}\"/>`).join('');\n return `<QueuePlaceRQ Version=\"2.0.4\" xmlns=\"${NAMESPACE}\"><QueueInfo>${identifiers}${ids}</QueueInfo></QueuePlaceRQ>`;\n}\n\n/** Colocar no es idempotente: dentro de una cola mueve el cursor, y fuera repetiría la colocación. */\nexport function queuePlaceRequest(payload: string, options: QueuePlaceOptions): SessionRequest {\n return {\n service: QUEUE_PLACE_SERVICE,\n action: 'QueuePlaceLLSRQ',\n payload,\n idempotent: false,\n operation: 'queue.place',\n ...options,\n };\n}\n\n/**\n * Línea de firma del PNR, al final del texto: `<PCC>.<PCC>*<agente> HHMM/DDMMMYY <localizador> H`,\n * p. ej. `7TZA.7TZA*AW5 0319/06SEP24 NGDEZP H`.\n */\nconst SIGNATURE_LINE = /\\s\\d{4}\\/\\d{2}[A-Z]{3}\\d{2}\\s+([A-Z0-9]{6})\\s+H\\s*$/;\n\n/** El localizador de la última línea de firma del texto, si hay una. */\nexport function signatureLocator(lines: readonly string[]): string | undefined {\n for (let index = lines.length - 1; index >= 0; index--) {\n const match = SIGNATURE_LINE.exec(lines[index] ?? '');\n if (match !== null) return match[1];\n }\n return undefined;\n}\n\n/** El fin de cola de `place`: como `stl:Warning` (evidencia de `1.0.8`) o como primera línea. */\nfunction isEnd(response: SoapResponse, text: readonly string[]): boolean {\n return response.warnings.some(isEndOfDisplayResult) || isEndOfDisplay(text.find((line) => line.trim() !== ''));\n}\n\n/**\n * Dentro de una cola, `QueuePlaceRS` trae el PNR siguiente en `Text` y no trae `Line`: el\n * localizador sale de la línea de firma, y `placedAt` y `placedBy` quedan en `undefined`, porque\n * esa firma es la última modificación del PNR y no su colocación en la cola.\n */\nexport function parsePlaceStep(response: SoapResponse): QueueStep {\n const text = textLines(response.raw, 'QueuePlaceRS');\n if (isEnd(response, text)) return endStep(response.warnings, 'end-of-display', response.raw);\n const locator = signatureLocator(text);\n if (locator === undefined) {\n throw new SabreGatewayError(`${QUEUE_PLACE_SERVICE}: respuesta no reconocida (sin línea de firma del PNR ni fin de cola)`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n return { done: false, kind: 'pnr', item: { locator, paragraph: text }, warnings: response.warnings, ...respondedAtField(response.raw) };\n}\n\n/**\n * Lo que `place` puede leer con la sesión en `'unknown'`: un fin de cola, un PNR con línea de\n * firma (seguía en la cola) o, si no, un `QueuePlaceResult`.\n */\nexport function parsePlaceUnknown(response: SoapResponse): QueuePlaceResponse {\n const text = textLines(response.raw, 'QueuePlaceRS');\n if (isEnd(response, text) || signatureLocator(text) !== undefined) return parsePlaceStep(response);\n return parsePlaceResult(response);\n}\n\n/** Fuera de una cola: las colocaciones de `QueueInfo` y el texto. */\nexport function parsePlaceResult(response: SoapResponse): QueuePlaceResult {\n const placements = asArray(response.payload.QueueInfo).map((info): QueuePlacement => {\n const identifier = node(node(info)?.QueueIdentifier);\n // `Number` es alfanumérico (\"400\" o \"S\"); `Name` es siempre un nombre.\n const number = attribute(identifier, 'Number');\n const name = attribute(identifier, 'Name');\n const queue: QueueRef | undefined = number !== undefined ? toQueueRef(number) : name !== undefined ? { name } : undefined;\n const pcc = attribute(identifier, 'PseudoCityCode');\n const locator = attribute(node(info)?.UniqueID, 'ID');\n const placedAt = attribute(info, 'DateTime');\n return {\n ...(queue === undefined ? {} : { queue }),\n ...(pcc === undefined ? {} : { pcc }),\n ...(locator === undefined ? {} : { locator }),\n ...(placedAt === undefined ? {} : { placedAt }),\n };\n });\n return {\n placements,\n text: textLines(response.raw, 'QueuePlaceRS'),\n warnings: response.warnings,\n ...respondedAtField(response.raw),\n };\n}\n","// Módulo de dominio `session.queue` (Queue Management). Las operaciones viven en la sesión porque\n// necesitan su estado. Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 2 y\n// decisiones de la revisión).\nimport { SabreBusinessError, SabreGatewayError, SabreSessionError } from '../errors/index.js';\nimport type { EventLogger } from '../logging/logger.js';\nimport type { SoapResponse } from '../http/soap-transport.js';\nimport { isPseudoCityCode } from '../session/credentials.js';\nimport type { SessionRequest } from '../session/session.js';\nimport {\n isOffQueueError,\n queueEndError,\n endStep,\n MAX_REMOVE_FROM,\n MAX_SELECTIONS,\n navigationOperation,\n type QueueAccessOptions,\n type QueueAccessRequest,\n queueAccessPayload,\n queueAccessRequest,\n type QueueNavigationOptions,\n queueNavigationPayload,\n type QueueRemoveRequest,\n type QueueEndReason,\n type QueueItem,\n type QueueSelection,\n type QueueStep,\n parseQueueStep,\n} from './queue-access.js';\nimport {\n type QueueCountOptions,\n type QueueCountRequest,\n type QueueCountResponse,\n parseQueueCountResponse,\n queueCountRequest,\n} from './queue-count.js';\nimport {\n emptyList,\n LIST_SELECTION_FUNCTIONS,\n parseQueueList,\n type QueueListOptions,\n type QueueListRequest,\n type QueueListResponse,\n queueListPayload,\n queueListRequest,\n} from './queue-list.js';\nimport {\n parseQueueActivityResponse,\n type QueueActivityOptions,\n type QueueActivityRequest,\n type QueueActivityResponse,\n queueActivityRequest,\n} from './queue-activity.js';\nimport {\n isInstructionCode,\n type QueuePlaceTarget,\n MAX_PLACE_LOCATORS,\n MAX_PLACE_TO,\n parsePlaceResult,\n parsePlaceStep,\n parsePlaceUnknown,\n type QueuePlaceOptions,\n type QueuePlaceRequest,\n type QueuePlaceResponse,\n type QueuePlaceResult,\n queuePlacePayload,\n queuePlaceRequest,\n type ResolvedPlaceTarget,\n} from './queue-place.js';\nimport { isMessageQueue, type QueueRef, validateQueueRef } from './queue-ref.js';\n\n/**\n * Dónde está la sesión respecto de las colas: `'outside'`, `'inside'` (hay un PNR de una cola en\n * el AAA) o `'unknown'` (una operación falló dentro de una cola, o un `access` falló sin respuesta\n * de Sabre, y no se sabe si Sabre dejó la sesión adentro). De `'unknown'` se sale con `exit()`.\n */\nexport type QueueState = 'outside' | 'inside' | 'unknown';\n\n/** Qué hacer con un PNR en `queue.process`. */\nexport type QueueProcessAction =\n | { action: 'remove' }\n | { action: 'ignore' }\n | { action: 'place'; to: readonly QueuePlaceTarget[] };\n\nexport interface QueueProcessRequest extends QueueAccessRequest {\n /** Cuántos PNR visitar como máximo. Al llegar, sale con `QXI`. Sin tope por defecto. */\n limit?: number;\n}\n\nexport interface QueueProcessResult {\n /** Cuántos PNR se pasaron al callback. */\n visited: number;\n /** Por qué terminó: el fin de cola, una cola vacía al entrar, o `limit`. */\n ended: QueueEndReason | 'limit';\n}\n\n/** @internal Lo que la sesión le presta al módulo de colas. */\nexport interface QueueContext {\n /** Una llamada a Sabre dentro de la sesión, con uso exclusivo. */\n send(request: SessionRequest): Promise<SoapResponse>;\n /** PCC de la sesión: el default de cada operación. */\n pcc: string;\n log: EventLogger;\n}\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/**\n * Si el error es una respuesta clara de Sabre que rechazó el request: un `stl:Error` o un SOAP\n * fault con código. Un fallo de red, una cancelación o una respuesta que el SDK no entiende no lo\n * son: el request pudo haberse procesado.\n */\nfunction rejectedBySabre(error: unknown): boolean {\n return error instanceof SabreBusinessError || (error instanceof SabreGatewayError && error.code !== undefined);\n}\n\nexport class QueueManagement {\n readonly #context: QueueContext;\n #state: QueueState = 'outside';\n /** Si la última cola a la que se entró es la `S`: ahí cada paso es un mensaje, no un PNR. */\n #messages = false;\n\n /** @internal Lo construye `SabreSession`. */\n constructor(context: QueueContext) {\n this.#context = context;\n }\n\n /**\n * Si la sesión está dentro de una cola. Lo lleva el SDK: `access` con un PNR la deja en\n * `'inside'`, y el fin de cola o `exit()`, en `'outside'`.\n */\n get state(): QueueState {\n return this.#state;\n }\n\n /**\n * Get Queue Count (`QueueCountLLSRQ` 2.2.1): cuántos mensajes o PNR hay en cada cola del PCC,\n * más los totales. Cada `queue` de la respuesta se puede pasar tal cual a las demás operaciones\n * de cola.\n *\n * Se puede llamar dentro o fuera de una cola, y no cambia `state`. Es una lectura: se reintenta\n * ante fallos transitorios. Un PCC que no tiene 3 o 4 caracteres alfanuméricos lanza\n * `TypeError` sin red.\n */\n async count(request: QueueCountRequest = {}, options: QueueCountOptions = {}): Promise<QueueCountResponse> {\n const pcc = this.#pcc(request.pcc, 'pcc');\n const response = await this.#context.send(queueCountRequest(pcc, options));\n return parseQueueCountResponse(response);\n }\n\n /**\n * Get Queue Activity (`QueueAnalysisLLSRQ` 2.0.0, el `QA` del host): por cada cola del PCC, los\n * ocho contadores de actividad (`numMessages`, `ended`, `ignored`, `moved`, `removed`,\n * `transferred`, `leftMessageToContact` y `unableToReach`), más los totales. Cada `queue` se puede\n * pasar tal cual a las demás operaciones de cola. Ninguna fuente dice desde cuándo cuentan\n * (Q-097): el SDK los devuelve sin interpretar.\n *\n * Se puede llamar dentro o fuera de una cola, y no cambia `state`. Es una lectura: se reintenta\n * ante fallos transitorios. No pide duty code 9 (CERT y producción, Q-098). Un PCC que no tiene 3\n * o 4 caracteres alfanuméricos lanza `TypeError` sin red.\n */\n async activity(request: QueueActivityRequest = {}, options: QueueActivityOptions = {}): Promise<QueueActivityResponse> {\n if (typeof request !== 'object' || request === null) fail('queue.activity recibe { pcc? }');\n const pcc = this.#pcc(request.pcc, 'pcc');\n const response = await this.#context.send(queueActivityRequest(pcc, options));\n return parseQueueActivityResponse(response);\n }\n\n /**\n * La lista de localizadores de una cola (`QueueAccessLLSRQ` con `List`), sin recorrerla. Con\n * `primaryPassenger: true`, cada entrada trae también el pasajero principal. Una cola vacía da\n * una lista vacía.\n *\n * No pagina: Sabre devuelve la cola entera en una respuesta, también con más de 1000 PNR. Con\n * `selection`, solo los PNR que cumplen el filtro; Sabre acepta solo `QD` o `AK` en la lista.\n *\n * No cambia `state`. Es una lectura: se reintenta ante fallos transitorios. Lanza `TypeError`\n * sin red si `queue` o `pcc` no son válidos, si `primaryPassenger` no es un boolean, o si\n * `selection` no es válida o trae un código que no es `QD` ni `AK`.\n */\n async list(request: QueueListRequest, options: QueueListOptions = {}): Promise<QueueListResponse> {\n if (typeof request !== 'object' || request === null) fail('queue.list recibe { queue, pcc?, primaryPassenger?, selection? }');\n validateQueueRef(request.queue, 'queue');\n // Sabre no lista la cola de mensajes de ninguna forma: INVALID ENTRY con Number=\"S\" (ADR-028).\n if (isMessageQueue(request.queue)) fail(\"la cola 'S' es la de mensajes del PCC: no tiene PNR y Sabre no la lista\");\n const pcc = this.#pcc(request.pcc, 'pcc');\n const { primaryPassenger = false } = request;\n if (typeof primaryPassenger !== 'boolean') fail('primaryPassenger debe ser un boolean');\n const selection = validateSelection(request.selection);\n selection.forEach((filter, index) => {\n // Sabre: VALID SELECTION CODE FOR QUEUE LIST ARE QD OR AK (producción, #155).\n if (!LIST_SELECTION_FUNCTIONS.includes(filter.function)) {\n fail(`selection[${index}].function en list solo puede ser ${LIST_SELECTION_FUNCTIONS.join(' o ')}: Sabre no acepta otro código en la lista`);\n }\n });\n const send = queueListRequest(queueListPayload(request.queue, pcc, primaryPassenger, selection), options);\n try {\n return parseQueueList(await this.#context.send(send));\n } catch (error) {\n const end = queueEndError(error, send.service);\n if (end !== undefined) return emptyList([...end.error.warnings], [], end.error.raw);\n throw error;\n }\n }\n\n /**\n * Access Queue (`QueueAccessLLSRQ` 2.1.1): entra a una cola y devuelve su primer PNR\n * (`kind: 'pnr'`). En la cola `S`, la de mensajes, devuelve el primer mensaje\n * (`kind: 'message'`), y `ignore` pasa al siguiente sin borrarlo (CERT, 2026-11-06). Una cola\n * vacía, o sin PNR que cumplan `selection`, devuelve `{ done: true }` y la sesión sigue afuera.\n *\n * Lanza `TypeError` sin red si la sesión ya está dentro de una cola (o en `'unknown'`: hay que\n * llamar a `exit()` primero), si `queue` no es de 0 a 511 o `{ name }`, o con más de 8 filtros.\n * Mueve el cursor: nunca se reintenta ante un fallo de red, y ese fallo deja `state` en\n * `'unknown'`.\n */\n async access(request: QueueAccessRequest, options: QueueAccessOptions = {}): Promise<QueueStep> {\n if (this.#state === 'inside') fail('la sesión ya está dentro de una cola: sal con queue.exit() antes de entrar a otra');\n if (this.#state === 'unknown') fail('no se sabe si la sesión sigue dentro de una cola: llama a queue.exit() antes de entrar');\n if (typeof request !== 'object' || request === null) fail('queue.access recibe { queue, pcc?, selection? }');\n validateQueueRef(request.queue, 'queue');\n const pcc = this.#pcc(request.pcc, 'pcc');\n const selection = validateSelection(request.selection);\n this.#messages = isMessageQueue(request.queue);\n return this.#step(queueAccessRequest(queueAccessPayload(request.queue, pcc, selection), 'queue.access', options));\n }\n\n /**\n * Deja el PNR actual en la cola y pasa al siguiente (`I`). Fuera de una cola lanza `TypeError`\n * sin red.\n */\n async ignore(options: QueueNavigationOptions = {}): Promise<QueueStep> {\n this.#requireQueue('ignore');\n return this.#step(queueAccessRequest(queueNavigationPayload('I'), navigationOperation('I'), options));\n }\n\n /**\n * Saca el PNR actual de la cola y pasa al siguiente (`QR`). Con `from` (de 1 a 3 colas), lo saca\n * de esas colas a la vez. Fuera de una cola lanza `TypeError` sin red. En la cola `S` manda `QR`\n * igual, pero no hay evidencia de qué hace Sabre con el mensaje.\n */\n async remove(request: QueueRemoveRequest = {}, options: QueueNavigationOptions = {}): Promise<QueueStep> {\n this.#requireQueue('remove');\n const from = this.#removeFrom(request.from);\n return this.#step(queueAccessRequest(queueNavigationPayload('QR', from), navigationOperation('QR'), options));\n }\n\n /**\n * Sale de la cola sin cerrar la transacción (`QXI`) y deja `state` en `'outside'`. Fuera de una\n * cola lanza `TypeError` sin red. En `'unknown'` manda `QXI` igual y, si Sabre lo rechaza con\n * `CANNOT DO THIS IF OFF QUEUE` (la sesión ya no estaba en una cola), lo da por bueno. Cualquier\n * otro error lanza y deja `'unknown'`.\n */\n async exit(options: QueueNavigationOptions = {}): Promise<void> {\n this.#requireQueue('exit');\n const before = this.#state;\n const request = queueAccessRequest(queueNavigationPayload('QXI'), navigationOperation('QXI'), options);\n try {\n await this.#context.send(request);\n } catch (error) {\n if (before === 'unknown' && isOffQueueError(error)) {\n // Sabre dice que la sesión ya no estaba en una cola (`CANNOT DO THIS IF OFF QUEUE`,\n // producción, #96): la salida se da por buena. Cualquier otro error lanza.\n this.#context.log.emit('info', 'sabre.queue.exitTolerated', { code: error.code, error });\n this.#state = 'outside';\n return;\n }\n this.#onError(error);\n throw error;\n }\n this.#state = 'outside';\n }\n\n /**\n * Recorre una cola: entra con `access`, llama a `callback` con cada PNR, ejecuta la acción que\n * devuelve (`remove`, `ignore` o `place`) y termina en el fin de cola. No hace nada que no se\n * pueda hacer con las primitivas.\n *\n * - Con `limit`, después de visitar esa cantidad de PNR sale con `QXI`. No tiene tope por\n * defecto: con una cola anómala que nunca llega al fin, el recorrido no termina. Conviene\n * pasarlo.\n * - Si el callback lanza, o devuelve una acción inválida, sale con `QXI` y propaga el error. No\n * lo convierte en `ignore`: para seguir de largo, el callback atrapa su error y devuelve\n * `{ action: 'ignore' }`.\n * - Si una operación falla, sale con `QXI` (tolerando que la sesión ya no esté en la cola) y\n * propaga el error. Con un `SabreSessionError` no intenta salir: la sesión ya no sirve.\n *\n * `options` se aplica a cada llamada a Sabre del recorrido.\n */\n async process(\n request: QueueProcessRequest,\n callback: (item: QueueItem) => QueueProcessAction | Promise<QueueProcessAction>,\n options: QueueNavigationOptions = {},\n ): Promise<QueueProcessResult> {\n if (typeof request !== 'object' || request === null) fail('queue.process recibe { queue, pcc?, selection?, limit? }');\n if (typeof callback !== 'function') fail('queue.process necesita un callback');\n const { limit, ...access } = request;\n // El callback recibe PNR, y sobre un mensaje no hay `place`: la S se recorre a mano (ADR-028).\n if (isMessageQueue(access.queue)) fail(\"queue.process no recorre la cola 'S', la de mensajes: usa queue.access() e queue.ignore()\");\n if (limit !== undefined && !(Number.isInteger(limit) && limit >= 1)) fail('limit debe ser un entero mayor o igual a 1');\n\n // Si la sesión ya estaba en una cola, `access` lanza sin red: esa cola es del consumidor.\n const startedOutside = this.#state === 'outside';\n let visited = 0;\n try {\n let step = await this.access(access, options);\n while (!step.done) {\n if (limit !== undefined && visited >= limit) {\n await this.exit(options);\n return { visited, ended: 'limit' };\n }\n // Fuera de la S no hay mensajes: parseQueueStep solo los lee dentro de ella.\n if (step.kind !== 'pnr') throw new TypeError('sabre-client: queue.process recibió un mensaje en vez de un PNR');\n const action = await callback(step.item);\n visited++;\n step = await this.#processAction(action, options);\n }\n return { visited, ended: step.reason };\n } catch (error) {\n if (startedOutside) await this.#exitQuietly(error, options);\n throw error;\n }\n }\n\n async #processAction(action: unknown, options: QueueNavigationOptions): Promise<QueueStep> {\n const kind = typeof action === 'object' && action !== null ? (action as { action?: unknown }).action : undefined;\n if (kind === 'ignore') return this.ignore(options);\n if (kind === 'remove') return this.remove({}, options);\n if (kind === 'place') {\n const step = await this.place({ to: (action as { to?: QueuePlaceTarget[] }).to as QueuePlaceTarget[] }, options);\n // Dentro de una cola, `place` siempre devuelve un `QueueStep`.\n if (!('done' in step)) throw new TypeError('sabre-client: queue.place no devolvió un paso de la cola');\n return step;\n }\n throw new TypeError(\"sabre-client: el callback de queue.process debe devolver { action: 'remove' }, { action: 'ignore' } o { action: 'place', to }\");\n }\n\n /** Sale de la cola después de un error del recorrido, sin pisar ese error. */\n async #exitQuietly(cause: unknown, options: QueueNavigationOptions): Promise<void> {\n if (this.#state === 'outside' || cause instanceof SabreSessionError) return;\n try {\n await this.exit(options);\n } catch (error) {\n this.#context.log.emit('warn', 'sabre.queue.exitFailed', { error });\n }\n }\n\n /**\n * Place Queue Message (`QueuePlaceLLSRQ` 2.0.4): coloca un PNR en 1 a 10 colas.\n *\n * - **Dentro de una cola**, coloca el PNR actual y devuelve un `QueueStep` con el siguiente,\n * como `ignore` y `remove`. El PNR se mueve: sale de la cola en curso (producción, #97). El localizador sale de la línea de firma del PNR; `placedAt` y\n * `placedBy` quedan en `undefined`. Con `locators` lanza `TypeError` sin red: para colocar\n * otros PNR, primero `exit()`.\n * - **Fuera de una cola**, coloca los `locators` (hasta 6) o el PNR del AAA, no avanza nada y\n * devuelve `{ placements, text, warnings }`.\n *\n * Cada destino necesita `instructionCode` (0–191 o 200–254), sin valor por defecto: sin él\n * lanza `TypeError` sin red, porque Sabre lo exige dentro y fuera de una cola. Nunca se\n * reintenta ante un fallo de red. Errores como `BAD PNR LOCATOR` o `NEED RECEIVED FROM FIELD`\n * salen como `SabreBusinessError` (`service: 'queuePlace'`).\n */\n place(request: QueuePlaceRequest & { locators: readonly string[] }, options?: QueuePlaceOptions): Promise<QueuePlaceResult>;\n place(request: QueuePlaceRequest, options?: QueuePlaceOptions): Promise<QueuePlaceResponse>;\n async place(request: QueuePlaceRequest, options: QueuePlaceOptions = {}): Promise<QueuePlaceResponse> {\n if (typeof request !== 'object' || request === null) fail('queue.place recibe { to, locators? }');\n const to = this.#placeTo(request.to);\n const locators = validateLocators(request.locators);\n if (this.#messages && this.#state !== 'outside') {\n fail(\"queue.place no se puede dentro de la cola 'S': lo que hay en pantalla es un mensaje, no un PNR\");\n }\n if (locators.length > 0 && this.#state === 'inside') {\n fail('queue.place con locators no se puede dentro de una cola, donde coloca el PNR actual: sal con queue.exit() antes');\n }\n if (locators.length > 0 && this.#state === 'unknown') {\n fail('no se sabe si la sesión sigue dentro de una cola: llama a queue.exit() antes de colocar por localizador');\n }\n if (to.some((target) => target.instructionCode === undefined)) {\n fail('queue.place necesita instructionCode en cada destino: Sabre lo exige, dentro y fuera de una cola');\n }\n const send = queuePlaceRequest(queuePlacePayload(to, locators), options);\n // Fuera de una cola, colocar no toca el cursor: el estado no cambia, ni con un error.\n if (this.#state === 'outside') return parsePlaceResult(await this.#context.send(send));\n return this.#advance(send, this.#state === 'inside' ? parsePlaceStep : parsePlaceUnknown);\n }\n\n /** Manda una operación que avanza y actualiza `state` con el resultado. */\n #step(request: SessionRequest): Promise<QueueStep> {\n const messages = this.#messages;\n return this.#advance(request, (response) => parseQueueStep(response, { messages }));\n }\n\n /**\n * Manda una operación que puede mover el cursor. Un `QueueStep` fija el estado: `'outside'` con\n * el fin de cola e `'inside'` con un PNR. Cualquier otro resultado lo deja como estaba.\n */\n async #advance<T extends QueuePlaceResponse>(request: SessionRequest, parse: (response: SoapResponse) => T): Promise<T> {\n let result: T;\n try {\n result = parse(await this.#context.send(request));\n } catch (error) {\n const end = queueEndError(error, request.service);\n if (end !== undefined) {\n this.#state = 'outside';\n return endStep([...end.error.warnings], end.reason, end.error.raw) as T;\n }\n this.#onError(error);\n throw error;\n }\n if ('done' in result) this.#state = result.done ? 'outside' : 'inside';\n return result;\n }\n\n /**\n * Qué pasa con `state` cuando una operación de cola falla. Los `TypeError` del uso exclusivo y\n * los errores de sesión no lo tocan: no llegaron a Sabre, o la sesión ya no sirve. Dentro de una\n * cola, cualquier otro error deja `'unknown'`. Fuera, solo lo que no es un rechazo claro de\n * Sabre (fallo de red, cancelación, respuesta ilegible).\n */\n #onError(error: unknown): void {\n if (error instanceof TypeError || error instanceof SabreSessionError) return;\n if (this.#state === 'outside' && rejectedBySabre(error)) return;\n this.#state = 'unknown';\n }\n\n #placeTo(to: unknown): ResolvedPlaceTarget[] {\n if (!Array.isArray(to) || to.length === 0 || to.length > MAX_PLACE_TO) {\n fail(`to debe ser una lista de 1 a ${MAX_PLACE_TO} colas`);\n }\n return to.map((target: unknown, index) => {\n if (typeof target !== 'object' || target === null) fail(`to[${index}] debe ser { queue, pcc?, instructionCode }`);\n const { queue, pcc, instructionCode } = target as { queue?: unknown; pcc?: unknown; instructionCode?: unknown };\n validateQueueRef(queue, `to[${index}].queue`);\n if (instructionCode !== undefined && !isInstructionCode(instructionCode)) {\n fail(`to[${index}].instructionCode debe ser un entero de 0 a 191 o de 200 a 254`);\n }\n return {\n queue,\n pcc: this.#pcc(pcc, `to[${index}].pcc`),\n ...(instructionCode === undefined ? {} : { instructionCode }),\n };\n });\n }\n\n #requireQueue(operation: string): void {\n if (this.#state === 'outside') fail(`queue.${operation} necesita estar dentro de una cola: entra con queue.access()`);\n }\n\n #pcc(value: unknown, label: string): string {\n if (value === undefined) return this.#context.pcc;\n if (!isPseudoCityCode(value)) fail(`${label} debe tener 3 o 4 caracteres alfanuméricos`);\n return value;\n }\n\n #removeFrom(from: unknown): Array<{ queue: QueueRef; pcc: string }> {\n if (from === undefined) return [];\n if (!Array.isArray(from) || from.length === 0 || from.length > MAX_REMOVE_FROM) {\n fail(`from debe ser una lista de 1 a ${MAX_REMOVE_FROM} colas`);\n }\n return from.map((target: unknown, index) => {\n if (typeof target !== 'object' || target === null) fail(`from[${index}] debe ser { queue, pcc? }`);\n const { queue, pcc } = target as { queue?: unknown; pcc?: unknown };\n validateQueueRef(queue, `from[${index}].queue`);\n return { queue, pcc: this.#pcc(pcc, `from[${index}].pcc`) };\n });\n }\n}\n\nfunction validateLocators(locators: unknown): string[] {\n if (locators === undefined) return [];\n if (!Array.isArray(locators) || locators.length === 0 || locators.length > MAX_PLACE_LOCATORS) {\n fail(`locators debe ser una lista de 1 a ${MAX_PLACE_LOCATORS} localizadores`);\n }\n return locators.map((locator: unknown, index) => {\n if (typeof locator !== 'string' || locator.trim() === '') fail(`locators[${index}] debe ser un string no vacío`);\n return locator;\n });\n}\n\nfunction validateSelection(selection: unknown): QueueSelection[] {\n if (selection === undefined) return [];\n if (!Array.isArray(selection)) fail('selection debe ser una lista de { function, criteria }');\n if (selection.length > MAX_SELECTIONS) fail(`selection admite hasta ${MAX_SELECTIONS} filtros`);\n return selection.map((filter: unknown, index) => {\n const { function: fn, criteria } = (typeof filter === 'object' && filter !== null ? filter : {}) as {\n function?: unknown;\n criteria?: unknown;\n };\n if (typeof fn !== 'string' || fn.trim() === '') fail(`selection[${index}].function debe ser un string no vacío`);\n if (typeof criteria !== 'string' || criteria.trim() === '') {\n fail(`selection[${index}].criteria debe ser un string no vacío`);\n }\n return { function: fn, criteria };\n });\n}\n","// Get Itinerary History (`TravelItineraryHistoryLLSRQ` 2.4.0): el historial de un PNR, el `*H` del\n// host. Ver sabre-wiki/wiki/proyectos/sabre-client/decisiones/tier-4-colas-avanzadas.md (B1),\n// wiki/sources/get-itinerary-history-v2-4-0-design.md y wiki/entities/get-itinerary-history.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, textOf, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\n\nexport const RESERVATION_HISTORY_SERVICE = 'itineraryHistory';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\nexport type ReservationHistoryOptions = RequestOptions;\n\n/**\n * Un elemento con su acción y su texto: `GeneralInfo` o `RemarkInfo/Remark`. Sabre no publica el\n * catálogo de `action`. En CERT llegaron `A4S` (SSR), `A7` (ticketing), `A9` (teléfono), `AN`\n * (nombre), `APE` (email) y `ADT`. La `A` inicial es un alta y la `X`, una baja.\n */\nexport interface ReservationHistoryText {\n action: string;\n /** `Text`, tal cual. Puede traer datos del pasajero. */\n text: string;\n}\n\n/** Un `FlightSegment` del historial, tal como estaba en esa transacción. */\nexport interface ReservationHistoryFlightSegment {\n /** `@Action`: `AS` (alta) o `XS` (baja), según las respuestas y el design. */\n action: string;\n /** `@Status` en ese momento (`HK`, `HKNN`, `UN`…). */\n status?: string;\n /** `MarketingAirline@Code`. */\n marketingAirline?: string;\n /** `@FlightNumber`. */\n flightNumber?: string;\n /** `@ResBookDesigCode`: la clase. */\n bookingClass?: string;\n /** `OriginLocation@LocationCode`. */\n origin?: string;\n /** `DestinationLocation@LocationCode`. */\n destination?: string;\n /** `@DepartureDateTime` tal cual, sin año (`\"12-19T13:10\"`). Se resuelve con `resolveHostDate`. */\n departureDateTime?: string;\n /** `@ArrivalDateTime` tal cual, sin año. */\n arrivalDateTime?: string;\n /** `@NumberInParty`. */\n numberInParty?: number;\n /** `SupplierRef@ID`: el localizador de la aerolínea (`DCAA*DVDMYA`). */\n supplierRef?: string;\n}\n\n/** Una `AccountingInfo` del historial: la línea de contabilidad, sin sus importes. */\nexport interface ReservationHistoryAccounting {\n /** `@Action` (`HK` en el design). */\n action?: string;\n /** `@Type`: `R` reembolso, `G` cambio con reembolso, `E` cambio par, `A` cobro adicional, `L` descuento, `B` bulk. */\n type?: string;\n /** `@LinkCode`. */\n linkCode?: string;\n}\n\n/**\n * Una transacción del historial (`HistoricalInfo`): quién la firmó, cuándo y desde qué PCC\n * (`ItineraryRef/Source`), y los elementos que cambió. Lo que el SDK no tipa (asientos, autos,\n * hoteles, tren, seguros, facturas, importes) queda en la respuesta cruda (`onRawResponse`).\n */\nexport interface ReservationHistoryTransaction {\n /** `@RPH`: el número de la firma de la transacción (`HSTSIG`). */\n rph?: number;\n /** `Source@CreateDateTime`, tal cual: con año y sin zona (`\"2026-11-04T17:15\"`). */\n createdAt?: string;\n /** `Source@CreationAgent`: el sine del agente que firmó. */\n agent?: string;\n /** `Source@CreationAgentDutyCode`. */\n agentDutyCode?: string;\n /** `Source@CreationAgentFunctionCode`. */\n agentFunctionCode?: string;\n /** `Source@PseudoCityCode`: el PCC de la firma del agente. */\n pcc?: string;\n /**\n * `Source@AAA_PseudoCityCode`: el PCC del AAA del agente. El sample lo escribe\n * `AAAPseudoCityCode`, sin guion bajo; el SDK lee los dos.\n */\n aaaPcc?: string;\n /** `Source@ReceivedFrom`: el campo de recibido de la transacción. */\n receivedFrom?: string;\n /** `ItineraryInfo/ReservationItems/Item/FlightSegment`, en orden. */\n flightSegments: ReservationHistoryFlightSegment[];\n /** `GeneralInfo`, en orden: SSR, ticketing, teléfonos, nombres, emails… como texto. */\n generalInfo: ReservationHistoryText[];\n /** `RemarkInfo/Remark`, en orden. */\n remarks: ReservationHistoryText[];\n /** `AccountingInfo`, en orden. */\n accounting: ReservationHistoryAccounting[];\n}\n\nexport interface ReservationHistoryResponse {\n /** Las transacciones (`HistoricalInfo`), en el orden de Sabre. */\n transactions: ReservationHistoryTransaction[];\n /** Los `stl:Warning` de la respuesta. No lanzan. */\n warnings: SabreWarning[];\n /** `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC. Falta si Sabre no lo manda. */\n respondedAt?: string;\n}\n\nconst LOCATOR = /^[A-Z0-9]{6}$/;\n\n/** Si un texto es un localizador de Sabre: 6 caracteres alfanuméricos en mayúscula. */\nexport function isRecordLocator(value: unknown): value is string {\n return typeof value === 'string' && LOCATOR.test(value);\n}\n\n/** Cuerpo de `TravelItineraryHistoryRQ` con el localizador (`JX HST*<localizador>`). */\nexport function reservationHistoryPayload(locator: string): string {\n return `<TravelItineraryHistoryRQ Version=\"2.4.0\" xmlns=\"${NAMESPACE}\"><UniqueID ID=\"${xmlEscape(locator)}\"/></TravelItineraryHistoryRQ>`;\n}\n\n/** Es una lectura: se reintenta ante `USG_*_BUSY`, transitorios y red. */\nexport function reservationHistoryRequest(locator: string, options: ReservationHistoryOptions): SessionRequest {\n return {\n service: RESERVATION_HISTORY_SERVICE,\n action: 'TravelItineraryHistoryLLSRQ',\n payload: reservationHistoryPayload(locator),\n idempotent: true,\n operation: 'reservation.history',\n ...options,\n };\n}\n\ntype XmlNode = Record<string, unknown>;\n\nfunction node(value: unknown): XmlNode | undefined {\n const first = Array.isArray(value) ? value[0] : value;\n return typeof first === 'object' && first !== null ? (first as XmlNode) : undefined;\n}\n\nfunction attribute(value: unknown, name: string): string | undefined {\n const text = node(value)?.[`@${name}`];\n if (typeof text !== 'string') return undefined;\n const trimmed = text.trim();\n return trimmed === '' ? undefined : trimmed;\n}\n\n/** Los campos opcionales que llegaron, sin claves en `undefined`. */\nfunction defined<T extends Record<string, unknown>>(fields: T): { [K in keyof T]?: Exclude<T[K], undefined> } {\n return Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined)) as {\n [K in keyof T]?: Exclude<T[K], undefined>;\n };\n}\n\nfunction integer(value: string | undefined): number | undefined {\n return value !== undefined && /^\\d+$/.test(value) ? Number(value) : undefined;\n}\n\n/**\n * Lee `TravelItineraryHistoryRS`. Un `GeneralInfo`, `Remark` o `FlightSegment` sin `@Action` es una\n * respuesta que el SDK no entiende: lanza `SabreGatewayError`.\n */\nexport function parseReservationHistoryResponse(response: SoapResponse): ReservationHistoryResponse {\n const transactions = asArray(response.payload.HistoricalInfo).map((info) => transaction(node(info) ?? {}, response));\n return { transactions, warnings: response.warnings, ...respondedAtField(response.raw) };\n}\n\nfunction transaction(info: XmlNode, response: SoapResponse): ReservationHistoryTransaction {\n const source = node(node(info.ItineraryRef)?.Source);\n const flightSegments = asArray(node(node(info.ItineraryInfo)?.ReservationItems)?.Item).flatMap((item) =>\n asArray(node(item)?.FlightSegment).map((segment) => flightSegment(node(segment) ?? {}, response)),\n );\n return {\n ...defined({\n rph: integer(attribute(info, 'RPH')),\n createdAt: attribute(source, 'CreateDateTime'),\n agent: attribute(source, 'CreationAgent'),\n agentDutyCode: attribute(source, 'CreationAgentDutyCode'),\n agentFunctionCode: attribute(source, 'CreationAgentFunctionCode'),\n pcc: attribute(source, 'PseudoCityCode'),\n aaaPcc: attribute(source, 'AAA_PseudoCityCode') ?? attribute(source, 'AAAPseudoCityCode'),\n receivedFrom: attribute(source, 'ReceivedFrom'),\n }),\n flightSegments,\n generalInfo: asArray(info.GeneralInfo).map((entry) => textEntry(entry, 'GeneralInfo', response)),\n remarks: asArray(node(info.RemarkInfo)?.Remark).map((entry) => textEntry(entry, 'Remark', response)),\n accounting: asArray(info.AccountingInfo).map((entry) =>\n defined({ action: attribute(entry, 'Action'), type: attribute(entry, 'Type'), linkCode: attribute(entry, 'LinkCode') }),\n ),\n };\n}\n\nfunction textEntry(entry: unknown, label: string, response: SoapResponse): ReservationHistoryText {\n const action = attribute(entry, 'Action');\n if (action === undefined) throw malformed(`${label} sin Action`, response);\n const texts = asArray(node(entry)?.Text).map((text) => textOf(text) ?? '');\n return { action, text: texts.join('\\n') };\n}\n\nfunction flightSegment(segment: XmlNode, response: SoapResponse): ReservationHistoryFlightSegment {\n const action = attribute(segment, 'Action');\n if (action === undefined) throw malformed('FlightSegment sin Action', response);\n return {\n action,\n ...defined({\n status: attribute(segment, 'Status'),\n marketingAirline: attribute(segment.MarketingAirline, 'Code'),\n flightNumber: attribute(segment, 'FlightNumber') ?? attribute(segment.MarketingAirline, 'FlightNumber'),\n bookingClass: attribute(segment, 'ResBookDesigCode'),\n origin: attribute(segment.OriginLocation, 'LocationCode'),\n destination: attribute(segment.DestinationLocation, 'LocationCode'),\n departureDateTime: attribute(segment, 'DepartureDateTime'),\n arrivalDateTime: attribute(segment, 'ArrivalDateTime'),\n numberInParty: integer(attribute(segment, 'NumberInParty')),\n supplierRef: attribute(segment.SupplierRef, 'ID'),\n }),\n };\n}\n\nfunction malformed(detail: string, response: SoapResponse): SabreGatewayError {\n return new SabreGatewayError(`${RESERVATION_HISTORY_SERVICE}: respuesta no reconocida (${detail})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n}\n","// La reserva dentro de una sesión SOAP: hoy, solo el historial (B1 de ADR-027).\nimport type { SoapResponse } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport {\n isRecordLocator,\n parseReservationHistoryResponse,\n type ReservationHistoryOptions,\n type ReservationHistoryResponse,\n reservationHistoryRequest,\n} from './reservation-history.js';\n\n/** @internal Lo que `SessionReservation` necesita de la sesión. */\nexport interface ReservationContext {\n send(request: SessionRequest): Promise<SoapResponse>;\n}\n\nexport class SessionReservation {\n readonly #context: ReservationContext;\n\n /** @internal Lo construye `SabreSession`. */\n constructor(context: ReservationContext) {\n this.#context = context;\n }\n\n /**\n * Get Itinerary History (`TravelItineraryHistoryLLSRQ` 2.4.0, el `*H` del host): el historial\n * del PNR, una entrada por transacción. Cada una trae quién la firmó, cuándo y desde qué PCC, y\n * los elementos que cambió con su `action`: los segmentos de vuelo con su estado en ese momento,\n * y SSR, ticketing, teléfonos, nombres y emails como texto en `generalInfo`. Lo que no se tipa\n * queda en la respuesta cruda (`onRawResponse`). **Trae datos del pasajero.**\n *\n * El historial no registra las colocaciones en cola, ni las del sistema ni un `place` manual\n * (CERT, 2026-11-06, Q-097): para eso están `queue.list`/`access` o los remarks `QUEUE_PLACE` de\n * Get Booking.\n *\n * **Dentro de una cola, Sabre lo rechaza** para otro PNR (CERT, 2026-11-06, Q-102): lanza\n * `SabreBusinessError` con `NAK6 -NOT ALLOWED- FINISH OR IGNORE OTHER ACTIVITY`. El PNR del AAA\n * no cambia, `queue.state` sigue en `'inside'` y el recorrido sigue con `ignore`. Conviene\n * llamarlo fuera de una cola.\n *\n * Es una lectura: se reintenta ante fallos transitorios. Un `locator` que no es de 6 caracteres\n * alfanuméricos en mayúscula lanza `TypeError` sin red. Un PNR que no existe sale como\n * `SabreBusinessError` (`service: 'itineraryHistory'`).\n */\n async history(locator: string, options: ReservationHistoryOptions = {}): Promise<ReservationHistoryResponse> {\n if (!isRecordLocator(locator)) {\n throw new TypeError('sabre-client: reservation.history necesita un localizador de 6 caracteres alfanuméricos en mayúscula');\n }\n const response = await this.#context.send(reservationHistoryRequest(locator, options));\n return parseReservationHistoryResponse(response);\n }\n}\n","// Send Sabre Command (`SabreCommandLLSRQ` 2.0.0): un comando de host dentro de la sesión, con la\n// pantalla como texto crudo. Ver sabre-wiki/wiki/proyectos/sabre-client/decisiones/comandos-de-host.md\n// (ADR-021) y wiki/entities/send-sabre-command.md. Request como `sabre-legacy-client@1.0.8` y el\n// script de configuración de agencia del 2026-11-03.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { respondedAtField, type SoapResponse, textOf, untrimmedPayload, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from './session.js';\n\nexport const SABRE_COMMAND_SERVICE = 'sabreCommand';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\n/** Largo máximo de `HostCommand`, contado como Sabre (ver `sabreCommandLength`). */\nexport const MAX_COMMAND_LENGTH = 1023;\n/** Caracteres que Sabre cuenta doble en el largo del comando. */\nconst DOUBLE_WIDTH = new Set(['!', '%', '$', '&', '¥', '§']);\n\nexport interface SabreCommandOptions extends RequestOptions {\n /**\n * `true` solo si el comando es una lectura (`W/PT¥*`, `DC¥…`): entra en la política de\n * reintentos. Por defecto `false`, porque el SDK no sabe si un comando cambia algo.\n */\n idempotent?: boolean;\n}\n\nexport interface SabreCommandResponse {\n /**\n * La pantalla tal como la devuelve Sabre (`Response`), sin interpretar y sin recortar: las\n * pantallas van alineadas por columna y pueden empezar con un espacio (` 17MAR WED…`). Recortar\n * es decisión de quien la lee. Un mensaje de host (`DUTY CODE 9 REQUIRED`, `FORMAT`) llega aquí:\n * no lanza.\n */\n text: string;\n /** Los `stl:Warning` de la respuesta. No lanzan. */\n warnings: SabreWarning[];\n /** `eb:MessageId` de la respuesta, el dato que pide soporte de Sabre. */\n messageId: string | undefined;\n /**\n * `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC (`\"2026-11-06T17:34:16Z\"`). A\n * diferencia de las fechas del host, trae año y zona. Falta si Sabre no lo manda.\n */\n respondedAt?: string;\n}\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/** Cuerpo de `SabreCommandLLSRQ`: el comando va tal cual, escapado para XML y sin transformar. */\nexport function sabreCommandPayload(command: string): string {\n return `<SabreCommandLLSRQ xmlns=\"${NAMESPACE}\" Version=\"2.0.0\" ReturnHostCommand=\"true\"><Request Output=\"SCREEN\"><HostCommand>${xmlEscape(command)}</HostCommand></Request></SabreCommandLLSRQ>`;\n}\n\n/**\n * Lo único del comando que va al log: lo que está antes del primer `¥`, `‡` o espacio, cortado a\n * 4 caracteres (`W/PT`, `DC`, `*IM`, `SI9`). Un comando sin separador puede traer un localizador\n * o un nombre (`*ABC123`, `N-SMITH/JOHN`); el corte deja solo el principio.\n */\nexport function commandToken(command: string): string {\n return (command.trim().split(/[¥‡\\s]/u)[0] ?? '').slice(0, 4);\n}\n\n/**\n * Largo del comando como lo cuenta Sabre: cada carácter vale 1, salvo `!`, `%`, `$`, `&`, `¥` y\n * `§`, que valen 2. Más de `MAX_COMMAND_LENGTH` y Sabre responde `REQUEST EXCEEDED MAXIMUM LENGTH`.\n */\nexport function sabreCommandLength(command: string): number {\n let length = 0;\n for (const char of command) length += DOUBLE_WIDTH.has(char) ? 2 : 1;\n return length;\n}\n\n/** Valida el comando y arma la request. Sin reintento salvo `idempotent: true`. */\nexport function sabreCommandRequest(command: string, options: SabreCommandOptions): SessionRequest {\n if (typeof command !== 'string' || command.trim() === '') fail('command es requerido y debe ser un string no vacío');\n const length = sabreCommandLength(command);\n if (length > MAX_COMMAND_LENGTH) {\n fail(`command mide ${length} y el máximo es ${MAX_COMMAND_LENGTH} (!, %, $, &, ¥ y § cuentan 2); Sabre respondería REQUEST EXCEEDED MAXIMUM LENGTH`);\n }\n const { idempotent = false, ...requestOptions } = options;\n if (typeof idempotent !== 'boolean') fail('idempotent debe ser un boolean');\n return {\n service: SABRE_COMMAND_SERVICE,\n action: 'SabreCommandLLSRQ',\n payload: sabreCommandPayload(command),\n idempotent,\n operation: 'command',\n ...requestOptions,\n };\n}\n\n/**\n * Lee `SabreCommandLLSRS`: solo la pantalla, los avisos y el `MessageId`. La pantalla sale de un\n * parseo sin recorte (`untrimmedPayload`), no del payload compartido. Sin `Response` la pantalla\n * queda vacía. Otro elemento en el `Body` es una respuesta que el SDK no entiende.\n */\nexport function parseSabreCommandResponse(response: SoapResponse): SabreCommandResponse {\n if (response.payloadName !== 'SabreCommandLLSRS') {\n throw new SabreGatewayError(`${SABRE_COMMAND_SERVICE}: respuesta no reconocida (${response.payloadName})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n return {\n text: textOf((untrimmedPayload(response.raw) ?? response.payload).Response) ?? '',\n warnings: response.warnings,\n messageId: response.messageId,\n ...respondedAtField(response.raw),\n };\n}\n","// Ciclo de vida de la sesión SOAP: `SessionCreateRQ` (2.0.0 o 1.0.0) y `SessionCloseRQ` 1.0.1,\n// con uso exclusivo. Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 1 y\n// decisiones de la revisión), wiki/entities/create-session.md y gestion-de-sesion-soap.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreError, SabreGatewayError, SabreSessionError, type SabreSessionErrorKind } from '../errors/index.js';\nimport {\n asArray,\n type SoapRequest,\n type SoapResponse,\n type SoapSecurity,\n type SoapTransport,\n textOf,\n xmlEscape,\n} from '../http/soap-transport.js';\nimport { QueueManagement } from '../queue/queue-management.js';\nimport { SessionReservation } from '../reservation/session-reservation.js';\nimport {\n commandToken,\n parseSabreCommandResponse,\n type SabreCommandOptions,\n type SabreCommandResponse,\n sabreCommandRequest,\n} from './command.js';\nimport type { SessionCredentials } from './credentials.js';\n\nconst OTA_NAMESPACE = 'http://www.opentravel.org/OTA/2002/11';\nconst SWS_NAMESPACE = 'http://webservices.sabre.com';\n\n/** Lo que una operación pide al transporte. La sesión agrega `CPAId`, `ConversationId` y el token. */\nexport type SessionRequest = Omit<SoapRequest, 'cpaId' | 'conversationId' | 'security'>;\n\n/**\n * Método interno por el que las operaciones de la sesión (cola, ping) llaman a Sabre. Va con un\n * símbolo que no se exporta del paquete para no sumar superficie pública.\n */\nexport const sessionSend: unique symbol = Symbol('sabre-client.session.send');\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/**\n * `USG_*` que dejan la sesión inutilizable (punto 4). Una sesión vencida en producción devuelve\n * `USG_INVALID_SECURITY_TOKEN` (#95, 2026-11-02): HTTP 500, `faultcode`\n * `soap-env:Client.InvalidSecurityToken`, y el código solo en el `detail`. `USG_AUTHENTICATION_FAILED`\n * sigue como `'expired'` de forma tentativa: no se observó con una sesión abierta.\n */\nconst SESSION_ERROR_KINDS: ReadonlyMap<string, SabreSessionErrorKind> = new Map([\n ['USG_RESOURCE_UNAVAILABLE', 'limit'],\n ['USG_INVALID_SESSION', 'invalid'],\n ['USG_INVALID_SECURITY_TOKEN', 'expired'],\n ['USG_AUTHENTICATION_FAILED', 'expired'],\n ['USG_RESOURCE_BLOCKED', 'blocked'],\n]);\n\n/**\n * Al abrir todavía no hay sesión que pueda vencer ni usarse en paralelo: ahí un\n * `USG_AUTHENTICATION_FAILED` son credenciales mal configuradas, y sigue como `SabreGatewayError`.\n */\nconst OPEN_ERROR_KINDS: ReadonlySet<SabreSessionErrorKind> = new Set(['limit', 'blocked']);\n\n/** Convierte un fault de sesión en `SabreSessionError`; cualquier otro error sale igual. */\nexport function toSessionError(error: unknown, allowed?: ReadonlySet<SabreSessionErrorKind>): unknown {\n if (!(error instanceof SabreGatewayError) || error instanceof SabreSessionError) return error;\n if (error.protocol !== 'soap' || error.code === undefined) return error;\n const kind = SESSION_ERROR_KINDS.get(error.code);\n if (kind === undefined || (allowed !== undefined && !allowed.has(kind))) return error;\n return new SabreSessionError(error.message, {\n kind,\n code: error.code,\n retryable: error.retryable,\n raw: error.raw,\n cause: error.cause,\n ...(error.status === undefined ? {} : { status: error.status }),\n });\n}\n\n/** Opciones de `openSession`. */\nexport interface OpenSessionOptions extends RequestOptions {\n /**\n * Manda `OTA_PingRQ` cuando la sesión lleva 13 minutos inactiva, antes del vencimiento de los\n * 15. Apagado por defecto: en runtimes serverless o edge un timer no sobrevive entre\n * invocaciones. Ahí conviene `withSession` por recorrido, o un `ping()` antes de reutilizar.\n */\n keepAlive?: boolean;\n}\n\n/** Inactividad a la que `keepAlive` manda el ping: 2 minutos antes de los 15 del vencimiento. */\nexport const KEEP_ALIVE_IDLE_MS = 13 * 60_000;\n\n/**\n * Una sesión SOAP abierta con `SessionCreateRQ`. Es exclusiva: Sabre no admite llamadas\n * concurrentes en la misma sesión (`USG_INVALID_SESSION`), así que una segunda llamada mientras\n * otra está en vuelo lanza `TypeError` sin llamar a la red. Se cierra con `close()`, o sola si\n * se abrió con `withSession`.\n */\nexport class SabreSession {\n /** Queue Management: contar, recorrer y colocar en colas, dentro de esta sesión. */\n readonly queue: QueueManagement;\n /** La reserva: el historial de un PNR, dentro de esta sesión. */\n readonly reservation: SessionReservation;\n readonly #transport: SoapTransport;\n readonly #pcc: string;\n readonly #conversationId: string;\n readonly #security: SoapSecurity;\n #busy = false;\n #closing: Promise<void> | undefined;\n /** El `SabreSessionError` que dejó la sesión inutilizable. */\n #unusable: SabreSessionError | undefined;\n /** Última vez que Sabre respondió en esta sesión (`Date.now()`). */\n #lastActivity = Date.now();\n #keepAliveTimer: ReturnType<typeof setTimeout> | undefined;\n /** El ping de `keepAlive` en vuelo: las llamadas del consumidor lo esperan en vez de chocar. */\n #keepAlivePing: Promise<void> | undefined;\n\n static {\n // `await using` es un extra: solo si el runtime tiene el símbolo (Node 22 no tiene la\n // sintaxis nativa, y algunos runtimes edge no tienen el símbolo).\n installAsyncDispose(this.prototype, (Symbol as { asyncDispose?: symbol }).asyncDispose);\n }\n\n /** @internal Se crea con `SabreLegacy.openSession()`. */\n constructor(internal: {\n transport: SoapTransport;\n pcc: string;\n conversationId: string;\n token: string;\n keepAlive: boolean;\n }) {\n this.#transport = internal.transport;\n this.#pcc = internal.pcc;\n this.#conversationId = internal.conversationId;\n this.#security = { binarySecurityToken: internal.token };\n this.queue = new QueueManagement({\n send: (request) => this[sessionSend](request),\n pcc: internal.pcc,\n log: internal.transport.log,\n });\n this.reservation = new SessionReservation({ send: (request) => this[sessionSend](request) });\n if (internal.keepAlive) this.#scheduleKeepAlive(KEEP_ALIVE_IDLE_MS);\n }\n\n /**\n * Milisegundos desde la última respuesta de Sabre en esta sesión; `0` mientras hay una llamada\n * en vuelo. Sabre cierra la sesión a los 15 minutos de inactividad.\n */\n get idleMs(): number {\n return this.#busy ? 0 : Math.max(0, Date.now() - this.#lastActivity);\n }\n\n /**\n * Manda `OTA_PingRQ`, que reinicia el contador de inactividad sin tocar el AAA. Durante un\n * recorrido de cola no hace falta: cada operación ya lo reinicia.\n */\n async ping(options: RequestOptions = {}): Promise<void> {\n checkPingResponse(await this[sessionSend]({ ...pingRequest(), ...options }));\n }\n\n /**\n * Manda un comando de host (`SabreCommandLLSRQ` 2.0.0) y devuelve la pantalla como texto, sin\n * interpretarla. Es una vía de escape: sin tipos ni garantías, y un comando puede cambiar la\n * configuración del PCC o emitir. El comando va tal cual; el separador de Sabre Red (`‡`) se\n * escribe `¥`. Sin reintento salvo `{ idempotent: true }`, para comandos de solo lectura. La\n * pantalla llega sin recortar, y más de 1023 caracteres (contados como Sabre) lanza sin red.\n */\n async command(command: string, options: SabreCommandOptions = {}): Promise<SabreCommandResponse> {\n const request = sabreCommandRequest(command, options);\n this.#transport.log.emit('debug', 'sabre.session.command', { command: commandToken(command) });\n return parseSabreCommandResponse(await this[sessionSend](request));\n }\n\n /**\n * Cierra la sesión con `SessionCloseRQ`: Sabre descarta el AAA e invalida el token. Es\n * idempotente: las llamadas siguientes devuelven la misma promesa, sin volver a la red. Si el\n * cierre falla, la sesión queda cerrada igual del lado del SDK; la de Sabre vence sola a los\n * 15 minutos. Una sesión inutilizable (ver `SabreSessionError`) se cierra sin red: Sabre ya no\n * la reconoce.\n */\n close(options: RequestOptions = {}): Promise<void> {\n if (this.#closing !== undefined) return this.#closing;\n if (this.#busy && this.#keepAlivePing === undefined) {\n return Promise.reject(new TypeError('sabre-client: session busy'));\n }\n this.#stopKeepAlive();\n if (this.#unusable !== undefined) {\n this.#closing = Promise.resolve();\n return this.#closing;\n }\n // Si el ping de `keepAlive` está en vuelo, el cierre sale cuando termina.\n const before = this.#keepAlivePing ?? Promise.resolve();\n this.#closing = before.then(() => this.#sendClose(options));\n return this.#closing;\n }\n\n /** @internal Una llamada a Sabre dentro de la sesión, con uso exclusivo. */\n async [sessionSend](request: SessionRequest): Promise<SoapResponse> {\n if (this.#keepAlivePing !== undefined && this.#closing === undefined) await this.#keepAlivePing;\n return this.#send(request);\n }\n\n async #send(request: SessionRequest): Promise<SoapResponse> {\n if (this.#closing !== undefined) fail('session closed');\n if (this.#unusable !== undefined) {\n throw new TypeError(`sabre-client: session unusable (${this.#unusable.kind})`, { cause: this.#unusable });\n }\n if (this.#busy) fail('session busy');\n this.#busy = true;\n try {\n const response = await this.#transport.request({ ...request, ...this.#envelopeFields() });\n this.#touch();\n return response;\n } catch (error) {\n if (reachedSabre(error)) this.#touch();\n throw this.#markUnusable(error);\n } finally {\n this.#busy = false;\n }\n }\n\n async #sendClose(options: RequestOptions): Promise<void> {\n if (this.#unusable !== undefined) return;\n // SessionCloseRQ queda fuera de onRawRequest, como las demás llamadas de auth (ADR-029).\n const { onRawRequest: _skipped, ...closeOptions } = options;\n this.#busy = true;\n try {\n await this.#transport.request({\n service: 'sessionClose',\n action: 'SessionCloseRQ',\n payload: `<SessionCloseRQ Version=\"1.0.1\"><POS><Source PseudoCityCode=\"${xmlEscape(this.#pcc)}\"/></POS></SessionCloseRQ>`,\n ...this.#envelopeFields(),\n // Solo se reintenta ante `USG_*_BUSY`: tras un fallo de red no se sabe si ya se cerró.\n idempotent: false,\n operation: 'close',\n ...closeOptions,\n });\n } catch (error) {\n throw this.#markUnusable(error);\n } finally {\n this.#busy = false;\n }\n this.#transport.log.emit('info', 'sabre.session.close', { pseudoCityCode: this.#pcc });\n }\n\n /** Un error de sesión deja la sesión inutilizable. No se reabre sola: el cursor ya se perdió. */\n #markUnusable(error: unknown): unknown {\n const mapped = toSessionError(error);\n if (mapped instanceof SabreSessionError) {\n this.#unusable = mapped;\n this.#stopKeepAlive();\n }\n return mapped;\n }\n\n #touch(): void {\n this.#lastActivity = Date.now();\n }\n\n #envelopeFields(): Pick<SoapRequest, 'cpaId' | 'conversationId' | 'security'> {\n return { cpaId: this.#pcc, conversationId: this.#conversationId, security: this.#security };\n }\n\n /**\n * Un solo timer, que se reprograma según `idleMs`: cada respuesta de Sabre corre el ping. Si el\n * ping falla (ya con los reintentos del transporte), se avisa con un `warn` y `keepAlive` se\n * apaga: reintentar sin fin no tiene sentido con una sesión que vence a los 15 minutos.\n */\n #scheduleKeepAlive(delayMs: number): void {\n const timer = setTimeout(() => this.#onKeepAlive(), delayMs);\n // Que el timer no mantenga vivo el proceso si el consumidor se olvida de cerrar (Node).\n (timer as { unref?: () => void }).unref?.();\n this.#keepAliveTimer = timer;\n }\n\n #onKeepAlive(): void {\n this.#keepAliveTimer = undefined;\n if (this.#closing !== undefined || this.#unusable !== undefined) return;\n if (this.#busy) {\n this.#scheduleKeepAlive(KEEP_ALIVE_IDLE_MS);\n return;\n }\n const remaining = KEEP_ALIVE_IDLE_MS - this.idleMs;\n if (remaining > 0) {\n this.#scheduleKeepAlive(remaining);\n return;\n }\n this.#keepAlivePing = this.#send(pingRequest()).then(\n () => {\n if (this.#closing === undefined && this.#unusable === undefined) this.#scheduleKeepAlive(KEEP_ALIVE_IDLE_MS);\n },\n (error: unknown) => {\n this.#transport.log.emit('warn', 'sabre.session.keepAliveFailed', { error });\n },\n );\n void this.#keepAlivePing.finally(() => {\n this.#keepAlivePing = undefined;\n });\n }\n\n #stopKeepAlive(): void {\n if (this.#keepAliveTimer !== undefined) clearTimeout(this.#keepAliveTimer);\n this.#keepAliveTimer = undefined;\n }\n}\n\n/**\n * `OTA_PingRQ` 1.0.0, como el sample oficial pero con el namespace OTA de la respuesta: sin él,\n * producción contesta `Invalid version` (#95). Idempotente: no toca el estado de negocio.\n */\nfunction pingRequest(): SessionRequest {\n const timestamp = new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n return {\n service: 'ping',\n action: 'OTA_PingRQ',\n payload: `<OTA_PingRQ xmlns=\"${OTA_PING_NAMESPACE}\" TimeStamp=\"${timestamp}\" Version=\"1.0.0\"><EchoData>sabre-client</EchoData></OTA_PingRQ>`,\n idempotent: true,\n operation: 'ping',\n };\n}\n\nconst OTA_PING_NAMESPACE = 'http://www.opentravel.org/OTA/2003/05';\n\n/**\n * `OTA_PingRS` puede traer un error con HTTP 200 y sin fault, como `<Errors><Error Type=\"VER\">\n * Invalid version</Error></Errors>` (producción, #95). Es un rechazo del request, así que sale\n * como `SabreGatewayError`, igual que un error de validación. Sin `Success` tampoco se da por bueno.\n */\nfunction checkPingResponse(response: SoapResponse): void {\n const errors = asArray(response.payload.Errors)[0] as Record<string, unknown> | undefined;\n const error = asArray(errors?.Error)[0];\n if (error !== undefined) {\n const type = (error as Record<string, unknown>)['@Type'];\n const text = textOf(error)?.trim();\n throw new SabreGatewayError(`ping: OTA_PingRS con error${text ? `: ${text}` : ''}`, {\n protocol: 'soap',\n status: response.status,\n ...(typeof type === 'string' && type !== '' && { code: type }),\n retryable: false,\n raw: response.raw,\n });\n }\n if (response.payloadName !== 'OTA_PingRS' || !('Success' in response.payload)) {\n throw new SabreGatewayError('ping: respuesta no reconocida (sin OTA_PingRS/Success)', {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n}\n\n/**\n * Si Sabre llegó a responder: cualquier error del SDK salvo un fallo de red (sin status). Solo\n * eso reinicia el contador de inactividad.\n */\nfunction reachedSabre(error: unknown): boolean {\n if (!(error instanceof SabreError)) return false;\n return !(error instanceof SabreGatewayError && error.status === undefined);\n}\n\n/** Define `[Symbol.asyncDispose]` como `close()`, si el runtime tiene el símbolo. */\nexport function installAsyncDispose(target: object, symbol: symbol | undefined): void {\n if (symbol === undefined) return;\n Object.defineProperty(target, symbol, {\n value(this: SabreSession): Promise<void> {\n return this.close();\n },\n configurable: true,\n writable: true,\n });\n}\n\n/** Cuerpo de `SessionCreateRQ`: 2.0.0 en el namespace de Sabre, 1.0.0 en el de OTA. */\nexport function sessionCreatePayload(credentials: Pick<SessionCredentials, 'version' | 'organization'>): string {\n const pos = `<POS><Source PseudoCityCode=\"${xmlEscape(credentials.organization)}\"/></POS>`;\n return credentials.version === '2.0.0'\n ? `<SessionCreateRQ xmlns=\"${SWS_NAMESPACE}\" Version=\"2.0.0\">${pos}</SessionCreateRQ>`\n : `<SessionCreateRQ xmlns=\"${OTA_NAMESPACE}\" Version=\"1.0.0\" returnContextID=\"true\">${pos}</SessionCreateRQ>`;\n}\n\nfunction usernameToken(credentials: SessionCredentials): SoapSecurity {\n const { username, password, organization, domain, clientId, clientSecret } = credentials;\n return {\n usernameToken: {\n username,\n password,\n organization,\n domain,\n ...(clientId === undefined ? {} : { clientId }),\n ...(clientSecret === undefined ? {} : { clientSecret }),\n },\n };\n}\n\n/**\n * Abre una sesión. Se reintenta solo ante `USG_*_BUSY`: `USG_RESOURCE_UNAVAILABLE` (más de 50\n * sesiones) se lanza sin reintentar.\n */\nexport async function openSession(\n transport: SoapTransport,\n credentials: SessionCredentials,\n options: OpenSessionOptions = {},\n): Promise<SabreSession> {\n const { keepAlive = false, ...requestOptions } = options;\n if (typeof keepAlive !== 'boolean') fail('keepAlive debe ser un boolean');\n const conversationId = globalThis.crypto.randomUUID();\n const request: SoapRequest = {\n service: 'sessionCreate',\n action: 'SessionCreateRQ',\n payload: sessionCreatePayload(credentials),\n cpaId: credentials.organization,\n conversationId,\n security: usernameToken(credentials),\n idempotent: false,\n readSecurityToken: true,\n operation: 'openSession',\n ...requestOptions,\n };\n const response = await transport.request(request).catch((error: unknown) => {\n throw toSessionError(error, OPEN_ERROR_KINDS);\n });\n\n const status = response.payload['@status'];\n if (typeof status === 'string' && status !== 'Approved') {\n throw new SabreGatewayError(`sessionCreate: SessionCreateRS con status ${status}`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n });\n }\n if (response.securityToken === undefined) {\n throw new SabreGatewayError('sessionCreate: la respuesta no trae BinarySecurityToken', {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n });\n }\n\n // La versión elegida queda en el log, sin credenciales.\n transport.log.emit('info', 'sabre.session.open', {\n version: credentials.version,\n pseudoCityCode: credentials.organization,\n });\n return new SabreSession({\n transport,\n pcc: credentials.organization,\n conversationId,\n token: response.securityToken,\n keepAlive,\n });\n}\n","// Cliente SOAP. Ver sabre-wiki/wiki/sdk/arquitectura-clientes-transporte.md y\n// tier-3-sesion-y-colas-soap.md.\nimport { type ResolvedConfig, resolveConfig, type SabreConfig, type SabreEnvironment } from './config.js';\nimport { SoapTransport } from './http/soap-transport.js';\nimport { resolveSessionCredentials, type SessionCredentials } from './session/credentials.js';\nimport { type OpenSessionOptions, openSession, type SabreSession } from './session/session.js';\n\nexport class SabreLegacy {\n readonly #config: ResolvedConfig;\n /** Usuario, PCC, domain y versión de `SessionCreateRQ`, validados al crear el cliente. */\n readonly #session: Readonly<SessionCredentials>;\n readonly #transport: SoapTransport;\n\n /**\n * Recibe la misma config que `Sabre`. Usuario, PCC y domain de la sesión salen de\n * `credentials.username` (`V1:<user>:<PCC>:<domain>` o `<user>-<PCC>-<domain>`), y la versión\n * de `SessionCreateRQ` de las credenciales: 2.0.0 con `clientId` y `clientSecret`, 1.0.0 sin\n * ellos. Una config inválida lanza `TypeError` aquí, sin llamar a la red.\n */\n constructor(config: SabreConfig) {\n this.#config = resolveConfig(config);\n this.#session = Object.freeze(resolveSessionCredentials(this.#config.credentials));\n this.#transport = new SoapTransport(this.#config);\n }\n\n get environment(): SabreEnvironment {\n return this.#config.environment;\n }\n\n /** Endpoint SOAP del entorno. */\n get baseUrl(): string {\n return this.#config.soapBaseUrl;\n }\n\n /**\n * Abre una sesión SOAP. Quien la abre la cierra: `try { … } finally { await session.close() }`.\n * Para el caso común, `withSession` la cierra sola. Con `keepAlive: true`, manda un ping a los\n * 13 minutos de inactividad.\n */\n openSession(options: OpenSessionOptions = {}): Promise<SabreSession> {\n return openSession(this.#transport, this.#session, options);\n }\n\n /**\n * Abre una sesión, se la presta al callback y la cierra en un `finally`. Devuelve lo mismo que\n * el callback y propaga su error. Si el cierre falla, emite `sabre.session.closeFailed` en\n * `warn` y no pisa el resultado ni el error del callback.\n */\n async withSession<T>(callback: (session: SabreSession) => Promise<T>): Promise<T> {\n const session = await this.openSession();\n let result: T;\n try {\n result = await callback(session);\n } catch (error) {\n await this.#closeQuietly(session);\n throw error;\n }\n await this.#closeQuietly(session);\n return result;\n }\n\n async #closeQuietly(session: SabreSession): Promise<void> {\n try {\n await session.close();\n } catch (error) {\n this.#transport.log.emit('warn', 'sabre.session.closeFailed', { error });\n }\n }\n}\n","// Arma el `credentials` de la config a partir de un solo juego de partes. El mismo objeto sirve\n// para `Sabre` (REST) y para `SabreLegacy` (SOAP); la versión de OAuth solo cambia el formato\n// del username. Ver sabre-wiki/wiki/proyectos/sabre-client/decisiones/configuracion-logging-y-build.md\n// (ADR-010, #134) y wiki/entities/oauth-token-create.md (formato del EPR por versión).\nimport type { SabreAuthVersion, SabreCredentials, SabreCredentialsV2 } from '../config.js';\nimport { isPseudoCityCode } from '../session/credentials.js';\n\ninterface BuildCredentialsBase {\n /** Usuario EPR, sin PCC ni domain. */\n user: string;\n /** PCC del EPR (el *group*): 3 o 4 caracteres alfanuméricos. */\n pcc: string;\n /** Domain del EPR. Default `'AA'`. */\n domain?: string;\n /** Contraseña EPR. */\n password: string;\n}\n\n/** Partes para OAuth Token Create v3 (default): `clientId` y `clientSecret` son obligatorios. */\nexport interface BuildCredentialsOptionsV3 extends BuildCredentialsBase {\n authVersion?: 'v3';\n clientId: string;\n clientSecret: string;\n}\n\n/**\n * Partes para OAuth Token Create v2: `clientId`/`clientSecret` son opcionales. REST los ignora,\n * pero si vienen los dos, `SabreLegacy` abre la sesión con `SessionCreateRQ` 2.0.0.\n */\nexport interface BuildCredentialsOptionsV2 extends BuildCredentialsBase {\n authVersion: 'v2';\n clientId?: string;\n clientSecret?: string;\n}\n\nexport type BuildCredentialsOptions = BuildCredentialsOptionsV3 | BuildCredentialsOptionsV2;\n\n/** Lo que devuelve `buildCredentials` para v3: lleva `authVersion: 'v3'`. */\nexport type BuiltCredentialsV3 = SabreCredentials & { authVersion: 'v3' };\n\n/**\n * Lo que devuelve `buildCredentials` para v2: lleva `authVersion: 'v2'`, así que la config no\n * necesita repetirlo (#148).\n */\nexport type BuiltCredentialsV2 = SabreCredentialsV2 & { authVersion: 'v2' };\n\nconst DEFAULT_DOMAIN = 'AA';\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\nfunction requireString(value: unknown, field: string): asserts value is string {\n if (typeof value !== 'string' || value.trim() === '') fail(`${field} es requerido y debe ser un string no vacío`);\n}\n\n/**\n * Arma el `credentials` para `Sabre` y `SabreLegacy` a partir del usuario, el PCC, el domain y\n * la contraseña del EPR, más `clientId`/`clientSecret` cuando los hay. El username queda como\n * `<user>-<PCC>-<domain>` (v3) o `V1:<user>:<PCC>:<domain>` (v2). No lee variables de entorno\n * ni toca la red; un dato inválido lanza `TypeError` sin repetir secretos. El resultado lleva\n * `authVersion`, que la config usa si no trae el suyo.\n */\nexport function buildCredentials(options: BuildCredentialsOptionsV3): BuiltCredentialsV3;\nexport function buildCredentials(options: BuildCredentialsOptionsV2): BuiltCredentialsV2;\nexport function buildCredentials(options: BuildCredentialsOptions): BuiltCredentialsV3 | BuiltCredentialsV2;\nexport function buildCredentials(options: BuildCredentialsOptions): BuiltCredentialsV3 | BuiltCredentialsV2 {\n if (typeof options !== 'object' || options === null) fail('buildCredentials recibe un objeto');\n\n const authVersion: SabreAuthVersion = options.authVersion ?? 'v3';\n if (authVersion !== 'v3' && authVersion !== 'v2') {\n fail(`authVersion debe ser 'v3' o 'v2' (recibido: ${JSON.stringify(authVersion)})`);\n }\n\n const { user, pcc, password, clientId, clientSecret } = options;\n const domain = options.domain ?? DEFAULT_DOMAIN;\n requireString(user, 'user');\n requireString(password, 'password');\n if (!isPseudoCityCode(pcc)) fail('pcc debe tener 3 o 4 caracteres alfanuméricos');\n requireString(domain, 'domain');\n // El username se lee de derecha a izquierda: un separador en el domain lo partiría mal.\n if (/[-:]/.test(domain)) fail(\"domain no puede contener '-' ni ':'\");\n\n if ((clientId === undefined) !== (clientSecret === undefined)) {\n fail('clientId y clientSecret van juntos: pasa los dos o ninguno');\n }\n if (authVersion === 'v3' || clientId !== undefined) {\n requireString(clientId, authVersion === 'v3' ? 'clientId (requerido con authVersion v3)' : 'clientId');\n requireString(clientSecret, authVersion === 'v3' ? 'clientSecret (requerido con authVersion v3)' : 'clientSecret');\n }\n\n const username = authVersion === 'v3' ? `${user}-${pcc}-${domain}` : `V1:${user}:${pcc}:${domain}`;\n if (authVersion === 'v3') return { authVersion, clientId: clientId!, clientSecret: clientSecret!, username, password };\n return clientId === undefined\n ? { authVersion, username, password }\n : { authVersion, clientId, clientSecret: clientSecret!, username, password };\n}\n","// Fechas de host sin año → strings ISO, con la regla del año. Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 3 y decisiones de la revisión).\n\n/**\n * Cómo se elige el año cuando el texto no lo trae:\n *\n * - `'past'`: la fecha más reciente que no sea posterior a `referenceDate` (el mismo día cuenta).\n * Es la regla de los hechos que ya pasaron: la línea de recibido, `placedAt` y `countedAt`.\n * - `'nearest'`: la fecha más cercana a `referenceDate`, hacia adelante o hacia atrás, dentro de\n * ±6 meses. Es la regla de los segmentos y del plazo de ticketing (`T-`, `TAW`). Con un empate\n * gana la fecha futura.\n */\nexport type HostDateDirection = 'past' | 'nearest';\n\nexport interface ResolveHostDateOptions {\n /** Regla del año. Por defecto `'past'`, la de `placedAt` y `countedAt`. */\n direction?: HostDateDirection;\n}\n\nconst MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];\n\nconst DAY_MS = 86_400_000;\n\n/** Medio año, en días: la distancia más larga de una fecha a la referencia con `'nearest'`. */\nconst HALF_YEAR_DAYS = 184;\n\ninterface HostDate {\n year?: number;\n month: number;\n day: number;\n time?: string;\n}\n\n/**\n * Convierte una fecha de host en un string ISO sin zona horaria: `'YYYY-MM-DD'`, o\n * `'YYYY-MM-DDTHH:mm'` si el texto trae hora.\n *\n * Formatos que reconoce (sin distinguir mayúsculas, sin espacios a los costados):\n *\n * - `06SEP` y `06SEP26`, como en los segmentos, el ticketing y la línea de recibido;\n * - `12-21` y `12-21T07:00`, como el `DateTime` de `QueueCountRS`;\n * - `2024-05-15` y `2024-05-15T13:24`, como el `DateTime` de una línea de cola real.\n *\n * Si el texto trae año, se usa ese (un año de dos dígitos es del 2000 en adelante). Si no, el año\n * se resuelve contra `referenceDate` con la regla de `options.direction`.\n *\n * `referenceDate` es un `'YYYY-MM-DD'` (puede seguir una hora, que no se usa) o un `Date`, del que\n * se toma el día en UTC. Conviene pasar el día en el calendario del PCC: la regla compara días, y\n * con zonas distintas la referencia puede quedar un día corrida.\n *\n * Devuelve `undefined` si el texto no tiene un formato reconocido, si la fecha no existe\n * (`2026-02-29`, `31APR`) o si no hay un año que cumpla la regla (un `29FEB` sin un año bisiesto a\n * menos de 6 meses, con `'nearest'`). Lanza `TypeError` si `referenceDate` no es válida.\n */\nexport function resolveHostDate(\n text: string,\n referenceDate: Date | string,\n options: ResolveHostDateOptions = {},\n): string | undefined {\n const reference = referenceDay(referenceDate);\n const direction = options.direction ?? 'past';\n if (direction !== 'past' && direction !== 'nearest') {\n throw new TypeError(\"sabre-client: direction debe ser 'past' o 'nearest'\");\n }\n if (typeof text !== 'string') return undefined;\n\n const parsed = parseHostDate(text.trim().toUpperCase());\n if (parsed === undefined) return undefined;\n\n const year = parsed.year ?? resolveYear(parsed.month, parsed.day, reference, direction);\n if (year === undefined || !isValidDate(year, parsed.month, parsed.day)) return undefined;\n\n const date = `${pad(year, 4)}-${pad(parsed.month, 2)}-${pad(parsed.day, 2)}`;\n return parsed.time === undefined ? date : `${date}T${parsed.time}`;\n}\n\nfunction parseHostDate(text: string): HostDate | undefined {\n // 06SEP, 06SEP26\n let match = /^(\\d{1,2})([A-Z]{3})(\\d{2})?$/.exec(text);\n if (match !== null) {\n const month = MONTHS.indexOf(match[2]!) + 1;\n if (month === 0) return undefined;\n return {\n ...(match[3] !== undefined && { year: 2000 + Number(match[3]) }),\n month,\n day: Number(match[1]),\n };\n }\n\n // 12-21, 12-21T07:00, 2024-05-15, 2024-05-15T13:24\n match = /^(?:(\\d{4})-)?(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2}))?$/.exec(text);\n if (match === null) return undefined;\n const [, year, month, day, hours, minutes] = match;\n if (hours !== undefined && (Number(hours) > 23 || Number(minutes) > 59)) return undefined;\n return {\n ...(year !== undefined && { year: Number(year) }),\n month: Number(month),\n day: Number(day),\n ...(hours !== undefined && { time: `${hours}:${minutes}` }),\n };\n}\n\n/** Año que cumple la regla, o `undefined` si ninguno de los candidatos la cumple. */\nfunction resolveYear(month: number, day: number, reference: number, direction: HostDateDirection) {\n const year = new Date(reference).getUTCFullYear();\n\n if (direction === 'past') {\n // Hacia atrás no hay ventana: un 29FEB puede caer hasta 8 años antes (con un 2100 en medio).\n for (let candidate = year; candidate >= year - 8; candidate--) {\n if (isValidDate(candidate, month, day) && dayNumber(candidate, month, day) <= reference) return candidate;\n }\n return undefined;\n }\n\n let best: { year: number; distance: number } | undefined;\n for (const candidate of [year + 1, year, year - 1]) {\n if (!isValidDate(candidate, month, day)) continue;\n const distance = Math.abs(dayNumber(candidate, month, day) - reference);\n // Los candidatos van del futuro al pasado: con un empate se queda el futuro.\n if (best === undefined || distance < best.distance) best = { year: candidate, distance };\n }\n return best !== undefined && best.distance <= HALF_YEAR_DAYS * DAY_MS ? best.year : undefined;\n}\n\n/**\n * El día de `referenceDate`, como milisegundos UTC de su medianoche. Lanza `TypeError` si no es\n * válida. Lo usa también el parser del párrafo, para validarla aunque el párrafo no traiga fechas.\n */\nexport function referenceDay(referenceDate: Date | string): number {\n if (referenceDate instanceof Date) {\n const time = referenceDate.getTime();\n if (Number.isNaN(time)) throw new TypeError('sabre-client: referenceDate es un Date inválido');\n return time - (((time % DAY_MS) + DAY_MS) % DAY_MS);\n }\n if (typeof referenceDate === 'string') {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})(?:T.*)?$/.exec(referenceDate.trim());\n if (match !== null) {\n const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];\n if (isValidDate(year, month, day)) return dayNumber(year, month, day);\n }\n }\n throw new TypeError(\"sabre-client: referenceDate es obligatoria, como 'YYYY-MM-DD' o un Date válido\");\n}\n\nfunction dayNumber(year: number, month: number, day: number): number {\n const date = new Date(0);\n date.setUTCFullYear(year, month - 1, day);\n return date.getTime();\n}\n\nfunction isValidDate(year: number, month: number, day: number): boolean {\n if (month < 1 || month > 12 || day < 1) return false;\n const date = new Date(0);\n date.setUTCFullYear(year, month - 1, day);\n return date.getUTCMonth() === month - 1 && date.getUTCDate() === day;\n}\n\nfunction pad(value: number, length: number): string {\n return String(value).padStart(length, '0');\n}\n","// Parser best-effort del párrafo de cola (un PNR en formato de host). Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 3 y decisiones de la revisión).\nimport { referenceDay, resolveHostDate } from './host-date.js';\n\nexport interface QueueParagraphOptions {\n /**\n * Fecha contra la que se resuelve el año de las fechas sin año: un `'YYYY-MM-DD'` o un `Date`\n * (se toma el día en UTC). Es obligatoria. Ver `resolveHostDate`.\n */\n referenceDate: Date | string;\n}\n\n/** Aviso de cola del principio del párrafo: el código PIC y su descripción (`011 SEE REMARKS`). */\nexport interface QueueParagraphMessage {\n instructionCode: number;\n text: string;\n}\n\n/** Un nombre del PNR (`1.1TEST/SWS*FSG`). */\nexport interface QueueParagraphPassenger {\n /** Número de nombre, tal cual: `'1.1'`. */\n nameNumber: string;\n surname: string;\n givenName?: string;\n /** Lo que sigue al `*` del nombre. */\n nameRemark?: string;\n /** El nombre como llegó, sin el número: `'TEST/SWS*FSG'`. */\n text: string;\n}\n\ninterface QueueParagraphSegmentBase {\n /** Número de segmento en el PNR. */\n number: number;\n /** Fecha ISO (`'2026-05-22'`), con el año resuelto con la regla `'nearest'`. */\n date?: string;\n /** Estado del segmento: `HK`, `HX`, `UN`, `GK`… */\n status: string;\n /** Cantidad que acompaña al estado (`HK1` → `1`). */\n quantity: number;\n /** La línea como llegó, sin espacios a los costados. */\n text: string;\n}\n\n/** Un segmento aéreo: ` 1 DL2151E 20MAR 5 MIALGA HK1 0700 1003 /DCDL*HTDHAT /E`. */\nexport interface QueueParagraphAirSegment extends QueueParagraphSegmentBase {\n kind: 'air';\n airlineCode: string;\n flightNumber: number;\n bookingClass: string;\n fromAirportCode: string;\n toAirportCode: string;\n /** Hora local de salida, en 24 horas (`'07:00'`). */\n departureTime?: string;\n /** Hora local de llegada, en 24 horas. Puede ser de otro día: el host no siempre lo marca. */\n arrivalTime?: string;\n}\n\n/** Un segmento no aéreo con fecha: `2 CAR ZE 22APR Q GK1 DFW/24APR/…`. */\nexport interface QueueParagraphOtherSegment extends QueueParagraphSegmentBase {\n kind: 'other';\n /** Tipo de segmento del host: `CAR`, `OTH`… */\n segmentType: string;\n vendorCode: string;\n}\n\nexport type QueueParagraphSegment = QueueParagraphAirSegment | QueueParagraphOtherSegment;\n\n/** Una entrada del campo de ticketing (`TKT/TIME LIMIT`). */\nexport interface QueueParagraphTicketingEntry {\n /** Número de la entrada: `1` en `1.T-13MAY-X6R3*N18`. */\n number: number;\n /** `'T-'`, `'TAW'` (o `TAC`, `TAM`, `TAT`, `TAX`), o `'TE'`/`'TK'` para una línea de boleto. */\n code: string;\n /** Fecha ISO de la entrada, con el año resuelto con la regla `'nearest'`. */\n date?: string;\n pseudoCityCode?: string;\n agentSine?: string;\n /** Número de boleto de una línea `TE` o `TK`. */\n ticketNumber?: string;\n /** La entrada como llegó, sin el número: `'T-13MAY-X6R3*N18'`. */\n text: string;\n}\n\nexport interface QueueParagraphTicketing {\n entries: QueueParagraphTicketingEntry[];\n /** `true` si alguna entrada es una línea de boleto (`TE` o `TK`, con número). */\n issued: boolean;\n}\n\n/**\n * La línea `RECEIVED FROM - …` y la línea de firma del PNR\n * (`<PCC>.<PCC>*<agente> HHMM/DDMMMYY <localizador> H`). La firma es la de la última modificación.\n */\nexport interface QueueParagraphReceivedFrom {\n /** Lo que sigue a `RECEIVED FROM - `. */\n name?: string;\n /** El primer PCC de la firma. */\n pseudoCityCode?: string;\n /** La firma del agente, lo que sigue al `*`. */\n agentSine?: string;\n /** Fecha y hora de la firma, `'YYYY-MM-DDTHH:mm'`. Sin año, se resuelve hacia atrás. */\n receivedAt?: string;\n locator?: string;\n}\n\nexport interface QueueParagraph {\n messages: QueueParagraphMessage[];\n passengers: QueueParagraphPassenger[];\n segments: QueueParagraphSegment[];\n /** El campo de ticketing, si el párrafo trae la sección `TKT/TIME LIMIT`. */\n ticketing?: QueueParagraphTicketing;\n /** La línea de recibido y la firma, si llega alguna de las dos. */\n receivedFrom?: QueueParagraphReceivedFrom;\n /** Las líneas que no se reconocieron, tal cual y en orden. Las líneas vacías no se incluyen. */\n unparsed: string[];\n}\n\nconst MESSAGE = /^\\s*(\\d{3})\\s{2,}(\\S.*?)\\s*$/;\nconst PASSENGER_LINE = /^\\s*\\d+\\.\\d+[A-Z]/;\nconst PASSENGER_SPLIT = /\\s+(?=\\d+\\.\\d+[A-Z])/;\nconst PASSENGER = /^(\\d+\\.\\d+)([^/*]+?)\\s*(?:\\/([^*]*?))?\\s*(?:\\*(.*?))?\\s*$/;\nconst AIR_SEGMENT =\n /^\\s*(\\d{1,2})\\s+([A-Z0-9]{2})\\s*(\\d{1,4})([A-Z])\\s+(\\d{2}[A-Z]{3})\\s+[A-Z0-9]\\s+([A-Z]{3})([A-Z]{3})\\s+([A-Z]{2})(\\d{1,3})(?=\\s|$)(.*)$/;\nconst SEGMENT_TIMES = /^\\s+(\\d{3,4}[APNM]?)\\s+(\\d{3,4}[APNM]?)(?=\\s|$)/;\nconst OTHER_SEGMENT =\n /^\\s*(\\d{1,2})\\s+([A-Z]{3})\\s+([A-Z0-9]{2})\\s+(\\d{2}[A-Z]{3})\\s+[A-Z0-9]\\s+([A-Z]{2})(\\d{1,3})(?=\\s|$)/;\nconst NO_ITINERARY = /^\\s*NO ITIN\\s*$/;\nconst TICKETING_HEADER = /^\\s*TKT\\/TIME LIMIT\\s*$/;\nconst TICKETING_ENTRY = /^\\s*(\\d+)\\.(.*?)\\s*$/;\nconst TICKETED = /^T-(\\d{2}[A-Z]{3})?(?:-([A-Z0-9]{3,4})\\*([A-Z0-9]+))?(?:\\/.*)?$/;\nconst ARRANGEMENT = /^(TA[WCMTX])([A-Z0-9]{3,4})?(\\d{2}[A-Z]{3})?\\d{0,3}\\/.*$/;\nconst TICKET = /^(TE|TK)\\s+(\\d{13})\\b/;\nconst RECEIVED = /^\\s*RECEIVED FROM -\\s?(.*?)\\s*$/;\nconst SIGNATURE = /^\\s*([A-Z0-9]{3,4})\\.(\\S+)\\s+(\\d{2})(\\d{2})\\/(\\d{2}[A-Z]{3}\\d{2})\\s+([A-Z0-9]{6})\\s+H\\s*$/;\n\n/** En qué parte del párrafo va el parser: cada sección solo se reconoce hasta que empieza la siguiente. */\nconst Phase = { Messages: 0, Passengers: 1, Segments: 2, Body: 3 } as const;\ntype Phase = (typeof Phase)[keyof typeof Phase];\n\n/**\n * Lee un párrafo de cola (`QueueItem.paragraph`) y extrae las secciones estándar de un PNR en\n * formato de host: los avisos de cola, los nombres, los segmentos con su estado, el campo de\n * ticketing y la línea de recibido con la firma.\n *\n * **Es best-effort**: el formato de host no tiene contrato. Una línea que no reconoce va a\n * `unparsed` y nunca lanza por el contenido del párrafo. Solo lanza `TypeError` si `lines` no es\n * un array o si `referenceDate` falta o no es válida.\n *\n * **No extrae** los plazos escritos en texto libre por la aerolínea (`ADTK BY`, `BEFORE` en\n * remarks, SSR u OSI): su formato lo pone cada aerolínea. Esas líneas van a `unparsed`.\n *\n * Las fechas salen como strings ISO sin zona horaria. Los segmentos y el ticketing toman la fecha\n * más cercana a `referenceDate` dentro de ±6 meses, y la firma se resuelve hacia atrás.\n *\n * **Versionado**: que una línea pase de `unparsed` a un campo nuevo es un cambio minor. Que cambie\n * la forma de un campo existente es major.\n */\nexport function parseQueueParagraph(lines: readonly string[], options: QueueParagraphOptions): QueueParagraph {\n if (!Array.isArray(lines)) throw new TypeError('sabre-client: lines debe ser un array de strings');\n if (typeof options !== 'object' || options === null) {\n throw new TypeError(\"sabre-client: referenceDate es obligatoria, como 'YYYY-MM-DD' o un Date válido\");\n }\n const { referenceDate } = options;\n referenceDay(referenceDate);\n\n const result: QueueParagraph = { messages: [], passengers: [], segments: [], unparsed: [] };\n const signatureIndex = lastSignatureIndex(lines);\n let phase: Phase = Phase.Messages;\n let inTicketing = false;\n\n lines.forEach((value, index) => {\n const line = typeof value === 'string' ? value : '';\n if (line.trim() === '') return;\n\n if (index === signatureIndex) {\n result.receivedFrom = { ...result.receivedFrom, ...parseSignature(line, referenceDate) };\n return;\n }\n\n if (inTicketing) {\n const entry = TICKETING_ENTRY.exec(line);\n if (entry !== null) {\n const parsed = parseTicketingEntry(Number(entry[1]), entry[2]!, referenceDate);\n if (parsed === undefined) result.unparsed.push(line);\n else result.ticketing!.entries.push(parsed);\n return;\n }\n inTicketing = false;\n }\n\n if (TICKETING_HEADER.test(line)) {\n phase = Phase.Body;\n inTicketing = true;\n result.ticketing ??= { entries: [], issued: false };\n return;\n }\n\n const received = RECEIVED.exec(line);\n if (received !== null) {\n phase = Phase.Body;\n result.receivedFrom = { ...result.receivedFrom, ...(received[1] !== '' && { name: received[1]! }) };\n return;\n }\n\n if (phase === Phase.Messages) {\n const message = MESSAGE.exec(line);\n if (message !== null) {\n result.messages.push({ instructionCode: Number(message[1]), text: message[2]! });\n return;\n }\n }\n\n if (phase <= Phase.Passengers && PASSENGER_LINE.test(line)) {\n const passengers = parsePassengers(line);\n if (passengers !== undefined) {\n phase = Phase.Passengers;\n result.passengers.push(...passengers);\n return;\n }\n }\n\n if (phase <= Phase.Segments) {\n if (NO_ITINERARY.test(line)) {\n phase = Phase.Segments;\n return;\n }\n const segment = parseSegment(line, referenceDate);\n if (segment !== undefined) {\n phase = Phase.Segments;\n result.segments.push(segment);\n return;\n }\n }\n\n result.unparsed.push(line);\n });\n\n if (result.ticketing !== undefined) {\n result.ticketing.issued = result.ticketing.entries.some((entry) => entry.ticketNumber !== undefined);\n }\n return result;\n}\n\nfunction parsePassengers(line: string): QueueParagraphPassenger[] | undefined {\n const passengers: QueueParagraphPassenger[] = [];\n for (const part of line.trim().split(PASSENGER_SPLIT)) {\n const match = PASSENGER.exec(part);\n if (match === null) return undefined;\n const [, nameNumber, surname, givenName, nameRemark] = match;\n passengers.push({\n nameNumber: nameNumber!,\n surname: surname!.trim(),\n ...(givenName !== undefined && givenName !== '' && { givenName }),\n ...(nameRemark !== undefined && nameRemark !== '' && { nameRemark }),\n text: part.slice(nameNumber!.length).trim(),\n });\n }\n return passengers;\n}\n\nfunction parseSegment(line: string, referenceDate: Date | string): QueueParagraphSegment | undefined {\n const air = AIR_SEGMENT.exec(line);\n if (air !== null) {\n const [, number, airlineCode, flightNumber, bookingClass, date, from, to, status, quantity, rest] = air;\n const times = SEGMENT_TIMES.exec(rest!);\n const departureTime = times === null ? undefined : hostTime(times[1]!);\n const arrivalTime = times === null ? undefined : hostTime(times[2]!);\n return {\n kind: 'air',\n number: Number(number),\n ...withDate(date!, referenceDate),\n status: status!,\n quantity: Number(quantity),\n airlineCode: airlineCode!,\n flightNumber: Number(flightNumber),\n bookingClass: bookingClass!,\n fromAirportCode: from!,\n toAirportCode: to!,\n ...(departureTime !== undefined && { departureTime }),\n ...(arrivalTime !== undefined && { arrivalTime }),\n text: line.trim(),\n };\n }\n\n const other = OTHER_SEGMENT.exec(line);\n if (other === null) return undefined;\n const [, number, segmentType, vendorCode, date, status, quantity] = other;\n return {\n kind: 'other',\n number: Number(number),\n ...withDate(date!, referenceDate),\n status: status!,\n quantity: Number(quantity),\n segmentType: segmentType!,\n vendorCode: vendorCode!,\n text: line.trim(),\n };\n}\n\nfunction parseTicketingEntry(\n number: number,\n text: string,\n referenceDate: Date | string,\n): QueueParagraphTicketingEntry | undefined {\n const ticketed = TICKETED.exec(text);\n if (ticketed !== null) {\n const [, date, pseudoCityCode, agentSine] = ticketed;\n return {\n number,\n code: 'T-',\n ...(date !== undefined && withDate(date, referenceDate)),\n ...(pseudoCityCode !== undefined && { pseudoCityCode }),\n ...(agentSine !== undefined && { agentSine }),\n text,\n };\n }\n\n const arrangement = ARRANGEMENT.exec(text);\n if (arrangement !== null) {\n const [, code, pseudoCityCode, date] = arrangement;\n return {\n number,\n code: code!,\n ...(date !== undefined && withDate(date, referenceDate)),\n ...(pseudoCityCode !== undefined && { pseudoCityCode }),\n text,\n };\n }\n\n const ticket = TICKET.exec(text);\n if (ticket !== null) return { number, code: ticket[1]!, ticketNumber: ticket[2]!, text };\n return undefined;\n}\n\n/** La firma, si hay una, es la última línea con ese formato. Las anteriores van a `unparsed`. */\nfunction lastSignatureIndex(lines: readonly string[]): number {\n for (let index = lines.length - 1; index >= 0; index--) {\n const line = lines[index];\n if (typeof line === 'string' && SIGNATURE.test(line)) return index;\n }\n return -1;\n}\n\nfunction parseSignature(line: string, referenceDate: Date | string): QueueParagraphReceivedFrom {\n const [, pseudoCityCode, sign, hours, minutes, date, locator] = SIGNATURE.exec(line)!;\n const agentSine = /\\*([A-Z0-9]+)$/.exec(sign!)?.[1];\n const day = Number(hours) <= 23 && Number(minutes) <= 59 ? resolveHostDate(date!, referenceDate) : undefined;\n return {\n pseudoCityCode: pseudoCityCode!,\n ...(agentSine !== undefined && { agentSine }),\n ...(day !== undefined && { receivedAt: `${day}T${hours}:${minutes}` }),\n locator: locator!,\n };\n}\n\nfunction withDate(text: string, referenceDate: Date | string): { date?: string } {\n const date = resolveHostDate(text, referenceDate, { direction: 'nearest' });\n return date === undefined ? {} : { date };\n}\n\n/**\n * Hora del host en 24 horas: `0700` y `1003` tal cual, y con sufijo `A` (a. m.), `P` (p. m.),\n * `N` (mediodía) o `M` (medianoche): `740P` → `19:40`, `1200N` → `12:00`.\n */\nfunction hostTime(text: string): string | undefined {\n const match = /^(\\d{1,2})(\\d{2})([APNM])?$/.exec(text);\n if (match === null) return undefined;\n let hours = Number(match[1]);\n const minutes = Number(match[2]);\n const suffix = match[3];\n if (minutes > 59) return undefined;\n if (suffix === undefined) {\n if (hours > 23) return undefined;\n } else {\n if (hours < 1 || hours > 12) return undefined;\n if (suffix === 'A' || suffix === 'M') hours %= 12;\n else if (suffix === 'P') hours = (hours % 12) + 12;\n else if (hours !== 12) return undefined;\n }\n return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;\n}\n","// El remark `QUEUE_PLACE` de Get Booking: dónde se colocó el PNR. Ver\n// sabre-wiki/wiki/proyectos/sabre-client/decisiones/tier-4-colas-avanzadas.md (A4) y\n// wiki/entities/booking-management-api.md (Q-090).\nimport { isInstructionCode } from './queue-place.js';\nimport { MAX_QUEUE_NUMBER } from './queue-ref.js';\n\n/** Un remark `QUEUE_PLACE` ya separado en sus partes. */\nexport interface QueuePlaceRemark {\n /** El PCC de la cola, de 3 o 4 caracteres alfanuméricos (`'MEX'`, `'AB12'`). */\n pcc: string;\n /**\n * La fecha de la colocación, `DDMMM` sin año, tal cual llegó (`'25SEP'`). El año se resuelve con\n * `resolveHostDate(date, referenceDate)`.\n */\n date: string;\n /** El número de cola, de 0 a 511. */\n queue: number;\n /** El PIC (prefatory instruction code), de 0 a 191 o de 200 a 254. Llega con ceros a la izquierda. */\n pic: number;\n}\n\nconst MONTHS = new Set(['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']);\n\n/**\n * `PCC` + `DDMMM` + cola + `/` + PIC, sin separadores: `MEX25SEP146/015`. El mes son las tres letras\n * que van antes de la cola, así que un PCC de 4 caracteres que termina en dígito (`AB1205JUL…`) no\n * se confunde con el día.\n */\nconst REMARK = /^([A-Z0-9]{3,4})(\\d{2})([A-Z]{3})(\\d{1,3})\\/(\\d{1,3})$/;\n\n/**\n * Parsea el `text` de un remark `QUEUE_PLACE` de Get Booking (`remarks[].type === 'QUEUE_PLACE'`).\n * La forma salió de remarks reales de producción (Q-090): `MEX25SEP146/015` da\n * `{ pcc: 'MEX', date: '25SEP', queue: 146, pic: 15 }`.\n *\n * Devuelve `null` si el texto no tiene esa forma, o si el día no está entre 01 y 31, el mes entre\n * `JAN` y `DEC`, la cola entre 0 y 511, o el PIC en 0–191 o 200–254. No lanza: con un valor que no\n * es un string también devuelve `null`. Ignora los espacios a los costados. Sabre manda el texto en\n * mayúsculas, así que uno en minúsculas da `null`.\n */\nexport function parseQueuePlaceRemark(text: string): QueuePlaceRemark | null {\n if (typeof text !== 'string') return null;\n const match = REMARK.exec(text.trim());\n if (match === null) return null;\n const [, pcc, day, month, queueText, picText] = match as unknown as [string, string, string, string, string, string];\n const dayNumber = Number(day);\n if (dayNumber < 1 || dayNumber > 31 || !MONTHS.has(month)) return null;\n const queue = Number(queueText);\n const pic = Number(picText);\n if (queue > MAX_QUEUE_NUMBER || !isInstructionCode(pic)) return null;\n return { pcc, date: `${day}${month}`, queue, pic };\n}\n","// Armado de `SeatAvailabilityByPayloadRq` de Get Seats desde un itinerario de BFM/Revalidate.\n// El mapeo está inferido: ver la tabla \"Armado del request desde el itinerario revalidado\" en\n// sabre-wiki/wiki/sdk/get-seats-en-el-sdk.md.\nimport { definedOnly } from '../config.js';\nimport type {\n SeatAvailabilityByPayloadRq,\n SeatFareComponent,\n SeatPassengerPayloadRq,\n SeatSegmentPayloadRq,\n} from './get-seats.js';\nimport type { FareComponent, Itinerary, ItineraryGroup } from './grouped-itinerary.js';\nimport { itineraryFlights } from './itinerary-flights.js';\n\nexport interface SeatAvailabilityRequestSource {\n /** Grupo del itinerario: aporta la fecha de cada tramo. */\n group: ItineraryGroup;\n /** Itinerario elegido, idealmente el devuelto por Revalidate Itinerary. */\n itinerary: Itinerary;\n /**\n * Números de los vuelos para los que se piden mapas, empezando en 1, igual que `segmentIndex`\n * de `buildBookingFlightDetails` (`1` es `S1`). Por defecto, todos.\n */\n segments?: number[];\n /** ISO 4217 para los precios de los asientos. Si falta, Sabre la elige. */\n currencyCode?: string;\n}\n\n/**\n * Arma el request de `sabre.air.getSeats` por payload para un itinerario ya revalidado.\n *\n * - `segments[]`: un segmento por vuelo, en el orden del itinerario, con `id` `S1`, `S2`, …\n * (`IdType` exige empezar por letra). Vuelo, fechas y clase con las mismas reglas que\n * `buildBookingFlightDetails`; horas en `HH:MM`. Si el operador o su número de vuelo difieren\n * del comercializador, van en `operatingAirlineCode` / `operatingFlightNumber`.\n * - `fareComponents[]`: uno por componente de tarifa (`FC` + su `id` en BFM), con `fareBasis`,\n * `governingCarrier` y `fareDetail`. `brandCode` no se manda: el itinerario no lo trae.\n * - `passengers[]`: `P1`, `P2`, … en el orden de `passengerInfoList`, repetidos según\n * `passengerNumber`. Coinciden con `travelerIndex` de Create Booking si `travelers[]` va en\n * el mismo orden. `fareSegmentAssociation` une cada segmento con su componente de tarifa.\n */\nexport function buildSeatAvailabilityRequest(source: SeatAvailabilityRequestSource): SeatAvailabilityByPayloadRq {\n const { group, itinerary, segments: only, currencyCode } = source;\n const flights = itineraryFlights(group, itinerary);\n\n const segments = flights.map(\n ({ schedule, departureDate, arrivalDate, bookingCode }, i): SeatSegmentPayloadRq => {\n const { carrier } = schedule;\n const operating =\n carrier.operating !== undefined &&\n (carrier.operating !== carrier.marketing ||\n (carrier.operatingFlightNumber !== undefined && carrier.operatingFlightNumber !== carrier.marketingFlightNumber));\n return {\n id: segmentId(i),\n bookingAirlineCode: carrier.marketing,\n bookingFlightNumber: carrier.marketingFlightNumber,\n departureAirportCode: schedule.departure.airport,\n arrivalAirportCode: schedule.arrival.airport,\n departureDate,\n departureTime: schedule.departure.time.slice(0, 5),\n arrivalDate,\n arrivalTime: schedule.arrival.time.slice(0, 5),\n bookingClassCode: bookingCode,\n ...(operating ? { operatingAirlineCode: carrier.operating! } : {}),\n ...(operating && carrier.operatingFlightNumber !== undefined\n ? { operatingFlightNumber: carrier.operatingFlightNumber }\n : {}),\n };\n },\n );\n\n const fare = itinerary.pricingInformation[0]?.fare;\n if (fare === undefined) {\n throw new TypeError('sabre-client: el itinerario no trae pricingInformation');\n }\n const fareComponents = new Map<string, SeatFareComponent>();\n const passengers: SeatPassengerPayloadRq[] = [];\n for (const { passengerInfo } of fare.passengerInfoList) {\n const fareSegmentAssociation: NonNullable<SeatPassengerPayloadRq['fareSegmentAssociation']> = [];\n let next = 0;\n for (const component of passengerInfo.fareComponents ?? []) {\n const fareComponentId = `FC${component.id}`;\n if (!fareComponents.has(fareComponentId)) fareComponents.set(fareComponentId, fareComponent(fareComponentId, component));\n for (const { segment } of component.segments ?? []) {\n const flight = segments[next];\n if (flight === undefined) break;\n if (flight.cabinCode === undefined && segment.cabinCode !== undefined) flight.cabinCode = segment.cabinCode;\n fareSegmentAssociation.push({ segmentRef: flight.id, fareComponentRef: fareComponentId });\n next++;\n }\n }\n for (let n = 0; n < (passengerInfo.passengerNumber ?? 1); n++) {\n passengers.push({\n id: `P${passengers.length + 1}`,\n passengerType: passengerInfo.passengerType,\n ...(fareSegmentAssociation.length === 0 ? {} : { fareSegmentAssociation }),\n });\n }\n }\n\n const refs = (only ?? segments.map((_s, i) => i + 1)).map((n) => {\n if (!Number.isInteger(n) || n < 1 || n > segments.length) {\n throw new TypeError(`sabre-client: segments pide el vuelo ${n}, y hay ${segments.length} (empieza en 1)`);\n }\n return segmentId(n - 1);\n });\n if (refs.length === 0) {\n throw new TypeError('sabre-client: segments no puede ir vacío');\n }\n\n return {\n returnSeatMapsOnlyForSegmentRefs: refs,\n segments,\n passengers,\n ...(fareComponents.size === 0 ? {} : { fareComponents: [...fareComponents.values()] }),\n ...(currencyCode === undefined ? {} : { currencyCode }),\n };\n}\n\nfunction segmentId(index: number): string {\n return `S${index + 1}`;\n}\n\nfunction fareComponent(fareComponentId: string, component: FareComponent): SeatFareComponent {\n const { fareBasisCode, governingCarrier, fareType, fareTariff, fareRule, fareTypeBitmap } = component;\n const fareDetail = definedOnly({ fareType, fareTariff, fareRule, fareTypeBitmap });\n return {\n fareComponentId,\n fareBasis: fareBasisCode,\n ...(governingCarrier === undefined ? {} : { governingCarrier }),\n ...(Object.keys(fareDetail).length === 0 ? {} : { fareDetail }),\n };\n}\n\n","export const VERSION = '0.5.1';\n\nexport { Sabre } from './sabre.js';\nexport { SabreLegacy } from './sabre-legacy.js';\nexport { buildCredentials } from './auth/credentials.js';\nexport type {\n BuildCredentialsOptions,\n BuildCredentialsOptionsV2,\n BuildCredentialsOptionsV3,\n BuiltCredentialsV2,\n BuiltCredentialsV3,\n} from './auth/credentials.js';\nexport type { OpenSessionOptions, SabreSession } from './session/session.js';\nexport type { SabreCommandOptions, SabreCommandResponse } from './session/command.js';\nexport type {\n QueueManagement,\n QueueProcessAction,\n QueueProcessRequest,\n QueueProcessResult,\n QueueState,\n} from './queue/queue-management.js';\nexport type {\n QueueAccessOptions,\n QueueAccessRequest,\n QueueEndReason,\n QueueItem,\n QueueMessage,\n QueueNavigationOptions,\n QueueRemoveRequest,\n QueueRemoveTarget,\n QueueSelection,\n QueueStep,\n} from './queue/queue-access.js';\nexport type {\n QueuePlacement,\n QueuePlaceOptions,\n QueuePlaceRequest,\n QueuePlaceResponse,\n QueuePlaceResult,\n QueuePlaceTarget,\n} from './queue/queue-place.js';\nexport type { QueueListEntry, QueueListOptions, QueueListRequest, QueueListResponse } from './queue/queue-list.js';\nexport { isMessageQueue, MESSAGE_QUEUE } from './queue/queue-ref.js';\nexport type { QueueRef } from './queue/queue-ref.js';\nexport type { QueueCount, QueueCountOptions, QueueCountRequest, QueueCountResponse } from './queue/queue-count.js';\nexport type { SessionReservation } from './reservation/session-reservation.js';\nexport type {\n ReservationHistoryAccounting,\n ReservationHistoryFlightSegment,\n ReservationHistoryOptions,\n ReservationHistoryResponse,\n ReservationHistoryText,\n ReservationHistoryTransaction,\n} from './reservation/reservation-history.js';\nexport type {\n QueueActivity,\n QueueActivityCounters,\n QueueActivityOptions,\n QueueActivityRequest,\n QueueActivityResponse,\n} from './queue/queue-activity.js';\nexport { resolveHostDate } from './queue/host-date.js';\nexport type { HostDateDirection, ResolveHostDateOptions } from './queue/host-date.js';\nexport { parseQueueParagraph } from './queue/queue-paragraph.js';\nexport { parseQueuePlaceRemark } from './queue/queue-place-remark.js';\nexport type { QueuePlaceRemark } from './queue/queue-place-remark.js';\nexport type {\n QueueParagraph,\n QueueParagraphAirSegment,\n QueueParagraphMessage,\n QueueParagraphOptions,\n QueueParagraphOtherSegment,\n QueueParagraphPassenger,\n QueueParagraphReceivedFrom,\n QueueParagraphSegment,\n QueueParagraphTicketing,\n QueueParagraphTicketingEntry,\n} from './queue/queue-paragraph.js';\nexport type { Air } from './air/air.js';\nexport type {\n BargainFinderMaxRequest,\n BargainFinderMaxResponse,\n RequestOptions,\n} from './air/bargain-finder-max.js';\nexport type {\n GetSeatsRequest,\n GetSeatsResponse,\n RawSeatAvailabilityRs,\n Seat,\n SeatAvailabilityByPayloadRq,\n SeatAvailabilityByPnrLocatorRq,\n SeatAvailabilityIssue,\n SeatAvailabilityResponse,\n SeatCabinCompartment,\n SeatCabinFacility,\n SeatCabinAisle,\n SeatCabinLayout,\n SeatCabinRowPosition,\n SeatCharacteristic,\n SeatDisplayOnlyItem,\n SeatFareComponent,\n SeatFareDetail,\n SeatFareSegmentAssociation,\n SeatFlightLeg,\n SeatKeyValuePair,\n SeatLoyaltyProgramAccount,\n SeatMap,\n SeatOfferItem,\n SeatOfferItemDetails,\n SeatPassenger,\n SeatPassengerPayloadRq,\n SeatPassengerRs,\n SeatPriceBreakdown,\n SeatPriceDefinition,\n SeatRow,\n SeatSegment,\n SeatSegmentPayloadRq,\n SeatSegmentRs,\n SeatServiceDefinition,\n SeatSpecialServiceRequest,\n SeatTax,\n} from './air/get-seats.js';\nexport { buildSeatAvailabilityRequest } from './air/seat-availability-request.js';\nexport type { SeatAvailabilityRequestSource } from './air/seat-availability-request.js';\nexport { buildRevalidateItineraryRequest } from './air/revalidate-itinerary.js';\nexport type {\n RevalidateItineraryRequest,\n RevalidateItineraryRequestSource,\n RevalidateItineraryResponse,\n} from './air/revalidate-itinerary.js';\nexport type {\n LowFareSearchFlight,\n LowFareSearchLocation,\n LowFareSearchOriginDestination,\n LowFareSearchPassengerTypeQuantity,\n LowFareSearchRequestorId,\n LowFareSearchSource,\n LowFareSearchTpaExtensions,\n LowFareSearchTravelerInfoSummary,\n LowFareSearchTravelPreferences,\n OtaAirLowFareSearchRq,\n} from './air/low-fare-search-request.js';\nexport type { SabreTokenStore, StoredToken } from './auth/token-store.js';\nexport type { BookingManagement } from './booking/booking-management.js';\nexport type {\n Booking,\n CreateBookingOptions,\n CreateBookingResponse,\n CreateBookingResponseError,\n} from './booking/create-booking.js';\nexport type {\n BookContactInformation,\n BookGenericSeat,\n BookingAgency,\n BookSeat,\n BookTraveler,\n BrandedFare,\n CreateBookingErrorPolicy,\n CreateBookingRequest,\n FlightDetails,\n FlightStatusCode,\n FlightToBook,\n PassengerPricing,\n PaymentMethod,\n PriceComparison,\n PriceComparisonType,\n PricingDetails,\n PricingQualifiers,\n SeatAreaPreference,\n SpecificFare,\n TicketingPolicy,\n TravelerPhone,\n TravelerTitle,\n} from './booking/create-booking-request.js';\nexport type {\n BookingSource,\n GetBookingExtraFeatures,\n GetBookingOptions,\n GetBookingRequest,\n GetBookingResponse,\n GetBookingReturnOnly,\n} from './booking/get-booking.js';\nexport type {\n BookingItemReference,\n CancelBookingErrorPolicy,\n CancelBookingNotification,\n CancelBookingOptions,\n CancelBookingRequest,\n CancelBookingResponse,\n CancelSegmentReference,\n FlightTicketOperation,\n RefundDocumentsType,\n} from './booking/cancel-booking.js';\nexport type { BookingResponseError } from './booking/booking-errors.js';\nexport { buildBookingFlightDetails } from './booking/flight-details.js';\nexport type { BookingFlightDetailsSource, BookingSeatSelection, PricedSeat } from './booking/flight-details.js';\nexport type {\n SabreAuthVersion,\n SabreConfig,\n SabreConfigV2,\n SabreConfigFromCredentials,\n SabreConfigV2FromCredentials,\n SabreConfigV3,\n SabreCredentials,\n SabreCredentialsAnyVersion,\n SabreCredentialsV2,\n SabreEnvironment,\n} from './config.js';\nexport type { RetryOptions } from './http/retry.js';\nexport type { SabreRawRequest, SabreRawRequestCallback } from './http/raw-request.js';\nexport type { SabreRawResponse, SabreRawResponseCallback } from './http/raw-response.js';\nexport * from './errors/index.js';\nexport * from './logging/index.js';\nexport type {\n BaggageAllowanceDesc,\n BaggageInformation,\n CurrencyConversion,\n Fare,\n FareComponent,\n FareComponentDesc,\n FareComponentDescSegment,\n FareComponentSegment,\n FareComponentSegmentDetail,\n FareMessage,\n GroupedItineraryResponse,\n Itinerary,\n ItineraryGroup,\n ItineraryMessage,\n Leg,\n LegDesc,\n LegSchedule,\n LegScheduleRef,\n LegDescription,\n ObFeeDesc,\n PassengerInfo,\n PassengerTotalFare,\n PricingInformation,\n Ref,\n ScheduleCarrier,\n ScheduleDesc,\n ScheduleEndpoint,\n ScheduleEquipment,\n TaxDesc,\n TaxSummaryDesc,\n TotalFare,\n ValidatingCarrierDesc,\n} from './air/grouped-itinerary.js';\n// Tipos completos de `Booking` (spec v1.33, #158).\nexport type * from './booking/booking-types.js';\n"],"mappings":";AAiBO,IAAM,aAAN,cAAyB,MAAM;AAAA,EAC3B,OAAO;AAAA,EACP;AAAA,EAGT,YAAY,SAAiB,SAA4B;AACvD,UAAM,SAAS,QAAQ,UAAU,SAAY,SAAY,EAAE,OAAO,QAAQ,MAAM,CAAC;AACjF,SAAK,YAAY,QAAQ;AACzB,WAAO,eAAe,MAAM,OAAO;AAAA,MACjC,OAAO,QAAQ;AAAA,MACf,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEA,SAAkC;AAChC,UAAM,SAAkC,OAAO,YAAY,OAAO,QAAQ,IAAI,CAAC;AAC/E,WAAO,EAAE,GAAG,QAAQ,MAAM,KAAK,MAAM,SAAS,KAAK,QAAQ;AAAA,EAC7D;AACF;AAaO,IAAM,oBAAN,cAAgC,WAAW;AAAA,EACvC,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,SAAmC;AAC9D,UAAM,SAAS,OAAO;AACtB,SAAK,WAAW,QAAQ;AACxB,SAAK,SAAS,QAAQ;AACtB,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;AAiBO,IAAM,oBAAN,cAAgC,kBAAkB;AAAA,EAC9C,OAAO;AAAA,EACP;AAAA,EAET,YAAY,SAAiB,SAAmC;AAC9D,UAAM,SAAS,EAAE,GAAG,SAAS,UAAU,OAAO,CAAC;AAC/C,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;AAWO,IAAM,0BAAN,cAAsC,WAAW;AAAA,EAC7C,OAAO;AAAA,EACP;AAAA,EAET,YAAY,SAAiB,SAAyC;AACpE,UAAM,SAAS,EAAE,GAAG,SAAS,WAAW,QAAQ,SAAS,oBAAoB,CAAC;AAC9E,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;AA6BO,IAAM,qBAAN,cAAiC,WAAW;AAAA,EACxC,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,SAAoC;AAC/D,UAAM,SAAS,EAAE,GAAG,SAAS,WAAW,QAAQ,aAAa,MAAM,CAAC;AACpE,SAAK,UAAU,QAAQ;AACvB,SAAK,OAAO,QAAQ;AACpB,SAAK,WAAW,QAAQ,YAAY,CAAC;AACrC,SAAK,SAAS,QAAQ,UAAU,CAAC;AAAA,EACnC;AACF;AAMO,IAAM,eAAN,cAA2B,WAAW;AAAA,EAClC,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,SAAmC;AAC9D,UAAM,SAAS,EAAE,GAAG,SAAS,WAAW,MAAM,CAAC;AAC/C,SAAK,UAAU,QAAQ;AACvB,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;;;AC8OO,SAAS,oCACd,KACA,SAC0B;AAC1B,QAAM,WAAW,IAAI,SAAS,KAAK,OAAO;AAC1C,SAAO;AAAA,IACL,SAAS,IAAI;AAAA,IACb,UAAU,IAAI,YAAY,CAAC;AAAA,IAC3B,GAAI,IAAI,eAAe,SAAY,CAAC,IAAI,EAAE,YAAY,IAAI,WAAW;AAAA,IACrE,kBAAkB,IAAI,mBAAmB,CAAC,GAAG,IAAI,CAAC,WAAW;AAAA,MAC3D,kBAAkB,MAAM;AAAA,MACxB,aAAa,MAAM,YAAY,IAAI,CAAC,cAAc,SAAS,UAAU,SAAS,CAAC;AAAA,IACjF,EAAE;AAAA,EACJ;AACF;AAEA,IAAM,WAAN,MAAe;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,KAAkC,SAAiB;AAC7D,SAAK,WAAW;AAChB,SAAK,aAAa,KAAK,IAAI,aAAa;AACxC,SAAK,QAAQ,KAAK,IAAI,QAAQ;AAC9B,SAAK,SAAS,KAAK,IAAI,QAAQ;AAC/B,SAAK,gBAAgB,KAAK,IAAI,eAAe;AAC7C,SAAK,UAAU,KAAK,IAAI,UAAU;AAClC,SAAK,kBAAkB,KAAK,IAAI,kBAAkB;AAClD,SAAK,sBAAsB,KAAK,IAAI,sBAAsB;AAC1D,SAAK,qBAAqB,KAAK,IAAI,qBAAqB;AAAA,EAC1D;AAAA,EAEA,UAAU,WAAoC;AAC5C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,UAAU,KAAK,IAAI,CAAC,QAAQ,KAAK,KAAK,GAAG,CAAC;AAAA,MAChD,oBAAoB,UAAU,mBAAmB,IAAI,CAAC,aAAa;AAAA,QACjE,GAAG;AAAA,QACH,MAAM,KAAK,MAAM,QAAQ,IAAI;AAAA,MAC/B,EAAE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,KAAK,KAAe;AAClB,UAAM,MAAM,KAAK,OAAO,KAAK,OAAO,YAAY,GAAG;AACnD,WAAO,EAAE,GAAG,KAAK,WAAW,IAAI,UAAU,IAAI,CAAC,aAAa,KAAK,OAAO,KAAK,YAAY,iBAAiB,QAAQ,CAAC,EAAE;AAAA,EACvH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,oBAAoB,GAAG,KAAK,IAAI;AACxC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,mBAAmB,KAAK,kBAAkB,IAAI,CAAC,EAAE,eAAe,GAAG,MAAM,OAAO;AAAA,QAC9E,GAAG;AAAA,QACH,eAAe,KAAK,eAAe,aAAa;AAAA,MAClD,EAAE;AAAA,MACF,GAAI,uBAAuB,SACvB,CAAC,IACD;AAAA,QACE,oBAAoB,mBAAmB;AAAA,UAAI,CAAC,QAC1C,KAAK,OAAO,KAAK,qBAAqB,0BAA0B,GAAG;AAAA,QACrE;AAAA,MACF;AAAA,IACN;AAAA,EACF;AAAA,EAEA,eAAe,MAAuC;AACpD,UAAM,EAAE,gBAAgB,OAAO,cAAc,QAAQ,oBAAoB,GAAG,KAAK,IAAI;AACrF,UAAM,SAAwB,EAAE,GAAG,KAAK;AACxC,QAAI,mBAAmB,OAAW,QAAO,iBAAiB,eAAe,IAAI,CAAC,QAAQ,KAAK,eAAe,GAAG,CAAC;AAC9G,QAAI,UAAU,OAAW,QAAO,QAAQ,MAAM,IAAI,CAAC,QAAQ,KAAK,OAAO,KAAK,QAAQ,YAAY,GAAG,CAAC;AACpG,QAAI,iBAAiB,QAAW;AAC9B,aAAO,eAAe,aAAa,IAAI,CAAC,QAAQ,KAAK,OAAO,KAAK,eAAe,mBAAmB,GAAG,CAAC;AAAA,IACzG;AACA,QAAI,WAAW,OAAW,QAAO,SAAS,OAAO,IAAI,CAAC,QAAQ,KAAK,OAAO,KAAK,SAAS,cAAc,GAAG,CAAC;AAC1G,QAAI,uBAAuB,QAAW;AACpC,aAAO,qBAAqB,mBAAmB,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,OAAO;AAAA,QAC7E,GAAG;AAAA,QACH,GAAI,cAAc,SACd,CAAC,IACD,EAAE,WAAW,KAAK,OAAO,KAAK,oBAAoB,yBAAyB,SAAS,EAAE;AAAA,MAC5F,EAAE;AAAA,IACJ;AACA,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,KAAsC;AACnD,UAAM,OAAO,KAAK,QAAQ,KAAK,iBAAiB,sBAAsB,IAAI,GAAG;AAC7E,UAAM,EAAE,KAAK,MAAM,UAAU,cAAc,GAAG,KAAK,IAAI;AACvD,UAAM,EAAE,UAAU,cAAc,GAAG,SAAS,IAAI;AAChD,QAAI,iBAAiB,UAAa,iBAAiB,UAAa,aAAa,WAAW,aAAa,QAAQ;AAC3G,YAAM,KAAK;AAAA,QACT,sBAAsB,aAAa,MAAM,mCAAmC,IAAI,GAAG,QAAQ,aAAa,MAAM;AAAA,MAChH;AAAA,IACF;AACA,UAAM,WAAW,cAAc,cAAc,YAAY;AACzD,WAAO,EAAE,GAAG,UAAU,GAAG,MAAM,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS,EAAG;AAAA,EACjF;AAAA;AAAA,EAGA,OAAiC,OAAuB,MAAc,KAAa;AACjF,UAAM,EAAE,KAAK,IAAI,GAAG,KAAK,IAAI;AAC7B,WAAO,EAAE,GAAG,KAAK,QAAQ,OAAO,MAAM,EAAE,GAAG,GAAG,KAAK;AAAA,EACrD;AAAA,EAEA,QAAW,OAAuB,MAAc,IAAe;AAC7D,UAAM,OAAO,MAAM,IAAI,EAAE;AACzB,QAAI,SAAS,OAAW,OAAM,KAAK,WAAW,OAAO,EAAE,sBAAsB,IAAI,EAAE;AACnF,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,QAA4B;AACrC,WAAO,IAAI,WAAW,GAAG,KAAK,QAAQ,2BAA2B,MAAM,IAAI,EAAE,WAAW,MAAM,CAAC;AAAA,EACjG;AACF;AAEA,SAAS,KAA+B,OAAwC;AAC9E,SAAO,IAAI,KAAK,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC7D;AAEA,SAAS,cACP,MACA,MACoC;AACpC,MAAI,SAAS,UAAa,SAAS,OAAW,QAAO;AAErD,QAAM,SAAS,MAAM,UAAU,MAAM,UAAU;AAC/C,SAAO,MAAM,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG,OAAO;AAAA,IACvC,SAAS,EAAE,GAAG,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,GAAG,QAAQ;AAAA,EAC1D,EAAE;AACJ;;;ACvgBO,SAAS,0BACd,MACA,SACA,SACwB;AACxB,QAAM,WAAW,SAAS,IAAI,IAAI,KAAK,2BAA2B;AAClE,MAAI,CAAC,SAAS,QAAQ,GAAG;AACvB,WAAO,IAAI,WAAW,GAAG,OAAO,0DAA0D;AAAA,MACxF,WAAW;AAAA,MACX,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACA,QAAM,WAAW,MAAM,QAAQ,SAAS,QAAQ,IAAK,SAAS,WAA2C,CAAC;AAC1G,QAAM,QAAQ,SAAS,KAAK,CAAC,YAAY,QAAQ,UAAU,YAAY,MAAM,OAAO;AACpF,MAAI,UAAU,OAAW,QAAO;AAEhC,QAAM,QAAQ,cAAc,UAAU,OAAO;AAC7C,QAAM,OAAO,OAAO,SAAS,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAC3E,QAAM,QAAQ,OAAO;AACrB,QAAM,OAAO,OAAO,QAAQ,MAAM,QAAQ;AAC1C,SAAO,IAAI,mBAAmB,GAAG,OAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,IAC3D;AAAA,IACA;AAAA,IACA,WAAW,OAAO,aAAa;AAAA,IAC/B,KAAK;AAAA,EACP,CAAC;AACH;AAEA,SAAS,cACP,UACA,SACmE;AACnE,aAAW,WAAW,UAAU;AAC9B,QAAI,OAAO,QAAQ,SAAS,SAAU;AACtC,UAAM,OAAO,QAAQ,KAAK,YAAY;AACtC,UAAM,QAAQ,QAAQ,KAAK,CAAC,cAAc,KAAK,SAAS,UAAU,KAAK,YAAY,CAAC,CAAC;AACrF,QAAI,UAAU,OAAW,QAAO,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,EAC9D;AACA,SAAO;AACT;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;;;AClBO,SAAS,kBAAkB,SAA+B;AAC/D,QAAM,OAAO,IAAI,QAAQ,OAAO;AAChC,OAAK,OAAO,eAAe;AAC3B,SAAO;AACT;AAMO,SAAS,SACd,SACA,WAC0G;AAC1G,QAAM,EAAE,eAAe,aAAa,IAAI;AACxC,MAAI,kBAAkB,UAAa,iBAAiB,OAAW,QAAO,CAAC;AACvE,SAAO;AAAA,IACL;AAAA,IACA,GAAI,kBAAkB,SAAY,CAAC,IAAI,EAAE,cAAc;AAAA,IACvD,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA,EACvD;AACF;;;ACpDO,IAAM,6BAA6B;AAC1C,IAAM,OAAO;AAyBN,IAAM,6BAA0E;AAAA,EACrF,EAAE,MAAM,mBAAmB,WAAW,MAAM;AAAA,EAC5C,EAAE,MAAM,2CAA2C,WAAW,MAAM;AAAA,EACpE,EAAE,MAAM,4BAA4B,WAAW,KAAK;AAAA,EACpD,EAAE,MAAM,wBAAwB,WAAW,KAAK;AAAA,EAChD,EAAE,MAAM,0BAA0B,WAAW,KAAK;AAAA,EAClD,EAAE,MAAM,iCAAiC,WAAW,KAAK;AAC3D;AAEA,eAAsB,iBACpB,WACA,SACA,UAA0B,CAAC,GACQ;AACnC,MAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,OAAO,QAAQ,2BAA2B,UAAU;AACzG,UAAM,IAAI,UAAU,2EAA2E;AAAA,EACjG;AACA,QAAM,OAAO,MAAM,UAAU,QAAmE;AAAA,IAC9F,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA;AAAA,IAET,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,GAAI,QAAQ,UAAU,SAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;AAAA,IAC9D,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,IACjE,GAAG,SAAS,SAAS,sBAAsB;AAAA,EAC7C,CAAC;AACD,SAAO,oCAAoC,KAAK,0BAA0B,0BAA0B;AACtG;AAGO,SAAS,yBAAyB,MAAuC;AAC9E,SAAO,0BAA0B,MAAM,4BAA4B,0BAA0B;AAC/F;;;ACxEA,IAAM,UAAU;AAeT,SAAS,eAAe,UAAuE;AACpG,SAAO,MAAM,QAAQ,SAAS,MAAM,IAAI,SAAS,OAAO,OAAOA,SAAQ,IAA8B,CAAC;AACxG;AAEO,SAAS,UAAU,MAAqC;AAC7D,SAAO,OAAO,KAAK,aAAa,YAAY,KAAK,SAAS,YAAY,MAAM;AAC9E;AAEO,SAAS,UAAU,SAAiB,MAA0C;AACnF,SAAO,IAAI,aAAa,UAAU,SAAS,IAAI,GAAG,EAAE,SAAS,MAAM,OAAO,IAAI,GAAG,KAAK,KAAK,CAAC;AAC9F;AAQO,SAAS,gBACd,SACA,MACA,EAAE,WAAW,CAAC,GAAG,SAAS,CAAC,GAAG,YAAY,MAAM,IAA8B,CAAC,GAC3D;AACpB,SAAO,IAAI,mBAAmB,UAAU,SAAS,IAAI,GAAG;AAAA,IACtD;AAAA,IACA,MAAM,OAAO,IAAI;AAAA,IACjB,KAAK;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEO,SAAS,OAAO,MAAoC;AACzD,SAAO,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,KAAK,KAAK,OAAO,OAAO,KAAK,QAAQ;AAC7F;AAGA,SAAS,UAAU,SAAiB,MAAoC;AACtE,QAAM,QAAQ,OAAO,KAAK,cAAc,YAAY,KAAK,cAAc,KAAK,OAAO,KAAK,SAAS,KAAK;AACtG,QAAM,cAAc,OAAO,KAAK,gBAAgB,YAAY,KAAK,gBAAgB,KAAK,KAAK,KAAK,WAAW,KAAK;AAChH,SAAO,GAAG,OAAO,KAAK,OAAO,KAAK,QAAQ,CAAC,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,GAAG,WAAW;AACnF;AAEO,SAAS,SAAS,OAAiC;AACxD,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEO,SAASA,UAAS,OAAkD;AACzE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;;;AC5DO,IAAM,+BAA+B;AAC5C,IAAM,kBAAkB;AACjB,IAAM,mCAAmC;AAChD,IAAM,sBAAsB;AAE5B,IAAM,iBAAiB,CAAC,YAAY,cAAc,kCAAkC;AAkXpF,eAAsB,SACpB,WACA,SACA,UAA0B,CAAC,GACA;AAC3B,MAAI,CAACC,UAAS,OAAO,GAAG;AACtB,UAAM,IAAI,UAAU,6CAA6C;AAAA,EACnE;AACA,MAAI,gBAAgB,SAAS;AAE3B,QAAI,CAAC,SAAS,QAAQ,UAAU,GAAG;AACjC,YAAM,IAAI,UAAU,oDAAiD;AAAA,IACvE;AACA,UAAM,QAAQ,eAAe,OAAO,CAAC,UAAU,SAAS,OAAO;AAC/D,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,IAAI,UAAU,uDAAuD,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,IAC/F;AACA,WAAO,KAAK,WAAW,qBAAqB,kCAAkC,SAAS,OAAO;AAAA,EAChG;AACA,MAAI,CAAC,MAAM,QAAQ,QAAQ,QAAQ,KAAK,CAAC,MAAM,QAAQ,QAAQ,UAAU,GAAG;AAC1E,UAAM,IAAI,UAAU,gGAAgG;AAAA,EACtH;AACA,SAAO,KAAK,WAAW,iBAAiB,8BAA8B,SAAS,OAAO;AACxF;AAEA,eAAe,KACb,WACA,MACA,SACA,SACA,SAC2B;AAC3B,QAAM,OAAO,MAAM,UAAU,QAA+B;AAAA,IAC1D,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,UAAU,CAAC,QAAQ,iBAAiB,KAAK,OAAO;AAAA,IAChD,GAAI,QAAQ,UAAU,SAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;AAAA,IAC9D,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,IACjE,GAAG,SAAS,SAAS,OAAO,OAAO,EAAE;AAAA,EACvC,CAAC;AACD,SAAO;AAAA,IACL,UAAU,KAAK;AAAA,IACf,UAAU,OAAO,KAAK,QAAQ,EAAE,IAAI,CAAC,SAAS,UAAU,SAAS,IAAI,CAAC;AAAA,IACtE,QAAQ,OAAO,KAAK,MAAM,EAAE,IAAI,CAAC,SAAS,gBAAgB,SAAS,IAAI,CAAC;AAAA,EAC1E;AACF;AAWO,SAAS,iBAAiB,MAAe,SAAyC;AACvF,MAAI,CAACA,UAAS,IAAI,GAAG;AACnB,WAAO,IAAI,WAAW,GAAG,OAAO,iDAAiD,EAAE,WAAW,OAAO,KAAK,KAAK,CAAC;AAAA,EAClH;AACA,QAAM,KAAK;AACX,MAAIA,UAAS,GAAG,QAAQ,EAAG,QAAO;AAElC,QAAM,CAAC,OAAO,GAAG,IAAI,IAAI,OAAO,GAAG,MAAM;AACzC,MAAI,UAAU,QAAW;AACvB,WAAO,gBAAgB,SAAS,OAAO;AAAA,MACrC,UAAU,OAAO,GAAG,QAAQ,EAAE,IAAI,CAAC,SAAS,UAAU,SAAS,IAAI,CAAC;AAAA,MACpE,QAAQ,KAAK,IAAI,CAAC,SAAS,gBAAgB,SAAS,IAAI,CAAC;AAAA,IAC3D,CAAC;AAAA,EACH;AACA,SAAO,IAAI,WAAW,GAAG,OAAO,kDAAkD,EAAE,WAAW,OAAO,KAAK,KAAK,CAAC;AACnH;AAEA,SAAS,OAAO,MAAoE;AAClF,SAAO,MAAM,QAAQ,IAAI,IAAI,KAAK,OAAOA,SAAQ,IAA+B,CAAC;AACnF;;;ACrbO,SAAS,iBAAiB,OAAuB,WAAyC;AAC/F,QAAM,EAAE,gBAAgB,IAAI,MAAM;AAClC,MAAI,gBAAgB,WAAW,UAAU,KAAK,QAAQ;AACpD,UAAM,IAAI;AAAA,MACR,qCAAqC,UAAU,KAAK,MAAM,sBAAsB,gBAAgB,MAAM;AAAA,IACxG;AAAA,EACF;AACA,QAAM,UAAU,aAAa,SAAS;AACtC,QAAM,cAAc,UAAU,KAAK,OAAO,CAAC,GAAG,QAAQ,IAAI,IAAI,UAAU,QAAQ,CAAC;AACjF,MAAI,QAAQ,WAAW,aAAa;AAClC,UAAM,IAAI;AAAA,MACR,qCAAqC,WAAW,aAAa,QAAQ,MAAM;AAAA,IAC7E;AAAA,EACF;AAEA,MAAI,OAAO;AACX,SAAO,UAAU,KAAK,QAAQ,CAAC,KAAK,aAAa;AAC/C,UAAM,UAAU,gBAAgB,QAAQ,EAAG;AAC3C,WAAO,IAAI,UAAU,IAAI,CAAC,aAAa;AACrC,YAAM,gBAAgB,QAAQ,SAAS,SAAS,2BAA2B,CAAC;AAC5E,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,QAAQ,eAAe,SAAS,QAAQ,kBAAkB,CAAC;AAAA,QACxE,aAAa,QAAQ,MAAM;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,aAAa,WAAgC;AACpD,QAAM,YAAY,UAAU,mBAAmB,CAAC,GAAG,KAAK,kBAAkB,CAAC,GAAG;AAC9E,UAAQ,WAAW,kBAAkB,CAAC,GAAG;AAAA,IAAQ,CAAC,eAC/C,UAAU,YAAY,CAAC,GAAG,IAAI,CAAC,EAAE,QAAQ,MAAM;AAC9C,UAAI,QAAQ,gBAAgB,QAAW;AACrC,cAAM,IAAI,UAAU,iEAAiE;AAAA,MACvF;AACA,aAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AACF;AAGA,SAAS,QAAQ,MAAc,MAAsB;AACnD,MAAI,SAAS,EAAG,QAAO;AACvB,QAAM,CAAC,MAAM,OAAO,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,MAAM;AACrD,SAAO,IAAI,KAAK,KAAK,IAAI,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAClF;;;ACpDO,IAAM,+BAA+B;AAC5C,IAAMC,QAAO;AAUb,eAAsB,oBACpB,WACA,SACA,UAA0B,CAAC,GACW;AACtC,MAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,OAAO,QAAQ,2BAA2B,UAAU;AACzG,UAAM,IAAI,UAAU,8EAA8E;AAAA,EACpG;AACA,QAAM,OAAO,MAAM,UAAU,QAAmE;AAAA,IAC9F,QAAQ;AAAA,IACR,MAAMA;AAAA,IACN,SAAS;AAAA;AAAA,IAET,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,GAAI,QAAQ,UAAU,SAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;AAAA,IAC9D,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,IACjE,GAAG,SAAS,SAAS,yBAAyB;AAAA,EAChD,CAAC;AACD,SAAO,oCAAoC,KAAK,0BAA0B,4BAA4B;AACxG;AAWO,IAAM,+BAA4E;AAAA,EACvF,EAAE,MAAM,sCAAsC,WAAW,MAAM;AAAA,EAC/D,EAAE,MAAM,0BAA0B,WAAW,MAAM;AAAA,EACnD,EAAE,MAAM,2CAA2C,WAAW,MAAM;AAAA,EACpE,EAAE,MAAM,kBAAkB,WAAW,MAAM;AAAA,EAC3C,EAAE,MAAM,mBAAmB,WAAW,MAAM;AAAA,EAC5C,GAAG,2BAA2B,OAAO,CAAC,UAAU,MAAM,SAAS;AACjE;AAGO,SAAS,4BAA4B,MAAuC;AACjF,SAAO,0BAA0B,MAAM,8BAA8B,4BAA4B;AACnG;AAoBO,SAAS,gCAAgC,QAAsE;AACpH,QAAM,EAAE,QAAQ,OAAO,UAAU,IAAI;AACrC,QAAM,UAAU,iBAAiB,OAAO,SAAS;AAEjD,QAAM,qBAAqB,UAAU,KAAK,IAAI,CAAC,MAAM,MAAsC;AACzF,UAAM,aAAa,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,IAAI,MAAM;AACrE,UAAM,QAAQ,WAAW,CAAC;AAC1B,UAAM,OAAO,WAAW,GAAG,EAAE;AAC7B,WAAO;AAAA,MACL,OAAO;AAAA,MACP,mBAAmB,MAAM;AAAA,MACzB,gBAAgB,EAAE,cAAc,MAAM,eAAe,aAAa;AAAA,MAClE,qBAAqB,EAAE,cAAc,KAAK,oBAAoB,aAAa;AAAA,MAC3E,gBAAgB,EAAE,QAAQ,WAAW;AAAA,IACvC;AAAA,EACF,CAAC;AAED,QAAM,EAAE,SAAS,KAAK,qBAAqB,eAAe,IAAI,OAAO;AACrE,SAAO;AAAA,IACL,wBAAwB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,8BAA8B;AAAA,MAC9B,mBAAmB;AAAA,QACjB,kBAAkB,KAAK,IAAI,GAAG,UAAU,KAAK,IAAI,CAAC,QAAQ,IAAI,UAAU,SAAS,CAAC,CAAC;AAAA,QACnF,gBAAgB,EAAE,2BAA2B,EAAE,OAAO,IAAI,EAAE;AAAA,MAC9D;AAAA,MACA;AAAA,MACA,GAAI,mBAAmB,SAAY,CAAC,IAAI,EAAE,eAAe;AAAA,IAC3D;AAAA,EACF;AACF;AAEA,SAAS,OAAO,EAAE,UAAU,eAAe,aAAa,YAAY,GAAyC;AAC3G,QAAM,EAAE,QAAQ,IAAI;AACpB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,QAAQ;AAAA,IAChB,mBAAmB,GAAG,aAAa,IAAI,UAAU,SAAS,UAAU,IAAI,CAAC;AAAA,IACzE,iBAAiB,GAAG,WAAW,IAAI,UAAU,SAAS,QAAQ,IAAI,CAAC;AAAA,IACnE,gBAAgB;AAAA,IAChB,gBAAgB,EAAE,cAAc,SAAS,UAAU,QAAQ;AAAA,IAC3D,qBAAqB,EAAE,cAAc,SAAS,QAAQ,QAAQ;AAAA,IAC9D,SAAS;AAAA,MACP,WAAW,QAAQ;AAAA,MACnB,GAAI,QAAQ,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;AAAA,IAC5E;AAAA,EACF;AACF;AAGA,SAAS,UAAU,MAAsB;AACvC,SAAO,KAAK,MAAM,GAAG,CAAC;AACxB;;;ACtIO,IAAM,MAAN,MAAU;AAAA,EACN;AAAA;AAAA,EAGT,YAAY,WAA0B;AACpC,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,SAAkC,SAA6D;AAC9G,WAAO,iBAAiB,KAAK,YAAY,SAAS,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBACE,SACA,SACsC;AACtC,WAAO,oBAAoB,KAAK,YAAY,SAAS,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,SAA0B,SAAqD;AACtF,WAAO,SAAS,KAAK,YAAY,SAAS,OAAO;AAAA,EACnD;AACF;;;AChDO,IAAM,WAAW;AAMxB,IAAM,iBAAiB,IAAI;AAAA,EACzB;AAAA;AAAA,IAEE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,EACF,EAAE,IAAI,YAAY;AACpB;AAEA,SAAS,aAAa,KAAqB;AACzC,SAAO,IAAI,QAAQ,WAAW,EAAE,EAAE,YAAY;AAChD;AAEO,SAAS,eAAe,KAAsB;AACnD,SAAO,eAAe,IAAI,aAAa,GAAG,CAAC;AAC7C;AAGO,SAAS,OAAO,OAAyB;AAC9C,SAAO,YAAY,OAAO,oBAAI,QAAQ,CAAC;AACzC;AAEA,SAAS,YAAY,OAAgB,MAAgC;AACnE,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,KAAK,IAAI,KAAK,EAAG,QAAO;AAC5B,OAAK,IAAI,KAAK;AAEd,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,CAAC,SAAS,YAAY,MAAM,IAAI,CAAC;AAC5E,MAAI,iBAAiB,QAAS,QAAO,cAAc,MAAM,QAAQ,GAAG,IAAI;AACxE,MAAI,iBAAiB,KAAM,QAAO,MAAM,YAAY;AACpD,MAAI,iBAAiB,OAAO;AAE1B,UAAM,OAAO,YAAY,SAAS,OAAO,MAAM,WAAW,aAAa,MAAM,OAAO,IAAI;AACxF,WAAO,YAAY,QAAQ,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ,GAAG,IAAI;AAAA,EAC/E;AACA,SAAO,cAAc,OAAO,QAAQ,KAAK,GAAG,IAAI;AAClD;AAEA,SAAS,cAAc,SAAsC,MAAgD;AAC3G,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,KAAK,IAAI,KAAK,SAAS;AACjC,QAAI,GAAG,IAAI,eAAe,GAAG,IAAI,WAAW,YAAY,MAAM,IAAI;AAAA,EACpE;AACA,SAAO;AACT;AAOA,IAAM,wBACJ;AAUK,SAAS,mBAAmB,UAA0B;AAC3D,SAAO,SAAS;AAAA,IAAQ;AAAA,IAAuB,CAAC,OAAO,MAAc,OAAe,UAClF,MAAM,KAAK,MAAM,KAAK,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,KAAK;AAAA,EAC1D;AACF;;;AChDO,IAAM,cAAN,MAAkB;AAAA,EACd;AAAA,EAET,YAAY,QAAsB;AAChC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,KAAK,OAAsB,OAAsB,UAAmC,CAAC,GAAS;AAC5F,QAAI,KAAK,YAAY,OAAW;AAChC,QAAI;AACF,WAAK,QAAQ,KAAK,EAAE,OAAO,OAAO,OAAO,CAA4B;AAAA,IACvE,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;ACtCO,SAAS,oBAAoB,aAA6C;AAC/E,SAAO;AAAA,IACL,MAAM;AAAA,IACN,eAAe,SAAS,OAAO,GAAG,YAAY,QAAQ,IAAI,YAAY,YAAY,EAAE,CAAC;AAAA,IACrF,MAAM,IAAI,gBAAgB;AAAA,MACxB,YAAY;AAAA,MACZ,UAAU,YAAY;AAAA,MACtB,UAAU,YAAY;AAAA,IACxB,CAAC;AAAA,EACH;AACF;AAGO,SAAS,oBAAoB,aAA+C;AACjF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,eAAe,SAAS,OAAO,GAAG,OAAO,YAAY,QAAQ,CAAC,IAAI,OAAO,YAAY,QAAQ,CAAC,EAAE,CAAC;AAAA,IACjG,MAAM,IAAI,gBAAgB,EAAE,YAAY,qBAAqB,CAAC;AAAA,EAChE;AACF;AAEO,SAAS,kBACd,aACA,aACc;AAEd,SAAO,gBAAgB,OACnB,oBAAoB,WAA+B,IACnD,oBAAoB,WAAiC;AAC3D;AAGO,SAAS,OAAO,MAAsB;AAC3C,MAAI,SAAS;AACb,aAAW,QAAQ,IAAI,YAAY,EAAE,OAAO,IAAI,EAAG,WAAU,OAAO,aAAa,IAAI;AACrF,SAAO,KAAK,MAAM;AACpB;;;ACjBA,eAAsB,cACpB,aACA,aACA,aACiB;AACjB,QAAM,WAAW,gBAAgB,OAAO,GAAG,YAAY,QAAQ;AAAA,EAAK,YAAY,QAAQ,KAAK,YAAY;AACzG,QAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI,YAAY,EAAE,OAAO,QAAQ,CAAC;AACvF,QAAM,OAAO,CAAC,GAAG,IAAI,WAAW,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAC/G,SAAO,gBAAgB,WAAW,IAAI,WAAW,IAAI,IAAI;AAC3D;AAGO,SAAS,cAAc,OAAsC;AAClE,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,EAAE,aAAa,YAAY,UAAU,IAAI;AAC/C,SACE,OAAO,gBAAgB,YACvB,gBAAgB,MAChB,OAAO,eAAe,YACtB,OAAO,cAAc,YACrB,OAAO,SAAS,UAAU,KAC1B,YAAY;AAEhB;;;AC7CO,IAAM,gBAAgB;AAGtB,IAAM,sBAAsB;AA4B5B,IAAM,cAAN,MAAkB;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA;AAAA;AAAA,EAEA,eAAe;AAAA;AAAA,EAEf;AAAA,EACS;AAAA,EACT;AAAA,EAEA,YAAY,QAAwB,WAA0B,UAA8B,CAAC,GAAG;AAC9F,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,OAAO,QAAQ,OAAO,KAAK;AAChC,SAAK,OAAO,IAAI,YAAY,OAAO,MAAM;AACzC,SAAK,SAAS,OAAO;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,WAA4B;AAChC,UAAM,QAAQ,KAAK;AACnB,QAAI,UAAU,UAAa,CAAC,KAAK,cAAc,KAAK,EAAG,QAAO,MAAM;AACpE,UAAM,SAAS,UAAU,SAAY,cAAc,KAAK,eAAe,aAAa;AACpF,YAAQ,MAAM,KAAK,SAAS,MAAM,GAAG;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,aAA2B;AACpC,QAAI,KAAK,QAAQ,gBAAgB,YAAa;AAC9C,SAAK,SAAS;AACd,SAAK,eAAe;AACpB,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA,EAGA,iBAAwC;AACtC,WAAO;AAAA,MACL,KAAK,YAAY,UAAU,MAAM,KAAK,SAAS,CAAC;AAAA,MAChD,YAAY,CAAC,kBAAkB,KAAK,WAAW,cAAc,QAAQ,YAAY,EAAE,CAAC;AAAA,IACtF;AAAA,EACF;AAAA,EAEA,cAAc,OAA6B;AACzC,UAAM,cAAc,KAAK,IAAI,qBAAqB,MAAM,YAAY,CAAC,IAAI;AACzE,WAAO,KAAK,KAAK,KAAK,MAAM,aAAa,MAAM,YAAY,MAAO;AAAA,EACpE;AAAA;AAAA,EAGA,SAAS,QAAkD;AACzD,SAAK,cAAc,KAAK,QAAQ,MAAM,EAAE,QAAQ,MAAM;AACpD,WAAK,YAAY;AAAA,IACnB,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,QAAQ,QAAkD;AAC9D,UAAM,SAAS,MAAM,KAAK,WAAW;AACrC,QAAI,WAAW,UAAa,OAAO,gBAAgB,KAAK,aAAa,CAAC,KAAK,cAAc,MAAM,GAAG;AAChG,WAAK,SAAS;AACd,WAAK,eAAe;AACpB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,MAAM,KAAK,WAAW;AACpC,SAAK,SAAS;AACd,SAAK,eAAe;AACpB,SAAK,YAAY;AACjB,SAAK,KAAK,KAAK,QAAQ,4BAA4B;AAAA,MACjD,aAAa,KAAK,QAAQ;AAAA,MAC1B;AAAA,MACA,WAAW,MAAM;AAAA,IACnB,CAAC;AACD,UAAM,KAAK,YAAY,KAAK;AAC5B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAA+C;AACnD,QAAI,KAAK,WAAW,OAAW,QAAO;AACtC,QAAI;AACF,YAAM,QAAQ,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,KAAK,CAAC;AACrD,UAAI,CAAC,cAAc,KAAK,EAAG,QAAO;AAClC,aAAO;AAAA,QACL,aAAa,MAAM;AAAA,QACnB,YAAY,MAAM,YAAY,MAAM,cAAc;AAAA,QAClD,YAAY,MAAM;AAAA,MACpB;AAAA,IACF,SAAS,OAAO;AACd,WAAK,aAAa,OAAO,KAAK;AAC9B,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,OAAmC;AACnD,QAAI,KAAK,WAAW,OAAW;AAC/B,UAAM,SAAsB;AAAA,MAC1B,aAAa,MAAM;AAAA,MACnB,YAAY,MAAM;AAAA,MAClB,WAAW,MAAM,aAAa,MAAM,YAAY;AAAA,IAClD;AACA,QAAI;AACF,YAAM,KAAK,OAAO,IAAI,MAAM,KAAK,KAAK,GAAG,MAAM;AAAA,IACjD,SAAS,OAAO;AACd,WAAK,aAAa,OAAO,KAAK;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,OAAwB;AACtB,UAAM,EAAE,aAAa,aAAa,YAAY,IAAI,KAAK;AACvD,SAAK,cAAc,cAAc,aAAa,aAAa,WAAW;AACtE,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,WAA0B,OAAsB;AAC3D,SAAK,KAAK,KAAK,QAAQ,0BAA0B;AAAA,MAC/C,aAAa,KAAK,QAAQ;AAAA,MAC1B;AAAA,MACA,WAAW,iBAAiB,QAAQ,MAAM,OAAO,OAAO;AAAA,IAC1D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAmC;AACvC,UAAM,EAAE,MAAM,eAAe,KAAK,IAAI,kBAAkB,KAAK,QAAQ,aAAa,KAAK,QAAQ,WAAW;AAC1G,UAAM,WAAW,MAAM,KAAK,WAAW,QAAmC;AAAA,MACxE,QAAQ;AAAA,MACR;AAAA,MACA,SAAS;AAAA;AAAA,MAET,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,SAAS,EAAE,eAAe,cAAc;AAAA,MACxC;AAAA,IACF,CAAC;AACD,WAAO,KAAK,OAAO,QAAQ;AAAA,EAC7B;AAAA,EAEA,OAAO,UAAkD;AACvD,UAAM,cAAc,UAAU;AAC9B,UAAM,YAAY,UAAU;AAC5B,QAAI,OAAO,gBAAgB,YAAY,gBAAgB,MAAM,OAAO,cAAc,YAAY,EAAE,YAAY,IAAI;AAC9G,YAAM,IAAI,kBAAkB,GAAG,aAAa,sDAAmD;AAAA,QAC7F,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AACA,WAAO,EAAE,aAAa,WAAW,YAAY,KAAK,KAAK,EAAE;AAAA,EAC3D;AACF;;;AC1LO,IAAM,yBAAyB;AACtC,IAAMC,QAAO;AAEb,IAAM,qBAAqB;AAC3B,IAAM,aAAa,CAAC,WAAW,UAAU,QAAQ,UAAU,WAAW,UAAU;AA4GhF,eAAsB,cACpB,WACA,SACA,UAAgC,CAAC,GACD;AAChC,+BAA6B,OAAO;AACpC,QAAM,OAAO,MAAM,UAAU,QAAkC;AAAA,IAC7D,QAAQ;AAAA,IACR,MAAMA;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,IACjE,GAAG,SAAS,SAAS,gBAAgB;AAAA,EACvC,CAAC;AACD,SAAO,wBAAwB,IAAI;AACrC;AAGA,SAAS,6BAA6B,SAAqC;AACzE,MAAI,CAACC,UAAS,OAAO,KAAK,CAAC,SAAS,QAAQ,cAAc,GAAG;AAC3D,UAAM,IAAI,UAAU,qEAAqE;AAAA,EAC3F;AACA,QAAM,QAAQ,WAAW,KAAK,IAAI;AAClC,MAAI,QAAQ,cAAc,MAAM;AAC9B,QAAI,WAAW,KAAK,CAAC,SAAS,QAAQ,IAAI,MAAM,MAAS,GAAG;AAC1D,YAAM,IAAI,UAAU,iEAAiE,KAAK,GAAG;AAAA,IAC/F;AAAA,EACF,WAAW,CAAC,WAAW,KAAK,CAAC,SAAS,MAAM,QAAQ,QAAQ,IAAI,CAAC,KAAK,QAAQ,IAAI,EAAE,SAAS,CAAC,GAAG;AAC/F,UAAM,IAAI,UAAU,+EAA+E,KAAK,GAAG;AAAA,EAC7G;AACA,MAAI,QAAQ,gBAAgB,UAAa,QAAQ,0BAA0B,QAAW;AACpF,UAAM,IAAI,UAAU,+EAA+E;AAAA,EACrG;AACF;AAWO,SAAS,sBAAsB,MAAuC;AAC3E,MAAI,CAACA,UAAS,IAAI,GAAG;AACnB,WAAO,IAAI,WAAW,GAAG,sBAAsB,iDAAiD;AAAA,MAC9F,WAAW;AAAA,MACX,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACA,QAAM,QAAQ,eAAe,IAAgC;AAC7D,QAAM,mBAAmB,MAAM,KAAK,kBAAkB;AACtD,QAAM,WAAW,MAAM,OAAO,CAAC,SAAS,UAAU,IAAI,KAAK,CAAC,mBAAmB,IAAI,CAAC,EAAE,IAAI,SAAS;AACnG,QAAM,QAAQ,MAAM,OAAO,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC;AAErD,MAAI,qBAAqB,QAAW;AAClC,WAAO,gBAAgB,wBAAwB,kBAAkB,EAAE,UAAU,QAAQ,MAAM,IAAI,OAAO,EAAE,CAAC;AAAA,EAC3G;AACA,QAAM,CAAC,OAAO,GAAG,IAAI,IAAI;AACzB,MAAI,UAAU,OAAW,QAAO;AAChC,SAAO,gBAAgB,wBAAwB,OAAO,EAAE,UAAU,QAAQ,KAAK,IAAI,OAAO,EAAE,CAAC;AAC/F;AAGA,SAAS,wBAAwB,MAAuD;AACtF,QAAM,EAAE,QAAQ,SAAS,GAAG,KAAK,IAAI;AACrC,SAAO,EAAE,GAAG,MAAM,UAAU,eAAe,IAAI,EAAE,IAAI,SAAS,EAAE;AAClE;AAEA,SAAS,mBAAmB,MAAqC;AAC/D,SAAO,KAAK,SAAS;AACvB;AAEA,SAAS,UAAU,MAA0C;AAC3D,SAAO,UAAU,wBAAwB,IAAI;AAC/C;AAEA,SAAS,QAAQ,MAA4B;AAC3C,SAAO,gBAAgB,wBAAwB,IAAI;AACrD;;;AC3MA,IAAM,cAAc;AA+BpB,IAAM,cAAc,oBAAI,QAAqC;AAGtD,SAAS,cAAc,SAAkD;AAC9E,SAAO,YAAY,SAAY,CAAC,IAAK,YAAY,IAAI,OAAO,KAAK,CAAC;AACpE;AAoCO,SAAS,0BAA0B,QAAmD;AAC3F,QAAM,EAAE,OAAO,WAAW,iBAAiB,QAAQ,CAAC,GAAG,iBAAiB,IAAI;AAC5E,QAAM,UAAU,iBAAiB,OAAO,SAAS,EAAE;AAAA,IACjD,CAAC,EAAE,UAAU,eAAe,YAAY,OAAqB;AAAA,MAC3D,cAAc,SAAS,QAAQ;AAAA,MAC/B,aAAa,SAAS,QAAQ;AAAA,MAC9B,iBAAiB,SAAS,UAAU;AAAA,MACpC,eAAe,SAAS,QAAQ;AAAA,MAChC;AAAA,MACA,eAAe,SAAS,UAAU,KAAK,MAAM,GAAG,CAAC;AAAA,MACjD,cAAc;AAAA,MACd,kBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,OAAO,UAAU,mBAAmB,CAAC,GAAG;AAC9C,MAAI,SAAS,QAAW;AACtB,UAAM,IAAI,UAAU,wDAAwD;AAAA,EAC9E;AACA,QAAM,oBAAoB,KAAK,kBAAkB;AAAA,IAC/C,CAAC,EAAE,cAAc,OAAyB;AAAA,MACxC,eAAe,cAAc;AAAA,MAC7B,oBAAoB,cAAc,mBAAmB;AAAA,IACvD;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,oBAAoB,QAAW;AACjC,UAAM,QAAQ,KAAK,WAAW;AAC9B,QAAI,UAAU,QAAW;AACvB,YAAM,IAAI,UAAU,+EAA+E;AAAA,IACrG;AACA,uBAAmB,CAAC,EAAE,eAAe,OAAO,KAAK,GAAG,GAAG,gBAAgB,CAAC;AAAA,EAC1E;AAEA,QAAM,gBAAgB,kBAAkB,OAAO,CAAC,GAAG,MAAM,KAAK,EAAE,sBAAsB,IAAI,CAAC;AAC3F,QAAM,SAAuB,CAAC;AAC9B,aAAW,aAAa,OAAO;AAC7B,UAAMC,UAAS,QAAQ,UAAU,WAAW,QAAQ,QAAQ,aAAa,CAAC;AAC1E,KAACA,QAAO,UAAU,CAAC,GAAG,KAAK,EAAE,QAAQ,UAAU,QAAQ,eAAe,UAAU,cAAc,CAAC;AAC/F,UAAM,QAAQ,qBAAqB,SAAY,SAAY,UAAU,kBAAkBA,SAAQ,UAAU,MAAM;AAC/G,QAAI,UAAU,QAAW;AACvB,aAAO,KAAK;AAAA,QACV,cAAc,UAAU;AAAA,QACxB,QAAQ,GAAGA,QAAO,WAAW,GAAGA,QAAO,YAAY;AAAA,QACnD,MAAM,UAAU;AAAA,QAChB,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,UAAyB;AAAA,IAC7B;AAAA,IACA,eAAe;AAAA,MACb;AAAA,QACE,GAAI,qBAAqB,SAAY,CAAC,IAAI,EAAE,iBAAiB;AAAA,QAC7D,YAAY;AAAA,UACV;AAAA,UACA,GAAI,KAAK,0BAA0B,SAAY,CAAC,IAAI,EAAE,uBAAuB,KAAK,sBAAsB;AAAA,QAC1G;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,SAAS,EAAG,aAAY,IAAI,SAAS,MAAM;AACtD,SAAO;AACT;AAGA,SAAS,UAAU,WAAiC,aAAqB,eAA+B;AACtG,QAAM,EAAE,cAAc,eAAe,OAAO,IAAI;AAChD,MAAI,OAAO,WAAW,YAAY,CAAC,YAAY,KAAK,MAAM,GAAG;AAC3D,UAAM,IAAI,UAAU,4BAA4B,OAAO,MAAM,CAAC,uCAAuC;AAAA,EACvG;AACA,MAAI,CAAC,OAAO,UAAU,YAAY,KAAK,eAAe,KAAK,eAAe,aAAa;AACrF,UAAM,IAAI;AAAA,MACR,4BAA4B,MAAM,kBAAkB,YAAY,WAAW,WAAW;AAAA,IACxF;AAAA,EACF;AACA,MAAI,CAAC,OAAO,UAAU,aAAa,KAAK,gBAAgB,KAAK,gBAAgB,eAAe;AAC1F,UAAM,IAAI;AAAA,MACR,4BAA4B,MAAM,oBAAoB,aAAa,WAAW,aAAa;AAAA,IAC7F;AAAA,EACF;AACA,SAAO,eAAe;AACxB;AAOA,SAAS,UACP,cACAA,SACA,QACsD;AACtD,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,aAAa,IAAI;AAAA,IACrB,SAAS,SACN;AAAA,MACC,CAAC,MACC,EAAE,uBAAuBA,QAAO,eAChC,EAAE,wBAAwBA,QAAO,gBACjC,EAAE,yBAAyBA,QAAO,mBAClC,EAAE,kBAAkBA,QAAO;AAAA,IAC/B,EACC,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,EACpB;AACA,QAAM,MAAM,OAAO,OAAO,MAAM,GAAG,EAAE,CAAC;AACtC,QAAM,SAAS,OAAO,MAAM,EAAE;AAC9B,QAAM,OAAO,SAAS,SACnB,OAAO,CAAC,QAAQ,WAAW,IAAI,IAAI,UAAU,CAAC,EAC9C,QAAQ,CAAC,QAAQ,IAAI,qBAAqB,CAAC,CAAC,EAC5C,QAAQ,CAAC,UAAU,MAAM,YAAY,CAAC,CAAC,EACvC,OAAO,CAAC,MAAM,EAAE,QAAQ,GAAG,EAC3B,QAAQ,CAAC,MAAM,EAAE,KAAK,EACtB,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AAElC,aAAW,UAAU,MAAM,mBAAmB,CAAC,GAAG;AAChD,UAAM,OAAO,SAAS,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC5D,UAAM,QAAQ,SAAS,kBAAkB,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,kBAAkB;AACtF,QAAI,UAAU,UAAa,OAAO,MAAM,WAAW,MAAM,IAAI,GAAG;AAE9D,aAAO,EAAE,QAAQ,OAAO,MAAM,WAAW,MAAM,GAAG,cAAc,MAAM,aAAa;AAAA,IACrF;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,OAAO,OAAuB;AACrC,SAAO,OAAO,KAAK,MAAM,QAAQ,GAAI,IAAI,GAAI;AAC/C;;;ACjMO,IAAM,yBAAyB;AACtC,IAAMC,QAAO;AAEb,IAAM,6BAA6B;AA+CnC,eAAsB,cACpB,WACA,SACA,UAAgC,CAAC,GACD;AAChC,+BAA6B,OAAO;AAEpC,aAAW,QAAQ,cAAc,QAAQ,aAAa,GAAG;AACvD,cAAU,IAAI,KAAK,QAAQ,6BAA6B,EAAE,SAAS,wBAAwB,GAAG,KAAK,CAAC;AAAA,EACtG;AACA,QAAM,OAAO,MAAM,UAAU,QAAkC;AAAA,IAC7D,QAAQ;AAAA,IACR,MAAMA;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,IACjE,GAAG,SAAS,SAAS,gBAAgB;AAAA,EACvC,CAAC;AACD,SAAO,wBAAwB,IAAI;AACrC;AAOA,SAAS,6BAA6B,SAAqC;AACzE,MAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AACnD,UAAM,IAAI,UAAU,oEAAoE;AAAA,EAC1F;AACA,QAAM,SAAS,QAAQ;AACvB,MAAI,QAAQ,oBAAoB,sBAAsB,OAAO,0BAA0B,QAAW;AAChG,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,QAAQ,QAAQ,SAAS,IAAI,QAAQ,UAAU,SAAS;AAChF,aAAWC,WAAU,QAAQ,eAAe,WAAW,CAAC,GAAG;AACzD,eAAW,QAAQA,QAAO,SAAS,CAAC,GAAG;AACrC,UAAI,KAAK,gBAAgB,KAAK,KAAK,gBAAgB,WAAW;AAC5D,cAAM,IAAI;AAAA,UACR,+DAA+D,KAAK,aAAa,uBAAuB,SAAS;AAAA,QACnH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAYO,SAAS,sBAAsB,MAAuC;AAC3E,MAAI,CAACC,UAAS,IAAI,GAAG;AACnB,WAAO,IAAI,WAAW,GAAG,sBAAsB,iDAAiD;AAAA,MAC9F,WAAW;AAAA,MACX,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACA,QAAM,WAAW;AACjB,MAAI,iBAAiB,QAAQ,MAAM,OAAW,QAAO;AAGrD,MAAI,qBAAqB,QAAQ,GAAG;AAClC,WAAO,IAAI;AAAA,MACT,GAAG,sBAAsB;AAAA,MACzB,EAAE,WAAW,OAAO,KAAK,KAAK;AAAA,IAChC;AAAA,EACF;AACA,QAAM,QAAQ,eAAe,QAAQ;AACrC,QAAM,QAAQ,MAAM,KAAK,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC;AACnD,MAAI,UAAU,OAAW,QAAO,gBAAgB,wBAAwB,OAAO,EAAE,UAAU,MAAM,OAAO,SAAS,EAAE,IAAIC,UAAS,EAAE,CAAC;AACnI,SAAO,IAAI,WAAW,GAAG,sBAAsB,iEAAiE;AAAA,IAC9G,WAAW;AAAA,IACX,KAAK;AAAA,EACP,CAAC;AACH;AAGA,SAAS,wBAAwB,MAAuD;AACtF,QAAM,QAAQ,eAAe,IAAI;AACjC,SAAO;AAAA,IACL,gBAAgB,iBAAiB,IAAI;AAAA,IACrC,GAAI,KAAK,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,KAAK,UAAU;AAAA,IACpE,GAAI,KAAK,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;AAAA,IAC9D,GAAI,KAAK,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;AAAA,IAC9D,UAAU,MAAM,OAAO,SAAS,EAAE,IAAIA,UAAS;AAAA,IAC/C,QAAQ,MAAM,OAAO,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,gBAAgB,wBAAwB,IAAI,CAAC;AAAA,EAC9G;AACF;AAEA,SAAS,iBAAiB,UAAwD;AAChF,MAAI,SAAS,SAAS,cAAc,EAAG,QAAO,SAAS;AACvD,MAAI,SAAS,SAAS,SAAS,SAAS,EAAG,QAAO,SAAS,QAAQ;AACnE,QAAM,eAAe,eAAe,QAAQ,EAAE,KAAK,CAAC,SAAS,KAAK,SAAS,0BAA0B;AACrG,SAAO,iBAAiB,SAAY,SAAY,UAAU,aAAa,WAAW;AACpF;AAEA,SAAS,qBAAqB,UAA6C;AACzE,SAAO,SAAS,YAAY,UAAa,eAAe,QAAQ,EAAE,KAAK,CAAC,SAAS,KAAK,SAAS,0BAA0B;AAC3H;AAMA,SAAS,UAAU,aAAqD;AACtE,MAAI,gBAAgB,OAAW,QAAO;AACtC,SAAO,qBAAqB,KAAK,WAAW,IAAI,CAAC,KAAK,qBAAqB,KAAK,WAAW,IAAI,CAAC;AAClG;AAEA,SAASA,WAAU,MAA0C;AAC3D,SAAO,UAAU,wBAAwB,IAAI;AAC/C;;;AC/KO,IAAM,sBAAsB;AACnC,IAAMC,QAAO;AAEb,IAAM,kBAAkB,oBAAI,IAAI,CAAC,2BAA2B,0BAA0B,CAAC;AAiHvF,eAAsB,WACpB,WACA,SACA,UAA6B,CAAC,GACD;AAC7B,MAAI,CAACC,UAAS,OAAO,KAAK,CAAC,SAAS,QAAQ,cAAc,GAAG;AAC3D,UAAM,IAAI,UAAU,kEAAkE;AAAA,EACxF;AACA,QAAM,OAAO,MAAM,UAAU,QAA+B;AAAA,IAC1D,QAAQ;AAAA,IACR,MAAMD;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,IACjE,GAAG,SAAS,SAAS,aAAa;AAAA,EACpC,CAAC;AACD,SAAO,qBAAqB,IAAI;AAClC;AASO,SAAS,mBAAmB,MAAuC;AACxE,MAAI,CAACC,UAAS,IAAI,GAAG;AACnB,WAAO,IAAI,WAAW,GAAG,mBAAmB,iDAAiD;AAAA,MAC3F,WAAW;AAAA,MACX,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACA,QAAM,WAAW;AACjB,MAAI,SAAS,SAAS,SAAS,EAAG,QAAO;AAEzC,QAAM,QAAQ,eAAe,QAAQ;AACrC,QAAM,QAAQ,MAAM,KAAK,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC;AACnD,MAAI,UAAU,OAAW,QAAOC,SAAQ,OAAO,MAAM,OAAO,SAAS,EAAE,IAAIC,UAAS,CAAC;AACrF,SAAO,IAAI,WAAW,GAAG,mBAAmB,4DAA4D;AAAA,IACtG,WAAW;AAAA,IACX,KAAK;AAAA,EACP,CAAC;AACH;AAGA,SAAS,qBAAqB,MAAiD;AAC7E,QAAM,QAAQ,eAAe,IAAI;AACjC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,KAAK;AAAA,IAChB,UAAU,MAAM,OAAO,SAAS,EAAE,IAAIA,UAAS;AAAA,IAC/C,QAAQ,MAAM,OAAO,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,EAAE,IAAI,CAAC,SAASD,SAAQ,MAAM,CAAC,CAAC,CAAC;AAAA,EAClF;AACF;AAEA,SAASC,WAAU,MAA0C;AAC3D,SAAO,UAAU,qBAAqB,IAAI;AAC5C;AAEA,SAASD,SAAQ,MAA4B,UAA8C;AACzF,SAAO,gBAAgB,qBAAqB,MAAM,EAAE,UAAU,WAAW,gBAAgB,IAAI,KAAK,IAAI,EAAE,CAAC;AAC3G;;;ACxLO,IAAM,oBAAN,MAAwB;AAAA,EACpB;AAAA;AAAA,EAGT,YAAY,WAA0B;AACpC,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAO,SAA+B,SAAgE;AACpG,WAAO,cAAc,KAAK,YAAY,SAAS,OAAO;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IAAI,SAA4B,SAA0D;AACxF,WAAO,WAAW,KAAK,YAAY,SAAS,OAAO;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,SAA+B,SAAgE;AACpG,WAAO,cAAc,KAAK,YAAY,SAAS,OAAO;AAAA,EACxD;AACF;;;ACnDO,IAAM,gBAAwC,OAAO,OAAO,EAAE,YAAY,GAAG,aAAa,IAAI,CAAC;AAG/F,IAAM,qBAAqB;AAG3B,SAAS,WAAW,OAAe,aAAqB,SAAuB,KAAK,QAAgB;AACzG,SAAO,KAAK,IAAI,oBAAoB,KAAK,MAAM,OAAO,IAAI,cAAc,KAAK,KAAK,CAAC;AACrF;AAGO,SAAS,YAAY,OAAgB,YAA8B;AACxE,SAAO,cAAc,iBAAiB,cAAc,MAAM;AAC5D;AAEO,SAAS,qBAAqB,OAA8B,OAAqB;AACtF,MAAI,MAAM,eAAe,UAAa,EAAE,OAAO,UAAU,MAAM,UAAU,KAAK,MAAM,cAAc,IAAI;AACpG,UAAM,IAAI,UAAU,iBAAiB,KAAK,qCAAqC;AAAA,EACjF;AACA,MAAI,MAAM,gBAAgB,UAAa,EAAE,OAAO,SAAS,MAAM,WAAW,KAAK,MAAM,eAAe,IAAI;AACtG,UAAM,IAAI,UAAU,iBAAiB,KAAK,yCAAsC;AAAA,EAClF;AACF;AAGO,SAAS,MAAM,IAAY,QAAqC;AACrE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,QAAQ,QAAS,QAAO,OAAO,OAAO,MAAM;AAChD,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ,oBAAoB,SAAS,OAAO;AAC5C,cAAQ;AAAA,IACV,GAAG,EAAE;AACL,UAAM,UAAU,MAAM;AACpB,mBAAa,KAAK;AAClB,aAAO,QAAQ,MAAM;AAAA,IACvB;AACA,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC3D,CAAC;AACH;;;ACyDO,IAAM,YAAwD,OAAO,OAAO;AAAA,EACjF,SAAS;AAAA,EACT,YAAY;AACd,CAAC;AAGM,IAAM,iBAA6D,OAAO,OAAO;AAAA,EACtF,SAAS;AAAA,EACT,YAAY;AACd,CAAC;AAeD,IAAM,iBAAiB,CAAC,SAAS,QAAQ,QAAQ,OAAO;AAExD,SAAS,KAAK,SAAwB;AACpC,QAAM,IAAI,UAAU,iBAAiB,OAAO,EAAE;AAChD;AAEA,SAASE,UAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,cAAc,OAAgB,OAAqB;AAC1D,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,GAAI,MAAK,GAAG,KAAK,gDAA6C;AAClH;AAEO,SAAS,cAAc,QAAqC;AACjE,MAAI,CAACA,UAAS,MAAM,EAAG,MAAK,8BAA8B;AAE1D,QAAM,EAAE,YAAY,IAAI;AACxB,MAAI,gBAAgB,aAAa,gBAAgB,cAAc;AAC7D,SAAK,4DAA4D,KAAK,UAAU,WAAW,CAAC,GAAG;AAAA,EACjG;AAEA,QAAM,gBAAgB,OAAO,eAAe;AAC5C,MAAI,kBAAkB,UAAa,kBAAkB,QAAQ,kBAAkB,MAAM;AACnF,SAAK,+CAA+C,KAAK,UAAU,aAAa,CAAC,GAAG;AAAA,EACtF;AAEA,QAAM,EAAE,YAAY,IAAI;AACxB,MAAI,CAACA,UAAS,WAAW,EAAG,MAAK,0BAA0B;AAE3D,QAAM,qBAAqB,YAAY,eAAe;AACtD,MAAI,uBAAuB,UAAa,uBAAuB,QAAQ,uBAAuB,MAAM;AAClG,SAAK,2DAA2D,KAAK,UAAU,kBAAkB,CAAC,GAAG;AAAA,EACvG;AACA,MAAI,kBAAkB,UAAa,uBAAuB,UAAa,kBAAkB,oBAAoB;AAC3G,SAAK,gBAAgB,aAAa,8CAA8C,kBAAkB,GAAG;AAAA,EACvG;AACA,QAAM,cAAgC,iBAAiB,sBAAsB;AAC7E,gBAAc,YAAY,UAAU,sBAAsB;AAC1D,gBAAc,YAAY,UAAU,sBAAsB;AAC1D,MAAI,gBAAgB,MAAM;AACxB,kBAAc,YAAY,UAAU,qDAAqD;AACzF,kBAAc,YAAY,cAAc,yDAAyD;AAAA,EACnG;AAEA,QAAM,EAAE,OAAO,IAAI;AACnB,MAAI,WAAW,QAAW;AACxB,QAAI,CAACA,UAAS,MAAM,EAAG,MAAK,qDAAqD;AACjF,eAAW,UAAU,gBAAgB;AACnC,UAAI,OAAO,OAAO,MAAM,MAAM,WAAY,MAAK,UAAU,MAAM,0BAAuB;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,OAAO,UAAU,QAAW;AAC9B,QAAI,CAACA,UAAS,OAAO,KAAK,EAAG,MAAK,0BAA0B;AAC5D,yBAAqB,OAAO,OAAO,OAAO;AAAA,EAC5C;AAEA,QAAM,EAAE,WAAW,IAAI;AACvB,MAAI,eAAe,QAAW;AAC5B,QAAI,CAACA,UAAS,UAAU,KAAK,OAAO,WAAW,QAAQ,cAAc,OAAO,WAAW,QAAQ,YAAY;AACzG,WAAK,8DAA8D;AAAA,IACrE;AAAA,EACF;AAEA,QAAM,YAAY,OAAO,SAAS,WAAW;AAC7C,MAAI,OAAO,cAAc,WAAY,MAAK,4CAA4C;AAEtF,SAAO;AAAA;AAAA,IAEL,aAAa,OAAO,OAAO,EAAE,GAAG,YAAY,CAAC;AAAA,IAC7C;AAAA,IACA,SAAS,UAAU,WAAW;AAAA,IAC9B,aAAa,eAAe,WAAW;AAAA,IACvC;AAAA,IACA;AAAA,IACA,OAAO,OAAO,OAAO,EAAE,GAAG,eAAe,GAAG,YAAY,OAAO,SAAS,CAAC,CAAC,EAAE,CAAC;AAAA;AAAA,IAE7E,OAAO,OAAO,SAAS,WAAW,MAAM,KAAK,UAAU;AAAA,IACvD;AAAA,EACF;AACF;AAGO,SAAS,YAA8B,OAAsB;AAClE,SAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,MAAS,CAAC;AACpF;;;AC3MA,IAAM,mBAAmB,oBAAI,IAAI,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC;AA8D9C,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EAEA,YAAY,QAAwB,UAAgC,CAAC,GAAG;AACtE,SAAK,UAAU;AACf,SAAK,OAAO,IAAI,YAAY,OAAO,MAAM;AACzC,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,UAAU,QAAQ,UAAU,KAAK;AACtC,SAAK,SAAS,QAAQ,SAAS;AAAA,EACjC;AAAA;AAAA,EAGA,IAAI,MAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,yBAAyB,UAAmD;AAC1E,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,MAAM,QAAW,SAAkC;AACjD,QAAI,QAAQ,UAAU,OAAW,sBAAqB,QAAQ,OAAO,OAAO;AAC5E,UAAM,eAAe,QAAQ,iBAAiB,UAAa,QAAQ,SAAS;AAC5E,UAAM,UACJ,QAAQ,kBAAkB,UAAa,CAAC,eAAe,SAAY,EAAE,UAAU,EAAE;AACnF,QAAI;AACF,aAAO,MAAM,KAAK,UAAa,SAAS,OAAO;AAAA,IACjD,UAAE;AAGA,UAAI,gBAAgB,SAAS,YAAY,OAAW,MAAK,mBAAmB,SAAS,QAAQ,SAAS,QAAQ,QAAQ;AACtH,UAAI,SAAS,SAAS,OAAW,MAAK,YAAY,SAAS,EAAE,GAAG,QAAQ,MAAM,UAAU,QAAQ,SAAS,CAAC;AAAA,IAC5G;AAAA,EACF;AAAA,EAEA,MAAM,UAAa,SAAsB,SAA6C;AACpF,UAAM,QAAQ,EAAE,GAAG,KAAK,QAAQ,OAAO,GAAG,YAAY,QAAQ,SAAS,CAAC,CAAC,EAAE;AAE3E,QAAI,eAAe;AACnB,aAAS,UAAU,KAAK,WAAW;AAEjC,YAAM,gBAAgB,MAAM,KAAK,kBAAkB,OAAO;AAC1D,UAAI;AACF,eAAO,MAAM,KAAK,MAAS,SAAS,SAAS,eAAe,OAAO;AAAA,MACrE,SAAS,OAAO;AAGd,YAAI,kBAAkB,UAAa,CAAC,gBAAgB,eAAe,KAAK,GAAG;AACzE,yBAAe;AACf,eAAK,gBAAgB,WAAW,aAAa;AAC7C,eAAK,KAAK,KAAK,QAAQ,uBAAuB;AAAA,YAC5C,SAAS,QAAQ;AAAA,YACjB,QAAQ,QAAQ;AAAA,YAChB,MAAM,QAAQ;AAAA,YACd,SAAS,UAAU;AAAA,YACnB,QAAQ;AAAA,YACR;AAAA,UACF,CAAC;AACD;AACA;AAAA,QACF;AACA,YAAI,WAAW,MAAM,cAAc,CAAC,YAAY,OAAO,QAAQ,UAAU,EAAG,OAAM;AAClF,cAAM,UAAU,WAAW,SAAS,MAAM,aAAa,KAAK,OAAO;AACnE,aAAK,KAAK,KAAK,QAAQ,uBAAuB;AAAA,UAC5C,SAAS,QAAQ;AAAA,UACjB,QAAQ,QAAQ;AAAA,UAChB,MAAM,QAAQ;AAAA,UACd,SAAS,UAAU;AAAA,UACnB,YAAY,MAAM;AAAA,UAClB;AAAA,UACA;AAAA,QACF,CAAC;AACD,cAAM,KAAK,OAAO,SAAS,QAAQ,MAAM;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,YAAY,SAAsB,KAA6D;AAC7F,UAAM,YAAY,QAAQ,aAAa,QAAQ;AAC/C,QAAI;AACF,cAAQ,gBAAgB,EAAE,WAAW,UAAU,QAAQ,GAAG,IAAI,CAAC;AAAA,IACjE,SAAS,OAAO;AACd,WAAK,KAAK,KAAK,QAAQ,uCAAuC;AAAA,QAC5D,SAAS,QAAQ;AAAA,QACjB;AAAA,QACA,WAAW,iBAAiB,QAAQ,MAAM,OAAO,OAAO;AAAA,MAC1D,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA,EAGA,mBAAmB,SAAsB,KAAwB,UAAwB;AACvF,UAAM,YAAY,QAAQ,aAAa,QAAQ;AAC/C,QAAI;AACF,cAAQ,eAAe,EAAE,WAAW,UAAU,QAAQ,GAAG,KAAK,SAAS,CAAC;AAAA,IAC1E,SAAS,OAAO;AACd,WAAK,KAAK,KAAK,QAAQ,sCAAsC;AAAA,QAC3D,SAAS,QAAQ;AAAA,QACjB;AAAA,QACA,WAAW,iBAAiB,QAAQ,MAAM,OAAO,OAAO;AAAA,MAC1D,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,SAAmD;AACzE,QAAI,QAAQ,SAAS,SAAS,KAAK,mBAAmB,OAAW,QAAO;AACxE,WAAO,KAAK,eAAe,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,MACJ,SACA,SACA,eACA,SACY;AACZ,UAAM,MAAM,KAAK,KAAK,OAAO;AAC7B,UAAM,UAAU,IAAI,QAAQ,EAAE,QAAQ,oBAAoB,GAAG,QAAQ,QAAQ,CAAC;AAC9E,UAAM,OAAO,QAAQ,gBAAgB;AACrC,QAAI,QAAQ,SAAS,UAAa,CAAC,QAAQ,IAAI,cAAc,GAAG;AAC9D,cAAQ,IAAI,gBAAgB,OAAO,sCAAsC,kBAAkB;AAAA,IAC7F;AACA,QAAI,kBAAkB,OAAW,SAAQ,IAAI,iBAAiB,aAAa;AAE3E,UAAM,aAAa,EAAE,SAAS,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,MAAM,QAAQ,MAAM,QAAQ;AACnG,SAAK,KAAK,KAAK,SAAS,uBAAuB,UAAU;AACzD,UAAM,YAAY,KAAK,IAAI;AAE3B,QAAI;AACJ,UAAM,OAAO,QAAQ,SAAS,SAAY,SAAY,OAAO,OAAO,QAAQ,IAAI,IAAI,KAAK,UAAU,QAAQ,IAAI;AAC/G,QAAI,YAAY,QAAW;AACzB,cAAQ;AACR,UAAI,QAAQ,iBAAiB,UAAa,QAAQ,SAAS,OAAO;AAChE,gBAAQ,UAAU,EAAE,QAAQ,QAAQ,QAAQ,KAAK,SAAS,kBAAkB,OAAO,GAAG,KAAK;AAAA,MAC7F;AAAA,IACF;AACA,QAAI;AACF,iBAAW,MAAM,KAAK,QAAQ,MAAM,KAAK;AAAA,QACvC,QAAQ,QAAQ;AAAA,QAChB;AAAA,QACA,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,KAAK;AAAA,QACrC,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,MACnE,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAI,QAAQ,OAAO,QAAQ,MAAM,EAAG,OAAM;AAC1C,YAAM,QAAQ,IAAI,kBAAkB,GAAG,QAAQ,OAAO,mBAAmB,SAAS,KAAK,CAAC,KAAK;AAAA,QAC3F,UAAU;AAAA,QACV,WAAW;AAAA,QACX;AAAA,MACF,CAAC;AACD,WAAK,KAAK,KAAK,SAAS,qBAAqB,EAAE,GAAG,YAAY,YAAY,KAAK,IAAI,IAAI,WAAW,MAAM,CAAC;AACzG,YAAM;AAAA,IACR;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,YAAY,OAAW,SAAQ,OAAO,EAAE,QAAQ,SAAS,QAAQ,SAAS,SAAS,SAAS,MAAM,KAAK;AAC3G,UAAM,SAAS,UAAU,IAAI;AAC7B,UAAM,aAAa,EAAE,GAAG,YAAY,QAAQ,SAAS,QAAQ,YAAY,KAAK,IAAI,IAAI,UAAU;AAGhG,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,aAAa,QAAQ,SAAS,SAAS,QAAQ,MAAM;AACnE,WAAK,KAAK,KAAK,SAAS,qBAAqB,EAAE,GAAG,YAAY,MAAM,CAAC;AACrE,YAAM;AAAA,IACR;AAGA,UAAM,eAAe,QAAQ,WAAW,QAAQ,QAAQ;AACxD,QAAI,iBAAiB,QAAW;AAC9B,WAAK,KAAK,KAAK,QAAQ,qBAAqB,EAAE,GAAG,YAAY,OAAO,aAAa,CAAC;AAClF,YAAM;AAAA,IACR;AAGA,SAAK,KAAK,KAAK,QAAQ,qBAAqB,UAAU;AACtD,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,SAA8B;AACjC,UAAM,OAAO,QAAQ,KAAK,WAAW,GAAG,IAAI,QAAQ,OAAO,IAAI,QAAQ,IAAI;AAC3E,UAAM,MAAM,IAAI,IAAI,MAAM,KAAK,QAAQ,OAAO;AAC9C,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,SAAS,CAAC,CAAC,GAAG;AAC9D,UAAI,UAAU,OAAW,KAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IAClE;AACA,WAAO,IAAI,SAAS;AAAA,EACtB;AACF;AAGA,SAAS,UAAU,MAAuB;AACxC,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,SAAiB,QAAgB,MAAkC;AACvF,QAAM,OAAO,YAAY,IAAI;AAC7B,QAAM,SAAS,mBAAmB,IAAI;AACtC,SAAO,IAAI;AAAA,IACT,GAAG,OAAO,UAAU,MAAM,GAAG,SAAS,SAAY,KAAK,IAAI,IAAI,EAAE,GAAG,WAAW,SAAY,KAAK,KAAK,MAAM,EAAE;AAAA,IAC7G;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,WAAW,iBAAiB,IAAI,MAAM;AAAA,MACtC,KAAK;AAAA,MACL,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,KAAK;AAAA,IACvC;AAAA,EACF;AACF;AASA,SAAS,YAAY,MAAmC;AACtD,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,aAAW,OAAO,CAAC,aAAa,OAAO,GAAY;AACjD,UAAM,QAAS,KAAiC,GAAG;AACnD,QAAI,OAAO,UAAU,YAAY,UAAU,GAAI,QAAO;AAAA,EACxD;AACA,SAAO,gBAAgB,MAAM,MAAM,KAAK,gBAAgB,MAAM,MAAM;AACtE;AAGA,SAAS,mBAAmB,MAAmC;AAC7D,SAAO,gBAAgB,MAAM,iBAAiB,KAAK,gBAAgB,MAAM,aAAa;AACxF;AAEA,SAAS,gBAAgB,MAAe,KAAiC;AACvE,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,QAAM,SAAU,KAA8B;AAC9C,QAAM,QAAiB,MAAM,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI;AAC3D,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,QAAS,MAAkC,GAAG;AACpD,SAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC7D;AAEA,SAAS,eAAe,OAAyB;AAC/C,SAAO,iBAAiB,qBAAqB,MAAM,aAAa,UAAU,MAAM,WAAW;AAC7F;AAEA,SAAS,QAAQ,OAAgB,QAA0C;AACzE,SAAO,QAAQ,YAAY,QAAS,iBAAiB,SAAS,MAAM,SAAS;AAC/E;AAEA,SAAS,SAAS,OAAwB;AACxC,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;;ACrUO,IAAM,QAAN,MAAY;AAAA,EACR;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,QAAqB;AAC/B,SAAK,UAAU,cAAc,MAAM;AACnC,SAAK,aAAa,IAAI,cAAc,KAAK,OAAO;AAEhD,UAAM,OAAO,IAAI,YAAY,KAAK,SAAS,KAAK,UAAU;AAC1D,SAAK,WAAW,yBAAyB,KAAK,eAAe,CAAC;AAC9D,SAAK,MAAM,IAAI,IAAI,KAAK,UAAU;AAClC,SAAK,UAAU,IAAI,kBAAkB,KAAK,UAAU;AAAA,EACtD;AAAA,EAEA,IAAI,cAAgC;AAClC,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,KAAK,QAAQ;AAAA,EACtB;AACF;;;AC7BA,SAAS,iBAAiB;AAa1B,IAAM,mBAAmB,oBAAI,IAAI,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC;AAO9C,IAAM,aAAkC,oBAAI,IAAI,CAAC,yBAAyB,eAAe,qBAAqB,CAAC;AAOtH,IAAM,kBAAuC,oBAAI,IAAI;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,gCAAgC;AACtC,IAAM,iCAAiC;AAC9C,IAAM,wBAAwB;AA0F9B,IAAM,eAAe,EAAE,gBAAgB,2BAA2B,QAAQ,WAAW;AAQrF,IAAM,iBAAiB;AAAA,EACrB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,iBAAiB;AACnB;AACA,IAAM,SAAS,IAAI,UAAU,cAAc;AAE3C,IAAM,kBAAkB,IAAI,UAAU,EAAE,GAAG,gBAAgB,YAAY,MAAM,CAAC;AAEvE,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAwB,UAAgC,CAAC,GAAG;AACtE,SAAK,UAAU;AACf,SAAK,OAAO,IAAI,YAAY,OAAO,MAAM;AACzC,SAAK,aAAa,QAAQ,cAAc,MAAM,WAAW,OAAO,WAAW;AAC3E,SAAK,OAAO,QAAQ,QAAQ,MAAM,oBAAI,KAAK;AAC3C,SAAK,UAAU,QAAQ,UAAU,KAAK;AACtC,SAAK,SAAS,QAAQ,SAAS;AAAA,EACjC;AAAA;AAAA,EAGA,IAAI,MAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAQ,SAA6C;AACzD,QAAI,QAAQ,UAAU,OAAW,sBAAqB,QAAQ,OAAO,OAAO;AAC5E,UAAM,UAAsB,EAAE,UAAU,EAAE;AAC1C,QAAI;AACF,aAAO,MAAM,KAAK,UAAU,SAAS,OAAO;AAAA,IAC9C,UAAE;AAGA,UAAI,QAAQ,YAAY,OAAW,MAAK,mBAAmB,SAAS,QAAQ,SAAS,QAAQ,QAAQ;AACrG,UAAI,QAAQ,SAAS,OAAW,MAAK,YAAY,SAAS,EAAE,GAAG,QAAQ,MAAM,UAAU,QAAQ,SAAS,CAAC;AAAA,IAC3G;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU,SAAsB,SAA4C;AAChF,UAAM,QAAQ,EAAE,GAAG,KAAK,QAAQ,OAAO,GAAG,YAAY,QAAQ,SAAS,CAAC,CAAC,EAAE;AAC3E,QAAI,UAAU;AACd,QAAI,sBAAsB;AAC1B,aAAS,UAAU,KAAK,WAAW;AACjC,UAAI;AACF,eAAO,MAAM,KAAK,MAAM,SAAS,SAAS,OAAO;AAAA,MACnD,SAAS,OAAO;AACd,cAAM,SAAS,YAAY,OAAO,QAAQ,UAAU;AACpD,YAAI;AACJ,YAAI,WAAW,2BAA2B,sBAAsB,+BAA+B;AAC7F;AACA,oBAAU;AAAA,QACZ,YAAY,WAAW,UAAU,WAAW,gBAAgB,UAAU,MAAM,YAAY;AACtF,oBAAU,WAAW,SAAS,MAAM,aAAa,KAAK,OAAO;AAC7D;AAAA,QACF,OAAO;AACL,gBAAM;AAAA,QACR;AACA,aAAK,KAAK,KAAK,QAAQ,uBAAuB;AAAA,UAC5C,UAAU;AAAA,UACV,SAAS,QAAQ;AAAA,UACjB,QAAQ,QAAQ;AAAA,UAChB,SAAS,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AACD,cAAM,KAAK,OAAO,SAAS,QAAQ,MAAM;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,SAAsB,SAAiB,SAA4C;AAC7F,UAAM,WAAW,KAAK,UAAU,OAAO;AACvC,UAAM,aAAa,EAAE,UAAU,QAAQ,SAAS,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,QAAQ;AACjG,SAAK,KAAK,KAAK,SAAS,uBAAuB,UAAU;AACzD,UAAM,YAAY,KAAK,IAAI;AAE3B,QAAI;AACJ,YAAQ;AACR,QAAI,gBAAgB,OAAO,GAAG;AAE5B,cAAQ,UAAU;AAAA,QAChB,QAAQ;AAAA,QACR,KAAK,KAAK,QAAQ;AAAA,QAClB,SAAS,kBAAkB,YAAY;AAAA,QACvC,MAAM,mBAAmB,WAAW,UAAU,QAAQ,QAAQ,CAAC;AAAA,MACjE;AAAA,IACF;AACA,QAAI;AACF,iBAAW,MAAM,KAAK,QAAQ,MAAM,KAAK,QAAQ,aAAa;AAAA,QAC5D,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,MAAM;AAAA,QACN,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,MACnE,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAIC,SAAQ,OAAO,QAAQ,MAAM,EAAG,OAAM;AAC1C,YAAM,QAAQ,IAAI,kBAAkB,GAAG,QAAQ,OAAO,mBAAmBC,UAAS,KAAK,CAAC,KAAK;AAAA,QAC3F,UAAU;AAAA,QACV,WAAW;AAAA,QACX;AAAA,MACF,CAAC;AACD,WAAK,KAAK,KAAK,SAAS,qBAAqB,EAAE,GAAG,YAAY,YAAY,KAAK,IAAI,IAAI,WAAW,MAAM,CAAC;AACzG,YAAM;AAAA,IACR;AAEA,UAAM,WAAW,MAAM,SAAS,KAAK;AAErC,UAAM,OAAO,mBAAmB,WAAW,UAAU,QAAQ,QAAQ,CAAC;AACtE,YAAQ,OAAO,EAAE,QAAQ,SAAS,QAAQ,SAAS,SAAS,SAAS,MAAM,KAAK;AAEhF,UAAM,WAAW,cAAc,IAAI;AACnC,UAAM,YAAY,SAAS,UAAU,QAAQ,iBAAiB,eAAe,WAAW;AACxF,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,QAAQ,SAAS;AAAA,MACjB,YAAY,KAAK,IAAI,IAAI;AAAA,MACzB,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,UAAU;AAAA,IACjD;AAEA,QAAI;AACF,YAAM,SAAS,KAAK,UAAU,SAAS,UAAU,UAAU,IAAI;AAC/D,WAAK,KAAK,KAAK,QAAQ,qBAAqB,EAAE,GAAG,YAAY,UAAU,OAAO,SAAS,OAAO,CAAC;AAC/F,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,QACA,aAAa,cAAc,IAAI;AAAA,QAC/B,KAAK;AAAA,QACL,eAAe,QAAQ,sBAAsB,OAAO,kBAAkB,QAAQ,IAAI;AAAA,QAClF,QAAQ,SAAS;AAAA,MACnB;AAAA,IACF,SAAS,OAAO;AACd,YAAM,QAAQ,iBAAiB,qBAAqB,SAAS;AAC7D,WAAK,KAAK,KAAK,OAAO,qBAAqB,EAAE,GAAG,YAAY,MAAM,CAAC;AACnE,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,UACE,SACA,UACA,UACA,MAC4D;AAC5D,UAAM,EAAE,QAAQ,IAAI;AACpB,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,kBAAkB,GAAG,OAAO,UAAU,SAAS,MAAM,sCAAsC;AAAA,QACnG,UAAU;AAAA,QACV,QAAQ,SAAS;AAAA,QACjB,WAAW;AAAA,QACX,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AAGA,UAAM,QAAQ,OAAO,SAAS,KAAK,KAAK;AACxC,QAAI,UAAU,OAAW,OAAM,WAAW,SAAS,SAAS,QAAQ,OAAO,IAAI;AAE/E,UAAM,CAAC,aAAa,YAAY,IAAI,aAAa,SAAS,IAAI;AAC9D,UAAM,UAAU,OAAO,YAAY;AACnC,QAAI,gBAAgB,UAAa,YAAY,QAAW;AACtD,YAAM,IAAI,kBAAkB,GAAG,OAAO,UAAU,SAAS,MAAM,mCAAmC;AAAA,QAChG,UAAU;AAAA,QACV,QAAQ,SAAS;AAAA,QACjB,WAAW;AAAA,QACX,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,kBAAkB,GAAG,OAAO,UAAU,SAAS,MAAM,IAAI;AAAA,QACjE,UAAU;AAAA,QACV,QAAQ,SAAS;AAAA,QACjB,WAAW;AAAA,QACX,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AAGA,UAAM,UAAU,OAAO,QAAQ,kBAAkB;AACjD,UAAM,WAAW,QAAQ,SAAS,OAAO,EAAE,IAAI,CAACC,UAAS;AACvD,YAAM,QAAQ,YAAYA,KAAI;AAC9B,aAAO,IAAI,aAAa,GAAG,OAAO,KAAK,MAAM,WAAW,IAAI,EAAE,SAAS,MAAM,MAAM,MAAM,KAAK,KAAK,CAAC;AAAA,IACtG,CAAC;AACD,UAAM,SAAS,QAAQ,SAAS,KAAK,EAAE,IAAI,CAACA,UAAS;AACnD,YAAM,QAAQ,YAAYA,KAAI;AAC9B,aAAO,IAAI,mBAAmB,GAAG,OAAO,KAAK,MAAM,WAAW,IAAI;AAAA,QAChE;AAAA,QACA,MAAM,MAAM;AAAA,QACZ,KAAK;AAAA,QACL,WAAW,sBAAsB,KAAK,MAAM,WAAW;AAAA,MACzD,CAAC;AAAA,IACH,CAAC;AACD,UAAM,CAAC,OAAO,GAAG,IAAI,IAAI;AACzB,QAAI,UAAU,QAAW;AACvB,YAAM,IAAI,mBAAmB,MAAM,SAAS;AAAA,QAC1C;AAAA,QACA,MAAM,MAAM;AAAA,QACZ,KAAK;AAAA,QACL,WAAW,MAAM;AAAA,QACjB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAGA,WAAO,EAAE,SAAS,aAAa,SAAS;AAAA,EAC1C;AAAA,EAEA,UAAU,SAA8B;AACtC,UAAM,YAAY,KAAK,KAAK,EAAE,YAAY,EAAE,QAAQ,aAAa,GAAG;AACpE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,UAAU,QAAQ,KAAK,CAAC;AAAA,MACrC,sBAAsB,UAAU,QAAQ,cAAc,CAAC;AAAA,MACvD,eAAe,UAAU,QAAQ,MAAM,CAAC;AAAA,MACxC,cAAc,UAAU,QAAQ,MAAM,CAAC;AAAA,MACvC;AAAA,MACA,qBAAqB,UAAU,KAAK,WAAW,CAAC,CAAC;AAAA,MACjD,iBAAiB,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,eAAe,QAAQ,QAAQ;AAAA,MAC/B;AAAA,MACA,kBAAkB,QAAQ,OAAO;AAAA,MACjC;AAAA,IACF,EAAE,KAAK,EAAE;AAAA,EACX;AAAA;AAAA,EAGA,mBAAmB,SAAsB,KAAwB,UAAwB;AACvF,UAAM,YAAY,QAAQ,aAAa,QAAQ;AAC/C,QAAI;AACF,cAAQ,eAAe,EAAE,WAAW,UAAU,QAAQ,GAAG,KAAK,SAAS,CAAC;AAAA,IAC1E,SAAS,OAAO;AACd,WAAK,KAAK,KAAK,QAAQ,sCAAsC;AAAA,QAC3D,SAAS,QAAQ;AAAA,QACjB;AAAA,QACA,WAAW,iBAAiB,QAAQ,MAAM,OAAO,OAAO;AAAA,MAC1D,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA,EAGA,YAAY,SAAsB,KAAgE;AAChG,QAAI,QAAQ,kBAAkB,OAAW;AACzC,UAAM,YAAY,QAAQ,aAAa,QAAQ;AAC/C,QAAI;AACF,cAAQ,cAAc,EAAE,WAAW,UAAU,QAAQ,GAAG,IAAI,CAAC;AAAA,IAC/D,SAAS,OAAO;AACd,WAAK,KAAK,KAAK,QAAQ,uCAAuC;AAAA,QAC5D,SAAS,QAAQ;AAAA,QACjB;AAAA,QACA,WAAW,iBAAiB,QAAQ,MAAM,OAAO,OAAO;AAAA,MAC1D,CAAC;AAAA,IACH;AAAA,EACF;AACF;AASO,SAAS,cAAc,KAAkC;AAC9D,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAM,SAAS,sDAAsD,KAAK,GAAG,IAAI,CAAC;AAClF,QAAM,QAAQ,WAAW,SAAY,SAAY,0CAA0C,KAAK,MAAM,IAAI,CAAC;AAC3G,QAAM,QAAQ,UAAU,SAAY,OAAO,6EAA6E,KAAK,KAAK;AAClI,MAAI,UAAU,KAAM,QAAO;AAC3B,SAAO,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG;AACtC;AAGO,SAAS,iBAAiB,KAAwC;AACvE,QAAM,cAAc,cAAc,GAAG;AACrC,SAAO,gBAAgB,SAAY,CAAC,IAAI,EAAE,YAAY;AACxD;AAEO,SAAS,UAAU,OAAuB;AAC/C,SAAO,MACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAC3B;AAEA,SAAS,eAAe,UAAgC;AACtD,QAAM,OAAO;AACb,MAAI,yBAAyB,UAAU;AACrC,WAAO,GAAG,IAAI,iFAAiF,UAAU,SAAS,mBAAmB,CAAC;AAAA,EACxI;AACA,QAAM,QAAQ,SAAS;AACvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,kBAAkB,UAAU,MAAM,QAAQ,CAAC;AAAA,IAC3C,kBAAkB,UAAU,MAAM,QAAQ,CAAC;AAAA,IAC3C,iBAAiB,UAAU,MAAM,YAAY,CAAC;AAAA,IAC9C,WAAW,UAAU,MAAM,MAAM,CAAC;AAAA,IAClC,MAAM,aAAa,SAAY,KAAK,aAAa,UAAU,MAAM,QAAQ,CAAC;AAAA,IAC1E,MAAM,iBAAiB,SAAY,KAAK,iBAAiB,UAAU,MAAM,YAAY,CAAC;AAAA,IACtF;AAAA,IACA;AAAA,EACF,EAAE,KAAK,EAAE;AACX;AAQA,SAAS,gBAAgB,SAA+B;AACtD,SAAO,QAAQ,iBAAiB,UAAa,yBAAyB,QAAQ;AAChF;AAEA,SAAS,WAAW,MAAc,UAAgC;AAChE,MAAI,EAAE,yBAAyB,aAAa,SAAS,wBAAwB,GAAI,QAAO;AACxF,QAAM,QAAQ,SAAS;AACvB,SAAO,KAAK,MAAM,KAAK,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,KAAK,CAAC,EAAE,KAAK,QAAQ;AAC/E;AAEA,SAAS,cAAc,MAAc,YAAY,QAAwD;AACvG,MAAI,KAAK,KAAK,MAAM,GAAI,QAAO;AAC/B,MAAI;AACJ,MAAI;AACF,aAAS,UAAU,MAAM,IAAI;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,WAAW,OAAO,OAAO,MAAM,GAAG,QAAQ;AAChD,QAAM,OAAO,OAAO,UAAU,IAAI;AAClC,MAAI,aAAa,UAAa,SAAS,OAAW,QAAO;AACzD,SAAO,EAAE,QAAQ,SAAS,QAAQ,MAAM,KAAK;AAC/C;AAGA,SAAS,kBAAkB,UAAsC;AAC/D,QAAM,WAAW,cAAc,QAAQ;AACvC,QAAM,QAAQ,SAAS,UAAU,QAAQ,YAAY,qBAAqB;AAC1E,SAAO,UAAU,UAAa,MAAM,KAAK,MAAM,KAAK,SAAY,MAAM,KAAK;AAC7E;AAOA,IAAM,WAAW;AAEjB,SAAS,WAAW,SAAiB,QAAgB,OAAgB,MAAiC;AACpG,QAAM,YAAY,OAAO,MAAM,SAAS;AACxC,QAAM,cAAc,OAAO,MAAM,WAAW;AAC5C,QAAM,WAAW,CAAC,WAAW,aAAa,KAAK,UAAU,MAAM,UAAU,EAAE,CAAC,EAAE,KAAK,GAAG;AACtF,QAAM,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,KAAK;AAC7C,QAAM,SAAS,CAAC,WAAW,WAAW,EAAE,OAAO,CAAC,SAAS,SAAS,UAAa,SAAS,EAAE,EAAE,KAAK,IAAI;AAErG,QAAM,YAAa,SAAS,UAAa,WAAW,IAAI,IAAI,KAAM,sBAAsB,KAAK,QAAQ;AACrG,SAAO,IAAI,kBAAkB,GAAG,OAAO,eAAe,WAAW,KAAK,KAAK,IAAI,MAAM,EAAE,IAAI;AAAA,IACzF,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,KAAK;AAAA,IACL,GAAI,SAAS,UAAa,SAAS,KAAK,CAAC,IAAI,EAAE,KAAK;AAAA,EACtD,CAAC;AACH;AAOA,SAAS,YAAYA,OAAsD;AACzE,QAAM,QAAQ,OAAOA,KAAI,KAAK,CAAC;AAC/B,QAAM,WAAqB,CAAC;AAC5B,QAAM,aAAuB,CAAC;AAC9B,MAAI;AACJ,aAAW,WAAW,QAAQ,MAAM,qBAAqB,GAAG;AAC1D,UAAM,cAAc,OAAO,OAAO,KAAK,CAAC;AACxC,eAAW,WAAW,QAAQ,YAAY,OAAO,GAAG;AAClD,eAASC,UAAS,OAAO,OAAO,IAAI,OAAO,CAAC;AAC5C,YAAM,QAAQ,OAAO,OAAO;AAC5B,UAAI,UAAU,UAAa,UAAU,GAAI,UAAS,KAAK,KAAK;AAAA,IAC9D;AACA,eAAW,aAAa,QAAQ,YAAY,SAAS,GAAG;AACtD,YAAM,QAAQ,OAAO,SAAS;AAC9B,UAAI,UAAU,UAAa,UAAU,GAAI,YAAW,KAAK,KAAK;AAAA,IAChE;AAAA,EACF;AACA,QAAM,OAAOA,UAAS,MAAM,OAAO,CAAC;AACpC,QAAM,cAAc;AAAA,IAClB,SAAS,KAAK,KAAK,KAAK,QAAQ;AAAA,IAChC,GAAG,WAAW,OAAO,CAAC,UAAU,CAAC,SAAS,SAAS,KAAK,CAAC,EAAE,IAAI,CAAC,UAAU,IAAI,KAAK,GAAG;AAAA,EACxF,EAAE,KAAK,GAAG;AACV,SAAO,EAAE,MAAM,QAAQ,WAAW,CAAC,KAAK,QAAQ,WAAW,YAAY;AACzE;AAMA,SAAS,YAAY,OAAgB,YAA8C;AACjF,OAAK,iBAAiB,sBAAsB,iBAAiB,sBAAsB,sBAAsB,KAAK,MAAM,OAAO,GAAG;AAC5H,WAAO;AAAA,EACT;AACA,MAAI,EAAE,iBAAiB,sBAAsB,MAAM,aAAa,OAAQ,QAAO;AAC/E,MAAI,MAAM,SAAS,UAAa,WAAW,IAAI,MAAM,IAAI,EAAG,QAAO;AAEnE,MAAI,CAAC,WAAY,QAAO;AACxB,MAAI,MAAM,SAAS,OAAW,QAAO,gBAAgB,IAAI,MAAM,IAAI,IAAI,cAAc;AAErF,MAAI,MAAM,WAAW,UAAa,iBAAiB,IAAI,MAAM,MAAM,EAAG,QAAO;AAC7E,SAAO;AACT;AAOO,SAAS,iBAAiB,KAAkD;AACjF,QAAM,WAAW,cAAc,KAAK,eAAe;AACnD,SAAO,aAAa,SAAY,SAAY,OAAO,aAAa,SAAS,IAAI,EAAE,CAAC,CAAC;AACnF;AAEA,SAAS,aAAaD,OAA8C;AAClE,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQA,KAAI,GAAG;AAC/C,QAAI,CAAC,IAAI,WAAW,GAAG,KAAK,QAAQ,QAAS,QAAO,CAAC,KAAK,MAAM,QAAQ,KAAK,IAAI,MAAM,CAAC,IAAI,KAAK;AAAA,EACnG;AACA,SAAO,CAAC,QAAW,MAAS;AAC9B;AAEA,SAAS,OAAO,OAAqC;AACnD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,OAAO,MAAM,CAAC,CAAC;AAChD,SAAO,OAAO,UAAU,YAAY,UAAU,OAAQ,QAAoB;AAC5E;AAEO,SAAS,QAAQ,OAA2B;AACjD,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GAAI,QAAO,CAAC;AACnE,SAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAC9C;AAGO,SAAS,OAAO,OAAoC;AACzD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAMA,QAAO,OAAO,KAAK;AACzB,QAAM,OAAOA,QAAO,OAAO;AAC3B,SAAO,OAAO,SAAS,WAAW,OAAOA,UAAS,SAAY,SAAY;AAC5E;AAEA,SAAS,SAASE,UAAkB,MAAoC;AACtE,MAAIF,QAAgBE;AACpB,aAAW,OAAO,KAAM,CAAAF,QAAO,OAAOA,KAAI,IAAI,GAAG;AACjD,SAAOC,UAAS,OAAOD,KAAI,CAAC;AAC9B;AAEA,SAASC,UAAS,OAAoC;AACpD,SAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC7D;AAEA,SAASH,SAAQ,OAAgB,QAA0C;AACzE,SAAO,QAAQ,YAAY,QAAS,iBAAiB,SAAS,MAAM,SAAS;AAC/E;AAEA,SAASC,UAAS,OAAwB;AACxC,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;;AC9lBA,IAAM,MAAM;AAGL,SAAS,iBAAiB,OAAiC;AAChE,SAAO,OAAO,UAAU,YAAY,IAAI,KAAK,KAAK;AACpD;AAGA,IAAM,YAAY;AAElB,IAAM,UAAU;AAEhB,SAASI,MAAK,SAAwB;AACpC,QAAM,IAAI,UAAU,iBAAiB,OAAO,EAAE;AAChD;AAOO,SAAS,iBAAiB,UAA8E;AAC7G,QAAM,KAAK,SAAS,WAAW,SAAS;AACxC,QAAM,UAAU,KAAK,SAAS,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM,KAAK,MAAM,GAAG;AACtF,MAAI,OAAO,SAAS,EAAG,CAAAA,MAAK,8CAA8C,OAAO,gCAA6B;AAE9G,QAAM,SAAS,OAAO,IAAI;AAC1B,QAAM,eAAe,OAAO,IAAI;AAChC,QAAM,OAAO,OAAO,KAAK,KAAK,MAAM,GAAG;AACvC,MAAI,KAAK,KAAK,MAAM,MAAM,OAAO,KAAK,MAAM,IAAI;AAC9C,IAAAA,MAAK,8CAA8C,OAAO,gCAA6B;AAAA,EACzF;AACA,MAAI,CAAC,IAAI,KAAK,YAAY,GAAG;AAC3B,IAAAA,MAAK,6EAA0E;AAAA,EACjF;AACA,SAAO,EAAE,UAAU,MAAM,cAAc,OAAO;AAChD;AAOO,SAAS,0BACd,aACoB;AACpB,QAAM,EAAE,UAAU,cAAc,SAAS,IAAI;AAC7C,MAAK,aAAa,YAAgB,iBAAiB,SAAY;AAC7D,IAAAA,MAAK,oHAAoH;AAAA,EAC3H;AACA,QAAM,MAAM,iBAAiB,YAAY,QAAQ;AACjD,MAAI,aAAa,UAAa,iBAAiB,OAAW,QAAO,EAAE,SAAS,SAAS,GAAG,KAAK,SAAS;AAEtG,MAAI,OAAO,aAAa,YAAY,SAAS,KAAK,MAAM,GAAI,CAAAA,MAAK,qDAAkD;AACnH,MAAI,OAAO,iBAAiB,YAAY,aAAa,KAAK,MAAM,IAAI;AAClE,IAAAA,MAAK,yDAAsD;AAAA,EAC7D;AACA,SAAO,EAAE,SAAS,SAAS,GAAG,KAAK,UAAU,UAAU,aAAa;AACtE;;;AC/EA,SAAS,aAAAC,kBAAiB;;;ACgBnB,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAGzB,IAAM,gBAAgB;AAM7B,IAAM,cAAc;AAEpB,SAASC,MAAK,SAAwB;AACpC,QAAM,IAAI,UAAU,iBAAiB,OAAO,EAAE;AAChD;AAGO,SAAS,iBAAiB,OAAgB,OAA0C;AACzF,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,OAAO,UAAU,KAAK,KAAK,SAAS,oBAAoB,SAAS,iBAAkB;AACvF,IAAAA,MAAK,GAAG,KAAK,4CAAyC,gBAAgB,MAAM,gBAAgB,2CAAwC;AAAA,EACtI;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,YAAY,KAAK,KAAK,EAAG;AAE7B,QAAI,QAAQ,KAAK,MAAM,KAAK,CAAC,EAAG,CAAAA,MAAK,GAAG,KAAK,6CAAuC,OAAO,KAAK,CAAC,mBAAmB;AACpH,IAAAA,MAAK,GAAG,KAAK,iFAA2E;AAAA,EAC1F;AACA,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,GAAG;AACxE,UAAM,EAAE,KAAK,IAAI;AACjB,QAAI,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,GAAI,CAAAA,MAAK,GAAG,KAAK,sCAAmC;AAKpG,QAAI,YAAY,KAAK,IAAI,EAAG,CAAAA,MAAK,GAAG,KAAK,MAAM,IAAI,sCAAmC,IAAI,kBAAkB,IAAI,KAAK;AACrH;AAAA,EACF;AACA,EAAAA,MAAK,GAAG,KAAK,sFAA2E;AAC1F;AAGO,SAAS,kBAAkB,OAAyB;AACzD,MAAI,OAAO,UAAU,SAAU,QAAO,WAAW,KAAK;AACtD,MAAI,OAAO,UAAU,SAAU,QAAO,WAAW,UAAU,KAAK,CAAC;AACjE,SAAO,SAAS,UAAU,MAAM,IAAI,CAAC;AACvC;AAGO,SAAS,eAAe,OAA0B;AACvD,SAAO,UAAU;AACnB;AAOO,SAAS,WAAW,OAAiD;AAC1E,QAAM,OAAO,OAAO,KAAK;AACzB,MAAI,SAAS,UAAa,SAAS,GAAI,QAAO;AAC9C,SAAO,QAAQ,KAAK,IAAI,IAAI,OAAO,IAAI,IAAI;AAC7C;;;ADvEO,IAAM,uBAAuB;AACpC,IAAM,YAAY;AAGX,IAAM,iBAAiB;AAKvB,IAAM,cAAc;AAEpB,IAAM,YAAY;AAMlB,IAAM,iBAAiB;AACvB,IAAM,kBAAkB;AAkF/B,IAAM,aAA+C,EAAE,GAAG,gBAAgB,IAAI,gBAAgB,KAAK,aAAa;AAEhH,SAAS,KAAK,MAAsB;AAClC,SAAO,yCAAyC,SAAS,KAAK,IAAI;AACpE;AAEA,SAAS,WAAW,OAAiB,KAAqB;AACxD,SAAO,oBAAoB,kBAAkB,KAAK,CAAC,oBAAoB,UAAU,GAAG,CAAC;AACvF;AAGO,SAAS,aAAa,WAA8C;AACzE,SAAO,UACJ,IAAI,CAAC,WAAW,wBAAwB,UAAU,OAAO,QAAQ,CAAC,eAAe,UAAU,OAAO,QAAQ,CAAC,KAAK,EAChH,KAAK,EAAE;AACZ;AAGO,SAAS,mBAAmB,OAAiB,KAAa,YAAuC,CAAC,GAAW;AAClH,SAAO,KAAK,GAAG,WAAW,OAAO,GAAG,CAAC,GAAG,aAAa,SAAS,CAAC,EAAE;AACnE;AAGO,SAAS,uBAAuB,QAA0B,OAAwD,CAAC,GAAW;AACnI,SAAO,KAAK,uBAAuB,MAAM,MAAM,KAAK,IAAI,CAAC,WAAW,WAAW,OAAO,OAAO,OAAO,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;AACtH;AAMO,SAAS,mBAAmB,SAAiB,WAAmB,SAAyC;AAC9G,SAAO,EAAE,SAAS,sBAAsB,QAAQ,oBAAoB,SAAS,YAAY,OAAO,WAAW,GAAG,QAAQ;AACxH;AAEO,SAAS,oBAAoB,QAAkC;AACpE,SAAO,WAAW,MAAM;AAC1B;AAMA,IAAM,kBAAkB,IAAIC,WAAU;AAAA,EACpC,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,SAAS,CAAC,SAAS,SAAS;AAC9B,CAAC;AAIM,SAAS,KAAK,OAAqC;AACxD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,KAAK,MAAM,CAAC,CAAC;AAC9C,SAAO,OAAO,UAAU,YAAY,UAAU,OAAQ,QAAoB;AAC5E;AAEO,SAAS,UAAU,OAAgB,MAAkC;AAC1E,QAAM,OAAO,KAAK,KAAK,IAAI,IAAI,IAAI,EAAE;AACrC,SAAO,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,KAAK,KAAK,KAAK,IAAI;AACxE;AAEA,SAAS,QAAQ,OAAoC;AACnD,QAAM,OAAO,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,CAAC,IAAI,KAAK,GAAG,KAAK;AACnE,SAAO,SAAS,UAAa,SAAS,KAAK,SAAY;AACzD;AAMO,SAAS,UAAU,KAAa,aAAyD;AAC9F,MAAI;AACJ,MAAI;AACF,aAAS,gBAAgB,MAAM,GAAG;AAAA,EACpC,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,QAAM,UAAU,KAAK,KAAK,KAAK,KAAK,MAAM,GAAG,QAAQ,GAAG,IAAI,IAAI,WAAW,CAAC;AAC5E,QAAM,YAAY,gBAAgB,kBAAkB,KAAK,SAAS,SAAS,IAAI;AAC/E,SAAO,QAAQ,WAAW,IAAI,EAAE,IAAI,CAAC,SAAU,OAAO,SAAS,WAAW,OAAQ,OAAO,IAAI,KAAK,EAAI;AACxG;AAGO,SAAS,eAAe,KAAuB;AACpD,SAAO,UAAU,KAAK,eAAe;AACvC;AAGO,SAAS,eAAe,MAAmC;AAChE,SAAO,MAAM,KAAK,MAAM;AAC1B;AAOO,SAAS,qBAAqB,OAAsD;AACzF,SAAO,cAAc,OAAO,cAAc;AAC5C;AAGO,SAAS,cAAc,OAA6C,MAAuB;AAChG,QAAM,SAAS,GAAG,MAAM,OAAO;AAC/B,QAAM,cAAc,MAAM,QAAQ,WAAW,MAAM,IAAI,MAAM,QAAQ,MAAM,OAAO,MAAM,IAAI,MAAM;AAClG,SAAO,YACJ,MAAM,aAAa,EACnB,KAAK,CAAC,SAAS,KAAK,KAAK,MAAM,IAAI;AACxC;AAMO,SAAS,cAAc,OAAgB,SAAoF;AAChI,MAAI,EAAE,iBAAiB,uBAAuB,MAAM,YAAY,QAAS,QAAO;AAChF,QAAM,UAAU,CAAC,OAAO,GAAG,MAAM,MAAM;AACvC,MAAI,QAAQ,KAAK,CAAC,WAAW,cAAc,QAAQ,WAAW,CAAC,EAAG,QAAO,EAAE,QAAQ,SAAS,MAAM;AAClG,MAAI,QAAQ,KAAK,oBAAoB,EAAG,QAAO,EAAE,QAAQ,kBAAkB,MAAM;AACjF,SAAO;AACT;AAGO,SAAS,gBAAgB,OAA6C;AAC3E,SAAO,iBAAiB,sBAAsB,CAAC,OAAO,GAAG,MAAM,MAAM,EAAE,KAAK,CAAC,WAAW,cAAc,QAAQ,SAAS,CAAC;AAC1H;AAGO,SAAS,QAAQ,UAA0B,SAAyB,kBAAkB,KAA0B;AACrH,SAAO,EAAE,MAAM,MAAM,QAAQ,SAAS,WAAW,UAAU,cAAc,gBAAgB,UAAU,GAAG,iBAAiB,GAAG,EAAE;AAC9H;AASO,SAAS,eAAe,UAAwB,EAAE,WAAW,MAAM,IAA4B,CAAC,GAAc;AACnH,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,YAAY,eAAe,SAAS,GAAG;AAC7C,QAAM,YAAY,UAAU,KAAK,CAAC,SAAS,KAAK,KAAK,MAAM,EAAE;AAC7D,MAAI,eAAe,SAAS,KAAK,SAAS,KAAK,oBAAoB,EAAG,QAAO,QAAQ,UAAU,kBAAkB,SAAS,GAAG;AAE7H,MAAI,YAAY,SAAS,QAAQ,SAAS,UAAa,cAAc,QAAW;AAC9E,WAAO,EAAE,MAAM,OAAO,MAAM,WAAW,SAAS,EAAE,MAAM,UAAU,GAAG,UAAU,GAAG,iBAAiB,SAAS,GAAG,EAAE;AAAA,EACnH;AACA,QAAM,SAAS,WAAW,SAAY,WAAW,SAAS,QAAQ,IAAI;AACtE,MAAI,WAAW,QAAW;AACxB,UAAM,WAAW,WAAW,yDAAyD;AACrF,UAAM,IAAI,kBAAkB,GAAG,oBAAoB,8BAA8B,QAAQ,KAAK;AAAA,MAC5F,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,WAAW;AAAA,MACX,KAAK,SAAS;AAAA,IAChB,CAAC;AAAA,EACH;AACA,QAAM,OAAkB,EAAE,GAAG,QAAQ,UAAU;AAC/C,SAAO,EAAE,MAAM,OAAO,MAAM,OAAO,MAAM,UAAU,GAAG,iBAAiB,SAAS,GAAG,EAAE;AACvF;AAGO,SAAS,WAAW,OAA0D;AACnF,QAAM,OAAO,KAAK,KAAK;AACvB,QAAM,UAAU,UAAU,MAAM,UAAU,IAAI;AAC9C,MAAI,SAAS,UAAa,YAAY,OAAW,QAAO;AACxD,QAAM,SAAS,KAAK,KAAK,KAAK,GAAG,GAAG,MAAM;AAC1C,QAAM,YAAY,UAAU,QAAQ,WAAW;AAC/C,QAAM,iBAAiB,UAAU,QAAQ,gBAAgB;AACzD,QAAM,WAAW,QAAQ,KAAK,QAAQ;AACtC,QAAM,mBAAmB,QAAQ,KAAK,aAAa;AACnD,QAAM,QAAQ,QAAQ,KAAK,KAAK;AAChC,SAAO;AAAA,IACL;AAAA,IACA,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,IAC7C,GAAI,cAAc,UAAa,mBAAmB,SAC9C,CAAC,IACD;AAAA,MACE,UAAU;AAAA,QACR,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,UAAU;AAAA,QAC/C,GAAI,mBAAmB,SAAY,CAAC,IAAI,EAAE,eAAe;AAAA,MAC3D;AAAA,IACF;AAAA,IACJ,GAAI,qBAAqB,SAAY,CAAC,IAAI,EAAE,iBAAiB;AAAA,IAC7D,GAAI,UAAU,SAAY,CAAC,IAAI,EAAE,MAAM;AAAA,EACzC;AACF;;;AEpSO,IAAM,sBAAsB;AACnC,IAAMC,aAAY;AAqClB,IAAM,cAAc,EAAE,UAAU,YAAY,UAAU,YAAY,MAAM,OAAO;AAGxE,SAAS,kBAAkB,KAAqB;AACrD,SAAO,wCAAwCA,UAAS,iDAAiD,UAAU,GAAG,CAAC;AACzH;AAGO,SAAS,kBAAkB,KAAa,SAA4C;AACzF,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS,kBAAkB,GAAG;AAAA,IAC9B,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,GAAG;AAAA,EACL;AACF;AAOO,SAAS,eAAe,OAA+C;AAC5E,QAAM,QAAQ,mBAAmB,KAAK,SAAS,EAAE;AACjD,SAAO,UAAU,OAAO,SAAY,OAAO,MAAM,CAAC,CAAC;AACrD;AAIA,SAASC,WAAUC,OAAe,MAAkC;AAClE,QAAM,QAASA,QAA+B,IAAI,IAAI,EAAE;AACxD,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAOO,SAAS,wBAAwB,UAA4C;AAClF,QAAM,SAAuB,CAAC;AAC9B,MAAI;AACJ,aAAW,QAAQ,QAAQ,SAAS,QAAQ,SAAS,GAAG;AACtD,kBAAcC,UAASF,WAAU,MAAM,UAAU,CAAC;AAClD,eAAWG,eAAc,QAAS,KAAiB,eAAe,GAAG;AAGnE,YAAM,SAASH,WAAUG,aAAY,QAAQ;AAC7C,YAAM,OAAOD,UAASF,WAAUG,aAAY,MAAM,CAAC;AACnD,YAAM,QAA8B,WAAW,UAAa,SAAS,SAAY,EAAE,KAAK,IAAI,WAAW,MAAM;AAC7G,YAAM,QAAQ,eAAeH,WAAUG,aAAY,OAAO,CAAC;AAC3D,UAAI,UAAU,UAAa,UAAU,QAAW;AAC9C,cAAM,UAAU,+BAA+B,UAAU,EAAE,cAAcH,WAAUG,aAAY,OAAO,KAAK,EAAE,KAAK,QAAQ;AAAA,MAC5H;AACA,aAAO,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,SAAuC,CAAC;AAC9C,aAAW,SAAS,QAAQ,SAAS,QAAQ,MAAM,GAAG;AACpD,UAAM,MAAM,aAAaH,WAAU,OAAO,MAAM,KAAK,IAAI,YAAY,CAA6B;AAClG,QAAI,QAAQ,OAAW;AACvB,UAAM,QAAQ,eAAeA,WAAU,OAAO,OAAO,CAAC;AACtD,QAAI,UAAU,OAAW,OAAM,UAAU,UAAU,GAAG,eAAeA,WAAU,OAAO,OAAO,KAAK,EAAE,KAAK,QAAQ;AACjH,WAAO,GAAG,IAAI;AAAA,EAChB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,UAAU;AAAA,IAC/C,UAAU,SAAS;AAAA,IACnB,GAAG,iBAAiB,SAAS,GAAG;AAAA,EAClC;AACF;AAEA,SAAS,UAAU,QAAgB,UAA2C;AAC5E,SAAO,IAAI,kBAAkB,GAAG,mBAAmB,8BAA8B,MAAM,KAAK;AAAA,IAC1F,UAAU;AAAA,IACV,QAAQ,SAAS;AAAA,IACjB,WAAW;AAAA,IACX,KAAK,SAAS;AAAA,EAChB,CAAC;AACH;AAEA,SAASE,UAAS,OAA+C;AAC/D,QAAM,OAAO,OAAO,KAAK;AACzB,SAAO,SAAS,UAAa,SAAS,KAAK,SAAY;AACzD;;;ACpHA,IAAME,aAAY;AAsBX,IAAM,2BAA8C,CAAC,MAAM,IAAI;AA8B/D,SAAS,iBACd,OACA,KACA,kBACA,YAAuC,CAAC,GAChC;AACR,QAAM,OAAO,mBAAmB,+CAA+C;AAC/E,SAAO,yCAAyCA,UAAS,sBAAsB,kBAAkB,KAAK,CAAC,oBAAoB,UAAU,GAAG,CAAC,KAAK,IAAI,qBAAqB,aAAa,SAAS,CAAC;AAChM;AAGO,SAAS,iBAAiB,SAAiB,SAA2C;AAC3F,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR;AAAA,IACA,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,GAAG;AAAA,EACL;AACF;AAEO,SAAS,UAAU,UAA0B,YAAsB,CAAC,GAAG,KAAkC;AAC9G,SAAO,EAAE,UAAU,CAAC,GAAG,SAAS,CAAC,GAAG,WAAW,UAAU,GAAG,iBAAiB,GAAG,EAAE;AACpF;AAQO,SAAS,eAAe,UAA2C;AACxE,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,YAAY,eAAe,SAAS,GAAG;AAC7C,QAAM,YAAY,UAAU,KAAK,CAAC,SAAS,KAAK,KAAK,MAAM,EAAE;AAC7D,MAAI,eAAe,SAAS,KAAK,SAAS,KAAK,oBAAoB,EAAG,QAAO,UAAU,UAAU,WAAW,SAAS,GAAG;AAExH,QAAM,UAAU,QAAQ,SAAS,QAAQ,IAAI,EAAE,IAAI,CAAC,SAAyB;AAC3E,UAAM,SAAS,WAAW,IAAI;AAC9B,QAAI,WAAW,QAAW;AACxB,YAAM,IAAI,kBAAkB,GAAG,oBAAoB,6DAA6D;AAAA,QAC9G,UAAU;AAAA,QACV,QAAQ,SAAS;AAAA,QACjB,WAAW;AAAA,QACX,KAAK,SAAS;AAAA,MAChB,CAAC;AAAA,IACH;AACA,UAAM,SAAS,UAAU,MAAM,QAAQ;AACvC,UAAM,WAAW,WAAW,UAAa,QAAQ,KAAK,MAAM,IAAI,OAAO,MAAM,IAAI;AACjF,WAAO,EAAE,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS,GAAI,GAAG,OAAO;AAAA,EACtE,CAAC;AACD,SAAO,EAAE,UAAU,QAAQ,IAAI,CAAC,UAAU,MAAM,OAAO,GAAG,SAAS,WAAW,UAAU,GAAG,iBAAiB,SAAS,GAAG,EAAE;AAC5H;;;ACnHO,IAAM,yBAAyB;AACtC,IAAMC,aAAY;AAwDlB,IAAM,WAAiE;AAAA,EACrE,CAAC,eAAe,aAAa;AAAA,EAC7B,CAAC,SAAS,OAAO;AAAA,EACjB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,SAAS,OAAO;AAAA,EACjB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,eAAe,aAAa;AAAA,EAC7B,CAAC,wBAAwB,sBAAsB;AAAA,EAC/C,CAAC,iBAAiB,eAAe;AACnC;AAGO,SAAS,qBAAqB,KAAqB;AACxD,SAAO,2CAA2CA,UAAS,iDAAiD,UAAU,GAAG,CAAC;AAC5H;AAMO,SAAS,qBAAqB,KAAa,SAA+C;AAC/F,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS,qBAAqB,GAAG;AAAA,IACjC,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,GAAG;AAAA,EACL;AACF;AAIA,SAASC,WAAUC,OAAe,MAAkC;AAClE,QAAM,SAAS,MAAM,QAAQA,KAAI,IAAIA,MAAK,CAAC,IAAKA,SAAgC,IAAI,IAAI,EAAE;AAC1F,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,SAASC,UAAS,OAA+C;AAC/D,QAAM,OAAO,OAAO,KAAK;AACzB,SAAO,SAAS,UAAa,SAAS,KAAK,SAAY;AACzD;AAOO,SAAS,2BAA2B,UAA+C;AACxF,QAAM,SAA0B,CAAC;AACjC,MAAI;AACJ,aAAW,QAAQ,QAAQ,SAAS,QAAQ,SAAS,GAAG;AACtD,mBAAeA,UAASF,WAAU,MAAM,UAAU,CAAC;AACnD,eAAWG,eAAc,QAAS,KAAiB,eAAe,GAAG;AAEnE,YAAM,SAASH,WAAUG,aAAY,QAAQ;AAC7C,YAAM,OAAOD,UAASF,WAAUG,aAAY,MAAM,CAAC;AACnD,YAAM,QAA8B,WAAW,UAAa,SAAS,SAAY,EAAE,KAAK,IAAI,WAAW,MAAM;AAC7G,UAAI,UAAU,OAAW,OAAMC,WAAU,+BAA+B,UAAU,EAAE,KAAK,QAAQ;AACjG,aAAO,KAAK,EAAE,OAAO,GAAG,SAASD,aAAY,WAAW,UAAU,IAAI,IAAI,QAAQ,EAAE,CAAC;AAAA,IACvF;AAAA,EACF;AACA,QAAM,aAAa,QAAQ,SAAS,QAAQ,MAAM,EAAE,CAAC;AACrD,QAAM,SAAS,eAAe,SAAY,SAAY,SAAS,YAAY,UAAU,QAAQ;AAE7F,SAAO;AAAA,IACL;AAAA,IACA,GAAI,WAAW,SAAY,CAAC,IAAI,EAAE,OAAO;AAAA,IACzC,GAAI,eAAe,SAAY,CAAC,IAAI,EAAE,WAAW;AAAA,IACjD,UAAU,SAAS;AAAA,IACnB,GAAG,iBAAiB,SAAS,GAAG;AAAA,EAClC;AACF;AAEA,SAAS,SAASF,OAAe,OAAe,UAA+C;AAC7F,QAAM,SAAS,CAAC;AAChB,aAAW,CAACI,UAAS,GAAG,KAAK,UAAU;AACrC,UAAM,MAAML,WAAWC,MAAiBI,QAAO,GAAG,OAAO;AACzD,UAAM,QAAQ,eAAe,GAAG;AAChC,QAAI,UAAU,OAAW,OAAMD,WAAU,GAAG,KAAK,QAAQC,QAAO,WAAW,OAAO,EAAE,KAAK,QAAQ;AACjG,WAAO,GAAG,IAAI;AAAA,EAChB;AACA,SAAO;AACT;AAEA,SAASD,WAAU,QAAgB,UAA2C;AAC5E,SAAO,IAAI,kBAAkB,GAAG,sBAAsB,8BAA8B,MAAM,KAAK;AAAA,IAC7F,UAAU;AAAA,IACV,QAAQ,SAAS;AAAA,IACjB,WAAW;AAAA,IACX,KAAK,SAAS;AAAA,EAChB,CAAC;AACH;;;AC7IO,IAAM,sBAAsB;AACnC,IAAME,aAAY;AAGX,IAAM,eAAe;AACrB,IAAM,qBAAqB;AAGlC,IAAM,0BAAoE;AAAA,EACxE,CAAC,GAAG,GAAG;AAAA,EACP,CAAC,KAAK,GAAG;AACX;AAgEO,SAAS,kBAAkB,OAAiC;AACjE,SACE,OAAO,UAAU,YACjB,OAAO,UAAU,KAAK,KACtB,wBAAwB,KAAK,CAAC,CAAC,KAAK,GAAG,MAAM,SAAS,OAAO,SAAS,GAAG;AAE7E;AAEO,SAAS,kBAAkB,IAAoC,WAA8B,CAAC,GAAW;AAC9G,QAAM,cAAc,GACjB,IAAI,CAAC,WAAW;AACf,UAAM,MAAM,OAAO,oBAAoB,SAAY,KAAK,8BAA8B,OAAO,eAAe;AAC5G,WAAO,oBAAoB,kBAAkB,OAAO,KAAK,CAAC,GAAG,GAAG,oBAAoB,UAAU,OAAO,GAAG,CAAC;AAAA,EAC3G,CAAC,EACA,KAAK,EAAE;AACV,QAAM,MAAM,SAAS,IAAI,CAAC,YAAY,iBAAiB,UAAU,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE;AACvF,SAAO,wCAAwCA,UAAS,gBAAgB,WAAW,GAAG,GAAG;AAC3F;AAGO,SAAS,kBAAkB,SAAiB,SAA4C;AAC7F,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR;AAAA,IACA,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,GAAG;AAAA,EACL;AACF;AAMA,IAAM,iBAAiB;AAGhB,SAAS,iBAAiB,OAA8C;AAC7E,WAAS,QAAQ,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS;AACtD,UAAM,QAAQ,eAAe,KAAK,MAAM,KAAK,KAAK,EAAE;AACpD,QAAI,UAAU,KAAM,QAAO,MAAM,CAAC;AAAA,EACpC;AACA,SAAO;AACT;AAGA,SAAS,MAAM,UAAwB,MAAkC;AACvE,SAAO,SAAS,SAAS,KAAK,oBAAoB,KAAK,eAAe,KAAK,KAAK,CAAC,SAAS,KAAK,KAAK,MAAM,EAAE,CAAC;AAC/G;AAOO,SAAS,eAAe,UAAmC;AAChE,QAAM,OAAO,UAAU,SAAS,KAAK,cAAc;AACnD,MAAI,MAAM,UAAU,IAAI,EAAG,QAAO,QAAQ,SAAS,UAAU,kBAAkB,SAAS,GAAG;AAC3F,QAAM,UAAU,iBAAiB,IAAI;AACrC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,kBAAkB,GAAG,mBAAmB,4EAAyE;AAAA,MACzH,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,WAAW;AAAA,MACX,KAAK,SAAS;AAAA,IAChB,CAAC;AAAA,EACH;AACA,SAAO,EAAE,MAAM,OAAO,MAAM,OAAO,MAAM,EAAE,SAAS,WAAW,KAAK,GAAG,UAAU,SAAS,UAAU,GAAG,iBAAiB,SAAS,GAAG,EAAE;AACxI;AAMO,SAAS,kBAAkB,UAA4C;AAC5E,QAAM,OAAO,UAAU,SAAS,KAAK,cAAc;AACnD,MAAI,MAAM,UAAU,IAAI,KAAK,iBAAiB,IAAI,MAAM,OAAW,QAAO,eAAe,QAAQ;AACjG,SAAO,iBAAiB,QAAQ;AAClC;AAGO,SAAS,iBAAiB,UAA0C;AACzE,QAAM,aAAa,QAAQ,SAAS,QAAQ,SAAS,EAAE,IAAI,CAAC,SAAyB;AACnF,UAAMC,cAAa,KAAK,KAAK,IAAI,GAAG,eAAe;AAEnD,UAAM,SAAS,UAAUA,aAAY,QAAQ;AAC7C,UAAM,OAAO,UAAUA,aAAY,MAAM;AACzC,UAAM,QAA8B,WAAW,SAAY,WAAW,MAAM,IAAI,SAAS,SAAY,EAAE,KAAK,IAAI;AAChH,UAAM,MAAM,UAAUA,aAAY,gBAAgB;AAClD,UAAM,UAAU,UAAU,KAAK,IAAI,GAAG,UAAU,IAAI;AACpD,UAAM,WAAW,UAAU,MAAM,UAAU;AAC3C,WAAO;AAAA,MACL,GAAI,UAAU,SAAY,CAAC,IAAI,EAAE,MAAM;AAAA,MACvC,GAAI,QAAQ,SAAY,CAAC,IAAI,EAAE,IAAI;AAAA,MACnC,GAAI,YAAY,SAAY,CAAC,IAAI,EAAE,QAAQ;AAAA,MAC3C,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,IAC/C;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA,MAAM,UAAU,SAAS,KAAK,cAAc;AAAA,IAC5C,UAAU,SAAS;AAAA,IACnB,GAAG,iBAAiB,SAAS,GAAG;AAAA,EAClC;AACF;;;AC9FA,SAASC,MAAK,SAAwB;AACpC,QAAM,IAAI,UAAU,iBAAiB,OAAO,EAAE;AAChD;AAOA,SAAS,gBAAgB,OAAyB;AAChD,SAAO,iBAAiB,sBAAuB,iBAAiB,qBAAqB,MAAM,SAAS;AACtG;AAEO,IAAM,kBAAN,MAAsB;AAAA,EAClB;AAAA,EACT,SAAqB;AAAA;AAAA,EAErB,YAAY;AAAA;AAAA,EAGZ,YAAY,SAAuB;AACjC,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,QAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,MAAM,UAA6B,CAAC,GAAG,UAA6B,CAAC,GAAgC;AACzG,UAAM,MAAM,KAAK,KAAK,QAAQ,KAAK,KAAK;AACxC,UAAM,WAAW,MAAM,KAAK,SAAS,KAAK,kBAAkB,KAAK,OAAO,CAAC;AACzE,WAAO,wBAAwB,QAAQ;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,SAAS,UAAgC,CAAC,GAAG,UAAgC,CAAC,GAAmC;AACrH,QAAI,OAAO,YAAY,YAAY,YAAY,KAAM,CAAAA,MAAK,gCAAgC;AAC1F,UAAM,MAAM,KAAK,KAAK,QAAQ,KAAK,KAAK;AACxC,UAAM,WAAW,MAAM,KAAK,SAAS,KAAK,qBAAqB,KAAK,OAAO,CAAC;AAC5E,WAAO,2BAA2B,QAAQ;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,KAAK,SAA2B,UAA4B,CAAC,GAA+B;AAChG,QAAI,OAAO,YAAY,YAAY,YAAY,KAAM,CAAAA,MAAK,kEAAkE;AAC5H,qBAAiB,QAAQ,OAAO,OAAO;AAEvC,QAAI,eAAe,QAAQ,KAAK,EAAG,CAAAA,MAAK,yEAAyE;AACjH,UAAM,MAAM,KAAK,KAAK,QAAQ,KAAK,KAAK;AACxC,UAAM,EAAE,mBAAmB,MAAM,IAAI;AACrC,QAAI,OAAO,qBAAqB,UAAW,CAAAA,MAAK,sCAAsC;AACtF,UAAM,YAAY,kBAAkB,QAAQ,SAAS;AACrD,cAAU,QAAQ,CAAC,QAAQ,UAAU;AAEnC,UAAI,CAAC,yBAAyB,SAAS,OAAO,QAAQ,GAAG;AACvD,QAAAA,MAAK,aAAa,KAAK,qCAAqC,yBAAyB,KAAK,KAAK,CAAC,8CAA2C;AAAA,MAC7I;AAAA,IACF,CAAC;AACD,UAAMC,QAAO,iBAAiB,iBAAiB,QAAQ,OAAO,KAAK,kBAAkB,SAAS,GAAG,OAAO;AACxG,QAAI;AACF,aAAO,eAAe,MAAM,KAAK,SAAS,KAAKA,KAAI,CAAC;AAAA,IACtD,SAAS,OAAO;AACd,YAAM,MAAM,cAAc,OAAOA,MAAK,OAAO;AAC7C,UAAI,QAAQ,OAAW,QAAO,UAAU,CAAC,GAAG,IAAI,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,MAAM,GAAG;AAClF,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,OAAO,SAA6B,UAA8B,CAAC,GAAuB;AAC9F,QAAI,KAAK,WAAW,SAAU,CAAAD,MAAK,yFAAmF;AACtH,QAAI,KAAK,WAAW,UAAW,CAAAA,MAAK,2FAAwF;AAC5H,QAAI,OAAO,YAAY,YAAY,YAAY,KAAM,CAAAA,MAAK,iDAAiD;AAC3G,qBAAiB,QAAQ,OAAO,OAAO;AACvC,UAAM,MAAM,KAAK,KAAK,QAAQ,KAAK,KAAK;AACxC,UAAM,YAAY,kBAAkB,QAAQ,SAAS;AACrD,SAAK,YAAY,eAAe,QAAQ,KAAK;AAC7C,WAAO,KAAK,MAAM,mBAAmB,mBAAmB,QAAQ,OAAO,KAAK,SAAS,GAAG,gBAAgB,OAAO,CAAC;AAAA,EAClH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,UAAkC,CAAC,GAAuB;AACrE,SAAK,cAAc,QAAQ;AAC3B,WAAO,KAAK,MAAM,mBAAmB,uBAAuB,GAAG,GAAG,oBAAoB,GAAG,GAAG,OAAO,CAAC;AAAA,EACtG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,UAA8B,CAAC,GAAG,UAAkC,CAAC,GAAuB;AACvG,SAAK,cAAc,QAAQ;AAC3B,UAAM,OAAO,KAAK,YAAY,QAAQ,IAAI;AAC1C,WAAO,KAAK,MAAM,mBAAmB,uBAAuB,MAAM,IAAI,GAAG,oBAAoB,IAAI,GAAG,OAAO,CAAC;AAAA,EAC9G;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAK,UAAkC,CAAC,GAAkB;AAC9D,SAAK,cAAc,MAAM;AACzB,UAAM,SAAS,KAAK;AACpB,UAAM,UAAU,mBAAmB,uBAAuB,KAAK,GAAG,oBAAoB,KAAK,GAAG,OAAO;AACrG,QAAI;AACF,YAAM,KAAK,SAAS,KAAK,OAAO;AAAA,IAClC,SAAS,OAAO;AACd,UAAI,WAAW,aAAa,gBAAgB,KAAK,GAAG;AAGlD,aAAK,SAAS,IAAI,KAAK,QAAQ,6BAA6B,EAAE,MAAM,MAAM,MAAM,MAAM,CAAC;AACvF,aAAK,SAAS;AACd;AAAA,MACF;AACA,WAAK,SAAS,KAAK;AACnB,YAAM;AAAA,IACR;AACA,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,QACJ,SACA,UACA,UAAkC,CAAC,GACN;AAC7B,QAAI,OAAO,YAAY,YAAY,YAAY,KAAM,CAAAA,MAAK,0DAA0D;AACpH,QAAI,OAAO,aAAa,WAAY,CAAAA,MAAK,oCAAoC;AAC7E,UAAM,EAAE,OAAO,GAAG,OAAO,IAAI;AAE7B,QAAI,eAAe,OAAO,KAAK,EAAG,CAAAA,MAAK,2FAA2F;AAClI,QAAI,UAAU,UAAa,EAAE,OAAO,UAAU,KAAK,KAAK,SAAS,GAAI,CAAAA,MAAK,4CAA4C;AAGtH,UAAM,iBAAiB,KAAK,WAAW;AACvC,QAAI,UAAU;AACd,QAAI;AACF,UAAI,OAAO,MAAM,KAAK,OAAO,QAAQ,OAAO;AAC5C,aAAO,CAAC,KAAK,MAAM;AACjB,YAAI,UAAU,UAAa,WAAW,OAAO;AAC3C,gBAAM,KAAK,KAAK,OAAO;AACvB,iBAAO,EAAE,SAAS,OAAO,QAAQ;AAAA,QACnC;AAEA,YAAI,KAAK,SAAS,MAAO,OAAM,IAAI,UAAU,oEAAiE;AAC9G,cAAM,SAAS,MAAM,SAAS,KAAK,IAAI;AACvC;AACA,eAAO,MAAM,KAAK,eAAe,QAAQ,OAAO;AAAA,MAClD;AACA,aAAO,EAAE,SAAS,OAAO,KAAK,OAAO;AAAA,IACvC,SAAS,OAAO;AACd,UAAI,eAAgB,OAAM,KAAK,aAAa,OAAO,OAAO;AAC1D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,QAAiB,SAAqD;AACzF,UAAM,OAAO,OAAO,WAAW,YAAY,WAAW,OAAQ,OAAgC,SAAS;AACvG,QAAI,SAAS,SAAU,QAAO,KAAK,OAAO,OAAO;AACjD,QAAI,SAAS,SAAU,QAAO,KAAK,OAAO,CAAC,GAAG,OAAO;AACrD,QAAI,SAAS,SAAS;AACpB,YAAM,OAAO,MAAM,KAAK,MAAM,EAAE,IAAK,OAAuC,GAAyB,GAAG,OAAO;AAE/G,UAAI,EAAE,UAAU,MAAO,OAAM,IAAI,UAAU,6DAA0D;AACrG,aAAO;AAAA,IACT;AACA,UAAM,IAAI,UAAU,+HAA+H;AAAA,EACrJ;AAAA;AAAA,EAGA,MAAM,aAAa,OAAgB,SAAgD;AACjF,QAAI,KAAK,WAAW,aAAa,iBAAiB,kBAAmB;AACrE,QAAI;AACF,YAAM,KAAK,KAAK,OAAO;AAAA,IACzB,SAAS,OAAO;AACd,WAAK,SAAS,IAAI,KAAK,QAAQ,0BAA0B,EAAE,MAAM,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAmBA,MAAM,MAAM,SAA4B,UAA6B,CAAC,GAAgC;AACpG,QAAI,OAAO,YAAY,YAAY,YAAY,KAAM,CAAAA,MAAK,sCAAsC;AAChG,UAAM,KAAK,KAAK,SAAS,QAAQ,EAAE;AACnC,UAAM,WAAW,iBAAiB,QAAQ,QAAQ;AAClD,QAAI,KAAK,aAAa,KAAK,WAAW,WAAW;AAC/C,MAAAA,MAAK,gGAAgG;AAAA,IACvG;AACA,QAAI,SAAS,SAAS,KAAK,KAAK,WAAW,UAAU;AACnD,MAAAA,MAAK,iHAAiH;AAAA,IACxH;AACA,QAAI,SAAS,SAAS,KAAK,KAAK,WAAW,WAAW;AACpD,MAAAA,MAAK,4GAAyG;AAAA,IAChH;AACA,QAAI,GAAG,KAAK,CAAC,WAAW,OAAO,oBAAoB,MAAS,GAAG;AAC7D,MAAAA,MAAK,kGAAkG;AAAA,IACzG;AACA,UAAMC,QAAO,kBAAkB,kBAAkB,IAAI,QAAQ,GAAG,OAAO;AAEvE,QAAI,KAAK,WAAW,UAAW,QAAO,iBAAiB,MAAM,KAAK,SAAS,KAAKA,KAAI,CAAC;AACrF,WAAO,KAAK,SAASA,OAAM,KAAK,WAAW,WAAW,iBAAiB,iBAAiB;AAAA,EAC1F;AAAA;AAAA,EAGA,MAAM,SAA6C;AACjD,UAAM,WAAW,KAAK;AACtB,WAAO,KAAK,SAAS,SAAS,CAAC,aAAa,eAAe,UAAU,EAAE,SAAS,CAAC,CAAC;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAuC,SAAyB,OAAkD;AACtH,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,MAAM,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,IAClD,SAAS,OAAO;AACd,YAAM,MAAM,cAAc,OAAO,QAAQ,OAAO;AAChD,UAAI,QAAQ,QAAW;AACrB,aAAK,SAAS;AACd,eAAO,QAAQ,CAAC,GAAG,IAAI,MAAM,QAAQ,GAAG,IAAI,QAAQ,IAAI,MAAM,GAAG;AAAA,MACnE;AACA,WAAK,SAAS,KAAK;AACnB,YAAM;AAAA,IACR;AACA,QAAI,UAAU,OAAQ,MAAK,SAAS,OAAO,OAAO,YAAY;AAC9D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,OAAsB;AAC7B,QAAI,iBAAiB,aAAa,iBAAiB,kBAAmB;AACtE,QAAI,KAAK,WAAW,aAAa,gBAAgB,KAAK,EAAG;AACzD,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,SAAS,IAAoC;AAC3C,QAAI,CAAC,MAAM,QAAQ,EAAE,KAAK,GAAG,WAAW,KAAK,GAAG,SAAS,cAAc;AACrE,MAAAD,MAAK,gCAAgC,YAAY,QAAQ;AAAA,IAC3D;AACA,WAAO,GAAG,IAAI,CAAC,QAAiB,UAAU;AACxC,UAAI,OAAO,WAAW,YAAY,WAAW,KAAM,CAAAA,MAAK,MAAM,KAAK,6CAA6C;AAChH,YAAM,EAAE,OAAO,KAAK,gBAAgB,IAAI;AACxC,uBAAiB,OAAO,MAAM,KAAK,SAAS;AAC5C,UAAI,oBAAoB,UAAa,CAAC,kBAAkB,eAAe,GAAG;AACxE,QAAAA,MAAK,MAAM,KAAK,gEAAgE;AAAA,MAClF;AACA,aAAO;AAAA,QACL;AAAA,QACA,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,OAAO;AAAA,QACtC,GAAI,oBAAoB,SAAY,CAAC,IAAI,EAAE,gBAAgB;AAAA,MAC7D;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,cAAc,WAAyB;AACrC,QAAI,KAAK,WAAW,UAAW,CAAAA,MAAK,SAAS,SAAS,8DAA8D;AAAA,EACtH;AAAA,EAEA,KAAK,OAAgB,OAAuB;AAC1C,QAAI,UAAU,OAAW,QAAO,KAAK,SAAS;AAC9C,QAAI,CAAC,iBAAiB,KAAK,EAAG,CAAAA,MAAK,GAAG,KAAK,+CAA4C;AACvF,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,MAAwD;AAClE,QAAI,SAAS,OAAW,QAAO,CAAC;AAChC,QAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,KAAK,KAAK,SAAS,iBAAiB;AAC9E,MAAAA,MAAK,kCAAkC,eAAe,QAAQ;AAAA,IAChE;AACA,WAAO,KAAK,IAAI,CAAC,QAAiB,UAAU;AAC1C,UAAI,OAAO,WAAW,YAAY,WAAW,KAAM,CAAAA,MAAK,QAAQ,KAAK,4BAA4B;AACjG,YAAM,EAAE,OAAO,IAAI,IAAI;AACvB,uBAAiB,OAAO,QAAQ,KAAK,SAAS;AAC9C,aAAO,EAAE,OAAO,KAAK,KAAK,KAAK,KAAK,QAAQ,KAAK,OAAO,EAAE;AAAA,IAC5D,CAAC;AAAA,EACH;AACF;AAEA,SAAS,iBAAiB,UAA6B;AACrD,MAAI,aAAa,OAAW,QAAO,CAAC;AACpC,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW,KAAK,SAAS,SAAS,oBAAoB;AAC7F,IAAAA,MAAK,sCAAsC,kBAAkB,gBAAgB;AAAA,EAC/E;AACA,SAAO,SAAS,IAAI,CAAC,SAAkB,UAAU;AAC/C,QAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,MAAM,GAAI,CAAAA,MAAK,YAAY,KAAK,kCAA+B;AAC/G,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,kBAAkB,WAAsC;AAC/D,MAAI,cAAc,OAAW,QAAO,CAAC;AACrC,MAAI,CAAC,MAAM,QAAQ,SAAS,EAAG,CAAAA,MAAK,wDAAwD;AAC5F,MAAI,UAAU,SAAS,eAAgB,CAAAA,MAAK,0BAA0B,cAAc,UAAU;AAC9F,SAAO,UAAU,IAAI,CAAC,QAAiB,UAAU;AAC/C,UAAM,EAAE,UAAU,IAAI,SAAS,IAAK,OAAO,WAAW,YAAY,WAAW,OAAO,SAAS,CAAC;AAI9F,QAAI,OAAO,OAAO,YAAY,GAAG,KAAK,MAAM,GAAI,CAAAA,MAAK,aAAa,KAAK,2CAAwC;AAC/G,QAAI,OAAO,aAAa,YAAY,SAAS,KAAK,MAAM,IAAI;AAC1D,MAAAA,MAAK,aAAa,KAAK,2CAAwC;AAAA,IACjE;AACA,WAAO,EAAE,UAAU,IAAI,SAAS;AAAA,EAClC,CAAC;AACH;;;ACveO,IAAM,8BAA8B;AAC3C,IAAME,aAAY;AA+FlB,IAAM,UAAU;AAGT,SAAS,gBAAgB,OAAiC;AAC/D,SAAO,OAAO,UAAU,YAAY,QAAQ,KAAK,KAAK;AACxD;AAGO,SAAS,0BAA0B,SAAyB;AACjE,SAAO,oDAAoDA,UAAS,mBAAmB,UAAU,OAAO,CAAC;AAC3G;AAGO,SAAS,0BAA0B,SAAiB,SAAoD;AAC7G,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS,0BAA0B,OAAO;AAAA,IAC1C,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,GAAG;AAAA,EACL;AACF;AAIA,SAASC,MAAK,OAAqC;AACjD,QAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,MAAM,CAAC,IAAI;AAChD,SAAO,OAAO,UAAU,YAAY,UAAU,OAAQ,QAAoB;AAC5E;AAEA,SAASC,WAAU,OAAgB,MAAkC;AACnE,QAAM,OAAOD,MAAK,KAAK,IAAI,IAAI,IAAI,EAAE;AACrC,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,QAAM,UAAU,KAAK,KAAK;AAC1B,SAAO,YAAY,KAAK,SAAY;AACtC;AAGA,SAAS,QAA2C,QAA0D;AAC5G,SAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS,CAAC;AAG7F;AAEA,SAAS,QAAQ,OAA+C;AAC9D,SAAO,UAAU,UAAa,QAAQ,KAAK,KAAK,IAAI,OAAO,KAAK,IAAI;AACtE;AAMO,SAAS,gCAAgC,UAAoD;AAClG,QAAM,eAAe,QAAQ,SAAS,QAAQ,cAAc,EAAE,IAAI,CAAC,SAAS,YAAYA,MAAK,IAAI,KAAK,CAAC,GAAG,QAAQ,CAAC;AACnH,SAAO,EAAE,cAAc,UAAU,SAAS,UAAU,GAAG,iBAAiB,SAAS,GAAG,EAAE;AACxF;AAEA,SAAS,YAAY,MAAe,UAAuD;AACzF,QAAM,SAASA,MAAKA,MAAK,KAAK,YAAY,GAAG,MAAM;AACnD,QAAM,iBAAiB,QAAQA,MAAKA,MAAK,KAAK,aAAa,GAAG,gBAAgB,GAAG,IAAI,EAAE;AAAA,IAAQ,CAAC,SAC9F,QAAQA,MAAK,IAAI,GAAG,aAAa,EAAE,IAAI,CAAC,YAAY,cAAcA,MAAK,OAAO,KAAK,CAAC,GAAG,QAAQ,CAAC;AAAA,EAClG;AACA,SAAO;AAAA,IACL,GAAG,QAAQ;AAAA,MACT,KAAK,QAAQC,WAAU,MAAM,KAAK,CAAC;AAAA,MACnC,WAAWA,WAAU,QAAQ,gBAAgB;AAAA,MAC7C,OAAOA,WAAU,QAAQ,eAAe;AAAA,MACxC,eAAeA,WAAU,QAAQ,uBAAuB;AAAA,MACxD,mBAAmBA,WAAU,QAAQ,2BAA2B;AAAA,MAChE,KAAKA,WAAU,QAAQ,gBAAgB;AAAA,MACvC,QAAQA,WAAU,QAAQ,oBAAoB,KAAKA,WAAU,QAAQ,mBAAmB;AAAA,MACxF,cAAcA,WAAU,QAAQ,cAAc;AAAA,IAChD,CAAC;AAAA,IACD;AAAA,IACA,aAAa,QAAQ,KAAK,WAAW,EAAE,IAAI,CAAC,UAAU,UAAU,OAAO,eAAe,QAAQ,CAAC;AAAA,IAC/F,SAAS,QAAQD,MAAK,KAAK,UAAU,GAAG,MAAM,EAAE,IAAI,CAAC,UAAU,UAAU,OAAO,UAAU,QAAQ,CAAC;AAAA,IACnG,YAAY,QAAQ,KAAK,cAAc,EAAE;AAAA,MAAI,CAAC,UAC5C,QAAQ,EAAE,QAAQC,WAAU,OAAO,QAAQ,GAAG,MAAMA,WAAU,OAAO,MAAM,GAAG,UAAUA,WAAU,OAAO,UAAU,EAAE,CAAC;AAAA,IACxH;AAAA,EACF;AACF;AAEA,SAAS,UAAU,OAAgB,OAAe,UAAgD;AAChG,QAAM,SAASA,WAAU,OAAO,QAAQ;AACxC,MAAI,WAAW,OAAW,OAAMC,WAAU,GAAG,KAAK,eAAe,QAAQ;AACzE,QAAM,QAAQ,QAAQF,MAAK,KAAK,GAAG,IAAI,EAAE,IAAI,CAAC,SAAS,OAAO,IAAI,KAAK,EAAE;AACzE,SAAO,EAAE,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE;AAC1C;AAEA,SAAS,cAAc,SAAkB,UAAyD;AAChG,QAAM,SAASC,WAAU,SAAS,QAAQ;AAC1C,MAAI,WAAW,OAAW,OAAMC,WAAU,4BAA4B,QAAQ;AAC9E,SAAO;AAAA,IACL;AAAA,IACA,GAAG,QAAQ;AAAA,MACT,QAAQD,WAAU,SAAS,QAAQ;AAAA,MACnC,kBAAkBA,WAAU,QAAQ,kBAAkB,MAAM;AAAA,MAC5D,cAAcA,WAAU,SAAS,cAAc,KAAKA,WAAU,QAAQ,kBAAkB,cAAc;AAAA,MACtG,cAAcA,WAAU,SAAS,kBAAkB;AAAA,MACnD,QAAQA,WAAU,QAAQ,gBAAgB,cAAc;AAAA,MACxD,aAAaA,WAAU,QAAQ,qBAAqB,cAAc;AAAA,MAClE,mBAAmBA,WAAU,SAAS,mBAAmB;AAAA,MACzD,iBAAiBA,WAAU,SAAS,iBAAiB;AAAA,MACrD,eAAe,QAAQA,WAAU,SAAS,eAAe,CAAC;AAAA,MAC1D,aAAaA,WAAU,QAAQ,aAAa,IAAI;AAAA,IAClD,CAAC;AAAA,EACH;AACF;AAEA,SAASC,WAAU,QAAgB,UAA2C;AAC5E,SAAO,IAAI,kBAAkB,GAAG,2BAA2B,8BAA8B,MAAM,KAAK;AAAA,IAClG,UAAU;AAAA,IACV,QAAQ,SAAS;AAAA,IACjB,WAAW;AAAA,IACX,KAAK,SAAS;AAAA,EAChB,CAAC;AACH;;;AC7MO,IAAM,qBAAN,MAAyB;AAAA,EACrB;AAAA;AAAA,EAGT,YAAY,SAA6B;AACvC,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,QAAQ,SAAiB,UAAqC,CAAC,GAAwC;AAC3G,QAAI,CAAC,gBAAgB,OAAO,GAAG;AAC7B,YAAM,IAAI,UAAU,4GAAsG;AAAA,IAC5H;AACA,UAAM,WAAW,MAAM,KAAK,SAAS,KAAK,0BAA0B,SAAS,OAAO,CAAC;AACrF,WAAO,gCAAgC,QAAQ;AAAA,EACjD;AACF;;;AC1CO,IAAM,wBAAwB;AACrC,IAAMC,aAAY;AAGX,IAAM,qBAAqB;AAElC,IAAM,eAAe,oBAAI,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,QAAK,MAAG,CAAC;AA6B3D,SAASC,MAAK,SAAwB;AACpC,QAAM,IAAI,UAAU,iBAAiB,OAAO,EAAE;AAChD;AAGO,SAAS,oBAAoB,SAAyB;AAC3D,SAAO,6BAA6BD,UAAS,oFAAoF,UAAU,OAAO,CAAC;AACrJ;AAOO,SAAS,aAAa,SAAyB;AACpD,UAAQ,QAAQ,KAAK,EAAE,MAAM,SAAS,EAAE,CAAC,KAAK,IAAI,MAAM,GAAG,CAAC;AAC9D;AAMO,SAAS,mBAAmB,SAAyB;AAC1D,MAAI,SAAS;AACb,aAAW,QAAQ,QAAS,WAAU,aAAa,IAAI,IAAI,IAAI,IAAI;AACnE,SAAO;AACT;AAGO,SAAS,oBAAoB,SAAiB,SAA8C;AACjG,MAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,MAAM,GAAI,CAAAC,MAAK,uDAAoD;AACnH,QAAM,SAAS,mBAAmB,OAAO;AACzC,MAAI,SAAS,oBAAoB;AAC/B,IAAAA,MAAK,gBAAgB,MAAM,sBAAmB,kBAAkB,4FAAmF;AAAA,EACrJ;AACA,QAAM,EAAE,aAAa,OAAO,GAAG,eAAe,IAAI;AAClD,MAAI,OAAO,eAAe,UAAW,CAAAA,MAAK,gCAAgC;AAC1E,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS,oBAAoB,OAAO;AAAA,IACpC;AAAA,IACA,WAAW;AAAA,IACX,GAAG;AAAA,EACL;AACF;AAOO,SAAS,0BAA0B,UAA8C;AACtF,MAAI,SAAS,gBAAgB,qBAAqB;AAChD,UAAM,IAAI,kBAAkB,GAAG,qBAAqB,8BAA8B,SAAS,WAAW,KAAK;AAAA,MACzG,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,WAAW;AAAA,MACX,KAAK,SAAS;AAAA,IAChB,CAAC;AAAA,EACH;AACA,SAAO;AAAA,IACL,MAAM,QAAQ,iBAAiB,SAAS,GAAG,KAAK,SAAS,SAAS,QAAQ,KAAK;AAAA,IAC/E,UAAU,SAAS;AAAA,IACnB,WAAW,SAAS;AAAA,IACpB,GAAG,iBAAiB,SAAS,GAAG;AAAA,EAClC;AACF;;;ACtFA,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AASf,IAAM,cAA6B,uBAAO,2BAA2B;AAE5E,SAASC,MAAK,SAAwB;AACpC,QAAM,IAAI,UAAU,iBAAiB,OAAO,EAAE;AAChD;AAQA,IAAM,sBAAkE,oBAAI,IAAI;AAAA,EAC9E,CAAC,4BAA4B,OAAO;AAAA,EACpC,CAAC,uBAAuB,SAAS;AAAA,EACjC,CAAC,8BAA8B,SAAS;AAAA,EACxC,CAAC,6BAA6B,SAAS;AAAA,EACvC,CAAC,wBAAwB,SAAS;AACpC,CAAC;AAMD,IAAM,mBAAuD,oBAAI,IAAI,CAAC,SAAS,SAAS,CAAC;AAGlF,SAAS,eAAe,OAAgB,SAAuD;AACpG,MAAI,EAAE,iBAAiB,sBAAsB,iBAAiB,kBAAmB,QAAO;AACxF,MAAI,MAAM,aAAa,UAAU,MAAM,SAAS,OAAW,QAAO;AAClE,QAAM,OAAO,oBAAoB,IAAI,MAAM,IAAI;AAC/C,MAAI,SAAS,UAAc,YAAY,UAAa,CAAC,QAAQ,IAAI,IAAI,EAAI,QAAO;AAChF,SAAO,IAAI,kBAAkB,MAAM,SAAS;AAAA,IAC1C;AAAA,IACA,MAAM,MAAM;AAAA,IACZ,WAAW,MAAM;AAAA,IACjB,KAAK,MAAM;AAAA,IACX,OAAO,MAAM;AAAA,IACb,GAAI,MAAM,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,OAAO;AAAA,EAC/D,CAAC;AACH;AAaO,IAAM,qBAAqB,KAAK;AAQhC,IAAM,eAAN,MAAmB;AAAA;AAAA,EAEf;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,QAAQ;AAAA,EACR;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA,gBAAgB,KAAK,IAAI;AAAA,EACzB;AAAA;AAAA,EAEA;AAAA,EAEA,OAAO;AAGL,wBAAoB,KAAK,WAAY,OAAqC,YAAY;AAAA,EACxF;AAAA;AAAA,EAGA,YAAY,UAMT;AACD,SAAK,aAAa,SAAS;AAC3B,SAAK,OAAO,SAAS;AACrB,SAAK,kBAAkB,SAAS;AAChC,SAAK,YAAY,EAAE,qBAAqB,SAAS,MAAM;AACvD,SAAK,QAAQ,IAAI,gBAAgB;AAAA,MAC/B,MAAM,CAAC,YAAY,KAAK,WAAW,EAAE,OAAO;AAAA,MAC5C,KAAK,SAAS;AAAA,MACd,KAAK,SAAS,UAAU;AAAA,IAC1B,CAAC;AACD,SAAK,cAAc,IAAI,mBAAmB,EAAE,MAAM,CAAC,YAAY,KAAK,WAAW,EAAE,OAAO,EAAE,CAAC;AAC3F,QAAI,SAAS,UAAW,MAAK,mBAAmB,kBAAkB;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,SAAiB;AACnB,WAAO,KAAK,QAAQ,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,aAAa;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,UAA0B,CAAC,GAAkB;AACtD,sBAAkB,MAAM,KAAK,WAAW,EAAE,EAAE,GAAG,YAAY,GAAG,GAAG,QAAQ,CAAC,CAAC;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,SAAiB,UAA+B,CAAC,GAAkC;AAC/F,UAAM,UAAU,oBAAoB,SAAS,OAAO;AACpD,SAAK,WAAW,IAAI,KAAK,SAAS,yBAAyB,EAAE,SAAS,aAAa,OAAO,EAAE,CAAC;AAC7F,WAAO,0BAA0B,MAAM,KAAK,WAAW,EAAE,OAAO,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAA0B,CAAC,GAAkB;AACjD,QAAI,KAAK,aAAa,OAAW,QAAO,KAAK;AAC7C,QAAI,KAAK,SAAS,KAAK,mBAAmB,QAAW;AACnD,aAAO,QAAQ,OAAO,IAAI,UAAU,4BAA4B,CAAC;AAAA,IACnE;AACA,SAAK,eAAe;AACpB,QAAI,KAAK,cAAc,QAAW;AAChC,WAAK,WAAW,QAAQ,QAAQ;AAChC,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,SAAS,KAAK,kBAAkB,QAAQ,QAAQ;AACtD,SAAK,WAAW,OAAO,KAAK,MAAM,KAAK,WAAW,OAAO,CAAC;AAC1D,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,OAAO,WAAW,EAAE,SAAgD;AAClE,QAAI,KAAK,mBAAmB,UAAa,KAAK,aAAa,OAAW,OAAM,KAAK;AACjF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B;AAAA,EAEA,MAAM,MAAM,SAAgD;AAC1D,QAAI,KAAK,aAAa,OAAW,CAAAA,MAAK,gBAAgB;AACtD,QAAI,KAAK,cAAc,QAAW;AAChC,YAAM,IAAI,UAAU,mCAAmC,KAAK,UAAU,IAAI,KAAK,EAAE,OAAO,KAAK,UAAU,CAAC;AAAA,IAC1G;AACA,QAAI,KAAK,MAAO,CAAAA,MAAK,cAAc;AACnC,SAAK,QAAQ;AACb,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,WAAW,QAAQ,EAAE,GAAG,SAAS,GAAG,KAAK,gBAAgB,EAAE,CAAC;AACxF,WAAK,OAAO;AACZ,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,aAAa,KAAK,EAAG,MAAK,OAAO;AACrC,YAAM,KAAK,cAAc,KAAK;AAAA,IAChC,UAAE;AACA,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAAwC;AACvD,QAAI,KAAK,cAAc,OAAW;AAElC,UAAM,EAAE,cAAc,UAAU,GAAG,aAAa,IAAI;AACpD,SAAK,QAAQ;AACb,QAAI;AACF,YAAM,KAAK,WAAW,QAAQ;AAAA,QAC5B,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,SAAS,gEAAgE,UAAU,KAAK,IAAI,CAAC;AAAA,QAC7F,GAAG,KAAK,gBAAgB;AAAA;AAAA,QAExB,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,GAAG;AAAA,MACL,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,KAAK,cAAc,KAAK;AAAA,IAChC,UAAE;AACA,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,WAAW,IAAI,KAAK,QAAQ,uBAAuB,EAAE,gBAAgB,KAAK,KAAK,CAAC;AAAA,EACvF;AAAA;AAAA,EAGA,cAAc,OAAyB;AACrC,UAAM,SAAS,eAAe,KAAK;AACnC,QAAI,kBAAkB,mBAAmB;AACvC,WAAK,YAAY;AACjB,WAAK,eAAe;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,SAAe;AACb,SAAK,gBAAgB,KAAK,IAAI;AAAA,EAChC;AAAA,EAEA,kBAA8E;AAC5E,WAAO,EAAE,OAAO,KAAK,MAAM,gBAAgB,KAAK,iBAAiB,UAAU,KAAK,UAAU;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,SAAuB;AACxC,UAAM,QAAQ,WAAW,MAAM,KAAK,aAAa,GAAG,OAAO;AAE3D,IAAC,MAAiC,QAAQ;AAC1C,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,eAAqB;AACnB,SAAK,kBAAkB;AACvB,QAAI,KAAK,aAAa,UAAa,KAAK,cAAc,OAAW;AACjE,QAAI,KAAK,OAAO;AACd,WAAK,mBAAmB,kBAAkB;AAC1C;AAAA,IACF;AACA,UAAM,YAAY,qBAAqB,KAAK;AAC5C,QAAI,YAAY,GAAG;AACjB,WAAK,mBAAmB,SAAS;AACjC;AAAA,IACF;AACA,SAAK,iBAAiB,KAAK,MAAM,YAAY,CAAC,EAAE;AAAA,MAC9C,MAAM;AACJ,YAAI,KAAK,aAAa,UAAa,KAAK,cAAc,OAAW,MAAK,mBAAmB,kBAAkB;AAAA,MAC7G;AAAA,MACA,CAAC,UAAmB;AAClB,aAAK,WAAW,IAAI,KAAK,QAAQ,iCAAiC,EAAE,MAAM,CAAC;AAAA,MAC7E;AAAA,IACF;AACA,SAAK,KAAK,eAAe,QAAQ,MAAM;AACrC,WAAK,iBAAiB;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEA,iBAAuB;AACrB,QAAI,KAAK,oBAAoB,OAAW,cAAa,KAAK,eAAe;AACzE,SAAK,kBAAkB;AAAA,EACzB;AACF;AAMA,SAAS,cAA8B;AACrC,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,aAAa,GAAG;AACnE,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS,sBAAsB,kBAAkB,gBAAgB,SAAS;AAAA,IAC1E,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AACF;AAEA,IAAM,qBAAqB;AAO3B,SAAS,kBAAkB,UAA8B;AACvD,QAAM,SAAS,QAAQ,SAAS,QAAQ,MAAM,EAAE,CAAC;AACjD,QAAM,QAAQ,QAAQ,QAAQ,KAAK,EAAE,CAAC;AACtC,MAAI,UAAU,QAAW;AACvB,UAAM,OAAQ,MAAkC,OAAO;AACvD,UAAM,OAAO,OAAO,KAAK,GAAG,KAAK;AACjC,UAAM,IAAI,kBAAkB,6BAA6B,OAAO,KAAK,IAAI,KAAK,EAAE,IAAI;AAAA,MAClF,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,GAAI,OAAO,SAAS,YAAY,SAAS,MAAM,EAAE,MAAM,KAAK;AAAA,MAC5D,WAAW;AAAA,MACX,KAAK,SAAS;AAAA,IAChB,CAAC;AAAA,EACH;AACA,MAAI,SAAS,gBAAgB,gBAAgB,EAAE,aAAa,SAAS,UAAU;AAC7E,UAAM,IAAI,kBAAkB,0DAA0D;AAAA,MACpF,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,WAAW;AAAA,MACX,KAAK,SAAS;AAAA,IAChB,CAAC;AAAA,EACH;AACF;AAMA,SAAS,aAAa,OAAyB;AAC7C,MAAI,EAAE,iBAAiB,YAAa,QAAO;AAC3C,SAAO,EAAE,iBAAiB,qBAAqB,MAAM,WAAW;AAClE;AAGO,SAAS,oBAAoB,QAAgB,QAAkC;AACpF,MAAI,WAAW,OAAW;AAC1B,SAAO,eAAe,QAAQ,QAAQ;AAAA,IACpC,QAAyC;AACvC,aAAO,KAAK,MAAM;AAAA,IACpB;AAAA,IACA,cAAc;AAAA,IACd,UAAU;AAAA,EACZ,CAAC;AACH;AAGO,SAAS,qBAAqB,aAA2E;AAC9G,QAAM,MAAM,gCAAgC,UAAU,YAAY,YAAY,CAAC;AAC/E,SAAO,YAAY,YAAY,UAC3B,2BAA2B,aAAa,qBAAqB,GAAG,uBAChE,2BAA2B,aAAa,4CAA4C,GAAG;AAC7F;AAEA,SAAS,cAAc,aAA+C;AACpE,QAAM,EAAE,UAAU,UAAU,cAAc,QAAQ,UAAU,aAAa,IAAI;AAC7E,SAAO;AAAA,IACL,eAAe;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,MAC7C,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA,IACvD;AAAA,EACF;AACF;AAMA,eAAsB,YACpB,WACA,aACA,UAA8B,CAAC,GACR;AACvB,QAAM,EAAE,YAAY,OAAO,GAAG,eAAe,IAAI;AACjD,MAAI,OAAO,cAAc,UAAW,CAAAA,MAAK,+BAA+B;AACxE,QAAM,iBAAiB,WAAW,OAAO,WAAW;AACpD,QAAM,UAAuB;AAAA,IAC3B,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS,qBAAqB,WAAW;AAAA,IACzC,OAAO,YAAY;AAAA,IACnB;AAAA,IACA,UAAU,cAAc,WAAW;AAAA,IACnC,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,WAAW;AAAA,IACX,GAAG;AAAA,EACL;AACA,QAAM,WAAW,MAAM,UAAU,QAAQ,OAAO,EAAE,MAAM,CAAC,UAAmB;AAC1E,UAAM,eAAe,OAAO,gBAAgB;AAAA,EAC9C,CAAC;AAED,QAAM,SAAS,SAAS,QAAQ,SAAS;AACzC,MAAI,OAAO,WAAW,YAAY,WAAW,YAAY;AACvD,UAAM,IAAI,kBAAkB,6CAA6C,MAAM,IAAI;AAAA,MACjF,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACA,MAAI,SAAS,kBAAkB,QAAW;AACxC,UAAM,IAAI,kBAAkB,2DAA2D;AAAA,MACrF,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAGA,YAAU,IAAI,KAAK,QAAQ,sBAAsB;AAAA,IAC/C,SAAS,YAAY;AAAA,IACrB,gBAAgB,YAAY;AAAA,EAC9B,CAAC;AACD,SAAO,IAAI,aAAa;AAAA,IACtB;AAAA,IACA,KAAK,YAAY;AAAA,IACjB;AAAA,IACA,OAAO,SAAS;AAAA,IAChB;AAAA,EACF,CAAC;AACH;;;AC1bO,IAAM,cAAN,MAAkB;AAAA,EACd;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,YAAY,QAAqB;AAC/B,SAAK,UAAU,cAAc,MAAM;AACnC,SAAK,WAAW,OAAO,OAAO,0BAA0B,KAAK,QAAQ,WAAW,CAAC;AACjF,SAAK,aAAa,IAAI,cAAc,KAAK,OAAO;AAAA,EAClD;AAAA,EAEA,IAAI,cAAgC;AAClC,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA,EAGA,IAAI,UAAkB;AACpB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,UAA8B,CAAC,GAA0B;AACnE,WAAO,YAAY,KAAK,YAAY,KAAK,UAAU,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAe,UAA6D;AAChF,UAAM,UAAU,MAAM,KAAK,YAAY;AACvC,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,SAAS,OAAO;AAAA,IACjC,SAAS,OAAO;AACd,YAAM,KAAK,cAAc,OAAO;AAChC,YAAM;AAAA,IACR;AACA,UAAM,KAAK,cAAc,OAAO;AAChC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,SAAsC;AACxD,QAAI;AACF,YAAM,QAAQ,MAAM;AAAA,IACtB,SAAS,OAAO;AACd,WAAK,WAAW,IAAI,KAAK,QAAQ,6BAA6B,EAAE,MAAM,CAAC;AAAA,IACzE;AAAA,EACF;AACF;;;ACtBA,IAAM,iBAAiB;AAEvB,SAASC,MAAK,SAAwB;AACpC,QAAM,IAAI,UAAU,iBAAiB,OAAO,EAAE;AAChD;AAEA,SAASC,eAAc,OAAgB,OAAwC;AAC7E,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,GAAI,CAAAD,MAAK,GAAG,KAAK,gDAA6C;AAClH;AAYO,SAAS,iBAAiB,SAA2E;AAC1G,MAAI,OAAO,YAAY,YAAY,YAAY,KAAM,CAAAA,MAAK,mCAAmC;AAE7F,QAAM,cAAgC,QAAQ,eAAe;AAC7D,MAAI,gBAAgB,QAAQ,gBAAgB,MAAM;AAChD,IAAAA,MAAK,+CAA+C,KAAK,UAAU,WAAW,CAAC,GAAG;AAAA,EACpF;AAEA,QAAM,EAAE,MAAM,KAAK,UAAU,UAAU,aAAa,IAAI;AACxD,QAAM,SAAS,QAAQ,UAAU;AACjC,EAAAC,eAAc,MAAM,MAAM;AAC1B,EAAAA,eAAc,UAAU,UAAU;AAClC,MAAI,CAAC,iBAAiB,GAAG,EAAG,CAAAD,MAAK,kDAA+C;AAChF,EAAAC,eAAc,QAAQ,QAAQ;AAE9B,MAAI,OAAO,KAAK,MAAM,EAAG,CAAAD,MAAK,qCAAqC;AAEnE,MAAK,aAAa,YAAgB,iBAAiB,SAAY;AAC7D,IAAAA,MAAK,4DAA4D;AAAA,EACnE;AACA,MAAI,gBAAgB,QAAQ,aAAa,QAAW;AAClD,IAAAC,eAAc,UAAU,gBAAgB,OAAO,4CAA4C,UAAU;AACrG,IAAAA,eAAc,cAAc,gBAAgB,OAAO,gDAAgD,cAAc;AAAA,EACnH;AAEA,QAAM,WAAW,gBAAgB,OAAO,GAAG,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,MAAM;AAChG,MAAI,gBAAgB,KAAM,QAAO,EAAE,aAAa,UAAqB,cAA6B,UAAU,SAAS;AACrH,SAAO,aAAa,SAChB,EAAE,aAAa,UAAU,SAAS,IAClC,EAAE,aAAa,UAAU,cAA6B,UAAU,SAAS;AAC/E;;;AC7EA,IAAM,SAAS,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AAElG,IAAM,SAAS;AAGf,IAAM,iBAAiB;AA8BhB,SAAS,gBACd,MACA,eACA,UAAkC,CAAC,GACf;AACpB,QAAM,YAAY,aAAa,aAAa;AAC5C,QAAM,YAAY,QAAQ,aAAa;AACvC,MAAI,cAAc,UAAU,cAAc,WAAW;AACnD,UAAM,IAAI,UAAU,qDAAqD;AAAA,EAC3E;AACA,MAAI,OAAO,SAAS,SAAU,QAAO;AAErC,QAAM,SAAS,cAAc,KAAK,KAAK,EAAE,YAAY,CAAC;AACtD,MAAI,WAAW,OAAW,QAAO;AAEjC,QAAM,OAAO,OAAO,QAAQ,YAAY,OAAO,OAAO,OAAO,KAAK,WAAW,SAAS;AACtF,MAAI,SAAS,UAAa,CAAC,YAAY,MAAM,OAAO,OAAO,OAAO,GAAG,EAAG,QAAO;AAE/E,QAAM,OAAO,GAAG,IAAI,MAAM,CAAC,CAAC,IAAI,IAAI,OAAO,OAAO,CAAC,CAAC,IAAI,IAAI,OAAO,KAAK,CAAC,CAAC;AAC1E,SAAO,OAAO,SAAS,SAAY,OAAO,GAAG,IAAI,IAAI,OAAO,IAAI;AAClE;AAEA,SAAS,cAAc,MAAoC;AAEzD,MAAI,QAAQ,gCAAgC,KAAK,IAAI;AACrD,MAAI,UAAU,MAAM;AAClB,UAAMC,SAAQ,OAAO,QAAQ,MAAM,CAAC,CAAE,IAAI;AAC1C,QAAIA,WAAU,EAAG,QAAO;AACxB,WAAO;AAAA,MACL,GAAI,MAAM,CAAC,MAAM,UAAa,EAAE,MAAM,MAAO,OAAO,MAAM,CAAC,CAAC,EAAE;AAAA,MAC9D,OAAAA;AAAA,MACA,KAAK,OAAO,MAAM,CAAC,CAAC;AAAA,IACtB;AAAA,EACF;AAGA,UAAQ,sDAAsD,KAAK,IAAI;AACvE,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,CAAC,EAAE,MAAM,OAAO,KAAK,OAAO,OAAO,IAAI;AAC7C,MAAI,UAAU,WAAc,OAAO,KAAK,IAAI,MAAM,OAAO,OAAO,IAAI,IAAK,QAAO;AAChF,SAAO;AAAA,IACL,GAAI,SAAS,UAAa,EAAE,MAAM,OAAO,IAAI,EAAE;AAAA,IAC/C,OAAO,OAAO,KAAK;AAAA,IACnB,KAAK,OAAO,GAAG;AAAA,IACf,GAAI,UAAU,UAAa,EAAE,MAAM,GAAG,KAAK,IAAI,OAAO,GAAG;AAAA,EAC3D;AACF;AAGA,SAAS,YAAY,OAAe,KAAa,WAAmB,WAA8B;AAChG,QAAM,OAAO,IAAI,KAAK,SAAS,EAAE,eAAe;AAEhD,MAAI,cAAc,QAAQ;AAExB,aAAS,YAAY,MAAM,aAAa,OAAO,GAAG,aAAa;AAC7D,UAAI,YAAY,WAAW,OAAO,GAAG,KAAK,UAAU,WAAW,OAAO,GAAG,KAAK,UAAW,QAAO;AAAA,IAClG;AACA,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,aAAW,aAAa,CAAC,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG;AAClD,QAAI,CAAC,YAAY,WAAW,OAAO,GAAG,EAAG;AACzC,UAAM,WAAW,KAAK,IAAI,UAAU,WAAW,OAAO,GAAG,IAAI,SAAS;AAEtE,QAAI,SAAS,UAAa,WAAW,KAAK,SAAU,QAAO,EAAE,MAAM,WAAW,SAAS;AAAA,EACzF;AACA,SAAO,SAAS,UAAa,KAAK,YAAY,iBAAiB,SAAS,KAAK,OAAO;AACtF;AAMO,SAAS,aAAa,eAAsC;AACjE,MAAI,yBAAyB,MAAM;AACjC,UAAM,OAAO,cAAc,QAAQ;AACnC,QAAI,OAAO,MAAM,IAAI,EAAG,OAAM,IAAI,UAAU,oDAAiD;AAC7F,WAAO,QAAU,OAAO,SAAU,UAAU;AAAA,EAC9C;AACA,MAAI,OAAO,kBAAkB,UAAU;AACrC,UAAM,QAAQ,oCAAoC,KAAK,cAAc,KAAK,CAAC;AAC3E,QAAI,UAAU,MAAM;AAClB,YAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,MAAM,CAAC,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC,CAAC;AAChF,UAAI,YAAY,MAAM,OAAO,GAAG,EAAG,QAAO,UAAU,MAAM,OAAO,GAAG;AAAA,IACtE;AAAA,EACF;AACA,QAAM,IAAI,UAAU,mFAAgF;AACtG;AAEA,SAAS,UAAU,MAAc,OAAe,KAAqB;AACnE,QAAM,OAAO,oBAAI,KAAK,CAAC;AACvB,OAAK,eAAe,MAAM,QAAQ,GAAG,GAAG;AACxC,SAAO,KAAK,QAAQ;AACtB;AAEA,SAAS,YAAY,MAAc,OAAe,KAAsB;AACtE,MAAI,QAAQ,KAAK,QAAQ,MAAM,MAAM,EAAG,QAAO;AAC/C,QAAM,OAAO,oBAAI,KAAK,CAAC;AACvB,OAAK,eAAe,MAAM,QAAQ,GAAG,GAAG;AACxC,SAAO,KAAK,YAAY,MAAM,QAAQ,KAAK,KAAK,WAAW,MAAM;AACnE;AAEA,SAAS,IAAI,OAAe,QAAwB;AAClD,SAAO,OAAO,KAAK,EAAE,SAAS,QAAQ,GAAG;AAC3C;;;AC1CA,IAAM,UAAU;AAChB,IAAM,iBAAiB;AACvB,IAAM,kBAAkB;AACxB,IAAM,YAAY;AAClB,IAAM,cACJ;AACF,IAAM,gBAAgB;AACtB,IAAM,gBACJ;AACF,IAAM,eAAe;AACrB,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AACxB,IAAM,WAAW;AACjB,IAAM,cAAc;AACpB,IAAM,SAAS;AACf,IAAM,WAAW;AACjB,IAAM,YAAY;AAGlB,IAAM,QAAQ,EAAE,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,EAAE;AAqB1D,SAAS,oBAAoB,OAA0B,SAAgD;AAC5G,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,OAAM,IAAI,UAAU,kDAAkD;AACjG,MAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AACnD,UAAM,IAAI,UAAU,mFAAgF;AAAA,EACtG;AACA,QAAM,EAAE,cAAc,IAAI;AAC1B,eAAa,aAAa;AAE1B,QAAM,SAAyB,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC,GAAG,UAAU,CAAC,GAAG,UAAU,CAAC,EAAE;AAC1F,QAAM,iBAAiB,mBAAmB,KAAK;AAC/C,MAAI,QAAe,MAAM;AACzB,MAAI,cAAc;AAElB,QAAM,QAAQ,CAAC,OAAO,UAAU;AAC9B,UAAM,OAAO,OAAO,UAAU,WAAW,QAAQ;AACjD,QAAI,KAAK,KAAK,MAAM,GAAI;AAExB,QAAI,UAAU,gBAAgB;AAC5B,aAAO,eAAe,EAAE,GAAG,OAAO,cAAc,GAAG,eAAe,MAAM,aAAa,EAAE;AACvF;AAAA,IACF;AAEA,QAAI,aAAa;AACf,YAAM,QAAQ,gBAAgB,KAAK,IAAI;AACvC,UAAI,UAAU,MAAM;AAClB,cAAM,SAAS,oBAAoB,OAAO,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,GAAI,aAAa;AAC7E,YAAI,WAAW,OAAW,QAAO,SAAS,KAAK,IAAI;AAAA,YAC9C,QAAO,UAAW,QAAQ,KAAK,MAAM;AAC1C;AAAA,MACF;AACA,oBAAc;AAAA,IAChB;AAEA,QAAI,iBAAiB,KAAK,IAAI,GAAG;AAC/B,cAAQ,MAAM;AACd,oBAAc;AACd,aAAO,cAAc,EAAE,SAAS,CAAC,GAAG,QAAQ,MAAM;AAClD;AAAA,IACF;AAEA,UAAM,WAAW,SAAS,KAAK,IAAI;AACnC,QAAI,aAAa,MAAM;AACrB,cAAQ,MAAM;AACd,aAAO,eAAe,EAAE,GAAG,OAAO,cAAc,GAAI,SAAS,CAAC,MAAM,MAAM,EAAE,MAAM,SAAS,CAAC,EAAG,EAAG;AAClG;AAAA,IACF;AAEA,QAAI,UAAU,MAAM,UAAU;AAC5B,YAAM,UAAU,QAAQ,KAAK,IAAI;AACjC,UAAI,YAAY,MAAM;AACpB,eAAO,SAAS,KAAK,EAAE,iBAAiB,OAAO,QAAQ,CAAC,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAG,CAAC;AAC/E;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,MAAM,cAAc,eAAe,KAAK,IAAI,GAAG;AAC1D,YAAM,aAAa,gBAAgB,IAAI;AACvC,UAAI,eAAe,QAAW;AAC5B,gBAAQ,MAAM;AACd,eAAO,WAAW,KAAK,GAAG,UAAU;AACpC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,MAAM,UAAU;AAC3B,UAAI,aAAa,KAAK,IAAI,GAAG;AAC3B,gBAAQ,MAAM;AACd;AAAA,MACF;AACA,YAAM,UAAU,aAAa,MAAM,aAAa;AAChD,UAAI,YAAY,QAAW;AACzB,gBAAQ,MAAM;AACd,eAAO,SAAS,KAAK,OAAO;AAC5B;AAAA,MACF;AAAA,IACF;AAEA,WAAO,SAAS,KAAK,IAAI;AAAA,EAC3B,CAAC;AAED,MAAI,OAAO,cAAc,QAAW;AAClC,WAAO,UAAU,SAAS,OAAO,UAAU,QAAQ,KAAK,CAAC,UAAU,MAAM,iBAAiB,MAAS;AAAA,EACrG;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,MAAqD;AAC5E,QAAM,aAAwC,CAAC;AAC/C,aAAW,QAAQ,KAAK,KAAK,EAAE,MAAM,eAAe,GAAG;AACrD,UAAM,QAAQ,UAAU,KAAK,IAAI;AACjC,QAAI,UAAU,KAAM,QAAO;AAC3B,UAAM,CAAC,EAAE,YAAY,SAAS,WAAW,UAAU,IAAI;AACvD,eAAW,KAAK;AAAA,MACd;AAAA,MACA,SAAS,QAAS,KAAK;AAAA,MACvB,GAAI,cAAc,UAAa,cAAc,MAAM,EAAE,UAAU;AAAA,MAC/D,GAAI,eAAe,UAAa,eAAe,MAAM,EAAE,WAAW;AAAA,MAClE,MAAM,KAAK,MAAM,WAAY,MAAM,EAAE,KAAK;AAAA,IAC5C,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,aAAa,MAAc,eAAiE;AACnG,QAAM,MAAM,YAAY,KAAK,IAAI;AACjC,MAAI,QAAQ,MAAM;AAChB,UAAM,CAAC,EAAEC,SAAQ,aAAa,cAAc,cAAcC,OAAM,MAAM,IAAIC,SAAQC,WAAU,IAAI,IAAI;AACpG,UAAM,QAAQ,cAAc,KAAK,IAAK;AACtC,UAAM,gBAAgB,UAAU,OAAO,SAAY,SAAS,MAAM,CAAC,CAAE;AACrE,UAAM,cAAc,UAAU,OAAO,SAAY,SAAS,MAAM,CAAC,CAAE;AACnE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,OAAOH,OAAM;AAAA,MACrB,GAAG,SAASC,OAAO,aAAa;AAAA,MAChC,QAAQC;AAAA,MACR,UAAU,OAAOC,SAAQ;AAAA,MACzB;AAAA,MACA,cAAc,OAAO,YAAY;AAAA,MACjC;AAAA,MACA,iBAAiB;AAAA,MACjB,eAAe;AAAA,MACf,GAAI,kBAAkB,UAAa,EAAE,cAAc;AAAA,MACnD,GAAI,gBAAgB,UAAa,EAAE,YAAY;AAAA,MAC/C,MAAM,KAAK,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,QAAQ,cAAc,KAAK,IAAI;AACrC,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,CAAC,EAAE,QAAQ,aAAa,YAAY,MAAM,QAAQ,QAAQ,IAAI;AACpE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,OAAO,MAAM;AAAA,IACrB,GAAG,SAAS,MAAO,aAAa;AAAA,IAChC;AAAA,IACA,UAAU,OAAO,QAAQ;AAAA,IACzB;AAAA,IACA;AAAA,IACA,MAAM,KAAK,KAAK;AAAA,EAClB;AACF;AAEA,SAAS,oBACP,QACA,MACA,eAC0C;AAC1C,QAAM,WAAW,SAAS,KAAK,IAAI;AACnC,MAAI,aAAa,MAAM;AACrB,UAAM,CAAC,EAAE,MAAM,gBAAgB,SAAS,IAAI;AAC5C,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAA,MACN,GAAI,SAAS,UAAa,SAAS,MAAM,aAAa;AAAA,MACtD,GAAI,mBAAmB,UAAa,EAAE,eAAe;AAAA,MACrD,GAAI,cAAc,UAAa,EAAE,UAAU;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAc,YAAY,KAAK,IAAI;AACzC,MAAI,gBAAgB,MAAM;AACxB,UAAM,CAAC,EAAE,MAAM,gBAAgB,IAAI,IAAI;AACvC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,GAAI,SAAS,UAAa,SAAS,MAAM,aAAa;AAAA,MACtD,GAAI,mBAAmB,UAAa,EAAE,eAAe;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,OAAO,KAAK,IAAI;AAC/B,MAAI,WAAW,KAAM,QAAO,EAAE,QAAQ,MAAM,OAAO,CAAC,GAAI,cAAc,OAAO,CAAC,GAAI,KAAK;AACvF,SAAO;AACT;AAGA,SAAS,mBAAmB,OAAkC;AAC5D,WAAS,QAAQ,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS;AACtD,UAAM,OAAO,MAAM,KAAK;AACxB,QAAI,OAAO,SAAS,YAAY,UAAU,KAAK,IAAI,EAAG,QAAO;AAAA,EAC/D;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAAc,eAA0D;AAC9F,QAAM,CAAC,EAAE,gBAAgB,MAAM,OAAO,SAAS,MAAM,OAAO,IAAI,UAAU,KAAK,IAAI;AACnF,QAAM,YAAY,iBAAiB,KAAK,IAAK,IAAI,CAAC;AAClD,QAAM,MAAM,OAAO,KAAK,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,gBAAgB,MAAO,aAAa,IAAI;AACnG,SAAO;AAAA,IACL;AAAA,IACA,GAAI,cAAc,UAAa,EAAE,UAAU;AAAA,IAC3C,GAAI,QAAQ,UAAa,EAAE,YAAY,GAAG,GAAG,IAAI,KAAK,IAAI,OAAO,GAAG;AAAA,IACpE;AAAA,EACF;AACF;AAEA,SAAS,SAAS,MAAc,eAAiD;AAC/E,QAAM,OAAO,gBAAgB,MAAM,eAAe,EAAE,WAAW,UAAU,CAAC;AAC1E,SAAO,SAAS,SAAY,CAAC,IAAI,EAAE,KAAK;AAC1C;AAMA,SAAS,SAAS,MAAkC;AAClD,QAAM,QAAQ,8BAA8B,KAAK,IAAI;AACrD,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,QAAQ,OAAO,MAAM,CAAC,CAAC;AAC3B,QAAM,UAAU,OAAO,MAAM,CAAC,CAAC;AAC/B,QAAM,SAAS,MAAM,CAAC;AACtB,MAAI,UAAU,GAAI,QAAO;AACzB,MAAI,WAAW,QAAW;AACxB,QAAI,QAAQ,GAAI,QAAO;AAAA,EACzB,OAAO;AACL,QAAI,QAAQ,KAAK,QAAQ,GAAI,QAAO;AACpC,QAAI,WAAW,OAAO,WAAW,IAAK,UAAS;AAAA,aACtC,WAAW,IAAK,SAAS,QAAQ,KAAM;AAAA,aACvC,UAAU,GAAI,QAAO;AAAA,EAChC;AACA,SAAO,GAAG,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,OAAO,EAAE,SAAS,GAAG,GAAG,CAAC;AAC9E;;;ACvWA,IAAMC,UAAS,oBAAI,IAAI,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,CAAC;AAO3G,IAAM,SAAS;AAYR,SAAS,sBAAsB,MAAuC;AAC3E,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,QAAM,QAAQ,OAAO,KAAK,KAAK,KAAK,CAAC;AACrC,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,CAAC,EAAE,KAAK,KAAK,OAAO,WAAW,OAAO,IAAI;AAChD,QAAMC,aAAY,OAAO,GAAG;AAC5B,MAAIA,aAAY,KAAKA,aAAY,MAAM,CAACD,QAAO,IAAI,KAAK,EAAG,QAAO;AAClE,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,MAAM,OAAO,OAAO;AAC1B,MAAI,QAAQ,oBAAoB,CAAC,kBAAkB,GAAG,EAAG,QAAO;AAChE,SAAO,EAAE,KAAK,MAAM,GAAG,GAAG,GAAG,KAAK,IAAI,OAAO,IAAI;AACnD;;;ACXO,SAAS,6BAA6B,QAAoE;AAC/G,QAAM,EAAE,OAAO,WAAW,UAAU,MAAM,aAAa,IAAI;AAC3D,QAAM,UAAU,iBAAiB,OAAO,SAAS;AAEjD,QAAM,WAAW,QAAQ;AAAA,IACvB,CAAC,EAAE,UAAU,eAAe,aAAa,YAAY,GAAG,MAA4B;AAClF,YAAM,EAAE,QAAQ,IAAI;AACpB,YAAM,YACJ,QAAQ,cAAc,WACrB,QAAQ,cAAc,QAAQ,aAC5B,QAAQ,0BAA0B,UAAa,QAAQ,0BAA0B,QAAQ;AAC9F,aAAO;AAAA,QACL,IAAI,UAAU,CAAC;AAAA,QACf,oBAAoB,QAAQ;AAAA,QAC5B,qBAAqB,QAAQ;AAAA,QAC7B,sBAAsB,SAAS,UAAU;AAAA,QACzC,oBAAoB,SAAS,QAAQ;AAAA,QACrC;AAAA,QACA,eAAe,SAAS,UAAU,KAAK,MAAM,GAAG,CAAC;AAAA,QACjD;AAAA,QACA,aAAa,SAAS,QAAQ,KAAK,MAAM,GAAG,CAAC;AAAA,QAC7C,kBAAkB;AAAA,QAClB,GAAI,YAAY,EAAE,sBAAsB,QAAQ,UAAW,IAAI,CAAC;AAAA,QAChE,GAAI,aAAa,QAAQ,0BAA0B,SAC/C,EAAE,uBAAuB,QAAQ,sBAAsB,IACvD,CAAC;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,UAAU,mBAAmB,CAAC,GAAG;AAC9C,MAAI,SAAS,QAAW;AACtB,UAAM,IAAI,UAAU,wDAAwD;AAAA,EAC9E;AACA,QAAM,iBAAiB,oBAAI,IAA+B;AAC1D,QAAM,aAAuC,CAAC;AAC9C,aAAW,EAAE,cAAc,KAAK,KAAK,mBAAmB;AACtD,UAAM,yBAAwF,CAAC;AAC/F,QAAI,OAAO;AACX,eAAW,aAAa,cAAc,kBAAkB,CAAC,GAAG;AAC1D,YAAM,kBAAkB,KAAK,UAAU,EAAE;AACzC,UAAI,CAAC,eAAe,IAAI,eAAe,EAAG,gBAAe,IAAI,iBAAiB,cAAc,iBAAiB,SAAS,CAAC;AACvH,iBAAW,EAAE,QAAQ,KAAK,UAAU,YAAY,CAAC,GAAG;AAClD,cAAME,UAAS,SAAS,IAAI;AAC5B,YAAIA,YAAW,OAAW;AAC1B,YAAIA,QAAO,cAAc,UAAa,QAAQ,cAAc,OAAW,CAAAA,QAAO,YAAY,QAAQ;AAClG,+BAAuB,KAAK,EAAE,YAAYA,QAAO,IAAI,kBAAkB,gBAAgB,CAAC;AACxF;AAAA,MACF;AAAA,IACF;AACA,aAAS,IAAI,GAAG,KAAK,cAAc,mBAAmB,IAAI,KAAK;AAC7D,iBAAW,KAAK;AAAA,QACd,IAAI,IAAI,WAAW,SAAS,CAAC;AAAA,QAC7B,eAAe,cAAc;AAAA,QAC7B,GAAI,uBAAuB,WAAW,IAAI,CAAC,IAAI,EAAE,uBAAuB;AAAA,MAC1E,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,QAAQ,QAAQ,SAAS,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM;AAC/D,QAAI,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,KAAK,IAAI,SAAS,QAAQ;AACxD,YAAM,IAAI,UAAU,wCAAwC,CAAC,WAAW,SAAS,MAAM,iBAAiB;AAAA,IAC1G;AACA,WAAO,UAAU,IAAI,CAAC;AAAA,EACxB,CAAC;AACD,MAAI,KAAK,WAAW,GAAG;AACrB,UAAM,IAAI,UAAU,6CAA0C;AAAA,EAChE;AAEA,SAAO;AAAA,IACL,kCAAkC;AAAA,IAClC;AAAA,IACA;AAAA,IACA,GAAI,eAAe,SAAS,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,GAAG,eAAe,OAAO,CAAC,EAAE;AAAA,IACpF,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA,EACvD;AACF;AAEA,SAAS,UAAU,OAAuB;AACxC,SAAO,IAAI,QAAQ,CAAC;AACtB;AAEA,SAAS,cAAc,iBAAyB,WAA6C;AAC3F,QAAM,EAAE,eAAe,kBAAkB,UAAU,YAAY,UAAU,eAAe,IAAI;AAC5F,QAAM,aAAa,YAAY,EAAE,UAAU,YAAY,UAAU,eAAe,CAAC;AACjF,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA,IACX,GAAI,qBAAqB,SAAY,CAAC,IAAI,EAAE,iBAAiB;AAAA,IAC7D,GAAI,OAAO,KAAK,UAAU,EAAE,WAAW,IAAI,CAAC,IAAI,EAAE,WAAW;AAAA,EAC/D;AACF;;;ACnIO,IAAM,UAAU;","names":["isObject","isObject","PATH","PATH","isObject","flight","PATH","flight","isObject","warningOf","PATH","isObject","errorOf","warningOf","isObject","isAbort","describe","node","nonEmpty","root","fail","XMLParser","fail","XMLParser","NAMESPACE","attribute","node","nonEmpty","identifier","NAMESPACE","NAMESPACE","attribute","node","nonEmpty","identifier","malformed","element","NAMESPACE","identifier","fail","send","NAMESPACE","node","attribute","malformed","NAMESPACE","fail","fail","fail","requireString","month","number","date","status","quantity","MONTHS","dayNumber","flight"]}
1
+ {"version":3,"sources":["../src/errors/sabre-error.ts","../src/air/grouped-itinerary.ts","../src/air/itinerary-messages.ts","../src/http/raw-request.ts","../src/air/bargain-finder-max.ts","../src/booking/booking-errors.ts","../src/air/get-seats.ts","../src/air/itinerary-flights.ts","../src/air/revalidate-itinerary.ts","../src/air/air.ts","../src/logging/redact.ts","../src/logging/logger.ts","../src/auth/token-request.ts","../src/auth/token-store.ts","../src/auth/auth-manager.ts","../src/booking/cancel-booking.ts","../src/booking/flight-details.ts","../src/booking/create-booking.ts","../src/booking/get-booking.ts","../src/booking/booking-management.ts","../src/http/retry.ts","../src/config.ts","../src/http/rest-transport.ts","../src/sabre.ts","../src/http/soap-transport.ts","../src/session/credentials.ts","../src/queue/queue-access.ts","../src/queue/queue-ref.ts","../src/queue/queue-count.ts","../src/queue/queue-list.ts","../src/queue/queue-activity.ts","../src/queue/queue-place.ts","../src/queue/queue-management.ts","../src/reservation/reservation-history.ts","../src/reservation/session-reservation.ts","../src/session/command.ts","../src/session/session.ts","../src/sabre-legacy.ts","../src/auth/credentials.ts","../src/queue/host-date.ts","../src/queue/queue-paragraph.ts","../src/queue/queue-place-remark.ts","../src/air/seat-availability-request.ts","../src/index.ts"],"sourcesContent":["// Jerarquía de errores del SDK. Ver sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md.\n\nexport interface SabreErrorOptions {\n /** Si la política de reintentos puede volver a intentar la operación. */\n retryable: boolean;\n /** Fragmento de la respuesta original sin transformar (JSON parseado o nodo XML). */\n raw?: unknown;\n cause?: unknown;\n}\n\n/**\n * Base de todos los errores del SDK.\n *\n * `raw` puede contener credenciales o datos de pasajero: no es enumerable, así que\n * no aparece en `JSON.stringify`, spreads ni serializadores de logs, pero sigue\n * accesible como `error.raw` para debugging. No lo vuelques a un logger sin sanitizar.\n */\nexport class SabreError extends Error {\n override name = 'SabreError';\n readonly retryable: boolean;\n declare readonly raw: unknown;\n\n constructor(message: string, options: SabreErrorOptions) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.retryable = options.retryable;\n Object.defineProperty(this, 'raw', {\n value: options.raw,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n }\n\n toJSON(): Record<string, unknown> {\n const fields: Record<string, unknown> = Object.fromEntries(Object.entries(this));\n return { ...fields, name: this.name, message: this.message };\n }\n}\n\nexport type SabreProtocol = 'rest' | 'soap';\n\nexport interface SabreGatewayErrorOptions extends SabreErrorOptions {\n protocol: SabreProtocol;\n /** HTTP status de la respuesta, si la hubo. */\n status?: number;\n /** Código tal cual lo devuelve el gateway (`ERR.2SG.*`, `USG_*`), si viene en el body. */\n code?: string;\n}\n\n/** Error de transporte/gateway (`ERR.2SG.*` + HTTP status en REST, `USG_*` en SOAP). */\nexport class SabreGatewayError extends SabreError {\n override name = 'SabreGatewayError';\n readonly protocol: SabreProtocol;\n readonly status: number | undefined;\n readonly code: string | undefined;\n\n constructor(message: string, options: SabreGatewayErrorOptions) {\n super(message, options);\n this.protocol = options.protocol;\n this.status = options.status;\n this.code = options.code;\n }\n}\n\n/**\n * Por qué una sesión SOAP no sirve: `'limit'` (más de 50 sesiones), `'invalid'` (uso\n * concurrente de la sesión), `'expired'` (sesión vencida) o `'blocked'` (creación de sesión\n * bloqueada para el usuario).\n */\nexport type SabreSessionErrorKind = 'limit' | 'invalid' | 'expired' | 'blocked';\n\nexport interface SabreSessionErrorOptions extends Omit<SabreGatewayErrorOptions, 'protocol'> {\n kind: SabreSessionErrorKind;\n}\n\n/**\n * Error de la sesión SOAP de `SabreLegacy`. Se distingue con `instanceof` y `kind`, sin comparar\n * mensajes. La sesión que lo lanzó queda inutilizable: las llamadas siguientes lanzan sin red.\n */\nexport class SabreSessionError extends SabreGatewayError {\n override name = 'SabreSessionError';\n readonly kind: SabreSessionErrorKind;\n\n constructor(message: string, options: SabreSessionErrorOptions) {\n super(message, { ...options, protocol: 'soap' });\n this.kind = options.kind;\n }\n}\n\nexport interface SabreOrchestrationErrorOptions extends Omit<SabreErrorOptions, 'retryable'> {\n /** `SP.PROVIDER_ERROR` o `SP.INTERNAL_ERROR`. */\n code: string;\n}\n\n/**\n * Error de servicio orquestado (`SP.*`), viaja dentro de una respuesta 200.\n * `SP.PROVIDER_ERROR` es reintentable; `SP.INTERNAL_ERROR` (y cualquier otro) no.\n */\nexport class SabreOrchestrationError extends SabreError {\n override name = 'SabreOrchestrationError';\n readonly code: string;\n\n constructor(message: string, options: SabreOrchestrationErrorOptions) {\n super(message, { ...options, retryable: options.code === 'SP.PROVIDER_ERROR' });\n this.code = options.code;\n }\n}\n\nexport interface SabreServiceErrorOptions extends Omit<SabreErrorOptions, 'retryable'> {\n /** Servicio que originó el error, p. ej. `'createBooking'`. */\n service: string;\n /** Código tal cual lo documenta Sabre, sin normalizar. */\n code: string;\n}\n\nexport interface SabreBusinessErrorOptions extends SabreServiceErrorOptions {\n /**\n * Solo para códigos que Sabre documenta como temporales en un servicio de lectura\n * (p. ej. `Transmission timeout` de Bargain Finder Max). Por defecto `false`.\n * La política de reintentos igual exige que la operación sea idempotente.\n */\n retryable?: boolean;\n /** Avisos que llegaron junto con el error (p. ej. `category: WARNING` de Create Booking). */\n warnings?: readonly SabreWarning[];\n /**\n * Otros errores que llegaron junto con este (p. ej. la causa real detrás de\n * `NO_ITEMS_CANCELLED` en Cancel Booking).\n */\n errors?: readonly SabreBusinessError[];\n}\n\n/**\n * Error del catálogo propio de un servicio. No es reintentable, salvo los códigos\n * temporales de servicios de lectura que se marcan con `retryable: true`.\n */\nexport class SabreBusinessError extends SabreError {\n override name = 'SabreBusinessError';\n readonly service: string;\n readonly code: string;\n readonly warnings: readonly SabreWarning[];\n readonly errors: readonly SabreBusinessError[];\n\n constructor(message: string, options: SabreBusinessErrorOptions) {\n super(message, { ...options, retryable: options.retryable ?? false });\n this.service = options.service;\n this.code = options.code;\n this.warnings = options.warnings ?? [];\n this.errors = options.errors ?? [];\n }\n}\n\n/**\n * Advertencia de un servicio (p. ej. `category: WARNING` de Create Booking, soft errors\n * de End Transaction): no es un fallo fatal. Nunca se reintenta automáticamente.\n */\nexport class SabreWarning extends SabreError {\n override name = 'SabreWarning';\n readonly service: string;\n readonly code: string;\n\n constructor(message: string, options: SabreServiceErrorOptions) {\n super(message, { ...options, retryable: false });\n this.service = options.service;\n this.code = options.code;\n }\n}\n","// Modelo `groupedItineraryResponse` compartido por Bargain Finder Max y Revalidate Itinerary,\n// y su desnormalizador: resuelve cada `ref` al objeto completo antes de exponerlo.\n// Ver sabre-wiki/wiki/concepts/modelo-de-itinerario.md.\n//\n// Sin schema formal: los campos salen de los ejemplos de BFM y Revalidate del wiki. Los que\n// solo aparecieron en uno de los dos van como opcionales.\nimport { SabreError } from '../errors/index.js';\n\n// ---------------------------------------------------------------------------\n// Descriptores compartidos (arrays planos indexados por `id`)\n// ---------------------------------------------------------------------------\n\nexport interface ScheduleEndpoint {\n airport: string;\n city?: string;\n /** Visto en sandbox para aeropuertos de EE. UU. */\n state?: string;\n country?: string;\n /** Hora local con offset, p. ej. `17:10:00+02:00`. */\n time: string;\n terminal?: string;\n /** Días que se suman a la fecha de salida del vuelo. Visto en sandbox (`arrival`). */\n dateAdjustment?: number;\n}\n\nexport interface ScheduleEquipment {\n code: string;\n typeForFirstLeg?: string;\n typeForLastLeg?: string;\n}\n\nexport interface ScheduleCarrier {\n marketing: string;\n marketingFlightNumber: number;\n operating?: string;\n operatingFlightNumber?: number;\n alliances?: string;\n equipment?: ScheduleEquipment;\n /**\n * Nombre del operador en un código compartido, tal cual (p. ej. `\"/AVIANCA\"`). No está en el\n * spec. Se observó en BFM y Revalidate en CERT, también cuando `operating` y\n * `operatingFlightNumber` coinciden con el comercializador (AM101 TRC→MEX, operado por\n * `\"AEROLITORAL DBA AEROMEXICO CONNECT\"`, 2026-11-05).\n */\n codeShared?: string;\n}\n\n/** Vuelo/segmento operado (`scheduleDescs[]`). */\nexport interface ScheduleDesc {\n id: number;\n /** Visto en sandbox, p. ej. `\"7\"`; significado sin confirmar. */\n dotRating?: string;\n frequency?: string;\n stopCount?: number;\n eTicketable?: boolean;\n totalMilesFlown?: number;\n /** Minutos. */\n elapsedTime?: number;\n departure: ScheduleEndpoint;\n arrival: ScheduleEndpoint;\n carrier: ScheduleCarrier;\n}\n\n/** Tramo lógico (`legDescs[]`): agrupa schedules por `ref`. */\nexport interface LegDesc {\n id: number;\n /** Minutos. */\n elapsedTime?: number;\n schedules: LegScheduleRef[];\n}\n\n/**\n * Schedule dentro de un tramo. `departureDateAdjustment`: días que se suman a la fecha del\n * tramo para la salida de este vuelo (conexión al día siguiente). Visto en sandbox, sin\n * documentar en los ejemplos de Sabre.\n */\nexport interface LegScheduleRef extends Ref {\n departureDateAdjustment?: number;\n}\n\n/** Impuesto individual (`taxDescs[]`). */\nexport interface TaxDesc {\n id: number;\n code: string;\n amount: number;\n currency: string;\n description?: string;\n publishedAmount?: number;\n publishedCurrency?: string;\n station?: string;\n country?: string;\n /** Visto en sandbox. */\n taxReissue?: { refundable?: boolean };\n}\n\n/** Resumen de impuestos por código (`taxSummaryDescs[]`). Misma forma que `TaxDesc`. */\nexport type TaxSummaryDesc = TaxDesc;\n\n/** Cargo adicional (`obFeeDescs[]`). Significado exacto de \"OB\" sin confirmar. */\nexport interface ObFeeDesc {\n id: number;\n amount: number;\n currency: string;\n}\n\nexport interface FareComponentDescSegment {\n segment: {\n stopover?: boolean;\n };\n}\n\n/** Componente de tarifa (`fareComponentDescs[]`). */\nexport interface FareComponentDesc {\n id: number;\n governingCarrier?: string;\n fareAmount?: number;\n fareCurrency?: string;\n fareBasisCode: string;\n farePassengerType?: string;\n publishedFareAmount?: number;\n publishedFareCurrency?: string;\n /** `FROM` / `TO`. */\n directionality?: string;\n applicablePricingCategories?: string;\n vendorCode?: string;\n fareTypeBitmap?: string;\n fareType?: string;\n fareTariff?: string;\n fareRule?: string;\n cabinCode?: string;\n segments?: FareComponentDescSegment[];\n // Vistos solo en Revalidate Itinerary.\n ticketDesignator?: string;\n mileageSurcharge?: number;\n mileage?: boolean;\n oneWayFare?: boolean;\n negotiatedFare?: boolean;\n privateFare?: boolean;\n notValidAfter?: string;\n /** Distinto de `directionality`; significado sin confirmar. */\n direction?: string;\n}\n\n/** Aerolínea validadora (`validatingCarrierDescs[]`). */\nexport interface ValidatingCarrierDesc {\n id: number;\n settlementMethod?: string;\n newVcxProcess?: boolean;\n default?: { code: string };\n}\n\n/** Franquicia de equipaje (`baggageAllowanceDescs[]`). */\nexport interface BaggageAllowanceDesc {\n id: number;\n pieceCount?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Piezas que no llevan referencias\n// ---------------------------------------------------------------------------\n\n/** Referencia a un descriptor por su `id`. */\nexport interface Ref {\n ref: number;\n}\n\nexport interface ItineraryMessage {\n severity: string;\n type: string;\n code: string;\n text: string;\n}\n\nexport interface LegDescription {\n departureDate: string;\n departureLocation: string;\n arrivalLocation: string;\n}\n\nexport interface CurrencyConversion {\n from: string;\n to: string;\n exchangeRateUsed: number;\n}\n\nexport interface PassengerTotalFare {\n totalFare: number;\n totalTaxAmount?: number;\n currency: string;\n baseFareAmount?: number;\n baseFareCurrency?: string;\n equivalentAmount?: number;\n equivalentCurrency?: string;\n constructionAmount?: number;\n constructionCurrency?: string;\n exchangeRateOne?: number;\n // Comisión de agencia: vistos solo en Revalidate Itinerary.\n commissionPercentage?: number;\n commissionAmount?: number;\n cat35CommissionPercentage?: number;\n cat35CommissionAmount?: number;\n cat35MarkupAmount?: number;\n commissionAmountInEquivalent?: number;\n commissionSource?: string;\n}\n\nexport interface TotalFare {\n totalPrice: number;\n totalTaxAmount?: number;\n currency: string;\n baseFareAmount?: number;\n baseFareCurrency?: string;\n constructionAmount?: number;\n constructionCurrency?: string;\n equivalentAmount?: number;\n equivalentCurrency?: string;\n}\n\n/** Disponibilidad del segmento dentro de un componente de tarifa. */\nexport interface FareComponentSegmentDetail {\n bookingCode?: string;\n cabinCode?: string;\n mealCode?: string;\n seatsAvailable?: number;\n availabilityBreak?: boolean;\n fareBreakPoint?: boolean;\n}\n\nexport interface FareMessage {\n type: string;\n code: string;\n /** Visto en sandbox de Revalidate. */\n carrier?: string;\n info: string;\n}\n\n// ---------------------------------------------------------------------------\n// Respuesta tal cual la manda Sabre (con `ref`). Interna: el SDK expone la desnormalizada.\n// ---------------------------------------------------------------------------\n\nexport interface RawFareComponent extends Ref {\n beginAirport?: string;\n endAirport?: string;\n segments?: Array<{ segment: FareComponentSegmentDetail }>;\n}\n\nexport interface RawBaggageInformation {\n provisionType?: string;\n airlineCode?: string;\n /** Índices de segmento, no referencias a descriptores. */\n segments?: Array<{ id: number }>;\n allowance?: Ref;\n}\n\nexport interface RawPassengerInfo {\n passengerType: string;\n passengerNumber?: number;\n nonRefundable?: boolean;\n fareComponents?: RawFareComponent[];\n taxes?: Ref[];\n taxSummaries?: Ref[];\n obFees?: Ref[];\n currencyConversion?: CurrencyConversion;\n passengerTotalFare?: PassengerTotalFare;\n baggageInformation?: RawBaggageInformation[];\n // Vistos solo en Revalidate Itinerary.\n fareMessages?: FareMessage[];\n fareCalcLine?: { info: string };\n}\n\nexport interface RawFare {\n mandatoryInd?: boolean;\n validatingCarrierCode?: string;\n vita?: boolean;\n eTicketable?: boolean;\n lastTicketDate?: string;\n lastTicketTime?: string;\n governingCarriers?: string;\n passengerInfoList: Array<{ passengerInfo: RawPassengerInfo }>;\n totalFare?: TotalFare;\n validatingCarriers?: Ref[];\n}\n\nexport interface RawPricingInformation {\n pricingSubsource?: string;\n /** P. ej. `ATPCO`. Visto en Revalidate y en sandbox de BFM. */\n distributionModel?: string;\n fare: RawFare;\n}\n\nexport interface RawItinerary {\n id: number;\n pricingSource?: string;\n /** Visto solo en Revalidate Itinerary. */\n currentItinerary?: boolean;\n /** Visto en sandbox de BFM; significado sin confirmar. */\n diversitySwapper?: { weighedPrice?: number };\n legs: Ref[];\n pricingInformation: RawPricingInformation[];\n}\n\nexport interface RawItineraryGroup {\n groupDescription: { legDescriptions: LegDescription[] };\n itineraries: RawItinerary[];\n}\n\n/** Contenido de `groupedItineraryResponse` tal cual llega de Sabre. */\nexport interface RawGroupedItineraryResponse {\n version: string;\n messages?: ItineraryMessage[];\n statistics?: { itineraryCount: number };\n scheduleDescs?: ScheduleDesc[];\n taxDescs?: TaxDesc[];\n taxSummaryDescs?: TaxSummaryDesc[];\n obFeeDescs?: ObFeeDesc[];\n fareComponentDescs?: FareComponentDesc[];\n validatingCarrierDescs?: ValidatingCarrierDesc[];\n baggageAllowanceDescs?: BaggageAllowanceDesc[];\n legDescs?: LegDesc[];\n itineraryGroups?: RawItineraryGroup[];\n}\n\n// ---------------------------------------------------------------------------\n// Respuesta desnormalizada (superficie pública)\n// ---------------------------------------------------------------------------\n\n/** Tramo con sus schedules resueltos. */\nexport interface Leg extends Omit<LegDesc, 'schedules'> {\n schedules: LegSchedule[];\n}\n\n/** Schedule resuelto, con lo que la referencia del tramo agrega. */\nexport type LegSchedule = ScheduleDesc & Omit<LegScheduleRef, 'ref'>;\n\n/** Segmento de un componente de tarifa: lo del descriptor más la disponibilidad del itinerario. */\nexport interface FareComponentSegment {\n segment: FareComponentDescSegment['segment'] & FareComponentSegmentDetail;\n}\n\n/** Componente de tarifa resuelto: descriptor + datos propios del itinerario. */\nexport interface FareComponent extends Omit<FareComponentDesc, 'segments'> {\n beginAirport?: string;\n endAirport?: string;\n segments?: FareComponentSegment[];\n}\n\nexport interface BaggageInformation extends Omit<RawBaggageInformation, 'allowance'> {\n allowance?: BaggageAllowanceDesc;\n}\n\nexport interface PassengerInfo\n extends Omit<RawPassengerInfo, 'fareComponents' | 'taxes' | 'taxSummaries' | 'obFees' | 'baggageInformation'> {\n fareComponents?: FareComponent[];\n taxes?: TaxDesc[];\n taxSummaries?: TaxSummaryDesc[];\n obFees?: ObFeeDesc[];\n baggageInformation?: BaggageInformation[];\n}\n\nexport interface Fare extends Omit<RawFare, 'passengerInfoList' | 'validatingCarriers'> {\n passengerInfoList: Array<{ passengerInfo: PassengerInfo }>;\n validatingCarriers?: ValidatingCarrierDesc[];\n}\n\nexport interface PricingInformation extends Omit<RawPricingInformation, 'fare'> {\n fare: Fare;\n}\n\nexport interface Itinerary extends Omit<RawItinerary, 'legs' | 'pricingInformation'> {\n legs: Leg[];\n pricingInformation: PricingInformation[];\n}\n\nexport interface ItineraryGroup {\n groupDescription: { legDescriptions: LegDescription[] };\n itineraries: Itinerary[];\n}\n\n/**\n * `groupedItineraryResponse` con cada `ref` resuelto al objeto completo. Los arrays de\n * descriptores (`scheduleDescs`, `legDescs`, …) ya no se exponen: su contenido vive\n * dentro de cada itinerario.\n */\nexport interface GroupedItineraryResponse {\n version: string;\n messages: ItineraryMessage[];\n statistics?: { itineraryCount: number };\n itineraryGroups: ItineraryGroup[];\n}\n\n// ---------------------------------------------------------------------------\n// Desnormalizador\n// ---------------------------------------------------------------------------\n\n/**\n * Resuelve cada `{ ref, ...resto }` a `{ ...descriptor, ...resto }` (sin `ref`; el `id` del\n * descriptor se conserva). En los componentes de tarifa, `segments` se fusiona elemento a\n * elemento: el descriptor aporta `stopover` y el itinerario la disponibilidad; si los dos\n * traen `segments` con distinto largo, la respuesta es malformada.\n *\n * Un `ref` sin descriptor con ese `id` es una respuesta malformada: lanza `SabreError`\n * no reintentable en vez de devolver un objeto a medias. No muta la entrada.\n */\nexport function denormalizeGroupedItineraryResponse(\n raw: RawGroupedItineraryResponse,\n service: string,\n): GroupedItineraryResponse {\n const resolver = new Resolver(raw, service);\n return {\n version: raw.version,\n messages: raw.messages ?? [],\n ...(raw.statistics === undefined ? {} : { statistics: raw.statistics }),\n itineraryGroups: (raw.itineraryGroups ?? []).map((group) => ({\n groupDescription: group.groupDescription,\n itineraries: group.itineraries.map((itinerary) => resolver.itinerary(itinerary)),\n })),\n };\n}\n\nclass Resolver {\n readonly #service: string;\n readonly #schedules: Map<number, ScheduleDesc>;\n readonly #legs: Map<number, LegDesc>;\n readonly #taxes: Map<number, TaxDesc>;\n readonly #taxSummaries: Map<number, TaxSummaryDesc>;\n readonly #obFees: Map<number, ObFeeDesc>;\n readonly #fareComponents: Map<number, FareComponentDesc>;\n readonly #validatingCarriers: Map<number, ValidatingCarrierDesc>;\n readonly #baggageAllowances: Map<number, BaggageAllowanceDesc>;\n\n constructor(raw: RawGroupedItineraryResponse, service: string) {\n this.#service = service;\n this.#schedules = byId(raw.scheduleDescs);\n this.#legs = byId(raw.legDescs);\n this.#taxes = byId(raw.taxDescs);\n this.#taxSummaries = byId(raw.taxSummaryDescs);\n this.#obFees = byId(raw.obFeeDescs);\n this.#fareComponents = byId(raw.fareComponentDescs);\n this.#validatingCarriers = byId(raw.validatingCarrierDescs);\n this.#baggageAllowances = byId(raw.baggageAllowanceDescs);\n }\n\n itinerary(itinerary: RawItinerary): Itinerary {\n return {\n ...itinerary,\n legs: itinerary.legs.map((ref) => this.#leg(ref)),\n pricingInformation: itinerary.pricingInformation.map((pricing) => ({\n ...pricing,\n fare: this.#fare(pricing.fare),\n })),\n };\n }\n\n #leg(ref: Ref): Leg {\n const leg = this.#merge(this.#legs, 'legDescs', ref);\n return { ...leg, schedules: leg.schedules.map((schedule) => this.#merge(this.#schedules, 'scheduleDescs', schedule)) };\n }\n\n #fare(fare: RawFare): Fare {\n const { validatingCarriers, ...rest } = fare;\n return {\n ...rest,\n passengerInfoList: fare.passengerInfoList.map(({ passengerInfo, ...entry }) => ({\n ...entry,\n passengerInfo: this.#passengerInfo(passengerInfo),\n })),\n ...(validatingCarriers === undefined\n ? {}\n : {\n validatingCarriers: validatingCarriers.map((ref) =>\n this.#merge(this.#validatingCarriers, 'validatingCarrierDescs', ref),\n ),\n }),\n };\n }\n\n #passengerInfo(info: RawPassengerInfo): PassengerInfo {\n const { fareComponents, taxes, taxSummaries, obFees, baggageInformation, ...rest } = info;\n const result: PassengerInfo = { ...rest };\n if (fareComponents !== undefined) result.fareComponents = fareComponents.map((ref) => this.#fareComponent(ref));\n if (taxes !== undefined) result.taxes = taxes.map((ref) => this.#merge(this.#taxes, 'taxDescs', ref));\n if (taxSummaries !== undefined) {\n result.taxSummaries = taxSummaries.map((ref) => this.#merge(this.#taxSummaries, 'taxSummaryDescs', ref));\n }\n if (obFees !== undefined) result.obFees = obFees.map((ref) => this.#merge(this.#obFees, 'obFeeDescs', ref));\n if (baggageInformation !== undefined) {\n result.baggageInformation = baggageInformation.map(({ allowance, ...bag }) => ({\n ...bag,\n ...(allowance === undefined\n ? {}\n : { allowance: this.#merge(this.#baggageAllowances, 'baggageAllowanceDescs', allowance) }),\n }));\n }\n return result;\n }\n\n #fareComponent(ref: RawFareComponent): FareComponent {\n const desc = this.#lookup(this.#fareComponents, 'fareComponentDescs', ref.ref);\n const { ref: _ref, segments: siteSegments, ...site } = ref;\n const { segments: descSegments, ...descRest } = desc;\n if (descSegments !== undefined && siteSegments !== undefined && descSegments.length !== siteSegments.length) {\n throw this.#malformed(\n `fareComponents con ${siteSegments.length} segmentos y fareComponentDescs ${ref.ref} con ${descSegments.length}`,\n );\n }\n const segments = mergeSegments(descSegments, siteSegments);\n return { ...descRest, ...site, ...(segments === undefined ? {} : { segments }) };\n }\n\n /** `{ ref, ...resto }` → `{ ...descriptor, ...resto }`. */\n #merge<T extends { id: number }>(index: Map<number, T>, kind: string, ref: Ref): T {\n const { ref: id, ...site } = ref;\n return { ...this.#lookup(index, kind, id), ...site };\n }\n\n #lookup<T>(index: Map<number, T>, kind: string, id: number): T {\n const desc = index.get(id);\n if (desc === undefined) throw this.#malformed(`ref ${id} sin descriptor en ${kind}`);\n return desc;\n }\n\n #malformed(detail: string): SabreError {\n return new SabreError(`${this.#service}: respuesta malformada, ${detail}`, { retryable: false });\n }\n}\n\nfunction byId<T extends { id: number }>(descs: T[] | undefined): Map<number, T> {\n return new Map((descs ?? []).map((desc) => [desc.id, desc]));\n}\n\nfunction mergeSegments(\n desc: FareComponentDescSegment[] | undefined,\n site: Array<{ segment: FareComponentSegmentDetail }> | undefined,\n): FareComponentSegment[] | undefined {\n if (desc === undefined && site === undefined) return undefined;\n // Los largos ya se validaron iguales cuando vienen los dos.\n const length = desc?.length ?? site?.length ?? 0;\n return Array.from({ length }, (_, i) => ({\n segment: { ...desc?.[i]?.segment, ...site?.[i]?.segment },\n }));\n}\n","// Clasificación de errores de negocio en `groupedItineraryResponse.messages[]`, compartida por\n// los servicios que responden con ese modelo (Bargain Finder Max, Revalidate Itinerary).\n// Ver sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md.\nimport { SabreBusinessError, SabreError } from '../errors/index.js';\nimport type { ItineraryMessage } from './grouped-itinerary.js';\n\n/** Entrada de catálogo: se compara por substring del `text`, sin distinguir mayúsculas. */\nexport interface ItineraryMessageCatalogEntry {\n code: string;\n retryable: boolean;\n}\n\n/**\n * Paso 3 del orden de detección: un mensaje con `severity: Error` en\n * `groupedItineraryResponse.messages[]` (respuesta 200) es un `SabreBusinessError`.\n *\n * En sandbox, los mensajes `Error` son genéricos (`No complete journey can be built…`,\n * `Error during Processing`) y el texto del catálogo llega en un mensaje `Info`\n * (`NO FLIGHT SCHEDULES FOR QUALIFIERS USED`). Por eso, cuando hay algún `Error`, el\n * catálogo se busca en el `text` de todos los mensajes.\n */\nexport function classifyItineraryMessages(\n body: unknown,\n service: string,\n catalog: ReadonlyArray<ItineraryMessageCatalogEntry>,\n): SabreError | undefined {\n const response = isObject(body) ? body.groupedItineraryResponse : undefined;\n if (!isObject(response)) {\n return new SabreError(`${service}: respuesta malformada, falta groupedItineraryResponse`, {\n retryable: false,\n raw: body,\n });\n }\n const messages = Array.isArray(response.messages) ? (response.messages as Partial<ItineraryMessage>[]) : [];\n const error = messages.find((message) => message.severity?.toLowerCase() === 'error');\n if (error === undefined) return undefined;\n\n const match = findInCatalog(messages, catalog);\n const text = match?.text ?? (typeof error.text === 'string' ? error.text : '');\n const known = match?.entry;\n const code = known?.code ?? error.code ?? text;\n return new SabreBusinessError(`${service}: ${text || code}`, {\n service,\n code,\n retryable: known?.retryable ?? false,\n raw: body,\n });\n}\n\nfunction findInCatalog(\n messages: Partial<ItineraryMessage>[],\n catalog: ReadonlyArray<ItineraryMessageCatalogEntry>,\n): { entry: ItineraryMessageCatalogEntry; text: string } | undefined {\n for (const message of messages) {\n if (typeof message.text !== 'string') continue;\n const text = message.text.toLowerCase();\n const entry = catalog.find((candidate) => text.includes(candidate.code.toLowerCase()));\n if (entry !== undefined) return { entry, text: message.text };\n }\n return undefined;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n","// Request crudo que mandó el SDK, por operación. Ver\n// sabre-wiki/wiki/proyectos/sabre-client/decisiones/request-crudo.md (ADR-029).\nimport type { SabreRawResponseCallback } from './raw-response.js';\n\n/**\n * Lo que el SDK mandó por la red en el último intento de una operación.\n *\n * ⚠️ El `body` y la `url` traen datos de pasajeros (PII): localizadores, nombres, contactos. El\n * SDK nunca los envía al logger; quien usa `onRawRequest` responde por dónde los guarda.\n */\nexport interface SabreRawRequest {\n /** El mismo valor que en `onRawResponse`, p. ej. `'booking.get'` o `'queue.access'`. */\n operation: string;\n protocol: 'rest' | 'soap';\n /** `'GET'`, `'POST'`… En SOAP, siempre `'POST'`. */\n method: string;\n /** URL completa, con query string. */\n url: string;\n /** Los headers que se mandaron, sin `Authorization` (se quita el header entero). */\n headers: Headers;\n /**\n * El texto que se mandó, o `undefined` si el request no llevaba body. En REST va tal cual. En\n * SOAP es el sobre completo, con una sola modificación: el valor de cada `BinarySecurityToken`\n * va como `[REDACTED]`.\n */\n body: string | undefined;\n /** Intentos que llegaron a llamar a `fetch`, contando los reintentos (1 si no hubo). */\n attempts: number;\n}\n\n/**\n * Se llama una sola vez por operación, con el último intento que se mandó, antes de devolver o de\n * lanzar y antes que `onRawResponse`. A diferencia de este, se llama también si ningún intento tuvo\n * respuesta HTTP (fallo de red, `AbortError`). No se llama si la operación lanza antes de mandar\n * nada, ni con las llamadas de auth: el token de OAuth y `SessionCreateRQ` (`openSession`), que\n * llevan credenciales, y `SessionCloseRQ` (`close`).\n *\n * Es síncrono y su retorno se ignora. Si lanza, el SDK lo atrapa, emite\n * `sabre.request.rawRequestHookFailed` al logger (sin el body) y la operación sigue.\n */\nexport type SabreRawRequestCallback = (raw: SabreRawRequest) => void;\n\n/** Lo que se guarda de un intento, hasta entregarlo. */\nexport type RawRequestCapture = Omit<SabreRawRequest, 'operation' | 'protocol' | 'attempts'>;\n\n/** Los headers que se entregan: una copia, sin `Authorization`. */\nexport function rawRequestHeaders(headers: HeadersInit): Headers {\n const copy = new Headers(headers);\n copy.delete('Authorization');\n return copy;\n}\n\n/**\n * Los campos de una operación REST para el transporte: `operation` y los callbacks que haya. Sin\n * callbacks, nada.\n */\nexport function rawHooks(\n options: { onRawResponse?: SabreRawResponseCallback | undefined; onRawRequest?: SabreRawRequestCallback | undefined },\n operation: string,\n): { operation?: string; onRawResponse?: SabreRawResponseCallback; onRawRequest?: SabreRawRequestCallback } {\n const { onRawResponse, onRawRequest } = options;\n if (onRawResponse === undefined && onRawRequest === undefined) return {};\n return {\n operation,\n ...(onRawResponse === undefined ? {} : { onRawResponse }),\n ...(onRawRequest === undefined ? {} : { onRawRequest }),\n };\n}\n","// Bargain Finder Max v5 (`POST /v5/offers/shop`).\n// Ver sabre-wiki/wiki/entities/bargain-finder-max.md.\nimport type { SabreError } from '../errors/index.js';\nimport type { SabreRawResponseCallback } from '../http/raw-response.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport type { RetryOptions } from '../http/retry.js';\nimport {\n denormalizeGroupedItineraryResponse,\n type GroupedItineraryResponse,\n type RawGroupedItineraryResponse,\n} from './grouped-itinerary.js';\nimport { classifyItineraryMessages, type ItineraryMessageCatalogEntry } from './itinerary-messages.js';\nimport type { OtaAirLowFareSearchRq } from './low-fare-search-request.js';\nimport { rawHooks, type SabreRawRequestCallback } from '../http/raw-request.js';\n\nexport const BARGAIN_FINDER_MAX_SERVICE = 'bargainFinderMax';\nconst PATH = '/v5/offers/shop';\n\n/** Body de Bargain Finder Max v5, tal cual lo documenta Sabre. */\nexport interface BargainFinderMaxRequest {\n OTA_AirLowFareSearchRQ: OtaAirLowFareSearchRq;\n}\n\n/** `groupedItineraryResponse` con las referencias ya resueltas. */\nexport type BargainFinderMaxResponse = GroupedItineraryResponse;\n\nexport interface RequestOptions {\n signal?: AbortSignal;\n /** Respuesta cruda del último intento HTTP. El body trae PII: ver `SabreRawResponse`. */\n onRawResponse?: SabreRawResponseCallback;\n /** Request crudo del último intento que se mandó, sin `Authorization`. Trae PII: ver `SabreRawRequest`. */\n onRawRequest?: SabreRawRequestCallback;\n /** Pisa los reintentos del cliente solo para esta request. */\n retry?: Partial<RetryOptions>;\n}\n\n/**\n * Catálogo de errores de BFM (guía oficial de errores). Se compara por substring del\n * `text` porque Sabre agrega detalle variable. Los temporales son reintentables: BFM es\n * una lectura idempotente y Sabre indica reintentar.\n */\nexport const BARGAIN_FINDER_MAX_CATALOG: ReadonlyArray<ItineraryMessageCatalogEntry> = [\n { code: 'No Availability', retryable: false },\n { code: 'NO FLIGHT SCHEDULES FOR QUALIFIERS USED', retryable: false },\n { code: 'Connection reset by peer', retryable: true },\n { code: 'Transmission timeout', retryable: true },\n { code: 'Insufficient resources', retryable: true },\n { code: 'MAX NBR COMBINATIONS EXCEEDED', retryable: true },\n];\n\nexport async function bargainFinderMax(\n transport: RestTransport,\n request: BargainFinderMaxRequest,\n options: RequestOptions = {},\n): Promise<BargainFinderMaxResponse> {\n if (typeof request !== 'object' || request === null || typeof request.OTA_AirLowFareSearchRQ !== 'object') {\n throw new TypeError('sabre-client: bargainFinderMax espera { OTA_AirLowFareSearchRQ: { ... } }');\n }\n const body = await transport.request<{ groupedItineraryResponse: RawGroupedItineraryResponse }>({\n method: 'POST',\n path: PATH,\n service: BARGAIN_FINDER_MAX_SERVICE,\n // POST, pero de solo lectura: se puede reintentar sin efectos duplicados.\n idempotent: true,\n body: request,\n classify: classifyBargainFinderMax,\n ...(options.retry === undefined ? {} : { retry: options.retry }),\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'air.bargainFinderMax'),\n });\n return denormalizeGroupedItineraryResponse(body.groupedItineraryResponse, BARGAIN_FINDER_MAX_SERVICE);\n}\n\n/** Ver `classifyItineraryMessages`. */\nexport function classifyBargainFinderMax(body: unknown): SabreError | undefined {\n return classifyItineraryMessages(body, BARGAIN_FINDER_MAX_SERVICE, BARGAIN_FINDER_MAX_CATALOG);\n}\n","// `errors[]` de la Booking Management API: mismo `Error` del spec en Create, Get y Cancel.\n// Ver sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md.\nimport { SabreBusinessError, SabreWarning } from '../errors/index.js';\n\nconst WARNING = 'WARNING';\n\n/** Elemento de `errors[]` tal cual lo manda Sabre (`Error` del spec; los avisos comparten forma). */\nexport interface BookingResponseError {\n /** `BAD_REQUEST`, `APPLICATION_ERROR`, `WARNING`, … */\n category: string;\n /** P. ej. `UNABLE_TO_BOOK_FLIGHTS`. */\n type: string;\n description?: string;\n fieldPath?: string;\n fieldName?: string;\n /** Puede traer datos del request (p. ej. un email): no se copia a los errores del SDK. */\n fieldValue?: string;\n}\n\nexport function responseErrors(response: { errors?: BookingResponseError[] }): BookingResponseError[] {\n return Array.isArray(response.errors) ? response.errors.filter(isObject) as BookingResponseError[] : [];\n}\n\nexport function isWarning(item: BookingResponseError): boolean {\n return typeof item.category === 'string' && item.category.toUpperCase() === WARNING;\n}\n\nexport function toWarning(service: string, item: BookingResponseError): SabreWarning {\n return new SabreWarning(messageOf(service, item), { service, code: codeOf(item), raw: item });\n}\n\nexport interface BusinessErrorAttachments {\n warnings?: SabreWarning[];\n errors?: SabreBusinessError[];\n retryable?: boolean;\n}\n\nexport function toBusinessError(\n service: string,\n item: BookingResponseError,\n { warnings = [], errors = [], retryable = false }: BusinessErrorAttachments = {},\n): SabreBusinessError {\n return new SabreBusinessError(messageOf(service, item), {\n service,\n code: codeOf(item),\n raw: item,\n warnings,\n errors,\n retryable,\n });\n}\n\nexport function codeOf(item: BookingResponseError): string {\n return typeof item.type === 'string' && item.type !== '' ? item.type : String(item.category);\n}\n\n/** Sin `fieldValue`, que puede traer datos del pasajero; queda en `raw`. */\nfunction messageOf(service: string, item: BookingResponseError): string {\n const where = typeof item.fieldPath === 'string' && item.fieldPath !== '' ? ` en ${item.fieldPath}` : '';\n const description = typeof item.description === 'string' && item.description !== '' ? `: ${item.description}` : '';\n return `${service}: ${String(item.category)} ${codeOf(item)}${where}${description}`;\n}\n\nexport function nonEmpty(value: unknown): value is string {\n return typeof value === 'string' && value !== '';\n}\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n","// Get Seats v3 (`POST /v3/offers/getseats/...`).\n// Ver sabre-wiki/wiki/entities/get-seats.md y sabre-wiki/wiki/sdk/get-seats-en-el-sdk.md.\nimport { isObject, nonEmpty, toBusinessError, toWarning } from '../booking/booking-errors.js';\nimport { type SabreBusinessError, SabreError, type SabreWarning } from '../errors/index.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport type { RequestOptions } from './bargain-finder-max.js';\nimport { rawHooks } from '../http/raw-request.js';\n\n/** `service` de errores y logs; distinto por endpoint para que no quede oculto (ADR, opción C). */\nexport const GET_SEATS_BY_PAYLOAD_SERVICE = 'getSeatsByPayload';\nconst BY_PAYLOAD_PATH = '/v3/offers/getseats/byReservationPayload';\nexport const GET_SEATS_BY_PNR_LOCATOR_SERVICE = 'getSeatsByPnrLocator';\nconst BY_PNR_LOCATOR_PATH = '/v3/offers/getseats/byPnrLocator';\n/** Campos del payload que no pueden ir junto con `pnrLocator`. */\nconst PAYLOAD_FIELDS = ['segments', 'passengers', 'returnSeatMapsOnlyForSegmentRefs'] as const;\n\n// ─── Request ────────────────────────────────────────────────────────────────\n\n/** `KeyValuePair` del spec. */\nexport interface SeatKeyValuePair {\n key: string;\n value: string;\n}\n\n/** `LoyaltyProgramAccount` del spec. */\nexport interface SeatLoyaltyProgramAccount {\n airlineCode?: string;\n accountNumber?: string;\n programName?: string;\n}\n\n/** `SegmentBase` del spec. Fechas `YYYY-MM-DD` y horas `HH:MM`, locales del aeropuerto. */\nexport interface SeatSegment {\n /** Identifica el segmento dentro del mensaje (`IdType`: `^[a-zA-Z_][a-zA-Z0-9_\\-.]*$`). */\n id: string;\n bookingAirlineCode: string;\n bookingFlightNumber: number;\n departureAirportCode: string;\n arrivalAirportCode: string;\n departureDate: string;\n bookingClassCode: string;\n departureTime?: string;\n arrivalDate?: string;\n arrivalTime?: string;\n operatingAirlineCode?: string;\n operatingFlightNumber?: number;\n operatingBookingClassCode?: string;\n cabinCode?: string;\n}\n\n/** `SegmentPayloadRq` del spec. */\nexport interface SeatSegmentPayloadRq extends SeatSegment {\n /** Si el segmento tiene el tag `/RCRQ`. */\n hasRecordCreateTag?: boolean;\n}\n\n/** `FareSegmentAssociation` del spec. */\nexport interface SeatFareSegmentAssociation {\n segmentRef: string;\n fareComponentRef: string;\n}\n\n/** `SpecialServiceRequest` del spec. */\nexport interface SeatSpecialServiceRequest {\n codes: string[];\n segmentRef?: string;\n}\n\n/** `PassengerBase` del spec. */\nexport interface SeatPassenger {\n id: string;\n passengerType?: string;\n givenName?: string;\n surname?: string;\n loyaltyProgramAccounts?: SeatLoyaltyProgramAccount[];\n}\n\n/** `PassengerPayloadRq` del spec. */\nexport interface SeatPassengerPayloadRq extends SeatPassenger {\n fareSegmentAssociation?: SeatFareSegmentAssociation[];\n specialServiceRequests?: SeatSpecialServiceRequest[];\n /** Pasajero con un infante sin asiento. Por defecto `false`. */\n isAccompaniedByInfant?: boolean;\n customAttributes?: SeatKeyValuePair[];\n}\n\n/** `FareDetail` del spec. */\nexport interface SeatFareDetail {\n fareType?: string;\n fareTariff?: string;\n fareRule?: string;\n fareIndicator?: number;\n fareTypeBitmap?: string;\n hasPrivateTariff?: boolean;\n}\n\n/** `FareComponent` del spec. */\nexport interface SeatFareComponent {\n fareComponentId: string;\n fareBasis: string;\n governingCarrier?: string;\n /** Número como string, p. ej. `'500.00'`. Exige `totalPriceCurrencyCode`. */\n totalPrice?: string;\n totalPriceCurrencyCode?: string;\n brandCode?: string;\n fareDetail?: SeatFareDetail;\n}\n\n/** `SeatAvailabilityByPayloadRq` del spec 3.0: la reserva armada a mano. */\nexport interface SeatAvailabilityByPayloadRq {\n /** `id` de los segmentos para los que se piden mapas. */\n returnSeatMapsOnlyForSegmentRefs: string[];\n segments: SeatSegmentPayloadRq[];\n passengers: SeatPassengerPayloadRq[];\n returnSeatOffersOnlyForPassengerRefs?: string[];\n fareComponents?: SeatFareComponent[];\n /** ISO 4217. Si falta, Sabre la elige según otros factores. */\n currencyCode?: string;\n /** `true`: mapa de check-in; `false`: mapa de reserva. */\n isCheckinMode?: boolean;\n customAttributes?: SeatKeyValuePair[];\n}\n\n/**\n * `SeatAvailabilityByPnrLocatorRq` del spec 3.0: un PNR ya creado. Sabre lo lee sin estado,\n * así que no ve los cambios sin confirmar.\n */\nexport interface SeatAvailabilityByPnrLocatorRq {\n /** Localizador del PNR (`^[A-Z]{6}$`). */\n pnrLocator: string;\n /** IDs de segmento del PNR para los que se piden mapas. */\n returnSeatMapsOnlyForSegmentIds?: string[];\n /** Name reference numbers del PNR, p. ej. `'01.01'`. */\n returnSeatOffersOnlyForPassengerNameReferenceNumbers?: string[];\n currencyCode?: string;\n isCheckinMode?: boolean;\n customAttributes?: SeatKeyValuePair[];\n}\n\n/** Entrada de `sabre.air.getSeats`: con `pnrLocator` va a `byPnrLocator`; sin él, a `byReservationPayload`. */\nexport type GetSeatsRequest = SeatAvailabilityByPayloadRq | SeatAvailabilityByPnrLocatorRq;\n\n// ─── Response ───────────────────────────────────────────────────────────────\n\n/** `FlightLeg` del spec. */\nexport interface SeatFlightLeg {\n id: string;\n departureAirportCode: string;\n arrivalAirportCode: string;\n departureScheduledDateTime?: string;\n aircraftCode?: string;\n}\n\n/** `SegmentRs` del spec. */\nexport interface SeatSegmentRs extends SeatSegment {\n isChangeOfGauge?: boolean;\n flightLegs?: SeatFlightLeg[];\n /**\n * El segmento en la reserva (p. ej. `\"10\"`). Coincide con `flights[].itemId` y\n * `allSegments[].id` de Get Booking, así que sirve para cruzar el mapa con la reserva. No está en\n * el spec 3.0: llega en `byPnrLocator` (CERT, 2026-11-04, sabre-playground #11).\n */\n reservationSegmentId?: string;\n}\n\n/** `PassengerRs` del spec. */\nexport type SeatPassengerRs = SeatPassenger;\n\n/** `TaxType` del spec. */\nexport interface SeatTax {\n taxAmount?: number | string;\n taxCode?: string;\n description?: string;\n}\n\n/**\n * `PriceBreakdown` del spec, en la moneda del `PriceDefinition`. El spec dice string, pero en\n * producción los importes llegaron como número (`1200`, 2026-10-31): se acepta cualquiera.\n */\nexport interface SeatPriceBreakdown {\n /** Con impuestos. */\n amount: number | string;\n amountWithoutTaxes?: number | string;\n taxesTotal?: number | string;\n taxes?: SeatTax[];\n isTaxExempt?: boolean;\n}\n\n/** `PriceDefinition` del spec. */\nexport interface SeatPriceDefinition {\n id: string;\n currencyCode: string;\n totalPrice: SeatPriceBreakdown;\n referenceBasePrice?: SeatPriceBreakdown;\n}\n\n/** `OfferItemDetails` del spec. */\nexport interface SeatOfferItemDetails {\n serviceDefinitionRef: string;\n /** `id` de un `PriceDefinition` del mismo mensaje: ahí está el precio del asiento. */\n priceDefinitionRef?: string;\n segmentRefs: string[];\n passengerRefs: string[];\n refundableReissuableIndicator?: 'Yes' | 'No' | 'Reuse';\n isInterlineable?: boolean;\n sectorPortionIndicator?: 'Sector' | 'Portion' | 'Journey';\n feeApplicationMethod?: string;\n purchaseByDateTime?: string;\n annotations?: SeatKeyValuePair[];\n}\n\n/** `OfferItem` del spec: ítem reservable asignado a asientos. */\nexport interface SeatOfferItem extends SeatOfferItemDetails {\n id: string;\n}\n\n/** `DisplayOnlyItem` del spec: ítem solo informativo. */\nexport interface SeatDisplayOnlyItem extends SeatOfferItemDetails {\n id: string;\n displayOnlyReason?: 'Unavailable' | 'Unable To Book' | 'Restricted' | 'Unknown';\n displayOnlySource?: string;\n displayOnlyReasonDetails?: SeatKeyValuePair[];\n}\n\n/** `ServiceDefinition` del spec. */\nexport interface SeatServiceDefinition {\n id: string;\n serviceCode?: string;\n airlineCode?: string;\n commercialName?: string;\n /** Group code de ATPCO. */\n groupCode?: string;\n emdType?: 'Standalone' | 'Flight Coupon Associated' | 'Standalone Ticket Associated' | 'Other Than Emd' | 'Eticket';\n emdTypeCode?: number;\n specialServiceCode?: string;\n reasonForIssuance?: string;\n reasonForIssuanceCode?: string;\n isCommissionable?: boolean;\n isFeeGuaranteed?: boolean;\n}\n\n/** `SeatCharacteristic` / `RowCharacteristic` del spec (PADIS 9825). */\nexport interface SeatCharacteristic {\n code: string;\n description?: string;\n}\n\n/** `SeatType` del spec. El número de asiento es `row` de la fila más `column`. */\nexport interface Seat {\n column: string;\n /** PADIS 9865: `F` libre, `O` ocupado, … */\n occupationStatusCode?: string;\n characteristics?: SeatCharacteristic[];\n isOperative?: boolean;\n /** Ítems reservables (`offerItems[].id`) del asiento. */\n offerItemRefIds?: string[];\n /** Ítems solo informativos (`displayOnlyItems[].id`) del asiento. */\n displayOnlyItemRefIds?: string[];\n}\n\n/** `SeatRow` del spec. */\nexport interface SeatRow {\n row: number;\n characteristics?: SeatCharacteristic[];\n seats: Seat[];\n}\n\n/** `CabinLayoutRowPosition` del spec. */\nexport interface SeatCabinRowPosition {\n firstRow: number;\n lastRow: number;\n}\n\n/** `Facility` del spec. */\nexport interface SeatCabinFacility {\n firstRow: number;\n lastRow: number;\n columnIds?: string[];\n orientationCode: string;\n positionCodes: string[];\n facilityTypeCode: string;\n}\n\n/**\n * Un pasillo de la cabina: entre qué filas está y entre qué columnas (p. ej. `leftFromColumn: \"D\"`,\n * `rightFromColumn: \"C\"`). No está en el spec 3.0: llega en `byPnrLocator` y en\n * `byReservationPayload`, en CERT y en producción.\n */\nexport interface SeatCabinAisle {\n firstRow: number;\n lastRow: number;\n leftFromColumn: string;\n rightFromColumn: string;\n}\n\n/** `CabinLayoutType` del spec, más `aisles`, que el spec no trae. */\nexport interface SeatCabinLayout {\n columns: Array<{ id: string; position?: string[] }>;\n rows: SeatCabinRowPosition;\n wingRowPosition?: SeatCabinRowPosition[];\n exitRowPosition?: SeatCabinRowPosition[];\n seatCount?: number;\n authorizedSeatCount?: number;\n missingRowNumbers?: number[];\n missingSeats?: string[];\n facilities?: SeatCabinFacility[];\n deckCode?: string;\n /** Los pasillos. No está en el spec 3.0 (ver `SeatCabinAisle`). */\n aisles?: SeatCabinAisle[];\n}\n\n/** `CabinCompartment` del spec. */\nexport interface SeatCabinCompartment {\n firstRow?: number;\n lastRow?: number;\n columnIds?: string[];\n cabinCode?: string;\n cabinName?: string;\n cabinLayout?: SeatCabinLayout;\n seatRows?: SeatRow[];\n}\n\n/** `SeatMap` del spec. */\nexport interface SeatMap {\n /** `id` del segmento, del request o de `segments[]` de la respuesta. */\n segmentRef: string;\n /**\n * `id` de un `flightLegs[]` del segmento. En un vuelo directo, `byPnrLocator` lo manda como\n * `null` y `byReservationPayload` no lo manda (CERT, 2026-11-04, sabre-playground #11).\n */\n flightLegRef?: string | null;\n cabinCompartments?: SeatCabinCompartment[];\n}\n\n/** `SeatAvailabilityResponse` del spec 3.0. */\nexport interface SeatAvailabilityResponse {\n /** Solo lo usa `seatOffers` (NDC); por ATPCO el asiento se reserva por número. */\n offerId?: string;\n offerExpirationDateTime?: string;\n segments: SeatSegmentRs[];\n passengers: SeatPassengerRs[];\n serviceDefinitions: SeatServiceDefinition[];\n priceDefinitions?: SeatPriceDefinition[];\n offerItems: SeatOfferItem[];\n displayOnlyItems?: SeatDisplayOnlyItem[];\n seatMaps: SeatMap[];\n}\n\n/** `Error` / `Warning` del spec: la misma forma que los de Booking Management. */\nexport interface SeatAvailabilityIssue {\n category: string;\n type: string;\n description?: string;\n fieldName?: string;\n fieldPath?: string;\n /** Puede traer datos del request: no se copia a los errores del SDK. */\n fieldValue?: string;\n}\n\n/** `SeatAvailabilityRs` tal cual llega de Sabre. */\nexport interface RawSeatAvailabilityRs {\n response?: SeatAvailabilityResponse;\n errors?: SeatAvailabilityIssue[];\n warnings?: SeatAvailabilityIssue[];\n}\n\n/**\n * Resultado de `sabre.air.getSeats`: el `SeatAvailabilityRs` del spec con `errors[]` y\n * `warnings[]` reemplazados por los del SDK.\n */\nexport interface GetSeatsResponse {\n response: SeatAvailabilityResponse;\n /** `warnings[]` de Sabre. Nunca se lanzan. */\n warnings: SabreWarning[];\n /** `errors[]` que llegaron junto con un `response`: el mapa existe, pero puede faltar algo. */\n errors: SabreBusinessError[];\n}\n\n// ─── Operación ──────────────────────────────────────────────────────────────\n\n/**\n * Get Seats: una sola función que elige el endpoint según si el request trae `pnrLocator`\n * (opción C de sabre-wiki/wiki/sdk/get-seats-en-el-sdk.md). Lectura: se puede reintentar.\n */\nexport async function getSeats(\n transport: RestTransport,\n request: GetSeatsRequest,\n options: RequestOptions = {},\n): Promise<GetSeatsResponse> {\n if (!isObject(request)) {\n throw new TypeError('sabre-client: air.getSeats espera un objeto');\n }\n if ('pnrLocator' in request) {\n // Una mezcla nunca cae en silencio en un endpoint (ADR, opción C).\n if (!nonEmpty(request.pnrLocator)) {\n throw new TypeError('sabre-client: air.getSeats con pnrLocator vacío');\n }\n const mixed = PAYLOAD_FIELDS.filter((field) => field in request);\n if (mixed.length > 0) {\n throw new TypeError(`sabre-client: air.getSeats con pnrLocator no acepta ${mixed.join(', ')}`);\n }\n return send(transport, BY_PNR_LOCATOR_PATH, GET_SEATS_BY_PNR_LOCATOR_SERVICE, request, options);\n }\n if (!Array.isArray(request.segments) || !Array.isArray(request.passengers)) {\n throw new TypeError('sabre-client: air.getSeats espera { segments: [...], passengers: [...], ... } o { pnrLocator }');\n }\n return send(transport, BY_PAYLOAD_PATH, GET_SEATS_BY_PAYLOAD_SERVICE, request, options);\n}\n\nasync function send(\n transport: RestTransport,\n path: string,\n service: string,\n request: GetSeatsRequest,\n options: RequestOptions,\n): Promise<GetSeatsResponse> {\n const body = await transport.request<RawSeatAvailabilityRs>({\n method: 'POST',\n path,\n service,\n idempotent: true,\n body: request,\n classify: (raw) => classifyGetSeats(raw, service),\n ...(options.retry === undefined ? {} : { retry: options.retry }),\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, `air.${service}`),\n });\n return {\n response: body.response!,\n warnings: issues(body.warnings).map((item) => toWarning(service, item)),\n errors: issues(body.errors).map((item) => toBusinessError(service, item)),\n };\n}\n\n/**\n * Paso 3 del orden de detección, con la política para servicios sin catálogo\n * (sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md): lo que decide si se lanza es si hay\n * `response`.\n *\n * - Hay `response`: no hay error; `errors[]` y `warnings[]` van adjuntos al resultado.\n * - No hay `response`: `SabreBusinessError` con el primer elemento de `errors[]`, y el resto\n * de los errores y los `warnings[]` adjuntos. Sin catálogo, nada es reintentable.\n */\nexport function classifyGetSeats(body: unknown, service: string): SabreError | undefined {\n if (!isObject(body)) {\n return new SabreError(`${service}: respuesta malformada, se esperaba un objeto`, { retryable: false, raw: body });\n }\n const rs = body as RawSeatAvailabilityRs;\n if (isObject(rs.response)) return undefined;\n\n const [first, ...rest] = issues(rs.errors);\n if (first !== undefined) {\n return toBusinessError(service, first, {\n warnings: issues(rs.warnings).map((item) => toWarning(service, item)),\n errors: rest.map((item) => toBusinessError(service, item)),\n });\n }\n return new SabreError(`${service}: respuesta malformada, sin response ni errors`, { retryable: false, raw: body });\n}\n\nfunction issues(list: SeatAvailabilityIssue[] | undefined): SeatAvailabilityIssue[] {\n return Array.isArray(list) ? list.filter(isObject) as SeatAvailabilityIssue[] : [];\n}\n","// Reglas para fijar los vuelos de un itinerario desnormalizado, compartidas por los\n// helpers que arman requests a partir de él (Revalidate Itinerary, Create Booking).\n// Ver sabre-wiki/wiki/concepts/modelo-de-itinerario.md.\nimport type { Itinerary, ItineraryGroup, LegSchedule } from './grouped-itinerary.js';\n\n/** Un vuelo del itinerario con su fecha de salida ya resuelta y su clase de servicio. */\nexport interface ItineraryFlight {\n /** Índice del tramo (`legs[]`) al que pertenece. */\n legIndex: number;\n schedule: LegSchedule;\n /** `YYYY-MM-DD`, hora local del aeropuerto de salida. */\n departureDate: string;\n /** `YYYY-MM-DD`, hora local del aeropuerto de llegada. */\n arrivalDate: string;\n bookingCode: string;\n}\n\n/**\n * Aplana los vuelos del itinerario en orden.\n *\n * - La clase de servicio de cada vuelo sale de `fareComponents[].segments[].bookingCode` del\n * primer pasajero de la primera cotización, en el orden de los vuelos del itinerario.\n * - Las fechas salen de `legDescriptions[].departureDate` más `departureDateAdjustment` del\n * schedule (salida) y `arrival.dateAdjustment` (llegada).\n */\nexport function itineraryFlights(group: ItineraryGroup, itinerary: Itinerary): ItineraryFlight[] {\n const { legDescriptions } = group.groupDescription;\n if (legDescriptions.length !== itinerary.legs.length) {\n throw new TypeError(\n `sabre-client: el itinerario tiene ${itinerary.legs.length} tramos y el grupo ${legDescriptions.length}`,\n );\n }\n const classes = bookingCodes(itinerary);\n const flightCount = itinerary.legs.reduce((n, leg) => n + leg.schedules.length, 0);\n if (classes.length !== flightCount) {\n throw new TypeError(\n `sabre-client: el itinerario tiene ${flightCount} vuelos y ${classes.length} clases de servicio en fareComponents`,\n );\n }\n\n let next = 0;\n return itinerary.legs.flatMap((leg, legIndex) => {\n const legDate = legDescriptions[legIndex]!.departureDate;\n return leg.schedules.map((schedule) => {\n const departureDate = addDays(legDate, schedule.departureDateAdjustment ?? 0);\n return {\n legIndex,\n schedule,\n departureDate,\n arrivalDate: addDays(departureDate, schedule.arrival.dateAdjustment ?? 0),\n bookingCode: classes[next++]!,\n };\n });\n });\n}\n\nfunction bookingCodes(itinerary: Itinerary): string[] {\n const passenger = itinerary.pricingInformation[0]?.fare.passengerInfoList[0]?.passengerInfo;\n return (passenger?.fareComponents ?? []).flatMap((component) =>\n (component.segments ?? []).map(({ segment }) => {\n if (segment.bookingCode === undefined) {\n throw new TypeError('sabre-client: un segmento de fareComponents no trae bookingCode');\n }\n return segment.bookingCode;\n }),\n );\n}\n\n/** `2026-09-11` + n días, en calendario puro (sin zona horaria). */\nfunction addDays(date: string, days: number): string {\n if (days === 0) return date;\n const [year, month, day] = date.split('-').map(Number) as [number, number, number];\n return new Date(Date.UTC(year, month - 1, day + days)).toISOString().slice(0, 10);\n}\n","// Revalidate Itinerary v5 (`POST /v5/shop/flights/revalidate`).\n// Ver sabre-wiki/wiki/entities/revalidate-itinerary.md.\nimport type { SabreError } from '../errors/index.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport { BARGAIN_FINDER_MAX_CATALOG, type BargainFinderMaxRequest, type RequestOptions } from './bargain-finder-max.js';\nimport {\n denormalizeGroupedItineraryResponse,\n type GroupedItineraryResponse,\n type Itinerary,\n type ItineraryGroup,\n type RawGroupedItineraryResponse,\n} from './grouped-itinerary.js';\nimport { type ItineraryFlight, itineraryFlights } from './itinerary-flights.js';\nimport { classifyItineraryMessages, type ItineraryMessageCatalogEntry } from './itinerary-messages.js';\nimport type {\n LowFareSearchFlight,\n LowFareSearchOriginDestination,\n OtaAirLowFareSearchRq,\n} from './low-fare-search-request.js';\nimport { rawHooks } from '../http/raw-request.js';\n\nexport const REVALIDATE_ITINERARY_SERVICE = 'revalidateItinerary';\nconst PATH = '/v5/shop/flights/revalidate';\n\n/** Body de Revalidate Itinerary v5: el mismo `OTA_AirLowFareSearchRQ` que BFM, con los vuelos fijados. */\nexport interface RevalidateItineraryRequest {\n OTA_AirLowFareSearchRQ: OtaAirLowFareSearchRq;\n}\n\n/** `groupedItineraryResponse` con las referencias ya resueltas. */\nexport type RevalidateItineraryResponse = GroupedItineraryResponse;\n\nexport async function revalidateItinerary(\n transport: RestTransport,\n request: RevalidateItineraryRequest,\n options: RequestOptions = {},\n): Promise<RevalidateItineraryResponse> {\n if (typeof request !== 'object' || request === null || typeof request.OTA_AirLowFareSearchRQ !== 'object') {\n throw new TypeError('sabre-client: revalidateItinerary espera { OTA_AirLowFareSearchRQ: { ... } }');\n }\n const body = await transport.request<{ groupedItineraryResponse: RawGroupedItineraryResponse }>({\n method: 'POST',\n path: PATH,\n service: REVALIDATE_ITINERARY_SERVICE,\n // POST, pero de solo lectura: no sostiene inventario, se puede reintentar.\n idempotent: true,\n body: request,\n classify: classifyRevalidateItinerary,\n ...(options.retry === undefined ? {} : { retry: options.retry }),\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'air.revalidateItinerary'),\n });\n return denormalizeGroupedItineraryResponse(body.groupedItineraryResponse, REVALIDATE_ITINERARY_SERVICE);\n}\n\n/**\n * Catálogo de errores de Revalidate (guía oficial de errores de Revalidate Itinerary, en la\n * documentación SOAP de BFM 7.2.0; ver sabre-wiki/wiki/entities/revalidate-itinerary.md).\n * Las cinco condiciones describen un dato que no existe (tarifa, horario o disponibilidad):\n * reintentar no cambia el resultado. En producción, `NO FARE FOR CLASS USED` llegó con\n * `code: 'PROCESS'`; el catálogo le da un `code` estable.\n *\n * Los temporales se heredan de BFM (mismo motor), con `retryable: true`.\n */\nexport const REVALIDATE_ITINERARY_CATALOG: ReadonlyArray<ItineraryMessageCatalogEntry> = [\n { code: 'NO COMBINABLE FARES FOR CLASS USED', retryable: false },\n { code: 'NO FARE FOR CLASS USED', retryable: false },\n { code: 'NO FLIGHT SCHEDULES FOR QUALIFIERS USED', retryable: false },\n { code: 'NO SUCH FLIGHT', retryable: false },\n { code: 'NO AVAILABILITY', retryable: false },\n ...BARGAIN_FINDER_MAX_CATALOG.filter((entry) => entry.retryable),\n];\n\n/** Ver `classifyItineraryMessages`. */\nexport function classifyRevalidateItinerary(body: unknown): SabreError | undefined {\n return classifyItineraryMessages(body, REVALIDATE_ITINERARY_SERVICE, REVALIDATE_ITINERARY_CATALOG);\n}\n\nexport interface RevalidateItineraryRequestSource {\n /** Request de BFM que produjo el itinerario: aporta `Version`, `POS`, pasajeros y `TPA_Extensions`. */\n search: BargainFinderMaxRequest;\n /** Grupo del itinerario: aporta la fecha de cada tramo. */\n group: ItineraryGroup;\n itinerary: Itinerary;\n}\n\n/**\n * Arma el request de Revalidate Itinerary para un itinerario devuelto por BFM, fijando cada\n * vuelo en `OriginDestinationInformation[].TPA_Extensions.Flight[]`.\n *\n * - Clases de servicio y fechas: ver `itineraryFlights`. Las horas salen de `time` sin el offset.\n * - `MaxStopsQuantity` es el máximo de conexiones de un tramo, para no rechazar itinerarios\n * con escala.\n * - `Fixed: false` y `VerificationItinCallLogic: \"L\"` se copian del ejemplo de Sabre; su\n * efecto no está documentado.\n */\nexport function buildRevalidateItineraryRequest(source: RevalidateItineraryRequestSource): RevalidateItineraryRequest {\n const { search, group, itinerary } = source;\n const flights = itineraryFlights(group, itinerary);\n\n const originDestinations = itinerary.legs.map((_leg, i): LowFareSearchOriginDestination => {\n const legFlights = flights.filter((f) => f.legIndex === i).map(flight);\n const first = legFlights[0]!;\n const last = legFlights.at(-1)!;\n return {\n Fixed: false,\n DepartureDateTime: first.DepartureDateTime,\n OriginLocation: { LocationCode: first.OriginLocation.LocationCode },\n DestinationLocation: { LocationCode: last.DestinationLocation.LocationCode },\n TPA_Extensions: { Flight: legFlights },\n };\n });\n\n const { Version, POS, TravelerInfoSummary, TPA_Extensions } = search.OTA_AirLowFareSearchRQ;\n return {\n OTA_AirLowFareSearchRQ: {\n Version,\n POS,\n OriginDestinationInformation: originDestinations,\n TravelPreferences: {\n MaxStopsQuantity: Math.max(...itinerary.legs.map((leg) => leg.schedules.length - 1)),\n TPA_Extensions: { VerificationItinCallLogic: { Value: 'L' } },\n },\n TravelerInfoSummary,\n ...(TPA_Extensions === undefined ? {} : { TPA_Extensions }),\n },\n };\n}\n\nfunction flight({ schedule, departureDate, arrivalDate, bookingCode }: ItineraryFlight): LowFareSearchFlight {\n const { carrier } = schedule;\n return {\n Type: 'A',\n Number: carrier.marketingFlightNumber,\n DepartureDateTime: `${departureDate}T${localTime(schedule.departure.time)}`,\n ArrivalDateTime: `${arrivalDate}T${localTime(schedule.arrival.time)}`,\n ClassOfService: bookingCode,\n OriginLocation: { LocationCode: schedule.departure.airport },\n DestinationLocation: { LocationCode: schedule.arrival.airport },\n Airline: {\n Marketing: carrier.marketing,\n ...(carrier.operating === undefined ? {} : { Operating: carrier.operating }),\n },\n };\n}\n\n/** `17:10:00+02:00` → `17:10:00`. */\nfunction localTime(time: string): string {\n return time.slice(0, 8);\n}\n","// Módulo de dominio `sabre.air`. Ver sabre-wiki/wiki/sdk/convenciones-de-nombres-y-versionado.md.\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n bargainFinderMax,\n type BargainFinderMaxRequest,\n type BargainFinderMaxResponse,\n type RequestOptions,\n} from './bargain-finder-max.js';\nimport { getSeats, type GetSeatsRequest, type GetSeatsResponse } from './get-seats.js';\nimport {\n revalidateItinerary,\n type RevalidateItineraryRequest,\n type RevalidateItineraryResponse,\n} from './revalidate-itinerary.js';\n\nexport class Air {\n readonly #transport: RestTransport;\n\n /** @internal Lo construye el cliente `Sabre`. */\n constructor(transport: RestTransport) {\n this.#transport = transport;\n }\n\n /**\n * Bargain Finder Max v5: busca itinerarios de menor precio. Devuelve el\n * `groupedItineraryResponse` con las referencias ya resueltas.\n */\n bargainFinderMax(request: BargainFinderMaxRequest, options?: RequestOptions): Promise<BargainFinderMaxResponse> {\n return bargainFinderMax(this.#transport, request, options);\n }\n\n /**\n * Revalidate Itinerary v5: revalida disponibilidad y precio de un itinerario ya elegido,\n * sin sostener inventario. El request se arma con `buildRevalidateItineraryRequest`.\n */\n revalidateItinerary(\n request: RevalidateItineraryRequest,\n options?: RequestOptions,\n ): Promise<RevalidateItineraryResponse> {\n return revalidateItinerary(this.#transport, request, options);\n }\n\n /**\n * Get Seats v3: mapa de asientos con disponibilidad y precio. Sin `pnrLocator` va a\n * `byReservationPayload`, armado con `buildSeatAvailabilityRequest`; con `pnrLocator`, a\n * `byPnrLocator`. Un `pnrLocator` vacío o mezclado con `segments`, `passengers` o\n * `returnSeatMapsOnlyForSegmentRefs` lanza `TypeError` sin llamar a la red.\n */\n getSeats(request: GetSeatsRequest, options?: RequestOptions): Promise<GetSeatsResponse> {\n return getSeats(this.#transport, request, options);\n }\n}\n","// Redacción obligatoria antes de que cualquier dato llegue al logger.\n// Ver sabre-wiki/wiki/sdk/configuracion-logging-y-build.md.\n\nexport const REDACTED = '[REDACTED]';\n\n/**\n * Claves cuyo valor se enmascara completo, comparadas sin distinguir mayúsculas\n * ni separadores (`client_secret`, `Client-Secret` y `clientSecret` son la misma).\n */\nconst SENSITIVE_KEYS = new Set(\n [\n // Credenciales\n 'clientSecret',\n 'password',\n 'username',\n 'authorization',\n 'binarySecurityToken',\n 'accessToken',\n 'refreshToken',\n 'token',\n // Datos de pasajero\n 'travelers',\n 'passengers',\n ].map(normalizeKey),\n);\n\nfunction normalizeKey(key: string): string {\n return key.replace(/[-_\\s]/g, '').toLowerCase();\n}\n\nexport function isSensitiveKey(key: string): boolean {\n return SENSITIVE_KEYS.has(normalizeKey(key));\n}\n\n/** Copia profunda de `value` con los campos sensibles enmascarados. No muta la entrada. */\nexport function redact(value: unknown): unknown {\n return redactValue(value, new WeakSet());\n}\n\nfunction redactValue(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null || typeof value !== 'object') return value;\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n\n if (Array.isArray(value)) return value.map((item) => redactValue(item, seen));\n if (value instanceof Headers) return redactEntries(value.entries(), seen);\n if (value instanceof Date) return value.toISOString();\n if (value instanceof Error) {\n // Los errores del SDK definen toJSON sin `raw`; para el resto, solo nombre y mensaje.\n const json = 'toJSON' in value && typeof value.toJSON === 'function' ? value.toJSON() : undefined;\n return redactValue(json ?? { name: value.name, message: value.message }, seen);\n }\n return redactEntries(Object.entries(value), seen);\n}\n\nfunction redactEntries(entries: Iterable<[string, unknown]>, seen: WeakSet<object>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, item] of entries) {\n out[key] = isSensitiveKey(key) ? REDACTED : redactValue(item, seen);\n }\n return out;\n}\n\n/**\n * Elemento `BinarySecurityToken` con cualquier prefijo (o ninguno), sin contar el\n * autocerrado. Los atributos admiten valores entre comillas con `>` adentro. El cierre\n * acepta cualquier prefijo: ante un sobre mal formado, conviene tapar de más.\n */\nconst BINARY_SECURITY_TOKEN =\n /(<(?:[A-Za-z_][\\w.-]*:)?BinarySecurityToken(?=[\\s/>])(?:[^>\"']|\"[^\"]*\"|'[^']*')*(?<!\\/)>)([\\s\\S]*?)(<\\/(?:[A-Za-z_][\\w.-]*:)?BinarySecurityToken\\s*>)/g;\n\n/**\n * Reemplaza el valor de cada `BinarySecurityToken` del sobre SOAP por `[REDACTED]`.\n *\n * Trabaja sobre el texto, sin parsear ni volver a serializar: el resto del sobre queda byte\n * a byte (indentación, orden de atributos, prefijos y `eb:MessageHeader`). Un sobre sin\n * token, o con el token vacío, vuelve idéntico. Ver sabre-wiki/wiki/sdk/respuesta-cruda-soap.md\n * (opción D).\n */\nexport function redactSoapEnvelope(envelope: string): string {\n return envelope.replace(BINARY_SECURITY_TOKEN, (match, open: string, value: string, close: string) =>\n value.trim() === '' ? match : `${open}${REDACTED}${close}`,\n );\n}\n","// Logger inyectable. Ver sabre-wiki/wiki/sdk/configuracion-logging-y-build.md.\nimport { redact } from './redact.js';\n\n/**\n * Interfaz mínima de logger, compatible con `winston` y `console`.\n * Con `pino`, que invierte el orden: `info: (m, c) => pino.info(c, m)`.\n */\nexport interface SabreLogger {\n debug(message: string, context?: Record<string, unknown>): void;\n info(message: string, context?: Record<string, unknown>): void;\n warn(message: string, context?: Record<string, unknown>): void;\n error(message: string, context?: Record<string, unknown>): void;\n}\n\nexport type SabreLogLevel = keyof SabreLogger;\n\n/** Eventos estables que emite el SDK como `message`. */\nexport type SabreLogEvent =\n | 'sabre.request.start'\n | 'sabre.request.end'\n | 'sabre.request.retry'\n | 'sabre.request.rawResponseHookFailed'\n | 'sabre.request.rawRequestHookFailed'\n | 'sabre.auth.token.refresh'\n | 'sabre.auth.token.store'\n | 'sabre.booking.seat.priced'\n | 'sabre.session.open'\n | 'sabre.session.close'\n | 'sabre.session.closeFailed'\n | 'sabre.session.keepAliveFailed'\n | 'sabre.session.command'\n | 'sabre.queue.exitTolerated'\n | 'sabre.queue.exitFailed';\n\n/** Logger interno: redacta siempre el contexto y no hace nada si no hay logger. */\nexport class EventLogger {\n readonly #logger: SabreLogger | undefined;\n\n constructor(logger?: SabreLogger) {\n this.#logger = logger;\n }\n\n emit(level: SabreLogLevel, event: SabreLogEvent, context: Record<string, unknown> = {}): void {\n if (this.#logger === undefined) return;\n try {\n this.#logger[level](event, redact(context) as Record<string, unknown>);\n } catch {\n // Un logger que falla no debe romper la request en curso.\n }\n }\n}\n","// Armado de la request de OAuth Token Create, una estrategia por versión.\n// Ver sabre-wiki/wiki/entities/oauth-token-create.md: v2 y v3 no son intercambiables.\nimport type { SabreAuthVersion, SabreCredentials, SabreCredentialsV2 } from '../config.js';\n\nexport interface TokenRequest {\n path: string;\n /** Valor del header `Authorization` (`Basic ...`). */\n authorization: string;\n body: URLSearchParams;\n}\n\n/** v3: `Basic base64(clientId:clientSecret)` y el EPR en el body con `grant_type=password`. */\nexport function buildTokenRequestV3(credentials: SabreCredentials): TokenRequest {\n return {\n path: '/v3/auth/token',\n authorization: `Basic ${base64(`${credentials.clientId}:${credentials.clientSecret}`)}`,\n body: new URLSearchParams({\n grant_type: 'password',\n username: credentials.username,\n password: credentials.password,\n }),\n };\n}\n\n/** v2: doble Base64 sobre el EPR y su password, con `grant_type=client_credentials`. */\nexport function buildTokenRequestV2(credentials: SabreCredentialsV2): TokenRequest {\n return {\n path: '/v2/auth/token',\n authorization: `Basic ${base64(`${base64(credentials.username)}:${base64(credentials.password)}`)}`,\n body: new URLSearchParams({ grant_type: 'client_credentials' }),\n };\n}\n\nexport function buildTokenRequest(\n authVersion: SabreAuthVersion,\n credentials: SabreCredentials | SabreCredentialsV2,\n): TokenRequest {\n // `resolveConfig` ya exige clientId/clientSecret cuando la versión es v3.\n return authVersion === 'v3'\n ? buildTokenRequestV3(credentials as SabreCredentials)\n : buildTokenRequestV2(credentials as SabreCredentialsV2);\n}\n\n/** Base64 de los bytes UTF-8 de `text`, solo con Web APIs (sin `Buffer`). */\nexport function base64(text: string): string {\n let binary = '';\n for (const byte of new TextEncoder().encode(text)) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n","// Almacén de token inyectable por el consumidor. Ver sabre-wiki/wiki/sdk/renovacion-token-oauth.md,\n// sección \"Decisiones de la Fase 4\" (decisión B).\nimport type { SabreAuthVersion, SabreCredentials, SabreCredentialsV2, SabreEnvironment } from '../config.js';\n\n/** Token ATK tal cual se guarda: tiempos absolutos, para que otro proceso sepa cuánto le queda. */\nexport interface StoredToken {\n accessToken: string;\n /** Momento de obtención, en ms desde epoch. */\n obtainedAt: number;\n /** Momento de expiración, en ms desde epoch. */\n expiresAt: number;\n}\n\n/**\n * Almacén de token del consumidor (archivo, Redis, KV…). El SDK no trae implementaciones.\n *\n * `key` identifica la configuración (entorno, versión de OAuth y credencial, sin secretos):\n * un mismo store puede servir a varios clientes sin mezclar sus tokens. El token es un\n * secreto: protegerlo dentro del store es responsabilidad del consumidor.\n *\n * Si `get` o `set` lanzan, el SDK sigue con su caché en memoria: el store nunca rompe una llamada.\n */\nexport interface SabreTokenStore {\n get(key: string): Promise<StoredToken | undefined>;\n set(key: string, token: StoredToken): Promise<void>;\n}\n\n/**\n * `sabre-client:<environment>:<authVersion>:<hash>`, donde `hash` son los primeros 16 bytes\n * en hex del SHA-256 del username EPR (y del clientId en v3). No contiene secretos.\n */\nexport async function tokenStoreKey(\n environment: SabreEnvironment,\n authVersion: SabreAuthVersion,\n credentials: Readonly<SabreCredentials | SabreCredentialsV2>,\n): Promise<string> {\n const identity = authVersion === 'v3' ? `${credentials.clientId}\\n${credentials.username}` : credentials.username;\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(identity));\n const hash = [...new Uint8Array(digest).slice(0, 16)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n return `sabre-client:${environment}:${authVersion}:${hash}`;\n}\n\n/** Un valor de `get` que no tenga la forma de `StoredToken` se ignora. */\nexport function isStoredToken(value: unknown): value is StoredToken {\n if (typeof value !== 'object' || value === null) return false;\n const { accessToken, obtainedAt, expiresAt } = value as Record<string, unknown>;\n return (\n typeof accessToken === 'string' &&\n accessToken !== '' &&\n typeof obtainedAt === 'number' &&\n typeof expiresAt === 'number' &&\n Number.isFinite(obtainedAt) &&\n expiresAt > obtainedAt\n );\n}\n","// Obtención del token ATK de OAuth Token Create.\n// Ver sabre-wiki/wiki/sdk/renovacion-token-oauth.md y wiki/entities/oauth-token-create.md.\nimport type { ResolvedConfig } from '../config.js';\nimport { SabreGatewayError } from '../errors/index.js';\nimport type { AuthorizationProvider, RestTransport } from '../http/rest-transport.js';\nimport { EventLogger } from '../logging/logger.js';\nimport { buildTokenRequest } from './token-request.js';\nimport { isStoredToken, type SabreTokenStore, type StoredToken, tokenStoreKey } from './token-store.js';\n\nexport const TOKEN_SERVICE = 'oauthTokenCreate';\n\n/** Margen de refresco proactivo: 1 h antes de expirar (o media vida si el token dura menos). */\nexport const REFRESH_THRESHOLD_S = 3600;\n\nexport type TokenRefreshReason = 'initial' | 'proactive' | 'reactive';\n\n/** Token ATK obtenido de OAuth Token Create. */\nexport interface AccessToken {\n accessToken: string;\n /** Vida del token en segundos, tal cual llega en `expires_in`. */\n expiresIn: number;\n /** Momento de obtención, en ms desde epoch. */\n obtainedAt: number;\n}\n\ninterface TokenResponse {\n access_token?: unknown;\n expires_in?: unknown;\n token_type?: unknown;\n}\n\nexport interface AuthManagerOptions {\n /** Solo para tests: reloj en ms. */\n now?: () => number;\n}\n\n/**\n * Cachea el token en memoria (y en `tokenStore`, si lo hay), lo renueva antes de que expire\n * y comparte una sola petición en vuelo entre requests concurrentes. Interno en v0.3.0.\n */\nexport class AuthManager {\n readonly #config: ResolvedConfig;\n readonly #transport: RestTransport;\n readonly #now: () => number;\n readonly #log: EventLogger;\n #token: AccessToken | undefined;\n #inFlight: Promise<AccessToken> | undefined;\n /** El último token cacheado fue rechazado con 401 (el próximo refresco es reactivo). */\n #invalidated = false;\n /** Token rechazado con 401: si el store todavía lo tiene, no se vuelve a usar. */\n #rejected: string | undefined;\n readonly #store: SabreTokenStore | undefined;\n #storeKey: Promise<string> | undefined;\n\n constructor(config: ResolvedConfig, transport: RestTransport, options: AuthManagerOptions = {}) {\n this.#config = config;\n this.#transport = transport;\n this.#now = options.now ?? Date.now;\n this.#log = new EventLogger(config.logger);\n this.#store = config.tokenStore;\n }\n\n /** Token vigente; pide uno nuevo si no hay o si cruzó el umbral de refresco. */\n async getToken(): Promise<string> {\n const token = this.#token;\n if (token !== undefined && !this.#needsRefresh(token)) return token.accessToken;\n const reason = token !== undefined ? 'proactive' : this.#invalidated ? 'reactive' : 'initial';\n return (await this.#refresh(reason)).accessToken;\n }\n\n /**\n * Descarta `accessToken` tras un 401 de un servicio. Si el caché ya tiene otro token\n * (otra request lo renovó), no hace nada: los 401 concurrentes comparten un refresco.\n */\n invalidate(accessToken: string): void {\n if (this.#token?.accessToken !== accessToken) return;\n this.#token = undefined;\n this.#invalidated = true;\n this.#rejected = accessToken;\n }\n\n /** Adaptador de salida para el transporte REST: `Authorization: Bearer <token>`. */\n bearerProvider(): AuthorizationProvider {\n return {\n get: async () => `Bearer ${await this.getToken()}`,\n invalidate: (authorization) => this.invalidate(authorization.replace(/^Bearer /, '')),\n };\n }\n\n #needsRefresh(token: AccessToken): boolean {\n const thresholdMs = Math.min(REFRESH_THRESHOLD_S, token.expiresIn / 2) * 1000;\n return this.#now() >= token.obtainedAt + token.expiresIn * 1000 - thresholdMs;\n }\n\n /** Una sola petición en vuelo: las llamadas concurrentes esperan la misma promesa. */\n #refresh(reason: TokenRefreshReason): Promise<AccessToken> {\n this.#inFlight ??= this.#obtain(reason).finally(() => {\n this.#inFlight = undefined;\n });\n return this.#inFlight;\n }\n\n /** Token del store si sigue vigente (otro proceso pudo renovarlo); si no, uno nuevo. */\n async #obtain(reason: TokenRefreshReason): Promise<AccessToken> {\n const stored = await this.#readStore();\n if (stored !== undefined && stored.accessToken !== this.#rejected && !this.#needsRefresh(stored)) {\n this.#token = stored;\n this.#invalidated = false;\n return stored;\n }\n\n const token = await this.fetchToken();\n this.#token = token;\n this.#invalidated = false;\n this.#rejected = undefined;\n this.#log.emit('info', 'sabre.auth.token.refresh', {\n authVersion: this.#config.authVersion,\n reason,\n expiresIn: token.expiresIn,\n });\n await this.#writeStore(token);\n return token;\n }\n\n async #readStore(): Promise<AccessToken | undefined> {\n if (this.#store === undefined) return undefined;\n try {\n const value = await this.#store.get(await this.#key());\n if (!isStoredToken(value)) return undefined;\n return {\n accessToken: value.accessToken,\n expiresIn: (value.expiresAt - value.obtainedAt) / 1000,\n obtainedAt: value.obtainedAt,\n };\n } catch (error) {\n this.#storeFailed('get', error);\n return undefined;\n }\n }\n\n async #writeStore(token: AccessToken): Promise<void> {\n if (this.#store === undefined) return;\n const stored: StoredToken = {\n accessToken: token.accessToken,\n obtainedAt: token.obtainedAt,\n expiresAt: token.obtainedAt + token.expiresIn * 1000,\n };\n try {\n await this.#store.set(await this.#key(), stored);\n } catch (error) {\n this.#storeFailed('set', error);\n }\n }\n\n #key(): Promise<string> {\n const { environment, authVersion, credentials } = this.#config;\n this.#storeKey ??= tokenStoreKey(environment, authVersion, credentials);\n return this.#storeKey;\n }\n\n /**\n * El store nunca rompe la llamada: se sigue con el caché en memoria. Del error solo se\n * loguea el nombre: el mensaje lo arma el store del consumidor y podría traer el token.\n */\n #storeFailed(operation: 'get' | 'set', error: unknown): void {\n this.#log.emit('warn', 'sabre.auth.token.store', {\n authVersion: this.#config.authVersion,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n\n /**\n * Pide un token nuevo. Los errores del endpoint (`invalid_request`/`invalid_client` 401,\n * `unauthorized` 403) salen como `SabreGatewayError` con `retryable: false`.\n */\n async fetchToken(): Promise<AccessToken> {\n const { path, authorization, body } = buildTokenRequest(this.#config.authVersion, this.#config.credentials);\n const response = await this.#transport.request<TokenResponse | undefined>({\n method: 'POST',\n path,\n service: TOKEN_SERVICE,\n // Pedir otro token no tiene efectos duplicados: 429/5xx entran en la política genérica.\n idempotent: true,\n auth: false,\n headers: { Authorization: authorization },\n body,\n });\n return this.#parse(response);\n }\n\n #parse(response: TokenResponse | undefined): AccessToken {\n const accessToken = response?.access_token;\n const expiresIn = response?.expires_in;\n if (typeof accessToken !== 'string' || accessToken === '' || typeof expiresIn !== 'number' || !(expiresIn > 0)) {\n throw new SabreGatewayError(`${TOKEN_SERVICE}: respuesta sin access_token/expires_in válidos`, {\n protocol: 'rest',\n status: 200,\n retryable: false,\n raw: response,\n });\n }\n return { accessToken, expiresIn, obtainedAt: this.#now() };\n }\n}\n","// Cancel Booking (`POST /v1/trip/orders/cancelBooking`).\n// Ver sabre-wiki/wiki/sdk/gestion-de-reserva.md y sabre-wiki/wiki/sources/cancel-booking.md.\nimport { SabreError, type SabreWarning } from '../errors/index.js';\nimport type { SabreRawResponseCallback } from '../http/raw-response.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n type BookingResponseError,\n isObject,\n isWarning,\n nonEmpty,\n responseErrors,\n toBusinessError,\n toWarning,\n} from './booking-errors.js';\nimport type { Booking } from './create-booking.js';\nimport type { BookingSource } from './get-booking.js';\nimport { rawHooks, type SabreRawRequestCallback } from '../http/raw-request.js';\n\nexport const CANCEL_BOOKING_SERVICE = 'cancelBooking';\nconst PATH = '/v1/trip/orders/cancelBooking';\n/** Llega con `category: WARNING`, pero significa que no se canceló nada (decidido en #39). */\nconst NO_ITEMS_CANCELLED = 'NO_ITEMS_CANCELLED';\nconst ITEM_LISTS = ['flights', 'hotels', 'cars', 'trains', 'cruises', 'segments'] as const;\n\n/** `HALT_ON_ERROR` (default de Sabre, con rollback) o `ALLOW_PARTIAL_CANCEL`. */\nexport type CancelBookingErrorPolicy = 'HALT_ON_ERROR' | 'ALLOW_PARTIAL_CANCEL';\n\nexport type FlightTicketOperation = 'VOID' | 'REFUND';\n\nexport type RefundDocumentsType = 'Tickets' | 'EMDs' | 'Tickets and EMDs';\n\n/** Producto a cancelar, por el `itemId` que devuelve Get Booking (p. ej. `flights[].itemId`). */\nexport interface BookingItemReference {\n itemId: string;\n}\n\n/**\n * Segmento a cancelar, por `id` o por `sequence`. Sabre desaconseja `sequence`: la posición\n * puede cambiar entre la lectura y la cancelación.\n */\nexport interface CancelSegmentReference {\n id?: string;\n sequence?: number;\n}\n\n/** `Notification` del spec: `email` o `queuePlacement`, no los dos. Se envía tal cual. */\nexport interface CancelBookingNotification {\n email?: 'DEFAULT' | 'INVOICE' | 'ETICKET' | 'ETICKET_PDF' | 'ITINERARY' | 'ITINERARY_PDF';\n queuePlacement?: Array<Record<string, unknown>>;\n}\n\n/**\n * `CancelBookingRequest` del spec v1.33. El Tier 1 usa `cancelAll` o `flights[].itemId` sobre\n * contenido ATPCO; los campos de tickets, NDC, impresoras, notificación y retención se envían\n * tal cual, sin lógica propia.\n */\nexport interface CancelBookingRequest {\n /** Localizador del PNR u Order ID (`^[A-Z0-9]{6,}$`). Único campo obligatorio. */\n confirmationId: string;\n bookingSource?: BookingSource;\n /** Cancela todos los segmentos. No se combina con las listas. */\n cancelAll?: boolean;\n flights?: BookingItemReference[];\n hotels?: BookingItemReference[];\n cars?: BookingItemReference[];\n trains?: BookingItemReference[];\n cruises?: BookingItemReference[];\n segments?: CancelSegmentReference[];\n /** Sin valor, Sabre aplica `HALT_ON_ERROR`: si algo falla, deshace lo ya cancelado. */\n errorHandlingPolicy?: CancelBookingErrorPolicy;\n /** Si es `true`, la respuesta trae el estado posterior en `booking`. */\n retrieveBooking?: boolean;\n /** Firma del cambio en el PNR. Sabre usa `LW CANCEL API` por defecto. */\n receivedFrom?: string;\n /** El contexto no se revierte al terminar. */\n targetPcc?: string;\n /** No se combina con `offerItemId`. */\n flightTicketOperation?: FlightTicketOperation;\n /** Solo NDC. No se combina con `flightTicketOperation`. */\n offerItemId?: string;\n notification?: CancelBookingNotification;\n designatePrinters?: Array<Record<string, unknown>>;\n retentionEndDate?: string;\n retentionLabel?: string;\n voidNonElectronicTickets?: boolean;\n refundDocumentsType?: RefundDocumentsType;\n}\n\nexport interface CancelBookingOptions {\n signal?: AbortSignal;\n /** Respuesta cruda del último intento HTTP. El body trae PII: ver `SabreRawResponse`. */\n onRawResponse?: SabreRawResponseCallback;\n /** Request crudo del último intento que se mandó, sin `Authorization`. Trae PII: ver `SabreRawRequest`. */\n onRawRequest?: SabreRawRequestCallback;\n}\n\n/** `CancelBookingResponse` tal cual llega de Sabre. */\nexport interface RawCancelBookingResponse {\n timestamp?: string;\n request?: CancelBookingRequest;\n booking?: Booking;\n tickets?: Array<Record<string, unknown>>;\n voidedTickets?: string[];\n refundedTickets?: string[];\n flightRefunds?: Array<Record<string, unknown>>;\n errors?: BookingResponseError[];\n}\n\n/** Cancelación con éxito: sin errores fatales y sin `NO_ITEMS_CANCELLED`. */\nexport interface CancelBookingResponse {\n timestamp?: string;\n /** Eco del request con los defaults de Sabre completados. */\n request?: CancelBookingRequest;\n /** Estado posterior de la reserva, anidado (solo con `retrieveBooking: true`). */\n booking?: Booking;\n tickets?: Array<Record<string, unknown>>;\n voidedTickets?: string[];\n refundedTickets?: string[];\n flightRefunds?: Array<Record<string, unknown>>;\n /**\n * Elementos de `errors[]` con `category: WARNING`. Con `END_TRANSACTION_PROBLEM` la\n * confirmación quedó pendiente: verifica el resultado con `sabre.booking.get`.\n */\n warnings: SabreWarning[];\n}\n\n/**\n * Cancel Booking: escritura sin reintento automático. Solo el reintento reactivo ante 401,\n * que el gateway rechaza antes de llegar al proveedor.\n */\nexport async function cancelBooking(\n transport: RestTransport,\n request: CancelBookingRequest,\n options: CancelBookingOptions = {},\n): Promise<CancelBookingResponse> {\n validateCancelBookingRequest(request);\n const body = await transport.request<RawCancelBookingResponse>({\n method: 'POST',\n path: PATH,\n service: CANCEL_BOOKING_SERVICE,\n idempotent: false,\n body: request,\n classify: classifyCancelBooking,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'booking.cancel'),\n });\n return toCancelBookingResponse(body);\n}\n\n/** Combinaciones que Sabre rechaza seguro (`INVALID_FLAGS_COMBINATION`, `CANCEL_DATA_MISSING`). */\nfunction validateCancelBookingRequest(request: CancelBookingRequest): void {\n if (!isObject(request) || !nonEmpty(request.confirmationId)) {\n throw new TypeError('sabre-client: booking.cancel espera { confirmationId: string, ... }');\n }\n const lists = ITEM_LISTS.join(', ');\n if (request.cancelAll === true) {\n if (ITEM_LISTS.some((list) => request[list] !== undefined)) {\n throw new TypeError(`sabre-client: booking.cancel no combina cancelAll con listas (${lists})`);\n }\n } else if (!ITEM_LISTS.some((list) => Array.isArray(request[list]) && request[list].length > 0)) {\n throw new TypeError(`sabre-client: booking.cancel necesita cancelAll: true o al menos una lista (${lists})`);\n }\n if (request.offerItemId !== undefined && request.flightTicketOperation !== undefined) {\n throw new TypeError('sabre-client: booking.cancel no combina offerItemId con flightTicketOperation');\n }\n}\n\n/**\n * Paso 3 del orden de detección. Éxito = ningún error que no sea `WARNING` y ningún\n * `NO_ITEMS_CANCELLED`. Si no:\n *\n * - Con `NO_ITEMS_CANCELLED`: `SabreBusinessError` con ese código; los errores que explican\n * el fallo van en `errors` y los demás avisos en `warnings`.\n * - Sin él: `SabreBusinessError` con el primer error que no sea `WARNING`, el resto en\n * `errors` y los avisos en `warnings`.\n */\nexport function classifyCancelBooking(body: unknown): SabreError | undefined {\n if (!isObject(body)) {\n return new SabreError(`${CANCEL_BOOKING_SERVICE}: respuesta malformada, se esperaba un objeto`, {\n retryable: false,\n raw: body,\n });\n }\n const items = responseErrors(body as RawCancelBookingResponse);\n const nothingCancelled = items.find(isNoItemsCancelled);\n const warnings = items.filter((item) => isWarning(item) && !isNoItemsCancelled(item)).map(warningOf);\n const fatal = items.filter((item) => !isWarning(item));\n\n if (nothingCancelled !== undefined) {\n return toBusinessError(CANCEL_BOOKING_SERVICE, nothingCancelled, { warnings, errors: fatal.map(errorOf) });\n }\n const [first, ...rest] = fatal;\n if (first === undefined) return undefined;\n return toBusinessError(CANCEL_BOOKING_SERVICE, first, { warnings, errors: rest.map(errorOf) });\n}\n\n/** Solo para respuestas con éxito (ver `classifyCancelBooking`): `errors[]` trae solo avisos. */\nfunction toCancelBookingResponse(body: RawCancelBookingResponse): CancelBookingResponse {\n const { errors: _errors, ...rest } = body;\n return { ...rest, warnings: responseErrors(body).map(warningOf) };\n}\n\nfunction isNoItemsCancelled(item: BookingResponseError): boolean {\n return item.type === NO_ITEMS_CANCELLED;\n}\n\nfunction warningOf(item: BookingResponseError): SabreWarning {\n return toWarning(CANCEL_BOOKING_SERVICE, item);\n}\n\nfunction errorOf(item: BookingResponseError) {\n return toBusinessError(CANCEL_BOOKING_SERVICE, item);\n}\n","// Armado de `flightDetails` de Create Booking desde un itinerario de BFM/Revalidate.\n// El mapeo está inferido, ninguna fuente lo documenta: ver la tabla \"Mapeo desde un\n// itinerario de BFM/Revalidate → flightDetails\" en sabre-wiki/wiki/entities/booking-management-api.md.\nimport type { GetSeatsResponse } from '../air/get-seats.js';\nimport type { Itinerary, ItineraryGroup } from '../air/grouped-itinerary.js';\nimport { itineraryFlights } from '../air/itinerary-flights.js';\nimport type { FlightDetails, FlightToBook, PassengerPricing, PriceComparison } from './create-booking-request.js';\n\n/** Patrón de `BookGenericSeat.number` en el spec de Booking Management. */\nconst SEAT_NUMBER = /^[0-9]+[A-Z]$/;\n\n/** Asiento elegido para un vuelo del itinerario. */\nexport interface BookingSeatSelection {\n /**\n * Número del vuelo en el itinerario, empezando en 1 (`1` es `flights[0]`). Misma base que\n * `travelerIndex`, para no confundirlos.\n */\n segmentIndex: number;\n /** Número del viajero en `travelers[]` de Create Booking, empezando en 1 (lo fija el spec). */\n travelerIndex: number;\n /** Fila y columna, p. ej. `13A`. */\n number: string;\n}\n\n/** Asiento elegido que tiene precio en Get Seats. Sin datos del pasajero. */\nexport interface PricedSeat {\n /** Empieza en 1, como en `BookingSeatSelection`. */\n segmentIndex: number;\n /** Vuelo comercializador, p. ej. `AA1234`. */\n flight: string;\n seat: string;\n amount: string;\n currencyCode: string;\n}\n\n/**\n * Asientos con precio de cada `FlightDetails` armado por `buildBookingFlightDetails`. El\n * helper es puro y no tiene logger: `booking.create` los busca acá y emite el `warn` con el\n * logger del cliente. Si el objeto se clona, el aviso se pierde; el request no cambia.\n */\nconst pricedSeats = new WeakMap<FlightDetails, PricedSeat[]>();\n\n/** @internal Para `booking.create`. */\nexport function pricedSeatsOf(details: FlightDetails | undefined): PricedSeat[] {\n return details === undefined ? [] : (pricedSeats.get(details) ?? []);\n}\n\nexport interface BookingFlightDetailsSource {\n /** Grupo del itinerario: aporta la fecha de cada tramo. */\n group: ItineraryGroup;\n /** Itinerario elegido, idealmente el devuelto por Revalidate Itinerary. */\n itinerary: Itinerary;\n /**\n * Umbral de precio. `desiredAmount` sale de `totalFare.totalPrice` del itinerario. El spec no\n * tiene campo de moneda: se supone la del pricing (la del PCC, salvo `currencyPricing`).\n */\n priceComparison?: Omit<PriceComparison, 'desiredAmount'>;\n /**\n * Asientos por número, para `flights[segmentIndex - 1].seats[]` (camino ATPCO; `seatOffers` es\n * solo NDC). Conviene elegir asientos sin cargo: no se sabe qué hace Sabre con uno cobrable.\n */\n seats?: BookingSeatSelection[];\n /**\n * Respuesta de `sabre.air.getSeats` para el mismo itinerario. Si un asiento elegido tiene\n * precio ahí, `booking.create` emite `sabre.booking.seat.priced` (`warn`) y reserva igual.\n */\n seatAvailability?: GetSeatsResponse;\n}\n\n/**\n * Arma `flightDetails` para reservar por el camino ATPCO un itinerario ya revalidado.\n *\n * - `flights[]`: vuelo comercializador, aeropuertos, fecha y clase con las mismas reglas que\n * Revalidate (`itineraryFlights`); `departureTime` en `HH:MM` y `flightStatusCode: 'NN'`.\n * `isMarriageGroup` no se manda: no hay fuente para él.\n * - `flightPricing[0].qualifiers`: `passengersPricing` desde `passengerInfoList` y\n * `validatingAirlineCode` desde `validatingCarrierCode` de la primera cotización.\n * - `seats`: se validan sin llamar a Sabre (`number` con el patrón del spec, vuelo y viajero\n * existentes, los dos índices empiezan en 1) y se agregan a `flights[segmentIndex - 1].seats[]`.\n * Sin `seats`, nada cambia.\n */\nexport function buildBookingFlightDetails(source: BookingFlightDetailsSource): FlightDetails {\n const { group, itinerary, priceComparison, seats = [], seatAvailability } = source;\n const flights = itineraryFlights(group, itinerary).map(\n ({ schedule, departureDate, bookingCode }): FlightToBook => ({\n flightNumber: schedule.carrier.marketingFlightNumber,\n airlineCode: schedule.carrier.marketing,\n fromAirportCode: schedule.departure.airport,\n toAirportCode: schedule.arrival.airport,\n departureDate,\n departureTime: schedule.departure.time.slice(0, 5),\n bookingClass: bookingCode,\n flightStatusCode: 'NN',\n }),\n );\n\n const fare = itinerary.pricingInformation[0]?.fare;\n if (fare === undefined) {\n throw new TypeError('sabre-client: el itinerario no trae pricingInformation');\n }\n const passengersPricing = fare.passengerInfoList.map(\n ({ passengerInfo }): PassengerPricing => ({\n passengerCode: passengerInfo.passengerType,\n numberOfpassengers: passengerInfo.passengerNumber ?? 1,\n }),\n );\n\n let priceComparisons: PriceComparison[] | undefined;\n if (priceComparison !== undefined) {\n const total = fare.totalFare?.totalPrice;\n if (total === undefined) {\n throw new TypeError('sabre-client: el itinerario no trae totalFare.totalPrice para priceComparison');\n }\n priceComparisons = [{ desiredAmount: amount(total), ...priceComparison }];\n }\n\n const travelerCount = passengersPricing.reduce((n, p) => n + (p.numberOfpassengers ?? 1), 0);\n const priced: PricedSeat[] = [];\n for (const selection of seats) {\n const flight = flights[validSeat(selection, flights.length, travelerCount)]!;\n (flight.seats ??= []).push({ number: selection.number, travelerIndex: selection.travelerIndex });\n const price = seatAvailability === undefined ? undefined : seatPrice(seatAvailability, flight, selection.number);\n if (price !== undefined) {\n priced.push({\n segmentIndex: selection.segmentIndex,\n flight: `${flight.airlineCode}${flight.flightNumber}`,\n seat: selection.number,\n ...price,\n });\n }\n }\n\n const details: FlightDetails = {\n flights,\n flightPricing: [\n {\n ...(priceComparisons === undefined ? {} : { priceComparisons }),\n qualifiers: {\n passengersPricing,\n ...(fare.validatingCarrierCode === undefined ? {} : { validatingAirlineCode: fare.validatingCarrierCode }),\n },\n },\n ],\n };\n if (priced.length > 0) pricedSeats.set(details, priced);\n return details;\n}\n\n/** Devuelve la posición en `flights[]` (`segmentIndex - 1`) si la selección es válida; si no, `TypeError`. */\nfunction validSeat(selection: BookingSeatSelection, flightCount: number, travelerCount: number): number {\n const { segmentIndex, travelerIndex, number } = selection;\n if (typeof number !== 'string' || !SEAT_NUMBER.test(number)) {\n throw new TypeError(`sabre-client: el asiento ${String(number)} no cumple ^[0-9]+[A-Z]$ (p. ej. 13A)`);\n }\n if (!Number.isInteger(segmentIndex) || segmentIndex < 1 || segmentIndex > flightCount) {\n throw new TypeError(\n `sabre-client: el asiento ${number} pide el vuelo ${segmentIndex}, y hay ${flightCount} (empieza en 1)`,\n );\n }\n if (!Number.isInteger(travelerIndex) || travelerIndex < 1 || travelerIndex > travelerCount) {\n throw new TypeError(\n `sabre-client: el asiento ${number} pide el viajero ${travelerIndex}, y hay ${travelerCount} (empieza en 1)`,\n );\n }\n return segmentIndex - 1;\n}\n\n/**\n * Precio del asiento en Get Seats, si es mayor que cero. El segmento se busca por vuelo,\n * fecha y aeropuerto de salida, no por `id`: así no depende de cómo se armó el request.\n * Ruta: `seats[].offerItemRefIds` → `offerItems[].priceDefinitionRef` → `priceDefinitions[]`.\n */\nfunction seatPrice(\n availability: GetSeatsResponse,\n flight: FlightToBook,\n number: string,\n): { amount: string; currencyCode: string } | undefined {\n const { response } = availability;\n const segmentIds = new Set(\n response.segments\n .filter(\n (s) =>\n s.bookingAirlineCode === flight.airlineCode &&\n s.bookingFlightNumber === flight.flightNumber &&\n s.departureAirportCode === flight.fromAirportCode &&\n s.departureDate === flight.departureDate,\n )\n .map((s) => s.id),\n );\n const row = Number(number.slice(0, -1));\n const column = number.slice(-1);\n const seat = response.seatMaps\n .filter((map) => segmentIds.has(map.segmentRef))\n .flatMap((map) => map.cabinCompartments ?? [])\n .flatMap((cabin) => cabin.seatRows ?? [])\n .filter((r) => r.row === row)\n .flatMap((r) => r.seats)\n .find((s) => s.column === column);\n\n for (const itemId of seat?.offerItemRefIds ?? []) {\n const item = response.offerItems.find((i) => i.id === itemId);\n const price = response.priceDefinitions?.find((p) => p.id === item?.priceDefinitionRef);\n if (price !== undefined && Number(price.totalPrice.amount) > 0) {\n // Sabre manda número aunque el spec diga string: se normaliza para el evento.\n return { amount: String(price.totalPrice.amount), currencyCode: price.currencyCode };\n }\n }\n return undefined;\n}\n\n/** `1234.5` → `'1234.5'`; el spec acepta hasta 3 decimales. */\nfunction amount(value: number): string {\n return String(Math.round(value * 1000) / 1000);\n}\n","// Create Booking (`POST /v1/trip/orders/createBooking`).\n// Ver sabre-wiki/wiki/entities/booking-management-api.md y\n// sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md (éxito parcial de Create Booking).\nimport { type SabreBusinessError, SabreError, type SabreWarning } from '../errors/index.js';\nimport type { SabreRawResponseCallback } from '../http/raw-response.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n type BookingResponseError,\n isObject,\n isWarning,\n nonEmpty,\n responseErrors,\n toBusinessError,\n toWarning,\n} from './booking-errors.js';\nimport type { Booking } from './booking-types.js';\nimport type { CreateBookingRequest } from './create-booking-request.js';\nimport { pricedSeatsOf } from './flight-details.js';\nimport { rawHooks, type SabreRawRequestCallback } from '../http/raw-request.js';\n\nexport const CREATE_BOOKING_SERVICE = 'createBooking';\nconst PATH = '/v1/trip/orders/createBooking';\n/** Aviso cuyo `description` trae el `confirmationId` de una reserva que sí se creó. */\nconst UNABLE_TO_RETRIEVE_BOOKING = 'UNABLE_TO_RETRIEVE_BOOKING';\n\nexport interface CreateBookingOptions {\n signal?: AbortSignal;\n /** Respuesta cruda del último intento HTTP. El body trae PII: ver `SabreRawResponse`. */\n onRawResponse?: SabreRawResponseCallback;\n /** Request crudo del último intento que se mandó, sin `Authorization`. Trae PII: ver `SabreRawRequest`. */\n onRawRequest?: SabreRawRequestCallback;\n}\n\n/** Elemento de `errors[]` de Create Booking. */\nexport type CreateBookingResponseError = BookingResponseError;\n\n/** `Booking` del spec v1.33, tipado completo (#158): ver `booking-types.ts`. */\nexport type { Booking };\n\n/** `CreateBookingResponse` tal cual llega de Sabre. */\nexport interface RawCreateBookingResponse {\n timestamp?: string;\n confirmationId?: string;\n booking?: Booking;\n errors?: CreateBookingResponseError[];\n request?: CreateBookingRequest;\n}\n\n/**\n * Reserva creada. Si Sabre la creó con avisos o con errores no fatales (p. ej. con\n * `errorHandlingPolicy: DO_NOT_HALT_ON_*`), no se lanza: van adjuntos aquí.\n */\nexport interface CreateBookingResponse {\n /** Localizador del PNR. */\n confirmationId: string;\n timestamp?: string;\n /** Falta, p. ej., con el aviso `UNABLE_TO_RETRIEVE_BOOKING`. */\n booking?: Booking;\n /** Copia del request enviado, si Sabre la devuelve. */\n request?: CreateBookingRequest;\n /** Elementos de `errors[]` con `category: WARNING`. */\n warnings: SabreWarning[];\n /** Elementos de `errors[]` de otras categorías que no impidieron crear la reserva. */\n errors: SabreBusinessError[];\n}\n\n/**\n * Create Booking: escritura no idempotente, sin reintento automático. Solo el reintento\n * reactivo ante 401, que el gateway rechaza antes de llegar al proveedor.\n */\nexport async function createBooking(\n transport: RestTransport,\n request: CreateBookingRequest,\n options: CreateBookingOptions = {},\n): Promise<CreateBookingResponse> {\n validateCreateBookingRequest(request);\n // Decidido en #62: un asiento con precio solo se avisa; la reserva se envía igual.\n for (const seat of pricedSeatsOf(request.flightDetails)) {\n transport.log.emit('warn', 'sabre.booking.seat.priced', { service: CREATE_BOOKING_SERVICE, ...seat });\n }\n const body = await transport.request<RawCreateBookingResponse>({\n method: 'POST',\n path: PATH,\n service: CREATE_BOOKING_SERVICE,\n idempotent: false,\n body: request,\n classify: classifyCreateBooking,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'booking.create'),\n });\n return toCreateBookingResponse(body);\n}\n\n/**\n * Reglas de la API que Sabre rechaza seguro, iguales para todas las agencias:\n * `FUTURE_TICKETING` sin `futureTicketingPolicy` vuelve como `MANDATORY_DATA_MISSING`. Solo se\n * revisa que la policy esté, no su contenido; los valores de la agencia van tal cual.\n */\nfunction validateCreateBookingRequest(request: CreateBookingRequest): void {\n if (typeof request !== 'object' || request === null) {\n throw new TypeError('sabre-client: booking.create espera un objeto CreateBookingRequest');\n }\n const agency = request.agency;\n if (agency?.ticketingPolicy === 'FUTURE_TICKETING' && agency.futureTicketingPolicy === undefined) {\n throw new TypeError(\n 'sabre-client: booking.create con agency.ticketingPolicy FUTURE_TICKETING necesita agency.futureTicketingPolicy',\n );\n }\n // `BookGenericSeat.travelerIndex` es 1-based sobre `travelers[]`.\n const travelers = Array.isArray(request.travelers) ? request.travelers.length : 0;\n for (const flight of request.flightDetails?.flights ?? []) {\n for (const seat of flight.seats ?? []) {\n if (seat.travelerIndex < 1 || seat.travelerIndex > travelers) {\n throw new TypeError(\n `sabre-client: booking.create con un asiento para el viajero ${seat.travelerIndex}, y travelers tiene ${travelers}`,\n );\n }\n }\n }\n}\n\n/**\n * Paso 3 del orden de detección. Lo que decide si se lanza es si la reserva se creó, no la\n * categoría de `errors[]`:\n *\n * - Hay reserva (`confirmationId`, `booking.bookingId` o el aviso `UNABLE_TO_RETRIEVE_BOOKING`\n * con el localizador en el `description`): no hay error, `toCreateBookingResponse` adjunta\n * avisos y errores al resultado.\n * - No hay reserva: `SabreBusinessError` con el primer error que no sea `WARNING`, y los\n * avisos adjuntos.\n */\nexport function classifyCreateBooking(body: unknown): SabreError | undefined {\n if (!isObject(body)) {\n return new SabreError(`${CREATE_BOOKING_SERVICE}: respuesta malformada, se esperaba un objeto`, {\n retryable: false,\n raw: body,\n });\n }\n const response = body as RawCreateBookingResponse;\n if (confirmationIdOf(response) !== undefined) return undefined;\n\n // La reserva existe pero no hay localizador que devolver: no es un \"no se creó\".\n if (reservationWithoutId(response)) {\n return new SabreError(\n `${CREATE_BOOKING_SERVICE}: Sabre indica que la reserva se creó, pero no devolvió su confirmationId`,\n { retryable: false, raw: body },\n );\n }\n const items = responseErrors(response);\n const fatal = items.find((item) => !isWarning(item));\n if (fatal !== undefined) return toBusinessError(CREATE_BOOKING_SERVICE, fatal, { warnings: items.filter(isWarning).map(warningOf) });\n return new SabreError(`${CREATE_BOOKING_SERVICE}: respuesta malformada, sin confirmationId ni errores fatales`, {\n retryable: false,\n raw: body,\n });\n}\n\n/** Solo para respuestas con reserva (ver `classifyCreateBooking`). */\nfunction toCreateBookingResponse(body: RawCreateBookingResponse): CreateBookingResponse {\n const items = responseErrors(body);\n return {\n confirmationId: confirmationIdOf(body)!,\n ...(body.timestamp === undefined ? {} : { timestamp: body.timestamp }),\n ...(body.booking === undefined ? {} : { booking: body.booking }),\n ...(body.request === undefined ? {} : { request: body.request }),\n warnings: items.filter(isWarning).map(warningOf),\n errors: items.filter((item) => !isWarning(item)).map((item) => toBusinessError(CREATE_BOOKING_SERVICE, item)),\n };\n}\n\nfunction confirmationIdOf(response: RawCreateBookingResponse): string | undefined {\n if (nonEmpty(response.confirmationId)) return response.confirmationId;\n if (nonEmpty(response.booking?.bookingId)) return response.booking.bookingId;\n const notRetrieved = responseErrors(response).find((item) => item.type === UNABLE_TO_RETRIEVE_BOOKING);\n return notRetrieved === undefined ? undefined : locatorIn(notRetrieved.description);\n}\n\nfunction reservationWithoutId(response: RawCreateBookingResponse): boolean {\n return response.booking !== undefined || responseErrors(response).some((item) => item.type === UNABLE_TO_RETRIEVE_BOOKING);\n}\n\n/**\n * El catálogo documenta el description como `Booking was created successfully but could not\n * be retrieved. (confirmationId)`. Se prefiere el valor entre paréntesis.\n */\nfunction locatorIn(description: string | undefined): string | undefined {\n if (description === undefined) return undefined;\n return /\\(([A-Z0-9]{6,})\\)/.exec(description)?.[1] ?? /\\b([A-Z0-9]{6,})\\b/.exec(description)?.[1];\n}\n\nfunction warningOf(item: BookingResponseError): SabreWarning {\n return toWarning(CREATE_BOOKING_SERVICE, item);\n}\n","// Get Booking (`POST /v1/trip/orders/getBooking`).\n// Ver sabre-wiki/wiki/sdk/gestion-de-reserva.md y sabre-wiki/wiki/sources/get-booking.md.\nimport { type SabreBusinessError, SabreError, type SabreWarning } from '../errors/index.js';\nimport type { SabreRawResponseCallback } from '../http/raw-response.js';\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n type BookingResponseError,\n isObject,\n isWarning,\n nonEmpty,\n responseErrors,\n toBusinessError,\n toWarning,\n} from './booking-errors.js';\nimport type { Booking } from './create-booking.js';\nimport { rawHooks, type SabreRawRequestCallback } from '../http/raw-request.js';\n\nexport const GET_BOOKING_SERVICE = 'getBooking';\nconst PATH = '/v1/trip/orders/getBooking';\n/** Fallos de sistema que Sabre puede resolver al repetir la lectura (decidido en #39). */\nconst RETRYABLE_TYPES = new Set(['INTERNAL_SERVER_TIMEOUT', 'DOWNLINE_SERVICE_FAILURE']);\n\n/** Secciones de la respuesta (`ReturnOnlyEnum`). Además evitan llamadas downline de Sabre. */\nexport type GetBookingReturnOnly =\n | 'FLIGHTS'\n | 'FLIGHT_PENALTY'\n | 'BAGGAGE_POLICY'\n | 'JOURNEYS'\n | 'HOTELS'\n | 'HOTEL_ADDRESS'\n | 'CARS'\n | 'CAR_RENTAL_ADDRESS'\n | 'CAR_RENTAL_PENALTY'\n | 'TRAINS'\n | 'CRUISES'\n | 'ALL_SEGMENTS'\n | 'TRAVELERS'\n | 'TICKETS'\n | 'PAYMENTS'\n | 'PENALTIES'\n | 'REMARKS'\n | 'IS_CANCELABLE'\n | 'IS_TICKETED'\n | 'CONTACT_INFO'\n | 'OTHER_SERVICES'\n | 'SPECIAL_SERVICES'\n | 'FARES'\n | 'CREATION_DETAILS'\n | 'ANCILLARIES'\n | 'FORMS_OF_PAYMENT'\n | 'RETENTION_DATE'\n | 'ACCOUNTING_ITEMS'\n | 'NON_ELECTRONIC_TICKETS'\n | 'TRAVELERS_EMPLOYERS'\n | 'PROFILES';\n\n/** `BookingSourceEnum`. Por defecto `SABRE`. */\nexport type BookingSource = 'SABRE' | 'SABRE_ORDER';\n\n/** `ExtraFeatures` del spec (incluye `CommonExtraFeatures`). */\nexport interface GetBookingExtraFeatures {\n /** Solo NDC. Por defecto `true`. */\n returnEmptySeatObjects?: boolean;\n /** Por defecto `false`; más lento. */\n forceHotelUpdate?: boolean;\n returnFrequentRenter?: boolean;\n returnWalletFormsOfPayment?: boolean;\n returnFiscalId?: boolean;\n}\n\n/** `GetBookingRequest` del spec v1.33. */\nexport interface GetBookingRequest {\n /** Localizador del PNR u Order ID (`^[A-Z0-9]{6,}$`). Único campo obligatorio. */\n confirmationId: string;\n bookingSource?: BookingSource;\n /** Cambio de contexto (`^[A-Z0-9]{3,4}$`). */\n targetPcc?: string;\n /** Validación extra: si no coincide con el PNR, Sabre responde `UNAUTHORIZED_ACCESS`. */\n surname?: string;\n /** Según el spec, Sabre no los usa; solo `surname`. */\n givenName?: string;\n middleName?: string;\n /** Vacío o ausente: la reserva completa. */\n returnOnly?: GetBookingReturnOnly[];\n extraFeatures?: GetBookingExtraFeatures;\n /** Requiere el keyword `CCVIEW` en el EPR. */\n unmaskPaymentCardNumbers?: boolean;\n}\n\nexport interface GetBookingOptions {\n signal?: AbortSignal;\n /** Respuesta cruda del último intento HTTP. El body trae PII: ver `SabreRawResponse`. */\n onRawResponse?: SabreRawResponseCallback;\n /** Request crudo del último intento que se mandó, sin `Authorization`. Trae PII: ver `SabreRawRequest`. */\n onRawRequest?: SabreRawRequestCallback;\n}\n\n/** `GetBookingResponse` tal cual llega de Sabre: el `Booking` va en el primer nivel. */\nexport interface RawGetBookingResponse extends Booking {\n timestamp?: string;\n bookingSignature?: string;\n request?: GetBookingRequest;\n errors?: BookingResponseError[];\n}\n\n/**\n * Reserva leída, con el `Booking` en el primer nivel tal cual lo define Sabre (no se normaliza\n * contra Create ni Cancel, que lo anidan en `booking`). `errors[]` del original se reemplaza\n * por los errores del SDK.\n */\nexport interface GetBookingResponse extends Booking {\n bookingId: string;\n timestamp?: string;\n /** Solo viene si Sabre armó la reserva sin errores. Lo usa Modify Booking. */\n bookingSignature?: string;\n /** Copia del request enviado, si Sabre la devuelve. */\n request?: GetBookingRequest;\n /**\n * Elementos de `errors[]` con `category: WARNING`. En un PNR sin emitir es normal\n * `RESOURCE_UNAVAILABLE` por falta de fare rules.\n */\n warnings: SabreWarning[];\n /**\n * Elementos de `errors[]` de otras categorías que llegaron junto con la reserva, p. ej.\n * `UNAUTHORIZED_ACCESS` de un servicio downline: faltan secciones, pero la reserva existe.\n */\n errors: SabreBusinessError[];\n}\n\n/**\n * Get Booking: lectura idempotente. Los 429/5xx de gateway se reintentan con la política\n * genérica, y también `INTERNAL_SERVER_TIMEOUT` y `DOWNLINE_SERVICE_FAILURE`.\n */\nexport async function getBooking(\n transport: RestTransport,\n request: GetBookingRequest,\n options: GetBookingOptions = {},\n): Promise<GetBookingResponse> {\n if (!isObject(request) || !nonEmpty(request.confirmationId)) {\n throw new TypeError('sabre-client: booking.get espera { confirmationId: string, ... }');\n }\n const body = await transport.request<RawGetBookingResponse>({\n method: 'POST',\n path: PATH,\n service: GET_BOOKING_SERVICE,\n idempotent: true,\n body: request,\n classify: classifyGetBooking,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...rawHooks(options, 'booking.get'),\n });\n return toGetBookingResponse(body);\n}\n\n/**\n * Paso 3 del orden de detección. Lo que decide si se lanza es si hay reserva (`bookingId`):\n *\n * - Hay reserva: no hay error; `toGetBookingResponse` adjunta avisos y errores al resultado.\n * - No hay reserva: `SabreBusinessError` con el primer error que no sea `WARNING` (p. ej.\n * `BOOKING_NOT_FOUND` o `UNAUTHORIZED_ACCESS`), y los avisos adjuntos.\n */\nexport function classifyGetBooking(body: unknown): SabreError | undefined {\n if (!isObject(body)) {\n return new SabreError(`${GET_BOOKING_SERVICE}: respuesta malformada, se esperaba un objeto`, {\n retryable: false,\n raw: body,\n });\n }\n const response = body as RawGetBookingResponse;\n if (nonEmpty(response.bookingId)) return undefined;\n\n const items = responseErrors(response);\n const fatal = items.find((item) => !isWarning(item));\n if (fatal !== undefined) return errorOf(fatal, items.filter(isWarning).map(warningOf));\n return new SabreError(`${GET_BOOKING_SERVICE}: respuesta malformada, sin bookingId ni errores fatales`, {\n retryable: false,\n raw: body,\n });\n}\n\n/** Solo para respuestas con reserva (ver `classifyGetBooking`). */\nfunction toGetBookingResponse(body: RawGetBookingResponse): GetBookingResponse {\n const items = responseErrors(body);\n return {\n ...body,\n bookingId: body.bookingId!,\n warnings: items.filter(isWarning).map(warningOf),\n errors: items.filter((item) => !isWarning(item)).map((item) => errorOf(item, [])),\n };\n}\n\nfunction warningOf(item: BookingResponseError): SabreWarning {\n return toWarning(GET_BOOKING_SERVICE, item);\n}\n\nfunction errorOf(item: BookingResponseError, warnings: SabreWarning[]): SabreBusinessError {\n return toBusinessError(GET_BOOKING_SERVICE, item, { warnings, retryable: RETRYABLE_TYPES.has(item.type) });\n}\n","// Módulo de dominio `sabre.booking` (Booking Management API).\n// Ver sabre-wiki/wiki/sdk/convenciones-de-nombres-y-versionado.md.\nimport type { RestTransport } from '../http/rest-transport.js';\nimport {\n cancelBooking,\n type CancelBookingOptions,\n type CancelBookingRequest,\n type CancelBookingResponse,\n} from './cancel-booking.js';\nimport type { CreateBookingRequest } from './create-booking-request.js';\nimport { createBooking, type CreateBookingOptions, type CreateBookingResponse } from './create-booking.js';\nimport { getBooking, type GetBookingOptions, type GetBookingRequest, type GetBookingResponse } from './get-booking.js';\n\nexport class BookingManagement {\n readonly #transport: RestTransport;\n\n /** @internal Lo construye el cliente `Sabre`. */\n constructor(transport: RestTransport) {\n this.#transport = transport;\n }\n\n /**\n * Create Booking: crea la reserva. Para un itinerario de BFM/Revalidate, `flightDetails` se\n * arma con `buildBookingFlightDetails`.\n *\n * Nunca se reintenta automáticamente. Si la reserva se crea con avisos o errores no fatales,\n * no lanza: los devuelve en `warnings` y `errors`. Si no se crea, lanza `SabreBusinessError`.\n * Con `agency.ticketingPolicy: 'FUTURE_TICKETING'` y sin `agency.futureTicketingPolicy`, lanza\n * `TypeError` sin llamar a la red: Sabre lo rechaza seguro. Lo mismo con un asiento cuyo\n * `travelerIndex` no está en `travelers`. Un asiento con precio en Get Seats (ver\n * `buildBookingFlightDetails`) solo emite `sabre.booking.seat.priced` en `warn`.\n */\n create(request: CreateBookingRequest, options?: CreateBookingOptions): Promise<CreateBookingResponse> {\n return createBooking(this.#transport, request, options);\n }\n\n /**\n * Get Booking: lee la reserva por `confirmationId`. El `Booking` va en el primer nivel de la\n * respuesta, a diferencia de `create`. Usa `returnOnly` para pedir solo las secciones que\n * hacen falta: además acelera la respuesta.\n *\n * Si la reserva existe, no lanza: los avisos y errores parciales van en `warnings` y\n * `errors`. Si no existe o no se pudo leer (p. ej. `BOOKING_NOT_FOUND`), lanza\n * `SabreBusinessError`. Es una lectura: se reintenta ante fallos transitorios.\n */\n get(request: GetBookingRequest, options?: GetBookingOptions): Promise<GetBookingResponse> {\n return getBooking(this.#transport, request, options);\n }\n\n /**\n * Cancel Booking: cancela la reserva entera (`cancelAll: true`) o por `itemId` (p. ej. los\n * `flights[].itemId` de `get`). Valida antes de enviar las combinaciones que Sabre rechaza y,\n * si encuentra una, lanza `TypeError` sin llamar a la red.\n *\n * Nunca se reintenta automáticamente. Lanza `SabreBusinessError` si algo falló o si Sabre\n * responde `NO_ITEMS_CANCELLED` (no se canceló nada), aunque llegue como aviso. Con\n * `END_TRANSACTION_PROBLEM` en `warnings`, la confirmación quedó pendiente: verifica con `get`.\n */\n cancel(request: CancelBookingRequest, options?: CancelBookingOptions): Promise<CancelBookingResponse> {\n return cancelBooking(this.#transport, request, options);\n }\n}\n","// Política de reintentos. Ver sabre-wiki/wiki/sdk/politica-de-reintentos-y-backoff.md.\nimport { SabreError } from '../errors/index.js';\n\nexport interface RetryOptions {\n /** Reintentos después de la primera llamada (3 → hasta 4 llamadas en total). */\n maxRetries: number;\n /** Delay base del backoff exponencial, en milisegundos. */\n baseDelayMs: number;\n}\n\nexport const DEFAULT_RETRY: Readonly<RetryOptions> = Object.freeze({ maxRetries: 3, baseDelayMs: 500 });\n\n/** Piso mínimo de espera que documenta Sabre para 429/5xx de gateway. */\nexport const MIN_RETRY_DELAY_MS = 500;\n\n/** Full jitter: aleatorio entre 0 y `baseDelayMs · 2^retry`, con piso de 500 ms. */\nexport function retryDelay(retry: number, baseDelayMs: number, random: () => number = Math.random): number {\n return Math.max(MIN_RETRY_DELAY_MS, Math.floor(random() * baseDelayMs * 2 ** retry));\n}\n\n/** Solo se reintenta un `SabreError` con `retryable: true` en una operación idempotente. */\nexport function shouldRetry(error: unknown, idempotent: boolean): boolean {\n return idempotent && error instanceof SabreError && error.retryable;\n}\n\nexport function validateRetryOptions(retry: Partial<RetryOptions>, where: string): void {\n if (retry.maxRetries !== undefined && !(Number.isInteger(retry.maxRetries) && retry.maxRetries >= 0)) {\n throw new TypeError(`sabre-client: ${where}.maxRetries debe ser un entero >= 0`);\n }\n if (retry.baseDelayMs !== undefined && !(Number.isFinite(retry.baseDelayMs) && retry.baseDelayMs >= 0)) {\n throw new TypeError(`sabre-client: ${where}.baseDelayMs debe ser un número >= 0`);\n }\n}\n\n/** Espera `ms`, o rechaza con el motivo del `signal` si se aborta antes. */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason);\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","// Config explícita del consumidor; el SDK nunca lee variables de entorno.\n// Ver sabre-wiki/wiki/sdk/configuracion-logging-y-build.md.\nimport type { SabreTokenStore } from './auth/token-store.js';\nimport { DEFAULT_RETRY, type RetryOptions, validateRetryOptions } from './http/retry.js';\nimport type { SabreLogger } from './logging/index.js';\n\nexport type SabreEnvironment = 'sandbox' | 'production';\n\nexport type SabreAuthVersion = 'v3' | 'v2';\n\n/** Credenciales para OAuth Token Create v3: Client ID/Secret más usuario EPR. */\nexport interface SabreCredentials {\n /**\n * Versión de OAuth para la que se armaron. `buildCredentials` la pone; la config la usa cuando\n * no trae su propio `authVersion`.\n */\n authVersion?: 'v3';\n clientId: string;\n clientSecret: string;\n /** Usuario EPR. */\n username: string;\n /** Contraseña EPR. */\n password: string;\n}\n\n/** Credenciales para OAuth Token Create v2: solo EPR; `clientId`/`clientSecret` se ignoran. */\nexport interface SabreCredentialsV2 {\n /**\n * Versión de OAuth para la que se armaron. `buildCredentials` la pone, y con ella la config no\n * necesita repetir `authVersion: 'v2'`.\n */\n authVersion?: 'v2';\n clientId?: string;\n clientSecret?: string;\n /** Usuario EPR. */\n username: string;\n /** Contraseña EPR. */\n password: string;\n}\n\ninterface SabreBaseConfig {\n environment: SabreEnvironment;\n logger?: SabreLogger;\n /** Reintentos por defecto del cliente; cada request puede pisarlos. */\n retry?: Partial<RetryOptions>;\n /** `fetch` a usar en lugar del global (tests, proxies, runtimes edge). */\n fetch?: typeof fetch;\n /**\n * Almacén del token para reutilizarlo entre procesos (scripts, serverless). Sin él, el\n * token se cachea solo en memoria.\n */\n tokenStore?: SabreTokenStore;\n}\n\n/** OAuth Token Create v3 (por defecto). */\nexport interface SabreConfigV3 extends SabreBaseConfig {\n authVersion?: 'v3';\n credentials: SabreCredentials;\n}\n\n/** OAuth Token Create v2. */\nexport interface SabreConfigV2 extends SabreBaseConfig {\n authVersion: 'v2';\n credentials: SabreCredentialsV2;\n}\n\n/**\n * OAuth Token Create v2 sin `authVersion` en la config: la versión sale de las credenciales,\n * como las devuelve `buildCredentials({ authVersion: 'v2', … })`.\n */\nexport interface SabreConfigV2FromCredentials extends SabreBaseConfig {\n authVersion?: never;\n credentials: SabreCredentialsV2 & { authVersion: 'v2' };\n}\n\n/**\n * Credenciales con su versión, sin saber cuál al compilar: lo que devuelve\n * `buildCredentials(options: BuildCredentialsOptions)`. Es un solo tipo y no la unión de\n * `BuiltCredentialsV3 | BuiltCredentialsV2`: con la unión, TypeScript aceptaría también un\n * `SabreCredentialsV2` sin marca, porque toma su `authVersion` opcional como discriminante. A\n * cambio, el tipo no exige `clientId`/`clientSecret` con `'v3'`: eso lo valida `resolveConfig`.\n */\nexport interface SabreCredentialsAnyVersion {\n authVersion: SabreAuthVersion;\n clientId?: string;\n clientSecret?: string;\n username: string;\n password: string;\n}\n\n/**\n * Config sin `authVersion`, con credenciales de `buildCredentials` cuya versión no se conoce al\n * compilar. La versión sale de la marca de las credenciales en runtime (Q-084, #159).\n */\nexport interface SabreConfigFromCredentials extends SabreBaseConfig {\n authVersion?: never;\n credentials: SabreCredentialsAnyVersion;\n}\n\n/**\n * Config del cliente, discriminada por `authVersion`: el de la config o, si falta, el de\n * `credentials`. Sin ninguno de los dos, es v3.\n */\nexport type SabreConfig = SabreConfigV3 | SabreConfigV2 | SabreConfigV2FromCredentials | SabreConfigFromCredentials;\n\nexport const BASE_URLS: Readonly<Record<SabreEnvironment, string>> = Object.freeze({\n sandbox: 'https://api.cert.platform.sabre.com',\n production: 'https://api.platform.sabre.com',\n});\n\n/** Endpoints SOAP de `SabreLegacy` (ver entornos-y-certificacion). */\nexport const SOAP_BASE_URLS: Readonly<Record<SabreEnvironment, string>> = Object.freeze({\n sandbox: 'https://webservices.cert.platform.sabre.com',\n production: 'https://webservices.platform.sabre.com',\n});\n\n/** Config validada y con defaults aplicados. */\nexport interface ResolvedConfig {\n credentials: Readonly<SabreCredentials | SabreCredentialsV2>;\n environment: SabreEnvironment;\n baseUrl: string;\n soapBaseUrl: string;\n authVersion: SabreAuthVersion;\n logger: SabreLogger | undefined;\n retry: Readonly<RetryOptions>;\n fetch: typeof fetch;\n tokenStore: SabreTokenStore | undefined;\n}\n\nconst LOGGER_METHODS = ['debug', 'info', 'warn', 'error'] as const;\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction requireString(value: unknown, field: string): void {\n if (typeof value !== 'string' || value.trim() === '') fail(`${field} es requerido y debe ser un string no vacío`);\n}\n\nexport function resolveConfig(config: SabreConfig): ResolvedConfig {\n if (!isObject(config)) fail('la config debe ser un objeto');\n\n const { environment } = config;\n if (environment !== 'sandbox' && environment !== 'production') {\n fail(`environment debe ser 'sandbox' o 'production' (recibido: ${JSON.stringify(environment)})`);\n }\n\n const configVersion = config.authVersion ?? undefined;\n if (configVersion !== undefined && configVersion !== 'v3' && configVersion !== 'v2') {\n fail(`authVersion debe ser 'v3' o 'v2' (recibido: ${JSON.stringify(configVersion)})`);\n }\n\n const { credentials } = config;\n if (!isObject(credentials)) fail('credentials es requerido');\n // La marca que pone `buildCredentials`: evita repetir `authVersion` en la config (#148).\n const credentialsVersion = credentials.authVersion ?? undefined;\n if (credentialsVersion !== undefined && credentialsVersion !== 'v3' && credentialsVersion !== 'v2') {\n fail(`credentials.authVersion debe ser 'v3' o 'v2' (recibido: ${JSON.stringify(credentialsVersion)})`);\n }\n if (configVersion !== undefined && credentialsVersion !== undefined && configVersion !== credentialsVersion) {\n fail(`authVersion '${configVersion}' no coincide con credentials.authVersion '${credentialsVersion}'`);\n }\n const authVersion: SabreAuthVersion = configVersion ?? credentialsVersion ?? 'v3';\n requireString(credentials.username, 'credentials.username');\n requireString(credentials.password, 'credentials.password');\n if (authVersion === 'v3') {\n requireString(credentials.clientId, 'credentials.clientId (requerido con authVersion v3)');\n requireString(credentials.clientSecret, 'credentials.clientSecret (requerido con authVersion v3)');\n }\n\n const { logger } = config;\n if (logger !== undefined) {\n if (!isObject(logger)) fail('logger debe ser un objeto con debug/info/warn/error');\n for (const method of LOGGER_METHODS) {\n if (typeof logger[method] !== 'function') fail(`logger.${method} debe ser una función`);\n }\n }\n\n if (config.retry !== undefined) {\n if (!isObject(config.retry)) fail('retry debe ser un objeto');\n validateRetryOptions(config.retry, 'retry');\n }\n\n const { tokenStore } = config;\n if (tokenStore !== undefined) {\n if (!isObject(tokenStore) || typeof tokenStore.get !== 'function' || typeof tokenStore.set !== 'function') {\n fail('tokenStore debe ser un objeto con get(key) y set(key, token)');\n }\n }\n\n const fetchImpl = config.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') fail('no hay fetch disponible: pasa config.fetch');\n\n return {\n // Ya validado arriba: con v3 trae clientId/clientSecret; la marca de versión ya se resolvió.\n credentials: Object.freeze({ ...credentials }) as SabreCredentials | SabreCredentialsV2,\n environment,\n baseUrl: BASE_URLS[environment],\n soapBaseUrl: SOAP_BASE_URLS[environment],\n authVersion,\n logger,\n retry: Object.freeze({ ...DEFAULT_RETRY, ...definedOnly(config.retry ?? {}) }),\n // Enlazado al global para evitar \"Illegal invocation\" en algunos runtimes.\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n tokenStore,\n };\n}\n\n/** Quita claves con valor `undefined` para que no pisen los defaults. */\nexport function definedOnly<T extends object>(value: T): Partial<T> {\n return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== undefined)) as Partial<T>;\n}\n","// Transporte REST del cliente `Sabre`: fetch JSON, detección de errores y reintentos.\n// Ver sabre-wiki/wiki/sdk/manejo-y-mapeo-de-errores.md y politica-de-reintentos-y-backoff.md.\nimport { definedOnly, type ResolvedConfig } from '../config.js';\nimport { SabreError, SabreGatewayError } from '../errors/index.js';\nimport { EventLogger } from '../logging/logger.js';\nimport { type RawRequestCapture, rawRequestHeaders, type SabreRawRequestCallback } from './raw-request.js';\nimport type { SabreRawResponse, SabreRawResponseCallback } from './raw-response.js';\nimport { type RetryOptions, retryDelay, shouldRetry, sleep, validateRetryOptions } from './retry.js';\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\n/** Status de gateway REST reintentables (ver errores-comunes-api). */\nconst RETRYABLE_STATUS = new Set([429, 500, 503, 504]);\n\n/**\n * Pasos 2–3 del orden de detección, aportados por cada servicio: recibe el body de una\n * respuesta 2xx y devuelve el error de su catálogo (orquestado, negocio o warning), o\n * `undefined` si la respuesta es data válida.\n */\nexport type ResponseClassifier = (body: unknown, response: Response) => SabreError | undefined;\n\nexport interface RestRequest {\n method: HttpMethod;\n /** Ruta relativa a la base URL, p. ej. `/v5/offers/shop`. */\n path: string;\n /** Nombre del servicio para errores y logs, p. ej. `'bargainFinderMax'`. */\n service: string;\n /**\n * Si la operación se puede repetir sin efectos duplicados. Las escrituras\n * (Create Booking, End Transaction) van en `false` y nunca se reintentan.\n */\n idempotent: boolean;\n query?: Record<string, string | number | boolean | undefined>;\n /** Se serializa como JSON, salvo `URLSearchParams`, que va como form-urlencoded. */\n body?: unknown;\n headers?: Record<string, string>;\n /** `false` para no pedir el header `Authorization` (p. ej. la propia request de token). */\n auth?: boolean;\n classify?: ResponseClassifier;\n retry?: Partial<RetryOptions>;\n signal?: AbortSignal;\n /** Método público sin `sabre.`, p. ej. `'booking.get'`. Lo reciben `onRawResponse` y `onRawRequest`. */\n operation?: string;\n onRawResponse?: SabreRawResponseCallback;\n /** No se llama si `auth` es `false` (la request de token lleva la credencial). */\n onRawRequest?: SabreRawRequestCallback;\n}\n\n/**\n * Último intento con respuesta HTTP (`last`) y último request mandado (`request`). Solo se lleva\n * si hay `onRawResponse` u `onRawRequest`.\n */\ninterface RawCapture {\n attempts: number;\n last?: { status: number; headers: Headers; body: string };\n request?: RawRequestCapture;\n}\n\n/** Fuente del header `Authorization` de los servicios (la implementa `AuthManager`). */\nexport interface AuthorizationProvider {\n /** Valor vigente del header, p. ej. `Bearer <token>`. */\n get(): Promise<string>;\n /** El gateway rechazó `authorization` con 401: descartarlo para que `get` traiga otro. */\n invalidate(authorization: string): void;\n}\n\nexport interface RestTransportOptions {\n authorization?: AuthorizationProvider;\n /** Solo para tests: fuente de aleatoriedad del jitter. */\n random?: () => number;\n /** Solo para tests: espera entre reintentos. */\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n}\n\nexport class RestTransport {\n readonly #config: ResolvedConfig;\n readonly #log: EventLogger;\n readonly #random: () => number;\n readonly #sleep: (ms: number, signal?: AbortSignal) => Promise<void>;\n #authorization: AuthorizationProvider | undefined;\n\n constructor(config: ResolvedConfig, options: RestTransportOptions = {}) {\n this.#config = config;\n this.#log = new EventLogger(config.logger);\n this.#authorization = options.authorization;\n this.#random = options.random ?? Math.random;\n this.#sleep = options.sleep ?? sleep;\n }\n\n /** @internal Para los avisos de las operaciones que no son de una request (p. ej. asientos con precio). */\n get log(): EventLogger {\n return this.#log;\n }\n\n /** Punto de enganche para `AuthManager`. */\n setAuthorizationProvider(provider: AuthorizationProvider | undefined): void {\n this.#authorization = provider;\n }\n\n async request<T>(request: RestRequest): Promise<T> {\n if (request.retry !== undefined) validateRetryOptions(request.retry, 'retry');\n const wantsRequest = request.onRawRequest !== undefined && request.auth !== false;\n const capture: RawCapture | undefined =\n request.onRawResponse === undefined && !wantsRequest ? undefined : { attempts: 0 };\n try {\n return await this.#attempts<T>(request, capture);\n } finally {\n // Antes de devolver o de lanzar: primero el último request que se mandó, aunque no haya\n // tenido respuesta, y después el último intento que tuvo respuesta HTTP.\n if (wantsRequest && capture?.request !== undefined) this.#deliverRawRequest(request, capture.request, capture.attempts);\n if (capture?.last !== undefined) this.#deliverRaw(request, { ...capture.last, attempts: capture.attempts });\n }\n }\n\n async #attempts<T>(request: RestRequest, capture: RawCapture | undefined): Promise<T> {\n const retry = { ...this.#config.retry, ...definedOnly(request.retry ?? {}) };\n\n let reauthorized = false;\n for (let attempt = 0; ; attempt++) {\n // Fuera del try: un fallo al obtener el token ya pasó por sus propios reintentos.\n const authorization = await this.#authorizationFor(request);\n try {\n return await this.#send<T>(request, attempt, authorization, capture);\n } catch (error) {\n // Refresco reactivo: un solo reintento con token nuevo, fuera del presupuesto genérico.\n // Aplica también a escrituras: el 401 del gateway rechaza la request antes del proveedor.\n if (authorization !== undefined && !reauthorized && isUnauthorized(error)) {\n reauthorized = true;\n this.#authorization?.invalidate(authorization);\n this.#log.emit('warn', 'sabre.request.retry', {\n service: request.service,\n method: request.method,\n path: request.path,\n attempt: attempt + 1,\n reason: 'unauthorized',\n error: error as SabreError,\n });\n attempt--;\n continue;\n }\n if (attempt >= retry.maxRetries || !shouldRetry(error, request.idempotent)) throw error;\n const delayMs = retryDelay(attempt, retry.baseDelayMs, this.#random);\n this.#log.emit('warn', 'sabre.request.retry', {\n service: request.service,\n method: request.method,\n path: request.path,\n attempt: attempt + 1,\n maxRetries: retry.maxRetries,\n delayMs,\n error: error as SabreError,\n });\n await this.#sleep(delayMs, request.signal);\n }\n }\n }\n\n /** Un callback que lanza no rompe la operación: Create Booking no puede perder su localizador. */\n #deliverRaw(request: RestRequest, raw: Omit<SabreRawResponse, 'operation' | 'protocol'>): void {\n const operation = request.operation ?? request.service;\n try {\n request.onRawResponse?.({ operation, protocol: 'rest', ...raw });\n } catch (error) {\n this.#log.emit('warn', 'sabre.request.rawResponseHookFailed', {\n service: request.service,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n }\n\n /** Igual que `#deliverRaw`: un callback que lanza no rompe la operación. */\n #deliverRawRequest(request: RestRequest, raw: RawRequestCapture, attempts: number): void {\n const operation = request.operation ?? request.service;\n try {\n request.onRawRequest?.({ operation, protocol: 'rest', ...raw, attempts });\n } catch (error) {\n this.#log.emit('warn', 'sabre.request.rawRequestHookFailed', {\n service: request.service,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n }\n\n async #authorizationFor(request: RestRequest): Promise<string | undefined> {\n if (request.auth === false || this.#authorization === undefined) return undefined;\n return this.#authorization.get();\n }\n\n async #send<T>(\n request: RestRequest,\n attempt: number,\n authorization: string | undefined,\n capture: RawCapture | undefined,\n ): Promise<T> {\n const url = this.#url(request);\n const headers = new Headers({ Accept: 'application/json', ...request.headers });\n const form = request.body instanceof URLSearchParams;\n if (request.body !== undefined && !headers.has('Content-Type')) {\n headers.set('Content-Type', form ? 'application/x-www-form-urlencoded' : 'application/json');\n }\n if (authorization !== undefined) headers.set('Authorization', authorization);\n\n const logContext = { service: request.service, method: request.method, path: request.path, attempt };\n this.#log.emit('debug', 'sabre.request.start', logContext);\n const startedAt = Date.now();\n\n let response: Response;\n const body = request.body === undefined ? undefined : form ? String(request.body) : JSON.stringify(request.body);\n if (capture !== undefined) {\n capture.attempts++;\n if (request.onRawRequest !== undefined && request.auth !== false) {\n capture.request = { method: request.method, url, headers: rawRequestHeaders(headers), body };\n }\n }\n try {\n response = await this.#config.fetch(url, {\n method: request.method,\n headers,\n ...(body === undefined ? {} : { body }),\n ...(request.signal === undefined ? {} : { signal: request.signal }),\n });\n } catch (cause) {\n if (isAbort(cause, request.signal)) throw cause;\n const error = new SabreGatewayError(`${request.service}: fallo de red (${describe(cause)})`, {\n protocol: 'rest',\n retryable: true,\n cause,\n });\n this.#log.emit('error', 'sabre.request.end', { ...logContext, durationMs: Date.now() - startedAt, error });\n throw error;\n }\n\n const text = await response.text();\n if (capture !== undefined) capture.last = { status: response.status, headers: response.headers, body: text };\n const parsed = parseBody(text);\n const endContext = { ...logContext, status: response.status, durationMs: Date.now() - startedAt };\n\n // Paso 1: HTTP status de gateway.\n if (!response.ok) {\n const error = gatewayError(request.service, response.status, parsed);\n this.#log.emit('error', 'sabre.request.end', { ...endContext, error });\n throw error;\n }\n\n // Pasos 2–3: catálogo propio del servicio.\n const serviceError = request.classify?.(parsed, response);\n if (serviceError !== undefined) {\n this.#log.emit('warn', 'sabre.request.end', { ...endContext, error: serviceError });\n throw serviceError;\n }\n\n // Paso 4: data.\n this.#log.emit('info', 'sabre.request.end', endContext);\n return parsed as T;\n }\n\n #url(request: RestRequest): string {\n const path = request.path.startsWith('/') ? request.path : `/${request.path}`;\n const url = new URL(path, this.#config.baseUrl);\n for (const [key, value] of Object.entries(request.query ?? {})) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n return url.toString();\n }\n}\n\n/** Body parseado como JSON; si no es JSON, el texto tal cual; vacío → `undefined`. */\nfunction parseBody(text: string): unknown {\n if (text === '') return undefined;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return text;\n }\n}\n\nfunction gatewayError(service: string, status: number, body: unknown): SabreGatewayError {\n const code = extractCode(body);\n const detail = extractDescription(body);\n return new SabreGatewayError(\n `${service}: HTTP ${status}${code === undefined ? '' : ` ${code}`}${detail === undefined ? '' : `: ${detail}`}`,\n {\n protocol: 'rest',\n status,\n retryable: RETRYABLE_STATUS.has(status),\n raw: body,\n ...(code === undefined ? {} : { code }),\n },\n );\n}\n\n/**\n * Best-effort: el campo del código `ERR.2SG.*` no está confirmado (issue de fuente #21). Se\n * prueban `errorCode`, `error` y `errors[0].code`; este último, visto en un 401 de Get Seats\n * en CERT (`{ errors: [{ code: '305', descriptionText, statusText }] }`, 2026-10-31). Si no\n * viene, `errors[0].type`: un 502 de Get Seats `byPnrLocator` en CERT lo trae así\n * (`{ errors: [{ type: 'DOWNLINE_ERROR', description }] }`, 2026-11-02, #124).\n */\nfunction extractCode(body: unknown): string | undefined {\n if (typeof body !== 'object' || body === null) return undefined;\n for (const key of ['errorCode', 'error'] as const) {\n const value = (body as Record<string, unknown>)[key];\n if (typeof value === 'string' && value !== '') return value;\n }\n return firstErrorField(body, 'code') ?? firstErrorField(body, 'type');\n}\n\n/** Detalle legible de `errors[0]`: `descriptionText` o, si no viene, `description`. */\nfunction extractDescription(body: unknown): string | undefined {\n return firstErrorField(body, 'descriptionText') ?? firstErrorField(body, 'description');\n}\n\nfunction firstErrorField(body: unknown, key: string): string | undefined {\n if (typeof body !== 'object' || body === null) return undefined;\n const errors = (body as { errors?: unknown }).errors;\n const first: unknown = Array.isArray(errors) ? errors[0] : undefined;\n if (typeof first !== 'object' || first === null) return undefined;\n const value = (first as Record<string, unknown>)[key];\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction isUnauthorized(error: unknown): boolean {\n return error instanceof SabreGatewayError && error.protocol === 'rest' && error.status === 401;\n}\n\nfunction isAbort(error: unknown, signal: AbortSignal | undefined): boolean {\n return signal?.aborted === true || (error instanceof Error && error.name === 'AbortError');\n}\n\nfunction describe(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","// Cliente REST. Ver sabre-wiki/wiki/sdk/arquitectura-clientes-transporte.md.\nimport { Air } from './air/air.js';\nimport { AuthManager } from './auth/auth-manager.js';\nimport { BookingManagement } from './booking/booking-management.js';\nimport { type ResolvedConfig, resolveConfig, type SabreConfig, type SabreEnvironment } from './config.js';\nimport { RestTransport } from './http/rest-transport.js';\n\nexport class Sabre {\n readonly #config: ResolvedConfig;\n readonly #transport: RestTransport;\n /** Servicios de Air: shopping, revalidación. */\n readonly air: Air;\n /** Booking Management: creación de reservas. */\n readonly booking: BookingManagement;\n\n constructor(config: SabreConfig) {\n this.#config = resolveConfig(config);\n this.#transport = new RestTransport(this.#config);\n // Toda request lleva `Authorization: Bearer <token>`, salvo la propia de token (`auth: false`).\n const auth = new AuthManager(this.#config, this.#transport);\n this.#transport.setAuthorizationProvider(auth.bearerProvider());\n this.air = new Air(this.#transport);\n this.booking = new BookingManagement(this.#transport);\n }\n\n get environment(): SabreEnvironment {\n return this.#config.environment;\n }\n\n get baseUrl(): string {\n return this.#config.baseUrl;\n }\n}\n","// Transporte SOAP de `SabreLegacy`: sobre armado a mano, fetch, parseo y mapeo de errores.\n// Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (puntos 4 y 6),\n// cliente-http-y-libreria-xml.md y respuesta-cruda-soap.md.\nimport { XMLParser } from 'fast-xml-parser';\nimport { definedOnly, type ResolvedConfig } from '../config.js';\nimport { SabreBusinessError, SabreGatewayError, SabreWarning } from '../errors/index.js';\nimport { EventLogger } from '../logging/logger.js';\nimport { REDACTED, redactSoapEnvelope } from '../logging/redact.js';\nimport { type RawRequestCapture, rawRequestHeaders, type SabreRawRequestCallback } from './raw-request.js';\nimport type { SabreRawResponseCallback } from './raw-response.js';\nimport { type RetryOptions, retryDelay, sleep, validateRetryOptions } from './retry.js';\n\n/**\n * Status HTTP transitorios cuando la respuesta no trae un sobre SOAP (proxy, balanceador).\n * Solo se reintentan en operaciones idempotentes.\n */\nconst TRANSIENT_STATUS = new Set([429, 500, 503, 504]);\n\n/**\n * \"Se excedió el máximo de requests concurrentes: esperar ≥ 500 ms y reintentar\". Se asume que\n * Sabre no procesó el request, así que se reintentan también en las operaciones que mueven el\n * cursor. Sin confirmar: se valida en la Fase 4.\n */\nexport const BUSY_CODES: ReadonlySet<string> = new Set(['USG_CONNECTOR_IS_BUSY', 'USG_IS_BUSY', 'USG_SERVICE_IS_BUSY']);\n\n/**\n * Los demás `USG_*` que el catálogo manda a \"esperar ≥ 500 ms y reintentar\". No dicen si el\n * request se procesó, así que solo se reintentan en operaciones idempotentes.\n * `USG_RESOURCE_UNAVAILABLE` (límite de sesiones) no está: no se reintenta.\n */\nconst TRANSIENT_CODES: ReadonlySet<string> = new Set([\n 'USG_SECURITY_ICE_ERROR',\n 'USG_SERVICE_PROVIDER_ERROR',\n 'USG_NO_RESPONSE_FROM_JMSRECEIVER_IN_TIME',\n 'SC_SERVICE_UNAVAILABLE',\n 'USG_COULD_NOT_COMPLETE_REQUEST',\n 'USG_IIOP_OBJECT_NOT_EXIST',\n 'USG_IIOP_TRANSIENT_EXCEPTION',\n 'USG_MOM_SERVICE_PROVIDER_INFRASTRUCTURE_ERROR',\n]);\n\n/** Esquema fijo que documenta Sabre: 3 reintentos con 1 s de intervalo, sin jitter. */\nexport const PREVIOUS_ENTRY_ACTIVE_RETRIES = 3;\nexport const PREVIOUS_ENTRY_ACTIVE_DELAY_MS = 1000;\nconst PREVIOUS_ENTRY_ACTIVE = /PREVIOUS ENTRY ACTIVE/i;\n\ntype RetryReason = 'busy' | 'previous-entry-active' | 'transient';\n\n/** Credencial del header `wsse:Security`. */\nexport type SoapSecurity =\n /** Token de sesión (ATH) o stateless (ATK). */\n | { binarySecurityToken: string }\n /** Credenciales de `SessionCreateRQ`. `clientId` y `clientSecret` solo van en la 2.0.0. */\n | {\n usernameToken: {\n username: string;\n password: string;\n organization: string;\n domain: string;\n clientId?: string;\n clientSecret?: string;\n };\n };\n\nexport interface SoapRequest {\n /** Nombre del servicio para errores y logs, p. ej. `'queueAccess'`. */\n service: string;\n /** `eb:Service` y `eb:Action`, p. ej. `'QueueAccessLLSRQ'`. */\n action: string;\n /** Payload del `soap-env:Body`, ya armado y escapado (ver `xmlEscape`). */\n payload: string;\n /** `eb:CPAId`: el PCC. */\n cpaId: string;\n /** `eb:ConversationId` de la sesión. */\n conversationId: string;\n security: SoapSecurity;\n /**\n * Si la operación se puede repetir sin efectos (`count`, `list`, `ping`). Las que mueven el\n * cursor de una cola van en `false`: nunca se reintentan ante un fallo de red.\n */\n idempotent: boolean;\n retry?: Partial<RetryOptions>;\n /** `true` para devolver el `BinarySecurityToken` de la respuesta (solo `SessionCreateRQ`). */\n readSecurityToken?: boolean;\n signal?: AbortSignal;\n /** Método público sin `legacy.`, p. ej. `'queue.access'`. Lo reciben `onRawResponse` y `onRawRequest`. */\n operation?: string;\n onRawResponse?: SabreRawResponseCallback;\n /**\n * No se llama con `usernameToken` (`SessionCreateRQ`): el sobre lleva `wsse:Password` y el\n * `ClientSecret`, y la regla de auth lo deja fuera (ADR-029).\n */\n onRawRequest?: SabreRawRequestCallback;\n}\n\nexport interface SoapResponse {\n /** Elemento hijo del `Body` (p. ej. `QueueAccessRS`), parseado y sin prefijos de namespace. */\n payload: Record<string, unknown>;\n /** Nombre local de ese elemento, p. ej. `'QueueAccessRS'`. */\n payloadName: string;\n /** Los `stl:Warning` de `stl:ApplicationResults`. */\n warnings: SabreWarning[];\n /** `eb:MessageId` de la respuesta, el dato que pide soporte de Sabre. */\n messageId: string | undefined;\n /** `eb:Timestamp` de la respuesta, en UTC con `Z` (ver `respondedAtOf`). */\n respondedAt: string | undefined;\n /** El sobre redactado, como `raw` de los errores que arme la operación al leer el payload. */\n raw: string;\n /** El `BinarySecurityToken` del header, solo con `readSecurityToken`. */\n securityToken: string | undefined;\n status: number;\n}\n\nexport interface SoapTransportOptions {\n /** Solo para tests: id del `eb:MessageId`. */\n messageId?: () => string;\n /** Solo para tests: reloj del `eb:Timestamp`. */\n now?: () => Date;\n /** Solo para tests: fuente de aleatoriedad del jitter. */\n random?: () => number;\n /** Solo para tests: espera entre reintentos. */\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n}\n\n/**\n * Último intento con respuesta HTTP (`last`), para entregarlo una sola vez a `onRawResponse`, y\n * último sobre mandado (`request`), para `onRawRequest`.\n */\ninterface RawCapture {\n attempts: number;\n last?: { status: number; headers: Headers; body: string };\n request?: RawRequestCapture;\n}\n\nconst SOAP_HEADERS = { 'Content-Type': 'text/xml; charset=utf-8', Accept: 'text/xml' } as const;\n\ntype XmlNode = Record<string, unknown>;\n\n/**\n * Atributos con `@`, sin prefijos de namespace y todo como string: `\"011\"` y `\"....261\"`\n * llegan tal cual, para que cada servicio decida cómo leerlos.\n */\nconst PARSER_OPTIONS = {\n ignoreAttributes: false,\n attributeNamePrefix: '@',\n removeNSPrefix: true,\n parseTagValue: false,\n parseAttributeValue: false,\n processEntities: true,\n} as const;\nconst parser = new XMLParser(PARSER_OPTIONS);\n/** Igual, pero sin recortar los textos: solo para lo que depende de los espacios. */\nconst untrimmedParser = new XMLParser({ ...PARSER_OPTIONS, trimValues: false });\n\nexport class SoapTransport {\n readonly #config: ResolvedConfig;\n readonly #log: EventLogger;\n readonly #messageId: () => string;\n readonly #now: () => Date;\n readonly #random: () => number;\n readonly #sleep: (ms: number, signal?: AbortSignal) => Promise<void>;\n\n constructor(config: ResolvedConfig, options: SoapTransportOptions = {}) {\n this.#config = config;\n this.#log = new EventLogger(config.logger);\n this.#messageId = options.messageId ?? (() => globalThis.crypto.randomUUID());\n this.#now = options.now ?? (() => new Date());\n this.#random = options.random ?? Math.random;\n this.#sleep = options.sleep ?? sleep;\n }\n\n /** @internal Para los eventos de sesión que no son una request. */\n get log(): EventLogger {\n return this.#log;\n }\n\n async request(request: SoapRequest): Promise<SoapResponse> {\n if (request.retry !== undefined) validateRetryOptions(request.retry, 'retry');\n const capture: RawCapture = { attempts: 0 };\n try {\n return await this.#attempts(request, capture);\n } finally {\n // Una sola vez por operación: primero el último sobre que se mandó, aunque no haya tenido\n // respuesta, y después el último intento que tuvo respuesta HTTP.\n if (capture.request !== undefined) this.#deliverRawRequest(request, capture.request, capture.attempts);\n if (capture.last !== undefined) this.#deliverRaw(request, { ...capture.last, attempts: capture.attempts });\n }\n }\n\n /**\n * Dos presupuestos separados: el backoff genérico (`retry.maxRetries`, para `USG_*_BUSY` y\n * los transitorios) y el esquema fijo de `PREVIOUS ENTRY ACTIVE`, que no se ajusta a la config.\n */\n async #attempts(request: SoapRequest, capture: RawCapture): Promise<SoapResponse> {\n const retry = { ...this.#config.retry, ...definedOnly(request.retry ?? {}) };\n let generic = 0;\n let previousEntryActive = 0;\n for (let attempt = 0; ; attempt++) {\n try {\n return await this.#send(request, attempt, capture);\n } catch (error) {\n const reason = retryReason(error, request.idempotent);\n let delayMs: number;\n if (reason === 'previous-entry-active' && previousEntryActive < PREVIOUS_ENTRY_ACTIVE_RETRIES) {\n previousEntryActive++;\n delayMs = PREVIOUS_ENTRY_ACTIVE_DELAY_MS;\n } else if ((reason === 'busy' || reason === 'transient') && generic < retry.maxRetries) {\n delayMs = retryDelay(generic, retry.baseDelayMs, this.#random);\n generic++;\n } else {\n throw error;\n }\n this.#log.emit('warn', 'sabre.request.retry', {\n protocol: 'soap',\n service: request.service,\n action: request.action,\n attempt: attempt + 1,\n reason,\n delayMs,\n error: error as SabreGatewayError,\n });\n await this.#sleep(delayMs, request.signal);\n }\n }\n }\n\n async #send(request: SoapRequest, attempt: number, capture: RawCapture): Promise<SoapResponse> {\n const envelope = this.#envelope(request);\n const logContext = { protocol: 'soap', service: request.service, action: request.action, attempt };\n this.#log.emit('debug', 'sabre.request.start', logContext);\n const startedAt = Date.now();\n\n let response: Response;\n capture.attempts++;\n if (wantsRawRequest(request)) {\n // eb:MessageId y eb:Timestamp se generan en cada intento: se guarda el último sobre.\n capture.request = {\n method: 'POST',\n url: this.#config.soapBaseUrl,\n headers: rawRequestHeaders(SOAP_HEADERS),\n body: redactSoapEnvelope(scrubToken(envelope, request.security)),\n };\n }\n try {\n response = await this.#config.fetch(this.#config.soapBaseUrl, {\n method: 'POST',\n headers: SOAP_HEADERS,\n body: envelope,\n ...(request.signal === undefined ? {} : { signal: request.signal }),\n });\n } catch (cause) {\n if (isAbort(cause, request.signal)) throw cause;\n const error = new SabreGatewayError(`${request.service}: fallo de red (${describe(cause)})`, {\n protocol: 'soap',\n retryable: false,\n cause,\n });\n this.#log.emit('error', 'sabre.request.end', { ...logContext, durationMs: Date.now() - startedAt, error });\n throw error;\n }\n\n const original = await response.text();\n // Todo lo que sale del transporte (raw, errores, logs) se arma desde el texto redactado.\n const text = redactSoapEnvelope(scrubToken(original, request.security));\n capture.last = { status: response.status, headers: response.headers, body: text };\n\n const document = parseEnvelope(text);\n const messageId = stringAt(document?.Header, 'MessageHeader', 'MessageData', 'MessageId');\n const endContext = {\n ...logContext,\n status: response.status,\n durationMs: Date.now() - startedAt,\n ...(messageId === undefined ? {} : { messageId }),\n };\n\n try {\n const result = this.#classify(request, response, document, text);\n this.#log.emit('info', 'sabre.request.end', { ...endContext, warnings: result.warnings.length });\n return {\n ...result,\n messageId,\n respondedAt: respondedAtOf(text),\n raw: text,\n securityToken: request.readSecurityToken === true ? readSecurityToken(original) : undefined,\n status: response.status,\n };\n } catch (error) {\n const level = error instanceof SabreBusinessError ? 'warn' : 'error';\n this.#log.emit(level, 'sabre.request.end', { ...endContext, error });\n throw error;\n }\n }\n\n /** Orden de detección: fault (gateway), luego `stl:Error` (negocio), luego data. */\n #classify(\n request: SoapRequest,\n response: Response,\n document: { Header: unknown; Body: XmlNode } | undefined,\n text: string,\n ): Pick<SoapResponse, 'payload' | 'payloadName' | 'warnings'> {\n const { service } = request;\n if (document === undefined) {\n throw new SabreGatewayError(`${service}: HTTP ${response.status}, la respuesta no es un sobre SOAP`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: text,\n });\n }\n\n // Paso 1: SOAP fault (errores de `Transport` y `Validation`, y los `USG_*` del gateway).\n const fault = asNode(document.Body.Fault);\n if (fault !== undefined) throw faultError(service, response.status, fault, text);\n\n const [payloadName, payloadValue] = firstElement(document.Body);\n const payload = asNode(payloadValue);\n if (payloadName === undefined || payload === undefined) {\n throw new SabreGatewayError(`${service}: HTTP ${response.status}, el sobre SOAP no trae payload`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: text,\n });\n }\n if (!response.ok) {\n throw new SabreGatewayError(`${service}: HTTP ${response.status}`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: text,\n });\n }\n\n // Paso 3: `stl:ApplicationResults`. Los `stl:Warning` no lanzan.\n const results = asNode(payload.ApplicationResults);\n const warnings = asArray(results?.Warning).map((node) => {\n const entry = resultEntry(node);\n return new SabreWarning(`${service}: ${entry.description}`, { service, code: entry.code, raw: text });\n });\n const errors = asArray(results?.Error).map((node) => {\n const entry = resultEntry(node);\n return new SabreBusinessError(`${service}: ${entry.description}`, {\n service,\n code: entry.code,\n raw: text,\n retryable: PREVIOUS_ENTRY_ACTIVE.test(entry.description),\n });\n });\n const [first, ...rest] = errors;\n if (first !== undefined) {\n throw new SabreBusinessError(first.message, {\n service,\n code: first.code,\n raw: text,\n retryable: first.retryable,\n warnings,\n errors: rest,\n });\n }\n\n // Paso 4: data.\n return { payload, payloadName, warnings };\n }\n\n #envelope(request: SoapRequest): string {\n const timestamp = this.#now().toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n return [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:eb=\"http://www.ebxml.org/namespaces/messageHeader\">',\n '<soap-env:Header>',\n '<eb:MessageHeader soap-env:mustUnderstand=\"1\" eb:version=\"1.0\">',\n '<eb:From><eb:PartyId/></eb:From>',\n '<eb:To><eb:PartyId/></eb:To>',\n `<eb:CPAId>${xmlEscape(request.cpaId)}</eb:CPAId>`,\n `<eb:ConversationId>${xmlEscape(request.conversationId)}</eb:ConversationId>`,\n `<eb:Service>${xmlEscape(request.action)}</eb:Service>`,\n `<eb:Action>${xmlEscape(request.action)}</eb:Action>`,\n '<eb:MessageData>',\n `<eb:MessageId>mid:${xmlEscape(this.#messageId())}</eb:MessageId>`,\n `<eb:Timestamp>${timestamp}</eb:Timestamp>`,\n '</eb:MessageData>',\n '</eb:MessageHeader>',\n securityHeader(request.security),\n '</soap-env:Header>',\n `<soap-env:Body>${request.payload}</soap-env:Body>`,\n '</soap-env:Envelope>',\n ].join('');\n }\n\n /** Un callback que lanza no rompe la operación (mismo criterio que REST). */\n #deliverRawRequest(request: SoapRequest, raw: RawRequestCapture, attempts: number): void {\n const operation = request.operation ?? request.service;\n try {\n request.onRawRequest?.({ operation, protocol: 'soap', ...raw, attempts });\n } catch (error) {\n this.#log.emit('warn', 'sabre.request.rawRequestHookFailed', {\n service: request.service,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n }\n\n /** Un callback que lanza no rompe la operación (mismo criterio que REST). */\n #deliverRaw(request: SoapRequest, raw: Required<RawCapture>['last'] & { attempts: number }): void {\n if (request.onRawResponse === undefined) return;\n const operation = request.operation ?? request.service;\n try {\n request.onRawResponse({ operation, protocol: 'soap', ...raw });\n } catch (error) {\n this.#log.emit('warn', 'sabre.request.rawResponseHookFailed', {\n service: request.service,\n operation,\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n }\n}\n\n/** Escapa texto para un elemento o un atributo XML. */\n/**\n * `eb:Timestamp` del header de un sobre de respuesta, en ISO 8601 UTC: Sabre lo manda sin zona\n * (`\"2026-11-06T17:34:16\"`) y en UTC (comparado con `stl:Success@timeStamp`, que trae `Z`, en\n * CERT el 2026-11-06), así que se le agrega `Z`. Con una zona explícita queda tal cual. Si no\n * viene o no tiene forma de fecha y hora, `undefined`. Ver ADR-027 (C1).\n */\nexport function respondedAtOf(raw: unknown): string | undefined {\n if (typeof raw !== 'string') return undefined;\n const header = /<(?:[\\w-]+:)?Header\\b[\\s\\S]*?<\\/(?:[\\w-]+:)?Header>/.exec(raw)?.[0];\n const value = header === undefined ? undefined : /<(?:[\\w-]+:)?Timestamp>\\s*([^<\\s]+)\\s*</.exec(header)?.[1];\n const match = value === undefined ? null : /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?)(Z|[+-]\\d{2}:\\d{2})?$/.exec(value);\n if (match === null) return undefined;\n return `${match[1]}${match[2] ?? 'Z'}`;\n}\n\n/** `{ respondedAt }` si el sobre lo trae; si no, nada (`exactOptionalPropertyTypes`). */\nexport function respondedAtField(raw: unknown): { respondedAt?: string } {\n const respondedAt = respondedAtOf(raw);\n return respondedAt === undefined ? {} : { respondedAt };\n}\n\nexport function xmlEscape(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\nfunction securityHeader(security: SoapSecurity): string {\n const open = '<wsse:Security xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2002/12/secext\">';\n if ('binarySecurityToken' in security) {\n return `${open}<wsse:BinarySecurityToken valueType=\"String\" EncodingType=\"wsse:Base64Binary\">${xmlEscape(security.binarySecurityToken)}</wsse:BinarySecurityToken></wsse:Security>`;\n }\n const token = security.usernameToken;\n return [\n open,\n '<wsse:UsernameToken>',\n `<wsse:Username>${xmlEscape(token.username)}</wsse:Username>`,\n `<wsse:Password>${xmlEscape(token.password)}</wsse:Password>`,\n `<Organization>${xmlEscape(token.organization)}</Organization>`,\n `<Domain>${xmlEscape(token.domain)}</Domain>`,\n token.clientId === undefined ? '' : `<ClientId>${xmlEscape(token.clientId)}</ClientId>`,\n token.clientSecret === undefined ? '' : `<ClientSecret>${xmlEscape(token.clientSecret)}</ClientSecret>`,\n '</wsse:UsernameToken>',\n '</wsse:Security>',\n ].join('');\n}\n\n/**\n * Tapa el token que mandó el SDK donde sea que Sabre lo repita (p. ej. dentro de un\n * `faultstring`), en texto plano o escapado. El `BinarySecurityToken` del header lo tapa\n * después `redactSoapEnvelope`.\n */\n/** `onRawRequest` solo con token de sesión: el sobre de `SessionCreateRQ` es la credencial. */\nfunction wantsRawRequest(request: SoapRequest): boolean {\n return request.onRawRequest !== undefined && 'binarySecurityToken' in request.security;\n}\n\nfunction scrubToken(text: string, security: SoapSecurity): string {\n if (!('binarySecurityToken' in security) || security.binarySecurityToken === '') return text;\n const token = security.binarySecurityToken;\n return text.split(token).join(REDACTED).split(xmlEscape(token)).join(REDACTED);\n}\n\nfunction parseEnvelope(text: string, xmlParser = parser): { Header: unknown; Body: XmlNode } | undefined {\n if (text.trim() === '') return undefined;\n let parsed: unknown;\n try {\n parsed = xmlParser.parse(text);\n } catch {\n return undefined;\n }\n const envelope = asNode(asNode(parsed)?.Envelope);\n const body = asNode(envelope?.Body);\n if (envelope === undefined || body === undefined) return undefined;\n return { Header: envelope.Header, Body: body };\n}\n\n/** Lee el token del texto original, antes de redactar. Solo para `SessionCreateRS`. */\nfunction readSecurityToken(original: string): string | undefined {\n const document = parseEnvelope(original);\n const token = stringAt(document?.Header, 'Security', 'BinarySecurityToken');\n return token === undefined || token.trim() === '' ? undefined : token.trim();\n}\n\n/**\n * `USG_*` dentro del fault, best-effort: ninguna fuente dice en qué campo viaja. Se busca en\n * `faultcode`, `faultstring` y `detail`, y si no aparece se usa el `faultcode`. Se confirma\n * con la primera sesión real (#95).\n */\nconst USG_CODE = /\\bUSG_[A-Z0-9_]+\\b/;\n\nfunction faultError(service: string, status: number, fault: XmlNode, text: string): SabreGatewayError {\n const faultcode = textOf(fault.faultcode);\n const faultstring = textOf(fault.faultstring);\n const haystack = [faultcode, faultstring, JSON.stringify(fault.detail ?? '')].join(' ');\n const code = USG_CODE.exec(haystack)?.[0] ?? faultcode;\n const detail = [faultcode, faultstring].filter((part) => part !== undefined && part !== '').join(': ');\n // `retryable: true` solo para `USG_*_BUSY` y `PREVIOUS ENTRY ACTIVE` (decisiones 4 y 5).\n const retryable = (code !== undefined && BUSY_CODES.has(code)) || PREVIOUS_ENTRY_ACTIVE.test(haystack);\n return new SabreGatewayError(`${service}: SOAP fault${detail === '' ? '' : ` ${detail}`}`, {\n protocol: 'soap',\n status,\n retryable,\n raw: text,\n ...(code === undefined || code === '' ? {} : { code }),\n });\n}\n\n/**\n * Un `stl:Error` o `stl:Warning`: `code` es el primer `Message@code`, o el primer `ShortText` si\n * no viene (las respuestas reales traen el `ERR.SWS.*` ahí, #96), o el `type`. La descripción junta\n * los textos de `Message` con el `ShortText`.\n */\nfunction resultEntry(node: unknown): { code: string; description: string } {\n const entry = asNode(node) ?? {};\n const messages: string[] = [];\n const shortTexts: string[] = [];\n let code: string | undefined;\n for (const results of asArray(entry.SystemSpecificResults)) {\n const resultsNode = asNode(results) ?? {};\n for (const message of asArray(resultsNode.Message)) {\n code ??= nonEmpty(asNode(message)?.['@code']);\n const value = textOf(message);\n if (value !== undefined && value !== '') messages.push(value);\n }\n for (const shortText of asArray(resultsNode.ShortText)) {\n const value = textOf(shortText);\n if (value !== undefined && value !== '') shortTexts.push(value);\n }\n }\n const type = nonEmpty(entry['@type']);\n const description = [\n messages.join(' / ') || type || 'sin detalle',\n ...shortTexts.filter((short) => !messages.includes(short)).map((short) => `(${short})`),\n ].join(' ');\n return { code: code ?? shortTexts[0] ?? type ?? 'UNKNOWN', description };\n}\n\n/**\n * Por qué se puede reintentar un error, según la idempotencia de la operación. Ver\n * tier-3-sesion-y-colas-soap.md (punto 5) y politica-de-reintentos-y-backoff.md.\n */\nfunction retryReason(error: unknown, idempotent: boolean): RetryReason | undefined {\n if ((error instanceof SabreBusinessError || error instanceof SabreGatewayError) && PREVIOUS_ENTRY_ACTIVE.test(error.message)) {\n return 'previous-entry-active';\n }\n if (!(error instanceof SabreGatewayError) || error.protocol !== 'soap') return undefined;\n if (error.code !== undefined && BUSY_CODES.has(error.code)) return 'busy';\n // Lo que sigue pudo haber llegado a Sabre: solo se repite si la operación es idempotente.\n if (!idempotent) return undefined;\n if (error.code !== undefined) return TRANSIENT_CODES.has(error.code) ? 'transient' : undefined;\n // Sin código: un fallo de red (sin status) o una respuesta sin sobre SOAP.\n if (error.status === undefined || TRANSIENT_STATUS.has(error.status)) return 'transient';\n return undefined;\n}\n\n/**\n * El payload del `Body` de `raw` con los textos tal cual, sin recortar espacios ni saltos de\n * línea. Para las pantallas de host (`SabreCommandLLSRS`), que van alineadas por columna: el\n * parser compartido recorta y desalinea la primera línea.\n */\nexport function untrimmedPayload(raw: string): Record<string, unknown> | undefined {\n const document = parseEnvelope(raw, untrimmedParser);\n return document === undefined ? undefined : asNode(firstElement(document.Body)[1]);\n}\n\nfunction firstElement(node: XmlNode): [string | undefined, unknown] {\n for (const [key, value] of Object.entries(node)) {\n if (!key.startsWith('@') && key !== '#text') return [key, Array.isArray(value) ? value[0] : value];\n }\n return [undefined, undefined];\n}\n\nfunction asNode(value: unknown): XmlNode | undefined {\n if (Array.isArray(value)) return asNode(value[0]);\n return typeof value === 'object' && value !== null ? (value as XmlNode) : undefined;\n}\n\nexport function asArray(value: unknown): unknown[] {\n if (value === undefined || value === null || value === '') return [];\n return Array.isArray(value) ? value : [value];\n}\n\n/** Texto de un elemento: un string, o el `#text` de un elemento con atributos. */\nexport function textOf(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n const node = asNode(value);\n const text = node?.['#text'];\n return typeof text === 'string' ? text : node === undefined ? undefined : '';\n}\n\nfunction stringAt(root: unknown, ...path: string[]): string | undefined {\n let node: unknown = root;\n for (const key of path) node = asNode(node)?.[key];\n return nonEmpty(textOf(node));\n}\n\nfunction nonEmpty(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction isAbort(error: unknown, signal: AbortSignal | undefined): boolean {\n return signal?.aborted === true || (error instanceof Error && error.name === 'AbortError');\n}\n\nfunction describe(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n","// Credenciales de `SessionCreateRQ`, sacadas del mismo `username` EPR que autentica en REST.\n// Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 1 y \"Decisiones tomadas en la\n// revisión\") y wiki/entities/oauth-token-create.md (formatos del EPR).\nimport type { SabreCredentials, SabreCredentialsV2 } from '../config.js';\n\n/** Versión de `SessionCreateRQ`: 2.0.0 con `clientId`/`clientSecret`, 1.0.0 sin ellos. */\nexport type SessionCreateVersion = '2.0.0' | '1.0.0';\n\n/** Lo que pide el `wsse:UsernameToken` de `SessionCreateRQ`, ya separado. */\nexport interface SessionCredentials {\n version: SessionCreateVersion;\n /** Usuario EPR, sin PCC ni domain. */\n username: string;\n password: string;\n /** PCC: `Organization` del `UsernameToken` y `eb:CPAId`. Default de las operaciones de cola. */\n organization: string;\n domain: string;\n /** Solo en la 2.0.0. */\n clientId?: string;\n /** Solo en la 2.0.0. */\n clientSecret?: string;\n}\n\n/** 3 o 4 caracteres alfanuméricos. */\nconst PCC = /^[A-Za-z0-9]{3,4}$/;\n\n/** Si el texto es un PCC: 3 o 4 caracteres alfanuméricos. */\nexport function isPseudoCityCode(value: unknown): value is string {\n return typeof value === 'string' && PCC.test(value);\n}\n\n/** Prefijo del EPR de OAuth v2: `V1:<user>:<PCC>:<domain>`. */\nconst V2_PREFIX = 'V1:';\n\nconst FORMATS = \"'V1:<user>:<PCC>:<domain>' (OAuth v2) o '<user>-<PCC>-<domain>' (OAuth v3)\";\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/**\n * Separa usuario, PCC y domain del `username` EPR, leyendo de derecha a izquierda: el último\n * campo es el domain, el anterior el PCC y lo que queda es el usuario. Así un usuario con `-`\n * o `:` no rompe el formato. Los mensajes de error no repiten el `username`.\n */\nexport function parseEprUsername(username: string): { username: string; organization: string; domain: string } {\n const v2 = username.startsWith(V2_PREFIX);\n const fields = (v2 ? username.slice(V2_PREFIX.length) : username).split(v2 ? ':' : '-');\n if (fields.length < 3) fail(`credentials.username debe tener el formato ${FORMATS} para abrir una sesión SOAP`);\n\n const domain = fields.pop()!;\n const organization = fields.pop()!;\n const user = fields.join(v2 ? ':' : '-');\n if (user.trim() === '' || domain.trim() === '') {\n fail(`credentials.username debe tener el formato ${FORMATS} para abrir una sesión SOAP`);\n }\n if (!PCC.test(organization)) {\n fail('el PCC de credentials.username debe tener 3 o 4 caracteres alfanuméricos');\n }\n return { username: user, organization, domain };\n}\n\n/**\n * Credenciales de sesión a partir de las de la config. La versión sale de los datos, sin\n * fallback: con `clientId` y `clientSecret`, 2.0.0; sin ninguno, 1.0.0; con uno solo, error de\n * configuración.\n */\nexport function resolveSessionCredentials(\n credentials: Readonly<SabreCredentials | SabreCredentialsV2>,\n): SessionCredentials {\n const { clientId, clientSecret, password } = credentials;\n if ((clientId === undefined) !== (clientSecret === undefined)) {\n fail('credentials.clientId y credentials.clientSecret van juntos: pasa los dos (SessionCreateRQ 2.0.0) o ninguno (1.0.0)');\n }\n const epr = parseEprUsername(credentials.username);\n if (clientId === undefined || clientSecret === undefined) return { version: '1.0.0', ...epr, password };\n\n if (typeof clientId !== 'string' || clientId.trim() === '') fail('credentials.clientId debe ser un string no vacío');\n if (typeof clientSecret !== 'string' || clientSecret.trim() === '') {\n fail('credentials.clientSecret debe ser un string no vacío');\n }\n return { version: '2.0.0', ...epr, password, clientId, clientSecret };\n}\n","// Access Queue (`QueueAccessLLSRQ` 2.1.1): entrar a una cola y navegarla. Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (puntos 2, 3 y 4) y\n// wiki/sources/access-queue-v2-1-1-design.md.\nimport { XMLParser } from 'fast-xml-parser';\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreBusinessError, SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, textOf, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport { type QueueRef, queueRefAttribute } from './queue-ref.js';\n\nexport const QUEUE_ACCESS_SERVICE = 'queueAccess';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\n/** Texto exacto del fin de cola. Es la respuesta normal cuando no queda ningún PNR. */\nexport const END_OF_DISPLAY = 'END OF DISPLAY FOR REQUESTED DATA';\n/**\n * Una cola vacía, como `stl:Error` de `access` y `list` (producción, #96). Las fuentes solo\n * mostraban `END OF DISPLAY`.\n */\nexport const QUEUE_EMPTY = 'QUEUE SELECTED WAS EMPTY';\n/** `QXI` con la sesión fuera de una cola, como `stl:Error` (producción, #96). */\nexport const OFF_QUEUE = 'CANNOT DO THIS IF OFF QUEUE';\n\n/** Por qué terminó la cola: el fin de cola de siempre o una cola vacía al entrar. */\nexport type QueueEndReason = 'end-of-display' | 'empty';\n\n/** Máximo de filtros de `selection` y de colas de `remove({ from })`, según el design 2.1.1. */\nexport const MAX_SELECTIONS = 8;\nexport const MAX_REMOVE_FROM = 3;\n\n/**\n * Un filtro al entrar a una cola: un calificador de host, p. ej. `{ function: 'AL', criteria: 'DL' }`\n * (solo los PNR de esa aerolínea). Las reglas de combinación las valida Sabre.\n */\nexport interface QueueSelection {\n function: string;\n criteria: string;\n}\n\nexport interface QueueAccessRequest {\n queue: QueueRef;\n /** PCC de la cola. Por defecto, el de la sesión. */\n pcc?: string;\n /** Hasta 8 filtros. Con selección, la cola abre solo los PNR que cumplen el criterio. */\n selection?: readonly QueueSelection[];\n}\n\n/** Una cola de la que `remove` saca el PNR actual. */\nexport interface QueueRemoveTarget {\n queue: QueueRef;\n /** Por defecto, el PCC de la sesión. */\n pcc?: string;\n}\n\nexport interface QueueRemoveRequest {\n /** De 1 a 3 colas de las que sacar el PNR actual a la vez. Sin `from`, sale de la cola en curso. */\n from?: readonly QueueRemoveTarget[];\n}\n\nexport type QueueAccessOptions = RequestOptions;\nexport type QueueNavigationOptions = RequestOptions;\n\n/** El PNR en el que quedó parada la cola. */\nexport interface QueueItem {\n /** Localizador: `Line/UniqueID@ID`. */\n locator: string;\n /**\n * `Line/DateTime`, tal cual llegó: con año en las respuestas reales (`\"2024-05-15T13:24\"`), sin\n * año en el design (`\"12-21T07:00\"`). Al entrar a una cola (`access`, `ignore`, `remove`, `place`)\n * es la **última modificación del PNR**, no la colocación en la cola: para un mismo PNR no\n * coincide con el de `list`, que sí es la colocación (producción, #96 y #155). Se devuelve tal cual.\n */\n placedAt?: string;\n /** `Line/POS/Source`: quién colocó el PNR. `agentSine` puede ser `SABRE`. */\n placedBy?: { agentSine?: string; pseudoCityCode?: string };\n /** `Line/PassengerName`. Las respuestas reales de entrar a una cola no lo traen. */\n primaryPassenger?: string;\n /** `Line/Group`. Las respuestas reales de entrar a una cola no lo traen. */\n group?: string;\n /**\n * `Paragraph/Text`: el PNR en formato de host, línea por línea y tal cual, con su sangría. Las\n * líneas vacías llegan como `\"\"`. Se interpreta con `parseQueueParagraph`.\n */\n paragraph: readonly string[];\n}\n\n/**\n * Un mensaje de la cola `S`, la de mensajes del PCC (ADR-028). No es un PNR: no trae localizador\n * ni datos de colocación, solo texto libre.\n */\nexport interface QueueMessage {\n /** `Paragraph/Text`, línea por línea y tal cual, con su sangría. */\n text: string[];\n}\n\n/**\n * Resultado de una operación que avanza en la cola. Lo que queda en pantalla se distingue por\n * `kind`: un PNR (`'pnr'`, en las colas numéricas y con nombre) o un mensaje (`'message'`, en la\n * cola `S`). El fin de cola es un resultado, no un error: `END OF DISPLAY FOR REQUESTED DATA`\n * llega como `{ done: true }`, también al entrar a una cola vacía, y deja la sesión fuera de la\n * cola.\n */\nexport type QueueStep =\n | { done: false; kind: 'pnr'; item: QueueItem; warnings: SabreWarning[]; respondedAt?: string }\n | { done: false; kind: 'message'; message: QueueMessage; warnings: SabreWarning[]; respondedAt?: string }\n | { done: true; reason: QueueEndReason; message: string; warnings: SabreWarning[]; respondedAt?: string };\n\n/** Qué acción de navegación se manda en `Navigation@Action`. */\ntype NavigationAction = 'I' | 'QR' | 'QXI';\n\nconst OPERATIONS: Record<NavigationAction, string> = { I: 'queue.ignore', QR: 'queue.remove', QXI: 'queue.exit' };\n\nfunction root(body: string): string {\n return `<QueueAccessRQ Version=\"2.1.1\" xmlns=\"${NAMESPACE}\">${body}</QueueAccessRQ>`;\n}\n\nfunction identifier(queue: QueueRef, pcc: string): string {\n return `<QueueIdentifier ${queueRefAttribute(queue)} PseudoCityCode=\"${xmlEscape(pcc)}\"/>`;\n}\n\n/** Los `Selection`, hermanos de `QueueIdentifier`. Los usan `access` y `list`. */\nexport function selectionXml(selection: readonly QueueSelection[]): string {\n return selection\n .map((filter) => `<Selection Function=\"${xmlEscape(filter.function)}\" Criteria=\"${xmlEscape(filter.criteria)}\"/>`)\n .join('');\n}\n\n/** `Q/<PCC><cola>`, con los filtros de `Selection` si los hay. */\nexport function queueAccessPayload(queue: QueueRef, pcc: string, selection: readonly QueueSelection[] = []): string {\n return root(`${identifier(queue, pcc)}${selectionXml(selection)}`);\n}\n\n/** `Navigation@Action`. Solo `QR` lleva `QueueIdentifier`: las colas de las que sacar el PNR. */\nexport function queueNavigationPayload(action: NavigationAction, from: ReadonlyArray<{ queue: QueueRef; pcc: string }> = []): string {\n return root(`<Navigation Action=\"${action}\"/>${from.map((target) => identifier(target.queue, target.pcc)).join('')}`);\n}\n\n/**\n * Las operaciones de Access Queue mueven el cursor: no se reintentan ante un fallo de red. El\n * transporte solo las repite ante `USG_*_BUSY` y `PREVIOUS ENTRY ACTIVE`.\n */\nexport function queueAccessRequest(payload: string, operation: string, options: RequestOptions): SessionRequest {\n return { service: QUEUE_ACCESS_SERVICE, action: 'QueueAccessLLSRQ', payload, idempotent: false, operation, ...options };\n}\n\nexport function navigationOperation(action: NavigationAction): string {\n return OPERATIONS[action];\n}\n\n/**\n * Parser aparte para el `Paragraph`: el del transporte recorta los espacios, y el formato de host\n * usa la sangría. Se vuelve a leer el sobre (ya redactado) sin recortar.\n */\nconst paragraphParser = new XMLParser({\n ignoreAttributes: true,\n removeNSPrefix: true,\n parseTagValue: false,\n trimValues: false,\n processEntities: true,\n isArray: (name) => name === 'Text',\n});\n\nexport type XmlNode = Record<string, unknown>;\n\nexport function node(value: unknown): XmlNode | undefined {\n if (Array.isArray(value)) return node(value[0]);\n return typeof value === 'object' && value !== null ? (value as XmlNode) : undefined;\n}\n\nexport function attribute(value: unknown, name: string): string | undefined {\n const text = node(value)?.[`@${name}`];\n return typeof text === 'string' && text.trim() !== '' ? text.trim() : undefined;\n}\n\nfunction element(value: unknown): string | undefined {\n const text = textOf(Array.isArray(value) ? value[0] : value)?.trim();\n return text === undefined || text === '' ? undefined : text;\n}\n\n/**\n * Las líneas `Text` de una respuesta, tal cual: las de `Paragraph` en `QueueAccessRS` y las del\n * primer nivel en `QueuePlaceRS`.\n */\nexport function textLines(raw: string, payloadName: 'QueueAccessRS' | 'QueuePlaceRS'): string[] {\n let parsed: unknown;\n try {\n parsed = paragraphParser.parse(raw);\n } catch {\n return [];\n }\n const payload = node(node(node(node(parsed)?.Envelope)?.Body)?.[payloadName]);\n const container = payloadName === 'QueueAccessRS' ? node(payload?.Paragraph) : payload;\n return asArray(container?.Text).map((line) => (typeof line === 'string' ? line : (textOf(line) ?? '')));\n}\n\n/** Las líneas de `Paragraph/Text` de un `QueueAccessRS`, tal cual. */\nexport function paragraphLines(raw: string): string[] {\n return textLines(raw, 'QueueAccessRS');\n}\n\n/** Si un texto de Sabre es el fin de cola, comparado por el texto exacto. */\nexport function isEndOfDisplay(text: string | undefined): boolean {\n return text?.trim() === END_OF_DISPLAY;\n}\n\n/**\n * Si un `stl:Warning` o `stl:Error` es el fin de cola. El transporte junta los `Message` con\n * `\" / \"` y agrega el `ShortText` entre paréntesis, así que se busca el texto como una de esas\n * partes, entero.\n */\nexport function isEndOfDisplayResult(error: { message: string; service: string }): boolean {\n return resultHasText(error, END_OF_DISPLAY);\n}\n\n/** Si un `stl:Warning` o `stl:Error` trae `text` como una de sus partes, entero. */\nexport function resultHasText(error: { message: string; service: string }, text: string): boolean {\n const prefix = `${error.service}: `;\n const description = error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message;\n return description\n .split(/ \\/ | \\(|\\)/)\n .some((part) => part.trim() === text);\n}\n\n/**\n * El fin de cola, si llegó como `stl:Error` de `service`: `END OF DISPLAY` o una cola vacía\n * (`QUEUE SELECTED WAS EMPTY`). Si no, `undefined`.\n */\nexport function queueEndError(error: unknown, service: string): { reason: QueueEndReason; error: SabreBusinessError } | undefined {\n if (!(error instanceof SabreBusinessError) || error.service !== service) return undefined;\n const results = [error, ...error.errors];\n if (results.some((result) => resultHasText(result, QUEUE_EMPTY))) return { reason: 'empty', error };\n if (results.some(isEndOfDisplayResult)) return { reason: 'end-of-display', error };\n return undefined;\n}\n\n/** Si el error es el de `QXI` con la sesión fuera de una cola. */\nexport function isOffQueueError(error: unknown): error is SabreBusinessError {\n return error instanceof SabreBusinessError && [error, ...error.errors].some((result) => resultHasText(result, OFF_QUEUE));\n}\n\n/** El fin de cola. `raw` es el sobre del que sale `respondedAt`: la respuesta o el `stl:Error`. */\nexport function endStep(warnings: SabreWarning[], reason: QueueEndReason = 'end-of-display', raw?: unknown): QueueStep {\n return { done: true, reason, message: reason === 'empty' ? QUEUE_EMPTY : END_OF_DISPLAY, warnings, ...respondedAtField(raw) };\n}\n\n/**\n * Lee el paso de un `QueueAccessRS`. El fin de cola llega como primera línea del `Paragraph`\n * (evidencia de `1.0.8`, y la cola `S` en CERT) o como `stl:Warning`. Con `messages` (la sesión\n * está en la cola `S`), un `Paragraph` sin `Line` es un mensaje (CERT, 2026-11-06). Fuera de la\n * `S`, un `Line` sin localizador es una respuesta que el SDK no entiende: lanza\n * `SabreGatewayError`. En la `S`, un `Line` con localizador también lanza.\n */\nexport function parseQueueStep(response: SoapResponse, { messages = false }: { messages?: boolean } = {}): QueueStep {\n const { warnings } = response;\n const paragraph = paragraphLines(response.raw);\n const firstLine = paragraph.find((line) => line.trim() !== '');\n if (isEndOfDisplay(firstLine) || warnings.some(isEndOfDisplayResult)) return endStep(warnings, 'end-of-display', response.raw);\n\n if (messages && response.payload.Line === undefined && firstLine !== undefined) {\n return { done: false, kind: 'message', message: { text: paragraph }, warnings, ...respondedAtField(response.raw) };\n }\n const fields = messages ? undefined : lineFields(response.payload.Line);\n if (fields === undefined) {\n const expected = messages ? 'sin Paragraph de mensaje ni fin de cola en la cola S' : 'sin Line/UniqueID ni fin de cola';\n throw new SabreGatewayError(`${QUEUE_ACCESS_SERVICE}: respuesta no reconocida (${expected})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n const item: QueueItem = { ...fields, paragraph };\n return { done: false, kind: 'pnr', item, warnings, ...respondedAtField(response.raw) };\n}\n\n/** Los campos de un `Line`, o `undefined` si no trae `UniqueID`. */\nexport function lineFields(value: unknown): Omit<QueueItem, 'paragraph'> | undefined {\n const line = node(value);\n const locator = attribute(line?.UniqueID, 'ID');\n if (line === undefined || locator === undefined) return undefined;\n const source = node(node(line.POS)?.Source);\n const agentSine = attribute(source, 'AgentSine');\n const pseudoCityCode = attribute(source, 'PseudoCityCode');\n const placedAt = element(line.DateTime);\n const primaryPassenger = element(line.PassengerName);\n const group = element(line.Group);\n return {\n locator,\n ...(placedAt === undefined ? {} : { placedAt }),\n ...(agentSine === undefined && pseudoCityCode === undefined\n ? {}\n : {\n placedBy: {\n ...(agentSine === undefined ? {} : { agentSine }),\n ...(pseudoCityCode === undefined ? {} : { pseudoCityCode }),\n },\n }),\n ...(primaryPassenger === undefined ? {} : { primaryPassenger }),\n ...(group === undefined ? {} : { group }),\n };\n}\n","// Referencia a una cola de PNR, la misma en la entrada y en la salida. Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 2 y decisiones de la revisión) y\n// wiki/sources/ingresar-a-una-cola.md.\nimport { xmlEscape } from '../http/soap-transport.js';\n\n/**\n * Una cola (ADR-028). Hay tres clases, y viajan por dos atributos distintos de `QueueIdentifier`:\n * - **numérica**, de 0 a 511: `400` → `Number=\"400\"`;\n * - **alfabética**, una o dos letras mayúsculas: `'S'` → `Number=\"S\"`. La `S` es la cola de\n * **mensajes** del PCC (cuenta lo mismo que `Totals Type=\"MESSAGES\"`): no tiene PNR y no se puede\n * listar;\n * - **con nombre** (tablas QN y QNB): `{ name: 'HOTELS' }` → `Name=\"HOTELS\"`.\n *\n * Lo que devuelve `queue.count` se pasa tal cual a las demás operaciones. Las colas 0–49 son del\n * sistema: el SDK no las restringe.\n */\nexport type QueueRef = number | string | { name: string };\n\n/** Primera y última cola numérica de un PCC. */\nexport const MIN_QUEUE_NUMBER = 0;\nexport const MAX_QUEUE_NUMBER = 511;\n\n/** La cola de mensajes del PCC: no tiene PNR y Sabre no la lista (`INVALID ENTRY`). */\nexport const MESSAGE_QUEUE = 'S';\n\n/**\n * Una cola alfabética: una o dos letras mayúsculas. Es una regla laxa a propósito: la documentación\n * solo muestra `S` y `A`, y no se sabe si hay colas de dos letras (ADR-028).\n */\nconst ALPHA_QUEUE = /^[A-Z]{1,2}$/;\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/** Valida una `QueueRef` de la entrada, sin red. `label` es el nombre del campo en el mensaje. */\nexport function validateQueueRef(value: unknown, label: string): asserts value is QueueRef {\n if (typeof value === 'number') {\n if (Number.isInteger(value) && value >= MIN_QUEUE_NUMBER && value <= MAX_QUEUE_NUMBER) return;\n fail(`${label} debe ser un número de cola entero de ${MIN_QUEUE_NUMBER} a ${MAX_QUEUE_NUMBER}, una cola alfabética ('S') o { name }`);\n }\n if (typeof value === 'string') {\n if (ALPHA_QUEUE.test(value)) return;\n // Cada cola tiene una sola forma: '12' no se convierte en 12, ni 's' en 'S' (ADR-028).\n if (/^\\d+$/.test(value.trim())) fail(`${label}: una cola numérica va como número (${Number(value)}), no como string`);\n fail(`${label} debe ser una cola alfabética de una o dos letras mayúsculas (p. ej. 'S')`);\n }\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const { name } = value as { name?: unknown };\n if (typeof name !== 'string' || name.trim() === '') fail(`${label}.name debe ser un string no vacío`);\n // Un { name } de una o dos letras es casi seguro una cola alfabética mal armada, p. ej. el\n // { name: 'S' } que devolvía count en la 0.4.x: Sabre lo rechaza con INVALID QUEUE NAME FORMAT.\n // Ninguna fuente confirma que no existan colas con nombre tan cortas: si aparece una, se afloja\n // esta regla, y eso no rompe la compatibilidad (ADR-028, sub-decisión ii).\n if (ALPHA_QUEUE.test(name)) fail(`${label}: '${name}' es una cola alfabética: pasa '${name}', no { name: '${name}' }`);\n return;\n }\n fail(`${label} debe ser un número de cola (0–511), una cola alfabética ('S') o { name }`);\n}\n\n/** Atributo de `QueueIdentifier`: `Number=\"12\"`, `Number=\"S\"` o `Name=\"HOTELS\"`, ya escapado. */\nexport function queueRefAttribute(queue: QueueRef): string {\n if (typeof queue === 'number') return `Number=\"${queue}\"`;\n if (typeof queue === 'string') return `Number=\"${xmlEscape(queue)}\"`;\n return `Name=\"${xmlEscape(queue.name)}\"`;\n}\n\n/**\n * Un rango de colas numéricas, de `start` a `end`, las dos incluidas: `{ start: 1, end: 25 }` es el\n * `QC/<PCC>1-25` del host. Lo usan `count` y `activity`. A diferencia de pedir todo el PCC, Sabre\n * devuelve cada cola del rango, también las vacías, con cuenta `0` (CERT y producción, #213).\n *\n * El design también acepta rangos de colas con nombre (`TEST1-TEST2`), pero ninguna prueba los vio:\n * por ahora solo van números.\n */\nexport interface QueueRange {\n start: number;\n end: number;\n}\n\n/** Valida un `QueueRange` de la entrada, sin red. `label` es el nombre del campo en el mensaje. */\nexport function validateQueueRange(value: unknown, label: string): asserts value is QueueRange {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) fail(`${label} debe ser { start, end }`);\n const { start, end } = value as { start?: unknown; end?: unknown };\n for (const [name, bound] of [['start', start], ['end', end]] as const) {\n if (typeof bound !== 'number' || !Number.isInteger(bound) || bound < MIN_QUEUE_NUMBER || bound > MAX_QUEUE_NUMBER) {\n fail(`${label}.${name} debe ser un número de cola entero de ${MIN_QUEUE_NUMBER} a ${MAX_QUEUE_NUMBER}`);\n }\n }\n if ((start as number) >= (end as number)) fail(`${label}.start debe ser menor que ${label}.end (para una sola cola, usa queue)`);\n}\n\n/**\n * `QueueIdentifier` de `QueueCountRQ` y `QueueAnalysisRQ`: todo el PCC, una cola o un rango. `Range`\n * va como hijo y sin `Number` ni `Name`: con los dos, Sabre responde `Client.Validation` (#213).\n */\nexport function queueIdentifierXml(pcc: string, target: { queue?: QueueRef; range?: QueueRange } = {}): string {\n const pccAttribute = `PseudoCityCode=\"${xmlEscape(pcc)}\"`;\n if (target.range !== undefined) {\n return `<QueueIdentifier ${pccAttribute}><Range Start=\"${target.range.start}\" End=\"${target.range.end}\"/></QueueIdentifier>`;\n }\n if (target.queue !== undefined) return `<QueueIdentifier ${queueRefAttribute(target.queue)} ${pccAttribute}/>`;\n return `<QueueIdentifier ${pccAttribute}/>`;\n}\n\n/** Si la cola es la de mensajes (`'S'`). */\nexport function isMessageQueue(queue: QueueRef): boolean {\n return queue === MESSAGE_QUEUE;\n}\n\n/**\n * Lee el `Number` de una respuesta (`QueueCountRS`, `QueuePlaceRS`, `QueueAnalysisRS`): `\"12\"` da\n * `12`, y `\"S\"`, `'S'`. Devuelve `undefined` si viene vacío. Un `Number` que no es ni numérico ni\n * alfabético sale tal cual, como string: es lo que mandó Sabre.\n */\nexport function toQueueRef(value: string | undefined): QueueRef | undefined {\n const text = value?.trim();\n if (text === undefined || text === '') return undefined;\n return /^\\d+$/.test(text) ? Number(text) : text;\n}\n","// Get Queue Count (`QueueCountLLSRQ` 2.2.1). Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md\n// (punto 2) y wiki/entities/queue-management.md (Get Queue Count y respuestas reales).\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport { type QueueSelection, selectionXml } from './queue-access.js';\nimport { type QueueRange, type QueueRef, queueIdentifierXml, toQueueRef } from './queue-ref.js';\n\nexport const QUEUE_COUNT_SERVICE = 'queueCount';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\nexport interface QueueCountRequest {\n /** PCC cuyas colas se cuentan. Por defecto, el de la sesión. */\n pcc?: string;\n /** Contar solo esta cola (`QC/<PCC><cola>`). No se combina con `range`. */\n queue?: QueueRef;\n /**\n * Contar un rango de colas (`QC/<PCC>1-25`). No se combina con `queue`. La respuesta trae cada\n * cola del rango, también las vacías, con `count: 0`.\n */\n range?: QueueRange;\n /**\n * Hasta 8 filtros, como en `access`: la cola cuenta solo los PNR que cumplen (`QC/<PCC>20‡QD-08NOV`).\n * El host acepta cualquier función (`QD`, `AK`, `AL`, `PI`, `AC`… y combinaciones); un criterio\n * que no vale llega como `SabreBusinessError` (p. ej. `INVALID PLACING AGENT`). Necesita `queue`:\n * sin cola, Sabre responde `QUEUE SELECTED NOT VALID OR CLOSED`, y con `range`, `KEYS NOT ALLOWED`\n * (#213), así que el SDK lo rechaza antes con `TypeError`.\n */\n selection?: readonly QueueSelection[];\n}\n\nexport type QueueCountOptions = RequestOptions;\n\n/** Una cola con mensajes o PNR. */\nexport interface QueueCount {\n queue: QueueRef;\n count: number;\n}\n\n/**\n * `AdditionalQueueInfo` (desde la 2.2.0): información extra de una cola, como su transferencia a\n * otra cola o PCC (`FreeText=\"IS TRANSFERRED TO\"`). Se tipa desde el design: ninguna respuesta real\n * la trajo todavía (#213), así que los valores van tal cual llegan, sin interpretar.\n */\nexport interface QueueAdditionalInfo {\n /** La cola dentro de cuyo `QueueIdentifier` llegó, si llegó dentro de uno. */\n queue?: QueueRef;\n /** `@FreeText`, p. ej. `\"IS TRANSFERRED TO\"`. */\n freeText?: string;\n /** `@PseudoCityCode`. */\n pseudoCityCode?: string;\n /** `@QueueNumber`, tal cual llegó. */\n queueNumber?: string;\n}\n\nexport interface QueueCountResponse {\n /**\n * Las colas que trae la respuesta, en el orden de Sabre. Sin `range`, Sabre no lista las vacías;\n * con `range`, lista todas las del rango, las vacías con `count: 0`. Con `queue`, trae solo esa\n * (con `count: 0` si está vacía o si ningún PNR cumple `selection`).\n */\n queues: QueueCount[];\n /** Los `AdditionalQueueInfo` de la respuesta, si vino alguno. */\n additionalInfo?: QueueAdditionalInfo[];\n /**\n * Los `Totals` por `Type`: `MESSAGES`, `SPECIALS` y `PNRS`. Si Sabre no manda alguno, queda en\n * `undefined`. Sin filtros son los del PCC, y con `range`, los del rango. Con `queue` y sin\n * `selection`, Sabre no manda `Totals` (CERT y producción, #213).\n *\n * `unfiltered` sale de un `Totals` sin `Type`, que Sabre manda solo con `selection` y que el\n * design no menciona: cuántos PNR tiene la cola sin filtrar (el `1 MATCHING PNRS OUT OF 80` del\n * host, #213).\n */\n totals: { messages?: number; specials?: number; pnrs?: number; unfiltered?: number };\n /**\n * `QueueInfo@DateTime` tal cual llegó, sin año (`\"06-25T09:46\"`): la hora del host al contar.\n * Es un hecho pasado, así que el año se resuelve hacia atrás desde una fecha de referencia.\n */\n countedAt?: string;\n /** Los `stl:Warning` de la respuesta. No lanzan. */\n warnings: SabreWarning[];\n /**\n * `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC (`\"2026-11-06T17:34:16Z\"`). A\n * diferencia de las fechas del host, trae año y zona. Falta si Sabre no lo manda.\n */\n respondedAt?: string;\n}\n\nconst TOTAL_TYPES = { MESSAGES: 'messages', SPECIALS: 'specials', PNRS: 'pnrs' } as const;\n\n/** Lo que filtra un `count`, ya validado: la cola o el rango, y los `Selection`. */\nexport interface QueueCountTarget {\n queue?: QueueRef;\n range?: QueueRange;\n selection?: readonly QueueSelection[];\n}\n\n/**\n * Cuerpo de `QueueCountRQ`: todo el PCC, una cola o un rango, con los `Selection` como hermanos de\n * `QueueInfo` (design 2.2.1).\n */\nexport function queueCountPayload(pcc: string, target: QueueCountTarget = {}): string {\n return `<QueueCountRQ Version=\"2.2.1\" xmlns=\"${NAMESPACE}\"><QueueInfo>${queueIdentifierXml(pcc, target)}</QueueInfo>${selectionXml(target.selection ?? [])}</QueueCountRQ>`;\n}\n\n/** `QueueCountLLSRQ` es una lectura: se reintenta ante `USG_*_BUSY`, transitorios y red. */\nexport function queueCountRequest(pcc: string, options: QueueCountOptions, target: QueueCountTarget = {}): SessionRequest {\n return {\n service: QUEUE_COUNT_SERVICE,\n action: 'QueueCountLLSRQ',\n payload: queueCountPayload(pcc, target),\n idempotent: true,\n operation: 'queue.count',\n ...options,\n };\n}\n\n/**\n * Normaliza un `Count` de Sabre a número. Llega con relleno de puntos, como en la documentación\n * (`\"....261\"`), o sin él, como en las respuestas reales (`\"6\"`). Devuelve `undefined` si no es\n * un entero con ese formato.\n */\nexport function parseHostCount(value: string | undefined): number | undefined {\n const match = /^[.\\s]*(\\d+)\\s*$/.exec(value ?? '');\n return match === null ? undefined : Number(match[1]);\n}\n\ntype XmlNode = Record<string, unknown>;\n\nfunction attribute(node: unknown, name: string): string | undefined {\n const value = (node as XmlNode | undefined)?.[`@${name}`];\n return typeof value === 'string' ? value : undefined;\n}\n\n/**\n * Lee `QueueCountRS`. Si falta una sección, queda vacía o en `undefined`. Un `Number` o un `Count`\n * que no se puede leer es una respuesta que el SDK no entiende: lanza `SabreGatewayError` antes\n * que devolver una cuenta equivocada.\n */\nexport function parseQueueCountResponse(response: SoapResponse): QueueCountResponse {\n const queues: QueueCount[] = [];\n const additionalInfo: QueueAdditionalInfo[] = [];\n let countedAt: string | undefined;\n // El design no deja claro si `AdditionalQueueInfo` es hijo de `QueueIdentifier` o hermano: se lee\n // en los dos lugares, y también al nivel de `QueueInfo` por si acaso.\n additionalInfo.push(...readAdditionalInfo(response.payload.AdditionalQueueInfo));\n for (const info of asArray(response.payload.QueueInfo)) {\n countedAt ??= nonEmpty(attribute(info, 'DateTime'));\n additionalInfo.push(...readAdditionalInfo((info as XmlNode).AdditionalQueueInfo));\n for (const identifier of asArray((info as XmlNode).QueueIdentifier)) {\n // `Number` trae las numéricas y las alfabéticas (\"400\", \"S\"); `Name`, las colas con nombre\n // (ADR-028). Las respuestas reales solo traen `Number`, pero se lee igual que en place.\n const number = attribute(identifier, 'Number');\n const name = nonEmpty(attribute(identifier, 'Name'));\n const queue: QueueRef | undefined = number === undefined && name !== undefined ? { name } : toQueueRef(number);\n const count = parseHostCount(attribute(identifier, 'Count'));\n if (queue === undefined || count === undefined) {\n throw malformed(`QueueIdentifier con Number=\"${number ?? ''}\" y Count=\"${attribute(identifier, 'Count') ?? ''}\"`, response);\n }\n queues.push({ queue, count });\n additionalInfo.push(...readAdditionalInfo((identifier as XmlNode).AdditionalQueueInfo, queue));\n }\n }\n\n const totals: QueueCountResponse['totals'] = {};\n for (const total of asArray(response.payload.Totals)) {\n const type = attribute(total, 'Type');\n const key = type === undefined ? 'unfiltered' : TOTAL_TYPES[type.toUpperCase() as keyof typeof TOTAL_TYPES];\n if (key === undefined) continue;\n const count = parseHostCount(attribute(total, 'Count'));\n if (count === undefined) throw malformed(`Totals ${key} con Count=\"${attribute(total, 'Count') ?? ''}\"`, response);\n totals[key] = count;\n }\n\n return {\n queues,\n ...(additionalInfo.length === 0 ? {} : { additionalInfo }),\n totals,\n ...(countedAt === undefined ? {} : { countedAt }),\n warnings: response.warnings,\n ...respondedAtField(response.raw),\n };\n}\n\nfunction readAdditionalInfo(value: unknown, queue?: QueueRef): QueueAdditionalInfo[] {\n return asArray(value).map((element) => {\n const freeText = nonEmpty(attribute(element, 'FreeText'));\n const pseudoCityCode = nonEmpty(attribute(element, 'PseudoCityCode'));\n const queueNumber = nonEmpty(attribute(element, 'QueueNumber'));\n return {\n ...(queue === undefined ? {} : { queue }),\n ...(freeText === undefined ? {} : { freeText }),\n ...(pseudoCityCode === undefined ? {} : { pseudoCityCode }),\n ...(queueNumber === undefined ? {} : { queueNumber }),\n };\n });\n}\n\nfunction malformed(detail: string, response: SoapResponse): SabreGatewayError {\n return new SabreGatewayError(`${QUEUE_COUNT_SERVICE}: respuesta no reconocida (${detail})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n}\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n const text = value?.trim();\n return text === undefined || text === '' ? undefined : text;\n}\n","// Lista de una cola (`QueueAccessLLSRQ` 2.1.1 con `List@Ind`): sus localizadores, sin recorrerla.\n// Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 2) y\n// wiki/sources/access-queue-v2-1-1-design.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport {\n attribute,\n isEndOfDisplay,\n isEndOfDisplayResult,\n lineFields,\n paragraphLines,\n QUEUE_ACCESS_SERVICE,\n type QueueItem,\n type QueueSelection,\n selectionXml,\n} from './queue-access.js';\nimport { type QueueRef, queueRefAttribute } from './queue-ref.js';\n\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\nexport interface QueueListRequest {\n queue: QueueRef;\n /** PCC de la cola. Por defecto, el de la sesión. */\n pcc?: string;\n /** `true` para pedir también el pasajero principal de cada PNR (`Q/…/LN`). */\n primaryPassenger?: boolean;\n /**\n * Hasta 8 filtros, como en `access`, pero Sabre solo acepta `QD` (fecha de colocación en la cola,\n * p. ej. `{ function: 'QD', criteria: '05NOV' }`) o `AK` (el agente que lo colocó, PCC más firma,\n * p. ej. `{ function: 'AK', criteria: 'PCC1AAT' }`) en la lista: con otro código responde\n * `VALID SELECTION CODE FOR QUEUE LIST ARE QD OR AK` (producción, #155). El SDK lo rechaza sin red.\n */\n selection?: readonly QueueSelection[];\n}\n\n/**\n * Los únicos códigos de `Selection` que Sabre acepta en la lista (producción, #155): `QD`, la fecha\n * de colocación en la cola, y `AK`, el agente que colocó el PNR (`AK-<PCC><firma>`, según\n * wiki/sources/funciones-de-seleccion-de-colas.md). `QD` se probó en `list`; `AK` no.\n */\nexport const LIST_SELECTION_FUNCTIONS: readonly string[] = ['QD', 'AK'];\n\nexport type QueueListOptions = RequestOptions;\n\n/**\n * Un PNR de la lista: los campos de su `Line`. Su `placedAt` es la **colocación en la cola**, la\n * fecha por la que filtra `QD`. No es la misma fecha que el `placedAt` de `access`, que es la última\n * modificación del PNR (producción, #155).\n */\nexport interface QueueListEntry extends Omit<QueueItem, 'paragraph'> {\n /** `Line@Number`: la posición en la lista. */\n position?: number;\n}\n\nexport interface QueueListResponse {\n /** Los localizadores, en el orden de la cola. */\n locators: string[];\n /** Un elemento por PNR, en el mismo orden que `locators`. */\n entries: QueueListEntry[];\n /** `Paragraph/Text` tal cual: empieza con la cabecera `QUEUE LIST FOR <PCC> QUEUE <n>`. */\n paragraph: string[];\n warnings: SabreWarning[];\n /**\n * `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC (`\"2026-11-06T17:34:16Z\"`). A\n * diferencia de las fechas del host, trae año y zona. Falta si Sabre no lo manda.\n */\n respondedAt?: string;\n}\n\n/** `Q/<PCC><cola>/L`. Los `Selection` van después de `QueueIdentifier`, como en `access`. */\nexport function queueListPayload(\n queue: QueueRef,\n pcc: string,\n primaryPassenger: boolean,\n selection: readonly QueueSelection[] = [],\n): string {\n const list = primaryPassenger ? '<List Ind=\"true\" PrimaryPassenger=\"true\"/>' : '<List Ind=\"true\"/>';\n return `<QueueAccessRQ Version=\"2.1.1\" xmlns=\"${NAMESPACE}\"><QueueIdentifier ${queueRefAttribute(queue)} PseudoCityCode=\"${xmlEscape(pcc)}\">${list}</QueueIdentifier>${selectionXml(selection)}</QueueAccessRQ>`;\n}\n\n/** `list` es una lectura (decisión de la revisión): se reintenta como `count`. */\nexport function queueListRequest(payload: string, options: QueueListOptions): SessionRequest {\n return {\n service: QUEUE_ACCESS_SERVICE,\n action: 'QueueAccessLLSRQ',\n payload,\n idempotent: true,\n operation: 'queue.list',\n ...options,\n };\n}\n\nexport function emptyList(warnings: SabreWarning[], paragraph: string[] = [], raw?: unknown): QueueListResponse {\n return { locators: [], entries: [], paragraph, warnings, ...respondedAtField(raw) };\n}\n\n/**\n * Lee la lista. No pagina: Sabre devuelve la cola entera en una sola respuesta (1221 `Line` en\n * ~279 KB, producción, #155). Una cola vacía (fin de cola como primera línea o como `stl:Warning`) da una lista\n * vacía. Un `Line` sin `UniqueID` es una respuesta que el SDK no entiende: lanza\n * `SabreGatewayError`.\n */\nexport function parseQueueList(response: SoapResponse): QueueListResponse {\n const { warnings } = response;\n const paragraph = paragraphLines(response.raw);\n const firstLine = paragraph.find((line) => line.trim() !== '');\n if (isEndOfDisplay(firstLine) || warnings.some(isEndOfDisplayResult)) return emptyList(warnings, paragraph, response.raw);\n\n const entries = asArray(response.payload.Line).map((line): QueueListEntry => {\n const fields = lineFields(line);\n if (fields === undefined) {\n throw new SabreGatewayError(`${QUEUE_ACCESS_SERVICE}: respuesta no reconocida (Line sin UniqueID en la lista)`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n const number = attribute(line, 'Number');\n const position = number !== undefined && /^\\d+$/.test(number) ? Number(number) : undefined;\n return { ...(position === undefined ? {} : { position }), ...fields };\n });\n return { locators: entries.map((entry) => entry.locator), entries, paragraph, warnings, ...respondedAtField(response.raw) };\n}\n","// Get Queue Activity (`QueueAnalysisLLSRQ` 2.0.0). Ver\n// sabre-wiki/wiki/proyectos/sabre-client/decisiones/tier-4-colas-avanzadas.md (A1),\n// wiki/sources/get-queue-activity-v2-0-0-design.md y wiki/entities/queue-management.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport { parseHostCount } from './queue-count.js';\nimport { type QueueRange, type QueueRef, queueIdentifierXml, toQueueRef } from './queue-ref.js';\n\nexport const QUEUE_ACTIVITY_SERVICE = 'queueAnalysis';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\nexport interface QueueActivityRequest {\n /** PCC cuyas colas se analizan. Por defecto, el de la sesión. */\n pcc?: string;\n /** Analizar solo esta cola (`QA/<PCC><cola>`). No se combina con `range`. */\n queue?: QueueRef;\n /**\n * Analizar un rango de colas (`QA/<PCC>1-25`). No se combina con `queue`. La respuesta trae cada\n * cola del rango, también las que tienen todos los contadores en 0.\n */\n range?: QueueRange;\n}\n\nexport type QueueActivityOptions = RequestOptions;\n\n/**\n * Los ocho contadores de Get Queue Activity, con los nombres de Sabre. La pantalla `QA` del host los\n * muestra en columnas (`ON Q`, `REMOVD`, …). Ninguna fuente dice desde cuándo cuentan (Q-097): el\n * SDK los devuelve sin interpretar.\n */\nexport interface QueueActivityCounters {\n /** `NumMessages`: los mensajes o PNR que están hoy en la cola (`ON Q`). */\n numMessages: number;\n /** `Ended`: los terminados en la cola. */\n ended: number;\n /** `Ignored`: los ignorados (`I`). */\n ignored: number;\n /** `Moved`: los movidos a otra cola. */\n moved: number;\n /** `Removed`: los sacados de la cola (`QR`). */\n removed: number;\n /** `Transferred`: los transferidos. */\n transferred: number;\n /** `LeftMessageToContact`: con un mensaje dejado al contacto. */\n leftMessageToContact: number;\n /** `UnableToReach`: los que no se pudo contactar. */\n unableToReach: number;\n}\n\n/** Los contadores de una cola. Sabre lista también colas vacías con contadores. */\nexport interface QueueActivity extends QueueActivityCounters {\n /** La cola, como en `count`: `400`, `'S'` o `{ name }`. Se pasa tal cual a las demás operaciones. */\n queue: QueueRef;\n}\n\nexport interface QueueActivityResponse {\n /**\n * Las colas que trae la respuesta, en el orden de Sabre. Sin filtros, Sabre omite las que tienen\n * todos los contadores en 0; con `range`, trae todas las del rango, y con `queue`, solo esa\n * (CERT y producción, #213).\n */\n queues: QueueActivity[];\n /**\n * `Totals`: los ocho contadores sumados para el PCC, o para el rango con `range`. Con `queue`,\n * Sabre no manda `Totals` y queda en `undefined` (#213).\n */\n totals?: QueueActivityCounters;\n /**\n * `QueueInfo@DateTime` tal cual llegó, sin año (`\"11-06T11:33\"`): la hora del host al analizar.\n * Es un hecho pasado, así que el año se resuelve hacia atrás, como `countedAt`.\n */\n analyzedAt?: string;\n /** Los `stl:Warning` de la respuesta. No lanzan. */\n warnings: SabreWarning[];\n /** `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC. Falta si Sabre no lo manda. */\n respondedAt?: string;\n}\n\n/** Elemento de Sabre → contador. */\nconst COUNTERS: ReadonlyArray<[string, keyof QueueActivityCounters]> = [\n ['NumMessages', 'numMessages'],\n ['Ended', 'ended'],\n ['Ignored', 'ignored'],\n ['Moved', 'moved'],\n ['Removed', 'removed'],\n ['Transferred', 'transferred'],\n ['LeftMessageToContact', 'leftMessageToContact'],\n ['UnableToReach', 'unableToReach'],\n];\n\n/** Cuerpo de `QueueAnalysisRQ`: todo el PCC (`QA/<PCC>`), una cola o un rango. */\nexport function queueActivityPayload(pcc: string, target: { queue?: QueueRef; range?: QueueRange } = {}): string {\n return `<QueueAnalysisRQ Version=\"2.0.0\" xmlns=\"${NAMESPACE}\"><QueueInfo>${queueIdentifierXml(pcc, target)}</QueueInfo></QueueAnalysisRQ>`;\n}\n\n/**\n * `QueueAnalysisLLSRQ` es una lectura: se reintenta ante `USG_*_BUSY`, transitorios y red. No pide\n * duty code 9, aunque el sample lo diga (CERT y producción, Q-098).\n */\nexport function queueActivityRequest(pcc: string, options: QueueActivityOptions, target: { queue?: QueueRef; range?: QueueRange } = {}): SessionRequest {\n return {\n service: QUEUE_ACTIVITY_SERVICE,\n action: 'QueueAnalysisLLSRQ',\n payload: queueActivityPayload(pcc, target),\n idempotent: true,\n operation: 'queue.activity',\n ...options,\n };\n}\n\ntype XmlNode = Record<string, unknown>;\n\nfunction attribute(node: unknown, name: string): string | undefined {\n const value = (Array.isArray(node) ? node[0] : (node as XmlNode | undefined))?.[`@${name}`];\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n const text = value?.trim();\n return text === undefined || text === '' ? undefined : text;\n}\n\n/**\n * Lee `QueueAnalysisRS`. Un `Number` que no se puede leer, o un contador que falta o no es un\n * entero, es una respuesta que el SDK no entiende: lanza `SabreGatewayError` antes que devolver un\n * contador equivocado.\n */\nexport function parseQueueActivityResponse(response: SoapResponse): QueueActivityResponse {\n const queues: QueueActivity[] = [];\n let analyzedAt: string | undefined;\n for (const info of asArray(response.payload.QueueInfo)) {\n analyzedAt ??= nonEmpty(attribute(info, 'DateTime'));\n for (const identifier of asArray((info as XmlNode).QueueIdentifier)) {\n // `Number` trae las numéricas y las alfabéticas (\"400\", \"S\"); `Name`, las con nombre (ADR-028).\n const number = attribute(identifier, 'Number');\n const name = nonEmpty(attribute(identifier, 'Name'));\n const queue: QueueRef | undefined = number === undefined && name !== undefined ? { name } : toQueueRef(number);\n if (queue === undefined) throw malformed(`QueueIdentifier con Number=\"${number ?? ''}\"`, response);\n queues.push({ queue, ...counters(identifier, `la cola ${number ?? name}`, response) });\n }\n }\n const totalsNode = asArray(response.payload.Totals)[0];\n const totals = totalsNode === undefined ? undefined : counters(totalsNode, 'Totals', response);\n\n return {\n queues,\n ...(totals === undefined ? {} : { totals }),\n ...(analyzedAt === undefined ? {} : { analyzedAt }),\n warnings: response.warnings,\n ...respondedAtField(response.raw),\n };\n}\n\nfunction counters(node: unknown, label: string, response: SoapResponse): QueueActivityCounters {\n const result = {} as QueueActivityCounters;\n for (const [element, key] of COUNTERS) {\n const raw = attribute((node as XmlNode)[element], 'Count');\n const count = parseHostCount(raw);\n if (count === undefined) throw malformed(`${label} con ${element} Count=\"${raw ?? ''}\"`, response);\n result[key] = count;\n }\n return result;\n}\n\nfunction malformed(detail: string, response: SoapResponse): SabreGatewayError {\n return new SabreGatewayError(`${QUEUE_ACTIVITY_SERVICE}: respuesta no reconocida (${detail})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n}\n","// Place Queue Message (`QueuePlaceLLSRQ` 2.0.4): colocar PNR en colas. Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 2, \"place\"),\n// wiki/sources/place-queue-message-v2-0-4-design.md y wiki/sources/sabre-legacy-client-1-0-8.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport {\n attribute,\n endStep,\n isEndOfDisplay,\n isEndOfDisplayResult,\n node,\n type QueueStep,\n textLines,\n} from './queue-access.js';\nimport { type QueueRef, queueRefAttribute, toQueueRef } from './queue-ref.js';\n\nexport const QUEUE_PLACE_SERVICE = 'queuePlace';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\n/** Límites del design 2.0.4: hasta 10 colas y hasta 6 localizadores. */\nexport const MAX_PLACE_TO = 10;\nexport const MAX_PLACE_LOCATORS = 6;\n\n/** Rangos de PIC válidos (`PrefatoryInstructionCode`), según el artículo de selección de colas. */\nconst INSTRUCTION_CODE_RANGES: ReadonlyArray<readonly [number, number]> = [\n [0, 191],\n [200, 254],\n];\n\n/** Una cola de destino. */\nexport interface QueuePlaceTarget {\n queue: QueueRef;\n /** Por defecto, el PCC de la sesión. */\n pcc?: string;\n /**\n * Código PIC (`PrefatoryInstructionCode`): 0–191 o 200–254. **Obligatorio**, aunque el design\n * 2.0.4 lo da como opcional: sin PIC, producción rechaza el place con `INSTRUCTION NUMBER NOT IN\n * RANGE` fuera de una cola y con `NEED INSTRUCTION NUMBER` dentro (#97). Sin valor por defecto.\n */\n instructionCode: number;\n}\n\nexport interface QueuePlaceRequest {\n /** De 1 a 10 colas de destino. */\n to: readonly QueuePlaceTarget[];\n /**\n * Hasta 6 localizadores a colocar, sin tenerlos en el AAA. Solo fuera de una cola: dentro,\n * `place` coloca el PNR actual.\n */\n locators?: readonly string[];\n}\n\nexport type QueuePlaceOptions = RequestOptions;\n\n/** Una colocación que confirma Sabre (`QueueInfo`). */\nexport interface QueuePlacement {\n queue?: QueueRef;\n pcc?: string;\n locator?: string;\n /** `QueueInfo@DateTime` tal cual, sin año (`\"12-21T12:00\"`). */\n placedAt?: string;\n}\n\n/** Lo que devuelve `place` fuera de una cola: no avanza nada. */\nexport interface QueuePlaceResult {\n /** Las colocaciones de `QueueInfo`, si Sabre las manda. */\n placements: QueuePlacement[];\n /** Las líneas `Text`, tal cual (p. ej. `\"OK 1030 NMIUTF\"`). */\n text: string[];\n warnings: SabreWarning[];\n /**\n * `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC (`\"2026-11-06T17:34:16Z\"`). A\n * diferencia de las fechas del host, trae año y zona. Falta si Sabre no lo manda.\n */\n respondedAt?: string;\n}\n\n/**\n * Lo que devuelve `place`: un `QueueStep` dentro de una cola, y un `QueuePlaceResult` fuera. Se\n * distinguen con `'done' in result`. Con `locators`, el tipo ya es `QueuePlaceResult`.\n */\nexport type QueuePlaceResponse = QueueStep | QueuePlaceResult;\n\n/** Destino ya validado, con el PCC resuelto. */\nexport interface ResolvedPlaceTarget {\n queue: QueueRef;\n pcc: string;\n instructionCode?: number;\n}\n\n/** Si un PIC está en los rangos válidos. */\nexport function isInstructionCode(value: unknown): value is number {\n return (\n typeof value === 'number' &&\n Number.isInteger(value) &&\n INSTRUCTION_CODE_RANGES.some(([min, max]) => value >= min && value <= max)\n );\n}\n\nexport function queuePlacePayload(to: readonly ResolvedPlaceTarget[], locators: readonly string[] = []): string {\n const identifiers = to\n .map((target) => {\n const pic = target.instructionCode === undefined ? '' : ` PrefatoryInstructionCode=\"${target.instructionCode}\"`;\n return `<QueueIdentifier ${queueRefAttribute(target.queue)}${pic} PseudoCityCode=\"${xmlEscape(target.pcc)}\"/>`;\n })\n .join('');\n const ids = locators.map((locator) => `<UniqueID ID=\"${xmlEscape(locator)}\"/>`).join('');\n return `<QueuePlaceRQ Version=\"2.0.4\" xmlns=\"${NAMESPACE}\"><QueueInfo>${identifiers}${ids}</QueueInfo></QueuePlaceRQ>`;\n}\n\n/** Colocar no es idempotente: dentro de una cola mueve el cursor, y fuera repetiría la colocación. */\nexport function queuePlaceRequest(payload: string, options: QueuePlaceOptions): SessionRequest {\n return {\n service: QUEUE_PLACE_SERVICE,\n action: 'QueuePlaceLLSRQ',\n payload,\n idempotent: false,\n operation: 'queue.place',\n ...options,\n };\n}\n\n/**\n * Línea de firma del PNR, al final del texto: `<PCC>.<PCC>*<agente> HHMM/DDMMMYY <localizador> H`,\n * p. ej. `7TZA.7TZA*AW5 0319/06SEP24 NGDEZP H`.\n */\nconst SIGNATURE_LINE = /\\s\\d{4}\\/\\d{2}[A-Z]{3}\\d{2}\\s+([A-Z0-9]{6})\\s+H\\s*$/;\n\n/** El localizador de la última línea de firma del texto, si hay una. */\nexport function signatureLocator(lines: readonly string[]): string | undefined {\n for (let index = lines.length - 1; index >= 0; index--) {\n const match = SIGNATURE_LINE.exec(lines[index] ?? '');\n if (match !== null) return match[1];\n }\n return undefined;\n}\n\n/** El fin de cola de `place`: como `stl:Warning` (evidencia de `1.0.8`) o como primera línea. */\nfunction isEnd(response: SoapResponse, text: readonly string[]): boolean {\n return response.warnings.some(isEndOfDisplayResult) || isEndOfDisplay(text.find((line) => line.trim() !== ''));\n}\n\n/**\n * Dentro de una cola, `QueuePlaceRS` trae el PNR siguiente en `Text` y no trae `Line`: el\n * localizador sale de la línea de firma, y `placedAt` y `placedBy` quedan en `undefined`, porque\n * esa firma es la última modificación del PNR y no su colocación en la cola.\n */\nexport function parsePlaceStep(response: SoapResponse): QueueStep {\n const text = textLines(response.raw, 'QueuePlaceRS');\n if (isEnd(response, text)) return endStep(response.warnings, 'end-of-display', response.raw);\n const locator = signatureLocator(text);\n if (locator === undefined) {\n throw new SabreGatewayError(`${QUEUE_PLACE_SERVICE}: respuesta no reconocida (sin línea de firma del PNR ni fin de cola)`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n return { done: false, kind: 'pnr', item: { locator, paragraph: text }, warnings: response.warnings, ...respondedAtField(response.raw) };\n}\n\n/**\n * Lo que `place` puede leer con la sesión en `'unknown'`: un fin de cola, un PNR con línea de\n * firma (seguía en la cola) o, si no, un `QueuePlaceResult`.\n */\nexport function parsePlaceUnknown(response: SoapResponse): QueuePlaceResponse {\n const text = textLines(response.raw, 'QueuePlaceRS');\n if (isEnd(response, text) || signatureLocator(text) !== undefined) return parsePlaceStep(response);\n return parsePlaceResult(response);\n}\n\n/** Fuera de una cola: las colocaciones de `QueueInfo` y el texto. */\nexport function parsePlaceResult(response: SoapResponse): QueuePlaceResult {\n const placements = asArray(response.payload.QueueInfo).map((info): QueuePlacement => {\n const identifier = node(node(info)?.QueueIdentifier);\n // `Number` es alfanumérico (\"400\" o \"S\"); `Name` es siempre un nombre.\n const number = attribute(identifier, 'Number');\n const name = attribute(identifier, 'Name');\n const queue: QueueRef | undefined = number !== undefined ? toQueueRef(number) : name !== undefined ? { name } : undefined;\n const pcc = attribute(identifier, 'PseudoCityCode');\n const locator = attribute(node(info)?.UniqueID, 'ID');\n const placedAt = attribute(info, 'DateTime');\n return {\n ...(queue === undefined ? {} : { queue }),\n ...(pcc === undefined ? {} : { pcc }),\n ...(locator === undefined ? {} : { locator }),\n ...(placedAt === undefined ? {} : { placedAt }),\n };\n });\n return {\n placements,\n text: textLines(response.raw, 'QueuePlaceRS'),\n warnings: response.warnings,\n ...respondedAtField(response.raw),\n };\n}\n","// Módulo de dominio `session.queue` (Queue Management). Las operaciones viven en la sesión porque\n// necesitan su estado. Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 2 y\n// decisiones de la revisión).\nimport { SabreBusinessError, SabreGatewayError, SabreSessionError } from '../errors/index.js';\nimport type { EventLogger } from '../logging/logger.js';\nimport type { SoapResponse } from '../http/soap-transport.js';\nimport { isPseudoCityCode } from '../session/credentials.js';\nimport type { SessionRequest } from '../session/session.js';\nimport {\n isOffQueueError,\n queueEndError,\n endStep,\n MAX_REMOVE_FROM,\n MAX_SELECTIONS,\n navigationOperation,\n type QueueAccessOptions,\n type QueueAccessRequest,\n queueAccessPayload,\n queueAccessRequest,\n type QueueNavigationOptions,\n queueNavigationPayload,\n type QueueRemoveRequest,\n type QueueEndReason,\n type QueueItem,\n type QueueSelection,\n type QueueStep,\n parseQueueStep,\n} from './queue-access.js';\nimport {\n type QueueCountOptions,\n type QueueCountRequest,\n type QueueCountResponse,\n parseQueueCountResponse,\n queueCountRequest,\n} from './queue-count.js';\nimport {\n emptyList,\n LIST_SELECTION_FUNCTIONS,\n parseQueueList,\n type QueueListOptions,\n type QueueListRequest,\n type QueueListResponse,\n queueListPayload,\n queueListRequest,\n} from './queue-list.js';\nimport {\n parseQueueActivityResponse,\n type QueueActivityOptions,\n type QueueActivityRequest,\n type QueueActivityResponse,\n queueActivityRequest,\n} from './queue-activity.js';\nimport {\n isInstructionCode,\n type QueuePlaceTarget,\n MAX_PLACE_LOCATORS,\n MAX_PLACE_TO,\n parsePlaceResult,\n parsePlaceStep,\n parsePlaceUnknown,\n type QueuePlaceOptions,\n type QueuePlaceRequest,\n type QueuePlaceResponse,\n type QueuePlaceResult,\n queuePlacePayload,\n queuePlaceRequest,\n type ResolvedPlaceTarget,\n} from './queue-place.js';\nimport { isMessageQueue, type QueueRange, type QueueRef, validateQueueRange, validateQueueRef } from './queue-ref.js';\n\n/**\n * Dónde está la sesión respecto de las colas: `'outside'`, `'inside'` (hay un PNR de una cola en\n * el AAA) o `'unknown'` (una operación falló dentro de una cola, o un `access` falló sin respuesta\n * de Sabre, y no se sabe si Sabre dejó la sesión adentro). De `'unknown'` se sale con `exit()`.\n */\nexport type QueueState = 'outside' | 'inside' | 'unknown';\n\n/** Qué hacer con un PNR en `queue.process`. */\nexport type QueueProcessAction =\n | { action: 'remove' }\n | { action: 'ignore' }\n | { action: 'place'; to: readonly QueuePlaceTarget[] };\n\nexport interface QueueProcessRequest extends QueueAccessRequest {\n /** Cuántos PNR visitar como máximo. Al llegar, sale con `QXI`. Sin tope por defecto. */\n limit?: number;\n}\n\nexport interface QueueProcessResult {\n /** Cuántos PNR se pasaron al callback. */\n visited: number;\n /** Por qué terminó: el fin de cola, una cola vacía al entrar, o `limit`. */\n ended: QueueEndReason | 'limit';\n}\n\n/** @internal Lo que la sesión le presta al módulo de colas. */\nexport interface QueueContext {\n /** Una llamada a Sabre dentro de la sesión, con uso exclusivo. */\n send(request: SessionRequest): Promise<SoapResponse>;\n /** PCC de la sesión: el default de cada operación. */\n pcc: string;\n log: EventLogger;\n}\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/**\n * Si el error es una respuesta clara de Sabre que rechazó el request: un `stl:Error` o un SOAP\n * fault con código. Un fallo de red, una cancelación o una respuesta que el SDK no entiende no lo\n * son: el request pudo haberse procesado.\n */\nfunction rejectedBySabre(error: unknown): boolean {\n return error instanceof SabreBusinessError || (error instanceof SabreGatewayError && error.code !== undefined);\n}\n\nexport class QueueManagement {\n readonly #context: QueueContext;\n #state: QueueState = 'outside';\n /** Si la última cola a la que se entró es la `S`: ahí cada paso es un mensaje, no un PNR. */\n #messages = false;\n\n /** @internal Lo construye `SabreSession`. */\n constructor(context: QueueContext) {\n this.#context = context;\n }\n\n /**\n * Si la sesión está dentro de una cola. Lo lleva el SDK: `access` con un PNR la deja en\n * `'inside'`, y el fin de cola o `exit()`, en `'outside'`.\n */\n get state(): QueueState {\n return this.#state;\n }\n\n /**\n * Get Queue Count (`QueueCountLLSRQ` 2.2.1): cuántos mensajes o PNR hay en cada cola del PCC,\n * más los totales. Cada `queue` de la respuesta se puede pasar tal cual a las demás operaciones\n * de cola.\n *\n * Sin filtros cuenta todo el PCC. Con `queue`, solo esa cola; con `range`, cada cola del rango,\n * también las vacías. Con `selection` (que necesita `queue`), solo los PNR que cumplen: con el\n * mismo `QD`, da lo mismo que `list` (CERT y producción, #213).\n *\n * Se puede llamar dentro o fuera de una cola, y no cambia `state`. Es una lectura: se reintenta\n * ante fallos transitorios. Lanzan `TypeError` sin red: un PCC que no tiene 3 o 4 caracteres\n * alfanuméricos, una `queue` o un `range` inválidos, `queue` y `range` juntos, una `selection`\n * inválida (como en `access`) o una `selection` sin `queue`.\n */\n async count(request: QueueCountRequest = {}, options: QueueCountOptions = {}): Promise<QueueCountResponse> {\n if (typeof request !== 'object' || request === null) fail('queue.count recibe { pcc?, queue?, range?, selection? }');\n const pcc = this.#pcc(request.pcc, 'pcc');\n const { queue, range } = validateQueueTarget(request, 'queue.count');\n const selection = validateSelection(request.selection);\n if (selection.length > 0 && queue === undefined) {\n fail(\n range === undefined\n ? 'selection en count necesita queue: sin cola, Sabre responde QUEUE SELECTED NOT VALID OR CLOSED'\n : 'selection en count necesita queue, no range: con un rango, Sabre responde KEYS NOT ALLOWED',\n );\n }\n const target = { ...(queue === undefined ? {} : { queue }), ...(range === undefined ? {} : { range }), ...(selection.length === 0 ? {} : { selection }) };\n const response = await this.#context.send(queueCountRequest(pcc, options, target));\n return parseQueueCountResponse(response);\n }\n\n /**\n * Get Queue Activity (`QueueAnalysisLLSRQ` 2.0.0, el `QA` del host): por cada cola del PCC, los\n * ocho contadores de actividad (`numMessages`, `ended`, `ignored`, `moved`, `removed`,\n * `transferred`, `leftMessageToContact` y `unableToReach`), más los totales. Cada `queue` se puede\n * pasar tal cual a las demás operaciones de cola. Ninguna fuente dice desde cuándo cuentan\n * (Q-097): el SDK los devuelve sin interpretar.\n *\n * Se puede llamar dentro o fuera de una cola, y no cambia `state`. Es una lectura: se reintenta\n * ante fallos transitorios. No pide duty code 9 (CERT y producción, Q-098).\n *\n * Sin filtros analiza todo el PCC. Con `queue`, solo esa cola; con `range`, cada cola del rango,\n * también las que tienen todos los contadores en 0. Lanzan `TypeError` sin red: un PCC que no\n * tiene 3 o 4 caracteres alfanuméricos, una `queue` o un `range` inválidos, y `queue` y `range`\n * juntos.\n */\n async activity(request: QueueActivityRequest = {}, options: QueueActivityOptions = {}): Promise<QueueActivityResponse> {\n if (typeof request !== 'object' || request === null) fail('queue.activity recibe { pcc?, queue?, range? }');\n const pcc = this.#pcc(request.pcc, 'pcc');\n const target = validateQueueTarget(request, 'queue.activity');\n const response = await this.#context.send(queueActivityRequest(pcc, options, target));\n return parseQueueActivityResponse(response);\n }\n\n /**\n * La lista de localizadores de una cola (`QueueAccessLLSRQ` con `List`), sin recorrerla. Con\n * `primaryPassenger: true`, cada entrada trae también el pasajero principal. Una cola vacía da\n * una lista vacía.\n *\n * No pagina: Sabre devuelve la cola entera en una respuesta, también con más de 1000 PNR. Con\n * `selection`, solo los PNR que cumplen el filtro; Sabre acepta solo `QD` o `AK` en la lista.\n *\n * No cambia `state`. Es una lectura: se reintenta ante fallos transitorios. Lanza `TypeError`\n * sin red si `queue` o `pcc` no son válidos, si `primaryPassenger` no es un boolean, o si\n * `selection` no es válida o trae un código que no es `QD` ni `AK`.\n */\n async list(request: QueueListRequest, options: QueueListOptions = {}): Promise<QueueListResponse> {\n if (typeof request !== 'object' || request === null) fail('queue.list recibe { queue, pcc?, primaryPassenger?, selection? }');\n validateQueueRef(request.queue, 'queue');\n // Sabre no lista la cola de mensajes de ninguna forma: INVALID ENTRY con Number=\"S\" (ADR-028).\n if (isMessageQueue(request.queue)) fail(\"la cola 'S' es la de mensajes del PCC: no tiene PNR y Sabre no la lista\");\n const pcc = this.#pcc(request.pcc, 'pcc');\n const { primaryPassenger = false } = request;\n if (typeof primaryPassenger !== 'boolean') fail('primaryPassenger debe ser un boolean');\n const selection = validateSelection(request.selection);\n selection.forEach((filter, index) => {\n // Sabre: VALID SELECTION CODE FOR QUEUE LIST ARE QD OR AK (producción, #155).\n if (!LIST_SELECTION_FUNCTIONS.includes(filter.function)) {\n fail(`selection[${index}].function en list solo puede ser ${LIST_SELECTION_FUNCTIONS.join(' o ')}: Sabre no acepta otro código en la lista`);\n }\n });\n const send = queueListRequest(queueListPayload(request.queue, pcc, primaryPassenger, selection), options);\n try {\n return parseQueueList(await this.#context.send(send));\n } catch (error) {\n const end = queueEndError(error, send.service);\n if (end !== undefined) return emptyList([...end.error.warnings], [], end.error.raw);\n throw error;\n }\n }\n\n /**\n * Access Queue (`QueueAccessLLSRQ` 2.1.1): entra a una cola y devuelve su primer PNR\n * (`kind: 'pnr'`). En la cola `S`, la de mensajes, devuelve el primer mensaje\n * (`kind: 'message'`), y `ignore` pasa al siguiente sin borrarlo (CERT, 2026-11-06). Una cola\n * vacía, o sin PNR que cumplan `selection`, devuelve `{ done: true }` y la sesión sigue afuera.\n *\n * Lanza `TypeError` sin red si la sesión ya está dentro de una cola (o en `'unknown'`: hay que\n * llamar a `exit()` primero), si `queue` no es de 0 a 511 o `{ name }`, o con más de 8 filtros.\n * Mueve el cursor: nunca se reintenta ante un fallo de red, y ese fallo deja `state` en\n * `'unknown'`.\n */\n async access(request: QueueAccessRequest, options: QueueAccessOptions = {}): Promise<QueueStep> {\n if (this.#state === 'inside') fail('la sesión ya está dentro de una cola: sal con queue.exit() antes de entrar a otra');\n if (this.#state === 'unknown') fail('no se sabe si la sesión sigue dentro de una cola: llama a queue.exit() antes de entrar');\n if (typeof request !== 'object' || request === null) fail('queue.access recibe { queue, pcc?, selection? }');\n validateQueueRef(request.queue, 'queue');\n const pcc = this.#pcc(request.pcc, 'pcc');\n const selection = validateSelection(request.selection);\n this.#messages = isMessageQueue(request.queue);\n return this.#step(queueAccessRequest(queueAccessPayload(request.queue, pcc, selection), 'queue.access', options));\n }\n\n /**\n * Deja el PNR actual en la cola y pasa al siguiente (`I`). Fuera de una cola lanza `TypeError`\n * sin red.\n */\n async ignore(options: QueueNavigationOptions = {}): Promise<QueueStep> {\n this.#requireQueue('ignore');\n return this.#step(queueAccessRequest(queueNavigationPayload('I'), navigationOperation('I'), options));\n }\n\n /**\n * Saca el PNR actual de la cola y pasa al siguiente (`QR`). Con `from` (de 1 a 3 colas), lo saca\n * de esas colas a la vez. Fuera de una cola lanza `TypeError` sin red. En la cola `S` manda `QR`\n * igual, pero no hay evidencia de qué hace Sabre con el mensaje.\n */\n async remove(request: QueueRemoveRequest = {}, options: QueueNavigationOptions = {}): Promise<QueueStep> {\n this.#requireQueue('remove');\n const from = this.#removeFrom(request.from);\n return this.#step(queueAccessRequest(queueNavigationPayload('QR', from), navigationOperation('QR'), options));\n }\n\n /**\n * Sale de la cola sin cerrar la transacción (`QXI`) y deja `state` en `'outside'`. Fuera de una\n * cola lanza `TypeError` sin red. En `'unknown'` manda `QXI` igual y, si Sabre lo rechaza con\n * `CANNOT DO THIS IF OFF QUEUE` (la sesión ya no estaba en una cola), lo da por bueno. Cualquier\n * otro error lanza y deja `'unknown'`.\n */\n async exit(options: QueueNavigationOptions = {}): Promise<void> {\n this.#requireQueue('exit');\n const before = this.#state;\n const request = queueAccessRequest(queueNavigationPayload('QXI'), navigationOperation('QXI'), options);\n try {\n await this.#context.send(request);\n } catch (error) {\n if (before === 'unknown' && isOffQueueError(error)) {\n // Sabre dice que la sesión ya no estaba en una cola (`CANNOT DO THIS IF OFF QUEUE`,\n // producción, #96): la salida se da por buena. Cualquier otro error lanza.\n this.#context.log.emit('info', 'sabre.queue.exitTolerated', { code: error.code, error });\n this.#state = 'outside';\n return;\n }\n this.#onError(error);\n throw error;\n }\n this.#state = 'outside';\n }\n\n /**\n * Recorre una cola: entra con `access`, llama a `callback` con cada PNR, ejecuta la acción que\n * devuelve (`remove`, `ignore` o `place`) y termina en el fin de cola. No hace nada que no se\n * pueda hacer con las primitivas.\n *\n * - Con `limit`, después de visitar esa cantidad de PNR sale con `QXI`. No tiene tope por\n * defecto: con una cola anómala que nunca llega al fin, el recorrido no termina. Conviene\n * pasarlo.\n * - Si el callback lanza, o devuelve una acción inválida, sale con `QXI` y propaga el error. No\n * lo convierte en `ignore`: para seguir de largo, el callback atrapa su error y devuelve\n * `{ action: 'ignore' }`.\n * - Si una operación falla, sale con `QXI` (tolerando que la sesión ya no esté en la cola) y\n * propaga el error. Con un `SabreSessionError` no intenta salir: la sesión ya no sirve.\n *\n * `options` se aplica a cada llamada a Sabre del recorrido.\n */\n async process(\n request: QueueProcessRequest,\n callback: (item: QueueItem) => QueueProcessAction | Promise<QueueProcessAction>,\n options: QueueNavigationOptions = {},\n ): Promise<QueueProcessResult> {\n if (typeof request !== 'object' || request === null) fail('queue.process recibe { queue, pcc?, selection?, limit? }');\n if (typeof callback !== 'function') fail('queue.process necesita un callback');\n const { limit, ...access } = request;\n // El callback recibe PNR, y sobre un mensaje no hay `place`: la S se recorre a mano (ADR-028).\n if (isMessageQueue(access.queue)) fail(\"queue.process no recorre la cola 'S', la de mensajes: usa queue.access() e queue.ignore()\");\n if (limit !== undefined && !(Number.isInteger(limit) && limit >= 1)) fail('limit debe ser un entero mayor o igual a 1');\n\n // Si la sesión ya estaba en una cola, `access` lanza sin red: esa cola es del consumidor.\n const startedOutside = this.#state === 'outside';\n let visited = 0;\n try {\n let step = await this.access(access, options);\n while (!step.done) {\n if (limit !== undefined && visited >= limit) {\n await this.exit(options);\n return { visited, ended: 'limit' };\n }\n // Fuera de la S no hay mensajes: parseQueueStep solo los lee dentro de ella.\n if (step.kind !== 'pnr') throw new TypeError('sabre-client: queue.process recibió un mensaje en vez de un PNR');\n const action = await callback(step.item);\n visited++;\n step = await this.#processAction(action, options);\n }\n return { visited, ended: step.reason };\n } catch (error) {\n if (startedOutside) await this.#exitQuietly(error, options);\n throw error;\n }\n }\n\n async #processAction(action: unknown, options: QueueNavigationOptions): Promise<QueueStep> {\n const kind = typeof action === 'object' && action !== null ? (action as { action?: unknown }).action : undefined;\n if (kind === 'ignore') return this.ignore(options);\n if (kind === 'remove') return this.remove({}, options);\n if (kind === 'place') {\n const step = await this.place({ to: (action as { to?: QueuePlaceTarget[] }).to as QueuePlaceTarget[] }, options);\n // Dentro de una cola, `place` siempre devuelve un `QueueStep`.\n if (!('done' in step)) throw new TypeError('sabre-client: queue.place no devolvió un paso de la cola');\n return step;\n }\n throw new TypeError(\"sabre-client: el callback de queue.process debe devolver { action: 'remove' }, { action: 'ignore' } o { action: 'place', to }\");\n }\n\n /** Sale de la cola después de un error del recorrido, sin pisar ese error. */\n async #exitQuietly(cause: unknown, options: QueueNavigationOptions): Promise<void> {\n if (this.#state === 'outside' || cause instanceof SabreSessionError) return;\n try {\n await this.exit(options);\n } catch (error) {\n this.#context.log.emit('warn', 'sabre.queue.exitFailed', { error });\n }\n }\n\n /**\n * Place Queue Message (`QueuePlaceLLSRQ` 2.0.4): coloca un PNR en 1 a 10 colas.\n *\n * - **Dentro de una cola**, coloca el PNR actual y devuelve un `QueueStep` con el siguiente,\n * como `ignore` y `remove`. El PNR se mueve: sale de la cola en curso (producción, #97). El localizador sale de la línea de firma del PNR; `placedAt` y\n * `placedBy` quedan en `undefined`. Con `locators` lanza `TypeError` sin red: para colocar\n * otros PNR, primero `exit()`.\n * - **Fuera de una cola**, coloca los `locators` (hasta 6) o el PNR del AAA, no avanza nada y\n * devuelve `{ placements, text, warnings }`.\n *\n * Cada destino necesita `instructionCode` (0–191 o 200–254), sin valor por defecto: sin él\n * lanza `TypeError` sin red, porque Sabre lo exige dentro y fuera de una cola. Nunca se\n * reintenta ante un fallo de red. Errores como `BAD PNR LOCATOR` o `NEED RECEIVED FROM FIELD`\n * salen como `SabreBusinessError` (`service: 'queuePlace'`).\n */\n place(request: QueuePlaceRequest & { locators: readonly string[] }, options?: QueuePlaceOptions): Promise<QueuePlaceResult>;\n place(request: QueuePlaceRequest, options?: QueuePlaceOptions): Promise<QueuePlaceResponse>;\n async place(request: QueuePlaceRequest, options: QueuePlaceOptions = {}): Promise<QueuePlaceResponse> {\n if (typeof request !== 'object' || request === null) fail('queue.place recibe { to, locators? }');\n const to = this.#placeTo(request.to);\n const locators = validateLocators(request.locators);\n if (this.#messages && this.#state !== 'outside') {\n fail(\"queue.place no se puede dentro de la cola 'S': lo que hay en pantalla es un mensaje, no un PNR\");\n }\n if (locators.length > 0 && this.#state === 'inside') {\n fail('queue.place con locators no se puede dentro de una cola, donde coloca el PNR actual: sal con queue.exit() antes');\n }\n if (locators.length > 0 && this.#state === 'unknown') {\n fail('no se sabe si la sesión sigue dentro de una cola: llama a queue.exit() antes de colocar por localizador');\n }\n if (to.some((target) => target.instructionCode === undefined)) {\n fail('queue.place necesita instructionCode en cada destino: Sabre lo exige, dentro y fuera de una cola');\n }\n const send = queuePlaceRequest(queuePlacePayload(to, locators), options);\n // Fuera de una cola, colocar no toca el cursor: el estado no cambia, ni con un error.\n if (this.#state === 'outside') return parsePlaceResult(await this.#context.send(send));\n return this.#advance(send, this.#state === 'inside' ? parsePlaceStep : parsePlaceUnknown);\n }\n\n /** Manda una operación que avanza y actualiza `state` con el resultado. */\n #step(request: SessionRequest): Promise<QueueStep> {\n const messages = this.#messages;\n return this.#advance(request, (response) => parseQueueStep(response, { messages }));\n }\n\n /**\n * Manda una operación que puede mover el cursor. Un `QueueStep` fija el estado: `'outside'` con\n * el fin de cola e `'inside'` con un PNR. Cualquier otro resultado lo deja como estaba.\n */\n async #advance<T extends QueuePlaceResponse>(request: SessionRequest, parse: (response: SoapResponse) => T): Promise<T> {\n let result: T;\n try {\n result = parse(await this.#context.send(request));\n } catch (error) {\n const end = queueEndError(error, request.service);\n if (end !== undefined) {\n this.#state = 'outside';\n return endStep([...end.error.warnings], end.reason, end.error.raw) as T;\n }\n this.#onError(error);\n throw error;\n }\n if ('done' in result) this.#state = result.done ? 'outside' : 'inside';\n return result;\n }\n\n /**\n * Qué pasa con `state` cuando una operación de cola falla. Los `TypeError` del uso exclusivo y\n * los errores de sesión no lo tocan: no llegaron a Sabre, o la sesión ya no sirve. Dentro de una\n * cola, cualquier otro error deja `'unknown'`. Fuera, solo lo que no es un rechazo claro de\n * Sabre (fallo de red, cancelación, respuesta ilegible).\n */\n #onError(error: unknown): void {\n if (error instanceof TypeError || error instanceof SabreSessionError) return;\n if (this.#state === 'outside' && rejectedBySabre(error)) return;\n this.#state = 'unknown';\n }\n\n #placeTo(to: unknown): ResolvedPlaceTarget[] {\n if (!Array.isArray(to) || to.length === 0 || to.length > MAX_PLACE_TO) {\n fail(`to debe ser una lista de 1 a ${MAX_PLACE_TO} colas`);\n }\n return to.map((target: unknown, index) => {\n if (typeof target !== 'object' || target === null) fail(`to[${index}] debe ser { queue, pcc?, instructionCode }`);\n const { queue, pcc, instructionCode } = target as { queue?: unknown; pcc?: unknown; instructionCode?: unknown };\n validateQueueRef(queue, `to[${index}].queue`);\n if (instructionCode !== undefined && !isInstructionCode(instructionCode)) {\n fail(`to[${index}].instructionCode debe ser un entero de 0 a 191 o de 200 a 254`);\n }\n return {\n queue,\n pcc: this.#pcc(pcc, `to[${index}].pcc`),\n ...(instructionCode === undefined ? {} : { instructionCode }),\n };\n });\n }\n\n #requireQueue(operation: string): void {\n if (this.#state === 'outside') fail(`queue.${operation} necesita estar dentro de una cola: entra con queue.access()`);\n }\n\n #pcc(value: unknown, label: string): string {\n if (value === undefined) return this.#context.pcc;\n if (!isPseudoCityCode(value)) fail(`${label} debe tener 3 o 4 caracteres alfanuméricos`);\n return value;\n }\n\n #removeFrom(from: unknown): Array<{ queue: QueueRef; pcc: string }> {\n if (from === undefined) return [];\n if (!Array.isArray(from) || from.length === 0 || from.length > MAX_REMOVE_FROM) {\n fail(`from debe ser una lista de 1 a ${MAX_REMOVE_FROM} colas`);\n }\n return from.map((target: unknown, index) => {\n if (typeof target !== 'object' || target === null) fail(`from[${index}] debe ser { queue, pcc? }`);\n const { queue, pcc } = target as { queue?: unknown; pcc?: unknown };\n validateQueueRef(queue, `from[${index}].queue`);\n return { queue, pcc: this.#pcc(pcc, `from[${index}].pcc`) };\n });\n }\n}\n\nfunction validateLocators(locators: unknown): string[] {\n if (locators === undefined) return [];\n if (!Array.isArray(locators) || locators.length === 0 || locators.length > MAX_PLACE_LOCATORS) {\n fail(`locators debe ser una lista de 1 a ${MAX_PLACE_LOCATORS} localizadores`);\n }\n return locators.map((locator: unknown, index) => {\n if (typeof locator !== 'string' || locator.trim() === '') fail(`locators[${index}] debe ser un string no vacío`);\n return locator;\n });\n}\n\n/**\n * La cola o el rango de `count` y `activity`, validados. Son excluyentes: con los dos, Sabre\n * responde `Client.Validation` (#213). Devuelve solo los que vinieron.\n */\nfunction validateQueueTarget(request: { queue?: unknown; range?: unknown }, operation: string): { queue?: QueueRef; range?: QueueRange } {\n const { queue, range } = request;\n if (queue !== undefined) validateQueueRef(queue, 'queue');\n if (range !== undefined) validateQueueRange(range, 'range');\n if (queue !== undefined && range !== undefined) fail(`${operation} recibe queue o range, no los dos: Sabre no los combina`);\n return { ...(queue === undefined ? {} : { queue }), ...(range === undefined ? {} : { range }) };\n}\n\nfunction validateSelection(selection: unknown): QueueSelection[] {\n if (selection === undefined) return [];\n if (!Array.isArray(selection)) fail('selection debe ser una lista de { function, criteria }');\n if (selection.length > MAX_SELECTIONS) fail(`selection admite hasta ${MAX_SELECTIONS} filtros`);\n return selection.map((filter: unknown, index) => {\n const { function: fn, criteria } = (typeof filter === 'object' && filter !== null ? filter : {}) as {\n function?: unknown;\n criteria?: unknown;\n };\n if (typeof fn !== 'string' || fn.trim() === '') fail(`selection[${index}].function debe ser un string no vacío`);\n if (typeof criteria !== 'string' || criteria.trim() === '') {\n fail(`selection[${index}].criteria debe ser un string no vacío`);\n }\n return { function: fn, criteria };\n });\n}\n","// Get Itinerary History (`TravelItineraryHistoryLLSRQ` 2.4.0): el historial de un PNR, el `*H` del\n// host. Ver sabre-wiki/wiki/proyectos/sabre-client/decisiones/tier-4-colas-avanzadas.md (B1),\n// wiki/sources/get-itinerary-history-v2-4-0-design.md y wiki/entities/get-itinerary-history.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { asArray, respondedAtField, type SoapResponse, textOf, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\n\nexport const RESERVATION_HISTORY_SERVICE = 'itineraryHistory';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\nexport type ReservationHistoryOptions = RequestOptions;\n\n/**\n * Un elemento con su acción y su texto: `GeneralInfo` o `RemarkInfo/Remark`. Sabre no publica el\n * catálogo de `action`. En CERT llegaron `A4S` (SSR), `A7` (ticketing), `A9` (teléfono), `AN`\n * (nombre), `APE` (email) y `ADT`. La `A` inicial es un alta y la `X`, una baja.\n */\nexport interface ReservationHistoryText {\n action: string;\n /** `Text`, tal cual. Puede traer datos del pasajero. */\n text: string;\n}\n\n/** Un `FlightSegment` del historial, tal como estaba en esa transacción. */\nexport interface ReservationHistoryFlightSegment {\n /** `@Action`: `AS` (alta) o `XS` (baja), según las respuestas y el design. */\n action: string;\n /** `@Status` en ese momento (`HK`, `HKNN`, `UN`…). */\n status?: string;\n /** `MarketingAirline@Code`. */\n marketingAirline?: string;\n /** `@FlightNumber`. */\n flightNumber?: string;\n /** `@ResBookDesigCode`: la clase. */\n bookingClass?: string;\n /** `OriginLocation@LocationCode`. */\n origin?: string;\n /** `DestinationLocation@LocationCode`. */\n destination?: string;\n /** `@DepartureDateTime` tal cual, sin año (`\"12-19T13:10\"`). Se resuelve con `resolveHostDate`. */\n departureDateTime?: string;\n /** `@ArrivalDateTime` tal cual, sin año. */\n arrivalDateTime?: string;\n /** `@NumberInParty`. */\n numberInParty?: number;\n /** `SupplierRef@ID`: el localizador de la aerolínea (`DCAA*DVDMYA`). */\n supplierRef?: string;\n}\n\n/** Una `AccountingInfo` del historial: la línea de contabilidad, sin sus importes. */\nexport interface ReservationHistoryAccounting {\n /** `@Action` (`HK` en el design). */\n action?: string;\n /** `@Type`: `R` reembolso, `G` cambio con reembolso, `E` cambio par, `A` cobro adicional, `L` descuento, `B` bulk. */\n type?: string;\n /** `@LinkCode`. */\n linkCode?: string;\n}\n\n/**\n * Una transacción del historial (`HistoricalInfo`): quién la firmó, cuándo y desde qué PCC\n * (`ItineraryRef/Source`), y los elementos que cambió. Lo que el SDK no tipa (asientos, autos,\n * hoteles, tren, seguros, facturas, importes) queda en la respuesta cruda (`onRawResponse`).\n */\nexport interface ReservationHistoryTransaction {\n /** `@RPH`: el número de la firma de la transacción (`HSTSIG`). */\n rph?: number;\n /** `Source@CreateDateTime`, tal cual: con año y sin zona (`\"2026-11-04T17:15\"`). */\n createdAt?: string;\n /** `Source@CreationAgent`: el sine del agente que firmó. */\n agent?: string;\n /** `Source@CreationAgentDutyCode`. */\n agentDutyCode?: string;\n /** `Source@CreationAgentFunctionCode`. */\n agentFunctionCode?: string;\n /** `Source@PseudoCityCode`: el PCC de la firma del agente. */\n pcc?: string;\n /**\n * `Source@AAA_PseudoCityCode`: el PCC del AAA del agente. El sample lo escribe\n * `AAAPseudoCityCode`, sin guion bajo; el SDK lee los dos.\n */\n aaaPcc?: string;\n /** `Source@ReceivedFrom`: el campo de recibido de la transacción. */\n receivedFrom?: string;\n /** `ItineraryInfo/ReservationItems/Item/FlightSegment`, en orden. */\n flightSegments: ReservationHistoryFlightSegment[];\n /** `GeneralInfo`, en orden: SSR, ticketing, teléfonos, nombres, emails… como texto. */\n generalInfo: ReservationHistoryText[];\n /** `RemarkInfo/Remark`, en orden. */\n remarks: ReservationHistoryText[];\n /** `AccountingInfo`, en orden. */\n accounting: ReservationHistoryAccounting[];\n}\n\nexport interface ReservationHistoryResponse {\n /** Las transacciones (`HistoricalInfo`), en el orden de Sabre. */\n transactions: ReservationHistoryTransaction[];\n /** Los `stl:Warning` de la respuesta. No lanzan. */\n warnings: SabreWarning[];\n /** `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC. Falta si Sabre no lo manda. */\n respondedAt?: string;\n}\n\nconst LOCATOR = /^[A-Z0-9]{6}$/;\n\n/** Si un texto es un localizador de Sabre: 6 caracteres alfanuméricos en mayúscula. */\nexport function isRecordLocator(value: unknown): value is string {\n return typeof value === 'string' && LOCATOR.test(value);\n}\n\n/** Cuerpo de `TravelItineraryHistoryRQ` con el localizador (`JX HST*<localizador>`). */\nexport function reservationHistoryPayload(locator: string): string {\n return `<TravelItineraryHistoryRQ Version=\"2.4.0\" xmlns=\"${NAMESPACE}\"><UniqueID ID=\"${xmlEscape(locator)}\"/></TravelItineraryHistoryRQ>`;\n}\n\n/** Es una lectura: se reintenta ante `USG_*_BUSY`, transitorios y red. */\nexport function reservationHistoryRequest(locator: string, options: ReservationHistoryOptions): SessionRequest {\n return {\n service: RESERVATION_HISTORY_SERVICE,\n action: 'TravelItineraryHistoryLLSRQ',\n payload: reservationHistoryPayload(locator),\n idempotent: true,\n operation: 'reservation.history',\n ...options,\n };\n}\n\ntype XmlNode = Record<string, unknown>;\n\nfunction node(value: unknown): XmlNode | undefined {\n const first = Array.isArray(value) ? value[0] : value;\n return typeof first === 'object' && first !== null ? (first as XmlNode) : undefined;\n}\n\nfunction attribute(value: unknown, name: string): string | undefined {\n const text = node(value)?.[`@${name}`];\n if (typeof text !== 'string') return undefined;\n const trimmed = text.trim();\n return trimmed === '' ? undefined : trimmed;\n}\n\n/** Los campos opcionales que llegaron, sin claves en `undefined`. */\nfunction defined<T extends Record<string, unknown>>(fields: T): { [K in keyof T]?: Exclude<T[K], undefined> } {\n return Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined)) as {\n [K in keyof T]?: Exclude<T[K], undefined>;\n };\n}\n\nfunction integer(value: string | undefined): number | undefined {\n return value !== undefined && /^\\d+$/.test(value) ? Number(value) : undefined;\n}\n\n/**\n * Lee `TravelItineraryHistoryRS`. Un `GeneralInfo`, `Remark` o `FlightSegment` sin `@Action` es una\n * respuesta que el SDK no entiende: lanza `SabreGatewayError`.\n */\nexport function parseReservationHistoryResponse(response: SoapResponse): ReservationHistoryResponse {\n const transactions = asArray(response.payload.HistoricalInfo).map((info) => transaction(node(info) ?? {}, response));\n return { transactions, warnings: response.warnings, ...respondedAtField(response.raw) };\n}\n\nfunction transaction(info: XmlNode, response: SoapResponse): ReservationHistoryTransaction {\n const source = node(node(info.ItineraryRef)?.Source);\n const flightSegments = asArray(node(node(info.ItineraryInfo)?.ReservationItems)?.Item).flatMap((item) =>\n asArray(node(item)?.FlightSegment).map((segment) => flightSegment(node(segment) ?? {}, response)),\n );\n return {\n ...defined({\n rph: integer(attribute(info, 'RPH')),\n createdAt: attribute(source, 'CreateDateTime'),\n agent: attribute(source, 'CreationAgent'),\n agentDutyCode: attribute(source, 'CreationAgentDutyCode'),\n agentFunctionCode: attribute(source, 'CreationAgentFunctionCode'),\n pcc: attribute(source, 'PseudoCityCode'),\n aaaPcc: attribute(source, 'AAA_PseudoCityCode') ?? attribute(source, 'AAAPseudoCityCode'),\n receivedFrom: attribute(source, 'ReceivedFrom'),\n }),\n flightSegments,\n generalInfo: asArray(info.GeneralInfo).map((entry) => textEntry(entry, 'GeneralInfo', response)),\n remarks: asArray(node(info.RemarkInfo)?.Remark).map((entry) => textEntry(entry, 'Remark', response)),\n accounting: asArray(info.AccountingInfo).map((entry) =>\n defined({ action: attribute(entry, 'Action'), type: attribute(entry, 'Type'), linkCode: attribute(entry, 'LinkCode') }),\n ),\n };\n}\n\nfunction textEntry(entry: unknown, label: string, response: SoapResponse): ReservationHistoryText {\n const action = attribute(entry, 'Action');\n if (action === undefined) throw malformed(`${label} sin Action`, response);\n const texts = asArray(node(entry)?.Text).map((text) => textOf(text) ?? '');\n return { action, text: texts.join('\\n') };\n}\n\nfunction flightSegment(segment: XmlNode, response: SoapResponse): ReservationHistoryFlightSegment {\n const action = attribute(segment, 'Action');\n if (action === undefined) throw malformed('FlightSegment sin Action', response);\n return {\n action,\n ...defined({\n status: attribute(segment, 'Status'),\n marketingAirline: attribute(segment.MarketingAirline, 'Code'),\n flightNumber: attribute(segment, 'FlightNumber') ?? attribute(segment.MarketingAirline, 'FlightNumber'),\n bookingClass: attribute(segment, 'ResBookDesigCode'),\n origin: attribute(segment.OriginLocation, 'LocationCode'),\n destination: attribute(segment.DestinationLocation, 'LocationCode'),\n departureDateTime: attribute(segment, 'DepartureDateTime'),\n arrivalDateTime: attribute(segment, 'ArrivalDateTime'),\n numberInParty: integer(attribute(segment, 'NumberInParty')),\n supplierRef: attribute(segment.SupplierRef, 'ID'),\n }),\n };\n}\n\nfunction malformed(detail: string, response: SoapResponse): SabreGatewayError {\n return new SabreGatewayError(`${RESERVATION_HISTORY_SERVICE}: respuesta no reconocida (${detail})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n}\n","// La reserva dentro de una sesión SOAP: hoy, solo el historial (B1 de ADR-027).\nimport type { SoapResponse } from '../http/soap-transport.js';\nimport type { SessionRequest } from '../session/session.js';\nimport {\n isRecordLocator,\n parseReservationHistoryResponse,\n type ReservationHistoryOptions,\n type ReservationHistoryResponse,\n reservationHistoryRequest,\n} from './reservation-history.js';\n\n/** @internal Lo que `SessionReservation` necesita de la sesión. */\nexport interface ReservationContext {\n send(request: SessionRequest): Promise<SoapResponse>;\n}\n\nexport class SessionReservation {\n readonly #context: ReservationContext;\n\n /** @internal Lo construye `SabreSession`. */\n constructor(context: ReservationContext) {\n this.#context = context;\n }\n\n /**\n * Get Itinerary History (`TravelItineraryHistoryLLSRQ` 2.4.0, el `*H` del host): el historial\n * del PNR, una entrada por transacción. Cada una trae quién la firmó, cuándo y desde qué PCC, y\n * los elementos que cambió con su `action`: los segmentos de vuelo con su estado en ese momento,\n * y SSR, ticketing, teléfonos, nombres y emails como texto en `generalInfo`. Lo que no se tipa\n * queda en la respuesta cruda (`onRawResponse`). **Trae datos del pasajero.**\n *\n * El historial no registra las colocaciones en cola, ni las del sistema ni un `place` manual\n * (CERT, 2026-11-06, Q-097): para eso están `queue.list`/`access` o los remarks `QUEUE_PLACE` de\n * Get Booking.\n *\n * **Dentro de una cola, Sabre lo rechaza** para otro PNR (CERT, 2026-11-06, Q-102): lanza\n * `SabreBusinessError` con `NAK6 -NOT ALLOWED- FINISH OR IGNORE OTHER ACTIVITY`. El PNR del AAA\n * no cambia, `queue.state` sigue en `'inside'` y el recorrido sigue con `ignore`. Conviene\n * llamarlo fuera de una cola.\n *\n * Es una lectura: se reintenta ante fallos transitorios. Un `locator` que no es de 6 caracteres\n * alfanuméricos en mayúscula lanza `TypeError` sin red. Un PNR que no existe sale como\n * `SabreBusinessError` (`service: 'itineraryHistory'`).\n */\n async history(locator: string, options: ReservationHistoryOptions = {}): Promise<ReservationHistoryResponse> {\n if (!isRecordLocator(locator)) {\n throw new TypeError('sabre-client: reservation.history necesita un localizador de 6 caracteres alfanuméricos en mayúscula');\n }\n const response = await this.#context.send(reservationHistoryRequest(locator, options));\n return parseReservationHistoryResponse(response);\n }\n}\n","// Send Sabre Command (`SabreCommandLLSRQ` 2.0.0): un comando de host dentro de la sesión, con la\n// pantalla como texto crudo. Ver sabre-wiki/wiki/proyectos/sabre-client/decisiones/comandos-de-host.md\n// (ADR-021) y wiki/entities/send-sabre-command.md. Request como `sabre-legacy-client@1.0.8` y el\n// script de configuración de agencia del 2026-11-03.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreGatewayError, type SabreWarning } from '../errors/index.js';\nimport { respondedAtField, type SoapResponse, textOf, untrimmedPayload, xmlEscape } from '../http/soap-transport.js';\nimport type { SessionRequest } from './session.js';\n\nexport const SABRE_COMMAND_SERVICE = 'sabreCommand';\nconst NAMESPACE = 'http://webservices.sabre.com/sabreXML/2011/10';\n\n/** Largo máximo de `HostCommand`, contado como Sabre (ver `sabreCommandLength`). */\nexport const MAX_COMMAND_LENGTH = 1023;\n/** Caracteres que Sabre cuenta doble en el largo del comando. */\nconst DOUBLE_WIDTH = new Set(['!', '%', '$', '&', '¥', '§']);\n\nexport interface SabreCommandOptions extends RequestOptions {\n /**\n * `true` solo si el comando es una lectura (`W/PT¥*`, `DC¥…`): entra en la política de\n * reintentos. Por defecto `false`, porque el SDK no sabe si un comando cambia algo.\n */\n idempotent?: boolean;\n}\n\nexport interface SabreCommandResponse {\n /**\n * La pantalla tal como la devuelve Sabre (`Response`), sin interpretar y sin recortar: las\n * pantallas van alineadas por columna y pueden empezar con un espacio (` 17MAR WED…`). Recortar\n * es decisión de quien la lee. Un mensaje de host (`DUTY CODE 9 REQUIRED`, `FORMAT`) llega aquí:\n * no lanza.\n */\n text: string;\n /** Los `stl:Warning` de la respuesta. No lanzan. */\n warnings: SabreWarning[];\n /** `eb:MessageId` de la respuesta, el dato que pide soporte de Sabre. */\n messageId: string | undefined;\n /**\n * `eb:Timestamp` de la respuesta de Sabre, en ISO 8601 UTC (`\"2026-11-06T17:34:16Z\"`). A\n * diferencia de las fechas del host, trae año y zona. Falta si Sabre no lo manda.\n */\n respondedAt?: string;\n}\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/** Cuerpo de `SabreCommandLLSRQ`: el comando va tal cual, escapado para XML y sin transformar. */\nexport function sabreCommandPayload(command: string): string {\n return `<SabreCommandLLSRQ xmlns=\"${NAMESPACE}\" Version=\"2.0.0\" ReturnHostCommand=\"true\"><Request Output=\"SCREEN\"><HostCommand>${xmlEscape(command)}</HostCommand></Request></SabreCommandLLSRQ>`;\n}\n\n/**\n * Lo único del comando que va al log: lo que está antes del primer `¥`, `‡` o espacio, cortado a\n * 4 caracteres (`W/PT`, `DC`, `*IM`, `SI9`). Un comando sin separador puede traer un localizador\n * o un nombre (`*ABC123`, `N-SMITH/JOHN`); el corte deja solo el principio.\n */\nexport function commandToken(command: string): string {\n return (command.trim().split(/[¥‡\\s]/u)[0] ?? '').slice(0, 4);\n}\n\n/**\n * Largo del comando como lo cuenta Sabre: cada carácter vale 1, salvo `!`, `%`, `$`, `&`, `¥` y\n * `§`, que valen 2. Más de `MAX_COMMAND_LENGTH` y Sabre responde `REQUEST EXCEEDED MAXIMUM LENGTH`.\n */\nexport function sabreCommandLength(command: string): number {\n let length = 0;\n for (const char of command) length += DOUBLE_WIDTH.has(char) ? 2 : 1;\n return length;\n}\n\n/** Valida el comando y arma la request. Sin reintento salvo `idempotent: true`. */\nexport function sabreCommandRequest(command: string, options: SabreCommandOptions): SessionRequest {\n if (typeof command !== 'string' || command.trim() === '') fail('command es requerido y debe ser un string no vacío');\n const length = sabreCommandLength(command);\n if (length > MAX_COMMAND_LENGTH) {\n fail(`command mide ${length} y el máximo es ${MAX_COMMAND_LENGTH} (!, %, $, &, ¥ y § cuentan 2); Sabre respondería REQUEST EXCEEDED MAXIMUM LENGTH`);\n }\n const { idempotent = false, ...requestOptions } = options;\n if (typeof idempotent !== 'boolean') fail('idempotent debe ser un boolean');\n return {\n service: SABRE_COMMAND_SERVICE,\n action: 'SabreCommandLLSRQ',\n payload: sabreCommandPayload(command),\n idempotent,\n operation: 'command',\n ...requestOptions,\n };\n}\n\n/**\n * Lee `SabreCommandLLSRS`: solo la pantalla, los avisos y el `MessageId`. La pantalla sale de un\n * parseo sin recorte (`untrimmedPayload`), no del payload compartido. Sin `Response` la pantalla\n * queda vacía. Otro elemento en el `Body` es una respuesta que el SDK no entiende.\n */\nexport function parseSabreCommandResponse(response: SoapResponse): SabreCommandResponse {\n if (response.payloadName !== 'SabreCommandLLSRS') {\n throw new SabreGatewayError(`${SABRE_COMMAND_SERVICE}: respuesta no reconocida (${response.payloadName})`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n return {\n text: textOf((untrimmedPayload(response.raw) ?? response.payload).Response) ?? '',\n warnings: response.warnings,\n messageId: response.messageId,\n ...respondedAtField(response.raw),\n };\n}\n","// Ciclo de vida de la sesión SOAP: `SessionCreateRQ` (2.0.0 o 1.0.0) y `SessionCloseRQ` 1.0.1,\n// con uso exclusivo. Ver sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 1 y\n// decisiones de la revisión), wiki/entities/create-session.md y gestion-de-sesion-soap.md.\nimport type { RequestOptions } from '../air/bargain-finder-max.js';\nimport { SabreError, SabreGatewayError, SabreSessionError, type SabreSessionErrorKind } from '../errors/index.js';\nimport {\n asArray,\n type SoapRequest,\n type SoapResponse,\n type SoapSecurity,\n type SoapTransport,\n textOf,\n xmlEscape,\n} from '../http/soap-transport.js';\nimport { QueueManagement } from '../queue/queue-management.js';\nimport { SessionReservation } from '../reservation/session-reservation.js';\nimport {\n commandToken,\n parseSabreCommandResponse,\n type SabreCommandOptions,\n type SabreCommandResponse,\n sabreCommandRequest,\n} from './command.js';\nimport type { SessionCredentials } from './credentials.js';\n\nconst OTA_NAMESPACE = 'http://www.opentravel.org/OTA/2002/11';\nconst SWS_NAMESPACE = 'http://webservices.sabre.com';\n\n/** Lo que una operación pide al transporte. La sesión agrega `CPAId`, `ConversationId` y el token. */\nexport type SessionRequest = Omit<SoapRequest, 'cpaId' | 'conversationId' | 'security'>;\n\n/**\n * Método interno por el que las operaciones de la sesión (cola, ping) llaman a Sabre. Va con un\n * símbolo que no se exporta del paquete para no sumar superficie pública.\n */\nexport const sessionSend: unique symbol = Symbol('sabre-client.session.send');\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\n/**\n * `USG_*` que dejan la sesión inutilizable (punto 4). Una sesión vencida en producción devuelve\n * `USG_INVALID_SECURITY_TOKEN` (#95, 2026-11-02): HTTP 500, `faultcode`\n * `soap-env:Client.InvalidSecurityToken`, y el código solo en el `detail`. `USG_AUTHENTICATION_FAILED`\n * sigue como `'expired'` de forma tentativa: no se observó con una sesión abierta.\n */\nconst SESSION_ERROR_KINDS: ReadonlyMap<string, SabreSessionErrorKind> = new Map([\n ['USG_RESOURCE_UNAVAILABLE', 'limit'],\n ['USG_INVALID_SESSION', 'invalid'],\n ['USG_INVALID_SECURITY_TOKEN', 'expired'],\n ['USG_AUTHENTICATION_FAILED', 'expired'],\n ['USG_RESOURCE_BLOCKED', 'blocked'],\n]);\n\n/**\n * Al abrir todavía no hay sesión que pueda vencer ni usarse en paralelo: ahí un\n * `USG_AUTHENTICATION_FAILED` son credenciales mal configuradas, y sigue como `SabreGatewayError`.\n */\nconst OPEN_ERROR_KINDS: ReadonlySet<SabreSessionErrorKind> = new Set(['limit', 'blocked']);\n\n/** Convierte un fault de sesión en `SabreSessionError`; cualquier otro error sale igual. */\nexport function toSessionError(error: unknown, allowed?: ReadonlySet<SabreSessionErrorKind>): unknown {\n if (!(error instanceof SabreGatewayError) || error instanceof SabreSessionError) return error;\n if (error.protocol !== 'soap' || error.code === undefined) return error;\n const kind = SESSION_ERROR_KINDS.get(error.code);\n if (kind === undefined || (allowed !== undefined && !allowed.has(kind))) return error;\n return new SabreSessionError(error.message, {\n kind,\n code: error.code,\n retryable: error.retryable,\n raw: error.raw,\n cause: error.cause,\n ...(error.status === undefined ? {} : { status: error.status }),\n });\n}\n\n/** Opciones de `openSession`. */\nexport interface OpenSessionOptions extends RequestOptions {\n /**\n * Manda `OTA_PingRQ` cuando la sesión lleva 13 minutos inactiva, antes del vencimiento de los\n * 15. Apagado por defecto: en runtimes serverless o edge un timer no sobrevive entre\n * invocaciones. Ahí conviene `withSession` por recorrido, o un `ping()` antes de reutilizar.\n */\n keepAlive?: boolean;\n}\n\n/** Inactividad a la que `keepAlive` manda el ping: 2 minutos antes de los 15 del vencimiento. */\nexport const KEEP_ALIVE_IDLE_MS = 13 * 60_000;\n\n/**\n * Una sesión SOAP abierta con `SessionCreateRQ`. Es exclusiva: Sabre no admite llamadas\n * concurrentes en la misma sesión (`USG_INVALID_SESSION`), así que una segunda llamada mientras\n * otra está en vuelo lanza `TypeError` sin llamar a la red. Se cierra con `close()`, o sola si\n * se abrió con `withSession`.\n */\nexport class SabreSession {\n /** Queue Management: contar, recorrer y colocar en colas, dentro de esta sesión. */\n readonly queue: QueueManagement;\n /** La reserva: el historial de un PNR, dentro de esta sesión. */\n readonly reservation: SessionReservation;\n readonly #transport: SoapTransport;\n readonly #pcc: string;\n readonly #conversationId: string;\n readonly #security: SoapSecurity;\n #busy = false;\n #closing: Promise<void> | undefined;\n /** El `SabreSessionError` que dejó la sesión inutilizable. */\n #unusable: SabreSessionError | undefined;\n /** Última vez que Sabre respondió en esta sesión (`Date.now()`). */\n #lastActivity = Date.now();\n #keepAliveTimer: ReturnType<typeof setTimeout> | undefined;\n /** El ping de `keepAlive` en vuelo: las llamadas del consumidor lo esperan en vez de chocar. */\n #keepAlivePing: Promise<void> | undefined;\n\n static {\n // `await using` es un extra: solo si el runtime tiene el símbolo (Node 22 no tiene la\n // sintaxis nativa, y algunos runtimes edge no tienen el símbolo).\n installAsyncDispose(this.prototype, (Symbol as { asyncDispose?: symbol }).asyncDispose);\n }\n\n /** @internal Se crea con `SabreLegacy.openSession()`. */\n constructor(internal: {\n transport: SoapTransport;\n pcc: string;\n conversationId: string;\n token: string;\n keepAlive: boolean;\n }) {\n this.#transport = internal.transport;\n this.#pcc = internal.pcc;\n this.#conversationId = internal.conversationId;\n this.#security = { binarySecurityToken: internal.token };\n this.queue = new QueueManagement({\n send: (request) => this[sessionSend](request),\n pcc: internal.pcc,\n log: internal.transport.log,\n });\n this.reservation = new SessionReservation({ send: (request) => this[sessionSend](request) });\n if (internal.keepAlive) this.#scheduleKeepAlive(KEEP_ALIVE_IDLE_MS);\n }\n\n /**\n * Milisegundos desde la última respuesta de Sabre en esta sesión; `0` mientras hay una llamada\n * en vuelo. Sabre cierra la sesión a los 15 minutos de inactividad.\n */\n get idleMs(): number {\n return this.#busy ? 0 : Math.max(0, Date.now() - this.#lastActivity);\n }\n\n /**\n * Manda `OTA_PingRQ`, que reinicia el contador de inactividad sin tocar el AAA. Durante un\n * recorrido de cola no hace falta: cada operación ya lo reinicia.\n */\n async ping(options: RequestOptions = {}): Promise<void> {\n checkPingResponse(await this[sessionSend]({ ...pingRequest(), ...options }));\n }\n\n /**\n * Manda un comando de host (`SabreCommandLLSRQ` 2.0.0) y devuelve la pantalla como texto, sin\n * interpretarla. Es una vía de escape: sin tipos ni garantías, y un comando puede cambiar la\n * configuración del PCC o emitir. El comando va tal cual; el separador de Sabre Red (`‡`) se\n * escribe `¥`. Sin reintento salvo `{ idempotent: true }`, para comandos de solo lectura. La\n * pantalla llega sin recortar, y más de 1023 caracteres (contados como Sabre) lanza sin red.\n */\n async command(command: string, options: SabreCommandOptions = {}): Promise<SabreCommandResponse> {\n const request = sabreCommandRequest(command, options);\n this.#transport.log.emit('debug', 'sabre.session.command', { command: commandToken(command) });\n return parseSabreCommandResponse(await this[sessionSend](request));\n }\n\n /**\n * Cierra la sesión con `SessionCloseRQ`: Sabre descarta el AAA e invalida el token. Es\n * idempotente: las llamadas siguientes devuelven la misma promesa, sin volver a la red. Si el\n * cierre falla, la sesión queda cerrada igual del lado del SDK; la de Sabre vence sola a los\n * 15 minutos. Una sesión inutilizable (ver `SabreSessionError`) se cierra sin red: Sabre ya no\n * la reconoce.\n */\n close(options: RequestOptions = {}): Promise<void> {\n if (this.#closing !== undefined) return this.#closing;\n if (this.#busy && this.#keepAlivePing === undefined) {\n return Promise.reject(new TypeError('sabre-client: session busy'));\n }\n this.#stopKeepAlive();\n if (this.#unusable !== undefined) {\n this.#closing = Promise.resolve();\n return this.#closing;\n }\n // Si el ping de `keepAlive` está en vuelo, el cierre sale cuando termina.\n const before = this.#keepAlivePing ?? Promise.resolve();\n this.#closing = before.then(() => this.#sendClose(options));\n return this.#closing;\n }\n\n /** @internal Una llamada a Sabre dentro de la sesión, con uso exclusivo. */\n async [sessionSend](request: SessionRequest): Promise<SoapResponse> {\n if (this.#keepAlivePing !== undefined && this.#closing === undefined) await this.#keepAlivePing;\n return this.#send(request);\n }\n\n async #send(request: SessionRequest): Promise<SoapResponse> {\n if (this.#closing !== undefined) fail('session closed');\n if (this.#unusable !== undefined) {\n throw new TypeError(`sabre-client: session unusable (${this.#unusable.kind})`, { cause: this.#unusable });\n }\n if (this.#busy) fail('session busy');\n this.#busy = true;\n try {\n const response = await this.#transport.request({ ...request, ...this.#envelopeFields() });\n this.#touch();\n return response;\n } catch (error) {\n if (reachedSabre(error)) this.#touch();\n throw this.#markUnusable(error);\n } finally {\n this.#busy = false;\n }\n }\n\n async #sendClose(options: RequestOptions): Promise<void> {\n if (this.#unusable !== undefined) return;\n // SessionCloseRQ queda fuera de onRawRequest, como las demás llamadas de auth (ADR-029).\n const { onRawRequest: _skipped, ...closeOptions } = options;\n this.#busy = true;\n try {\n await this.#transport.request({\n service: 'sessionClose',\n action: 'SessionCloseRQ',\n payload: `<SessionCloseRQ Version=\"1.0.1\"><POS><Source PseudoCityCode=\"${xmlEscape(this.#pcc)}\"/></POS></SessionCloseRQ>`,\n ...this.#envelopeFields(),\n // Solo se reintenta ante `USG_*_BUSY`: tras un fallo de red no se sabe si ya se cerró.\n idempotent: false,\n operation: 'close',\n ...closeOptions,\n });\n } catch (error) {\n throw this.#markUnusable(error);\n } finally {\n this.#busy = false;\n }\n this.#transport.log.emit('info', 'sabre.session.close', { pseudoCityCode: this.#pcc });\n }\n\n /** Un error de sesión deja la sesión inutilizable. No se reabre sola: el cursor ya se perdió. */\n #markUnusable(error: unknown): unknown {\n const mapped = toSessionError(error);\n if (mapped instanceof SabreSessionError) {\n this.#unusable = mapped;\n this.#stopKeepAlive();\n }\n return mapped;\n }\n\n #touch(): void {\n this.#lastActivity = Date.now();\n }\n\n #envelopeFields(): Pick<SoapRequest, 'cpaId' | 'conversationId' | 'security'> {\n return { cpaId: this.#pcc, conversationId: this.#conversationId, security: this.#security };\n }\n\n /**\n * Un solo timer, que se reprograma según `idleMs`: cada respuesta de Sabre corre el ping. Si el\n * ping falla (ya con los reintentos del transporte), se avisa con un `warn` y `keepAlive` se\n * apaga: reintentar sin fin no tiene sentido con una sesión que vence a los 15 minutos.\n */\n #scheduleKeepAlive(delayMs: number): void {\n const timer = setTimeout(() => this.#onKeepAlive(), delayMs);\n // Que el timer no mantenga vivo el proceso si el consumidor se olvida de cerrar (Node).\n (timer as { unref?: () => void }).unref?.();\n this.#keepAliveTimer = timer;\n }\n\n #onKeepAlive(): void {\n this.#keepAliveTimer = undefined;\n if (this.#closing !== undefined || this.#unusable !== undefined) return;\n if (this.#busy) {\n this.#scheduleKeepAlive(KEEP_ALIVE_IDLE_MS);\n return;\n }\n const remaining = KEEP_ALIVE_IDLE_MS - this.idleMs;\n if (remaining > 0) {\n this.#scheduleKeepAlive(remaining);\n return;\n }\n this.#keepAlivePing = this.#send(pingRequest()).then(\n () => {\n if (this.#closing === undefined && this.#unusable === undefined) this.#scheduleKeepAlive(KEEP_ALIVE_IDLE_MS);\n },\n (error: unknown) => {\n this.#transport.log.emit('warn', 'sabre.session.keepAliveFailed', { error });\n },\n );\n void this.#keepAlivePing.finally(() => {\n this.#keepAlivePing = undefined;\n });\n }\n\n #stopKeepAlive(): void {\n if (this.#keepAliveTimer !== undefined) clearTimeout(this.#keepAliveTimer);\n this.#keepAliveTimer = undefined;\n }\n}\n\n/**\n * `OTA_PingRQ` 1.0.0, como el sample oficial pero con el namespace OTA de la respuesta: sin él,\n * producción contesta `Invalid version` (#95). Idempotente: no toca el estado de negocio.\n */\nfunction pingRequest(): SessionRequest {\n const timestamp = new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n return {\n service: 'ping',\n action: 'OTA_PingRQ',\n payload: `<OTA_PingRQ xmlns=\"${OTA_PING_NAMESPACE}\" TimeStamp=\"${timestamp}\" Version=\"1.0.0\"><EchoData>sabre-client</EchoData></OTA_PingRQ>`,\n idempotent: true,\n operation: 'ping',\n };\n}\n\nconst OTA_PING_NAMESPACE = 'http://www.opentravel.org/OTA/2003/05';\n\n/**\n * `OTA_PingRS` puede traer un error con HTTP 200 y sin fault, como `<Errors><Error Type=\"VER\">\n * Invalid version</Error></Errors>` (producción, #95). Es un rechazo del request, así que sale\n * como `SabreGatewayError`, igual que un error de validación. Sin `Success` tampoco se da por bueno.\n */\nfunction checkPingResponse(response: SoapResponse): void {\n const errors = asArray(response.payload.Errors)[0] as Record<string, unknown> | undefined;\n const error = asArray(errors?.Error)[0];\n if (error !== undefined) {\n const type = (error as Record<string, unknown>)['@Type'];\n const text = textOf(error)?.trim();\n throw new SabreGatewayError(`ping: OTA_PingRS con error${text ? `: ${text}` : ''}`, {\n protocol: 'soap',\n status: response.status,\n ...(typeof type === 'string' && type !== '' && { code: type }),\n retryable: false,\n raw: response.raw,\n });\n }\n if (response.payloadName !== 'OTA_PingRS' || !('Success' in response.payload)) {\n throw new SabreGatewayError('ping: respuesta no reconocida (sin OTA_PingRS/Success)', {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n raw: response.raw,\n });\n }\n}\n\n/**\n * Si Sabre llegó a responder: cualquier error del SDK salvo un fallo de red (sin status). Solo\n * eso reinicia el contador de inactividad.\n */\nfunction reachedSabre(error: unknown): boolean {\n if (!(error instanceof SabreError)) return false;\n return !(error instanceof SabreGatewayError && error.status === undefined);\n}\n\n/** Define `[Symbol.asyncDispose]` como `close()`, si el runtime tiene el símbolo. */\nexport function installAsyncDispose(target: object, symbol: symbol | undefined): void {\n if (symbol === undefined) return;\n Object.defineProperty(target, symbol, {\n value(this: SabreSession): Promise<void> {\n return this.close();\n },\n configurable: true,\n writable: true,\n });\n}\n\n/** Cuerpo de `SessionCreateRQ`: 2.0.0 en el namespace de Sabre, 1.0.0 en el de OTA. */\nexport function sessionCreatePayload(credentials: Pick<SessionCredentials, 'version' | 'organization'>): string {\n const pos = `<POS><Source PseudoCityCode=\"${xmlEscape(credentials.organization)}\"/></POS>`;\n return credentials.version === '2.0.0'\n ? `<SessionCreateRQ xmlns=\"${SWS_NAMESPACE}\" Version=\"2.0.0\">${pos}</SessionCreateRQ>`\n : `<SessionCreateRQ xmlns=\"${OTA_NAMESPACE}\" Version=\"1.0.0\" returnContextID=\"true\">${pos}</SessionCreateRQ>`;\n}\n\nfunction usernameToken(credentials: SessionCredentials): SoapSecurity {\n const { username, password, organization, domain, clientId, clientSecret } = credentials;\n return {\n usernameToken: {\n username,\n password,\n organization,\n domain,\n ...(clientId === undefined ? {} : { clientId }),\n ...(clientSecret === undefined ? {} : { clientSecret }),\n },\n };\n}\n\n/**\n * Abre una sesión. Se reintenta solo ante `USG_*_BUSY`: `USG_RESOURCE_UNAVAILABLE` (más de 50\n * sesiones) se lanza sin reintentar.\n */\nexport async function openSession(\n transport: SoapTransport,\n credentials: SessionCredentials,\n options: OpenSessionOptions = {},\n): Promise<SabreSession> {\n const { keepAlive = false, ...requestOptions } = options;\n if (typeof keepAlive !== 'boolean') fail('keepAlive debe ser un boolean');\n const conversationId = globalThis.crypto.randomUUID();\n const request: SoapRequest = {\n service: 'sessionCreate',\n action: 'SessionCreateRQ',\n payload: sessionCreatePayload(credentials),\n cpaId: credentials.organization,\n conversationId,\n security: usernameToken(credentials),\n idempotent: false,\n readSecurityToken: true,\n operation: 'openSession',\n ...requestOptions,\n };\n const response = await transport.request(request).catch((error: unknown) => {\n throw toSessionError(error, OPEN_ERROR_KINDS);\n });\n\n const status = response.payload['@status'];\n if (typeof status === 'string' && status !== 'Approved') {\n throw new SabreGatewayError(`sessionCreate: SessionCreateRS con status ${status}`, {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n });\n }\n if (response.securityToken === undefined) {\n throw new SabreGatewayError('sessionCreate: la respuesta no trae BinarySecurityToken', {\n protocol: 'soap',\n status: response.status,\n retryable: false,\n });\n }\n\n // La versión elegida queda en el log, sin credenciales.\n transport.log.emit('info', 'sabre.session.open', {\n version: credentials.version,\n pseudoCityCode: credentials.organization,\n });\n return new SabreSession({\n transport,\n pcc: credentials.organization,\n conversationId,\n token: response.securityToken,\n keepAlive,\n });\n}\n","// Cliente SOAP. Ver sabre-wiki/wiki/sdk/arquitectura-clientes-transporte.md y\n// tier-3-sesion-y-colas-soap.md.\nimport { type ResolvedConfig, resolveConfig, type SabreConfig, type SabreEnvironment } from './config.js';\nimport { SoapTransport } from './http/soap-transport.js';\nimport { resolveSessionCredentials, type SessionCredentials } from './session/credentials.js';\nimport { type OpenSessionOptions, openSession, type SabreSession } from './session/session.js';\n\nexport class SabreLegacy {\n readonly #config: ResolvedConfig;\n /** Usuario, PCC, domain y versión de `SessionCreateRQ`, validados al crear el cliente. */\n readonly #session: Readonly<SessionCredentials>;\n readonly #transport: SoapTransport;\n\n /**\n * Recibe la misma config que `Sabre`. Usuario, PCC y domain de la sesión salen de\n * `credentials.username` (`V1:<user>:<PCC>:<domain>` o `<user>-<PCC>-<domain>`), y la versión\n * de `SessionCreateRQ` de las credenciales: 2.0.0 con `clientId` y `clientSecret`, 1.0.0 sin\n * ellos. Una config inválida lanza `TypeError` aquí, sin llamar a la red.\n */\n constructor(config: SabreConfig) {\n this.#config = resolveConfig(config);\n this.#session = Object.freeze(resolveSessionCredentials(this.#config.credentials));\n this.#transport = new SoapTransport(this.#config);\n }\n\n get environment(): SabreEnvironment {\n return this.#config.environment;\n }\n\n /** Endpoint SOAP del entorno. */\n get baseUrl(): string {\n return this.#config.soapBaseUrl;\n }\n\n /**\n * Abre una sesión SOAP. Quien la abre la cierra: `try { … } finally { await session.close() }`.\n * Para el caso común, `withSession` la cierra sola. Con `keepAlive: true`, manda un ping a los\n * 13 minutos de inactividad.\n */\n openSession(options: OpenSessionOptions = {}): Promise<SabreSession> {\n return openSession(this.#transport, this.#session, options);\n }\n\n /**\n * Abre una sesión, se la presta al callback y la cierra en un `finally`. Devuelve lo mismo que\n * el callback y propaga su error. Si el cierre falla, emite `sabre.session.closeFailed` en\n * `warn` y no pisa el resultado ni el error del callback.\n */\n async withSession<T>(callback: (session: SabreSession) => Promise<T>): Promise<T> {\n const session = await this.openSession();\n let result: T;\n try {\n result = await callback(session);\n } catch (error) {\n await this.#closeQuietly(session);\n throw error;\n }\n await this.#closeQuietly(session);\n return result;\n }\n\n async #closeQuietly(session: SabreSession): Promise<void> {\n try {\n await session.close();\n } catch (error) {\n this.#transport.log.emit('warn', 'sabre.session.closeFailed', { error });\n }\n }\n}\n","// Arma el `credentials` de la config a partir de un solo juego de partes. El mismo objeto sirve\n// para `Sabre` (REST) y para `SabreLegacy` (SOAP); la versión de OAuth solo cambia el formato\n// del username. Ver sabre-wiki/wiki/proyectos/sabre-client/decisiones/configuracion-logging-y-build.md\n// (ADR-010, #134) y wiki/entities/oauth-token-create.md (formato del EPR por versión).\nimport type { SabreAuthVersion, SabreCredentials, SabreCredentialsV2 } from '../config.js';\nimport { isPseudoCityCode } from '../session/credentials.js';\n\ninterface BuildCredentialsBase {\n /** Usuario EPR, sin PCC ni domain. */\n user: string;\n /** PCC del EPR (el *group*): 3 o 4 caracteres alfanuméricos. */\n pcc: string;\n /** Domain del EPR. Default `'AA'`. */\n domain?: string;\n /** Contraseña EPR. */\n password: string;\n}\n\n/** Partes para OAuth Token Create v3 (default): `clientId` y `clientSecret` son obligatorios. */\nexport interface BuildCredentialsOptionsV3 extends BuildCredentialsBase {\n authVersion?: 'v3';\n clientId: string;\n clientSecret: string;\n}\n\n/**\n * Partes para OAuth Token Create v2: `clientId`/`clientSecret` son opcionales. REST los ignora,\n * pero si vienen los dos, `SabreLegacy` abre la sesión con `SessionCreateRQ` 2.0.0.\n */\nexport interface BuildCredentialsOptionsV2 extends BuildCredentialsBase {\n authVersion: 'v2';\n clientId?: string;\n clientSecret?: string;\n}\n\nexport type BuildCredentialsOptions = BuildCredentialsOptionsV3 | BuildCredentialsOptionsV2;\n\n/** Lo que devuelve `buildCredentials` para v3: lleva `authVersion: 'v3'`. */\nexport type BuiltCredentialsV3 = SabreCredentials & { authVersion: 'v3' };\n\n/**\n * Lo que devuelve `buildCredentials` para v2: lleva `authVersion: 'v2'`, así que la config no\n * necesita repetirlo (#148).\n */\nexport type BuiltCredentialsV2 = SabreCredentialsV2 & { authVersion: 'v2' };\n\nconst DEFAULT_DOMAIN = 'AA';\n\nfunction fail(message: string): never {\n throw new TypeError(`sabre-client: ${message}`);\n}\n\nfunction requireString(value: unknown, field: string): asserts value is string {\n if (typeof value !== 'string' || value.trim() === '') fail(`${field} es requerido y debe ser un string no vacío`);\n}\n\n/**\n * Arma el `credentials` para `Sabre` y `SabreLegacy` a partir del usuario, el PCC, el domain y\n * la contraseña del EPR, más `clientId`/`clientSecret` cuando los hay. El username queda como\n * `<user>-<PCC>-<domain>` (v3) o `V1:<user>:<PCC>:<domain>` (v2). No lee variables de entorno\n * ni toca la red; un dato inválido lanza `TypeError` sin repetir secretos. El resultado lleva\n * `authVersion`, que la config usa si no trae el suyo.\n */\nexport function buildCredentials(options: BuildCredentialsOptionsV3): BuiltCredentialsV3;\nexport function buildCredentials(options: BuildCredentialsOptionsV2): BuiltCredentialsV2;\nexport function buildCredentials(options: BuildCredentialsOptions): BuiltCredentialsV3 | BuiltCredentialsV2;\nexport function buildCredentials(options: BuildCredentialsOptions): BuiltCredentialsV3 | BuiltCredentialsV2 {\n if (typeof options !== 'object' || options === null) fail('buildCredentials recibe un objeto');\n\n const authVersion: SabreAuthVersion = options.authVersion ?? 'v3';\n if (authVersion !== 'v3' && authVersion !== 'v2') {\n fail(`authVersion debe ser 'v3' o 'v2' (recibido: ${JSON.stringify(authVersion)})`);\n }\n\n const { user, pcc, password, clientId, clientSecret } = options;\n const domain = options.domain ?? DEFAULT_DOMAIN;\n requireString(user, 'user');\n requireString(password, 'password');\n if (!isPseudoCityCode(pcc)) fail('pcc debe tener 3 o 4 caracteres alfanuméricos');\n requireString(domain, 'domain');\n // El username se lee de derecha a izquierda: un separador en el domain lo partiría mal.\n if (/[-:]/.test(domain)) fail(\"domain no puede contener '-' ni ':'\");\n\n if ((clientId === undefined) !== (clientSecret === undefined)) {\n fail('clientId y clientSecret van juntos: pasa los dos o ninguno');\n }\n if (authVersion === 'v3' || clientId !== undefined) {\n requireString(clientId, authVersion === 'v3' ? 'clientId (requerido con authVersion v3)' : 'clientId');\n requireString(clientSecret, authVersion === 'v3' ? 'clientSecret (requerido con authVersion v3)' : 'clientSecret');\n }\n\n const username = authVersion === 'v3' ? `${user}-${pcc}-${domain}` : `V1:${user}:${pcc}:${domain}`;\n if (authVersion === 'v3') return { authVersion, clientId: clientId!, clientSecret: clientSecret!, username, password };\n return clientId === undefined\n ? { authVersion, username, password }\n : { authVersion, clientId, clientSecret: clientSecret!, username, password };\n}\n","// Fechas de host sin año → strings ISO, con la regla del año. Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 3 y decisiones de la revisión).\n\n/**\n * Cómo se elige el año cuando el texto no lo trae:\n *\n * - `'past'`: la fecha más reciente que no sea posterior a `referenceDate` (el mismo día cuenta).\n * Es la regla de los hechos que ya pasaron: la línea de recibido, `placedAt` y `countedAt`.\n * - `'nearest'`: la fecha más cercana a `referenceDate`, hacia adelante o hacia atrás, dentro de\n * ±6 meses. Es la regla de los segmentos y del plazo de ticketing (`T-`, `TAW`). Con un empate\n * gana la fecha futura.\n */\nexport type HostDateDirection = 'past' | 'nearest';\n\nexport interface ResolveHostDateOptions {\n /** Regla del año. Por defecto `'past'`, la de `placedAt` y `countedAt`. */\n direction?: HostDateDirection;\n}\n\nconst MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];\n\nconst DAY_MS = 86_400_000;\n\n/** Medio año, en días: la distancia más larga de una fecha a la referencia con `'nearest'`. */\nconst HALF_YEAR_DAYS = 184;\n\ninterface HostDate {\n year?: number;\n month: number;\n day: number;\n time?: string;\n}\n\n/**\n * Convierte una fecha de host en un string ISO sin zona horaria: `'YYYY-MM-DD'`, o\n * `'YYYY-MM-DDTHH:mm'` si el texto trae hora.\n *\n * Formatos que reconoce (sin distinguir mayúsculas, sin espacios a los costados):\n *\n * - `06SEP` y `06SEP26`, como en los segmentos, el ticketing y la línea de recibido;\n * - `12-21` y `12-21T07:00`, como el `DateTime` de `QueueCountRS`;\n * - `2024-05-15` y `2024-05-15T13:24`, como el `DateTime` de una línea de cola real.\n *\n * Si el texto trae año, se usa ese (un año de dos dígitos es del 2000 en adelante). Si no, el año\n * se resuelve contra `referenceDate` con la regla de `options.direction`.\n *\n * `referenceDate` es un `'YYYY-MM-DD'` (puede seguir una hora, que no se usa) o un `Date`, del que\n * se toma el día en UTC. Conviene pasar el día en el calendario del PCC: la regla compara días, y\n * con zonas distintas la referencia puede quedar un día corrida.\n *\n * Devuelve `undefined` si el texto no tiene un formato reconocido, si la fecha no existe\n * (`2026-02-29`, `31APR`) o si no hay un año que cumpla la regla (un `29FEB` sin un año bisiesto a\n * menos de 6 meses, con `'nearest'`). Lanza `TypeError` si `referenceDate` no es válida.\n */\nexport function resolveHostDate(\n text: string,\n referenceDate: Date | string,\n options: ResolveHostDateOptions = {},\n): string | undefined {\n const reference = referenceDay(referenceDate);\n const direction = options.direction ?? 'past';\n if (direction !== 'past' && direction !== 'nearest') {\n throw new TypeError(\"sabre-client: direction debe ser 'past' o 'nearest'\");\n }\n if (typeof text !== 'string') return undefined;\n\n const parsed = parseHostDate(text.trim().toUpperCase());\n if (parsed === undefined) return undefined;\n\n const year = parsed.year ?? resolveYear(parsed.month, parsed.day, reference, direction);\n if (year === undefined || !isValidDate(year, parsed.month, parsed.day)) return undefined;\n\n const date = `${pad(year, 4)}-${pad(parsed.month, 2)}-${pad(parsed.day, 2)}`;\n return parsed.time === undefined ? date : `${date}T${parsed.time}`;\n}\n\nfunction parseHostDate(text: string): HostDate | undefined {\n // 06SEP, 06SEP26\n let match = /^(\\d{1,2})([A-Z]{3})(\\d{2})?$/.exec(text);\n if (match !== null) {\n const month = MONTHS.indexOf(match[2]!) + 1;\n if (month === 0) return undefined;\n return {\n ...(match[3] !== undefined && { year: 2000 + Number(match[3]) }),\n month,\n day: Number(match[1]),\n };\n }\n\n // 12-21, 12-21T07:00, 2024-05-15, 2024-05-15T13:24\n match = /^(?:(\\d{4})-)?(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2}))?$/.exec(text);\n if (match === null) return undefined;\n const [, year, month, day, hours, minutes] = match;\n if (hours !== undefined && (Number(hours) > 23 || Number(minutes) > 59)) return undefined;\n return {\n ...(year !== undefined && { year: Number(year) }),\n month: Number(month),\n day: Number(day),\n ...(hours !== undefined && { time: `${hours}:${minutes}` }),\n };\n}\n\n/** Año que cumple la regla, o `undefined` si ninguno de los candidatos la cumple. */\nfunction resolveYear(month: number, day: number, reference: number, direction: HostDateDirection) {\n const year = new Date(reference).getUTCFullYear();\n\n if (direction === 'past') {\n // Hacia atrás no hay ventana: un 29FEB puede caer hasta 8 años antes (con un 2100 en medio).\n for (let candidate = year; candidate >= year - 8; candidate--) {\n if (isValidDate(candidate, month, day) && dayNumber(candidate, month, day) <= reference) return candidate;\n }\n return undefined;\n }\n\n let best: { year: number; distance: number } | undefined;\n for (const candidate of [year + 1, year, year - 1]) {\n if (!isValidDate(candidate, month, day)) continue;\n const distance = Math.abs(dayNumber(candidate, month, day) - reference);\n // Los candidatos van del futuro al pasado: con un empate se queda el futuro.\n if (best === undefined || distance < best.distance) best = { year: candidate, distance };\n }\n return best !== undefined && best.distance <= HALF_YEAR_DAYS * DAY_MS ? best.year : undefined;\n}\n\n/**\n * El día de `referenceDate`, como milisegundos UTC de su medianoche. Lanza `TypeError` si no es\n * válida. Lo usa también el parser del párrafo, para validarla aunque el párrafo no traiga fechas.\n */\nexport function referenceDay(referenceDate: Date | string): number {\n if (referenceDate instanceof Date) {\n const time = referenceDate.getTime();\n if (Number.isNaN(time)) throw new TypeError('sabre-client: referenceDate es un Date inválido');\n return time - (((time % DAY_MS) + DAY_MS) % DAY_MS);\n }\n if (typeof referenceDate === 'string') {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})(?:T.*)?$/.exec(referenceDate.trim());\n if (match !== null) {\n const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];\n if (isValidDate(year, month, day)) return dayNumber(year, month, day);\n }\n }\n throw new TypeError(\"sabre-client: referenceDate es obligatoria, como 'YYYY-MM-DD' o un Date válido\");\n}\n\nfunction dayNumber(year: number, month: number, day: number): number {\n const date = new Date(0);\n date.setUTCFullYear(year, month - 1, day);\n return date.getTime();\n}\n\nfunction isValidDate(year: number, month: number, day: number): boolean {\n if (month < 1 || month > 12 || day < 1) return false;\n const date = new Date(0);\n date.setUTCFullYear(year, month - 1, day);\n return date.getUTCMonth() === month - 1 && date.getUTCDate() === day;\n}\n\nfunction pad(value: number, length: number): string {\n return String(value).padStart(length, '0');\n}\n","// Parser best-effort del párrafo de cola (un PNR en formato de host). Ver\n// sabre-wiki/wiki/sdk/tier-3-sesion-y-colas-soap.md (punto 3 y decisiones de la revisión).\nimport { referenceDay, resolveHostDate } from './host-date.js';\n\nexport interface QueueParagraphOptions {\n /**\n * Fecha contra la que se resuelve el año de las fechas sin año: un `'YYYY-MM-DD'` o un `Date`\n * (se toma el día en UTC). Es obligatoria. Ver `resolveHostDate`.\n */\n referenceDate: Date | string;\n}\n\n/** Aviso de cola del principio del párrafo: el código PIC y su descripción (`011 SEE REMARKS`). */\nexport interface QueueParagraphMessage {\n instructionCode: number;\n text: string;\n}\n\n/** Un nombre del PNR (`1.1TEST/SWS*FSG`). */\nexport interface QueueParagraphPassenger {\n /** Número de nombre, tal cual: `'1.1'`. */\n nameNumber: string;\n surname: string;\n givenName?: string;\n /** Lo que sigue al `*` del nombre. */\n nameRemark?: string;\n /** El nombre como llegó, sin el número: `'TEST/SWS*FSG'`. */\n text: string;\n}\n\ninterface QueueParagraphSegmentBase {\n /** Número de segmento en el PNR. */\n number: number;\n /** Fecha ISO (`'2026-05-22'`), con el año resuelto con la regla `'nearest'`. */\n date?: string;\n /** Estado del segmento: `HK`, `HX`, `UN`, `GK`… */\n status: string;\n /** Cantidad que acompaña al estado (`HK1` → `1`). */\n quantity: number;\n /** La línea como llegó, sin espacios a los costados. */\n text: string;\n}\n\n/** Un segmento aéreo: ` 1 DL2151E 20MAR 5 MIALGA HK1 0700 1003 /DCDL*HTDHAT /E`. */\nexport interface QueueParagraphAirSegment extends QueueParagraphSegmentBase {\n kind: 'air';\n airlineCode: string;\n flightNumber: number;\n bookingClass: string;\n fromAirportCode: string;\n toAirportCode: string;\n /** Hora local de salida, en 24 horas (`'07:00'`). */\n departureTime?: string;\n /** Hora local de llegada, en 24 horas. Puede ser de otro día: el host no siempre lo marca. */\n arrivalTime?: string;\n}\n\n/** Un segmento no aéreo con fecha: `2 CAR ZE 22APR Q GK1 DFW/24APR/…`. */\nexport interface QueueParagraphOtherSegment extends QueueParagraphSegmentBase {\n kind: 'other';\n /** Tipo de segmento del host: `CAR`, `OTH`… */\n segmentType: string;\n vendorCode: string;\n}\n\nexport type QueueParagraphSegment = QueueParagraphAirSegment | QueueParagraphOtherSegment;\n\n/** Una entrada del campo de ticketing (`TKT/TIME LIMIT`). */\nexport interface QueueParagraphTicketingEntry {\n /** Número de la entrada: `1` en `1.T-13MAY-X6R3*N18`. */\n number: number;\n /** `'T-'`, `'TAW'` (o `TAC`, `TAM`, `TAT`, `TAX`), o `'TE'`/`'TK'` para una línea de boleto. */\n code: string;\n /** Fecha ISO de la entrada, con el año resuelto con la regla `'nearest'`. */\n date?: string;\n pseudoCityCode?: string;\n agentSine?: string;\n /** Número de boleto de una línea `TE` o `TK`. */\n ticketNumber?: string;\n /** La entrada como llegó, sin el número: `'T-13MAY-X6R3*N18'`. */\n text: string;\n}\n\nexport interface QueueParagraphTicketing {\n entries: QueueParagraphTicketingEntry[];\n /** `true` si alguna entrada es una línea de boleto (`TE` o `TK`, con número). */\n issued: boolean;\n}\n\n/**\n * La línea `RECEIVED FROM - …` y la línea de firma del PNR\n * (`<PCC>.<PCC>*<agente> HHMM/DDMMMYY <localizador> H`). La firma es la de la última modificación.\n */\nexport interface QueueParagraphReceivedFrom {\n /** Lo que sigue a `RECEIVED FROM - `. */\n name?: string;\n /** El primer PCC de la firma. */\n pseudoCityCode?: string;\n /** La firma del agente, lo que sigue al `*`. */\n agentSine?: string;\n /** Fecha y hora de la firma, `'YYYY-MM-DDTHH:mm'`. Sin año, se resuelve hacia atrás. */\n receivedAt?: string;\n locator?: string;\n}\n\nexport interface QueueParagraph {\n messages: QueueParagraphMessage[];\n passengers: QueueParagraphPassenger[];\n segments: QueueParagraphSegment[];\n /** El campo de ticketing, si el párrafo trae la sección `TKT/TIME LIMIT`. */\n ticketing?: QueueParagraphTicketing;\n /** La línea de recibido y la firma, si llega alguna de las dos. */\n receivedFrom?: QueueParagraphReceivedFrom;\n /** Las líneas que no se reconocieron, tal cual y en orden. Las líneas vacías no se incluyen. */\n unparsed: string[];\n}\n\nconst MESSAGE = /^\\s*(\\d{3})\\s{2,}(\\S.*?)\\s*$/;\nconst PASSENGER_LINE = /^\\s*\\d+\\.\\d+[A-Z]/;\nconst PASSENGER_SPLIT = /\\s+(?=\\d+\\.\\d+[A-Z])/;\nconst PASSENGER = /^(\\d+\\.\\d+)([^/*]+?)\\s*(?:\\/([^*]*?))?\\s*(?:\\*(.*?))?\\s*$/;\nconst AIR_SEGMENT =\n /^\\s*(\\d{1,2})\\s+([A-Z0-9]{2})\\s*(\\d{1,4})([A-Z])\\s+(\\d{2}[A-Z]{3})\\s+[A-Z0-9]\\s+([A-Z]{3})([A-Z]{3})\\s+([A-Z]{2})(\\d{1,3})(?=\\s|$)(.*)$/;\nconst SEGMENT_TIMES = /^\\s+(\\d{3,4}[APNM]?)\\s+(\\d{3,4}[APNM]?)(?=\\s|$)/;\nconst OTHER_SEGMENT =\n /^\\s*(\\d{1,2})\\s+([A-Z]{3})\\s+([A-Z0-9]{2})\\s+(\\d{2}[A-Z]{3})\\s+[A-Z0-9]\\s+([A-Z]{2})(\\d{1,3})(?=\\s|$)/;\nconst NO_ITINERARY = /^\\s*NO ITIN\\s*$/;\nconst TICKETING_HEADER = /^\\s*TKT\\/TIME LIMIT\\s*$/;\nconst TICKETING_ENTRY = /^\\s*(\\d+)\\.(.*?)\\s*$/;\nconst TICKETED = /^T-(\\d{2}[A-Z]{3})?(?:-([A-Z0-9]{3,4})\\*([A-Z0-9]+))?(?:\\/.*)?$/;\nconst ARRANGEMENT = /^(TA[WCMTX])([A-Z0-9]{3,4})?(\\d{2}[A-Z]{3})?\\d{0,3}\\/.*$/;\nconst TICKET = /^(TE|TK)\\s+(\\d{13})\\b/;\nconst RECEIVED = /^\\s*RECEIVED FROM -\\s?(.*?)\\s*$/;\nconst SIGNATURE = /^\\s*([A-Z0-9]{3,4})\\.(\\S+)\\s+(\\d{2})(\\d{2})\\/(\\d{2}[A-Z]{3}\\d{2})\\s+([A-Z0-9]{6})\\s+H\\s*$/;\n\n/** En qué parte del párrafo va el parser: cada sección solo se reconoce hasta que empieza la siguiente. */\nconst Phase = { Messages: 0, Passengers: 1, Segments: 2, Body: 3 } as const;\ntype Phase = (typeof Phase)[keyof typeof Phase];\n\n/**\n * Lee un párrafo de cola (`QueueItem.paragraph`) y extrae las secciones estándar de un PNR en\n * formato de host: los avisos de cola, los nombres, los segmentos con su estado, el campo de\n * ticketing y la línea de recibido con la firma.\n *\n * **Es best-effort**: el formato de host no tiene contrato. Una línea que no reconoce va a\n * `unparsed` y nunca lanza por el contenido del párrafo. Solo lanza `TypeError` si `lines` no es\n * un array o si `referenceDate` falta o no es válida.\n *\n * **No extrae** los plazos escritos en texto libre por la aerolínea (`ADTK BY`, `BEFORE` en\n * remarks, SSR u OSI): su formato lo pone cada aerolínea. Esas líneas van a `unparsed`.\n *\n * Las fechas salen como strings ISO sin zona horaria. Los segmentos y el ticketing toman la fecha\n * más cercana a `referenceDate` dentro de ±6 meses, y la firma se resuelve hacia atrás.\n *\n * **Versionado**: que una línea pase de `unparsed` a un campo nuevo es un cambio minor. Que cambie\n * la forma de un campo existente es major.\n */\nexport function parseQueueParagraph(lines: readonly string[], options: QueueParagraphOptions): QueueParagraph {\n if (!Array.isArray(lines)) throw new TypeError('sabre-client: lines debe ser un array de strings');\n if (typeof options !== 'object' || options === null) {\n throw new TypeError(\"sabre-client: referenceDate es obligatoria, como 'YYYY-MM-DD' o un Date válido\");\n }\n const { referenceDate } = options;\n referenceDay(referenceDate);\n\n const result: QueueParagraph = { messages: [], passengers: [], segments: [], unparsed: [] };\n const signatureIndex = lastSignatureIndex(lines);\n let phase: Phase = Phase.Messages;\n let inTicketing = false;\n\n lines.forEach((value, index) => {\n const line = typeof value === 'string' ? value : '';\n if (line.trim() === '') return;\n\n if (index === signatureIndex) {\n result.receivedFrom = { ...result.receivedFrom, ...parseSignature(line, referenceDate) };\n return;\n }\n\n if (inTicketing) {\n const entry = TICKETING_ENTRY.exec(line);\n if (entry !== null) {\n const parsed = parseTicketingEntry(Number(entry[1]), entry[2]!, referenceDate);\n if (parsed === undefined) result.unparsed.push(line);\n else result.ticketing!.entries.push(parsed);\n return;\n }\n inTicketing = false;\n }\n\n if (TICKETING_HEADER.test(line)) {\n phase = Phase.Body;\n inTicketing = true;\n result.ticketing ??= { entries: [], issued: false };\n return;\n }\n\n const received = RECEIVED.exec(line);\n if (received !== null) {\n phase = Phase.Body;\n result.receivedFrom = { ...result.receivedFrom, ...(received[1] !== '' && { name: received[1]! }) };\n return;\n }\n\n if (phase === Phase.Messages) {\n const message = MESSAGE.exec(line);\n if (message !== null) {\n result.messages.push({ instructionCode: Number(message[1]), text: message[2]! });\n return;\n }\n }\n\n if (phase <= Phase.Passengers && PASSENGER_LINE.test(line)) {\n const passengers = parsePassengers(line);\n if (passengers !== undefined) {\n phase = Phase.Passengers;\n result.passengers.push(...passengers);\n return;\n }\n }\n\n if (phase <= Phase.Segments) {\n if (NO_ITINERARY.test(line)) {\n phase = Phase.Segments;\n return;\n }\n const segment = parseSegment(line, referenceDate);\n if (segment !== undefined) {\n phase = Phase.Segments;\n result.segments.push(segment);\n return;\n }\n }\n\n result.unparsed.push(line);\n });\n\n if (result.ticketing !== undefined) {\n result.ticketing.issued = result.ticketing.entries.some((entry) => entry.ticketNumber !== undefined);\n }\n return result;\n}\n\nfunction parsePassengers(line: string): QueueParagraphPassenger[] | undefined {\n const passengers: QueueParagraphPassenger[] = [];\n for (const part of line.trim().split(PASSENGER_SPLIT)) {\n const match = PASSENGER.exec(part);\n if (match === null) return undefined;\n const [, nameNumber, surname, givenName, nameRemark] = match;\n passengers.push({\n nameNumber: nameNumber!,\n surname: surname!.trim(),\n ...(givenName !== undefined && givenName !== '' && { givenName }),\n ...(nameRemark !== undefined && nameRemark !== '' && { nameRemark }),\n text: part.slice(nameNumber!.length).trim(),\n });\n }\n return passengers;\n}\n\nfunction parseSegment(line: string, referenceDate: Date | string): QueueParagraphSegment | undefined {\n const air = AIR_SEGMENT.exec(line);\n if (air !== null) {\n const [, number, airlineCode, flightNumber, bookingClass, date, from, to, status, quantity, rest] = air;\n const times = SEGMENT_TIMES.exec(rest!);\n const departureTime = times === null ? undefined : hostTime(times[1]!);\n const arrivalTime = times === null ? undefined : hostTime(times[2]!);\n return {\n kind: 'air',\n number: Number(number),\n ...withDate(date!, referenceDate),\n status: status!,\n quantity: Number(quantity),\n airlineCode: airlineCode!,\n flightNumber: Number(flightNumber),\n bookingClass: bookingClass!,\n fromAirportCode: from!,\n toAirportCode: to!,\n ...(departureTime !== undefined && { departureTime }),\n ...(arrivalTime !== undefined && { arrivalTime }),\n text: line.trim(),\n };\n }\n\n const other = OTHER_SEGMENT.exec(line);\n if (other === null) return undefined;\n const [, number, segmentType, vendorCode, date, status, quantity] = other;\n return {\n kind: 'other',\n number: Number(number),\n ...withDate(date!, referenceDate),\n status: status!,\n quantity: Number(quantity),\n segmentType: segmentType!,\n vendorCode: vendorCode!,\n text: line.trim(),\n };\n}\n\nfunction parseTicketingEntry(\n number: number,\n text: string,\n referenceDate: Date | string,\n): QueueParagraphTicketingEntry | undefined {\n const ticketed = TICKETED.exec(text);\n if (ticketed !== null) {\n const [, date, pseudoCityCode, agentSine] = ticketed;\n return {\n number,\n code: 'T-',\n ...(date !== undefined && withDate(date, referenceDate)),\n ...(pseudoCityCode !== undefined && { pseudoCityCode }),\n ...(agentSine !== undefined && { agentSine }),\n text,\n };\n }\n\n const arrangement = ARRANGEMENT.exec(text);\n if (arrangement !== null) {\n const [, code, pseudoCityCode, date] = arrangement;\n return {\n number,\n code: code!,\n ...(date !== undefined && withDate(date, referenceDate)),\n ...(pseudoCityCode !== undefined && { pseudoCityCode }),\n text,\n };\n }\n\n const ticket = TICKET.exec(text);\n if (ticket !== null) return { number, code: ticket[1]!, ticketNumber: ticket[2]!, text };\n return undefined;\n}\n\n/** La firma, si hay una, es la última línea con ese formato. Las anteriores van a `unparsed`. */\nfunction lastSignatureIndex(lines: readonly string[]): number {\n for (let index = lines.length - 1; index >= 0; index--) {\n const line = lines[index];\n if (typeof line === 'string' && SIGNATURE.test(line)) return index;\n }\n return -1;\n}\n\nfunction parseSignature(line: string, referenceDate: Date | string): QueueParagraphReceivedFrom {\n const [, pseudoCityCode, sign, hours, minutes, date, locator] = SIGNATURE.exec(line)!;\n const agentSine = /\\*([A-Z0-9]+)$/.exec(sign!)?.[1];\n const day = Number(hours) <= 23 && Number(minutes) <= 59 ? resolveHostDate(date!, referenceDate) : undefined;\n return {\n pseudoCityCode: pseudoCityCode!,\n ...(agentSine !== undefined && { agentSine }),\n ...(day !== undefined && { receivedAt: `${day}T${hours}:${minutes}` }),\n locator: locator!,\n };\n}\n\nfunction withDate(text: string, referenceDate: Date | string): { date?: string } {\n const date = resolveHostDate(text, referenceDate, { direction: 'nearest' });\n return date === undefined ? {} : { date };\n}\n\n/**\n * Hora del host en 24 horas: `0700` y `1003` tal cual, y con sufijo `A` (a. m.), `P` (p. m.),\n * `N` (mediodía) o `M` (medianoche): `740P` → `19:40`, `1200N` → `12:00`.\n */\nfunction hostTime(text: string): string | undefined {\n const match = /^(\\d{1,2})(\\d{2})([APNM])?$/.exec(text);\n if (match === null) return undefined;\n let hours = Number(match[1]);\n const minutes = Number(match[2]);\n const suffix = match[3];\n if (minutes > 59) return undefined;\n if (suffix === undefined) {\n if (hours > 23) return undefined;\n } else {\n if (hours < 1 || hours > 12) return undefined;\n if (suffix === 'A' || suffix === 'M') hours %= 12;\n else if (suffix === 'P') hours = (hours % 12) + 12;\n else if (hours !== 12) return undefined;\n }\n return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;\n}\n","// El remark `QUEUE_PLACE` de Get Booking: dónde se colocó el PNR. Ver\n// sabre-wiki/wiki/proyectos/sabre-client/decisiones/tier-4-colas-avanzadas.md (A4) y\n// wiki/entities/booking-management-api.md (Q-090).\nimport { isInstructionCode } from './queue-place.js';\nimport { MAX_QUEUE_NUMBER } from './queue-ref.js';\n\n/** Un remark `QUEUE_PLACE` ya separado en sus partes. */\nexport interface QueuePlaceRemark {\n /** El PCC de la cola, de 3 o 4 caracteres alfanuméricos (`'MEX'`, `'AB12'`). */\n pcc: string;\n /**\n * La fecha de la colocación, `DDMMM` sin año, tal cual llegó (`'25SEP'`). El año se resuelve con\n * `resolveHostDate(date, referenceDate)`.\n */\n date: string;\n /** El número de cola, de 0 a 511. */\n queue: number;\n /** El PIC (prefatory instruction code), de 0 a 191 o de 200 a 254. Llega con ceros a la izquierda. */\n pic: number;\n}\n\nconst MONTHS = new Set(['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']);\n\n/**\n * `PCC` + `DDMMM` + cola + `/` + PIC, sin separadores: `MEX25SEP146/015`. El mes son las tres letras\n * que van antes de la cola, así que un PCC de 4 caracteres que termina en dígito (`AB1205JUL…`) no\n * se confunde con el día.\n */\nconst REMARK = /^([A-Z0-9]{3,4})(\\d{2})([A-Z]{3})(\\d{1,3})\\/(\\d{1,3})$/;\n\n/**\n * Parsea el `text` de un remark `QUEUE_PLACE` de Get Booking (`remarks[].type === 'QUEUE_PLACE'`).\n * La forma salió de remarks reales de producción (Q-090): `MEX25SEP146/015` da\n * `{ pcc: 'MEX', date: '25SEP', queue: 146, pic: 15 }`.\n *\n * Devuelve `null` si el texto no tiene esa forma, o si el día no está entre 01 y 31, el mes entre\n * `JAN` y `DEC`, la cola entre 0 y 511, o el PIC en 0–191 o 200–254. No lanza: con un valor que no\n * es un string también devuelve `null`. Ignora los espacios a los costados. Sabre manda el texto en\n * mayúsculas, así que uno en minúsculas da `null`.\n */\nexport function parseQueuePlaceRemark(text: string): QueuePlaceRemark | null {\n if (typeof text !== 'string') return null;\n const match = REMARK.exec(text.trim());\n if (match === null) return null;\n const [, pcc, day, month, queueText, picText] = match as unknown as [string, string, string, string, string, string];\n const dayNumber = Number(day);\n if (dayNumber < 1 || dayNumber > 31 || !MONTHS.has(month)) return null;\n const queue = Number(queueText);\n const pic = Number(picText);\n if (queue > MAX_QUEUE_NUMBER || !isInstructionCode(pic)) return null;\n return { pcc, date: `${day}${month}`, queue, pic };\n}\n","// Armado de `SeatAvailabilityByPayloadRq` de Get Seats desde un itinerario de BFM/Revalidate.\n// El mapeo está inferido: ver la tabla \"Armado del request desde el itinerario revalidado\" en\n// sabre-wiki/wiki/sdk/get-seats-en-el-sdk.md.\nimport { definedOnly } from '../config.js';\nimport type {\n SeatAvailabilityByPayloadRq,\n SeatFareComponent,\n SeatPassengerPayloadRq,\n SeatSegmentPayloadRq,\n} from './get-seats.js';\nimport type { FareComponent, Itinerary, ItineraryGroup } from './grouped-itinerary.js';\nimport { itineraryFlights } from './itinerary-flights.js';\n\nexport interface SeatAvailabilityRequestSource {\n /** Grupo del itinerario: aporta la fecha de cada tramo. */\n group: ItineraryGroup;\n /** Itinerario elegido, idealmente el devuelto por Revalidate Itinerary. */\n itinerary: Itinerary;\n /**\n * Números de los vuelos para los que se piden mapas, empezando en 1, igual que `segmentIndex`\n * de `buildBookingFlightDetails` (`1` es `S1`). Por defecto, todos.\n */\n segments?: number[];\n /** ISO 4217 para los precios de los asientos. Si falta, Sabre la elige. */\n currencyCode?: string;\n}\n\n/**\n * Arma el request de `sabre.air.getSeats` por payload para un itinerario ya revalidado.\n *\n * - `segments[]`: un segmento por vuelo, en el orden del itinerario, con `id` `S1`, `S2`, …\n * (`IdType` exige empezar por letra). Vuelo, fechas y clase con las mismas reglas que\n * `buildBookingFlightDetails`; horas en `HH:MM`. Si el operador o su número de vuelo difieren\n * del comercializador, van en `operatingAirlineCode` / `operatingFlightNumber`.\n * - `fareComponents[]`: uno por componente de tarifa (`FC` + su `id` en BFM), con `fareBasis`,\n * `governingCarrier` y `fareDetail`. `brandCode` no se manda: el itinerario no lo trae.\n * - `passengers[]`: `P1`, `P2`, … en el orden de `passengerInfoList`, repetidos según\n * `passengerNumber`. Coinciden con `travelerIndex` de Create Booking si `travelers[]` va en\n * el mismo orden. `fareSegmentAssociation` une cada segmento con su componente de tarifa.\n */\nexport function buildSeatAvailabilityRequest(source: SeatAvailabilityRequestSource): SeatAvailabilityByPayloadRq {\n const { group, itinerary, segments: only, currencyCode } = source;\n const flights = itineraryFlights(group, itinerary);\n\n const segments = flights.map(\n ({ schedule, departureDate, arrivalDate, bookingCode }, i): SeatSegmentPayloadRq => {\n const { carrier } = schedule;\n const operating =\n carrier.operating !== undefined &&\n (carrier.operating !== carrier.marketing ||\n (carrier.operatingFlightNumber !== undefined && carrier.operatingFlightNumber !== carrier.marketingFlightNumber));\n return {\n id: segmentId(i),\n bookingAirlineCode: carrier.marketing,\n bookingFlightNumber: carrier.marketingFlightNumber,\n departureAirportCode: schedule.departure.airport,\n arrivalAirportCode: schedule.arrival.airport,\n departureDate,\n departureTime: schedule.departure.time.slice(0, 5),\n arrivalDate,\n arrivalTime: schedule.arrival.time.slice(0, 5),\n bookingClassCode: bookingCode,\n ...(operating ? { operatingAirlineCode: carrier.operating! } : {}),\n ...(operating && carrier.operatingFlightNumber !== undefined\n ? { operatingFlightNumber: carrier.operatingFlightNumber }\n : {}),\n };\n },\n );\n\n const fare = itinerary.pricingInformation[0]?.fare;\n if (fare === undefined) {\n throw new TypeError('sabre-client: el itinerario no trae pricingInformation');\n }\n const fareComponents = new Map<string, SeatFareComponent>();\n const passengers: SeatPassengerPayloadRq[] = [];\n for (const { passengerInfo } of fare.passengerInfoList) {\n const fareSegmentAssociation: NonNullable<SeatPassengerPayloadRq['fareSegmentAssociation']> = [];\n let next = 0;\n for (const component of passengerInfo.fareComponents ?? []) {\n const fareComponentId = `FC${component.id}`;\n if (!fareComponents.has(fareComponentId)) fareComponents.set(fareComponentId, fareComponent(fareComponentId, component));\n for (const { segment } of component.segments ?? []) {\n const flight = segments[next];\n if (flight === undefined) break;\n if (flight.cabinCode === undefined && segment.cabinCode !== undefined) flight.cabinCode = segment.cabinCode;\n fareSegmentAssociation.push({ segmentRef: flight.id, fareComponentRef: fareComponentId });\n next++;\n }\n }\n for (let n = 0; n < (passengerInfo.passengerNumber ?? 1); n++) {\n passengers.push({\n id: `P${passengers.length + 1}`,\n passengerType: passengerInfo.passengerType,\n ...(fareSegmentAssociation.length === 0 ? {} : { fareSegmentAssociation }),\n });\n }\n }\n\n const refs = (only ?? segments.map((_s, i) => i + 1)).map((n) => {\n if (!Number.isInteger(n) || n < 1 || n > segments.length) {\n throw new TypeError(`sabre-client: segments pide el vuelo ${n}, y hay ${segments.length} (empieza en 1)`);\n }\n return segmentId(n - 1);\n });\n if (refs.length === 0) {\n throw new TypeError('sabre-client: segments no puede ir vacío');\n }\n\n return {\n returnSeatMapsOnlyForSegmentRefs: refs,\n segments,\n passengers,\n ...(fareComponents.size === 0 ? {} : { fareComponents: [...fareComponents.values()] }),\n ...(currencyCode === undefined ? {} : { currencyCode }),\n };\n}\n\nfunction segmentId(index: number): string {\n return `S${index + 1}`;\n}\n\nfunction fareComponent(fareComponentId: string, component: FareComponent): SeatFareComponent {\n const { fareBasisCode, governingCarrier, fareType, fareTariff, fareRule, fareTypeBitmap } = component;\n const fareDetail = definedOnly({ fareType, fareTariff, fareRule, fareTypeBitmap });\n return {\n fareComponentId,\n fareBasis: fareBasisCode,\n ...(governingCarrier === undefined ? {} : { governingCarrier }),\n ...(Object.keys(fareDetail).length === 0 ? {} : { fareDetail }),\n };\n}\n\n","export const VERSION = '0.6.0';\n\nexport { Sabre } from './sabre.js';\nexport { SabreLegacy } from './sabre-legacy.js';\nexport { buildCredentials } from './auth/credentials.js';\nexport type {\n BuildCredentialsOptions,\n BuildCredentialsOptionsV2,\n BuildCredentialsOptionsV3,\n BuiltCredentialsV2,\n BuiltCredentialsV3,\n} from './auth/credentials.js';\nexport type { OpenSessionOptions, SabreSession } from './session/session.js';\nexport type { SabreCommandOptions, SabreCommandResponse } from './session/command.js';\nexport type {\n QueueManagement,\n QueueProcessAction,\n QueueProcessRequest,\n QueueProcessResult,\n QueueState,\n} from './queue/queue-management.js';\nexport type {\n QueueAccessOptions,\n QueueAccessRequest,\n QueueEndReason,\n QueueItem,\n QueueMessage,\n QueueNavigationOptions,\n QueueRemoveRequest,\n QueueRemoveTarget,\n QueueSelection,\n QueueStep,\n} from './queue/queue-access.js';\nexport type {\n QueuePlacement,\n QueuePlaceOptions,\n QueuePlaceRequest,\n QueuePlaceResponse,\n QueuePlaceResult,\n QueuePlaceTarget,\n} from './queue/queue-place.js';\nexport type { QueueListEntry, QueueListOptions, QueueListRequest, QueueListResponse } from './queue/queue-list.js';\nexport { isMessageQueue, MESSAGE_QUEUE } from './queue/queue-ref.js';\nexport type { QueueRange, QueueRef } from './queue/queue-ref.js';\nexport type { QueueAdditionalInfo, QueueCount, QueueCountOptions, QueueCountRequest, QueueCountResponse } from './queue/queue-count.js';\nexport type { SessionReservation } from './reservation/session-reservation.js';\nexport type {\n ReservationHistoryAccounting,\n ReservationHistoryFlightSegment,\n ReservationHistoryOptions,\n ReservationHistoryResponse,\n ReservationHistoryText,\n ReservationHistoryTransaction,\n} from './reservation/reservation-history.js';\nexport type {\n QueueActivity,\n QueueActivityCounters,\n QueueActivityOptions,\n QueueActivityRequest,\n QueueActivityResponse,\n} from './queue/queue-activity.js';\nexport { resolveHostDate } from './queue/host-date.js';\nexport type { HostDateDirection, ResolveHostDateOptions } from './queue/host-date.js';\nexport { parseQueueParagraph } from './queue/queue-paragraph.js';\nexport { parseQueuePlaceRemark } from './queue/queue-place-remark.js';\nexport type { QueuePlaceRemark } from './queue/queue-place-remark.js';\nexport type {\n QueueParagraph,\n QueueParagraphAirSegment,\n QueueParagraphMessage,\n QueueParagraphOptions,\n QueueParagraphOtherSegment,\n QueueParagraphPassenger,\n QueueParagraphReceivedFrom,\n QueueParagraphSegment,\n QueueParagraphTicketing,\n QueueParagraphTicketingEntry,\n} from './queue/queue-paragraph.js';\nexport type { Air } from './air/air.js';\nexport type {\n BargainFinderMaxRequest,\n BargainFinderMaxResponse,\n RequestOptions,\n} from './air/bargain-finder-max.js';\nexport type {\n GetSeatsRequest,\n GetSeatsResponse,\n RawSeatAvailabilityRs,\n Seat,\n SeatAvailabilityByPayloadRq,\n SeatAvailabilityByPnrLocatorRq,\n SeatAvailabilityIssue,\n SeatAvailabilityResponse,\n SeatCabinCompartment,\n SeatCabinFacility,\n SeatCabinAisle,\n SeatCabinLayout,\n SeatCabinRowPosition,\n SeatCharacteristic,\n SeatDisplayOnlyItem,\n SeatFareComponent,\n SeatFareDetail,\n SeatFareSegmentAssociation,\n SeatFlightLeg,\n SeatKeyValuePair,\n SeatLoyaltyProgramAccount,\n SeatMap,\n SeatOfferItem,\n SeatOfferItemDetails,\n SeatPassenger,\n SeatPassengerPayloadRq,\n SeatPassengerRs,\n SeatPriceBreakdown,\n SeatPriceDefinition,\n SeatRow,\n SeatSegment,\n SeatSegmentPayloadRq,\n SeatSegmentRs,\n SeatServiceDefinition,\n SeatSpecialServiceRequest,\n SeatTax,\n} from './air/get-seats.js';\nexport { buildSeatAvailabilityRequest } from './air/seat-availability-request.js';\nexport type { SeatAvailabilityRequestSource } from './air/seat-availability-request.js';\nexport { buildRevalidateItineraryRequest } from './air/revalidate-itinerary.js';\nexport type {\n RevalidateItineraryRequest,\n RevalidateItineraryRequestSource,\n RevalidateItineraryResponse,\n} from './air/revalidate-itinerary.js';\nexport type {\n LowFareSearchFlight,\n LowFareSearchLocation,\n LowFareSearchOriginDestination,\n LowFareSearchPassengerTypeQuantity,\n LowFareSearchRequestorId,\n LowFareSearchSource,\n LowFareSearchTpaExtensions,\n LowFareSearchTravelerInfoSummary,\n LowFareSearchTravelPreferences,\n OtaAirLowFareSearchRq,\n} from './air/low-fare-search-request.js';\nexport type { SabreTokenStore, StoredToken } from './auth/token-store.js';\nexport type { BookingManagement } from './booking/booking-management.js';\nexport type {\n Booking,\n CreateBookingOptions,\n CreateBookingResponse,\n CreateBookingResponseError,\n} from './booking/create-booking.js';\nexport type {\n BookContactInformation,\n BookGenericSeat,\n BookingAgency,\n BookSeat,\n BookTraveler,\n BrandedFare,\n CreateBookingErrorPolicy,\n CreateBookingRequest,\n FlightDetails,\n FlightStatusCode,\n FlightToBook,\n PassengerPricing,\n PaymentMethod,\n PriceComparison,\n PriceComparisonType,\n PricingDetails,\n PricingQualifiers,\n SeatAreaPreference,\n SpecificFare,\n TicketingPolicy,\n TravelerPhone,\n TravelerTitle,\n} from './booking/create-booking-request.js';\nexport type {\n BookingSource,\n GetBookingExtraFeatures,\n GetBookingOptions,\n GetBookingRequest,\n GetBookingResponse,\n GetBookingReturnOnly,\n} from './booking/get-booking.js';\nexport type {\n BookingItemReference,\n CancelBookingErrorPolicy,\n CancelBookingNotification,\n CancelBookingOptions,\n CancelBookingRequest,\n CancelBookingResponse,\n CancelSegmentReference,\n FlightTicketOperation,\n RefundDocumentsType,\n} from './booking/cancel-booking.js';\nexport type { BookingResponseError } from './booking/booking-errors.js';\nexport { buildBookingFlightDetails } from './booking/flight-details.js';\nexport type { BookingFlightDetailsSource, BookingSeatSelection, PricedSeat } from './booking/flight-details.js';\nexport type {\n SabreAuthVersion,\n SabreConfig,\n SabreConfigV2,\n SabreConfigFromCredentials,\n SabreConfigV2FromCredentials,\n SabreConfigV3,\n SabreCredentials,\n SabreCredentialsAnyVersion,\n SabreCredentialsV2,\n SabreEnvironment,\n} from './config.js';\nexport type { RetryOptions } from './http/retry.js';\nexport type { SabreRawRequest, SabreRawRequestCallback } from './http/raw-request.js';\nexport type { SabreRawResponse, SabreRawResponseCallback } from './http/raw-response.js';\nexport * from './errors/index.js';\nexport * from './logging/index.js';\nexport type {\n BaggageAllowanceDesc,\n BaggageInformation,\n CurrencyConversion,\n Fare,\n FareComponent,\n FareComponentDesc,\n FareComponentDescSegment,\n FareComponentSegment,\n FareComponentSegmentDetail,\n FareMessage,\n GroupedItineraryResponse,\n Itinerary,\n ItineraryGroup,\n ItineraryMessage,\n Leg,\n LegDesc,\n LegSchedule,\n LegScheduleRef,\n LegDescription,\n ObFeeDesc,\n PassengerInfo,\n PassengerTotalFare,\n PricingInformation,\n Ref,\n ScheduleCarrier,\n ScheduleDesc,\n ScheduleEndpoint,\n ScheduleEquipment,\n TaxDesc,\n TaxSummaryDesc,\n TotalFare,\n ValidatingCarrierDesc,\n} from './air/grouped-itinerary.js';\n// Tipos completos de `Booking` (spec v1.33, #158).\nexport type * from './booking/booking-types.js';\n"],"mappings":"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","names":["isObject","isObject","PATH","PATH","isObject","flight","PATH","flight","isObject","warningOf","PATH","isObject","errorOf","warningOf","isObject","isAbort","describe","node","nonEmpty","root","fail","XMLParser","fail","XMLParser","NAMESPACE","attribute","node","nonEmpty","identifier","element","NAMESPACE","NAMESPACE","attribute","node","nonEmpty","identifier","malformed","element","NAMESPACE","identifier","fail","send","NAMESPACE","node","attribute","malformed","NAMESPACE","fail","fail","fail","requireString","month","number","date","status","quantity","MONTHS","dayNumber","flight"]}