From bc8fd8b0f287ebbe9b58522e78575c27f2e68ffc Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 6 Oct 2023 01:25:11 +0100 Subject: [PATCH] feature: Guild setup and default loading --- .gitignore | 4 +- app/src/main/kotlin/Application.kt | 69 ++++++++++++++----- .../kotlin/controller/ApiGuildController.kt | 49 +++++++++++++ .../main/kotlin/database/entity/DocsEntity.kt | 4 +- app/src/main/kotlin/defaults/Defaults.kt | 49 +++++++++++++ .../main/kotlin/meilisearch/MeiliClient.kt | 21 +++--- .../main/kotlin/meilisearch/MeiliPlugin.kt | 8 ++- app/src/main/kotlin/project/Projects.kt | 65 +++++++++++++++++ app/src/main/resources/log4j2.xml | 1 + .../src/main/kotlin/resource/ApiResources.kt | 31 ++++++--- .../main/kotlin/renderer/ContentBuilder.kt | 2 +- .../src/main/kotlin/renderer/JsonRenderer.kt | 33 +++++---- .../kotlin/renderer/ext/AnnotationsExt.kt | 14 ++-- .../kotlin/renderer/ext/DocumentationExt.kt | 24 +++---- .../src/main/kotlin/renderer/ext/DokkaExt.kt | 8 +-- .../src/main/kotlin/renderer/ext/TypesExt.kt | 16 ++--- gradle/libs.versions.toml | 14 +++- serializable/src/main/kotlin/api/ApiGuild.kt | 11 +++ .../{serializable => elements}/ClassLike.kt | 12 +++- .../Documentation.kt | 28 ++++---- .../Serializable.kt | 12 +++- .../SerializableAnnotation.kt | 2 +- .../SerializableMember.kt | 47 ++++++++++++- .../SerializableType.kt | 2 +- .../kotlin/{serializable => elements}/With.kt | 2 +- 25 files changed, 413 insertions(+), 115 deletions(-) create mode 100644 app/src/main/kotlin/controller/ApiGuildController.kt create mode 100644 app/src/main/kotlin/defaults/Defaults.kt create mode 100644 app/src/main/kotlin/project/Projects.kt create mode 100644 serializable/src/main/kotlin/api/ApiGuild.kt rename serializable/src/main/kotlin/{serializable => elements}/ClassLike.kt (96%) rename serializable/src/main/kotlin/{serializable => elements}/Documentation.kt (87%) rename serializable/src/main/kotlin/{serializable => elements}/Serializable.kt (93%) rename serializable/src/main/kotlin/{serializable => elements}/SerializableAnnotation.kt (98%) rename serializable/src/main/kotlin/{serializable => elements}/SerializableMember.kt (83%) rename serializable/src/main/kotlin/{serializable => elements}/SerializableType.kt (98%) rename serializable/src/main/kotlin/{serializable => elements}/With.kt (98%) diff --git a/.gitignore b/.gitignore index 31fe9ed..728449c 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,7 @@ cmake-build-*/ # Mongo Explorer plugin .idea/**/mongoSettings.xml -# File-based project format +# File-based defaults format *.iws # IntelliJ @@ -107,7 +107,7 @@ gradle-app.setting # Avoid ignore Gradle wrappper properties !gradle-wrapper.properties -# Cache of project +# Cache of defaults .gradletasknamecache # Eclipse Gradle plugin generated files diff --git a/app/src/main/kotlin/Application.kt b/app/src/main/kotlin/Application.kt index 7a9948f..1095bc9 100644 --- a/app/src/main/kotlin/Application.kt +++ b/app/src/main/kotlin/Application.kt @@ -23,42 +23,79 @@ */ package dev.triumphteam.docsly -import com.zaxxer.hikari.HikariDataSource import dev.triumphteam.docsly.config.createOrGetConfig +import dev.triumphteam.docsly.controller.apiGuild +import dev.triumphteam.docsly.defaults.Defaults import dev.triumphteam.docsly.meilisearch.Meili -import dev.triumphteam.docsly.resource.Api +import dev.triumphteam.docsly.project.Projects +import io.ktor.serialization.kotlinx.json.json import io.ktor.server.application.Application import io.ktor.server.application.install +import io.ktor.server.cio.CIO import io.ktor.server.engine.embeddedServer -import io.ktor.server.netty.Netty +import io.ktor.server.plugins.callloging.CallLogging +import io.ktor.server.plugins.contentnegotiation.ContentNegotiation +import io.ktor.server.request.path import io.ktor.server.resources.Resources -import io.ktor.server.resources.get -import io.ktor.server.routing.get import io.ktor.server.routing.routing -import org.jetbrains.exposed.sql.Database -import org.jetbrains.exposed.sql.transactions.transaction +import kotlinx.serialization.Serializable +import org.slf4j.event.Level private val config = createOrGetConfig() public fun main() { - embeddedServer(Netty, port = config.port, host = config.host, module = Application::module).start(wait = true) + embeddedServer(CIO, port = config.port, host = config.host, module = Application::module).start(wait = true) } public fun Application.module() { - Database.connect(HikariDataSource(config.postgres.toHikariConfig())) + // Database.connect(HikariDataSource(config.postgres.toHikariConfig())) + + /*install(CORS) { + anyHost() + allowHeader(HttpHeaders.ContentType) + allowMethod(HttpMethod.Get) + allowMethod(HttpMethod.Post) + }*/ - install(Meili) { config(config.meili) } install(Resources) + install(ContentNegotiation) { + json() + } + install(CallLogging) { + level = Level.DEBUG + filter { call -> call.request.path().startsWith("/") } + } + + install(Meili) { from(config.meili) } + install(Defaults) + install(Projects) routing { - get { + + // Setup guild api/routing + apiGuild() + + /*get { // Here you handle the "api/{index}/search" endpoint // Getting the index passed - // search(it.parent.index, "") - transaction { - // DocDao.find { DocsTable.name eq "Ass" }.firstOrNull() - } - } + *//*val test = index("test").searchFull("e", null) + // val test = search>(it.parent.index, "e") + println(test)*//* + + index("test").addDocuments( + listOf( + Test("Hello"), + Test("there"), + Test("thing"), + ), + primaryKey = "boy", + ) + + call.respond(HttpStatusCode.Accepted) + }*/ } } + +@Serializable +public data class Test(val boy: String) diff --git a/app/src/main/kotlin/controller/ApiGuildController.kt b/app/src/main/kotlin/controller/ApiGuildController.kt new file mode 100644 index 0000000..868e2df --- /dev/null +++ b/app/src/main/kotlin/controller/ApiGuildController.kt @@ -0,0 +1,49 @@ +package dev.triumphteam.docsly.controller + +import dev.triumphteam.docsly.api.GuildSetupRequest +import dev.triumphteam.docsly.defaults.Defaults +import dev.triumphteam.docsly.project.Projects +import dev.triumphteam.docsly.resource.GuildApi +import io.ktor.http.HttpStatusCode +import io.ktor.server.application.call +import io.ktor.server.application.plugin +import io.ktor.server.request.receive +import io.ktor.server.resources.post +import io.ktor.server.response.respond +import io.ktor.server.routing.Routing + +public fun Routing.apiGuild() { + + val defaults = plugin(Defaults) + val projects = plugin(Projects) + + post { setup -> + val guild = setup.parent.guild + val setupDefaults = call.receive().defaults + + val defaultProjects = defaults.defaultProjects() + + // Validate data + setupDefaults.forEach { (project, versions) -> + val defaultVersions = defaultProjects[project] ?: run { + call.respond(HttpStatusCode.BadRequest, "Invalid default project '$project'.") + return@post + } + + versions.forEach { version -> + // TODO: Figure better way to get version, and not use folder name + val replaced = version.replace(".", "_") + if (replaced !in defaultVersions) { + call.respond(HttpStatusCode.BadRequest, "Invalid default project version '$version' for project '$project'.") + return@post + } + } + } + + // If it goes well nothing will throw and it'll work well! + projects.setupProjects(guild, setupDefaults) + + // So we return "accepted" + call.respond(HttpStatusCode.Accepted) + } +} diff --git a/app/src/main/kotlin/database/entity/DocsEntity.kt b/app/src/main/kotlin/database/entity/DocsEntity.kt index f870d01..cdd8119 100644 --- a/app/src/main/kotlin/database/entity/DocsEntity.kt +++ b/app/src/main/kotlin/database/entity/DocsEntity.kt @@ -1,7 +1,7 @@ package dev.triumphteam.docsly.database.entity import dev.triumphteam.docsly.database.exposed.serializable -import dev.triumphteam.docsly.serializable.DocElement +import dev.triumphteam.docsly.elements.DocElement import org.jetbrains.exposed.dao.LongEntity import org.jetbrains.exposed.dao.LongEntityClass import org.jetbrains.exposed.dao.id.EntityID @@ -10,7 +10,7 @@ import org.jetbrains.exposed.sql.Column public object DocsTable : IdTable() { public val guild: Column = long("guild_id").uniqueIndex() - public val project: Column = text("project").uniqueIndex() + public val project: Column = text("defaults").uniqueIndex() public val version: Column = text("version").uniqueIndex() public val location: Column = text("location").uniqueIndex() public val doc: Column = serializable("doc") diff --git a/app/src/main/kotlin/defaults/Defaults.kt b/app/src/main/kotlin/defaults/Defaults.kt new file mode 100644 index 0000000..52639b1 --- /dev/null +++ b/app/src/main/kotlin/defaults/Defaults.kt @@ -0,0 +1,49 @@ +package dev.triumphteam.docsly.defaults + +import io.ktor.server.application.Application +import io.ktor.server.application.BaseApplicationPlugin +import io.ktor.util.AttributeKey +import java.io.File +import java.io.FileNotFoundException +import java.nio.file.Path +import kotlin.io.path.Path +import kotlin.io.path.isDirectory +import kotlin.io.path.notExists + +public class Defaults { + + // Move to separate repo + private val defaultsFolder: Path = Path("data/defaults") + private val defaults: Map> = defaultsFolder.toFile().listFiles()?.mapNotNull { project -> + if (!project.isDirectory) return@mapNotNull null + + val versions = project.listFiles()?.mapNotNull { version -> + if (!version.isDirectory) null else version.name + }?.toSet() ?: emptySet() + + project.name to versions + }?.toMap() ?: emptyMap() + + public fun defaultProjects(): Map> { + return defaults + } + + public fun resolve(project: String, version: String): File { + val folder = defaultsFolder.resolve("$project/$version") + if (folder.notExists() || !folder.isDirectory()) { + throw FileNotFoundException("Could not find file with path '${"$project/$version"}'") + } + + return folder.toFile().listFiles()?.find { it.name.endsWith(".json") } + ?: throw FileNotFoundException("Could not find json file for '${"$project/$version"}'") + } + + public companion object Plugin : BaseApplicationPlugin { + + override val key: AttributeKey = AttributeKey("defaults") + + override fun install(pipeline: Application, configure: Defaults.() -> Unit): Defaults { + return Defaults() + } + } +} diff --git a/app/src/main/kotlin/meilisearch/MeiliClient.kt b/app/src/main/kotlin/meilisearch/MeiliClient.kt index ed1b4de..c46c5fa 100644 --- a/app/src/main/kotlin/meilisearch/MeiliClient.kt +++ b/app/src/main/kotlin/meilisearch/MeiliClient.kt @@ -70,33 +70,35 @@ public class MeiliClient( public fun index( uid: String, primaryKey: String? = null, - searchableAttributes: List? = null, - ): Index = Index(uid, primaryKey, searchableAttributes) + ): Index = Index(uid, primaryKey) /** Representation of an index. Contains the needed operations with the index. */ public inner class Index( public val uid: String, public val primaryKey: String?, - private val searchableAttributes: List? = null, ) { /** Create the index. Success even if it already exists. */ public suspend fun create(): HttpResponse = client.post(Indexes()) { - setBody(Create(uid, primaryKey, searchableAttributes)) + contentType(ContentType.Application.Json) + setBody(Create(uid, primaryKey)) + }.also { + println(it) } /** Deletes the current index. Success even if it doesn't exist. */ public suspend fun delete(): HttpResponse = client.delete(Indexes.Uid(uid = uid)) /** Search for specific content in the index. */ - public suspend inline fun search(query: String, filter: Map): List { + public suspend inline fun search(query: String, filter: String?): List { return searchFull(query, filter).hits } /** [search] but returns all the data ([SearchResult]) provided by the search. */ - public suspend inline fun searchFull(query: String, filter: Map): SearchResult { + public suspend inline fun searchFull(query: String, filter: String?): SearchResult { // TODO: Handle errors. return client.post(Indexes.Uid.Search(Indexes.Uid(uid = uid))) { + contentType(ContentType.Application.Json) setBody(SearchRequest(query, filter)) }.body() } @@ -111,9 +113,11 @@ public class MeiliClient( } return client.post(Indexes.Uid.Documents(Indexes.Uid(uid = uid))) { - contentType(ContentType.Application.Json) // Json body + contentType(ContentType.Application.Json) parameter(PRIMARY_KEY_PARAM, pk) setBody(documents) + }.also { + println(it) } } @@ -168,7 +172,6 @@ public class MeiliClient( public data class Create( val uid: String, val primaryKey: String?, - val searchableAttributes: List?, ) /** Serializable class for the search result from end point. */ @@ -186,7 +189,7 @@ public class MeiliClient( @Serializable public data class SearchRequest( public val q: String, - public val filter: Map, + public val filter: String?, ) /** Serializable class for the swap end point. */ diff --git a/app/src/main/kotlin/meilisearch/MeiliPlugin.kt b/app/src/main/kotlin/meilisearch/MeiliPlugin.kt index bcb807e..ac03289 100644 --- a/app/src/main/kotlin/meilisearch/MeiliPlugin.kt +++ b/app/src/main/kotlin/meilisearch/MeiliPlugin.kt @@ -25,6 +25,7 @@ package dev.triumphteam.docsly.meilisearch import dev.triumphteam.docsly.config.MeiliConfig import io.ktor.http.URLProtocol +import io.ktor.serialization.Configuration import io.ktor.server.application.Application import io.ktor.server.application.ApplicationCall import io.ktor.server.application.BaseApplicationPlugin @@ -43,7 +44,7 @@ public class Meili(config: Configuration) { private var apiKey: String = "masterKey" private var protocol: URLProtocol = URLProtocol.HTTP - public fun config(config: MeiliConfig) { + public fun from(config: MeiliConfig) { host = config.host port = config.port apiKey = config.apiKey @@ -66,7 +67,10 @@ public class Meili(config: Configuration) { public suspend inline fun PipelineContext<*, ApplicationCall>.search( index: String, query: String, - filter: Map = emptyMap(), + filter: String? = null, ): List = with(this.application.plugin(Meili).client) { return index(index).search(query, filter) } + +public suspend inline fun PipelineContext<*, ApplicationCall>.index(index: String): MeiliClient.Index = + application.plugin(Meili).client.index(index) diff --git a/app/src/main/kotlin/project/Projects.kt b/app/src/main/kotlin/project/Projects.kt new file mode 100644 index 0000000..ec96cfd --- /dev/null +++ b/app/src/main/kotlin/project/Projects.kt @@ -0,0 +1,65 @@ +package dev.triumphteam.docsly.project + +import dev.triumphteam.docsly.defaults.Defaults +import dev.triumphteam.docsly.elements.DocElement +import dev.triumphteam.docsly.meilisearch.Meili +import dev.triumphteam.docsly.meilisearch.annotation.PrimaryKey +import io.ktor.server.application.Application +import io.ktor.server.application.BaseApplicationPlugin +import io.ktor.server.application.plugin +import io.ktor.util.AttributeKey +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json + +public class Projects(private val meili: Meili, private val defaults: Defaults) { + + public companion object Plugin : BaseApplicationPlugin { + + override val key: AttributeKey = AttributeKey("Projects") + + override fun install(pipeline: Application, configure: Projects.() -> Unit): Projects { + return Projects(pipeline.plugin(Meili), pipeline.plugin(Defaults)) + } + + public fun indexKeyFor(guild: String, project: String, version: String): String { + return "$guild:$project:$version" + } + } + + private val json = Json { + explicitNulls = false + ignoreUnknownKeys = true + } + + public suspend fun setupProjects(guild: String, projects: Map>) { + // transaction { + val mapped = projects.mapValues { (project, versions) -> + versions.associateWith { version -> + val jsonFile = defaults.resolve(project, version.replace(".", "_")) + json.decodeFromString>(jsonFile.readText()) + } + } + + runBlocking { + mapped.forEach { (project, versions) -> + versions.forEach { (version, docs) -> + meili.client.index(indexKeyFor(guild, project, version)).addDocuments( + docs.map { doc -> + IndexDocument(doc.location, doc.createReferences()) + } + ) + } + } + } + + // TODO: Postgres + // } + } +} + +@Serializable +public data class IndexDocument( + @PrimaryKey public val location: String, + public val references: List, +) diff --git a/app/src/main/resources/log4j2.xml b/app/src/main/resources/log4j2.xml index f6ff3df..65200b6 100644 --- a/app/src/main/resources/log4j2.xml +++ b/app/src/main/resources/log4j2.xml @@ -13,5 +13,6 @@ + diff --git a/common/src/main/kotlin/resource/ApiResources.kt b/common/src/main/kotlin/resource/ApiResources.kt index ea10d75..ebabde5 100644 --- a/common/src/main/kotlin/resource/ApiResources.kt +++ b/common/src/main/kotlin/resource/ApiResources.kt @@ -28,17 +28,32 @@ import kotlinx.serialization.Serializable /** Resource location for "/api". */ @Serializable -@Resource("/api") -public class Api { +@Resource("/api/guild") +public class GuildApi { - /** Resource location for "/api/[index]". */ + /** Resource location for "/api/[guild]". */ @Serializable - @Resource("{index}") - public class Index(public val parent: Api = Api(), public val index: String) { + @Resource("{guild}") + public class Guild(public val parent: GuildApi = GuildApi(), public val guild: String) { - /** Resource location for "/api/[index]/search". */ + /** Resource location for "/api/[guild]/setup". */ @Serializable - @Resource("/search") - public class Search(public val parent: Index) + @Resource("setup") + public class Setup(public val parent: Guild) + + /** Resource location for "/api/[guild]/[index]/[version]". *//* + @Serializable + @Resource("{project}/{version}") + public class Project( + public val parent: Guild, + public val index: String, + public val version: String, + ) { + + *//** Resource location for "/api/[guild]/[index]/[version]/search". *//* + @Serializable + @Resource("search") + public class Search(public val parent: Project) + }*/ } } diff --git a/dokka-plugin/src/main/kotlin/renderer/ContentBuilder.kt b/dokka-plugin/src/main/kotlin/renderer/ContentBuilder.kt index 4f6d0e5..be90c77 100644 --- a/dokka-plugin/src/main/kotlin/renderer/ContentBuilder.kt +++ b/dokka-plugin/src/main/kotlin/renderer/ContentBuilder.kt @@ -23,7 +23,7 @@ */ package dev.triumphteam.docsly.renderer -import dev.triumphteam.docsly.serializable.DocElement +import dev.triumphteam.docsly.elements.DocElement public class ContentBuilder { diff --git a/dokka-plugin/src/main/kotlin/renderer/JsonRenderer.kt b/dokka-plugin/src/main/kotlin/renderer/JsonRenderer.kt index 189a16a..097b461 100644 --- a/dokka-plugin/src/main/kotlin/renderer/JsonRenderer.kt +++ b/dokka-plugin/src/main/kotlin/renderer/JsonRenderer.kt @@ -35,22 +35,22 @@ import dev.triumphteam.docsly.renderer.ext.toPath import dev.triumphteam.docsly.renderer.ext.toSerialAnnotations import dev.triumphteam.docsly.renderer.ext.toSerialModifiers import dev.triumphteam.docsly.renderer.ext.toSerialType -import dev.triumphteam.docsly.serializable.ClassKind -import dev.triumphteam.docsly.serializable.ClassLike -import dev.triumphteam.docsly.serializable.Language -import dev.triumphteam.docsly.serializable.Modifier -import dev.triumphteam.docsly.serializable.SerializableAnnotationClass -import dev.triumphteam.docsly.serializable.SerializableClass -import dev.triumphteam.docsly.serializable.SerializableEnum -import dev.triumphteam.docsly.serializable.SerializableEnumEntry -import dev.triumphteam.docsly.serializable.SerializableFunction -import dev.triumphteam.docsly.serializable.SerializableInterface -import dev.triumphteam.docsly.serializable.SerializableObject -import dev.triumphteam.docsly.serializable.SerializablePackage -import dev.triumphteam.docsly.serializable.SerializableParameter -import dev.triumphteam.docsly.serializable.SerializableProperty -import dev.triumphteam.docsly.serializable.SerializableTypeAlias -import dev.triumphteam.docsly.serializable.SuperType +import dev.triumphteam.docsly.elements.ClassKind +import dev.triumphteam.docsly.elements.ClassLike +import dev.triumphteam.docsly.elements.Language +import dev.triumphteam.docsly.elements.Modifier +import dev.triumphteam.docsly.elements.SerializableAnnotationClass +import dev.triumphteam.docsly.elements.SerializableClass +import dev.triumphteam.docsly.elements.SerializableEnum +import dev.triumphteam.docsly.elements.SerializableEnumEntry +import dev.triumphteam.docsly.elements.SerializableFunction +import dev.triumphteam.docsly.elements.SerializableInterface +import dev.triumphteam.docsly.elements.SerializableObject +import dev.triumphteam.docsly.elements.SerializablePackage +import dev.triumphteam.docsly.elements.SerializableParameter +import dev.triumphteam.docsly.elements.SerializableProperty +import dev.triumphteam.docsly.elements.SerializableTypeAlias +import dev.triumphteam.docsly.elements.SuperType import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.coroutineScope @@ -106,7 +106,6 @@ public class JsonRenderer(context: DokkaContext) : Renderer, CoroutineScope { // Main json instance for serializing private val json = Json { - prettyPrint = true explicitNulls = false } diff --git a/dokka-plugin/src/main/kotlin/renderer/ext/AnnotationsExt.kt b/dokka-plugin/src/main/kotlin/renderer/ext/AnnotationsExt.kt index 29bc38e..687da2b 100644 --- a/dokka-plugin/src/main/kotlin/renderer/ext/AnnotationsExt.kt +++ b/dokka-plugin/src/main/kotlin/renderer/ext/AnnotationsExt.kt @@ -23,13 +23,13 @@ */ package dev.triumphteam.docsly.renderer.ext -import dev.triumphteam.docsly.serializable.AnnotationAnnotationArgument -import dev.triumphteam.docsly.serializable.AnnotationValueType -import dev.triumphteam.docsly.serializable.ArrayAnnotationArgument -import dev.triumphteam.docsly.serializable.LiteralAnnotationArgument -import dev.triumphteam.docsly.serializable.SerializableAnnotation -import dev.triumphteam.docsly.serializable.SerializableAnnotationArgument -import dev.triumphteam.docsly.serializable.TypedAnnotationArgument +import dev.triumphteam.docsly.elements.AnnotationAnnotationArgument +import dev.triumphteam.docsly.elements.AnnotationValueType +import dev.triumphteam.docsly.elements.ArrayAnnotationArgument +import dev.triumphteam.docsly.elements.LiteralAnnotationArgument +import dev.triumphteam.docsly.elements.SerializableAnnotation +import dev.triumphteam.docsly.elements.SerializableAnnotationArgument +import dev.triumphteam.docsly.elements.TypedAnnotationArgument import org.jetbrains.dokka.DokkaConfiguration import org.jetbrains.dokka.model.AnnotationParameterValue import org.jetbrains.dokka.model.AnnotationValue diff --git a/dokka-plugin/src/main/kotlin/renderer/ext/DocumentationExt.kt b/dokka-plugin/src/main/kotlin/renderer/ext/DocumentationExt.kt index 3e2f47d..4560fa8 100644 --- a/dokka-plugin/src/main/kotlin/renderer/ext/DocumentationExt.kt +++ b/dokka-plugin/src/main/kotlin/renderer/ext/DocumentationExt.kt @@ -23,18 +23,18 @@ */ package dev.triumphteam.docsly.renderer.ext -import dev.triumphteam.docsly.serializable.AuthorDocumentation -import dev.triumphteam.docsly.serializable.CustomDocumentation -import dev.triumphteam.docsly.serializable.DeprecatedDocumentation -import dev.triumphteam.docsly.serializable.DescriptionDocumentation -import dev.triumphteam.docsly.serializable.Documentation -import dev.triumphteam.docsly.serializable.ReceiverDocumentation -import dev.triumphteam.docsly.serializable.ReturnDocumentation -import dev.triumphteam.docsly.serializable.SampleDocumentation -import dev.triumphteam.docsly.serializable.SeeDocumentation -import dev.triumphteam.docsly.serializable.SinceDocumentation -import dev.triumphteam.docsly.serializable.ThrowsDocumentation -import dev.triumphteam.docsly.serializable.VersionDocumentation +import dev.triumphteam.docsly.elements.AuthorDocumentation +import dev.triumphteam.docsly.elements.CustomDocumentation +import dev.triumphteam.docsly.elements.DeprecatedDocumentation +import dev.triumphteam.docsly.elements.DescriptionDocumentation +import dev.triumphteam.docsly.elements.Documentation +import dev.triumphteam.docsly.elements.ReceiverDocumentation +import dev.triumphteam.docsly.elements.ReturnDocumentation +import dev.triumphteam.docsly.elements.SampleDocumentation +import dev.triumphteam.docsly.elements.SeeDocumentation +import dev.triumphteam.docsly.elements.SinceDocumentation +import dev.triumphteam.docsly.elements.ThrowsDocumentation +import dev.triumphteam.docsly.elements.VersionDocumentation import org.jetbrains.dokka.model.DParameter import org.jetbrains.dokka.model.Documentable import org.jetbrains.dokka.model.doc.Author diff --git a/dokka-plugin/src/main/kotlin/renderer/ext/DokkaExt.kt b/dokka-plugin/src/main/kotlin/renderer/ext/DokkaExt.kt index 17f95e9..f11f79a 100644 --- a/dokka-plugin/src/main/kotlin/renderer/ext/DokkaExt.kt +++ b/dokka-plugin/src/main/kotlin/renderer/ext/DokkaExt.kt @@ -24,10 +24,10 @@ package dev.triumphteam.docsly.renderer.ext import dev.triumphteam.docsly.KOTLIN_EXTENSION -import dev.triumphteam.docsly.serializable.Language -import dev.triumphteam.docsly.serializable.Modifier -import dev.triumphteam.docsly.serializable.Path -import dev.triumphteam.docsly.serializable.Visibility +import dev.triumphteam.docsly.elements.Language +import dev.triumphteam.docsly.elements.Modifier +import dev.triumphteam.docsly.elements.Path +import dev.triumphteam.docsly.elements.Visibility import org.jetbrains.dokka.DokkaConfiguration import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.AdditionalModifiers diff --git a/dokka-plugin/src/main/kotlin/renderer/ext/TypesExt.kt b/dokka-plugin/src/main/kotlin/renderer/ext/TypesExt.kt index 0eff686..6b9ec55 100644 --- a/dokka-plugin/src/main/kotlin/renderer/ext/TypesExt.kt +++ b/dokka-plugin/src/main/kotlin/renderer/ext/TypesExt.kt @@ -27,14 +27,14 @@ import dev.triumphteam.docsly.KOTLIN import dev.triumphteam.docsly.OBJECT import dev.triumphteam.docsly.PLUGIN_NAME import dev.triumphteam.docsly.WILD_CARD -import dev.triumphteam.docsly.serializable.BasicType -import dev.triumphteam.docsly.serializable.FunctionType -import dev.triumphteam.docsly.serializable.GenericProjection -import dev.triumphteam.docsly.serializable.GenericType -import dev.triumphteam.docsly.serializable.Nullability -import dev.triumphteam.docsly.serializable.SerializableType -import dev.triumphteam.docsly.serializable.StarType -import dev.triumphteam.docsly.serializable.TypeAliasType +import dev.triumphteam.docsly.elements.BasicType +import dev.triumphteam.docsly.elements.FunctionType +import dev.triumphteam.docsly.elements.GenericProjection +import dev.triumphteam.docsly.elements.GenericType +import dev.triumphteam.docsly.elements.Nullability +import dev.triumphteam.docsly.elements.SerializableType +import dev.triumphteam.docsly.elements.StarType +import dev.triumphteam.docsly.elements.TypeAliasType import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.annotations import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.modifiers import org.jetbrains.dokka.links.DriOfUnit diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3eb007c..2bf478e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,8 +33,12 @@ gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version. # Ktor server ktor-server-core = { module = "io.ktor:ktor-server-core-jvm", version.ref = "ktor" } -ktor-server-netty = { module = "io.ktor:ktor-server-netty-jvm", version.ref = "ktor" } +ktor-server-cio = { module = "io.ktor:ktor-server-cio-jvm", version.ref = "ktor" } +ktor-server-cors = { module = "io.ktor:ktor-server-cors", version.ref = "ktor" } ktor-server-resources = { module = "io.ktor:ktor-server-resources", version.ref = "ktor" } +ktor-server-negociation = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" } +ktor-server-call-logging = { module = "io.ktor:ktor-server-call-logging", version.ref = "ktor" } +ktor-server-call-logging-jvm = { module = "io.ktor:ktor-server-call-logging-jvm", version.ref = "ktor" } # Common ktor-resources = { module = "io.ktor:ktor-resources", version.ref = "ktor" } @@ -72,8 +76,12 @@ build-spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", vers [bundles] ktor-server = [ "ktor-server-core", - "ktor-server-netty", - "ktor-server-resources" + "ktor-server-cio", + "ktor-server-cors", + "ktor-server-resources", + "ktor-server-negociation", + "ktor-server-call-logging", + "ktor-server-call-logging-jvm" ] ktor-client = [ "ktor-client-core", diff --git a/serializable/src/main/kotlin/api/ApiGuild.kt b/serializable/src/main/kotlin/api/ApiGuild.kt new file mode 100644 index 0000000..dfb232a --- /dev/null +++ b/serializable/src/main/kotlin/api/ApiGuild.kt @@ -0,0 +1,11 @@ +package dev.triumphteam.docsly.api + +import kotlinx.serialization.Serializable + +/** + * Represents a guild setup request, containing a map of default projects and their versions for setup. + * + * @property defaults A map of default projects and their versions for setup, where the keys are strings and the values are lists of strings. + */ +@Serializable +public data class GuildSetupRequest(public val defaults: Map>) diff --git a/serializable/src/main/kotlin/serializable/ClassLike.kt b/serializable/src/main/kotlin/elements/ClassLike.kt similarity index 96% rename from serializable/src/main/kotlin/serializable/ClassLike.kt rename to serializable/src/main/kotlin/elements/ClassLike.kt index ecad3be..bdf087a 100644 --- a/serializable/src/main/kotlin/serializable/ClassLike.kt +++ b/serializable/src/main/kotlin/elements/ClassLike.kt @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package dev.triumphteam.docsly.serializable +package dev.triumphteam.docsly.elements import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -34,7 +34,15 @@ public sealed interface ClassLike : WithVisibility, WithAnnotations, WithModifiers, - WithExtraDocs + WithExtraDocs { + + override fun createReferences(): List { + return listOf( + name, + "${path.packagePath}.$name" + ) + } +} /** A serializable object that contains all information needed to describe a class. */ @Serializable diff --git a/serializable/src/main/kotlin/serializable/Documentation.kt b/serializable/src/main/kotlin/elements/Documentation.kt similarity index 87% rename from serializable/src/main/kotlin/serializable/Documentation.kt rename to serializable/src/main/kotlin/elements/Documentation.kt index 10a21c6..e85094b 100644 --- a/serializable/src/main/kotlin/serializable/Documentation.kt +++ b/serializable/src/main/kotlin/elements/Documentation.kt @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package dev.triumphteam.docsly.serializable +package dev.triumphteam.docsly.elements import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -29,7 +29,7 @@ import kotlinx.serialization.Serializable /** A [Documentation] simply has its display [String]. */ @Serializable public sealed interface Documentation { - public val comment: String + public val comment: String? } /** A [Documentation] that also contains a name. */ @@ -38,59 +38,59 @@ public sealed interface NamedDocumentation : Documentation, WithName /** Generally a description of a serializable. */ @Serializable @SerialName("DESCRIPTION") -public data class DescriptionDocumentation(override val comment: String) : Documentation +public data class DescriptionDocumentation(override val comment: String?) : Documentation /** Documentation of the `@author` tag. */ @Serializable @SerialName("AUTHOR") -public data class AuthorDocumentation(override val comment: String) : Documentation +public data class AuthorDocumentation(override val comment: String?) : Documentation /** Documentation of the `@version` tag. */ @Serializable @SerialName("VERSION") -public data class VersionDocumentation(override val comment: String) : Documentation +public data class VersionDocumentation(override val comment: String?) : Documentation /** Documentation of the `@since` tag. */ @Serializable @SerialName("SINCE") -public data class SinceDocumentation(override val comment: String) : Documentation +public data class SinceDocumentation(override val comment: String?) : Documentation /** Documentation of the `@see` tag. */ @Serializable @SerialName("SEE") -public data class SeeDocumentation(override val name: String, override val comment: String) : NamedDocumentation +public data class SeeDocumentation(override val name: String, override val comment: String?) : NamedDocumentation /** Documentation of the `@return` tag. */ @Serializable @SerialName("RETURN") -public data class ReturnDocumentation(override val comment: String) : Documentation +public data class ReturnDocumentation(override val comment: String?) : Documentation /** Documentation of the `@receiver` tag. */ @Serializable @SerialName("RECEIVER") -public data class ReceiverDocumentation(override val comment: String) : Documentation +public data class ReceiverDocumentation(override val comment: String?) : Documentation /** Documentation of the `@constructor` tag. */ @Serializable @SerialName("CONSTRUCTOR") -public data class ConstructorDocumentation(override val comment: String) : Documentation +public data class ConstructorDocumentation(override val comment: String?) : Documentation /** Documentation of the `@throws` tag. */ @Serializable @SerialName("THROWS") -public data class ThrowsDocumentation(override val name: String, override val comment: String) : NamedDocumentation +public data class ThrowsDocumentation(override val name: String, override val comment: String?) : NamedDocumentation /** Documentation of the `@sample` tag. */ @Serializable @SerialName("SAMPLE") -public data class SampleDocumentation(override val name: String, override val comment: String) : NamedDocumentation +public data class SampleDocumentation(override val name: String, override val comment: String?) : NamedDocumentation /** Documentation of the `@deprecated` tag. */ @Serializable @SerialName("DEPRECATED") -public data class DeprecatedDocumentation(override val comment: String) : Documentation +public data class DeprecatedDocumentation(override val comment: String?) : Documentation /** Documentation of a custom tag. */ @Serializable @SerialName("CUSTOM") -public data class CustomDocumentation(override val name: String, override val comment: String) : NamedDocumentation +public data class CustomDocumentation(override val name: String, override val comment: String?) : NamedDocumentation diff --git a/serializable/src/main/kotlin/serializable/Serializable.kt b/serializable/src/main/kotlin/elements/Serializable.kt similarity index 93% rename from serializable/src/main/kotlin/serializable/Serializable.kt rename to serializable/src/main/kotlin/elements/Serializable.kt index aa3d5c8..cb61817 100644 --- a/serializable/src/main/kotlin/serializable/Serializable.kt +++ b/serializable/src/main/kotlin/elements/Serializable.kt @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package dev.triumphteam.docsly.serializable +package dev.triumphteam.docsly.elements import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -34,6 +34,9 @@ public sealed interface DocElement : WithName { /** The virtual path of the serializable within the codebase. */ public val path: Path + + /** Create a list of possible search references for the doc element. */ + public fun createReferences(): List } /** A [DocElement] that also contains language details. */ @@ -56,7 +59,12 @@ public data class SerializablePackage( override val annotations: List, override val documentation: DescriptionDocumentation?, override val extraDocumentation: List, -) : DocElement, WithDocumentation, WithExtraDocs, WithAnnotations +) : DocElement, WithDocumentation, WithExtraDocs, WithAnnotations { + + override fun createReferences(): List { + return listOf(name) + } +} /** Possible documentation languages. */ @Serializable diff --git a/serializable/src/main/kotlin/serializable/SerializableAnnotation.kt b/serializable/src/main/kotlin/elements/SerializableAnnotation.kt similarity index 98% rename from serializable/src/main/kotlin/serializable/SerializableAnnotation.kt rename to serializable/src/main/kotlin/elements/SerializableAnnotation.kt index 9be9786..632cdb5 100644 --- a/serializable/src/main/kotlin/serializable/SerializableAnnotation.kt +++ b/serializable/src/main/kotlin/elements/SerializableAnnotation.kt @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package dev.triumphteam.docsly.serializable +package dev.triumphteam.docsly.elements import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/serializable/src/main/kotlin/serializable/SerializableMember.kt b/serializable/src/main/kotlin/elements/SerializableMember.kt similarity index 83% rename from serializable/src/main/kotlin/serializable/SerializableMember.kt rename to serializable/src/main/kotlin/elements/SerializableMember.kt index dd2a9cb..c7f929d 100644 --- a/serializable/src/main/kotlin/serializable/SerializableMember.kt +++ b/serializable/src/main/kotlin/elements/SerializableMember.kt @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package dev.triumphteam.docsly.serializable +package dev.triumphteam.docsly.elements import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -34,7 +34,30 @@ public sealed interface SerializableMember : WithVisibility, WithExtraDocs, WithGenerics, - WithAnnotations + WithAnnotations { + + override fun createReferences(): List { + return listOf( + name, + createReference("."), + createReference("#"), + ) + } + + private fun createReference(separator: String): String { + return buildString { + append(path.packagePath) + + path.classPath?.firstOrNull()?.let { + append(".") + append(it) + } + + append(separator) + append(name) + } + } +} /** * A property! @@ -120,4 +143,22 @@ public data class SerializableEnumEntry( override val modifiers: Set, override val documentation: DescriptionDocumentation?, override val extraDocumentation: List, -) : DocElement, WithDocumentation, WithExtraDocs, WithAnnotations, WithModifiers +) : DocElement, WithDocumentation, WithExtraDocs, WithAnnotations, WithModifiers { + + override fun createReferences(): List { + return listOf( + name, + buildString { + append(path.packagePath) + + path.classPath?.firstOrNull()?.let { + append(".") + append(it) + } + + append("#") + append(name) + } + ) + } +} diff --git a/serializable/src/main/kotlin/serializable/SerializableType.kt b/serializable/src/main/kotlin/elements/SerializableType.kt similarity index 98% rename from serializable/src/main/kotlin/serializable/SerializableType.kt rename to serializable/src/main/kotlin/elements/SerializableType.kt index d00c396..9e89aa6 100644 --- a/serializable/src/main/kotlin/serializable/SerializableType.kt +++ b/serializable/src/main/kotlin/elements/SerializableType.kt @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package dev.triumphteam.docsly.serializable +package dev.triumphteam.docsly.elements import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/serializable/src/main/kotlin/serializable/With.kt b/serializable/src/main/kotlin/elements/With.kt similarity index 98% rename from serializable/src/main/kotlin/serializable/With.kt rename to serializable/src/main/kotlin/elements/With.kt index 7a7b92e..1243440 100644 --- a/serializable/src/main/kotlin/serializable/With.kt +++ b/serializable/src/main/kotlin/elements/With.kt @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package dev.triumphteam.docsly.serializable +package dev.triumphteam.docsly.elements /** The language the serializable was written in. */ public interface WithLanguage {