I created a first draft of how I would write it in the playground:
// LIB / BINDINGS
module Error = {
@new
external make: string => Js.Exn.t = "Error"
}
module Express = {
module Request = {
type t
}
module Response = {
type t
@send
external set: (t, ~name: string, ~value: string) => unit = "set"
@send
external setMany: (t, Js.Dict.t<string>) => unit = "set"
@send
external status: (t, int) => t = "status"
@send
external send: (t, string) => unit = "send" // NOTE: this actually takes other types than string as well, according to https://expressjs.com/en/5x/api.html#res.send
@send
external json: (t, Js.Json.t) => unit = "json"
module NodeResponse = {
@send
external setHeader: (t, ~name: string, ~value: string) => unit =
"setHeader" // NOTE: this really returns t, but it's easier to use this way
@send
external write: (t, string) => unit = "write" // NOTE: this really returns bool, but it's easier to use this way
@send
external end: t => unit = "end"
}
}
module Application = {
type t
@module @new
external make: unit => t = "express"
type next = (~error: Js.Exn.t=?) => unit
type callback = (Request.t, Response.t, next) => unit
@send
external get: (t, string, callback) => unit = "get"
@send
external post: (t, string, callback) => unit = "post"
@send
external listen: (t, int, unit => unit) => unit = "listen"
}
}
// APPLICATION
open Express.Application
let app = make()
let okText = (_req, res, _next) => {
open Express.Response
res->set(~name="Content-Type", ~value="text/plain")
res->send("Ok")
}
let error = (isUnhandled, _req, res, next: next) => {
open Express.Response
if isUnhandled {
next(~error=Error.make("Server Error"))
} else {
res->set(~name="Content-Type", ~value="text/plain")
res->status(500)->send("Server Error")
}
}
app->get("/", okText)
app->post("/compile/", okText)
app->get("/error/handled", error(false))
app->get("/error/unhandled", error(true))
let port = 8080
let default = () => {
app->listen(port, () =>
Js.Console.log("Listening at http://localhost:" ++ port->Js.Int.toString)
)
}
default()
Warning: I’m not using Express regularly, therefore my usage may not be optimal. But I’m very confident to write bindings. I tried to stick to the expressjs docs.
I successfully ran the given code, but didn’t test every possible aspect.
My example code does not translate exactly to your given raw-block, but uses functions provided by express and not the underlying node apis. (I still included them in the bindings)
@bloodyowl created a package of bindings for express a while ago as well. I’m not sure on how up to date the package actually is. But I’m sure there is a lot you can learn from that repo as well, since the author is well experienced in using rescript.
Do you have some questions about the given example?