All Downloads are FREE. Search and download functionalities are using the official Maven repository.

modules.BakuModuleConfiguration.kt Maven / Gradle / Ivy

There is a newer version: 0.9.27
Show newest version
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}")
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy