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

@bratsos/workflow-engine-host-serverless

v0.2.11

Published

Platform-agnostic serverless host for @bratsos/workflow-engine command kernel

Readme

@bratsos/workflow-engine-host-serverless

Platform-agnostic serverless host for the @bratsos/workflow-engine command kernel. Works with Cloudflare Workers, AWS Lambda, Vercel Edge, Deno Deploy, and any stateless runtime.

Installation

npm install @bratsos/workflow-engine-host-serverless

Quick Start

import { createKernel } from "@bratsos/workflow-engine/kernel";
import { createServerlessHost } from "@bratsos/workflow-engine-host-serverless";

const kernel = createKernel({ /* ... */ });

const host = createServerlessHost({
  kernel,
  jobTransport,
  workerId: "my-worker",
});

// Handle a job from a queue message
const result = await host.handleJob(msg);

// Run maintenance from a cron trigger
const tick = await host.runMaintenanceTick();

API

createServerlessHost(config): ServerlessHost

Creates a new serverless host instance.

ServerlessHostConfig

| Option | Type | Default | Description | |--------|------|---------|-------------| | kernel | Kernel | required | Kernel instance to dispatch commands to | | jobTransport | JobTransport | required | Job transport for complete/suspend/fail lifecycle | | workerId | string | required | Unique worker identifier (e.g. function name) | | staleLeaseThresholdMs | number | 60_000 | Time before a job lease is considered stale | | maxClaimsPerTick | number | 10 | Max pending runs to claim per maintenance tick | | maxSuspendedChecksPerTick | number | 10 | Max suspended stages to poll per tick | | maxOutboxFlushPerTick | number | 100 | Max outbox events to flush per tick |

ServerlessHost

| Method | Returns | Description | |--------|---------|-------------| | handleJob(msg) | Promise<JobResult> | Execute a single pre-dequeued job | | processAvailableJobs(opts?) | Promise<ProcessJobsResult> | Dequeue and process jobs | | runMaintenanceTick() | Promise<MaintenanceTickResult> | Run one bounded maintenance cycle |

JobMessage

The shape of a job message passed to handleJob():

interface JobMessage {
  jobId: string;
  workflowRunId: string;
  workflowId: string;
  stageId: string;
  attempt: number;
  payload: Record<string, unknown>;
}

JobResult

interface JobResult {
  outcome: "completed" | "suspended" | "failed";
  error?: string;
}

ProcessJobsResult

interface ProcessJobsResult {
  processed: number;
  succeeded: number;
  failed: number;
}

MaintenanceTickResult

interface MaintenanceTickResult {
  claimed: number;          // Pending runs claimed
  suspendedChecked: number; // Suspended stages polled
  staleReleased: number;    // Stale leases released
  eventsFlushed: number;    // Outbox events published
}

Platform Integration Examples

Cloudflare Workers (Queue + Cron)

import { createServerlessHost } from "@bratsos/workflow-engine-host-serverless";

export default {
  // Queue consumer -- process jobs from Cloudflare Queue
  async queue(batch, env, ctx) {
    const host = createServerlessHost({ kernel, jobTransport, workerId: "cf-worker" });

    for (const msg of batch.messages) {
      const result = await host.handleJob(msg.body);

      if (result.outcome === "failed") {
        msg.retry();
      } else {
        msg.ack();
      }
    }
  },

  // Cron trigger -- run maintenance
  async scheduled(event, env, ctx) {
    const host = createServerlessHost({ kernel, jobTransport, workerId: "cf-worker" });
    ctx.waitUntil(host.runMaintenanceTick());
  },
};

AWS Lambda (SQS + EventBridge)

import { createServerlessHost } from "@bratsos/workflow-engine-host-serverless";

// SQS handler -- process jobs
export async function jobHandler(event) {
  const host = createServerlessHost({ kernel, jobTransport, workerId: "lambda-worker" });

  for (const record of event.Records) {
    const msg = JSON.parse(record.body);
    await host.handleJob(msg);
  }
}

// EventBridge handler -- maintenance cron
export async function maintenanceHandler() {
  const host = createServerlessHost({ kernel, jobTransport, workerId: "lambda-worker" });
  return host.runMaintenanceTick();
}

Vercel Edge (API Route + Cron)

import { createServerlessHost } from "@bratsos/workflow-engine-host-serverless";

// POST /api/process-job
export async function POST(request: Request) {
  const host = createServerlessHost({ kernel, jobTransport, workerId: "vercel-worker" });
  const result = await host.processAvailableJobs({ maxJobs: 5 });
  return Response.json(result);
}

// GET /api/cron/maintenance (Vercel Cron)
export async function GET() {
  const host = createServerlessHost({ kernel, jobTransport, workerId: "vercel-worker" });
  const tick = await host.runMaintenanceTick();
  return Response.json(tick);
}

How It Works

Unlike the Node host, the serverless host has no loops, timers, or signal handlers. Every method is a single stateless invocation:

  • handleJob(msg) -- Dispatches job.execute to the kernel, then marks the job complete/suspended/failed via jobTransport. On completion, also dispatches run.transition to advance the workflow.

  • processAvailableJobs(opts?) -- Dequeues up to maxJobs (default: 1) from the job transport and processes each via handleJob. Safe for edge runtimes with CPU limits.

  • runMaintenanceTick() -- Runs one bounded pass of all orchestration duties: run.claimPending, stage.pollSuspended, lease.reapStale, outbox.flush.

Consumers wire platform-specific glue (queue ack/retry, waitUntil, cron triggers) around these methods.

License

MIT