API reference@evolu/nodejs › runMain

Call Signature

function runMain<T, E>(
  main: Task<T, E>,
  options?: RunMainOptions,
): Promise<void>;

Defined in: packages/nodejs/src/Task.ts:121

Runs the main Task of a Node.js command or service.

A command does a finite job, such as importing data. A service handles ongoing work, such as accepting connections. Choose a mode for how the program reports an interruption:

  • "command": A termination signal means the job was interrupted. After cleanup, use the conventional signal exit status, such as 130 for Ctrl-C, unless process.exitCode is already set.
  • "service" (default): A termination signal is an expected way to stop the service. Graceful shutdown does not set a failure exit status.

Both modes create one root Run and wait for cleanup. The mode controls signal exit status; the main Task controls how long runMain waits.

Lifetime

When the main Task returns void, runMain finishes after the Task and root Run cleanup. It does not force the Node.js process to exit.

A service can return a live Resource, such as the relay created by createRelay. This transfers ownership to runMain, which waits for shutdown and then disposes the Resource. It must remain usable after the creating Task finishes; do not dispose it before returning it.

Alternatively, the main Task can own its resources with using or await using while awaiting waitForAbort with run(waitForAbort). Waiting for abort does not itself keep Node.js running: the service needs active work, such as a listening server.

Shutdown and errors

Handles SIGINT (Ctrl-C), SIGTERM (termination by the OS or a service host), and SIGBREAK (Ctrl-Break on Windows). The first signal logs shutdown progress, aborts the root Run, and waits for cleanup. A second signal exits immediately with its conventional signal status, abandoning cleanup. Signals are still handled during final cleanup.

An error returned by the main Task is fatal. getOrThrow preserves it in Error.cause; the Run reports the failure and finishes cleanup. Every reported defect sets process.exitCode to 1, including an observer defect that does not abort the Run. The default reporter logs to the configured Evolu console.

Escaped uncaught exceptions and unhandled rejections remain under Node.js native reporting and termination.

Example

A command finishes when its main Task completes:

import { assertTrue, ok, type Task } from "@evolu/common";
import { runMain } from "@evolu/nodejs";

let completed = false;
const command: Task<void> = () => {
  completed = true;
  return ok();
};

await runMain(command, { mode: "command" });
assertTrue(completed);

Call Signature

function runMain<D>(
  deps: RunCustomDeps<D>,
  options?: RunMainOptions,
): <T, E>(main: Task<T, E, D>) => Promise<void>;

Defined in: packages/nodejs/src/Task.ts:126

With custom dependencies.