[ANN] rescript-rest - RPC-like client, contract, and server implementation for a pure REST API

Creating and consuming REST APIs was a neglected part of the ReScript ecosystem, and since the first days of using ReScript, I have been thinking about how to solve the problem. This is how I started creating rescript-schema and rescript-json-schema. After a long break, I collected all my OSS experience, took inspiration from ts-rest, and started building the new rescript-rest with the goal of creating an ultimate tool for working with REST API in ReScript with top-notch DX.

And today, I want to announce the first Beta version of the library rescript-rest. It currently covers very little scope of problems I plan to solve, but that’s the first step for a great library that is already usable to some extent.

Basic usage

Create Contract.res and define your routes:

// Contract.res

let createGame = Rest.route(() => {
  path: "/game",
  method: "POST",
  schema: s => {
    "userName": s.field("user_name", S.string),
  },
})

:brain: Currently rescript-rest supports only client, but the idea is to reuse the file both for client and server.

Now you can use the contract to perform type-safe calls to your server:

// Client.res

let client = Rest.client(~baseUrl="http://localhost:3000")

let _ = await client.call(Contract.createGame, ~variables={"userName": "Dmitry"})

Planned features

  • Support path params
  • Support query params
  • Implement type-safe response
  • Support passing headers and fetch options
  • Generate OpenAPI from Contract
  • Generate Contract from OpenAPI
  • Integrate with Fastify on server-side

I have a vision of how the library should look in the end, but one of the reasons I posted the announcement this early is to get your feedback, so feel free to leave any thoughts you have. Also, I will use the thread to post new versions with new features :blush:

11 Likes

In the end, the tool should support the majority of ts-rest features, have a more ergonomic design for ReScript users, have a tree-shakable contract, and be more convenient for passing body/params/query - as a single variables value where you can use variants. While in ts-rest you should use separate fields for them.

1 Like

This especially would be a fantastic addition to the ecosystem. I look forward to following your progress!

2 Likes