@voyant-travel/flights 0.137.0 → 0.137.2
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/contract/schemas.test.js +2 -1
- package/dist/hono.d.ts +6 -3
- package/dist/hono.d.ts.map +1 -1
- package/dist/hono.js +30 -10
- package/dist/hono.test.js +243 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/payment-integration.d.ts +7 -1
- package/dist/payment-integration.d.ts.map +1 -1
- package/dist/payment-integration.js +4 -2
- package/dist/payment-integration.test.js +14 -0
- package/package.json +10 -10
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// agent-quality: file-size exception -- owner: flights; existing coverage file stays co-located until a dedicated split preserves behavior and tests.
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { ancillaryRequestSchema, ancillaryResponseSchema, checkInRequestSchema, checkInResponseSchema, flightAdapterCapabilitiesSchema, flightAdapterContextSchema, flightBookRequestSchema, flightBookResponseSchema, flightCancelResponseSchema, flightGetOrderResponseSchema, flightModifyRequestSchema, flightModifyResponseSchema, flightOrdersListQuerySchema, flightOrdersListResponseSchema, flightPriceRequestSchema, flightPriceResponseSchema, flightRefundRequestSchema, flightRefundResponseSchema, flightSearchRequestSchema, flightSearchResponseSchema, flightVoidResponseSchema, moneySchema, seatMapRequestSchema, seatMapResponseSchema, seatSelectionRequestSchema, seatSelectionResponseSchema, ssrRequestSchema, ssrResponseSchema, } from "./schemas.js";
|
|
3
|
+
import { ancillaryRequestSchema, ancillaryResponseSchema, checkInRequestSchema, checkInResponseSchema, flightAdapterCapabilitiesSchema, flightAdapterContextSchema, flightBookRequestSchema, flightBookResponseSchema, flightCancelResponseSchema, flightGetOrderResponseSchema, flightModifyRequestSchema, flightModifyResponseSchema, flightOrdersListQuerySchema, flightOrdersListResponseSchema, flightPriceRequestSchema, flightPriceResponseSchema, flightRefundRequestSchema, flightRefundResponseSchema, flightSearchRequestSchema, flightSearchResponseSchema, flightVoidResponseSchema, moneySchema, paymentIntentSchema, seatMapRequestSchema, seatMapResponseSchema, seatSelectionRequestSchema, seatSelectionResponseSchema, ssrRequestSchema, ssrResponseSchema, } from "./schemas.js";
|
|
4
4
|
const typeChecks = [
|
|
5
5
|
true,
|
|
6
6
|
true,
|
|
@@ -164,6 +164,7 @@ const roundTripCases = [
|
|
|
164
164
|
["flightSearchResponseSchema", flightSearchResponseSchema, { offers: [offer] }],
|
|
165
165
|
["flightPriceRequestSchema", flightPriceRequestSchema, { offerId: "offer_1", offer }],
|
|
166
166
|
["flightPriceResponseSchema", flightPriceResponseSchema, { offer, valid: true }],
|
|
167
|
+
["paymentIntentSchema", paymentIntentSchema, { type: "bank_transfer" }],
|
|
167
168
|
[
|
|
168
169
|
"flightBookRequestSchema",
|
|
169
170
|
flightBookRequestSchema,
|
package/dist/hono.d.ts
CHANGED
|
@@ -2,21 +2,24 @@ import type { HonoModule } from "@voyant-travel/hono";
|
|
|
2
2
|
import { type Context, Hono } from "hono";
|
|
3
3
|
import type { FlightConnectorAdapter } from "./contract/adapter.js";
|
|
4
4
|
import type { FlightOrder } from "./contract/types.js";
|
|
5
|
-
/** A resolved payment session for a flight
|
|
5
|
+
/** A resolved payment session for a flight order. */
|
|
6
6
|
export interface FlightOrderPaymentSummary {
|
|
7
7
|
sessionId: string;
|
|
8
8
|
status: string;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* Deployment-supplied payment integration for flight
|
|
11
|
+
* Deployment-supplied payment integration for flight orders. The flights
|
|
12
12
|
* module stays payment-provider agnostic; the deployment wires its finance /
|
|
13
13
|
* payment provider here.
|
|
14
14
|
*/
|
|
15
15
|
export interface FlightPaymentIntegration {
|
|
16
|
-
/** Ensure (idempotently) a payment session exists for
|
|
16
|
+
/** Ensure (idempotently) a payment session exists for an order. */
|
|
17
17
|
ensureOrderSession(c: Context, order: FlightOrder, contact?: {
|
|
18
18
|
email?: string;
|
|
19
19
|
phone?: string;
|
|
20
|
+
}, options?: {
|
|
21
|
+
paymentMethod?: "bank_transfer" | "credit_card";
|
|
22
|
+
startCardPayment?: boolean;
|
|
20
23
|
}): Promise<FlightOrderPaymentSummary | null>;
|
|
21
24
|
/** Bulk-resolve the most relevant payment session per order id (no N+1). */
|
|
22
25
|
fetchOrderSessions(c: Context, orderIds: string[]): Promise<Map<string, FlightOrderPaymentSummary>>;
|
package/dist/hono.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEzC,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAGV,WAAW,
|
|
1
|
+
{"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEzC,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAGV,WAAW,EAKZ,MAAM,qBAAqB,CAAA;AAO5B,qDAAqD;AACrD,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,mEAAmE;IACnE,kBAAkB,CAChB,CAAC,EAAE,OAAO,EACV,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAC5C,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,eAAe,GAAG,aAAa,CAAC;QAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,GACxF,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAA;IAC5C,4EAA4E;IAC5E,kBAAkB,CAChB,CAAC,EAAE,OAAO,EACV,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAA;CACnD;AAED,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,sBAAsB,CAAA;IAClD,yDAAyD;IACzD,OAAO,CAAC,EAAE,wBAAwB,CAAA;CACnC;AAED,MAAM,MAAM,wBAAwB,GAAG,mBAAmB,CAAA;AAoD1D,oFAAoF;AACpF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CA+O1E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,UAAU,CAKrF"}
|
package/dist/hono.js
CHANGED
|
@@ -24,6 +24,25 @@ function attachPaymentSession(order, summary) {
|
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
function statusForAdapterErrorMessage(message) {
|
|
28
|
+
return /(?:not found|_not_found\b)/i.test(message) ? 404 : 500;
|
|
29
|
+
}
|
|
30
|
+
function paymentSessionOptionsForIntent(intent) {
|
|
31
|
+
if (!intent || intent.type === "hold")
|
|
32
|
+
return { startCardPayment: true };
|
|
33
|
+
if (intent.type === "bank_transfer") {
|
|
34
|
+
return { paymentMethod: "bank_transfer", startCardPayment: false };
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function adapterBookingRequestForIntent(body) {
|
|
39
|
+
if (body.paymentIntent?.type !== "bank_transfer")
|
|
40
|
+
return body;
|
|
41
|
+
return {
|
|
42
|
+
...body,
|
|
43
|
+
paymentIntent: { type: "hold" },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
27
46
|
/** Build the flight admin routes (relative paths; mount at `/v1/admin/flights`). */
|
|
28
47
|
export function createFlightAdminRoutes(options) {
|
|
29
48
|
const { resolveAdapter, payment } = options;
|
|
@@ -96,7 +115,7 @@ export function createFlightAdminRoutes(options) {
|
|
|
96
115
|
}
|
|
97
116
|
catch (err) {
|
|
98
117
|
const message = err instanceof Error ? err.message : String(err);
|
|
99
|
-
return c.json({ error: message },
|
|
118
|
+
return c.json({ error: message }, statusForAdapterErrorMessage(message));
|
|
100
119
|
}
|
|
101
120
|
});
|
|
102
121
|
// ── Re-price ────────────────────────────────────────────────────────────
|
|
@@ -132,12 +151,12 @@ export function createFlightAdminRoutes(options) {
|
|
|
132
151
|
if (!body.passengers?.length)
|
|
133
152
|
return c.json({ error: "passengers is required" }, 400);
|
|
134
153
|
try {
|
|
135
|
-
const response = await resolveAdapter(c).bookFlight(buildContext(c), body);
|
|
136
|
-
// Hold is the default intent
|
|
137
|
-
// order
|
|
138
|
-
const
|
|
139
|
-
if (
|
|
140
|
-
const summary = await payment.ensureOrderSession(c, response.order, body.contact);
|
|
154
|
+
const response = await resolveAdapter(c).bookFlight(buildContext(c), adapterBookingRequestForIntent(body));
|
|
155
|
+
// Hold is the default intent. Bank transfer also needs a finance session
|
|
156
|
+
// so the order can expose the reference/instructions through checkout.
|
|
157
|
+
const paymentSessionOptions = paymentSessionOptionsForIntent(body.paymentIntent);
|
|
158
|
+
if (paymentSessionOptions && response.order && payment) {
|
|
159
|
+
const summary = await payment.ensureOrderSession(c, response.order, body.contact, paymentSessionOptions);
|
|
141
160
|
response.order = attachPaymentSession(response.order, summary);
|
|
142
161
|
}
|
|
143
162
|
return c.json(response);
|
|
@@ -191,14 +210,15 @@ export function createFlightAdminRoutes(options) {
|
|
|
191
210
|
try {
|
|
192
211
|
const response = await resolveAdapter(c).getOrder(buildContext(c), orderId);
|
|
193
212
|
if (response.order && payment) {
|
|
194
|
-
const
|
|
213
|
+
const sessionByOrderId = await payment.fetchOrderSessions(c, [response.order.orderId]);
|
|
214
|
+
const summary = sessionByOrderId.get(response.order.orderId) ?? null;
|
|
195
215
|
response.order = attachPaymentSession(response.order, summary);
|
|
196
216
|
}
|
|
197
217
|
return c.json(response);
|
|
198
218
|
}
|
|
199
219
|
catch (err) {
|
|
200
220
|
const message = err instanceof Error ? err.message : String(err);
|
|
201
|
-
return c.json({ error: message },
|
|
221
|
+
return c.json({ error: message }, statusForAdapterErrorMessage(message));
|
|
202
222
|
}
|
|
203
223
|
});
|
|
204
224
|
// ── Cancel order ────────────────────────────────────────────────────────
|
|
@@ -219,7 +239,7 @@ export function createFlightAdminRoutes(options) {
|
|
|
219
239
|
}
|
|
220
240
|
catch (err) {
|
|
221
241
|
const message = err instanceof Error ? err.message : String(err);
|
|
222
|
-
return c.json({ error: message },
|
|
242
|
+
return c.json({ error: message }, statusForAdapterErrorMessage(message));
|
|
223
243
|
}
|
|
224
244
|
});
|
|
225
245
|
// ── Reference: airports (with substring search) ───────────────────────────
|
package/dist/hono.test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import { describe, expect, it, vi } from "vitest";
|
|
3
|
-
import { createFlightAdminRoutes, createFlightsHonoModule } from "./hono.js";
|
|
3
|
+
import { createFlightAdminRoutes, createFlightsHonoModule, } from "./hono.js";
|
|
4
4
|
function stubAdapter(over = {}) {
|
|
5
5
|
return {
|
|
6
6
|
capabilities: { provider: "stub", declared: [] },
|
|
@@ -12,8 +12,8 @@ function stubAdapter(over = {}) {
|
|
|
12
12
|
...over,
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
-
function mount(adapter) {
|
|
16
|
-
return new Hono().route("/v1/admin/flights", createFlightAdminRoutes({ resolveAdapter: () => adapter }));
|
|
15
|
+
function mount(adapter, payment) {
|
|
16
|
+
return new Hono().route("/v1/admin/flights", createFlightAdminRoutes({ resolveAdapter: () => adapter, payment }));
|
|
17
17
|
}
|
|
18
18
|
describe("flights hono module", () => {
|
|
19
19
|
it("createFlightsHonoModule exposes adminRoutes on module 'flights'", () => {
|
|
@@ -50,4 +50,244 @@ describe("flights hono module", () => {
|
|
|
50
50
|
});
|
|
51
51
|
expect(res.status).toBe(501);
|
|
52
52
|
});
|
|
53
|
+
it("creates and attaches a bank-transfer payment session during booking", async () => {
|
|
54
|
+
const adapter = stubAdapter();
|
|
55
|
+
const payment = {
|
|
56
|
+
ensureOrderSession: vi.fn(async () => ({ sessionId: "ps_bank", status: "pending" })),
|
|
57
|
+
fetchOrderSessions: vi.fn(async () => new Map()),
|
|
58
|
+
};
|
|
59
|
+
const app = mount(adapter, payment);
|
|
60
|
+
const res = await app.request("/v1/admin/flights/book", {
|
|
61
|
+
method: "POST",
|
|
62
|
+
headers: { "Content-Type": "application/json" },
|
|
63
|
+
body: JSON.stringify({
|
|
64
|
+
offerId: "off_1",
|
|
65
|
+
passengers: [{ passengerId: "p1" }],
|
|
66
|
+
contact: { email: "payer@example.com" },
|
|
67
|
+
paymentIntent: { type: "bank_transfer" },
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
expect(res.status).toBe(200);
|
|
71
|
+
await expect(res.json()).resolves.toMatchObject({
|
|
72
|
+
order: {
|
|
73
|
+
providerData: {
|
|
74
|
+
paymentSessionId: "ps_bank",
|
|
75
|
+
paymentStatus: "pending",
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
expect(payment.ensureOrderSession).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ orderId: "ord_1" }), { email: "payer@example.com" }, { paymentMethod: "bank_transfer", startCardPayment: false });
|
|
80
|
+
expect(adapter.bookFlight).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ paymentIntent: { type: "hold" } }));
|
|
81
|
+
});
|
|
82
|
+
it("preserves hold payment-session creation during booking", async () => {
|
|
83
|
+
const adapter = stubAdapter();
|
|
84
|
+
const payment = {
|
|
85
|
+
ensureOrderSession: vi.fn(async () => ({ sessionId: "ps_hold", status: "pending" })),
|
|
86
|
+
fetchOrderSessions: vi.fn(async () => new Map()),
|
|
87
|
+
};
|
|
88
|
+
const app = mount(adapter, payment);
|
|
89
|
+
const res = await app.request("/v1/admin/flights/book", {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: { "Content-Type": "application/json" },
|
|
92
|
+
body: JSON.stringify({
|
|
93
|
+
offerId: "off_1",
|
|
94
|
+
passengers: [{ passengerId: "p1" }],
|
|
95
|
+
paymentIntent: { type: "hold" },
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
expect(res.status).toBe(200);
|
|
99
|
+
expect(payment.ensureOrderSession).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ orderId: "ord_1" }), undefined, { startCardPayment: true });
|
|
100
|
+
});
|
|
101
|
+
it("does not create a payment session for card booking intent", async () => {
|
|
102
|
+
const adapter = stubAdapter();
|
|
103
|
+
const payment = {
|
|
104
|
+
ensureOrderSession: vi.fn(async () => ({ sessionId: "ps_card", status: "pending" })),
|
|
105
|
+
fetchOrderSessions: vi.fn(async () => new Map()),
|
|
106
|
+
};
|
|
107
|
+
const app = mount(adapter, payment);
|
|
108
|
+
const res = await app.request("/v1/admin/flights/book", {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: { "Content-Type": "application/json" },
|
|
111
|
+
body: JSON.stringify({
|
|
112
|
+
offerId: "off_1",
|
|
113
|
+
passengers: [{ passengerId: "p1" }],
|
|
114
|
+
paymentIntent: { type: "card", token: "tok_1" },
|
|
115
|
+
}),
|
|
116
|
+
});
|
|
117
|
+
expect(res.status).toBe(200);
|
|
118
|
+
expect(payment.ensureOrderSession).not.toHaveBeenCalled();
|
|
119
|
+
expect(adapter.bookFlight).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ paymentIntent: { type: "card", token: "tok_1" } }));
|
|
120
|
+
});
|
|
121
|
+
it("does not create a delayed payment session when reading a card-ticketed order", async () => {
|
|
122
|
+
const adapter = stubAdapter({
|
|
123
|
+
bookFlight: vi.fn(async () => ({
|
|
124
|
+
order: {
|
|
125
|
+
orderId: "ord_card",
|
|
126
|
+
status: "ticketed",
|
|
127
|
+
passengers: [{ passengerId: "p1" }],
|
|
128
|
+
},
|
|
129
|
+
})),
|
|
130
|
+
getOrder: vi.fn(async () => ({
|
|
131
|
+
order: {
|
|
132
|
+
orderId: "ord_card",
|
|
133
|
+
status: "ticketed",
|
|
134
|
+
passengers: [{ passengerId: "p1" }],
|
|
135
|
+
},
|
|
136
|
+
})),
|
|
137
|
+
});
|
|
138
|
+
const payment = {
|
|
139
|
+
ensureOrderSession: vi.fn(async () => ({ sessionId: "ps_card", status: "pending" })),
|
|
140
|
+
fetchOrderSessions: vi.fn(async () => new Map()),
|
|
141
|
+
};
|
|
142
|
+
const app = mount(adapter, payment);
|
|
143
|
+
const bookRes = await app.request("/v1/admin/flights/book", {
|
|
144
|
+
method: "POST",
|
|
145
|
+
headers: { "Content-Type": "application/json" },
|
|
146
|
+
body: JSON.stringify({
|
|
147
|
+
offerId: "off_1",
|
|
148
|
+
passengers: [{ passengerId: "p1" }],
|
|
149
|
+
paymentIntent: { type: "card", token: "tok_1" },
|
|
150
|
+
}),
|
|
151
|
+
});
|
|
152
|
+
const readRes = await app.request("/v1/admin/flights/orders/ord_card");
|
|
153
|
+
expect(bookRes.status).toBe(200);
|
|
154
|
+
expect(readRes.status).toBe(200);
|
|
155
|
+
await expect(readRes.json()).resolves.toMatchObject({
|
|
156
|
+
order: {
|
|
157
|
+
orderId: "ord_card",
|
|
158
|
+
status: "ticketed",
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
expect(payment.ensureOrderSession).not.toHaveBeenCalled();
|
|
162
|
+
expect(payment.fetchOrderSessions).toHaveBeenCalledWith(expect.anything(), ["ord_card"]);
|
|
163
|
+
});
|
|
164
|
+
it("GET /orders/:orderId attaches an existing payment session without ensuring one", async () => {
|
|
165
|
+
const adapter = stubAdapter({
|
|
166
|
+
getOrder: vi.fn(async () => ({
|
|
167
|
+
order: {
|
|
168
|
+
orderId: "ord_1",
|
|
169
|
+
passengers: [],
|
|
170
|
+
providerData: { source: "stub" },
|
|
171
|
+
},
|
|
172
|
+
})),
|
|
173
|
+
});
|
|
174
|
+
const payment = {
|
|
175
|
+
ensureOrderSession: vi.fn(async () => {
|
|
176
|
+
throw new Error("GET must not create or start payment sessions");
|
|
177
|
+
}),
|
|
178
|
+
fetchOrderSessions: vi.fn(async () => new Map([["ord_1", { sessionId: "ps_existing", status: "pending" }]])),
|
|
179
|
+
};
|
|
180
|
+
const app = mount(adapter, payment);
|
|
181
|
+
const res = await app.request("/v1/admin/flights/orders/ord_1");
|
|
182
|
+
expect(res.status).toBe(200);
|
|
183
|
+
await expect(res.json()).resolves.toMatchObject({
|
|
184
|
+
order: {
|
|
185
|
+
providerData: {
|
|
186
|
+
source: "stub",
|
|
187
|
+
paymentSessionId: "ps_existing",
|
|
188
|
+
paymentStatus: "pending",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
expect(payment.fetchOrderSessions).toHaveBeenCalledWith(expect.anything(), ["ord_1"]);
|
|
193
|
+
expect(payment.ensureOrderSession).not.toHaveBeenCalled();
|
|
194
|
+
});
|
|
195
|
+
it("does not create payment sessions when listing orders", async () => {
|
|
196
|
+
const adapter = stubAdapter({
|
|
197
|
+
listOrders: vi.fn(async () => ({
|
|
198
|
+
orders: [{ orderId: "ord_card", status: "ticketed", passengers: [] }],
|
|
199
|
+
pagination: { total: 1, hasMore: false },
|
|
200
|
+
})),
|
|
201
|
+
});
|
|
202
|
+
const payment = {
|
|
203
|
+
ensureOrderSession: vi.fn(async () => ({ sessionId: "ps_unexpected", status: "pending" })),
|
|
204
|
+
fetchOrderSessions: vi.fn(async () => new Map()),
|
|
205
|
+
};
|
|
206
|
+
const app = mount(adapter, payment);
|
|
207
|
+
const res = await app.request("/v1/admin/flights/orders");
|
|
208
|
+
expect(res.status).toBe(200);
|
|
209
|
+
await expect(res.json()).resolves.toMatchObject({
|
|
210
|
+
orders: [{ orderId: "ord_card", status: "ticketed" }],
|
|
211
|
+
});
|
|
212
|
+
expect(payment.fetchOrderSessions).toHaveBeenCalledWith(expect.anything(), ["ord_card"]);
|
|
213
|
+
expect(payment.ensureOrderSession).not.toHaveBeenCalled();
|
|
214
|
+
});
|
|
215
|
+
it("GET /orders attaches existing payment sessions without ensuring any", async () => {
|
|
216
|
+
const adapter = stubAdapter({
|
|
217
|
+
listOrders: vi.fn(async () => ({
|
|
218
|
+
orders: [
|
|
219
|
+
{ orderId: "ord_1", passengers: [] },
|
|
220
|
+
{ orderId: "ord_2", passengers: [] },
|
|
221
|
+
],
|
|
222
|
+
pagination: { total: 2, hasMore: false },
|
|
223
|
+
})),
|
|
224
|
+
});
|
|
225
|
+
const payment = {
|
|
226
|
+
ensureOrderSession: vi.fn(async () => {
|
|
227
|
+
throw new Error("GET must not create or start payment sessions");
|
|
228
|
+
}),
|
|
229
|
+
fetchOrderSessions: vi.fn(async () => new Map([
|
|
230
|
+
["ord_1", { sessionId: "ps_1", status: "pending" }],
|
|
231
|
+
["ord_2", { sessionId: "ps_2", status: "paid" }],
|
|
232
|
+
])),
|
|
233
|
+
};
|
|
234
|
+
const app = mount(adapter, payment);
|
|
235
|
+
const res = await app.request("/v1/admin/flights/orders");
|
|
236
|
+
expect(res.status).toBe(200);
|
|
237
|
+
await expect(res.json()).resolves.toMatchObject({
|
|
238
|
+
orders: [
|
|
239
|
+
{ providerData: { paymentSessionId: "ps_1", paymentStatus: "pending" } },
|
|
240
|
+
{ providerData: { paymentSessionId: "ps_2", paymentStatus: "paid" } },
|
|
241
|
+
],
|
|
242
|
+
});
|
|
243
|
+
expect(payment.fetchOrderSessions).toHaveBeenCalledWith(expect.anything(), ["ord_1", "ord_2"]);
|
|
244
|
+
expect(payment.ensureOrderSession).not.toHaveBeenCalled();
|
|
245
|
+
});
|
|
246
|
+
it("attaches an existing payment session when reading an order", async () => {
|
|
247
|
+
const adapter = stubAdapter({
|
|
248
|
+
getOrder: vi.fn(async () => ({
|
|
249
|
+
order: { orderId: "ord_hold", status: "confirmed", passengers: [] },
|
|
250
|
+
})),
|
|
251
|
+
});
|
|
252
|
+
const payment = {
|
|
253
|
+
ensureOrderSession: vi.fn(async () => ({ sessionId: "ps_unexpected", status: "pending" })),
|
|
254
|
+
fetchOrderSessions: vi.fn(async () => new Map([["ord_hold", { sessionId: "ps_existing", status: "paid" }]])),
|
|
255
|
+
};
|
|
256
|
+
const app = mount(adapter, payment);
|
|
257
|
+
const res = await app.request("/v1/admin/flights/orders/ord_hold");
|
|
258
|
+
expect(res.status).toBe(200);
|
|
259
|
+
await expect(res.json()).resolves.toMatchObject({
|
|
260
|
+
order: {
|
|
261
|
+
providerData: {
|
|
262
|
+
paymentSessionId: "ps_existing",
|
|
263
|
+
paymentStatus: "paid",
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
expect(payment.ensureOrderSession).not.toHaveBeenCalled();
|
|
268
|
+
});
|
|
269
|
+
it("returns 404 when reading a missing order", async () => {
|
|
270
|
+
const adapter = stubAdapter({
|
|
271
|
+
getOrder: vi.fn(async () => {
|
|
272
|
+
throw new Error("order_not_found");
|
|
273
|
+
}),
|
|
274
|
+
});
|
|
275
|
+
const app = mount(adapter);
|
|
276
|
+
const res = await app.request("/v1/admin/flights/orders/no_such_order");
|
|
277
|
+
expect(res.status).toBe(404);
|
|
278
|
+
await expect(res.json()).resolves.toEqual({ error: "order_not_found" });
|
|
279
|
+
});
|
|
280
|
+
it("returns 404 when cancelling a missing order", async () => {
|
|
281
|
+
const adapter = stubAdapter({
|
|
282
|
+
cancelOrder: vi.fn(async () => {
|
|
283
|
+
throw new Error("order_not_found");
|
|
284
|
+
}),
|
|
285
|
+
});
|
|
286
|
+
const app = mount(adapter);
|
|
287
|
+
const res = await app.request("/v1/admin/flights/orders/no_such_order/cancel", {
|
|
288
|
+
method: "POST",
|
|
289
|
+
});
|
|
290
|
+
expect(res.status).toBe(404);
|
|
291
|
+
await expect(res.json()).resolves.toEqual({ error: "order_not_found" });
|
|
292
|
+
});
|
|
53
293
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { createFlightAdminRoutes, createFlightsHonoModule, type FlightOrderPayme
|
|
|
5
5
|
export { FLIGHTS_ENTITY_MODULE, mergedFlightOffersToCandidates, mergedFlightOfferToCandidate, } from "./orchestration/availability-bridge.js";
|
|
6
6
|
export { type ConnectionResult, type ConnectionSearchStatus, type FanOutFlightSearchOptions, type FanOutFlightSearchResult, fanOutFlightSearch, type MergedFlightOffer, } from "./orchestration/fan-out.js";
|
|
7
7
|
export { itineraryFingerprint } from "./orchestration/fingerprint.js";
|
|
8
|
-
export { buildFlightSummary, createFlightOrderPaymentIntegration, type FlightCardBilling, type FlightOrderPaymentIntegrationDeps, formatDay, type OrderPaymentSessionsLike, parseAmountToCents, synthesizeBilling, } from "./payment-integration.js";
|
|
8
|
+
export { buildFlightSummary, createFlightOrderPaymentIntegration, type FlightCardBilling, type FlightOrderPaymentIntegrationDeps, type FlightOrderPaymentSessionOptions, formatDay, type OrderPaymentSessionsLike, parseAmountToCents, synthesizeBilling, } from "./payment-integration.js";
|
|
9
9
|
export { type Aircraft, type Airline, type Airport, dedupeCodes, type ReferenceDataCapabilities, type ReferenceDataProvider, } from "./reference/contract.js";
|
|
10
10
|
export { createLocalPostgresReferenceProvider, type LocalPostgresReferenceProviderOptions, referenceAircraft, referenceAirlines, referenceAirports, } from "./reference/local-postgres.js";
|
|
11
11
|
export { createStaticBundleReferenceProvider, type StaticBundleProviderOptions, type StaticBundleReferenceData, } from "./reference/static-bundle.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAClB,wBAAwB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,iCAAiC,EACjC,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AAGnC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,qBAAqB,EACrB,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAA;AAGrE,OAAO,EACL,kBAAkB,EAClB,mCAAmC,EACnC,KAAK,iBAAiB,EACtB,KAAK,iCAAiC,EACtC,SAAS,EACT,KAAK,wBAAwB,EAC7B,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,WAAW,EACX,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,GAC3B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,oCAAoC,EACpC,KAAK,qCAAqC,EAC1C,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,mCAAmC,EACnC,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,GAC/B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,KAAK,+BAA+B,EACpC,wBAAwB,GACzB,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAClB,wBAAwB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,iCAAiC,EACjC,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AAGnC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,qBAAqB,EACrB,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAA;AAGrE,OAAO,EACL,kBAAkB,EAClB,mCAAmC,EACnC,KAAK,iBAAiB,EACtB,KAAK,iCAAiC,EACtC,KAAK,gCAAgC,EACrC,SAAS,EACT,KAAK,wBAAwB,EAC7B,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,WAAW,EACX,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,GAC3B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,oCAAoC,EACpC,KAAK,qCAAqC,EAC1C,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,mCAAmC,EACnC,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,GAC/B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,KAAK,+BAA+B,EACpC,wBAAwB,GACzB,MAAM,eAAe,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Flight-specific payment integration: maps a `FlightOrder` onto finance's
|
|
3
|
-
* generic order-payment-session service and
|
|
3
|
+
* generic order-payment-session service and, for card-capable flows,
|
|
4
|
+
* optionally starts a card provider.
|
|
4
5
|
*
|
|
5
6
|
* The flights module stays payment-provider agnostic AND finance-agnostic — the
|
|
6
7
|
* deps below are typed STRUCTURALLY so this file imports neither
|
|
@@ -53,6 +54,7 @@ export interface OrderPaymentSessionsLike {
|
|
|
53
54
|
payerEmail?: string | null;
|
|
54
55
|
payerName?: string | null;
|
|
55
56
|
notes?: string | null;
|
|
57
|
+
paymentMethod?: "bank_transfer" | "credit_card" | null;
|
|
56
58
|
}, startProvider?: (db: AnyDrizzleDb, sessionId: string) => Promise<void>): Promise<{
|
|
57
59
|
sessionId: string;
|
|
58
60
|
status: string;
|
|
@@ -62,6 +64,10 @@ export interface OrderPaymentSessionsLike {
|
|
|
62
64
|
status: string;
|
|
63
65
|
}>>;
|
|
64
66
|
}
|
|
67
|
+
export interface FlightOrderPaymentSessionOptions {
|
|
68
|
+
paymentMethod?: "bank_transfer" | "credit_card";
|
|
69
|
+
startCardPayment?: boolean;
|
|
70
|
+
}
|
|
65
71
|
export interface FlightOrderPaymentIntegrationDeps {
|
|
66
72
|
/** Finance's generic order-payment-session service (structural). */
|
|
67
73
|
orderPaymentSessions: OrderPaymentSessionsLike;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment-integration.d.ts","sourceRoot":"","sources":["../src/payment-integration.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"payment-integration.d.ts","sourceRoot":"","sources":["../src/payment-integration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACvE,OAAO,KAAK,EAA6B,wBAAwB,EAAE,MAAM,WAAW,CAAA;AAQpF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACtD,iBAAiB,CAYnB;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI7C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAgB7D;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,aAAa,CACX,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;QACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,aAAa,CAAC,EAAE,eAAe,GAAG,aAAa,GAAG,IAAI,CAAA;KACvD,EACD,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACrE,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IACxD,aAAa,CACX,EAAE,EAAE,YAAY,EAChB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAC/D;AAED,MAAM,WAAW,gCAAgC;IAC/C,aAAa,CAAC,EAAE,eAAe,GAAG,aAAa,CAAA;IAC/C,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,iCAAiC;IAChD,oEAAoE;IACpE,oBAAoB,EAAE,wBAAwB,CAAA;IAC9C;;;;;;;;OAQG;IACH,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5F;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,iCAAiC,GACtC,wBAAwB,CAuC1B"}
|
|
@@ -58,13 +58,14 @@ export function buildFlightSummary(order) {
|
|
|
58
58
|
export function createFlightOrderPaymentIntegration(deps) {
|
|
59
59
|
const { orderPaymentSessions, startCardPayment } = deps;
|
|
60
60
|
return {
|
|
61
|
-
async ensureOrderSession(c, order, contact) {
|
|
61
|
+
async ensureOrderSession(c, order, contact, options) {
|
|
62
62
|
const db = getDb(c);
|
|
63
63
|
const passengerForBilling = order.passengers[0];
|
|
64
64
|
if (!passengerForBilling)
|
|
65
65
|
return null;
|
|
66
66
|
const amountCents = parseAmountToCents(order.totalPrice.amount);
|
|
67
|
-
const
|
|
67
|
+
const shouldStartCardPayment = options?.startCardPayment ?? true;
|
|
68
|
+
const startProvider = startCardPayment && shouldStartCardPayment
|
|
68
69
|
? (_writer, sessionId) => startCardPayment(c, sessionId, synthesizeBilling(passengerForBilling, contact))
|
|
69
70
|
: undefined;
|
|
70
71
|
return orderPaymentSessions.ensureSession(db, {
|
|
@@ -74,6 +75,7 @@ export function createFlightOrderPaymentIntegration(deps) {
|
|
|
74
75
|
payerEmail: contact?.email ?? passengerForBilling.email ?? null,
|
|
75
76
|
payerName: `${passengerForBilling.firstName} ${passengerForBilling.lastName}`.trim(),
|
|
76
77
|
notes: buildFlightSummary(order),
|
|
78
|
+
paymentMethod: options?.paymentMethod,
|
|
77
79
|
}, startProvider);
|
|
78
80
|
},
|
|
79
81
|
async fetchOrderSessions(c, orderIds) {
|
|
@@ -83,6 +83,20 @@ describe("createFlightOrderPaymentIntegration", () => {
|
|
|
83
83
|
notes: expect.stringContaining("LHR → CDG"),
|
|
84
84
|
}), undefined);
|
|
85
85
|
});
|
|
86
|
+
it("stamps bank-transfer sessions without starting the card provider", async () => {
|
|
87
|
+
const startCardPayment = vi.fn(async () => undefined);
|
|
88
|
+
const orderPaymentSessions = stubSessions();
|
|
89
|
+
const integration = createFlightOrderPaymentIntegration({
|
|
90
|
+
orderPaymentSessions,
|
|
91
|
+
startCardPayment,
|
|
92
|
+
});
|
|
93
|
+
await integration.ensureOrderSession(stubContext(), stubOrder(), undefined, {
|
|
94
|
+
paymentMethod: "bank_transfer",
|
|
95
|
+
startCardPayment: false,
|
|
96
|
+
});
|
|
97
|
+
expect(orderPaymentSessions.ensureSession).toHaveBeenCalledWith(DB, expect.objectContaining({ paymentMethod: "bank_transfer" }), undefined);
|
|
98
|
+
expect(startCardPayment).not.toHaveBeenCalled();
|
|
99
|
+
});
|
|
86
100
|
it("returns null when the order has no passengers", async () => {
|
|
87
101
|
const orderPaymentSessions = stubSessions();
|
|
88
102
|
const integration = createFlightOrderPaymentIntegration({ orderPaymentSessions });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyant-travel/flights",
|
|
3
|
-
"version": "0.137.
|
|
3
|
+
"version": "0.137.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -81,18 +81,18 @@
|
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
83
|
"drizzle-orm": "^0.45.2",
|
|
84
|
-
"hono": "^4.12.
|
|
85
|
-
"zod": "^4.3
|
|
84
|
+
"hono": "^4.12.25",
|
|
85
|
+
"zod": "^4.4.3",
|
|
86
86
|
"@voyant-travel/db": "^0.109.4",
|
|
87
|
-
"@voyant-travel/catalog": "^0.135.
|
|
87
|
+
"@voyant-travel/catalog": "^0.135.6",
|
|
88
88
|
"@voyant-travel/catalog-contracts": "^0.108.0",
|
|
89
|
-
"@voyant-travel/flights-contracts": "^0.104.
|
|
90
|
-
"@voyant-travel/hono": "^0.
|
|
89
|
+
"@voyant-travel/flights-contracts": "^0.104.6",
|
|
90
|
+
"@voyant-travel/hono": "^0.118.2"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"drizzle-kit": "^0.31.10",
|
|
94
|
-
"typescript": "^6.0.
|
|
95
|
-
"vitest": "^4.1.
|
|
94
|
+
"typescript": "^6.0.3",
|
|
95
|
+
"vitest": "^4.1.9",
|
|
96
96
|
"@voyant-travel/voyant-typescript-config": "^0.1.0"
|
|
97
97
|
},
|
|
98
98
|
"repository": {
|
|
@@ -101,10 +101,10 @@
|
|
|
101
101
|
"directory": "packages/flights"
|
|
102
102
|
},
|
|
103
103
|
"scripts": {
|
|
104
|
-
"typecheck": "tsc
|
|
104
|
+
"typecheck": "tsc -p tsconfig.typecheck.json",
|
|
105
105
|
"lint": "biome check src/",
|
|
106
106
|
"test": "vitest run",
|
|
107
|
-
"build": "tsc -p tsconfig.json",
|
|
107
|
+
"build": "tsc -p tsconfig.build.json",
|
|
108
108
|
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
109
109
|
"db:generate": "drizzle-kit generate --config=drizzle.migrations.config.ts --name=flights_baseline && node ../../scripts/migrations/guard-create-type.mjs ./migrations && node ../../scripts/migrations/ensure-extensions.mjs ./migrations"
|
|
110
110
|
},
|