protoc-gen-ts-temporal 0.0.1

protoc plugin that emits a typed TypeScript Temporal client from temporal.v1.* annotated protos
Documentation
  • Coverage
  • 100%
    1 out of 1 items documented0 out of 0 items with examples
  • Size
  • Source code size: 104.13 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 229.58 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 14s Average build duration of successful builds.
  • all releases: 14s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • nu-sync/protoc-gen-ts-temporal
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • wcygan

protoc-gen-ts-temporal

A protoc plugin that emits a typed TypeScript Temporal client from temporal.v1.*-annotated protos.

Status: pre-release (v0.0.0). The plugin works end-to-end against the golden fixtures in crates/protoc-gen-ts-temporal/tests/fixtures/; distribution (crates.io / GitHub Releases / BSR Remote Plugin) is Phase 4.

What you get

For each service annotated with temporal.v1.workflow / signal / query / update options, the plugin emits two TypeScript files next to your normal *_pb.ts:

  • <basename>_temporal.ts — typed client class, workflow name constants, defineSignal / defineQuery / defineUpdate exports, a *Run handle class per workflow with typed signal / query / update methods, and free *With*Start helpers when the workflow opts into signal-with-start or update-with-start.
  • <basename>_pb_register.ts — exports schemas: readonly DescMessage[] for every proto message reachable from the file's services. Feed the union of these arrays into @temporalio/common/lib/protobufs-es's DefaultPayloadConverterWithProtobufsEs({ registry }) at your data-converter site (the constructor accepts a schemas array directly).

Schema source

Annotations come from cludden/protoc-gen-go-temporal, published on BSR as buf.build/cludden/protoc-gen-go-temporal. We do not ship our own annotation schema — a proto annotated for protoc-gen-go-temporal generates a Go client (cludden), a Rust client (planned: protoc-gen-rust-temporal), and a TS client (this plugin) with zero proto changes.

Wire format

Owned upstream by @temporalio/common/lib/protobufs-es. The plugin emits @bufbuild/protobuf v2 message types plus a schemas: readonly DescMessage[] inventory per file; the SDK converter handles serialization (binary + JSON), the messageType header, and cross-language compatibility with the Go SDK.

Runtime targets

Runtime Tier
Bun 1
Deno ≥ 2.7.14 1
Node 2

Generator hygiene rules: explicit .ts extensions on relative imports, bare specifiers for npm packages, no node: imports, no process.env.

Quickstart

Phase 4 distribution is not yet shipped. Until then, build the binary from this repo and point buf / protoc at it directly.

1. Add the annotation schema to your buf.yaml

version: v2
deps:
  - buf.build/cludden/protoc-gen-go-temporal   # annotation schema
  - buf.build/temporalio/api                   # transitive enum deps

2. Annotate your service

syntax = "proto3";
package invoice.v1;

import "temporal/v1/temporal.proto";

message RunRequest { string id = 1; }
message RunResponse { string result = 1; }

service InvoiceBatch {
  rpc Run(RunRequest) returns (RunResponse) {
    option (temporal.v1.workflow) = {
      task_queue: "invoice-generator"
    };
  }
}

3. Build the plugin and wire it into buf.gen.yaml

cargo build --release --bin protoc-gen-ts-temporal
# binary lands at target/release/protoc-gen-ts-temporal
# buf.gen.yaml
version: v2
plugins:
  - local: ./target/release/protoc-gen-ts-temporal
    out: gen
buf generate

This emits gen/invoice/v1/invoice_temporal.ts and gen/invoice/v1/invoice_pb_register.ts.

4. Wire the data converter

// src/data-converter.ts
import { DefaultPayloadConverterWithProtobufsEs } from "@temporalio/common/lib/protobufs-es";
import { schemas as invoiceSchemas } from "./gen/invoice/v1/invoice_pb_register.ts";

export const payloadConverter = new DefaultPayloadConverterWithProtobufsEs({
  registry: [...invoiceSchemas],
});

5. Use the generated client

import { Client } from "@temporalio/client";
import { InvoiceBatchClient } from "./gen/invoice/v1/invoice_temporal.ts";
import { payloadConverter } from "./src/data-converter.ts";

const client = new Client({ dataConverter: { payloadConverter } /* ... */ });
const batch = new InvoiceBatchClient(client);
const run = await batch.run({ id: "inv-123" });
const result = await run.result();

Plugin options

Pass via --ts-temporal_opt=k=v,k=v (or opt: in buf.gen.yaml):

Key Default Effect
pb_suffix _pb Sibling proto-types module suffix used by generated imports. Matches @bufbuild/protobuf-es out of the box; switch to _proto for ts-proto, etc.

Unknown keys are an error so typos surface immediately.

# buf.gen.yaml
version: v2
plugins:
  - local: ./target/release/protoc-gen-ts-temporal
    out: gen
    opt:
      - pb_suffix=_proto

Annotation surface

Annotation What the plugin emits
temporal.v1.workflow on a method Typed start(input, opts) method + a *Run handle class with typed result().
temporal.v1.query handle.<queryName>() returning the typed response.
temporal.v1.signal handle.<signalName>(input). Signal output must be google.protobuf.Empty.
temporal.v1.update handle.<updateName>(input) returning the typed response.
temporal.v1.activity Validate only in v1 — used for name-collision detection. Worker-side activity codegen is out of scope here.
WorkflowOptions.Signal.start = true Free function <signal>With<Workflow>Start(...) invoking client.workflow.signalWithStart.
WorkflowOptions.Update.start = true Free function <update>With<Workflow>Start(...) invoking client.workflow.startUpdateWithStart.

Out of scope for v1 emit: XNSActivityOptions, Patch, CLI*Options, FieldOptions.

Development

cargo test            # runs unit + golden tests; requires `protoc` on PATH
TEMPORAL_GOLDEN_BLESS=1 cargo test --test golden   # re-bless fixtures
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings

Fixtures live under crates/protoc-gen-ts-temporal/tests/fixtures/<name>/ with one .proto per fixture and the blessed *_temporal.ts + *_pb_register.ts outputs alongside.

Roadmap

See SPEC.md. Phases 0–3 are shipped (scaffold, parse, render, end-to-end golden fixtures). Phase 4 (distribution) and Phase 5 (invoice-generator migration as the first external consumer) are next.

License

MIT. See LICENSE.