Database Reference (@thebookingkit/db)
@thebookingkit/db provides the Drizzle ORM schema, a typed database client factory, inferred TypeScript types for all tables, and a migration runner for custom SQL that Drizzle’s kit does not handle.
npm install @thebookingkit/db drizzle-orm postgresDatabase Client
Section titled “Database Client”createDb()
Section titled “createDb()”Creates a Drizzle database client connected to a Postgres instance. Uses postgres.js as the driver.
import { createDb } from "@thebookingkit/db";
const db = createDb(process.env.DATABASE_URL!, { max: 10, // connection pool size});Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
databaseUrl | string | Yes | Postgres connection string |
options.max | number | No | Maximum pool connections. Default: 10 |
options.ssl | boolean | object | No | SSL config. Defaults to false for localhost, "require" otherwise |
Returns Database — a Drizzle ORM instance with the full BookingKit schema loaded.
Database
Section titled “Database”The type of the client returned by createDb. Use this to type function parameters that accept a database connection.
import type { Database } from "@thebookingkit/db";
async function getBooking(db: Database, id: string) { return db.query.bookings.findFirst({ where: (b, { eq }) => eq(b.id, id), });}Schema Tables
Section titled “Schema Tables”All tables are exported from @thebookingkit/db and can be used with Drizzle’s query builder or SQL template tags.
import { bookings, providers, eventTypes, availabilityRules, availabilityOverrides, outOfOffice, organizations, teams, teamMembers, bookingEvents, bookingQuestionsResponses, bookingSeats, recurringBookings, payments, routingForms, routingSubmissions, workflows, workflowLogs, webhooks, webhookDeliveries, emailDeliveryLog, customerPreferences, walkInQueue, resources, resourceAvailabilityRules, resourceAvailabilityOverrides,} from "@thebookingkit/db";Core tables
| Table export | DB table name | Description |
|---|---|---|
bookings | bookings | All booking records with status, times, and customer info |
bookingEvents | booking_events | Append-only audit trail of every booking state change |
bookingSeats | booking_seats | Individual seat reservations for group events |
bookingQuestionsResponses | booking_questions_responses | Customer answers to event type intake questions |
recurringBookings | recurring_bookings | Recurring series parent records |
Provider and scheduling tables
| Table export | DB table name | Description |
|---|---|---|
providers | providers | Service providers (staff members, contractors) |
eventTypes | event_types | Bookable service definitions with duration, price, and settings |
availabilityRules | availability_rules | RRULE-based recurring availability windows |
availabilityOverrides | availability_overrides | One-off date overrides (extra availability or blocks) |
outOfOffice | out_of_office | Multi-day out-of-office periods |
Organization and team tables
| Table export | DB table name | Description |
|---|---|---|
organizations | organizations | Multi-tenant organization records |
teams | teams | Provider groups with shared scheduling |
teamMembers | team_members | Provider-to-team membership with roles |
Payment and commerce tables
| Table export | DB table name | Description |
|---|---|---|
payments | payments | Payment intent and capture records |
Automation tables
| Table export | DB table name | Description |
|---|---|---|
workflows | workflows | Trigger-based automation definitions |
workflowLogs | workflow_logs | Execution history for workflow runs |
webhooks | webhooks | Webhook subscription registrations |
webhookDeliveries | webhook_deliveries | Delivery attempt log with response codes |
emailDeliveryLog | email_delivery_log | Transactional email send history |
routingForms | routing_forms | Conditional routing form definitions |
routingSubmissions | routing_submissions | Customer responses to routing forms |
customerPreferences | customer_preferences | Per-customer notification and timezone preferences |
Queue and resource tables
| Table export | DB table name | Description |
|---|---|---|
walkInQueue | walk_in_queue | Walk-in waitlist entries |
resources | resources | Bookable resources (rooms, equipment, vehicles) |
resourceAvailabilityRules | resource_availability_rules | RRULE-based resource availability |
resourceAvailabilityOverrides | resource_availability_overrides | One-off resource availability overrides |
All tables include id (UUID), created_at, and updated_at columns. Most tables include an optional organization_id column for multi-tenancy.
Enum Union Types
Section titled “Enum Union Types”Enum types derived from the Drizzle pgEnum definitions. Use these for type-safe status comparisons without importing Drizzle internals.
import type { BookingStatusDb, PaymentStatusDb, BookingEventTypeDb, PaymentTypeDb, LocationTypeDb, AssignmentStrategyDb, TeamMemberRoleDb, QuestionFieldTypeDb, RecurringFrequencyDb, SeatStatusDb, WorkflowTriggerDb, WorkflowActionTypeDb, EmailDeliveryStatusDb, BookingSourceDb, WalkInStatusDb,} from "@thebookingkit/db";| Type | Values |
|---|---|
BookingStatusDb | "pending", "confirmed", "completed", "cancelled", "rejected", "rescheduled", "no_show" |
PaymentStatusDb | "unpaid", "paid", "partially_refunded", "refunded", "failed" |
BookingEventTypeDb | "created", "confirmed", "cancelled", "rescheduled", "completed", "no_show", "payment_received", "refunded", "rejected" |
PaymentTypeDb | "full", "deposit", "free" |
LocationTypeDb | "in_person", "video", "phone", "custom" |
AssignmentStrategyDb | "round_robin", "least_busy", "fixed", "customer_choice" |
TeamMemberRoleDb | "owner", "admin", "member" |
QuestionFieldTypeDb | "text", "textarea", "select", "checkbox", "phone", "email", "number", "date" |
RecurringFrequencyDb | "daily", "weekly", "biweekly", "monthly" |
SeatStatusDb | "reserved", "confirmed", "cancelled" |
WorkflowTriggerDb | "booking_created", "booking_confirmed", "booking_cancelled", "booking_rescheduled", "before_event", "after_event" |
WorkflowActionTypeDb | "send_email", "send_sms", "webhook", "update_status", "add_to_calendar" |
EmailDeliveryStatusDb | "queued", "sent", "delivered", "failed", "bounced" |
BookingSourceDb | "web", "api", "embed", "walk_in", "manual" |
WalkInStatusDb | "waiting", "called", "in_progress", "completed", "cancelled", "no_show" |
Select Types
Section titled “Select Types”TypeScript types inferred from Drizzle’s InferSelectModel. These represent rows as they come back from database queries.
import type { Booking, Provider, EventType, AvailabilityRule, AvailabilityOverride, OutOfOffice, Organization, Team, TeamMember, BookingEvent, BookingQuestionResponse, BookingSeat, RecurringBooking, Payment, RoutingForm, RoutingSubmission, Workflow, WorkflowLog, Webhook, WebhookDelivery, EmailDeliveryLogEntry, CustomerPreference, WalkInQueue, Resource, ResourceAvailabilityRule, ResourceAvailabilityOverride,} from "@thebookingkit/db";Insert Types
Section titled “Insert Types”TypeScript types inferred from Drizzle’s InferInsertModel. These represent the data required to insert a new row. Fields with database defaults (id, created_at, updated_at) are optional.
import type { NewBooking, NewProvider, NewEventType, NewAvailabilityRule, NewAvailabilityOverride, NewOutOfOffice, NewOrganization, NewTeam, NewTeamMember, NewBookingEvent, NewBookingQuestionResponse, NewBookingSeat, NewRecurringBooking, NewPayment, NewRoutingForm, NewRoutingSubmission, NewWorkflow, NewWorkflowLog, NewWebhook, NewWebhookDelivery, NewEmailDeliveryLogEntry, NewCustomerPreference, NewWalkInQueue, NewResource, NewResourceAvailabilityRule, NewResourceAvailabilityOverride,} from "@thebookingkit/db";Migration Utilities
Section titled “Migration Utilities”runCustomMigrations()
Section titled “runCustomMigrations()”Runs the custom SQL migration files that Drizzle Kit does not manage — extensions, exclusion constraints, audit triggers, stored functions, and resource tables.
import { runCustomMigrations } from "@thebookingkit/db";
await runCustomMigrations(process.env.DATABASE_URL!);Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
databaseUrl | string | Yes | Postgres connection string |
Migration files applied (in order)
| File | Purpose |
|---|---|
0001_setup_extensions.sql | Enable btree_gist, uuid-ossp, and other required extensions |
0002_booking_audit_trigger.sql | Install the trigger that writes to booking_events on every status change |
0003_gdpr_anonymize.sql | Install the anonymize_customer stored function |
0004_create_booking_function.sql | Install the atomic create_booking function with exclusion constraint enforcement |
0005_resources.sql | Set up the EXCLUDE USING gist constraint on the resources table |
Run this once after your initial schema push and after any upgrade that adds new migration files.
Examples
Section titled “Examples”Querying bookings with Drizzle
Section titled “Querying bookings with Drizzle”import { createDb, bookings, providers } from "@thebookingkit/db";import { eq, and, gte, lte } from "drizzle-orm";
const db = createDb(process.env.DATABASE_URL!);
// Find upcoming confirmed bookings for a providerconst upcoming = await db .select() .from(bookings) .where( and( eq(bookings.providerId, providerId), eq(bookings.status, "confirmed"), gte(bookings.startsAt, new Date()), ) ) .orderBy(bookings.startsAt);Inserting a booking with type safety
Section titled “Inserting a booking with type safety”import { createDb, bookings, type NewBooking } from "@thebookingkit/db";
const db = createDb(process.env.DATABASE_URL!);
const newBooking: NewBooking = { providerId: "uuid-here", eventTypeId: "uuid-here", customerEmail: "alice@example.com", customerName: "Alice", startsAt: new Date("2026-04-15T10:00:00.000Z"), endsAt: new Date("2026-04-15T10:30:00.000Z"), status: "pending", timezone: "America/New_York",};
const [inserted] = await db.insert(bookings).values(newBooking).returning();Using select types in API responses
Section titled “Using select types in API responses”import type { Booking, BookingStatusDb } from "@thebookingkit/db";
function isConfirmed(booking: Booking): boolean { return booking.status === "confirmed" satisfies BookingStatusDb;}Full project setup
Section titled “Full project setup”// lib/db.ts — singleton database clientimport { createDb, type Database } from "@thebookingkit/db";import { runCustomMigrations } from "@thebookingkit/db";
let _db: Database | null = null;
export function getDb(): Database { if (!_db) { _db = createDb(process.env.DATABASE_URL!, { max: 5 }); } return _db;}
// In your migration script / startup:// await runCustomMigrations(process.env.DATABASE_URL!);