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

@flowspine/core

v0.1.1-beta.20260407.1

Published

Flowspine core DSL and step runtime contracts (beta, not production-ready)

Readme

@flowspine/core

Flowspine core package for:

  • defining process topology with defineProcess
  • defining executable step contracts with defineStep
  • executing individual steps with runStep

This package is the semantic foundation of Flowspine.

Use it when you need to:

  • describe a business flow as a graph
  • define step input/output contracts
  • implement step logic
  • add retry / timeout / idempotency behavior to step execution

Do not use this package for:

  • repository-wide extraction of process files
  • catalog generation
  • validation/export/watch workflows

For those tasks, use @flowspine/extractor or @flowspine/cli.


Installation

pnpm add @flowspine/core@beta

Mental Model

Flowspine has two different concerns inside this package:

1. Process topology

defineProcess(...) describes a process graph:

  • nodes
  • edges
  • branch conditions
  • start/end structure

It does not execute the graph.

2. Step runtime

defineStep(...) and runStep(...) define and execute a single step:

  • validate input
  • run handler
  • validate output
  • enforce allowed outcomes
  • apply retry/timeout/idempotency options

If you need full graph execution/orchestration, that is outside the scope of this package.


API Overview

Process DSL

defineProcess(processId, build)

Builder methods:

  • step(id, metadata?)
  • branch(id, metadata?)
  • event(id, metadata?)
  • action(id, metadata?)
  • start(targetNode)
  • end(targetNode)
  • link(from, to, condition?)
  • when(branchNode, condition)

Step Runtime

defineStep({
  id,
  validateInput,
  validateOutput,
  allowedOutcomes,
  handler,
  timeoutMs?,
  retry?
})
runStep(step, input, options?)

runStep(...) options include:

  • processId
  • traceId
  • timeoutMs
  • retry
  • idempotencyKey
  • cache
  • onEvent

Example: Define Process Topology

import { defineProcess } from "@flowspine/core";

export default defineProcess("order-fulfillment", ({ step, branch, action, event, start, end, link, when }) => {
  const validateOrder = step("ValidateOrder", {
    owner: "CheckoutService",
    description: "Validate payload, customer status, and line items"
  });

  const paymentRequired = branch("PaymentRequired", {
    description: "Branch by order total and payment method"
  });

  const chargePayment = action("ChargePayment", {
    description: "Authorize and capture payment"
  });

  const reserveInventory = action("ReserveInventory", {
    description: "Reserve items for shipment"
  });

  const orderConfirmed = event("OrderConfirmed");
  const orderRejected = event("OrderRejected");

  start(validateOrder);
  link(validateOrder, paymentRequired);
  link(when(paymentRequired, "yes"), chargePayment);
  link(when(paymentRequired, "no"), reserveInventory);
  link(chargePayment, reserveInventory, "success");
  link(chargePayment, orderRejected, "failed");
  link(reserveInventory, orderConfirmed);
  end(orderConfirmed);
  end(orderRejected);
});

Example: Define and Run a Step

import { defineStep, runStep } from "@flowspine/core";

const ValidateOrder = defineStep({
  id: "ValidateOrder",
  validateInput: (v): v is { orderId: string; itemsCount: number } =>
    Boolean(v && typeof v === "object" && typeof (v as { orderId?: unknown }).orderId === "string"),

  validateOutput: (v): v is { orderId: string; valid: boolean } =>
    Boolean(v && typeof v === "object" && typeof (v as { orderId?: unknown }).orderId === "string"),

  allowedOutcomes: ["success", "invalid_order"] as const,

  handler: async (input) => {
    if (input.itemsCount <= 0) {
      return {
        outcome: "invalid_order",
        output: { orderId: input.orderId, valid: false }
      };
    }

    return {
      outcome: "success",
      output: { orderId: input.orderId, valid: true }
    };
  }
});

const result = await runStep(ValidateOrder, {
  orderId: "ord-1",
  itemsCount: 2
});

if (result.outcome !== "success") {
  throw new Error("Order is invalid.");
}

Runtime Guarantees

runStep(...) enforces:

  • input validation before handler execution
  • outcome membership in allowedOutcomes
  • output validation after handler execution
  • timeout handling
  • retry policy handling
  • optional idempotency cache handling

This makes defineStep useful as a strongly-guarded step contract, even outside full Flowspine process graphs.


Important Constraints

  • allowedOutcomes must not be empty
  • retry.maxAttempts must be >= 1
  • timeout must be > 0
  • when(...) is only valid for branch nodes
  • duplicate node IDs in a process throw an error

Also note:

  • action("X") and defineStep({ id: "X" }) may be used together by convention, but they are not automatically linked by the package
  • metadata is optional and not globally schema-enforced

When To Reach For Other Packages

Use @flowspine/extractor when you need to read process definitions from TypeScript files and build a catalog.

Use @flowspine/cli when you need operational workflows such as:

  • scaffold
  • build
  • validate
  • export
  • watch

Related Packages

  • @flowspine/extractor
  • @flowspine/cli

License

Apache 2.0

Copyright

Copyright (c) 2026 Flowspine contributors.