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

@abshahin/workflows-sdk

v0.1.0

Published

TypeScript SDK for dispatching typed workflow events to a Cloudflare Worker runtime.

Readme

@abshahin/workflows-sdk

TypeScript SDK for dispatching typed background workflow events to a Cloudflare Worker runtime.

The package is transport-oriented and framework-agnostic. It provides a client, an HTTP transport, strongly typed event contracts, retry utilities, and job facades for email, notification, and payment workflows.

Related worker runtime: https://github.com/aashahin/cloudflare-workflows-worker

Why this package exists

@abshahin/workflows-sdk separates event production from workflow execution.

  • Producers only need to know how to send typed events
  • The transport layer decides how those events reach the workflow runtime
  • Event names and payloads stay typed across package boundaries
  • Existing application code can migrate away from Inngest-style producers with minimal surface change
  • The default companion runtime for this SDK is the Workflows Worker: https://github.com/aashahin/cloudflare-workflows-worker

Features

  • Typed contracts for email, notification, and payment events
  • HTTP transport for dispatching event batches to a worker endpoint
  • Producer-friendly job facades: EmailJobs, NotificationJobs, PaymentJobs
  • Transport retry support with exponential backoff
  • Optional dual-run mode for phased migrations
  • Optional onSendExhausted hook for persisting failed transport attempts
  • Sub-path exports for contracts and helpers

Installation

Inside this monorepo:

"@abshahin/workflows-sdk": "workspace:*"

Once published publicly, install it with your package manager of choice:

bun add @abshahin/workflows-sdk
npm install @abshahin/workflows-sdk

Quick start

import {
  EmailJobs,
  HttpTransport,
  NotificationJobs,
  PaymentJobs,
  createWorkflowsClient,
} from "@abshahin/workflows-sdk";

const client = createWorkflowsClient({
  transport: new HttpTransport({
    baseUrl: "https://workflows.example.com",
    authToken: process.env.WORKFLOWS_AUTH_TOKEN!,
  }),
});

const emailJobs = new EmailJobs(client, () => true);
const notificationJobs = new NotificationJobs(client);
const paymentJobs = new PaymentJobs(client);

await emailJobs.sendResetPasswordEmail({
  email: "[email protected]",
  userName: "John",
  otpCode: "123456",
  tenantId: "tenant_123",
});

await notificationJobs.addNotification(
  "tenant_123",
  "user_456",
  {
    title: "New course available",
    message: "Check the dashboard for details.",
    type: "info",
  },
  { delay: 5_000 },
);

await paymentJobs.processPayout({
  tenantId: "tenant_123",
  transactionId: "txn_001",
  walletId: "wallet_001",
  amount: 250,
  currency: "USD",
});

How it fits together

flowchart LR
  A[Application code] --> B[Job facade]
  B --> C[WorkflowsClient]
  C --> D[Transport]
  D --> E[Worker /dispatch endpoint]
  E --> F[Workflow runtime]

Core API

createWorkflowsClient

Creates a WorkflowsClient from a transport configuration.

Use it when you want a minimal factory instead of constructing the client class directly.

HttpTransport

Sends one or more workflow events to the worker's /dispatch endpoint.

Config:

  • baseUrl: worker base URL
  • authToken: shared bearer token
  • timeoutMs: request timeout, default 10000
  • retry: retry policy, or false to disable transport retries

Transport behavior:

  • Trims trailing slashes from baseUrl
  • Wraps network/timeouts as WorkflowSendError
  • Treats 429 and all 5xx responses as retryable
  • Treats other 4xx responses as non-retryable transport failures
  • Logs partial batch failures without throwing away successful IDs

EmailJobs

Facade for email-related workflow events.

Notable methods:

  • sendResetPasswordEmail
  • sendVerificationEmail
  • sendChangeEmailVerification
  • sendNewAccountCredentials
  • sendInvitationEmail
  • sendEnrollmentConfirmationEmail
  • sendCartRecoveryEmail
  • sendTrialEndingReminder
  • sendPaymentReceiptEmail
  • sendWithdrawalStatusEmail
  • sendFailedPaymentAlertEmail
  • sendRefundConfirmationEmail

The constructor accepts an optional isEnabled callback to short-circuit email dispatch when email delivery is disabled.

NotificationJobs

Facade for notification-related workflow events.

Notable methods:

  • addNotification
  • addNotificationForCustomer
  • addBulkNotification
  • addMultipleNotifications

addMultipleNotifications preserves per-item delays by sending individual events only when needed; otherwise it batches them.

PaymentJobs

Facade for payment-related workflow events.

Current method:

  • processPayout

This dispatches the payout orchestration workflow handled by the worker runtime.

Usage examples

Email workflow dispatch

import {
  EmailJobs,
  HttpTransport,
  createWorkflowsClient,
} from "@abshahin/workflows-sdk";

const client = createWorkflowsClient({
  transport: new HttpTransport({
    baseUrl: "https://workflows.example.com",
    authToken: "secret",
  }),
});

const emailJobs = new EmailJobs(client, () => true);

await emailJobs.sendVerificationEmail(
  {
    email: "[email protected]",
    otpCode: "123456",
    tenantId: "tenant_123",
  },
  { delay: 5_000 },
);

Notification workflow dispatch

import {
  HttpTransport,
  NotificationJobs,
  createWorkflowsClient,
} from "@abshahin/workflows-sdk";

const client = createWorkflowsClient({
  transport: new HttpTransport({
    baseUrl: "https://workflows.example.com",
    authToken: "secret",
  }),
});

const notificationJobs = new NotificationJobs(client);

await notificationJobs.addBulkNotification(
  "tenant_123",
  {
    title: "Billing update",
    message: "Your subscription has been renewed.",
    type: "billing",
  },
  ["user_1", "user_2"],
);

Payment workflow dispatch

import {
  HttpTransport,
  PaymentJobs,
  createWorkflowsClient,
} from "@abshahin/workflows-sdk";

const client = createWorkflowsClient({
  transport: new HttpTransport({
    baseUrl: "https://workflows.example.com",
    authToken: "secret",
  }),
});

const paymentJobs = new PaymentJobs(client);

await paymentJobs.processPayout({
  tenantId: "tenant_123",
  transactionId: "txn_001",
  walletId: "wallet_001",
  amount: 250,
  currency: "USD",
});

Advanced patterns

Dual-run mode

Use dual-run mode when migrating between workflow backends or validating a new transport.

import { HttpTransport, createWorkflowsClient } from "@abshahin/workflows-sdk";

const primaryTransport = new HttpTransport({
  baseUrl: "https://primary.example.com",
  authToken: "primary-secret",
});

const shadowTransport = new HttpTransport({
  baseUrl: "https://shadow.example.com",
  authToken: "shadow-secret",
});

const client = createWorkflowsClient({
  transport: primaryTransport,
  shadowTransport,
  dualRun: true,
});

The primary transport result is returned. Shadow transport failures are logged and suppressed.

Persist exhausted transport failures

Use onSendExhausted when you want to store failed dispatches for later replay instead of letting producer-side business logic fail immediately.

import { HttpTransport, createWorkflowsClient } from "@abshahin/workflows-sdk";

const client = createWorkflowsClient({
  transport: new HttpTransport({
    baseUrl: "https://workflows.example.com",
    authToken: "secret",
  }),
  onSendExhausted: async ({ events, options, error, attempts }) => {
    console.error("Persist failed workflow dispatch", {
      attempts,
      error: error.message,
      eventCount: events.length,
      traceId: options?.traceId,
    });
  },
});

When persistence succeeds, the client returns { ids: [] } instead of throwing.

Event domains

Email events

  • email/reset-password
  • email/new-account-credentials
  • email/change-email-verification
  • email/verification
  • email/cart-recovery
  • email/invitation
  • email/enrollment-confirmation
  • email/trial-reminder
  • email/payment-receipt
  • email/withdrawal-status
  • email/failed-payment-alert
  • email/refund-confirmation

Notification events

  • notification/create
  • notification/create-for-customer
  • notification/bulk-create

Payment events

  • payment/process-payout

Exports

| Export | Description | | ------------------------------------------------------------------------------------------------- | ----------------------------- | | createWorkflowsClient | Factory for WorkflowsClient | | WorkflowsClient | Core dispatch client | | HttpTransport | HTTP transport adapter | | EmailJobs | Email job facade | | NotificationJobs | Notification job facade | | PaymentJobs | Payment job facade | | EMAIL_EVENTS / NOTIFICATION_EVENTS / PAYMENT_EVENTS | Event name constants | | withRetry / getBackoffDelay / DEFAULT_RETRY_POLICY | Retry helpers | | deriveIdempotencyKey / generateEventId | Idempotency helpers | | WorkflowError / WorkflowSendError / WorkflowValidationError / WorkflowRetryExhaustedError | Typed errors |

Sub-path exports

The SDK exposes sub-path imports for tree-shaking or isolated usage:

import {
  EMAIL_EVENTS,
  type ResetPasswordEmailData,
} from "@abshahin/workflows-sdk/contracts";
import {
  deriveIdempotencyKey,
  withRetry,
} from "@abshahin/workflows-sdk/helpers";

Migration from Inngest

The job facades are designed to make migration straightforward, but there is one important API difference.

Previous Inngest usage relied on static methods:

- EmailJobs.sendResetPasswordEmail(data);
+ emailJobs.sendResetPasswordEmail(data);

The SDK uses instance-based facades so transports, feature flags, and fallback behavior can be injected once at application bootstrap.

License

MIT. Add the LICENSE file in the published workflows-sdk repository.