JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 276
  • Score
    100M100P100Q82863F
  • License MIT

React bindings for Durably - step-oriented resumable batch execution

Package Exports

  • @coji/durably-react
  • @coji/durably-react/spa

Readme

@coji/durably-react

React bindings for Durably — steps that survive crashes.

Documentation | GitHub

Note: This package is ESM-only. CommonJS is not supported.

Installation

# Fullstack mode (connects to Durably server)
npm install @coji/durably-react

# SPA mode (runs Durably in the browser with SQLocal)
npm install @coji/durably-react @coji/durably kysely zod sqlocal

Quick Start (Fullstack Mode)

import { createDurably } from '@coji/durably-react'
import type { durably } from './durably.server'

// Create type-safe hooks from server's Durably type
export const durably = createDurably<typeof durably>({
  api: '/api/durably',
})

function MyComponent() {
  const { trigger, isLeased, isCompleted, output } = durably.myJob.useJob()

  return (
    <button onClick={() => trigger({ id: '123' })} disabled={isLeased}>
      Run
    </button>
  )
}

SPA Mode

For browser-only apps, import from @coji/durably-react/spa:

import { createDurably, defineJob } from '@coji/durably'
import { DurablyProvider, useJob } from '@coji/durably-react/spa'
import { SQLocalKysely } from 'sqlocal/kysely'
import { z } from 'zod'

const myJob = defineJob({
  name: 'my-job',
  input: z.object({ id: z.string() }),
  run: async (step, input) => {
    await step.run('step-1', async () => {
      /* ... */
    })
  },
})

// Initialize Durably
async function initDurably() {
  const sqlocal = new SQLocalKysely('app.sqlite3')
  const durably = createDurably({
    dialect: sqlocal.dialect,
    jobs: { myJob },
  })
  await durably.init() // migrate + start
  return durably
}
const durablyPromise = initDurably()

function App() {
  return (
    <DurablyProvider durably={durablyPromise} fallback={<div>Loading...</div>}>
      <MyComponent />
    </DurablyProvider>
  )
}

function MyComponent() {
  const { trigger, isLeased, isCompleted } = useJob(myJob)
  return (
    <button onClick={() => trigger({ id: '123' })} disabled={isLeased}>
      Run
    </button>
  )
}

Documentation

For full documentation, visit coji.github.io/durably.

License

MIT