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

@duraflows/kysely

v0.5.1

Published

[Kysely](https://kysely.dev/) persistence adapter for [duraflows](https://github.com/camcima/duraflows).

Readme

@duraflows/kysely

Kysely persistence adapter for duraflows.

Part of the duraflows monorepo.

Features

  • Full implementation of @duraflows/core persistence interfaces using Kysely query builder
  • Row-level locking with SKIP LOCKED for concurrent access safety
  • JSONB storage for workflow context, metadata, and command results
  • Transaction sharing via AsyncLocalStorage -- run Duraflows and your own queries in a single Kysely transaction
  • Type-safe WorkflowDatabase interface for composing with your own Kysely database types

Installation

npm install @duraflows/core @duraflows/kysely kysely pg

Quick Start

import { WorkflowRuntime, InMemoryDefinitionRegistry, InMemoryCommandRegistry } from "@duraflows/core";
import { kyselyWorkflowProviders } from "@duraflows/kysely";
import { Kysely, PostgresDialect } from "kysely";
import { Pool } from "pg";

const db = new Kysely({
  dialect: new PostgresDialect({ pool: new Pool({ connectionString: process.env.DATABASE_URL }) }),
});

const persistence = kyselyWorkflowProviders(db);

const runtime = new WorkflowRuntime({
  definitionRegistry,
  commandRegistry,
  ...persistence,
  clock: { now: () => new Date() },
});

Sharing a Transaction

The primary use case for this package is running Duraflows workflow transitions and your own database writes in a single atomic transaction.

import { KyselyTransactionContext } from "@duraflows/kysely";

// Seed the transaction context so Duraflows participates in your transaction
await db.transaction().execute(async (trx) => {
  await KyselyTransactionContext.run(trx, async () => {
    // Your own writes -- uses trx
    await trx.insertInto("orders").values({ id: "ORD-1", status: "paid" }).execute();

    // Duraflows writes -- also uses trx (same transaction)
    await runtime.triggerEvent({
      workflowInstanceUuid: instanceUuid,
      eventName: "PaymentReceived",
    });
  });
});
// Both commit or both rollback -- no split-brain

How It Works

KyselyTransactionContext uses Node.js AsyncLocalStorage to propagate the active Kysely transaction through the async call chain. When Duraflows' internal WorkflowTransactionRunner.runInTransaction() is called, it checks for an existing transaction in the context:

  • Found: Reuses it (no nested transaction)
  • Not found: Starts a new Kysely transaction and seeds the context

This re-entrancy contract means your application code controls the transaction boundary.

Composing Database Types

Merge WorkflowDatabase with your own Kysely database type:

import type { WorkflowDatabase } from "@duraflows/kysely";

interface MyDatabase extends WorkflowDatabase {
  orders: OrdersTable;
  products: ProductsTable;
}

const db = new Kysely<MyDatabase>({ ... });

Database Setup

This package uses the same database schema as @duraflows/pg. Use the migration generator from @duraflows/pg or copy the reference migration:

import { generateMigrationSql } from "@duraflows/pg";

const { up, down } = generateMigrationSql();

See the @duraflows/pg README for full details.

API

kyselyWorkflowProviders(db): WorkflowPersistenceProvider

Factory function that creates all required persistence providers from a Kysely<WorkflowDatabase> instance. Returns:

  • instanceStore -- KyselyWorkflowInstanceStore
  • historyStore -- KyselyWorkflowHistoryStore
  • transactionRunner -- KyselyTransactionRunner

kyselyWorkflowProvidersFromTransaction(trx): WorkflowPersistenceProvider

Convenience factory for short-lived runtimes pre-bound to an existing transaction. The returned transaction runner seeds the context with the bound trx if no context already exists.

KyselyTransactionContext

  • getTransaction() -- Returns the active Transaction<WorkflowDatabase> or undefined
  • run(trx, callback) -- Executes callback with trx as the active transaction context

Documentation

See the full documentation in the duraflows repository.

License

MIT