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

com.papsign.ktor.openapigen.route.Functions.kt Maven / Gradle / Ivy

package com.papsign.ktor.openapigen.route

import com.papsign.ktor.openapigen.APITag
import com.papsign.ktor.openapigen.annotations.Path
import com.papsign.ktor.openapigen.content.type.ContentTypeProvider
import com.papsign.ktor.openapigen.getKType
import com.papsign.ktor.openapigen.modules.handlers.RequestHandlerModule
import com.papsign.ktor.openapigen.modules.handlers.ResponseHandlerModule
import com.papsign.ktor.openapigen.modules.registerModule
import com.papsign.ktor.openapigen.route.modules.HttpMethodProviderModule
import com.papsign.ktor.openapigen.route.modules.PathProviderModule
import io.ktor.http.HttpMethod
import io.ktor.server.routing.HttpMethodRouteSelector
import io.ktor.server.routing.createRouteFromPath
import io.ktor.util.KtorDsl
import kotlin.reflect.KType
import kotlin.reflect.KTypeProjection
import kotlin.reflect.KVariance
import kotlin.reflect.full.createType
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.starProjectedType
import kotlin.reflect.jvm.jvmErasure
import kotlin.reflect.typeOf

fun > T.route(path: String): T {
    return child(ktorRoute.createRouteFromPath(path)).apply {
        provider.registerModule(PathProviderModule(path))
    }
}

/**
 * Creates a new route matching the specified [path]
 */
@KtorDsl
inline fun > TRoute.route(path: String, crossinline fn: TRoute.() -> Unit) {
    route(path).fn()
}

fun > TRoute.method(method: HttpMethod): TRoute {
    return child(ktorRoute.createChild(HttpMethodRouteSelector(method))).apply {
        provider.registerModule(HttpMethodProviderModule(method))
    }
}

/**
 * Creates a new route matching the specified [method]
 */
@KtorDsl
inline fun > TRoute.method(method: HttpMethod, crossinline fn: TRoute.() -> Unit) {
    method(method).fn()
}

fun > TRoute.provider(vararg content: ContentTypeProvider): TRoute {
    return child().apply {
        content.forEach {
            provider.registerModule(it)
        }
    }
}

/**
 * Creates a new route matching the specified [content]
 */
@KtorDsl
inline fun > TRoute.provider(vararg content: ContentTypeProvider, crossinline fn: TRoute.() -> Unit) {
    provider(*content).fn()
}

/**
 * Applies a tag to all children of this route.
 * Parameter [tag] should be an enum that inherits from [APITag], check [APITag] description for
 * an explanation.
 *
 * @param tag the tag to apply
 * @return the same route that received the call to chain multiple calls
 */
fun > TRoute.tag(tag: APITag): TRoute {
    return child().apply {
        provider.registerModule(TagModule(listOf(tag)))
    }
}


/**
 * This method assigns an OpenAPI [tag] too all child routes defined inside [fn].
 * Parameter [tag] should be an enum that inherits from [APITag], check [APITag] description for an
 * explanation.
 *
 * Usage example:
 *
 *  // Defined tags
 *  enum class Tags(override val description: String) : APITag {
 *      EXAMPLE("Wow this is a tag?!")
 *  }
 *
 *  ...
 *  apiRouting {
 *      route("examples") {
 *          tag(Tags.EXAMPLE) { // <-- Applies the tag here
 *              route("getTextData").get { params ->
 *                  respond(StringResponse(params.a))
 *              }
 *              // Multiple routes can be specified here
 *          }
 *      }
 *  }
 *  ...
 *
 * @param tag the tag to apply
 * @param fn the block where the sub routes are defined
 */
@KtorDsl
inline fun > TRoute.tag(tag: APITag, crossinline fn: TRoute.() -> Unit) {
    tag(tag).fn()
}

inline fun > TRoute.preHandle(
    exampleResponse: TResponse? = null,
    exampleRequest: TRequest? = null,
    noinline handle: TRoute.() -> Unit
) {
    preHandle(
        typeOf(),
        typeOf(),
        typeOf(),
        exampleResponse,
        exampleRequest,
        handle
    )
}

// hide this function from public api as it can be "misused" easily but make it accessible to inlined functions from this package
@PublishedApi
internal fun > TRoute.preHandle(
    pType: KType,
    rType: KType,
    bType: KType,
    exampleResponse: TResponse? = null,
    exampleRequest: TRequest? = null,
    handle: TRoute.() -> Unit
) {
    val path = pType.jvmErasure.findAnnotation()
    val new = if (path != null) child(ktorRoute.createRouteFromPath(path.path)) else child()
    new.apply {
        provider.registerModule(
            RequestHandlerModule.create(
                bType,
                exampleRequest
            ),
            RequestHandlerModule::class.createType(listOf(KTypeProjection(KVariance.INVARIANT, bType)))
        )
        provider.registerModule(
            ResponseHandlerModule.create(
                rType,
                exampleResponse
            ),
            ResponseHandlerModule::class.createType(listOf(KTypeProjection(KVariance.INVARIANT, rType)))
        )
        if (path != null) {
            provider.registerModule(PathProviderModule(path.path))
        }
        handle()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy