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

@meridianjs/workflow-engine

v1.28.0

Published

Meridian workflow engine — DAG runner with LIFO saga compensation

Downloads

2,979

Readme

@meridianjs/workflow-engine

DAG-based workflow engine for MeridianJS with LIFO saga compensation. Define multi-step operations where each step declares a rollback function — if any step fails, all previously completed steps are automatically compensated in reverse order.

Installation

npm install @meridianjs/workflow-engine

Overview

Workflows are used for any operation that touches multiple services or needs transactional guarantees. Every mutation route in a MeridianJS application runs through a workflow.

Core Concepts

Steps

A step is the atomic unit of a workflow. It has a forward function (the operation) and an optional compensation function (the rollback):

import { createStep, StepResponse } from "@meridianjs/workflow-engine"
import type { MeridianContainer } from "@meridianjs/types"

const createProjectStep = createStep(
  "create-project",
  async (input: { name: string; workspace_id: string }, { container }: { container: MeridianContainer }) => {
    const svc = container.resolve("projectModuleService") as any
    const project = await svc.createProject(input)
    return new StepResponse({ project }, { projectId: project.id })
  },
  // Compensation — called if a later step fails
  async ({ projectId }: { projectId: string }, { container }: { container: MeridianContainer }) => {
    const svc = container.resolve("projectModuleService") as any
    await svc.deleteProject(projectId)
  }
)

StepResponse takes two arguments: the output (passed to the next step) and the compensation data (passed back to the compensation function if needed).

Workflows

Wire steps together into a named workflow:

import { createWorkflow, WorkflowResponse } from "@meridianjs/workflow-engine"

interface CreateProjectInput {
  name: string
  workspace_id: string
  identifier?: string
}

export const createProjectWorkflow = createWorkflow(
  "create-project",
  (input: CreateProjectInput) => {
    const projectResult = createProjectStep(input)
    const statusResult  = seedDefaultStatusesStep(projectResult)
    return new WorkflowResponse(statusResult)
  }
)

Running a Workflow

Call the workflow from a route handler using req.scope as the container:

export const POST = async (req: any, res: Response) => {
  const { result, errors, transaction_status } = await createProjectWorkflow(req.scope).run({
    input: req.body,
  })

  if (transaction_status === "reverted") {
    res.status(500).json({ error: { message: errors[0].message } })
    return
  }

  res.status(201).json({ project: result.project })
}

| transaction_status | Meaning | |---|---| | "done" | All steps completed successfully | | "reverted" | A step failed; compensation ran for all previous steps |

Conditional Branching

Use when() to execute steps conditionally:

import { when } from "@meridianjs/workflow-engine"

const workflowResult = createWorkflow("my-workflow", (input: Input) => {
  const base = createBaseStep(input)
  const extra = when(base, (data) => data.needsExtra === true, () => extraStep(base))
  return new WorkflowResponse(extra)
})

Data Transformation

Use transform() to reshape step output before passing it to the next step:

import { transform } from "@meridianjs/workflow-engine"

const shaped = transform(stepResult, (data) => ({
  projectId: data.project.id,
  workspaceId: data.project.workspace_id,
}))

API Reference

| Export | Description | |---|---| | createStep(name, forward, compensate?) | Define a step with optional rollback | | createWorkflow(name, builder) | Define a workflow from a step composition function | | StepResponse(output, compensationData?) | Wrap step output + compensation payload | | WorkflowResponse(stepResult) | Declare the workflow's final return value | | transform(input, fn) | Reshape step output | | when(input, condition, fn) | Conditionally run a step |

License

MIT