@thebookingkit/server 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/adapters/calendar-adapter.d.ts +47 -0
- package/dist/adapters/calendar-adapter.d.ts.map +1 -0
- package/dist/adapters/calendar-adapter.js +2 -0
- package/dist/adapters/calendar-adapter.js.map +1 -0
- package/dist/adapters/email-adapter.d.ts +65 -0
- package/dist/adapters/email-adapter.d.ts.map +1 -0
- package/dist/adapters/email-adapter.js +41 -0
- package/dist/adapters/email-adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +9 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +3 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/job-adapter.d.ts +26 -0
- package/dist/adapters/job-adapter.d.ts.map +1 -0
- package/dist/adapters/job-adapter.js +13 -0
- package/dist/adapters/job-adapter.js.map +1 -0
- package/dist/adapters/payment-adapter.d.ts +106 -0
- package/dist/adapters/payment-adapter.d.ts.map +1 -0
- package/dist/adapters/payment-adapter.js +8 -0
- package/dist/adapters/payment-adapter.js.map +1 -0
- package/dist/adapters/sms-adapter.d.ts +33 -0
- package/dist/adapters/sms-adapter.d.ts.map +1 -0
- package/dist/adapters/sms-adapter.js +8 -0
- package/dist/adapters/sms-adapter.js.map +1 -0
- package/{src/adapters/storage-adapter.ts → dist/adapters/storage-adapter.d.ts} +5 -4
- package/dist/adapters/storage-adapter.d.ts.map +1 -0
- package/dist/adapters/storage-adapter.js +2 -0
- package/dist/adapters/storage-adapter.js.map +1 -0
- package/dist/api.d.ts +223 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +286 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.d.ts +71 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +90 -0
- package/dist/auth.js.map +1 -0
- package/dist/booking-tokens.d.ts +23 -0
- package/dist/booking-tokens.d.ts.map +1 -0
- package/dist/booking-tokens.js +52 -0
- package/dist/booking-tokens.js.map +1 -0
- package/dist/email-templates.d.ts +32 -0
- package/dist/email-templates.d.ts.map +1 -0
- package/{src/email-templates.ts → dist/email-templates.js} +14 -34
- package/dist/email-templates.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/multi-tenancy.d.ts +123 -0
- package/dist/multi-tenancy.d.ts.map +1 -0
- package/dist/multi-tenancy.js +197 -0
- package/dist/multi-tenancy.js.map +1 -0
- package/dist/notification-jobs.d.ts +143 -0
- package/dist/notification-jobs.d.ts.map +1 -0
- package/dist/notification-jobs.js +278 -0
- package/dist/notification-jobs.js.map +1 -0
- package/dist/serialization-retry.d.ts +28 -0
- package/dist/serialization-retry.d.ts.map +1 -0
- package/dist/serialization-retry.js +71 -0
- package/dist/serialization-retry.js.map +1 -0
- package/dist/webhooks.d.ts +164 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +239 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/workflows.d.ts +169 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +271 -0
- package/dist/workflows.js.map +1 -0
- package/package.json +21 -2
- package/CHANGELOG.md +0 -9
- package/src/__tests__/api.test.ts +0 -354
- package/src/__tests__/auth.test.ts +0 -111
- package/src/__tests__/concurrent-booking.test.ts +0 -170
- package/src/__tests__/multi-tenancy.test.ts +0 -267
- package/src/__tests__/serialization-retry.test.ts +0 -76
- package/src/__tests__/webhooks.test.ts +0 -412
- package/src/__tests__/workflows.test.ts +0 -422
- package/src/adapters/calendar-adapter.ts +0 -49
- package/src/adapters/email-adapter.ts +0 -108
- package/src/adapters/index.ts +0 -36
- package/src/adapters/job-adapter.ts +0 -26
- package/src/adapters/payment-adapter.ts +0 -118
- package/src/adapters/sms-adapter.ts +0 -35
- package/src/api.ts +0 -446
- package/src/auth.ts +0 -146
- package/src/booking-tokens.ts +0 -61
- package/src/index.ts +0 -192
- package/src/multi-tenancy.ts +0 -301
- package/src/notification-jobs.ts +0 -428
- package/src/serialization-retry.ts +0 -94
- package/src/webhooks.ts +0 -378
- package/src/workflows.ts +0 -441
- package/tsconfig.json +0 -9
- package/vitest.config.ts +0 -7
package/dist/auth.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { UnauthorizedError, ForbiddenError } from "@thebookingkit/core";
|
|
2
|
+
const ROLE_HIERARCHY = {
|
|
3
|
+
admin: 3,
|
|
4
|
+
provider: 2,
|
|
5
|
+
member: 1,
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Middleware wrapper that injects the authenticated user into every request.
|
|
9
|
+
*
|
|
10
|
+
* - Rejects unauthenticated requests with 401.
|
|
11
|
+
* - Optionally checks user role.
|
|
12
|
+
* - Passes the authenticated user to the handler.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* // In a Next.js API route
|
|
17
|
+
* export const GET = withAuth(authAdapter, async (req) => {
|
|
18
|
+
* const userId = req.user.id;
|
|
19
|
+
* // Provider can only access their own data
|
|
20
|
+
* const bookings = await db.query.bookings.findMany({
|
|
21
|
+
* where: eq(bookings.providerId, userId)
|
|
22
|
+
* });
|
|
23
|
+
* return Response.json(bookings);
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function withAuth(adapter, handler, options) {
|
|
28
|
+
return async (req) => {
|
|
29
|
+
try {
|
|
30
|
+
// Try to get user from session first
|
|
31
|
+
let user = await adapter.getCurrentUser(req);
|
|
32
|
+
// If no session, try Bearer token
|
|
33
|
+
if (!user) {
|
|
34
|
+
const authHeader = req.headers.get("authorization");
|
|
35
|
+
if (authHeader?.startsWith("Bearer ")) {
|
|
36
|
+
const token = authHeader.slice(7);
|
|
37
|
+
user = await adapter.verifyToken(token);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!user) {
|
|
41
|
+
throw new UnauthorizedError();
|
|
42
|
+
}
|
|
43
|
+
// Check required role if specified — use hierarchy so admin satisfies provider requirement
|
|
44
|
+
if (options?.requiredRole) {
|
|
45
|
+
const userLevel = ROLE_HIERARCHY[user.role ?? ""] ?? 0;
|
|
46
|
+
const requiredLevel = ROLE_HIERARCHY[options.requiredRole] ?? 0;
|
|
47
|
+
if (userLevel < requiredLevel) {
|
|
48
|
+
throw new ForbiddenError();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Inject user into request
|
|
52
|
+
const authReq = req;
|
|
53
|
+
authReq.user = user;
|
|
54
|
+
return await handler(authReq);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error instanceof UnauthorizedError) {
|
|
58
|
+
return Response.json({ error: error.message, code: error.code }, { status: 401 });
|
|
59
|
+
}
|
|
60
|
+
if (error instanceof ForbiddenError) {
|
|
61
|
+
return Response.json({ error: error.message, code: error.code }, { status: 403 });
|
|
62
|
+
}
|
|
63
|
+
return Response.json({ error: "Internal server error", code: "INTERNAL_ERROR" }, { status: 500 });
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Helper to scope database queries to the authenticated user.
|
|
69
|
+
* Providers can only access their own rows (user_id matches).
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const provider = await assertOwnership(db, providers, req.user.id, providerId);
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function assertProviderOwnership(userId, resourceUserId) {
|
|
77
|
+
if (userId !== resourceUserId) {
|
|
78
|
+
throw new ForbiddenError("You do not have permission to access this provider's data.");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Helper to verify customer access to their own bookings.
|
|
83
|
+
* Customers can only access bookings where customer_email matches.
|
|
84
|
+
*/
|
|
85
|
+
export function assertCustomerAccess(userEmail, bookingCustomerEmail) {
|
|
86
|
+
if (userEmail !== bookingCustomerEmail) {
|
|
87
|
+
throw new ForbiddenError("You do not have permission to access this booking.");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a signed booking management token.
|
|
3
|
+
*
|
|
4
|
+
* The token is a signed payload containing the booking ID and expiry time.
|
|
5
|
+
* It allows customers to view/manage their booking without authentication.
|
|
6
|
+
*
|
|
7
|
+
* @param bookingId - The booking UUID
|
|
8
|
+
* @param expiresAt - When the token expires
|
|
9
|
+
* @param secret - HMAC signing secret
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateBookingToken(bookingId: string, expiresAt: Date, secret: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Verify and decode a booking management token.
|
|
14
|
+
*
|
|
15
|
+
* @param token - The base64url-encoded token
|
|
16
|
+
* @param secret - HMAC signing secret (must match generation)
|
|
17
|
+
* @returns The booking ID if valid, null if invalid or expired
|
|
18
|
+
*/
|
|
19
|
+
export declare function verifyBookingToken(token: string, secret: string): {
|
|
20
|
+
bookingId: string;
|
|
21
|
+
expiresAt: Date;
|
|
22
|
+
} | null;
|
|
23
|
+
//# sourceMappingURL=booking-tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-tokens.d.ts","sourceRoot":"","sources":["../src/booking-tokens.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,IAAI,EACf,MAAM,EAAE,MAAM,GACb,MAAM,CAMR;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CA0B/C"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Generate a signed booking management token.
|
|
4
|
+
*
|
|
5
|
+
* The token is a signed payload containing the booking ID and expiry time.
|
|
6
|
+
* It allows customers to view/manage their booking without authentication.
|
|
7
|
+
*
|
|
8
|
+
* @param bookingId - The booking UUID
|
|
9
|
+
* @param expiresAt - When the token expires
|
|
10
|
+
* @param secret - HMAC signing secret
|
|
11
|
+
*/
|
|
12
|
+
export function generateBookingToken(bookingId, expiresAt, secret) {
|
|
13
|
+
const payload = `${bookingId}:${expiresAt.getTime()}`;
|
|
14
|
+
const signature = createHmac("sha256", secret)
|
|
15
|
+
.update(payload)
|
|
16
|
+
.digest("hex");
|
|
17
|
+
return Buffer.from(`${payload}:${signature}`).toString("base64url");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Verify and decode a booking management token.
|
|
21
|
+
*
|
|
22
|
+
* @param token - The base64url-encoded token
|
|
23
|
+
* @param secret - HMAC signing secret (must match generation)
|
|
24
|
+
* @returns The booking ID if valid, null if invalid or expired
|
|
25
|
+
*/
|
|
26
|
+
export function verifyBookingToken(token, secret) {
|
|
27
|
+
try {
|
|
28
|
+
const decoded = Buffer.from(token, "base64url").toString("utf-8");
|
|
29
|
+
const parts = decoded.split(":");
|
|
30
|
+
if (parts.length !== 3)
|
|
31
|
+
return null;
|
|
32
|
+
const [bookingId, expiresAtStr, signature] = parts;
|
|
33
|
+
const expiresAt = new Date(Number(expiresAtStr));
|
|
34
|
+
// Check expiry
|
|
35
|
+
if (expiresAt < new Date())
|
|
36
|
+
return null;
|
|
37
|
+
// Verify signature
|
|
38
|
+
const payload = `${bookingId}:${expiresAtStr}`;
|
|
39
|
+
const expectedSig = createHmac("sha256", secret)
|
|
40
|
+
.update(payload)
|
|
41
|
+
.digest("hex");
|
|
42
|
+
const a = Buffer.from(expectedSig, "hex");
|
|
43
|
+
const b = Buffer.from(signature, "hex");
|
|
44
|
+
if (a.length !== b.length || !timingSafeEqual(a, b))
|
|
45
|
+
return null;
|
|
46
|
+
return { bookingId, expiresAt };
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=booking-tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-tokens.js","sourceRoot":"","sources":["../src/booking-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAErD;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAAiB,EACjB,SAAe,EACf,MAAc;IAEd,MAAM,OAAO,GAAG,GAAG,SAAS,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;IACtD,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC3C,MAAM,CAAC,OAAO,CAAC;SACf,MAAM,CAAC,KAAK,CAAC,CAAC;IACjB,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpC,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC;QACnD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QAEjD,eAAe;QACf,IAAI,SAAS,GAAG,IAAI,IAAI,EAAE;YAAE,OAAO,IAAI,CAAC;QAExC,mBAAmB;QACnB,MAAM,OAAO,GAAG,GAAG,SAAS,IAAI,YAAY,EAAE,CAAC;QAC/C,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;aAC7C,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC,KAAK,CAAC,CAAC;QAEjB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAEjE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Variables available in email templates */
|
|
2
|
+
export interface EmailTemplateVars {
|
|
3
|
+
bookingId: string;
|
|
4
|
+
eventTitle: string;
|
|
5
|
+
providerName: string;
|
|
6
|
+
customerName: string;
|
|
7
|
+
customerEmail: string;
|
|
8
|
+
date: string;
|
|
9
|
+
time: string;
|
|
10
|
+
duration: string;
|
|
11
|
+
timezone: string;
|
|
12
|
+
location?: string;
|
|
13
|
+
managementUrl?: string;
|
|
14
|
+
unsubscribeUrl?: string;
|
|
15
|
+
cancelReason?: string;
|
|
16
|
+
oldDate?: string;
|
|
17
|
+
oldTime?: string;
|
|
18
|
+
newDate?: string;
|
|
19
|
+
newTime?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function interpolateTemplate(template: string, vars: EmailTemplateVars): string;
|
|
22
|
+
/** Default booking confirmation email template (HTML) */
|
|
23
|
+
export declare const CONFIRMATION_EMAIL_HTML: string;
|
|
24
|
+
/** Default booking confirmation email (plain text) */
|
|
25
|
+
export declare const CONFIRMATION_EMAIL_TEXT: string;
|
|
26
|
+
/** Default reminder email template */
|
|
27
|
+
export declare const REMINDER_EMAIL_HTML: string;
|
|
28
|
+
/** Default cancellation email template */
|
|
29
|
+
export declare const CANCELLATION_EMAIL_HTML: string;
|
|
30
|
+
/** Default reschedule email template */
|
|
31
|
+
export declare const RESCHEDULE_EMAIL_HTML: string;
|
|
32
|
+
//# sourceMappingURL=email-templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-templates.d.ts","sourceRoot":"","sources":["../src/email-templates.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAeD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,iBAAiB,GACtB,MAAM,CAKR;AAED,yDAAyD;AACzD,eAAO,MAAM,uBAAuB,QAqB5B,CAAC;AAET,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,QAgB5B,CAAC;AAET,sCAAsC;AACtC,eAAO,MAAM,mBAAmB,QAoBxB,CAAC;AAET,0CAA0C;AAC1C,eAAO,MAAM,uBAAuB,QAc5B,CAAC;AAET,wCAAwC;AACxC,eAAO,MAAM,qBAAqB,QAoB1B,CAAC"}
|
|
@@ -1,38 +1,21 @@
|
|
|
1
|
-
/** Variables available in email templates */
|
|
2
|
-
export interface EmailTemplateVars {
|
|
3
|
-
bookingId: string;
|
|
4
|
-
eventTitle: string;
|
|
5
|
-
providerName: string;
|
|
6
|
-
customerName: string;
|
|
7
|
-
customerEmail: string;
|
|
8
|
-
date: string;
|
|
9
|
-
time: string;
|
|
10
|
-
duration: string;
|
|
11
|
-
timezone: string;
|
|
12
|
-
location?: string;
|
|
13
|
-
managementUrl?: string;
|
|
14
|
-
unsubscribeUrl?: string;
|
|
15
|
-
cancelReason?: string;
|
|
16
|
-
oldDate?: string;
|
|
17
|
-
oldTime?: string;
|
|
18
|
-
newDate?: string;
|
|
19
|
-
newTime?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
1
|
/**
|
|
23
2
|
* Interpolate template variables into a template string.
|
|
24
3
|
* Variables use the format `{variableName}`.
|
|
25
4
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
5
|
+
function escapeHtml(str) {
|
|
6
|
+
return str
|
|
7
|
+
.replace(/&/g, "&")
|
|
8
|
+
.replace(/</g, "<")
|
|
9
|
+
.replace(/>/g, ">")
|
|
10
|
+
.replace(/"/g, """)
|
|
11
|
+
.replace(/'/g, "'");
|
|
12
|
+
}
|
|
13
|
+
export function interpolateTemplate(template, vars) {
|
|
14
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
|
15
|
+
const value = vars[key];
|
|
16
|
+
return value != null ? escapeHtml(value) : match;
|
|
17
|
+
});
|
|
34
18
|
}
|
|
35
|
-
|
|
36
19
|
/** Default booking confirmation email template (HTML) */
|
|
37
20
|
export const CONFIRMATION_EMAIL_HTML = `
|
|
38
21
|
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
|
|
@@ -56,7 +39,6 @@ export const CONFIRMATION_EMAIL_HTML = `
|
|
|
56
39
|
</p>
|
|
57
40
|
</div>
|
|
58
41
|
`.trim();
|
|
59
|
-
|
|
60
42
|
/** Default booking confirmation email (plain text) */
|
|
61
43
|
export const CONFIRMATION_EMAIL_TEXT = `
|
|
62
44
|
Booking Confirmed
|
|
@@ -75,7 +57,6 @@ Manage your booking: {managementUrl}
|
|
|
75
57
|
|
|
76
58
|
To unsubscribe: {unsubscribeUrl}
|
|
77
59
|
`.trim();
|
|
78
|
-
|
|
79
60
|
/** Default reminder email template */
|
|
80
61
|
export const REMINDER_EMAIL_HTML = `
|
|
81
62
|
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
|
|
@@ -98,7 +79,6 @@ export const REMINDER_EMAIL_HTML = `
|
|
|
98
79
|
</p>
|
|
99
80
|
</div>
|
|
100
81
|
`.trim();
|
|
101
|
-
|
|
102
82
|
/** Default cancellation email template */
|
|
103
83
|
export const CANCELLATION_EMAIL_HTML = `
|
|
104
84
|
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
|
|
@@ -115,7 +95,6 @@ export const CANCELLATION_EMAIL_HTML = `
|
|
|
115
95
|
</p>
|
|
116
96
|
</div>
|
|
117
97
|
`.trim();
|
|
118
|
-
|
|
119
98
|
/** Default reschedule email template */
|
|
120
99
|
export const RESCHEDULE_EMAIL_HTML = `
|
|
121
100
|
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
|
|
@@ -138,3 +117,4 @@ export const RESCHEDULE_EMAIL_HTML = `
|
|
|
138
117
|
</p>
|
|
139
118
|
</div>
|
|
140
119
|
`.trim();
|
|
120
|
+
//# sourceMappingURL=email-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-templates.js","sourceRoot":"","sources":["../src/email-templates.ts"],"names":[],"mappings":"AAqBA;;;GAGG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,IAAuB;IAEvB,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACnD,MAAM,KAAK,GAAI,IAAsD,CAAC,GAAG,CAAC,CAAC;QAC3E,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBtC,CAAC,IAAI,EAAE,CAAC;AAET,sDAAsD;AACtD,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;CAgBtC,CAAC,IAAI,EAAE,CAAC;AAET,sCAAsC;AACtC,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;CAoBlC,CAAC,IAAI,EAAE,CAAC;AAET,0CAA0C;AAC1C,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;CActC,CAAC,IAAI,EAAE,CAAC;AAET,wCAAwC;AACxC,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;CAoBpC,CAAC,IAAI,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { BookingConflictError, SerializationRetryExhaustedError, UnauthorizedError, ForbiddenError, } from "@thebookingkit/core";
|
|
2
|
+
export { withSerializableRetry, type SerializableRetryOptions, } from "./serialization-retry.js";
|
|
3
|
+
export { withAuth, assertProviderOwnership, assertCustomerAccess, type AuthUser, type AuthSession, type AuthAdapter, type AuthenticatedRequest, type WithAuthOptions, } from "./auth.js";
|
|
4
|
+
export type { EmailAdapter, SendEmailOptions, EmailResult, EmailDeliveryStatus, EmailAttachment, CalendarAdapter, CalendarEventOptions, CalendarEventResult, CalendarConflict, JobAdapter, StorageAdapter, SmsAdapter, SendSmsOptions, SmsResult, PaymentAdapter, CreatePaymentIntentOptions, CreatePaymentIntentResult, CreateSetupIntentOptions, CreateSetupIntentResult, CaptureResult, RefundResult, } from "./adapters/index.js";
|
|
5
|
+
export { generateICSAttachment, JOB_NAMES } from "./adapters/index.js";
|
|
6
|
+
export { generateBookingToken, verifyBookingToken, } from "./booking-tokens.js";
|
|
7
|
+
export { sendConfirmationEmail, sendReminderEmail, sendCancellationEmail, sendRescheduleEmail, scheduleAutoReject, syncBookingToCalendar, deleteBookingFromCalendar, formatDateTimeForEmail, formatDurationForEmail, type NotificationBookingData, type ConfirmationEmailPayload, type ReminderEmailPayload, type CancellationEmailPayload, type RescheduleEmailPayload, type CalendarSyncPayload, type CalendarDeletePayload, type AutoRejectPendingPayload, } from "./notification-jobs.js";
|
|
8
|
+
export { interpolateTemplate, CONFIRMATION_EMAIL_HTML, CONFIRMATION_EMAIL_TEXT, REMINDER_EMAIL_HTML, CANCELLATION_EMAIL_HTML, RESCHEDULE_EMAIL_HTML, type EmailTemplateVars, } from "./email-templates.js";
|
|
9
|
+
export { resolveTemplateVariables, evaluateConditions, validateWorkflow, matchWorkflows, DEFAULT_TEMPLATES, TEMPLATE_VARIABLES, WorkflowValidationError, type WorkflowTrigger, type WorkflowActionType, type ConditionOperator, type WorkflowCondition, type EmailActionConfig, type SmsActionConfig, type WebhookActionConfig, type StatusUpdateActionConfig, type CalendarEventActionConfig, type WorkflowAction, type WorkflowDefinition, type WorkflowContext, type WorkflowLogEntry, } from "./workflows.js";
|
|
10
|
+
export { signWebhookPayload, verifyWebhookSignature, createWebhookEnvelope, resolvePayloadTemplate, matchWebhookSubscriptions, getRetryDelay, isSuccessResponse, validateWebhookSubscription, WebhookValidationError, DEFAULT_RETRY_CONFIG, WEBHOOK_TRIGGERS, SIGNATURE_HEADER, TIMESTAMP_HEADER, DEFAULT_TOLERANCE_SECONDS, type WebhookTrigger, type WebhookAttendee, type WebhookPayload, type WebhookEnvelope, type WebhookSubscription, type WebhookDeliveryResult, type WebhookRetryConfig, type WebhookVerificationResult, } from "./webhooks.js";
|
|
11
|
+
export { createErrorResponse, createSuccessResponse, createPaginatedResponse, generateApiKey, hashApiKey, verifyApiKey, hasScope, isKeyExpired, checkRateLimit, encodeCursor, decodeCursor, validateSlotQueryParams, parseSortParam, API_ERROR_CODES, type ApiError, type ApiErrorResponse, type ApiSuccessResponse, type ApiMeta, type PaginatedResponse, type ApiErrorCode, type ApiKeyRecord, type ApiKeyScope, type GeneratedApiKey, type RateLimitState, type RateLimitResult, type ValidationDetail, type ValidationResult, } from "./api.js";
|
|
12
|
+
export { resolveEffectiveSettings, getRolePermissions, roleHasPermission, assertOrgPermission, assertTenantScope, buildOrgBookingUrl, parseOrgBookingPath, TenantAuthorizationError, GLOBAL_DEFAULTS, type OrgRole, type OrgMember, type OrgBranding, type OrgSettings, type ProviderSettings, type EventTypeSettings, type GlobalDefaults, type ResolvedSettings, type OrgPermission, } from "./multi-tenancy.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Re-export core errors used by server modules
|
|
2
|
+
export { BookingConflictError, SerializationRetryExhaustedError, UnauthorizedError, ForbiddenError, } from "@thebookingkit/core";
|
|
3
|
+
// Serialization retry utility
|
|
4
|
+
export { withSerializableRetry, } from "./serialization-retry.js";
|
|
5
|
+
// Auth middleware & adapters
|
|
6
|
+
export { withAuth, assertProviderOwnership, assertCustomerAccess, } from "./auth.js";
|
|
7
|
+
export { generateICSAttachment, JOB_NAMES } from "./adapters/index.js";
|
|
8
|
+
// Booking Tokens
|
|
9
|
+
export { generateBookingToken, verifyBookingToken, } from "./booking-tokens.js";
|
|
10
|
+
// Notification Jobs
|
|
11
|
+
export { sendConfirmationEmail, sendReminderEmail, sendCancellationEmail, sendRescheduleEmail, scheduleAutoReject, syncBookingToCalendar, deleteBookingFromCalendar, formatDateTimeForEmail, formatDurationForEmail, } from "./notification-jobs.js";
|
|
12
|
+
// Email Templates
|
|
13
|
+
export { interpolateTemplate, CONFIRMATION_EMAIL_HTML, CONFIRMATION_EMAIL_TEXT, REMINDER_EMAIL_HTML, CANCELLATION_EMAIL_HTML, RESCHEDULE_EMAIL_HTML, } from "./email-templates.js";
|
|
14
|
+
// Workflows
|
|
15
|
+
export { resolveTemplateVariables, evaluateConditions, validateWorkflow, matchWorkflows, DEFAULT_TEMPLATES, TEMPLATE_VARIABLES, WorkflowValidationError, } from "./workflows.js";
|
|
16
|
+
// Webhooks
|
|
17
|
+
export { signWebhookPayload, verifyWebhookSignature, createWebhookEnvelope, resolvePayloadTemplate, matchWebhookSubscriptions, getRetryDelay, isSuccessResponse, validateWebhookSubscription, WebhookValidationError, DEFAULT_RETRY_CONFIG, WEBHOOK_TRIGGERS, SIGNATURE_HEADER, TIMESTAMP_HEADER, DEFAULT_TOLERANCE_SECONDS, } from "./webhooks.js";
|
|
18
|
+
// REST API Utilities
|
|
19
|
+
export { createErrorResponse, createSuccessResponse, createPaginatedResponse, generateApiKey, hashApiKey, verifyApiKey, hasScope, isKeyExpired, checkRateLimit, encodeCursor, decodeCursor, validateSlotQueryParams, parseSortParam, API_ERROR_CODES, } from "./api.js";
|
|
20
|
+
// Multi-Tenancy
|
|
21
|
+
export { resolveEffectiveSettings, getRolePermissions, roleHasPermission, assertOrgPermission, assertTenantScope, buildOrgBookingUrl, parseOrgBookingPath, TenantAuthorizationError, GLOBAL_DEFAULTS, } from "./multi-tenancy.js";
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EACL,oBAAoB,EACpB,gCAAgC,EAChC,iBAAiB,EACjB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B,8BAA8B;AAC9B,OAAO,EACL,qBAAqB,GAEtB,MAAM,0BAA0B,CAAC;AAElC,6BAA6B;AAC7B,OAAO,EACL,QAAQ,EACR,uBAAuB,EACvB,oBAAoB,GAMrB,MAAM,WAAW,CAAC;AA0BnB,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEvE,iBAAiB;AACjB,OAAO,EACL,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,oBAAoB;AACpB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,GASvB,MAAM,wBAAwB,CAAC;AAEhC,kBAAkB;AAClB,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,GAEtB,MAAM,sBAAsB,CAAC;AAE9B,YAAY;AACZ,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GAcxB,MAAM,gBAAgB,CAAC;AAExB,WAAW;AACX,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,aAAa,EACb,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,GAS1B,MAAM,eAAe,CAAC;AAEvB,qBAAqB;AACrB,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,EACvB,cAAc,EACd,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,uBAAuB,EACvB,cAAc,EACd,eAAe,GAchB,MAAM,UAAU,CAAC;AAElB,gBAAgB;AAChB,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,eAAe,GAUhB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-tenancy utilities for organization-scoped deployments.
|
|
3
|
+
*
|
|
4
|
+
* Provides organization settings resolution, cascading defaults,
|
|
5
|
+
* role-based access control, and tenant authorization helpers.
|
|
6
|
+
*/
|
|
7
|
+
/** Organization member role */
|
|
8
|
+
export type OrgRole = "owner" | "admin" | "member";
|
|
9
|
+
/** Organization member */
|
|
10
|
+
export interface OrgMember {
|
|
11
|
+
userId: string;
|
|
12
|
+
organizationId: string;
|
|
13
|
+
role: OrgRole;
|
|
14
|
+
}
|
|
15
|
+
/** Organization branding */
|
|
16
|
+
export interface OrgBranding {
|
|
17
|
+
logoUrl?: string;
|
|
18
|
+
primaryColor?: string;
|
|
19
|
+
accentColor?: string;
|
|
20
|
+
fontFamily?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Organization-level settings */
|
|
23
|
+
export interface OrgSettings {
|
|
24
|
+
defaultTimezone?: string;
|
|
25
|
+
defaultCurrency?: string;
|
|
26
|
+
branding?: OrgBranding;
|
|
27
|
+
defaultBufferMinutes?: number;
|
|
28
|
+
defaultBookingLimits?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
/** Provider-level settings that can override org defaults */
|
|
31
|
+
export interface ProviderSettings {
|
|
32
|
+
timezone?: string;
|
|
33
|
+
currency?: string;
|
|
34
|
+
branding?: Partial<OrgBranding>;
|
|
35
|
+
bufferMinutes?: number;
|
|
36
|
+
bookingLimits?: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
/** Event type settings that can override provider defaults */
|
|
39
|
+
export interface EventTypeSettings {
|
|
40
|
+
timezone?: string;
|
|
41
|
+
currency?: string;
|
|
42
|
+
bufferBefore?: number;
|
|
43
|
+
bufferAfter?: number;
|
|
44
|
+
bookingLimits?: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
/** Global SlotKit defaults */
|
|
47
|
+
export interface GlobalDefaults {
|
|
48
|
+
timezone: string;
|
|
49
|
+
currency: string;
|
|
50
|
+
bufferMinutes: number;
|
|
51
|
+
}
|
|
52
|
+
/** Resolved effective settings after cascading resolution */
|
|
53
|
+
export interface ResolvedSettings {
|
|
54
|
+
timezone: string;
|
|
55
|
+
currency: string;
|
|
56
|
+
bufferMinutes: number;
|
|
57
|
+
branding: OrgBranding;
|
|
58
|
+
bookingLimits: Record<string, unknown>;
|
|
59
|
+
}
|
|
60
|
+
/** Permissions available in the system */
|
|
61
|
+
export type OrgPermission = "manage:members" | "manage:teams" | "manage:event-types" | "view:all-bookings" | "view:own-bookings" | "manage:own-availability" | "view:analytics" | "manage:organization";
|
|
62
|
+
/** Error thrown for multi-tenancy authorization violations */
|
|
63
|
+
export declare class TenantAuthorizationError extends Error {
|
|
64
|
+
constructor(message: string);
|
|
65
|
+
}
|
|
66
|
+
/** System-wide defaults used as the base for cascading resolution */
|
|
67
|
+
export declare const GLOBAL_DEFAULTS: GlobalDefaults;
|
|
68
|
+
/**
|
|
69
|
+
* Resolve effective settings via the cascade:
|
|
70
|
+
* `event_type > provider > organization > global defaults`
|
|
71
|
+
*
|
|
72
|
+
* @param orgSettings - Organization-level settings
|
|
73
|
+
* @param providerSettings - Provider-level settings (overrides org)
|
|
74
|
+
* @param eventTypeSettings - Event type settings (overrides provider)
|
|
75
|
+
* @returns Fully resolved effective settings
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveEffectiveSettings(orgSettings?: OrgSettings | null, providerSettings?: ProviderSettings | null, eventTypeSettings?: EventTypeSettings | null): ResolvedSettings;
|
|
78
|
+
/**
|
|
79
|
+
* Get all permissions granted to a role.
|
|
80
|
+
*
|
|
81
|
+
* @param role - The organization role
|
|
82
|
+
* @returns Array of permissions
|
|
83
|
+
*/
|
|
84
|
+
export declare function getRolePermissions(role: OrgRole): OrgPermission[];
|
|
85
|
+
/**
|
|
86
|
+
* Check if a role has a specific permission.
|
|
87
|
+
*
|
|
88
|
+
* @param role - The organization role
|
|
89
|
+
* @param permission - The permission to check
|
|
90
|
+
* @returns Whether the role has the permission
|
|
91
|
+
*/
|
|
92
|
+
export declare function roleHasPermission(role: OrgRole, permission: OrgPermission): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Assert that an org member has a required permission.
|
|
95
|
+
*
|
|
96
|
+
* @param member - The org member
|
|
97
|
+
* @param permission - The required permission
|
|
98
|
+
* @throws {TenantAuthorizationError} If the member lacks the permission
|
|
99
|
+
*/
|
|
100
|
+
export declare function assertOrgPermission(member: OrgMember, permission: OrgPermission): void;
|
|
101
|
+
/**
|
|
102
|
+
* Validate that a resource belongs to the expected organization.
|
|
103
|
+
*
|
|
104
|
+
* @param resourceOrgId - Organization ID on the resource
|
|
105
|
+
* @param expectedOrgId - The org ID from the authenticated context
|
|
106
|
+
* @throws {TenantAuthorizationError} If there is a tenant mismatch
|
|
107
|
+
*/
|
|
108
|
+
export declare function assertTenantScope(resourceOrgId: string | null | undefined, expectedOrgId: string): void;
|
|
109
|
+
export declare function buildOrgBookingUrl(orgSlug: string, providerSlug: string, eventTypeSlug: string, baseUrl: string): string;
|
|
110
|
+
/**
|
|
111
|
+
* Parse an organization slug from a booking URL path.
|
|
112
|
+
*
|
|
113
|
+
* Expected format: `/{orgSlug}/{providerSlug}/{eventTypeSlug}`
|
|
114
|
+
*
|
|
115
|
+
* @param pathname - URL pathname
|
|
116
|
+
* @returns Parsed segments, or null if format is invalid
|
|
117
|
+
*/
|
|
118
|
+
export declare function parseOrgBookingPath(pathname: string): {
|
|
119
|
+
orgSlug: string;
|
|
120
|
+
providerSlug: string;
|
|
121
|
+
eventTypeSlug: string;
|
|
122
|
+
} | null;
|
|
123
|
+
//# sourceMappingURL=multi-tenancy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-tenancy.d.ts","sourceRoot":"","sources":["../src/multi-tenancy.ts"],"names":[],"mappings":"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"}
|