0.1.0-alpha.7

Diagnostics

Every error and warning zerolith emits is the same record, whether the runtime, the build, or the dev tools found it. Tools read it as data: the inspector shows it, a test asserts on it, and a listener can send it anywhere.

The record

Field Holds
code A stable snake_case identifier, such as signal_written_inside_computed
severity "error", "warning", "deprecation", or "info"
cause One sentence naming what happened
fix One sentence naming what to do about it
url The code's documentation page, with the arguments in its query string
args The values the message is about, such as the index and the type of a refused value, kept apart so a tool can write its own text
location Where it points, when known: a file, line, and column in the source, or a selector for a node in the page
suggestion A change that would resolve it: its description, its replacement text, and its applicability

The applicability of a suggestion follows the grades rustc uses for its own: machine_applicable for a change a tool can make without a human reading it, maybe_incorrect and has_placeholders for one a person should check or complete, and unspecified otherwise.

Errors and warnings

Severity Delivered
error Thrown as a ZerolithError, with the record on .diagnostic and a message that holds the code, the cause, the fix, and the URL
warning, deprecation, and info Passed to every onDiagnostic listener, and listed in the inspector's Diagnostics tab; with no listener registered, the development build prints them to the console
import { type ZerolithError, onDiagnostic, onDispose } from "zerolith";

// Warnings go to every listener, such as one that reports them:
const stop = onDiagnostic((diagnostic) => console.warn(diagnostic.code));

// Errors are thrown, carrying the same record:
try
{
    onDispose(() => undefined);         // outside any effect or scope
}
catch (error)
{
    const { diagnostic } = error as ZerolithError;
    console.log(diagnostic.code);       // "on_dispose_outside_scope"
    console.log(diagnostic.url);        // ".../e/on_dispose_outside_scope"
}
stop();

onDiagnostic returns the function that removes the listener.

Production builds

The code and the URL are public API and never change meaning. The message text is not: production builds ship an empty catalog, so cause and fix are empty strings and an error's message carries only the code and the URL, and the page behind the URL carries the explanation. A report from production is still actionable: the code names the problem, and the URL's query string carries its arguments.

Every code

Each code has a page at https://zerolith.dev/e/<code>/ with its cause and its fix, and the diagnostics index lists them all:

The command line's own checks, such as the findings of zerolith doctor, use codes of their own with the same cause and fix, printed in the terminal; the command line guide lists them.