Which solution comes to mind to when you control the client and the server.
You want to share types between front-end and back-end.
Right now I have a Hono server and I call this from my client using fetch.
And I cheat by saying “trust me bro” using
external fromJson: Js.Json.t => 't = "%identity"
external toJson: 't => Js.Json.t = "%identity"
// On the client
let response = await fetch(
url,
{
method: #POST,
headers: Headers.fromObject({
"Content-Type": "application/json",
}),
body: reqData
->toJson
->JSON.stringify
->Body.string,
},
)
let json = await response->Response.json
let resData: vrindelyckResponse = fromJson(json)
// On the server
app
->Hono.post(route, async ctx => {
let json = await ctx->Context.req->Request.json
let requestData = json->fromJson
I mean, this all works, but do I really care how this is done on the http level?
The fact that my endpoint is a POST for example.
I just want to invoke something on the server, and get that return type.
Does anything come to mind to solve this?
Yeah, I looked at that, but I still need to define the rest route and have some opinion on how I want to do it http-wise.
Maybe that is fine, but I just wonder if there is nothing out there where I can define the function server-side and invoke it on the client as if it was a local function.
ReScript Rest is very flexible, and if you miss something, let me know about it in issues, and I’ll add it. For example, if your server uses Hono.js it’s not difficult to add an integration for it, so both client and server side are 100% typesafe.
As for the need to manually describe the contract, we are discussing with @zth the solution to codegen ReScript Rest from OpenAPI, but this will probably happen after ReScript v12 is released
Also, you can build a wrapper around it to always use JSON body for your transfer and simply use it like an RPC. Actually, I might make it myself as a part of the library
I don’t know how to make it without a separate Contract.res, but maybe it’s not bad. Also, you’ll always be able to move to Rest.route if you need more HTTP control.
type middleware
@module("hono/cors")
external cors: unit => middleware = "cors"
@send
external use: (Hono.t<'t>, middleware) => unit = "use"
// To use
app->use(cors())
Me neither. So I built an rpc library some time ago (wow, 3 years ago). Never published it on npm or somewhere else. Hasn’t been updated a while. Just for my own side project. But you can have a look: GitHub - dkirchhof/rescript-rpc
Thanks a lot!
So, for my understanding, I stil need to wire this on the server side like this right:
let app = Fastify.make()
app->Fastify.route(Contract.getPosts, async ({input}) => {
// Implementation where return type is promise<'response>
})
let _ = app->Fastify.listen({port: 3000})
Sorry, I was really busy recently. Contributions are welcome. I think it should be really similar to Fastify integration, which you can use as a reference.