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
asString

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

f
bestEffort
No documentation available
f
bracket

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

f
chunk

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

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
No documentation available
f
createRequestTimer

Create a request timer for measuring duration

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
delay

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

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

Index one field from each item by its id.

f
filter

Curried filter

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
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
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
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
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 random slugs 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
getRequestId

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

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
hasPendingWorkScope

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

f
identity

Return a value unchanged.

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

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

f
pipe

Compose functions left-to-right (pipe).

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

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

f
requiredMapValue

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

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
setSuppressRequestLogs

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

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
sort

Non-mutating sort with comparator

f
sortStrings

Sort strings in ascending locale order without changing the input.

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

Validate a normalized slug. Returns error message or null.

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.

Type Aliases

T
CacheInvalidation

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

T
CacheStat

A single cache's stats snapshot

T
CollectionCache

Collection cache returned by collectionCache()

T
DependsOnEntry

A dependsOn entry accepted by cachedTable / cachedEntityTable.

T
ErrorCodeType
No documentation available
T
ErrorContext

Error log context (privacy-safe metadata only)

T
LogCategory

Log categories for debug logging

T
SlugWithIndex

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

T
TtlCache

TTL cache returned by ttlCache()

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
WriteInfo

Context extracted from a write statement for column-gated invalidation

T
WriteVerb

Verb of a mutating SQL statement

Variables

v
ErrorCode

Error code strings for use in logError calls

v
errorCodeLabel

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

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

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

Usage

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