Elyra
Elyra The coding agent e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Elyra SQL Server MySQL-compatible SQL server in Rust Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine
Release notes
Changelog
Elyra
Codegen — specta → TypeScript

Codegen — specta → TypeScript

rata codegen generates a bindings.ts from your commands, containing:

  1. TypeScript type declarations for every referenced Rust type, and
  2. a typed api.* facade whose calls delegate to @elyra/runtime's invoke.

It uses specta for the type graph and specta-typescript's framework_runtime hook (the same mechanism tauri-specta uses) — but Elyra has its own bridge, so rata codegen is the replacement for tauri-specta's generator.

Running it

rata codegen        # writes to [codegen].out (default app/src/bindings.ts)

Under the hood the app runs in codegen mode (ELYRA_CODEGEN_OUT is set), writes the file, and exits before opening a window.

Example output

// Generated by Ratatosk (`rata codegen`). Do not edit by hand.
import { invoke } from "@elyra/runtime";

export type Todo = { id: number, title: string, done: boolean };

export const api = {
  greet(name: string): Promise<string> {
    return invoke("greet", name);
  },
  list_todos(): Promise<Todo[]> {
    return invoke("list_todos");
  },
  checked_div(a: number, b: number): Promise<number> {
    return invoke("checked_div", a, b);
  },
};
  • Named types render as references (Promise<Todo>), not inlined.
  • Result<T, E> commands surface T; errors reject the promise.
  • Every command arg/return type must implement specta::Type (and serde).

serde attributes

Types are exported through specta-serde, so serde container attributes are reflected in the generated TypeScript:

  • #[serde(rename = "...")] / #[serde(rename_all = "...")] — field and variant renaming.
  • Tagged enums (#[serde(tag = "...")], tag + content, untagged) — rendered as discriminated (or bare) unions.
  • #[serde(flatten)] — merged as a TypeScript intersection (A & B).
  • #[serde(skip)] / skip_serializing — omitted fields.

Keep serde symmetric (the same shape for serialize and deserialize); asymmetric attributes aren't supported by this single-shape export.

Number policy

The sqlx/JS number story has sharp edges; Elyra's policy (in codegen.rs):

  • specta-typescript refuses to export 64-bit integers (they can't round-trip through a JS number). Elyra's wire is MessagePack, where they already arrive as JS numbers, so i64/u64/… render as number.
  • Floats render as number (not specta's JSON-oriented number | null) — MessagePack represents NaN/Infinity natively.
  • This applies both to the facade and to named-struct fields (a collection-level pass), so a struct with an i64 field exports cleanly.

If you need integers beyond 2^53, reach for bigint transport (a future opt-in).

Related