Skip to content

Frank-III/convex-rescript-codegen

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

convex-rescript-codegen

Generate type-safe ReScript bindings from your Convex backend functions. This tool parses your Convex TypeScript code using the TypeScript AST and generates idiomatic ReScript modules with proper types and React hooks.

✨ Features

  • 🎯 Type-safe bindings - Generates fully typed ReScript modules from Convex functions
  • πŸ”„ React hooks - Ready-to-use useQuery and useMutation hooks
  • πŸ“¦ Schema support - Parses Convex schema to generate document types
  • πŸ” AST-based parsing - Uses TypeScript compiler API for accurate parsing
  • ⚑ Blazing fast - Powered by Bun runtime (10x faster than Node.js)
  • πŸ‘οΈ Watch mode - Auto-regenerate on file changes with @parcel/watcher
  • 🎨 Idiomatic ReScript - Generates clean, idiomatic ReScript code
  • πŸ›‘οΈ Edge case handling - Handles reserved keywords, polymorphic variants

πŸ“¦ Installation

This package is designed to run with Bun for best performance:

# Recommended: Install with Bun bun add -D convex-rescript-codegen # Also works with npm/yarn/pnpm (requires Bun runtime) npm install -D convex-rescript-codegen

Note: This package requires Bun runtime to be installed on your system.

πŸš€ Quick Start

  1. Install Bun if you haven't already:
curl -fsSL https://bun.sh/install | bash
  1. Add to your package.json scripts:
{ "scripts": { "codegen": "bunx convex-rescript", "codegen:watch": "bunx convex-rescript --watch" } }
  1. Run the generator:
bun run codegen # or directly with bunx convex-rescript
  1. Use the generated bindings:
// Your generated bindings are in src/bindings/generated/ open ConvexTypes @react.component let make = () => { // Use generated query hook let users = Convex_users.Query_list.use(~limit=Some(JSON.Encode.int(10))) // Use generated mutation hook let createUser = Convex_users.Mutation_create.use() // Type-safe function calls let handleCreate = async () => { let userId = await createUser({ name: "Alice", email: "alice@example.com" }) Console.log2("Created:", userId) } // Render your UI... }

πŸ“ Generated File Structure

src/bindings/generated/ β”œβ”€β”€ ConvexTypes.res # Document types from schema β”œβ”€β”€ ConvexBindings.res # Core Convex React bindings β”œβ”€β”€ ConvexGenerated.res # Module exports β”œβ”€β”€ Convex_users.res # Bindings for users.ts β”œβ”€β”€ Convex_rooms.res # Bindings for rooms.ts └── Convex_messages.res # Bindings for messages.ts 

πŸ”§ Configuration

Command Line Options

convex-rescript [options] Options: -i, --input <path> Input directory (default: ./convex) -o, --output <path> Output directory (default: ./src/bindings/generated) -w, --watch Watch for changes -v, --verbose Verbose output -h, --help Show help

Examples

# Basic usage (uses defaults) convex-rescript # Watch mode convex-rescript --watch # Custom paths convex-rescript -i ./backend/convex -o ./frontend/src/bindings # Verbose output for debugging convex-rescript --verbose

πŸ“ Type Mappings

Convex Type ReScript Type
v.string() string
v.number() float
v.boolean() bool
v.null() unit
v.id("table") tableId (e.g., usersId)
v.optional(...) option<...>
v.array(...) array<...>
v.object(...) JSON.t
v.any() JSON.t
v.union(...) Polymorphic variants
v.literal(...) Polymorphic variants

🎯 Generated Code Examples

Query with no arguments

module Query_list = { type output = array<usersDoc> @module("convex/react") external useQuery: ('api, unit) => option<output> = "useQuery" let use = () => { useQuery(api["users"]["list"], ()) } }

Query with arguments

module Query_getById = { type input = { userId: usersId, } type output = option<usersDoc> @module("convex/react") external useQuery: ('api, input) => option<output> = "useQuery" let use = (~userId) => { useQuery(api["users"]["getById"], { userId: userId }) } }

Mutation

module Mutation_create = { type input = { name: string, email: string, avatar: option<string>, } type t = input => promise<usersId> @module("convex/react") external useMutation: 'api => t = "useMutation" let use = () => { useMutation(api["users"]["create"]) } }

Document Types from Schema

type usersDoc = { @as("_id") id: usersId, @as("_creationTime") creationTime: float, name: string, email: string, avatar: option<string>, status: [| #online | #offline | #away], lastSeen: float, createdAt: float, }

πŸ›‘οΈ Edge Case Handling

Reserved Keywords

The generator automatically escapes ReScript reserved keywords:

  • type β†’ type_ with @as("type")
  • private β†’ #"private" in polymorphic variants

Polymorphic Variants

Convex string unions are converted to ReScript polymorphic variants:

// Convex status: v.union( v.literal("online"), v.literal("offline"), v.literal("away") )
// ReScript status: [| #online | #offline | #away]

🀝 Requirements

  • Bun runtime 1.0+ (required) - Install Bun
  • ReScript v11+ (tested with v12 RC)
  • Convex backend with TypeScript functions
  • React project (for the generated hooks)

πŸ› Known Limitations

  1. Complex nested types - Very complex nested object types default to JSON.t
  2. Function return types - Currently infers common patterns, not all return types
  3. Convex validators - Complex validator compositions may not be fully supported
  4. Actions - Limited support for Convex actions (treated similar to mutations)

🚧 Roadmap

  • Full return type inference from function implementations
  • Support for Convex HTTP endpoints
  • Custom type mapping configuration
  • Generate mock data for testing
  • VS Code extension for instant generation
  • Support for convex-helpers library patterns

πŸ“„ License

MIT

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ™ Acknowledgments

  • Built for the ReScript and Convex communities
  • Inspired by GraphQL Code Generator and similar tools
  • Uses ts-morph for robust TypeScript AST parsing

πŸ“š Resources


Made with ❀️ for type-safe full-stack development

About

Generate type-safe ReScript bindings from Convex backend functions

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published