Support partial mutation responses (#954)

In case e.g. a mutation was made which looked like this

myMutation {
  mutationA { ... }
  mutationB { ... }
  mutationC { ... }
}

and mutation A and B succeeded while mutation C failed, the response only included the error of C and the successful mutation data response of A and B was missing
This commit is contained in:
schroda
2024-06-03 02:33:17 +02:00
committed by GitHub
parent fc2f5ffdf9
commit ff23f58a4f
11 changed files with 737 additions and 593 deletions

View File

@@ -0,0 +1,25 @@
package suwayomi.tachidesk.graphql
import com.expediagroup.graphql.server.extensions.toGraphQLError
import graphql.execution.DataFetcherResult
import mu.KotlinLogging
val logger = KotlinLogging.logger { }
inline fun <T> asDataFetcherResult(block: () -> T): DataFetcherResult<T?> {
val result =
runCatching {
block()
}
if (result.isFailure) {
logger.error(result.exceptionOrNull()) { "asDataFetcherResult: failed due to" }
return DataFetcherResult.newResult<T?>()
.error(result.exceptionOrNull()?.toGraphQLError())
.build()
}
return DataFetcherResult.newResult<T?>()
.data(result.getOrNull())
.build()
}

View File

@@ -1,5 +1,6 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
import org.jetbrains.exposed.sql.SqlExpressionBuilder.minus import org.jetbrains.exposed.sql.SqlExpressionBuilder.minus
@@ -12,6 +13,7 @@ import org.jetbrains.exposed.sql.select
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 org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.CategoryMetaType import suwayomi.tachidesk.graphql.types.CategoryMetaType
import suwayomi.tachidesk.graphql.types.CategoryType import suwayomi.tachidesk.graphql.types.CategoryType
import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.graphql.types.MangaType
@@ -36,12 +38,14 @@ class CategoryMutation {
val meta: CategoryMetaType, val meta: CategoryMetaType,
) )
fun setCategoryMeta(input: SetCategoryMetaInput): SetCategoryMetaPayload { fun setCategoryMeta(input: SetCategoryMetaInput): DataFetcherResult<SetCategoryMetaPayload?> {
return asDataFetcherResult {
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
Category.modifyMeta(meta.categoryId, meta.key, meta.value) Category.modifyMeta(meta.categoryId, meta.key, meta.value)
return SetCategoryMetaPayload(clientMutationId, meta) SetCategoryMetaPayload(clientMutationId, meta)
}
} }
data class DeleteCategoryMetaInput( data class DeleteCategoryMetaInput(
@@ -56,7 +60,8 @@ class CategoryMutation {
val category: CategoryType, val category: CategoryType,
) )
fun deleteCategoryMeta(input: DeleteCategoryMetaInput): DeleteCategoryMetaPayload { fun deleteCategoryMeta(input: DeleteCategoryMetaInput): DataFetcherResult<DeleteCategoryMetaPayload?> {
return asDataFetcherResult {
val (clientMutationId, categoryId, key) = input val (clientMutationId, categoryId, key) = input
val (meta, category) = val (meta, category) =
@@ -79,7 +84,8 @@ class CategoryMutation {
} to category } to category
} }
return DeleteCategoryMetaPayload(clientMutationId, meta, category) DeleteCategoryMetaPayload(clientMutationId, meta, category)
}
} }
data class UpdateCategoryPatch( data class UpdateCategoryPatch(
@@ -147,7 +153,8 @@ class CategoryMutation {
} }
} }
fun updateCategory(input: UpdateCategoryInput): UpdateCategoryPayload { fun updateCategory(input: UpdateCategoryInput): DataFetcherResult<UpdateCategoryPayload?> {
return asDataFetcherResult {
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
updateCategories(listOf(id), patch) updateCategories(listOf(id), patch)
@@ -157,13 +164,15 @@ class CategoryMutation {
CategoryType(CategoryTable.select { CategoryTable.id eq id }.first()) CategoryType(CategoryTable.select { CategoryTable.id eq id }.first())
} }
return UpdateCategoryPayload( UpdateCategoryPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
category = category, category = category,
) )
} }
}
fun updateCategories(input: UpdateCategoriesInput): UpdateCategoriesPayload { fun updateCategories(input: UpdateCategoriesInput): DataFetcherResult<UpdateCategoriesPayload?> {
return asDataFetcherResult {
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
updateCategories(ids, patch) updateCategories(ids, patch)
@@ -173,11 +182,12 @@ class CategoryMutation {
CategoryTable.select { CategoryTable.id inList ids }.map { CategoryType(it) } CategoryTable.select { CategoryTable.id inList ids }.map { CategoryType(it) }
} }
return UpdateCategoriesPayload( UpdateCategoriesPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
categories = categories, categories = categories,
) )
} }
}
data class UpdateCategoryOrderPayload( data class UpdateCategoryOrderPayload(
val clientMutationId: String?, val clientMutationId: String?,
@@ -190,7 +200,8 @@ class CategoryMutation {
val position: Int, val position: Int,
) )
fun updateCategoryOrder(input: UpdateCategoryOrderInput): UpdateCategoryOrderPayload { fun updateCategoryOrder(input: UpdateCategoryOrderInput): DataFetcherResult<UpdateCategoryOrderPayload?> {
return asDataFetcherResult {
val (clientMutationId, categoryId, position) = input val (clientMutationId, categoryId, position) = input
require(position > 0) { require(position > 0) {
"'order' must not be <= 0" "'order' must not be <= 0"
@@ -226,11 +237,12 @@ class CategoryMutation {
CategoryTable.selectAll().orderBy(CategoryTable.order).map { CategoryType(it) } CategoryTable.selectAll().orderBy(CategoryTable.order).map { CategoryType(it) }
} }
return UpdateCategoryOrderPayload( UpdateCategoryOrderPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
categories = categories, categories = categories,
) )
} }
}
data class CreateCategoryInput( data class CreateCategoryInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -246,7 +258,8 @@ class CategoryMutation {
val category: CategoryType, val category: CategoryType,
) )
fun createCategory(input: CreateCategoryInput): CreateCategoryPayload { fun createCategory(input: CreateCategoryInput): DataFetcherResult<CreateCategoryPayload?> {
return asDataFetcherResult {
val (clientMutationId, name, order, default, includeInUpdate, includeInDownload) = input val (clientMutationId, name, order, default, includeInUpdate, includeInDownload) = input
transaction { transaction {
require(CategoryTable.select { CategoryTable.name eq input.name }.isEmpty()) { require(CategoryTable.select { CategoryTable.name eq input.name }.isEmpty()) {
@@ -290,7 +303,8 @@ class CategoryMutation {
CategoryType(CategoryTable.select { CategoryTable.id eq id }.first()) CategoryType(CategoryTable.select { CategoryTable.id eq id }.first())
} }
return CreateCategoryPayload(clientMutationId, category) CreateCategoryPayload(clientMutationId, category)
}
} }
data class DeleteCategoryInput( data class DeleteCategoryInput(
@@ -304,10 +318,11 @@ class CategoryMutation {
val mangas: List<MangaType>, val mangas: List<MangaType>,
) )
fun deleteCategory(input: DeleteCategoryInput): DeleteCategoryPayload { fun deleteCategory(input: DeleteCategoryInput): DataFetcherResult<DeleteCategoryPayload?> {
return asDataFetcherResult {
val (clientMutationId, categoryId) = input val (clientMutationId, categoryId) = input
if (categoryId == 0) { // Don't delete default category if (categoryId == 0) { // Don't delete default category
return DeleteCategoryPayload( return@asDataFetcherResult DeleteCategoryPayload(
clientMutationId, clientMutationId,
null, null,
emptyList(), emptyList(),
@@ -338,7 +353,8 @@ class CategoryMutation {
} to mangas } to mangas
} }
return DeleteCategoryPayload(clientMutationId, category, mangas) DeleteCategoryPayload(clientMutationId, category, mangas)
}
} }
data class UpdateMangaCategoriesPatch( data class UpdateMangaCategoriesPatch(
@@ -406,7 +422,8 @@ class CategoryMutation {
} }
} }
fun updateMangaCategories(input: UpdateMangaCategoriesInput): UpdateMangaCategoriesPayload { fun updateMangaCategories(input: UpdateMangaCategoriesInput): DataFetcherResult<UpdateMangaCategoriesPayload?> {
return asDataFetcherResult {
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
updateMangas(listOf(id), patch) updateMangas(listOf(id), patch)
@@ -416,13 +433,15 @@ class CategoryMutation {
MangaType(MangaTable.select { MangaTable.id eq id }.first()) MangaType(MangaTable.select { MangaTable.id eq id }.first())
} }
return UpdateMangaCategoriesPayload( UpdateMangaCategoriesPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
manga = manga, manga = manga,
) )
} }
}
fun updateMangasCategories(input: UpdateMangasCategoriesInput): UpdateMangasCategoriesPayload { fun updateMangasCategories(input: UpdateMangasCategoriesInput): DataFetcherResult<UpdateMangasCategoriesPayload?> {
return asDataFetcherResult {
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
updateMangas(ids, patch) updateMangas(ids, patch)
@@ -432,9 +451,10 @@ class CategoryMutation {
MangaTable.select { MangaTable.id inList ids }.map { MangaType(it) } MangaTable.select { MangaTable.id inList ids }.map { MangaType(it) }
} }
return UpdateMangasCategoriesPayload( UpdateMangasCategoriesPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
mangas = mangas, mangas = mangas,
) )
} }
} }
}

View File

@@ -1,5 +1,6 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult
import org.jetbrains.exposed.dao.id.EntityID import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
@@ -7,6 +8,7 @@ import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.statements.BatchUpdateStatement import org.jetbrains.exposed.sql.statements.BatchUpdateStatement
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.ChapterMetaType import suwayomi.tachidesk.graphql.types.ChapterMetaType
import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.graphql.types.ChapterType
import suwayomi.tachidesk.manga.impl.Chapter import suwayomi.tachidesk.manga.impl.Chapter
@@ -89,7 +91,8 @@ class ChapterMutation {
} }
} }
fun updateChapter(input: UpdateChapterInput): UpdateChapterPayload { fun updateChapter(input: UpdateChapterInput): DataFetcherResult<UpdateChapterPayload?> {
return asDataFetcherResult {
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
updateChapters(listOf(id), patch) updateChapters(listOf(id), patch)
@@ -99,13 +102,15 @@ class ChapterMutation {
ChapterType(ChapterTable.select { ChapterTable.id eq id }.first()) ChapterType(ChapterTable.select { ChapterTable.id eq id }.first())
} }
return UpdateChapterPayload( UpdateChapterPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
chapter = chapter, chapter = chapter,
) )
} }
}
fun updateChapters(input: UpdateChaptersInput): UpdateChaptersPayload { fun updateChapters(input: UpdateChaptersInput): DataFetcherResult<UpdateChaptersPayload?> {
return asDataFetcherResult {
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
updateChapters(ids, patch) updateChapters(ids, patch)
@@ -115,11 +120,12 @@ class ChapterMutation {
ChapterTable.select { ChapterTable.id inList ids }.map { ChapterType(it) } ChapterTable.select { ChapterTable.id inList ids }.map { ChapterType(it) }
} }
return UpdateChaptersPayload( UpdateChaptersPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
chapters = chapters, chapters = chapters,
) )
} }
}
data class FetchChaptersInput( data class FetchChaptersInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -131,12 +137,13 @@ class ChapterMutation {
val chapters: List<ChapterType>, val chapters: List<ChapterType>,
) )
fun fetchChapters(input: FetchChaptersInput): CompletableFuture<FetchChaptersPayload> { fun fetchChapters(input: FetchChaptersInput): CompletableFuture<DataFetcherResult<FetchChaptersPayload?>> {
val (clientMutationId, mangaId) = input val (clientMutationId, mangaId) = input
return future { return future {
asDataFetcherResult {
Chapter.fetchChapterList(mangaId) Chapter.fetchChapterList(mangaId)
}.thenApply {
val chapters = val chapters =
transaction { transaction {
ChapterTable.select { ChapterTable.manga eq mangaId } ChapterTable.select { ChapterTable.manga eq mangaId }
@@ -150,6 +157,7 @@ class ChapterMutation {
) )
} }
} }
}
data class SetChapterMetaInput( data class SetChapterMetaInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -161,12 +169,14 @@ class ChapterMutation {
val meta: ChapterMetaType, val meta: ChapterMetaType,
) )
fun setChapterMeta(input: SetChapterMetaInput): SetChapterMetaPayload { fun setChapterMeta(input: SetChapterMetaInput): DataFetcherResult<SetChapterMetaPayload?> {
return asDataFetcherResult {
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
Chapter.modifyChapterMeta(meta.chapterId, meta.key, meta.value) Chapter.modifyChapterMeta(meta.chapterId, meta.key, meta.value)
return SetChapterMetaPayload(clientMutationId, meta) SetChapterMetaPayload(clientMutationId, meta)
}
} }
data class DeleteChapterMetaInput( data class DeleteChapterMetaInput(
@@ -181,7 +191,8 @@ class ChapterMutation {
val chapter: ChapterType, val chapter: ChapterType,
) )
fun deleteChapterMeta(input: DeleteChapterMetaInput): DeleteChapterMetaPayload { fun deleteChapterMeta(input: DeleteChapterMetaInput): DataFetcherResult<DeleteChapterMetaPayload?> {
return asDataFetcherResult {
val (clientMutationId, chapterId, key) = input val (clientMutationId, chapterId, key) = input
val (meta, chapter) = val (meta, chapter) =
@@ -204,7 +215,8 @@ class ChapterMutation {
} to chapter } to chapter
} }
return DeleteChapterMetaPayload(clientMutationId, meta, chapter) DeleteChapterMetaPayload(clientMutationId, meta, chapter)
}
} }
data class FetchChapterPagesInput( data class FetchChapterPagesInput(
@@ -218,12 +230,13 @@ class ChapterMutation {
val chapter: ChapterType, val chapter: ChapterType,
) )
fun fetchChapterPages(input: FetchChapterPagesInput): CompletableFuture<FetchChapterPagesPayload> { fun fetchChapterPages(input: FetchChapterPagesInput): CompletableFuture<DataFetcherResult<FetchChapterPagesPayload?>> {
val (clientMutationId, chapterId) = input val (clientMutationId, chapterId) = input
return future { return future {
getChapterDownloadReadyById(chapterId) asDataFetcherResult {
}.thenApply { chapter -> val chapter = getChapterDownloadReadyById(chapterId)
FetchChapterPagesPayload( FetchChapterPagesPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
pages = pages =
@@ -235,3 +248,4 @@ class ChapterMutation {
} }
} }
} }
}

View File

@@ -1,9 +1,11 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
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.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.graphql.types.ChapterType
import suwayomi.tachidesk.graphql.types.DownloadStatus import suwayomi.tachidesk.graphql.types.DownloadStatus
import suwayomi.tachidesk.manga.impl.Chapter import suwayomi.tachidesk.manga.impl.Chapter
@@ -25,12 +27,13 @@ class DownloadMutation {
val chapters: List<ChapterType>, val chapters: List<ChapterType>,
) )
fun deleteDownloadedChapters(input: DeleteDownloadedChaptersInput): DeleteDownloadedChaptersPayload { fun deleteDownloadedChapters(input: DeleteDownloadedChaptersInput): DataFetcherResult<DeleteDownloadedChaptersPayload?> {
val (clientMutationId, chapters) = input val (clientMutationId, chapters) = input
return asDataFetcherResult {
Chapter.deleteChapters(chapters) Chapter.deleteChapters(chapters)
return DeleteDownloadedChaptersPayload( DeleteDownloadedChaptersPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
chapters = chapters =
transaction { transaction {
@@ -39,6 +42,7 @@ class DownloadMutation {
}, },
) )
} }
}
data class DeleteDownloadedChapterInput( data class DeleteDownloadedChapterInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -50,12 +54,13 @@ class DownloadMutation {
val chapters: ChapterType, val chapters: ChapterType,
) )
fun deleteDownloadedChapter(input: DeleteDownloadedChapterInput): DeleteDownloadedChapterPayload { fun deleteDownloadedChapter(input: DeleteDownloadedChapterInput): DataFetcherResult<DeleteDownloadedChapterPayload?> {
val (clientMutationId, chapter) = input val (clientMutationId, chapter) = input
return asDataFetcherResult {
Chapter.deleteChapters(listOf(chapter)) Chapter.deleteChapters(listOf(chapter))
return DeleteDownloadedChapterPayload( DeleteDownloadedChapterPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
chapters = chapters =
transaction { transaction {
@@ -63,6 +68,7 @@ class DownloadMutation {
}, },
) )
} }
}
data class EnqueueChapterDownloadsInput( data class EnqueueChapterDownloadsInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -74,12 +80,15 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun enqueueChapterDownloads(input: EnqueueChapterDownloadsInput): CompletableFuture<EnqueueChapterDownloadsPayload> { fun enqueueChapterDownloads(
input: EnqueueChapterDownloadsInput,
): CompletableFuture<DataFetcherResult<EnqueueChapterDownloadsPayload?>> {
val (clientMutationId, chapters) = input val (clientMutationId, chapters) = input
return future {
asDataFetcherResult {
DownloadManager.enqueue(DownloadManager.EnqueueInput(chapters)) DownloadManager.enqueue(DownloadManager.EnqueueInput(chapters))
return future {
EnqueueChapterDownloadsPayload( EnqueueChapterDownloadsPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
downloadStatus = downloadStatus =
@@ -89,6 +98,7 @@ class DownloadMutation {
) )
} }
} }
}
data class EnqueueChapterDownloadInput( data class EnqueueChapterDownloadInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -100,12 +110,13 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun enqueueChapterDownload(input: EnqueueChapterDownloadInput): CompletableFuture<EnqueueChapterDownloadPayload> { fun enqueueChapterDownload(input: EnqueueChapterDownloadInput): CompletableFuture<DataFetcherResult<EnqueueChapterDownloadPayload?>> {
val (clientMutationId, chapter) = input val (clientMutationId, chapter) = input
return future {
asDataFetcherResult {
DownloadManager.enqueue(DownloadManager.EnqueueInput(listOf(chapter))) DownloadManager.enqueue(DownloadManager.EnqueueInput(listOf(chapter)))
return future {
EnqueueChapterDownloadPayload( EnqueueChapterDownloadPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
downloadStatus = downloadStatus =
@@ -115,6 +126,7 @@ class DownloadMutation {
) )
} }
} }
}
data class DequeueChapterDownloadsInput( data class DequeueChapterDownloadsInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -126,12 +138,15 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun dequeueChapterDownloads(input: DequeueChapterDownloadsInput): CompletableFuture<DequeueChapterDownloadsPayload> { fun dequeueChapterDownloads(
input: DequeueChapterDownloadsInput,
): CompletableFuture<DataFetcherResult<DequeueChapterDownloadsPayload?>> {
val (clientMutationId, chapters) = input val (clientMutationId, chapters) = input
return future {
asDataFetcherResult {
DownloadManager.dequeue(DownloadManager.EnqueueInput(chapters)) DownloadManager.dequeue(DownloadManager.EnqueueInput(chapters))
return future {
DequeueChapterDownloadsPayload( DequeueChapterDownloadsPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
downloadStatus = downloadStatus =
@@ -141,6 +156,7 @@ class DownloadMutation {
) )
} }
} }
}
data class DequeueChapterDownloadInput( data class DequeueChapterDownloadInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -152,12 +168,13 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun dequeueChapterDownload(input: DequeueChapterDownloadInput): CompletableFuture<DequeueChapterDownloadPayload> { fun dequeueChapterDownload(input: DequeueChapterDownloadInput): CompletableFuture<DataFetcherResult<DequeueChapterDownloadPayload?>> {
val (clientMutationId, chapter) = input val (clientMutationId, chapter) = input
return future {
asDataFetcherResult {
DownloadManager.dequeue(DownloadManager.EnqueueInput(listOf(chapter))) DownloadManager.dequeue(DownloadManager.EnqueueInput(listOf(chapter)))
return future {
DequeueChapterDownloadPayload( DequeueChapterDownloadPayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
downloadStatus = downloadStatus =
@@ -167,6 +184,7 @@ class DownloadMutation {
) )
} }
} }
}
data class StartDownloaderInput( data class StartDownloaderInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -177,10 +195,11 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun startDownloader(input: StartDownloaderInput): CompletableFuture<StartDownloaderPayload> { fun startDownloader(input: StartDownloaderInput): CompletableFuture<DataFetcherResult<StartDownloaderPayload?>> {
return future {
asDataFetcherResult {
DownloadManager.start() DownloadManager.start()
return future {
StartDownloaderPayload( StartDownloaderPayload(
input.clientMutationId, input.clientMutationId,
downloadStatus = downloadStatus =
@@ -192,6 +211,7 @@ class DownloadMutation {
) )
} }
} }
}
data class StopDownloaderInput( data class StopDownloaderInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -202,9 +222,11 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun stopDownloader(input: StopDownloaderInput): CompletableFuture<StopDownloaderPayload> { fun stopDownloader(input: StopDownloaderInput): CompletableFuture<DataFetcherResult<StopDownloaderPayload?>> {
return future { return future {
asDataFetcherResult {
DownloadManager.stop() DownloadManager.stop()
StopDownloaderPayload( StopDownloaderPayload(
input.clientMutationId, input.clientMutationId,
downloadStatus = downloadStatus =
@@ -216,6 +238,7 @@ class DownloadMutation {
) )
} }
} }
}
data class ClearDownloaderInput( data class ClearDownloaderInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -226,9 +249,11 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun clearDownloader(input: ClearDownloaderInput): CompletableFuture<ClearDownloaderPayload> { fun clearDownloader(input: ClearDownloaderInput): CompletableFuture<DataFetcherResult<ClearDownloaderPayload?>> {
return future { return future {
asDataFetcherResult {
DownloadManager.clear() DownloadManager.clear()
ClearDownloaderPayload( ClearDownloaderPayload(
input.clientMutationId, input.clientMutationId,
downloadStatus = downloadStatus =
@@ -240,6 +265,7 @@ class DownloadMutation {
) )
} }
} }
}
data class ReorderChapterDownloadInput( data class ReorderChapterDownloadInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -252,11 +278,13 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun reorderChapterDownload(input: ReorderChapterDownloadInput): CompletableFuture<ReorderChapterDownloadPayload> { fun reorderChapterDownload(input: ReorderChapterDownloadInput): CompletableFuture<DataFetcherResult<ReorderChapterDownloadPayload?>> {
val (clientMutationId, chapter, to) = input val (clientMutationId, chapter, to) = input
DownloadManager.reorder(chapter, to)
return future { return future {
asDataFetcherResult {
DownloadManager.reorder(chapter, to)
ReorderChapterDownloadPayload( ReorderChapterDownloadPayload(
clientMutationId, clientMutationId,
downloadStatus = downloadStatus =
@@ -269,3 +297,4 @@ class DownloadMutation {
} }
} }
} }
}

View File

@@ -1,9 +1,11 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import eu.kanade.tachiyomi.source.local.LocalSource import eu.kanade.tachiyomi.source.local.LocalSource
import graphql.execution.DataFetcherResult
import io.javalin.http.UploadedFile import io.javalin.http.UploadedFile
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.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.ExtensionType import suwayomi.tachidesk.graphql.types.ExtensionType
import suwayomi.tachidesk.manga.impl.extension.Extension import suwayomi.tachidesk.manga.impl.extension.Extension
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList import suwayomi.tachidesk.manga.impl.extension.ExtensionsList
@@ -69,12 +71,13 @@ class ExtensionMutation {
} }
} }
fun updateExtension(input: UpdateExtensionInput): CompletableFuture<UpdateExtensionPayload> { fun updateExtension(input: UpdateExtensionInput): CompletableFuture<DataFetcherResult<UpdateExtensionPayload?>> {
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
return future { return future {
asDataFetcherResult {
updateExtensions(listOf(id), patch) updateExtensions(listOf(id), patch)
}.thenApply {
val extension = val extension =
transaction { transaction {
ExtensionTable.select { ExtensionTable.pkgName eq id }.firstOrNull() ExtensionTable.select { ExtensionTable.pkgName eq id }.firstOrNull()
@@ -87,13 +90,15 @@ class ExtensionMutation {
) )
} }
} }
}
fun updateExtensions(input: UpdateExtensionsInput): CompletableFuture<UpdateExtensionsPayload> { fun updateExtensions(input: UpdateExtensionsInput): CompletableFuture<DataFetcherResult<UpdateExtensionsPayload?>> {
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
return future { return future {
asDataFetcherResult {
updateExtensions(ids, patch) updateExtensions(ids, patch)
}.thenApply {
val extensions = val extensions =
transaction { transaction {
ExtensionTable.select { ExtensionTable.pkgName inList ids } ExtensionTable.select { ExtensionTable.pkgName inList ids }
@@ -106,6 +111,7 @@ class ExtensionMutation {
) )
} }
} }
}
data class FetchExtensionsInput( data class FetchExtensionsInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -116,12 +122,13 @@ class ExtensionMutation {
val extensions: List<ExtensionType>, val extensions: List<ExtensionType>,
) )
fun fetchExtensions(input: FetchExtensionsInput): CompletableFuture<FetchExtensionsPayload> { fun fetchExtensions(input: FetchExtensionsInput): CompletableFuture<DataFetcherResult<FetchExtensionsPayload?>> {
val (clientMutationId) = input val (clientMutationId) = input
return future { return future {
asDataFetcherResult {
ExtensionsList.fetchExtensions() ExtensionsList.fetchExtensions()
}.thenApply {
val extensions = val extensions =
transaction { transaction {
ExtensionTable.select { ExtensionTable.name neq LocalSource.EXTENSION_NAME } ExtensionTable.select { ExtensionTable.name neq LocalSource.EXTENSION_NAME }
@@ -134,6 +141,7 @@ class ExtensionMutation {
) )
} }
} }
}
data class InstallExternalExtensionInput( data class InstallExternalExtensionInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -145,12 +153,15 @@ class ExtensionMutation {
val extension: ExtensionType, val extension: ExtensionType,
) )
fun installExternalExtension(input: InstallExternalExtensionInput): CompletableFuture<InstallExternalExtensionPayload> { fun installExternalExtension(
input: InstallExternalExtensionInput,
): CompletableFuture<DataFetcherResult<InstallExternalExtensionPayload?>> {
val (clientMutationId, extensionFile) = input val (clientMutationId, extensionFile) = input
return future { return future {
asDataFetcherResult {
Extension.installExternalExtension(extensionFile.content, extensionFile.filename) Extension.installExternalExtension(extensionFile.content, extensionFile.filename)
}.thenApply {
val dbExtension = transaction { ExtensionTable.select { ExtensionTable.apkName eq extensionFile.filename }.first() } val dbExtension = transaction { ExtensionTable.select { ExtensionTable.apkName eq extensionFile.filename }.first() }
InstallExternalExtensionPayload( InstallExternalExtensionPayload(
@@ -160,3 +171,4 @@ class ExtensionMutation {
} }
} }
} }
}

View File

@@ -1,7 +1,9 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.UpdateState.DOWNLOADING import suwayomi.tachidesk.graphql.types.UpdateState.DOWNLOADING
import suwayomi.tachidesk.graphql.types.UpdateState.ERROR import suwayomi.tachidesk.graphql.types.UpdateState.ERROR
import suwayomi.tachidesk.graphql.types.UpdateState.IDLE import suwayomi.tachidesk.graphql.types.UpdateState.IDLE
@@ -22,8 +24,9 @@ class InfoMutation {
val updateStatus: WebUIUpdateStatus, val updateStatus: WebUIUpdateStatus,
) )
fun updateWebUI(input: WebUIUpdateInput): CompletableFuture<WebUIUpdatePayload> { fun updateWebUI(input: WebUIUpdateInput): CompletableFuture<DataFetcherResult<WebUIUpdatePayload?>> {
return future { return future {
asDataFetcherResult {
withTimeout(30.seconds) { withTimeout(30.seconds) {
if (WebInterfaceManager.status.value.state === DOWNLOADING) { if (WebInterfaceManager.status.value.state === DOWNLOADING) {
return@withTimeout WebUIUpdatePayload(input.clientMutationId, WebInterfaceManager.status.value) return@withTimeout WebUIUpdatePayload(input.clientMutationId, WebInterfaceManager.status.value)
@@ -54,9 +57,11 @@ class InfoMutation {
} }
} }
} }
}
fun resetWebUIUpdateStatus(): CompletableFuture<WebUIUpdateStatus> { fun resetWebUIUpdateStatus(): CompletableFuture<DataFetcherResult<WebUIUpdateStatus?>> {
return future { return future {
asDataFetcherResult {
withTimeout(30.seconds) { withTimeout(30.seconds) {
val isUpdateFinished = WebInterfaceManager.status.value.state != DOWNLOADING val isUpdateFinished = WebInterfaceManager.status.value.state != DOWNLOADING
if (!isUpdateFinished) { if (!isUpdateFinished) {
@@ -70,3 +75,4 @@ class InfoMutation {
} }
} }
} }
}

View File

@@ -1,11 +1,13 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.deleteWhere
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 org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.MangaMetaType import suwayomi.tachidesk.graphql.types.MangaMetaType
import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.graphql.types.MangaType
import suwayomi.tachidesk.manga.impl.Library import suwayomi.tachidesk.manga.impl.Library
@@ -70,12 +72,13 @@ class MangaMutation {
} }
} }
fun updateManga(input: UpdateMangaInput): CompletableFuture<UpdateMangaPayload> { fun updateManga(input: UpdateMangaInput): CompletableFuture<DataFetcherResult<UpdateMangaPayload?>> {
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
return future { return future {
asDataFetcherResult {
updateMangas(listOf(id), patch) updateMangas(listOf(id), patch)
}.thenApply {
val manga = val manga =
transaction { transaction {
MangaType(MangaTable.select { MangaTable.id eq id }.first()) MangaType(MangaTable.select { MangaTable.id eq id }.first())
@@ -87,13 +90,15 @@ class MangaMutation {
) )
} }
} }
}
fun updateMangas(input: UpdateMangasInput): CompletableFuture<UpdateMangasPayload> { fun updateMangas(input: UpdateMangasInput): CompletableFuture<DataFetcherResult<UpdateMangasPayload?>> {
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
return future { return future {
asDataFetcherResult {
updateMangas(ids, patch) updateMangas(ids, patch)
}.thenApply {
val mangas = val mangas =
transaction { transaction {
MangaTable.select { MangaTable.id inList ids }.map { MangaType(it) } MangaTable.select { MangaTable.id inList ids }.map { MangaType(it) }
@@ -105,6 +110,7 @@ class MangaMutation {
) )
} }
} }
}
data class FetchMangaInput( data class FetchMangaInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -116,12 +122,13 @@ class MangaMutation {
val manga: MangaType, val manga: MangaType,
) )
fun fetchManga(input: FetchMangaInput): CompletableFuture<FetchMangaPayload> { fun fetchManga(input: FetchMangaInput): CompletableFuture<DataFetcherResult<FetchMangaPayload?>> {
val (clientMutationId, id) = input val (clientMutationId, id) = input
return future { return future {
asDataFetcherResult {
Manga.fetchManga(id) Manga.fetchManga(id)
}.thenApply {
val manga = val manga =
transaction { transaction {
MangaTable.select { MangaTable.id eq id }.first() MangaTable.select { MangaTable.id eq id }.first()
@@ -132,6 +139,7 @@ class MangaMutation {
) )
} }
} }
}
data class SetMangaMetaInput( data class SetMangaMetaInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -143,12 +151,14 @@ class MangaMutation {
val meta: MangaMetaType, val meta: MangaMetaType,
) )
fun setMangaMeta(input: SetMangaMetaInput): SetMangaMetaPayload { fun setMangaMeta(input: SetMangaMetaInput): DataFetcherResult<SetMangaMetaPayload?> {
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
return asDataFetcherResult {
Manga.modifyMangaMeta(meta.mangaId, meta.key, meta.value) Manga.modifyMangaMeta(meta.mangaId, meta.key, meta.value)
return SetMangaMetaPayload(clientMutationId, meta) SetMangaMetaPayload(clientMutationId, meta)
}
} }
data class DeleteMangaMetaInput( data class DeleteMangaMetaInput(
@@ -163,9 +173,10 @@ class MangaMutation {
val manga: MangaType, val manga: MangaType,
) )
fun deleteMangaMeta(input: DeleteMangaMetaInput): DeleteMangaMetaPayload { fun deleteMangaMeta(input: DeleteMangaMetaInput): DataFetcherResult<DeleteMangaMetaPayload?> {
val (clientMutationId, mangaId, key) = input val (clientMutationId, mangaId, key) = input
return asDataFetcherResult {
val (meta, manga) = val (meta, manga) =
transaction { transaction {
val meta = val meta =
@@ -186,6 +197,7 @@ class MangaMutation {
} to manga } to manga
} }
return DeleteMangaMetaPayload(clientMutationId, meta, manga) DeleteMangaMetaPayload(clientMutationId, meta, manga)
}
} }
} }

View File

@@ -1,11 +1,13 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.deleteWhere
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.global.impl.GlobalMeta import suwayomi.tachidesk.global.impl.GlobalMeta
import suwayomi.tachidesk.global.model.table.GlobalMetaTable import suwayomi.tachidesk.global.model.table.GlobalMetaTable
import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.GlobalMetaType import suwayomi.tachidesk.graphql.types.GlobalMetaType
class MetaMutation { class MetaMutation {
@@ -19,12 +21,14 @@ class MetaMutation {
val meta: GlobalMetaType, val meta: GlobalMetaType,
) )
fun setGlobalMeta(input: SetGlobalMetaInput): SetGlobalMetaPayload { fun setGlobalMeta(input: SetGlobalMetaInput): DataFetcherResult<SetGlobalMetaPayload?> {
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
return asDataFetcherResult {
GlobalMeta.modifyMeta(meta.key, meta.value) GlobalMeta.modifyMeta(meta.key, meta.value)
return SetGlobalMetaPayload(clientMutationId, meta) SetGlobalMetaPayload(clientMutationId, meta)
}
} }
data class DeleteGlobalMetaInput( data class DeleteGlobalMetaInput(
@@ -37,9 +41,10 @@ class MetaMutation {
val meta: GlobalMetaType?, val meta: GlobalMetaType?,
) )
fun deleteGlobalMeta(input: DeleteGlobalMetaInput): DeleteGlobalMetaPayload { fun deleteGlobalMeta(input: DeleteGlobalMetaInput): DataFetcherResult<DeleteGlobalMetaPayload?> {
val (clientMutationId, key) = input val (clientMutationId, key) = input
return asDataFetcherResult {
val meta = val meta =
transaction { transaction {
val meta = val meta =
@@ -55,6 +60,7 @@ class MetaMutation {
} }
} }
return DeleteGlobalMetaPayload(clientMutationId, meta) DeleteGlobalMetaPayload(clientMutationId, meta)
}
} }
} }

View File

@@ -5,11 +5,13 @@ import androidx.preference.EditTextPreference
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.MultiSelectListPreference import androidx.preference.MultiSelectListPreference
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import graphql.execution.DataFetcherResult
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.deleteWhere
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.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.FilterChange import suwayomi.tachidesk.graphql.types.FilterChange
import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.graphql.types.MangaType
import suwayomi.tachidesk.graphql.types.Preference import suwayomi.tachidesk.graphql.types.Preference
@@ -37,12 +39,14 @@ class SourceMutation {
val meta: SourceMetaType, val meta: SourceMetaType,
) )
fun setSourceMeta(input: SetSourceMetaInput): SetSourceMetaPayload { fun setSourceMeta(input: SetSourceMetaInput): DataFetcherResult<SetSourceMetaPayload?> {
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
return asDataFetcherResult {
Source.modifyMeta(meta.sourceId, meta.key, meta.value) Source.modifyMeta(meta.sourceId, meta.key, meta.value)
return SetSourceMetaPayload(clientMutationId, meta) SetSourceMetaPayload(clientMutationId, meta)
}
} }
data class DeleteSourceMetaInput( data class DeleteSourceMetaInput(
@@ -57,9 +61,10 @@ class SourceMutation {
val source: SourceType?, val source: SourceType?,
) )
fun deleteSourceMeta(input: DeleteSourceMetaInput): DeleteSourceMetaPayload { fun deleteSourceMeta(input: DeleteSourceMetaInput): DataFetcherResult<DeleteSourceMetaPayload?> {
val (clientMutationId, sourceId, key) = input val (clientMutationId, sourceId, key) = input
return asDataFetcherResult {
val (meta, source) = val (meta, source) =
transaction { transaction {
val meta = val meta =
@@ -81,7 +86,8 @@ class SourceMutation {
} to source } to source
} }
return DeleteSourceMetaPayload(clientMutationId, meta, source) DeleteSourceMetaPayload(clientMutationId, meta, source)
}
} }
enum class FetchSourceMangaType { enum class FetchSourceMangaType {
@@ -105,10 +111,11 @@ class SourceMutation {
val hasNextPage: Boolean, val hasNextPage: Boolean,
) )
fun fetchSourceManga(input: FetchSourceMangaInput): CompletableFuture<FetchSourceMangaPayload> { fun fetchSourceManga(input: FetchSourceMangaInput): CompletableFuture<DataFetcherResult<FetchSourceMangaPayload?>> {
val (clientMutationId, sourceId, type, page, query, filters) = input val (clientMutationId, sourceId, type, page, query, filters) = input
return future { return future {
asDataFetcherResult {
val source = GetCatalogueSource.getCatalogueSourceOrNull(sourceId)!! val source = GetCatalogueSource.getCatalogueSourceOrNull(sourceId)!!
val mangasPage = val mangasPage =
when (type) { when (type) {
@@ -145,6 +152,7 @@ class SourceMutation {
) )
} }
} }
}
data class SourcePreferenceChange( data class SourcePreferenceChange(
val position: Int, val position: Int,
@@ -167,9 +175,10 @@ class SourceMutation {
val source: SourceType, val source: SourceType,
) )
fun updateSourcePreference(input: UpdateSourcePreferenceInput): UpdateSourcePreferencePayload { fun updateSourcePreference(input: UpdateSourcePreferenceInput): DataFetcherResult<UpdateSourcePreferencePayload?> {
val (clientMutationId, sourceId, change) = input val (clientMutationId, sourceId, change) = input
return asDataFetcherResult {
Source.setSourcePreference(sourceId, change.position, "") { preference -> Source.setSourcePreference(sourceId, change.position, "") { preference ->
when (preference) { when (preference) {
is SwitchPreferenceCompat -> change.switchState is SwitchPreferenceCompat -> change.switchState
@@ -181,7 +190,7 @@ class SourceMutation {
} ?: throw Exception("Expected change to ${preference::class.simpleName}") } ?: throw Exception("Expected change to ${preference::class.simpleName}")
} }
return UpdateSourcePreferencePayload( UpdateSourcePreferencePayload(
clientMutationId = clientMutationId, clientMutationId = clientMutationId,
preferences = Source.getSourcePreferencesRaw(sourceId).map { preferenceOf(it) }, preferences = Source.getSourcePreferencesRaw(sourceId).map { preferenceOf(it) },
source = source =
@@ -191,3 +200,4 @@ class SourceMutation {
) )
} }
} }
}

View File

@@ -2,9 +2,11 @@ package suwayomi.tachidesk.graphql.mutations
import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated
import com.expediagroup.graphql.generator.annotations.GraphQLDescription import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import graphql.execution.DataFetcherResult
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.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.TrackRecordType import suwayomi.tachidesk.graphql.types.TrackRecordType
import suwayomi.tachidesk.graphql.types.TrackerType import suwayomi.tachidesk.graphql.types.TrackerType
import suwayomi.tachidesk.manga.impl.track.Track import suwayomi.tachidesk.manga.impl.track.Track
@@ -203,10 +205,11 @@ class TrackMutation {
val trackRecords: List<TrackRecordType>, val trackRecords: List<TrackRecordType>,
) )
fun trackProgress(input: TrackProgressInput): CompletableFuture<TrackProgressPayload> { fun trackProgress(input: TrackProgressInput): CompletableFuture<DataFetcherResult<TrackProgressPayload?>> {
val (clientMutationId, mangaId) = input val (clientMutationId, mangaId) = input
return future { return future {
asDataFetcherResult {
Track.trackChapter(mangaId) Track.trackChapter(mangaId)
val trackRecords = val trackRecords =
transaction { transaction {
@@ -219,6 +222,7 @@ class TrackMutation {
) )
} }
} }
}
data class UpdateTrackInput( data class UpdateTrackInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,

View File

@@ -1,5 +1,6 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
@@ -7,6 +8,7 @@ import org.jetbrains.exposed.sql.transactions.transaction
import org.kodein.di.DI import org.kodein.di.DI
import org.kodein.di.conf.global import org.kodein.di.conf.global
import org.kodein.di.instance import org.kodein.di.instance
import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.types.UpdateStatus import suwayomi.tachidesk.graphql.types.UpdateStatus
import suwayomi.tachidesk.manga.impl.Category import suwayomi.tachidesk.manga.impl.Category
import suwayomi.tachidesk.manga.impl.update.IUpdater import suwayomi.tachidesk.manga.impl.update.IUpdater
@@ -28,7 +30,7 @@ class UpdateMutation {
val updateStatus: UpdateStatus, val updateStatus: UpdateStatus,
) )
fun updateLibraryManga(input: UpdateLibraryMangaInput): CompletableFuture<UpdateLibraryMangaPayload> { fun updateLibraryManga(input: UpdateLibraryMangaInput): CompletableFuture<DataFetcherResult<UpdateLibraryMangaPayload?>> {
updater.addCategoriesToUpdateQueue( updater.addCategoriesToUpdateQueue(
Category.getCategoryList(), Category.getCategoryList(),
clear = true, clear = true,
@@ -36,6 +38,7 @@ class UpdateMutation {
) )
return future { return future {
asDataFetcherResult {
UpdateLibraryMangaPayload( UpdateLibraryMangaPayload(
input.clientMutationId, input.clientMutationId,
updateStatus = updateStatus =
@@ -45,6 +48,7 @@ class UpdateMutation {
) )
} }
} }
}
data class UpdateCategoryMangaInput( data class UpdateCategoryMangaInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
@@ -56,7 +60,7 @@ class UpdateMutation {
val updateStatus: UpdateStatus, val updateStatus: UpdateStatus,
) )
fun updateCategoryManga(input: UpdateCategoryMangaInput): CompletableFuture<UpdateCategoryMangaPayload> { fun updateCategoryManga(input: UpdateCategoryMangaInput): CompletableFuture<DataFetcherResult<UpdateCategoryMangaPayload?>> {
val categories = val categories =
transaction { transaction {
CategoryTable.select { CategoryTable.id inList input.categories }.map { CategoryTable.select { CategoryTable.id inList input.categories }.map {
@@ -66,6 +70,7 @@ class UpdateMutation {
updater.addCategoriesToUpdateQueue(categories, clear = true, forceAll = true) updater.addCategoriesToUpdateQueue(categories, clear = true, forceAll = true)
return future { return future {
asDataFetcherResult {
UpdateCategoryMangaPayload( UpdateCategoryMangaPayload(
input.clientMutationId, input.clientMutationId,
updateStatus = updateStatus =
@@ -75,6 +80,7 @@ class UpdateMutation {
) )
} }
} }
}
data class UpdateStopInput( data class UpdateStopInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,