Chobble Tickets

A self-hosted ticket reservation system built on Deno with libsql.

Features

  • Free and paid listings (Stripe, Square, and SumUp integration)
  • Standard listings (fixed capacity) and daily listings (date-based booking)
  • Multi-listing bookings in one checkout
  • Hybrid RSA-OAEP + AES-256-GCM encryption for PII at rest
  • Check-in with QR codes (built-in scanner)
  • Apple Wallet pass support
  • Admin dashboard with multi-user management
  • Email notifications (Resend, Postmark, SendGrid, Mailgun)
  • Public JSON API (optional)
  • Webhooks on registration
  • ICS/RSS calendar feeds
  • Embeddable widget via iframe

Modules

Module Description
Database ORM, table abstractions, and entity CRUD
Crypto Encryption, hashing, and CSRF
Payments Stripe, Square, and SumUp integration
Email Email sending and templates
Tickets QR codes, SVG tickets, Apple Wallet
Listings Listing fields, sorting, availability
Config Settings, environment, sessions
Utilities FP helpers, formatting, caching
Embed Widget embedding and CDN
Webhooks Webhook delivery and API examples
Demo Demo mode and seed data

Deployment Options

  • Bunny Edge Scripting (edge-deployed)
  • Docker containers
  • Any Deno-compatible environment

Classes

c
DatabaseBusyError

Raised when a write can't get through because the database stays locked after the retries below — too busy. The request layer turns this into a friendly auto-reloading page rather than a generic error.

c
PaymentUserError

Error subclass for user-facing payment validation errors (e.g. invalid phone number). These propagate through safeAsync so the message can be shown to the user.

Functions

f
acceptInvite
No documentation available
f
activateKeylessUser

Complete a keyless invite (the editor role): set the password and clear the invite, leaving wrapped_data_key NULL. An editor holds no DATA_KEY, so unlike acceptInvite there is no handoff to unwrap or re-wrap — the password only authenticates; it protects no key. The user's role is fixed at invite time and is not changed here.

f
addDays

Add days to a YYYY-MM-DD date string

f
addMonthsIso

Add N months to an ISO timestamp, clamping to the last day of the target month. e.g. 2026-01-31 + 1mo → 2026-02-28 Preserves the time component (hour/minute/second/ms). Zero months returns the input with canonical ISO string formatting.

f
addPendingWork

Queue a promise that must complete before the response is sent

f
adjustListingIncome

Correct projected listing income to the requested amount.

f
aesGcmDecryptBytes

AES-GCM decrypt with raw key bytes. The mirror of aesGcmEncryptBytes; note it measures the ciphertext, which carries the tag the plaintext does not.

f
aesGcmDecryptRaw

AES-GCM decrypt raw data with an imported key

f
aesGcmEncryptBytes

AES-GCM encrypt with raw key bytes, using whichever implementation is faster for this payload.

f
aesGcmEncryptRaw

AES-GCM encrypt raw data with an imported key, returning IV and ciphertext

f
aesGcmEncryptText

AES-GCM encrypt a text string with an imported key

f
andConditions

Join SQL conditions with AND while preserving their argument order.

f
anyHiddenPackageGroup

Whether any of the given group ids names a HIDDEN package group (hide_package_listings). A hidden package collapses its members to the package name on every buyer surface, so a member there can never gate its own add-on children — the selector would name them.

f
anyListingInPackageGroup

Whether any of the given listings is a member of a package group. Empty input → false (no query). Used to keep a package member from being turned into another listing's required child (a package page can't render child edges).

f
appendIframeParam

Append iframe=true query param to a URL when in iframe mode

f
applyDemoOverrides

Replace form field values with demo data when demo mode is active. Only replaces fields that are present and non-empty in the form. Mutates and returns the same URLSearchParams for chaining.

f
ascending

The day counts a customisable listing offers, ascending: the priced counts that fall within [1, duration_days] (duration_days is the maximum when customisable_days is on). Empty for non-customisable listings.

f
assembleCheckoutMetadata

Build a checkout's signed metadata the way the given provider needs it, with the caps read from the provider registry: build the logical shape within the per-value and entry caps, pack the small fields into one entry when the provider needs that to fit, and enforce the caps on the shape that reaches the wire. SumUp's caps are unbounded (its metadata is stored locally, never sent to the provider), which makes the enforcement a no-op for it.

f
assignListingsToGroup

Add listings to a group (membership rows), ignoring any already present.

f
asString

Narrow an unknown value to string, defaulting to "" if not a string. Replaces typeof x === "string" ? x : "" at type boundaries.

f
attendeeDependentDeleteStatements

Build the common dependent-row deletes for one or many attendee ids.

f
attendeeIdByLedgerEventGroup

The id of the attendee whose booking owns this ledger event group, or null when none does. The single-batch booking write stamps every one of an attendee's listing_attendees rows with the booking's ledger_event_group (in the same batch that posts the legs), so a paid session's event group resolves back to exactly the attendee it created. This lets an idempotent replay recover the existing booking from the durable ledger after the (prunable) processed_payments idempotency row has gone — without it, a replay whose legs already exist would be mistaken for a capacity failure and refund a live ticket.

f
availableDayCounts
No documentation available
f
base64ToBase64Url

Convert standard base64 to base64url (no padding). Works on both strings and Uint8Array (bytes are first encoded to base64).

f
bestEffort
No documentation available
f
bookedRangeLabel

The human-readable label for one booking's actual span: the stored [date, endDate) range when a multi-day range is stored, the listing's fixed duration when only a start date is (legacy rows written before end dates were stored), else the single booked day. "" when there is no date. The ONE booked-range renderer the confirmation email, the /t ticket cards, and the collapsed package displays share, so they can never disagree about a booking's stay.

f
bookedSpanDays

The whole day count of a stored [start_at, end_at) booking range — the customisable day count the buyer chose. A missing or degenerate range is 1.

f
bracket

Resource management pattern (like Haskell's bracket or try-with-resources). Ensures cleanup happens even if the operation throws.

f
buildAttendeeInsert
No documentation available
f
buildCapacityCheckedInsert

Build an INSERT into listing_attendees, capacity-checked by default.

f
buildCheckinUrl

Build the check-in URL for a single ticket token

f
buildDayPrices

Build a DayPrices map from raw entries. checkEntry reads one raw key/value pair and returns the day count and price to keep, null to skip that entry, or a problem message — which stops the walk and is returned in place of the map. Shared by the lenient stored-value reader (parseDayPrices) and the fail-closed admin API body parser.

f
buildEmbedSnippets

Build embed snippets (script and iframe variants) for a ticket URL

f
buildFlashCookie

Build a flash cookie containing a success, error, or info message, keyed by ID. level defaults to success/error from succeeded; pass it to override. formToken redeems the in-memory form re-fill stash on the follow-up GET; it rides in this HttpOnly, SameSite=Strict cookie rather than the URL so it can't be guessed or leaked via history/referrer.

f
buildFrameAncestors

Build a frame-ancestors CSP value from allowed embed hosts. Returns null if the list is empty (allow embedding from anywhere).

f
buildInfoLines

Build info lines from ticket data (non-PII listing and booking details)

f
buildInputKeyMap

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

f
buildItemsMetadata
No documentation available
f
buildMetadata

Build checkout session metadata from booking data (items already compact).

f
buildPiiBlob

Build a PII blob JSON from contact fields. An unpinned latitude/longitude ("") is left out of the JSON so blobs without a pin stay as small as before.

f
buildPkpass

Build a complete .pkpass file as a Uint8Array (ZIP archive)

f
buildProviderLineItems

Render a priced order into a provider's line-item array: each ticket line via line, each extra (booking fee, …) via extra. Providers supply the two shape callbacks; the ordering (tickets, then extras) matches what Stripe and Square built by hand before.

f
buildSessionCookie
No documentation available
f
buildSubdomainRecordName

Build the full subdomain record name (user choice + suffix). e.g. "mylisting" + ".tickets" → "mylisting.tickets"

f
buildSvgTicketData

Build SVG ticket data from an email entry (non-PII only)

f
buildTemplateData

Build the data object exposed to Liquid templates. Rows booked through a package head the email by the package's name (listing_names); an order may carry several bundles beside plain rows. hidePackageMembers (set for the buyer's confirmation, not the admin notification) collapses each HIDDEN package's member rows into one package row so members aren't revealed — whatever else the order carries beside them.

f
buildTicketAttachments

Generate SVG ticket attachments for the buyer's row groups: each HIDDEN package collapses to a single package-level SVG so the attachments don't reveal the member listings the email body hides — whatever else the order carries beside the bundle. Callers without package rows pass one group per entry (buyerEntryGroups builds the real thing).

f
buildTicketUrl
No documentation available
f
buildWebhookPayload

Build a consolidated webhook payload from registration entries

f
bumpSettingsVersion
No documentation available
f
cachedClientFactory

Cache a provider API client keyed on its config. Reuses the cached client while the config is unchanged and recreates it when the config changes; returns null when the provider is unconfigured.

f
cachedEntityTable

Wire a keyed cache to an id-table in one step: build the cache, register it for the debug-footer stats, and register it with the table→cache invalidation registry so any write to the table (or to a dependsOn table whose triggers feed it — e.g. listings depend on listing_attendees) clears the cache automatically at the db-client layer. Centralises the create-cache + register trio that listings and groups would otherwise each repeat. Cached lets the cache hold a richer row than the table writes (e.g. listings cached with attendee counts).

f
cachedTable

Bundle a request-scoped cache around a table.

f
calendarGridDates

Build the calendar grid for a YYYY-MM month as a flat list of YYYY-MM-DD strings. The grid is whole Monday→Sunday weeks spanning the month plus one extra full week on each side, so adjacent-month context is always visible.

f
checkBatchAvailabilityImpl

Check a whole booking batch in one preflight query.

f
checkGroupCapAfterDurationChange

After a duration change on a grouped listing, check whether any day in any existing booking's new range now exceeds the group cap. Returns the earliest over-capacity day, or null if everything fits. Call AFTER recomputeListingBookingRanges so end_at is already updated.

f
checkLinesCapacity

Check several capacity conditions in one query.

f
checkListingAvailability

Check one listing's availability, including its group limits.

f
checkoutItem

Build a standalone-line CheckoutItem for one listing — the shared shape every single-listing checkout (direct-to-provider QR booking, the plain public booking form) builds its one-item items array from.

f
checkoutStageDeleteStatement

Delete checkout stages for one or many attendee ids.

f
checkSubdomainAvailable

Check whether a bunny subdomain is available.

f
chunk

Split an array into chunks of a given size. Curried adapter over @std/collections.chunk (which throws for size < 1).

f
clampDurationDays

Clamp a valid whole-day count to the supported booking range.

f
clearAllCaches

Clear every module-level in-process cache.

f
clearFlashCookie

Clear a keyed flash cookie (set after reading)

f
clearLoginAttempts

Clear login attempts for an IP on successful login. Clearing is login-only: successful API-key, booking, and address requests must retain their counters.

f
clearSessionCookie
No documentation available
f
clearSessionTokens

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

f
cloneGroupMembershipStatement

One group_listings row for a DUPLICATED group, resolving both the new group and the cloned listing by the slug_index each was just inserted with, so the whole clone (group + listings + memberships) runs as one batch — one round-trip, atomic, and clear of the interactive-transaction round-trip guard. Carries the source member's per-package quantity; the flat price override lives in listing_prices and is copied separately (keyed to the new group).

f
collapsedPackageSummary

The single-row summary a hidden package collapses to for buyers: the bundle's summed price and quantity plus the widest member's dated stay (hiding members must not lose the date the buyer booked). Shared by the email body row and the SVG ticket, so the two can never disagree.

f
collectionCache

Create an in-memory collection cache with TTL. Loads all items via fetchAll on first access or after invalidation/expiry, then serves from memory until the TTL expires or invalidate() is called. Accepts an optional clock function for testing.

f
columnMapByIds
No documentation available
f
compact
No documentation available
f
computeGroupSlugIndex

Compute slug index from slug for blind index lookup

f
computeHmacSha256

Compute HMAC-SHA256 using Web Crypto API, returning raw ArrayBuffer

f
computeSlugIndex

Compute the blind index used for listing slug lookups.

f
concatBytes

Concatenate byte arrays into one array.

f
constantTimeCodesEqual

Constant-time compare of two code sequences, given their lengths and a per-index code reader for each. Walks the longer sequence and folds every difference into one flag with XOR, so no early return leaks a length or the position of the first mismatch. Callers supply the code source (UTF-8 bytes, UTF-16 char codes, …), keeping this the single constant-time comparison loop.

f
constantTimeEqual

Constant-time string comparison to prevent timing attacks Always iterates over the longer string and XORs the lengths so that different-length inputs don't leak via an early return.

f
constantTimeEqualBytes

Constant-time comparison for Uint8Arrays of equal length Caller must ensure arrays have the same length (validated by verifyPassword)

f
contactFields

Extract ContactInfo fields from an object

f
copyPackageMemberOverridesTx

Copy the source's package overrides onto the duplicate's membership rows in the SAME transaction that inserted them (the create write's afterWrite), so a failure rolls the whole duplicate back rather than leaving a live member at the default price. The flat group and per-day group_day price rows are copied only for package groups the NEW listing actually joined (the duplicate form may untick some of the source's groups) — scoping each source row's encoded group to the clone's group_listings, exactly as the quantity copy does. Otherwise a copied override for a non-joined group would lurk invisibly and resurrect the source's price if the clone were later added to that package.

f
countDatabaseRoundTrip

Count one actual libsql client call and stop before call 51 reaches the network. Unlike advisory N+1 reporting, this stays hard in production because Bunny would reject the same request immediately afterwards anyway.

f
countRows

Count all rows in a table. table must be a trusted constant, not input.

f
createInvitedUser

Create an invited user (no password yet, has invite code). When the inviter passes a wrapped DATA_KEY handoff, the invitee self-activates at /join under the v2 scheme; otherwise an admin activates them later (legacy v1 path). kek_version is a placeholder here — there is no wrapped_data_key until activation, which sets the real version.

f
createKeyedCache
No documentation available
f
createManifest

Create manifest.json mapping filenames to SHA-1 hashes

f
createRequestTimer

Create a request timer for measuring duration

f
createSeeds

Create seed listings and attendees using efficient batch writes. Encrypts all data before inserting, matching production behavior. Assigns random ticket quantities (1-4) per attendee without overselling.

f
createSession

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

f
createWithClient

Create a withClient helper that runs an operation with a lazily-resolved client. Returns null if the client is not available or the operation fails.

f
csrfInvalidFormMessage

Default message for invalid/expired CSRF form submissions (request-scoped).

f
dateRange

Generate a range of YYYY-MM-DD date strings from start to end (inclusive)

f
dateToStartEnd

Convert a nullable date to the stored half-open range.

f
dayPriceFor

The per-ticket price (minor units) for booking days on a customisable listing, or null when the listing isn't customisable or that count has no configured price (and therefore isn't offered).

f
daysAgo

Compute how many days ago an listing started, relative to today in the configured timezone. Returns null if the listing date is today or in the future, or if the date is empty/invalid. For past listings, returns a positive integer (1 = yesterday).

f
daySpan

Half-open span covering a non-empty set of YYYY-MM-DD days.

f
dayStartEpochMs

The epoch-ms instant of the START of a calendar day (00:00 local time) in the given timezone. Used to turn a YYYY-MM-DD filter bound into the integer occurred_at bound the ledger queries compare against, so a day range is interpreted in the operator's own timezone rather than UTC.

f
decodeKeyBytes
No documentation available
f
decrypt

Decrypt a string value encrypted with encrypt() Expects format: enc:1:$base64iv:$base64ciphertext

f
decryptAdminLevel

Decrypt a user's admin level

f
decryptAttendeeFields

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

f
decryptAttendeeOrNull

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

f
decryptAttendees

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

f
decryptBytes

Decrypt binary data encrypted with encryptBytes(). Expects ENCB binary format: magic + version + IV + ciphertext.

f
decryptListingWithCount

Convert a projected DB row and overlay the effective listing defaults.

f
decryptPiiBlob

Decrypt a PII blob and extract all contact fields

f
decryptSessionTokens

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

f
decryptUsername

Decrypt a user's username

f
decryptWithKey

Decrypt data with a symmetric key

f
decryptWithOwnerKey

Decrypt a value encrypted with encryptWithOwnerKey, using the owner's private key (obtained from the session in admin views).

f
defineCachedListTable

Define a cached "list" table in one call: build the table with defineTable, then wrap it in cachedTable whose fetchAll selects and decrypts every row in orderBy sequence. Returns the cached table plus its getAll/invalidate.

f
defineIdTable

Helper for tables whose primary key column is id.

f
defineTable

Define a table with CRUD operations

f
defineTableProjection

Define an explicit physical-column projection and reuse the table's read transforms without loading or decrypting the rest of the row.

f
delay

Resolve after ms milliseconds — for retry backoff and similar waits.

f
deleteAllImageStorageFiles

Delete all first-class image files.

f
deleteAllListingAttachmentFiles

Delete all attachment files for a list of listings

f
deleteAllSessions

Delete all sessions (used when password is changed)

f
deleteAllStaleReservations

Delete all stale reservations (unfinalized, outcome-less, and older than STALE_RESERVATION_MS). Called from admin listing views to clean up abandoned checkouts. Rows carrying a recorded terminal failure are kept so a late redirect/webhook replays the handled outcome rather than re-refunding.

f
deleteAttendee

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

f
deleteByField

Delete rows matching a field value

f
deleteByFieldBatch

Delete rows from multiple tables in a single batch transaction

f
deleteByFieldStatement

Build the DELETE statement for one DeleteByFieldTarget — for batches that mix these deletes with other statements.

f
deleteFile

Delete a file, routing to local or Bunny based on config.

f
deleteImageStorageFiles

Delete the full-size image and thumbnail files for a first-class image.

f
deleteImageStorageFilesStrict

Delete an image's storage files, throwing if any file could not be removed (a file that is already gone counts as success, so retries are safe). Unlike deleteImageStorageFiles, this surfaces failures so the caller can keep the image's DB record for a later retry instead of orphaning the stored files under a deleted record.

f
deleteListing

Delete one listing and its listing-owned relationships in one batch.

f
deleteListingAttachmentFile

Delete the attachment file for a single listing

f
deleteOtherSessions

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

f
deleteSession

Delete a session by token Token is hashed before database lookup

f
deleteUser

Delete a user and all their sessions and API keys

f
demoBanner

Demo mode banner HTML, built on demand.

f
deployScriptCode

Upload and publish new script code to a Bunny edge script (defaults to this host's own script when scriptId is omitted).

f
deriveKEK

Legacy (v1) KEK derived from the stored password hash. Retained only to unwrap and migrate existing wrapped_data_keys — new wraps use deriveKEKFromPassword. Salt prefix is empty so this stays byte-compatible with keys wrapped before the v2 split.

f
deriveKEKFromPassword

Password-bound (v2) KEK derived from the raw password. Because the password is never stored, a database dump plus DB_ENCRYPTION_KEY cannot unwrap the DATA_KEY — this is what binds attendee PII at rest to the account password.

f
detectIframeMode

Detect iframe mode from a request URL and store it for the current request

f
detectImageType

Detect the actual image type from magic bytes. Returns the MIME type if matched, null otherwise.

f
downloadImage

Download and decrypt a file. Returns the decrypted bytes, or null if the file does not exist.

f
downloadRaw

Download raw bytes from storage. Returns null if the file does not exist.

f
emailHost

Host (everything after the last @) of a validated address. The ValidEmail type guarantees a host is present, so there is no empty-host case to handle and the compiler forbids passing a raw, unvalidated string.

f
emailLocalPart

Local part (everything before the last @) of a validated address.

f
enableFooterDebug

Allow the admin debug footer to render the captured queries (staff-only).

f
enableQueryLog

Enable query logging and clear previous entries

f
encrypt

Encrypt a string value using AES-256-GCM via node:crypto (faster than Web Crypto for the small payloads this handles; output stays interoperable). Returns format: enc:1:$base64iv:$base64ciphertext Note: ciphertext includes the GCM auth tag appended.

f
encryptAttendeeFields

Encrypt attendee fields into a PII blob.

f
encryptBytes

Encrypt binary data with AES-256-GCM using compact binary format. Output: ENCB + version byte + 12-byte IV + ciphertext (with GCM auth tag). Overhead is only 33 bytes (vs ~76% bloat in the legacy text format).

f
encryptedNameSchema

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

f
encryptedSeoContentSchema

Shared encrypted SEO/content columns for operator-authored pages (site pages, news posts): the markdown body plus the meta pair.

f
encryptedSlugSchema

Encrypted slug + its plaintext blind-index slug_index (the permalink pair shared by pages and news posts).

f
encryptPiiBlob

Encrypt a PII blob JSON string with the public key

f
encryptTicketTokens

Encrypt ticket tokens for the atomic payment finalize.

f
encryptWithKey

Encrypt data with a symmetric key (for wrapping private key with DATA_KEY)

f
encryptWithOwnerKey

Encrypt a value with the site owner's public key (hybrid RSA+AES). Only the owner's password-derived private key can decrypt it. Used for attendee PII, email-preference blobs, and bulk-email drafts/templates. Can be called without authentication (e.g. from public ticket forms).

f
enforceMetadataLimits

Enforce a payment provider's metadata limits.

f
enforceTransactionRoundTripGuard

Count a statement within one interactive transaction and fire once, exactly when the running count crosses the threshold. Only enforced inside a request scope — startup migrations rebuild tables in one big transaction outside any request, so they are never counted. count is the running per-transaction statement count.

f
envNameSource

A table's env-key-encrypted name column as an id → name source. The env decrypt and the name column are the common case, so per-table wrappers bind just the table and its singular-word alias, then take .byIds (narrow id lookups) or .all() (every name, for pickers/labels).

f
epochMsToTzDate

The YYYY-MM-DD calendar day an epoch-ms instant falls on in tz. The inverse direction of dayStartEpochMs, for labelling a stored occurred_at as the local day it belongs to.

f
executeBatch

Execute multiple write statements, discarding results.

f
executeBatchWithoutCacheInvalidation

Write without firing cache invalidation. Reserved for plaintext bookkeeping rows (script-version markers) no cache ever holds — written concurrently with requests, the normal path would wipe the settings snapshot the request just loaded.

f
executeUpdate

Build the update statement and run it in one call — the executing form for the single-statement call sites (batch and transactional callers use update itself).

f
executeWithoutCacheInvalidation

Run a single statement without table-scoped cache invalidation.

f
expandDailyRange

Expand a daily-listing range into individual day strings.

f
expiresIn

Epoch seconds maxAgeSeconds from now — the expiry (e) that signed tokens carry, kept in one place so every builder computes it the same way.

f
extendedBy

A copy of base with extra entries merged on top (an extra key wins over the same key in base). Curried so a constant overlay (a fixed content type, a default set) can extend whatever record it is given.

f
extractSessionMetadata

Normalize validated session metadata into the canonical SessionMetadata shape.

f
extractSvgContent

Extract the inner content of an SVG element (strip the outer <svg> wrapper)

f
extractUpdateColumns

Parse the column names assigned by an UPDATE SET clause. Returns a lower-cased Set, or null if the SET clause cannot be found. Each col = expr left-hand side is extracted; commas inside parentheses are skipped so subexpressions don't split assignments. If extraction yields no columns the caller falls back to unconditional invalidation. Exported for unit testing; not part of the public db-client API.

f
extractViewBox

Extract the viewBox from an SVG element to compute its coordinate space

f
fieldById

Index one field from each item by its id.

f
filter

Curried filter

f
finalizeSessionIfUnresolved

Heal a still-unresolved reservation by stamping attendee_id, leaving ticket_tokens untouched. The ledger-replay path uses this: when a late delivery finds the booking already recorded in the ledger, it points its fresh reservation row at the existing attendee so the next delivery takes the fast already-processed path — but ONLY while the row is unresolved, so it never overwrites the attendee_id or blanks the ticket_tokens a racing delivery may have just finalized and stored. Guarded on UNRESOLVED_RESERVATION (the first outcome wins), and a no-op if the row was pruned away.

f
firstIssueMessage

Run a valibot schema with abortPipeEarly and return the first error message or null.

f
firstMatch

Alternative combinator: try a sequence of producers in order and return the first that yields a defined value, or undefined if every one declines.

f
firstProblem

Check items in order and stop at the first reported problem.

f
flatMap

Curried flatMap

f
flushPendingWork

Await all queued work. Call before returning the response. Loops until the queue stays empty: work already running can queue more (a background job that fails queues its error's activity-log write), and a single pass would discard those late arrivals unawaited.

f
formatCurrency

Format an amount in minor units (pence/cents) as a currency string. e.g. formatCurrency(1050) → "£10.50" (when currency is GBP)

f
formatDateLabel

Format a YYYY-MM-DD date for display. Returns "Monday 15 March 2026"

f
formatDateLongLabel

Format a UTC ISO datetime as a date-only label in the configured timezone, e.g. "Monday 15 June 2026" — no time. Returns "" for an empty/invalid input. Used where a stored timestamp should read as a plain published date (the public news post page).

f
formatDateRangeLabel

Format a booking's stored [start_at, end_at) ISO range as a human label. 1-day bookings collapse to formatDateLabel; multi-day bookings use the compact English range formatter (inclusive — subtracts 1 day from end_at, which is the first midnight after the booked window).

f
formatDateRangeLabelCompactEn

Compact English date-range formatter. Uses an en dash () for ranges.

f
formatDatetimeInTz

Format a UTC ISO datetime string for display in the given timezone. Returns e.g. "Monday 15 June 2026 at 14:00 BST"

f
formatDatetimeLabel

Format an ISO datetime string for display in the given timezone. Returns e.g. "Monday 15 June 2026 at 14:00 BST"

f
formatDatetimeShort

Compact ISO datetime formatter for table cells. Returns e.g. "07/04/2026 14:00" in the configured timezone.

f
formatDatetimeShortInTz

Compact format for table cells: "yyyy-MM-dd HH:mm" in the given timezone. Delegates to the browser-compatible formatIsoForPreview helper so the same formatting runs on the server and in the admin JS bundle.

f
formatErrorMessage

Format an error context into a human-readable activity log message

f
formatMonthLabel

Format a YYYY-MM month string for display, e.g. "July 2026".

f
formatPrefixed

Format IV + ciphertext as a prefixed base64 string

f
formatRequestError

Format an error detail string with request context and error message

f
formatSignedCurrency

Format a signed change in minor units. Positive value is added, negative value is removed, and zero has no misleading sign.

f
formatTimeAgo

Human "time ago" label for a past ISO timestamp, relative to nowMsValue (epoch ms), via Intl.RelativeTimeFormat in the largest whole unit that applies — e.g. "now", "5 minutes ago", "yesterday", "2 days ago". Returns null for an unparseable or future timestamp.

f
fromBase64

Convert base64 string to Uint8Array

f
fromBase64Url

Convert a base64url string (no padding) back to a Uint8Array — the inverse of toBase64Url.

f
generateAttachmentFilename

Generate a random CDN filename preserving the original name for readability

f
generateDataKey

Generate a random 256-bit symmetric key for data encryption

f
generateKeyPair

Generate an RSA key pair for asymmetric encryption Returns { publicKey, privateKey } as exportable JWK strings

f
generatePassJson

Build the pass.json content from pass data and signing credentials

f
generateQrSvg

Generate an SVG string for a QR code encoding the given text. Returns a complete <svg> element suitable for inline embedding.

f
generateSecureToken

Generate a cryptographically secure random token Uses Web Crypto API getRandomValues

f
generateSlug

Generate a random slug with at least 2 digits and 2 letters. Uses Fisher-Yates shuffle on the fixed positions to avoid bias.

f
generateSvgTicket

Generate a standalone SVG ticket with QR code and listing/booking details. Returns a complete SVG document string.

f
generateTicketToken

Generate a 5-byte uppercase hex ticket token for public ticket URLs

f
generateUniqueGroupSlug

Generate a unique group slug, retrying on collision.

f
generateUniqueSlug

Generate a unique slug by retrying random slugs until one is not taken.

f
generateWebpFilename

Generate a random .webp filename. Every uploaded image is transcoded to WebP, so stored image variants always carry the .webp extension.

f
getActiveEmailConfig

The email config sending should use: the site's own settings when complete, otherwise the host-level config. Null when neither is configured — callers treat that as "email is off".

f
getActiveHolidays

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

f
getActiveListingStats

Get aggregated statistics for active listings. All three values are summed from the precomputed aggregate columns on ListingWithCount (trigger-maintained), which are already in memory from the caller's getAllListings() fetch — no additional DB query needed.

f
getActivePaymentProvider
No documentation available
f
getAllActivityLog

Get all activity log entries (most recent first)

f
getAllAttendeePiiBlobs

Get every attendee's encrypted PII blob (one row per attendee). Used to resolve bulk-email recipient lists, where only the email inside each blob is needed. De-duplication of addresses happens after decryption.

f
getAllCacheStats

Collect stats from all registered caches

f
getAllGroupNames

Narrow id → name map for every group (selects + decrypts only the name), for pickers/labels that must not load the whole groups cache.

f
getAllListingOptions

Read the narrow listing option projection used by item pickers.

f
getAllListings

Read every listing with effective defaults and aggregate projections.

f
getAllSessions

Get all sessions ordered by expiration (newest first)

f
getAllUsers
No documentation available
f
getAttendeeActivityLog

Get activity log entries for a specific attendee (most recent first), decrypting messages.

f
getAttendeeBookingRowsByTokens

Look up attendees by plaintext tokens for the Previous bookings table.

f
getAttendeeKindsByIds

Bounded id → kind lookup for attendee-linked admin surfaces. Empty ids ⇒ empty map. Unknown/deleted ids are omitted.

f
getAttendeeNamesByIds

Bounded id → name lookup for the given attendees, decrypting only the name from each PII blob with the owner private key (no booking join, one row per attendee). Empty ids ⇒ empty map. Used for link labels in the activity log; a deleted attendee's id simply has no entry.

f
getAttendeeOrNull

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

f
getAttendeePackageRowsRaw

One attendee's raw booking rows within one package group (real lines only — quantity > 0). Lets a listing-scoped action rehydrate the WHOLE package the selected line belongs to, so a per-member notification resend doesn't treat a single member row as the complete package.

f
getAttendeePiiBlobForToken

Get the encrypted PII blob for the attendee identified by a plaintext ticket token. Used to resolve a single-attendee bulk-email recipient. Ticket tokens are unique, so this matches at most one attendee; returns null when the token matches none, so a stale or unknown token resolves to no recipient rather than erroring.

f
getAttendeePiiBlobsForListings

Get the encrypted PII blobs for attendees booked onto any of the given listings (one row per attendee, even if booked onto several of them). Returns an empty array when no listing IDs are supplied.

f
getAttendeeRaw

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, listing_id, quantity are plaintext)

f
getAttendeesByIds

Get attendees by ID without decrypting PII, one row per (attendee, booking). Used by the agent run sheet, which already knows the attendee ids it needs and only reads each attendee's contact fields. Returns an empty array for no ids. Decrypt with decryptAttendees before display.

f
getAttendeesByListingIds

Read raw attendees attached to any requested listing.

f
getAttendeesByTokens

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

f
getAttendeesPage

Get one page of attendees — with every one of their booking rows — for the admin attendees browser.

f
getAttendeesRaw
No documentation available
f
getAvailableDates

Compute available booking dates for a daily listing. Filters by bookable days of the week and excludes holidays. For listings with duration_days > 1, excludes start dates whose full range would hit a non-bookable day or extend past the booking window.

f
getBasename

Extract the basename from a path (handles both forward and backslash separators)

f
getBookableStartDates

Available start dates for a daily listing's booking/date pickers. Customisable-days listings use single-day availability — the span is chosen separately and validated at submit time — so every individually-bookable start is offered; other listings use their fixed duration.

f
getBookingFee

Get booking fee percentage from database. Returns 0 if not set.

f
getBotpoisonPublicKey

Get the Botpoison public key from environment (safe to expose to browsers). Returns empty string when unset.

f
getBotpoisonSecretKey

Get the Botpoison secret key from environment (server-side verification only). Returns empty string when unset.

f
getBunnyApiKey

Get the Bunny CDN API key from environment

f
getBunnyDnsSubdomainSuffix

Get the Bunny DNS subdomain suffix (e.g. ".tickets") from environment

f
getBunnyDnsZoneId

Get the Bunny DNS zone ID from environment

f
getBunnyScriptId

Get the Bunny Edge Script ID from environment

f
getCachedSession

Return the cached session if already resolved, or undefined if not yet resolved

f
getCatalogListings

Read only active, effectively visible listings for the public catalog.

f
getCdnHostname

Get CDN hostname (delegates to bunnyCdnApi for testability).

f
getCurrentCsrfToken

Get the most recently generated CSRF token (for synchronous JSX rendering)

f
getCurrentSettingsVersion

Read the current settings_version counter straight from the DB (bypassing the snapshot and the read audit — it is cache machinery, not an app setting). The row is an integer once any write has created it; before the first write (a fresh database) it is absent, which reads as version 0.

f
getDailyListingAttendeeDates

Read every occupied date across daily listing bookings.

f
getDailyListingAttendeesByDate

Read daily-listing attendees whose booking overlaps one date.

f
getDatelessGroupRemaining

Date-less remaining for capped groups reached from cumulative listings.

f
getDb

Get or create database client

f
getDebugKey

Diagnostic key gating the verbose /health response. Empty when unset, in which case /health only ever returns the plain liveness reply. Holding the key reveals non-private build/runtime diagnostics (commit, build time) that are useful for operators but needlessly helpful to an attacker.

f
getDecimalPlaces

Get the number of decimal places for a currency code

f
getDefaultDbProvider

Get the default database provider from DEFAULT_DB_HOST env var. Returns "turso" when set to "turso", "bunny" otherwise.

f
getDenoDeployOrgId

Get the Deno Deploy organization ID from environment.

f
getDenoDeployOrgSlug

Get the Deno Deploy organization slug used in managed production domains.

f
getDenoDeployToken

Get the Deno Deploy API token from environment.

f
getEffectiveDomain

Get the effective domain synchronously; DEFAULT_DOMAIN until a request resolves a real one.

f
getEmailConfig

Read email config from DB settings. Falls back to business email for fromAddress. Returns null if not configured or the from address is invalid.

f
getEmbedHosts

Get allowed embed hosts from database (encrypted, parsed to array) Returns empty array if not configured (embedding allowed from anywhere)

f
getEncryptionKeyBytes

Raw 256-bit encryption key bytes, decoded once from DB_ENCRYPTION_KEY

f
getEncryptionKeyString

Get the encryption key bytes from environment variable (sync validation only) Expects DB_ENCRYPTION_KEY to be a base64-encoded 256-bit (32 byte) key

f
getEnv

Get an environment variable value Checks process.env first (Bunny Edge), falls back to Deno.env (local dev)

f
getGroupBySlugIndex

Get a single group by slug_index (from cache)

f
getGroupPackagePrices

Every membership row for a group, carrying its package_price override and per-package quantity. A null package_price means "no override — use the listing's own price", 0 means explicitly free in this package, and a positive value overrides the price; quantity defaults to 1. The override is read from the group dimension of listing_prices; quantity from the membership row.

f
getGroupPackagePricesByGroupIds

The membership rows for several groups in one query, keyed by group id, so a list endpoint can hydrate every group's package members without a per-group round-trip. Groups with no membership rows are absent from the map.

f
getGroupRemainingForListing

Remaining group capacity for one listing, or undefined when no cap applies or the listing does not exist.

f
getGroupRemainingForSpan

Tightest remaining group capacity over a whole daily span.

f
getGroupsById

Every group keyed by id, from the request-cached set — the batched alternative to one findById per id when resolving or validating many groups without tripping the N+1 read guard.

f
getGroupStaticCapByGroupId

Static maximum capacity for each capped group.

f
getHiddenPackageMemberIds

Of the given listing ids, those that belong to a HIDDEN package — a package group (is_package = 1) with hide_package_listings = 1. Buyers must never meet these members standalone: the package name is the only public surface, so every buyer-facing discovery/direct path drops them.

f
getHostEmailConfig

Get host-level email config. Uses test override if set, otherwise reads env vars.

f
getIframeMode

Get the current request's iframe mode

f
getImageProxyUrl

Images are encrypted at rest, so browsers load them through this route.

f
getListingActivityLog

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

f
getListingAggregateRecalculation

Compare stored listing aggregates with the values rebuilt from bookings.

f
getListingOfferFlags

Read the flags that decide whether one listing may be offered.

f
getListingPickerNames

Read names and offer flags for the admin site-page picker.

f
getListingRemainingForRange

Remaining bookable units for each listing over a date range.

f
getListingRows

The one reader every listing-record surface uses: declare the filter and the order, and it returns raw rows. Encrypted columns are still encrypted — decrypt with the readers in records.ts before display.

f
getListingsByGroupIds

Members of SEVERAL groups at once, keyed by group id — the batched form of the single-group loaders for a multi-group surface. A page with many group leaves would otherwise run one member query per group; this loads the join once and the member listings once, then assembles each group's list in memory. Every requested group id maps to an entry (empty when it has no matching member). activeOnly keeps just active members (the site-page nav's liveness gate); the default includes inactive members (the validators' group-compatibility read for a listing that joins many groups, kept batched to stay under the N+1 guard).

f
getListingsById

Read every listing keyed by id.

f
getListingsBySlugs

Read listings by slug in input order, retaining nulls for missing rows.

f
getListingsWithCountsByIds

Read listings in input order, retaining nulls for expected missing rows.

f
getListingWithActivityLogOrNull

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

f
getListingWithAttendeeRaw

Read one listing and one attendee in one round-trip.

f
getListingWithAttendeesRaw

Read one listing and all its attendee rows in one round-trip.

f
getListingWithCount

Read one listing when absence is expected.

f
getListingWithCountBySlug

Read one listing by its plaintext slug when absence is expected.

f
getListingWithCountPrimary

Read a just-written listing from the primary, or null if it was deleted.

f
getMainInstanceKey

The shared secret authorizing the inter-instance site-credentials endpoint.

f
getMimeTypeFromFilename

Get the MIME type for an image filename from its extension.

f
getNewestAttendeesRaw

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

f
getNextBookableDate

Get the next available booking date for a daily listing. More efficient than getAvailableDates()[0] — stops at first match. Returns null if no bookable dates are available.

f
getPackageDisplaysByIds

The package displays for a set of (possibly repeated or zero) package_group_ids — only ids naming a live package appear in the map. Lets the ticket view collapse each token's package rows into one card per package, so an attendee holding both a package booking and a standalone one (e.g. after an attendee merge) doesn't fall back to per-row cards that leak a hidden member. Groups are resolved together from their shared cache.

f
getPbkdf2Iterations
No documentation available
f
getPrivateKeyFromSession

Derive the private key from session credentials Used to decrypt attendee PII in admin views Results are cached per session token for 10 seconds

f
getQueryLog

Return a snapshot of all logged queries

f
getQueryLogStartTime

Return the start time recorded by enableQueryLog()

f
getRandomBytes

Generate random bytes using Web Crypto API

f
getReadOnlyCutoffIso

Get the READ_ONLY_FROM cutoff ISO string, or null if not set

f
getRenewalUrl

Get the RENEWAL_URL, or null if not set

f
getRequestId

Get the current request ID, or empty string if outside request context

f
getSession

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

f
getSessionCookieName
No documentation available
f
getSharedGroupCapacities

Group remaining, static caps, and membership for date-less package checks.

f
getStorageBackend

Returns which storage backend is active: "bunny", "local", or "none".

f
getStoredListingsWithCountsByIds

Read requested listings' stored values without overlaying inherited defaults.

f
getStoredListingWithCount

Read one listing's stored values without overlaying inherited defaults.

f
getTursoApiToken

Get the Turso API token from environment.

f
getTursoGroup

Get the Turso database group from environment.

f
getTursoOrganization

Get the Turso organization name from environment.

f
getUserAuthFieldsById

Get the minimal encrypted user fields needed to authenticate a session.

f
getUserById

Get a user by ID (from cache)

f
getUserByInviteCode

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

f
getUserByUsername

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

f
getUserDisplayFields

Get the minimal encrypted user fields needed to show assignable users.

f
groupExists

Does a group row exist? The add-item revalidation's single-row check — no name decryption, never the whole table.

f
groupListingTypeError

The in-memory core of validateGroupListingType: given a group's already-loaded members, return the homogeneity error (or null). Callers that validate many groups at once batch the member reads (see getListingsByGroupIds) and drive this directly, so they never issue one sibling query per group and trip the N+1 read guard.

f
groupToMap

Group rows by a key, keeping only the chosen value from each row. Keys appear in first-occurrence order and each value list preserves input order.

f
hasActiveBookingLine

True when the attendee has a real (quantity > 0) booking on the exact listing. Authorizes per-(attendee, listing) actions — e.g. the signed attachment download — against the EXACT row, not getAttendeeRaw's arbitrary left-joined sibling row (which for a mixed attendee could pass on a ghost/other-listing row, or wrongly reject a valid real-line download). A no-quantity sentinel line is excluded, so a line later marked no-quantity stops authorizing.

f
hashInviteCode

Hash an invite code using SHA-256

f
hashPassword

Hash a password using PBKDF2 Returns format: pbkdf2:iterations:$base64salt:$base64hash

f
hashSessionToken

Hash a session token using SHA-256 Used to store session lookups without exposing the actual token

f
hasPackageBookings

Whether any booking row is stamped with this package's group id — sold tickets whose display (and hidden-member concealment) resolves through the live package row. Refund placeholders (quantity 0) don't count.

f
hasPendingWorkScope

True when running inside a runWithPendingWork scope (i.e. a request).

f
hasRequiredSessionMetadata
No documentation available
f
hasTicketQuantity

True when an attendee/booking row is a real ticket (quantity ≥ 1) rather than the no-quantity sentinel (quantity 0). The shared "is this a real ticket, not a ghost" test for the readers, rosters, and exports that must skip sentinel rows — one home for the rule instead of a bare quantity > 0 plus an explanatory comment at each call site.

f
hmacHash
No documentation available
f
hmacHashSync

HMAC-SHA256 hash using DB_ENCRYPTION_KEY Used for blind indexes and hashing limited keyspace values Returns deterministic output for same input (unlike encrypt)

f
hmacSha256Hex

Hex-encoded HMAC-SHA256 of a UTF-8 message under the given secret.

f
hmacToBase64

Convert ArrayBuffer to base64 string

f
hmacToHex

Convert ArrayBuffer to hex string

f
hybridDecrypt

Decrypt data using hybrid encryption Expects format: hyb:1:$base64WrappedKey:$base64iv:$base64ciphertext Results are cached in a bounded LRU (ciphertext -> plaintext)

f
hybridEncrypt

Encrypt data using hybrid encryption (RSA + AES)

f
idAndCreatedSchema

Shared generated id + plaintext created stamp columns. created stays unencrypted so SQL can order and prune by time without decrypting.

f
identity

Return a value unchanged.

f
importKey

Import a CryptoKey from DB_ENCRYPTION_KEY.

f
importPrivateKey

Import a private key from JWK string

f
importPublicKey

Import a public key from JWK string

f
incrementAttachmentDownloads
No documentation available
f
initDb

Initialize database tables for an existing database. Fresh database creation requires allowMissingSettings. Uses an advisory lock to prevent concurrent migrations.

f
inPlaceholders

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

f
insert

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

f
invalidateCachesForTable

Fire every cache invalidator registered against table (no-op if none). Treats the write as unconditional (INSERT semantics): always fires column-gated entries too.

f
invalidateCachesForWrite

Fire registered cache invalidators for table, respecting column gates.

f
invalidateInitDbCache

Forget the per-isolate "database is ready" cache.

f
invalidateListingsCache

Clear the listing entity cache.

f
invalidateUsersCache

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

f
isBookingRangeValid

Whether booking days consecutive days starting on date is valid for a daily listing: every day must be a bookable weekday, fall outside all holidays, and stay within the listing's booking window. Used to enforce the visitor's chosen span on "customisable days" listings at submit time, where the day count isn't known when the date list is rendered.

f
isBotpoisonEnabled

Check if Botpoison spam protection is configured. Requires both BOTPOISON_PUBLIC_KEY and BOTPOISON_SECRET_KEY to be set. This gates the public contact form feature.

f
isBuilderEnabled

Check if this instance can build other sites.

f
isBunnyCdnEnabled

Check if Bunny CDN pull zone management is enabled Requires both BUNNY_API_KEY and BUNNY_SCRIPT_ID to be set

f
isBunnyDbEnabled

Check if the Bunny hosted database provider is enabled (requires BUNNY_API_KEY).

f
isBunnyDnsEnabled

Check if Bunny DNS subdomain feature is enabled. Requires BUNNY_API_KEY and BUNNY_DNS_ZONE_ID to be set.

f
isDatabaseRoundTripLimited

Whether database calls are currently subject to Bunny's per-request cap.

f
isDemoMode

Check if demo mode is enabled

f
isDenoDeployEnabled

Check if Deno Deploy hosting has its token, organization ID, and domain slug.

f
isFooterDebugEnabled

Whether the admin debug footer may render the captured queries.

f
isGroupSlugTaken

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

f
isHiddenPackageMember

Whether a single listing is a HIDDEN package's member — the one-listing form of getHiddenPackageMemberIds, for the buyer-facing guards (API lookup, QR booking, standalone-page test) that ask this of one listing at a time.

f
isInstanceApiEnabled

Whether the inter-instance site-credentials endpoint is enabled. Off unless MAIN_INSTANCE_KEY is set, so a non-builder instance never exposes it. The key is a high-entropy shared secret the operator passes to the upgrade workflow at trigger time (it is never stored in GitHub).

f
isInviteExpired

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

f
isInviteValid

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

f
isInWarningWindow

Pure helper: is the current time within the warning window before cutoff?

f
isNotNullish
No documentation available
f
isNullish

Remove null and undefined values from array

f
isoBefore

ISO timestamp a fixed duration before the current time.

f
isPaidListing

Whether an listing can accept payments: a flat price, pay-what-you-want, or a customisable-days listing with at least one non-zero day-count price.

f
isPaymentsEnabled

Check if payments are enabled (any provider configured with valid keys)

f
isReadOnly

Check if the system is in read-only mode based on the READ_ONLY_FROM cutoff

f
isReadOnlyFromCutoff

Pure helper: is the site read-only based on a cutoff timestamp?

f
isReadOnlyWarning

Check if the site should show a pre-expiry warning banner

f
isRecord

Type guard: a non-null, non-array object (a Record shape).

f
isReservationStale

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

f
isSafeUrl

True when a link/image URL is safe to render. Relative URLs (no scheme) are allowed; absolute URLs must use a scheme from SAFE_URL_SCHEMES. Leading ASCII control characters and spaces — which browsers strip before resolving a scheme — are removed first so java\tscript: can't sneak through.

f
isSecureMode

Whether we are serving a real, resolved host rather than the default. Gates HTTPS-only behaviour — Secure/__Host- cookies and the HSTS header — which must stay off for local development on DEFAULT_DOMAIN.

f
isSessionProcessed

Check if a payment session has already been processed

f
isSignedCsrfToken

Check whether a token uses the signed format

f
isSimpleMarkdown

True when text is markdown so simple it renders as nothing more than a single <p> of plain text — no bold, italic, links, lists, headings, code, blockquotes, tables, or multiple paragraphs. When this returns true the question can safely be used as the clickable label of its control; when false the question should be rendered as a prose block above the control.

f
isSlugTaken

Check whether a slug is already used, optionally excluding one listing.

f
isStorageEnabled

Check if image storage is enabled (Bunny CDN or local filesystem).

f
isTursoEnabled

Check if Turso hosted database provider is enabled (requires TURSO_API_TOKEN, TURSO_ORGANIZATION, TURSO_GROUP).

f
isUnresolvedReservation

True when a row is an in-progress reservation with no recorded outcome — the in-memory mirror of the UNRESOLVED_RESERVATION SQL predicate.

f
isUsernameTaken

Check if a username is already taken

f
isValidDatetime

Check if a naive datetime-local string is a parseable datetime. Does not interpret timezone — purely a format check.

f
isValidEmail

Whether a string is a valid email (trimmed) per EmailSchema.

f
isValidTimezone

Validate that a string is a valid IANA timezone identifier.

f
joinStatements

Combine several { sql, args } pieces into one statement: the SQL fragments joined with joiner, the args concatenated in the same order. For SQL built from repeated sub-clauses (e.g. one capacity clause per day, joined with " AND ").

f
lazyRef

Resettable lazy reference - like once() but can be reset for testing. Returns [get, set] tuple where set(null) resets to uncomputed state.

f
lineKeyFromBooking

Build the canonical line key from a stored booking row (matches the ${listingId}|${startAt}|${parentListingId}|${packageGroupId} identity carried by the form's hidden key field). parent_listing_id distinguishes the two rows produced when the same child is booked under two different parents; package_group_id the rows produced when the same listing is booked through two packages (or a package plus its own standalone row) in one order.

f
listFiles

List files in storage matching a prefix (names only), sorted by name.

f
listFilesWithMeta

List files (with size metadata) matching a path prefix, sorted by name. The prefix may name a subfolder (see splitListingPrefix); returned names always include that folder so callers can download/delete them directly. For Bunny CDN the size comes from the Length field of the listing API.

f
listingAttendeeRowColumnsFrom

Columns for a ListingAttendeeRow read straight from one listing_attendees source. The source name feeds correlated ledger subqueries, so a caller can pass either the table name or a query alias without the sibling subquery shadowing bare column names.

f
listingDateToCalendarDate

Convert a UTC ISO datetime to a YYYY-MM-DD calendar date in the given timezone. Returns null if the input is empty or invalid. Used by the calendar view to map standard listing dates to calendar days.

f
listingHasSpots

True when the listing still has spots for this quantity on this date (no date for a date-less listing, whose capacity is one running total).

f
listingStatement

A queryBatch statement (SQL + bound args) for a listing read: the single place a declared query becomes runnable SQL. getListingRows runs it; the activity-log reader embeds it in a batch, and the read-your-own-write reader runs it against the primary.

f
listingSupportsDirectCheckout

Whether this listing can send QR code scanners directly to checkout. True when no extra contact fields or questions are required.

f
loadAfterDemoOverrides

Apply demo-mode overrides to the form, then run the loader — the shared prelude of the attendee submit handlers, which 404 when the loader finds nothing (a stale id racing a delete).

f
loadAttendeeRows

Load attendee rows carrying the standard ATTENDEE_FIELDS set (PII still encrypted — decrypt before display). Callers vary only in join, order, and where, so the field set is declared in exactly one place.

f
loadEffectiveDomain

Load the effective domain from DB, falling back to the request URL hostname.

f
loadExistingLines

Read all current listing_attendees rows for an attendee, with line keys.

f
loadPackageMemberPricing

A package group's full pricing state in one load: its membership rows, the flat override + quantity maps (packageMemberMaps), and each customisable member's per-day overrides — the shape the booking flow, the webhook payload, and the payment revalidation all consume.

f
loadSortedListings

Load all listings with holidays and return them sorted. With a filter, only the listings it keeps are returned; without one, every listing is returned.

f
localToUtc

Convert a naive datetime-local value (YYYY-MM-DDTHH:MM) to a UTC ISO string, interpreting the value as local time in the given timezone.

f
logActivity

Log an activity. Optionally associate it with a listing and/or attendee so admin views can filter the log by either. A caller may pass its open write transaction so the activity and the action it records commit together.

f
logAndNotifyRegistration

Log attendee registration and send consolidated webhook Used for single-listing registrations

f
logCompletedSql

Mirror the debug footer to the system logs: emit each SQL statement as it completes, with its bound values omitted. The statement is parameterised, so the string carries only ? placeholders — never PII or secrets — exactly the value-free view the admin footer renders. Whitespace is collapsed so a multi-line statement logs on one line. Routed through logDebug (category "SQL") so it honours the same debug-log suppression as other debug output; the dynamic import avoids the static cycle (query-log is imported by the db client, which the logger transitively depends on), mirroring notifyN1Violation.

f
logDbError

Log a failed database operation under the standard DB_QUERY code.

f
logDebug

Log a debug message with category prefix For detailed debugging during development

f
logError

Log a classified error to console.error and persist to the activity log. Console output uses error codes and safe metadata (never PII). Activity log entry is encrypted and visible to admins on the log pages.

f
logErrorLocal

Log a classified error to console.error only (no ntfy, no activity log). Use this where calling logError would cause infinite recursion (e.g. ntfy.ts).

f
logRequest

Log a completed request to console.debug Path is automatically redacted for privacy

f
makeCreateCheckoutSession

Build a provider's createCheckoutSession: call the provider's own create function, read the session id and URL off whatever shape it returns, and map that to a shared CheckoutSessionResult — all inside the standard checkout error guard. Each provider only supplies its create call, how to read the id/url, and its display label.

f
makeIpRateLimiter

Build a namespaced per-IP limiter: isLimited checks the lockout, record counts one attempt (locking out at maxAttempts for lockoutMs and returning true once locked). Each caller picks its own prefix so counters never collide across features.

f
map

Curried map

f
mapBy

Index items by one field and chosen value. Keys keep first-occurrence order, while later matching items replace the stored value.

f
mapById

Index items by id and a chosen value.

f
mapByIds

Run an integer-keyed lookup query and turn each row into a [key, value] pair via toEntry, returning the id-keyed map (empty when ids is empty).

f
mapNotNullish

Curried map that drops null/undefined results in one pass. Curried adapter over @std/collections.mapNotNullish. Replaces the two-step pattern: compact(map(fn)(array))

f
mapParallel

Map over a promise-returning function in parallel (Promise.all)

f
markSessionFailed

Record a handled terminal failure on a still-unresolved session. A later redirect/webhook for the same session reads this back via parseSessionFailure and returns the same outcome, so refunds and validation never run twice. Guarded on UNRESOLVED_RESERVATION, so it never clobbers a finalized success and never overwrites an already-recorded failure (the first outcome wins); a no-op if the row was pruned away.

f
mergeListingFields

Determine which contact fields to collect for multiple listings. Returns the union of all field settings, sorted by canonical CONTACT_FIELDS order.

f
migrateUserToV2Kek

Re-wrap a user's DATA_KEY under the password-bound (v2) KEK. Called at login — the one place both the raw password and the freshly-unwrapped DATA_KEY are in hand — for users still on the legacy v1 wrap, replacing the DB-recoverable wrap in place without touching any encrypted data.

f
monthsAround

List every YYYY-MM month within yearsEitherSide years of the given month's year, in ascending order. e.g. monthsAround("2026-03", 5) runs from "2021-01" to "2031-12". Used to populate the calendar's month picker.

f
nameSource

A table's id → name projection, bound to its columns once. byIds returns the map for the requested ids (empty ids ⇒ empty map); all returns it for every row, ordered by id. Only the name column is decrypted, via the decryption-agnostic decryptName; table/alias/nameColumn (alias qualifies the selected columns, repo SQL convention) are internal constants.

f
normalizeDatetime

Normalize datetime-local "YYYY-MM-DDTHH:MM" to full UTC ISO string. The input is interpreted as local time in the given timezone and converted to UTC.

f
normalizePhone

Strip non-numeric characters from a phone number and normalize to +{prefix}{local}

f
normalizeSlug

Normalize a user-provided slug: trim, lowercase, replace spaces with hyphens

f
now

Current time as a Date

f
nowIso

Full ISO-8601 timestamp for created/logged_at fields

f
nowMs

Epoch milliseconds for numeric comparisons

f
nowSeconds

Current time in whole epoch seconds — the unit signed-token expiry uses.

f
once

Lazy evaluation - compute once on first call, cache forever. Use instead of let x = null; const getX = () => x ??= compute();

f
onEncryptionKeyChange
No documentation available
f
onUsersInvalidated

Register a callback to run whenever the users cache is invalidated.

f
overlapsDay

Whether a stored booking overlaps one day. String comparison mirrors the SQLite overlap check byte-for-byte.

f
packageChildEdgeConflict

Which package invariant adding child edges would violate, or null when the edges are fine: gate_in_hidden when the parent is joining/in a HIDDEN package group (a visible package renders the member's child selector, so a member gating children is fine there), or child_is_member when any chosen child is itself a package member (a package member is only ever sold as part of its bundle, never folded under another parent). An empty childIds (clearing children) is never a conflict.

f
packageDisplaysForRows

The package displays behind a set of booked rows — each row's attendee names its persisted package_group_id (0 on a plain row, matching no package). Shared by the ticket view, the wallet lookup, and the email renderer, which all carry { attendee, listing } row shapes.

f
packageMemberMaps

A package group's member rows projected into the two maps every consumer needs (the booking flow, the webhook revalidation, the bookability gate, and the test harness): prices keeps only members with a real override — a positive price OR an explicit free 0, dropping a null "no override" — while quantities covers every member (default 1). Owning both here keeps the "what counts as an override" rule in one place; callers destructure what they use.

f
packageMembersError

The member-naming package error for the first listing in listings that can't be a package member (pay-what-you-want, an add-on of another listing, or — on a hidden package — a member gating its own children), or null when every listing is a valid member. The one place every package save (group form, add-listings, listing form/API, catalog import) turns an unpackageable member into its user-facing message.

f
packMetadata

Collapse the packable small fields into one JSON b entry, dropping them from the top level. Falsy values are omitted (the "" = absent convention), so the b entry only appears when at least one packed field is actually present.

f
padAuthToken

Pad a serial number to meet Apple's minimum authenticationToken length. Uses "-" (not in uppercase hex charset) so padding is cleanly reversible.

f
parseBunnyError

Parse a Bunny API error response into a BunnyApiResult.

f
parseDateMs

Parse a date/timestamp string to epoch milliseconds, or null when it doesn't parse — the safe wrapper around Date.parse, whose own failure mode (NaN) is easy to let leak into arithmetic by accident.

f
parseDayPrices

Coerce an arbitrary stored/parsed value into a clean DayPrices map. Keeps only whole-number day counts in [1, MAX_DURATION_DAYS] mapped to finite, non-negative whole-number minor-unit prices; everything else is dropped. Used on both the DB read path and form parsing so the rest of the code can treat the map as already-valid.

f
parseEmail

Parse and normalize a candidate email, returning the branded ValidEmail when it is valid or null otherwise. Use this in preference to isValidEmail when the validated address needs to be carried onward in a type-safe way.

f
parseEmbedHosts

Parse a comma-separated list of hosts into trimmed, lowercased entries. Filters out empty strings from trailing commas etc.

f
parseEncryptedPayload

Parse a prefixed encrypted payload into IV and ciphertext bytes. Validates the prefix and separator; throws on invalid format.

f
parseFlashValue

Parse a flash cookie value into type, message, optional result, and the optional form re-fill stash token.

f
parseIsoDateParam

Parse a user-supplied YYYY-MM-DD value (a ?date= query param): the string when well-formed and a real calendar date, else null. The UTC round-trip rejects rolled-over impossibilities like 2025-02-30.

f
parseListingFields

Parse a comma-separated fields string into individual ContactField names

f
parsePiiBlob

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

f
parseSessionFailure

Parse a stored terminal failure, or null when the row carries none. We only ever write valid encrypted JSON (via markSessionFailed), but a value that won't decrypt or parse (restore, manual edit, rotated key) must not crash the replay path — it degrades to a generic terminal failure so the session still resolves instead of looping.

f
parseWarnDays

Parse a string into a positive integer for warning days. Returns defaultVal on bad input.

f
parseWebhookPayload
No documentation available
f
partition

Split an array into [matching, rest] by a predicate, keeping order. Curried adapter over @std/collections.partition.

f
perDayLoads

Per-day quantity sums from rows fetched for the whole span.

f
pipe

Compose functions left-to-right (pipe).

f
processBooking

Process a single-listing booking.

f
providerValue

Pick the value for the active payment provider from a per-provider set, or null when no known provider is active. The one place the stripe/square/sumup dispatch lives, so every per-provider flag is read the same way.

f
queryAll

Query all rows, returning a typed array.

f
queryAndMap

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

f
queryColumnSet

Run a single-column SELECT and collect that column's values into a Set of strings — the shared shape of the "which hashes/names already exist" reads (e.g. the live table names, the unsubscribed contact hashes).

f
queryIdColumn

Run a query whose single selected column is aliased id and return the ids.

f
queryOne

Query one row, or null when the query returns none.

f
queryOnePrimary

Query an optional row on the primary (read-your-writes). Use this to read a row back immediately after committing its own write: a plain queryOne runs in "read" mode, which Turso can route to a replica lagging the just-committed write and so miss the row (returning null); routing through queryBatchPrimary ("write" mode) always hits the primary. Mirrors the same guard on syncListingPrices. args is required — every read-back keys on the written row's id.

f
randomChoice

Pick a random element from an array

f
rawSql

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

f
rebuildWipedSchema

Rebuild the full schema on a database that resetDatabase() just wiped, without reading the database to decide what to create.

f
recomputeListingBookingRanges

Recompute end_at on all existing listing_attendees rows for an listing based on a new duration_days value. Leaves NULL-start rows alone. The .000Z suffix matches the format fresh inserts produce via toISOString() so raw-row dumps stay consistent.

f
redactPath

Redact dynamic segments from paths for privacy-safe logging Replaces:

f
reduce

Curried reduce

f
registerBunnySubdomain

Register a bunny subdomain (DNS + CDN).

f
registerCache

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

f
registerCacheReset

Register an extra full-clear to run with a write cause when every cache is reset. Only needed by caches without a table registration; resetAllCaches already fires every table-registered invalidator.

f
registerDependencies

Register invalidate to fire whenever ownTable or any deps entry is written. Plain string entries are unconditional; object entries may carry whenColumns to gate on specific UPDATE columns (INSERT/DELETE always fire). Centralises the registration loop shared by cachedTable and cachedEntityTable.

f
registerTableInvalidation

Register invalidate to run whenever any of tables is written.

f
releaseReservation

Release an in-progress reservation so the very next delivery can re-claim it. Deletes only a still-unresolved row, so it never clobbers a finalized success or a recorded terminal failure that a racing delivery may have written.

f
remainingByListingOverGroups

Tightest capped-group value for each listing.

f
renderEmailContent

Render all 3 parts (subject, html, text) using custom templates with fallback to defaults

f
renderMarkdown

Render markdown to HTML (block-level: paragraphs, lists, etc.). Raw HTML is escaped and unsafe URLs are stripped.

f
renderTemplate

Render a single Liquid template string with the given data

f
requiredMapValue

Read a required map entry, failing where a broken completeness invariant is first observed instead of passing an undefined value onward.

f
requireEnv

Get a required environment variable, throwing if not set. Use this instead of getEnv(key) as string when the variable must exist.

f
requireListingsWithCountsByIds

Read required listings in input order through the shared cache path.

f
requireListingWithCount

Read one required listing through the shared many-listing path.

f
requireOne

Query one required row and name the failed query when none exists.

f
requireOnePrimary

Query one required row from the primary.

f
reserveSession

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
resetAggregates

Reset selected aggregate columns from trusted SQL expressions. Each expression must use the entity id as its only placeholder.

f
resetAllCaches

Clear every registered cache: each table-registered invalidator once (a cache registered against several tables still only clears once) plus every extra reset hook. Runs after operations that bypass the normal write path — a full reset or a restore — where any warm cache is stale. A lazily-loaded cache module that never ran is absent from the registry, which is correct: it has no cache to clear.

f
resetDatabase

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

f
resetDemoMode

Reset cached demo mode value (for testing and cache invalidation)

f
resetEffectiveDomain

Reset effective domain cache back to the default (for testing).

f
resetEngine

For testing: reset the engine (so filters can be re-registered after currency changes)

f
resetGroupListings

Remove every listing from a group (used when the group is deleted), along with the group's package price overrides — its flat group and per-day group_day price rows key on the group id, so they'd otherwise outlive the deletion.

f
resetHostEmailConfig

For testing: reset host email config to read from env vars.

f
resetListingAggregateFields

Reset selected listing aggregate columns from booking rows.

f
resultRows

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

f
rowExists

True when the query returns at least one row. sql should be an existence probe (e.g. SELECT 1 ... LIMIT 1); the selected columns are ignored. Shared by the per-(attendee, listing) and built-site assignment checks so the row-presence boilerplate lives in one place.

f
rowExistsForIdList

Build an existence check for "one leading id, matched against a list of ids". The returned checker binds leadingId to the first ? and expands ids into the IN (...) your buildSql embeds via the placeholder string it receives. Shared by the per-attendee "across these listings" probes so their signature and args boilerplate live in one place. Empty ids still runs the query with an empty IN (), which matches nothing — callers pass a non-empty list.

f
rowsByIds

Run an id-keyed SELECT, short-circuiting to [] (no query) when ids is empty. buildSql receives the bound ?-placeholder list for ids, so ids are the only query args. The base skeleton for the id-map helpers below and for any read that loads rows for a caller-supplied id list.

f
runWithCsrfContext

Run a function within a CSRF-token scope (one container per request)

f
runWithIframeContext

Run a function within an iframe-mode scope (one container per request)

f
runWithQueryLogContext
No documentation available
f
runWithSessionContext

Run a function within a session-memoization scope

f
runWithStorageConfig

Run fn with an isolated storage configuration (test-only).

f
sanitizeBasename

Strip a path's basename down with each [pattern, replacement] rule in turn, falling back to "file" when nothing is left. Shared by every filename sanitiser — each supplies its own character rules.

f
secureCompare

Constant-time string comparison (over UTF-16 char codes) to prevent timing attacks. Shares the one constant-time loop in constantTimeCodesEqual.

f
seedEffectiveDomainHost

Seed the effective domain from the request's own hostname.

f
sendBulkEmails

Send a bulk email via the configured provider. Every supported provider has a batch endpoint, so this works for any EmailConfig. Chunks recipients to the provider's batch limit and POSTs each chunk; logs (never throws) on a non-OK batch, whose recipients then count as failed. Each batch's provider response is captured so the caller can relay it to the sender.

f
sendEmail

Send a single email via the configured provider. Logs errors, never throws. Returns HTTP status or undefined on non-HTTP errors.

f
sendNtfyError

Send an error notification to the configured ntfy URL Returns a promise so callers can await delivery if needed. Delivery failures are logged locally (via logErrorLocal) but never throw.

f
sendRegistrationEmails

Send registration confirmation + admin notification emails. Entries is an array because one registration can cover multiple listings. Silently skips if email is not configured. Attaches one SVG ticket per entry to the confirmation email.

f
sendRegistrationWebhooks

Send consolidated webhook to all unique webhook URLs for the given entries

f
sendTestEmail

Send a test email to the business email address. Returns HTTP status or undefined on non-HTTP errors.

f
sendWebhook

Send a webhook payload to a URL Fires and forgets - errors are logged but don't block registration

f
setCachedSession

Store the resolved session in the current request scope

f
setDb

Set database client (for testing)

f
setDemoModeForTest

Explicitly set demo mode on or off (for testing). Bypasses Deno.env to avoid races between parallel test workers.

f
setEffectiveDomainForTest

Set effective domain directly (for testing).

f
setEncryptionKeyForTest

Explicitly set or clear the encryption key for testing. Bypasses Deno.env to avoid races between parallel test workers. Automatically clears all crypto caches (encryption, HMAC, and any registered via onEncryptionKeyChange).

f
setFastPbkdf2ForTest

Explicitly enable/disable fast PBKDF2 for testing without env var races

f
setGroupListingsActive

Set the active flag on every listing in a group. Returns the number of listings affected.

f
setGroupPackageMembers

Set a group's package member overrides — the flat group price rows in listing_prices plus the per-package quantity on the membership rows. Pass tx to run inside an existing write transaction (the admin API update path, so the overrides commit atomically with the group row write); omit it to run as the function's own statements. See applyPackageMembers for the partial-update rules.

f
setHostEmailConfigForTest

For testing: set host email config directly. Bypasses env vars to avoid races.

f
setListingGroupsTx

Replace a listing's group memberships inside an existing write transaction, so the change commits atomically with the listing row write (the admin API create/update path). Mirrors setListingGroups but reads the current set and runs each statement on the caller's tx.

f
setN1GuardNotifyOnly

Switch the N+1 guard between throw (default) and notify-only (production).

f
setRsaKeySizeForTest

Explicitly set RSA key size for testing without env var races

f
setStorageConfigForTest

Test-only: set the suite-level storage config that describeWithEnv's storage option applies. A directly-exported named function (not an export {} list, which the test-hook scanner does not detect, nor a module-level alias) so it is visible to and registered in ALLOWED_TEST_HOOKS (test/lib/code-quality.test.ts), alongside runWithStorageConfig.

f
setSuppressRequestLogs

Set module-level request log suppression (avoids env race in parallel tests).

f
sha1Hex

Apple requires SHA-1 for manifest entries; CMS signs the manifest with SHA-256.

f
sharedGroupCapacity

Build the SharedGroupCapacity for a parent/child pair from the PER-GROUP capacity maps (groupId → spots; uncapped groups omitted). They are co-grouped when their group sets intersect in at least one CAPPED group; when they are not, there is no shared cap (both facts undefined).

f
sharedGroupRemaining

The remaining spots of the capped group a parent and one of its children share, or undefined when they don't share a capped group. A parent and its required child in the same capped group consume two group spots per order, so callers must reason about combined demand, not each row in isolation.

f
shiftMonth

Shift a YYYY-MM month string by delta months (negative goes backwards). Crosses year boundaries: shiftMonth("2026-12", 1) → "2027-01".

f
signCsrfToken

Create a signed CSRF token: s1.{timestamp}.{nonce}.{hmac}

f
signedTestWebhook

Build a test webhook delivery: JSON-encode the event, sign it with the provider's own signing rule, and return the payload/signature pair a test can POST to the webhook route. Each provider supplies only sign.

f
singleListingAnswerIds

Convert single-listing answerIds to the per-listing format used in metadata

f
slugify

Turn arbitrary text into a URL slug: lowercase, every run of non [a-z0-9] collapsed to a single hyphen, no leading/trailing hyphen. Shared by the news permalink builder and the provider-resource slug.

f
slugifyForProvider

Sanitize a site name into a valid provider resource slug: the shared slugify, capped at maxLength with any hyphen the cut left trimmed.

f
sort

Non-mutating sort with comparator

f
sortListings

Sort listings in unified 3-tier order. Takes anything carrying the values the order is built from, so a narrow picker read sorts the same way a full listing record does.

f
sortStrings

Sort strings in ascending locale order without changing the input.

f
sqlWallClockMs

Wall-clock milliseconds during which at least one query was in flight: the combined length of the query intervals with overlaps merged.

f
startOfHour

Round a date down to the start of the current hour for cache-stable signatures

f
stringColumnSet

Collapse a result's rows to the set of one column's values, as strings — the shared tail of the "which names/ids already exist" reads (applied migrations, live table columns, index and trigger names).

f
sumByKey

Curried group-and-sum: accumulate valueOf(item) into a Map keyed by keyOf(item). Replaces the common pattern: const m = new Map(); for (const x of xs) m.set(k(x), (m.get(k(x)) ?? 0) + v(x))

f
sumOf

Curried sum-by-selector. Adds up the numbers produced by selector for each item. Curried adapter over @std/collections.sumOf. Replaces the common pattern: reduce((acc, x) => acc + selector(x), 0)

f
symmetricDecrypt

Decrypt a prefixed AES-GCM payload with the given key.

f
symmetricEncrypt

Encrypt plaintext with an AES-GCM key, returning prefixed format: enc:1:$base64iv:$base64ciphertext

f
toBase64

Convert Uint8Array to base64 string

f
toBase64Url

Convert Uint8Array to base64url string (no padding)

f
toBookingItems

Convert registration line items to compact, edge-tagged booking items (v2). Each package member line carries ITS OWN package edge (k:"p", r=its group id) so the webhook can revalidate each line's nodeKey — an order can book several packages, so the edge is per line, never order-wide; folded children (in allocations) and standalone lines stay untagged. See signed-metadata.ts.

f
toCamelCase

Convert snake_case to camelCase (e.g. max_attendeesmaxAttendees).

f
toCanonicalIso

Normalise a provider timestamp to the ledger's canonical ISO 8601 form (YYYY-MM-DDTHH:mm:ss.sssZ), or undefined when it's absent or unparseable.

f
toCheckoutResult

Convert a provider-specific checkout result to a CheckoutSessionResult. Returns null if session ID or URL is missing.

f
todayInTz

Get today's date as YYYY-MM-DD in the given timezone.

f
toMajorUnits

Convert minor units to major units string for form display. e.g. toMajorUnits(1050) → "10.50" (for GBP)

f
toMinorUnits

Convert major units (decimal) to minor units (integer). e.g. toMinorUnits(10.50) → 1050 (for GBP)

f
toModifierRefs

Compact the resolved modifier specs to id/quantity references for metadata.

f
toSnakeCase

Convert camelCase to snake_case (the inverse of toCamelCase).

f
trackSql

Run an async DB operation, enforcing the N+1 read guard and logging it when footer tracking is active.

f
trimAuthToken

Strip padding added by padAuthToken to recover the original serial number

f
tryDeleteFile

Try to delete a file from storage, logging errors on failure

f
ttlCache

Create a TTL (Time-To-Live) cache. Entries expire after ttlMs milliseconds. Accepts an optional clock function for testing.

f
unique

Remove duplicate values (by reference/value equality), keeping first occurrences in order. Curried adapter over @std/collections.distinct.

f
uniqueBy

Remove duplicates by a key function, keeping first occurrences in order. Curried adapter over @std/collections.distinctBy.

f
uniqueSlugFromBase

Make a deterministic base slug unique by appending -2, -3, … until one is free. Unlike generateUniqueSlug (random 5-char slugs), this keeps a human-readable base — the news permalink yyyy-MM-dd-post-name — and only disambiguates on collision (two same-day posts with the same name).

f
unwrapKey

Unwrap a symmetric key Expects format: wk:1:$base64iv:$base64wrapped

f
unwrapKeyWithToken

Unwrap a key using a session token

f
unwrapSessionDataKey

Unwrap a session's DATA_KEY from its token. An authenticated session that reaches a data-key operation always carries a wrapped data key, so a missing one is a broken invariant — throw rather than invent a key.

f
update

Build an UPDATE statement from a table name, a column→value record for the SET clause, and a column→value record for the WHERE clause (equality checks, ANDed together). The counterpart of insert — use it instead of hand-writing the UPDATE … SET … WHERE … string when every condition is a plain column = value match; a write that needs a richer guard (IS NULL, an inequality, a subquery) keeps its own SQL. SET values may be rawSql expressions (e.g. a counter increment).

f
updateAttendeePII
No documentation available
f
updateAttendeeStatus

Set an attendee's status from the admin edit form (a plain column write, outside the encrypted pii_blob). The outstanding balance is NOT set from the form — it projects from the transfers ledger, and an operator adjusts it through the ledger's manual write-off entries.

f
updateBusinessEmail

Updates the business email in the database. Pass empty string to clear the business email. Email is encrypted at rest.

f
updateCheckedIn

Set a line's check-in flag, refusing a no-quantity (quantity 0) line — it isn't a real ticket, mirroring the refunded-ticket guard in checkin.ts. The quantity > 0 predicate scopes the write so a ghost row is a no-op (it can never have been checked in, so scoping the check-OUT case too is harmless).

f
updateListingAggregateValues

Manually set every editable listing aggregate.

f
uploadAttachment

Upload an attachment to Bunny storage. Encrypts the file bytes before uploading. Uses the provided filename (caller generates via generateAttachmentFilename). Returns the filename on success.

f
uploadRaw

Upload raw bytes to storage, routing to local or Bunny based on config

f
useTransaction

Run work on the caller's open transaction, or open one when there is no caller transaction. Transaction-aware table methods use this so direct calls and larger atomic operations share the same write path.

f
utcToLocalInput

Convert a UTC ISO datetime string to a datetime-local input value (YYYY-MM-DDTHH:MM) in the given timezone. Used for pre-populating form inputs with timezone-adjusted values.

f
utcToZoned

Parse a UTC ISO string into a ZonedDateTime in the given timezone

f
validateAttachment

Validate an attachment file: check size only (any file type allowed).

f
validateCustomDomain

Validate a custom domain (delegates to bunnyCdnApi for testability).

f
validatedPaymentSession

Assemble the one ValidatedPaymentSession shape every provider adapter returns. Owns the createdAt rule — the key is left out entirely when the provider gave no usable timestamp — and normalizes the guarded wire metadata into the canonical shape. metadata must already have passed hasRequiredSessionMetadata (or come from our own staged checkout row).

f
validateEmbedHosts

Validate a comma-separated list of host patterns. Returns null if all valid, or the first error message.

f
validateEncryptionKey

Validate encryption key is present and valid Call this on startup to fail fast if key is missing

f
validateGroupListingType

Validate that a listing is compatible with a group's existing listings. Every listing in a group must share both the same ListingType and the same customisable_days setting, so the shared booking form can show a single day-count selector (or none) for the whole group. Returns an error message if mismatched, null if OK. Pass excludeListingId to skip a specific listing (for edit-self case).

f
validateHostPattern

Validate a single host pattern Returns null if valid, or an error message if invalid

f
validateImage

Validate an image file: check size, the declared MIME type, and the magic bytes. Both the declared type and the sniffed content must be an accepted upload format; a mismatch or an unsupported format (e.g. a GIF, or a file whose bytes don't match any decodable format) is rejected. On success, detectedType is the sniffed format the transcoder will decode.

f
validateSlug

Validate a normalized slug. Returns error message or null.

f
validateTemplate

Validate a Liquid template by parsing it (no rendering). Returns null if valid, or an error message string if invalid.

f
verifyPassword

Verify a password against a hash Uses constant-time comparison to prevent timing attacks

f
verifySignedCsrfToken

Verify a signed CSRF token's signature and expiry

f
verifyUserPassword

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

f
widestDatedEntry

The dated entry whose booked range ends last — the stay covering a whole package bundle — or null when every entry is date-less (a standard package). A dated entry with no stored end (a single-day booking, or a legacy row) sorts below any ranged stay. Shared by the collapsed email/SVG displays and the /t package card, so every surface picks the SAME representative stay.

f
withCheckoutError

Wrap a checkout operation, converting PaymentUserError to { error } result and swallowing unexpected errors as null. Used by both provider adapters.

f
withoutLinksTo

Replace each markdown link whose target matches matcher with its plain text. Used to strip links the viewer isn't allowed to open (e.g. owner-only admin pages) before rendering — a rendered link is a promise that it works, so a viewer who can't follow it gets the words without the link.

f
withRequiredEmail

Ensure "email" is included in an listing fields setting

f
withTransaction

Run work inside one interactive write transaction, committing on success and rolling back (then rethrowing) on any error. Use this — rather than a plain batch — when a multi-step write needs conditional logic between steps, e.g. create → check capacity → finalize, where a zero-row guard must abort and undo everything.

f
wrapDataKeyForPassword

Wrap a DATA_KEY under the password-bound (v2) KEK in one step. The single place new wrapped_data_keys are produced — setup, login migration, invite acceptance, password change, and superuser creation all go through here, so the derive-then-wrap pair lives in exactly one spot.

f
wrapKey

Wrap a symmetric key with another key using AES-GCM Returns format: wk:1:$base64iv:$base64wrapped

f
wrapKeyWithToken

Wrap a key using a session token (derives a wrapping key from the token)

f
wrapResourceForDemo

Wrap a named resource so create/update apply demo overrides to the form

f
writeRowInTransaction

Write one row statement in a fresh write transaction and run persist (the coupled join-table writes) on the same tx, so the row and its side writes commit or roll back together. Returns the row id — existingId on update, or the INSERT's lastInsertRowid on create (existingId null). Shared by the REST resource (HTML forms) and CRUD API write paths.

f
writeTableRow

Execute one table-built INSERT/UPDATE on an open transaction and return the affected row. A conditional write returns null when its condition is false.

Interfaces

I
ActivityLogEntry

Activity log entry as callers see it: the message decrypted to plaintext.

I
EdgeScriptSecret

A secret as reported by the Bunny API (name + metadata only — never the value).

I
EncryptedContentRecord

The fields shared by every named, slugged content record whose free-text columns are stored encrypted: the body/meta blobs, the display name, and the /slug permalink paired with its plaintext HMAC blind index (slug_index). Both site pages and news posts build on this.

I
GroupListing

A membership of listing_id in group_id, hydrated for the package editor and booking flow. A listing may belong to several groups. package_price (minor units) is the per-listing override when the group is a package, read from the group dimension of listing_prices (not a column on the join table): null means no override (use the listing's own price), 0 means explicitly free in the package, and a positive value overrides the price. quantity (≥1, stored on the join row) is how many of this listing one unit of the package includes. Both are ignored for non-package groups.

I
GroupWithMembers

A group paired with the active member listings used to decide and render it.

I
Holiday
No documentation available
I
Image
No documentation available
I
ImageUse
No documentation available
I
IntervalRow

A booking row's stored range and quantity.

I
ListingCapacityRow

A listing's identity, capacity, and current booked quantity.

I
LogisticsAgent

A logistics agent (typically a van) used for drop-off and collection.

I
Modifier

An owner-defined price modifier (surcharge / discount / add-on). calc_value is the positive magnitude the owner entered (a fixed amount in major currency units, a percentage, or a multiplier); direction chooses charge vs discount.

I
NamedSortOrderInput

Input shared by ordered tables whose only required value is a name.

I
NewsPost

A news post shown on the public /news page. All free-text columns are stored encrypted; created stays plaintext (like listings) so the newest-first ordering and the RSS pubDate never need a scan-and-decrypt. slug is the /news/:slug permalink (auto-generated from the created date and the name at creation, then immutable); slug_index is its blind index.

I
Settings
No documentation available
I
SitePage

A user-created content page. Adds sort_order, which positions the page among root-level pages.

I
SitePageItem

One ordered membership edge: item (of item_type) sits inside page_id at sort_order. Keyed on the composite (page_id, item_type, item_id).

I
UserLogisticsAgent

A link between an agent user and a logistics agent (van/crew) they drive. Many-to-many: a user may cover several agents and an agent may have several users.

Type Aliases

T
ActiveListingStats

Aggregated statistics for active listings

T
ActivityLogInput

Activity log input for create

T
AdminLevel

Admin role levels

T
AdminListing

Admin API listing shape — all listing fields except internal indices. Used by both admin JSON API and admin templates to ensure consistent field exposure. Snake_case keys match the DB schema.

T
AdminSession

Session data needed by admin page templates

T
AesGcmEncrypted

The IV and ciphertext bytes one AES-GCM encryption produces.

T
AggregateRecalculation

Per-column comparison of each aggregate F's stored value against its rebuilt-from-source value — what the "recalculate aggregates" tools return.

T
AggregateValues

Stored values of the trigger-maintained aggregate columns F, keyed by column.

T
AtomicDesiredLine

A desired final-state line for the atomic update path. Re-exported from the shared types module so callers can keep importing it from here.

T
AttachmentValidationError

Attachment validation error

T
AttachmentValidationResult

Attachment validation result

T
AttendeeBookingRows

PII-free booking rows for a token-resolved attendee.

T
AttendeeInput

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

T
AttendeeRowListing

One listing shown in an attendee row's Listings cell

T
AttendeeSort
No documentation available
T
AttendeesPage

One page of attendee booking rows, plus whether a further page exists. Carries the full field set because the same page query feeds both the browsing table (which shows no money) and the CSV export (which sums price_paid); the table simply ignores the columns it doesn't render.

T
AttendeeTableRow

A single row in the attendee table: an attendee plus the listings the row covers, in display order. Roster/check-in tables render one row per booking line (a one-listing array); the browsing tables (attendees list, dashboard) group an attendee's lines into one row carrying every listing.

T
T
BatchAvailabilityItem

Item for batch availability check

T
BookingBatchPlan
No documentation available
T
BookingIntent

Processed booking intent extracted from payment session metadata

T
BookingItem
No documentation available
T
BookingResult

Booking result — callers map this to their response format

T
BrowsingAttendee

A browsing-table attendee row — every core column plus refunded, but none of the expensive money projections.

T
BulkBatchResponse

What the provider returned for one batch: HTTP status, ok flag, and the raw response body. Providers reply with queued message IDs (or rejection reasons), so the body is kept to surface back to the sender and the log.

T
BulkEmailPayload

A bulk send: shared template (html/text may contain the placeholder) + recipients.

T
BulkRecipient

One bulk recipient: address plus its unsubscribe URL (marketing sends only).

T
BulkSendResult

Outcome of a bulk send: recipients attempted, batches sent, recipients in failed batches, and the raw per-batch provider responses.

T
BuyerEntryGroup

One buyer-facing row group: a HIDDEN package's rows gather behind its name; every other row stands alone.

T
CacheInvalidation

Why cached data was cleared. Only a committed write needs primary refills.

T
CacheStat

A single cache's stats snapshot

T
CheckoutIntent

Registration intent for checkout (one or more listings)

T
CheckoutItem

Single item within a checkout — one bookable PATH. A listing booked through two overlapping packages (or a package plus its own standalone row) in one order is one item per path, each with its own quantity and price.

T
CheckoutSessionResult

Result of creating a checkout session.

T
ClientRunner

Run an operation with the lazily-resolved client. Returns null when the client is unconfigured or the operation fails (unless the error should propagate). The named type keeps the contract visible to callers of the widely-used stripeClientRuntime.run so a signature drift fails at the definition instead of leaking to callers.

T
CollectionCache

Collection cache returned by collectionCache()

T
ColumnDef

Column definition for a table

T
ContactField

Individual contact field name

T
ContactFields

Required name+email with optional phone/address/special_instructions from ContactInfo

T
ContactInfo

Attendee contact details — the core PII fields collected at registration

T
CreateAttendeeResult

Result of atomic attendee creation

T
CredentialCheck

Shared shape for a provider credential check in connection-test results.

T
DayPricedListing

The subset of listing fields needed to reason about day-count pricing.

T
DayPrices

Per-day-count ticket prices for "customisable days" listings, in minor units, keyed by the number of days booked. e.g. { 1: 1000, 2: 1800 } means a 1-day booking costs 1000 and a 2-day booking 1800. Only counts present here are offered to the visitor.

T
DecryptedAttendeeRow

A decrypted attendee row: the raw row with its PII overlaid and its booleans/price coerced, keeping exactly whichever optional money fields the read selected. DecryptedAttendeeRow<Attendee> is the full Attendee.

T
DeleteByFieldTarget

One delete-rows-matching-a-field target: which table, matched on which field, for which value.

T
DemoFieldMap

Maps form field names to arrays of possible demo values

T
DependsOnEntry

A dependsOn entry accepted by cachedTable / cachedEntityTable.

T
DisplayAttendee

The attendee fields the shared attendee table and its column registry actually read. A full decrypted Attendee satisfies it, and so does a field-selected read that skipped the money subqueries — which is exactly why the browsing tables can render rows that never computed price_paid or remaining_balance (see src/shared/db/attendees/select.ts).

T
EmailAttachment

A base64-encoded email attachment

T
EmailConfig
No documentation available
T
EmailEntry

Attendee + listing pair for email rendering

T
EmailListing

Listing data needed for registration pipeline (extends webhook listing with display + assignment fields)

T
EmailProvider

Union of all supported email provider keys, derived from the PROVIDERS map

T
EmailTemplateFormat

A single part of an email template

T
EmailTemplateType

Persisted email template type

T
EmbedSnippets
No documentation available
T
ErrorCodeType
No documentation available
T
ErrorContext

Error log context (privacy-safe metadata only)

T
ExistingLine

A pre-fetched existing booking row plus its line key.

T
FlashLevel

Visual level of a flash message: a positive result, a failure, or a neutral acknowledgement.

T
GetListingsQuery

Everything a caller declares to read listing records: which rows to keep and in what order.

T
GroupIdsByListingId

The group ids each listing belongs to (listing id → group ids). A listing absent from the map belongs to no group.

T
HolidayInput

Holiday input fields for create/update (camelCase)

T
ImageUseItemType
No documentation available
T
ImageValidationError

Image validation error

T
ImageValidationResult

Image validation result

T
ListingAggregateField
No documentation available
T
ListingAggregateRecalculation
No documentation available
T
ListingAggregateValues
No documentation available
T
ListingAnswerRefs

Per-listing answer references carried through a checkout, shared by the booking and checkout intents.

T
ListingBooking

A single listing booking within a multi-listing attendee creation

T
ListingFields

Contact fields setting for an listing (comma-separated ContactField names, or empty for name-only). Alias kept for documentation; runtime enforcement happens in parseListingFields.

T
ListingOfferFlags
No documentation available
T
ListingOption
No documentation available
T
ListingOrder

How the rows come back. A named order so callers can't hand-roll a stray ORDER BY. Exported because a narrow listing read — one that selects its own columns rather than the whole record — still wants to come back in the same order as the full reads.

T
ListingProjectionRow

The raw shape a listing read returns: the stored columns plus the projected values, before decryption and before any inherited defaults are overlaid.

T
ListingType

Listing type: standard (one-time) or daily (date-based booking)

T
ListingWhere

A declarative filter for a listing read. Each present field adds one WHERE clause (absent fields don't constrain), so a caller says WHICH listings it wants rather than hand-writing SQL. An empty filter reads every listing.

T
ListingWithActivityLog

Result type for listing + activity log batch query

T
ListingWithAttendeeRaw
No documentation available
T
ListingWithAttendees
No documentation available
T
ListsByIds

A batch loader: takes a list of ids and returns, for each id, the list of related numbers found for it. Ids with no matches are absent from the map.

T
LogCategory

Log categories for debug logging

T
Migration
No documentation available
T
ModifierRef

Compact modifier reference stored in session metadata: the modifier id and the quantity taken. The webhook re-fetches the modifier by id and re-derives its amount from the current database — provider metadata amounts are never trusted.

T
ModifierSpec

A modifier resolved for a specific checkout — the input the pricing pipeline applies. Eligibility (scope, stock, codes) is decided upstream; by the time a spec reaches pricing it is known to apply. value is the signed calc value (see modifierDelta); listingIds scopes which items it is charged on (null = the whole order); quantity is how many the buyer took (1 for an automatic or code modifier, more for an opt-in add-on).

T
NagId

Unique identifiers for settings nags that prompt the admin to complete required or recommended configuration.

T
NagItem

A single settings nag item presented to the admin.

T
NewsPostCard

The public /news list projection: a summary plus the post's first image (the shared ItemImageProjection columns).

T
NewsPostSummary

The narrow list projection — id, created, slug, name, snippet — for readers that render no images (the RSS feed, the admin list). Never the large content/meta_* blobs (cold-start efficiency, like SitePageNavRow).

T
PackageDisplay

Package-group display info for grouping a booking's lines under the package name on tickets/emails.

T
PassData

Data needed to generate a pass — maps to existing ticket/listing data

T
PaymentProviderSetting
No documentation available
T
PaymentProviderType

Supported payment provider identifiers

T
PaymentStatus

Valid payment status value

T
PiiBlob

Short keys used in the PII blob JSON to minimize encrypted payload size

T
T
RawAttendeeRow

The raw attendee columns the decrypt step reads and coerces. price_paid and refunded are optional because a field-selected read may leave them out (see file://./select.ts); the decrypt then leaves them out too rather than coercing an absent column into "undefined" / false.

T
ReadColumn

Run one column's declared read transform (e.g. decrypt) on a stored value — identity when the column declares none or the value is null. For reading a single column back without building a whole row. rowId (when known) lets the transform name the record in error reports.

T
RegistrationEntry

Registration entry: listing + attendee pair

T
ReserveSessionResult

Result of session reservation attempt

T
SchemaRequirement

The schema objects a single migration is responsible for. Drives that migration's verify() so failures name exactly what the migration was meant to add or remove.

T
SeedResult

Result of a seed operation

T
SessionMetadata

Metadata attached to a validated payment session.

T
SettingsData

Full settings snapshot type.

T
SetupWebhookEndpoint

Set up a webhook endpoint for a provider. Some providers (e.g. Stripe) support programmatic creation; recreating any existing endpoint returns a fresh signing secret. Shared by the provider interface and each provider's own implementation so the signature can't drift.

T
SharedGroupCapacity

The capacity a parent and one of its children share, as two orthogonal facts:

T
SignedTestWebhook

The payload/signature pair a test POSTs to a provider webhook route.

T
SitePageItemType

The kind of thing a SitePageItem points at. Exhaustive union — a new member is a compile error at every Record<SitePageItemType, …> dispatch.

T
SitePageNavRow

The narrow projection used to build the public nav: enough to render a link and order it, without decrypting the large content/meta_* blobs on every public request (cold-start efficiency).

T
SlugWithIndex

Slug-with-index pair. Index is the blind-index type computeIndex produces (a BlindIndex for the real tables).

T
SortableListing

The listing values needed to place a listing in the shared sort order: which tier it belongs to (its type and date), its name for the within-tier sort, and — for a daily listing — the values that decide its next bookable date. A read that only lists or picks listings can select these columns alone and skip the whole listing record.

T
SqlStatement

A single SQL statement plus its bound arguments — the object form libsql's batch API accepts. This is the one shared shape for a { sql, args } pair; callers that build statements to hand to executeBatch and friends import this rather than re-declaring the same object type locally.

T
StorageFileMeta

A stored file with its name and size in bytes.

T
StoredLogMessage

A stored log message: owner-key ciphertext for rows written since the keypair existed, env-key ciphertext for legacy rows the backfill hasn't re-encrypted yet. The format prefix routes decryption at runtime.

T
StoredPaymentFailure
No documentation available
T
StoredTableProjectionRow

A selected row before the table's declared read transforms run. Database values are unknown here because booleans and encrypted strings have a different stored representation from the application's Row type.

T
SuperuserChoice
No documentation available
T
SvgTicketData

Non-PII ticket data for SVG rendering (extends shared wallet fields with display-formatted values)

T
TableDefinition

The shape that defines a table: its name, primary key, and column schema.

T
TableSchema

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

T
TextAnswerRef
No documentation available
T
Theme

UI theme

T
TtlCache

TTL cache returned by ttlCache()

T
TxScope

The slice of an open write transaction handed to a withTransaction callback: run statements singly or as one batch; commit/rollback are managed for you.

T
Unregister

Remove one registration from the registry (handed back by the register functions; production callers register for the process's lifetime and drop it, tests must call it so their entries never outlive the test).

T
UpdateAttendeeAtomicResult

Result of an atomic attendee update. Every failure carries listingIds — the SPECIFIC listings that failed the capacity preflight — so a caller can tell the operator what was actually sold out instead of a bare reason string. Empty when no particular listing is to blame: a duplicate booking slot (see applyAttendeeAtomicEdit's duplicate-slot guard) or a no_lines rejection.

T
UpdateAttendeePIIInput

Input for updating attendee PII (shared across listings)

T
UserAuthFields
No documentation available
T
UserDisplayFields
No documentation available
T
ValidatedPaymentSession

A validated payment session returned after checkout completion

T
ValidEmail

An email address that has passed validation (a non-empty host containing at least one dot) and been normalized (trimmed, lowercased).

T
WebhookAttendee

Attendee data needed for webhook notifications

T
WebhookEvent

Provider-agnostic webhook event

T
WebhookPayload

Consolidated payload sent to webhook endpoints

T
WebhookSetupResult

Result of webhook endpoint setup

T
WebhookVerifyResult

Result of webhook signature verification

T
WebKeySource

Hands back the Web Crypto key the large-payload path needs. Nothing imports a key until a payload is actually big enough to want one.

T
WriteInfo

Context extracted from a write statement for column-gated invalidation

T
WriteVerb

Verb of a mutating SQL statement

Variables

v
activityLogTable

Activity log table definition.

v
AdminLevelSchema

Schema for admin role levels.

v
AES_KEY_BYTES

Key length AES-256 takes, in bytes.

v
ALL_ADMIN_LEVELS

Every admin role level — used to gate actions every authenticated user must reach (e.g. logout). Derived from AdminLevelSchema so adding a new role propagates automatically instead of being hand-listed here.

v
ALL_SETTINGS_KEYS

All keys that populate the snapshot plus the setup-complete flag. Equivalent to the former loadAll SELECT * in terms of what affects request behaviour. Use in tests and in pre-load bundles that need every setting.

v
API_AVAILABILITY_EXAMPLE_JSON

Example availability response JSON

v
API_BOOK_FREE_EXAMPLE_JSON

Example free booking response JSON

v
API_BOOK_PAID_EXAMPLE_JSON

Example paid booking response JSON

v
API_BOOK_REQUEST_JSON

Example booking request body

v
API_EXAMPLE_LISTING

Example listing matching the webhook example data

v
API_EXAMPLE_PACKAGE

The bundle both package examples describe: browsing lists it, and the package endpoint documents the same one in full.

v
API_EXAMPLE_PUBLIC_LISTING

The example PublicListing, produced by toPublicListing

v
API_LIST_EXAMPLE_JSON

Example list response JSON

v
API_SINGLE_EXAMPLE_JSON

Example single-listing response JSON

v
ATTACHMENT_ERROR_MESSAGES

User-facing messages for attachment validation errors

v
ATTENDEE_DEMO_FIELDS

Attendee PII fields

v
ATTENDEE_LISTING_CONTRIBUTIONS_SQL

Per-listing aggregate contributions of an attendee's lines, summed so the hold-delete restore can add them back after deleting. tickets_count counts only quantity > 0 rows (mirroring the delete trigger, which now subtracts 0 for a no-quantity line — see ticketCountSumExpr); booked_quantity sums over all rows. Exported for the shared-predicate guard test.

v
ATTENDEES_PAGE_SIZE

Attendees per page in the admin attendees browser. Fixed here so the page size is never derived from the request — callers choose only the page.

v
AttendeeSortSchema

Sort order for the admin attendees browser

v
BookingItemsSchema
No documentation available
v
buildCreateUserStatement

Build the INSERT that createUser would run, without executing it, so a caller can include the user creation in a batch/transaction with other writes (e.g. initial setup creates the owner atomically alongside its config keys).

v
BULK_UNSUBSCRIBE_PLACEHOLDER

Placeholder in a bulk template marking where each recipient's unsubscribe URL goes.

v
bunnyHostingProvider
No documentation available
v
buyerEntryGroups

Group an order's entries for buyer-facing rendering (the confirmation body and its SVG tickets): each hidden package's rows collapse into one group sitting where its first row was, so a mixed order conceals every hidden bundle while its other rows render normally.

v
CONFIG_KEYS
No documentation available
v
CONTACT_FIELDS

All valid contact field names (runtime array matching the ContactField union)

v
ContactFieldSchema

Schema for an individual contact field name

v
CONTENT_ADMIN_LEVELS

Admin role levels that may create/edit listings & groups: the back-office staff plus the content-only editor. Used to gate the listing/group content routes editors are explicitly opted into; deliberately excludes agent.

v
createUser

Create a new (already-activated) user with encrypted fields. Activated users are created at the password-bound KEK scheme (v2); the caller computes the matching wrapped_data_key via wrapDataKeyForPassword.

v
DayPricesSchema

Strict stored shape for per-day-count prices.

v
DELIVERY_ADMIN_LEVELS

Admin role levels that may reach the delivery run sheet (/admin/deliveries): staff plus delivery agents. This is the audience the run sheet has always had; the content-only editor is excluded.

v
DEMO_ADDRESSES

Demo addresses

v
DEMO_EMAILS

Demo email addresses

v
DEMO_GROUP_DESCRIPTIONS

Demo group descriptions

v
DEMO_GROUP_NAMES

Demo group names

v
DEMO_HOLIDAY_NAMES

Demo holiday names

v
DEMO_LISTING_DESCRIPTIONS

Demo listing descriptions — rock-themed gig blurbs assembled from word pools. Like the names above, the list is procedurally generated but seeded so it stays deterministic across runs.

v
DEMO_LISTING_LOCATIONS

Demo listing locations — pretend rock-venue / festival listings. Procedurally generated from the venue word pools using a seeded PRNG.

v
DEMO_LISTING_NAMES

Demo listing names — pretend rock/heavy-metal band listings. Generated procedurally from a seeded PRNG so the list stays deterministic across runs (tests rely on this) but offers far more variety than a hand-curated list while staying on-theme.

v
DEMO_NAMES

Demo attendee names (full names for demo mode overrides)

v
DEMO_PAGE_TEXT

Demo page text (homepage / contact)

v
DEMO_PHONES

Demo phone numbers (UK format)

v
DEMO_SERVICING_NAMES

Demo servicing-event names (a reason/job for a capacity hold, not a person)

v
DEMO_SPECIAL_INSTRUCTIONS

Demo special instructions

v
DEMO_TERMS

Demo terms and conditions

v
DEMO_WEBSITE_TITLES

Demo website titles

v
DOMAIN_PATTERN

Matches a valid hostname like "example.com" or "sub.example.com"

v
EMAIL_BODY_KEYS
No documentation available
v
EMAIL_PROVIDER_LABELS

Display labels for email providers — keys must match EmailProvider

v
EmailFormatSchema

Format-only email schema: validates an address exactly as typed, without trimming or lowercasing. Used by field validators that check raw user input (see validateEmail in #templates/fields.ts).

v
EmailProviderSchema

Picklist schema for the supported email providers. Its options are derived from the PROVIDERS map so the two can never drift, and it mirrors the string-union picklists in types.ts (ContactFieldSchema, PaymentProviderSchema …) — EmailProviderSchema.options + v.is replace the previous hand-rolled Set + .has() guard.

v
EmailSchema

Canonical email schema used across the app: local@host.tld. valibot's email action guarantees a non-empty local part and a host containing at least one dot. The input is trimmed and lowercased before validation, and the output is branded as ValidEmail so a value can only be produced by passing validation. All email validation that needs a normalized, carry-onward value goes through this (see isValidEmail / parseEmail).

v
EmailTemplateFormatSchema

Schema for the parts of an email template: the subject line, the html body, and the plain-text body.

v
EmailTemplateTypeSchema

Schema for the persisted email template types: the attendee confirmation and the admin notification. The single source of truth for the template discriminator used by the renderer, settings store, and admin forms.

v
ENCRYPTION_PREFIX

Encryption format version prefix Format: enc:1:$base64iv:$base64ciphertext

v
ErrorCode

Error code strings for use in logError calls

v
errorCodeLabel

Human-readable labels for error codes (shown in admin activity log)

v
EXAMPLE_BUSINESS_EMAIL
No documentation available
v
EXAMPLE_CURRENCY
No documentation available
v
EXAMPLE_LISTING

Example inputs used by both the fixture and the test

v
execute

Run a single statement: track it for the query log / N+1 guard, then fire any table-scoped cache invalidation. Every single-statement read and write goes through here (queryOne/queryAll wrap it), so cache invalidation is driven by the write itself rather than by each call site remembering to invalidate.

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
getActiveListingsByGroupId
No documentation available
v
getGroupPerDayRemaining

Per-day remaining for several capped groups, loaded in two queries.

v
getGroupRemainingByGroupId

Remaining capacity for each capped group.

v
getGroupRemainingByListingId

Tightest remaining capped-group capacity for each listing.

v
getListingsByGroupId

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

v
GROUP_DEMO_FIELDS

Group name and description fields

v
groupListings

The listing ids in a group, and the reverse listing-to-groups side.

v
groups
No documentation available
v
hasPaidLine

True when any of the listings has a paid line for this attendee — a gross sale leg in the row's ledger_event_group (a sale leg's amount is always > 0, so its existence is exactly a non-zero projected price_paid; a refund keeps the gross leg, so a refunded line still reads as paid). One query over all the IDs, read from the live ledger rather than the edit form's submitted key (a stale/missing key can leave it null), so a recorded payment is never dropped onto a fresh quantity-0 row. Callers pass a non-empty list.

v
HOLIDAY_DEMO_FIELDS

Holiday name field

v
holidays

Cached holidays table — name is encrypted, dates are plaintext; writes auto-invalidate the cache.

v
HYBRID_PREFIX

Prefix tagging a hybrid (RSA+AES) ciphertext, e.g. owner-key activity-log messages and attendee PII. Distinguishes them from env-key ENCRYPTION_PREFIX values so a decrypt path can route by format.

v
idAndEncryptedNameSchema

Shared columns for tables with a generated id plus an encrypted name.

v
idAndEncryptedSlugSchema

Shared columns for tables with a generated id plus the encrypted slug pair.

v
IMAGE_ERROR_MESSAGES

User-facing messages for image validation errors

v
ImageUseItemTypeSchema

Schema for the kind of item an image can be attached to.

v
isAdminLevel

Type guard: check if a string is a valid AdminLevel

v
isAttendeeSort

Type guard: narrows an arbitrary string to an AttendeeSort.

v
isContactField

Type guard: check if an arbitrary string is a valid ContactField

v
isContentRole

True for roles that may create/edit listings & groups (owner/manager/editor).

v
isDeliveryRole

True for roles that may reach the delivery run sheet (owner/manager/agent).

v
isEmailProvider

Type guard: checks if a string is a valid EmailProvider

v
isEmailTemplateFormat

Type guard: check if a string is a valid EmailTemplateFormat

v
isEmailTemplateType

Type guard: check if a string is a valid EmailTemplateType

v
isImageUseItemType
No documentation available
v
isListingType

Type guard: check if an arbitrary string is a valid ListingType

v
isOwnerRole

True only for the owner role.

v
isPaymentProvider

Type guard: check if a string is a valid PaymentProviderType

v
isPaymentProviderSetting

Type guard: check if a string is a valid PaymentProviderSetting

v
isSitePageItemType

Type guard: is this string a valid SitePageItemType?

v
isSiteRole

True for roles that may edit public-site content (owner/editor).

v
isStaffRole

True for back-office staff (owner/manager).

v
isSuperuserChoice
No documentation available
v
joinStrings

Join an array of strings into a single string (curried reduce shorthand). Replaces the common pattern: reduce((acc: string, s: string) => acc + s, "")

v
LATEST_UPDATE

Schema version label and the migrations bookkeeping table name.

v
LISTING_AGGREGATE_FIELDS
No documentation available
v
LISTING_ATTENDEE_ROW_COLS
No documentation available
v
LISTING_DEMO_FIELDS

Listing metadata fields

v
LISTING_ORDER_SQL
No documentation available
v
listingGroups
No documentation available
v
listingNames

Read and decrypt listing names without loading full records.

v
listingOptionProjection

The shared narrow listing shape used by listing and attribute pickers.

v
listingsTable

Listing CRUD with cache invalidation and listing-price synchronization.

v
ListingTypeSchema

Schema for a listing type: standard (one-time) or daily (date-based booking)

v
loginLimiter
No documentation available
v
LOGISTICS_DEMO_FIELDS

Attendee Logistics tab fields: the address is masked like the attendee form's, and the pinned latitude/longitude are cleared outright — an exact real-world location is PII even beside a masked address.

v
MAX_ATTACHMENT_SIZE

Maximum attachment file size in bytes (default: 25MB)

v
MAX_DURATION_DAYS

Upper bound on multi-day booking duration. Each day in a booking range adds a per-day clause to the atomic capacity SQL, so the cap keeps that statement bounded regardless of which write path set the value.

v
N_PLUS_ONE_THRESHOLD

Max times one parameterized read may run as a separate round-trip within a single request before the N+1 guard fires. Set above the worst legitimate repeat in the suite; lower it to catch smaller N+1s.

v
PARENT_CHILD_GROUP_UNITS

Units of a shared capped group consumed by one parent+child order: the parent line plus its single required child line each take one spot in the group they share (invariants I1, I7). Used to convert a shared group's remaining spots into how many whole parent+child orders still fit.

v
PaymentProviderSchema

Schema for supported payment provider identifiers

v
PaymentProviderSettingSchema

Persisted payment-provider setting: an explicit provider, "none" (admin saved payments-disabled), or absent (never saved — drives the settings nag).

v
paymentsApi

Stubbable API for internal calls (testable via spyOn, like stripeApi/squareApi)

v
PaymentStatusSchema

Schema for valid payment status values. "failed" is a terminal non-payment (declined or expired checkout) — distinct from "unpaid", which may still complete.

v
PII_BLOB_VERSION

Current PII blob schema version

v
queryBatch

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

v
queryBatchPrimary

Run read queries pinned to the primary in a single round-trip.

v
rawListingsTable

Raw listings table. Records adds cache-aware CRUD and price syncing.

v
runWithPendingWork

Run a function within a pending-work scope. Whatever fn resolves to, the queue is drained once more on the way out: an error logged after the request's own flush (e.g. while the response is finalised) still queues work, and work that outlived its request would complete during whatever runs next — on Bunny that's a killed fetch, in tests a sanitizer failure in an unrelated test.

v
runWithRequestId

Run a function with a request-scoped random ID for log correlation

v
safeAsync

Safely execute async operation, returning null on error. Re-throws PaymentUserError so user-facing messages propagate.

v
SCHEMA_HASH
No documentation available
v
SCHEMA_TABLE_NAMES

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

v
SEED_MAX_ATTENDEES

Max attendees per seeded listing

v
SERVICING_DEMO_FIELDS

Servicing-event fields — name only, and a servicing reason rather than a person's name, so demo mode doesn't turn "Boiler Service" into "Bob Smith".

v
setListingGroups
No documentation available
v
settings
No documentation available
v
SITE_ADMIN_LEVELS

Admin role levels that may edit the public-facing site content (homepage, contact, order intro). Site editing has always been owner-only; the editor role is added to it, but manager stays excluded — so this is owner+editor, NOT the broader CONTENT_ADMIN_LEVELS.

v
SITE_CONTACT_DEMO_FIELDS

Site contact page fields

v
SITE_HOME_DEMO_FIELDS

Site homepage fields

v
SitePageItemTypeSchema

Schema for the kind of thing a SitePageItem points at.

v
SNAPSHOT_KEYS

Every config key that maps to a snapshot field, in load order.

v
STAFF_ADMIN_LEVELS

Admin role levels that are back-office staff (not delivery agents).

v
STALE_RESERVATION_MS

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

v
sum

Sum an array of numbers (identity selector shorthand for sumOf). Replaces the common pattern: reduce((acc, n) => acc + n, 0)

v
sumEntryPrices

The buyer's summed price (minor units) across an order's entries.

v
sumEntryQuantities

The bundle's summed booked quantity across an order's entries.

v
SuperuserChoiceSchema
No documentation available
v
TERMS_DEMO_FIELDS

Terms and conditions field

v
TRANSACTION_ROUNDTRIP_THRESHOLD

Max statements one interactive write transaction may issue before the round-trip guard fires. Every statement inside a withTransaction holds the single primary write connection open for another edge→primary round-trip, so a chatty interactive transaction is what the primary aborts as "Transaction timed-out". A plain batch (executeBatch) is one round-trip regardless of how many statements it carries and is never counted — the whole point is to push chatty writes onto it. Set above the largest legitimate interactive transaction; anything that grows with input size (a big attendee merge, a per-leg ledger post) must prepare its reads outside the lock and apply its writes as one batch instead. The current high-water mark is recreateTable on attendee_answers: 8 DROP TRIGGER + 5 rebuild + 6 CREATE INDEX + 8 CREATE TRIGGER = 27 statements; the threshold sits above that.

v
UNRESOLVED_RESERVATION

A processed_payments row is in exactly one of three lifecycle states, encoded across two columns: reserved (in-progress: attendee_id NULL, no failure_data), finalized (success: attendee_id set), failed (terminal handled failure: attendee_id NULL, failure_data set). This predicate is the single source of truth for the unresolved shape, so the encoding can't drift between call sites.

v
uploadImageTargets

Transcode an uploaded image to WebP and store one file per target.

v
VALID_EMAIL_PROVIDERS

Valid provider names (the picklist options), derived from the PROVIDERS map

v
WALLET_ICONS

Decoded icon files for inclusion in .pkpass bundles

v
WEBHOOK_EXAMPLE_JSON

Pretty-printed JSON for embedding in documentation

v
WEBHOOK_EXAMPLE_PAYLOAD

The example payload, matching what buildWebhookPayload would produce

Usage

import * as mod from "doc.ts";