// SPDX-License-Identifier: PMPL-1.0-or-later // SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell
= rescript-openapi :toc: :icons: font
Generate type-safe ReScript clients from OpenAPI specifications.
== Why
OpenAPI is the de facto standard for describing REST APIs. This tool generates:
- Type definitions - Records, variants, aliases from schemas
- Runtime validators - Using
rescript-schemafor safe JSON parsing - HTTP clients - Pluggable HTTP layer (fetch by default, bring your own)
- Operation aliases - Multiple ways to call the same endpoint
== Installation
[source,bash]
cargo install rescript-openapi
Or build from source:
[source,bash]
git clone https://github.com/hyperpolymath/rescript-openapi cd rescript-openapi cargo build --release
== Usage
=== Generate Client
[source,bash]
rescript-openapi generate -i openapi.yaml -o src/api
This generates:
ApiTypes.res- All type definitionsApiSchema.res- rescript-schema validatorsApiClient.res- HTTP client with fetch
=== Options
[cols="1,2,1"] |=== | Flag | Description | Default
| -i, --input
| Path to OpenAPI spec (JSON/YAML)
| Required
| -o, --output
| Output directory
| src/api
| -m, --module
| Module name prefix
| Api
| --with-schema
| Generate rescript-schema validators
| true
| --with-client
| Generate HTTP client
| true
| --unified
| Generate single module with types + schemas
| false
| --client-mode
| Client generation: full, functor-only, none
| full
| --variant-mode
| Variant style: polymorphic, standard
| polymorphic
| -c, --config
| Path to rescript-openapi.toml config file
| rescript-openapi.toml
| -w, --watch
| Watch input file and regenerate on change
| false
| --dry-run
| Print generated code to stdout
| false
|===
=== Validate Spec
[source,bash]
rescript-openapi validate -i openapi.yaml
=== Show Info
[source,bash]
rescript-openapi info -i openapi.yaml
== Generated Code
=== Types (ApiTypes.res)
[source,rescript]
/** A user in the system */ type user = { id: string, @as("full_name") fullName: string, email: string, role: option, }
type userRole = [ | #Admin | #User | #Guest ]
=== Schema Validators (ApiSchema.res)
[source,rescript]
module S = RescriptSchema.S
let userSchema: S.t = S.object(s => ({ id: s.field("id", S.string), fullName: s.field("full_name", S.string), email: s.field("email", S.string), role: s.fieldOr("role", S.option(userRoleSchema), None), }: user))
let parseUser = (json: Js.Json.t): user => { S.parseJsonOrThrow(json, userSchema) }
let serializeUser = (value: user): Js.Json.t => { S.reverseConvertToJsonOrThrow(value, userSchema) }
=== HTTP Client (ApiClient.res)
[source,rescript]
// Default client using fetch module Client = Make(FetchClient)
// Usage let config = makeConfig(~baseUrl="https://api.example.com", ())
let result = await Client.getUser(config, ~id="123", ()) switch result { | Ok(user) => Console.log(user.fullName) | Error(err) => Console.error(err.message) }
=== Custom HTTP Backend
[source,rescript]
// Implement the HttpClient signature module AxiosClient: HttpClient = { let request = async (req: httpRequest) => { // Use axios, ky, got, or any HTTP library let response = await Axios.request({ method: req.method->methodToString, url: req.url, headers: req.headers, data: req.body, }) Ok(response.data) } }
// Create client with custom HTTP module Api = Make(AxiosClient)
=== Mock for Testing
[source,rescript]
module MockClient: HttpClient = {
let request = async (req) => {
// Return mock data
Ok(%raw({"id": "123", "full_name": "Test User"}))
}
}
module TestApi = Make(MockClient)
== ReScript Dependencies
Add to your rescript.json:
[source,json]
{ "bs-dependencies": [ "@rescript/core", "rescript-schema", "@glennsl/rescript-fetch" ] }
Install with npm:
[source,bash]
npm install @rescript/core rescript-schema @glennsl/rescript-fetch
== Roadmap
- OpenAPI 3.1 support
-
oneOf/anyOfdiscriminated unions - File upload/download
- Streaming responses
- WebSocket support
- GraphQL schema generation
== Part of rescript-full-stack
This tool is part of the link:https://github.com/hyperpolymath/rescript-full-stack[ReScript Full Stack] ecosystem.
== License
PMPL-1.0-or-later