npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@voyantjs/workflows-orchestrator-node

v0.107.10

Published

Node/Docker runtime primitives for @voyantjs/workflows-orchestrator, including a file-backed run store and local scheduler.

Readme

@voyantjs/workflows-orchestrator-node

Node/Docker runtime primitives for @voyantjs/workflows-orchestrator.

This package is the first building block for the Docker/GCE self-host target:

  • file-backed RunRecordStore for single-node development and early self-host installs
  • file-backed snapshot run store for dashboard / self-host HTTP APIs
  • Drizzle-backed PostgreSQL snapshot + wakeup stores for Docker/GCE installs
  • local scheduler for workflow schedule declarations
  • run-record snapshot helpers for dashboard-facing local state
  • local sleep-alarm manager for ctx.sleep wakeups in a single Node process
  • lease-based wakeup store + poller primitives for the future multi-process / Postgres-backed adapter
  • persistent wakeup manager for file-backed self-host installs
  • entry loading + HTTP/SSE server helpers for the Node self-host target
  • failed-step resume dispatch for operator dashboards (POST /api/runs/:id/resume)
  • package-owned Postgres migration runner for Docker/runtime boot flows

It is intentionally smaller than the future full Node adapter. The first goal is to move Node-specific runtime concerns out of the CLI and into a reusable package.

Self-host dispatch client

Operator admin processes can use the client helper instead of hand-rolling the self-host HTTP contract:

import { createNodeSelfHostWorkflowClient } from "@voyantjs/workflows-orchestrator-node";

const workflows = createNodeSelfHostWorkflowClient({
  baseUrl: process.env.WORKFLOW_SERVER_URL!,
});

const rerun = await workflows.trigger({
  workflowId: "checkout-finalize",
  input,
  tags: ["rerun:true"],
});

const resumed = await workflows.resume(parentRunId, {
  workflowId: "checkout-finalize",
  input,
  resumeFromStep: "issue_invoice",
  seedResults: {
    validate_booking: { ok: true },
  },
  tags: ["resume:true"],
  triggeredByUserId: userId,
});

resume(...) starts a new run linked to the parent id. When the parent id is a self-host snapshot id and seedResults is omitted, the server derives seed entries from the parent run's successful journaled steps before the failed step. When the parent id comes from an external admin recorder such as @voyantjs/workflow-runs, pass workflowId, resumeFromStep, and seedResults from that recorder's WorkflowResumeContext. Seeded steps are replayed from the journal, so their side effects do not run again.

Service-backed package workflows

Package workflows can resolve host-provided services through ctx.services.resolve(...). For example, @voyantjs/promotions exports the promotions.reindex-all-products workflow, which resolves the bulk reindex service registered under BULK_REINDEX_SERVICE_KEY.

For app-integrated Node runtimes, prefer the createApp() workflow runtime. createApp() builds the module container, passes a read-only service resolver to the driver factory, and the Node standalone driver forwards that resolver into every workflow step:

import { createApp } from "@voyantjs/hono"
import type { HonoModule } from "@voyantjs/hono/module"
import { createNodeStandaloneDriver } from "@voyantjs/workflows-orchestrator-node"
import {
  BULK_REINDEX_SERVICE_KEY,
  promotionsHonoModule,
} from "@voyantjs/promotions"

const promotionsWorkflowServices: HonoModule = {
  module: {
    name: BULK_REINDEX_SERVICE_KEY,
    service: bulkReindexProductsService,
  },
}

const app = createApp({
  db: () => db,
  modules: [promotionsHonoModule, promotionsWorkflowServices],
  workflows: {
    driver: () => createNodeStandaloneDriver({ db }),
    environment: "production",
  },
})

await app.ready()

The key point is that service registration happens in the host app and the driver receives the framework's service resolver from createApp(); workflow code stays package-owned and deployment-agnostic.

If you are still using the standalone self-host HTTP helper directly with an entry file, pass the same read-only resolver to startNodeSelfHostServer() or createNodeSelfHostDeps():

import { BULK_REINDEX_SERVICE_KEY } from "@voyantjs/promotions"
import type { ServiceResolver } from "@voyantjs/workflows/driver"
import { startNodeSelfHostServer } from "@voyantjs/workflows-orchestrator-node"

const services: ServiceResolver = {
  resolve<T>(name: string): T {
    if (name === BULK_REINDEX_SERVICE_KEY) {
      return bulkReindexProductsService as T
    }
    throw new Error(`Service "${name}" is not registered`)
  },
  has(name: string): boolean {
    return name === BULK_REINDEX_SERVICE_KEY
  },
}

await startNodeSelfHostServer({
  entryFile: "./dist/workflows.mjs",
  databaseUrl: process.env.DATABASE_URL,
  services,
})

That direct helper is useful for existing entry-file deployments. New service-backed package workflow integrations should usually migrate to createApp({ workflows: { driver: () => createNodeStandaloneDriver({ db }) } }) so module services, event filters, manifest registration, and ctx.services all come from one app composition path.

Postgres migrations

The PostgreSQL schema for the Node self-host target lives in src/postgres-schema.ts and is versioned through committed Drizzle migrations in drizzle/.

Apply migrations with:

DATABASE_URL='<postgres connection string>' \
  pnpm --filter @voyantjs/workflows-orchestrator-node db:migrate

Or run the same committed SQL migrations through the runtime-owned helper:

import { runPostgresMigrations } from "@voyantjs/workflows-orchestrator-node";

await runPostgresMigrations({
  databaseUrl: process.env.DATABASE_URL!,
});

Generate a new migration after editing the schema with:

pnpm --filter @voyantjs/workflows-orchestrator-node db:generate -- --name your_change_name

Integration test

Run the Postgres-backed integration suite with a local database, for example:

TEST_DATABASE_URL='<postgres test connection string>' \
  pnpm --filter @voyantjs/workflows-orchestrator-node test:integration

For a Docker-first reference deployment, use apps/workflows-selfhost-node-server, which now includes a multi-stage image, a container entrypoint, and a compose example that can run these migrations on boot.

The reference HTTP server also exposes GET /healthz, GET /readyz, and GET /metrics. When PostgreSQL is configured, readiness includes a database connectivity check. The metrics endpoint emits Prometheus-style gauges for registered workflows/schedules, persisted runs by status, and persisted wakeups.

Operational notes for single-node and multi-instance Postgres deployments live in docs/selfhost-node-ops.md.