A ReScript library that automatically generates builder patterns for your types using docstring annotations.
This library searches for a rescript.json file containing "derive-builder" configuration and generates fluent builder code for ReScript types annotated with @@deriving(builder) in their docstrings. It traverses up the directory tree to find the configuration and processes all matching source files.
The library uses the rescript-tools doc command internally to extract type information and docstrings from your ReScript source files, then processes this data to generate builder patterns.
- Install:
npm install rescript-derive-builder(requires ReScript >= 12.0.0) - Configure: Add to your
rescript.json:{ "derive-builder": { "include": ["src/**/*.res"], "output": "src/generated" } } - Annotate: Add
@@deriving(builder)to your type's docstring - Generate: Run
npx rescript-derive-builder - Use: Import and use your generated builder!
Requirements:
- ReScript >= 12.0.0
npm install rescript-derive-builderAdd a "derive-builder" section to your rescript.json file:
{
"derive-builder": {
"include": ["src/**/*.res"],
"output": "src/generated"
}
}include: Array of glob patterns for source files to processoutput: Directory where generated builder files will be created
Add the @@deriving(builder) annotation in a docstring comment above your type:
/**
* @@deriving(builder)
*
* User type with builder pattern support.
* Other documentation can be present too.
*/
type user = {
name: string,
age: int,
email: option<string>,
}npx rescript-derive-builderlet user = UserBuilder.empty()
->UserBuilder.name("John Doe")
->UserBuilder.age(25)
->UserBuilder.email(Some("john@example.com"))
->UserBuilder.build()
switch user {
| Ok(validUser) => Stdlib.Console.log("Created user successfully")
| Error(message) => Js.Console.error(`Builder error: ${message}`)
}- Optional Field Support: Supports ReScript's optional field syntax (
name?: string) - Comprehensive Error Messages: Specific error messages for each missing required field
- Automatic Discovery: Finds
rescript.jsonwith derive-builder config - Glob Pattern Support: Flexible file matching with glob patterns
- Builder Pattern Generation: Creates fluent, type-safe builders with validation
- Error Handling: Comprehensive error messages for configuration issues
- Chain of Command: Extensible code generation strategies
Currently, this library only supports the main type pattern - types named t that are the primary type in a ReScript module:
// ✅ Supported: Main module type named 't'
/**
* @@deriving(builder)
*/
type t = {
name: string,
age: int,
}// ❌ Not yet supported: Named types other than 't'
/**
* @@deriving(builder)
*/
type user = {
name: string,
age: int,
}
// ❌ Not yet supported: Variant types
/**
* @@deriving(builder)
*/
type shape = Circle(float) | Rectangle(float, float)The library is architected with a strategy pattern that makes adding support for new type patterns straightforward:
HandlerInterface: Defines the contract for new type handlers- Chain of Command: Handlers are linked together, trying each in sequence
- Modular Handlers: Each type pattern has its own dedicated handler module
Adding new type support requires:
- Creating a new handler module implementing
HandlerInterface - Adding it to the handler chain in
CodegenStrategyCoordinator
This design ensures the library can easily grow to support:
- Named record types (
type user = {...}) - Variant types with constructors
- Tuple types
- Nested type definitions
- Custom type patterns
The current limitation is intentional - we're starting with the most common ReScript pattern (.t types) and will expand based on community needs.
You can mark fields as optional using ReScript's optional syntax:
/**
* @@deriving(builder)
*/
type user = {
name: string, // Required field
age: int, // Required field
email?: string, // Optional field
phone?: string, // Optional field
}Optional fields:
- Don't need to be set in the builder
- Won't generate "missing field" errors
- Are automatically typed as
option<T>in the final record
- Build:
npm run res:build - Clean:
npm run res:clean - Build & watch:
npm run res:dev
npm run res:build
node lib/es6/src/Codegen.res.mjsnpm run res:build
node bin/cli.jsThe library consists of several key modules:
ConfigDiscovery: Finds and parses derive-builder configuration with detailed error messagesBuilderMetadata: Parses ReScript documentation JSON for type information (fromrescript-tools docoutput), extracts field declarations with optional field detectionCodegenStrategy: Chain of command pattern for code generation strategies, supports different type patterns (currently.ttypes)Codegen: Main coordination module that executesrescript-tools docand orchestrates the generation process
For each type, the generator creates:
- Builder type: Internal state tracking with
option<T>for all fields empty()function: Creates initial builder state- Setter functions: One per field, with proper type signature based on whether field is optional
build()function: Validates required fields and constructs final object using comprehensive pattern matching
The library provides detailed error messages to help with integration:
- Configuration file discovery issues
- JSON syntax errors
- Missing or invalid configuration fields
- File system permission problems
- Fork the repository
- Create your feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
MIT