Skip to main content

@effectstream/runtime

Package: @effectstream/runtime · Source

The state-machine runtime — the loop that ties sync, state machine, database, events, and HTTP API together inside an EffectStream node. Boot it with init() then drive it with start(config) and your node is up.

Install

bun add @effectstream/runtime
# or
npm install @effectstream/runtime

@effectstream/runtime is the canonical import for init and start, used directly by every template. The same surface is also reachable through @effectstream/node-sdk/runtime if you prefer the umbrella.

Standalone usage

This package owns the node's process model. You don't pick parts of it; you call init() once at boot and then start(config). The config brings together everything else:

import { init, start } from "@effectstream/runtime";
import { Stm } from "@effectstream/sm";
import { config } from "./config.dev.ts";

await init();

const gameStm = new Stm(grammar);
gameStm.addStateTransition("join", function* () { /* ... */ });

await start({
config,
gameStateTransitions: [gameStm],
apiRouter: undefined, // optional Fastify route plugin
dbMigrations: [], // SQL migrations
});

While running, the runtime:

  • Reads finalized blocks via @effectstream/sync.
  • Routes batcher inputs through your registered Stms.
  • Commits all yielded SQL inside a per-block transaction.
  • Publishes lifecycle and app events via @effectstream/event-server.
  • Serves the optional Fastify API.
  • Emits OpenTelemetry traces and logs through @effectstream/log.

Inside EffectStream

@effectstream/runtime is the conductor: it doesn't define any chain integrations or queries itself, but every other node package only gets exercised when this loop is running. The StartConfig shape determines which DB migrations apply, which state machines fire, and whether the runtime exposes a Fastify router.

Key exports

  • init()Operation<void>. One-shot setup: OpenTelemetry, config validation, version pinning. Call before start.
  • start(config: StartConfig)Operation<void>. Run the node loop until cancelled.

Types and helpers re-exported alongside init / start:

  • DBMigrations — versioned SQL migrations passed into start.
  • StartConfig, StartConfigGameStateTransitions, StartConfigApiRouterstart's config types. Templates type-check against these implicitly but don't usually import them by name.
  • PrimitiveConstructor<T> — extension point for new primitives.
  • VERSION${number}.${number}.${number} literal type for version pinning.
  • Pagination helpers re-exported from ./api/pagination.ts.

Examples

The templates under templates/ are full working init() + start() examples. The simplest is templates/minimal/.

End-to-end EVM sync test: e2e/evm/sync/.

Runnable: test/examples.test.ts.