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

@quantumbpm/sdk

v1.0.1

Published

QuantumBPM TypeScript/JavaScript SDK — DMN evaluation, BPMN orchestration, and external job workers.

Readme

QuantumBPM TypeScript/JavaScript SDK

Official TypeScript/JavaScript SDK for the QuantumBPM platform — DMN evaluation, BPMN process orchestration, and external job workers.

Installation

npm install @quantumbpm/sdk

Node.js 18+ (uses native AbortController and AbortSignal).

What's in the box

| Module | Purpose | | ------------------------------------------------- | ----------------------------------------------------------------------------- | | QuantumBPM | Top-level client exposing .dmn and .bpmn, plus newWorker(...) | | ZitadelTokenProvider, StaticTokenProvider | Authentication. Implement TokenProvider for BYO providers | | DmnClient | DMN evaluation: stored definitions, ad-hoc XML, batch | | BpmnClient | BPMN resources, instances, messaging, user tasks, processes | | Worker | External job worker runtime — long-poll, lock heartbeat, dispatch | | Vars | Variables wrapper with typed accessors and FEEL-context conversion | | RawClient | OpenAPI-generated client. Reachable via client.raw, never hand-edited |

Quick start

import { QuantumBPM, Vars, ZitadelTokenProvider } from '@quantumbpm/sdk';

const provider = new ZitadelTokenProvider(
    './service-account.json',         // Zitadel JSON Key file
    'https://auth.quantumbpm.com',    // issuer
    'your-zitadel-project-id',        // audience scope
);

const client = new QuantumBPM({
    baseUrl: 'https://api.quantumbpm.com',
    projectId: '00000000-0000-0000-0000-000000000000',
    tokenProvider: provider,
});

const result = await client.dmn.evaluate(
    'loan-eligibility',
    new Vars().set('requestedAmt', 1000).set('creditScore', 720),
);
console.log(result);

Authentication

The TokenProvider interface returns a bearer token on each request. Two implementations ship out of the box.

Zitadel service account

const provider = new ZitadelTokenProvider(
    './service-account.json',         // path to JSON Key file
    'https://auth.quantumbpm.com',    // issuer URL
    'your-zitadel-project-id',        // adds the audience scope
);

The provider caches tokens in-memory until shortly before expiry.

Static bearer token

For Enterprise deployments that issue long-lived API keys, or in tests where a token is acquired out of band:

import { StaticTokenProvider } from '@quantumbpm/sdk';

const provider = new StaticTokenProvider('eyJhbGciOi...');

Bring your own

Implement the interface:

import { TokenProvider } from '@quantumbpm/sdk';

class MyProvider implements TokenProvider {
    async getToken(): Promise<string> {
        // ... your auth logic
        return token;
    }
}

DMN evaluation

The client.dmn sub-client offers four methods.

Evaluate a stored definition

const result = await client.dmn.evaluate(
    'loan-eligibility',
    new Vars().set('requestedAmt', 5000).set('creditScore', 720),
);

Returns Record<string, EvaluationResult> keyed by decision name. Each result has value, hitRules, error, and type.

Pin a version, restrict the evaluated decisions, or attach decision services:

const result = await client.dmn.evaluate('loan-eligibility', vars, {
    version: 3,
    decisions: ['eligibility', 'rate'],
});

Evaluate by platform UUID

When you already hold a database-version pointer:

const result = await client.dmn.evaluateById(definitionUuid, vars);

Ad-hoc XML evaluation

For "evaluate while editing" flows that don't store the XML:

const result = await client.dmn.evaluateDesign(dmnXml, vars, {
    additionalXMLs: [importedXml1, importedXml2],
    decisions: ['eligibility'],
});

Batch ad-hoc evaluation

const rows = [
    new Vars().set('requestedAmt', 1000),
    new Vars().set('requestedAmt', 5000),
    new Vars().set('requestedAmt', 25000),
];
const batch = await client.dmn.evaluateDesignBatch(dmnXml, rows);

BPMN processes

client.bpmn covers the full BPMN runtime surface.

Deploy and start

// Stage a BPMN draft, then deploy it.
const draft = await client.bpmn.createResource('loan-process', bpmnXml);
await client.bpmn.deployResource(draft.id);

// Re-fetch to get the populated process-definition list.
const deployed = await client.bpmn.getResource(draft.id);
const processDef = deployed.processes![0];

// Start an instance.
const workflowId = await client.bpmn.startInstance(
    processDef.id,
    new Vars().set('applicantID', 'u-123').set('requestedAmt', 25000),
);

Inspect runtime state

const state = await client.bpmn.getInstance(workflowId);
console.log(state.status, state.activeScopes);

const vars = await client.bpmn.getInstanceVariables(workflowId);

const children = await client.bpmn.getInstanceChildren(workflowId);

Send messages and signals

await client.bpmn.publishMessage(
    'loan-approved',
    new Vars().set('approvedAmt', 24000),
    {
        correlationKeys: { /* ... */ },
        ttl: 'PT5M',
    },
);

await client.bpmn.publishSignal('system-maintenance', new Vars());

User tasks

const page = await client.bpmn.listUserTasks({
    assignee: '[email protected]',
    status: 'CREATED',
});

await client.bpmn.completeUserTask(executionKey, new Vars().set('approved', true));

// Or fail with a BPMN error code (matches boundary error events):
await client.bpmn.throwUserTaskError(executionKey, 'REVIEW_REJECTED', new Vars());

External job workers

Workers handle service tasks asynchronously. Register a handler per task type, then call run. The runtime owns long-polling, lock heartbeats, dispatch, and outcome mapping.

Minimal worker

import { QuantumBPM, Vars, BpmnError } from '@quantumbpm/sdk';

const ac = new AbortController();
const worker = client.newWorker({ clientId: 'billing-svc' });

worker.handle('send-email', async (job) => {
    const recipient = job.vars.get<string>('recipient');
    const subject = job.vars.get<string>('subject');

    await emailer.send(recipient, subject);
    return new Vars().set('messageID', 'msg-123');  // → Complete
});

await worker.run(ac.signal);

run() resolves when the AbortSignal is triggered, after in-flight handlers settle.

Concurrency, polling, and locks

worker.handle('send-email', handler, {
    maxJobs: 10,                // up to 10 in flight per task type
    pollTimeout: '45s',         // long-poll wait
    lockDuration: '2m',         // exclusive lock per job
});

Concurrency is per task type. Different task types run independently. The runtime auto-renews the lock at half the lock-duration interval while the handler runs.

Throwing typed BPMN errors

Throw a BpmnError to fail the job with a code that boundary error events on the originating service task can catch:

worker.handle('charge-card', async (job) => {
    try {
        const txId = await charge(job.vars.toRecord());
        return new Vars().set('transactionID', txId);
    } catch (err) {
        if (err.code === 'INSUFFICIENT_FUNDS') {
            throw new BpmnError('INSUFFICIENT_FUNDS', new Vars().set('availableBalance', 12.0));
        }
        throw err;  // → ThrowError("WORKER_ERROR"); retry budget decrements
    }
});

Handlers that throw anything other than BpmnError report WORKER_ERROR and the server treats it as a retryable failure.

Typed handlers

Generic on handle() decodes the job's input variables into a typed shape. The SDK does not validate at runtime — TypeScript treats it as a hint:

interface EmailJob {
    recipient: string;
    subject: string;
}

worker.handle<EmailJob>('send-email', async (job) => {
    // job.typed is EmailJob
    await emailer.send(job.typed.recipient, job.typed.subject);
    return new Vars().set('messageID', 'msg-123');
});

Variables

Vars is a thin wrapper around Record<string, unknown> shared by DMN, BPMN, and workers.

Construction

const v = new Vars().set('amount', 100).set('name', 'Alice');
const v = Vars.from({ amount: 100, name: 'Alice' });

Typed access

const amount = v.get<number>('amount');
const flag   = v.get<boolean>('approved');

interface Loan {
    requestedAmt: number;
    approved: boolean;
}
const loan = v.as<Loan>();

get<T> and as<T> are TypeScript hints — no runtime validation. Combine with a runtime validator (e.g. Zod) at boundaries when you need it.

Number precision

FEEL numbers are exact decimals server-side, but this SDK deserializes JSON with JSON.parse, so numbers arrive as IEEE-754 doubles (~15–17 significant digits). Values beyond double precision — e.g. 1234567890.123456789012345678 — are silently rounded on receipt, and echoing them back sends the rounded value. This is a JavaScript platform limitation; the Go, Java, and Python SDKs preserve exact decimals.

If you need currency-grade round-trips through a JS worker or client, represent those values as FEEL strings in your processes and convert with a decimal library (e.g. decimal.js, big.js) at the edges.

Escape hatch

The client.raw property exposes the underlying generated client for endpoints not yet wrapped (instance migration, modification, ad-hoc triggers, batch job complete/error, etc.):

await client.raw.bpmn.migrateBpmnInstance(client.projectId, workflowId, body);

License

MIT License — see LICENSE for details.