@voyantjs/flights 0.55.1 → 0.57.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/README.md +16 -2
- package/dist/contract/adapter.d.ts +41 -3
- package/dist/contract/adapter.d.ts.map +1 -1
- package/dist/contract/adapter.test.d.ts +2 -0
- package/dist/contract/adapter.test.d.ts.map +1 -0
- package/dist/contract/adapter.test.js +171 -0
- package/dist/contract/post-book-types.d.ts +90 -0
- package/dist/contract/post-book-types.d.ts.map +1 -0
- package/dist/contract/post-book-types.js +1 -0
- package/dist/contract/schemas.d.ts +3896 -0
- package/dist/contract/schemas.d.ts.map +1 -0
- package/dist/contract/schemas.js +508 -0
- package/dist/contract/schemas.test.d.ts +2 -0
- package/dist/contract/schemas.test.d.ts.map +1 -0
- package/dist/contract/schemas.test.js +359 -0
- package/dist/contract/types.d.ts +1 -0
- package/dist/contract/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/orchestration/fan-out.test.js +35 -1
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -23,8 +23,13 @@ pnpm add @voyantjs/flights
|
|
|
23
23
|
discriminated union. Shapes mirror voyant-cloud's `connect-flight-contract`
|
|
24
24
|
so adapters are portable across `voyant-cloud` and Voyant Catalog.
|
|
25
25
|
- **`./contract/adapter`** — `FlightConnectorAdapter` interface (5 core methods
|
|
26
|
-
+ capability
|
|
27
|
-
|
|
26
|
+
+ optional capability-gated methods for holds, seat maps, post-book seat
|
|
27
|
+
selection, check-in, exchange, refund, void, SSR, ancillaries, and order
|
|
28
|
+
listing). Provider-agnostic; implementations come from Voyant Connect,
|
|
29
|
+
third-party providers, or operator-built adapters.
|
|
30
|
+
- **`./contract/schemas`** — zod schemas for the public flight contract
|
|
31
|
+
request, response, enum, and value-object shapes. Use these at HTTP, queue,
|
|
32
|
+
RPC, and adapter boundaries instead of re-declaring runtime validators.
|
|
28
33
|
- **`./orchestration/fingerprint`** — Itinerary fingerprint helper. Two
|
|
29
34
|
providers selling the same flight produce identical fingerprints.
|
|
30
35
|
- **`./orchestration/fan-out`** — Multi-connection fan-out search:
|
|
@@ -84,6 +89,15 @@ const result = await fanOutFlightSearch({
|
|
|
84
89
|
// result.perConnection — status + latency per connection.
|
|
85
90
|
```
|
|
86
91
|
|
|
92
|
+
### Runtime validation
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { flightBookRequestSchema } from "@voyantjs/flights/contract/schemas"
|
|
96
|
+
import type { FlightBookRequest } from "@voyantjs/flights/contract/types"
|
|
97
|
+
|
|
98
|
+
const request: FlightBookRequest = flightBookRequestSchema.parse(await req.json())
|
|
99
|
+
```
|
|
100
|
+
|
|
87
101
|
### Reference data — operator's own Postgres tables
|
|
88
102
|
|
|
89
103
|
```typescript
|
|
@@ -12,10 +12,18 @@
|
|
|
12
12
|
*
|
|
13
13
|
* See `docs/architecture/catalog-flights-architecture.md` §3.
|
|
14
14
|
*/
|
|
15
|
-
import type { AncillaryRequest, AncillaryResponse, FlightBookRequest, FlightCapability, FlightOffer, FlightOrder, FlightOrderStatus, FlightSearchPaginationMeta, FlightSearchRequest, SeatMapRequest, SeatMapResponse } from "./types.js";
|
|
15
|
+
import type { AncillaryRequest, AncillaryResponse, CheckInRequest, CheckInResponse, FlightBookRequest, FlightCapability, FlightModifyRequest, FlightModifyResponse, FlightOffer, FlightOrder, FlightOrderStatus, FlightRefundRequest, FlightRefundResponse, FlightSearchPaginationMeta, FlightSearchRequest, FlightVoidResponse, SeatMapRequest, SeatMapResponse, SeatSelectionRequest, SeatSelectionResponse, SsrRequest, SsrResponse } from "./types.js";
|
|
16
|
+
export interface AdapterLogger {
|
|
17
|
+
debug(message: string, meta?: Record<string, unknown>): void;
|
|
18
|
+
info(message: string, meta?: Record<string, unknown>): void;
|
|
19
|
+
warn(message: string, meta?: Record<string, unknown>): void;
|
|
20
|
+
error(message: string, meta?: Record<string, unknown>): void;
|
|
21
|
+
}
|
|
22
|
+
export type FlightAdapterEnvironment = "sandbox" | "production";
|
|
16
23
|
/**
|
|
17
24
|
* Context passed to every adapter call. Identifies the connection and
|
|
18
|
-
* carries credentials, optional point-of-sale, tracing identifiers
|
|
25
|
+
* carries credentials, optional point-of-sale, tracing identifiers,
|
|
26
|
+
* cancellation, idempotency, logging, and environment selection signals.
|
|
19
27
|
*
|
|
20
28
|
* `deps` is an escape hatch for adapter-specific runtime dependencies that
|
|
21
29
|
* shouldn't bleed into the contract — e.g. a Postgres handle for a demo
|
|
@@ -27,7 +35,18 @@ export interface FlightAdapterContext {
|
|
|
27
35
|
credentials?: Record<string, string>;
|
|
28
36
|
/** Operator's IATA office id / pseudo-city / point-of-sale, when applicable. */
|
|
29
37
|
pointOfSale?: string;
|
|
38
|
+
/** Upstream trace id, usually propagated from the caller. */
|
|
30
39
|
correlationId?: string;
|
|
40
|
+
/** Per-call request id for adapter-local tracing. */
|
|
41
|
+
requestId?: string;
|
|
42
|
+
/** Idempotency key for replay-safe writes: book, modify, refund, void. */
|
|
43
|
+
idempotencyKey?: string;
|
|
44
|
+
/** Adapter-scoped logger with provider/connection/request metadata bound in. */
|
|
45
|
+
logger?: AdapterLogger;
|
|
46
|
+
/** Cancellation signal propagated from the orchestration layer. */
|
|
47
|
+
signal?: AbortSignal;
|
|
48
|
+
/** Selects the supplier environment when the adapter supports both. */
|
|
49
|
+
environment?: FlightAdapterEnvironment;
|
|
31
50
|
deps?: Record<string, unknown>;
|
|
32
51
|
}
|
|
33
52
|
export interface FlightSearchResponse {
|
|
@@ -113,7 +132,14 @@ export interface FlightConnectorAdapter {
|
|
|
113
132
|
readonly capabilities: FlightAdapterCapabilities;
|
|
114
133
|
/** Search flights matching the request's slices + passengers + cabin. */
|
|
115
134
|
searchFlights(ctx: FlightAdapterContext, request: FlightSearchRequest): Promise<FlightSearchResponse>;
|
|
116
|
-
/**
|
|
135
|
+
/**
|
|
136
|
+
* Re-price an offer immediately before booking.
|
|
137
|
+
*
|
|
138
|
+
* This is also the canonical re-quote path for offers approaching
|
|
139
|
+
* `FlightOffer.expiresAt` or `lastTicketingDate`. Callers should invoke it
|
|
140
|
+
* before booking whenever the offer is older than the provider's freshness
|
|
141
|
+
* window or the UI is resuming a saved/held offer.
|
|
142
|
+
*/
|
|
117
143
|
priceOffer(ctx: FlightAdapterContext, request: FlightPriceRequest): Promise<FlightPriceResponse>;
|
|
118
144
|
/**
|
|
119
145
|
* Book the flight. Behavior depends on `paymentIntent`:
|
|
@@ -150,6 +176,18 @@ export interface FlightConnectorAdapter {
|
|
|
150
176
|
* are submitted at book time via `FlightBookRequest.ancillaries.seats`.
|
|
151
177
|
*/
|
|
152
178
|
getSeatMap?(ctx: FlightAdapterContext, request: SeatMapRequest): Promise<SeatMapResponse>;
|
|
179
|
+
/** `flight/seat-selection` — change/add seat selections on an existing order. */
|
|
180
|
+
selectSeats?(ctx: FlightAdapterContext, request: SeatSelectionRequest): Promise<SeatSelectionResponse>;
|
|
181
|
+
/** `flight/checkin` — initiate or complete online check-in for passengers. */
|
|
182
|
+
checkIn?(ctx: FlightAdapterContext, request: CheckInRequest): Promise<CheckInResponse>;
|
|
183
|
+
/** `flight/exchange` — change an existing order's itinerary, fare, pax, or extras. */
|
|
184
|
+
modifyOrder?(ctx: FlightAdapterContext, request: FlightModifyRequest): Promise<FlightModifyResponse>;
|
|
185
|
+
/** `flight/refund` — refund a ticketed order after the ticketing/void window. */
|
|
186
|
+
refundOrder?(ctx: FlightAdapterContext, request: FlightRefundRequest): Promise<FlightRefundResponse>;
|
|
187
|
+
/** `flight/void` — void a ticketed order inside the supplier void window. */
|
|
188
|
+
voidOrder?(ctx: FlightAdapterContext, orderId: string): Promise<FlightVoidResponse>;
|
|
189
|
+
/** `flight/ssr` — add a special service request such as wheelchair, meal, or UMNR. */
|
|
190
|
+
addSpecialServiceRequest?(ctx: FlightAdapterContext, request: SsrRequest): Promise<SsrResponse>;
|
|
153
191
|
}
|
|
154
192
|
/**
|
|
155
193
|
* Standard error code for capability-gated methods that aren't supported
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/contract/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,0BAA0B,EAC1B,mBAAmB,EACnB,cAAc,EACd,eAAe,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/contract/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.test.d.ts","sourceRoot":"","sources":["../../src/contract/adapter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { FlightCapabilityNotSupportedError, requireCapability, } from "./adapter.js";
|
|
3
|
+
import { FLIGHT_CAPABILITIES } from "./types.js";
|
|
4
|
+
const offer = {
|
|
5
|
+
offerId: "offer_1",
|
|
6
|
+
source: "test",
|
|
7
|
+
itineraries: [
|
|
8
|
+
{
|
|
9
|
+
segments: [
|
|
10
|
+
{
|
|
11
|
+
segmentId: "seg_1",
|
|
12
|
+
carrierCode: "BA",
|
|
13
|
+
flightNumber: "177",
|
|
14
|
+
departure: { iataCode: "LHR", at: "2026-10-15T11:00:00+00:00" },
|
|
15
|
+
arrival: { iataCode: "JFK", at: "2026-10-15T14:00:00-04:00" },
|
|
16
|
+
cabin: "economy",
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
fareBreakdowns: [
|
|
22
|
+
{
|
|
23
|
+
passengerType: "adult",
|
|
24
|
+
passengerCount: 1,
|
|
25
|
+
baseFare: { amount: "500.00", currency: "USD" },
|
|
26
|
+
taxes: { amount: "100.00", currency: "USD" },
|
|
27
|
+
total: { amount: "600.00", currency: "USD" },
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
totalPrice: { amount: "600.00", currency: "USD" },
|
|
31
|
+
};
|
|
32
|
+
const order = {
|
|
33
|
+
orderId: "order_1",
|
|
34
|
+
pnr: "ABC123",
|
|
35
|
+
status: "ticketed",
|
|
36
|
+
offer,
|
|
37
|
+
passengers: [
|
|
38
|
+
{
|
|
39
|
+
passengerId: "pax_1",
|
|
40
|
+
type: "adult",
|
|
41
|
+
firstName: "Ada",
|
|
42
|
+
lastName: "Lovelace",
|
|
43
|
+
dateOfBirth: "1980-01-01",
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
totalPrice: offer.totalPrice,
|
|
47
|
+
createdAt: "2026-10-01T10:00:00Z",
|
|
48
|
+
};
|
|
49
|
+
function makeCoreAdapter() {
|
|
50
|
+
return {
|
|
51
|
+
capabilities: { provider: "core", declared: [] },
|
|
52
|
+
async searchFlights() {
|
|
53
|
+
return { offers: [offer] };
|
|
54
|
+
},
|
|
55
|
+
async priceOffer() {
|
|
56
|
+
return { offer, valid: true };
|
|
57
|
+
},
|
|
58
|
+
async bookFlight() {
|
|
59
|
+
return { order };
|
|
60
|
+
},
|
|
61
|
+
async getOrder() {
|
|
62
|
+
return { order };
|
|
63
|
+
},
|
|
64
|
+
async cancelOrder() {
|
|
65
|
+
return { order: { ...order, status: "cancelled" } };
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
describe("FlightConnectorAdapter contract", () => {
|
|
70
|
+
it("allows core-only adapters to omit every optional capability method", async () => {
|
|
71
|
+
const adapter = makeCoreAdapter();
|
|
72
|
+
await expect(adapter.searchFlights({ connectionId: "conn" }, {})).resolves.toEqual({
|
|
73
|
+
offers: [offer],
|
|
74
|
+
});
|
|
75
|
+
expect(adapter.selectSeats).toBeUndefined();
|
|
76
|
+
expect(adapter.checkIn).toBeUndefined();
|
|
77
|
+
expect(adapter.modifyOrder).toBeUndefined();
|
|
78
|
+
expect(adapter.refundOrder).toBeUndefined();
|
|
79
|
+
expect(adapter.voidOrder).toBeUndefined();
|
|
80
|
+
expect(adapter.addSpecialServiceRequest).toBeUndefined();
|
|
81
|
+
});
|
|
82
|
+
it("allows adapters to implement every declared capability method", async () => {
|
|
83
|
+
const adapter = {
|
|
84
|
+
...makeCoreAdapter(),
|
|
85
|
+
capabilities: {
|
|
86
|
+
provider: "full",
|
|
87
|
+
declared: Object.values(FLIGHT_CAPABILITIES),
|
|
88
|
+
},
|
|
89
|
+
async listOrders() {
|
|
90
|
+
return { orders: [order], pagination: { total: 1, hasMore: false } };
|
|
91
|
+
},
|
|
92
|
+
async ticketOrder() {
|
|
93
|
+
return { order };
|
|
94
|
+
},
|
|
95
|
+
async getAncillaries() {
|
|
96
|
+
return { catalog: { baggage: [], assistance: [], extras: [] } };
|
|
97
|
+
},
|
|
98
|
+
async getSeatMap() {
|
|
99
|
+
return {
|
|
100
|
+
seatMap: {
|
|
101
|
+
segmentId: "seg_1",
|
|
102
|
+
cabin: "economy",
|
|
103
|
+
columnLayout: ["A", "B", "C", null, "D", "E", "F"],
|
|
104
|
+
rows: [],
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
async selectSeats(_ctx, request) {
|
|
109
|
+
return { order, selections: request.selections };
|
|
110
|
+
},
|
|
111
|
+
async checkIn() {
|
|
112
|
+
return { order, status: "checked_in", boardingPasses: [] };
|
|
113
|
+
},
|
|
114
|
+
async modifyOrder() {
|
|
115
|
+
return { order, priceDifference: { amount: "0.00", currency: "USD" } };
|
|
116
|
+
},
|
|
117
|
+
async refundOrder() {
|
|
118
|
+
return { order: { ...order, status: "cancelled" }, refundedAmount: order.totalPrice };
|
|
119
|
+
},
|
|
120
|
+
async voidOrder() {
|
|
121
|
+
return { order: { ...order, status: "cancelled" }, voidedAt: "2026-10-01T11:00:00Z" };
|
|
122
|
+
},
|
|
123
|
+
async addSpecialServiceRequest() {
|
|
124
|
+
return { order, status: "requested" };
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
await expect(adapter.selectSeats?.({ connectionId: "conn" }, { orderId: order.orderId, selections: [] })).resolves.toEqual({ order, selections: [] });
|
|
128
|
+
await expect(adapter.refundOrder?.({ connectionId: "conn" }, { orderId: order.orderId })).resolves.toEqual({
|
|
129
|
+
order: { ...order, status: "cancelled" },
|
|
130
|
+
refundedAmount: order.totalPrice,
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
it("types the new adapter context fields as optional runtime signals", () => {
|
|
134
|
+
const controller = new AbortController();
|
|
135
|
+
const loggerMessages = [];
|
|
136
|
+
const context = {
|
|
137
|
+
connectionId: "conn",
|
|
138
|
+
requestId: "req_1",
|
|
139
|
+
correlationId: "corr_1",
|
|
140
|
+
idempotencyKey: "idem_1",
|
|
141
|
+
environment: "sandbox",
|
|
142
|
+
signal: controller.signal,
|
|
143
|
+
logger: {
|
|
144
|
+
debug: (message) => loggerMessages.push(message),
|
|
145
|
+
info: (message) => loggerMessages.push(message),
|
|
146
|
+
warn: (message) => loggerMessages.push(message),
|
|
147
|
+
error: (message) => loggerMessages.push(message),
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
context.logger?.info("context ready");
|
|
151
|
+
expect(context.requestId).toBe("req_1");
|
|
152
|
+
expect(context.signal).toBe(controller.signal);
|
|
153
|
+
expect(loggerMessages).toEqual(["context ready"]);
|
|
154
|
+
});
|
|
155
|
+
it.each([
|
|
156
|
+
[FLIGHT_CAPABILITIES.SEAT_SELECTION, "selectSeats"],
|
|
157
|
+
[FLIGHT_CAPABILITIES.CHECKIN, "checkIn"],
|
|
158
|
+
[FLIGHT_CAPABILITIES.EXCHANGE, "modifyOrder"],
|
|
159
|
+
[FLIGHT_CAPABILITIES.REFUND, "refundOrder"],
|
|
160
|
+
[FLIGHT_CAPABILITIES.VOID, "voidOrder"],
|
|
161
|
+
[FLIGHT_CAPABILITIES.SSR, "addSpecialServiceRequest"],
|
|
162
|
+
])("throws the standard not-supported error for %s", (capability, operation) => {
|
|
163
|
+
expect(() => requireCapability({ provider: "core", declared: [] }, capability, operation)).toThrow(FlightCapabilityNotSupportedError);
|
|
164
|
+
try {
|
|
165
|
+
requireCapability({ provider: "core", declared: [] }, capability, operation);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
expect(error).toMatchObject({ provider: "core", capability, operation });
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { AncillarySelection, FlightOffer, FlightOrder, FlightPassenger, Money } from "./types.js";
|
|
2
|
+
export interface SeatAssignment {
|
|
3
|
+
passengerId: string;
|
|
4
|
+
segmentId: string;
|
|
5
|
+
seatNumber: string;
|
|
6
|
+
/** Per-pax seat fee. Omitted = included in fare or already paid. */
|
|
7
|
+
price?: Money;
|
|
8
|
+
/** Provider-specific data — opaque round-trip. */
|
|
9
|
+
providerData?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
export interface SeatSelectionRequest {
|
|
12
|
+
orderId: string;
|
|
13
|
+
selections: SeatAssignment[];
|
|
14
|
+
}
|
|
15
|
+
export interface SeatSelectionResponse {
|
|
16
|
+
order: FlightOrder;
|
|
17
|
+
selections: SeatAssignment[];
|
|
18
|
+
/** Total additional charge collected for the seat change, if any. */
|
|
19
|
+
additionalAmount?: Money;
|
|
20
|
+
}
|
|
21
|
+
export type CheckInStatus = "initiated" | "checked_in" | "failed";
|
|
22
|
+
export interface CheckInRequest {
|
|
23
|
+
orderId: string;
|
|
24
|
+
passengerIds?: string[];
|
|
25
|
+
segmentIds?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface FlightBoardingPass {
|
|
28
|
+
passengerId: string;
|
|
29
|
+
segmentId: string;
|
|
30
|
+
boardingPassId?: string;
|
|
31
|
+
seatNumber?: string;
|
|
32
|
+
sequenceNumber?: string;
|
|
33
|
+
zone?: string;
|
|
34
|
+
/** Provider-specific data — opaque round-trip. */
|
|
35
|
+
providerData?: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
export interface CheckInResponse {
|
|
38
|
+
order: FlightOrder;
|
|
39
|
+
status: CheckInStatus;
|
|
40
|
+
boardingPasses?: FlightBoardingPass[];
|
|
41
|
+
}
|
|
42
|
+
export type FlightModifyReason = "customer_request" | "schedule_change" | "name_correction" | "disruption" | "operational";
|
|
43
|
+
export interface FlightModifyRequest {
|
|
44
|
+
orderId: string;
|
|
45
|
+
/** Re-priced replacement offer when the modification changes itinerary/fare. */
|
|
46
|
+
offer?: FlightOffer;
|
|
47
|
+
/** Replacement passenger details for corrections allowed by the provider. */
|
|
48
|
+
passengers?: FlightPassenger[];
|
|
49
|
+
/** Add or replace ancillary picks as part of the modification. */
|
|
50
|
+
ancillaries?: AncillarySelection;
|
|
51
|
+
reason?: FlightModifyReason;
|
|
52
|
+
}
|
|
53
|
+
export interface FlightModifyResponse {
|
|
54
|
+
order: FlightOrder;
|
|
55
|
+
/** Positive means collect more from the traveler; negative means credit due. */
|
|
56
|
+
priceDifference?: Money;
|
|
57
|
+
penalties?: Money[];
|
|
58
|
+
}
|
|
59
|
+
export type FlightRefundReason = "customer_request" | "schedule_change" | "disruption" | "duplicate_booking" | "medical" | "other";
|
|
60
|
+
export interface FlightRefundRequest {
|
|
61
|
+
orderId: string;
|
|
62
|
+
reason?: FlightRefundReason;
|
|
63
|
+
/** Omit for a full refund; provide for supplier-supported partial refunds. */
|
|
64
|
+
amount?: Money;
|
|
65
|
+
}
|
|
66
|
+
export interface FlightRefundResponse {
|
|
67
|
+
order: FlightOrder;
|
|
68
|
+
refundId?: string;
|
|
69
|
+
refundedAmount: Money;
|
|
70
|
+
penalties?: Money[];
|
|
71
|
+
}
|
|
72
|
+
export interface FlightVoidResponse {
|
|
73
|
+
order: FlightOrder;
|
|
74
|
+
voidId?: string;
|
|
75
|
+
voidedAt: string;
|
|
76
|
+
}
|
|
77
|
+
export type SsrCode = "WCHR" | "WCHS" | "WCHC" | "BLND" | "DEAF" | "MAAS" | "UMNR" | "INFT" | "PETC" | "VGML" | "KSML" | "MOML" | "OTHER";
|
|
78
|
+
export interface SsrRequest {
|
|
79
|
+
orderId: string;
|
|
80
|
+
code: SsrCode;
|
|
81
|
+
passengerIds?: string[];
|
|
82
|
+
segmentIds?: string[];
|
|
83
|
+
text?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface SsrResponse {
|
|
86
|
+
order: FlightOrder;
|
|
87
|
+
ssrId?: string;
|
|
88
|
+
status: "requested" | "confirmed" | "rejected";
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=post-book-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-book-types.d.ts","sourceRoot":"","sources":["../../src/contract/post-book-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|