tauri-ts-generator 1.1.2

CLI tool to generate TypeScript bindings from Tauri commands
Documentation
# tauri-ts-generator

CLI tool to automatically generate TypeScript bindings from Tauri commands.

## Description

`tauri-ts-generator` scans your Rust code, finds all functions with the `#[tauri::command]` macro, and automatically generates:

- **TypeScript interfaces** for Rust structs and enums
- **TypeScript wrapper functions** to invoke Tauri commands via `invoke()`

This ensures type-safe interaction between the TypeScript frontend and Rust backend, minimizing manual boilerplate.

## Installation

```bash
cargo install --path .
```

Or build from source:

```bash
cargo build --release
```

## Quick Start

### 1. Initialize Configuration

```bash
cd your-tauri-project
tauri-ts-generator init
```

This will create a `tauri-codegen.toml` file with default settings.

### 2. Configure Settings

Edit `tauri-codegen.toml`:

```toml
[input]
source_dir = "src-tauri/src"
exclude = ["tests", "target"]
# Optional: enable for macro-generated types (requires cargo-expand)
# use_cargo_expand = true
# cargo_manifest = "src-tauri/Cargo.toml"

[output]
types_file = "src/generated/types.ts"
commands_file = "src/generated/commands.ts"

[naming]
type_prefix = ""
type_suffix = ""
function_prefix = ""
function_suffix = ""
```

### 3. Generate TypeScript Code

```bash
tauri-ts-generator generate
```

Or with verbose output:

```bash
tauri-ts-generator generate --verbose
```

## Example

### Rust Code (Input)

```rust
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct User {
    pub id: i32,
    pub name: String,
    pub email: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub enum UserStatus {
    Active,
    Inactive,
    Pending,
}

#[tauri::command]
pub async fn get_user(id: i32) -> Result<User, String> {
    // ...
}

#[tauri::command]
pub async fn get_all_users() -> Result<Vec<User>, String> {
    // ...
}

#[tauri::command]
pub fn greet(name: String) -> String {
    format!("Hello, {}!", name)
}
```

### TypeScript Code (Output)

**types.ts:**

```typescript
// This file was auto-generated by tauri-ts-generator
// Do not edit this file manually

export interface User {
  id: number;
  name: string;
  email: string | null;
}

export type UserStatus = "Active" | "Inactive" | "Pending";
```

**commands.ts:**

```typescript
// This file was auto-generated by tauri-ts-generator
// Do not edit this file manually

import { invoke } from "@tauri-apps/api/core";
import type { User } from "./types";

export async function getUser(id: number): Promise<User> {
  return invoke<User>("get_user", { id });
}

export async function getAllUsers(): Promise<User[]> {
  return invoke<User[]>("get_all_users");
}

export async function greet(name: string): Promise<string> {
  return invoke<string>("greet", { name });
}
```

## Type Mapping

### Basic Types

| Rust | TypeScript |
|------|------------|
| `String`, `&str`, `char` | `string` |
| `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64` | `number` |
| `f32`, `f64` | `number` |
| `bool` | `boolean` |
| `Vec<T>` | `T[]` |
| `Option<T>` | `T \| null` |
| `Result<T, E>` | `Promise<T>` |
| `HashMap<K, V>` | `Record<K, V>` |
| `()` | `void` |
| Custom struct | TypeScript interface |
| Simple enum | String union type |

### External Types (Crates)

| Rust | TypeScript | Description |
|------|------------|-------------|
| `chrono::DateTime<Tz>` | `string` | ISO 8601 format |
| `chrono::NaiveDateTime` | `string` | ISO 8601 format |
| `chrono::NaiveDate` | `string` | YYYY-MM-DD |
| `chrono::NaiveTime` | `string` | HH:MM:SS |
| `time::OffsetDateTime` | `string` | ISO 8601 format |
| `time::PrimitiveDateTime` | `string` | ISO 8601 format |
| `uuid::Uuid` | `string` | UUID string |
| `rust_decimal::Decimal` | `string` | Numeric string |
| `std::path::PathBuf` | `string` | File path |
| `url::Url` | `string` | URL string |
| `std::net::IpAddr` | `string` | IP address |
| `std::time::Duration` | `number` | Seconds |
| `serde_json::Value` | `unknown` | Any JSON |
| `bytes::Bytes` | `number[]` | Byte array |
| Complex enum | Discriminated union |

## Configuration

### `[input]`

| Parameter | Description | Default |
|-----------|-------------|---------|
| `source_dir` | Directory with Rust source files | `src-tauri/src` |
| `exclude` | List of directories/files to exclude | `["tests", "target"]` |
| `use_cargo_expand` | Use cargo expand for macro-generated types | `false` |
| `cargo_manifest` | Path to Cargo.toml for cargo expand | auto-detected |

### `[output]`

| Parameter | Description | Default |
|-----------|-------------|---------|
| `types_file` | Path to generate TypeScript types | `src/generated/types.ts` |
| `commands_file` | Path to generate TypeScript commands | `src/generated/commands.ts` |

### `[naming]`

| Parameter | Description | Default |
|-----------|-------------|---------|
| `type_prefix` | Prefix for type names | `""` |
| `type_suffix` | Suffix for type names | `""` |
| `function_prefix` | Prefix for function names | `""` |
| `function_suffix` | Suffix for function names | `""` |

## CLI Commands

```bash
tauri-ts-generator <COMMAND>

Commands:
  generate  Generate TypeScript bindings
  init      Create configuration file
  help      Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version
```

### generate

```bash
tauri-ts-generator generate [OPTIONS]

Options:
  -c, --config <FILE>  Path to config file [default: tauri-codegen.toml]
  -v, --verbose        Verbose output
  -h, --help           Print help
```

### init

```bash
tauri-ts-generator init [OPTIONS]

Options:
  -o, --output <FILE>  Path to create config file [default: tauri-codegen.toml]
  -f, --force          Overwrite existing file
  -h, --help           Print help
```

## Features

- **Automated Parsing** — uses `syn` to analyze Rust AST
- **Async Support** — correctly handles `async` commands
- **Custom Types** — parses structs and enums with `#[derive(Serialize)]` attributes
- **Serde Rename** — respects `#[serde(rename = "...")]`
- **Tauri Special Types** — automatically skips `State`, `Window`, `AppHandle`
- **Nested Modules** — scans commands inside `mod` blocks
- **Wildcard Re-exports** — supports `pub use module::*` patterns
- **Macro-generated Types** — optional support via `cargo expand`

## Macro-Generated Types

Some types in your project may be generated by macros (e.g., `progenitor`, `derive_builder`, etc.). These types don't exist as plain Rust source code, so the generator cannot find them by default.

### Detecting Unresolved Types

When the generator encounters types it cannot resolve, it will show a warning:

```
Warning: 4 type(s) could not be resolved and will not be generated:
  - 'AuthTokens' (used in src/commands/auth.rs)
  - 'UserProfile' (used in src/commands/auth.rs)

Hint: These types may be generated by macros (e.g., progenitor, serde, etc.).
      To include macro-generated types, add to your config:
        [input]
        use_cargo_expand = true
```

### Using cargo expand

To include macro-generated types, enable `cargo expand` in your configuration:

```toml
[input]
source_dir = "src-tauri/src"
use_cargo_expand = true
cargo_manifest = "src-tauri/Cargo.toml"  # optional, auto-detected
```

**Requirements:**
- Install cargo-expand: `cargo install cargo-expand`
- Nightly Rust toolchain (for cargo expand)

**Note:** Using `cargo expand` will compile your project, which may take longer than regular parsing.

## License

MIT