Quantcast
Channel: ReScript Forum - Latest posts
Viewing all articles
Browse latest Browse all 2592

New Library: rescript-derive-builder - Automatic Builder Pattern Generation

$
0
0

I’ve been working on a new library that automatically generates fluent builder patterns for ReScript types, and I’d love to get some feedback from the community before continuing development.

:rocket: What it does

rescript-derive-builder scans your ReScript codebase and generates type-safe builder patterns for types annotated with @@deriving(builder). Here’s a quick example:

/**
 * @@deriving(builder)
 * User profile with optional fields
 */
type t = {
  name: string,
  age: int,
  email?: string,  // Optional field support!
}

Generates:

let user = UserBuilder.empty()
  ->UserBuilder.name("Alice")
  ->UserBuilder.age(25)
  ->UserBuilder.email(Some("alice@example.com"))
  ->UserBuilder.build()
  
// Result: result<User.t, string> with specific error messages

GitHub: GitHub - nathan-tranquilla/rescript-derive-builder
NPM: https://www.npmjs.com/package/rescript-derive-builder

:dart: Design Decisions I’d Love Feedback On

1. Using rescript-tools doc for Type Extraction

Instead of using PPX, I chose to use rescript-tools doc to extract type information:

Pros:

  • :white_check_mark: Leverages the official ReScript toolchain
  • :white_check_mark: Gets accurate type information (handles all ReScript syntax)
  • :white_check_mark: JSON output is stable and well-structured
  • :white_check_mark: Future-proof against ReScript syntax changes
  • :white_check_mark: Allows me to write codegen in ReScript!

Cons:

  • :x: Requires an extra compilation step

Question: Does this approach feel right to the community? Are there concerns about the approach?

2. Docstring Annotations + JSON Config

I went with a hybrid approach:

  • Docstring annotations (@@deriving(builder)) mark which types to process
  • JSON configuration within the rescript.json file specify file patterns and output directories
{
  "derive-builder": {
    "include": ["src/**/*.res"],
    "output": "src/generated" 
  }
}

Rationale:

  • Docstring annotations keep the intent close to the type definition
  • JSON config handles project-level concerns (file patterns, output paths)

Question: How does this feel compared to any alternative approaches like a dedicated config file for the builder?

3. Strategy Pattern Architecture

The library uses a chain-of-responsibility pattern for code generation:

module type HandlerInterface = {
  let canHandle: JSON.t => bool
  let handle: JSON.t => string
}

This makes it easy to add support for different type patterns by implementing new handlers.

:construction: Current Limitations (Intentional)

Right now, the library only supports the main type pattern (single type t within a file):

// ✅ Supported
type t = { name: string, age: int }

// ❌ Multiple non-t types not yet supported  
type user = { name: string, age: int }
...

Why start here?

  • Most common ReScript pattern (module-scoped .t types)
  • Validates the architecture before expanding
  • Keeps initial scope manageable

:bulb: Key Features

  • Optional field support with ReScript’s field?: type syntax
  • Comprehensive error messages for missing required fields
  • Type-safe builders with proper ReScript typing
  • Automatic discovery of configuration files (looks for the first rescript.json file in parent having the “derive-builder” configuration key)
  • Extensible architecture for future type patterns

:thinking: Questions for the Community

  1. Architecture: Does the rescript-tools doc + docstring approach feel idiomatic?
  2. API Design: How does the generated builder API feel? Any ergonomic issues?
  3. Limitations: What type patterns should I prioritize next?
  4. Performance: Any concerns about the build-time code generation step?
  5. Integration: How would this fit into your existing ReScript workflows?

:chart_with_upwards_trend: Next Steps

Next steps would involve expanding type generation for other type patterns


Try it out:

npm install rescript-derive-builder
npx rescript-derive-builder

I’d really appreciate any thoughts, concerns, or suggestions! This is my first major ReScript library, so community input is invaluable for making sure I’m heading in the right direction.


Viewing all articles
Browse latest Browse all 2592

Trending Articles