Skip to content

Guidelines

In Effect, runMain is the primary entry point for executing an Effect application on Node.js.

Example (Running an Effect Application with Graceful Teardown)

import { Effect, Console, Schedule, pipe } from "effect"
import { NodeRuntime } from "@effect/platform-node"
const program = pipe(
Effect.addFinalizer(() => Console.log("Application is about to exit!")),
Effect.andThen(Console.log("Application started!")),
Effect.andThen(
Effect.repeat(Console.log("still alive..."), {
schedule: Schedule.spaced("1 second")
})
),
Effect.scoped
)
// No graceful teardown on CTRL+C
// Effect.runPromise(program)
// Use NodeRuntime.runMain for graceful teardown on CTRL+C
NodeRuntime.runMain(program)
/*
Output:
Application started!
still alive...
still alive...
still alive...
still alive...
^C <-- CTRL+C
Application is about to exit!
*/

The runMain function handles finding and interrupting all fibers. Internally, it observes the fiber and listens for sigint signals, ensuring a graceful shutdown of the application when interrupted (e.g., using CTRL+C).

Effect provides versions of runMain tailored for different platforms:

PlatformRuntime VersionImport Path
Node.jsNodeRuntime.runMain@effect/platform-node
BunBunRuntime.runMain@effect/platform-bun
BrowserBrowserRuntime.runMain@effect/platform-browser

Avoid using tacit (point-free) function calls, such as Effect.map(fn), or using flow from the effect/Function module.

In Effect, it’s generally safer to write functions explicitly:

Effect.map((x) => fn(x))

rather than in a point-free style:

Effect.map(fn)

While tacit functions may be appealing for their brevity, they can introduce a number of problems:

  • Using tacit functions, particularly when dealing with optional parameters, can be unsafe. For example, if a function has overloads, writing it in a tacit style may erase all generics, resulting in bugs. Check out this X thread for more details: link to thread.

  • Tacit usage can also compromise TypeScript’s ability to infer types, potentially causing unexpected errors. This isn’t just a matter of style but a way to avoid subtle mistakes that can arise from type inference issues.

  • Additionally, stack traces might not be as clear when tacit usage is employed.

Avoiding tacit usage is a simple precaution that makes your code more reliable.