From 52bda2c08051e187584073858e247657592f79e9 Mon Sep 17 00:00:00 2001 From: Syer10 Date: Sun, 2 Apr 2023 20:15:09 -0400 Subject: [PATCH] Start working on graphql paging --- .../graphql/dataLoaders/CategoryDataLoader.kt | 8 ++-- .../graphql/dataLoaders/ChapterDataLoader.kt | 8 ++-- .../graphql/dataLoaders/MangaDataLoader.kt | 8 ++-- .../graphql/dataLoaders/MetaDataLoader.kt | 21 +++++----- .../graphql/dataLoaders/SourceDataLoader.kt | 8 ++-- .../graphql/queries/CategoryQuery.kt | 6 ++- .../tachidesk/graphql/queries/ChapterQuery.kt | 6 ++- .../graphql/queries/ExtensionQuery.kt | 6 ++- .../tachidesk/graphql/queries/MangaQuery.kt | 6 ++- .../tachidesk/graphql/queries/MetaQuery.kt | 6 ++- .../tachidesk/graphql/queries/SourceQuery.kt | 6 ++- .../tachidesk/graphql/queries/UpdatesQuery.kt | 6 ++- .../tachidesk/graphql/types/CategoryType.kt | 41 ++++++++++++++++--- .../tachidesk/graphql/types/ChapterType.kt | 37 +++++++++++++++-- .../tachidesk/graphql/types/DownloadType.kt | 33 ++++++++++++++- .../tachidesk/graphql/types/ExtensionType.kt | 37 +++++++++++++++-- .../tachidesk/graphql/types/MangaType.kt | 41 ++++++++++++++++--- .../tachidesk/graphql/types/MetaType.kt | 35 ++++++++++++++-- .../tachidesk/graphql/types/NodeList.kt | 40 ++++++++++++++++++ .../tachidesk/graphql/types/SourceType.kt | 37 +++++++++++++++-- .../tachidesk/graphql/types/UpdatesType.kt | 33 ++++++++++++++- 21 files changed, 369 insertions(+), 60 deletions(-) create mode 100644 server/src/main/kotlin/suwayomi/tachidesk/graphql/types/NodeList.kt diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/CategoryDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/CategoryDataLoader.kt index 09dbc52d1..833cb51e7 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/CategoryDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/CategoryDataLoader.kt @@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.CategoryNodeList +import suwayomi.tachidesk.graphql.types.CategoryNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.CategoryType import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.CategoryTable @@ -32,9 +34,9 @@ class CategoryDataLoader : KotlinDataLoader { } } -class CategoriesForMangaDataLoader : KotlinDataLoader> { +class CategoriesForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "CategoriesForMangaDataLoader" - override fun getDataLoader(): DataLoader> = DataLoaderFactory.newDataLoader> { ids -> + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -43,7 +45,7 @@ class CategoriesForMangaDataLoader : KotlinDataLoader> { .map { Pair(it[CategoryMangaTable.manga].value, CategoryType(it)) } .groupBy { it.first } .mapValues { it.value.map { pair -> pair.second } } - ids.map { itemsByRef[it] ?: emptyList() } + ids.map { (itemsByRef[it] ?: emptyList()).toNodeList() } } } } 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 1713df8ab..79a8a7849 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt @@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.ChapterNodeList +import suwayomi.tachidesk.graphql.types.ChapterNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.server.JavalinSetup.future @@ -31,16 +33,16 @@ class ChapterDataLoader : KotlinDataLoader { } } -class ChaptersForMangaDataLoader : KotlinDataLoader> { +class ChaptersForMangaDataLoader : KotlinDataLoader { override val dataLoaderName = "ChaptersForMangaDataLoader" - override fun getDataLoader(): DataLoader> = DataLoaderFactory.newDataLoader> { ids -> + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) val chaptersByMangaId = ChapterTable.select { ChapterTable.manga inList ids } .map { ChapterType(it) } .groupBy { it.mangaId } - ids.map { chaptersByMangaId[it] ?: emptyList() } + ids.map { (chaptersByMangaId[it] ?: emptyList()).toNodeList() } } } } 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 3725efae0..3bd75c19f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt @@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.MangaNodeList +import suwayomi.tachidesk.graphql.types.MangaNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.MangaTable @@ -32,9 +34,9 @@ class MangaDataLoader : KotlinDataLoader { } } -class MangaForCategoryDataLoader : KotlinDataLoader> { +class MangaForCategoryDataLoader : KotlinDataLoader { override val dataLoaderName = "MangaForCategoryDataLoader" - override fun getDataLoader(): DataLoader> = DataLoaderFactory.newDataLoader> { ids -> + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -42,7 +44,7 @@ class MangaForCategoryDataLoader : KotlinDataLoader> { .map { Pair(it[CategoryMangaTable.category].value, MangaType(it)) } .groupBy { it.first } .mapValues { it.value.map { pair -> pair.second } } - ids.map { itemsByRef[it] ?: emptyList() } + ids.map { (itemsByRef[it] ?: emptyList()).toNodeList() } } } } 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 3a61300ab..6a7aca0a2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt @@ -13,7 +13,8 @@ import suwayomi.tachidesk.graphql.types.ChapterMetaItem import suwayomi.tachidesk.graphql.types.GlobalMetaItem import suwayomi.tachidesk.graphql.types.MangaMetaItem import suwayomi.tachidesk.graphql.types.MetaItem -import suwayomi.tachidesk.graphql.types.MetaType +import suwayomi.tachidesk.graphql.types.MetaNodeList +import suwayomi.tachidesk.graphql.types.MetaNodeList.Companion.toNodeList import suwayomi.tachidesk.manga.model.table.ChapterMetaTable import suwayomi.tachidesk.manga.model.table.MangaMetaTable import suwayomi.tachidesk.server.JavalinSetup.future @@ -33,46 +34,46 @@ class GlobalMetaDataLoader : KotlinDataLoader { } } -class ChapterMetaDataLoader : KotlinDataLoader { +class ChapterMetaDataLoader : KotlinDataLoader { override val dataLoaderName = "ChapterMetaDataLoader" - override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) val metasByRefId = ChapterMetaTable.select { ChapterMetaTable.ref inList ids } .map { ChapterMetaItem(it) } .groupBy { it.ref } - ids.map { metasByRefId[it] ?: emptyList() } + ids.map { (metasByRefId[it] ?: emptyList()).toNodeList() } } } } } -class MangaMetaDataLoader : KotlinDataLoader { +class MangaMetaDataLoader : KotlinDataLoader { override val dataLoaderName = "MangaMetaDataLoader" - override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) val metasByRefId = MangaMetaTable.select { MangaMetaTable.ref inList ids } .map { MangaMetaItem(it) } .groupBy { it.ref } - ids.map { metasByRefId[it] ?: emptyList() } + ids.map { (metasByRefId[it] ?: emptyList()).toNodeList() } } } } } -class CategoryMetaDataLoader : KotlinDataLoader { +class CategoryMetaDataLoader : KotlinDataLoader { override val dataLoaderName = "CategoryMetaDataLoader" - override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) val metasByRefId = MangaMetaTable.select { MangaMetaTable.ref inList ids } .map { CategoryMetaItem(it) } .groupBy { it.ref } - ids.map { metasByRefId[it] ?: emptyList() } + ids.map { (metasByRefId[it] ?: emptyList()).toNodeList() } } } } 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 031f621e2..469e55b92 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt @@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.SourceNodeList +import suwayomi.tachidesk.graphql.types.SourceNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.SourceType import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.MangaTable @@ -63,9 +65,9 @@ class SourceForMangaDataLoader : KotlinDataLoader { } } -class SourcesForExtensionDataLoader : KotlinDataLoader> { +class SourcesForExtensionDataLoader : KotlinDataLoader { override val dataLoaderName = "SourcesForExtensionDataLoader" - override fun getDataLoader(): DataLoader> = DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> future { transaction { addLogger(Slf4jSqlDebugLogger) @@ -76,7 +78,7 @@ class SourcesForExtensionDataLoader : KotlinDataLoader> .groupBy { it.first } .mapValues { it.value.mapNotNull { pair -> pair.second } } - ids.map { sourcesByExtensionPkg[it] ?: emptyList() } + ids.map { (sourcesByExtensionPkg[it] ?: emptyList()).toNodeList() } } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt index e2cd19ab2..c85f0fa06 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt @@ -13,6 +13,8 @@ import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.CategoryNodeList +import suwayomi.tachidesk.graphql.types.CategoryNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.CategoryType import suwayomi.tachidesk.manga.model.table.CategoryTable import java.util.concurrent.CompletableFuture @@ -48,7 +50,7 @@ class CategoryQuery { val query: String? = null ) - fun categories(input: CategoriesQueryInput? = null): List { + fun categories(input: CategoriesQueryInput? = null): CategoryNodeList { val results = transaction { val res = CategoryTable.selectAll() @@ -72,6 +74,6 @@ class CategoryQuery { res.toList() } - return results.map { CategoryType(it) } + return results.map { CategoryType(it) }.toNodeList() } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt index 372cde678..8ef601585 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt @@ -13,6 +13,8 @@ import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.ChapterNodeList +import suwayomi.tachidesk.graphql.types.ChapterNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.manga.model.table.ChapterTable import java.util.concurrent.CompletableFuture @@ -56,7 +58,7 @@ class ChapterQuery { val count: Int? = null ) - fun chapters(input: ChapterQueryInput? = null): List { + fun chapters(input: ChapterQueryInput? = null): ChapterNodeList { val results = transaction { var res = ChapterTable.selectAll() @@ -97,6 +99,6 @@ class ChapterQuery { res.toList() } - return results.map { ChapterType(it) } + return results.map { ChapterType(it) }.toNodeList() // todo paged } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt index cd3418327..3dfdd202e 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt @@ -11,6 +11,8 @@ import com.expediagroup.graphql.server.extensions.getValueFromDataLoader import graphql.schema.DataFetchingEnvironment import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.ExtensionNodeList +import suwayomi.tachidesk.graphql.types.ExtensionNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.ExtensionType import suwayomi.tachidesk.manga.model.table.ExtensionTable import java.util.concurrent.CompletableFuture @@ -37,11 +39,11 @@ class ExtensionQuery { return dataFetchingEnvironment.getValueFromDataLoader("ExtensionDataLoader", pkgName) } - fun extensions(): List { + fun extensions(): ExtensionNodeList { val results = transaction { ExtensionTable.selectAll().toList() } - return results.map { ExtensionType(it) } + return results.map { ExtensionType(it) }.toNodeList() } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt index 028db3f8d..ea691d5d2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt @@ -16,6 +16,8 @@ import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction import suwayomi.tachidesk.graphql.queries.util.GreaterOrLessThanLong import suwayomi.tachidesk.graphql.queries.util.andWhereGreaterOrLessThen +import suwayomi.tachidesk.graphql.types.MangaNodeList +import suwayomi.tachidesk.graphql.types.MangaNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.MangaTable @@ -60,7 +62,7 @@ class MangaQuery { val count: Int? = null ) - fun mangas(input: MangaQueryInput? = null): List { + fun mangas(input: MangaQueryInput? = null): MangaNodeList { val results = transaction { var res = MangaTable.selectAll() @@ -102,6 +104,6 @@ class MangaQuery { res.toList() } - return results.map { MangaType(it) } + return results.map { MangaType(it) }.toNodeList() // todo paged } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt index f5b2b2cc1..53170fa25 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt @@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.transactions.transaction import suwayomi.tachidesk.global.model.table.GlobalMetaTable import suwayomi.tachidesk.graphql.types.GlobalMetaItem import suwayomi.tachidesk.graphql.types.MetaItem +import suwayomi.tachidesk.graphql.types.MetaNodeList +import suwayomi.tachidesk.graphql.types.MetaNodeList.Companion.toNodeList import java.util.concurrent.CompletableFuture /** @@ -30,11 +32,11 @@ class MetaQuery { return dataFetchingEnvironment.getValueFromDataLoader("GlobalMetaDataLoader", key) } - fun metas(): List { + fun metas(): MetaNodeList { val results = transaction { GlobalMetaTable.selectAll().toList() } - return results.map { GlobalMetaItem(it) } + return results.map { GlobalMetaItem(it) }.toNodeList() } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt index 939b05230..533883af6 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt @@ -11,6 +11,8 @@ import com.expediagroup.graphql.server.extensions.getValueFromDataLoader import graphql.schema.DataFetchingEnvironment import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.SourceNodeList +import suwayomi.tachidesk.graphql.types.SourceNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.SourceType import suwayomi.tachidesk.manga.model.table.SourceTable import java.util.concurrent.CompletableFuture @@ -33,11 +35,11 @@ class SourceQuery { return dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", id) } - fun sources(): List { + fun sources(): SourceNodeList { val results = transaction { SourceTable.selectAll().toList().mapNotNull { SourceType(it) } } - return results + return results.toNodeList() } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/UpdatesQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/UpdatesQuery.kt index df4f50d34..949bb544b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/UpdatesQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/UpdatesQuery.kt @@ -11,6 +11,8 @@ import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.UpdatesNodeList +import suwayomi.tachidesk.graphql.types.UpdatesNodeList.Companion.toNodeList import suwayomi.tachidesk.graphql.types.UpdatesType import suwayomi.tachidesk.manga.model.dataclass.PaginationFactor import suwayomi.tachidesk.manga.model.table.ChapterTable @@ -31,7 +33,7 @@ class UpdatesQuery { val page: Int ) - fun updates(input: UpdatesQueryInput): List { + fun updates(input: UpdatesQueryInput): UpdatesNodeList { val results = transaction { ChapterTable.innerJoin(MangaTable) .select { (MangaTable.inLibrary eq true) and (ChapterTable.fetchedAt greater MangaTable.inLibraryAt) } @@ -42,6 +44,6 @@ class UpdatesQuery { } } - return results + return results.toNodeList() // todo paged } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/CategoryType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/CategoryType.kt index ada7129e5..727c475a2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/CategoryType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/CategoryType.kt @@ -18,7 +18,7 @@ class CategoryType( val order: Int, val name: String, val default: Boolean -) { +) : Node { constructor(row: ResultRow) : this( row[CategoryTable.id].value, row[CategoryTable.order], @@ -26,11 +26,42 @@ class CategoryType( row[CategoryTable.isDefault] ) - fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("MangaForCategoryDataLoader", id) + fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("MangaForCategoryDataLoader", id) } - fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("CategoryMetaDataLoader", id) + fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("CategoryMetaDataLoader", id) + } +} + +data class CategoryNodeList( + override val nodes: List, + override val edges: CategoryEdges, + override val pageInfo: PageInfo, + override val totalCount: Int +) : NodeList() { + data class CategoryEdges( + override val cursor: Cursor, + override val node: CategoryType? + ) : Edges() + + companion object { + fun List.toNodeList(): CategoryNodeList { + return CategoryNodeList( + nodes = this, + edges = CategoryEdges( + cursor = lastIndex, + node = lastOrNull() + ), + pageInfo = PageInfo( + hasNextPage = false, + hasPreviousPage = false, + startCursor = 0, + endCursor = lastIndex + ), + totalCount = size + ) + } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ChapterType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ChapterType.kt index 1d8f0e2c6..01276a44e 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ChapterType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ChapterType.kt @@ -31,7 +31,7 @@ class ChapterType( val isDownloaded: Boolean, val pageCount: Int // val chapterCount: Int?, -) { +) : Node { constructor(row: ResultRow) : this( row[ChapterTable.id].value, row[ChapterTable.url], @@ -73,7 +73,38 @@ class ChapterType( return dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", mangaId) } - fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("ChapterMetaDataLoader", id) + fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("ChapterMetaDataLoader", id) + } +} + +data class ChapterNodeList( + override val nodes: List, + override val edges: ChapterEdges, + override val pageInfo: PageInfo, + override val totalCount: Int +) : NodeList() { + data class ChapterEdges( + override val cursor: Cursor, + override val node: ChapterType? + ) : Edges() + + companion object { + fun List.toNodeList(): ChapterNodeList { + return ChapterNodeList( + nodes = this, + edges = ChapterEdges( + cursor = lastIndex, + node = lastOrNull() + ), + pageInfo = PageInfo( + hasNextPage = false, + hasPreviousPage = false, + startCursor = 0, + endCursor = lastIndex + ), + totalCount = size + ) + } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/DownloadType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/DownloadType.kt index 9e58d813e..e65adfc61 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/DownloadType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/DownloadType.kt @@ -24,7 +24,7 @@ class DownloadType( var mangaDataClass: MangaDataClass, @GraphQLIgnore var chapterDataClass: ChapterDataClass -) { +) : Node { constructor(downloadChapter: DownloadChapter) : this( downloadChapter.chapter.id, downloadChapter.chapterIndex, @@ -44,3 +44,34 @@ class DownloadType( return ChapterType(chapterDataClass) } } + +data class DownloadNodeList( + override val nodes: List, + override val edges: DownloadEdges, + override val pageInfo: PageInfo, + override val totalCount: Int +) : NodeList() { + data class DownloadEdges( + override val cursor: Cursor, + override val node: DownloadType? + ) : Edges() + + companion object { + fun List.toNodeList(): DownloadNodeList { + return DownloadNodeList( + nodes = this, + edges = DownloadEdges( + cursor = lastIndex, + node = lastOrNull() + ), + pageInfo = PageInfo( + hasNextPage = false, + hasPreviousPage = false, + startCursor = 0, + endCursor = lastIndex + ), + totalCount = size + ) + } + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt index 93bf09b1f..c725687d7 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt @@ -27,7 +27,7 @@ class ExtensionType( val installed: Boolean, val hasUpdate: Boolean, val obsolete: Boolean -) { +) : Node { constructor(row: ResultRow) : this( apkName = row[ExtensionTable.apkName], iconUrl = row[ExtensionTable.iconUrl], @@ -42,7 +42,38 @@ class ExtensionType( obsolete = row[ExtensionTable.isObsolete] ) - fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("SourcesForExtensionDataLoader", pkgName) + fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("SourcesForExtensionDataLoader", pkgName) + } +} + +data class ExtensionNodeList( + override val nodes: List, + override val edges: ExtensionEdges, + override val pageInfo: PageInfo, + override val totalCount: Int +) : NodeList() { + data class ExtensionEdges( + override val cursor: Cursor, + override val node: ExtensionType? + ) : Edges() + + companion object { + fun List.toNodeList(): ExtensionNodeList { + return ExtensionNodeList( + nodes = this, + edges = ExtensionEdges( + cursor = lastIndex, + node = lastOrNull() + ), + pageInfo = PageInfo( + hasNextPage = false, + hasPreviousPage = false, + startCursor = 0, + endCursor = lastIndex + ), + totalCount = size + ) + } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt index 1cc4c3c13..2b20a301f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt @@ -34,7 +34,7 @@ class MangaType( val realUrl: String?, var lastFetchedAt: Long?, var chaptersLastFetchedAt: Long? -) { +) : Node { constructor(row: ResultRow) : this( row[MangaTable.id].value, row[MangaTable.sourceReference], @@ -88,15 +88,46 @@ class MangaType( return Instant.now().epochSecond.minus(chaptersLastFetchedAt!!) } - fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("MangaMetaDataLoader", id) + fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("MangaMetaDataLoader", id) } - fun categories(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("CategoriesForMangaDataLoader", id) + fun categories(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("CategoriesForMangaDataLoader", id) } fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { return dataFetchingEnvironment.getValueFromDataLoader("SourceForMangaDataLoader", id) } } + +data class MangaNodeList( + override val nodes: List, + override val edges: MangaEdges, + override val pageInfo: PageInfo, + override val totalCount: Int +) : NodeList() { + data class MangaEdges( + override val cursor: Cursor, + override val node: MangaType? + ) : Edges() + + companion object { + fun List.toNodeList(): MangaNodeList { + return MangaNodeList( + nodes = this, + edges = MangaEdges( + cursor = lastIndex, + node = lastOrNull() + ), + pageInfo = PageInfo( + hasNextPage = false, + hasPreviousPage = false, + startCursor = 0, + endCursor = lastIndex + ), + totalCount = size + ) + } + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MetaType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MetaType.kt index 2283104e2..fe85a61a1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MetaType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MetaType.kt @@ -7,14 +7,12 @@ import suwayomi.tachidesk.manga.model.table.CategoryMetaTable import suwayomi.tachidesk.manga.model.table.ChapterMetaTable import suwayomi.tachidesk.manga.model.table.MangaMetaTable -typealias MetaType = List - open class MetaItem( val key: String, val value: String, @GraphQLIgnore val ref: Int? -) +) : Node class ChapterMetaItem( private val row: ResultRow @@ -31,3 +29,34 @@ class CategoryMetaItem( class GlobalMetaItem( private val row: ResultRow ) : MetaItem(row[GlobalMetaTable.key], row[GlobalMetaTable.value], null) + +data class MetaNodeList( + override val nodes: List, + override val edges: MetaEdges, + override val pageInfo: PageInfo, + override val totalCount: Int +) : NodeList() { + data class MetaEdges( + override val cursor: Cursor, + override val node: MetaItem? + ) : Edges() + + companion object { + fun List.toNodeList(): MetaNodeList { + return MetaNodeList( + nodes = this, + edges = MetaEdges( + cursor = lastIndex, + node = lastOrNull() + ), + pageInfo = PageInfo( + hasNextPage = false, + hasPreviousPage = false, + startCursor = 0, + endCursor = lastIndex + ), + totalCount = size + ) + } + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/NodeList.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/NodeList.kt new file mode 100644 index 000000000..0d0ced8f1 --- /dev/null +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/NodeList.kt @@ -0,0 +1,40 @@ +package suwayomi.tachidesk.graphql.types + +import com.expediagroup.graphql.generator.annotations.GraphQLDescription + +interface Node + +typealias Cursor = Int + +abstract class NodeList { + @GraphQLDescription("A list of [T] objects.") + abstract val nodes: List + + @GraphQLDescription("A list of edges which contains the [T] and cursor to aid in pagination.") + abstract val edges: Edges + + @GraphQLDescription("Information to aid in pagination.") + abstract val pageInfo: PageInfo + + @GraphQLDescription("The count of all nodes you could get from the connection.") + abstract val totalCount: Int +} + +data class PageInfo( + @GraphQLDescription("When paginating forwards, are there more items?") + val hasNextPage: Boolean, + @GraphQLDescription("When paginating backwards, are there more items?") + val hasPreviousPage: Boolean, + @GraphQLDescription("When paginating backwards, the cursor to continue.") + val startCursor: Cursor, + @GraphQLDescription("When paginating forwards, the cursor to continue.") + val endCursor: Cursor +) + +abstract class Edges { + @GraphQLDescription("A cursor for use in pagination.") + abstract val cursor: Cursor + + @GraphQLDescription("The [T] at the end of the edge.") + abstract val node: Node? +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt index 27d2db96f..2c9e19aa5 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt @@ -29,7 +29,7 @@ class SourceType( val isConfigurable: Boolean, val isNsfw: Boolean, val displayName: String -) { +) : Node { constructor(source: SourceDataClass) : this( id = source.id.toLong(), name = source.name, @@ -52,8 +52,8 @@ class SourceType( displayName = catalogueSource.toString() ) - fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("MangaForSourceDataLoader", id) + fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("MangaForSourceDataLoader", id) } fun extension(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { @@ -75,3 +75,34 @@ fun SourceType(row: ResultRow): SourceType? { return SourceType(row, sourceExtension, catalogueSource) } + +data class SourceNodeList( + override val nodes: List, + override val edges: SourceEdges, + override val pageInfo: PageInfo, + override val totalCount: Int +) : NodeList() { + data class SourceEdges( + override val cursor: Cursor, + override val node: SourceType? + ) : Edges() + + companion object { + fun List.toNodeList(): SourceNodeList { + return SourceNodeList( + nodes = this, + edges = SourceEdges( + cursor = lastIndex, + node = lastOrNull() + ), + pageInfo = PageInfo( + hasNextPage = false, + hasPreviousPage = false, + startCursor = 0, + endCursor = lastIndex + ), + totalCount = size + ) + } + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/UpdatesType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/UpdatesType.kt index 2e7d952c8..bacfd0140 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/UpdatesType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/UpdatesType.kt @@ -12,9 +12,40 @@ import org.jetbrains.exposed.sql.ResultRow class UpdatesType( val manga: MangaType, val chapter: ChapterType -) { +) : Node { constructor(row: ResultRow) : this( manga = MangaType(row), chapter = ChapterType(row) ) } + +data class UpdatesNodeList( + override val nodes: List, + override val edges: UpdatesEdges, + override val pageInfo: PageInfo, + override val totalCount: Int +) : NodeList() { + data class UpdatesEdges( + override val cursor: Cursor, + override val node: UpdatesType? + ) : Edges() + + companion object { + fun List.toNodeList(): UpdatesNodeList { + return UpdatesNodeList( + nodes = this, + edges = UpdatesEdges( + cursor = lastIndex, + node = lastOrNull() + ), + pageInfo = PageInfo( + hasNextPage = false, + hasPreviousPage = false, + startCursor = 0, + endCursor = lastIndex + ), + totalCount = size + ) + } + } +}