Utils

← Back to module

JSDoc

Functions

setDiagnosticHook

function
setDiagnosticHook(fn: typeof diagnosticHook): void

addDiagnosticListener

function

Subscribe an additional listener (e.g. a dev console store). Returns a dispose function — call it to unsubscribe. Additive to `setDiagnosticHook` — both the singleton hook and every registered listener receive every event, regardless of `kind`. Listeners are invoked in insertion order, after the singleton hook. Removing a listener during emission is safe: `Set.forEach` will not revisit items removed while iterating.

addDiagnosticListener(fn: (e: DiagnosticEvent) => void): () => void

clearDiagnosticListeners

function

Test-only: drop every registered listener.

clearDiagnosticListeners(): void

resetDiagnostics

function

Test-only: clear the dedup set between tests.

resetDiagnostics(): void

warnDegraded

function
warnDegraded(context: string, detail: string): void

warnNotImplemented

function
warnNotImplemented(category: string, detail: string): void

warnUnexpected

function
warnUnexpected(context: string, detail: string, data?: Record<string, unknown>): void

logInfo

function

Emit an informational lifecycle message. Never dedup'd — boot and ops messages typically fire at most a handful of times per process and operators want to see every one. Prefer a stable `context` (e.g. `"server.boot"`, `"relay.subscribe"`) so the UI debug panel and greps downstream can slice by call site.

logInfo(context: string, detail: string, data?: Record<string, unknown>): void

logError

function

Report a caught error (or any thrown value). Never dedup'd — every error is potentially its own story. If `err` is an `Error`, its `name`, `message`, and `stack` are captured as structured data on the diagnostic event. Otherwise the raw value is passed through under `data.err`. `detail` is optional — when omitted, the error's `.message` (or its string coercion) is used, which is the right default for `.catch(logError)`-style call sites.

logError(context: string, err: unknown, detail?: string): void

tryCatchWarn

function

Run `fn` and capture any throw into a discriminated union. Routes failures through `logError(context, err)` so the diagnostic sink sees the error regardless of how the caller handles it. Always returns a `Promise` — `fn` may be sync or async, both work. This keeps the type signature monomorphic (no overload explosion) and forces every call site to `await`, which is almost always what callers want when the wrapper exists specifically to capture errors. Example: const r = await tryCatchWarn("git.diff", () => runGitDiff(ref)) return match(r) .with({ ok: true }, ({ value }) => parseDiff(value)) .with({ ok: false }, () => null) .exhaustive()

<T>(context: string, fn: () => T | Promise<T>): Promise<TryCatchResult<T>>

Types

DiagnosticKind

type

Runtime diagnostics — deferred-work tracking, unexpected-state reporting, and the general structured-log sink for production code. Five functions, grouped by the kind they emit: - `warnNotImplemented` — feature exists upstream, port has nothing. Dedup'd. - `warnDegraded` — fallback running; usable but not faithful. Dedup'd. - `warnUnexpected` — value that should be impossible under the type system (Zod `safeParse` failure, non-exhaustive `match` arm, type-assertion guard). Never dedup'd. - `logInfo` — lifecycle / boot / ops messages that callers want visible but carry no "something is wrong" signal. Never dedup'd. - `logError` — something threw or errored. Serialises Error instances (name/message/stack). Never dedup'd. And a thin wrapper that turns throws into a discriminated-union result: - `tryCatchWarn<T>(context, fn)` — always async; returns `{ ok: true, value: T } | { ok: false, error: unknown }`. Routes throws through `logError`. Callers MUST `.exhaustive()` on `{ok}`. All five kinds flow through an optional `diagnosticHook` so the TUI / web debug panel can surface them. Tests call `resetDiagnostics()` in `beforeEach` to clear the dedup set. Usage: warnDegraded('polling.getPaneCurrentPath', 'Falling back to "/" — tmux display-message failed') warnNotImplemented('client.reconnect', 'Exponential backoff not yet tuned') warnUnexpected('connection.handleSseBlock', 'SSE message failed schema validation', { issues }) logInfo('server.boot', 'listening on port 7800', { port: 7800 }) logError('polling.tick', err) const result = await tryCatchWarn('some.op', () => doWork()) match(result) .with({ ok: true }, ({ value }) => ...) .with({ ok: false }, ({ error }) => ...) .exhaustive()

type DiagnosticKind = | "not-implemented"
	| "degraded"
	| "unexpected"
	| "info"
	| "error"

TryCatchResult

type

Discriminated result returned by `tryCatchWarn`. Callers MUST branch with `match(result).with({ ok: true }, ...).with({ ok: false }, ...).exhaustive()` — the whole point is that "succeeded" and "failed" are distinct types.

type TryCatchResult = TryCatchResult<T>

Interfaces

DiagnosticEvent

interface
interface DiagnosticEvent
Members

kind

property
kind: DiagnosticKind

category

property
category: string

detail

property
detail: string

stack

property
stack: string

data

property
data: Record<string, unknown>

timestamp

property
timestamp: number