@voyantjs/bookings 0.31.4 → 0.32.1
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/checkout-capability.d.ts +16 -0
- package/dist/checkout-capability.d.ts.map +1 -0
- package/dist/checkout-capability.js +61 -0
- package/dist/routes-groups.d.ts +4 -4
- package/dist/routes-public.d.ts +20 -13
- package/dist/routes-public.d.ts.map +1 -1
- package/dist/routes-public.js +38 -8
- package/dist/routes-shared.d.ts +1 -19
- package/dist/routes-shared.d.ts.map +1 -1
- package/dist/routes.d.ts +45 -45
- package/dist/schema-core.d.ts +3 -3
- package/dist/schema-items.d.ts +5 -5
- package/dist/service-public.d.ts +32 -32
- package/dist/service.d.ts +54 -54
- package/dist/validation-public.d.ts +61 -24
- package/dist/validation-public.d.ts.map +1 -1
- package/dist/validation-public.js +13 -0
- package/dist/validation-shared.d.ts +7 -7
- package/dist/validation.d.ts +34 -34
- package/package.json +11 -6
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
export declare const CHECKOUT_CAPABILITY_COOKIE = "voyant_checkout_session";
|
|
3
|
+
export declare const CHECKOUT_CAPABILITY_HEADER = "X-Voyant-Checkout-Capability";
|
|
4
|
+
export declare const CHECKOUT_CAPABILITY_SCOPE = "booking-checkout-session";
|
|
5
|
+
export declare const checkoutCapabilityActions: readonly ["session:read", "session:update", "session:reprice", "session:finalize", "payment:read", "payment:start"];
|
|
6
|
+
export type CheckoutCapabilityAction = (typeof checkoutCapabilityActions)[number];
|
|
7
|
+
export declare function resolveCheckoutCapabilitySecret(env: Record<string, string | undefined>): string;
|
|
8
|
+
export declare function resolveCheckoutCapabilityTtlSeconds(env: Record<string, string | undefined>): number;
|
|
9
|
+
export declare function issueCheckoutCapability(bookingId: string, env: Record<string, string | undefined>): Promise<{
|
|
10
|
+
token: string;
|
|
11
|
+
payload: import("@voyantjs/hono").PublicCapabilityPayload;
|
|
12
|
+
expiresAt: Date;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function requireCheckoutCapability(c: Context, bookingId: string, action: CheckoutCapabilityAction, env: Record<string, string | undefined>): Promise<import("@voyantjs/hono").PublicCapabilityPayload>;
|
|
15
|
+
export declare function checkoutCapabilityCookie(token: string, expiresAt: Date): string;
|
|
16
|
+
//# sourceMappingURL=checkout-capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout-capability.d.ts","sourceRoot":"","sources":["../src/checkout-capability.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,eAAO,MAAM,0BAA0B,4BAA4B,CAAA;AACnE,eAAO,MAAM,0BAA0B,iCAAiC,CAAA;AACxE,eAAO,MAAM,yBAAyB,6BAA6B,CAAA;AAEnE,eAAO,MAAM,yBAAyB,qHAO5B,CAAA;AAEV,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAA;AAKjF,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,UAQtF;AAED,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,UAQ1F;AAED,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;;;;GASxC;AAED,wBAAsB,yBAAyB,CAC7C,CAAC,EAAE,OAAO,EACV,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,wBAAwB,EAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,6DAiBxC;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,UAOtE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createPublicCapabilityToken, extractPublicCapabilityToken, serializePublicCapabilityCookie, UnauthorizedApiError, verifyPublicCapabilityToken, } from "@voyantjs/hono";
|
|
2
|
+
export const CHECKOUT_CAPABILITY_COOKIE = "voyant_checkout_session";
|
|
3
|
+
export const CHECKOUT_CAPABILITY_HEADER = "X-Voyant-Checkout-Capability";
|
|
4
|
+
export const CHECKOUT_CAPABILITY_SCOPE = "booking-checkout-session";
|
|
5
|
+
export const checkoutCapabilityActions = [
|
|
6
|
+
"session:read",
|
|
7
|
+
"session:update",
|
|
8
|
+
"session:reprice",
|
|
9
|
+
"session:finalize",
|
|
10
|
+
"payment:read",
|
|
11
|
+
"payment:start",
|
|
12
|
+
];
|
|
13
|
+
const DEFAULT_TTL_SECONDS = 30 * 60;
|
|
14
|
+
const MAX_TTL_SECONDS = 2 * 60 * 60;
|
|
15
|
+
export function resolveCheckoutCapabilitySecret(env) {
|
|
16
|
+
return (env.VOYANT_CHECKOUT_CAPABILITY_SECRET ??
|
|
17
|
+
env.CHECKOUT_CAPABILITY_SECRET ??
|
|
18
|
+
env.SESSION_CLAIMS_SECRET ??
|
|
19
|
+
env.BETTER_AUTH_SECRET ??
|
|
20
|
+
"");
|
|
21
|
+
}
|
|
22
|
+
export function resolveCheckoutCapabilityTtlSeconds(env) {
|
|
23
|
+
const raw = env.VOYANT_CHECKOUT_CAPABILITY_TTL_SECONDS ?? env.CHECKOUT_CAPABILITY_TTL_SECONDS;
|
|
24
|
+
const parsed = raw ? Number(raw) : DEFAULT_TTL_SECONDS;
|
|
25
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
26
|
+
return DEFAULT_TTL_SECONDS;
|
|
27
|
+
}
|
|
28
|
+
return Math.min(Math.floor(parsed), MAX_TTL_SECONDS);
|
|
29
|
+
}
|
|
30
|
+
export async function issueCheckoutCapability(bookingId, env) {
|
|
31
|
+
return createPublicCapabilityToken({
|
|
32
|
+
secret: resolveCheckoutCapabilitySecret(env),
|
|
33
|
+
scope: CHECKOUT_CAPABILITY_SCOPE,
|
|
34
|
+
subjectId: bookingId,
|
|
35
|
+
actions: [...checkoutCapabilityActions],
|
|
36
|
+
ttlSeconds: resolveCheckoutCapabilityTtlSeconds(env),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export async function requireCheckoutCapability(c, bookingId, action, env) {
|
|
40
|
+
const token = extractPublicCapabilityToken(c, {
|
|
41
|
+
headerName: CHECKOUT_CAPABILITY_HEADER,
|
|
42
|
+
cookieName: CHECKOUT_CAPABILITY_COOKIE,
|
|
43
|
+
});
|
|
44
|
+
if (!token) {
|
|
45
|
+
throw new UnauthorizedApiError("Missing checkout session capability");
|
|
46
|
+
}
|
|
47
|
+
return verifyPublicCapabilityToken(token, {
|
|
48
|
+
secret: resolveCheckoutCapabilitySecret(env),
|
|
49
|
+
scope: CHECKOUT_CAPABILITY_SCOPE,
|
|
50
|
+
subjectId: bookingId,
|
|
51
|
+
action,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export function checkoutCapabilityCookie(token, expiresAt) {
|
|
55
|
+
return serializePublicCapabilityCookie({
|
|
56
|
+
name: CHECKOUT_CAPABILITY_COOKIE,
|
|
57
|
+
token,
|
|
58
|
+
expiresAt,
|
|
59
|
+
path: "/v1/public",
|
|
60
|
+
});
|
|
61
|
+
}
|
package/dist/routes-groups.d.ts
CHANGED
|
@@ -83,7 +83,7 @@ export declare const bookingGroupRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
83
83
|
groupId: string;
|
|
84
84
|
booking: {
|
|
85
85
|
id: string;
|
|
86
|
-
status: "cancelled" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "
|
|
86
|
+
status: "cancelled" | "completed" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "expired";
|
|
87
87
|
createdAt: string;
|
|
88
88
|
updatedAt: string;
|
|
89
89
|
organizationId: string | null;
|
|
@@ -223,7 +223,7 @@ export declare const bookingGroupRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
223
223
|
groupId: string;
|
|
224
224
|
booking: {
|
|
225
225
|
id: string;
|
|
226
|
-
status: "cancelled" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "
|
|
226
|
+
status: "cancelled" | "completed" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "expired";
|
|
227
227
|
createdAt: string;
|
|
228
228
|
updatedAt: string;
|
|
229
229
|
organizationId: string | null;
|
|
@@ -361,10 +361,10 @@ export declare const bookingGroupRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
361
361
|
email: string | null;
|
|
362
362
|
firstName: string;
|
|
363
363
|
lastName: string;
|
|
364
|
-
personId: string | null;
|
|
365
364
|
bookingId: string;
|
|
365
|
+
personId: string | null;
|
|
366
366
|
participantType: "other" | "traveler" | "occupant";
|
|
367
|
-
travelerCategory: "
|
|
367
|
+
travelerCategory: "child" | "other" | "adult" | "infant" | "senior" | null;
|
|
368
368
|
phone: string | null;
|
|
369
369
|
preferredLanguage: string | null;
|
|
370
370
|
specialRequests: string | null;
|
package/dist/routes-public.d.ts
CHANGED
|
@@ -18,7 +18,14 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
18
18
|
} | {
|
|
19
19
|
input: {};
|
|
20
20
|
output: {
|
|
21
|
-
data:
|
|
21
|
+
data: {
|
|
22
|
+
sessionId: string;
|
|
23
|
+
checkoutCapability: {
|
|
24
|
+
token: string;
|
|
25
|
+
expiresAt: string;
|
|
26
|
+
actions: ("session:read" | "session:update" | "session:reprice" | "session:finalize" | "payment:read" | "payment:start")[];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
22
29
|
};
|
|
23
30
|
outputFormat: "json";
|
|
24
31
|
status: 201;
|
|
@@ -36,7 +43,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
36
43
|
data: {
|
|
37
44
|
sessionId: string;
|
|
38
45
|
bookingNumber: string;
|
|
39
|
-
status: "cancelled" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "
|
|
46
|
+
status: "cancelled" | "completed" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "expired";
|
|
40
47
|
externalBookingRef: string | null;
|
|
41
48
|
communicationLanguage: string | null;
|
|
42
49
|
sellCurrency: string;
|
|
@@ -52,7 +59,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
52
59
|
travelers: {
|
|
53
60
|
id: string;
|
|
54
61
|
participantType: "other" | "traveler" | "occupant";
|
|
55
|
-
travelerCategory: "
|
|
62
|
+
travelerCategory: "child" | "other" | "adult" | "infant" | "senior" | null;
|
|
56
63
|
firstName: string;
|
|
57
64
|
lastName: string;
|
|
58
65
|
email: string | null;
|
|
@@ -66,7 +73,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
66
73
|
id: string;
|
|
67
74
|
title: string;
|
|
68
75
|
description: string | null;
|
|
69
|
-
itemType: "service" | "
|
|
76
|
+
itemType: "service" | "other" | "unit" | "extra" | "fee" | "tax" | "discount" | "adjustment" | "accommodation" | "transport";
|
|
70
77
|
status: "cancelled" | "draft" | "on_hold" | "confirmed" | "expired" | "fulfilled";
|
|
71
78
|
serviceDate: string | null;
|
|
72
79
|
startsAt: string | null;
|
|
@@ -99,7 +106,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
99
106
|
pricingCategoryId: string | null;
|
|
100
107
|
availabilitySlotId: string | null;
|
|
101
108
|
quantity: number;
|
|
102
|
-
allocationType: "
|
|
109
|
+
allocationType: "resource" | "unit" | "pickup";
|
|
103
110
|
status: "cancelled" | "confirmed" | "expired" | "fulfilled" | "held" | "released";
|
|
104
111
|
holdExpiresAt: string | null;
|
|
105
112
|
confirmedAt: string | null;
|
|
@@ -321,7 +328,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
321
328
|
session: {
|
|
322
329
|
sessionId: string;
|
|
323
330
|
bookingNumber: string;
|
|
324
|
-
status: "cancelled" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "
|
|
331
|
+
status: "cancelled" | "completed" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "expired";
|
|
325
332
|
externalBookingRef: string | null;
|
|
326
333
|
communicationLanguage: string | null;
|
|
327
334
|
sellCurrency: string;
|
|
@@ -337,7 +344,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
337
344
|
travelers: {
|
|
338
345
|
id: string;
|
|
339
346
|
participantType: "other" | "traveler" | "occupant";
|
|
340
|
-
travelerCategory: "
|
|
347
|
+
travelerCategory: "child" | "other" | "adult" | "infant" | "senior" | null;
|
|
341
348
|
firstName: string;
|
|
342
349
|
lastName: string;
|
|
343
350
|
email: string | null;
|
|
@@ -351,7 +358,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
351
358
|
id: string;
|
|
352
359
|
title: string;
|
|
353
360
|
description: string | null;
|
|
354
|
-
itemType: "service" | "
|
|
361
|
+
itemType: "service" | "other" | "unit" | "extra" | "fee" | "tax" | "discount" | "adjustment" | "accommodation" | "transport";
|
|
355
362
|
status: "cancelled" | "draft" | "on_hold" | "confirmed" | "expired" | "fulfilled";
|
|
356
363
|
serviceDate: string | null;
|
|
357
364
|
startsAt: string | null;
|
|
@@ -384,7 +391,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
384
391
|
pricingCategoryId: string | null;
|
|
385
392
|
availabilitySlotId: string | null;
|
|
386
393
|
quantity: number;
|
|
387
|
-
allocationType: "
|
|
394
|
+
allocationType: "resource" | "unit" | "pickup";
|
|
388
395
|
status: "cancelled" | "confirmed" | "expired" | "fulfilled" | "held" | "released";
|
|
389
396
|
holdExpiresAt: string | null;
|
|
390
397
|
confirmedAt: string | null;
|
|
@@ -505,7 +512,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
505
512
|
data: {
|
|
506
513
|
bookingId: string;
|
|
507
514
|
bookingNumber: string;
|
|
508
|
-
status: "cancelled" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "
|
|
515
|
+
status: "cancelled" | "completed" | "draft" | "on_hold" | "awaiting_payment" | "confirmed" | "in_progress" | "expired";
|
|
509
516
|
sellCurrency: string;
|
|
510
517
|
sellAmountCents: number | null;
|
|
511
518
|
startDate: string | null;
|
|
@@ -525,7 +532,7 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
525
532
|
id: string;
|
|
526
533
|
title: string;
|
|
527
534
|
description: string | null;
|
|
528
|
-
itemType: "service" | "
|
|
535
|
+
itemType: "service" | "other" | "unit" | "extra" | "fee" | "tax" | "discount" | "adjustment" | "accommodation" | "transport";
|
|
529
536
|
status: "cancelled" | "draft" | "on_hold" | "confirmed" | "expired" | "fulfilled";
|
|
530
537
|
serviceDate: string | null;
|
|
531
538
|
startsAt: string | null;
|
|
@@ -561,8 +568,8 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
561
568
|
bookingItemId: string | null;
|
|
562
569
|
travelerId: string | null;
|
|
563
570
|
fulfillmentType: "other" | "voucher" | "ticket" | "pdf" | "qr_code" | "barcode" | "mobile";
|
|
564
|
-
deliveryChannel: "
|
|
565
|
-
status: "pending" | "
|
|
571
|
+
deliveryChannel: "api" | "email" | "other" | "download" | "wallet";
|
|
572
|
+
status: "pending" | "failed" | "issued" | "reissued" | "revoked";
|
|
566
573
|
artifactUrl: string | null;
|
|
567
574
|
}[];
|
|
568
575
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,GAAG,EAA2B,MAAM,oBAAoB,CAAA;AAoEtE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;+BAyBsC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAkJxE,CAAA;AAEJ,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAA"}
|
package/dist/routes-public.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { idempotencyKey, parseJsonBody, parseQuery } from "@voyantjs/hono";
|
|
1
|
+
import { idempotencyKey, parseJsonBody, parseQuery, UnauthorizedApiError } from "@voyantjs/hono";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
|
-
import {
|
|
3
|
+
import { checkoutCapabilityActions, checkoutCapabilityCookie, issueCheckoutCapability, requireCheckoutCapability, } from "./checkout-capability.js";
|
|
4
|
+
import { getRuntimeEnv, notFound } from "./routes-shared.js";
|
|
4
5
|
import { publicBookingsService } from "./service-public.js";
|
|
5
6
|
import { publicBookingOverviewLookupQuerySchema, publicBookingSessionMutationSchema, publicCreateBookingSessionSchema, publicRepriceBookingSessionSchema, publicUpdateBookingSessionSchema, publicUpsertBookingSessionStateSchema, } from "./validation-public.js";
|
|
6
7
|
function hasSessionResult(result) {
|
|
@@ -26,6 +27,29 @@ function sessionConflictError(status) {
|
|
|
26
27
|
return "Unable to process booking session";
|
|
27
28
|
}
|
|
28
29
|
}
|
|
30
|
+
function attachCheckoutCapability(session, issued) {
|
|
31
|
+
return {
|
|
32
|
+
...session,
|
|
33
|
+
checkoutCapability: {
|
|
34
|
+
token: issued.token,
|
|
35
|
+
expiresAt: issued.expiresAt.toISOString(),
|
|
36
|
+
actions: [...checkoutCapabilityActions],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async function requireSessionCapability(c, action) {
|
|
41
|
+
const sessionId = c.req.param("sessionId");
|
|
42
|
+
if (!sessionId) {
|
|
43
|
+
throw new UnauthorizedApiError("Missing checkout session id");
|
|
44
|
+
}
|
|
45
|
+
await requireCheckoutCapability(c, sessionId, action, getRuntimeEnv(c));
|
|
46
|
+
}
|
|
47
|
+
function sessionCapability(action) {
|
|
48
|
+
return async (c, next) => {
|
|
49
|
+
await requireSessionCapability(c, action);
|
|
50
|
+
await next();
|
|
51
|
+
};
|
|
52
|
+
}
|
|
29
53
|
export const publicBookingRoutes = new Hono()
|
|
30
54
|
.post("/sessions", idempotencyKey({ scope: "POST /v1/public/bookings/sessions" }), async (c) => {
|
|
31
55
|
const result = await publicBookingsService.createSession(c.get("db"), await parseJsonBody(c, publicCreateBookingSessionSchema), c.get("userId"));
|
|
@@ -35,13 +59,18 @@ export const publicBookingRoutes = new Hono()
|
|
|
35
59
|
if (!hasSessionResult(result)) {
|
|
36
60
|
return c.json({ error: sessionConflictError(result.status) }, 409);
|
|
37
61
|
}
|
|
38
|
-
|
|
62
|
+
const capability = await issueCheckoutCapability(result.session.sessionId, getRuntimeEnv(c));
|
|
63
|
+
c.header("Set-Cookie", checkoutCapabilityCookie(capability.token, capability.expiresAt), {
|
|
64
|
+
append: true,
|
|
65
|
+
});
|
|
66
|
+
return c.json({ data: attachCheckoutCapability(result.session, capability) }, 201);
|
|
39
67
|
})
|
|
40
68
|
.get("/sessions/:sessionId", async (c) => {
|
|
69
|
+
await requireSessionCapability(c, "session:read");
|
|
41
70
|
const session = await publicBookingsService.getSessionById(c.get("db"), c.req.param("sessionId"));
|
|
42
71
|
return session ? c.json({ data: session }) : notFound(c, "Booking session not found");
|
|
43
72
|
})
|
|
44
|
-
.patch("/sessions/:sessionId", async (c) => {
|
|
73
|
+
.patch("/sessions/:sessionId", sessionCapability("session:update"), idempotencyKey(), async (c) => {
|
|
45
74
|
const result = await publicBookingsService.updateSession(c.get("db"), c.req.param("sessionId"), await parseJsonBody(c, publicUpdateBookingSessionSchema), c.get("userId"));
|
|
46
75
|
if (result.status === "not_found") {
|
|
47
76
|
return notFound(c, "Booking session not found");
|
|
@@ -52,17 +81,18 @@ export const publicBookingRoutes = new Hono()
|
|
|
52
81
|
return c.json({ data: result.session });
|
|
53
82
|
})
|
|
54
83
|
.get("/sessions/:sessionId/state", async (c) => {
|
|
84
|
+
await requireSessionCapability(c, "session:read");
|
|
55
85
|
const state = await publicBookingsService.getSessionState(c.get("db"), c.req.param("sessionId"));
|
|
56
86
|
return state ? c.json({ data: state }) : notFound(c, "Booking session not found");
|
|
57
87
|
})
|
|
58
|
-
.put("/sessions/:sessionId/state", async (c) => {
|
|
88
|
+
.put("/sessions/:sessionId/state", sessionCapability("session:update"), idempotencyKey(), async (c) => {
|
|
59
89
|
const result = await publicBookingsService.updateSessionState(c.get("db"), c.req.param("sessionId"), await parseJsonBody(c, publicUpsertBookingSessionStateSchema));
|
|
60
90
|
if (result.status === "not_found") {
|
|
61
91
|
return notFound(c, "Booking session not found");
|
|
62
92
|
}
|
|
63
93
|
return c.json({ data: result.state });
|
|
64
94
|
})
|
|
65
|
-
.post("/sessions/:sessionId/reprice", async (c) => {
|
|
95
|
+
.post("/sessions/:sessionId/reprice", sessionCapability("session:reprice"), idempotencyKey(), async (c) => {
|
|
66
96
|
const result = await publicBookingsService.repriceSession(c.get("db"), c.req.param("sessionId"), await parseJsonBody(c, publicRepriceBookingSessionSchema));
|
|
67
97
|
if (result.status === "not_found") {
|
|
68
98
|
return notFound(c, "Booking session not found");
|
|
@@ -80,7 +110,7 @@ export const publicBookingRoutes = new Hono()
|
|
|
80
110
|
},
|
|
81
111
|
});
|
|
82
112
|
})
|
|
83
|
-
.post("/sessions/:sessionId/confirm",
|
|
113
|
+
.post("/sessions/:sessionId/confirm", sessionCapability("session:finalize"), idempotencyKey(), async (c) => {
|
|
84
114
|
const result = await publicBookingsService.confirmSession(c.get("db"), c.req.param("sessionId"), await parseJsonBody(c, publicBookingSessionMutationSchema), c.get("userId"));
|
|
85
115
|
if (result.status === "not_found") {
|
|
86
116
|
return notFound(c, "Booking session not found");
|
|
@@ -90,7 +120,7 @@ export const publicBookingRoutes = new Hono()
|
|
|
90
120
|
}
|
|
91
121
|
return c.json({ data: result.session });
|
|
92
122
|
})
|
|
93
|
-
.post("/sessions/:sessionId/expire", async (c) => {
|
|
123
|
+
.post("/sessions/:sessionId/expire", sessionCapability("session:finalize"), idempotencyKey(), async (c) => {
|
|
94
124
|
const result = await publicBookingsService.expireSession(c.get("db"), c.req.param("sessionId"), await parseJsonBody(c, publicBookingSessionMutationSchema), c.get("userId"));
|
|
95
125
|
if (result.status === "not_found") {
|
|
96
126
|
return notFound(c, "Booking session not found");
|
package/dist/routes-shared.d.ts
CHANGED
|
@@ -44,25 +44,7 @@ export type Env = {
|
|
|
44
44
|
}) => boolean | Promise<boolean>;
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
|
-
export declare function getRuntimeEnv(c: Context
|
|
48
|
-
KMS_PROVIDER?: string | undefined;
|
|
49
|
-
KMS_ENV_KEY?: string | undefined;
|
|
50
|
-
KMS_LOCAL_KEY?: string | undefined;
|
|
51
|
-
GCP_PROJECT_ID?: string | undefined;
|
|
52
|
-
GCP_SERVICE_ACCOUNT_EMAIL?: string | undefined;
|
|
53
|
-
GCP_PRIVATE_KEY?: string | undefined;
|
|
54
|
-
GCP_KMS_KEYRING?: string | undefined;
|
|
55
|
-
GCP_KMS_LOCATION?: string | undefined;
|
|
56
|
-
GCP_KMS_PEOPLE_KEY_NAME?: string | undefined;
|
|
57
|
-
GCP_KMS_INTEGRATIONS_KEY_NAME?: string | undefined;
|
|
58
|
-
AWS_REGION?: string | undefined;
|
|
59
|
-
AWS_ACCESS_KEY_ID?: string | undefined;
|
|
60
|
-
AWS_SECRET_ACCESS_KEY?: string | undefined;
|
|
61
|
-
AWS_SESSION_TOKEN?: string | undefined;
|
|
62
|
-
AWS_KMS_ENDPOINT?: string | undefined;
|
|
63
|
-
AWS_KMS_PEOPLE_KEY_ID?: string | undefined;
|
|
64
|
-
AWS_KMS_INTEGRATIONS_KEY_ID?: string | undefined;
|
|
65
|
-
};
|
|
47
|
+
export declare function getRuntimeEnv(c: Context): any;
|
|
66
48
|
export declare function notFound<T extends Env>(c: Context<T>, error: string): Response & import("hono").TypedResponse<{
|
|
67
49
|
error: string;
|
|
68
50
|
}, 404, "json">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-shared.d.ts","sourceRoot":"","sources":["../src/routes-shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,yBAAyB,EAAE,MAAM,CAAA;IACjC,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,6BAA6B,EAAE,MAAM,CAAA;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,EAAE,MAAM,CAAA;IACzB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;CACpC,CAAC,CAAA;AAEF,MAAM,MAAM,GAAG,GAAG;IAChB,QAAQ,EAAE,WAAW,CAAA;IACrB,SAAS,EAAE;QACT,SAAS,CAAC,EAAE,eAAe,CAAA;QAC3B,EAAE,EAAE,kBAAkB,CAAA;QACtB,QAAQ,CAAC,EAAE,QAAQ,CAAA;QACnB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;QACrD,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;QAC/C,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;QACxB,iBAAiB,CAAC,EAAE,OAAO,CAAA;QAC3B,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE;YAC3B,EAAE,EAAE,kBAAkB,CAAA;YACtB,MAAM,CAAC,EAAE,MAAM,CAAA;YACf,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;YACrD,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;YAC/C,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;YACxB,iBAAiB,CAAC,EAAE,OAAO,CAAA;YAC3B,SAAS,EAAE,MAAM,CAAA;YACjB,UAAU,EAAE,MAAM,CAAA;YAClB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAA;SACrC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KACjC,CAAA;CACF,CAAA;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"routes-shared.d.ts","sourceRoot":"","sources":["../src/routes-shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,yBAAyB,EAAE,MAAM,CAAA;IACjC,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,6BAA6B,EAAE,MAAM,CAAA;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,EAAE,MAAM,CAAA;IACzB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;CACpC,CAAC,CAAA;AAEF,MAAM,MAAM,GAAG,GAAG;IAChB,QAAQ,EAAE,WAAW,CAAA;IACrB,SAAS,EAAE;QACT,SAAS,CAAC,EAAE,eAAe,CAAA;QAC3B,EAAE,EAAE,kBAAkB,CAAA;QACtB,QAAQ,CAAC,EAAE,QAAQ,CAAA;QACnB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;QACrD,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;QAC/C,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;QACxB,iBAAiB,CAAC,EAAE,OAAO,CAAA;QAC3B,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE;YAC3B,EAAE,EAAE,kBAAkB,CAAA;YACtB,MAAM,CAAC,EAAE,MAAM,CAAA;YACf,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;YACrD,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;YAC/C,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;YACxB,iBAAiB,CAAC,EAAE,OAAO,CAAA;YAC3B,SAAS,EAAE,MAAM,CAAA;YACjB,UAAU,EAAE,MAAM,CAAA;YAClB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAA;SACrC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KACjC,CAAA;CACF,CAAA;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,OAYvC;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM;;gBAEnE"}
|