# schema-bridge

A minimal, practical Rust library for generating TypeScript type definitions from Rust types.

## Features

- **Simple to use**: Just derive `SchemaBridge` on your types
- **Serde compatible**: Works with serde attributes
- **Minimal dependencies**: No heavy tooling required
- **Workspace friendly**: Organized as a clean workspace

## Quick Start

Add to your `Cargo.toml`:

```toml
[dependencies]
schema-bridge = { path = "path/to/schema-bridge/crates/schema-bridge" }
serde = { version = "1.0", features = ["derive"] }
```

Define your types and export them:

```rust
use schema_bridge::{SchemaBridge, export_types};
use serde::{Serialize, Deserialize};

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

#[derive(Serialize, Deserialize, SchemaBridge)]
enum Status {
    Active,
    Inactive,
}

fn main() {
    // Easy export with the macro!
    export_types!("bindings.ts", User, Status).unwrap();
}
```

This generates `bindings.ts`:

```typescript
// This file is auto-generated by schema-bridge

export type User = { name: string; age: number; email: string | null; };

export type Status = 'Active' | 'Inactive';
```

## Architecture

The library is structured as a workspace with three crates:

- **schema-bridge**: Main entry point (facade)
- **schema-bridge-core**: Core traits and types
- **schema-bridge-macro**: Procedural macro for `#[derive(SchemaBridge)]`

This follows the pattern used by popular libraries like `serde`.

## Supported Types

- Primitives: `String`, `i32`, `f64`, `bool`, etc.
- Containers: `Vec<T>`, `Option<T>`
- Structs with named fields
- Enums (simple variants)
- **Newtype pattern**: `struct Wrapper(InnerType)` - delegates to wrapped type
- Tuple structs: `struct Point(f64, f64)` - generates TypeScript tuples
- **Serde attributes**: `#[serde(rename_all = "...")]` for name transformations

### Serde Attribute Support

The library respects `#[serde(rename_all)]` attributes on enums:

```rust
#[derive(Serialize, Deserialize, SchemaBridge)]
#[serde(rename_all = "snake_case")]
enum ConversationMode {
    Normal,      // → 'normal'
    Concise,     // → 'concise'
    Creative,    // → 'creative'
}
```

Supported transformations:
- `snake_case`: `MyVariant` → `my_variant`
- `camelCase`: `MyVariant` → `myVariant`
- `PascalCase`: `MyVariant` → `MyVariant` (no change)
- `SCREAMING_SNAKE_CASE`: `MyVariant` → `MY_VARIANT`
- `kebab-case`: `MyVariant` → `my-variant`

### String Conversion Support

Generate `Display` and `FromStr` implementations for easy string conversion:

```rust
#[derive(SchemaBridge)]
#[schema_bridge(string_conversion)]  // Enable Display + FromStr
#[serde(rename_all = "snake_case")]
enum TalkStyle {
    Brainstorm,
    Casual,
}

// Usage:
let style = TalkStyle::Brainstorm;
let s = style.to_string();  // "brainstorm"
let parsed: TalkStyle = "casual".parse().unwrap();  // TalkStyle::Casual
```

Perfect for:
- String-based APIs
- Command-line arguments
- Configuration parsing
- URL parameters

### Newtype Pattern for External Types

Perfect for wrapping external types you don't control:

```rust
// Wrap an external enum
#[derive(Serialize, Deserialize, SchemaBridge)]
struct MyStatus(external_crate::Status);

// Wrap a primitive for type safety
#[derive(Serialize, Deserialize, SchemaBridge)]
struct UserId(String);  // Generates: export type UserId = string;
```

## Use with Tauri

Perfect for Tauri applications where you need to keep Rust and TypeScript types in sync:

```rust
// In build.rs or a separate build tool
use schema_bridge::export_types;

fn main() {
    // Simple one-liner to export all your types!
    export_types!("../src/bindings.ts", AppConfig, UserData, TalkStyle).unwrap();
}
```

Or for more control:

```rust
use schema_bridge::{SchemaBridge, generate_ts_file};

fn main() {
    let types = vec![
        ("AppConfig", AppConfig::to_ts()),
        ("UserData", UserData::to_ts()),
    ];
    
    let ts_content = generate_ts_file(types);
    std::fs::write("../src/bindings.ts", ts_content)?;
}
```

## License

MIT OR Apache-2.0
