A code generator that turns Rust's Borsh structs into Zorsh TypeScript schemas, using Rust itself as the schema language.
zorsh-gen-rs takes your existing Rust types and automatically generates Zorsh schemas for TypeScript. One command, zero maintenance, complete type safety.
- 🎯 Use Rust as Your Schema - No separate schema language needed. Your Rust types are your source of truth
- 🔄 Automatic Conversion - Directly generate Zorsh schemas from your Rust structs and enums
- 🌳 Preserves Structure - Maintains your Rust module hierarchy in the generated TypeScript
- 🔍 Deep Type Analysis - Handles complex nested types, generics, and cross-module dependencies
- ⚡ Zero Runtime Overhead - Follows Borsh's philosophy of high performance serialization
- 🛡️ Type Safe - If it compiles in Rust, it works in TypeScript
# Using npx (Node.js)
npx @zorsh/cli ./src/models ./generated
# Or using pnpm
pnpm dlx @zorsh/cli ./src/models ./generated
Your Rust types:
use borsh::{BorshDeserialize, BorshSerialize};
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Player {
name: String,
score: u32,
inventory: HashMap<String, Vec<Item>>,
}
Automatically become Zorsh schemas:
import { b } from '@zorsh/zorsh';
export const PlayerSchema = b.struct({
name: b.string(),
score: b.u32(),
inventory: b.hashMap(b.string(), b.vec(ItemSchema))
});
Most serialization formats force you to define your data structures twice: once in your schema language (like .proto
files for Protocol Buffers or SDL for GraphQL), and again in your programming language. With Borsh, your data structures are already defined in Rust - that's where they live. zorsh-gen-rs recognizes this and lets your existing Rust types act as the schema language for Zorsh, the TypeScript implementation of Borsh.
No duplicate definitions. No schema syncing. No extra maintenance. Just:
- No Schema Maintenance - Your Rust types are your schema. No need to maintain separate schema files
- Compiler-Verified - If your Rust types compile, your schemas are valid
- IDE Support - Get full IDE support, type checking, and refactoring tools for your schemas
- Ecosystem Support - Use the full power of Rust's type system and module system
Choose the installation method that works best for your workflow:
# Install globally with npm
npm install -g @zorsh/cli
# Install as a dev dependency in your project
npm install --save-dev @zorsh/cli
# Or use without installing
npx @zorsh/cli
pnpm dlx @zorsh/cli
# Install from crates.io
cargo install zorsh-gen-rs
# Or build from source
git clone https://github.com/r-near/zorsh-gen-rs
cd zorsh-gen-rs
cargo install --path .
# Unix-like systems (Linux, macOS)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/r-near/zorsh-gen-rs/releases/latest/download/zorsh-gen-rs-installer.sh | sh
# Windows PowerShell
powershell -ExecutionPolicy Bypass -c "irm https://github.com/r-near/zorsh-gen-rs/releases/latest/download/zorsh-gen-rs-installer.ps1 | iex"
# Homebrew (macOS and Linux)
brew install r-near/tap/zorsh-gen-rs
Pre-built binaries are available for the following platforms:
- macOS (Apple Silicon, Intel)
- Windows (x64)
- Linux (x64, ARM64)
Download the appropriate binary for your platform from the releases page.
# Basic usage
zorsh-gen-rs <input-dir> <output-dir>
# With options
zorsh-gen-rs --flat-output --only-annotated ./src/models ./generated
use zorsh_gen_rs::{ZorshGen, Config};
let config = Config::default();
let generator = ZorshGen::new(config);
// Convert a directory
generator.convert("./src/models", "./generated")?;
// Or convert a string
let zorsh_code = zorsh_gen_rs::convert_str(rust_code)?;
- Primitives: All Rust numeric types (
u8
throughu128
,i8
throughi128
,f32
,f64
) - Strings:
String
and&str
- Collections:
Vec<T>
,[T; N]
,HashMap<K, V>
- Options:
Option<T>
- Custom Types: Structs and Enums (including complex nested types)
zorsh-gen-rs preserves your Rust module structure in the generated TypeScript:
src/
models/
player.rs
items/
mod.rs
weapon.rs
Becomes:
generated/
models/
player.ts
items/
index.ts
weapon.ts
let config = Config {
// Only process structs with #[derive(BorshSerialize)]
only_annotated: true,
// Skip certain paths
ignored_patterns: vec!["tests/", "examples/"],
// Output structure (nested or flat)
output_structure: OutputStructure::Nested,
};
Contributions are welcome! Before you start:
- Check out our Technical Documentation for a deep dive into the codebase
- Feel free to:
- Report bugs
- Suggest features
- Submit pull requests
- Zorsh - The TypeScript implementation of Borsh
- Borsh - The original Rust binary serialization format
MIT