Skip to content

btravers/temporal-contract

Repository files navigation

temporal-contract

Type-safe contracts for Temporal.io

End-to-end type safety and automatic validation for workflows and activities

CI npm version npm downloads TypeScript License: MIT

Documentation · Get Started · Examples

Features

  • End-to-end type safety — From contract to client, workflows, and activities
  • Automatic validation — Zod schemas validate at all network boundaries
  • Compile-time checks — TypeScript catches missing or incorrect implementations
  • Better DX — Autocomplete, refactoring support, inline documentation
  • Child workflows — Type-safe child workflow execution with neverthrow's ResultAsync
  • Result pattern — Explicit error handling without exceptions, powered by neverthrow
  • 🚧 Nexus support — Cross-namespace operations (planned for v0.5.0)

Quick Example

// Define contract once
const contract = defineContract({
  taskQueue: "orders",
  workflows: {
    processOrder: {
      input: z.object({ orderId: z.string() }),
      output: z.object({ success: z.boolean() }),
      activities: {
        processPayment: {
          input: z.object({ orderId: z.string() }),
          output: z.object({ transactionId: z.string() }),
        },
      },
    },
  },
});

// Implement activities with neverthrow's ResultAsync
import { declareActivitiesHandler, ApplicationFailure } from "@temporal-contract/worker/activity";
import { ResultAsync } from "neverthrow";

const activities = declareActivitiesHandler({
  contract,
  activities: {
    processPayment: ({ orderId }) =>
      ResultAsync.fromPromise(paymentService.process(orderId), (error) =>
        ApplicationFailure.create({
          type: "PAYMENT_FAILED",
          message: error instanceof Error ? error.message : "Payment failed",
          ...(error instanceof Error ? { cause: error } : {}),
        }),
      ).map((txId) => ({ transactionId: txId })),
  },
});

// Call from client - fully typed everywhere
const result = await client.executeWorkflow("processOrder", {
  workflowId: "order-123",
  args: { orderId: "ORD-123" }, // ✅ TypeScript knows!
});

Installation

# Core packages
pnpm add @temporal-contract/contract @temporal-contract/worker @temporal-contract/client

# Result/ResultAsync — peer dep used by worker/client APIs
pnpm add neverthrow

Documentation

📖 Read the full documentation →

Packages

Package Description
@temporal-contract/contract Contract builder and type definitions
@temporal-contract/worker Type-safe worker with automatic validation
@temporal-contract/client Type-safe client for consuming workflows
@temporal-contract/testing Testing utilities for integration tests

Usage Patterns

temporal-contract uses neverthrow end-to-end (workflows, activities, and the typed client) for explicit error handling via Result and ResultAsync. Migrating from a previous release that used @swan-io/boxed? See Migrating to neverthrow.

Contributing

See CONTRIBUTING.md.

License

MIT

About

End-to-end type safety and automatic validation for workflows and activities

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors