Skip to content

Type Definitions ​

Common types used across both SPA and Fullstack modes.

The React package’s SSE and client event shapes are transport-layer unions for the wire protocol. They are not the same symbols as @coji/durably’s DomainEvent / OperationalEvent helpers (isDomainEvent, etc.) exported from the core package — use the core helpers when classifying events inside Node or shared libraries; use hook payloads and documented client types when handling SSE in the browser.

RunStatus ​

Imported from @coji/durably and re-exported by @coji/durably-react:

ts
type RunStatus =
  'pending' | 'leased' | 'waiting' | 'completed' | 'failed' | 'cancelled'

Hooks expose isTerminal and isActive flags directly: terminal means completed, failed, or cancelled; active means pending or leased. ClientRun objects from the HTTP API also include these derived fields.

Both SPA and fullstack useJob results also expose isResolving: boolean. It is true while enabled auto-resume is resolving a pending, leased, or waiting run and false when the lookup succeeds, finds nothing, fails, is superseded, or is skipped by initialRunId or autoResume: false.

StatusDescription
pendingJob is queued, waiting to be picked up by worker
waitingJob is suspended for external input or awaiting a resume lease
leasedJob is currently executing
completedJob finished successfully
failedJob encountered an error
cancelledJob was cancelled before completion

Progress ​

ts
interface Progress {
  current: number
  total?: number
  message?: string
}
PropertyTypeDescription
currentnumberCurrent progress value
totalnumber | undefinedTotal expected value
messagestring | undefinedHuman-readable progress message

LogEntry ​

ts
interface LogEntry {
  id: string
  runId: string
  stepName: string | null
  level: 'info' | 'warn' | 'error'
  message: string
  data: unknown
  timestamp: string
}
PropertyTypeDescription
idstringUnique log entry ID
runIdstringAssociated run ID
stepNamestring | nullStep that created the log
level'info' | 'warn' | 'error'Log severity
messagestringLog message
dataunknownOptional structured data
timestampstringISO timestamp

ClientRun ​

A subset of the core Run type returned by HTTP endpoints. Internal fields (leaseOwner, leaseExpiresAt, idempotencyKey, concurrencyKey, leaseGeneration, updatedAt) are excluded. Responses include isTerminal, isActive, and isWaiting derived from status.

ts
interface ClientRun {
  id: string
  jobName: string
  status: RunStatus
  input: unknown
  output: unknown
  error: string | null
  currentStepIndex: number
  completedStepCount: number
  progress: Progress | null
  labels: Record<string, string>
  startedAt: string | null
  completedAt: string | null
  createdAt: string
  isTerminal: boolean
  isActive: boolean
  isWaiting: boolean
}
PropertyTypeDescription
idstringUnique run ID
jobNamestringName of the job
statusRunStatusCurrent status
inputunknownInput data
outputunknownJob output (when completed)
errorstring | nullError message (when failed)
currentStepIndexnumberIndex of the current step
completedStepCountnumberTotal number of completed steps
progressProgress | nullCurrent progress
labelsRecord<string, string>Labels set at trigger time
startedAtstring | nullISO timestamp of start
completedAtstring | nullISO timestamp of completion
createdAtstringISO timestamp of creation
isTerminalbooleantrue when status is completed, failed, or cancelled
isActivebooleantrue when status is pending or leased
isWaitingbooleantrue when status is waiting

TypedClientRun ​

A typed version of ClientRun with generic input/output types. Used by fullstack hooks (HTTP/SSE connection).

ts
type TypedClientRun<
  TInput extends Record<string, unknown> = Record<string, unknown>,
  TOutput extends Record<string, unknown> | undefined = Record<string, unknown>,
> = Omit<ClientRun, 'input' | 'output'> & {
  input: TInput
  output: TOutput | null
}

Use with useRuns to get typed runs in a multi-job dashboard:

tsx
type ImportRun = TypedClientRun<{ file: string }, { count: number }>
type SyncRun = TypedClientRun<{ userId: string }, { synced: boolean }>
type DashboardRun = ImportRun | SyncRun

const { runs } = durably.useRuns<DashboardRun>({ pageSize: 10 })

TypedRun ​

A typed version of the core Run type with generic input/output types. Used by SPA hooks (direct Durably access). Same shape as TypedClientRun but based on the full Run type (includes internal fields like leaseOwner).

ts
type TypedRun<
  TInput extends Record<string, unknown> = Record<string, unknown>,
  TOutput extends Record<string, unknown> | undefined = Record<string, unknown>,
> = Omit<Run, 'input' | 'output'> & {
  input: TInput
  output: TOutput | null
}

DurablyEvent ​

Union type for all SSE events streamed from the server. Useful for custom event handling.

ts
type DurablyEvent =
  | {
      type: 'run:waiting'
      runId: string
      jobName: string
      waitId: string
      labels: Record<string, string>
    }
  | { type: 'run:leased'; runId: string; jobName: string; input: unknown }
  | {
      type: 'run:complete'
      runId: string
      jobName: string
      output: unknown
      duration: number
    }
  | { type: 'run:fail'; runId: string; jobName: string; error: string }
  | { type: 'run:cancel'; runId: string; jobName: string }
  | { type: 'run:delete'; runId: string; jobName: string }
  | { type: 'run:trigger'; runId: string; jobName: string; input: unknown }
  | {
      type: 'run:coalesced'
      runId: string
      jobName: string
      status: 'pending' | 'leased' | 'waiting'
      labels: Record<string, string>
      skippedInput: unknown
      skippedLabels: Record<string, string>
    }
  | { type: 'run:progress'; runId: string; jobName: string; progress: Progress }
  | {
      type: 'step:start'
      runId: string
      jobName: string
      stepName: string
      stepIndex: number
    }
  | {
      type: 'step:complete'
      runId: string
      jobName: string
      stepName: string
      stepIndex: number
      output: unknown
    }
  | {
      type: 'step:cancel'
      runId: string
      jobName: string
      stepName: string
      stepIndex: number
      labels: Record<string, string>
    }
  | {
      type: 'log:write'
      runId: string
      jobName: string
      stepName: string | null
      labels: Record<string, string>
      level: 'info' | 'warn' | 'error'
      message: string
      data: unknown
    }

All events include runId and jobName. Unlike core Durably events, SSE events omit timestamp and sequence — only the fields needed by the UI are sent.

StepRecord ​

ts
interface StepRecord {
  name: string
  status: 'completed' | 'failed' | 'cancelled'
  output: unknown
  error: string | null
  startedAt: string
  completedAt: string | null
}
PropertyTypeDescription
namestringStep name
status'completed' | 'failed' | 'cancelled'Step result
outputunknownStep return value
errorstring | nullError message (when failed)
startedAtstringISO timestamp of start
completedAtstring | nullISO timestamp of completion

Waiting runs ​

isWaiting is true exactly when status is waiting. A signal or durable deadline can finalize the wait result while the run remains waiting for an available worker and any valid same-concurrency-key lease. The hook changes to leased on resume and then tracks the job's signal or timeout branch; finalizing the wait alone does not make the run terminal. isActive retains its pending/leased meaning, so it is not the inverse of isTerminal. Use !isTerminal to identify unfinished runs. Auto-resume prefers leased, then pending, then waiting runs. run:waiting updates tracked runs and run lists; subscriptions hydrate waiting state after reconnect. Cancellation remains available while waiting; delete/retrigger require cancellation first. Inspect saved wait outcomes and timing through the core getWait() / getWaits() methods or the HTTP handler’s /wait and /waits routes. Re-read the run and waits after reconnecting because SSE notifications may have been missed. Authorized input can be submitted through HTTP /signal.

Released under the MIT License.