diff --git a/web/backend/src/main/kotlin/dev/kordex/extra/web/WebRegistries.kt b/web/backend/src/main/kotlin/dev/kordex/extra/web/WebRegistries.kt new file mode 100644 index 0000000000..388a10eb08 --- /dev/null +++ b/web/backend/src/main/kotlin/dev/kordex/extra/web/WebRegistries.kt @@ -0,0 +1,50 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package dev.kordex.extra.web + +import dev.kordex.extra.web.pages.navigation.NavigationRegistry +import dev.kordex.extra.web.routes.RouteRegistry +import dev.kordex.extra.web.websockets.WebsocketRegistry + +public class WebRegistries { + public lateinit var navigation: NavigationRegistry + private set + + public lateinit var routes: RouteRegistry + private set + + public lateinit var websockets: WebsocketRegistry + private set + + public fun setup() { + if (!this::navigation.isInitialized) { + navigation = NavigationRegistry() + } + + if (!this::routes.isInitialized) { + routes = RouteRegistry() + } + + if (!this::websockets.isInitialized) { + websockets = WebsocketRegistry() + } + } + + public suspend fun teardown() { + if (this::navigation.isInitialized) { + navigation.removeAll() + } + + if (this::routes.isInitialized) { + routes.removeAll() + } + + if (this::websockets.isInitialized) { + websockets.removeAll() + } + } +} diff --git a/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/ExtensionNavigation.kt b/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/ExtensionNavigation.kt index 0c09614cf2..302c707334 100644 --- a/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/ExtensionNavigation.kt +++ b/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/ExtensionNavigation.kt @@ -12,7 +12,7 @@ public class ExtensionNavigation( public val extension: String, public val icon: Identifier, - public val setup: () -> Unit + public val setup: ExtensionNavigation.() -> Unit ) { public val navigation: MutableList = mutableListOf() diff --git a/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/NavigationItem.kt b/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/NavigationItem.kt index ef06b5094c..8dd17d657f 100644 --- a/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/NavigationItem.kt +++ b/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/NavigationItem.kt @@ -13,7 +13,7 @@ import kotlinx.serialization.Serializable public data class NavigationItem( public val name: String, public val icon: Identifier, - public val page: String?, + public val page: String?, // TODO: Page objects? public val children: MutableList = mutableListOf(), ) { public class Builder { diff --git a/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/NavigationRegistry.kt b/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/NavigationRegistry.kt index 5d04b5fb98..d79afa12a6 100644 --- a/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/NavigationRegistry.kt +++ b/web/backend/src/main/kotlin/dev/kordex/extra/web/pages/navigation/NavigationRegistry.kt @@ -7,5 +7,23 @@ package dev.kordex.extra.web.pages.navigation public class NavigationRegistry { - public val leftItems: MutableList = mutableListOf() + public val extensions: MutableMap = mutableMapOf() + + public fun add(navigation: ExtensionNavigation) { + if (navigation.extension in extensions) { + error("Navigation for ${navigation.extension} is already registered.") + } + + extensions[navigation.extension] = navigation + } + + public fun remove(navigation: ExtensionNavigation): ExtensionNavigation? = + remove(navigation.extension) + + public fun remove(extension: String): ExtensionNavigation? = + extensions.remove(extension) + + public fun removeAll() { + extensions.clear() + } } diff --git a/web/backend/src/main/kotlin/dev/kordex/extra/web/server/WebServer.kt b/web/backend/src/main/kotlin/dev/kordex/extra/web/server/WebServer.kt index 826dd75200..0f720d5217 100644 --- a/web/backend/src/main/kotlin/dev/kordex/extra/web/server/WebServer.kt +++ b/web/backend/src/main/kotlin/dev/kordex/extra/web/server/WebServer.kt @@ -8,11 +8,10 @@ package dev.kordex.extra.web.server import com.kotlindiscord.kord.extensions.ExtensibleBot import com.kotlindiscord.kord.extensions.koin.KordExKoinComponent +import dev.kordex.extra.web.WebRegistries import dev.kordex.extra.web.config.WebServerConfig import dev.kordex.extra.web.events.WebServerStartEvent import dev.kordex.extra.web.events.WebServerStopEvent -import dev.kordex.extra.web.routes.RouteRegistry -import dev.kordex.extra.web.websockets.WebsocketRegistry import io.ktor.server.engine.* import io.ktor.server.netty.* import kotlinx.coroutines.launch @@ -21,8 +20,7 @@ import org.koin.core.component.inject public class WebServer(internal val config: WebServerConfig) : KordExKoinComponent { private val bot: ExtensibleBot by inject() - public val routeRegistry: RouteRegistry = RouteRegistry() - public val wsRegistry: WebsocketRegistry = WebsocketRegistry() + public val registries: WebRegistries = WebRegistries() public var running: Boolean = false private set @@ -51,8 +49,7 @@ public class WebServer(internal val config: WebServerConfig) : KordExKoinCompone } public suspend fun stop() { - routeRegistry.removeAll() - wsRegistry.removeAll() + registries.teardown() server.stop( gracePeriodMillis = 0, diff --git a/web/backend/src/main/kotlin/dev/kordex/extra/web/server/_Routing.kt b/web/backend/src/main/kotlin/dev/kordex/extra/web/server/_Routing.kt index 2675816e6d..20f978ea2a 100644 --- a/web/backend/src/main/kotlin/dev/kordex/extra/web/server/_Routing.kt +++ b/web/backend/src/main/kotlin/dev/kordex/extra/web/server/_Routing.kt @@ -62,37 +62,37 @@ public fun WebServer.configureRouting(app: Application, config: WebServerConfig) route("/api/e/{path...}") { delete { - routeRegistry.handle(Verb.DELETE, this) + registries.routes.handle(Verb.DELETE, this) } get { - routeRegistry.handle(Verb.GET, this) + registries.routes.handle(Verb.GET, this) } head { - routeRegistry.handle(Verb.HEAD, this) + registries.routes.handle(Verb.HEAD, this) } options { - routeRegistry.handle(Verb.OPTIONS, this) + registries.routes.handle(Verb.OPTIONS, this) } patch { - routeRegistry.handle(Verb.PATCH, this) + registries.routes.handle(Verb.PATCH, this) } post { - routeRegistry.handle(Verb.POST, this) + registries.routes.handle(Verb.POST, this) } put { - routeRegistry.handle(Verb.PUT, this) + registries.routes.handle(Verb.PUT, this) } } route("/ws/e/{path...}") { webSocket { - wsRegistry.handle(this) + registries.websockets.handle(this) } } diff --git a/web/backend/src/main/kotlin/dev/kordex/extra/web/utils/_Extension.kt b/web/backend/src/main/kotlin/dev/kordex/extra/web/utils/_Extension.kt index f9f58345bc..46e83e154e 100644 --- a/web/backend/src/main/kotlin/dev/kordex/extra/web/utils/_Extension.kt +++ b/web/backend/src/main/kotlin/dev/kordex/extra/web/utils/_Extension.kt @@ -8,12 +8,14 @@ package dev.kordex.extra.web.utils import com.kotlindiscord.kord.extensions.events.EventContext import dev.kordex.extra.web.events.WebServerStartEvent +import dev.kordex.extra.web.pages.navigation.ExtensionNavigation import dev.kordex.extra.web.routes.Route +import dev.kordex.extra.web.types.Identifier import dev.kordex.extra.web.websockets.WebsocketBuilder import dev.kordex.extra.web.websockets.WebsocketBuilderFun -public fun EventContext.route(route: Route) { - if (!event.server.routeRegistry.add(route)) { +public fun EventContext.apiRoute(route: Route) { + if (!event.server.registries.routes.add(route)) { error("Route at ${route.path} for extension ${eventHandler.extension.name} already exists.") } } @@ -21,7 +23,15 @@ public fun EventContext.route(route: Route) { public fun EventContext.websocket(path: String, body: WebsocketBuilderFun) { val socketBuilder = WebsocketBuilder(eventHandler.extension.name, body) - if (!event.server.wsRegistry.add(path, socketBuilder)) { + if (!event.server.registries.websockets.add(path, socketBuilder)) { error("Websocket at $path for extension ${eventHandler.extension.name} already exists.") } } + +public fun EventContext.navigation(icon: Identifier, setup: ExtensionNavigation.() -> Unit) { + val navigation = ExtensionNavigation(eventHandler.extension.name, icon, setup) + + navigation.setup() + + // TODO: Register! +}