Database client, ORM abstractions, and entity tables.

The database layer uses libsql with a type-safe table abstraction that handles column definitions, field transformers (encrypt/decrypt), and generic CRUD operations.

Entity Tables

  • Events — event CRUD with cached encrypted slugs/names
  • Attendees — hybrid RSA+AES encryption for PII
  • Users — password hashing, admin levels, wrapped keys
  • Sessions — token hashing with TTL caching
  • Groups — event grouping with encrypted names
  • Settings — system configuration (currency, email, payment keys)
  • Holidays — date exclusions for daily events
  • Activity Log — admin audit trail
  • Processed Payments — idempotency tracking
  • Login Attempts — rate limiting and lockout

Functions

f
addQueryLogEntry(
sql: string,
durationMs: number
): void

Record a query (no-op when logging is disabled)

f
assignEventsToGroup(
eventIds: number[],
groupId: number
): Promise<void>

Assign events to a group by updating their group_id.

f
buildAttendeeInsert(enc: EncryptedAttendeeData)

Build an INSERT statement for the attendees table from encrypted fields.

f
buildInputKeyMap(columns: string[]): Record<string, string>

Build input key mapping from DB columns snake_case DB column → camelCase input key

f
checkBatchAvailability(
items: BatchAvailabilityItem[],
date?: string | null
): Promise<boolean>

Wrapper for test mocking - delegates to attendeesApi at runtime

f
checkCapacityResult(result: { rowsAffected: number; }): UpdateEventLinkResult

Check a capacity-guarded write result and invalidate cache on success

f
clearLoginAttempts(ip: string): Promise<void>

Clear login attempts for an IP (on successful login)

f
clearSessionTokens(sessionId: string): Promise<void>

Clear stored ticket tokens for a session (after redirect has consumed them)

f
computeGroupSlugIndex(slug: string): Promise<string>

Compute slug index from slug for blind index lookup

f
computeSlugIndex(slug: string): Promise<string>

Compute slug index from slug for blind index lookup

f
contactFields(unnamed 0: ContactInfo): ContactInfo

Extract ContactInfo fields from an object

f
createAttendeeAtomic(input: AttendeeInput): Promise<CreateAttendeeResult>

Wrapper for test mocking - delegates to attendeesApi at runtime

f
createSession(
token: string,
csrfToken: string,
expires: number,
wrappedDataKey: string | null,
userId: number
): Promise<void>

Create a new session with CSRF token, wrapped data key, and user ID Token is hashed before storage for security

f
dateToStartEnd(date: string | null): { startAt: string | null; endAt: string | null; }

Convert nullable date to start_at/end_at (null-safe wrapper around dateToRange)

f
decryptAttendeeFields(
row: Attendee,
privateKey: CryptoKey,
paidEvent?: boolean
): Promise<Attendee>

Decrypt attendee fields from the PII blob. Requires migration to be complete (admin is gated behind migration). When paidEvent is false, payment_id and refunded are skipped.

f
decryptAttendeeOrNull(
row: Attendee | null,
privateKey: CryptoKey
): Promise<Attendee | null>

Decrypt a single raw attendee, handling null input. Used when attendee is fetched via batch query.

f
decryptAttendees(
rows: Attendee[],
privateKey: CryptoKey,
paidEvent?: boolean
): Promise<Attendee[]>

Decrypt a list of raw attendees (all fields). Used when attendees are fetched via batch query.

f
decryptSessionTokens(encryptedTokens: string): Promise<string>

Decrypt the ticket_tokens field from a processed payment record. Returns the plaintext token string (e.g. "tok1+tok2") or empty string.

f
defineIdTable<Row, Input = Row>(
name: string,
schema: TableSchema<Row>
)

Helper for tables whose primary key column is id.

f
deleteAllSessions(): Promise<void>

Delete all sessions (used when password is changed)

f
deleteAllStaleReservations(): Promise<number>

Delete all stale reservations (unfinalized and older than STALE_RESERVATION_MS). Called from admin event views to clean up abandoned checkouts.

f
deleteAttendee(attendeeId: number): Promise<void>

Delete an attendee and all its event links, payments, and answers.

f
deleteEvent(eventId: number): Promise<void>

Delete an event and all its attendees in a single database round-trip. Uses write batch to cascade: processed_payments → attendees → event. Reduces 3 sequential HTTP round-trips to 1.

f
deleteOtherSessions(currentToken: string): Promise<void>

Delete all sessions except the current one Token is hashed before database comparison

f
deleteSession(token: string): Promise<void>

Delete a session by token Token is hashed before database lookup

f
deleteStaleReservation(sessionId: string): Promise<void>

Delete a stale reservation to allow retry

f
deleteUser(userId: number): Promise<void>

Delete a user and all their sessions and API keys

f
enableQueryLog(): void

Enable query logging and clear previous entries

f
encryptAttendeeFields(input: EncryptInput): Promise<EncryptedAttendeeData | null>

Encrypt attendee fields into a PII blob, returning null if key not configured

f
encryptedNameSchema(
encrypt: EncryptFn,
decrypt: DecryptFn
)

Shared encrypted name column for tables that store a display name.

f
encryptPiiBlob(
blobJson: string,
publicKeyJwk: string
): Promise<string>

Encrypt a PII blob JSON string with the public key

f
executeBatch(statements: Array<{ sql: string; args: InValue[]; }>): Promise<void>

Execute multiple write statements, discarding results.

f
finalizeSession(
sessionId: string,
attendeeId: number,
ticketTokens?: string[]
): Promise<void>

Finalize a reserved session with the created attendee ID (second phase)

f
getActiveEventsByGroupId(groupId: number): Promise<EventWithCount[]>

Get active events in a group with attendee counts.

f
getActiveEventStats(events: EventWithCount[]): Promise<ActiveEventStats>

Get aggregated statistics for active events. Filters active events from the provided list, computes attendees (sum of quantities) from cached EventWithCount data, and queries ticket count and income (sum of price_paid) via a single aggregate.

f
getActiveHolidays(): Promise<Holiday[]>

Get active holidays (end_date >= today) for date computation (from cache). "today" is computed in the configured timezone.

f
getAllActivityLog(limit?: number): Promise<ActivityLogEntry[]>

Get all activity log entries (most recent first)

f
getAllDailyEvents(): Promise<EventWithCount[]>

Get all daily events with attendee counts (from cache).

f
getAllEvents(): Promise<EventWithCount[]>

Get all events with attendee counts (from cache)

f
getAllGroups(): Promise<Group[]>

Get all groups, decrypted, ordered by id (from cache)

f
getAllHolidays(): Promise<Holiday[]>

Get all holidays, decrypted, ordered by start_date (from cache)

f
getAllSessions(): Promise<Session[]>

Get all sessions ordered by expiration (newest first)

f
getAllStandardEvents(): Promise<EventWithCount[]>

Get all standard events with attendee counts (from cache). Used by the calendar view to include one-time events on their scheduled date.

f
getAllUsers(): Promise<User[]>

Get all users (for admin user management page, from cache)

f
getAttendee(
id: number,
privateKey: CryptoKey
): Promise<Attendee | null>

Get an attendee by ID (decrypted) Requires private key for decryption - only available to authenticated sessions

f
getAttendeeRaw(id: number): Promise<Attendee | null>

Get an attendee by ID without decrypting PII Used for payment callbacks and webhooks where decryption is not needed Returns the attendee with encrypted fields (id, event_id, quantity are plaintext)

f
getAttendeesByEventIds(eventIds: number[]): Promise<Attendee[]>

Get raw attendees for a set of event IDs. Used by the calendar to load attendees for standard events whose decrypted date matches the selected calendar date.

f
getAttendeesByTokens(tokens: string[]): Promise<(AttendeeWithBookings | null)[]>

Look up attendees by plaintext tokens, returning full booking data. Two queries: attendees by token index, then all event_attendees for those attendees. Returns results in the same order as input tokens (deduped). Bookings sorted by start_at then event_id for deterministic ordering.

f
getAttendeesRaw(eventId: number): Promise<Attendee[]>

Get attendees for an event without decrypting PII Used for tests and operations that don't need decrypted data

f
getDailyEventAttendeeDates(): Promise<string[]>

Get distinct attendee dates for daily events. Used for the calendar date picker (lightweight, no attendee data).

f
getDailyEventAttendeesByDate(date: string): Promise<Attendee[]>

Get raw attendees for daily events on a specific date. Bounded query: only returns attendees matching the given date.

f
getDateAttendeeCount(
eventId: number,
date: string
): Promise<number>

Get the total attendee quantity for a specific event + date

f
getDb(): Client

Get or create database client

f
getEvent(id: number): Promise<Event | null>

Get a single event by ID (from cache)

f
getEventActivityLog(
eventId: number,
limit?: number
): Promise<ActivityLogEntry[]>

Get activity log entries for an event (most recent first)

f
getEventsByGroupId(groupId: number): Promise<EventWithCount[]>

Get all events in a group with attendee counts (including inactive).

f
getEventsBySlugsBatch(slugs: string[]): Promise<(EventWithCount | null)[]>

Get multiple events by slugs (from cache). Returns events in the same order as the input slugs. Missing or inactive events are returned as null.

f
getEventWithActivityLog(
eventId: number,
limit?: number
): Promise<EventWithActivityLog | null>

Get event and its activity log in a single database round-trip. Uses batch API to reduce latency for remote databases.

f
getEventWithAttendeeRaw(
eventId: number,
attendeeId: number
): Promise<EventWithAttendeeRaw | null>

Get event and a single attendee in a single database round-trip. Used for attendee management pages where we need both the event context and the specific attendee data.

f
getEventWithAttendeesRaw(id: number): Promise<EventWithAttendees | null>

Get event and all attendees in a single database round-trip. Uses batch API to execute both queries together, reducing latency for remote databases like Turso from 2 RTTs to 1. Computes attendee_count from the attendees array.

f
getEventWithCount(id: number): Promise<EventWithCount | null>

Get event with attendee count (from cache)

f
getEventWithCountBySlug(slug: string): Promise<EventWithCount | null>

Get event with attendee count by slug (from cache)

f
getGroupBySlugIndex(slugIndex: string): Promise<Group | null>

Get a single group by slug_index (from cache)

f
getGroupRemainingByEventId(
events: EventForGroupLookup[],
date?: string | null
): Promise<RemainingMap>

Per-event view of group remaining capacity. Daily events are dropped when date is null — their cap is per-date, so a cumulative count would misreport spots that other dates still have.

f
getGroupRemainingByGroupId(
groupIds: number[],
date?: string | null
): Promise<RemainingMap>

Per-group remaining capacity. Groups with max_attendees <= 0 (no cap) are omitted from the map. With date = null, daily-event attendees count cumulatively — correct for booking-time enforcement after upstream date validation, misleading for display.

f
getGroupRemainingForEvent(
event: EventForGroupLookup,
date?: string | null
): Promise<number | undefined>

Returns undefined when no group cap applies: ungrouped, uncapped group, or daily event without a date.

f
getNewestAttendeesRaw(limit: number): Promise<Attendee[]>

Get the newest attendees across all events without decrypting PII. Used for the admin dashboard to show recent registrations.

f
getProcessedAttendeeId(sessionId: string): Promise<number | null>

Get the attendee ID for an already-processed session Used to return success for idempotent webhook retries

f
getQueryLog(): QueryLogEntry[]

Return a snapshot of all logged queries

f
getQueryLogStartTime(): number

Return the start time recorded by enableQueryLog()

f
getSession(token: string): Promise<Session | null>

Get a session by token (with 10s TTL cache) Token is hashed for database lookup

f
getUngroupedEvents(): Promise<EventWithCount[]>

Get ungrouped events (group_id = 0) with attendee counts.

f
f
getUserByInviteCode(inviteCode: string): Promise<User | null>

Find a user by invite code hash Scans all users, decrypts invite_code_hash, and compares

f
getUserByUsername(username: string): Promise<User | null>

Look up a user by username (using blind index, from cache)

f
hasAvailableSpots(...args: Parameters<attendeesApi.hasAvailableSpots>): Promise<boolean>

Wrapper for test mocking - delegates to attendeesApi at runtime

f
hashInviteCode(code: string): Promise<string>

Hash an invite code using SHA-256

f
hasPassword(user: User): Promise<boolean>

Check if a user has set their password (password_hash is non-empty encrypted value)

f
idAndEncryptedSlugSchema(
encrypt: EncryptFn,
decrypt: DecryptFn
)

Shared columns for tables with encrypted slug + blind-index slug_index.

f
incrementAttachmentDownloads(
attendeeId: number,
eventId: number
): Promise<void>

Increment the attachment download counter for an attendee. Uses atomic SQL increment to avoid race conditions.

f
initDb(): Promise<void>

Initialize database tables — idempotent, safe to call on every startup. Uses an advisory lock to prevent concurrent migrations.

f
inPlaceholders(values: readonly unknown[]): string

Build SQL placeholders for an IN clause, e.g. "?, ?, ?"

f
insert(
table: string,
values: Record<string, InValue | RawSql>
): { sql: string; args: InValue[]; }

Build an INSERT statement from a table name and column→value record.

f
invalidateEventsCache(): void

Invalidate the events cache (for testing or after writes).

f
invalidateGroupsCache(): void

Invalidate the groups cache (for testing or after writes).

f
invalidateHolidaysCache(): void

Invalidate the holidays cache (for testing or after writes).

f
invalidateUsersCache(): void

Invalidate the users cache (for testing or after writes).

f
isGroupSlugTaken(
slug: string,
excludeGroupId?: number
): Promise<boolean>

Check if a group slug is already in use. Checks both events and groups for cross-table uniqueness.

f
isInviteExpired(user: User): Promise<boolean>

Check if a user's invite has expired. Callers should skip this for users who have already set a password.

f
isInviteValid(user: User): Promise<boolean>

Check if a user's invite is still valid (not expired, has invite code)

f
isLoginRateLimited(ip: string): Promise<boolean>

Check if IP is rate limited for login

f
isQueryLogEnabled(): boolean

Whether query logging is currently active

f
isReservationStale(processedAt: string): boolean

Check if a reservation is stale (abandoned by a crashed process)

f
isSessionProcessed(sessionId: string): Promise<ProcessedPayment | null>

Check if a payment session has already been processed

f
isSlugTaken(
slug: string,
excludeEventId?: number
): Promise<boolean>

Check if a slug is already in use (optionally excluding a specific event ID) Uses slug_index for lookup (blind index)

f
isUsernameTaken(username: string): Promise<boolean>

Check if a username is already taken

f
markRefunded(
attendeeId: number,
eventId: number
): Promise<void>

Mark an attendee as refunded for a specific event. Keeps payment_id intact so payment details can still be viewed.

f
parsePiiBlob(json: string): PiiBlob

Parse a PII blob JSON back into contact fields (defaults v to 1 for pre-versioned blobs)

f
queryAll<T>(
sql: string,
args?: InValue[]
): Promise<T[]>

Query all rows, returning a typed array

f
queryAndMap<Row, Out>(toOut: (row: Row) => Promise<Out>)

Execute a SQL query and map result rows through an async transformer.

f
queryOne<T>(
sql: string,
args: InValue[]
): Promise<T | null>

Query single row, returning null if not found

f
rawSql(expr: string): RawSql

Embed a raw SQL expression (e.g. last_insert_rowid())

f
recordFailedLogin(ip: string): Promise<boolean>

Record a failed login attempt Returns true if the account is now locked

f
registerCache(provider: CacheStatProvider): void

Register a cache stat provider (called at module load time)

f
reserveSession(sessionId: string): Promise<ReserveSessionResult>

Reserve a payment session for processing (first phase of two-phase lock) Inserts with NULL attendee_id to claim the session. Returns { reserved: true } if we claimed it, or { reserved: false, existing } if already claimed.

f
resetDatabase(): Promise<void>

Reset the database by dropping all tables (reverse order for FK safety)

f
resetGroupEvents(groupId: number): Promise<void>

Reset group assignment on all events in a group.

f
resetSessionCache(): void

Clear session cache (exported for testing)

f
resultRows<T>(result: ResultSet): T[]

Cast libsql ResultSet rows to a typed array (single centralized assertion)

f
setDb(client: Client | null): void

Set database client (for testing)

f
setGroupEventsActive(
groupId: number,
active: boolean
): Promise<number>

Set the active flag on every event in a group. Returns the number of events affected.

f
toCamelCase(s: string): string

Convert snake_case to camelCase

f
toSnakeCase(s: string): string

Convert camelCase to snake_case

f
trackQuery<T>(
sql: string,
fn: () => Promise<T>
): Promise<T>

Run an async DB operation and log it when tracking is active

f
unlinkAttendeeFromEvent(
attendeeId: number,
eventId: number
): Promise<{ attendeeDeleted: boolean; }>

Remove a single event link for an attendee. If the attendee has no remaining event links, deletes the attendee entirely. Returns whether the attendee was fully deleted.

f
updateAttendeePII(
attendeeId: number,
input: UpdateAttendeePIIInput
): Promise<void>

Update an attendee's PII (name, email, phone, etc.) — shared across all event links. Caller must be authenticated admin (public key always exists after setup).

f
updateCheckedIn(
attendeeId: number,
eventId: number,
checkedIn: boolean
): Promise<void>

Update an attendee's checked_in status for a specific event. Caller must be authenticated admin (public key always exists after setup)

f
validateGroupEventType(
groupId: number,
eventType: EventType,
excludeEventId?: number
): Promise<string | null>

Validate that an event type is compatible with a group's existing events. Returns an error message if mismatched, null if OK. Pass excludeEventId to skip a specific event (for edit-self case).

f
verifyUserPassword(
user: User,
password: string
): Promise<string | null>

Verify a user's password (decrypt stored hash, then verify) Returns the decrypted password hash if valid (needed for KEK derivation)

f
withCacheInvalidation<Row, Input>(
table: Table<Row, Input>,
invalidate: () => void
): Table<Row, Input>

Wrap a table so that insert, update, and deleteById automatically call an invalidation callback (e.g. cache invalidation). Eliminates the repeated spread-and-override pattern in groups/holidays/events.

f
writeClosesAt(v: string | null): Promise<string | null>

Encrypt closes_at for DB storage (null/empty → encrypted empty)

f
writeEventDate(v: string): Promise<string>

Encrypt event date for DB storage

Interfaces

I
Table

Table definition with CRUD operations

Type Aliases

T
AttendeeInput =
ContactFields
& { paymentId?: string; bookings: EventBooking[]; }

Input for creating an attendee atomically (one or more events)

T
T
ColumnDef<T = unknown> = { generated?: boolean; default?: () => T; write?: (v: T) => Promise<T> | T; read?: (v: T) => Promise<T> | T; }

Column definition for a table

T
TableSchema<Row> = [K in keyof Row]: ColumnDef<Row[K]>

Table schema definition Keys are DB column names (snake_case), values are column definitions

Variables

v
activityLogTable

Activity log table definition message is encrypted - decrypted only for admin view

v
ATTENDEE_JOIN_SELECT: string

SELECT clause for attendee + event_attendees JOINs (INNER JOIN context). Derives date from start_at for the Attendee type shape.

v
ATTENDEE_LEFT_JOIN_SELECT: string

SELECT clause for LEFT JOIN context — COALESCEs nullable join columns so attendees with broken/missing event_attendees linkage still appear in results (with event_id=0 as an obvious corruption indicator).

v
col: { boolean: (defaultValue: boolean) => ColumnDef<boolean>; converted: <App>(config: { default?: () => App; write: (v: App) => InValue; read: (raw: InValue) => App; }) => ColumnDef<App>; encrypted: <T>(
encrypt: ColumnTransform<T>,
decrypt: ColumnTransform<T>
) => ColumnDef<T>
; encryptedNullable: <T>(def: ColumnDef<T>) => ColumnDef<T | null>; encryptedText: (
encrypt: ColumnTransform<string>,
decrypt: ColumnTransform<string>
) => ColumnDef<string>
; generated: <T>() => ColumnDef<T>; simple: <T>() => ColumnDef<T>; transform: <T>(
write: (v: T) => Promise<T> | T,
read: (v: T) => Promise<T> | T
) => ColumnDef<T>
; withDefault: <T>(defaultFn: () => T) => ColumnDef<T>; }

Helper to create column definitions

v
CONFIG_KEYS: { APPLE_WALLET_PASS_TYPE_ID: string; APPLE_WALLET_SIGNING_CERT: string; APPLE_WALLET_SIGNING_KEY: string; APPLE_WALLET_TEAM_ID: string; APPLE_WALLET_WWDR_CERT: string; ATTENDEE_COLUMN_ORDER: string; BOOKING_FEE: string; BUNNY_SUBDOMAIN: string; BUSINESS_EMAIL: string; CONTACT_PAGE_TEXT: string; COUNTRY: string; CURRENT_TASK: string; CUSTOM_DOMAIN: string; CUSTOM_DOMAIN_LAST_VALIDATED: string; EMAIL_API_KEY: string; EMAIL_FROM_ADDRESS: string; EMAIL_PROVIDER: string; EMAIL_TPL_ADMIN_HTML: string; EMAIL_TPL_ADMIN_SUBJECT: string; EMAIL_TPL_ADMIN_TEXT: string; EMAIL_TPL_CONFIRMATION_HTML: string; EMAIL_TPL_CONFIRMATION_SUBJECT: string; EMAIL_TPL_CONFIRMATION_TEXT: string; EMBED_HOSTS: string; EVENT_COLUMN_ORDER: string; GOOGLE_WALLET_ISSUER_ID: string; GOOGLE_WALLET_SERVICE_ACCOUNT_EMAIL: string; GOOGLE_WALLET_SERVICE_ACCOUNT_KEY: string; HEADER_IMAGE_URL: string; HOMEPAGE_TEXT: string; LAST_PRUNED_LOGINS: string; LAST_PRUNED_PAYMENTS: string; LAST_PRUNED_SESSIONS: string; LAST_PRUNED_TOKENS: string; LATEST_SCRIPT_VERSION: string; LATEST_SCRIPT_VERSION_NAME: string; PAYMENT_PROVIDER: string; PUBLIC_KEY: string; SETUP_COMPLETE: string; SHOW_PUBLIC_API: string; SHOW_PUBLIC_SITE: string; SQUARE_ACCESS_TOKEN: string; SQUARE_LOCATION_ID: string; SQUARE_SANDBOX: string; SQUARE_WEBHOOK_SIGNATURE_KEY: string; STRIPE_SECRET_KEY: string; STRIPE_WEBHOOK_ENDPOINT_ID: string; STRIPE_WEBHOOK_SECRET: string; TERMS_AND_CONDITIONS: string; THEME: string; WEBSITE_TITLE: string; WRAPPED_PRIVATE_KEY: string; }
v
DEFAULT_BOOKABLE_DAYS: string[]

Default bookable days (all days of the week)

v
executeBatchWithResults

Execute multiple write statements and return their ResultSets. Statements run in order within a single transaction (Turso batch API). Ideal for cascading deletes and multi-step writes.

v
groupsTable

Groups table with CRUD operations — writes auto-invalidate the cache

v
holidaysTable

Holidays table with CRUD operations — writes auto-invalidate the cache

v
PII_BLOB_VERSION: 1

Current PII blob schema version

v
queryBatch

Execute multiple read queries in a single round-trip using Turso batch API.

v
SCHEMA_TABLE_NAMES: string[]

Ordered table names — matches FK dependency order (parents before children)

v
settings: { appleWallet; email: { get apiKey(): string; get fromAddress(): string; get hasApiKey(): boolean; get provider(): string; template(
type: EmailTemplateType,
format: EmailTemplateFormat
): string; templateSet(type: EmailTemplateType): { subject: string; html: string; text: string; }; }
; getCachedRaw; googleWallet; invalidateCache; loadAll; setRaw; setup: { clearCache; complete; isComplete; }; square: { get accessToken(): string; get hasToken(): boolean; get locationId(): string; get sandbox(): boolean; get webhookSignatureKey(): string; }; stripe: { get hasKey(): boolean; get keyMode(): "test" | "live" | null; get secretKey(): string; get webhookEndpointId(): string; get webhookSecret(): string; }; update: { appleWallet; attendeeColumnOrder; bookingFee: (v: string) => Promise<void>; bunnySubdomain; businessEmail; clearPaymentProvider: () => Promise<void>; contactPageText; country: (v: string) => Promise<void>; currentTask; customDomain; customDomainLastValidated: () => Promise<void>; email: { apiKey; fromAddress; provider; template: (
type: EmailTemplateType,
format: EmailTemplateFormat,
content: string
) => Promise<void>
; }
; embedHosts; eventColumnOrder; googleWallet; headerImageUrl; homepageText; lastPrunedLogins; lastPrunedPayments; lastPrunedSessions; lastPrunedTokens; latestScriptVersion; latestScriptVersionName; paymentProvider: (v: PaymentProviderType) => Promise<void>; showPublicApi; showPublicSite; square: { accessToken; locationId; sandbox; webhookSignatureKey; }; stripe: { secretKey; webhookConfig: (config: { secret: string; endpointId: string; }) => Promise<void>; }; terms; theme: (v: Theme) => Promise<void>; websiteTitle; }
; updateUserPassword; withCurrentTask; get attendeeColumnOrder(): string; get bookingFee(): string; get bunnySubdomain(): string; get businessEmail(): string; clearTestOverride(...keys: (keyof SettingsData)[]): void; clearTestOverrides(): void; get contactPageText(): string; get country(): string; get currency(): string; get currentTask(): string; get customDomain(): string; get customDomainLastValidated(): string; get embedHosts(): string; get eventColumnOrder(): string; get headerImageUrl(): string; get homepageText(): string; get lastPrunedLogins(): string; get lastPrunedPayments(): string; get lastPrunedSessions(): string; get lastPrunedTokens(): string; get latestScriptVersion(): string; get latestScriptVersionName(): string; get paymentProvider(): PaymentProviderType | null; get phonePrefix(): string; get publicKey(): string; setForTest(overrides: Partial<SettingsData>): void; get showPublicApi(): boolean; get showPublicSite(): boolean; get terms(): string; get theme(): Theme; get timezone(): string; get websiteTitle(): string; get wrappedPrivateKey(): string; }
v
STALE_RESERVATION_MS

Threshold for abandoned payment reservations in ms (default: 300000 = 5 min)

Usage

import * as mod from "docs/database.ts";