modules.BakuModuleConfiguration.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of baku Show documentation
Show all versions of baku Show documentation
helps you focus your REST API back-end on the business logic
package com.github.fluidsonic.baku
import com.github.fluidsonic.fluid.json.JSONCodecProvider
import com.github.fluidsonic.fluid.json.JSONEncoder
import io.ktor.application.Application
import io.ktor.http.HttpMethod
import io.ktor.routing.Route
import io.ktor.routing.method
import io.ktor.routing.route
import io.ktor.util.pipeline.ContextDsl
import kotlinx.coroutines.channels.ReceiveChannel
import kotlin.reflect.KClass
class BakuModuleConfiguration internal constructor(
internal val module: BakuModule
) {
@PublishedApi
internal val commands = Commands()
@PublishedApi
internal val entities = Entities()
internal val additionalResponseEncodings: MutableList.() -> Unit> = mutableListOf()
internal val bsonCodecProviders: MutableList> = mutableListOf()
internal val commandRoutes: MutableList> = mutableListOf()
internal val customConfigurations: MutableList Unit> = mutableListOf()
internal val idFactories: MutableSet> = mutableSetOf()
internal val jsonCodecProviders: MutableList> = mutableListOf()
internal val routeConfigurations: MutableList Unit> = mutableListOf()
internal val routeWrappers: MutableList Unit) -> Route> = mutableListOf()
internal val routedCommandNames: HashSet = hashSetOf()
fun bson(vararg providers: BSONCodecProvider) {
bsonCodecProviders += providers
}
inline fun commands(configure: Commands.() -> Unit) {
commands.configure()
}
fun custom(configure: Application.() -> Unit) {
customConfigurations += configure
}
inline fun entities(configure: Entities.() -> Unit) {
entities.configure()
}
fun ids(vararg factories: EntityId.Factory<*>) {
idFactories += factories
}
fun json(vararg providers: JSONCodecProvider) {
jsonCodecProviders += providers
}
fun additionalResponseEncoding(encode: JSONEncoder.() -> Unit) {
additionalResponseEncodings += encode
}
@ContextDsl
fun routes(configure: Route.() -> Unit) {
routeConfigurations += configure
}
fun wrapAllRoutes(wrapper: Route.(next: Route.() -> Unit) -> Route) {
routeWrappers += wrapper
}
private fun Route.addRoute(method: HttpMethod, commandFactory: BakuCommandFactory) {
method(method) {
handle(commandFactory = commandFactory)
}
}
private fun Route.addRoute(method: HttpMethod, path: String, commandFactory: BakuCommandFactory) =
route(path) {
addRoute(method = method, commandFactory = commandFactory)
}
@ContextDsl
fun Route.delete(path: String, commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Delete, path = path, commandFactory = commandFactory)
@ContextDsl
fun Route.delete(commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Delete, commandFactory = commandFactory)
@ContextDsl
fun Route.get(path: String, commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Get, path = path, commandFactory = commandFactory)
@ContextDsl
fun Route.get(commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Get, commandFactory = commandFactory)
@ContextDsl
fun Route.head(path: String, commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Head, path = path, commandFactory = commandFactory)
@ContextDsl
fun Route.head(commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Head, commandFactory = commandFactory)
@ContextDsl
fun Route.post(path: String, commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Post, path = path, commandFactory = commandFactory)
@ContextDsl
fun Route.post(commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Post, commandFactory = commandFactory)
@ContextDsl
private fun Route.handle(commandFactory: BakuCommandFactory) {
commandRoutes += BakuCommandRoute(
factory = commandFactory,
route = this
)
}
@ContextDsl
fun Route.options(path: String, commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Options, path = path, commandFactory = commandFactory)
@ContextDsl
fun Route.options(commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Options, commandFactory = commandFactory)
@ContextDsl
fun Route.patch(path: String, commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Patch, path = path, commandFactory = commandFactory)
@ContextDsl
fun Route.patch(commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Patch, commandFactory = commandFactory)
@ContextDsl
fun Route.put(path: String, commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Put, path = path, commandFactory = commandFactory)
@ContextDsl
fun Route.put(commandFactory: BakuCommandFactory) =
addRoute(method = HttpMethod.Put, commandFactory = commandFactory)
inner class Commands internal constructor() {
internal val handlers: MutableList> = mutableListOf()
operator fun BakuCommandFactory.invoke(
handler: Transaction.() -> (suspend (command: Command) -> Result)
) {
handlers += BakuCommandHandler(
factory = this,
handler = handler
)
}
}
inner class Entities internal constructor() {
@PublishedApi
internal val resolvers: MutableMap, suspend Transaction.(ids: Set) -> ReceiveChannel> = mutableMapOf()
inline fun resolve(noinline resolver: suspend Transaction.(ids: Set) -> ReceiveChannel) {
@Suppress("UNCHECKED_CAST")
if (resolvers.putIfAbsent(Id::class, resolver as suspend Transaction.(ids: Set) -> ReceiveChannel) != null) {
error("Cannot register multiple entity resolvers for ${Id::class}")
}
}
}
}