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

@voyant-travel/workflow-runs

v0.111.9

Published

Workflow run recording, admin routes, and rerun/resume dispatch primitives for Voyant operator apps.

Readme

@voyant-travel/workflow-runs

Workflow run recording, admin routes, and rerun/resume dispatch primitives for Voyant operator apps.

Install

pnpm add @voyant-travel/workflow-runs

The package is independently published with the rest of the workflows release cohort.

For the matching importable React admin surface, install @voyant-travel/workflows-react/ui and point its API client at the routes mounted by this package:

import {
  createWorkflowRunsApiClient,
  WorkflowRunsPage,
} from "@voyant-travel/workflows-react/ui"

const workflowRunsApi = createWorkflowRunsApiClient({ apiBase: "/api" })

export function WorkflowsRoute() {
  return <WorkflowRunsPage api={workflowRunsApi} />
}

Mount the admin routes

mountWorkflowRunsAdminRoutes adds the workflow-run list, detail, rerun, and resume endpoints under /v1/admin/workflow-runs, plus an explicit trigger endpoint at POST /v1/admin/workflows/:name/runs.

import { mountWorkflowRunsAdminRoutes, WorkflowRunnerRegistry } from "@voyant-travel/workflow-runs"
import { createSelfHostWorkflowClient } from "@voyant-travel/workflows-orchestrator/selfhost"

const workflowRunnerRegistry = new WorkflowRunnerRegistry()
const workflowServer = createSelfHostWorkflowClient({
  baseUrl: process.env.WORKFLOW_SERVER_URL!,
})

workflowRunnerRegistry.register({
  name: "checkout-finalize",
  idempotency: "unsafe",
  description:
    "Confirms the booking and issues the final invoice. Use Resume to retry from a failed step.",
  trigger: async (input, ctx) => {
    const saved = await workflowServer.trigger({
      workflowId: "checkout-finalize",
      input,
      tags: ctx.tags,
      triggeredByUserId: ctx.triggeredByUserId,
    })
    return { runId: saved.id }
  },
  rerun: async (input, ctx) => {
    const saved = await workflowServer.trigger({
      workflowId: "checkout-finalize",
      input,
      tags: [...ctx.tags, "rerun:true"],
    })
    return { runId: saved.id }
  },
  resume: async (input, ctx) => {
    const { saved } = await workflowServer.resume(ctx.parentRunId, {
      workflowId: "checkout-finalize",
      input,
      resumeFromStep: ctx.resumeFromStep,
      seedResults: ctx.seedResults,
      tags: [...ctx.tags, "resume:true"],
      triggeredByUserId: ctx.triggeredByUserId,
    })
    return { runId: saved.id }
  },
})

mountWorkflowRunsAdminRoutes(hono, {
  runners: workflowRunnerRegistry,
  adminSurface: process.env.VOYANT_WORKFLOW_ADMIN_SURFACE as
    | "tenant"
    | "cloud"
    | "disabled"
    | undefined,
})

adminSurface controls tenant-admin workflow management actions:

  • tenant keeps local/self-host trigger, rerun, and resume routes available.
  • cloud keeps read routes available but rejects tenant-admin trigger, rerun, and resume routes because the Voyant Cloud dashboard is the workflow control plane for managed deployments.
  • disabled keeps read routes available and disables tenant-admin management actions completely.

When omitted, the package reads VOYANT_WORKFLOW_ADMIN_SURFACE. If that is unset but managed Cloud workflow env is present, the default is cloud; otherwise the default is tenant for local/self-host compatibility.

Triggerable workflows must opt in by implementing trigger(...) on their registered runner. This keeps rerun/resume-only workflows closed to arbitrary admin dispatch while still allowing operators, cron jobs, queues, and API keys with workflows:trigger permission to call:

POST /v1/admin/workflows/checkout-finalize/runs
Content-Type: application/json

{
  "input": { "bookingId": "bk_123" },
  "idempotencyKey": "checkout-finalize:bk_123",
  "correlationId": "bk_123",
  "tags": ["source:admin"]
}

The route returns 202 Accepted with the queued run id:

{
  "data": {
    "runId": "wfrn_...",
    "workflowName": "checkout-finalize",
    "status": "queued"
  }
}

For self-hosted workflow services, keep runner registration close to the code that mounts the workflow service. The registry should dispatch to your external workflow server instead of importing worker-only runtime code into the admin API process. The resume path sends ctx.resumeFromStep plus ctx.seedResults; the self-host server starts a new run, pre-populates the journal with the seeded step outputs, and executes from the failed step onward.

Record @voyant-travel/workflows executions

Use recordedWorkflow as a drop-in replacement for workflow(...) when a workflow should appear in the workflow runs admin UI. The helper records start, success, and failure rows in workflow_runs without repeating recorder boilerplate in every workflow body.

import { recordedWorkflow } from "@voyant-travel/workflow-runs"

export const generatePdfWorkflow = recordedWorkflow({
  id: "products.generate-pdf",
  tags: ["products"],
  async run(input, ctx) {
    const renderer = ctx.services.resolve("products:pdf-renderer")
    return renderer.generate(input)
  },
})

By default, recordedWorkflow resolves a Drizzle database from ctx.services.resolve("db"). It records the workflow id, trigger, run id as the correlation id, configured/runtime tags, input, result, parent run id for child workflow triggers, and errors. Recording is best-effort: database or serializer failures do not fail the workflow execution.

You can customize the database service key or payload serializers:

export const syncCatalogWorkflow = recordedWorkflow(
  {
    id: "catalog.sync",
    async run(input, ctx) {
      return ctx.services.resolve("catalog:sync").run(input)
    },
  },
  {
    dbServiceName: "postgres",
    input: ({ input }) => ({ catalogId: input.catalogId }),
    result: ({ output }) => ({ changed: output.changed }),
  },
)

This helper only records observability data. Trigger, rerun, and resume support still uses WorkflowRunnerRegistry registration so apps can choose which workflows are safe to dispatch from the admin UI.