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

@nanobpm/bojtos-kit

v0.11.0

Published

Framework-agnostic core of the Bojtos in-browser BPMN demo framework (ADR 0043): a single scenario runner over the @nanobpm/engine-wasm engine (deploy, start instances, complete/fail jobs, advance the clock, read snapshots and the event log), plus the eng

Readme

@nanobpm/bojtos-kit

Framework-agnostic core of the Bojtos in-browser BPMN demo framework (ADR 0043).

It wraps @nanobpm/engine-wasm as a single scenario runner — the one runner the whole framework (and the console test-run panel) drives, so there is no second, drift-prone engine harness — and re-exports the engine's snapshot/event contract types.

import { createBojtosSession } from "@nanobpm/bojtos-kit";

const session = await createBojtosSession(); // loads the wasm engine once
const { processIds } = session.deploy(bpmnXml);
let snapshot = session.createInstance(processIds[0], "{}");
// a service task is now waiting as a job:
snapshot = session.completeJob(snapshot.jobs[0].key, JSON.stringify({ ok: true }));
const trace = session.events(); // WasmEvent[] for a step/trace view
session.free();

Each state-mutating run command returns the post-run Snapshot: activeElementIds / incidentElementIds drive the token/incident highlight, and instances[].variables is the live payload that mutates as workers complete. The deployment/evaluation entry points are the exceptions — deploy returns the deployable process ids, deployDecision the registered decisions, and the read-only evaluateDecision a decision output (see below).

For React, use @nanobpm/bojtos-react, which owns the session lifecycle and reactive state on top of this kit.

DMN decisions — deployDecision / evaluateDecision

Besides BPMN, a session can deploy and evaluate DMN decisions standalone (the counterpart to a businessRuleTask's in-line evaluation):

const { decisions } = session.deployDecision(dmnXml); // registers every <decision>
const { output } = session.evaluateDecision(
  "jedi_or_sith",
  JSON.stringify({ lightsaberColor: "blue" }),
); // => "Jedi"

deployDecision returns the registered decisions' metadata; evaluateDecision is read-only (it does not mutate engine state or record a decision instance). deploy also accepts a DMN resource (the engine routes by content), but is typed for BPMN — prefer deployDecision so the result is typed. A businessRuleTask with a zeebe:calledDecision resolves against decisions registered by either entry point, surfacing its result in snapshot.decisionInstances.

Engine variants — lean (default) and readmodel

@nanobpm/engine-wasm ships two binaries; a session picks one via variant:

  • lean (default) — primary state only. Read it through snapshot() / events(). Loaded statically, so every consumer bundles it.
  • readmodel — the lean surface plus the gateway's Camunda-parity REST read channel. Loaded via a dynamic import, so a lean-only page never downloads the heavier read-model binary (wasm can't be tree-shaken out of a single build — code-splitting is the only lever).
import {
  createBojtosSession,
  type UserTaskSearchQueryResult,
} from "@nanobpm/bojtos-kit";

// `variant: "readmodel"` widens the return type to `ReadModelBojtosSession`:
const session = await createBojtosSession({ variant: "readmodel" });
session.deploy(bpmnXml);
session.createInstance("review", "{}");

// Typed against @nanobpm/engine-wasm/readmodel-types (re-exported here):
const open: UserTaskSearchQueryResult = session.searchUserTasks(
  JSON.stringify({ state: "CREATED" }),
);
const form = session.getFormByKey("2251799813685250"); // FormResult | null

The read methods — searchUserTasks, searchProcessInstances, searchVariables, getFormByKey, getResourceByKey — return DTOs re-exported from @nanobpm/engine-wasm/readmodel-types, which are derived from the Camunda-parity REST OpenAPI (one source of truth, not a hand-copy).

readModel() — the @nanobpm/engine-testkit assertion handle

A readmodel-variant session also exposes readModel(), which returns the session's engine read model as @nanobpm/engine-testkit's structural EngineReadModel port (snapshot() + the user-task read channel). Hand it straight to the assertThat* DSL — it reads the engine's canonical snapshot off this session, so there is no re-derived copy of the state:

import { assertThatInstance, assertThatUserTask, byProcessId } from "@nanobpm/engine-testkit";

const rm = session.readModel(); // typed EngineReadModel — a compile-time guarantee

assertThatInstance(rm, byProcessId("review")).isActive().hasActiveElement("review-task");
await assertThatUserTask(rm, { elementId: "review-task" }).isCreated();

The React binding surfaces the same handle as useBojtos({ variant: "readmodel" }).readModel() (EngineReadModel | null until the engine is ready).

Trace model

The kit also holds the framework-agnostic trace model the shared <TraceTimeline> (in @nanobpm/bojtos-react) renders — one normalized row/turn-group model plus the two adapters that map a source into it, so the two formerly forked timelines share one fold instead of drifting apart:

  • foldEngineEvents(events) — the engine-event fold: a WasmEvent[] (from session.events() / useBojtos().events) → normalized TraceRow[], keeping the run's milestones and dropping low-signal lifecycle noise. The non-agentic / test-view case.
  • traceEntriesToRows(entries) — the handler-emitted adapter: agent/tool/turn TraceEntry lines (with the additive turn grouping field) → TraceRow[]. The agentic web-demo case.
  • buildTraceItems(rows) — folds consecutive same-turn rows into TraceTurnGroups; rows with no turn stay flat. isTraceTurnGroup narrows an item. This is the grouping the view consumes.

It is pure and React-free (no React import in the kit), keeping the presentational layer thin.

Build

dist/ (the tsc-emitted JS + .d.ts) is what ships, built by prepack on publish and by npm test locally. It is not committed — .gitignore covers it — so build before pointing a file: consumer at this workspace. Regenerate with npm run build.