The hydration-proof Node API runs the same test as the CLI from your own
script. run() resolves with the report and the exit code and never calls
process.exit, so you can start a server, seed data or publish the report
around it. Everything on this page is exported from the hydration-proof
package.
Run a test with run()
import { run } from "hydration-proof";
const { exitCode, report } = await run({
overrides: { url: "http://localhost:3000", reporters: ["json"] },
write: (text) => process.stdout.write(text),
});
// The report is the same object the JSON reporter writes.
for (const issue of report.issues) {
if (issue.severity !== "error") continue;
console.log(
`${issue.route.pattern} ${issue.code} ${issue.source?.file ?? "(no source)"} — ${issue.cause?.title ?? "unknown cause"}`
);
}
process.exit(exitCode);run() reads the config the way the CLI does, from cwd or the file you name
in config. overrides are the same overrides the command line applies, such
as url, routes, reporters, failOn, probes or shard. write
receives the progress and the terminal report (standard output by default),
and reporters adds your own reporters to the configured ones.
function run(options?: RunOptions): Promise<RunResult>Runs a test the way hydration-proof test does and resolves with the report and exit code. It never calls process.exit.
| Option | Type | Default | Description |
|---|---|---|---|
| cwd | string | process.cwd() | Directory the config is looked up from. |
| config | string | — | Config file path; found automatically when omitted. |
| overrides | CliOverrides | — | The same overrides the command line applies, e.g. { url, routes, reporters, failOn }. |
| write | (text: string) => void | — | Where progress and the terminal report are written. |
| reporters | Reporter[] | — | Extra reporters (in addition to the configured ones). |
| signal | AbortSignal | — | Abort the run (the app and browser are shut down). |
| Option | Type | Default | Description |
|---|---|---|---|
| report* | Report | — | The full report, the same object report.json holds. |
| exitCode* | ExitCode | — | The exit code the CLI would use. See ExitCode. |
| failures* | string[] | — | Human-readable reasons the run failed. |
| files* | string[] | — | Report files that were written. |
| notes* | string[] | — | Informational notes printed at the end of the run. |
| outputDir* | string | — | Where the reports were written. |
To stop a run early, pass an AbortSignal. When it aborts, the app and the
browser are shut down:
import { run } from "hydration-proof";
// Stop the run, the app and the browser after ten minutes.
await run({ signal: AbortSignal.timeout(10 * 60_000) });Handle errors with RunError
Problems found on pages never throw: they are in the report, and exitCode
says whether the policy failed. run() throws a RunError for failures that
stop a run before any page is tested, such as an invalid config, a failing
setup hook or login, a browser that cannot launch, or an app that cannot be
started. Its exitCode is the one the CLI would use:
import { run, RunError } from "hydration-proof";
try {
const result = await run();
process.exitCode = result.exitCode;
} catch (error) {
if (!(error instanceof RunError)) throw error;
console.error(error.message);
process.exitCode = error.exitCode;
}class RunError extends Error {
override name: string;
readonly exitCode: ExitCode;
readonly details: string | undefined;
constructor(message: string, exitCode: ExitCode, details?: string);
}Thrown by run() for failures that stop a run before any page is tested, with the exit code the CLI would use.
Exit codes
ExitCode names the codes the CLI exits with. They are stable:
| Name | Code | Meaning |
|---|---|---|
Ok | 0 | Every page passed the policy |
Failed | 1 | Findings, a budget or an expired ignore rule failed the policy |
Usage | 2 | Invalid configuration or command-line usage |
Server | 3 | The app could not be built, started or reached |
Browser | 4 | The browser is missing or failed to launch |
Internal | 70 | A bug in hydration-proof |
Interrupted | 130 | Interrupted (Ctrl+C) |
const ExitCode: {
/** Every page passed the policy. */
readonly Ok: 0;
/** Issues, budget or expired ignore rules failed the policy. */
readonly Failed: 1;
/** Invalid configuration or command-line usage. */
readonly Usage: 2;
/** The app could not be built, started or reached. */
readonly Server: 3;
/** The browser is missing or failed to launch. */
readonly Browser: 4;
/** A bug in hydration-proof. */
readonly Internal: 70;
/** Interrupted (Ctrl+C). */
readonly Interrupted: 130;
}Exit codes. They are stable: 0 ok, 1 failed, 2 usage or config error, 3 server, 4 browser, 70 internal error. An interrupted run exits 130.
Read and merge reports
readReport() reads report.json from a report folder or a file path.
mergeReports() combines the reports of sharded or per-project runs into one
report, removing duplicates. The CLI's
merge-reports command wraps it, and
also applies the CI policy and runs the reporters.
import { writeFileSync } from "node:fs";
import { mergeReports, readReport } from "hydration-proof";
const report = mergeReports(
["shards/shard-1", "shards/shard-2"].map((dir) => readReport(dir))
);
writeFileSync("merged-report.json", JSON.stringify(report, null, 2));
console.log(`${report.summary.failed} pages failed`);function mergeReports(inputs: readonly MergeInput[]): ReportCombines the reports of sharded or per-project runs into one, removing duplicates. The CLI's merge-reports command wraps it.
function readReport(path: string): MergeInputRead report.json from a folder or a file path.
Configs, plugins and adapters
defineConfig(), definePlugin() and defineAdapter() give the config file,
a plugin and an adapter type checking and completion. ADAPTERS lists the
built-in adapters in detection order, most specific first. See
plugins for normalizers, cause detectors, route providers and
reporters, and adapters for frameworks hydration-proof does
not know.
function defineConfig(config: HydrationProofConfig): HydrationProofConfigIdentity helper that gives hydration-proof.config.ts type checking and completion.
function definePlugin(plugin: HydrationProofPlugin): HydrationProofPluginIdentity helper with type checking for plugins.
function defineAdapter(definition: AdapterDefinition): AdapterCreate an adapter for a framework hydration-proof does not know.
Issue codes and documentation links
ISSUES maps every issue code to its name, title, default severity and
description. docsUrl() returns the documentation page of a code:
import { docsUrl, ISSUES } from "hydration-proof";
for (const [code, issue] of ISSUES) {
console.log(`${code} ${issue.severity} ${issue.title} ${docsUrl(code)}`);
}const ISSUES: ReadonlyMap<IssueCode, IssueDefinition>Every issue code with its name, title, default severity and description. The issue code reference is generated from it.
function docsUrl(code: IssueCode): stringThe documentation URL for an issue code, e.g. https://hydration.jscrate.dev/docs/issues/hp1001.
Schemas and versions
configJsonSchema() returns the JSON Schema of the config file, the same one
published at /schema/config.json and shipped as
node_modules/hydration-proof/schema/config.json. VERSION is the installed
version. REPORT_SCHEMA_VERSION is the schemaVersion written into
report.json, 1, and it changes only in a major release.
function configJsonSchema(): JsonSchemaThe JSON Schema of the config file, the same one published at /schema/config.json.
const VERSION: stringThe installed version of hydration-proof.
const REPORT_SCHEMA_VERSION = 1The schemaVersion written into report.json. It changes only in a major release.
What is stable in the hydration-proof Node API
From 1.0 on, the stable parts follow semver: they change only in a major release, with a migration path.
- Stable:
run(),defineConfig,definePlugin,defineAdapter,mergeReports,ISSUESand the types they use; the exit codes; andreport.jsonwithschemaVersion: 1, where fields are added but never removed or repurposed. - Not stable: anything the package does not export; the HTML report's
markup and embedded data; the wording of messages, the set of
evidenceentries and confidence scores; and which cause a finding is given. Treat a cause as an explanation for a person, not something to assert on.
A code's default severity can change in a minor release. If your script
depends on what fails, set failOn or a budget explicitly. The
compatibility page has the full list.
Related
- The CLI: the same run from the command line
- Write a plugin: reporters, detectors and route providers
- Adapters for other frameworks
- The report format
- Compatibility and stability