Shared utilities: FP helpers, formatting, slugs, caching, and logging.

Functional Programming

Curried utilities for data transformation: pipe, filter, map, reduce, compact, unique, and more.

Formatting

Currency formatting, phone normalization, markdown rendering, and timezone-aware date/time display.

Caching

TTL and LRU caches with a global registry for admin stats.

Functions

f
addPendingWork

Queue a promise that must complete before the response is sent

f
boundedLru

Create a bounded LRU (Least Recently Used) cache. Evicts the least-recently-used entry when capacity is reached. Uses a doubly-linked list for O(1) LRU tracking so that get() does not mutate the key-value index.

f
bracket

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

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
compact

Remove null and undefined values from array

f
createRequestTimer

Create a request timer for measuring duration

f
err

Create a failed result

f
filter

Curried filter

f
flatMap

Curried flatMap

f
flushPendingWork

Await all queued work. Call before returning the response.

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
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
formatErrorMessage

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

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
generateUniqueSlug

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

f
getAllCacheStats

Collect stats from all registered caches

f
getDecimalPlaces

Get the number of decimal places for a currency code

f
getTheme

Get the current theme ("light" or "dark")

f
groupBy

Group array items by a key function

f
identity

Identity function

f
isDefined

Check if value is not null or undefined

f
isValidDatetime

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

f
isValidTimezone

Validate that a string is a valid IANA timezone identifier.

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
loadCurrencyCode

Load currency code from settings into sync-accessible state. Called once per request in routes/index.ts before templates render. Settings are already cached so this is cheap on repeat calls.

f
loadTheme

Load theme from settings into sync-accessible state. Called once per request in routes/index.ts before templates render. Settings are already cached so this is cheap on repeat calls.

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
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
map

Curried map

f
mapParallel

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

f
mapSequential

Map over a promise-returning function sequentially (one at a time)

f
normalizePhone

Strip non-numeric characters from a phone number, then prefix if it starts with 0

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
ok

Create a successful result

f
once

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

f
pick

Pick specific keys from an object

f
pipe

Compose functions left-to-right (pipe) Uses recursive conditional types for arbitrary-length type safety.

f
pipeAsync

Async pipe - compose async functions left-to-right Each function receives the awaited result of the previous one. Uses recursive conditional types for arbitrary-length type safety.

f
redactPath

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

f
reduce

Curried reduce

f
registerCache

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

f
renderMarkdown

Render markdown to HTML (block-level: paragraphs, lists, etc.). Raw HTML is escaped.

f
renderMarkdownInline

Render markdown to inline HTML (no wrapping <p> tags). Raw HTML is escaped.

f
resetCacheRegistry

Reset the registry (for testing)

f
resetCurrencyCode

For testing: reset the currency code to default

f
resetTheme

For testing: reset the theme to default

f
runWithPendingWork

Run a function within a pending-work scope

f
runWithRequestId

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

f
setCurrencyCodeForTest

For testing: set the currency code directly

f
setThemeForTest

For testing: set the theme directly

f
sort

Non-mutating sort with comparator

f
sortBy

Sort by a key or getter function

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
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)

f
uniqueBy

Remove duplicates by a key function

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
validatePrice

Validate and convert a raw price string to minor units. Returns ok with 0 if raw is empty and minPrice is 0 (pay-what-you-want with no input). Returns error if raw is empty and minPrice > 0, or if parsed value is out of range.

f
validateSlug

Validate a normalized slug. Returns error message or null.

Type Aliases

T
BoundedLru

Bounded LRU cache returned by boundedLru()

T
CacheStat

A single cache's stats snapshot

T
CollectionCache

Collection cache returned by collectionCache()

T
ErrorCodeType
No documentation available
T
ErrorContext

Error log context (privacy-safe metadata only)

T
LogCategory

Log categories for debug logging

T
PriceResult

Result type for price validation

T
Result

Result type for operations that can fail with a Response

T
SlugWithIndex

Slug-with-index pair

T
TtlCache

TTL cache returned by ttlCache()

Variables

v
DEFAULT_TIMEZONE

Default timezone when none is configured

v
ErrorCode

Error code strings for use in logError calls

v
errorCodeLabel

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