Each contract block will current produce a single ...
# http4k
d
Each contract block will current produce a single swagger file. Because of the setup of the DSL, you can't extract them as a sub contract block in the same way that you can with a standard routes block. But you can nest contract blocks inside standard routes blocks (and routes blocks can be composed) to create a tree structure where some of the routes are covered by a contract and some aren't / we do this in the example by combining the API contract with static routing and the website routes.
n
In my case I have
/users
which has like 12 routes on top of it
/organizations
which has 10
/workspaces
that has 10 And I could make one giant chain of
routes += ...
* 32 But I was hoping to do that only 3 times and have each of those nested route sets in separate files, but still produce a single Swagger file
d
you could combine them into lists and combine the lists..
(we do this with versioned routes (so we have objects creating lists of /v1 and a /v2 routes)
n
Oooooo that’s not a bad idea. Me gusta.
Copy code
"/api/v1" bind contract {
    renderer = OpenApi(ApiInfo("My great API", "v1.0"), Jackson)
    descriptionPath = "/swagger.json"
    security = AuthSecurity(::authFilter, contexts)
    for (route in organizationsRoutes) {
        routes += route(contexts)
    }
},
it looks terrible in a Slack thread, but since each route takes the
RequestContexts
object, this is the only way i could find to do it
d
where route is
(RequestContext) -> ContractRoute
? looks fair enough
you could also do it with a map for l33t functional skillz:
routes.map { it(contexts) }
n
oh man, that’s why i asked this question: https://kotlinlang.slack.com/archives/C0922A726/p1556047869115400
routes
doesn’t seem to have a
.map
option
I assume because
Appendable
doesn’t inherit from any of the standard Kotlin collection types
d
sorry - it should be:
routes += organizationsRoutes.map { it(contexts) }
(Appendable does have:
Copy code
operator fun plusAssign(t: Collection<T>) { all += t }
) 🙂
as an aside, applying a list of functions to a particular value is quite a neat trick:
Copy code
listOf(::addOne, ::addTwo, ::addThree).fold(1, { acc, next -> next(acc) })
n
Mind blown.
I didn’t realize that
.map
had a
it
available
d
once of the nice thing about Kotlin is that it's very consistent, for example:
Copy code
data class Age(val i: Int)
    val ages: List<Age> = listOf(1, 2, 3).map(::Age)
because the constructor is just another function reference...