arrow-ktor
arrow-ktor copied to clipboard
Extracting Spine's Arrow helpers to this repository
Spine is an alpha-quality library for declaring Ktor endpoints in common code, with no code generation etc:
object Api : RootResource("v1")
object Users : StaticResource("users", parent = Api) {
class ListParameters(data: ParameterStorage) : Parameters(data) {
val includeInactive by parameter(default = true)
}
val list by get()
.parameters(::ListParameters)
.response<User>()
val create by post()
.request<User>()
.response<User>()
}
// Server-side
routing {
route(Users.create) {
require(!users.exists(body.email)) { "A user already exists with this email" }
respond(users.create(body))
}
}
// Client-side
client.request(Users.create, User("…", "…"))
Of course, I want Spine to play well with Arrow Core. To achieve this, I have a few helpers that look like:
// Server-side
routing {
route(Users.create) {
raise { // enter the world of Raise
ensure(!users.exists(body.email)) { HttpFailure("A user already exists with this email", HttpStatusCode.UnprocessableEntity) }
…
}
}
}
This helper is available standalone without the rest of Spine (dev.opensavvy.spine:arrow-server-independent).
Since you're starting development of a proper Ktor/Arrow integration, I think it would be beneficial that this part was extracted to your repository. Since both libraries are almost equivalent, I can almost replace mine by yours and be done with it.
The main difference is the Raise receiver… Mine is
class HttpFailure(
val body: Any,
val code: HttpStatusCode,
val type: TypeInfo,
)
inline fun <reified Out : Any> HttpFailure(
body: Out,
code: HttpStatusCode,
) = HttpFailure(body, code, typeInfo<Out>())
(source)
whereas, this library allows raising the content and the status code separately:
suspend context(Raise<HttpStatusCode>, Raise<OutgoingContent>) PipelineContext<Unit, ApplicationCall>.() -> Unit
I'm curious, why this choice? I'm not sure I understand what benefits this brings, nor how would it be used.