@voyant-travel/storefront 0.121.1 → 0.122.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.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/payment-link/routes.d.ts +97 -0
- package/dist/payment-link/routes.d.ts.map +1 -0
- package/dist/payment-link/routes.js +473 -0
- package/dist/routes-public.d.ts +15 -15
- package/dist/routes-public.d.ts.map +1 -1
- package/dist/routes-public.js +23 -17
- package/dist/service.d.ts +2 -2
- package/dist/validation/intake.d.ts +4 -4
- package/dist/verification/routes-public.d.ts +2 -2
- package/package.json +20 -15
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { HonoModule } from "@voyant-travel/hono/module";
|
|
|
3
3
|
import { createStorefrontPublicRoutes } from "./routes-public.js";
|
|
4
4
|
export type { GuestBookingGuardOptions, GuestBookingGuardRequest, GuestBookingLookupInput, } from "./guest-booking-guard.js";
|
|
5
5
|
export { createGuestBookingGuard } from "./guest-booking-guard.js";
|
|
6
|
+
export type { PaymentLinkBankTransferDetails, PaymentLinkRoutesOptions, PaymentLinkSessionInput, PaymentLinkTripComponent, PaymentLinkTripData, } from "./payment-link/routes.js";
|
|
7
|
+
export { createPaymentLinkRoutes } from "./payment-link/routes.js";
|
|
6
8
|
export type { StorefrontAdminRoutes } from "./routes-admin.js";
|
|
7
9
|
export { createStorefrontAdminRoutes } from "./routes-admin.js";
|
|
8
10
|
export type { StorefrontPublicRoutes } from "./routes-public.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { BOOKING_BOOTSTRAP_INTENT_EVENT, createBookingBootstrapIntentHandler, }
|
|
|
2
2
|
import { createStorefrontAdminRoutes } from "./routes-admin.js";
|
|
3
3
|
import { createStorefrontPublicRoutes } from "./routes-public.js";
|
|
4
4
|
export { createGuestBookingGuard } from "./guest-booking-guard.js";
|
|
5
|
+
export { createPaymentLinkRoutes } from "./payment-link/routes.js";
|
|
5
6
|
export { createStorefrontAdminRoutes } from "./routes-admin.js";
|
|
6
7
|
export { createStorefrontPublicRoutes } from "./routes-public.js";
|
|
7
8
|
export { createStorefrontService, mergeStorefrontSettingsPatch, resolveStorefrontSettings, } from "./service.js";
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
/** Resolved bank-transfer beneficiary details from operator settings + env. */
|
|
4
|
+
export interface PaymentLinkBankTransferDetails {
|
|
5
|
+
beneficiary: string;
|
|
6
|
+
iban: string;
|
|
7
|
+
bankName?: string | null;
|
|
8
|
+
}
|
|
9
|
+
/** A resolved trip component, with optional product enrichment. */
|
|
10
|
+
export interface PaymentLinkTripComponent {
|
|
11
|
+
id: string;
|
|
12
|
+
kind: string;
|
|
13
|
+
entityModule: string | null;
|
|
14
|
+
entityId: string | null;
|
|
15
|
+
description: string | null;
|
|
16
|
+
status: string | null;
|
|
17
|
+
sequence: number | null;
|
|
18
|
+
componentTotalAmountCents: number | null;
|
|
19
|
+
componentCurrency: string | null;
|
|
20
|
+
metadata: Record<string, unknown> | null;
|
|
21
|
+
}
|
|
22
|
+
/** A resolved trip envelope + its visible components and product enrichment. */
|
|
23
|
+
export interface PaymentLinkTripData {
|
|
24
|
+
envelope: {
|
|
25
|
+
id: string;
|
|
26
|
+
status: string | null;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Visible (non-removed, non-cancelled) components, already ordered by
|
|
30
|
+
* sequence then createdAt.
|
|
31
|
+
*/
|
|
32
|
+
components: PaymentLinkTripComponent[];
|
|
33
|
+
/** product id → display name (from the inventory product record). */
|
|
34
|
+
productNameById: Map<string, string>;
|
|
35
|
+
/** product id → cover image (from inventory product media). */
|
|
36
|
+
mediaByProductId: Map<string, {
|
|
37
|
+
url: string;
|
|
38
|
+
altText: string | null;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/** The payment-session record fields the handlers read across routes. */
|
|
42
|
+
export interface PaymentLinkSessionInput {
|
|
43
|
+
invoiceId: string | null;
|
|
44
|
+
amountCents: number;
|
|
45
|
+
currency: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Deployment-supplied access the payment-link handlers need. Everything here
|
|
49
|
+
* encapsulates a module storefront does not statically depend on, so the
|
|
50
|
+
* package stays free of inventory / trips / netopia / operator-settings
|
|
51
|
+
* imports.
|
|
52
|
+
*/
|
|
53
|
+
export interface PaymentLinkRoutesOptions {
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the bank-transfer beneficiary details (operator settings merged
|
|
56
|
+
* with deploy-wide env defaults), or `null` when not configured.
|
|
57
|
+
*/
|
|
58
|
+
resolveBankTransferDetails(c: Context): Promise<PaymentLinkBankTransferDetails | null>;
|
|
59
|
+
/** Resolve the public checkout base URL from the deployment bindings. */
|
|
60
|
+
resolvePublicCheckoutBaseUrl(c: Context): string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Best-effort: ensure a fresh payment session can be started on the card
|
|
63
|
+
* provider, returning the redirect URL (or null). Returns `{ configured:
|
|
64
|
+
* false }` when no card processor is wired so the handler can 503. May throw
|
|
65
|
+
* — the handler maps the error to a 502.
|
|
66
|
+
*/
|
|
67
|
+
startCardPayment(c: Context, session: {
|
|
68
|
+
id: string;
|
|
69
|
+
payerName: string | null;
|
|
70
|
+
payerEmail: string | null;
|
|
71
|
+
notes: string | null;
|
|
72
|
+
redirectUrl: string | null;
|
|
73
|
+
}): Promise<{
|
|
74
|
+
configured: true;
|
|
75
|
+
redirectUrl: string | null;
|
|
76
|
+
} | {
|
|
77
|
+
configured: false;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Resolve a trip envelope (+ reconcile a paid checkout) and its visible
|
|
81
|
+
* components with product-media enrichment, or `null` when the envelope is
|
|
82
|
+
* gone. Encapsulates the trips + inventory schema reads.
|
|
83
|
+
*/
|
|
84
|
+
resolveTripData(c: Context, tripEnvelopeId: string, session: {
|
|
85
|
+
id: string;
|
|
86
|
+
status: string | null;
|
|
87
|
+
amountCents: number;
|
|
88
|
+
currency: string;
|
|
89
|
+
provider: string | null;
|
|
90
|
+
}): Promise<PaymentLinkTripData | null>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Build the public payment-link routes. Paths are ABSOLUTE so the deployment
|
|
94
|
+
* can lazy-mount the returned app directly via `lazyRoutes.paths`.
|
|
95
|
+
*/
|
|
96
|
+
export declare function createPaymentLinkRoutes(options: PaymentLinkRoutesOptions): Hono;
|
|
97
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/payment-link/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public payment-link + checkout-status routes — owned by
|
|
3
|
+
* `@voyant-travel/storefront`.
|
|
4
|
+
*
|
|
5
|
+
* agent-quality: file-size exception -- the public payment-link surface
|
|
6
|
+
* (config, retry, resolve, start-card, trip/booking summary, checkout-status)
|
|
7
|
+
* is one cohesive route family backed by the finance payment-session record;
|
|
8
|
+
* splitting it would scatter a single checkout contract.
|
|
9
|
+
*
|
|
10
|
+
* GET /v1/public/payment-link-config
|
|
11
|
+
* POST /v1/public/payment-link/:sessionId/retry
|
|
12
|
+
* GET /v1/public/payment-link/resolve
|
|
13
|
+
* POST /v1/public/payment-link/:sessionId/start-card
|
|
14
|
+
* GET /v1/public/payment-link/:sessionId/trip-summary
|
|
15
|
+
* GET /v1/public/payment-link/:sessionId/booking-summary
|
|
16
|
+
* GET /v1/public/bookings/:bookingId/checkout-status
|
|
17
|
+
*
|
|
18
|
+
* The routes are mounted at their ABSOLUTE public paths so the deployment can
|
|
19
|
+
* lazy-mount them via `lazyRoutes.paths`. All cross-module access that
|
|
20
|
+
* storefront does not already depend on (inventory product media, trip
|
|
21
|
+
* envelopes/components reconciliation, the card-payment provider, and the
|
|
22
|
+
* operator settings + checkout base URL) is INJECTED via `options` — the
|
|
23
|
+
* package never statically imports inventory / trips / the netopia plugin /
|
|
24
|
+
* the operator settings module.
|
|
25
|
+
*
|
|
26
|
+
* Storefront already depends acyclically on `@voyant-travel/bookings` and
|
|
27
|
+
* `@voyant-travel/finance`, so the booking / invoice / payment-session reads
|
|
28
|
+
* use those schemas directly.
|
|
29
|
+
*/
|
|
30
|
+
import { bookingItems, bookings } from "@voyant-travel/bookings/schema";
|
|
31
|
+
import { financeService } from "@voyant-travel/finance";
|
|
32
|
+
import { invoices, paymentSessions } from "@voyant-travel/finance/schema";
|
|
33
|
+
import { and, asc, desc, eq, or } from "drizzle-orm";
|
|
34
|
+
import { Hono } from "hono";
|
|
35
|
+
const PUBLIC_PAYMENT_LINK_CONFIG_CACHE_CONTROL = "public, s-maxage=300, stale-while-revalidate=600";
|
|
36
|
+
// ─────────────────────────────────────────────────────────────────
|
|
37
|
+
// Local helpers
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────
|
|
39
|
+
function cachePublicPaymentLinkConfig(c) {
|
|
40
|
+
c.header("Cache-Control", PUBLIC_PAYMENT_LINK_CONFIG_CACHE_CONTROL);
|
|
41
|
+
}
|
|
42
|
+
function requireRouteParam(c, name) {
|
|
43
|
+
const value = c.req.param(name);
|
|
44
|
+
return value ? value : c.json({ error: `${name} route param is required` }, 400);
|
|
45
|
+
}
|
|
46
|
+
function getDb(c) {
|
|
47
|
+
return c.get("db");
|
|
48
|
+
}
|
|
49
|
+
async function buildPublicBankTransferInstructions(c, options, bookingNumber, session) {
|
|
50
|
+
const db = getDb(c);
|
|
51
|
+
const details = await options.resolveBankTransferDetails(c);
|
|
52
|
+
if (!details)
|
|
53
|
+
return null;
|
|
54
|
+
const [invoice] = session.invoiceId
|
|
55
|
+
? await db
|
|
56
|
+
.select({
|
|
57
|
+
invoiceNumber: invoices.invoiceNumber,
|
|
58
|
+
dueDate: invoices.dueDate,
|
|
59
|
+
balanceDueCents: invoices.balanceDueCents,
|
|
60
|
+
currency: invoices.currency,
|
|
61
|
+
})
|
|
62
|
+
.from(invoices)
|
|
63
|
+
.where(eq(invoices.id, session.invoiceId))
|
|
64
|
+
.limit(1)
|
|
65
|
+
: [];
|
|
66
|
+
return {
|
|
67
|
+
beneficiary: details.beneficiary,
|
|
68
|
+
iban: details.iban,
|
|
69
|
+
bankName: details.bankName ?? "-",
|
|
70
|
+
reference: `BOOK-${bookingNumber}`,
|
|
71
|
+
amountCents: invoice?.balanceDueCents ?? session.amountCents,
|
|
72
|
+
currency: invoice?.currency ?? session.currency,
|
|
73
|
+
dueAt: invoice?.dueDate ?? null,
|
|
74
|
+
proformaNumber: invoice?.invoiceNumber ?? null,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// ─────────────────────────────────────────────────────────────────
|
|
78
|
+
// Routes
|
|
79
|
+
// ─────────────────────────────────────────────────────────────────
|
|
80
|
+
/**
|
|
81
|
+
* Build the public payment-link routes. Paths are ABSOLUTE so the deployment
|
|
82
|
+
* can lazy-mount the returned app directly via `lazyRoutes.paths`.
|
|
83
|
+
*/
|
|
84
|
+
export function createPaymentLinkRoutes(options) {
|
|
85
|
+
const hono = new Hono();
|
|
86
|
+
hono.get("/v1/public/payment-link-config", async (c) => {
|
|
87
|
+
const bankTransfer = await options.resolveBankTransferDetails(c);
|
|
88
|
+
cachePublicPaymentLinkConfig(c);
|
|
89
|
+
return c.json({
|
|
90
|
+
data: {
|
|
91
|
+
publicCheckoutBaseUrl: options.resolvePublicCheckoutBaseUrl(c),
|
|
92
|
+
bankTransfer,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
hono.post("/v1/public/payment-link/:sessionId/retry", async (c) => {
|
|
97
|
+
const sessionId = requireRouteParam(c, "sessionId");
|
|
98
|
+
if (sessionId instanceof Response)
|
|
99
|
+
return sessionId;
|
|
100
|
+
const db = getDb(c);
|
|
101
|
+
const [original] = await db
|
|
102
|
+
.select()
|
|
103
|
+
.from(paymentSessions)
|
|
104
|
+
.where(eq(paymentSessions.id, sessionId))
|
|
105
|
+
.limit(1);
|
|
106
|
+
if (!original)
|
|
107
|
+
return c.json({ error: "Session not found" }, 404);
|
|
108
|
+
if (original.status === "paid" || original.status === "authorized") {
|
|
109
|
+
return c.json({ data: { sessionId: original.id, alreadyPaid: true } });
|
|
110
|
+
}
|
|
111
|
+
const dbCast = db;
|
|
112
|
+
const fresh = await financeService.createPaymentSession(dbCast, {
|
|
113
|
+
targetType: original.targetType,
|
|
114
|
+
targetId: original.targetId ?? undefined,
|
|
115
|
+
bookingId: original.bookingId ?? undefined,
|
|
116
|
+
invoiceId: original.invoiceId ?? undefined,
|
|
117
|
+
bookingPaymentScheduleId: original.bookingPaymentScheduleId ?? undefined,
|
|
118
|
+
bookingGuaranteeId: original.bookingGuaranteeId ?? undefined,
|
|
119
|
+
currency: original.currency,
|
|
120
|
+
amountCents: original.amountCents,
|
|
121
|
+
status: "pending",
|
|
122
|
+
provider: original.provider ?? undefined,
|
|
123
|
+
paymentMethod: original.paymentMethod ?? undefined,
|
|
124
|
+
payerEmail: original.payerEmail ?? undefined,
|
|
125
|
+
payerName: original.payerName ?? undefined,
|
|
126
|
+
notes: original.notes ?? undefined,
|
|
127
|
+
});
|
|
128
|
+
if (!fresh)
|
|
129
|
+
return c.json({ error: "Failed to create payment session" }, 500);
|
|
130
|
+
return c.json({ data: { sessionId: fresh.id } });
|
|
131
|
+
});
|
|
132
|
+
hono.get("/v1/public/payment-link/resolve", async (c) => {
|
|
133
|
+
const ref = c.req.query("ref");
|
|
134
|
+
if (!ref)
|
|
135
|
+
return c.json({ error: "ref query param is required" }, 400);
|
|
136
|
+
const db = getDb(c);
|
|
137
|
+
const [session] = await db
|
|
138
|
+
.select({ id: paymentSessions.id })
|
|
139
|
+
.from(paymentSessions)
|
|
140
|
+
.where(or(eq(paymentSessions.id, ref), eq(paymentSessions.clientReference, ref), eq(paymentSessions.externalReference, ref)))
|
|
141
|
+
.limit(1);
|
|
142
|
+
if (!session)
|
|
143
|
+
return c.json({ error: "Payment session not found" }, 404);
|
|
144
|
+
return c.json({ data: { sessionId: session.id } });
|
|
145
|
+
});
|
|
146
|
+
hono.post("/v1/public/payment-link/:sessionId/start-card", async (c) => {
|
|
147
|
+
const sessionId = requireRouteParam(c, "sessionId");
|
|
148
|
+
if (sessionId instanceof Response)
|
|
149
|
+
return sessionId;
|
|
150
|
+
const db = getDb(c);
|
|
151
|
+
const [session] = await db
|
|
152
|
+
.select()
|
|
153
|
+
.from(paymentSessions)
|
|
154
|
+
.where(eq(paymentSessions.id, sessionId))
|
|
155
|
+
.limit(1);
|
|
156
|
+
if (!session)
|
|
157
|
+
return c.json({ error: "Session not found" }, 404);
|
|
158
|
+
if (session.redirectUrl) {
|
|
159
|
+
return c.json({ data: { redirectUrl: session.redirectUrl } });
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const started = await options.startCardPayment(c, {
|
|
163
|
+
id: session.id,
|
|
164
|
+
payerName: session.payerName,
|
|
165
|
+
payerEmail: session.payerEmail,
|
|
166
|
+
notes: session.notes,
|
|
167
|
+
redirectUrl: session.redirectUrl,
|
|
168
|
+
});
|
|
169
|
+
if (!started.configured) {
|
|
170
|
+
return c.json({ error: "Card processor not configured" }, 503);
|
|
171
|
+
}
|
|
172
|
+
return c.json({ data: { redirectUrl: started.redirectUrl } });
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
const message = err instanceof Error ? err.message : "Failed to start card payment";
|
|
176
|
+
return c.json({ error: message }, 502);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
hono.get("/v1/public/payment-link/:sessionId/trip-summary", async (c) => {
|
|
180
|
+
const sessionId = requireRouteParam(c, "sessionId");
|
|
181
|
+
if (sessionId instanceof Response)
|
|
182
|
+
return sessionId;
|
|
183
|
+
const db = getDb(c);
|
|
184
|
+
const [session] = await db
|
|
185
|
+
.select()
|
|
186
|
+
.from(paymentSessions)
|
|
187
|
+
.where(eq(paymentSessions.id, sessionId))
|
|
188
|
+
.limit(1);
|
|
189
|
+
if (!session)
|
|
190
|
+
return c.json({ error: "Session not found" }, 404);
|
|
191
|
+
const metadata = (session.metadata ?? {});
|
|
192
|
+
const tripEnvelopeId = typeof metadata.tripEnvelopeId === "string" ? metadata.tripEnvelopeId : null;
|
|
193
|
+
if (!tripEnvelopeId)
|
|
194
|
+
return c.json({ data: null });
|
|
195
|
+
const tripData = await options.resolveTripData(c, tripEnvelopeId, {
|
|
196
|
+
id: session.id,
|
|
197
|
+
status: session.status,
|
|
198
|
+
amountCents: session.amountCents,
|
|
199
|
+
currency: session.currency,
|
|
200
|
+
provider: session.provider,
|
|
201
|
+
});
|
|
202
|
+
if (!tripData)
|
|
203
|
+
return c.json({ data: null });
|
|
204
|
+
const { envelope, components: visibleComponents, productNameById, mediaByProductId } = tripData;
|
|
205
|
+
const allocationsRaw = Array.isArray(metadata.componentAllocations)
|
|
206
|
+
? metadata.componentAllocations
|
|
207
|
+
: [];
|
|
208
|
+
const allocationByComponentId = new Map();
|
|
209
|
+
for (const allocation of allocationsRaw) {
|
|
210
|
+
if (allocation.componentId)
|
|
211
|
+
allocationByComponentId.set(allocation.componentId, allocation);
|
|
212
|
+
}
|
|
213
|
+
const trip = {
|
|
214
|
+
envelopeId: envelope.id,
|
|
215
|
+
currency: session.currency,
|
|
216
|
+
totalAmountCents: session.amountCents,
|
|
217
|
+
components: visibleComponents.map((component) => {
|
|
218
|
+
const metadataRecord = (component.metadata ?? {});
|
|
219
|
+
const catalogItem = (metadataRecord.catalogItem ?? null);
|
|
220
|
+
const flightDraft = (metadataRecord.flightDraft ?? null);
|
|
221
|
+
const schedule = resolvePublicTripComponentSchedule(metadataRecord);
|
|
222
|
+
const fallbackName = catalogItem?.name ??
|
|
223
|
+
(component.entityId ? productNameById.get(component.entityId) : null) ??
|
|
224
|
+
(flightDraft?.origin && flightDraft?.destination
|
|
225
|
+
? `${flightDraft.origin} -> ${flightDraft.destination}`
|
|
226
|
+
: null) ??
|
|
227
|
+
component.description ??
|
|
228
|
+
component.kind.replaceAll("_", " ");
|
|
229
|
+
const thumbnail = component.entityId
|
|
230
|
+
? (mediaByProductId.get(component.entityId) ?? null)
|
|
231
|
+
: null;
|
|
232
|
+
const catalogThumbnailUrl = publicStringValue(readPublicRecord(metadataRecord.catalogItem)?.thumbnailUrl);
|
|
233
|
+
const allocation = allocationByComponentId.get(component.id);
|
|
234
|
+
return {
|
|
235
|
+
id: component.id,
|
|
236
|
+
kind: component.kind,
|
|
237
|
+
entityModule: component.entityModule,
|
|
238
|
+
title: fallbackName,
|
|
239
|
+
thumbnailUrl: thumbnail?.url ?? catalogThumbnailUrl ?? null,
|
|
240
|
+
thumbnailAlt: thumbnail?.altText ?? null,
|
|
241
|
+
scheduledStartsAt: schedule.start,
|
|
242
|
+
scheduledEndsAt: schedule.end,
|
|
243
|
+
sourceAmountCents: allocation?.sourceAmountCents ?? component.componentTotalAmountCents ?? null,
|
|
244
|
+
sourceCurrency: allocation?.sourceCurrency ?? component.componentCurrency ?? session.currency,
|
|
245
|
+
targetAmountCents: allocation?.targetAmountCents ?? component.componentTotalAmountCents ?? null,
|
|
246
|
+
targetCurrency: allocation?.targetCurrency ?? session.currency,
|
|
247
|
+
fx: allocation?.fx ?? null,
|
|
248
|
+
};
|
|
249
|
+
}),
|
|
250
|
+
};
|
|
251
|
+
return c.json({ data: trip });
|
|
252
|
+
});
|
|
253
|
+
hono.get("/v1/public/payment-link/:sessionId/booking-summary", async (c) => {
|
|
254
|
+
const sessionId = requireRouteParam(c, "sessionId");
|
|
255
|
+
if (sessionId instanceof Response)
|
|
256
|
+
return sessionId;
|
|
257
|
+
const db = getDb(c);
|
|
258
|
+
const [session] = await db
|
|
259
|
+
.select({
|
|
260
|
+
id: paymentSessions.id,
|
|
261
|
+
bookingId: paymentSessions.bookingId,
|
|
262
|
+
amountCents: paymentSessions.amountCents,
|
|
263
|
+
currency: paymentSessions.currency,
|
|
264
|
+
metadata: paymentSessions.metadata,
|
|
265
|
+
})
|
|
266
|
+
.from(paymentSessions)
|
|
267
|
+
.where(eq(paymentSessions.id, sessionId))
|
|
268
|
+
.limit(1);
|
|
269
|
+
if (!session)
|
|
270
|
+
return c.json({ error: "Session not found" }, 404);
|
|
271
|
+
const metadata = (session.metadata ?? {});
|
|
272
|
+
if (typeof metadata.tripEnvelopeId === "string" && metadata.tripEnvelopeId.length > 0) {
|
|
273
|
+
return c.json({ data: null });
|
|
274
|
+
}
|
|
275
|
+
if (!session.bookingId)
|
|
276
|
+
return c.json({ data: null });
|
|
277
|
+
const [booking] = await db
|
|
278
|
+
.select({
|
|
279
|
+
id: bookings.id,
|
|
280
|
+
bookingNumber: bookings.bookingNumber,
|
|
281
|
+
status: bookings.status,
|
|
282
|
+
sellCurrency: bookings.sellCurrency,
|
|
283
|
+
sellAmountCents: bookings.sellAmountCents,
|
|
284
|
+
pax: bookings.pax,
|
|
285
|
+
startDate: bookings.startDate,
|
|
286
|
+
endDate: bookings.endDate,
|
|
287
|
+
})
|
|
288
|
+
.from(bookings)
|
|
289
|
+
.where(eq(bookings.id, session.bookingId))
|
|
290
|
+
.limit(1);
|
|
291
|
+
if (!booking)
|
|
292
|
+
return c.json({ data: null });
|
|
293
|
+
const items = await db
|
|
294
|
+
.select({
|
|
295
|
+
id: bookingItems.id,
|
|
296
|
+
title: bookingItems.title,
|
|
297
|
+
itemType: bookingItems.itemType,
|
|
298
|
+
quantity: bookingItems.quantity,
|
|
299
|
+
totalSellAmountCents: bookingItems.totalSellAmountCents,
|
|
300
|
+
sellCurrency: bookingItems.sellCurrency,
|
|
301
|
+
startsAt: bookingItems.startsAt,
|
|
302
|
+
endsAt: bookingItems.endsAt,
|
|
303
|
+
serviceDate: bookingItems.serviceDate,
|
|
304
|
+
productNameSnapshot: bookingItems.productNameSnapshot,
|
|
305
|
+
optionNameSnapshot: bookingItems.optionNameSnapshot,
|
|
306
|
+
unitNameSnapshot: bookingItems.unitNameSnapshot,
|
|
307
|
+
departureLabelSnapshot: bookingItems.departureLabelSnapshot,
|
|
308
|
+
})
|
|
309
|
+
.from(bookingItems)
|
|
310
|
+
.where(eq(bookingItems.bookingId, booking.id))
|
|
311
|
+
.orderBy(asc(bookingItems.createdAt));
|
|
312
|
+
return c.json({
|
|
313
|
+
data: {
|
|
314
|
+
bookingId: booking.id,
|
|
315
|
+
bookingNumber: booking.bookingNumber,
|
|
316
|
+
status: booking.status,
|
|
317
|
+
pax: booking.pax,
|
|
318
|
+
startDate: booking.startDate,
|
|
319
|
+
endDate: booking.endDate,
|
|
320
|
+
chargeAmountCents: session.amountCents,
|
|
321
|
+
currency: session.currency ?? booking.sellCurrency,
|
|
322
|
+
bookingTotalAmountCents: booking.sellAmountCents,
|
|
323
|
+
bookingCurrency: booking.sellCurrency,
|
|
324
|
+
items: items.map((item) => ({
|
|
325
|
+
id: item.id,
|
|
326
|
+
productName: item.productNameSnapshot ?? item.title,
|
|
327
|
+
optionName: item.optionNameSnapshot,
|
|
328
|
+
unitName: item.unitNameSnapshot,
|
|
329
|
+
departureLabel: item.departureLabelSnapshot,
|
|
330
|
+
startsAt: item.startsAt instanceof Date ? item.startsAt.toISOString() : item.startsAt,
|
|
331
|
+
endsAt: item.endsAt instanceof Date ? item.endsAt.toISOString() : item.endsAt,
|
|
332
|
+
serviceDate: item.serviceDate,
|
|
333
|
+
quantity: item.quantity,
|
|
334
|
+
itemType: item.itemType,
|
|
335
|
+
amountCents: item.totalSellAmountCents,
|
|
336
|
+
currency: item.sellCurrency,
|
|
337
|
+
})),
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
hono.get("/v1/public/bookings/:bookingId/checkout-status", async (c) => {
|
|
342
|
+
const bookingId = requireRouteParam(c, "bookingId");
|
|
343
|
+
if (bookingId instanceof Response)
|
|
344
|
+
return bookingId;
|
|
345
|
+
const ref = c.req.query("session") ?? c.req.query("orderId") ?? c.req.query("ref") ?? null;
|
|
346
|
+
const db = getDb(c);
|
|
347
|
+
const [booking] = await db
|
|
348
|
+
.select({
|
|
349
|
+
id: bookings.id,
|
|
350
|
+
bookingNumber: bookings.bookingNumber,
|
|
351
|
+
status: bookings.status,
|
|
352
|
+
updatedAt: bookings.updatedAt,
|
|
353
|
+
})
|
|
354
|
+
.from(bookings)
|
|
355
|
+
.where(eq(bookings.id, bookingId))
|
|
356
|
+
.limit(1);
|
|
357
|
+
if (!booking)
|
|
358
|
+
return c.json({ error: "Booking not found" }, 404);
|
|
359
|
+
const sessionRefFilter = ref
|
|
360
|
+
? or(eq(paymentSessions.id, ref), eq(paymentSessions.clientReference, ref), eq(paymentSessions.externalReference, ref), eq(paymentSessions.providerSessionId, ref), eq(paymentSessions.providerPaymentId, ref))
|
|
361
|
+
: undefined;
|
|
362
|
+
const sessionWhere = sessionRefFilter
|
|
363
|
+
? and(eq(paymentSessions.bookingId, bookingId), sessionRefFilter)
|
|
364
|
+
: eq(paymentSessions.bookingId, bookingId);
|
|
365
|
+
let sessions = await db
|
|
366
|
+
.select({
|
|
367
|
+
id: paymentSessions.id,
|
|
368
|
+
status: paymentSessions.status,
|
|
369
|
+
amountCents: paymentSessions.amountCents,
|
|
370
|
+
currency: paymentSessions.currency,
|
|
371
|
+
invoiceId: paymentSessions.invoiceId,
|
|
372
|
+
paymentMethod: paymentSessions.paymentMethod,
|
|
373
|
+
completedAt: paymentSessions.completedAt,
|
|
374
|
+
failedAt: paymentSessions.failedAt,
|
|
375
|
+
updatedAt: paymentSessions.updatedAt,
|
|
376
|
+
})
|
|
377
|
+
.from(paymentSessions)
|
|
378
|
+
.where(sessionWhere)
|
|
379
|
+
.orderBy(desc(paymentSessions.createdAt))
|
|
380
|
+
.limit(5);
|
|
381
|
+
if (sessions.length === 0 && ref) {
|
|
382
|
+
sessions = await db
|
|
383
|
+
.select({
|
|
384
|
+
id: paymentSessions.id,
|
|
385
|
+
status: paymentSessions.status,
|
|
386
|
+
amountCents: paymentSessions.amountCents,
|
|
387
|
+
currency: paymentSessions.currency,
|
|
388
|
+
invoiceId: paymentSessions.invoiceId,
|
|
389
|
+
paymentMethod: paymentSessions.paymentMethod,
|
|
390
|
+
completedAt: paymentSessions.completedAt,
|
|
391
|
+
failedAt: paymentSessions.failedAt,
|
|
392
|
+
updatedAt: paymentSessions.updatedAt,
|
|
393
|
+
})
|
|
394
|
+
.from(paymentSessions)
|
|
395
|
+
.where(eq(paymentSessions.bookingId, bookingId))
|
|
396
|
+
.orderBy(desc(paymentSessions.createdAt))
|
|
397
|
+
.limit(5);
|
|
398
|
+
}
|
|
399
|
+
const paidSession = sessions.find((session) => session.status === "paid" || session.status === "authorized");
|
|
400
|
+
const latestSession = paidSession ?? sessions[0] ?? null;
|
|
401
|
+
const isBankTransferSession = latestSession?.paymentMethod === "bank_transfer" ||
|
|
402
|
+
(booking.status === "awaiting_payment" && Boolean(latestSession?.invoiceId));
|
|
403
|
+
const bankTransferInstructions = isBankTransferSession && latestSession
|
|
404
|
+
? await buildPublicBankTransferInstructions(c, options, booking.bookingNumber, latestSession)
|
|
405
|
+
: null;
|
|
406
|
+
const failedStatuses = new Set(["failed", "cancelled", "expired"]);
|
|
407
|
+
const paymentStatus = booking.status === "confirmed" || paidSession
|
|
408
|
+
? "paid"
|
|
409
|
+
: sessions.length > 0 && sessions.every((session) => failedStatuses.has(session.status))
|
|
410
|
+
? "failed"
|
|
411
|
+
: "pending";
|
|
412
|
+
return c.json({
|
|
413
|
+
data: {
|
|
414
|
+
bookingId: booking.id,
|
|
415
|
+
bookingNumber: booking.bookingNumber,
|
|
416
|
+
bookingStatus: booking.status,
|
|
417
|
+
paymentStatus,
|
|
418
|
+
session: latestSession,
|
|
419
|
+
bankTransferInstructions,
|
|
420
|
+
updatedAt: (latestSession?.updatedAt ?? booking.updatedAt)?.toISOString?.() ?? null,
|
|
421
|
+
},
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
return hono;
|
|
425
|
+
}
|
|
426
|
+
// ─────────────────────────────────────────────────────────────────
|
|
427
|
+
// Pure schedule resolution helpers
|
|
428
|
+
// ─────────────────────────────────────────────────────────────────
|
|
429
|
+
function resolvePublicTripComponentSchedule(metadata) {
|
|
430
|
+
const scheduledStart = publicStringValue(metadata.scheduledStartsAt);
|
|
431
|
+
const scheduledEnd = publicStringValue(metadata.scheduledEndsAt);
|
|
432
|
+
if (scheduledStart)
|
|
433
|
+
return { start: scheduledStart, end: scheduledEnd };
|
|
434
|
+
const flightDraft = readPublicRecord(metadata.flightDraft);
|
|
435
|
+
if (flightDraft) {
|
|
436
|
+
const selectedOffer = readPublicRecord(flightDraft.selectedOffer);
|
|
437
|
+
const itineraries = Array.isArray(selectedOffer?.itineraries) ? selectedOffer.itineraries : [];
|
|
438
|
+
const firstItinerary = readPublicRecord(itineraries[0]);
|
|
439
|
+
const lastItinerary = readPublicRecord(itineraries[itineraries.length - 1]);
|
|
440
|
+
const firstSegments = Array.isArray(firstItinerary?.segments) ? firstItinerary.segments : [];
|
|
441
|
+
const lastSegments = Array.isArray(lastItinerary?.segments) ? lastItinerary.segments : [];
|
|
442
|
+
const firstSegment = readPublicRecord(firstSegments[0]);
|
|
443
|
+
const lastSegment = readPublicRecord(lastSegments[lastSegments.length - 1]);
|
|
444
|
+
const departure = readPublicRecord(firstSegment?.departure);
|
|
445
|
+
const arrival = readPublicRecord(lastSegment?.arrival);
|
|
446
|
+
return {
|
|
447
|
+
start: publicStringValue(departure?.at) ?? publicStringValue(flightDraft.departDate),
|
|
448
|
+
end: publicStringValue(arrival?.at) ?? publicStringValue(flightDraft.returnDate),
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
const bookingDraft = readPublicRecord(metadata.bookingDraftV1);
|
|
452
|
+
const configure = readPublicRecord(bookingDraft?.configure);
|
|
453
|
+
const dateRange = readPublicRecord(configure?.dateRange);
|
|
454
|
+
const departureDate = publicStringValue(configure?.departureDate);
|
|
455
|
+
const checkIn = publicStringValue(dateRange?.checkIn);
|
|
456
|
+
const checkOut = publicStringValue(dateRange?.checkOut);
|
|
457
|
+
if (departureDate || checkIn) {
|
|
458
|
+
return { start: departureDate ?? checkIn, end: checkOut };
|
|
459
|
+
}
|
|
460
|
+
const cruiseDraft = readPublicRecord(metadata.cruiseDraft);
|
|
461
|
+
const embarkationDate = publicStringValue(cruiseDraft?.embarkationDate);
|
|
462
|
+
if (embarkationDate)
|
|
463
|
+
return { start: embarkationDate, end: null };
|
|
464
|
+
return { start: null, end: null };
|
|
465
|
+
}
|
|
466
|
+
function readPublicRecord(value) {
|
|
467
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
468
|
+
? value
|
|
469
|
+
: null;
|
|
470
|
+
}
|
|
471
|
+
function publicStringValue(value) {
|
|
472
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
473
|
+
}
|
package/dist/routes-public.d.ts
CHANGED
|
@@ -126,7 +126,7 @@ export declare function createStorefrontPublicRoutes(options?: StorefrontService
|
|
|
126
126
|
error: string;
|
|
127
127
|
};
|
|
128
128
|
outputFormat: "json";
|
|
129
|
-
status:
|
|
129
|
+
status: 400 | 403 | 429;
|
|
130
130
|
} | {
|
|
131
131
|
input: {};
|
|
132
132
|
output: {
|
|
@@ -134,7 +134,7 @@ export declare function createStorefrontPublicRoutes(options?: StorefrontService
|
|
|
134
134
|
id: string;
|
|
135
135
|
personId: string;
|
|
136
136
|
kind: "notify" | "wishlist" | "inquiry" | "request_offer" | "referral";
|
|
137
|
-
source: "admin" | "
|
|
137
|
+
source: "admin" | "form" | "phone" | "booking" | "website" | "abandoned_cart";
|
|
138
138
|
status: "expired" | "new" | "contacted" | "qualified" | "converted" | "lost";
|
|
139
139
|
duplicate: boolean;
|
|
140
140
|
};
|
|
@@ -151,7 +151,7 @@ export declare function createStorefrontPublicRoutes(options?: StorefrontService
|
|
|
151
151
|
error: string;
|
|
152
152
|
};
|
|
153
153
|
outputFormat: "json";
|
|
154
|
-
status:
|
|
154
|
+
status: 400 | 403 | 429;
|
|
155
155
|
} | {
|
|
156
156
|
input: {};
|
|
157
157
|
output: {
|
|
@@ -159,7 +159,7 @@ export declare function createStorefrontPublicRoutes(options?: StorefrontService
|
|
|
159
159
|
id: string;
|
|
160
160
|
personId: string;
|
|
161
161
|
kind: "notify" | "wishlist" | "inquiry" | "request_offer" | "referral";
|
|
162
|
-
source: "admin" | "
|
|
162
|
+
source: "admin" | "form" | "phone" | "booking" | "website" | "abandoned_cart";
|
|
163
163
|
status: "expired" | "new" | "contacted" | "qualified" | "converted" | "lost";
|
|
164
164
|
duplicate: boolean;
|
|
165
165
|
doubleOptIn: "requested" | "not_configured";
|
|
@@ -1278,6 +1278,17 @@ export declare function createStorefrontPublicRoutes(options?: StorefrontService
|
|
|
1278
1278
|
} & {
|
|
1279
1279
|
"/offers/:slug": {
|
|
1280
1280
|
$get: {
|
|
1281
|
+
input: {
|
|
1282
|
+
param: {
|
|
1283
|
+
slug: string;
|
|
1284
|
+
};
|
|
1285
|
+
};
|
|
1286
|
+
output: {
|
|
1287
|
+
error: string;
|
|
1288
|
+
};
|
|
1289
|
+
outputFormat: "json";
|
|
1290
|
+
status: 404;
|
|
1291
|
+
} | {
|
|
1281
1292
|
input: {
|
|
1282
1293
|
param: {
|
|
1283
1294
|
slug: string;
|
|
@@ -1306,17 +1317,6 @@ export declare function createStorefrontPublicRoutes(options?: StorefrontService
|
|
|
1306
1317
|
};
|
|
1307
1318
|
outputFormat: "json";
|
|
1308
1319
|
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
1309
|
-
} | {
|
|
1310
|
-
input: {
|
|
1311
|
-
param: {
|
|
1312
|
-
slug: string;
|
|
1313
|
-
};
|
|
1314
|
-
};
|
|
1315
|
-
output: {
|
|
1316
|
-
error: string;
|
|
1317
|
-
};
|
|
1318
|
-
outputFormat: "json";
|
|
1319
|
-
status: 404;
|
|
1320
1320
|
};
|
|
1321
1321
|
};
|
|
1322
1322
|
} & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAQnC,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAQnC,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAA;AAuCrB,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAO1F;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAC3C,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,CAAC,CAAC,CAmBZ;AAED,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,cAAc,CAAA;IACxB,SAAS,EAAE;QACT,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,GAAG,eAAe,CAAA;CACpB,CAAA;AA+CD,wBAAgB,4BAA4B,CAAC,OAAO,CAAC,EAAE,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BA2W9E;AAED,MAAM,MAAM,sBAAsB,GAAG,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAA"}
|
package/dist/routes-public.js
CHANGED
|
@@ -15,6 +15,9 @@ import { storefrontTransportEligibilityInputSchema } from "./validation-transpor
|
|
|
15
15
|
* to success responses only.
|
|
16
16
|
*/
|
|
17
17
|
const PUBLIC_CACHE_CONTROL = "public, s-maxage=60, stale-while-revalidate=300";
|
|
18
|
+
function setPublicCacheHeaders(c) {
|
|
19
|
+
c.header("Cache-Control", PUBLIC_CACHE_CONTROL);
|
|
20
|
+
}
|
|
18
21
|
/**
|
|
19
22
|
* KV read-model TTL for the departure list (RFC voyant#1687 Phase 2.2).
|
|
20
23
|
* Departure availability shifts with every booking, so unlike the
|
|
@@ -144,14 +147,14 @@ export function createStorefrontPublicRoutes(options) {
|
|
|
144
147
|
const departure = await storefrontService.getDeparture(c.get("db"), c.req.param("departureId"));
|
|
145
148
|
if (!departure)
|
|
146
149
|
return c.json({ error: "Storefront departure not found" }, 404);
|
|
147
|
-
c
|
|
150
|
+
setPublicCacheHeaders(c);
|
|
148
151
|
return c.json({ data: departure });
|
|
149
152
|
})
|
|
150
153
|
.get("/products/:productId/departures", async (c) => {
|
|
151
154
|
const productId = c.req.param("productId");
|
|
152
155
|
const query = await parseQuery(c, storefrontDepartureListQuerySchema);
|
|
153
156
|
const result = await readThroughDepartures(c, departuresDocKey(productId, query), () => storefrontService.listProductDepartures(c.get("db"), productId, query));
|
|
154
|
-
c
|
|
157
|
+
setPublicCacheHeaders(c);
|
|
155
158
|
return c.json(result);
|
|
156
159
|
})
|
|
157
160
|
.post("/departures/:departureId/price", async (c) => {
|
|
@@ -301,14 +304,14 @@ export function createStorefrontPublicRoutes(options) {
|
|
|
301
304
|
})
|
|
302
305
|
.get("/products/:productId/extensions", async (c) => {
|
|
303
306
|
const query = await parseQuery(c, storefrontProductExtensionsQuerySchema);
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
});
|
|
307
|
+
const extensions = await storefrontService.getProductExtensions(c.get("db"), c.req.param("productId"), query.optionId);
|
|
308
|
+
setPublicCacheHeaders(c);
|
|
309
|
+
return c.json({ data: extensions });
|
|
307
310
|
})
|
|
308
311
|
.get("/products/:productId/availability", async (c) => {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
});
|
|
312
|
+
const availability = await storefrontService.getProductAvailabilitySummary(c.get("db"), c.req.param("productId"), await parseQuery(c, storefrontProductAvailabilitySummaryQuerySchema));
|
|
313
|
+
setPublicCacheHeaders(c);
|
|
314
|
+
return c.json({ data: availability });
|
|
312
315
|
})
|
|
313
316
|
.get("/products/:productId/departures/:departureId/itinerary", async (c) => {
|
|
314
317
|
const itinerary = await storefrontService.getDepartureItinerary(c.get("db"), {
|
|
@@ -317,19 +320,19 @@ export function createStorefrontPublicRoutes(options) {
|
|
|
317
320
|
});
|
|
318
321
|
if (!itinerary)
|
|
319
322
|
return c.json({ error: "Storefront itinerary not found" }, 404);
|
|
320
|
-
c
|
|
323
|
+
setPublicCacheHeaders(c);
|
|
321
324
|
return c.json({ data: itinerary });
|
|
322
325
|
})
|
|
323
326
|
.get("/products/:productId/offers", async (c) => {
|
|
324
327
|
const query = await parseQuery(c, storefrontPromotionalOfferListQuerySchema);
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
context: getRequestContext(c),
|
|
331
|
-
}),
|
|
328
|
+
const offers = await storefrontService.listApplicableOffers({
|
|
329
|
+
productId: c.req.param("productId"),
|
|
330
|
+
departureId: query.departureId,
|
|
331
|
+
locale: query.locale,
|
|
332
|
+
context: getRequestContext(c),
|
|
332
333
|
});
|
|
334
|
+
setPublicCacheHeaders(c);
|
|
335
|
+
return c.json({ data: offers });
|
|
333
336
|
})
|
|
334
337
|
.get("/offers/:slug", async (c) => {
|
|
335
338
|
const query = await parseQuery(c, storefrontPromotionalOfferListQuerySchema);
|
|
@@ -338,7 +341,10 @@ export function createStorefrontPublicRoutes(options) {
|
|
|
338
341
|
locale: query.locale,
|
|
339
342
|
context: getRequestContext(c),
|
|
340
343
|
});
|
|
341
|
-
|
|
344
|
+
if (!offer)
|
|
345
|
+
return c.json({ error: "Storefront offer not found" }, 404);
|
|
346
|
+
setPublicCacheHeaders(c);
|
|
347
|
+
return c.json({ data: offer });
|
|
342
348
|
})
|
|
343
349
|
.post("/offers/:slug/apply", async (c) => {
|
|
344
350
|
const result = await storefrontService.applyOffer({
|
package/dist/service.d.ts
CHANGED
|
@@ -1041,7 +1041,7 @@ export declare function createStorefrontService(options?: StorefrontServiceOptio
|
|
|
1041
1041
|
id: string;
|
|
1042
1042
|
personId: string;
|
|
1043
1043
|
kind: "notify" | "wishlist" | "inquiry" | "request_offer" | "referral";
|
|
1044
|
-
source: "admin" | "
|
|
1044
|
+
source: "admin" | "form" | "phone" | "booking" | "website" | "abandoned_cart";
|
|
1045
1045
|
status: "expired" | "new" | "contacted" | "qualified" | "converted" | "lost";
|
|
1046
1046
|
duplicate: boolean;
|
|
1047
1047
|
}>;
|
|
@@ -1052,7 +1052,7 @@ export declare function createStorefrontService(options?: StorefrontServiceOptio
|
|
|
1052
1052
|
id: string;
|
|
1053
1053
|
personId: string;
|
|
1054
1054
|
kind: "notify" | "wishlist" | "inquiry" | "request_offer" | "referral";
|
|
1055
|
-
source: "admin" | "
|
|
1055
|
+
source: "admin" | "form" | "phone" | "booking" | "website" | "abandoned_cart";
|
|
1056
1056
|
status: "expired" | "new" | "contacted" | "qualified" | "converted" | "lost";
|
|
1057
1057
|
duplicate: boolean;
|
|
1058
1058
|
doubleOptIn: "requested" | "not_configured";
|
|
@@ -23,9 +23,9 @@ export declare const storefrontLeadIntakeInputSchema: z.ZodObject<{
|
|
|
23
23
|
}>>;
|
|
24
24
|
source: z.ZodDefault<z.ZodEnum<{
|
|
25
25
|
admin: "admin";
|
|
26
|
+
form: "form";
|
|
26
27
|
phone: "phone";
|
|
27
28
|
booking: "booking";
|
|
28
|
-
form: "form";
|
|
29
29
|
website: "website";
|
|
30
30
|
abandoned_cart: "abandoned_cart";
|
|
31
31
|
}>>;
|
|
@@ -59,9 +59,9 @@ export declare const storefrontNewsletterSubscribeInputSchema: z.ZodObject<{
|
|
|
59
59
|
lastName: z.ZodOptional<z.ZodString>;
|
|
60
60
|
source: z.ZodDefault<z.ZodEnum<{
|
|
61
61
|
admin: "admin";
|
|
62
|
+
form: "form";
|
|
62
63
|
phone: "phone";
|
|
63
64
|
booking: "booking";
|
|
64
|
-
form: "form";
|
|
65
65
|
website: "website";
|
|
66
66
|
abandoned_cart: "abandoned_cart";
|
|
67
67
|
}>>;
|
|
@@ -90,9 +90,9 @@ export declare const storefrontIntakeResponseSchema: z.ZodObject<{
|
|
|
90
90
|
}>;
|
|
91
91
|
source: z.ZodEnum<{
|
|
92
92
|
admin: "admin";
|
|
93
|
+
form: "form";
|
|
93
94
|
phone: "phone";
|
|
94
95
|
booking: "booking";
|
|
95
|
-
form: "form";
|
|
96
96
|
website: "website";
|
|
97
97
|
abandoned_cart: "abandoned_cart";
|
|
98
98
|
}>;
|
|
@@ -118,9 +118,9 @@ export declare const storefrontNewsletterSubscribeResponseSchema: z.ZodObject<{
|
|
|
118
118
|
}>;
|
|
119
119
|
source: z.ZodEnum<{
|
|
120
120
|
admin: "admin";
|
|
121
|
+
form: "form";
|
|
121
122
|
phone: "phone";
|
|
122
123
|
booking: "booking";
|
|
123
|
-
form: "form";
|
|
124
124
|
website: "website";
|
|
125
125
|
abandoned_cart: "abandoned_cart";
|
|
126
126
|
}>;
|
|
@@ -46,7 +46,7 @@ export declare function createStorefrontVerificationPublicRoutes(options?: Store
|
|
|
46
46
|
error: string;
|
|
47
47
|
};
|
|
48
48
|
outputFormat: "json";
|
|
49
|
-
status:
|
|
49
|
+
status: 400 | 404 | 409 | 410 | 501;
|
|
50
50
|
} | {
|
|
51
51
|
input: {};
|
|
52
52
|
output: {
|
|
@@ -95,7 +95,7 @@ export declare function createStorefrontVerificationPublicRoutes(options?: Store
|
|
|
95
95
|
error: string;
|
|
96
96
|
};
|
|
97
97
|
outputFormat: "json";
|
|
98
|
-
status:
|
|
98
|
+
status: 400 | 404 | 409 | 410 | 501;
|
|
99
99
|
} | {
|
|
100
100
|
input: {};
|
|
101
101
|
output: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyant-travel/storefront",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.122.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -34,6 +34,11 @@
|
|
|
34
34
|
"import": "./dist/customer-portal/routes.js",
|
|
35
35
|
"default": "./dist/customer-portal/routes.js"
|
|
36
36
|
},
|
|
37
|
+
"./payment-link": {
|
|
38
|
+
"types": "./dist/payment-link/routes.d.ts",
|
|
39
|
+
"import": "./dist/payment-link/routes.js",
|
|
40
|
+
"default": "./dist/payment-link/routes.js"
|
|
41
|
+
},
|
|
37
42
|
"./public-routes": {
|
|
38
43
|
"types": "./dist/routes-public.d.ts",
|
|
39
44
|
"import": "./dist/routes-public.js",
|
|
@@ -90,19 +95,19 @@
|
|
|
90
95
|
"drizzle-orm": "^0.45.2",
|
|
91
96
|
"hono": "^4.12.10",
|
|
92
97
|
"zod": "^4.3.6",
|
|
93
|
-
"@voyant-travel/bookings": "^0.120.1",
|
|
94
|
-
"@voyant-travel/commerce": "^0.2.2",
|
|
95
|
-
"@voyant-travel/db": "^0.108.1",
|
|
96
|
-
"@voyant-travel/finance": "^0.120.1",
|
|
97
98
|
"@voyant-travel/core": "^0.109.0",
|
|
98
|
-
"@voyant-travel/
|
|
99
|
+
"@voyant-travel/bookings": "^0.121.0",
|
|
100
|
+
"@voyant-travel/db": "^0.108.1",
|
|
101
|
+
"@voyant-travel/commerce": "^0.3.0",
|
|
102
|
+
"@voyant-travel/finance": "^0.121.0",
|
|
103
|
+
"@voyant-travel/hono": "^0.111.0",
|
|
99
104
|
"@voyant-travel/utils": "^0.105.2",
|
|
100
105
|
"@voyant-travel/relationships-contracts": "^0.107.0"
|
|
101
106
|
},
|
|
102
107
|
"peerDependencies": {
|
|
103
|
-
"@voyant-travel/
|
|
104
|
-
"@voyant-travel/
|
|
105
|
-
"@voyant-travel/
|
|
108
|
+
"@voyant-travel/legal": "^0.121.0",
|
|
109
|
+
"@voyant-travel/relationships": "^0.119.4",
|
|
110
|
+
"@voyant-travel/identity": "^0.121.0"
|
|
106
111
|
},
|
|
107
112
|
"peerDependenciesMeta": {
|
|
108
113
|
"@voyant-travel/identity": {
|
|
@@ -118,12 +123,12 @@
|
|
|
118
123
|
"devDependencies": {
|
|
119
124
|
"typescript": "^6.0.2",
|
|
120
125
|
"vitest": "^4.1.2",
|
|
121
|
-
"@voyant-travel/identity": "^0.
|
|
122
|
-
"@voyant-travel/
|
|
123
|
-
"@voyant-travel/legal": "^0.
|
|
124
|
-
"@voyant-travel/
|
|
125
|
-
"@voyant-travel/relationships": "^0.119.
|
|
126
|
-
"@voyant-travel/
|
|
126
|
+
"@voyant-travel/identity": "^0.121.0",
|
|
127
|
+
"@voyant-travel/operations": "^0.1.1",
|
|
128
|
+
"@voyant-travel/legal": "^0.121.0",
|
|
129
|
+
"@voyant-travel/voyant-typescript-config": "^0.1.0",
|
|
130
|
+
"@voyant-travel/relationships": "^0.119.4",
|
|
131
|
+
"@voyant-travel/inventory": "^0.3.0"
|
|
127
132
|
},
|
|
128
133
|
"files": [
|
|
129
134
|
"dist"
|