This meeting focused primarily around the idea of a ServiceDefinition
. From a ServiceDefintion
, the HTTP API can produce a running service, documentation and a client.
John referenced previous work, redeyes, which will be our starting point.
Below is the example from the redeyes README
import redeyes.api._
val request: Api[Int] =
GET >~>
path("/employees/") >~>
contentType("application/json") >~>
queryInt("limit")
val response: Api[Json] =
contentType("application/json") >~> content(JsonCodec)
val listEmployees = serviceM(request, response) { limit =>
loadAllEmployees(limit).toJson
}
val docs: Markdown = document(listEmployees)
val server: Task[Unit] = compileToServer(listEmployees)
val remoteService: Int => Task[Json] = remotely(listEmployees)("localhost", 80)
server.run
The ServiceDefinition
has the following components:
request[A]
: A definition of an HTTP endpoint, method, URL, headers, etc. WhereA
is extracted from the request.response[B]
: The result of arequest
, and encoders specific toT
.service
: Monadic function whereA => M[B]
, such that a request providesA
and the responseB
. (For now avoid focusing onM
, the key is providing a function that acceptsA
and returnsB
).- documentation: Can be produced from any
ServiceDefinition
- "server": Produces a "runnable" HTTP service and a client.
John spent some time focused on going through his thinking on what is necessary to solve this problem and why other problems have failed in the past. I highly suggest reading through redeyes and the README is a great place to start.
Balance is crucial to this effort. Previous efforts with Parsers and Functions were unable to meet these goals. Functions and Parser both compose sufficiently well to build a ServiceDefinition
but the semantics of that definition are lost and cannot be inspected. The inspection is necessary for documentation and client generation (key insight).
I think that John will be walking us through some more of the high level design work necessary to get the balance correct. I suspect that Applicative Functors
will be very relevant to our project. These types will allow us to "inspect" any part of a ServiceDefinition
and produce documentation and client in a type safe manner.