Start working on graphql paging

This commit is contained in:
Syer10
2023-04-02 20:15:09 -04:00
parent 607919f40f
commit 52bda2c080
21 changed files with 369 additions and 60 deletions

View File

@@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger
import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.addLogger
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.CategoryType
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
import suwayomi.tachidesk.manga.model.table.CategoryTable import suwayomi.tachidesk.manga.model.table.CategoryTable
@@ -32,9 +34,9 @@ class CategoryDataLoader : KotlinDataLoader<Int, CategoryType> {
} }
} }
class CategoriesForMangaDataLoader : KotlinDataLoader<Int, List<CategoryType>> { class CategoriesForMangaDataLoader : KotlinDataLoader<Int, CategoryNodeList> {
override val dataLoaderName = "CategoriesForMangaDataLoader" override val dataLoaderName = "CategoriesForMangaDataLoader"
override fun getDataLoader(): DataLoader<Int, List<CategoryType>> = DataLoaderFactory.newDataLoader<Int, List<CategoryType>> { ids -> override fun getDataLoader(): DataLoader<Int, CategoryNodeList> = DataLoaderFactory.newDataLoader<Int, CategoryNodeList> { ids ->
future { future {
transaction { transaction {
addLogger(Slf4jSqlDebugLogger) addLogger(Slf4jSqlDebugLogger)
@@ -43,7 +45,7 @@ class CategoriesForMangaDataLoader : KotlinDataLoader<Int, List<CategoryType>> {
.map { Pair(it[CategoryMangaTable.manga].value, CategoryType(it)) } .map { Pair(it[CategoryMangaTable.manga].value, CategoryType(it)) }
.groupBy { it.first } .groupBy { it.first }
.mapValues { it.value.map { pair -> pair.second } } .mapValues { it.value.map { pair -> pair.second } }
ids.map { itemsByRef[it] ?: emptyList() } ids.map { (itemsByRef[it] ?: emptyList()).toNodeList() }
} }
} }
} }

View File

@@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger
import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.addLogger
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.ChapterType
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
@@ -31,16 +33,16 @@ class ChapterDataLoader : KotlinDataLoader<Int, ChapterType> {
} }
} }
class ChaptersForMangaDataLoader : KotlinDataLoader<Int, List<ChapterType>> { class ChaptersForMangaDataLoader : KotlinDataLoader<Int, ChapterNodeList> {
override val dataLoaderName = "ChaptersForMangaDataLoader" override val dataLoaderName = "ChaptersForMangaDataLoader"
override fun getDataLoader(): DataLoader<Int, List<ChapterType>> = DataLoaderFactory.newDataLoader<Int, List<ChapterType>> { ids -> override fun getDataLoader(): DataLoader<Int, ChapterNodeList> = DataLoaderFactory.newDataLoader<Int, ChapterNodeList> { ids ->
future { future {
transaction { transaction {
addLogger(Slf4jSqlDebugLogger) addLogger(Slf4jSqlDebugLogger)
val chaptersByMangaId = ChapterTable.select { ChapterTable.manga inList ids } val chaptersByMangaId = ChapterTable.select { ChapterTable.manga inList ids }
.map { ChapterType(it) } .map { ChapterType(it) }
.groupBy { it.mangaId } .groupBy { it.mangaId }
ids.map { chaptersByMangaId[it] ?: emptyList() } ids.map { (chaptersByMangaId[it] ?: emptyList()).toNodeList() }
} }
} }
} }

View File

@@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger
import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.addLogger
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.MangaType
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
@@ -32,9 +34,9 @@ class MangaDataLoader : KotlinDataLoader<Int, MangaType> {
} }
} }
class MangaForCategoryDataLoader : KotlinDataLoader<Int, List<MangaType>> { class MangaForCategoryDataLoader : KotlinDataLoader<Int, MangaNodeList> {
override val dataLoaderName = "MangaForCategoryDataLoader" override val dataLoaderName = "MangaForCategoryDataLoader"
override fun getDataLoader(): DataLoader<Int, List<MangaType>> = DataLoaderFactory.newDataLoader<Int, List<MangaType>> { ids -> override fun getDataLoader(): DataLoader<Int, MangaNodeList> = DataLoaderFactory.newDataLoader<Int, MangaNodeList> { ids ->
future { future {
transaction { transaction {
addLogger(Slf4jSqlDebugLogger) addLogger(Slf4jSqlDebugLogger)
@@ -42,7 +44,7 @@ class MangaForCategoryDataLoader : KotlinDataLoader<Int, List<MangaType>> {
.map { Pair(it[CategoryMangaTable.category].value, MangaType(it)) } .map { Pair(it[CategoryMangaTable.category].value, MangaType(it)) }
.groupBy { it.first } .groupBy { it.first }
.mapValues { it.value.map { pair -> pair.second } } .mapValues { it.value.map { pair -> pair.second } }
ids.map { itemsByRef[it] ?: emptyList() } ids.map { (itemsByRef[it] ?: emptyList()).toNodeList() }
} }
} }
} }

View File

@@ -13,7 +13,8 @@ import suwayomi.tachidesk.graphql.types.ChapterMetaItem
import suwayomi.tachidesk.graphql.types.GlobalMetaItem import suwayomi.tachidesk.graphql.types.GlobalMetaItem
import suwayomi.tachidesk.graphql.types.MangaMetaItem import suwayomi.tachidesk.graphql.types.MangaMetaItem
import suwayomi.tachidesk.graphql.types.MetaItem 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.ChapterMetaTable
import suwayomi.tachidesk.manga.model.table.MangaMetaTable import suwayomi.tachidesk.manga.model.table.MangaMetaTable
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
@@ -33,46 +34,46 @@ class GlobalMetaDataLoader : KotlinDataLoader<String, MetaItem?> {
} }
} }
class ChapterMetaDataLoader : KotlinDataLoader<Int, MetaType> { class ChapterMetaDataLoader : KotlinDataLoader<Int, MetaNodeList> {
override val dataLoaderName = "ChapterMetaDataLoader" override val dataLoaderName = "ChapterMetaDataLoader"
override fun getDataLoader(): DataLoader<Int, MetaType> = DataLoaderFactory.newDataLoader<Int, MetaType> { ids -> override fun getDataLoader(): DataLoader<Int, MetaNodeList> = DataLoaderFactory.newDataLoader<Int, MetaNodeList> { ids ->
future { future {
transaction { transaction {
addLogger(Slf4jSqlDebugLogger) addLogger(Slf4jSqlDebugLogger)
val metasByRefId = ChapterMetaTable.select { ChapterMetaTable.ref inList ids } val metasByRefId = ChapterMetaTable.select { ChapterMetaTable.ref inList ids }
.map { ChapterMetaItem(it) } .map { ChapterMetaItem(it) }
.groupBy { it.ref } .groupBy { it.ref }
ids.map { metasByRefId[it] ?: emptyList() } ids.map { (metasByRefId[it] ?: emptyList()).toNodeList() }
} }
} }
} }
} }
class MangaMetaDataLoader : KotlinDataLoader<Int, MetaType> { class MangaMetaDataLoader : KotlinDataLoader<Int, MetaNodeList> {
override val dataLoaderName = "MangaMetaDataLoader" override val dataLoaderName = "MangaMetaDataLoader"
override fun getDataLoader(): DataLoader<Int, MetaType> = DataLoaderFactory.newDataLoader<Int, MetaType> { ids -> override fun getDataLoader(): DataLoader<Int, MetaNodeList> = DataLoaderFactory.newDataLoader<Int, MetaNodeList> { ids ->
future { future {
transaction { transaction {
addLogger(Slf4jSqlDebugLogger) addLogger(Slf4jSqlDebugLogger)
val metasByRefId = MangaMetaTable.select { MangaMetaTable.ref inList ids } val metasByRefId = MangaMetaTable.select { MangaMetaTable.ref inList ids }
.map { MangaMetaItem(it) } .map { MangaMetaItem(it) }
.groupBy { it.ref } .groupBy { it.ref }
ids.map { metasByRefId[it] ?: emptyList() } ids.map { (metasByRefId[it] ?: emptyList()).toNodeList() }
} }
} }
} }
} }
class CategoryMetaDataLoader : KotlinDataLoader<Int, MetaType> { class CategoryMetaDataLoader : KotlinDataLoader<Int, MetaNodeList> {
override val dataLoaderName = "CategoryMetaDataLoader" override val dataLoaderName = "CategoryMetaDataLoader"
override fun getDataLoader(): DataLoader<Int, MetaType> = DataLoaderFactory.newDataLoader<Int, MetaType> { ids -> override fun getDataLoader(): DataLoader<Int, MetaNodeList> = DataLoaderFactory.newDataLoader<Int, MetaNodeList> { ids ->
future { future {
transaction { transaction {
addLogger(Slf4jSqlDebugLogger) addLogger(Slf4jSqlDebugLogger)
val metasByRefId = MangaMetaTable.select { MangaMetaTable.ref inList ids } val metasByRefId = MangaMetaTable.select { MangaMetaTable.ref inList ids }
.map { CategoryMetaItem(it) } .map { CategoryMetaItem(it) }
.groupBy { it.ref } .groupBy { it.ref }
ids.map { metasByRefId[it] ?: emptyList() } ids.map { (metasByRefId[it] ?: emptyList()).toNodeList() }
} }
} }
} }

View File

@@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger
import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.addLogger
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.SourceType
import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
@@ -63,9 +65,9 @@ class SourceForMangaDataLoader : KotlinDataLoader<Int, SourceType?> {
} }
} }
class SourcesForExtensionDataLoader : KotlinDataLoader<String, List<SourceType>> { class SourcesForExtensionDataLoader : KotlinDataLoader<String, SourceNodeList> {
override val dataLoaderName = "SourcesForExtensionDataLoader" override val dataLoaderName = "SourcesForExtensionDataLoader"
override fun getDataLoader(): DataLoader<String, List<SourceType>> = DataLoaderFactory.newDataLoader { ids -> override fun getDataLoader(): DataLoader<String, SourceNodeList> = DataLoaderFactory.newDataLoader { ids ->
future { future {
transaction { transaction {
addLogger(Slf4jSqlDebugLogger) addLogger(Slf4jSqlDebugLogger)
@@ -76,7 +78,7 @@ class SourcesForExtensionDataLoader : KotlinDataLoader<String, List<SourceType>>
.groupBy { it.first } .groupBy { it.first }
.mapValues { it.value.mapNotNull { pair -> pair.second } } .mapValues { it.value.mapNotNull { pair -> pair.second } }
ids.map { sourcesByExtensionPkg[it] ?: emptyList() } ids.map { (sourcesByExtensionPkg[it] ?: emptyList()).toNodeList() }
} }
} }
} }

View File

@@ -13,6 +13,8 @@ import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.andWhere
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.CategoryType
import suwayomi.tachidesk.manga.model.table.CategoryTable import suwayomi.tachidesk.manga.model.table.CategoryTable
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@@ -48,7 +50,7 @@ class CategoryQuery {
val query: String? = null val query: String? = null
) )
fun categories(input: CategoriesQueryInput? = null): List<CategoryType> { fun categories(input: CategoriesQueryInput? = null): CategoryNodeList {
val results = transaction { val results = transaction {
val res = CategoryTable.selectAll() val res = CategoryTable.selectAll()
@@ -72,6 +74,6 @@ class CategoryQuery {
res.toList() res.toList()
} }
return results.map { CategoryType(it) } return results.map { CategoryType(it) }.toNodeList()
} }
} }

View File

@@ -13,6 +13,8 @@ import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.andWhere
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.ChapterType
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@@ -56,7 +58,7 @@ class ChapterQuery {
val count: Int? = null val count: Int? = null
) )
fun chapters(input: ChapterQueryInput? = null): List<ChapterType> { fun chapters(input: ChapterQueryInput? = null): ChapterNodeList {
val results = transaction { val results = transaction {
var res = ChapterTable.selectAll() var res = ChapterTable.selectAll()
@@ -97,6 +99,6 @@ class ChapterQuery {
res.toList() res.toList()
} }
return results.map { ChapterType(it) } return results.map { ChapterType(it) }.toNodeList() // todo paged
} }
} }

View File

@@ -11,6 +11,8 @@ import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
import graphql.schema.DataFetchingEnvironment import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.ExtensionType
import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.ExtensionTable
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@@ -37,11 +39,11 @@ class ExtensionQuery {
return dataFetchingEnvironment.getValueFromDataLoader<String, ExtensionType>("ExtensionDataLoader", pkgName) return dataFetchingEnvironment.getValueFromDataLoader<String, ExtensionType>("ExtensionDataLoader", pkgName)
} }
fun extensions(): List<ExtensionType> { fun extensions(): ExtensionNodeList {
val results = transaction { val results = transaction {
ExtensionTable.selectAll().toList() ExtensionTable.selectAll().toList()
} }
return results.map { ExtensionType(it) } return results.map { ExtensionType(it) }.toNodeList()
} }
} }

View File

@@ -16,6 +16,8 @@ import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.queries.util.GreaterOrLessThanLong import suwayomi.tachidesk.graphql.queries.util.GreaterOrLessThanLong
import suwayomi.tachidesk.graphql.queries.util.andWhereGreaterOrLessThen 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.graphql.types.MangaType
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
@@ -60,7 +62,7 @@ class MangaQuery {
val count: Int? = null val count: Int? = null
) )
fun mangas(input: MangaQueryInput? = null): List<MangaType> { fun mangas(input: MangaQueryInput? = null): MangaNodeList {
val results = transaction { val results = transaction {
var res = MangaTable.selectAll() var res = MangaTable.selectAll()
@@ -102,6 +104,6 @@ class MangaQuery {
res.toList() res.toList()
} }
return results.map { MangaType(it) } return results.map { MangaType(it) }.toNodeList() // todo paged
} }
} }

View File

@@ -14,6 +14,8 @@ import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.global.model.table.GlobalMetaTable import suwayomi.tachidesk.global.model.table.GlobalMetaTable
import suwayomi.tachidesk.graphql.types.GlobalMetaItem import suwayomi.tachidesk.graphql.types.GlobalMetaItem
import suwayomi.tachidesk.graphql.types.MetaItem 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 import java.util.concurrent.CompletableFuture
/** /**
@@ -30,11 +32,11 @@ class MetaQuery {
return dataFetchingEnvironment.getValueFromDataLoader<String, MetaItem?>("GlobalMetaDataLoader", key) return dataFetchingEnvironment.getValueFromDataLoader<String, MetaItem?>("GlobalMetaDataLoader", key)
} }
fun metas(): List<GlobalMetaItem> { fun metas(): MetaNodeList {
val results = transaction { val results = transaction {
GlobalMetaTable.selectAll().toList() GlobalMetaTable.selectAll().toList()
} }
return results.map { GlobalMetaItem(it) } return results.map { GlobalMetaItem(it) }.toNodeList()
} }
} }

View File

@@ -11,6 +11,8 @@ import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
import graphql.schema.DataFetchingEnvironment import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.SourceType
import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.manga.model.table.SourceTable
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@@ -33,11 +35,11 @@ class SourceQuery {
return dataFetchingEnvironment.getValueFromDataLoader<Long, SourceType?>("SourceDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Long, SourceType?>("SourceDataLoader", id)
} }
fun sources(): List<SourceType> { fun sources(): SourceNodeList {
val results = transaction { val results = transaction {
SourceTable.selectAll().toList().mapNotNull { SourceType(it) } SourceTable.selectAll().toList().mapNotNull { SourceType(it) }
} }
return results return results.toNodeList()
} }
} }

View File

@@ -11,6 +11,8 @@ import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction 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.graphql.types.UpdatesType
import suwayomi.tachidesk.manga.model.dataclass.PaginationFactor import suwayomi.tachidesk.manga.model.dataclass.PaginationFactor
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
@@ -31,7 +33,7 @@ class UpdatesQuery {
val page: Int val page: Int
) )
fun updates(input: UpdatesQueryInput): List<UpdatesType> { fun updates(input: UpdatesQueryInput): UpdatesNodeList {
val results = transaction { val results = transaction {
ChapterTable.innerJoin(MangaTable) ChapterTable.innerJoin(MangaTable)
.select { (MangaTable.inLibrary eq true) and (ChapterTable.fetchedAt greater MangaTable.inLibraryAt) } .select { (MangaTable.inLibrary eq true) and (ChapterTable.fetchedAt greater MangaTable.inLibraryAt) }
@@ -42,6 +44,6 @@ class UpdatesQuery {
} }
} }
return results return results.toNodeList() // todo paged
} }
} }

View File

@@ -18,7 +18,7 @@ class CategoryType(
val order: Int, val order: Int,
val name: String, val name: String,
val default: Boolean val default: Boolean
) { ) : Node {
constructor(row: ResultRow) : this( constructor(row: ResultRow) : this(
row[CategoryTable.id].value, row[CategoryTable.id].value,
row[CategoryTable.order], row[CategoryTable.order],
@@ -26,11 +26,42 @@ class CategoryType(
row[CategoryTable.isDefault] row[CategoryTable.isDefault]
) )
fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<MangaType>> { fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MangaNodeList> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, List<MangaType>>("MangaForCategoryDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Int, MangaNodeList>("MangaForCategoryDataLoader", id)
} }
fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MetaType> { fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MetaNodeList> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, MetaType>("CategoryMetaDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Int, MetaNodeList>("CategoryMetaDataLoader", id)
}
}
data class CategoryNodeList(
override val nodes: List<CategoryType>,
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<CategoryType>.toNodeList(): CategoryNodeList {
return CategoryNodeList(
nodes = this,
edges = CategoryEdges(
cursor = lastIndex,
node = lastOrNull()
),
pageInfo = PageInfo(
hasNextPage = false,
hasPreviousPage = false,
startCursor = 0,
endCursor = lastIndex
),
totalCount = size
)
}
} }
} }

View File

@@ -31,7 +31,7 @@ class ChapterType(
val isDownloaded: Boolean, val isDownloaded: Boolean,
val pageCount: Int val pageCount: Int
// val chapterCount: Int?, // val chapterCount: Int?,
) { ) : Node {
constructor(row: ResultRow) : this( constructor(row: ResultRow) : this(
row[ChapterTable.id].value, row[ChapterTable.id].value,
row[ChapterTable.url], row[ChapterTable.url],
@@ -73,7 +73,38 @@ class ChapterType(
return dataFetchingEnvironment.getValueFromDataLoader<Int, MangaType>("MangaDataLoader", mangaId) return dataFetchingEnvironment.getValueFromDataLoader<Int, MangaType>("MangaDataLoader", mangaId)
} }
fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MetaType> { fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MetaNodeList> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, MetaType>("ChapterMetaDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Int, MetaNodeList>("ChapterMetaDataLoader", id)
}
}
data class ChapterNodeList(
override val nodes: List<ChapterType>,
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<ChapterType>.toNodeList(): ChapterNodeList {
return ChapterNodeList(
nodes = this,
edges = ChapterEdges(
cursor = lastIndex,
node = lastOrNull()
),
pageInfo = PageInfo(
hasNextPage = false,
hasPreviousPage = false,
startCursor = 0,
endCursor = lastIndex
),
totalCount = size
)
}
} }
} }

View File

@@ -24,7 +24,7 @@ class DownloadType(
var mangaDataClass: MangaDataClass, var mangaDataClass: MangaDataClass,
@GraphQLIgnore @GraphQLIgnore
var chapterDataClass: ChapterDataClass var chapterDataClass: ChapterDataClass
) { ) : Node {
constructor(downloadChapter: DownloadChapter) : this( constructor(downloadChapter: DownloadChapter) : this(
downloadChapter.chapter.id, downloadChapter.chapter.id,
downloadChapter.chapterIndex, downloadChapter.chapterIndex,
@@ -44,3 +44,34 @@ class DownloadType(
return ChapterType(chapterDataClass) return ChapterType(chapterDataClass)
} }
} }
data class DownloadNodeList(
override val nodes: List<DownloadType>,
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<DownloadType>.toNodeList(): DownloadNodeList {
return DownloadNodeList(
nodes = this,
edges = DownloadEdges(
cursor = lastIndex,
node = lastOrNull()
),
pageInfo = PageInfo(
hasNextPage = false,
hasPreviousPage = false,
startCursor = 0,
endCursor = lastIndex
),
totalCount = size
)
}
}
}

View File

@@ -27,7 +27,7 @@ class ExtensionType(
val installed: Boolean, val installed: Boolean,
val hasUpdate: Boolean, val hasUpdate: Boolean,
val obsolete: Boolean val obsolete: Boolean
) { ) : Node {
constructor(row: ResultRow) : this( constructor(row: ResultRow) : this(
apkName = row[ExtensionTable.apkName], apkName = row[ExtensionTable.apkName],
iconUrl = row[ExtensionTable.iconUrl], iconUrl = row[ExtensionTable.iconUrl],
@@ -42,7 +42,38 @@ class ExtensionType(
obsolete = row[ExtensionTable.isObsolete] obsolete = row[ExtensionTable.isObsolete]
) )
fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<SourceType>> { fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceNodeList> {
return dataFetchingEnvironment.getValueFromDataLoader<String, List<SourceType>>("SourcesForExtensionDataLoader", pkgName) return dataFetchingEnvironment.getValueFromDataLoader<String, SourceNodeList>("SourcesForExtensionDataLoader", pkgName)
}
}
data class ExtensionNodeList(
override val nodes: List<ExtensionType>,
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<ExtensionType>.toNodeList(): ExtensionNodeList {
return ExtensionNodeList(
nodes = this,
edges = ExtensionEdges(
cursor = lastIndex,
node = lastOrNull()
),
pageInfo = PageInfo(
hasNextPage = false,
hasPreviousPage = false,
startCursor = 0,
endCursor = lastIndex
),
totalCount = size
)
}
} }
} }

View File

@@ -34,7 +34,7 @@ class MangaType(
val realUrl: String?, val realUrl: String?,
var lastFetchedAt: Long?, var lastFetchedAt: Long?,
var chaptersLastFetchedAt: Long? var chaptersLastFetchedAt: Long?
) { ) : Node {
constructor(row: ResultRow) : this( constructor(row: ResultRow) : this(
row[MangaTable.id].value, row[MangaTable.id].value,
row[MangaTable.sourceReference], row[MangaTable.sourceReference],
@@ -88,15 +88,46 @@ class MangaType(
return Instant.now().epochSecond.minus(chaptersLastFetchedAt!!) return Instant.now().epochSecond.minus(chaptersLastFetchedAt!!)
} }
fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MetaType> { fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MetaNodeList> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, MetaType>("MangaMetaDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Int, MetaNodeList>("MangaMetaDataLoader", id)
} }
fun categories(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<CategoryType>> { fun categories(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<CategoryNodeList> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, List<CategoryType>>("CategoriesForMangaDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Int, CategoryNodeList>("CategoriesForMangaDataLoader", id)
} }
fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceType?> { fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceType?> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, SourceType?>("SourceForMangaDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Int, SourceType?>("SourceForMangaDataLoader", id)
} }
} }
data class MangaNodeList(
override val nodes: List<MangaType>,
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<MangaType>.toNodeList(): MangaNodeList {
return MangaNodeList(
nodes = this,
edges = MangaEdges(
cursor = lastIndex,
node = lastOrNull()
),
pageInfo = PageInfo(
hasNextPage = false,
hasPreviousPage = false,
startCursor = 0,
endCursor = lastIndex
),
totalCount = size
)
}
}
}

View File

@@ -7,14 +7,12 @@ import suwayomi.tachidesk.manga.model.table.CategoryMetaTable
import suwayomi.tachidesk.manga.model.table.ChapterMetaTable import suwayomi.tachidesk.manga.model.table.ChapterMetaTable
import suwayomi.tachidesk.manga.model.table.MangaMetaTable import suwayomi.tachidesk.manga.model.table.MangaMetaTable
typealias MetaType = List<MetaItem>
open class MetaItem( open class MetaItem(
val key: String, val key: String,
val value: String, val value: String,
@GraphQLIgnore @GraphQLIgnore
val ref: Int? val ref: Int?
) ) : Node
class ChapterMetaItem( class ChapterMetaItem(
private val row: ResultRow private val row: ResultRow
@@ -31,3 +29,34 @@ class CategoryMetaItem(
class GlobalMetaItem( class GlobalMetaItem(
private val row: ResultRow private val row: ResultRow
) : MetaItem(row[GlobalMetaTable.key], row[GlobalMetaTable.value], null) ) : MetaItem(row[GlobalMetaTable.key], row[GlobalMetaTable.value], null)
data class MetaNodeList(
override val nodes: List<MetaItem>,
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<MetaItem>.toNodeList(): MetaNodeList {
return MetaNodeList(
nodes = this,
edges = MetaEdges(
cursor = lastIndex,
node = lastOrNull()
),
pageInfo = PageInfo(
hasNextPage = false,
hasPreviousPage = false,
startCursor = 0,
endCursor = lastIndex
),
totalCount = size
)
}
}
}

View File

@@ -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<Node>
@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?
}

View File

@@ -29,7 +29,7 @@ class SourceType(
val isConfigurable: Boolean, val isConfigurable: Boolean,
val isNsfw: Boolean, val isNsfw: Boolean,
val displayName: String val displayName: String
) { ) : Node {
constructor(source: SourceDataClass) : this( constructor(source: SourceDataClass) : this(
id = source.id.toLong(), id = source.id.toLong(),
name = source.name, name = source.name,
@@ -52,8 +52,8 @@ class SourceType(
displayName = catalogueSource.toString() displayName = catalogueSource.toString()
) )
fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<MangaType>> { fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MangaNodeList> {
return dataFetchingEnvironment.getValueFromDataLoader<Long, List<MangaType>>("MangaForSourceDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Long, MangaNodeList>("MangaForSourceDataLoader", id)
} }
fun extension(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<ExtensionType> { fun extension(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<ExtensionType> {
@@ -75,3 +75,34 @@ fun SourceType(row: ResultRow): SourceType? {
return SourceType(row, sourceExtension, catalogueSource) return SourceType(row, sourceExtension, catalogueSource)
} }
data class SourceNodeList(
override val nodes: List<SourceType>,
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<SourceType>.toNodeList(): SourceNodeList {
return SourceNodeList(
nodes = this,
edges = SourceEdges(
cursor = lastIndex,
node = lastOrNull()
),
pageInfo = PageInfo(
hasNextPage = false,
hasPreviousPage = false,
startCursor = 0,
endCursor = lastIndex
),
totalCount = size
)
}
}
}

View File

@@ -12,9 +12,40 @@ import org.jetbrains.exposed.sql.ResultRow
class UpdatesType( class UpdatesType(
val manga: MangaType, val manga: MangaType,
val chapter: ChapterType val chapter: ChapterType
) { ) : Node {
constructor(row: ResultRow) : this( constructor(row: ResultRow) : this(
manga = MangaType(row), manga = MangaType(row),
chapter = ChapterType(row) chapter = ChapterType(row)
) )
} }
data class UpdatesNodeList(
override val nodes: List<UpdatesType>,
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<UpdatesType>.toNodeList(): UpdatesNodeList {
return UpdatesNodeList(
nodes = this,
edges = UpdatesEdges(
cursor = lastIndex,
node = lastOrNull()
),
pageInfo = PageInfo(
hasNextPage = false,
hasPreviousPage = false,
startCursor = 0,
endCursor = lastIndex
),
totalCount = size
)
}
}
}