npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rescript-derive-builder

v2.0.0

Published

Automatic builder pattern generation for ReScript using @@deriving(builder)

Readme

ReScript Derive Builder

A ReScript library that automatically generates builder patterns for your types using docstring annotations.

Overview

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.

Quick Start

  1. Install: npm install rescript-derive-builder (requires ReScript >= 12.0.0)
  2. Configure: Add to your rescript.json:
    {
      "derive-builder": {
        "include": ["src/**/*.res"],
        "output": "src/generated"
      }
    }
  3. Annotate: Add @@deriving(builder) to your type's docstring
  4. Generate: Run npx rescript-derive-builder
  5. Use: Import and use your generated builder!

Installation

Requirements:

  • ReScript >= 12.0.0
npm install rescript-derive-builder

Configuration

Add a "derive-builder" section to your rescript.json file:

{
  "derive-builder": {
    "include": ["src/**/*.res"],
    "output": "src/generated"
  }
}

Configuration Options

  • include: Array of glob patterns for source files to process
  • output: Directory where generated builder files will be created

Usage

1. Annotate your types

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>,
}

2. Run the code generator

npx rescript-derive-builder

3. Use the generated builder

let user = UserBuilder.empty()
  ->UserBuilder.name("John Doe")
  ->UserBuilder.age(25)
  ->UserBuilder.email(Some("[email protected]"))
  ->UserBuilder.build()

switch user {
| Ok(validUser) => Stdlib.Console.log("Created user successfully")
| Error(message) => Js.Console.error(`Builder error: ${message}`)
}

Features

  • 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.json with 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

Current Limitations & Extensibility

Supported Type Patterns

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)

Extensibility by Design

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:

  1. Creating a new handler module implementing HandlerInterface
  2. 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.

Optional Fields

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

Development

Build

  • Build: npm run res:build
  • Clean: npm run res:clean
  • Build & watch: npm run res:dev

Run locally

npm run res:build
node lib/es6/src/Codegen.res.mjs

Test the CLI

npm run res:build
node bin/cli.js

Architecture

The library consists of several key modules:

  • ConfigDiscovery: Finds and parses derive-builder configuration with detailed error messages
  • BuilderMetadata: Parses ReScript documentation JSON for type information (from rescript-tools doc output), extracts field declarations with optional field detection
  • CodegenStrategy: Chain of command pattern for code generation strategies, supports different type patterns (currently .t types)
  • Codegen: Main coordination module that executes rescript-tools doc and orchestrates the generation process

Generated Builder Structure

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

Error Messages

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

Contributing

  1. Fork the repository
  2. Create your feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

MIT