diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5054fc9e0..bf0fd3762 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ dex2jar = "2.4.36" polyglot = "25.0.3" settings = "1.3.0" twelvemonkeys = "3.13.1" -graphqlkotlin = "9.2.0" +graphqlkotlin = "10.0.0-alpha.3" xmlserialization = "0.91.3" ktlint = "1.8.0" koin = "4.2.1" diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 4e11d4a81..af90c3b04 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -43,7 +43,7 @@ dependencies { // Javalin api implementation(libs.bundles.javalin) - implementation(libs.bundles.jackson) + //implementation(libs.bundles.jackson) // GraphQL implementation(libs.graphql.kotlin.server) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/AsDataFetcherResult.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/AsDataFetcherResult.kt index 6c3a0f74a..cb23ed779 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/AsDataFetcherResult.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/AsDataFetcherResult.kt @@ -6,7 +6,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging val logger = KotlinLogging.logger { } -inline fun asDataFetcherResult(block: () -> T): DataFetcherResult { +inline fun asDataFetcherResult(block: () -> T): DataFetcherResult { val result = runCatching { block() @@ -15,13 +15,13 @@ inline fun asDataFetcherResult(block: () -> T): DataFetcherResult { if (result.isFailure) { logger.error(result.exceptionOrNull()) { "asDataFetcherResult: failed due to" } return DataFetcherResult - .newResult() - .error(result.exceptionOrNull()?.toGraphQLError()) + .newResult() + .error(result.exceptionOrNull()!!.toGraphQLError()) .build() } return DataFetcherResult - .newResult() + .newResult() .data(result.getOrNull()) .build() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/cache/CustomCacheMap.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/cache/CustomCacheMap.kt index 742da59a8..7f9b946b2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/cache/CustomCacheMap.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/cache/CustomCacheMap.kt @@ -3,12 +3,8 @@ package suwayomi.tachidesk.graphql.cache import org.dataloader.CacheMap import java.util.concurrent.CompletableFuture -class CustomCacheMap : CacheMap { - private val cache: MutableMap> - - init { - cache = HashMap() - } +class CustomCacheMap : CacheMap { + private val cache: MutableMap> = HashMap() override fun containsKey(key: K): Boolean = cache.containsKey(key) @@ -18,12 +14,12 @@ class CustomCacheMap : CacheMap { override fun getAll(): Collection> = cache.values - override fun set( + override fun putIfAbsentAtomically( key: K, value: CompletableFuture, - ): CacheMap { + ): CompletableFuture { cache[key] = value - return this + return value } override fun delete(key: K): CacheMap { @@ -35,4 +31,8 @@ class CustomCacheMap : CacheMap { cache.clear() return this } + + override fun size(): Int { + return cache.size + } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt index f0fe0a898..44ef6de3c 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt @@ -24,11 +24,11 @@ import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.server.JavalinSetup.future -class ChapterDataLoader : KotlinDataLoader { +class ChapterDataLoader : KotlinDataLoader { override val dataLoaderName = "ChapterDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -48,7 +48,7 @@ class ChaptersForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "ChaptersForMangaDataLoader" override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -68,7 +68,7 @@ class DownloadedChapterCountForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "DownloadedChapterCountForMangaDataLoader" override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -90,7 +90,7 @@ class UnreadChapterCountForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "UnreadChapterCountForMangaDataLoader" override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -112,7 +112,7 @@ class BookmarkedChapterCountForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "BookmarkedChapterCountForMangaDataLoader" override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -157,11 +157,11 @@ class HasDuplicateChaptersForMangaDataLoader : KotlinDataLoader { } } -class LastReadChapterForMangaDataLoader : KotlinDataLoader { +class LastReadChapterForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "LastReadChapterForMangaDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -177,11 +177,11 @@ class LastReadChapterForMangaDataLoader : KotlinDataLoader { } } -class LatestReadChapterForMangaDataLoader : KotlinDataLoader { +class LatestReadChapterForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "LatestReadChapterForMangaDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -197,11 +197,11 @@ class LatestReadChapterForMangaDataLoader : KotlinDataLoader } } -class LatestFetchedChapterForMangaDataLoader : KotlinDataLoader { +class LatestFetchedChapterForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "LatestFetchedChapterForMangaDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -217,11 +217,11 @@ class LatestFetchedChapterForMangaDataLoader : KotlinDataLoader { +class LatestUploadedChapterForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "LatestUploadedChapterForMangaDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -237,11 +237,11 @@ class LatestUploadedChapterForMangaDataLoader : KotlinDataLoader { +class FirstUnreadChapterForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "FirstUnreadChapterForMangaDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -257,11 +257,11 @@ class FirstUnreadChapterForMangaDataLoader : KotlinDataLoader } } -class HighestNumberedChapterForMangaDataLoader : KotlinDataLoader { +class HighestNumberedChapterForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "HighestNumberedChapterForMangaDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt index 2c7be2fa6..c3b4b6955 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt @@ -20,10 +20,10 @@ import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.server.JavalinSetup.future -class ExtensionDataLoader : KotlinDataLoader { +class ExtensionDataLoader : KotlinDataLoader { override val dataLoaderName = "ExtensionDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { @@ -40,10 +40,10 @@ class ExtensionDataLoader : KotlinDataLoader { } } -class ExtensionForSourceDataLoader : KotlinDataLoader { +class ExtensionForSourceDataLoader : KotlinDataLoader { override val dataLoaderName = "ExtensionForSourceDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt index 0775d71ad..a49b3260d 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt @@ -25,10 +25,10 @@ import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.server.JavalinSetup.future -class MangaDataLoader : KotlinDataLoader { +class MangaDataLoader : KotlinDataLoader { override val dataLoaderName = "MangaDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { @@ -122,6 +122,6 @@ class MangaForIdsDataLoader : KotlinDataLoader, MangaNodeList> { } } }, - DataLoaderOptions.newOptions().setCacheMap(CustomCacheMap, MangaNodeList>()), + DataLoaderOptions.newOptions().setCacheMap(CustomCacheMap, MangaNodeList>()).build(), ) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt index a01f2392c..d2515bca1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt @@ -20,11 +20,11 @@ import suwayomi.tachidesk.manga.model.table.MangaMetaTable import suwayomi.tachidesk.manga.model.table.SourceMetaTable import suwayomi.tachidesk.server.JavalinSetup.future -class GlobalMetaDataLoader : KotlinDataLoader { +class GlobalMetaDataLoader : KotlinDataLoader { override val dataLoaderName = "GlobalMetaDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = - DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt index be3c60e0b..3fc2269cf 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt @@ -22,10 +22,10 @@ import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.server.JavalinSetup.future -class SourceDataLoader : KotlinDataLoader { +class SourceDataLoader : KotlinDataLoader { override val dataLoaderName = "SourceDataLoader" - override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = + override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/CategoryMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/CategoryMutation.kt index 132a399e5..a899fa9ae 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/CategoryMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/CategoryMutation.kt @@ -42,7 +42,7 @@ class CategoryMutation { ) @RequireAuth - fun setCategoryMeta(input: SetCategoryMetaInput): DataFetcherResult = + fun setCategoryMeta(input: SetCategoryMetaInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, meta) = input @@ -64,7 +64,7 @@ class CategoryMutation { ) @RequireAuth - fun deleteCategoryMeta(input: DeleteCategoryMetaInput): DataFetcherResult = + fun deleteCategoryMeta(input: DeleteCategoryMetaInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, categoryId, key) = input @@ -110,7 +110,7 @@ class CategoryMutation { ) @RequireAuth - fun setCategoryMetas(input: SetCategoryMetasInput): DataFetcherResult = + fun setCategoryMetas(input: SetCategoryMetasInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, items) = input @@ -166,7 +166,7 @@ class CategoryMutation { ) @RequireAuth - fun deleteCategoryMetas(input: DeleteCategoryMetasInput): DataFetcherResult = + fun deleteCategoryMetas(input: DeleteCategoryMetasInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, items) = input @@ -291,7 +291,7 @@ class CategoryMutation { } @RequireAuth - fun updateCategory(input: UpdateCategoryInput): DataFetcherResult = + fun updateCategory(input: UpdateCategoryInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, id, patch) = input @@ -309,7 +309,7 @@ class CategoryMutation { } @RequireAuth - fun updateCategories(input: UpdateCategoriesInput): DataFetcherResult = + fun updateCategories(input: UpdateCategoriesInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, ids, patch) = input @@ -338,7 +338,7 @@ class CategoryMutation { ) @RequireAuth - fun updateCategoryOrder(input: UpdateCategoryOrderInput): DataFetcherResult = + fun updateCategoryOrder(input: UpdateCategoryOrderInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, categoryId, position) = input require(position > 0) { @@ -397,7 +397,7 @@ class CategoryMutation { ) @RequireAuth - fun createCategory(input: CreateCategoryInput): DataFetcherResult = + fun createCategory(input: CreateCategoryInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, name, order, default, includeInUpdate, includeInDownload) = input transaction { @@ -457,7 +457,7 @@ class CategoryMutation { ) @RequireAuth - fun deleteCategory(input: DeleteCategoryInput): DataFetcherResult { + fun deleteCategory(input: DeleteCategoryInput): DataFetcherResult { return asDataFetcherResult { val (clientMutationId, categoryId) = input if (categoryId == 0) { // Don't delete default category @@ -547,7 +547,7 @@ class CategoryMutation { } @RequireAuth - fun updateMangaCategories(input: UpdateMangaCategoriesInput): DataFetcherResult = + fun updateMangaCategories(input: UpdateMangaCategoriesInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, id, patch) = input @@ -565,7 +565,7 @@ class CategoryMutation { } @RequireAuth - fun updateMangasCategories(input: UpdateMangasCategoriesInput): DataFetcherResult = + fun updateMangasCategories(input: UpdateMangasCategoriesInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, ids, patch) = input diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt index 9d33fcf32..c79240379 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt @@ -120,7 +120,7 @@ class ChapterMutation { } @RequireAuth - fun updateChapter(input: UpdateChapterInput): DataFetcherResult = + fun updateChapter(input: UpdateChapterInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, id, patch) = input @@ -138,7 +138,7 @@ class ChapterMutation { } @RequireAuth - fun updateChapters(input: UpdateChaptersInput): DataFetcherResult = + fun updateChapters(input: UpdateChaptersInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, ids, patch) = input @@ -166,7 +166,7 @@ class ChapterMutation { ) @RequireAuth - fun fetchChapters(input: FetchChaptersInput): CompletableFuture> { + fun fetchChapters(input: FetchChaptersInput): CompletableFuture> { val (clientMutationId, mangaId) = input return future { @@ -201,7 +201,7 @@ class ChapterMutation { ) @RequireAuth - fun setChapterMeta(input: SetChapterMetaInput): DataFetcherResult = + fun setChapterMeta(input: SetChapterMetaInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, meta) = input @@ -223,7 +223,7 @@ class ChapterMutation { ) @RequireAuth - fun deleteChapterMeta(input: DeleteChapterMetaInput): DataFetcherResult = + fun deleteChapterMeta(input: DeleteChapterMetaInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, chapterId, key) = input @@ -269,7 +269,7 @@ class ChapterMutation { ) @RequireAuth - fun setChapterMetas(input: SetChapterMetasInput): DataFetcherResult = + fun setChapterMetas(input: SetChapterMetasInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, items) = input @@ -325,7 +325,7 @@ class ChapterMutation { ) @RequireAuth - fun deleteChapterMetas(input: DeleteChapterMetasInput): DataFetcherResult = + fun deleteChapterMetas(input: DeleteChapterMetasInput): DataFetcherResult = asDataFetcherResult { val (clientMutationId, items) = input @@ -405,7 +405,7 @@ class ChapterMutation { ) @RequireAuth - fun fetchChapterPages(input: FetchChapterPagesInput): CompletableFuture> { + fun fetchChapterPages(input: FetchChapterPagesInput): CompletableFuture> { val (clientMutationId, chapterId) = input val paramsMap = input.toParams() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/DownloadMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/DownloadMutation.kt index 57e5dfdfa..53536cf87 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/DownloadMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/DownloadMutation.kt @@ -30,7 +30,7 @@ class DownloadMutation { ) @RequireAuth - fun deleteDownloadedChapters(input: DeleteDownloadedChaptersInput): DataFetcherResult { + fun deleteDownloadedChapters(input: DeleteDownloadedChaptersInput): DataFetcherResult { val (clientMutationId, chapters) = input return asDataFetcherResult { @@ -60,7 +60,7 @@ class DownloadMutation { ) @RequireAuth - fun deleteDownloadedChapter(input: DeleteDownloadedChapterInput): DataFetcherResult { + fun deleteDownloadedChapter(input: DeleteDownloadedChapterInput): DataFetcherResult { val (clientMutationId, chapter) = input return asDataFetcherResult { @@ -89,7 +89,7 @@ class DownloadMutation { @RequireAuth fun enqueueChapterDownloads( input: EnqueueChapterDownloadsInput, - ): CompletableFuture> { + ): CompletableFuture> { val (clientMutationId, chapters) = input return future { @@ -123,7 +123,7 @@ class DownloadMutation { ) @RequireAuth - fun enqueueChapterDownload(input: EnqueueChapterDownloadInput): CompletableFuture> { + fun enqueueChapterDownload(input: EnqueueChapterDownloadInput): CompletableFuture> { val (clientMutationId, chapter) = input return future { @@ -158,7 +158,7 @@ class DownloadMutation { @RequireAuth fun dequeueChapterDownloads( input: DequeueChapterDownloadsInput, - ): CompletableFuture> { + ): CompletableFuture> { val (clientMutationId, chapters) = input return future { @@ -194,7 +194,7 @@ class DownloadMutation { ) @RequireAuth - fun dequeueChapterDownload(input: DequeueChapterDownloadInput): CompletableFuture> { + fun dequeueChapterDownload(input: DequeueChapterDownloadInput): CompletableFuture> { val (clientMutationId, chapter) = input return future { @@ -229,7 +229,7 @@ class DownloadMutation { ) @RequireAuth - fun startDownloader(input: StartDownloaderInput): CompletableFuture> = + fun startDownloader(input: StartDownloaderInput): CompletableFuture> = future { asDataFetcherResult { DownloadManager.start() @@ -258,7 +258,7 @@ class DownloadMutation { ) @RequireAuth - fun stopDownloader(input: StopDownloaderInput): CompletableFuture> = + fun stopDownloader(input: StopDownloaderInput): CompletableFuture> = future { asDataFetcherResult { DownloadManager.stop() @@ -287,7 +287,7 @@ class DownloadMutation { ) @RequireAuth - fun clearDownloader(input: ClearDownloaderInput): CompletableFuture> = + fun clearDownloader(input: ClearDownloaderInput): CompletableFuture> = future { asDataFetcherResult { DownloadManager.clear() @@ -318,7 +318,7 @@ class DownloadMutation { ) @RequireAuth - fun reorderChapterDownload(input: ReorderChapterDownloadInput): CompletableFuture> { + fun reorderChapterDownload(input: ReorderChapterDownloadInput): CompletableFuture> { val (clientMutationId, chapter, to) = input return future { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ExtensionMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ExtensionMutation.kt index b484890cf..a813ca98c 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ExtensionMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ExtensionMutation.kt @@ -75,7 +75,7 @@ class ExtensionMutation { } @RequireAuth - fun updateExtension(input: UpdateExtensionInput): CompletableFuture> { + fun updateExtension(input: UpdateExtensionInput): CompletableFuture> { val (clientMutationId, id, patch) = input return future { @@ -100,7 +100,7 @@ class ExtensionMutation { } @RequireAuth - fun updateExtensions(input: UpdateExtensionsInput): CompletableFuture> { + fun updateExtensions(input: UpdateExtensionsInput): CompletableFuture> { val (clientMutationId, ids, patch) = input return future { @@ -133,7 +133,7 @@ class ExtensionMutation { ) @RequireAuth - fun fetchExtensions(input: FetchExtensionsInput): CompletableFuture> { + fun fetchExtensions(input: FetchExtensionsInput): CompletableFuture> { val (clientMutationId) = input return future { @@ -169,7 +169,7 @@ class ExtensionMutation { @RequireAuth fun installExternalExtension( input: InstallExternalExtensionInput, - ): CompletableFuture> { + ): CompletableFuture> { val (clientMutationId, extensionFile) = input return future { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/InfoMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/InfoMutation.kt index 519f6aa77..a75b9baa2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/InfoMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/InfoMutation.kt @@ -26,7 +26,7 @@ class InfoMutation { ) @RequireAuth - fun updateWebUI(input: WebUIUpdateInput): CompletableFuture> { + fun updateWebUI(input: WebUIUpdateInput): CompletableFuture> { return future { asDataFetcherResult { withTimeout(30.seconds) { @@ -62,7 +62,7 @@ class InfoMutation { } @RequireAuth - fun resetWebUIUpdateStatus(): CompletableFuture> = + fun resetWebUIUpdateStatus(): CompletableFuture> = future { asDataFetcherResult { withTimeout(30.seconds) { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/KoreaderSyncMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/KoreaderSyncMutation.kt index e1ae1e4c5..b2de9b9e4 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/KoreaderSyncMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/KoreaderSyncMutation.kt @@ -62,7 +62,7 @@ class KoreaderSyncMutation { ) @RequireAuth - fun pushKoSyncProgress(input: PushKoSyncProgressInput): CompletableFuture> = + fun pushKoSyncProgress(input: PushKoSyncProgressInput): CompletableFuture> = future { asDataFetcherResult { KoreaderSyncService.pushProgress(input.chapterId) @@ -96,7 +96,7 @@ class KoreaderSyncMutation { ) @RequireAuth - fun pullKoSyncProgress(input: PullKoSyncProgressInput): CompletableFuture> = + fun pullKoSyncProgress(input: PullKoSyncProgressInput): CompletableFuture> = future { asDataFetcherResult { val syncResult = KoreaderSyncService.checkAndPullProgress(input.chapterId) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MangaMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MangaMutation.kt index 175c790ff..8be3be9af 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MangaMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MangaMutation.kt @@ -98,7 +98,7 @@ class MangaMutation { } @RequireAuth - fun updateManga(input: UpdateMangaInput): CompletableFuture> { + fun updateManga(input: UpdateMangaInput): CompletableFuture> { val (clientMutationId, id, patch) = input return future { @@ -119,7 +119,7 @@ class MangaMutation { } @RequireAuth - fun updateMangas(input: UpdateMangasInput): CompletableFuture> { + fun updateMangas(input: UpdateMangasInput): CompletableFuture> { val (clientMutationId, ids, patch) = input return future { @@ -150,7 +150,7 @@ class MangaMutation { ) @RequireAuth - fun fetchManga(input: FetchMangaInput): CompletableFuture> { + fun fetchManga(input: FetchMangaInput): CompletableFuture> { val (clientMutationId, id) = input return future { @@ -180,7 +180,7 @@ class MangaMutation { ) @RequireAuth - fun setMangaMeta(input: SetMangaMetaInput): DataFetcherResult { + fun setMangaMeta(input: SetMangaMetaInput): DataFetcherResult { val (clientMutationId, meta) = input return asDataFetcherResult { @@ -203,7 +203,7 @@ class MangaMutation { ) @RequireAuth - fun deleteMangaMeta(input: DeleteMangaMetaInput): DataFetcherResult { + fun deleteMangaMeta(input: DeleteMangaMetaInput): DataFetcherResult { val (clientMutationId, mangaId, key) = input return asDataFetcherResult { @@ -250,7 +250,7 @@ class MangaMutation { ) @RequireAuth - fun setMangaMetas(input: SetMangaMetasInput): DataFetcherResult { + fun setMangaMetas(input: SetMangaMetasInput): DataFetcherResult { val (clientMutationId, items) = input return asDataFetcherResult { @@ -307,7 +307,7 @@ class MangaMutation { ) @RequireAuth - fun deleteMangaMetas(input: DeleteMangaMetasInput): DataFetcherResult { + fun deleteMangaMetas(input: DeleteMangaMetasInput): DataFetcherResult { val (clientMutationId, items) = input return asDataFetcherResult { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MetaMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MetaMutation.kt index f29265283..64ae1d5b0 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MetaMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MetaMutation.kt @@ -29,7 +29,7 @@ class MetaMutation { ) @RequireAuth - fun setGlobalMeta(input: SetGlobalMetaInput): DataFetcherResult { + fun setGlobalMeta(input: SetGlobalMetaInput): DataFetcherResult { val (clientMutationId, meta) = input return asDataFetcherResult { @@ -50,7 +50,7 @@ class MetaMutation { ) @RequireAuth - fun deleteGlobalMeta(input: DeleteGlobalMetaInput): DataFetcherResult { + fun deleteGlobalMeta(input: DeleteGlobalMetaInput): DataFetcherResult { val (clientMutationId, key) = input return asDataFetcherResult { @@ -86,7 +86,7 @@ class MetaMutation { ) @RequireAuth - fun setGlobalMetas(input: SetGlobalMetasInput): DataFetcherResult { + fun setGlobalMetas(input: SetGlobalMetasInput): DataFetcherResult { val (clientMutationId, metas) = input return asDataFetcherResult { @@ -117,7 +117,7 @@ class MetaMutation { ) @RequireAuth - fun deleteGlobalMetas(input: DeleteGlobalMetasInput): DataFetcherResult { + fun deleteGlobalMetas(input: DeleteGlobalMetasInput): DataFetcherResult { val (clientMutationId, keys, prefixes) = input return asDataFetcherResult { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SourceMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SourceMutation.kt index c9b619e77..0cb9fff3b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SourceMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SourceMutation.kt @@ -47,7 +47,7 @@ class SourceMutation { ) @RequireAuth - fun setSourceMeta(input: SetSourceMetaInput): DataFetcherResult { + fun setSourceMeta(input: SetSourceMetaInput): DataFetcherResult { val (clientMutationId, meta) = input return asDataFetcherResult { @@ -70,7 +70,7 @@ class SourceMutation { ) @RequireAuth - fun deleteSourceMeta(input: DeleteSourceMetaInput): DataFetcherResult { + fun deleteSourceMeta(input: DeleteSourceMetaInput): DataFetcherResult { val (clientMutationId, sourceId, key) = input return asDataFetcherResult { @@ -121,7 +121,7 @@ class SourceMutation { ) @RequireAuth - fun setSourceMetas(input: SetSourceMetasInput): DataFetcherResult { + fun setSourceMetas(input: SetSourceMetasInput): DataFetcherResult { val (clientMutationId, items) = input return asDataFetcherResult { @@ -178,7 +178,7 @@ class SourceMutation { ) @RequireAuth - fun deleteSourceMetas(input: DeleteSourceMetasInput): DataFetcherResult { + fun deleteSourceMetas(input: DeleteSourceMetasInput): DataFetcherResult { val (clientMutationId, items) = input return asDataFetcherResult { @@ -260,7 +260,7 @@ class SourceMutation { ) @RequireAuth - fun fetchSourceManga(input: FetchSourceMangaInput): CompletableFuture> { + fun fetchSourceManga(input: FetchSourceMangaInput): CompletableFuture> { val (clientMutationId, sourceId, type, page, query, filters) = input return future { @@ -329,7 +329,7 @@ class SourceMutation { ) @RequireAuth - fun updateSourcePreference(input: UpdateSourcePreferenceInput): DataFetcherResult { + fun updateSourcePreference(input: UpdateSourcePreferenceInput): DataFetcherResult { val (clientMutationId, sourceId, change) = input return asDataFetcherResult { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/TrackMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/TrackMutation.kt index ac6181339..207d8eb82 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/TrackMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/TrackMutation.kt @@ -222,7 +222,7 @@ class TrackMutation { ) @RequireAuth - fun trackProgress(input: TrackProgressInput): CompletableFuture> { + fun trackProgress(input: TrackProgressInput): CompletableFuture> { val (clientMutationId, mangaId) = input return future { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/UpdateMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/UpdateMutation.kt index d8cbaa761..e2a125af3 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/UpdateMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/UpdateMutation.kt @@ -28,7 +28,7 @@ class UpdateMutation { ) @RequireAuth - fun updateLibrary(input: UpdateLibraryInput): CompletableFuture> { + fun updateLibrary(input: UpdateLibraryInput): CompletableFuture> { updater.addCategoriesToUpdateQueue( Category.getCategoryList().filter { input.categories?.contains(it.id) ?: true }, clear = true, @@ -60,7 +60,7 @@ class UpdateMutation { ) @RequireAuth - fun updateLibraryManga(input: UpdateLibraryMangaInput): CompletableFuture> { + fun updateLibraryManga(input: UpdateLibraryMangaInput): CompletableFuture> { updateLibrary( UpdateLibraryInput( clientMutationId = input.clientMutationId, @@ -92,7 +92,7 @@ class UpdateMutation { ) @RequireAuth - fun updateCategoryManga(input: UpdateCategoryMangaInput): CompletableFuture> { + fun updateCategoryManga(input: UpdateCategoryMangaInput): CompletableFuture> { updateLibrary( UpdateLibraryInput( clientMutationId = input.clientMutationId, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt index e8fefcb9a..f07d99629 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt @@ -11,6 +11,7 @@ import com.expediagroup.graphql.server.execution.GraphQLRequestParser import com.expediagroup.graphql.server.types.GraphQLBatchRequest import com.expediagroup.graphql.server.types.GraphQLRequest import com.expediagroup.graphql.server.types.GraphQLServerRequest +import io.github.oshai.kotlinlogging.KotlinLogging import io.javalin.http.Context import io.javalin.http.UploadedFile import io.javalin.json.JavalinJackson @@ -19,11 +20,12 @@ import io.javalin.json.fromJsonString import java.io.IOException class JavalinGraphQLRequestParser : GraphQLRequestParser { - val jsonMapper = JavalinJackson() + private val logger = KotlinLogging.logger {} @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") override suspend fun parseRequest(context: Context): GraphQLServerRequest? { return try { + val jsonMapper = context.jsonMapper() val contentType = context.contentType() val formParam = if ( @@ -77,7 +79,8 @@ class JavalinGraphQLRequestParser : GraphQLRequestParser { ) } } - } catch (_: IOException) { + } catch (e: IOException) { + logger.error(e) { "Error when parsing request" } null } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLServer.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLServer.kt index fbfd6945e..0b640b5e1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLServer.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLServer.kt @@ -10,7 +10,6 @@ package suwayomi.tachidesk.graphql.server import com.expediagroup.graphql.generator.execution.FlowSubscriptionExecutionStrategy import com.expediagroup.graphql.server.execution.GraphQLRequestHandler import com.expediagroup.graphql.server.execution.GraphQLServer -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import graphql.ExceptionWhileDataFetching import graphql.GraphQL import graphql.execution.AsyncExecutionStrategy @@ -27,6 +26,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import suwayomi.tachidesk.graphql.server.subscriptions.ApolloSubscriptionProtocolHandler import suwayomi.tachidesk.server.JavalinSetup.future +import tools.jackson.module.kotlin.jacksonObjectMapper class TachideskGraphQLServer( requestParser: JavalinGraphQLRequestParser, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Cursor.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Cursor.kt index 413c23ddf..7029663c1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Cursor.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Cursor.kt @@ -58,7 +58,7 @@ private class GraphqlCursorCoercing : Coercing { ), ) } - return Cursor(input.value) + return Cursor(input.value!!) } private fun valueToLiteralImpl(input: Any): StringValue = StringValue.newStringValue(input.toString()).build() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/DurationAsString.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/DurationAsString.kt index 3469900a2..633ed85b0 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/DurationAsString.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/DurationAsString.kt @@ -71,7 +71,7 @@ private class GraphqlDurationAsStringCoercing : Coercing { ) } return try { - Duration.parse(input.value) + Duration.parse(input.value!!) } catch (e: IllegalArgumentException) { throw CoercingParseLiteralException( "Invalid duration format: ${input.value}. Expected ISO-8601 duration string (e.g., 'PT30M', 'P1D')", diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/LongAsString.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/LongAsString.kt index 651c4fb80..6563c08f6 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/LongAsString.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/LongAsString.kt @@ -53,7 +53,7 @@ private class GraphqlLongAsStringCoercing : Coercing { ), ) } - return input.value.toLong() + return input.value!!.toLong() } private fun valueToLiteralImpl(input: Any): StringValue = StringValue.newStringValue(input.toString()).build() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionProtocolHandler.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionProtocolHandler.kt index aea05df0f..72ec0b7da 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionProtocolHandler.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionProtocolHandler.kt @@ -9,9 +9,6 @@ package suwayomi.tachidesk.graphql.server.subscriptions import com.expediagroup.graphql.server.execution.GraphQLRequestHandler import com.expediagroup.graphql.server.types.GraphQLRequest -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.kotlin.convertValue -import com.fasterxml.jackson.module.kotlin.readValue import io.github.oshai.kotlinlogging.KotlinLogging import io.javalin.http.Header import io.javalin.websocket.WsContext @@ -41,6 +38,9 @@ import suwayomi.tachidesk.server.JavalinSetup.Attribute import suwayomi.tachidesk.server.JavalinSetup.getAttributeOrSet import suwayomi.tachidesk.server.user.UserType import suwayomi.tachidesk.server.user.getUserFromToken +import tools.jackson.databind.ObjectMapper +import tools.jackson.module.kotlin.convertValue +import tools.jackson.module.kotlin.readValue /** * Implementation of the `graphql-transport-ws` protocol defined by Denis Badurina