Codegen — specta → TypeScript
rata codegen generates a bindings.ts from your commands, containing:
- TypeScript
typedeclarations for every referenced Rust type, and - a typed
api.*facade whose calls delegate to@elyra/runtime'sinvoke.
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 surfaceT; 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, soi64/u64/… render asnumber. - Floats render as
number(not specta's JSON-orientednumber | null) — MessagePack representsNaN/Infinitynatively. - This applies both to the facade and to named-struct fields (a collection-level
pass), so a struct with an
i64field exports cleanly.
If you need integers beyond 2^53, reach for bigint transport (a future opt-in).
Related
- Frontend runtime — using
api.* - Commands · Models (models are plain structs, so they flow through codegen)