diff --git a/.eslintignore b/.eslintignore index a9ba028c..bad9857a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,2 @@ .eslintrc.js +src/lib/graphql/generated diff --git a/.eslintrc.js b/.eslintrc.js index 29228c2e..49093f35 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { extends: ['airbnb', 'airbnb-typescript', 'prettier'], plugins: ['@typescript-eslint', 'no-relative-import-paths', 'prettier', 'header'], parserOptions: { - project: ['./tsconfig.json', './tools/scripts/tsconfig.json'], + project: ['./tsconfig.json', './tsconfig.node.json', './tools/scripts/tsconfig.json'], }, overrides: [ { @@ -27,6 +27,8 @@ module.exports = { 'prettier/prettier': 'error', + 'class-methods-use-this': 'off', + 'no-plusplus': ['error', { allowForLoopAfterthoughts: true }], // just why diff --git a/.gitignore b/.gitignore index 82e9a202..fde0f2b6 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ node_modules/ build/* -tools/scripts/github_token.json \ No newline at end of file +tools/scripts/github_token.json + +src/lib/graphql/schema.json diff --git a/gql_codegen.ts b/gql_codegen.ts new file mode 100644 index 00000000..467b5927 --- /dev/null +++ b/gql_codegen.ts @@ -0,0 +1,37 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import type { CodegenConfig } from '@graphql-codegen/cli'; + +const config: CodegenConfig = { + overwrite: true, + schema: 'http://localhost:4567/api/graphql', + documents: [ + 'src/lib/graphql/queries/**', + 'src/lib/graphql/mutations/**', + 'src/lib/graphql/subscriptions/**', + 'src/lib/graphql/Fragments.ts', + ], + ignoreNoDocuments: true, + generates: { + 'src/lib/graphql/generated/graphql.ts': { + plugins: ['typescript', 'typescript-operations'], + config: { + namingConvention: { + typeNames: 'change-case-all#pascalCase', + transformUnderscore: true, + }, + }, + }, + 'src/lib/graphql/generated/apollo-helpers.ts': { + plugins: ['typescript-apollo-client-helpers'], + }, + }, +}; + +export default config; diff --git a/package.json b/package.json index 2c28a422..d742f525 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,10 @@ "build-zip": "cd build && rev=$(git rev-list HEAD --count) && echo r$rev > revision && zip -9 -r ../buildZip/Tachidesk-WebUI-r$rev *", "lint": "eslint src --ext .ts,.tsx,.js,.jsx", "createChangelog": "ts-node tools/scripts/createReleaseChanglog.ts", - "updateDeps": "yarn outdated && yarn upgrade && yarn syncyarnlock -s -k && yarn && git add package.json yarn.lock && git commit -m \"Update dependencies\"" + "updateDeps": "yarn outdated && yarn upgrade && yarn syncyarnlock -s -k && yarn && git add package.json yarn.lock && git commit -m \"Update dependencies\"", + "gql:codegen-base": "graphql-codegen --config gql_codegen.ts", + "gql:codegen-formatter": "ts-node tools/scripts/codegenFormatter.ts", + "gql:codegen": "yarn gql:codegen-base & yarn gql:codegen-formatter" }, "browserslist": { "production": [ @@ -26,14 +29,18 @@ ] }, "dependencies": { + "@apollo/client": "^3.8.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@fontsource/roboto": "^5.0.8", "@mui/icons-material": "^5.14.9", "@mui/material": "^5.14.9", "@vitejs/plugin-react-swc": "^3.3.2", + "apollo-upload-client": "^17.0.0", "axios": "^1.5.0", "file-selector": "^0.6.0", + "graphql-tag": "^2.12.6", + "graphql-ws": "^5.14.1", "i18next": "^23.5.1", "i18next-browser-languagedetector": "^7.1.0", "react": "^18.2.0", @@ -42,12 +49,16 @@ "react-i18next": "^13.2.2", "react-router-dom": "^6.16.0", "react-virtuoso": "^4.5.1", - "swr": "^2.2.2", "use-query-params": "^2.2.1", "vite": "^4.4.9", "vite-tsconfig-paths": "^4.2.1" }, "devDependencies": { + "@graphql-codegen/cli": "^5.0.0", + "@graphql-codegen/client-preset": "^4.1.0", + "@graphql-codegen/typescript-apollo-client-helpers": "^2.2.6", + "@graphql-codegen/typescript-operations": "^4.0.1", + "@types/apollo-upload-client": "^17.0.2", "@types/node": "^20.6.2", "@types/react": "^18.2.21", "@types/react-beautiful-dnd": "^13.1.4", diff --git a/src/App.tsx b/src/App.tsx index 36b1a176..76130286 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,8 @@ import { Container } from '@mui/material'; import CssBaseline from '@mui/material/CssBaseline'; import React from 'react'; import { Navigate, Route, Routes } from 'react-router-dom'; +import { loadErrorMessages, loadDevMessages } from '@apollo/client/dev'; +import { __DEV__ } from '@apollo/client/utilities/globals'; import AppContext from '@/components/context/AppContext'; import Browse from '@/screens/Browse'; import DownloadQueue from '@/screens/DownloadQueue'; @@ -31,6 +33,11 @@ import '@/i18n'; import LibrarySettings from '@/screens/settings/LibrarySettings'; import DefaultNavBar from '@/components/navbar/DefaultNavBar'; +if (__DEV__) { + // Adds messages only in a dev environment + loadDevMessages(); + loadErrorMessages(); +} const App: React.FC = () => ( diff --git a/src/components/ExtensionCard.tsx b/src/components/ExtensionCard.tsx index d386d82e..cc917968 100644 --- a/src/components/ExtensionCard.tsx +++ b/src/components/ExtensionCard.tsx @@ -14,12 +14,11 @@ import Avatar from '@mui/material/Avatar'; import Typography from '@mui/material/Typography'; import { Box } from '@mui/material'; import { useTranslation } from 'react-i18next'; -import { IExtension, TranslationKey } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import { PartialExtension, TranslationKey } from '@/typings'; +import requestManager from '@/lib/requests/RequestManager.ts'; interface IProps { - extension: IExtension; - notifyInstall: () => void; + extension: PartialExtension; } enum ExtensionAction { @@ -65,17 +64,16 @@ export default function ExtensionCard(props: IProps) { const { t } = useTranslation(); const { - extension: { name, lang, versionName, installed, hasUpdate, obsolete, pkgName, iconUrl, isNsfw }, - notifyInstall, + extension: { name, lang, versionName, isInstalled, hasUpdate, isObsolete, pkgName, iconUrl, isNsfw }, } = props; const [installedState, setInstalledState] = useState(() => { - if (obsolete) { + if (isObsolete) { return InstalledState.OBSOLETE; } if (hasUpdate) { return InstalledState.UPDATE; } - return installed ? InstalledState.UNINSTALL : InstalledState.INSTALL; + return isInstalled ? InstalledState.UNINSTALL : InstalledState.INSTALL; }); const langPress = lang === 'all' ? t('extension.language.all') : lang.toUpperCase(); @@ -87,19 +85,18 @@ export default function ExtensionCard(props: IProps) { setInstalledState(state); switch (action) { case ExtensionAction.INSTALL: - await requestManager.installExtension(pkgName).response; + await requestManager.updateExtension(pkgName, { install: true }).response; break; case ExtensionAction.UNINSTALL: - await requestManager.uninstallExtension(pkgName).response; + await requestManager.updateExtension(pkgName, { uninstall: true }).response; break; case ExtensionAction.UPDATE: - await requestManager.updateExtension(pkgName).response; + await requestManager.updateExtension(pkgName, { update: true }).response; break; default: throw new Error(`Unexpected ExtensionAction "${action}"`); } setInstalledState(nextAction); - notifyInstall(); }; function handleButtonClick() { diff --git a/src/components/MangaCard.tsx b/src/components/MangaCard.tsx index 15c9d45f..bba7181f 100644 --- a/src/components/MangaCard.tsx +++ b/src/components/MangaCard.tsx @@ -12,10 +12,10 @@ import Typography from '@mui/material/Typography'; import { Link } from 'react-router-dom'; import { Avatar, Box, CardContent, styled } from '@mui/material'; import { useTranslation } from 'react-i18next'; -import { IMangaCard } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext'; import SpinnerImage from '@/components/util/SpinnerImage'; +import { TPartialManga } from '@/typings.ts'; const BottomGradient = styled('div')({ position: 'absolute', @@ -66,7 +66,7 @@ const BadgeContainer = styled('div')({ }); interface IProps { - manga: IMangaCard; + manga: TPartialManga; gridLayout?: GridLayout; inLibraryIndicator?: boolean; } @@ -75,10 +75,11 @@ const MangaCard = (props: IProps) => { const { t } = useTranslation(); const { - manga: { id, title, thumbnailUrl, downloadCount, unreadCount: unread, inLibrary }, + manga: { id, title, thumbnailUrl: tmpThumbnailUrl, downloadCount, unreadCount: unread, inLibrary }, gridLayout, inLibraryIndicator, } = props; + const thumbnailUrl = tmpThumbnailUrl ?? 'nonExistingMangaUrl'; const { options: { showUnreadBadge, showDownloadBadge }, } = useLibraryOptionsContext(); @@ -119,10 +120,10 @@ const MangaCard = (props: IProps) => { {t('manga.button.in_library')} )} - {showUnreadBadge && unread! > 0 && ( + {showUnreadBadge && (unread ?? 0) > 0 && ( {unread} )} - {showDownloadBadge && downloadCount! > 0 && ( + {showDownloadBadge && (downloadCount ?? 0) > 0 && ( (({ children, ...props }, ref) => ( @@ -40,13 +40,13 @@ const GridItemContainerWithDimension = ( ); }; -const createMangaCard = (manga: IMangaCard, gridLayout?: GridLayout, inLibraryIndicator?: boolean) => ( +const createMangaCard = (manga: TPartialManga, gridLayout?: GridLayout, inLibraryIndicator?: boolean) => ( ); type DefaultGridProps = { isLoading: boolean; - mangas: IMangaCard[]; + mangas: TPartialManga[]; inLibraryIndicator?: boolean; GridItemContainer: (props: GridTypeMap['props'] & Partial) => JSX.Element; gridLayout?: GridLayout; @@ -150,7 +150,7 @@ const VerticalGrid = ({ }; export interface IMangaGridProps { - mangas: IMangaCard[]; + mangas: TPartialManga[]; isLoading: boolean; message?: string; messageExtra?: JSX.Element; diff --git a/src/components/SourceCard.tsx b/src/components/SourceCard.tsx index 9b0c9561..d779de44 100644 --- a/src/components/SourceCard.tsx +++ b/src/components/SourceCard.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; import { ISource } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import { translateExtensionLanguage } from '@/screens/util/Extensions'; import { SourceContentType } from '@/screens/SourceMangas'; diff --git a/src/components/context/AppContext.tsx b/src/components/context/AppContext.tsx index dd793768..f79322a6 100644 --- a/src/components/context/AppContext.tsx +++ b/src/components/context/AppContext.tsx @@ -9,7 +9,6 @@ import { StyledEngineProvider, ThemeProvider } from '@mui/material/styles'; import React, { useMemo } from 'react'; import { BrowserRouter as Router } from 'react-router-dom'; -import { SWRConfig } from 'swr'; import { QueryParamProvider } from 'use-query-params'; import { ReactRouter6Adapter } from 'use-query-params/adapters/react-router-6'; import createTheme from '@/theme'; @@ -36,21 +35,19 @@ const AppContext: React.FC = ({ children }) => { const theme = useMemo(() => createTheme(darkTheme), [darkTheme]); return ( - - - - - - - - {children} - - - - - - - + + + + + + + {children} + + + + + + ); }; diff --git a/src/components/library/LibraryMangaGrid.tsx b/src/components/library/LibraryMangaGrid.tsx index c3250e05..93b67d99 100644 --- a/src/components/library/LibraryMangaGrid.tsx +++ b/src/components/library/LibraryMangaGrid.tsx @@ -9,12 +9,12 @@ import React, { useEffect, useMemo } from 'react'; import { StringParam, useQueryParam } from 'use-query-params'; import { useTranslation } from 'react-i18next'; -import { IMangaCard, LibrarySortMode, NullAndUndefined } from '@/typings'; +import { LibrarySortMode, NullAndUndefined, TManga } from '@/typings'; import { useSearchSettings } from '@/util/searchSettings'; import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext'; import MangaGrid from '@/components/MangaGrid'; -const unreadFilter = (unread: NullAndUndefined, { unreadCount }: IMangaCard): boolean => { +const unreadFilter = (unread: NullAndUndefined, { unreadCount }: TManga): boolean => { switch (unread) { case true: return !!unreadCount && unreadCount >= 1; @@ -25,7 +25,7 @@ const unreadFilter = (unread: NullAndUndefined, { unreadCount }: IManga } }; -const downloadedFilter = (downloaded: NullAndUndefined, { downloadCount }: IMangaCard): boolean => { +const downloadedFilter = (downloaded: NullAndUndefined, { downloadCount }: TManga): boolean => { switch (downloaded) { case true: return !!downloadCount && downloadCount >= 1; @@ -36,24 +36,24 @@ const downloadedFilter = (downloaded: NullAndUndefined, { downloadCount } }; -const queryFilter = (query: NullAndUndefined, { title }: IMangaCard): boolean => { +const queryFilter = (query: NullAndUndefined, { title }: TManga): boolean => { if (!query) return true; return title.toLowerCase().includes(query.toLowerCase()); }; -const queryGenreFilter = (query: NullAndUndefined, { genre }: IMangaCard): boolean => { +const queryGenreFilter = (query: NullAndUndefined, { genre }: TManga): boolean => { if (!query) return true; const queries = query.split(',').map((str) => str.toLowerCase().trim()); return queries.every((element) => genre.map((el) => el.toLowerCase()).includes(element)); }; const filterManga = ( - mangas: IMangaCard[], + mangas: TManga[], query: NullAndUndefined, unread: NullAndUndefined, downloaded: NullAndUndefined, ignoreFilters: boolean, -): IMangaCard[] => +): TManga[] => mangas.filter((manga) => { const ignoreFiltersWhileSearching = ignoreFilters && query?.length; const matchesSearch = queryFilter(query, manga) || queryGenreFilter(query, manga); @@ -63,19 +63,20 @@ const filterManga = ( return matchesSearch && matchesFilters; }); -const sortByUnread = (a: IMangaCard, b: IMangaCard): number => (a.unreadCount ?? 0) - (b.unreadCount ?? 0); +const sortByUnread = (a: TManga, b: TManga): number => (a.unreadCount ?? 0) - (b.unreadCount ?? 0); -const sortByTitle = (a: IMangaCard, b: IMangaCard): number => a.title.localeCompare(b.title); +const sortByTitle = (a: TManga, b: TManga): number => a.title.localeCompare(b.title); -const sortByDateAdded = (a: IMangaCard, b: IMangaCard): number => a.inLibraryAt - b.inLibraryAt; +const sortByDateAdded = (a: TManga, b: TManga): number => Number(a.inLibraryAt) - Number(b.inLibraryAt); -const sortByLastRead = (a: IMangaCard, b: IMangaCard): number => b.lastReadAt - a.lastReadAt; +const sortByLastRead = (a: TManga, b: TManga): number => + Number(b.lastReadChapter?.lastReadAt ?? 0) - Number(a.lastReadChapter?.lastReadAt ?? 0); const sortManga = ( - manga: IMangaCard[], + manga: TManga[], sort: NullAndUndefined, desc: NullAndUndefined, -): IMangaCard[] => { +): TManga[] => { const result = [...manga]; switch (sort) { @@ -103,17 +104,12 @@ const sortManga = ( }; interface LibraryMangaGridProps { - mangas: IMangaCard[]; + mangas: TManga[]; isLoading: boolean; message?: string; } -const LibraryMangaGrid: React.FC = ({ - mangas, - isLoading, - message, - lastLibraryUpdate, -}) => { +const LibraryMangaGrid: React.FC = ({ mangas, isLoading, message }) => { const { t } = useTranslation(); const [query] = useQueryParam('query', StringParam); @@ -127,7 +123,7 @@ const LibraryMangaGrid: React.FC sortManga(filteredMangas, options.sorts, options.sortDesc), - [filteredMangas, lastLibraryUpdate, options.sorts, options.sortDesc], + [filteredMangas, options.sorts, options.sortDesc], ); const showFilteredOutMessage = @@ -135,7 +131,7 @@ const LibraryMangaGrid: React.FC { window.scrollTo(0, 0); - }, [filteredMangas]); + }, [query, unread, downloaded]); return ( void; -} +const calcProgress = (status: UpdaterSubscription['updateStatusChanged'] | undefined) => { + if (!status) { + return 0; + } -function UpdateChecker({ handleFinishedUpdate }: IUpdateCheckerProps) { + const finishedUpdates = status.failedJobs.mangas.totalCount + status.completeJobs.mangas.totalCount; + const totalMangas = finishedUpdates + status.pendingJobs.mangas.totalCount + status.runningJobs.mangas.totalCount; + + const progress = 100 * (finishedUpdates / totalMangas); + + return Number.isNaN(progress) ? 0 : progress; +}; + +function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate: () => void }) { const { t } = useTranslation(); - const [loading, setLoading] = useState(false); - const [progress, setProgress] = useState(0); + const { data: updaterData } = requestManager.useUpdaterSubscription(); + const status = updaterData?.updateStatusChanged; + + const loading = !!status?.isRunning; + const progress = useMemo( + () => calcProgress(status), + [ + status?.failedJobs.mangas.totalCount, + status?.completeJobs.mangas.totalCount, + status?.pendingJobs.mangas.totalCount, + status?.runningJobs.mangas.totalCount, + ], + ); + + const isUpdateFinished = progress === 100; + if (isUpdateFinished) { + handleFinishedUpdate(); + } const onClick = async () => { try { - setLoading(true); - setProgress(0); await requestManager.startGlobalUpdate().response; } catch (e) { makeToast(t('global.error.label.update_failed'), 'error'); - setLoading(false); } }; - useEffect(() => { - const wsc = requestManager.getUpdateWebSocket(); - - // "loading" can't be used since it will be outdated once the state gets changed - // it could be used by adding it as a dependency of "useEffect" but then the socket would - // get closed and connected again every time it changes - let updateStarted = false; - - wsc.onmessage = (e) => { - const { running, mangaStatusMap } = JSON.parse(e.data) as IUpdateStatus; - const { COMPLETE = [], RUNNING = [], PENDING = [] } = mangaStatusMap; - - const currentProgress = 100 * (COMPLETE.length / (COMPLETE.length + RUNNING.length + PENDING.length)); - - const isUpdateFinished = currentProgress === 100; - const ignoreFaultyMessage = !updateStarted && !running && isUpdateFinished; - - // for some reason the server sends 100% completed manga updates when connecting to the - // socket while no update is running - if (ignoreFaultyMessage) { - return; - } - - updateStarted = running; - setLoading(running); - setProgress(Number.isNaN(currentProgress) ? 0 : currentProgress); - - if (isUpdateFinished) { - handleFinishedUpdate(Date.now()); - } - }; - - return () => wsc.close(); - }, []); - return ( {loading ? : } diff --git a/src/components/library/useSubscription.ts b/src/components/library/useSubscription.ts deleted file mode 100644 index 5c21f1dd..00000000 --- a/src/components/library/useSubscription.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) Contributors to the Suwayomi project - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -import { useEffect, useState } from 'react'; -import requestManager from '@/lib/RequestManager'; - -const useSubscription = (path: string, callback?: (newValue: T) => boolean | void) => { - const [state, setState] = useState(); - - useEffect(() => { - const wsc = new WebSocket(requestManager.getValidWebSocketUrl(path)); - - wsc.onmessage = (e) => { - const data = JSON.parse(e.data) as T; - if (callback) { - // If callback is specified, only update state if callback returns true - // This is so that useSubscription can be used without causing rerender - if (callback(data) === true) { - setState(data); - } - } else { - setState(data); - } - }; - - return () => wsc.close(); - }, [path]); - - return { data: state }; -}; - -export default useSubscription; diff --git a/src/components/manga/ChapterCard.tsx b/src/components/manga/ChapterCard.tsx index e6e492c4..a39db05a 100644 --- a/src/components/manga/ChapterCard.tsx +++ b/src/components/manga/ChapterCard.tsx @@ -27,15 +27,16 @@ import Typography from '@mui/material/Typography'; import React from 'react'; import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { IChapter, IDownloadChapter } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import { getUploadDateString } from '@/util/date'; import DownloadStateIndicator from '@/components/molecules/DownloadStateIndicator'; +import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts'; +import { TChapter } from '@/typings.ts'; interface IProps { - chapter: IChapter; - triggerChaptersUpdate: () => void; - downloadChapter: IDownloadChapter | undefined; + chapter: TChapter; + chapterIds: number[]; + downloadChapter: DownloadType | undefined; showChapterNumber: boolean; onSelect: (selected: boolean) => void; selected: boolean | null; @@ -45,7 +46,7 @@ const ChapterCard: React.FC = (props: IProps) => { const { t } = useTranslation(); const theme = useTheme(); - const { chapter, triggerChaptersUpdate, downloadChapter: dc, showChapterNumber, onSelect, selected } = props; + const { chapter, chapterIds, downloadChapter: dc, showChapterNumber, onSelect, selected } = props; const isSelecting = selected !== null; const [anchorEl, setAnchorEl] = React.useState(null); @@ -62,26 +63,29 @@ const ChapterCard: React.FC = (props: IProps) => { setAnchorEl(null); }; - const sendChange = (key: string, value: any) => { + type UpdatePatchInput = UpdateChapterPatchInput & { markPrevRead?: boolean }; + const sendChange = (key: Key, value: UpdatePatchInput[Key]) => { handleClose(); - requestManager - .updateChapter(chapter.mangaId, chapter.index, { - [key]: value, - lastPageRead: key === 'read' ? 0 : undefined, - }) - .response.then(() => triggerChaptersUpdate()); + if (key === 'markPrevRead') { + const index = chapterIds.findIndex((chapterId) => chapterId === chapter.id); + requestManager.updateChapters(chapterIds.slice(index, -1), { isRead: true }); + return; + } + + requestManager.updateChapter(chapter.id, { + [key]: value, + lastPageRead: key === 'isRead' ? 0 : undefined, + }); }; const downloadChapter = () => { - requestManager.addChapterToDownloadQueue(chapter.mangaId, chapter.index); + requestManager.addChapterToDownloadQueue(chapter.id); handleClose(); }; const deleteChapter = () => { - requestManager - .deleteDownloadedChapter(chapter.mangaId, chapter.index) - .response.then(() => triggerChaptersUpdate()); + requestManager.deleteDownloadedChapter(chapter.id); handleClose(); }; @@ -98,8 +102,8 @@ const ChapterCard: React.FC = (props: IProps) => { } }; - const isDownloaded = chapter.downloaded; - const canBeDownloaded = !chapter.downloaded && dc === undefined; + const { isDownloaded } = chapter; + const canBeDownloaded = !chapter.isDownloaded && dc === undefined; return (
  • @@ -111,9 +115,9 @@ const ChapterCard: React.FC = (props: IProps) => { > @@ -128,7 +132,7 @@ const ChapterCard: React.FC = (props: IProps) => { > - {chapter.bookmarked && ( + {chapter.isBookmarked && ( = (props: IProps) => { {chapter.scanlator} - {getUploadDateString(chapter.uploadDate)} + {getUploadDateString(Number(chapter.uploadDate ?? 0))} {isDownloaded && ` • ${t('chapter.status.label.downloaded')}`} @@ -177,24 +181,24 @@ const ChapterCard: React.FC = (props: IProps) => { {t('chapter.action.download.add.label.action')} )} - sendChange('bookmarked', !chapter.bookmarked)}> + sendChange('isBookmarked', !chapter.isBookmarked)}> - {chapter.bookmarked && } - {!chapter.bookmarked && } + {chapter.isBookmarked && } + {!chapter.isBookmarked && } - {chapter.bookmarked && t('chapter.action.bookmark.remove.label.action')} - {!chapter.bookmarked && t('chapter.action.bookmark.add.label.action')} + {chapter.isBookmarked && t('chapter.action.bookmark.remove.label.action')} + {!chapter.isBookmarked && t('chapter.action.bookmark.add.label.action')} - sendChange('read', !chapter.read)}> + sendChange('isRead', !chapter.isRead)}> - {chapter.read && } - {!chapter.read && } + {chapter.isRead && } + {!chapter.isRead && } - {chapter.read && t('chapter.action.mark_as_read.remove.label.action')} - {!chapter.read && t('chapter.action.mark_as_read.add.label.action.current')} + {chapter.isRead && t('chapter.action.mark_as_read.remove.label.action')} + {!chapter.isRead && t('chapter.action.mark_as_read.add.label.action.current')} sendChange('markPrevRead', true)}> diff --git a/src/components/manga/ChapterList.tsx b/src/components/manga/ChapterList.tsx index 1514bcce..b53e5732 100644 --- a/src/components/manga/ChapterList.tsx +++ b/src/components/manga/ChapterList.tsx @@ -11,9 +11,8 @@ import Typography from '@mui/material/Typography'; import React, { ComponentProps, useEffect, useMemo, useRef, useState } from 'react'; import { Virtuoso } from 'react-virtuoso'; import { useTranslation } from 'react-i18next'; -import { BatchChaptersChange, IChapter, IDownloadChapter, IQueue, TranslationKey } from '@/typings'; -import requestManager from '@/lib/RequestManager'; -import useSubscription from '@/components/library/useSubscription'; +import { TChapter, TManga, TranslationKey } from '@/typings'; +import requestManager from '@/lib/requests/RequestManager.ts'; import ChapterCard from '@/components/manga/ChapterCard'; import ResumeFab from '@/components/manga/ResumeFAB'; import { filterAndSortChapters, useChapterOptions } from '@/components/manga/util'; @@ -22,6 +21,7 @@ import makeToast from '@/components/util/Toast'; import ChaptersToolbarMenu from '@/components/manga/ChaptersToolbarMenu'; import SelectionFAB from '@/components/manga/SelectionFAB'; import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab'; +import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts'; const StyledVirtuoso = styled(Virtuoso)(({ theme }) => ({ listStyle: 'none', @@ -68,58 +68,54 @@ const actionsStrings: { }; export interface IChapterWithMeta { - chapter: IChapter; - downloadChapter: IDownloadChapter | undefined; + chapter: TChapter; + downloadChapter: DownloadType | undefined; selected: boolean | null; } interface IProps { - mangaId: string; + manga: TManga; + isRefreshing: boolean; } -const ChapterList: React.FC = ({ mangaId }) => { +const ChapterList: React.FC = ({ manga, isRefreshing }) => { const { t } = useTranslation(); const [selection, setSelection] = useState(null); - const prevQueueRef = useRef(); - const queue = useSubscription('downloads').data?.queue; + const prevQueueRef = useRef(); + const { data: downloaderData } = requestManager.useDownloadSubscription(); + const queue = (downloaderData?.downloadChanged.queue as DownloadType[]) ?? []; - const [options, dispatch] = useChapterOptions(mangaId); - const { data: chaptersData, mutate, isLoading } = requestManager.useGetMangaChapters(mangaId); - const chapters = useMemo(() => chaptersData ?? [], [chaptersData]); + const [options, dispatch] = useChapterOptions(manga.id); + const { data: chaptersData, loading: isLoading, refetch } = requestManager.useGetMangaChapters(manga.id); + const chapters = useMemo(() => chaptersData?.chapters.nodes ?? [], [chaptersData?.chapters.nodes]); + const mangaChapterIds = useMemo(() => chapters.map((chapter) => chapter.id), [chapters]); useEffect(() => { if (prevQueueRef.current && queue) { const prevQueue = prevQueueRef.current; const changedDownloads = queue.filter((cd) => { const prevChapterDownload = prevQueue.find( - (pcd) => cd.chapterIndex === pcd.chapterIndex && cd.mangaId === pcd.mangaId, + (pcd) => + cd.chapter.sourceOrder === pcd.chapter.sourceOrder && + cd.chapter.manga.id === pcd.chapter.manga.id, ); if (!prevChapterDownload) return true; return cd.state !== prevChapterDownload.state; }); - if (changedDownloads.length > 0) { - mutate(); + if (changedDownloads.length > 0 || prevQueue?.length !== queue.length) { + refetch(); } } prevQueueRef.current = queue; }, [queue]); - const visibleChapters = useMemo( - () => filterAndSortChapters(chapters, options), // - [chapters, options], - ); + const visibleChapters = useMemo(() => filterAndSortChapters(chapters, options), [chapters, options]); - const firstUnreadChapter = useMemo( - () => - chapters - .slice() - .reverse() - .find((chapter) => !chapter.read), - [chapters], - ); + const nextChapterIndexToRead = (manga.lastReadChapter?.sourceOrder ?? 0) + 1; + const isLatestChapterRead = manga.chapters.totalCount === manga.lastReadChapter?.sourceOrder; const handleSelection = (index: number) => { const chapter = visibleChapters[index]; @@ -154,26 +150,67 @@ const ChapterList: React.FC = ({ mangaId }) => { if (action === 'download') { actionPromise = requestManager.addChaptersToDownloadQueue(chapterIds).response; } else { - const change: BatchChaptersChange = {}; + const change: UpdateChapterPatchInput = {}; - if (action === 'delete') change.delete = true; - else if (action === 'bookmark') change.isBookmarked = true; + if (action === 'bookmark') change.isBookmarked = true; else if (action === 'unbookmark') change.isBookmarked = false; else if (action === 'mark_as_read' || action === 'mark_as_unread') { change.isRead = action === 'mark_as_read'; change.lastPageRead = 0; } - actionPromise = requestManager.updateChapters(chapterIds, change).response; + if (action === 'delete') { + actionPromise = requestManager.deleteDownloadedChapters(chapterIds).response; + } else { + actionPromise = requestManager.updateChapters(chapterIds, change).response; + } } actionPromise .then(() => makeToast(t(actionsStrings[action].success, { count: chapterIds.length }), 'success')) - .then(() => mutate()) .catch(() => makeToast(t(actionsStrings[action].error, { count: chapterIds.length }), 'error')); }; - if (isLoading) { + const noChaptersFound = chapters.length === 0; + const noChaptersMatchingFilter = !noChaptersFound && visibleChapters.length === 0; + + const chaptersWithMeta: IChapterWithMeta[] = useMemo( + () => + visibleChapters.map((chapter) => { + const downloadChapter = queue?.find( + (cd) => cd.chapter.sourceOrder === chapter.sourceOrder && cd.chapter.manga.id === chapter.manga.id, + ); + const selected = selection?.includes(chapter.id) ?? null; + return { + chapter, + downloadChapter, + selected, + }; + }), + [queue, selection, visibleChapters], + ); + + const selectedChapters = useMemo(() => { + if (!selection) { + return null; + } + + return chaptersWithMeta.filter(({ chapter }) => selection.includes(chapter.id)); + }, [selection, chapters]); + + const chapterListFAB = useMemo(() => { + if (selectedChapters) { + return ; + } + + if (!isLatestChapterRead) { + return ; + } + + return null; + }, [selectedChapters, isLatestChapterRead]); + + if (isLoading || (noChaptersFound && isRefreshing)) { return (
    = ({ mangaId }) => { ); } - const noChaptersFound = chapters.length === 0; - const noChaptersMatchingFilter = !noChaptersFound && visibleChapters.length === 0; - - const chaptersWithMeta: IChapterWithMeta[] = visibleChapters.map((chapter) => { - const downloadChapter = queue?.find( - (cd) => cd.chapterIndex === chapter.index && cd.mangaId === chapter.mangaId, - ); - const selected = selection?.includes(chapter.id) ?? null; - return { - chapter, - downloadChapter, - selected, - }; - }); - - const selectedChapters = - selection === null ? null : chaptersWithMeta.filter(({ chapter }) => selection.includes(chapter.id)); - return ( <> @@ -266,8 +285,8 @@ const ChapterList: React.FC = ({ mangaId }) => { return ( mutate()} onSelect={() => handleSelection(index)} /> ); @@ -276,11 +295,7 @@ const ChapterList: React.FC = ({ mangaId }) => { overscan={window.innerHeight * 0.5} /> - {selectedChapters !== null ? ( - - ) : ( - firstUnreadChapter && - )} + {chapterListFAB} ); }; diff --git a/src/components/manga/MangaDetails.tsx b/src/components/manga/MangaDetails.tsx index 85767253..0e783644 100644 --- a/src/components/manga/MangaDetails.tsx +++ b/src/components/manga/MangaDetails.tsx @@ -10,13 +10,12 @@ import FavoriteIcon from '@mui/icons-material/Favorite'; import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder'; import PublicIcon from '@mui/icons-material/Public'; import { styled } from '@mui/material/styles'; -import React, { useEffect } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { mutate } from 'swr'; import { t as translate } from 'i18next'; import Button from '@mui/material/Button'; -import { IManga, ISource } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import { ISource, TManga } from '@/typings'; +import requestManager from '@/lib/requests/RequestManager.ts'; import makeToast from '@/components/util/Toast'; const DetailsWrapper = styled('div')(({ theme }) => ({ @@ -125,11 +124,36 @@ const Genres = styled('div')(() => ({ }, })); +const OpenSourceButton = ({ url }: { url?: string | null }) => { + const { t } = useTranslation(); + + const button = useMemo( + () => ( + + ), + [url], + ); + + if (!url) { + return button; + } + + return ( + + + + ); +}; + interface IProps { - manga: IManga; + manga: TManga; } -function getSourceName(source: ISource) { +function getSourceName(source?: ISource | null) { if (!source) { return translate('global.label.unknown'); } @@ -137,12 +161,16 @@ function getSourceName(source: ISource) { return source.displayName ?? source.id; } -function getValueOrUnknown(val: string) { +function getValueOrUnknown(val?: string | null) { return val || 'UNKNOWN'; } const MangaDetails: React.FC = ({ manga }) => { const { t } = useTranslation(); + const { data: categoriesData, loading: areCategoriesLoading } = requestManager.useGetCategories(); + const categories = categoriesData?.categories.nodes ?? []; + const defaultCategoryIds = categories.filter((category) => category.default).map((category) => category.id); + const [updateMangaCategories] = requestManager.useUpdateMangaCategories(); useEffect(() => { if (!manga.source) { @@ -151,13 +179,24 @@ const MangaDetails: React.FC = ({ manga }) => { }, [manga.source]); const addToLibrary = () => { - mutate(`/api/v1/manga/${manga.id}`, { ...manga, inLibrary: true }, { revalidate: false }); - requestManager.addMangaToLibrary(manga.id).response.then(() => mutate(`/api/v1/manga/${manga.id}`)); + Promise.all([ + requestManager.updateManga(manga.id, { inLibrary: true }).response, + updateMangaCategories({ + variables: { input: { id: manga.id, patch: { addToCategories: defaultCategoryIds } } }, + }), + ]) + .then(() => makeToast(t('library.info.label.added_to_library'), 'success')) + .catch(() => { + makeToast(t('library.error.label.add_to_library'), 'error'); + }); }; const removeFromLibrary = () => { - mutate(`/api/v1/manga/${manga.id}`, { ...manga, inLibrary: false }, { revalidate: false }); - requestManager.removeMangaFromLibrary(manga.id).response.then(() => mutate(`/api/v1/manga/${manga.id}`)); + Promise.all([requestManager.updateManga(manga.id, { inLibrary: false }).response]) + .then(() => makeToast(t('library.info.label.removed_from_library'), 'success')) + .catch(() => { + makeToast(t('library.error.label.remove_from_library'), 'error'); + }); }; return ( @@ -165,7 +204,9 @@ const MangaDetails: React.FC = ({ manga }) => { - Manga Thumbnail + {manga.thumbnailUrl && ( + Manga Thumbnail + )}

    {manga.title}

    @@ -184,6 +225,7 @@ const MangaDetails: React.FC = ({ manga }) => {
    - - - +
    diff --git a/src/components/manga/MangaToolbarMenu.tsx b/src/components/manga/MangaToolbarMenu.tsx index 43980f94..5a2f886b 100644 --- a/src/components/manga/MangaToolbarMenu.tsx +++ b/src/components/manga/MangaToolbarMenu.tsx @@ -21,11 +21,11 @@ import { } from '@mui/material'; import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { IManga } from '@/typings'; import CategorySelect from '@/components/navbar/action/CategorySelect'; +import { TManga } from '@/typings.ts'; interface IProps { - manga: IManga; + manga: TManga; onRefresh: () => any; refreshing: boolean; } diff --git a/src/components/manga/ResumeFAB.tsx b/src/components/manga/ResumeFAB.tsx index 5c43c5d5..6e6c7eba 100644 --- a/src/components/manga/ResumeFAB.tsx +++ b/src/components/manga/ResumeFAB.tsx @@ -9,25 +9,21 @@ import { Link } from 'react-router-dom'; import { PlayArrow } from '@mui/icons-material'; import { useTranslation } from 'react-i18next'; -import { IChapter } from '@/typings'; import StyledFab from '@/components/util/StyledFab'; interface ResumeFABProps { - chapter: IChapter; - mangaId: string; + chapterIndex: number; + mangaId: number; } export default function ResumeFab(props: ResumeFABProps) { const { t } = useTranslation(); - const { - chapter: { index }, - mangaId, - } = props; + const { chapterIndex, mangaId } = props; return ( - + - {index === 1 ? t('global.button.start') : t('global.button.resume')} + {chapterIndex === 1 ? t('global.button.start') : t('global.button.resume')} ); } diff --git a/src/components/manga/SelectionFAB.tsx b/src/components/manga/SelectionFAB.tsx index bd2c0de4..93d1e514 100644 --- a/src/components/manga/SelectionFAB.tsx +++ b/src/components/manga/SelectionFAB.tsx @@ -63,38 +63,38 @@ const SelectionFAB: React.FC = (props) => { !c.downloaded && dc === undefined, + ({ chapter: c, downloadChapter: dc }) => !c.isDownloaded && dc === undefined, )} onClick={handleAction} title={t('chapter.action.download.add.button.selected')} /> chapter.downloaded)} + matchingChapters={selectedChapters.filter(({ chapter }) => chapter.isDownloaded)} onClick={handleAction} title={t('chapter.action.download.delete.button.selected')} /> !chapter.bookmarked)} + matchingChapters={selectedChapters.filter(({ chapter }) => !chapter.isBookmarked)} onClick={handleAction} title={t('chapter.action.bookmark.add.button.selected')} /> chapter.bookmarked)} + matchingChapters={selectedChapters.filter(({ chapter }) => chapter.isBookmarked)} onClick={handleAction} title={t('chapter.action.bookmark.remove.button.selected')} /> !chapter.read)} + matchingChapters={selectedChapters.filter(({ chapter }) => !chapter.isRead)} onClick={handleAction} title={t('chapter.action.mark_as_read.add.button.selected')} /> chapter.read)} + matchingChapters={selectedChapters.filter(({ chapter }) => chapter.isRead)} onClick={handleAction} title={t('chapter.action.mark_as_read.remove.button.selected')} /> diff --git a/src/components/manga/hooks.ts b/src/components/manga/hooks.ts index 0edbefb0..7eb1e41f 100644 --- a/src/components/manga/hooks.ts +++ b/src/components/manga/hooks.ts @@ -7,8 +7,7 @@ */ import { useCallback, useEffect, useState } from 'react'; -import { mutate } from 'swr'; -import requestManager, { RequestManager } from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; export const useRefreshManga = (mangaId: string) => { const [fetchingOnline, setFetchingOnline] = useState(false); @@ -16,14 +15,8 @@ export const useRefreshManga = (mangaId: string) => { const handleRefresh = useCallback(async () => { setFetchingOnline(true); await Promise.all([ - requestManager.getManga(mangaId, true).response.then((res) => { - mutate(`${RequestManager.API_VERSION}manga/${mangaId}`, res, { revalidate: false }); - }), - requestManager.getMangaChapters(mangaId, true).response.then((res) => - mutate(`${RequestManager.API_VERSION}manga/${mangaId}/chapters`, res, { - revalidate: false, - }), - ), + requestManager.getMangaFetch(mangaId, { awaitRefetchQueries: true }).response, + requestManager.getMangaChaptersFetch(mangaId, { awaitRefetchQueries: true }).response, ]).finally(() => setFetchingOnline(false)); }, [mangaId]); diff --git a/src/components/manga/util.tsx b/src/components/manga/util.tsx index 27073b1a..ec63ee08 100644 --- a/src/components/manga/util.tsx +++ b/src/components/manga/util.tsx @@ -11,8 +11,8 @@ import { ChapterListOptions, ChapterOptionsReducerAction, ChapterSortMode, - IChapter, NullAndUndefined, + TChapter, TranslationKey, } from '@/typings'; import { useReducerLocalStorage } from '@/util/useLocalStorage'; @@ -46,7 +46,7 @@ function chapterOptionsReducer(state: ChapterListOptions, actions: ChapterOption } } -export function unreadFilter(unread: NullAndUndefined, { read: isChapterRead }: IChapter) { +export function unreadFilter(unread: NullAndUndefined, { isRead: isChapterRead }: TChapter) { switch (unread) { case true: return !isChapterRead; @@ -57,7 +57,7 @@ export function unreadFilter(unread: NullAndUndefined, { read: isChapte } } -function downloadFilter(downloaded: NullAndUndefined, { downloaded: chapterDownload }: IChapter) { +function downloadFilter(downloaded: NullAndUndefined, { isDownloaded: chapterDownload }: TChapter) { switch (downloaded) { case true: return chapterDownload; @@ -68,7 +68,7 @@ function downloadFilter(downloaded: NullAndUndefined, { downloaded: cha } } -function bookmarkedFilter(bookmarked: NullAndUndefined, { bookmarked: chapterBookmarked }: IChapter) { +function bookmarkedFilter(bookmarked: NullAndUndefined, { isBookmarked: chapterBookmarked }: TChapter) { switch (bookmarked) { case true: return chapterBookmarked; @@ -79,7 +79,7 @@ function bookmarkedFilter(bookmarked: NullAndUndefined, { bookmarked: c } } -export function filterAndSortChapters(chapters: IChapter[], options: ChapterListOptions): IChapter[] { +export function filterAndSortChapters(chapters: TChapter[], options: ChapterListOptions): TChapter[] { const filtered = options.active ? chapters.filter( (chp) => @@ -88,14 +88,17 @@ export function filterAndSortChapters(chapters: IChapter[], options: ChapterList bookmarkedFilter(options.bookmarked, chp), ) : [...chapters]; - const Sorted = options.sortBy === 'fetchedAt' ? filtered.sort((a, b) => a.fetchedAt - b.fetchedAt) : filtered; + const Sorted = + options.sortBy === 'fetchedAt' + ? filtered.sort((a, b) => Number(a.fetchedAt ?? 0) - Number(b.fetchedAt ?? 0)) + : filtered; if (options.reverse) { Sorted.reverse(); } return Sorted; } -export const useChapterOptions = (mangaId: string) => +export const useChapterOptions = (mangaId: number) => useReducerLocalStorage( chapterOptionsReducer, `${mangaId}filterOptions`, diff --git a/src/components/molecules/DownloadStateIndicator.tsx b/src/components/molecules/DownloadStateIndicator.tsx index e4541227..7bf7e2c0 100644 --- a/src/components/molecules/DownloadStateIndicator.tsx +++ b/src/components/molecules/DownloadStateIndicator.tsx @@ -10,17 +10,18 @@ import { CircularProgress, Box } from '@mui/material'; import Typography from '@mui/material/Typography'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { IDownloadChapter, TranslationKey } from '@/typings'; +import { TranslationKey } from '@/typings'; +import { DownloadState, DownloadType } from '@/lib/graphql/generated/graphql.ts'; interface DownloadStateIndicatorProps { - download: IDownloadChapter; + download: DownloadType; } -const DOWNLOAD_STATE_TO_TRANSLATION_KEY_MAP: { [state in IDownloadChapter['state']]: TranslationKey } = { - Downloading: 'download.state.label.downloading', - Error: 'download.state.label.error', - Finished: 'download.state.label.finished', - Queued: 'download.state.label.queued', +const DOWNLOAD_STATE_TO_TRANSLATION_KEY_MAP: { [state in DownloadState]: TranslationKey } = { + DOWNLOADING: 'download.state.label.downloading', + ERROR: 'download.state.label.error', + FINISHED: 'download.state.label.finished', + QUEUED: 'download.state.label.queued', } as const; const DownloadStateIndicator: React.FC = ({ download }) => { diff --git a/src/components/navbar/ReaderNavBar.tsx b/src/components/navbar/ReaderNavBar.tsx index fba208aa..3ad637d1 100644 --- a/src/components/navbar/ReaderNavBar.tsx +++ b/src/components/navbar/ReaderNavBar.tsx @@ -24,7 +24,7 @@ import ListItemText from '@mui/material/ListItemText'; import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; import Collapse from '@mui/material/Collapse'; import { useTranslation } from 'react-i18next'; -import { ChapterOffset, IChapter, IManga, IMangaCard, IReaderSettings } from '@/typings'; +import { ChapterOffset, IReaderSettings, TChapter, TManga } from '@/typings'; import ReaderSettingsOptions from '@/components/reader/ReaderSettingsOptions'; const Root = styled('div')(({ theme }) => ({ @@ -114,8 +114,8 @@ const OpenDrawerButton = styled(IconButton)(({ theme }) => ({ interface IProps { settings: IReaderSettings; setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void; - manga: IManga | IMangaCard; - chapter: IChapter; + manga: TManga; + chapter: TChapter; curPage: number; scrollToPage: (page: number) => void; openNextChapter: (offset: ChapterOffset, setHistory: (nextChapterIndex: number) => void) => Promise; @@ -303,7 +303,7 @@ export default function ReaderNavBar(props: IProps) { openNextChapter(ChapterOffset.PREV, (prevChapterIndex) => { navigate(`/manga/${manga.id}/chapter/${prevChapterIndex}`, { @@ -321,11 +321,11 @@ export default function ReaderNavBar(props: IProps) { - {rett} - - - ); - } - return null; -} - function noSelect( values: string[], name: string, @@ -84,7 +40,7 @@ function noSelect( const upd = update.filter( (e: { position: number; group: number | undefined }) => !(position === e.position && group === e.group), ); - updateFilterValue([...upd, { position, state: vall.toString(), group }]); + updateFilterValue([...upd, { type: 'selectState', position, state: vall, group }]); }; const rett = values.map((value: string) => ( @@ -104,21 +60,7 @@ function noSelect( return null; } -const SelectFilter: React.FC = ({ - values, - name, - state, - selected, - position, - updateFilterValue, - update, - group, -}) => { - if (selected === undefined) { - return noSelect(values, name, state, position, updateFilterValue, update, group); - } - - return hasSelect(values, name, state, position, updateFilterValue, update, group); -}; +const SelectFilter: React.FC = ({ values, name, state, position, updateFilterValue, update, group }) => + noSelect(values, name, state, position, updateFilterValue, update, group); export default SelectFilter; diff --git a/src/components/source/filters/SortFilter.tsx b/src/components/source/filters/SortFilter.tsx index beb4f6a3..4748cf29 100644 --- a/src/components/source/filters/SortFilter.tsx +++ b/src/components/source/filters/SortFilter.tsx @@ -9,13 +9,13 @@ import { ExpandLess, ExpandMore } from '@mui/icons-material'; import { Collapse, ListItemButton, ListItemText, Stack, Box } from '@mui/material'; import React from 'react'; -import { IState } from '@/typings'; import SortRadioInput from '@/components/atoms/SortRadioInput'; +import { SortSelectionInput } from '@/lib/graphql/generated/graphql.ts'; interface Props { values: any; name: string; - state: IState; + state: SortSelectionInput; position: number; group: number | undefined; updateFilterValue: Function; @@ -45,7 +45,7 @@ const SortFilter: React.FC = (props: Props) => { const upd = update.filter( (e: { position: number; group: number | undefined }) => !(position === e.position && group === e.group), ); - updateFilterValue([...upd, { position, state: JSON.stringify(tmp), group }]); + updateFilterValue([...upd, { type: 'sortState', position, state: tmp, group }]); }; return ( diff --git a/src/components/source/filters/TextFilter.tsx b/src/components/source/filters/TextFilter.tsx index 7dd82065..7b62304b 100644 --- a/src/components/source/filters/TextFilter.tsx +++ b/src/components/source/filters/TextFilter.tsx @@ -29,7 +29,7 @@ const TextFilter: React.FC = (props) => { const upd = update.filter( (el: { position: number; group: number | undefined }) => !(position === el.position && group === el.group), ); - updateFilterValue([...upd, { position, state: inputText, group }]); + updateFilterValue([...upd, { type: 'textState', position, state: inputText, group }]); }, [inputText]); if (state !== undefined) { diff --git a/src/components/source/filters/TriStateFilter.tsx b/src/components/source/filters/TriStateFilter.tsx index e9270b25..70a53094 100644 --- a/src/components/source/filters/TriStateFilter.tsx +++ b/src/components/source/filters/TriStateFilter.tsx @@ -8,9 +8,10 @@ import React from 'react'; import ThreeStateCheckboxInput from '@/components/atoms/ThreeStateCheckboxInput'; +import { TriState } from '@/lib/graphql/generated/graphql.ts'; interface Props { - state: number; + state: TriState; name: string; position: number; group: number | undefined; @@ -18,9 +19,35 @@ interface Props { update: any; } +const convertTriStateToNumber = (triState: TriState): number => { + switch (triState) { + case TriState.Ignore: + return 0; + case TriState.Include: + return 1; + case TriState.Exclude: + return 2; + default: + throw new Error(`Unexpected TriState ${triState}`); + } +}; + +const convertNumberToTriState = (state: number): TriState => { + switch (state) { + case 0: + return TriState.Ignore; + case 1: + return TriState.Include; + case 2: + return TriState.Exclude; + default: + throw new Error(`Unexpected state number ${state}`); + } +}; + const TriStateFilter: React.FC = (props) => { const { state, name, position, group, updateFilterValue, update } = props; - const [val, setval] = React.useState(Number(state)); + const [val, setval] = React.useState(convertTriStateToNumber(state)); const handleChange = (checked: boolean | null | undefined) => { // eslint-disable-next-line no-nested-ternary @@ -32,8 +59,9 @@ const TriStateFilter: React.FC = (props) => { updateFilterValue([ ...upd, { + type: 'triState', position, - state: newState.toString(), + state: convertNumberToTriState(newState), group, }, ]); diff --git a/src/components/sourceConfiguration/EditTextPreference.tsx b/src/components/sourceConfiguration/EditTextPreference.tsx index 45a58e8d..9a364b35 100644 --- a/src/components/sourceConfiguration/EditTextPreference.tsx +++ b/src/components/sourceConfiguration/EditTextPreference.tsx @@ -22,22 +22,29 @@ import { EditTextPreferenceProps } from '@/typings'; export default function EditTextPreference(props: EditTextPreferenceProps) { const { t } = useTranslation(); - const { title, summary, dialogTitle, dialogMessage, currentValue, updateValue } = props; + const { + EditTextPreferenceTitle: title, + summary, + dialogTitle, + dialogMessage, + EditTextPreferenceCurrentValue: currentValue, + updateValue, + } = props; - const [internalCurrentValue, setInternalCurrentValue] = useState(currentValue); + const [internalCurrentValue, setInternalCurrentValue] = useState(currentValue ?? ''); const [dialogOpen, setDialogOpen] = useState(false); const handleDialogCancel = () => { setDialogOpen(false); // reset the dialog - setInternalCurrentValue(currentValue); + setInternalCurrentValue(currentValue ?? ''); }; const handleDialogSubmit = () => { setDialogOpen(false); - updateValue(internalCurrentValue); + updateValue('editTextState', internalCurrentValue); }; return ( diff --git a/src/components/sourceConfiguration/ListPreference.tsx b/src/components/sourceConfiguration/ListPreference.tsx index 6cee2401..0460be0c 100644 --- a/src/components/sourceConfiguration/ListPreference.tsx +++ b/src/components/sourceConfiguration/ListPreference.tsx @@ -85,12 +85,20 @@ function ListDialog(props: IListDialogProps) { } export default function ListPreference(props: ListPreferenceProps) { - const { title, summary, currentValue, updateValue, entryValues, entries } = props; - const [internalCurrentValue, setInternalCurrentValue] = useState(currentValue); + const { + ListPreferenceTitle: title, + summary, + ListPreferenceCurrentValue: currentValue, + ListPreferenceDefault: defaultValue, + updateValue, + entryValues, + entries, + } = props; + const [internalCurrentValue, setInternalCurrentValue] = useState(currentValue ?? defaultValue ?? ''); const [dialogOpen, setDialogOpen] = useState(false); useEffect(() => { - setInternalCurrentValue(currentValue); + setInternalCurrentValue(currentValue ?? defaultValue ?? ''); }, [currentValue]); const findEntryOf = (value: string) => { @@ -104,6 +112,10 @@ export default function ListPreference(props: ListPreferenceProps) { }; const getSummary = () => { + if (currentValue == null) { + return ''; + } + if (summary === '%s') { return findEntryOf(currentValue); } @@ -112,7 +124,7 @@ export default function ListPreference(props: ListPreferenceProps) { const handleDialogClose = (newValue: string | null) => { if (newValue !== null) { - updateValue(findEntryValueOf(newValue)); + updateValue('listState', findEntryValueOf(newValue)); // appear smooth setInternalCurrentValue(newValue); @@ -127,7 +139,7 @@ export default function ListPreference(props: ListPreferenceProps) { (currentValue); + const { + MultiSelectListPreferenceTitle: title, + summary, + MultiSelectListPreferenceCurrentValue: currentValue, + MultiSelectListPreferenceDefault: defaultValue, + updateValue, + entryValues, + entries, + } = props; + const [internalCurrentValue, setInternalCurrentValue] = useState(currentValue ?? defaultValue); const [dialogOpen, setDialogOpen] = useState(false); useEffect(() => { setInternalCurrentValue(currentValue); }, [currentValue]); - const findEntriesOf = (values: string[]) => - values.map((value) => { + const findEntriesOf = (values?: string[] | null) => + values?.map((value) => { const idx = entryValues.indexOf(value); return entries[idx]; - }); + }) ?? []; - const findEntryValuesOf = (values: string[]) => - values.map((value) => { + const findEntryValuesOf = (values?: string[] | null) => + values?.map((value) => { const idx = entries.indexOf(value); return entryValues[idx]; - }); + }) ?? []; const getSummary = () => summary; const handleDialogClose = (newValue: string[] | null) => { if (newValue !== null) { // console.log(newValue); - updateValue(findEntryValuesOf(newValue)); + updateValue('multiSelectState', findEntryValuesOf(newValue)); // appear smooth setInternalCurrentValue(newValue); @@ -139,7 +147,7 @@ export default function MultiSelectListPreference(props: MultiSelectListPreferen { + if (props.type === 'CheckBoxPreference') { + return { + title: props.CheckBoxTitle, + defaultValue: props.CheckBoxDefault, + currentValue: props.CheckBoxCheckBoxCurrentValue, + }; + } + + return { + title: props.SwitchPreferenceTitle, + defaultValue: props.SwitchPreferenceDefault, + currentValue: props.SwitchPreferenceCurrentValue, + }; +}; + function TwoSatePreference(props: TwoStatePreferenceProps) { - const { title, summary, currentValue, updateValue, type } = props; - const [internalCurrentValue, setInternalCurrentValue] = useState(currentValue); + const { title, defaultValue, currentValue, summary, updateValue, twoStateType } = { + ...props, + ...getTwoStateValues(props), + }; + const [internalCurrentValue, setInternalCurrentValue] = useState(currentValue ?? defaultValue); useEffect(() => { - setInternalCurrentValue(currentValue); + setInternalCurrentValue(currentValue ?? defaultValue); }, [currentValue]); return ( - {createElement(getTwoStateType(type), { + {createElement(getTwoStateType(twoStateType), { edge: 'end', checked: internalCurrentValue, onChange: () => { - updateValue(!currentValue); + updateValue(twoStateType === 'Switch' ? 'switchState' : 'checkBoxState', !currentValue); // appear smooth setInternalCurrentValue(!currentValue); @@ -49,11 +74,11 @@ function TwoSatePreference(props: TwoStatePreferenceProps) { } export function CheckBoxPreference(props: CheckBoxPreferenceProps) { - return ; + return ; } export function SwitchPreferenceCompat(props: SwitchPreferenceCompatProps) { - return ; + return ; } export default { CheckBoxPreference, SwitchPreferenceCompat }; diff --git a/src/components/util/EmptyView.tsx b/src/components/util/EmptyView.tsx index d2a9ad95..ee7df4c9 100644 --- a/src/components/util/EmptyView.tsx +++ b/src/components/util/EmptyView.tsx @@ -22,7 +22,7 @@ function getRandomErrorFace() { interface IProps { message: string; - messageExtra?: JSX.Element; + messageExtra?: JSX.Element | string; } export default function EmptyView({ message, messageExtra }: IProps) { diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 2ce8f44c..39527f13 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -268,7 +268,15 @@ "error": { "label": { "empty": "Your library is empty", - "no_matches": "No manga matches this filter" + "no_matches": "No manga matches this filter", + "add_to_library": "Added manga to library!", + "remove_from_library": "Could not add manga to library!" + } + }, + "info": { + "label": { + "added_to_library": "Added manga to library!", + "removed_from_library": "Removed manga from library!" } }, "option": { diff --git a/src/lib/RequestManager.ts b/src/lib/RequestManager.ts deleted file mode 100644 index 8a2e34e2..00000000 --- a/src/lib/RequestManager.ts +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright (C) Contributors to the Suwayomi project - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -import { AxiosInstance, AxiosRequestConfig } from 'axios'; -import useSWR, { Middleware, SWRConfiguration, SWRResponse } from 'swr'; -import useSWRInfinite, { SWRInfiniteConfiguration, SWRInfiniteResponse } from 'swr/infinite'; -import { - BackupValidationResult, - BatchChaptersChange, - IAbout, - ICategory, - IChapter, - IExtension, - IManga, - IMangaChapter, - IncludeInGlobalUpdate, - ISource, - ISourceFilters, - IUpdateStatus, - Metadata, - PaginatedList, - PaginatedMangaList, - SourcePreferences, - SourceSearchResult, - UpdateCheck, -} from '@/typings'; -import { HttpMethod as DefaultHttpMethod, IRestClient, RestClient } from '@/lib/RestClient'; -import storage from '@/util/localStorage'; - -enum SWRHttpMethod { - SWR_GET, - SWR_GET_INFINITE, - SWR_POST, - SWR_POST_INFINITE, -} - -type HttpMethodType = DefaultHttpMethod | SWRHttpMethod; -const HttpMethod = { ...SWRHttpMethod, ...DefaultHttpMethod }; - -type RequestOption = { doOnlineFetch?: boolean }; - -type CustomSWROptions = { - skipRequest?: boolean; - getEndpoint?: (index: number, previousData: Data | null) => string | null; - disableCache?: boolean; -}; - -type SWROptions = SWRConfiguration & CustomSWROptions; -type SWRInfiniteOptions = SWRInfiniteConfiguration & CustomSWROptions; - -type SWRInfiniteResponseLoadInfo = { - isInitialLoad: boolean; - isLoadMore: boolean; -}; -type AbortableRequest = { abortRequest: AbortController['abort'] }; -export type AbortableAxiosResponse = { response: Promise } & AbortableRequest; -export type AbortableSWRResponse = SWRResponse & AbortableRequest; -export type AbortableSWRInfiniteResponse = SWRInfiniteResponse & - AbortableRequest & - SWRInfiniteResponseLoadInfo; - -const isLoadingMore = (swrResult: SWRInfiniteResponse): boolean => { - const isNextPageMissing = !!swrResult.data && typeof swrResult.data[swrResult.size - 1] === 'undefined'; - const isRequestActive = swrResult.isValidating; - // SWR "isLoading" state is only updated for the first load, for every subsequent load it's "false" - return !swrResult.isLoading && swrResult.size > 0 && isNextPageMissing && isRequestActive; -}; - -const disableSwrInfiniteCache: Middleware = (useSWRNext) => (key, fetcher, config) => { - const swr = useSWRNext(key, fetcher, config) as unknown as SWRInfiniteResponse; - const { size, data, isLoading, isValidating } = swr; - const isActuallyValidating = !isLoading && !isLoadingMore(swr) && isValidating; - return { - ...swr, - isLoading: isActuallyValidating ? true : isLoading, - data: isActuallyValidating ? undefined : data, - size: isActuallyValidating ? 1 : size, - } as SWRResponse; -}; - -const disableSwrCache: Middleware = (useSWRNext) => (key, fetcher, config) => { - const swr = useSWRNext(key, fetcher, config); - const { data, isLoading, isValidating } = swr; - return { ...swr, isLoading: isValidating ? true : isLoading, data: isValidating ? undefined : data }; -}; - -// the following endpoints have not been implemented: -// - PUT /api/v1/manga/{mangaId}/chapter/{chapterIndex} - modify chapter # PATCH endpoint used instead -// - POST /api/v1/backup/import - import backup # "import backup file" endpoint used instead -// - POST /api/v1/backup/validate - validate backup # "validate backup file" endpoint used instead -// - GET /api/v1/backup/export - export backup # no function needed, url gets called via link triggering the download -export class RequestManager { - public static readonly API_VERSION = '/api/v1/'; - - private readonly restClient: RestClient = new RestClient(); - - public getClient(): IRestClient { - return this.restClient; - } - - public updateClient(config: Partial): void { - this.restClient.updateConfig(config); - } - - public getBaseUrl(): string { - return this.restClient.getClient().defaults.baseURL!; - } - - public getWebSocketBaseUrl(): string { - return this.getBaseUrl().replace('http', 'ws'); - } - - public getValidWebSocketUrl(path: string, apiVersion = RequestManager.API_VERSION): string { - return `${this.getWebSocketBaseUrl()}${apiVersion}${path}`; - } - - public getUpdateWebSocket(): WebSocket { - return new WebSocket(this.getValidWebSocketUrl('update')); - } - - public getDownloadWebSocket(): WebSocket { - return new WebSocket(this.getValidWebSocketUrl('downloads')); - } - - public getValidUrlFor(endpoint: string, apiVersion: string = RequestManager.API_VERSION): string { - return `${this.getBaseUrl()}${apiVersion}${endpoint}`; - } - - public getValidImgUrlFor(imageUrl: string, apiVersion: string = ''): string { - const useCache = storage.getItem('useCache', true); - const useCacheQuery = `?useCache=${useCache}`; - // server provided image urls already contain the api version - return `${this.getValidUrlFor(imageUrl, apiVersion)}${useCacheQuery}`; - } - - private useSwr< - Data = any, - ErrorResponse = any, - OptionsSWR extends SWROptions = SWROptions, - >( - url: string, - httpMethod: DefaultHttpMethod, - { - data, - axiosOptions, - swrOptions, - }: { - data?: Data; - axiosOptions?: AxiosRequestConfig; - swrOptions?: OptionsSWR; - } = {}, - ): SWRResponse { - const { skipRequest, disableCache, ...swrConfig } = swrOptions ?? {}; - - // in case "null" gets passed as the url, SWR won't do the request - return useSWR(skipRequest ? null : url, { - fetcher: (path: string) => this.restClient.fetcher(path, { data, httpMethod, config: axiosOptions }), - use: disableCache ? [disableSwrCache] : undefined, - ...swrConfig, - }); - } - - public useSwrInfinite< - Data = any, - ErrorResponse = any, - OptionsSWR extends SWRInfiniteOptions = SWRInfiniteOptions, - >( - getEndpoint: Required>['getEndpoint'], - httpMethod: DefaultHttpMethod, - { - data, - axiosOptions, - swrOptions, - }: { data?: any; axiosOptions?: AxiosRequestConfig; swrOptions?: OptionsSWR } = {}, - ): SWRInfiniteResponse & SWRInfiniteResponseLoadInfo { - const { skipRequest, disableCache, ...swrConfig } = swrOptions ?? {}; - - // useSWRInfinite will (by default) revalidate the first page, to check if the other pages have to be revalidated as well - const swrResult = useSWRInfinite( - (index, previousData) => { - const pageEndpoint = getEndpoint(index, previousData); - return pageEndpoint !== null && !skipRequest ? this.getValidUrlFor(pageEndpoint) : null; - }, - { - fetcher: (path: string) => this.restClient.fetcher(path, { httpMethod, data, config: axiosOptions }), - use: disableCache ? [disableSwrInfiniteCache] : undefined, - ...swrConfig, - }, - ); - - const customSwrResult = { - ...swrResult, - isInitialLoad: swrResult.isLoading, - isLoadMore: isLoadingMore(swrResult), - }; - customSwrResult.isLoading = customSwrResult.isInitialLoad || customSwrResult.isLoadMore; - - return customSwrResult; - } - - /** - * Performs the actual server request. - * - * In case {@link HttpMethod.GET_SWR} gets passed, the "useSWR" hook gets called. - * In case {@link HttpMethod.GET_SWR_INFINITE} gets passed, the "useSWRInfinite" hook gets called. - * In that case "getEndpoint" has to be passed, which gets used over "endpoint" - * - * Pass "skipRequest" to make SWR skip sending the request to the server. - * In case "formData" is passed, "data" gets ignored. - */ - private doRequest< - Result extends AbortableAxiosResponse | AbortableSWRResponse | AbortableSWRInfiniteResponse, - OptionsSWR extends SWROptions | SWRInfiniteOptions, - >( - httpMethod: HttpMethodType, - endpoint: string, - { - apiVersion = RequestManager.API_VERSION, - data: dataToSend, - formData, - axiosOptions, - swrOptions, - }: { - apiVersion?: string; - data?: any; - formData?: { [key: string]: any }; - axiosOptions?: AxiosRequestConfig; - swrOptions?: OptionsSWR; - } = {}, - ): Result { - const url = `${apiVersion}${endpoint}`; - - let data = dataToSend; - if (formData) { - data = new FormData(); - - Object.entries(formData).forEach(([key, value]) => { - if (value !== undefined) data.append(key, value); // "append" automatically converts non string or blob values to strings - }); - } - - const abortController = new AbortController(); - const abortRequest = (reason?: any): void => { - if (!abortController.signal.aborted) { - abortController.abort(reason); - } - }; - const axiosOptionsWithAbortController = { ...axiosOptions, signal: abortController.signal }; - switch (httpMethod) { - case HttpMethod.SWR_GET: - return { - ...(this.useSwr(url, HttpMethod.GET, { axiosOptions, swrOptions }) as Result), - abortRequest, - }; - case HttpMethod.SWR_GET_INFINITE: - // throw TypeError in case options aren't correctly passed - return { - ...(this.useSwrInfinite(swrOptions!.getEndpoint!, HttpMethod.GET, { - axiosOptions: axiosOptionsWithAbortController, - swrOptions, - }) as Result), - abortRequest, - }; - case SWRHttpMethod.SWR_POST_INFINITE: - return { - ...(this.useSwrInfinite(swrOptions!.getEndpoint!, HttpMethod.POST, { - data, - axiosOptions: axiosOptionsWithAbortController, - swrOptions, - }) as Result), - abortRequest, - }; - case HttpMethod.SWR_POST: - return { - ...(this.useSwr(url, HttpMethod.POST, { - data, - axiosOptions: axiosOptionsWithAbortController, - swrOptions, - }) as Result), - controller: abortController, - }; - default: - return { - response: this.restClient.fetcher(url, { - data, - httpMethod, - config: axiosOptionsWithAbortController, - checkResponseIsJson: false, - }), - abortRequest, - } as Result; - } - } - - public useGetGlobalMeta(swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, 'meta', { swrOptions }); - } - - public setGlobalMetadata(key: string, value: any): AbortableAxiosResponse { - return this.doRequest(HttpMethod.PATCH, 'meta', { formData: { key, value } }); - } - - public useGetAbout(swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, 'settings/about', { swrOptions }); - } - - public useCheckForUpdate(swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, 'settings/check-update', { swrOptions }); - } - - public useGetExtensionList(swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, 'extension/list', { swrOptions }); - } - - public installExtension(extension: string | File): AbortableAxiosResponse { - if (typeof extension === 'string') { - return this.doRequest(HttpMethod.GET, `extension/install/${extension}`); - } - - return this.doRequest(HttpMethod.POST, `extension/install`, { formData: { file: extension } }); - } - - public updateExtension(extension: string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, `extension/update/${extension}`); - } - - public uninstallExtension(extension: string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, `extension/uninstall/${extension}`); - } - - public getExtensionIconUrl(extension: string): string { - return this.getValidImgUrlFor(`extension/icon/${extension}`); - } - - public useGetSourceList(swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, 'source/list', { swrOptions }); - } - - public useGetSource(sourceId: string, swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, `source/${sourceId}`, { swrOptions }); - } - - public useGetSourcePopularMangas( - sourceId: string, - initialPages?: number, - swrOptions?: SWRInfiniteOptions, - ): AbortableSWRInfiniteResponse { - return this.doRequest(SWRHttpMethod.SWR_GET_INFINITE, '', { - swrOptions: { - getEndpoint: (page, previousData) => - previousData?.hasNextPage ?? true ? `source/${sourceId}/popular/${page + 1}` : null, - initialSize: initialPages, - ...swrOptions, - } as typeof swrOptions, - }); - } - - public useGetSourceLatestMangas( - sourceId: string, - initialPages?: number, - swrOptions?: SWRInfiniteOptions, - ): AbortableSWRInfiniteResponse { - return this.doRequest(SWRHttpMethod.SWR_GET_INFINITE, '', { - swrOptions: { - getEndpoint: (page, previousData) => - previousData?.hasNextPage ?? true ? `source/${sourceId}/latest/${page + 1}` : null, - initialSize: initialPages, - ...swrOptions, - } as typeof swrOptions, - }); - } - - public useGetSourcePreferences( - sourceId: string, - swrOptions?: SWROptions, - ): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, `source/${sourceId}/preferences`, { swrOptions }); - } - - public setSourcePreferences(sourceId: string, position: number, value: string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, `source/${sourceId}/preferences`, { data: { position, value } }); - } - - public useGetSourceFilters( - sourceId: string, - reset?: boolean, - swrOptions?: SWROptions, - ): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, `source/${sourceId}/filters`, { swrOptions }); - } - - public setSourceFilters(sourceId: string, filters: { position: number; state: string }[]): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, `source/${sourceId}/filters`, { data: filters }); - } - - public resetSourceFilters(sourceId: string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, `source/${sourceId}/filters?reset=true`); - } - - public useSourceSearch( - sourceId: string, - searchTerm: string, - initialPages?: number, - swrOptions?: SWRInfiniteOptions, - ): AbortableSWRInfiniteResponse { - return this.doRequest(HttpMethod.SWR_GET_INFINITE, '', { - swrOptions: { - getEndpoint: (page, previousData) => - previousData?.hasNextPage ?? true - ? `source/${sourceId}/search?searchTerm=${searchTerm}&pageNum=${page + 1}` - : null, - initialSize: initialPages, - ...swrOptions, - } as typeof swrOptions, - }); - } - - public useSourceQuickSearch( - sourceId: string, - searchTerm: string, - filters: { position: number; state: string }[], - initialPages?: number, - swrOptions?: SWRInfiniteOptions, - ): AbortableSWRInfiniteResponse { - return this.doRequest(HttpMethod.SWR_POST_INFINITE, '', { - data: { searchTerm, filter: filters }, - swrOptions: { - getEndpoint: (page, previousData) => - previousData?.hasNextPage ?? true - ? `source/${sourceId}/quick-search?searchTerm=${searchTerm}&pageNum=${page + 1}` - : null, - initialSize: initialPages, - ...swrOptions, - } as typeof swrOptions, - }); - } - - public useGetManga( - mangaId: number | string, - { doOnlineFetch, ...swrOptions }: SWROptions & RequestOption = {}, - ): AbortableSWRResponse { - const onlineFetch = doOnlineFetch ? '?onlineFetch=true' : ''; - return this.doRequest(HttpMethod.SWR_GET, `manga/${mangaId}${onlineFetch}`, { - swrOptions, - }); - } - - public getManga(mangaId: number | string, doOnlineFetch?: boolean): AbortableAxiosResponse { - const onlineFetch = doOnlineFetch ? '?onlineFetch=true' : ''; - return this.doRequest(HttpMethod.GET, `manga/${mangaId}${onlineFetch}`); - } - - public useGetFullManga( - mangaId: number | string, - { doOnlineFetch, ...swrOptions }: SWROptions & RequestOption = {}, - ): AbortableSWRResponse { - const onlineFetch = doOnlineFetch ? '?onlineFetch=true' : ''; - return this.doRequest(HttpMethod.SWR_GET, `manga/${mangaId}/full${onlineFetch}`, { - swrOptions, - }); - } - - public getMangaThumbnailUrl(mangaId: number): string { - return this.getValidImgUrlFor(`manga/${mangaId}/thumbnail`); - } - - public useGetMangaCategories( - mangaId: number, - swrOptions?: SWROptions, - ): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, `manga/${mangaId}/category`, { swrOptions }); - } - - public addMangaToCategory(mangaId: number, categoryId: number): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, `manga/${mangaId}/category/${categoryId}`); - } - - public removeMangaFromCategory(mangaId: number, categoryId: number): AbortableAxiosResponse { - return this.doRequest(HttpMethod.DELETE, `manga/${mangaId}/category/${categoryId}`); - } - - public addMangaToLibrary(mangaId: number | string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, `manga/${mangaId}/library`); - } - - public removeMangaFromLibrary(mangaId: number | string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.DELETE, `manga/${mangaId}/library`); - } - - public setMangaMeta(mangaId: number, key: string, value: any): AbortableAxiosResponse { - return this.doRequest(HttpMethod.PATCH, `manga/${mangaId}/meta`, { formData: { key, value } }); - } - - public useGetMangaChapters( - mangaId: number | string, - { doOnlineFetch, ...swrOptions }: SWROptions & RequestOption = {}, - ): AbortableSWRResponse { - const onlineFetch = doOnlineFetch ? '?onlineFetch=true' : ''; - return this.doRequest(HttpMethod.SWR_GET, `manga/${mangaId}/chapters${onlineFetch}`, { - swrOptions, - }); - } - - public getMangaChapters(mangaId: number | string, doOnlineFetch?: boolean): AbortableAxiosResponse { - const onlineFetch = doOnlineFetch ? '?onlineFetch=true' : ''; - return this.doRequest(HttpMethod.GET, `manga/${mangaId}/chapters${onlineFetch}`); - } - - public updateMangaChapters( - mangaId: number | string, - { - chapterIds, - chapterIndexes, - change, - }: ( - | { chapterIds?: number[]; chapterIndexes: number[] } - | { chapterIds: number[]; chapterIndexes?: number[] } - ) & { change: BatchChaptersChange }, - ): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, `manga/${mangaId}/chapter/batch`, { - data: { - chapterIds, - chapterIndexes, - change, - }, - }); - } - - public useGetChapter( - mangaId: number | string, - chapterIndex: number | string, - swrOptions?: SWROptions, - ): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, `manga/${mangaId}/chapter/${chapterIndex}`, { - swrOptions, - }); - } - - public getChapter(mangaId: number | string, chapterIndex: number | string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, `manga/${mangaId}/chapter/${chapterIndex}`); - } - - public deleteDownloadedChapter(mangaId: number | string, chapterIndex: number | string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.DELETE, `manga/${mangaId}/chapter/${chapterIndex}`); - } - - public updateChapter( - mangaId: number | string, - chapterIndex: number | string, - change: { read?: boolean; bookmarked?: boolean; markPrevRead?: boolean; lastPageRead?: number } = {}, - ): AbortableAxiosResponse { - return this.doRequest(HttpMethod.PATCH, `manga/${mangaId}/chapter/${chapterIndex}`, { formData: change }); - } - - public setChapterMeta( - mangaId: number | string, - chapterIndex: number | string, - key: string, - value: any, - ): AbortableAxiosResponse { - return this.doRequest(HttpMethod.PATCH, `manga/${mangaId}/chapter/${chapterIndex}/meta`, { - formData: { key, value }, - }); - } - - public getChapterPageUrl(mangaId: number | string, chapterIndex: number | string, page: number): string { - return this.getValidImgUrlFor( - `manga/${mangaId}/chapter/${chapterIndex}/page/${page}`, - RequestManager.API_VERSION, - ); - } - - public updateChapters(chapterIds: number[], change: BatchChaptersChange): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, `chapter/batch`, { data: { chapterIds, change } }); - } - - public useGetCategories(swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, `category`, { swrOptions }); - } - - public createCategory(name: string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, `category`, { formData: { name } }); - } - - public reorderCategory(currentPosition: number, newPosition: number): AbortableAxiosResponse { - return this.doRequest(HttpMethod.PATCH, `category/reorder`, { - formData: { from: currentPosition, to: newPosition }, - }); - } - - public useGetCategoryMangas(categoryId: number, swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, `category/${categoryId}`, { swrOptions }); - } - - public deleteCategory(categoryId: number): AbortableAxiosResponse { - return this.doRequest(HttpMethod.DELETE, `category/${categoryId}`); - } - - public updateCategory( - categoryId: number, - change: { name?: string; default?: boolean; includeInUpdate?: IncludeInGlobalUpdate } = {}, - ): AbortableAxiosResponse { - return this.doRequest(HttpMethod.PATCH, `category/${categoryId}`, { formData: change }); - } - - public setCategoryMeta(categoryId: number, key: string, value: any): AbortableAxiosResponse { - return this.doRequest(HttpMethod.PATCH, `category/${categoryId}/meta`, { formData: { key, value } }); - } - - public restoreBackupFile(file: File): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, 'backup/import/file', { formData: { 'backup.proto.gz': file } }); - } - - public useValidateBackupFile( - file: File, - swrOptions?: SWROptions, - ): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_POST, 'backup/validate/file', { - formData: { 'backup.proto.gz': file }, - swrOptions, - }); - } - - public getExportBackupUrl(): string { - return this.getValidUrlFor('backup/export/file'); - } - - public startDownloads(): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, 'downloads/start'); - } - - public stopDownloads(): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, 'downloads/stop'); - } - - public clearDownloads(): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, 'downloads/clear'); - } - - public addChapterToDownloadQueue(mangaId: number | string, chapterIndex: number | string): AbortableAxiosResponse { - return this.doRequest(HttpMethod.GET, `download/${mangaId}/chapter/${chapterIndex}`); - } - - public removeChapterFromDownloadQueue( - mangaId: number | string, - chapterIndex: number | string, - ): AbortableAxiosResponse { - return this.doRequest(HttpMethod.DELETE, `download/${mangaId}/chapter/${chapterIndex}`); - } - - public reorderChapterInDownloadQueue( - mangaId: number | string, - chapterIndex: number | string, - position: number, - ): AbortableAxiosResponse { - return this.doRequest(HttpMethod.PATCH, `download/${mangaId}/chapter/${chapterIndex}/reorder/${position}`); - } - - public addChaptersToDownloadQueue(chapterIds: number[]): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, 'download/batch', { data: { chapterIds } }); - } - - public removeChaptersFromDownloadQueue(chapterIds: number[]): AbortableAxiosResponse { - return this.doRequest(HttpMethod.DELETE, 'download/batch', { data: { chapterIds } }); - } - - public useGetRecentlyUpdatedChapters( - initialPages?: number, - swrOptions?: SWRInfiniteOptions>, - ): AbortableSWRInfiniteResponse> { - return this.doRequest(HttpMethod.SWR_GET_INFINITE, '', { - swrOptions: { - getEndpoint: (page, previousData) => - previousData?.hasNextPage ?? true ? `update/recentChapters/${page}` : null, - initialSize: initialPages, - ...swrOptions, - } as typeof swrOptions, - }); - } - - public startGlobalUpdate(categoryId?: number): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, 'update/fetch', { formData: { categoryId } }); - } - - public resetGlobalUpdate(): AbortableAxiosResponse { - return this.doRequest(HttpMethod.POST, 'update/reset'); - } - - public useGetGlobalUpdateSummary(swrOptions?: SWROptions): AbortableSWRResponse { - return this.doRequest(HttpMethod.SWR_GET, 'update/summary', { swrOptions }); - } -} - -const requestManager = new RequestManager(); -export default requestManager; diff --git a/src/lib/graphql/Fragments.ts b/src/lib/graphql/Fragments.ts new file mode 100644 index 00000000..e801d2da --- /dev/null +++ b/src/lib/graphql/Fragments.ts @@ -0,0 +1,439 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; + +export const PAGE_INFO = gql` + fragment PAGE_INFO on PageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } +`; + +export const GLOBAL_METADATA = gql` + fragment GLOBAL_METADATA on GlobalMetaType { + key + value + } +`; + +export const FULL_CATEGORY_FIELDS = gql` + fragment FULL_CATEGORY_FIELDS on CategoryType { + default + id + includeInUpdate + name + order + meta { + key + value + } + mangas { + totalCount + } + } +`; + +export const PARTIAL_SOURCE_FIELDS = gql` + fragment PARTIAL_SOURCE_FIELDS on SourceType { + displayName + iconUrl + id + isConfigurable + isNsfw + lang + name + supportsLatest + } +`; + +export const FULL_SOURCE_FIELDS = gql` + ${PARTIAL_SOURCE_FIELDS} + fragment FULL_SOURCE_FIELDS on SourceType { + ...PARTIAL_SOURCE_FIELDS + preferences { + ... on CheckBoxPreference { + type: __typename + CheckBoxCheckBoxCurrentValue: currentValue + summary + CheckBoxDefault: default + key + CheckBoxTitle: title + } + ... on EditTextPreference { + type: __typename + EditTextPreferenceCurrentValue: currentValue + EditTextPreferenceDefault: default + EditTextPreferenceTitle: title + text + summary + key + dialogTitle + dialogMessage + } + ... on SwitchPreference { + type: __typename + SwitchPreferenceCurrentValue: currentValue + summary + key + SwitchPreferenceDefault: default + SwitchPreferenceTitle: title + } + ... on MultiSelectListPreference { + type: __typename + dialogMessage + dialogTitle + MultiSelectListPreferenceTitle: title + summary + key + entryValues + entries + MultiSelectListPreferenceDefault: default + MultiSelectListPreferenceCurrentValue: currentValue + } + ... on ListPreference { + type: __typename + ListPreferenceCurrentValue: currentValue + ListPreferenceDefault: default + ListPreferenceTitle: title + summary + key + entryValues + entries + } + } + filters { + ... on TriStateFilter { + type: __typename + name + TriStateFilterDefault: default + } + ... on CheckBoxFilter { + type: __typename + CheckBoxFilterDefault: default + name + } + ... on TextFilter { + type: __typename + name + TextFilterDefault: default + } + ... on SortFilter { + type: __typename + values + name + SortFilterDefault: default { + ascending + index + } + } + ... on SeparatorFilter { + type: __typename + name + } + ... on SelectFilter { + type: __typename + values + name + SelectFilterDefault: default + } + ... on HeaderFilter { + type: __typename + name + } + ... on GroupFilter { + type: __typename + name + filters { + ... on CheckBoxFilter { + type: __typename + CheckBoxFilterDefault: default + name + } + ... on HeaderFilter { + type: __typename + name + } + ... on SelectFilter { + type: __typename + SelectFilterDefault: default + name + values + } + ... on TriStateFilter { + type: __typename + TriStateFilterDefault: default + name + } + ... on TextFilter { + type: __typename + TextFilterDefault: default + name + } + ... on SortFilter { + type: __typename + SorSortFilterDefault: default { + ascending + index + } + name + values + } + ... on SeparatorFilter { + type: __typename + name + } + } + } + } + } +`; + +export const BASE_MANGA_FIELDS = gql` + ${PARTIAL_SOURCE_FIELDS} + fragment BASE_MANGA_FIELDS on MangaType { + artist + author + chaptersLastFetchedAt + description + genre + id + inLibrary + inLibraryAt + initialized + lastFetchedAt + meta { + key + value + } + realUrl + source { + ...PARTIAL_SOURCE_FIELDS + } + status + thumbnailUrl + title + url + } +`; + +export const PARTIAL_MANGA_FIELDS = gql` + ${BASE_MANGA_FIELDS} + ${FULL_CATEGORY_FIELDS} + ${PARTIAL_SOURCE_FIELDS} + fragment PARTIAL_MANGA_FIELDS on MangaType { + ...BASE_MANGA_FIELDS + unreadCount + downloadCount + categories { + nodes { + ...FULL_CATEGORY_FIELDS + } + totalCount + } + chapters { + totalCount + } + } +`; + +export const FULL_CHAPTER_FIELDS = gql` + ${PARTIAL_MANGA_FIELDS} + fragment FULL_CHAPTER_FIELDS on ChapterType { + chapterNumber + fetchedAt + id + isBookmarked + isDownloaded + isRead + lastPageRead + lastReadAt + manga { + ...PARTIAL_MANGA_FIELDS + } + meta { + key + value + } + name + pageCount + realUrl + scanlator + sourceOrder + uploadDate + url + } +`; + +export const FULL_MANGA_FIELDS = gql` + ${PARTIAL_MANGA_FIELDS} + ${FULL_CHAPTER_FIELDS} + fragment FULL_MANGA_FIELDS on MangaType { + ...PARTIAL_MANGA_FIELDS + lastReadChapter { + ...FULL_CHAPTER_FIELDS + } + } +`; + +export const FULL_EXTENSION_FIELDS = gql` + fragment FULL_EXTENSION_FIELDS on ExtensionType { + apkName + hasUpdate + iconUrl + isInstalled + isNsfw + isObsolete + lang + name + pkgName + versionCode + versionName + } +`; + +export const FULL_DOWNLOAD_STATUS = gql` + ${FULL_CHAPTER_FIELDS} + fragment FULL_DOWNLOAD_STATUS on DownloadStatus { + queue { + chapter { + ...FULL_CHAPTER_FIELDS + } + progress + state + tries + } + state + } +`; + +export const PARTIAL_UPDATER_STATUS = gql` + fragment PARTIAL_UPDATER_STATUS on UpdateStatus { + isRunning + } +`; + +export const FULL_UPDATER_STATUS = gql` + ${FULL_MANGA_FIELDS} + ${PARTIAL_UPDATER_STATUS} + ${FULL_CATEGORY_FIELDS} + fragment FULL_UPDATER_STATUS on UpdateStatus { + ...PARTIAL_UPDATER_STATUS + completeJobs { + mangas { + nodes { + ...FULL_MANGA_FIELDS + } + totalCount + } + } + failedJobs { + mangas { + nodes { + ...FULL_MANGA_FIELDS + } + totalCount + } + } + pendingJobs { + mangas { + nodes { + ...FULL_MANGA_FIELDS + } + totalCount + } + } + runningJobs { + mangas { + nodes { + ...FULL_MANGA_FIELDS + } + totalCount + } + } + skippedJobs { + mangas { + nodes { + ...FULL_MANGA_FIELDS + } + totalCount + } + } + updatingCategories { + categories { + nodes { + ...FULL_CATEGORY_FIELDS + } + totalCount + } + } + skippedCategories { + categories { + nodes { + ...FULL_CATEGORY_FIELDS + } + totalCount + } + } + } +`; + +export const WEBUI_UPDATE_INFO = gql` + fragment WEBUI_UPDATE_INFO on WebUIUpdateInfo { + channel + tag + updateAvailable + } +`; + +export const WEBUI_UPDATE_STATUS = gql` + ${WEBUI_UPDATE_INFO} + fragment WEBUI_UPDATE_STATUS on WebUIUpdateStatus { + info { + ...WEBUI_UPDATE_INFO + } + progress + state + } +`; + +export const SERVER_SETTINGS = gql` + fragment SERVER_SETTINGS on SettingsType { + autoDownloadNewChapters + backupInterval + backupPath + backupTTL + backupTime + basicAuthEnabled + basicAuthPassword + basicAuthUsername + debugLogsEnabled + downloadAsCbz + downloadsPath + electronPath + excludeCompleted + excludeNotStarted + excludeUnreadChapters + globalUpdateInterval + initialOpenInBrowserEnabled + ip + localSourcePath + maxSourcesInParallel + port + socksProxyEnabled + socksProxyHost + socksProxyPort + systemTrayEnabled + webUIChannel + webUIFlavor + webUIInterface + webUIUpdateCheckInterval + } +`; diff --git a/src/lib/graphql/generated/apollo-helpers.ts b/src/lib/graphql/generated/apollo-helpers.ts new file mode 100644 index 00000000..f13ea61c --- /dev/null +++ b/src/lib/graphql/generated/apollo-helpers.ts @@ -0,0 +1,1251 @@ +import { FieldPolicy, FieldReadFunction, TypePolicies, TypePolicy } from '@apollo/client/cache'; +import { GetChaptersQuery } from "@/lib/graphql/generated/graphql.ts"; +export type AboutPayloadKeySpecifier = ('buildTime' | 'buildType' | 'discord' | 'github' | 'name' | 'revision' | 'version' | AboutPayloadKeySpecifier)[]; +export type AboutPayloadFieldPolicy = { + buildTime?: FieldPolicy | FieldReadFunction, + buildType?: FieldPolicy | FieldReadFunction, + discord?: FieldPolicy | FieldReadFunction, + github?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction, + revision?: FieldPolicy | FieldReadFunction, + version?: FieldPolicy | FieldReadFunction +}; +export type BackupRestoreStatusKeySpecifier = ('mangaProgress' | 'state' | 'totalManga' | BackupRestoreStatusKeySpecifier)[]; +export type BackupRestoreStatusFieldPolicy = { + mangaProgress?: FieldPolicy | FieldReadFunction, + state?: FieldPolicy | FieldReadFunction, + totalManga?: FieldPolicy | FieldReadFunction +}; +export type CategoryEdgeKeySpecifier = ('cursor' | 'node' | CategoryEdgeKeySpecifier)[]; +export type CategoryEdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type CategoryMetaTypeKeySpecifier = ('category' | 'categoryId' | 'key' | 'value' | CategoryMetaTypeKeySpecifier)[]; +export type CategoryMetaTypeFieldPolicy = { + category?: FieldPolicy | FieldReadFunction, + categoryId?: FieldPolicy | FieldReadFunction, + key?: FieldPolicy | FieldReadFunction, + value?: FieldPolicy | FieldReadFunction +}; +export type CategoryNodeListKeySpecifier = ('edges' | 'nodes' | 'pageInfo' | 'totalCount' | CategoryNodeListKeySpecifier)[]; +export type CategoryNodeListFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + nodes?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type CategoryTypeKeySpecifier = ('default' | 'id' | 'includeInUpdate' | 'mangas' | 'meta' | 'name' | 'order' | CategoryTypeKeySpecifier)[]; +export type CategoryTypeFieldPolicy = { + default?: FieldPolicy | FieldReadFunction, + id?: FieldPolicy | FieldReadFunction, + includeInUpdate?: FieldPolicy | FieldReadFunction, + mangas?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction, + order?: FieldPolicy | FieldReadFunction +}; +export type ChapterEdgeKeySpecifier = ('cursor' | 'node' | ChapterEdgeKeySpecifier)[]; +export type ChapterEdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type ChapterMetaTypeKeySpecifier = ('chapter' | 'chapterId' | 'key' | 'value' | ChapterMetaTypeKeySpecifier)[]; +export type ChapterMetaTypeFieldPolicy = { + chapter?: FieldPolicy | FieldReadFunction, + chapterId?: FieldPolicy | FieldReadFunction, + key?: FieldPolicy | FieldReadFunction, + value?: FieldPolicy | FieldReadFunction +}; +export type ChapterNodeListKeySpecifier = ('edges' | 'nodes' | 'pageInfo' | 'totalCount' | ChapterNodeListKeySpecifier)[]; +export type ChapterNodeListFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + nodes?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type ChapterTypeKeySpecifier = ('chapterNumber' | 'fetchedAt' | 'id' | 'isBookmarked' | 'isDownloaded' | 'isRead' | 'lastPageRead' | 'lastReadAt' | 'manga' | 'mangaId' | 'meta' | 'name' | 'pageCount' | 'realUrl' | 'scanlator' | 'sourceOrder' | 'uploadDate' | 'url' | ChapterTypeKeySpecifier)[]; +export type ChapterTypeFieldPolicy = { + chapterNumber?: FieldPolicy | FieldReadFunction, + fetchedAt?: FieldPolicy | FieldReadFunction, + id?: FieldPolicy | FieldReadFunction, + isBookmarked?: FieldPolicy | FieldReadFunction, + isDownloaded?: FieldPolicy | FieldReadFunction, + isRead?: FieldPolicy | FieldReadFunction, + lastPageRead?: FieldPolicy | FieldReadFunction, + lastReadAt?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction, + mangaId?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction, + pageCount?: FieldPolicy | FieldReadFunction, + realUrl?: FieldPolicy | FieldReadFunction, + scanlator?: FieldPolicy | FieldReadFunction, + sourceOrder?: FieldPolicy | FieldReadFunction, + uploadDate?: FieldPolicy | FieldReadFunction, + url?: FieldPolicy | FieldReadFunction +}; +export type CheckBoxFilterKeySpecifier = ('default' | 'name' | CheckBoxFilterKeySpecifier)[]; +export type CheckBoxFilterFieldPolicy = { + default?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction +}; +export type CheckBoxPreferenceKeySpecifier = ('currentValue' | 'default' | 'key' | 'summary' | 'title' | 'visible' | CheckBoxPreferenceKeySpecifier)[]; +export type CheckBoxPreferenceFieldPolicy = { + currentValue?: FieldPolicy | FieldReadFunction, + default?: FieldPolicy | FieldReadFunction, + key?: FieldPolicy | FieldReadFunction, + summary?: FieldPolicy | FieldReadFunction, + title?: FieldPolicy | FieldReadFunction, + visible?: FieldPolicy | FieldReadFunction +}; +export type CheckForServerUpdatesPayloadKeySpecifier = ('channel' | 'tag' | 'url' | CheckForServerUpdatesPayloadKeySpecifier)[]; +export type CheckForServerUpdatesPayloadFieldPolicy = { + channel?: FieldPolicy | FieldReadFunction, + tag?: FieldPolicy | FieldReadFunction, + url?: FieldPolicy | FieldReadFunction +}; +export type ClearDownloaderPayloadKeySpecifier = ('clientMutationId' | 'downloadStatus' | ClearDownloaderPayloadKeySpecifier)[]; +export type ClearDownloaderPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction +}; +export type CreateBackupPayloadKeySpecifier = ('clientMutationId' | 'url' | CreateBackupPayloadKeySpecifier)[]; +export type CreateBackupPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + url?: FieldPolicy | FieldReadFunction +}; +export type CreateCategoryPayloadKeySpecifier = ('category' | 'clientMutationId' | CreateCategoryPayloadKeySpecifier)[]; +export type CreateCategoryPayloadFieldPolicy = { + category?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type DeleteCategoryMetaPayloadKeySpecifier = ('category' | 'clientMutationId' | 'meta' | DeleteCategoryMetaPayloadKeySpecifier)[]; +export type DeleteCategoryMetaPayloadFieldPolicy = { + category?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction +}; +export type DeleteCategoryPayloadKeySpecifier = ('category' | 'clientMutationId' | 'mangas' | DeleteCategoryPayloadKeySpecifier)[]; +export type DeleteCategoryPayloadFieldPolicy = { + category?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction, + mangas?: FieldPolicy | FieldReadFunction +}; +export type DeleteChapterMetaPayloadKeySpecifier = ('chapter' | 'clientMutationId' | 'meta' | DeleteChapterMetaPayloadKeySpecifier)[]; +export type DeleteChapterMetaPayloadFieldPolicy = { + chapter?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction +}; +export type DeleteDownloadedChapterPayloadKeySpecifier = ('chapters' | 'clientMutationId' | DeleteDownloadedChapterPayloadKeySpecifier)[]; +export type DeleteDownloadedChapterPayloadFieldPolicy = { + chapters?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type DeleteDownloadedChaptersPayloadKeySpecifier = ('chapters' | 'clientMutationId' | DeleteDownloadedChaptersPayloadKeySpecifier)[]; +export type DeleteDownloadedChaptersPayloadFieldPolicy = { + chapters?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type DeleteGlobalMetaPayloadKeySpecifier = ('clientMutationId' | 'meta' | DeleteGlobalMetaPayloadKeySpecifier)[]; +export type DeleteGlobalMetaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction +}; +export type DeleteMangaMetaPayloadKeySpecifier = ('clientMutationId' | 'manga' | 'meta' | DeleteMangaMetaPayloadKeySpecifier)[]; +export type DeleteMangaMetaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction +}; +export type DequeueChapterDownloadPayloadKeySpecifier = ('clientMutationId' | 'downloadStatus' | DequeueChapterDownloadPayloadKeySpecifier)[]; +export type DequeueChapterDownloadPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction +}; +export type DequeueChapterDownloadsPayloadKeySpecifier = ('clientMutationId' | 'downloadStatus' | DequeueChapterDownloadsPayloadKeySpecifier)[]; +export type DequeueChapterDownloadsPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction +}; +export type DownloadAheadPayloadKeySpecifier = ('clientMutationId' | DownloadAheadPayloadKeySpecifier)[]; +export type DownloadAheadPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type DownloadEdgeKeySpecifier = ('cursor' | 'node' | DownloadEdgeKeySpecifier)[]; +export type DownloadEdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type DownloadNodeListKeySpecifier = ('edges' | 'nodes' | 'pageInfo' | 'totalCount' | DownloadNodeListKeySpecifier)[]; +export type DownloadNodeListFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + nodes?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type DownloadStatusKeySpecifier = ('queue' | 'state' | DownloadStatusKeySpecifier)[]; +export type DownloadStatusFieldPolicy = { + queue?: FieldPolicy | FieldReadFunction, + state?: FieldPolicy | FieldReadFunction +}; +export type DownloadTypeKeySpecifier = ('chapter' | 'manga' | 'progress' | 'state' | 'tries' | DownloadTypeKeySpecifier)[]; +export type DownloadTypeFieldPolicy = { + chapter?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction, + progress?: FieldPolicy | FieldReadFunction, + state?: FieldPolicy | FieldReadFunction, + tries?: FieldPolicy | FieldReadFunction +}; +export type EdgeKeySpecifier = ('cursor' | 'node' | EdgeKeySpecifier)[]; +export type EdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type EditTextPreferenceKeySpecifier = ('currentValue' | 'default' | 'dialogMessage' | 'dialogTitle' | 'key' | 'summary' | 'text' | 'title' | 'visible' | EditTextPreferenceKeySpecifier)[]; +export type EditTextPreferenceFieldPolicy = { + currentValue?: FieldPolicy | FieldReadFunction, + default?: FieldPolicy | FieldReadFunction, + dialogMessage?: FieldPolicy | FieldReadFunction, + dialogTitle?: FieldPolicy | FieldReadFunction, + key?: FieldPolicy | FieldReadFunction, + summary?: FieldPolicy | FieldReadFunction, + text?: FieldPolicy | FieldReadFunction, + title?: FieldPolicy | FieldReadFunction, + visible?: FieldPolicy | FieldReadFunction +}; +export type EnqueueChapterDownloadPayloadKeySpecifier = ('clientMutationId' | 'downloadStatus' | EnqueueChapterDownloadPayloadKeySpecifier)[]; +export type EnqueueChapterDownloadPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction +}; +export type EnqueueChapterDownloadsPayloadKeySpecifier = ('clientMutationId' | 'downloadStatus' | EnqueueChapterDownloadsPayloadKeySpecifier)[]; +export type EnqueueChapterDownloadsPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction +}; +export type ExtensionEdgeKeySpecifier = ('cursor' | 'node' | ExtensionEdgeKeySpecifier)[]; +export type ExtensionEdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type ExtensionNodeListKeySpecifier = ('edges' | 'nodes' | 'pageInfo' | 'totalCount' | ExtensionNodeListKeySpecifier)[]; +export type ExtensionNodeListFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + nodes?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type ExtensionTypeKeySpecifier = ('apkName' | 'hasUpdate' | 'iconUrl' | 'isInstalled' | 'isNsfw' | 'isObsolete' | 'lang' | 'name' | 'pkgName' | 'source' | 'versionCode' | 'versionName' | ExtensionTypeKeySpecifier)[]; +export type ExtensionTypeFieldPolicy = { + apkName?: FieldPolicy | FieldReadFunction, + hasUpdate?: FieldPolicy | FieldReadFunction, + iconUrl?: FieldPolicy | FieldReadFunction, + isInstalled?: FieldPolicy | FieldReadFunction, + isNsfw?: FieldPolicy | FieldReadFunction, + isObsolete?: FieldPolicy | FieldReadFunction, + lang?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction, + pkgName?: FieldPolicy | FieldReadFunction, + source?: FieldPolicy | FieldReadFunction, + versionCode?: FieldPolicy | FieldReadFunction, + versionName?: FieldPolicy | FieldReadFunction +}; +export type FetchChapterPagesPayloadKeySpecifier = ('chapter' | 'clientMutationId' | 'pages' | FetchChapterPagesPayloadKeySpecifier)[]; +export type FetchChapterPagesPayloadFieldPolicy = { + chapter?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction, + pages?: FieldPolicy | FieldReadFunction +}; +export type FetchChaptersPayloadKeySpecifier = ('chapters' | 'clientMutationId' | FetchChaptersPayloadKeySpecifier)[]; +export type FetchChaptersPayloadFieldPolicy = { + chapters?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type FetchExtensionsPayloadKeySpecifier = ('clientMutationId' | 'extensions' | FetchExtensionsPayloadKeySpecifier)[]; +export type FetchExtensionsPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + extensions?: FieldPolicy | FieldReadFunction +}; +export type FetchMangaPayloadKeySpecifier = ('clientMutationId' | 'manga' | FetchMangaPayloadKeySpecifier)[]; +export type FetchMangaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction +}; +export type FetchSourceMangaPayloadKeySpecifier = ('clientMutationId' | 'hasNextPage' | 'mangas' | FetchSourceMangaPayloadKeySpecifier)[]; +export type FetchSourceMangaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + hasNextPage?: FieldPolicy | FieldReadFunction, + mangas?: FieldPolicy | FieldReadFunction +}; +export type GlobalMetaNodeListKeySpecifier = ('edges' | 'nodes' | 'pageInfo' | 'totalCount' | GlobalMetaNodeListKeySpecifier)[]; +export type GlobalMetaNodeListFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + nodes?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type GlobalMetaTypeKeySpecifier = ('key' | 'value' | GlobalMetaTypeKeySpecifier)[]; +export type GlobalMetaTypeFieldPolicy = { + key?: FieldPolicy | FieldReadFunction, + value?: FieldPolicy | FieldReadFunction +}; +export type GroupFilterKeySpecifier = ('filters' | 'name' | GroupFilterKeySpecifier)[]; +export type GroupFilterFieldPolicy = { + filters?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction +}; +export type HeaderFilterKeySpecifier = ('name' | HeaderFilterKeySpecifier)[]; +export type HeaderFilterFieldPolicy = { + name?: FieldPolicy | FieldReadFunction +}; +export type InstallExternalExtensionPayloadKeySpecifier = ('clientMutationId' | 'extension' | InstallExternalExtensionPayloadKeySpecifier)[]; +export type InstallExternalExtensionPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + extension?: FieldPolicy | FieldReadFunction +}; +export type LastUpdateTimestampPayloadKeySpecifier = ('timestamp' | LastUpdateTimestampPayloadKeySpecifier)[]; +export type LastUpdateTimestampPayloadFieldPolicy = { + timestamp?: FieldPolicy | FieldReadFunction +}; +export type ListPreferenceKeySpecifier = ('currentValue' | 'default' | 'entries' | 'entryValues' | 'key' | 'summary' | 'title' | 'visible' | ListPreferenceKeySpecifier)[]; +export type ListPreferenceFieldPolicy = { + currentValue?: FieldPolicy | FieldReadFunction, + default?: FieldPolicy | FieldReadFunction, + entries?: FieldPolicy | FieldReadFunction, + entryValues?: FieldPolicy | FieldReadFunction, + key?: FieldPolicy | FieldReadFunction, + summary?: FieldPolicy | FieldReadFunction, + title?: FieldPolicy | FieldReadFunction, + visible?: FieldPolicy | FieldReadFunction +}; +export type MangaEdgeKeySpecifier = ('cursor' | 'node' | MangaEdgeKeySpecifier)[]; +export type MangaEdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type MangaMetaTypeKeySpecifier = ('key' | 'manga' | 'mangaId' | 'value' | MangaMetaTypeKeySpecifier)[]; +export type MangaMetaTypeFieldPolicy = { + key?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction, + mangaId?: FieldPolicy | FieldReadFunction, + value?: FieldPolicy | FieldReadFunction +}; +export type MangaNodeListKeySpecifier = ('edges' | 'nodes' | 'pageInfo' | 'totalCount' | MangaNodeListKeySpecifier)[]; +export type MangaNodeListFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + nodes?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type MangaTypeKeySpecifier = ('age' | 'artist' | 'author' | 'categories' | 'chapters' | 'chaptersAge' | 'chaptersLastFetchedAt' | 'description' | 'downloadCount' | 'genre' | 'id' | 'inLibrary' | 'inLibraryAt' | 'initialized' | 'lastFetchedAt' | 'lastReadChapter' | 'meta' | 'realUrl' | 'source' | 'sourceId' | 'status' | 'thumbnailUrl' | 'title' | 'unreadCount' | 'url' | MangaTypeKeySpecifier)[]; +export type MangaTypeFieldPolicy = { + age?: FieldPolicy | FieldReadFunction, + artist?: FieldPolicy | FieldReadFunction, + author?: FieldPolicy | FieldReadFunction, + categories?: FieldPolicy | FieldReadFunction, + chapters?: FieldPolicy | FieldReadFunction, + chaptersAge?: FieldPolicy | FieldReadFunction, + chaptersLastFetchedAt?: FieldPolicy | FieldReadFunction, + description?: FieldPolicy | FieldReadFunction, + downloadCount?: FieldPolicy | FieldReadFunction, + genre?: FieldPolicy | FieldReadFunction, + id?: FieldPolicy | FieldReadFunction, + inLibrary?: FieldPolicy | FieldReadFunction, + inLibraryAt?: FieldPolicy | FieldReadFunction, + initialized?: FieldPolicy | FieldReadFunction, + lastFetchedAt?: FieldPolicy | FieldReadFunction, + lastReadChapter?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction, + realUrl?: FieldPolicy | FieldReadFunction, + source?: FieldPolicy | FieldReadFunction, + sourceId?: FieldPolicy | FieldReadFunction, + status?: FieldPolicy | FieldReadFunction, + thumbnailUrl?: FieldPolicy | FieldReadFunction, + title?: FieldPolicy | FieldReadFunction, + unreadCount?: FieldPolicy | FieldReadFunction, + url?: FieldPolicy | FieldReadFunction +}; +export type MetaEdgeKeySpecifier = ('cursor' | 'node' | MetaEdgeKeySpecifier)[]; +export type MetaEdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type MetaTypeKeySpecifier = ('key' | 'value' | MetaTypeKeySpecifier)[]; +export type MetaTypeFieldPolicy = { + key?: FieldPolicy | FieldReadFunction, + value?: FieldPolicy | FieldReadFunction +}; +export type MultiSelectListPreferenceKeySpecifier = ('currentValue' | 'default' | 'dialogMessage' | 'dialogTitle' | 'entries' | 'entryValues' | 'key' | 'summary' | 'title' | 'visible' | MultiSelectListPreferenceKeySpecifier)[]; +export type MultiSelectListPreferenceFieldPolicy = { + currentValue?: FieldPolicy | FieldReadFunction, + default?: FieldPolicy | FieldReadFunction, + dialogMessage?: FieldPolicy | FieldReadFunction, + dialogTitle?: FieldPolicy | FieldReadFunction, + entries?: FieldPolicy | FieldReadFunction, + entryValues?: FieldPolicy | FieldReadFunction, + key?: FieldPolicy | FieldReadFunction, + summary?: FieldPolicy | FieldReadFunction, + title?: FieldPolicy | FieldReadFunction, + visible?: FieldPolicy | FieldReadFunction +}; +export type MutationKeySpecifier = ('clearDownloader' | 'createBackup' | 'createCategory' | 'deleteCategory' | 'deleteCategoryMeta' | 'deleteChapterMeta' | 'deleteDownloadedChapter' | 'deleteDownloadedChapters' | 'deleteGlobalMeta' | 'deleteMangaMeta' | 'dequeueChapterDownload' | 'dequeueChapterDownloads' | 'downloadAhead' | 'enqueueChapterDownload' | 'enqueueChapterDownloads' | 'fetchChapterPages' | 'fetchChapters' | 'fetchExtensions' | 'fetchManga' | 'fetchSourceManga' | 'installExternalExtension' | 'reorderChapterDownload' | 'resetSettings' | 'restoreBackup' | 'setCategoryMeta' | 'setChapterMeta' | 'setGlobalMeta' | 'setMangaMeta' | 'setSettings' | 'startDownloader' | 'stopDownloader' | 'updateCategories' | 'updateCategory' | 'updateCategoryManga' | 'updateCategoryOrder' | 'updateChapter' | 'updateChapters' | 'updateExtension' | 'updateExtensions' | 'updateLibraryManga' | 'updateManga' | 'updateMangaCategories' | 'updateMangas' | 'updateMangasCategories' | 'updateSourcePreference' | 'updateStop' | 'updateWebUI' | MutationKeySpecifier)[]; +export type MutationFieldPolicy = { + clearDownloader?: FieldPolicy | FieldReadFunction, + createBackup?: FieldPolicy | FieldReadFunction, + createCategory?: FieldPolicy | FieldReadFunction, + deleteCategory?: FieldPolicy | FieldReadFunction, + deleteCategoryMeta?: FieldPolicy | FieldReadFunction, + deleteChapterMeta?: FieldPolicy | FieldReadFunction, + deleteDownloadedChapter?: FieldPolicy | FieldReadFunction, + deleteDownloadedChapters?: FieldPolicy | FieldReadFunction, + deleteGlobalMeta?: FieldPolicy | FieldReadFunction, + deleteMangaMeta?: FieldPolicy | FieldReadFunction, + dequeueChapterDownload?: FieldPolicy | FieldReadFunction, + dequeueChapterDownloads?: FieldPolicy | FieldReadFunction, + downloadAhead?: FieldPolicy | FieldReadFunction, + enqueueChapterDownload?: FieldPolicy | FieldReadFunction, + enqueueChapterDownloads?: FieldPolicy | FieldReadFunction, + fetchChapterPages?: FieldPolicy | FieldReadFunction, + fetchChapters?: FieldPolicy | FieldReadFunction, + fetchExtensions?: FieldPolicy | FieldReadFunction, + fetchManga?: FieldPolicy | FieldReadFunction, + fetchSourceManga?: FieldPolicy | FieldReadFunction, + installExternalExtension?: FieldPolicy | FieldReadFunction, + reorderChapterDownload?: FieldPolicy | FieldReadFunction, + resetSettings?: FieldPolicy | FieldReadFunction, + restoreBackup?: FieldPolicy | FieldReadFunction, + setCategoryMeta?: FieldPolicy | FieldReadFunction, + setChapterMeta?: FieldPolicy | FieldReadFunction, + setGlobalMeta?: FieldPolicy | FieldReadFunction, + setMangaMeta?: FieldPolicy | FieldReadFunction, + setSettings?: FieldPolicy | FieldReadFunction, + startDownloader?: FieldPolicy | FieldReadFunction, + stopDownloader?: FieldPolicy | FieldReadFunction, + updateCategories?: FieldPolicy | FieldReadFunction, + updateCategory?: FieldPolicy | FieldReadFunction, + updateCategoryManga?: FieldPolicy | FieldReadFunction, + updateCategoryOrder?: FieldPolicy | FieldReadFunction, + updateChapter?: FieldPolicy | FieldReadFunction, + updateChapters?: FieldPolicy | FieldReadFunction, + updateExtension?: FieldPolicy | FieldReadFunction, + updateExtensions?: FieldPolicy | FieldReadFunction, + updateLibraryManga?: FieldPolicy | FieldReadFunction, + updateManga?: FieldPolicy | FieldReadFunction, + updateMangaCategories?: FieldPolicy | FieldReadFunction, + updateMangas?: FieldPolicy | FieldReadFunction, + updateMangasCategories?: FieldPolicy | FieldReadFunction, + updateSourcePreference?: FieldPolicy | FieldReadFunction, + updateStop?: FieldPolicy | FieldReadFunction, + updateWebUI?: FieldPolicy | FieldReadFunction +}; +export type NodeListKeySpecifier = ('edges' | 'nodes' | 'pageInfo' | 'totalCount' | NodeListKeySpecifier)[]; +export type NodeListFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + nodes?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type PageInfoKeySpecifier = ('endCursor' | 'hasNextPage' | 'hasPreviousPage' | 'startCursor' | PageInfoKeySpecifier)[]; +export type PageInfoFieldPolicy = { + endCursor?: FieldPolicy | FieldReadFunction, + hasNextPage?: FieldPolicy | FieldReadFunction, + hasPreviousPage?: FieldPolicy | FieldReadFunction, + startCursor?: FieldPolicy | FieldReadFunction +}; +export type PartialSettingsTypeKeySpecifier = ('autoDownloadNewChapters' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'globalUpdateInterval' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPort' | 'systemTrayEnabled' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | PartialSettingsTypeKeySpecifier)[]; +export type PartialSettingsTypeFieldPolicy = { + autoDownloadNewChapters?: FieldPolicy | FieldReadFunction, + backupInterval?: FieldPolicy | FieldReadFunction, + backupPath?: FieldPolicy | FieldReadFunction, + backupTTL?: FieldPolicy | FieldReadFunction, + backupTime?: FieldPolicy | FieldReadFunction, + basicAuthEnabled?: FieldPolicy | FieldReadFunction, + basicAuthPassword?: FieldPolicy | FieldReadFunction, + basicAuthUsername?: FieldPolicy | FieldReadFunction, + debugLogsEnabled?: FieldPolicy | FieldReadFunction, + downloadAsCbz?: FieldPolicy | FieldReadFunction, + downloadsPath?: FieldPolicy | FieldReadFunction, + electronPath?: FieldPolicy | FieldReadFunction, + excludeCompleted?: FieldPolicy | FieldReadFunction, + excludeNotStarted?: FieldPolicy | FieldReadFunction, + excludeUnreadChapters?: FieldPolicy | FieldReadFunction, + globalUpdateInterval?: FieldPolicy | FieldReadFunction, + initialOpenInBrowserEnabled?: FieldPolicy | FieldReadFunction, + ip?: FieldPolicy | FieldReadFunction, + localSourcePath?: FieldPolicy | FieldReadFunction, + maxSourcesInParallel?: FieldPolicy | FieldReadFunction, + port?: FieldPolicy | FieldReadFunction, + socksProxyEnabled?: FieldPolicy | FieldReadFunction, + socksProxyHost?: FieldPolicy | FieldReadFunction, + socksProxyPort?: FieldPolicy | FieldReadFunction, + systemTrayEnabled?: FieldPolicy | FieldReadFunction, + webUIChannel?: FieldPolicy | FieldReadFunction, + webUIFlavor?: FieldPolicy | FieldReadFunction, + webUIInterface?: FieldPolicy | FieldReadFunction, + webUIUpdateCheckInterval?: FieldPolicy | FieldReadFunction +}; +export type QueryKeySpecifier = ('about' | 'categories' | 'category' | 'chapter' | 'chapters' | 'checkForServerUpdates' | 'checkForWebUIUpdate' | 'downloadStatus' | 'extension' | 'extensions' | 'getWebUIUpdateStatus' | 'lastUpdateTimestamp' | 'manga' | 'mangas' | 'meta' | 'metas' | 'restoreStatus' | 'settings' | 'source' | 'sources' | 'updateStatus' | 'validateBackup' | QueryKeySpecifier)[]; +export type QueryFieldPolicy = { + about?: FieldPolicy | FieldReadFunction, + categories?: FieldPolicy | FieldReadFunction, + category?: FieldPolicy | FieldReadFunction, + chapter?: FieldPolicy | FieldReadFunction, + chapters?: FieldPolicy | FieldReadFunction, + checkForServerUpdates?: FieldPolicy | FieldReadFunction, + checkForWebUIUpdate?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction, + extension?: FieldPolicy | FieldReadFunction, + extensions?: FieldPolicy | FieldReadFunction, + getWebUIUpdateStatus?: FieldPolicy | FieldReadFunction, + lastUpdateTimestamp?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction, + mangas?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction, + metas?: FieldPolicy | FieldReadFunction, + restoreStatus?: FieldPolicy | FieldReadFunction, + settings?: FieldPolicy | FieldReadFunction, + source?: FieldPolicy | FieldReadFunction, + sources?: FieldPolicy | FieldReadFunction, + updateStatus?: FieldPolicy | FieldReadFunction, + validateBackup?: FieldPolicy | FieldReadFunction +}; +export type ReorderChapterDownloadPayloadKeySpecifier = ('clientMutationId' | 'downloadStatus' | ReorderChapterDownloadPayloadKeySpecifier)[]; +export type ReorderChapterDownloadPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction +}; +export type ResetSettingsPayloadKeySpecifier = ('clientMutationId' | 'settings' | ResetSettingsPayloadKeySpecifier)[]; +export type ResetSettingsPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + settings?: FieldPolicy | FieldReadFunction +}; +export type RestoreBackupPayloadKeySpecifier = ('clientMutationId' | 'status' | RestoreBackupPayloadKeySpecifier)[]; +export type RestoreBackupPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + status?: FieldPolicy | FieldReadFunction +}; +export type SelectFilterKeySpecifier = ('default' | 'name' | 'values' | SelectFilterKeySpecifier)[]; +export type SelectFilterFieldPolicy = { + default?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction, + values?: FieldPolicy | FieldReadFunction +}; +export type SeparatorFilterKeySpecifier = ('name' | SeparatorFilterKeySpecifier)[]; +export type SeparatorFilterFieldPolicy = { + name?: FieldPolicy | FieldReadFunction +}; +export type SetCategoryMetaPayloadKeySpecifier = ('clientMutationId' | 'meta' | SetCategoryMetaPayloadKeySpecifier)[]; +export type SetCategoryMetaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction +}; +export type SetChapterMetaPayloadKeySpecifier = ('clientMutationId' | 'meta' | SetChapterMetaPayloadKeySpecifier)[]; +export type SetChapterMetaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction +}; +export type SetGlobalMetaPayloadKeySpecifier = ('clientMutationId' | 'meta' | SetGlobalMetaPayloadKeySpecifier)[]; +export type SetGlobalMetaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction +}; +export type SetMangaMetaPayloadKeySpecifier = ('clientMutationId' | 'meta' | SetMangaMetaPayloadKeySpecifier)[]; +export type SetMangaMetaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + meta?: FieldPolicy | FieldReadFunction +}; +export type SetSettingsPayloadKeySpecifier = ('clientMutationId' | 'settings' | SetSettingsPayloadKeySpecifier)[]; +export type SetSettingsPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + settings?: FieldPolicy | FieldReadFunction +}; +export type SettingsKeySpecifier = ('autoDownloadNewChapters' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'globalUpdateInterval' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPort' | 'systemTrayEnabled' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | SettingsKeySpecifier)[]; +export type SettingsFieldPolicy = { + autoDownloadNewChapters?: FieldPolicy | FieldReadFunction, + backupInterval?: FieldPolicy | FieldReadFunction, + backupPath?: FieldPolicy | FieldReadFunction, + backupTTL?: FieldPolicy | FieldReadFunction, + backupTime?: FieldPolicy | FieldReadFunction, + basicAuthEnabled?: FieldPolicy | FieldReadFunction, + basicAuthPassword?: FieldPolicy | FieldReadFunction, + basicAuthUsername?: FieldPolicy | FieldReadFunction, + debugLogsEnabled?: FieldPolicy | FieldReadFunction, + downloadAsCbz?: FieldPolicy | FieldReadFunction, + downloadsPath?: FieldPolicy | FieldReadFunction, + electronPath?: FieldPolicy | FieldReadFunction, + excludeCompleted?: FieldPolicy | FieldReadFunction, + excludeNotStarted?: FieldPolicy | FieldReadFunction, + excludeUnreadChapters?: FieldPolicy | FieldReadFunction, + globalUpdateInterval?: FieldPolicy | FieldReadFunction, + initialOpenInBrowserEnabled?: FieldPolicy | FieldReadFunction, + ip?: FieldPolicy | FieldReadFunction, + localSourcePath?: FieldPolicy | FieldReadFunction, + maxSourcesInParallel?: FieldPolicy | FieldReadFunction, + port?: FieldPolicy | FieldReadFunction, + socksProxyEnabled?: FieldPolicy | FieldReadFunction, + socksProxyHost?: FieldPolicy | FieldReadFunction, + socksProxyPort?: FieldPolicy | FieldReadFunction, + systemTrayEnabled?: FieldPolicy | FieldReadFunction, + webUIChannel?: FieldPolicy | FieldReadFunction, + webUIFlavor?: FieldPolicy | FieldReadFunction, + webUIInterface?: FieldPolicy | FieldReadFunction, + webUIUpdateCheckInterval?: FieldPolicy | FieldReadFunction +}; +export type SettingsTypeKeySpecifier = ('autoDownloadNewChapters' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'globalUpdateInterval' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPort' | 'systemTrayEnabled' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | SettingsTypeKeySpecifier)[]; +export type SettingsTypeFieldPolicy = { + autoDownloadNewChapters?: FieldPolicy | FieldReadFunction, + backupInterval?: FieldPolicy | FieldReadFunction, + backupPath?: FieldPolicy | FieldReadFunction, + backupTTL?: FieldPolicy | FieldReadFunction, + backupTime?: FieldPolicy | FieldReadFunction, + basicAuthEnabled?: FieldPolicy | FieldReadFunction, + basicAuthPassword?: FieldPolicy | FieldReadFunction, + basicAuthUsername?: FieldPolicy | FieldReadFunction, + debugLogsEnabled?: FieldPolicy | FieldReadFunction, + downloadAsCbz?: FieldPolicy | FieldReadFunction, + downloadsPath?: FieldPolicy | FieldReadFunction, + electronPath?: FieldPolicy | FieldReadFunction, + excludeCompleted?: FieldPolicy | FieldReadFunction, + excludeNotStarted?: FieldPolicy | FieldReadFunction, + excludeUnreadChapters?: FieldPolicy | FieldReadFunction, + globalUpdateInterval?: FieldPolicy | FieldReadFunction, + initialOpenInBrowserEnabled?: FieldPolicy | FieldReadFunction, + ip?: FieldPolicy | FieldReadFunction, + localSourcePath?: FieldPolicy | FieldReadFunction, + maxSourcesInParallel?: FieldPolicy | FieldReadFunction, + port?: FieldPolicy | FieldReadFunction, + socksProxyEnabled?: FieldPolicy | FieldReadFunction, + socksProxyHost?: FieldPolicy | FieldReadFunction, + socksProxyPort?: FieldPolicy | FieldReadFunction, + systemTrayEnabled?: FieldPolicy | FieldReadFunction, + webUIChannel?: FieldPolicy | FieldReadFunction, + webUIFlavor?: FieldPolicy | FieldReadFunction, + webUIInterface?: FieldPolicy | FieldReadFunction, + webUIUpdateCheckInterval?: FieldPolicy | FieldReadFunction +}; +export type SortFilterKeySpecifier = ('default' | 'name' | 'values' | SortFilterKeySpecifier)[]; +export type SortFilterFieldPolicy = { + default?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction, + values?: FieldPolicy | FieldReadFunction +}; +export type SortSelectionKeySpecifier = ('ascending' | 'index' | SortSelectionKeySpecifier)[]; +export type SortSelectionFieldPolicy = { + ascending?: FieldPolicy | FieldReadFunction, + index?: FieldPolicy | FieldReadFunction +}; +export type SourceEdgeKeySpecifier = ('cursor' | 'node' | SourceEdgeKeySpecifier)[]; +export type SourceEdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type SourceNodeListKeySpecifier = ('edges' | 'nodes' | 'pageInfo' | 'totalCount' | SourceNodeListKeySpecifier)[]; +export type SourceNodeListFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + nodes?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type SourceTypeKeySpecifier = ('displayName' | 'extension' | 'filters' | 'iconUrl' | 'id' | 'isConfigurable' | 'isNsfw' | 'lang' | 'manga' | 'name' | 'preferences' | 'supportsLatest' | SourceTypeKeySpecifier)[]; +export type SourceTypeFieldPolicy = { + displayName?: FieldPolicy | FieldReadFunction, + extension?: FieldPolicy | FieldReadFunction, + filters?: FieldPolicy | FieldReadFunction, + iconUrl?: FieldPolicy | FieldReadFunction, + id?: FieldPolicy | FieldReadFunction, + isConfigurable?: FieldPolicy | FieldReadFunction, + isNsfw?: FieldPolicy | FieldReadFunction, + lang?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction, + preferences?: FieldPolicy | FieldReadFunction, + supportsLatest?: FieldPolicy | FieldReadFunction +}; +export type StartDownloaderPayloadKeySpecifier = ('clientMutationId' | 'downloadStatus' | StartDownloaderPayloadKeySpecifier)[]; +export type StartDownloaderPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction +}; +export type StopDownloaderPayloadKeySpecifier = ('clientMutationId' | 'downloadStatus' | StopDownloaderPayloadKeySpecifier)[]; +export type StopDownloaderPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + downloadStatus?: FieldPolicy | FieldReadFunction +}; +export type SubscriptionKeySpecifier = ('downloadChanged' | 'updateStatusChanged' | 'webUIUpdateStatusChange' | SubscriptionKeySpecifier)[]; +export type SubscriptionFieldPolicy = { + downloadChanged?: FieldPolicy | FieldReadFunction, + updateStatusChanged?: FieldPolicy | FieldReadFunction, + webUIUpdateStatusChange?: FieldPolicy | FieldReadFunction +}; +export type SwitchPreferenceKeySpecifier = ('currentValue' | 'default' | 'key' | 'summary' | 'title' | 'visible' | SwitchPreferenceKeySpecifier)[]; +export type SwitchPreferenceFieldPolicy = { + currentValue?: FieldPolicy | FieldReadFunction, + default?: FieldPolicy | FieldReadFunction, + key?: FieldPolicy | FieldReadFunction, + summary?: FieldPolicy | FieldReadFunction, + title?: FieldPolicy | FieldReadFunction, + visible?: FieldPolicy | FieldReadFunction +}; +export type TextFilterKeySpecifier = ('default' | 'name' | TextFilterKeySpecifier)[]; +export type TextFilterFieldPolicy = { + default?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction +}; +export type TriStateFilterKeySpecifier = ('default' | 'name' | TriStateFilterKeySpecifier)[]; +export type TriStateFilterFieldPolicy = { + default?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction +}; +export type UpdateCategoriesPayloadKeySpecifier = ('categories' | 'clientMutationId' | UpdateCategoriesPayloadKeySpecifier)[]; +export type UpdateCategoriesPayloadFieldPolicy = { + categories?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type UpdateCategoryMangaPayloadKeySpecifier = ('clientMutationId' | 'updateStatus' | UpdateCategoryMangaPayloadKeySpecifier)[]; +export type UpdateCategoryMangaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + updateStatus?: FieldPolicy | FieldReadFunction +}; +export type UpdateCategoryOrderPayloadKeySpecifier = ('categories' | 'clientMutationId' | UpdateCategoryOrderPayloadKeySpecifier)[]; +export type UpdateCategoryOrderPayloadFieldPolicy = { + categories?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type UpdateCategoryPayloadKeySpecifier = ('category' | 'clientMutationId' | UpdateCategoryPayloadKeySpecifier)[]; +export type UpdateCategoryPayloadFieldPolicy = { + category?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type UpdateChapterPayloadKeySpecifier = ('chapter' | 'clientMutationId' | UpdateChapterPayloadKeySpecifier)[]; +export type UpdateChapterPayloadFieldPolicy = { + chapter?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type UpdateChaptersPayloadKeySpecifier = ('chapters' | 'clientMutationId' | UpdateChaptersPayloadKeySpecifier)[]; +export type UpdateChaptersPayloadFieldPolicy = { + chapters?: FieldPolicy | FieldReadFunction, + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type UpdateExtensionPayloadKeySpecifier = ('clientMutationId' | 'extension' | UpdateExtensionPayloadKeySpecifier)[]; +export type UpdateExtensionPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + extension?: FieldPolicy | FieldReadFunction +}; +export type UpdateExtensionsPayloadKeySpecifier = ('clientMutationId' | 'extensions' | UpdateExtensionsPayloadKeySpecifier)[]; +export type UpdateExtensionsPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + extensions?: FieldPolicy | FieldReadFunction +}; +export type UpdateLibraryMangaPayloadKeySpecifier = ('clientMutationId' | 'updateStatus' | UpdateLibraryMangaPayloadKeySpecifier)[]; +export type UpdateLibraryMangaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + updateStatus?: FieldPolicy | FieldReadFunction +}; +export type UpdateMangaCategoriesPayloadKeySpecifier = ('clientMutationId' | 'manga' | UpdateMangaCategoriesPayloadKeySpecifier)[]; +export type UpdateMangaCategoriesPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction +}; +export type UpdateMangaPayloadKeySpecifier = ('clientMutationId' | 'manga' | UpdateMangaPayloadKeySpecifier)[]; +export type UpdateMangaPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + manga?: FieldPolicy | FieldReadFunction +}; +export type UpdateMangasCategoriesPayloadKeySpecifier = ('clientMutationId' | 'mangas' | UpdateMangasCategoriesPayloadKeySpecifier)[]; +export type UpdateMangasCategoriesPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + mangas?: FieldPolicy | FieldReadFunction +}; +export type UpdateMangasPayloadKeySpecifier = ('clientMutationId' | 'mangas' | UpdateMangasPayloadKeySpecifier)[]; +export type UpdateMangasPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + mangas?: FieldPolicy | FieldReadFunction +}; +export type UpdateSourcePreferencePayloadKeySpecifier = ('clientMutationId' | 'preferences' | 'source' | UpdateSourcePreferencePayloadKeySpecifier)[]; +export type UpdateSourcePreferencePayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + preferences?: FieldPolicy | FieldReadFunction, + source?: FieldPolicy | FieldReadFunction +}; +export type UpdateStatusKeySpecifier = ('completeJobs' | 'failedJobs' | 'isRunning' | 'pendingJobs' | 'runningJobs' | 'skippedCategories' | 'skippedJobs' | 'updatingCategories' | UpdateStatusKeySpecifier)[]; +export type UpdateStatusFieldPolicy = { + completeJobs?: FieldPolicy | FieldReadFunction, + failedJobs?: FieldPolicy | FieldReadFunction, + isRunning?: FieldPolicy | FieldReadFunction, + pendingJobs?: FieldPolicy | FieldReadFunction, + runningJobs?: FieldPolicy | FieldReadFunction, + skippedCategories?: FieldPolicy | FieldReadFunction, + skippedJobs?: FieldPolicy | FieldReadFunction, + updatingCategories?: FieldPolicy | FieldReadFunction +}; +export type UpdateStatusCategoryTypeKeySpecifier = ('categories' | UpdateStatusCategoryTypeKeySpecifier)[]; +export type UpdateStatusCategoryTypeFieldPolicy = { + categories?: FieldPolicy | FieldReadFunction +}; +export type UpdateStatusTypeKeySpecifier = ('mangas' | UpdateStatusTypeKeySpecifier)[]; +export type UpdateStatusTypeFieldPolicy = { + mangas?: FieldPolicy | FieldReadFunction +}; +export type UpdateStopPayloadKeySpecifier = ('clientMutationId' | UpdateStopPayloadKeySpecifier)[]; +export type UpdateStopPayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction +}; +export type ValidateBackupResultKeySpecifier = ('missingSources' | ValidateBackupResultKeySpecifier)[]; +export type ValidateBackupResultFieldPolicy = { + missingSources?: FieldPolicy | FieldReadFunction +}; +export type ValidateBackupSourceKeySpecifier = ('id' | 'name' | ValidateBackupSourceKeySpecifier)[]; +export type ValidateBackupSourceFieldPolicy = { + id?: FieldPolicy | FieldReadFunction, + name?: FieldPolicy | FieldReadFunction +}; +export type WebUIUpdateInfoKeySpecifier = ('channel' | 'tag' | 'updateAvailable' | WebUIUpdateInfoKeySpecifier)[]; +export type WebUIUpdateInfoFieldPolicy = { + channel?: FieldPolicy | FieldReadFunction, + tag?: FieldPolicy | FieldReadFunction, + updateAvailable?: FieldPolicy | FieldReadFunction +}; +export type WebUIUpdatePayloadKeySpecifier = ('clientMutationId' | 'updateStatus' | WebUIUpdatePayloadKeySpecifier)[]; +export type WebUIUpdatePayloadFieldPolicy = { + clientMutationId?: FieldPolicy | FieldReadFunction, + updateStatus?: FieldPolicy | FieldReadFunction +}; +export type WebUIUpdateStatusKeySpecifier = ('info' | 'progress' | 'state' | WebUIUpdateStatusKeySpecifier)[]; +export type WebUIUpdateStatusFieldPolicy = { + info?: FieldPolicy | FieldReadFunction, + progress?: FieldPolicy | FieldReadFunction, + state?: FieldPolicy | FieldReadFunction +}; +export type StrictTypedTypePolicies = { + AboutPayload?: Omit & { + keyFields?: false | AboutPayloadKeySpecifier | (() => undefined | AboutPayloadKeySpecifier), + fields?: AboutPayloadFieldPolicy, + }, + BackupRestoreStatus?: Omit & { + keyFields?: false | BackupRestoreStatusKeySpecifier | (() => undefined | BackupRestoreStatusKeySpecifier), + fields?: BackupRestoreStatusFieldPolicy, + }, + CategoryEdge?: Omit & { + keyFields?: false | CategoryEdgeKeySpecifier | (() => undefined | CategoryEdgeKeySpecifier), + fields?: CategoryEdgeFieldPolicy, + }, + CategoryMetaType?: Omit & { + keyFields?: false | CategoryMetaTypeKeySpecifier | (() => undefined | CategoryMetaTypeKeySpecifier), + fields?: CategoryMetaTypeFieldPolicy, + }, + CategoryNodeList?: Omit & { + keyFields?: false | CategoryNodeListKeySpecifier | (() => undefined | CategoryNodeListKeySpecifier), + fields?: CategoryNodeListFieldPolicy, + }, + CategoryType?: Omit & { + keyFields?: false | CategoryTypeKeySpecifier | (() => undefined | CategoryTypeKeySpecifier), + fields?: CategoryTypeFieldPolicy, + }, + ChapterEdge?: Omit & { + keyFields?: false | ChapterEdgeKeySpecifier | (() => undefined | ChapterEdgeKeySpecifier), + fields?: ChapterEdgeFieldPolicy, + }, + ChapterMetaType?: Omit & { + keyFields?: false | ChapterMetaTypeKeySpecifier | (() => undefined | ChapterMetaTypeKeySpecifier), + fields?: ChapterMetaTypeFieldPolicy, + }, + ChapterNodeList?: Omit & { + keyFields?: false | ChapterNodeListKeySpecifier | (() => undefined | ChapterNodeListKeySpecifier), + fields?: ChapterNodeListFieldPolicy, + }, + ChapterType?: Omit & { + keyFields?: false | ChapterTypeKeySpecifier | (() => undefined | ChapterTypeKeySpecifier), + fields?: ChapterTypeFieldPolicy, + }, + CheckBoxFilter?: Omit & { + keyFields?: false | CheckBoxFilterKeySpecifier | (() => undefined | CheckBoxFilterKeySpecifier), + fields?: CheckBoxFilterFieldPolicy, + }, + CheckBoxPreference?: Omit & { + keyFields?: false | CheckBoxPreferenceKeySpecifier | (() => undefined | CheckBoxPreferenceKeySpecifier), + fields?: CheckBoxPreferenceFieldPolicy, + }, + CheckForServerUpdatesPayload?: Omit & { + keyFields?: false | CheckForServerUpdatesPayloadKeySpecifier | (() => undefined | CheckForServerUpdatesPayloadKeySpecifier), + fields?: CheckForServerUpdatesPayloadFieldPolicy, + }, + ClearDownloaderPayload?: Omit & { + keyFields?: false | ClearDownloaderPayloadKeySpecifier | (() => undefined | ClearDownloaderPayloadKeySpecifier), + fields?: ClearDownloaderPayloadFieldPolicy, + }, + CreateBackupPayload?: Omit & { + keyFields?: false | CreateBackupPayloadKeySpecifier | (() => undefined | CreateBackupPayloadKeySpecifier), + fields?: CreateBackupPayloadFieldPolicy, + }, + CreateCategoryPayload?: Omit & { + keyFields?: false | CreateCategoryPayloadKeySpecifier | (() => undefined | CreateCategoryPayloadKeySpecifier), + fields?: CreateCategoryPayloadFieldPolicy, + }, + DeleteCategoryMetaPayload?: Omit & { + keyFields?: false | DeleteCategoryMetaPayloadKeySpecifier | (() => undefined | DeleteCategoryMetaPayloadKeySpecifier), + fields?: DeleteCategoryMetaPayloadFieldPolicy, + }, + DeleteCategoryPayload?: Omit & { + keyFields?: false | DeleteCategoryPayloadKeySpecifier | (() => undefined | DeleteCategoryPayloadKeySpecifier), + fields?: DeleteCategoryPayloadFieldPolicy, + }, + DeleteChapterMetaPayload?: Omit & { + keyFields?: false | DeleteChapterMetaPayloadKeySpecifier | (() => undefined | DeleteChapterMetaPayloadKeySpecifier), + fields?: DeleteChapterMetaPayloadFieldPolicy, + }, + DeleteDownloadedChapterPayload?: Omit & { + keyFields?: false | DeleteDownloadedChapterPayloadKeySpecifier | (() => undefined | DeleteDownloadedChapterPayloadKeySpecifier), + fields?: DeleteDownloadedChapterPayloadFieldPolicy, + }, + DeleteDownloadedChaptersPayload?: Omit & { + keyFields?: false | DeleteDownloadedChaptersPayloadKeySpecifier | (() => undefined | DeleteDownloadedChaptersPayloadKeySpecifier), + fields?: DeleteDownloadedChaptersPayloadFieldPolicy, + }, + DeleteGlobalMetaPayload?: Omit & { + keyFields?: false | DeleteGlobalMetaPayloadKeySpecifier | (() => undefined | DeleteGlobalMetaPayloadKeySpecifier), + fields?: DeleteGlobalMetaPayloadFieldPolicy, + }, + DeleteMangaMetaPayload?: Omit & { + keyFields?: false | DeleteMangaMetaPayloadKeySpecifier | (() => undefined | DeleteMangaMetaPayloadKeySpecifier), + fields?: DeleteMangaMetaPayloadFieldPolicy, + }, + DequeueChapterDownloadPayload?: Omit & { + keyFields?: false | DequeueChapterDownloadPayloadKeySpecifier | (() => undefined | DequeueChapterDownloadPayloadKeySpecifier), + fields?: DequeueChapterDownloadPayloadFieldPolicy, + }, + DequeueChapterDownloadsPayload?: Omit & { + keyFields?: false | DequeueChapterDownloadsPayloadKeySpecifier | (() => undefined | DequeueChapterDownloadsPayloadKeySpecifier), + fields?: DequeueChapterDownloadsPayloadFieldPolicy, + }, + DownloadAheadPayload?: Omit & { + keyFields?: false | DownloadAheadPayloadKeySpecifier | (() => undefined | DownloadAheadPayloadKeySpecifier), + fields?: DownloadAheadPayloadFieldPolicy, + }, + DownloadEdge?: Omit & { + keyFields?: false | DownloadEdgeKeySpecifier | (() => undefined | DownloadEdgeKeySpecifier), + fields?: DownloadEdgeFieldPolicy, + }, + DownloadNodeList?: Omit & { + keyFields?: false | DownloadNodeListKeySpecifier | (() => undefined | DownloadNodeListKeySpecifier), + fields?: DownloadNodeListFieldPolicy, + }, + DownloadStatus?: Omit & { + keyFields?: false | DownloadStatusKeySpecifier | (() => undefined | DownloadStatusKeySpecifier), + fields?: DownloadStatusFieldPolicy, + }, + DownloadType?: Omit & { + keyFields?: false | DownloadTypeKeySpecifier | (() => undefined | DownloadTypeKeySpecifier), + fields?: DownloadTypeFieldPolicy, + }, + Edge?: Omit & { + keyFields?: false | EdgeKeySpecifier | (() => undefined | EdgeKeySpecifier), + fields?: EdgeFieldPolicy, + }, + EditTextPreference?: Omit & { + keyFields?: false | EditTextPreferenceKeySpecifier | (() => undefined | EditTextPreferenceKeySpecifier), + fields?: EditTextPreferenceFieldPolicy, + }, + EnqueueChapterDownloadPayload?: Omit & { + keyFields?: false | EnqueueChapterDownloadPayloadKeySpecifier | (() => undefined | EnqueueChapterDownloadPayloadKeySpecifier), + fields?: EnqueueChapterDownloadPayloadFieldPolicy, + }, + EnqueueChapterDownloadsPayload?: Omit & { + keyFields?: false | EnqueueChapterDownloadsPayloadKeySpecifier | (() => undefined | EnqueueChapterDownloadsPayloadKeySpecifier), + fields?: EnqueueChapterDownloadsPayloadFieldPolicy, + }, + ExtensionEdge?: Omit & { + keyFields?: false | ExtensionEdgeKeySpecifier | (() => undefined | ExtensionEdgeKeySpecifier), + fields?: ExtensionEdgeFieldPolicy, + }, + ExtensionNodeList?: Omit & { + keyFields?: false | ExtensionNodeListKeySpecifier | (() => undefined | ExtensionNodeListKeySpecifier), + fields?: ExtensionNodeListFieldPolicy, + }, + ExtensionType?: Omit & { + keyFields?: false | ExtensionTypeKeySpecifier | (() => undefined | ExtensionTypeKeySpecifier), + fields?: ExtensionTypeFieldPolicy, + }, + FetchChapterPagesPayload?: Omit & { + keyFields?: false | FetchChapterPagesPayloadKeySpecifier | (() => undefined | FetchChapterPagesPayloadKeySpecifier), + fields?: FetchChapterPagesPayloadFieldPolicy, + }, + FetchChaptersPayload?: Omit & { + keyFields?: false | FetchChaptersPayloadKeySpecifier | (() => undefined | FetchChaptersPayloadKeySpecifier), + fields?: FetchChaptersPayloadFieldPolicy, + }, + FetchExtensionsPayload?: Omit & { + keyFields?: false | FetchExtensionsPayloadKeySpecifier | (() => undefined | FetchExtensionsPayloadKeySpecifier), + fields?: FetchExtensionsPayloadFieldPolicy, + }, + FetchMangaPayload?: Omit & { + keyFields?: false | FetchMangaPayloadKeySpecifier | (() => undefined | FetchMangaPayloadKeySpecifier), + fields?: FetchMangaPayloadFieldPolicy, + }, + FetchSourceMangaPayload?: Omit & { + keyFields?: false | FetchSourceMangaPayloadKeySpecifier | (() => undefined | FetchSourceMangaPayloadKeySpecifier), + fields?: FetchSourceMangaPayloadFieldPolicy, + }, + GlobalMetaNodeList?: Omit & { + keyFields?: false | GlobalMetaNodeListKeySpecifier | (() => undefined | GlobalMetaNodeListKeySpecifier), + fields?: GlobalMetaNodeListFieldPolicy, + }, + GlobalMetaType?: Omit & { + keyFields?: false | GlobalMetaTypeKeySpecifier | (() => undefined | GlobalMetaTypeKeySpecifier), + fields?: GlobalMetaTypeFieldPolicy, + }, + GroupFilter?: Omit & { + keyFields?: false | GroupFilterKeySpecifier | (() => undefined | GroupFilterKeySpecifier), + fields?: GroupFilterFieldPolicy, + }, + HeaderFilter?: Omit & { + keyFields?: false | HeaderFilterKeySpecifier | (() => undefined | HeaderFilterKeySpecifier), + fields?: HeaderFilterFieldPolicy, + }, + InstallExternalExtensionPayload?: Omit & { + keyFields?: false | InstallExternalExtensionPayloadKeySpecifier | (() => undefined | InstallExternalExtensionPayloadKeySpecifier), + fields?: InstallExternalExtensionPayloadFieldPolicy, + }, + LastUpdateTimestampPayload?: Omit & { + keyFields?: false | LastUpdateTimestampPayloadKeySpecifier | (() => undefined | LastUpdateTimestampPayloadKeySpecifier), + fields?: LastUpdateTimestampPayloadFieldPolicy, + }, + ListPreference?: Omit & { + keyFields?: false | ListPreferenceKeySpecifier | (() => undefined | ListPreferenceKeySpecifier), + fields?: ListPreferenceFieldPolicy, + }, + MangaEdge?: Omit & { + keyFields?: false | MangaEdgeKeySpecifier | (() => undefined | MangaEdgeKeySpecifier), + fields?: MangaEdgeFieldPolicy, + }, + MangaMetaType?: Omit & { + keyFields?: false | MangaMetaTypeKeySpecifier | (() => undefined | MangaMetaTypeKeySpecifier), + fields?: MangaMetaTypeFieldPolicy, + }, + MangaNodeList?: Omit & { + keyFields?: false | MangaNodeListKeySpecifier | (() => undefined | MangaNodeListKeySpecifier), + fields?: MangaNodeListFieldPolicy, + }, + MangaType?: Omit & { + keyFields?: false | MangaTypeKeySpecifier | (() => undefined | MangaTypeKeySpecifier), + fields?: MangaTypeFieldPolicy, + }, + MetaEdge?: Omit & { + keyFields?: false | MetaEdgeKeySpecifier | (() => undefined | MetaEdgeKeySpecifier), + fields?: MetaEdgeFieldPolicy, + }, + MetaType?: Omit & { + keyFields?: false | MetaTypeKeySpecifier | (() => undefined | MetaTypeKeySpecifier), + fields?: MetaTypeFieldPolicy, + }, + MultiSelectListPreference?: Omit & { + keyFields?: false | MultiSelectListPreferenceKeySpecifier | (() => undefined | MultiSelectListPreferenceKeySpecifier), + fields?: MultiSelectListPreferenceFieldPolicy, + }, + Mutation?: Omit & { + keyFields?: false | MutationKeySpecifier | (() => undefined | MutationKeySpecifier), + fields?: MutationFieldPolicy, + }, + NodeList?: Omit & { + keyFields?: false | NodeListKeySpecifier | (() => undefined | NodeListKeySpecifier), + fields?: NodeListFieldPolicy, + }, + PageInfo?: Omit & { + keyFields?: false | PageInfoKeySpecifier | (() => undefined | PageInfoKeySpecifier), + fields?: PageInfoFieldPolicy, + }, + PartialSettingsType?: Omit & { + keyFields?: false | PartialSettingsTypeKeySpecifier | (() => undefined | PartialSettingsTypeKeySpecifier), + fields?: PartialSettingsTypeFieldPolicy, + }, + Query?: Omit & { + keyFields?: false | QueryKeySpecifier | (() => undefined | QueryKeySpecifier), + fields?: QueryFieldPolicy, + }, + ReorderChapterDownloadPayload?: Omit & { + keyFields?: false | ReorderChapterDownloadPayloadKeySpecifier | (() => undefined | ReorderChapterDownloadPayloadKeySpecifier), + fields?: ReorderChapterDownloadPayloadFieldPolicy, + }, + ResetSettingsPayload?: Omit & { + keyFields?: false | ResetSettingsPayloadKeySpecifier | (() => undefined | ResetSettingsPayloadKeySpecifier), + fields?: ResetSettingsPayloadFieldPolicy, + }, + RestoreBackupPayload?: Omit & { + keyFields?: false | RestoreBackupPayloadKeySpecifier | (() => undefined | RestoreBackupPayloadKeySpecifier), + fields?: RestoreBackupPayloadFieldPolicy, + }, + SelectFilter?: Omit & { + keyFields?: false | SelectFilterKeySpecifier | (() => undefined | SelectFilterKeySpecifier), + fields?: SelectFilterFieldPolicy, + }, + SeparatorFilter?: Omit & { + keyFields?: false | SeparatorFilterKeySpecifier | (() => undefined | SeparatorFilterKeySpecifier), + fields?: SeparatorFilterFieldPolicy, + }, + SetCategoryMetaPayload?: Omit & { + keyFields?: false | SetCategoryMetaPayloadKeySpecifier | (() => undefined | SetCategoryMetaPayloadKeySpecifier), + fields?: SetCategoryMetaPayloadFieldPolicy, + }, + SetChapterMetaPayload?: Omit & { + keyFields?: false | SetChapterMetaPayloadKeySpecifier | (() => undefined | SetChapterMetaPayloadKeySpecifier), + fields?: SetChapterMetaPayloadFieldPolicy, + }, + SetGlobalMetaPayload?: Omit & { + keyFields?: false | SetGlobalMetaPayloadKeySpecifier | (() => undefined | SetGlobalMetaPayloadKeySpecifier), + fields?: SetGlobalMetaPayloadFieldPolicy, + }, + SetMangaMetaPayload?: Omit & { + keyFields?: false | SetMangaMetaPayloadKeySpecifier | (() => undefined | SetMangaMetaPayloadKeySpecifier), + fields?: SetMangaMetaPayloadFieldPolicy, + }, + SetSettingsPayload?: Omit & { + keyFields?: false | SetSettingsPayloadKeySpecifier | (() => undefined | SetSettingsPayloadKeySpecifier), + fields?: SetSettingsPayloadFieldPolicy, + }, + Settings?: Omit & { + keyFields?: false | SettingsKeySpecifier | (() => undefined | SettingsKeySpecifier), + fields?: SettingsFieldPolicy, + }, + SettingsType?: Omit & { + keyFields?: false | SettingsTypeKeySpecifier | (() => undefined | SettingsTypeKeySpecifier), + fields?: SettingsTypeFieldPolicy, + }, + SortFilter?: Omit & { + keyFields?: false | SortFilterKeySpecifier | (() => undefined | SortFilterKeySpecifier), + fields?: SortFilterFieldPolicy, + }, + SortSelection?: Omit & { + keyFields?: false | SortSelectionKeySpecifier | (() => undefined | SortSelectionKeySpecifier), + fields?: SortSelectionFieldPolicy, + }, + SourceEdge?: Omit & { + keyFields?: false | SourceEdgeKeySpecifier | (() => undefined | SourceEdgeKeySpecifier), + fields?: SourceEdgeFieldPolicy, + }, + SourceNodeList?: Omit & { + keyFields?: false | SourceNodeListKeySpecifier | (() => undefined | SourceNodeListKeySpecifier), + fields?: SourceNodeListFieldPolicy, + }, + SourceType?: Omit & { + keyFields?: false | SourceTypeKeySpecifier | (() => undefined | SourceTypeKeySpecifier), + fields?: SourceTypeFieldPolicy, + }, + StartDownloaderPayload?: Omit & { + keyFields?: false | StartDownloaderPayloadKeySpecifier | (() => undefined | StartDownloaderPayloadKeySpecifier), + fields?: StartDownloaderPayloadFieldPolicy, + }, + StopDownloaderPayload?: Omit & { + keyFields?: false | StopDownloaderPayloadKeySpecifier | (() => undefined | StopDownloaderPayloadKeySpecifier), + fields?: StopDownloaderPayloadFieldPolicy, + }, + Subscription?: Omit & { + keyFields?: false | SubscriptionKeySpecifier | (() => undefined | SubscriptionKeySpecifier), + fields?: SubscriptionFieldPolicy, + }, + SwitchPreference?: Omit & { + keyFields?: false | SwitchPreferenceKeySpecifier | (() => undefined | SwitchPreferenceKeySpecifier), + fields?: SwitchPreferenceFieldPolicy, + }, + TextFilter?: Omit & { + keyFields?: false | TextFilterKeySpecifier | (() => undefined | TextFilterKeySpecifier), + fields?: TextFilterFieldPolicy, + }, + TriStateFilter?: Omit & { + keyFields?: false | TriStateFilterKeySpecifier | (() => undefined | TriStateFilterKeySpecifier), + fields?: TriStateFilterFieldPolicy, + }, + UpdateCategoriesPayload?: Omit & { + keyFields?: false | UpdateCategoriesPayloadKeySpecifier | (() => undefined | UpdateCategoriesPayloadKeySpecifier), + fields?: UpdateCategoriesPayloadFieldPolicy, + }, + UpdateCategoryMangaPayload?: Omit & { + keyFields?: false | UpdateCategoryMangaPayloadKeySpecifier | (() => undefined | UpdateCategoryMangaPayloadKeySpecifier), + fields?: UpdateCategoryMangaPayloadFieldPolicy, + }, + UpdateCategoryOrderPayload?: Omit & { + keyFields?: false | UpdateCategoryOrderPayloadKeySpecifier | (() => undefined | UpdateCategoryOrderPayloadKeySpecifier), + fields?: UpdateCategoryOrderPayloadFieldPolicy, + }, + UpdateCategoryPayload?: Omit & { + keyFields?: false | UpdateCategoryPayloadKeySpecifier | (() => undefined | UpdateCategoryPayloadKeySpecifier), + fields?: UpdateCategoryPayloadFieldPolicy, + }, + UpdateChapterPayload?: Omit & { + keyFields?: false | UpdateChapterPayloadKeySpecifier | (() => undefined | UpdateChapterPayloadKeySpecifier), + fields?: UpdateChapterPayloadFieldPolicy, + }, + UpdateChaptersPayload?: Omit & { + keyFields?: false | UpdateChaptersPayloadKeySpecifier | (() => undefined | UpdateChaptersPayloadKeySpecifier), + fields?: UpdateChaptersPayloadFieldPolicy, + }, + UpdateExtensionPayload?: Omit & { + keyFields?: false | UpdateExtensionPayloadKeySpecifier | (() => undefined | UpdateExtensionPayloadKeySpecifier), + fields?: UpdateExtensionPayloadFieldPolicy, + }, + UpdateExtensionsPayload?: Omit & { + keyFields?: false | UpdateExtensionsPayloadKeySpecifier | (() => undefined | UpdateExtensionsPayloadKeySpecifier), + fields?: UpdateExtensionsPayloadFieldPolicy, + }, + UpdateLibraryMangaPayload?: Omit & { + keyFields?: false | UpdateLibraryMangaPayloadKeySpecifier | (() => undefined | UpdateLibraryMangaPayloadKeySpecifier), + fields?: UpdateLibraryMangaPayloadFieldPolicy, + }, + UpdateMangaCategoriesPayload?: Omit & { + keyFields?: false | UpdateMangaCategoriesPayloadKeySpecifier | (() => undefined | UpdateMangaCategoriesPayloadKeySpecifier), + fields?: UpdateMangaCategoriesPayloadFieldPolicy, + }, + UpdateMangaPayload?: Omit & { + keyFields?: false | UpdateMangaPayloadKeySpecifier | (() => undefined | UpdateMangaPayloadKeySpecifier), + fields?: UpdateMangaPayloadFieldPolicy, + }, + UpdateMangasCategoriesPayload?: Omit & { + keyFields?: false | UpdateMangasCategoriesPayloadKeySpecifier | (() => undefined | UpdateMangasCategoriesPayloadKeySpecifier), + fields?: UpdateMangasCategoriesPayloadFieldPolicy, + }, + UpdateMangasPayload?: Omit & { + keyFields?: false | UpdateMangasPayloadKeySpecifier | (() => undefined | UpdateMangasPayloadKeySpecifier), + fields?: UpdateMangasPayloadFieldPolicy, + }, + UpdateSourcePreferencePayload?: Omit & { + keyFields?: false | UpdateSourcePreferencePayloadKeySpecifier | (() => undefined | UpdateSourcePreferencePayloadKeySpecifier), + fields?: UpdateSourcePreferencePayloadFieldPolicy, + }, + UpdateStatus?: Omit & { + keyFields?: false | UpdateStatusKeySpecifier | (() => undefined | UpdateStatusKeySpecifier), + fields?: UpdateStatusFieldPolicy, + }, + UpdateStatusCategoryType?: Omit & { + keyFields?: false | UpdateStatusCategoryTypeKeySpecifier | (() => undefined | UpdateStatusCategoryTypeKeySpecifier), + fields?: UpdateStatusCategoryTypeFieldPolicy, + }, + UpdateStatusType?: Omit & { + keyFields?: false | UpdateStatusTypeKeySpecifier | (() => undefined | UpdateStatusTypeKeySpecifier), + fields?: UpdateStatusTypeFieldPolicy, + }, + UpdateStopPayload?: Omit & { + keyFields?: false | UpdateStopPayloadKeySpecifier | (() => undefined | UpdateStopPayloadKeySpecifier), + fields?: UpdateStopPayloadFieldPolicy, + }, + ValidateBackupResult?: Omit & { + keyFields?: false | ValidateBackupResultKeySpecifier | (() => undefined | ValidateBackupResultKeySpecifier), + fields?: ValidateBackupResultFieldPolicy, + }, + ValidateBackupSource?: Omit & { + keyFields?: false | ValidateBackupSourceKeySpecifier | (() => undefined | ValidateBackupSourceKeySpecifier), + fields?: ValidateBackupSourceFieldPolicy, + }, + WebUIUpdateInfo?: Omit & { + keyFields?: false | WebUIUpdateInfoKeySpecifier | (() => undefined | WebUIUpdateInfoKeySpecifier), + fields?: WebUIUpdateInfoFieldPolicy, + }, + WebUIUpdatePayload?: Omit & { + keyFields?: false | WebUIUpdatePayloadKeySpecifier | (() => undefined | WebUIUpdatePayloadKeySpecifier), + fields?: WebUIUpdatePayloadFieldPolicy, + }, + WebUIUpdateStatus?: Omit & { + keyFields?: false | WebUIUpdateStatusKeySpecifier | (() => undefined | WebUIUpdateStatusKeySpecifier), + fields?: WebUIUpdateStatusFieldPolicy, + } +}; +export type TypedTypePolicies = StrictTypedTypePolicies & TypePolicies; \ No newline at end of file diff --git a/src/lib/graphql/generated/graphql.ts b/src/lib/graphql/generated/graphql.ts new file mode 100644 index 00000000..c528500b --- /dev/null +++ b/src/lib/graphql/generated/graphql.ts @@ -0,0 +1,2605 @@ +export type Maybe = T | null; +export type InputMaybe = Maybe; +export type Exact = { [K in keyof T]: T[K] }; +export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; +export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; +export type MakeEmpty = { [_ in K]?: never }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: { input: string; output: string; } + String: { input: string; output: string; } + Boolean: { input: boolean; output: boolean; } + Int: { input: number; output: number; } + Float: { input: number; output: number; } + Cursor: { input: string; output: string; } + LongString: { input: string; output: string; } + Upload: { input: any; output: any; } +}; + +export type AboutPayload = { + __typename?: 'AboutPayload'; + buildTime: Scalars['LongString']['output']; + buildType: Scalars['String']['output']; + discord: Scalars['String']['output']; + github: Scalars['String']['output']; + name: Scalars['String']['output']; + revision: Scalars['String']['output']; + version: Scalars['String']['output']; +}; + +export enum BackupRestoreState { + Idle = 'IDLE', + RestoringCategories = 'RESTORING_CATEGORIES', + RestoringManga = 'RESTORING_MANGA' +} + +export type BackupRestoreStatus = { + __typename?: 'BackupRestoreStatus'; + mangaProgress: Scalars['Int']['output']; + state: BackupRestoreState; + totalManga: Scalars['Int']['output']; +}; + +export type BooleanFilterInput = { + distinctFrom?: InputMaybe; + equalTo?: InputMaybe; + greaterThan?: InputMaybe; + greaterThanOrEqualTo?: InputMaybe; + in?: InputMaybe>; + isNull?: InputMaybe; + lessThan?: InputMaybe; + lessThanOrEqualTo?: InputMaybe; + notDistinctFrom?: InputMaybe; + notEqualTo?: InputMaybe; + notIn?: InputMaybe>; +}; + +export type CategoryConditionInput = { + default?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + order?: InputMaybe; +}; + +export type CategoryEdge = Edge & { + __typename?: 'CategoryEdge'; + cursor: Scalars['Cursor']['output']; + node: CategoryType; +}; + +export type CategoryFilterInput = { + and?: InputMaybe>; + default?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>; + order?: InputMaybe; +}; + +export type CategoryMetaType = MetaType & { + __typename?: 'CategoryMetaType'; + category: CategoryType; + categoryId: Scalars['Int']['output']; + key: Scalars['String']['output']; + value: Scalars['String']['output']; +}; + +export type CategoryMetaTypeInput = { + categoryId: Scalars['Int']['input']; + key: Scalars['String']['input']; + value: Scalars['String']['input']; +}; + +export type CategoryNodeList = NodeList & { + __typename?: 'CategoryNodeList'; + edges: Array; + nodes: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + +export enum CategoryOrderBy { + Id = 'ID', + Name = 'NAME', + Order = 'ORDER' +} + +export type CategoryType = { + __typename?: 'CategoryType'; + default: Scalars['Boolean']['output']; + id: Scalars['Int']['output']; + includeInUpdate: IncludeInUpdate; + mangas: MangaNodeList; + meta: Array; + name: Scalars['String']['output']; + order: Scalars['Int']['output']; +}; + +export type ChapterConditionInput = { + chapterNumber?: InputMaybe; + fetchedAt?: InputMaybe; + id?: InputMaybe; + isBookmarked?: InputMaybe; + isDownloaded?: InputMaybe; + isRead?: InputMaybe; + lastPageRead?: InputMaybe; + lastReadAt?: InputMaybe; + mangaId?: InputMaybe; + name?: InputMaybe; + pageCount?: InputMaybe; + realUrl?: InputMaybe; + scanlator?: InputMaybe; + sourceOrder?: InputMaybe; + uploadDate?: InputMaybe; + url?: InputMaybe; +}; + +export type ChapterEdge = Edge & { + __typename?: 'ChapterEdge'; + cursor: Scalars['Cursor']['output']; + node: ChapterType; +}; + +export type ChapterFilterInput = { + and?: InputMaybe>; + chapterNumber?: InputMaybe; + fetchedAt?: InputMaybe; + id?: InputMaybe; + inLibrary?: InputMaybe; + isBookmarked?: InputMaybe; + isDownloaded?: InputMaybe; + isRead?: InputMaybe; + lastPageRead?: InputMaybe; + lastReadAt?: InputMaybe; + mangaId?: InputMaybe; + name?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>; + pageCount?: InputMaybe; + realUrl?: InputMaybe; + scanlator?: InputMaybe; + sourceOrder?: InputMaybe; + uploadDate?: InputMaybe; + url?: InputMaybe; +}; + +export type ChapterMetaType = MetaType & { + __typename?: 'ChapterMetaType'; + chapter: ChapterType; + chapterId: Scalars['Int']['output']; + key: Scalars['String']['output']; + value: Scalars['String']['output']; +}; + +export type ChapterMetaTypeInput = { + chapterId: Scalars['Int']['input']; + key: Scalars['String']['input']; + value: Scalars['String']['input']; +}; + +export type ChapterNodeList = NodeList & { + __typename?: 'ChapterNodeList'; + edges: Array; + nodes: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + +export enum ChapterOrderBy { + ChapterNumber = 'CHAPTER_NUMBER', + FetchedAt = 'FETCHED_AT', + Id = 'ID', + LastReadAt = 'LAST_READ_AT', + Name = 'NAME', + SourceOrder = 'SOURCE_ORDER', + UploadDate = 'UPLOAD_DATE' +} + +export type ChapterType = { + __typename?: 'ChapterType'; + chapterNumber: Scalars['Float']['output']; + fetchedAt: Scalars['LongString']['output']; + id: Scalars['Int']['output']; + isBookmarked: Scalars['Boolean']['output']; + isDownloaded: Scalars['Boolean']['output']; + isRead: Scalars['Boolean']['output']; + lastPageRead: Scalars['Int']['output']; + lastReadAt: Scalars['LongString']['output']; + manga: MangaType; + mangaId: Scalars['Int']['output']; + meta: Array; + name: Scalars['String']['output']; + pageCount: Scalars['Int']['output']; + realUrl?: Maybe; + scanlator?: Maybe; + sourceOrder: Scalars['Int']['output']; + uploadDate: Scalars['LongString']['output']; + url: Scalars['String']['output']; +}; + +export type CheckBoxFilter = { + __typename?: 'CheckBoxFilter'; + default: Scalars['Boolean']['output']; + name: Scalars['String']['output']; +}; + +export type CheckBoxPreference = { + __typename?: 'CheckBoxPreference'; + currentValue?: Maybe; + default: Scalars['Boolean']['output']; + key: Scalars['String']['output']; + summary?: Maybe; + title: Scalars['String']['output']; + visible: Scalars['Boolean']['output']; +}; + +export type CheckForServerUpdatesPayload = { + __typename?: 'CheckForServerUpdatesPayload'; + channel: Scalars['String']['output']; + tag: Scalars['String']['output']; + url: Scalars['String']['output']; +}; + +export type ClearDownloaderInput = { + clientMutationId?: InputMaybe; +}; + +export type ClearDownloaderPayload = { + __typename?: 'ClearDownloaderPayload'; + clientMutationId?: Maybe; + downloadStatus: DownloadStatus; +}; + +export type CreateBackupInput = { + clientMutationId?: InputMaybe; + includeCategories?: InputMaybe; + includeChapters?: InputMaybe; +}; + +export type CreateBackupPayload = { + __typename?: 'CreateBackupPayload'; + clientMutationId?: Maybe; + url: Scalars['String']['output']; +}; + +export type CreateCategoryInput = { + clientMutationId?: InputMaybe; + default?: InputMaybe; + includeInUpdate?: InputMaybe; + name: Scalars['String']['input']; + order?: InputMaybe; +}; + +export type CreateCategoryPayload = { + __typename?: 'CreateCategoryPayload'; + category: CategoryType; + clientMutationId?: Maybe; +}; + +export type DeleteCategoryInput = { + categoryId: Scalars['Int']['input']; + clientMutationId?: InputMaybe; +}; + +export type DeleteCategoryMetaInput = { + categoryId: Scalars['Int']['input']; + clientMutationId?: InputMaybe; + key: Scalars['String']['input']; +}; + +export type DeleteCategoryMetaPayload = { + __typename?: 'DeleteCategoryMetaPayload'; + category: CategoryType; + clientMutationId?: Maybe; + meta?: Maybe; +}; + +export type DeleteCategoryPayload = { + __typename?: 'DeleteCategoryPayload'; + category?: Maybe; + clientMutationId?: Maybe; + mangas: Array; +}; + +export type DeleteChapterMetaInput = { + chapterId: Scalars['Int']['input']; + clientMutationId?: InputMaybe; + key: Scalars['String']['input']; +}; + +export type DeleteChapterMetaPayload = { + __typename?: 'DeleteChapterMetaPayload'; + chapter: ChapterType; + clientMutationId?: Maybe; + meta?: Maybe; +}; + +export type DeleteDownloadedChapterInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; +}; + +export type DeleteDownloadedChapterPayload = { + __typename?: 'DeleteDownloadedChapterPayload'; + chapters: ChapterType; + clientMutationId?: Maybe; +}; + +export type DeleteDownloadedChaptersInput = { + clientMutationId?: InputMaybe; + ids: Array; +}; + +export type DeleteDownloadedChaptersPayload = { + __typename?: 'DeleteDownloadedChaptersPayload'; + chapters: Array; + clientMutationId?: Maybe; +}; + +export type DeleteGlobalMetaInput = { + clientMutationId?: InputMaybe; + key: Scalars['String']['input']; +}; + +export type DeleteGlobalMetaPayload = { + __typename?: 'DeleteGlobalMetaPayload'; + clientMutationId?: Maybe; + meta?: Maybe; +}; + +export type DeleteMangaMetaInput = { + clientMutationId?: InputMaybe; + key: Scalars['String']['input']; + mangaId: Scalars['Int']['input']; +}; + +export type DeleteMangaMetaPayload = { + __typename?: 'DeleteMangaMetaPayload'; + clientMutationId?: Maybe; + manga: MangaType; + meta?: Maybe; +}; + +export type DequeueChapterDownloadInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; +}; + +export type DequeueChapterDownloadPayload = { + __typename?: 'DequeueChapterDownloadPayload'; + clientMutationId?: Maybe; + downloadStatus: DownloadStatus; +}; + +export type DequeueChapterDownloadsInput = { + clientMutationId?: InputMaybe; + ids: Array; +}; + +export type DequeueChapterDownloadsPayload = { + __typename?: 'DequeueChapterDownloadsPayload'; + clientMutationId?: Maybe; + downloadStatus: DownloadStatus; +}; + +export type DownloadAheadInput = { + clientMutationId?: InputMaybe; + latestReadChapterIds?: InputMaybe>; + mangaIds: Array; +}; + +export type DownloadAheadPayload = { + __typename?: 'DownloadAheadPayload'; + clientMutationId?: Maybe; +}; + +export type DownloadEdge = Edge & { + __typename?: 'DownloadEdge'; + cursor: Scalars['Cursor']['output']; + node: DownloadType; +}; + +export type DownloadNodeList = NodeList & { + __typename?: 'DownloadNodeList'; + edges: Array; + nodes: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + +export enum DownloadState { + Downloading = 'DOWNLOADING', + Error = 'ERROR', + Finished = 'FINISHED', + Queued = 'QUEUED' +} + +export type DownloadStatus = { + __typename?: 'DownloadStatus'; + queue: Array; + state: DownloaderState; +}; + +export type DownloadType = { + __typename?: 'DownloadType'; + chapter: ChapterType; + manga: MangaType; + progress: Scalars['Float']['output']; + state: DownloadState; + tries: Scalars['Int']['output']; +}; + +export enum DownloaderState { + Started = 'STARTED', + Stopped = 'STOPPED' +} + +export type Edge = { + /** A cursor for use in pagination. */ + cursor: Scalars['Cursor']['output']; + /** The [T] at the end of the edge. */ + node: Node; +}; + +export type EditTextPreference = { + __typename?: 'EditTextPreference'; + currentValue?: Maybe; + default?: Maybe; + dialogMessage?: Maybe; + dialogTitle?: Maybe; + key: Scalars['String']['output']; + summary?: Maybe; + text?: Maybe; + title?: Maybe; + visible: Scalars['Boolean']['output']; +}; + +export type EnqueueChapterDownloadInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; +}; + +export type EnqueueChapterDownloadPayload = { + __typename?: 'EnqueueChapterDownloadPayload'; + clientMutationId?: Maybe; + downloadStatus: DownloadStatus; +}; + +export type EnqueueChapterDownloadsInput = { + clientMutationId?: InputMaybe; + ids: Array; +}; + +export type EnqueueChapterDownloadsPayload = { + __typename?: 'EnqueueChapterDownloadsPayload'; + clientMutationId?: Maybe; + downloadStatus: DownloadStatus; +}; + +export type ExtensionConditionInput = { + apkName?: InputMaybe; + hasUpdate?: InputMaybe; + iconUrl?: InputMaybe; + isInstalled?: InputMaybe; + isNsfw?: InputMaybe; + isObsolete?: InputMaybe; + lang?: InputMaybe; + name?: InputMaybe; + pkgName?: InputMaybe; + versionCode?: InputMaybe; + versionName?: InputMaybe; +}; + +export type ExtensionEdge = Edge & { + __typename?: 'ExtensionEdge'; + cursor: Scalars['Cursor']['output']; + node: ExtensionType; +}; + +export type ExtensionFilterInput = { + and?: InputMaybe>; + apkName?: InputMaybe; + hasUpdate?: InputMaybe; + iconUrl?: InputMaybe; + isInstalled?: InputMaybe; + isNsfw?: InputMaybe; + isObsolete?: InputMaybe; + lang?: InputMaybe; + name?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>; + pkgName?: InputMaybe; + versionCode?: InputMaybe; + versionName?: InputMaybe; +}; + +export type ExtensionNodeList = NodeList & { + __typename?: 'ExtensionNodeList'; + edges: Array; + nodes: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + +export enum ExtensionOrderBy { + ApkName = 'APK_NAME', + Name = 'NAME', + PkgName = 'PKG_NAME' +} + +export type ExtensionType = { + __typename?: 'ExtensionType'; + apkName: Scalars['String']['output']; + hasUpdate: Scalars['Boolean']['output']; + iconUrl: Scalars['String']['output']; + isInstalled: Scalars['Boolean']['output']; + isNsfw: Scalars['Boolean']['output']; + isObsolete: Scalars['Boolean']['output']; + lang: Scalars['String']['output']; + name: Scalars['String']['output']; + pkgName: Scalars['String']['output']; + source: SourceNodeList; + versionCode: Scalars['Int']['output']; + versionName: Scalars['String']['output']; +}; + +export type FetchChapterPagesInput = { + chapterId: Scalars['Int']['input']; + clientMutationId?: InputMaybe; +}; + +export type FetchChapterPagesPayload = { + __typename?: 'FetchChapterPagesPayload'; + chapter: ChapterType; + clientMutationId?: Maybe; + pages: Array; +}; + +export type FetchChaptersInput = { + clientMutationId?: InputMaybe; + mangaId: Scalars['Int']['input']; +}; + +export type FetchChaptersPayload = { + __typename?: 'FetchChaptersPayload'; + chapters: Array; + clientMutationId?: Maybe; +}; + +export type FetchExtensionsInput = { + clientMutationId?: InputMaybe; +}; + +export type FetchExtensionsPayload = { + __typename?: 'FetchExtensionsPayload'; + clientMutationId?: Maybe; + extensions: Array; +}; + +export type FetchMangaInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; +}; + +export type FetchMangaPayload = { + __typename?: 'FetchMangaPayload'; + clientMutationId?: Maybe; + manga: MangaType; +}; + +export type FetchSourceMangaInput = { + clientMutationId?: InputMaybe; + filters?: InputMaybe>; + page: Scalars['Int']['input']; + query?: InputMaybe; + source: Scalars['LongString']['input']; + type: FetchSourceMangaType; +}; + +export type FetchSourceMangaPayload = { + __typename?: 'FetchSourceMangaPayload'; + clientMutationId?: Maybe; + hasNextPage: Scalars['Boolean']['output']; + mangas: Array; +}; + +export enum FetchSourceMangaType { + Latest = 'LATEST', + Popular = 'POPULAR', + Search = 'SEARCH' +} + +export type Filter = CheckBoxFilter | GroupFilter | HeaderFilter | SelectFilter | SeparatorFilter | SortFilter | TextFilter | TriStateFilter; + +export type FilterChangeInput = { + checkBoxState?: InputMaybe; + groupChange?: InputMaybe; + position: Scalars['Int']['input']; + selectState?: InputMaybe; + sortState?: InputMaybe; + textState?: InputMaybe; + triState?: InputMaybe; +}; + +export type FloatFilterInput = { + distinctFrom?: InputMaybe; + equalTo?: InputMaybe; + greaterThan?: InputMaybe; + greaterThanOrEqualTo?: InputMaybe; + in?: InputMaybe>; + isNull?: InputMaybe; + lessThan?: InputMaybe; + lessThanOrEqualTo?: InputMaybe; + notDistinctFrom?: InputMaybe; + notEqualTo?: InputMaybe; + notIn?: InputMaybe>; +}; + +export type GlobalMetaNodeList = NodeList & { + __typename?: 'GlobalMetaNodeList'; + edges: Array; + nodes: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + +export type GlobalMetaType = MetaType & { + __typename?: 'GlobalMetaType'; + key: Scalars['String']['output']; + value: Scalars['String']['output']; +}; + +export type GlobalMetaTypeInput = { + key: Scalars['String']['input']; + value: Scalars['String']['input']; +}; + +export type GroupFilter = { + __typename?: 'GroupFilter'; + filters: Array; + name: Scalars['String']['output']; +}; + +export type HeaderFilter = { + __typename?: 'HeaderFilter'; + name: Scalars['String']['output']; +}; + +export enum IncludeInUpdate { + Exclude = 'EXCLUDE', + Include = 'INCLUDE', + Unset = 'UNSET' +} + +export type InstallExternalExtensionInput = { + clientMutationId?: InputMaybe; + extensionFile: Scalars['Upload']['input']; +}; + +export type InstallExternalExtensionPayload = { + __typename?: 'InstallExternalExtensionPayload'; + clientMutationId?: Maybe; + extension: ExtensionType; +}; + +export type IntFilterInput = { + distinctFrom?: InputMaybe; + equalTo?: InputMaybe; + greaterThan?: InputMaybe; + greaterThanOrEqualTo?: InputMaybe; + in?: InputMaybe>; + isNull?: InputMaybe; + lessThan?: InputMaybe; + lessThanOrEqualTo?: InputMaybe; + notDistinctFrom?: InputMaybe; + notEqualTo?: InputMaybe; + notIn?: InputMaybe>; +}; + +export type LastUpdateTimestampPayload = { + __typename?: 'LastUpdateTimestampPayload'; + timestamp: Scalars['LongString']['output']; +}; + +export type ListPreference = { + __typename?: 'ListPreference'; + currentValue?: Maybe; + default?: Maybe; + entries: Array; + entryValues: Array; + key: Scalars['String']['output']; + summary?: Maybe; + title?: Maybe; + visible: Scalars['Boolean']['output']; +}; + +export type LongFilterInput = { + distinctFrom?: InputMaybe; + equalTo?: InputMaybe; + greaterThan?: InputMaybe; + greaterThanOrEqualTo?: InputMaybe; + in?: InputMaybe>; + isNull?: InputMaybe; + lessThan?: InputMaybe; + lessThanOrEqualTo?: InputMaybe; + notDistinctFrom?: InputMaybe; + notEqualTo?: InputMaybe; + notIn?: InputMaybe>; +}; + +export type MangaConditionInput = { + artist?: InputMaybe; + author?: InputMaybe; + categoryIds?: InputMaybe>; + chaptersLastFetchedAt?: InputMaybe; + description?: InputMaybe; + genre?: InputMaybe>; + id?: InputMaybe; + inLibrary?: InputMaybe; + inLibraryAt?: InputMaybe; + initialized?: InputMaybe; + lastFetchedAt?: InputMaybe; + realUrl?: InputMaybe; + sourceId?: InputMaybe; + status?: InputMaybe; + thumbnailUrl?: InputMaybe; + title?: InputMaybe; + url?: InputMaybe; +}; + +export type MangaEdge = Edge & { + __typename?: 'MangaEdge'; + cursor: Scalars['Cursor']['output']; + node: MangaType; +}; + +export type MangaFilterInput = { + and?: InputMaybe>; + artist?: InputMaybe; + author?: InputMaybe; + categoryId?: InputMaybe; + chaptersLastFetchedAt?: InputMaybe; + description?: InputMaybe; + genre?: InputMaybe; + id?: InputMaybe; + inLibrary?: InputMaybe; + inLibraryAt?: InputMaybe; + initialized?: InputMaybe; + lastFetchedAt?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>; + realUrl?: InputMaybe; + sourceId?: InputMaybe; + status?: InputMaybe; + thumbnailUrl?: InputMaybe; + title?: InputMaybe; + url?: InputMaybe; +}; + +export type MangaMetaType = MetaType & { + __typename?: 'MangaMetaType'; + key: Scalars['String']['output']; + manga: MangaType; + mangaId: Scalars['Int']['output']; + value: Scalars['String']['output']; +}; + +export type MangaMetaTypeInput = { + key: Scalars['String']['input']; + mangaId: Scalars['Int']['input']; + value: Scalars['String']['input']; +}; + +export type MangaNodeList = NodeList & { + __typename?: 'MangaNodeList'; + edges: Array; + nodes: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + +export enum MangaOrderBy { + Id = 'ID', + InLibraryAt = 'IN_LIBRARY_AT', + LastFetchedAt = 'LAST_FETCHED_AT', + Title = 'TITLE' +} + +export enum MangaStatus { + Cancelled = 'CANCELLED', + Completed = 'COMPLETED', + Licensed = 'LICENSED', + Ongoing = 'ONGOING', + OnHiatus = 'ON_HIATUS', + PublishingFinished = 'PUBLISHING_FINISHED', + Unknown = 'UNKNOWN' +} + +export type MangaStatusFilterInput = { + distinctFrom?: InputMaybe; + equalTo?: InputMaybe; + greaterThan?: InputMaybe; + greaterThanOrEqualTo?: InputMaybe; + in?: InputMaybe>; + isNull?: InputMaybe; + lessThan?: InputMaybe; + lessThanOrEqualTo?: InputMaybe; + notDistinctFrom?: InputMaybe; + notEqualTo?: InputMaybe; + notIn?: InputMaybe>; +}; + +export type MangaType = { + __typename?: 'MangaType'; + age?: Maybe; + artist?: Maybe; + author?: Maybe; + categories: CategoryNodeList; + chapters: ChapterNodeList; + chaptersAge?: Maybe; + chaptersLastFetchedAt?: Maybe; + description?: Maybe; + downloadCount: Scalars['Int']['output']; + genre: Array; + id: Scalars['Int']['output']; + inLibrary: Scalars['Boolean']['output']; + inLibraryAt: Scalars['LongString']['output']; + initialized: Scalars['Boolean']['output']; + lastFetchedAt?: Maybe; + lastReadChapter?: Maybe; + meta: Array; + realUrl?: Maybe; + source?: Maybe; + sourceId: Scalars['LongString']['output']; + status: MangaStatus; + thumbnailUrl?: Maybe; + title: Scalars['String']['output']; + unreadCount: Scalars['Int']['output']; + url: Scalars['String']['output']; +}; + +export type MetaConditionInput = { + key?: InputMaybe; + value?: InputMaybe; +}; + +export type MetaEdge = Edge & { + __typename?: 'MetaEdge'; + cursor: Scalars['Cursor']['output']; + node: GlobalMetaType; +}; + +export type MetaFilterInput = { + and?: InputMaybe>; + key?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>; + value?: InputMaybe; +}; + +export enum MetaOrderBy { + Key = 'KEY', + Value = 'VALUE' +} + +export type MetaType = { + key: Scalars['String']['output']; + value: Scalars['String']['output']; +}; + +export type MultiSelectListPreference = { + __typename?: 'MultiSelectListPreference'; + currentValue?: Maybe>; + default?: Maybe>; + dialogMessage?: Maybe; + dialogTitle?: Maybe; + entries: Array; + entryValues: Array; + key: Scalars['String']['output']; + summary?: Maybe; + title?: Maybe; + visible: Scalars['Boolean']['output']; +}; + +export type Mutation = { + __typename?: 'Mutation'; + clearDownloader: ClearDownloaderPayload; + createBackup: CreateBackupPayload; + createCategory: CreateCategoryPayload; + deleteCategory: DeleteCategoryPayload; + deleteCategoryMeta: DeleteCategoryMetaPayload; + deleteChapterMeta: DeleteChapterMetaPayload; + deleteDownloadedChapter: DeleteDownloadedChapterPayload; + deleteDownloadedChapters: DeleteDownloadedChaptersPayload; + deleteGlobalMeta: DeleteGlobalMetaPayload; + deleteMangaMeta: DeleteMangaMetaPayload; + dequeueChapterDownload: DequeueChapterDownloadPayload; + dequeueChapterDownloads: DequeueChapterDownloadsPayload; + downloadAhead: DownloadAheadPayload; + enqueueChapterDownload: EnqueueChapterDownloadPayload; + enqueueChapterDownloads: EnqueueChapterDownloadsPayload; + fetchChapterPages: FetchChapterPagesPayload; + fetchChapters: FetchChaptersPayload; + fetchExtensions: FetchExtensionsPayload; + fetchManga: FetchMangaPayload; + fetchSourceManga: FetchSourceMangaPayload; + installExternalExtension: InstallExternalExtensionPayload; + reorderChapterDownload: ReorderChapterDownloadPayload; + resetSettings: ResetSettingsPayload; + restoreBackup: RestoreBackupPayload; + setCategoryMeta: SetCategoryMetaPayload; + setChapterMeta: SetChapterMetaPayload; + setGlobalMeta: SetGlobalMetaPayload; + setMangaMeta: SetMangaMetaPayload; + setSettings: SetSettingsPayload; + startDownloader: StartDownloaderPayload; + stopDownloader: StopDownloaderPayload; + updateCategories: UpdateCategoriesPayload; + updateCategory: UpdateCategoryPayload; + updateCategoryManga: UpdateCategoryMangaPayload; + updateCategoryOrder: UpdateCategoryOrderPayload; + updateChapter: UpdateChapterPayload; + updateChapters: UpdateChaptersPayload; + updateExtension: UpdateExtensionPayload; + updateExtensions: UpdateExtensionsPayload; + updateLibraryManga: UpdateLibraryMangaPayload; + updateManga: UpdateMangaPayload; + updateMangaCategories: UpdateMangaCategoriesPayload; + updateMangas: UpdateMangasPayload; + updateMangasCategories: UpdateMangasCategoriesPayload; + updateSourcePreference: UpdateSourcePreferencePayload; + updateStop: UpdateStopPayload; + updateWebUI: WebUiUpdatePayload; +}; + + +export type MutationClearDownloaderArgs = { + input: ClearDownloaderInput; +}; + + +export type MutationCreateBackupArgs = { + input?: InputMaybe; +}; + + +export type MutationCreateCategoryArgs = { + input: CreateCategoryInput; +}; + + +export type MutationDeleteCategoryArgs = { + input: DeleteCategoryInput; +}; + + +export type MutationDeleteCategoryMetaArgs = { + input: DeleteCategoryMetaInput; +}; + + +export type MutationDeleteChapterMetaArgs = { + input: DeleteChapterMetaInput; +}; + + +export type MutationDeleteDownloadedChapterArgs = { + input: DeleteDownloadedChapterInput; +}; + + +export type MutationDeleteDownloadedChaptersArgs = { + input: DeleteDownloadedChaptersInput; +}; + + +export type MutationDeleteGlobalMetaArgs = { + input: DeleteGlobalMetaInput; +}; + + +export type MutationDeleteMangaMetaArgs = { + input: DeleteMangaMetaInput; +}; + + +export type MutationDequeueChapterDownloadArgs = { + input: DequeueChapterDownloadInput; +}; + + +export type MutationDequeueChapterDownloadsArgs = { + input: DequeueChapterDownloadsInput; +}; + + +export type MutationDownloadAheadArgs = { + input: DownloadAheadInput; +}; + + +export type MutationEnqueueChapterDownloadArgs = { + input: EnqueueChapterDownloadInput; +}; + + +export type MutationEnqueueChapterDownloadsArgs = { + input: EnqueueChapterDownloadsInput; +}; + + +export type MutationFetchChapterPagesArgs = { + input: FetchChapterPagesInput; +}; + + +export type MutationFetchChaptersArgs = { + input: FetchChaptersInput; +}; + + +export type MutationFetchExtensionsArgs = { + input: FetchExtensionsInput; +}; + + +export type MutationFetchMangaArgs = { + input: FetchMangaInput; +}; + + +export type MutationFetchSourceMangaArgs = { + input: FetchSourceMangaInput; +}; + + +export type MutationInstallExternalExtensionArgs = { + input: InstallExternalExtensionInput; +}; + + +export type MutationReorderChapterDownloadArgs = { + input: ReorderChapterDownloadInput; +}; + + +export type MutationResetSettingsArgs = { + input: ResetSettingsInput; +}; + + +export type MutationRestoreBackupArgs = { + input: RestoreBackupInput; +}; + + +export type MutationSetCategoryMetaArgs = { + input: SetCategoryMetaInput; +}; + + +export type MutationSetChapterMetaArgs = { + input: SetChapterMetaInput; +}; + + +export type MutationSetGlobalMetaArgs = { + input: SetGlobalMetaInput; +}; + + +export type MutationSetMangaMetaArgs = { + input: SetMangaMetaInput; +}; + + +export type MutationSetSettingsArgs = { + input: SetSettingsInput; +}; + + +export type MutationStartDownloaderArgs = { + input: StartDownloaderInput; +}; + + +export type MutationStopDownloaderArgs = { + input: StopDownloaderInput; +}; + + +export type MutationUpdateCategoriesArgs = { + input: UpdateCategoriesInput; +}; + + +export type MutationUpdateCategoryArgs = { + input: UpdateCategoryInput; +}; + + +export type MutationUpdateCategoryMangaArgs = { + input: UpdateCategoryMangaInput; +}; + + +export type MutationUpdateCategoryOrderArgs = { + input: UpdateCategoryOrderInput; +}; + + +export type MutationUpdateChapterArgs = { + input: UpdateChapterInput; +}; + + +export type MutationUpdateChaptersArgs = { + input: UpdateChaptersInput; +}; + + +export type MutationUpdateExtensionArgs = { + input: UpdateExtensionInput; +}; + + +export type MutationUpdateExtensionsArgs = { + input: UpdateExtensionsInput; +}; + + +export type MutationUpdateLibraryMangaArgs = { + input: UpdateLibraryMangaInput; +}; + + +export type MutationUpdateMangaArgs = { + input: UpdateMangaInput; +}; + + +export type MutationUpdateMangaCategoriesArgs = { + input: UpdateMangaCategoriesInput; +}; + + +export type MutationUpdateMangasArgs = { + input: UpdateMangasInput; +}; + + +export type MutationUpdateMangasCategoriesArgs = { + input: UpdateMangasCategoriesInput; +}; + + +export type MutationUpdateSourcePreferenceArgs = { + input: UpdateSourcePreferenceInput; +}; + + +export type MutationUpdateStopArgs = { + input: UpdateStopInput; +}; + + +export type MutationUpdateWebUiArgs = { + input: WebUiUpdateInput; +}; + +export type Node = CategoryMetaType | CategoryType | ChapterMetaType | ChapterType | DownloadType | ExtensionType | GlobalMetaType | MangaMetaType | MangaType | PartialSettingsType | SettingsType | SourceType; + +export type NodeList = { + /** A list of edges which contains the [T] and cursor to aid in pagination. */ + edges: Array; + /** A list of [T] objects. */ + nodes: Array; + /** Information to aid in pagination. */ + pageInfo: PageInfo; + /** The count of all nodes you could get from the connection. */ + totalCount: Scalars['Int']['output']; +}; + +export type PageInfo = { + __typename?: 'PageInfo'; + /** When paginating forwards, the cursor to continue. */ + endCursor?: Maybe; + /** When paginating forwards, are there more items? */ + hasNextPage: Scalars['Boolean']['output']; + /** When paginating backwards, are there more items? */ + hasPreviousPage: Scalars['Boolean']['output']; + /** When paginating backwards, the cursor to continue. */ + startCursor?: Maybe; +}; + +export type PartialSettingsType = Settings & { + __typename?: 'PartialSettingsType'; + autoDownloadNewChapters?: Maybe; + backupInterval?: Maybe; + backupPath?: Maybe; + backupTTL?: Maybe; + backupTime?: Maybe; + basicAuthEnabled?: Maybe; + basicAuthPassword?: Maybe; + basicAuthUsername?: Maybe; + debugLogsEnabled?: Maybe; + downloadAsCbz?: Maybe; + downloadsPath?: Maybe; + electronPath?: Maybe; + excludeCompleted?: Maybe; + excludeNotStarted?: Maybe; + excludeUnreadChapters?: Maybe; + globalUpdateInterval?: Maybe; + initialOpenInBrowserEnabled?: Maybe; + ip?: Maybe; + localSourcePath?: Maybe; + maxSourcesInParallel?: Maybe; + port?: Maybe; + socksProxyEnabled?: Maybe; + socksProxyHost?: Maybe; + socksProxyPort?: Maybe; + systemTrayEnabled?: Maybe; + webUIChannel?: Maybe; + webUIFlavor?: Maybe; + webUIInterface?: Maybe; + webUIUpdateCheckInterval?: Maybe; +}; + +export type PartialSettingsTypeInput = { + autoDownloadNewChapters?: InputMaybe; + backupInterval?: InputMaybe; + backupPath?: InputMaybe; + backupTTL?: InputMaybe; + backupTime?: InputMaybe; + basicAuthEnabled?: InputMaybe; + basicAuthPassword?: InputMaybe; + basicAuthUsername?: InputMaybe; + debugLogsEnabled?: InputMaybe; + downloadAsCbz?: InputMaybe; + downloadsPath?: InputMaybe; + electronPath?: InputMaybe; + excludeCompleted?: InputMaybe; + excludeNotStarted?: InputMaybe; + excludeUnreadChapters?: InputMaybe; + globalUpdateInterval?: InputMaybe; + initialOpenInBrowserEnabled?: InputMaybe; + ip?: InputMaybe; + localSourcePath?: InputMaybe; + maxSourcesInParallel?: InputMaybe; + port?: InputMaybe; + socksProxyEnabled?: InputMaybe; + socksProxyHost?: InputMaybe; + socksProxyPort?: InputMaybe; + systemTrayEnabled?: InputMaybe; + webUIChannel?: InputMaybe; + webUIFlavor?: InputMaybe; + webUIInterface?: InputMaybe; + webUIUpdateCheckInterval?: InputMaybe; +}; + +export type Preference = CheckBoxPreference | EditTextPreference | ListPreference | MultiSelectListPreference | SwitchPreference; + +export type Query = { + __typename?: 'Query'; + about: AboutPayload; + categories: CategoryNodeList; + category: CategoryType; + chapter: ChapterType; + chapters: ChapterNodeList; + checkForServerUpdates: Array; + checkForWebUIUpdate: WebUiUpdateInfo; + downloadStatus: DownloadStatus; + extension: ExtensionType; + extensions: ExtensionNodeList; + getWebUIUpdateStatus: WebUiUpdateStatus; + lastUpdateTimestamp: LastUpdateTimestampPayload; + manga: MangaType; + mangas: MangaNodeList; + meta: GlobalMetaType; + metas: GlobalMetaNodeList; + restoreStatus: BackupRestoreStatus; + settings: SettingsType; + source: SourceType; + sources: SourceNodeList; + updateStatus: UpdateStatus; + validateBackup: ValidateBackupResult; +}; + + +export type QueryCategoriesArgs = { + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}; + + +export type QueryCategoryArgs = { + id: Scalars['Int']['input']; +}; + + +export type QueryChapterArgs = { + id: Scalars['Int']['input']; +}; + + +export type QueryChaptersArgs = { + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}; + + +export type QueryExtensionArgs = { + pkgName: Scalars['String']['input']; +}; + + +export type QueryExtensionsArgs = { + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}; + + +export type QueryMangaArgs = { + id: Scalars['Int']['input']; +}; + + +export type QueryMangasArgs = { + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}; + + +export type QueryMetaArgs = { + key: Scalars['String']['input']; +}; + + +export type QueryMetasArgs = { + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}; + + +export type QuerySourceArgs = { + id: Scalars['LongString']['input']; +}; + + +export type QuerySourcesArgs = { + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}; + + +export type QueryValidateBackupArgs = { + input: ValidateBackupInput; +}; + +export type ReorderChapterDownloadInput = { + chapterId: Scalars['Int']['input']; + clientMutationId?: InputMaybe; + to: Scalars['Int']['input']; +}; + +export type ReorderChapterDownloadPayload = { + __typename?: 'ReorderChapterDownloadPayload'; + clientMutationId?: Maybe; + downloadStatus: DownloadStatus; +}; + +export type ResetSettingsInput = { + clientMutationId?: InputMaybe; +}; + +export type ResetSettingsPayload = { + __typename?: 'ResetSettingsPayload'; + clientMutationId?: Maybe; + settings: SettingsType; +}; + +export type RestoreBackupInput = { + backup: Scalars['Upload']['input']; + clientMutationId?: InputMaybe; +}; + +export type RestoreBackupPayload = { + __typename?: 'RestoreBackupPayload'; + clientMutationId?: Maybe; + status: BackupRestoreStatus; +}; + +export type SelectFilter = { + __typename?: 'SelectFilter'; + default: Scalars['Int']['output']; + name: Scalars['String']['output']; + values: Array; +}; + +export type SeparatorFilter = { + __typename?: 'SeparatorFilter'; + name: Scalars['String']['output']; +}; + +export type SetCategoryMetaInput = { + clientMutationId?: InputMaybe; + meta: CategoryMetaTypeInput; +}; + +export type SetCategoryMetaPayload = { + __typename?: 'SetCategoryMetaPayload'; + clientMutationId?: Maybe; + meta: CategoryMetaType; +}; + +export type SetChapterMetaInput = { + clientMutationId?: InputMaybe; + meta: ChapterMetaTypeInput; +}; + +export type SetChapterMetaPayload = { + __typename?: 'SetChapterMetaPayload'; + clientMutationId?: Maybe; + meta: ChapterMetaType; +}; + +export type SetGlobalMetaInput = { + clientMutationId?: InputMaybe; + meta: GlobalMetaTypeInput; +}; + +export type SetGlobalMetaPayload = { + __typename?: 'SetGlobalMetaPayload'; + clientMutationId?: Maybe; + meta: GlobalMetaType; +}; + +export type SetMangaMetaInput = { + clientMutationId?: InputMaybe; + meta: MangaMetaTypeInput; +}; + +export type SetMangaMetaPayload = { + __typename?: 'SetMangaMetaPayload'; + clientMutationId?: Maybe; + meta: MangaMetaType; +}; + +export type SetSettingsInput = { + clientMutationId?: InputMaybe; + settings: PartialSettingsTypeInput; +}; + +export type SetSettingsPayload = { + __typename?: 'SetSettingsPayload'; + clientMutationId?: Maybe; + settings: SettingsType; +}; + +export type Settings = { + autoDownloadNewChapters?: Maybe; + backupInterval?: Maybe; + backupPath?: Maybe; + backupTTL?: Maybe; + backupTime?: Maybe; + basicAuthEnabled?: Maybe; + basicAuthPassword?: Maybe; + basicAuthUsername?: Maybe; + debugLogsEnabled?: Maybe; + downloadAsCbz?: Maybe; + downloadsPath?: Maybe; + electronPath?: Maybe; + excludeCompleted?: Maybe; + excludeNotStarted?: Maybe; + excludeUnreadChapters?: Maybe; + globalUpdateInterval?: Maybe; + initialOpenInBrowserEnabled?: Maybe; + ip?: Maybe; + localSourcePath?: Maybe; + maxSourcesInParallel?: Maybe; + port?: Maybe; + socksProxyEnabled?: Maybe; + socksProxyHost?: Maybe; + socksProxyPort?: Maybe; + systemTrayEnabled?: Maybe; + webUIChannel?: Maybe; + webUIFlavor?: Maybe; + webUIInterface?: Maybe; + webUIUpdateCheckInterval?: Maybe; +}; + +export type SettingsType = Settings & { + __typename?: 'SettingsType'; + autoDownloadNewChapters: Scalars['Boolean']['output']; + backupInterval: Scalars['Int']['output']; + backupPath: Scalars['String']['output']; + backupTTL: Scalars['Int']['output']; + backupTime: Scalars['String']['output']; + basicAuthEnabled: Scalars['Boolean']['output']; + basicAuthPassword: Scalars['String']['output']; + basicAuthUsername: Scalars['String']['output']; + debugLogsEnabled: Scalars['Boolean']['output']; + downloadAsCbz: Scalars['Boolean']['output']; + downloadsPath: Scalars['String']['output']; + electronPath: Scalars['String']['output']; + excludeCompleted: Scalars['Boolean']['output']; + excludeNotStarted: Scalars['Boolean']['output']; + excludeUnreadChapters: Scalars['Boolean']['output']; + globalUpdateInterval: Scalars['Float']['output']; + initialOpenInBrowserEnabled: Scalars['Boolean']['output']; + ip: Scalars['String']['output']; + localSourcePath: Scalars['String']['output']; + maxSourcesInParallel: Scalars['Int']['output']; + port: Scalars['Int']['output']; + socksProxyEnabled: Scalars['Boolean']['output']; + socksProxyHost: Scalars['String']['output']; + socksProxyPort: Scalars['String']['output']; + systemTrayEnabled: Scalars['Boolean']['output']; + webUIChannel: WebUiChannel; + webUIFlavor: WebUiFlavor; + webUIInterface: WebUiInterface; + webUIUpdateCheckInterval: Scalars['Float']['output']; +}; + +export type SortFilter = { + __typename?: 'SortFilter'; + default?: Maybe; + name: Scalars['String']['output']; + values: Array; +}; + +export enum SortOrder { + Asc = 'ASC', + AscNullsFirst = 'ASC_NULLS_FIRST', + AscNullsLast = 'ASC_NULLS_LAST', + Desc = 'DESC', + DescNullsFirst = 'DESC_NULLS_FIRST', + DescNullsLast = 'DESC_NULLS_LAST' +} + +export type SortSelection = { + __typename?: 'SortSelection'; + ascending: Scalars['Boolean']['output']; + index: Scalars['Int']['output']; +}; + +export type SortSelectionInput = { + ascending: Scalars['Boolean']['input']; + index: Scalars['Int']['input']; +}; + +export type SourceConditionInput = { + id?: InputMaybe; + isNsfw?: InputMaybe; + lang?: InputMaybe; + name?: InputMaybe; +}; + +export type SourceEdge = Edge & { + __typename?: 'SourceEdge'; + cursor: Scalars['Cursor']['output']; + node: SourceType; +}; + +export type SourceFilterInput = { + and?: InputMaybe>; + id?: InputMaybe; + isNsfw?: InputMaybe; + lang?: InputMaybe; + name?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>; +}; + +export type SourceNodeList = NodeList & { + __typename?: 'SourceNodeList'; + edges: Array; + nodes: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + +export enum SourceOrderBy { + Id = 'ID', + Lang = 'LANG', + Name = 'NAME' +} + +export type SourcePreferenceChangeInput = { + checkBoxState?: InputMaybe; + editTextState?: InputMaybe; + listState?: InputMaybe; + multiSelectState?: InputMaybe>; + position: Scalars['Int']['input']; + switchState?: InputMaybe; +}; + +export type SourceType = { + __typename?: 'SourceType'; + displayName: Scalars['String']['output']; + extension: ExtensionType; + filters: Array; + iconUrl: Scalars['String']['output']; + id: Scalars['LongString']['output']; + isConfigurable: Scalars['Boolean']['output']; + isNsfw: Scalars['Boolean']['output']; + lang: Scalars['String']['output']; + manga: MangaNodeList; + name: Scalars['String']['output']; + preferences: Array; + supportsLatest: Scalars['Boolean']['output']; +}; + +export type StartDownloaderInput = { + clientMutationId?: InputMaybe; +}; + +export type StartDownloaderPayload = { + __typename?: 'StartDownloaderPayload'; + clientMutationId?: Maybe; + downloadStatus: DownloadStatus; +}; + +export type StopDownloaderInput = { + clientMutationId?: InputMaybe; +}; + +export type StopDownloaderPayload = { + __typename?: 'StopDownloaderPayload'; + clientMutationId?: Maybe; + downloadStatus: DownloadStatus; +}; + +export type StringFilterInput = { + distinctFrom?: InputMaybe; + distinctFromInsensitive?: InputMaybe; + endsWith?: InputMaybe; + endsWithInsensitive?: InputMaybe; + equalTo?: InputMaybe; + greaterThan?: InputMaybe; + greaterThanInsensitive?: InputMaybe; + greaterThanOrEqualTo?: InputMaybe; + greaterThanOrEqualToInsensitive?: InputMaybe; + in?: InputMaybe>; + inInsensitive?: InputMaybe>; + includes?: InputMaybe; + includesInsensitive?: InputMaybe; + isNull?: InputMaybe; + lessThan?: InputMaybe; + lessThanInsensitive?: InputMaybe; + lessThanOrEqualTo?: InputMaybe; + lessThanOrEqualToInsensitive?: InputMaybe; + like?: InputMaybe; + likeInsensitive?: InputMaybe; + notDistinctFrom?: InputMaybe; + notDistinctFromInsensitive?: InputMaybe; + notEndsWith?: InputMaybe; + notEndsWithInsensitive?: InputMaybe; + notEqualTo?: InputMaybe; + notIn?: InputMaybe>; + notInInsensitive?: InputMaybe>; + notIncludes?: InputMaybe; + notIncludesInsensitive?: InputMaybe; + notLike?: InputMaybe; + notLikeInsensitive?: InputMaybe; + notStartsWith?: InputMaybe; + notStartsWithInsensitive?: InputMaybe; + startsWith?: InputMaybe; + startsWithInsensitive?: InputMaybe; +}; + +export type Subscription = { + __typename?: 'Subscription'; + downloadChanged: DownloadStatus; + updateStatusChanged: UpdateStatus; + webUIUpdateStatusChange: WebUiUpdateStatus; +}; + +export type SwitchPreference = { + __typename?: 'SwitchPreference'; + currentValue?: Maybe; + default: Scalars['Boolean']['output']; + key: Scalars['String']['output']; + summary?: Maybe; + title: Scalars['String']['output']; + visible: Scalars['Boolean']['output']; +}; + +export type TextFilter = { + __typename?: 'TextFilter'; + default: Scalars['String']['output']; + name: Scalars['String']['output']; +}; + +export enum TriState { + Exclude = 'EXCLUDE', + Ignore = 'IGNORE', + Include = 'INCLUDE' +} + +export type TriStateFilter = { + __typename?: 'TriStateFilter'; + default: TriState; + name: Scalars['String']['output']; +}; + +export type UpdateCategoriesInput = { + clientMutationId?: InputMaybe; + ids: Array; + patch: UpdateCategoryPatchInput; +}; + +export type UpdateCategoriesPayload = { + __typename?: 'UpdateCategoriesPayload'; + categories: Array; + clientMutationId?: Maybe; +}; + +export type UpdateCategoryInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; + patch: UpdateCategoryPatchInput; +}; + +export type UpdateCategoryMangaInput = { + categories: Array; + clientMutationId?: InputMaybe; +}; + +export type UpdateCategoryMangaPayload = { + __typename?: 'UpdateCategoryMangaPayload'; + clientMutationId?: Maybe; + updateStatus: UpdateStatus; +}; + +export type UpdateCategoryOrderInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; + position: Scalars['Int']['input']; +}; + +export type UpdateCategoryOrderPayload = { + __typename?: 'UpdateCategoryOrderPayload'; + categories: Array; + clientMutationId?: Maybe; +}; + +export type UpdateCategoryPatchInput = { + default?: InputMaybe; + includeInUpdate?: InputMaybe; + name?: InputMaybe; +}; + +export type UpdateCategoryPayload = { + __typename?: 'UpdateCategoryPayload'; + category: CategoryType; + clientMutationId?: Maybe; +}; + +export type UpdateChapterInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; + patch: UpdateChapterPatchInput; +}; + +export type UpdateChapterPatchInput = { + isBookmarked?: InputMaybe; + isRead?: InputMaybe; + lastPageRead?: InputMaybe; +}; + +export type UpdateChapterPayload = { + __typename?: 'UpdateChapterPayload'; + chapter: ChapterType; + clientMutationId?: Maybe; +}; + +export type UpdateChaptersInput = { + clientMutationId?: InputMaybe; + ids: Array; + patch: UpdateChapterPatchInput; +}; + +export type UpdateChaptersPayload = { + __typename?: 'UpdateChaptersPayload'; + chapters: Array; + clientMutationId?: Maybe; +}; + +export type UpdateExtensionInput = { + clientMutationId?: InputMaybe; + id: Scalars['String']['input']; + patch: UpdateExtensionPatchInput; +}; + +export type UpdateExtensionPatchInput = { + install?: InputMaybe; + uninstall?: InputMaybe; + update?: InputMaybe; +}; + +export type UpdateExtensionPayload = { + __typename?: 'UpdateExtensionPayload'; + clientMutationId?: Maybe; + extension: ExtensionType; +}; + +export type UpdateExtensionsInput = { + clientMutationId?: InputMaybe; + ids: Array; + patch: UpdateExtensionPatchInput; +}; + +export type UpdateExtensionsPayload = { + __typename?: 'UpdateExtensionsPayload'; + clientMutationId?: Maybe; + extensions: Array; +}; + +export type UpdateLibraryMangaInput = { + clientMutationId?: InputMaybe; +}; + +export type UpdateLibraryMangaPayload = { + __typename?: 'UpdateLibraryMangaPayload'; + clientMutationId?: Maybe; + updateStatus: UpdateStatus; +}; + +export type UpdateMangaCategoriesInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; + patch: UpdateMangaCategoriesPatchInput; +}; + +export type UpdateMangaCategoriesPatchInput = { + addToCategories?: InputMaybe>; + clearCategories?: InputMaybe; + removeFromCategories?: InputMaybe>; +}; + +export type UpdateMangaCategoriesPayload = { + __typename?: 'UpdateMangaCategoriesPayload'; + clientMutationId?: Maybe; + manga: MangaType; +}; + +export type UpdateMangaInput = { + clientMutationId?: InputMaybe; + id: Scalars['Int']['input']; + patch: UpdateMangaPatchInput; +}; + +export type UpdateMangaPatchInput = { + inLibrary?: InputMaybe; +}; + +export type UpdateMangaPayload = { + __typename?: 'UpdateMangaPayload'; + clientMutationId?: Maybe; + manga: MangaType; +}; + +export type UpdateMangasCategoriesInput = { + clientMutationId?: InputMaybe; + ids: Array; + patch: UpdateMangaCategoriesPatchInput; +}; + +export type UpdateMangasCategoriesPayload = { + __typename?: 'UpdateMangasCategoriesPayload'; + clientMutationId?: Maybe; + mangas: Array; +}; + +export type UpdateMangasInput = { + clientMutationId?: InputMaybe; + ids: Array; + patch: UpdateMangaPatchInput; +}; + +export type UpdateMangasPayload = { + __typename?: 'UpdateMangasPayload'; + clientMutationId?: Maybe; + mangas: Array; +}; + +export type UpdateSourcePreferenceInput = { + change: SourcePreferenceChangeInput; + clientMutationId?: InputMaybe; + source: Scalars['LongString']['input']; +}; + +export type UpdateSourcePreferencePayload = { + __typename?: 'UpdateSourcePreferencePayload'; + clientMutationId?: Maybe; + preferences: Array; + source: SourceType; +}; + +export enum UpdateState { + Downloading = 'DOWNLOADING', + Error = 'ERROR', + Finished = 'FINISHED', + Stopped = 'STOPPED' +} + +export type UpdateStatus = { + __typename?: 'UpdateStatus'; + completeJobs: UpdateStatusType; + failedJobs: UpdateStatusType; + isRunning: Scalars['Boolean']['output']; + pendingJobs: UpdateStatusType; + runningJobs: UpdateStatusType; + skippedCategories: UpdateStatusCategoryType; + skippedJobs: UpdateStatusType; + updatingCategories: UpdateStatusCategoryType; +}; + +export type UpdateStatusCategoryType = { + __typename?: 'UpdateStatusCategoryType'; + categories: CategoryNodeList; +}; + +export type UpdateStatusType = { + __typename?: 'UpdateStatusType'; + mangas: MangaNodeList; +}; + +export type UpdateStopInput = { + clientMutationId?: InputMaybe; +}; + +export type UpdateStopPayload = { + __typename?: 'UpdateStopPayload'; + clientMutationId?: Maybe; +}; + +export type ValidateBackupInput = { + backup: Scalars['Upload']['input']; +}; + +export type ValidateBackupResult = { + __typename?: 'ValidateBackupResult'; + missingSources: Array; +}; + +export type ValidateBackupSource = { + __typename?: 'ValidateBackupSource'; + id: Scalars['LongString']['output']; + name: Scalars['String']['output']; +}; + +export enum WebUiChannel { + Bundled = 'BUNDLED', + Preview = 'PREVIEW', + Stable = 'STABLE' +} + +export enum WebUiFlavor { + Custom = 'CUSTOM', + Webui = 'WEBUI' +} + +export enum WebUiInterface { + Browser = 'BROWSER', + Electron = 'ELECTRON' +} + +export type WebUiUpdateInfo = { + __typename?: 'WebUIUpdateInfo'; + channel: Scalars['String']['output']; + tag: Scalars['String']['output']; + updateAvailable: Scalars['Boolean']['output']; +}; + +export type WebUiUpdateInput = { + clientMutationId?: InputMaybe; +}; + +export type WebUiUpdatePayload = { + __typename?: 'WebUIUpdatePayload'; + clientMutationId?: Maybe; + updateStatus: WebUiUpdateStatus; +}; + +export type WebUiUpdateStatus = { + __typename?: 'WebUIUpdateStatus'; + info: WebUiUpdateInfo; + progress: Scalars['Int']['output']; + state: UpdateState; +}; + +export type PageInfoFragment = { __typename?: 'PageInfo', endCursor?: any | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: any | null }; + +export type GlobalMetadataFragment = { __typename?: 'GlobalMetaType', key: string, value: string }; + +export type FullCategoryFieldsFragment = { __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }; + +export type PartialSourceFieldsFragment = { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean }; + +export type FullSourceFieldsFragment = { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean, preferences: Array<{ __typename?: 'CheckBoxPreference', summary?: string | null, key: string, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle: string } | { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key: string, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null } | { __typename?: 'ListPreference', summary?: string | null, key: string, entryValues: Array, entries: Array, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null } | { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key: string, entryValues: Array, entries: Array, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array | null, MultiSelectListPreferenceCurrentValue?: Array | null } | { __typename?: 'SwitchPreference', summary?: string | null, key: string, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle: string }>, filters: Array<{ __typename?: 'CheckBoxFilter', name: string, type: 'CheckBoxFilter', CheckBoxFilterDefault: boolean } | { __typename?: 'GroupFilter', name: string, type: 'GroupFilter', filters: Array<{ __typename?: 'CheckBoxFilter', name: string, type: 'CheckBoxFilter', CheckBoxFilterDefault: boolean } | { __typename?: 'GroupFilter' } | { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' } | { __typename?: 'SelectFilter', name: string, values: Array, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', name: string, values: Array, type: 'SortFilter', SorSortFilterDefault?: { __typename?: 'SortSelection', ascending: boolean, index: number } | null } | { __typename?: 'TextFilter', name: string, type: 'TextFilter', TextFilterDefault: string } | { __typename?: 'TriStateFilter', name: string, type: 'TriStateFilter', TriStateFilterDefault: TriState }> } | { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' } | { __typename?: 'SelectFilter', values: Array, name: string, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', values: Array, name: string, type: 'SortFilter', SortFilterDefault?: { __typename?: 'SortSelection', ascending: boolean, index: number } | null } | { __typename?: 'TextFilter', name: string, type: 'TextFilter', TextFilterDefault: string } | { __typename?: 'TriStateFilter', name: string, type: 'TriStateFilter', TriStateFilterDefault: TriState }> }; + +export type BaseMangaFieldsFragment = { __typename?: 'MangaType', artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }; + +export type PartialMangaFieldsFragment = { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }; + +export type FullChapterFieldsFragment = { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> }; + +export type FullMangaFieldsFragment = { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }; + +export type FullExtensionFieldsFragment = { __typename?: 'ExtensionType', apkName: string, hasUpdate: boolean, iconUrl: string, isInstalled: boolean, isNsfw: boolean, isObsolete: boolean, lang: string, name: string, pkgName: string, versionCode: number, versionName: string }; + +export type FullDownloadStatusFragment = { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> }; + +export type PartialUpdaterStatusFragment = { __typename?: 'UpdateStatus', isRunning: boolean }; + +export type FullUpdaterStatusFragment = { __typename?: 'UpdateStatus', isRunning: boolean, completeJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, failedJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, pendingJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, runningJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, skippedJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, updatingCategories: { __typename?: 'UpdateStatusCategoryType', categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } }, skippedCategories: { __typename?: 'UpdateStatusCategoryType', categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } } }; + +export type WebuiUpdateInfoFragment = { __typename?: 'WebUIUpdateInfo', channel: string, tag: string, updateAvailable: boolean }; + +export type WebuiUpdateStatusFragment = { __typename?: 'WebUIUpdateStatus', progress: number, state: UpdateState, info: { __typename?: 'WebUIUpdateInfo', channel: string, tag: string, updateAvailable: boolean } }; + +export type ServerSettingsFragment = { __typename?: 'SettingsType', autoDownloadNewChapters: boolean, backupInterval: number, backupPath: string, backupTTL: number, backupTime: string, basicAuthEnabled: boolean, basicAuthPassword: string, basicAuthUsername: string, debugLogsEnabled: boolean, downloadAsCbz: boolean, downloadsPath: string, electronPath: string, excludeCompleted: boolean, excludeNotStarted: boolean, excludeUnreadChapters: boolean, globalUpdateInterval: number, initialOpenInBrowserEnabled: boolean, ip: string, localSourcePath: string, maxSourcesInParallel: number, port: number, socksProxyEnabled: boolean, socksProxyHost: string, socksProxyPort: string, systemTrayEnabled: boolean, webUIChannel: WebUiChannel, webUIFlavor: WebUiFlavor, webUIInterface: WebUiInterface, webUIUpdateCheckInterval: number }; + +export type CreateBackupMutationVariables = Exact<{ + input: CreateBackupInput; +}>; + + +export type CreateBackupMutation = { __typename?: 'Mutation', createBackup: { __typename?: 'CreateBackupPayload', clientMutationId?: string | null, url: string } }; + +export type RestoreBackupMutationVariables = Exact<{ + input: RestoreBackupInput; +}>; + + +export type RestoreBackupMutation = { __typename?: 'Mutation', restoreBackup: { __typename?: 'RestoreBackupPayload', clientMutationId?: string | null, status: { __typename?: 'BackupRestoreStatus', mangaProgress: number, state: BackupRestoreState, totalManga: number } } }; + +export type CreateCategoryMutationVariables = Exact<{ + input: CreateCategoryInput; +}>; + + +export type CreateCategoryMutation = { __typename?: 'Mutation', createCategory: { __typename?: 'CreateCategoryPayload', clientMutationId?: string | null, category: { __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } } } }; + +export type DeleteCategoryMutationVariables = Exact<{ + input: DeleteCategoryInput; +}>; + + +export type DeleteCategoryMutation = { __typename?: 'Mutation', deleteCategory: { __typename?: 'DeleteCategoryPayload', clientMutationId?: string | null, category?: { __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } } | null } }; + +export type DeleteCategoryMetadataMutationVariables = Exact<{ + input: DeleteCategoryMetaInput; +}>; + + +export type DeleteCategoryMetadataMutation = { __typename?: 'Mutation', deleteCategoryMeta: { __typename?: 'DeleteCategoryMetaPayload', clientMutationId?: string | null, meta?: { __typename?: 'CategoryMetaType', key: string, value: string, category: { __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } } } | null, category: { __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } } } }; + +export type SetCategoryMetadataMutationVariables = Exact<{ + input: SetCategoryMetaInput; +}>; + + +export type SetCategoryMetadataMutation = { __typename?: 'Mutation', setCategoryMeta: { __typename?: 'SetCategoryMetaPayload', clientMutationId?: string | null, meta: { __typename?: 'CategoryMetaType', key: string, value: string, category: { __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } } } } }; + +export type UpdateCategoryMutationVariables = Exact<{ + input: UpdateCategoryInput; +}>; + + +export type UpdateCategoryMutation = { __typename?: 'Mutation', updateCategory: { __typename?: 'UpdateCategoryPayload', clientMutationId?: string | null, category: { __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } } } }; + +export type UpdateCategoriesMutationVariables = Exact<{ + input: UpdateCategoriesInput; +}>; + + +export type UpdateCategoriesMutation = { __typename?: 'Mutation', updateCategories: { __typename?: 'UpdateCategoriesPayload', clientMutationId?: string | null, categories: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } }; + +export type UpdateCategoryOrderMutationVariables = Exact<{ + input: UpdateCategoryOrderInput; +}>; + + +export type UpdateCategoryOrderMutation = { __typename?: 'Mutation', updateCategoryOrder: { __typename?: 'UpdateCategoryOrderPayload', clientMutationId?: string | null, categories: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } }; + +export type DeleteChapterMetadataMutationVariables = Exact<{ + input: DeleteChapterMetaInput; +}>; + + +export type DeleteChapterMetadataMutation = { __typename?: 'Mutation', deleteChapterMeta: { __typename?: 'DeleteChapterMetaPayload', clientMutationId?: string | null, meta?: { __typename?: 'ChapterMetaType', key: string, value: string, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } } | null, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } } }; + +export type GetChapterPagesFetchMutationVariables = Exact<{ + input: FetchChapterPagesInput; +}>; + + +export type GetChapterPagesFetchMutation = { __typename?: 'Mutation', fetchChapterPages: { __typename?: 'FetchChapterPagesPayload', clientMutationId?: string | null, pages: Array, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } } }; + +export type GetMangaChaptersFetchMutationVariables = Exact<{ + input: FetchChaptersInput; +}>; + + +export type GetMangaChaptersFetchMutation = { __typename?: 'Mutation', fetchChapters: { __typename?: 'FetchChaptersPayload', clientMutationId?: string | null, chapters: Array<{ __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> }> } }; + +export type SetChapterMetadataMutationVariables = Exact<{ + input: SetChapterMetaInput; +}>; + + +export type SetChapterMetadataMutation = { __typename?: 'Mutation', setChapterMeta: { __typename?: 'SetChapterMetaPayload', clientMutationId?: string | null, meta: { __typename?: 'ChapterMetaType', key: string, value: string, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } } } }; + +export type UpdateChapterMutationVariables = Exact<{ + input: UpdateChapterInput; +}>; + + +export type UpdateChapterMutation = { __typename?: 'Mutation', updateChapter: { __typename?: 'UpdateChapterPayload', clientMutationId?: string | null, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } } }; + +export type UpdateChaptersMutationVariables = Exact<{ + input: UpdateChaptersInput; +}>; + + +export type UpdateChaptersMutation = { __typename?: 'Mutation', updateChapters: { __typename?: 'UpdateChaptersPayload', clientMutationId?: string | null, chapters: Array<{ __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> }> } }; + +export type ClearDownloaderMutationVariables = Exact<{ + input?: InputMaybe; +}>; + + +export type ClearDownloaderMutation = { __typename?: 'Mutation', clearDownloader: { __typename?: 'ClearDownloaderPayload', clientMutationId?: string | null, downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } } }; + +export type DeleteDownloadedChapterMutationVariables = Exact<{ + input: DeleteDownloadedChapterInput; +}>; + + +export type DeleteDownloadedChapterMutation = { __typename?: 'Mutation', deleteDownloadedChapter: { __typename?: 'DeleteDownloadedChapterPayload', clientMutationId?: string | null, chapters: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } } }; + +export type DeleteDownloadedChaptersMutationVariables = Exact<{ + input: DeleteDownloadedChaptersInput; +}>; + + +export type DeleteDownloadedChaptersMutation = { __typename?: 'Mutation', deleteDownloadedChapters: { __typename?: 'DeleteDownloadedChaptersPayload', clientMutationId?: string | null, chapters: Array<{ __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> }> } }; + +export type DequeueChapterDownloadMutationVariables = Exact<{ + input: DequeueChapterDownloadInput; +}>; + + +export type DequeueChapterDownloadMutation = { __typename?: 'Mutation', dequeueChapterDownload: { __typename?: 'DequeueChapterDownloadPayload', clientMutationId?: string | null, downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } } }; + +export type DequeueChapterDownloadsMutationVariables = Exact<{ + input: DequeueChapterDownloadsInput; +}>; + + +export type DequeueChapterDownloadsMutation = { __typename?: 'Mutation', dequeueChapterDownloads: { __typename?: 'DequeueChapterDownloadsPayload', clientMutationId?: string | null, downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } } }; + +export type EnqueueChapterDownloadMutationVariables = Exact<{ + input: EnqueueChapterDownloadInput; +}>; + + +export type EnqueueChapterDownloadMutation = { __typename?: 'Mutation', enqueueChapterDownload: { __typename?: 'EnqueueChapterDownloadPayload', clientMutationId?: string | null, downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } } }; + +export type EnqueueChapterDownloadsMutationVariables = Exact<{ + input: EnqueueChapterDownloadsInput; +}>; + + +export type EnqueueChapterDownloadsMutation = { __typename?: 'Mutation', enqueueChapterDownloads: { __typename?: 'EnqueueChapterDownloadsPayload', clientMutationId?: string | null, downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } } }; + +export type ReorderChapterDownloadMutationVariables = Exact<{ + input: ReorderChapterDownloadInput; +}>; + + +export type ReorderChapterDownloadMutation = { __typename?: 'Mutation', reorderChapterDownload: { __typename?: 'ReorderChapterDownloadPayload', clientMutationId?: string | null, downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } } }; + +export type StartDownloaderMutationVariables = Exact<{ + input?: InputMaybe; +}>; + + +export type StartDownloaderMutation = { __typename?: 'Mutation', startDownloader: { __typename?: 'StartDownloaderPayload', clientMutationId?: string | null, downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } } }; + +export type StopDownloaderMutationVariables = Exact<{ + input?: InputMaybe; +}>; + + +export type StopDownloaderMutation = { __typename?: 'Mutation', stopDownloader: { __typename?: 'StopDownloaderPayload', clientMutationId?: string | null, downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } } }; + +export type GetExtensionsFetchMutationVariables = Exact<{ + input?: InputMaybe; +}>; + + +export type GetExtensionsFetchMutation = { __typename?: 'Mutation', fetchExtensions: { __typename?: 'FetchExtensionsPayload', clientMutationId?: string | null, extensions: Array<{ __typename?: 'ExtensionType', apkName: string, hasUpdate: boolean, iconUrl: string, isInstalled: boolean, isNsfw: boolean, isObsolete: boolean, lang: string, name: string, pkgName: string, versionCode: number, versionName: string }> } }; + +export type UpdateExtensionMutationVariables = Exact<{ + input: UpdateExtensionInput; +}>; + + +export type UpdateExtensionMutation = { __typename?: 'Mutation', updateExtension: { __typename?: 'UpdateExtensionPayload', clientMutationId?: string | null, extension: { __typename?: 'ExtensionType', apkName: string, hasUpdate: boolean, iconUrl: string, isInstalled: boolean, isNsfw: boolean, isObsolete: boolean, lang: string, name: string, pkgName: string, versionCode: number, versionName: string } } }; + +export type UpdateExtensionsMutationVariables = Exact<{ + input: UpdateExtensionsInput; +}>; + + +export type UpdateExtensionsMutation = { __typename?: 'Mutation', updateExtensions: { __typename?: 'UpdateExtensionsPayload', clientMutationId?: string | null, extensions: Array<{ __typename?: 'ExtensionType', apkName: string, hasUpdate: boolean, iconUrl: string, isInstalled: boolean, isNsfw: boolean, isObsolete: boolean, lang: string, name: string, pkgName: string, versionCode: number, versionName: string }> } }; + +export type InstallExternalExtensionMutationVariables = Exact<{ + file: Scalars['Upload']['input']; +}>; + + +export type InstallExternalExtensionMutation = { __typename?: 'Mutation', installExternalExtension: { __typename?: 'InstallExternalExtensionPayload', clientMutationId?: string | null, extension: { __typename?: 'ExtensionType', apkName: string, hasUpdate: boolean, iconUrl: string, isInstalled: boolean, isNsfw: boolean, isObsolete: boolean, lang: string, name: string, pkgName: string, versionCode: number, versionName: string } } }; + +export type DeleteGlobalMetadataMutationVariables = Exact<{ + input: DeleteGlobalMetaInput; +}>; + + +export type DeleteGlobalMetadataMutation = { __typename?: 'Mutation', deleteGlobalMeta: { __typename?: 'DeleteGlobalMetaPayload', clientMutationId?: string | null, meta?: { __typename?: 'GlobalMetaType', key: string, value: string } | null } }; + +export type SetGlobalMetadataMutationVariables = Exact<{ + input: SetGlobalMetaInput; +}>; + + +export type SetGlobalMetadataMutation = { __typename?: 'Mutation', setGlobalMeta: { __typename?: 'SetGlobalMetaPayload', clientMutationId?: string | null, meta: { __typename?: 'GlobalMetaType', key: string, value: string } } }; + +export type DeleteMangaMetadataMutationVariables = Exact<{ + input: DeleteMangaMetaInput; +}>; + + +export type DeleteMangaMetadataMutation = { __typename?: 'Mutation', deleteMangaMeta: { __typename?: 'DeleteMangaMetaPayload', clientMutationId?: string | null, meta?: { __typename?: 'MangaMetaType', key: string, value: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null } } | null, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null } } }; + +export type GetMangaFetchMutationVariables = Exact<{ + input: FetchMangaInput; +}>; + + +export type GetMangaFetchMutation = { __typename?: 'Mutation', fetchManga: { __typename?: 'FetchMangaPayload', clientMutationId?: string | null, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null } } }; + +export type SetMangaMetadataMutationVariables = Exact<{ + input: SetMangaMetaInput; +}>; + + +export type SetMangaMetadataMutation = { __typename?: 'Mutation', setMangaMeta: { __typename?: 'SetMangaMetaPayload', clientMutationId?: string | null, meta: { __typename?: 'MangaMetaType', key: string, value: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null } } } }; + +export type UpdateMangaMutationVariables = Exact<{ + input: UpdateMangaInput; +}>; + + +export type UpdateMangaMutation = { __typename?: 'Mutation', updateManga: { __typename?: 'UpdateMangaPayload', clientMutationId?: string | null, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null } } }; + +export type UpdateMangaCategoriesMutationVariables = Exact<{ + input: UpdateMangaCategoriesInput; +}>; + + +export type UpdateMangaCategoriesMutation = { __typename?: 'Mutation', updateMangaCategories: { __typename?: 'UpdateMangaCategoriesPayload', clientMutationId?: string | null, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null } } }; + +export type UpdateMangasMutationVariables = Exact<{ + input: UpdateMangasInput; +}>; + + +export type UpdateMangasMutation = { __typename?: 'Mutation', updateMangas: { __typename?: 'UpdateMangasPayload', clientMutationId?: string | null, mangas: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }; + +export type UpdateMangasCategoriesMutationVariables = Exact<{ + input: UpdateMangasCategoriesInput; +}>; + + +export type UpdateMangasCategoriesMutation = { __typename?: 'Mutation', updateMangasCategories: { __typename?: 'UpdateMangasCategoriesPayload', clientMutationId?: string | null, mangas: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }; + +export type UpdateWebuiMutationVariables = Exact<{ + input?: InputMaybe; +}>; + + +export type UpdateWebuiMutation = { __typename?: 'Mutation', updateWebUI: { __typename?: 'WebUIUpdatePayload', clientMutationId?: string | null, updateStatus: { __typename?: 'WebUIUpdateStatus', progress: number, state: UpdateState, info: { __typename?: 'WebUIUpdateInfo', channel: string, tag: string, updateAvailable: boolean } } } }; + +export type ResetServerSettingsMutationVariables = Exact<{ + input: ResetSettingsInput; +}>; + + +export type ResetServerSettingsMutation = { __typename?: 'Mutation', resetSettings: { __typename?: 'ResetSettingsPayload', clientMutationId?: string | null, settings: { __typename?: 'SettingsType', autoDownloadNewChapters: boolean, backupInterval: number, backupPath: string, backupTTL: number, backupTime: string, basicAuthEnabled: boolean, basicAuthPassword: string, basicAuthUsername: string, debugLogsEnabled: boolean, downloadAsCbz: boolean, downloadsPath: string, electronPath: string, excludeCompleted: boolean, excludeNotStarted: boolean, excludeUnreadChapters: boolean, globalUpdateInterval: number, initialOpenInBrowserEnabled: boolean, ip: string, localSourcePath: string, maxSourcesInParallel: number, port: number, socksProxyEnabled: boolean, socksProxyHost: string, socksProxyPort: string, systemTrayEnabled: boolean, webUIChannel: WebUiChannel, webUIFlavor: WebUiFlavor, webUIInterface: WebUiInterface, webUIUpdateCheckInterval: number } } }; + +export type UpdateServerSettingsMutationVariables = Exact<{ + input: SetSettingsInput; +}>; + + +export type UpdateServerSettingsMutation = { __typename?: 'Mutation', setSettings: { __typename?: 'SetSettingsPayload', clientMutationId?: string | null, settings: { __typename?: 'SettingsType', autoDownloadNewChapters: boolean, backupInterval: number, backupPath: string, backupTTL: number, backupTime: string, basicAuthEnabled: boolean, basicAuthPassword: string, basicAuthUsername: string, debugLogsEnabled: boolean, downloadAsCbz: boolean, downloadsPath: string, electronPath: string, excludeCompleted: boolean, excludeNotStarted: boolean, excludeUnreadChapters: boolean, globalUpdateInterval: number, initialOpenInBrowserEnabled: boolean, ip: string, localSourcePath: string, maxSourcesInParallel: number, port: number, socksProxyEnabled: boolean, socksProxyHost: string, socksProxyPort: string, systemTrayEnabled: boolean, webUIChannel: WebUiChannel, webUIFlavor: WebUiFlavor, webUIInterface: WebUiInterface, webUIUpdateCheckInterval: number } } }; + +export type GetSourceMangasFetchMutationVariables = Exact<{ + input: FetchSourceMangaInput; +}>; + + +export type GetSourceMangasFetchMutation = { __typename?: 'Mutation', fetchSourceManga: { __typename?: 'FetchSourceMangaPayload', clientMutationId?: string | null, hasNextPage: boolean, mangas: Array<{ __typename?: 'MangaType', artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }; + +export type UpdateSourcePreferencesMutationVariables = Exact<{ + input: UpdateSourcePreferenceInput; +}>; + + +export type UpdateSourcePreferencesMutation = { __typename?: 'Mutation', updateSourcePreference: { __typename?: 'UpdateSourcePreferencePayload', clientMutationId?: string | null, source: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean, preferences: Array<{ __typename?: 'CheckBoxPreference', summary?: string | null, key: string, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle: string } | { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key: string, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null } | { __typename?: 'ListPreference', summary?: string | null, key: string, entryValues: Array, entries: Array, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null } | { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key: string, entryValues: Array, entries: Array, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array | null, MultiSelectListPreferenceCurrentValue?: Array | null } | { __typename?: 'SwitchPreference', summary?: string | null, key: string, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle: string }>, filters: Array<{ __typename?: 'CheckBoxFilter', name: string, type: 'CheckBoxFilter', CheckBoxFilterDefault: boolean } | { __typename?: 'GroupFilter', name: string, type: 'GroupFilter', filters: Array<{ __typename?: 'CheckBoxFilter', name: string, type: 'CheckBoxFilter', CheckBoxFilterDefault: boolean } | { __typename?: 'GroupFilter' } | { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' } | { __typename?: 'SelectFilter', name: string, values: Array, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', name: string, values: Array, type: 'SortFilter', SorSortFilterDefault?: { __typename?: 'SortSelection', ascending: boolean, index: number } | null } | { __typename?: 'TextFilter', name: string, type: 'TextFilter', TextFilterDefault: string } | { __typename?: 'TriStateFilter', name: string, type: 'TriStateFilter', TriStateFilterDefault: TriState }> } | { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' } | { __typename?: 'SelectFilter', values: Array, name: string, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', values: Array, name: string, type: 'SortFilter', SortFilterDefault?: { __typename?: 'SortSelection', ascending: boolean, index: number } | null } | { __typename?: 'TextFilter', name: string, type: 'TextFilter', TextFilterDefault: string } | { __typename?: 'TriStateFilter', name: string, type: 'TriStateFilter', TriStateFilterDefault: TriState }> } } }; + +export type UpdateCategoryMangasMutationVariables = Exact<{ + input: UpdateCategoryMangaInput; +}>; + + +export type UpdateCategoryMangasMutation = { __typename?: 'Mutation', updateCategoryManga: { __typename?: 'UpdateCategoryMangaPayload', clientMutationId?: string | null, updateStatus: { __typename?: 'UpdateStatus', isRunning: boolean } } }; + +export type UpdateLibraryMangasMutationVariables = Exact<{ + input?: InputMaybe; +}>; + + +export type UpdateLibraryMangasMutation = { __typename?: 'Mutation', updateLibraryManga: { __typename?: 'UpdateLibraryMangaPayload', clientMutationId?: string | null, updateStatus: { __typename?: 'UpdateStatus', isRunning: boolean } } }; + +export type StopUpdaterMutationVariables = Exact<{ + input?: InputMaybe; +}>; + + +export type StopUpdaterMutation = { __typename?: 'Mutation', updateStop: { __typename?: 'UpdateStopPayload', clientMutationId?: string | null } }; + +export type ValidateBackupQueryVariables = Exact<{ + input: ValidateBackupInput; +}>; + + +export type ValidateBackupQuery = { __typename?: 'Query', validateBackup: { __typename?: 'ValidateBackupResult', missingSources: Array<{ __typename?: 'ValidateBackupSource', id: any, name: string }> } }; + +export type GetRestoreStatusQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetRestoreStatusQuery = { __typename?: 'Query', restoreStatus: { __typename?: 'BackupRestoreStatus', mangaProgress: number, state: BackupRestoreState, totalManga: number } }; + +export type GetCategoriesQueryVariables = Exact<{ + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}>; + + +export type GetCategoriesQuery = { __typename?: 'Query', categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }>, pageInfo: { __typename?: 'PageInfo', endCursor?: any | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: any | null } } }; + +export type GetCategoryQueryVariables = Exact<{ + id: Scalars['Int']['input']; +}>; + + +export type GetCategoryQuery = { __typename?: 'Query', category: { __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } } }; + +export type GetCategoryMangasQueryVariables = Exact<{ + id: Scalars['Int']['input']; +}>; + + +export type GetCategoryMangasQuery = { __typename?: 'Query', category: { __typename?: 'CategoryType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }>, pageInfo: { __typename?: 'PageInfo', endCursor?: any | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: any | null } } } }; + +export type GetChapterQueryVariables = Exact<{ + id: Scalars['Int']['input']; +}>; + + +export type GetChapterQuery = { __typename?: 'Query', chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }; + +export type GetChaptersQueryVariables = Exact<{ + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}>; + + +export type GetChaptersQuery = { __typename?: 'Query', chapters: { __typename?: 'ChapterNodeList', totalCount: number, nodes: Array<{ __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> }>, pageInfo: { __typename?: 'PageInfo', endCursor?: any | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: any | null } } }; + +export type GetDownloadStatusQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetDownloadStatusQuery = { __typename?: 'Query', downloadStatus: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } }; + +export type GetExtensionQueryVariables = Exact<{ + pkgName: Scalars['String']['input']; +}>; + + +export type GetExtensionQuery = { __typename?: 'Query', extension: { __typename?: 'ExtensionType', apkName: string, hasUpdate: boolean, iconUrl: string, isInstalled: boolean, isNsfw: boolean, isObsolete: boolean, lang: string, name: string, pkgName: string, versionCode: number, versionName: string } }; + +export type GetExtensionsQueryVariables = Exact<{ + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}>; + + +export type GetExtensionsQuery = { __typename?: 'Query', extensions: { __typename?: 'ExtensionNodeList', totalCount: number, nodes: Array<{ __typename?: 'ExtensionType', apkName: string, hasUpdate: boolean, iconUrl: string, isInstalled: boolean, isNsfw: boolean, isObsolete: boolean, lang: string, name: string, pkgName: string, versionCode: number, versionName: string }>, pageInfo: { __typename?: 'PageInfo', endCursor?: any | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: any | null } } }; + +export type GetGlobalMetadataQueryVariables = Exact<{ + key: Scalars['String']['input']; +}>; + + +export type GetGlobalMetadataQuery = { __typename?: 'Query', meta: { __typename?: 'GlobalMetaType', key: string, value: string } }; + +export type GetGlobalMetadatasQueryVariables = Exact<{ + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}>; + + +export type GetGlobalMetadatasQuery = { __typename?: 'Query', metas: { __typename?: 'GlobalMetaNodeList', totalCount: number, nodes: Array<{ __typename?: 'GlobalMetaType', key: string, value: string }>, pageInfo: { __typename?: 'PageInfo', endCursor?: any | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: any | null } } }; + +export type GetMangaQueryVariables = Exact<{ + id: Scalars['Int']['input']; +}>; + + +export type GetMangaQuery = { __typename?: 'Query', manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null } }; + +export type GetMangasQueryVariables = Exact<{ + after?: InputMaybe; + before?: InputMaybe; + condition?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe; + orderByType?: InputMaybe; +}>; + + +export type GetMangasQuery = { __typename?: 'Query', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }>, pageInfo: { __typename?: 'PageInfo', endCursor?: any | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: any | null } } }; + +export type GetAboutQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetAboutQuery = { __typename?: 'Query', about: { __typename?: 'AboutPayload', buildTime: any, buildType: string, discord: string, github: string, name: string, revision: string, version: string } }; + +export type CheckForServerUpdatesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type CheckForServerUpdatesQuery = { __typename?: 'Query', checkForServerUpdates: Array<{ __typename?: 'CheckForServerUpdatesPayload', channel: string, tag: string, url: string }> }; + +export type CheckForWebuiUpdateQueryVariables = Exact<{ [key: string]: never; }>; + + +export type CheckForWebuiUpdateQuery = { __typename?: 'Query', checkForWebUIUpdate: { __typename?: 'WebUIUpdateInfo', channel: string, tag: string, updateAvailable: boolean } }; + +export type GetWebuiUpdateStatusQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetWebuiUpdateStatusQuery = { __typename?: 'Query', getWebUIUpdateStatus: { __typename?: 'WebUIUpdateStatus', progress: number, state: UpdateState, info: { __typename?: 'WebUIUpdateInfo', channel: string, tag: string, updateAvailable: boolean } } }; + +export type GetServerSettingsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetServerSettingsQuery = { __typename?: 'Query', settings: { __typename?: 'SettingsType', autoDownloadNewChapters: boolean, backupInterval: number, backupPath: string, backupTTL: number, backupTime: string, basicAuthEnabled: boolean, basicAuthPassword: string, basicAuthUsername: string, debugLogsEnabled: boolean, downloadAsCbz: boolean, downloadsPath: string, electronPath: string, excludeCompleted: boolean, excludeNotStarted: boolean, excludeUnreadChapters: boolean, globalUpdateInterval: number, initialOpenInBrowserEnabled: boolean, ip: string, localSourcePath: string, maxSourcesInParallel: number, port: number, socksProxyEnabled: boolean, socksProxyHost: string, socksProxyPort: string, systemTrayEnabled: boolean, webUIChannel: WebUiChannel, webUIFlavor: WebUiFlavor, webUIInterface: WebUiInterface, webUIUpdateCheckInterval: number } }; + +export type GetSourceQueryVariables = Exact<{ + id: Scalars['LongString']['input']; +}>; + + +export type GetSourceQuery = { __typename?: 'Query', source: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean, preferences: Array<{ __typename?: 'CheckBoxPreference', summary?: string | null, key: string, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle: string } | { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key: string, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null } | { __typename?: 'ListPreference', summary?: string | null, key: string, entryValues: Array, entries: Array, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null } | { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key: string, entryValues: Array, entries: Array, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array | null, MultiSelectListPreferenceCurrentValue?: Array | null } | { __typename?: 'SwitchPreference', summary?: string | null, key: string, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle: string }>, filters: Array<{ __typename?: 'CheckBoxFilter', name: string, type: 'CheckBoxFilter', CheckBoxFilterDefault: boolean } | { __typename?: 'GroupFilter', name: string, type: 'GroupFilter', filters: Array<{ __typename?: 'CheckBoxFilter', name: string, type: 'CheckBoxFilter', CheckBoxFilterDefault: boolean } | { __typename?: 'GroupFilter' } | { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' } | { __typename?: 'SelectFilter', name: string, values: Array, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', name: string, values: Array, type: 'SortFilter', SorSortFilterDefault?: { __typename?: 'SortSelection', ascending: boolean, index: number } | null } | { __typename?: 'TextFilter', name: string, type: 'TextFilter', TextFilterDefault: string } | { __typename?: 'TriStateFilter', name: string, type: 'TriStateFilter', TriStateFilterDefault: TriState }> } | { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' } | { __typename?: 'SelectFilter', values: Array, name: string, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', values: Array, name: string, type: 'SortFilter', SortFilterDefault?: { __typename?: 'SortSelection', ascending: boolean, index: number } | null } | { __typename?: 'TextFilter', name: string, type: 'TextFilter', TextFilterDefault: string } | { __typename?: 'TriStateFilter', name: string, type: 'TriStateFilter', TriStateFilterDefault: TriState }> } }; + +export type GetSourcesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetSourcesQuery = { __typename?: 'Query', sources: { __typename?: 'SourceNodeList', nodes: Array<{ __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean }> } }; + +export type GetUpdateStatusQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetUpdateStatusQuery = { __typename?: 'Query', updateStatus: { __typename?: 'UpdateStatus', isRunning: boolean, completeJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, failedJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, pendingJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, runningJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, skippedJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, updatingCategories: { __typename?: 'UpdateStatusCategoryType', categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } }, skippedCategories: { __typename?: 'UpdateStatusCategoryType', categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } } } }; + +export type GetLastUpdateTimestampQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetLastUpdateTimestampQuery = { __typename?: 'Query', lastUpdateTimestamp: { __typename?: 'LastUpdateTimestampPayload', timestamp: any } }; + +export type DownloadStatusSubscriptionVariables = Exact<{ [key: string]: never; }>; + + +export type DownloadStatusSubscription = { __typename?: 'Subscription', downloadChanged: { __typename?: 'DownloadStatus', state: DownloaderState, queue: Array<{ __typename?: 'DownloadType', progress: number, state: DownloadState, tries: number, chapter: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } }> } }; + +export type WebuiUpdateSubscriptionVariables = Exact<{ [key: string]: never; }>; + + +export type WebuiUpdateSubscription = { __typename?: 'Subscription', webUIUpdateStatusChange: { __typename?: 'WebUIUpdateStatus', progress: number, state: UpdateState, info: { __typename?: 'WebUIUpdateInfo', channel: string, tag: string, updateAvailable: boolean } } }; + +export type UpdaterSubscriptionVariables = Exact<{ [key: string]: never; }>; + + +export type UpdaterSubscription = { __typename?: 'Subscription', updateStatusChanged: { __typename?: 'UpdateStatus', isRunning: boolean, completeJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, failedJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, pendingJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, runningJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, skippedJobs: { __typename?: 'UpdateStatusType', mangas: { __typename?: 'MangaNodeList', totalCount: number, nodes: Array<{ __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, lastReadChapter?: { __typename?: 'ChapterType', chapterNumber: number, fetchedAt: any, id: number, isBookmarked: boolean, isDownloaded: boolean, isRead: boolean, lastPageRead: number, lastReadAt: any, name: string, pageCount: number, realUrl?: string | null, scanlator?: string | null, sourceOrder: number, uploadDate: any, url: string, manga: { __typename?: 'MangaType', unreadCount: number, downloadCount: number, artist?: string | null, author?: string | null, chaptersLastFetchedAt?: any | null, description?: string | null, genre: Array, id: number, inLibrary: boolean, inLibraryAt: any, initialized: boolean, lastFetchedAt?: any | null, realUrl?: string | null, status: MangaStatus, thumbnailUrl?: string | null, title: string, url: string, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }, meta: Array<{ __typename?: 'ChapterMetaType', key: string, value: string }> } | null, categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> }, chapters: { __typename?: 'ChapterNodeList', totalCount: number }, meta: Array<{ __typename?: 'MangaMetaType', key: string, value: string }>, source?: { __typename?: 'SourceType', displayName: string, iconUrl: string, id: any, isConfigurable: boolean, isNsfw: boolean, lang: string, name: string, supportsLatest: boolean } | null }> } }, updatingCategories: { __typename?: 'UpdateStatusCategoryType', categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } }, skippedCategories: { __typename?: 'UpdateStatusCategoryType', categories: { __typename?: 'CategoryNodeList', totalCount: number, nodes: Array<{ __typename?: 'CategoryType', default: boolean, id: number, includeInUpdate: IncludeInUpdate, name: string, order: number, meta: Array<{ __typename?: 'CategoryMetaType', key: string, value: string }>, mangas: { __typename?: 'MangaNodeList', totalCount: number } }> } } } }; diff --git a/src/lib/graphql/graphql.config.yml b/src/lib/graphql/graphql.config.yml new file mode 100644 index 00000000..0c80f0d1 --- /dev/null +++ b/src/lib/graphql/graphql.config.yml @@ -0,0 +1,7 @@ +schema: schema.json # download the schema from the server and place it in "src/lib/graphql/" +documents: [ + 'src/lib/graphql/queries/**', + 'src/lib/graphql/mutations/**', + 'src/lib/graphql/subscriptions/**', + 'src/lib/graphql/Fragments.ts', +] \ No newline at end of file diff --git a/src/lib/graphql/mutations/BackupMutation.ts b/src/lib/graphql/mutations/BackupMutation.ts new file mode 100644 index 00000000..dc4c1d5a --- /dev/null +++ b/src/lib/graphql/mutations/BackupMutation.ts @@ -0,0 +1,31 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; + +export const CREATE_BACKUP = gql` + mutation CREATE_BACKUP($input: CreateBackupInput!) { + createBackup(input: $input) { + clientMutationId + url + } + } +`; + +export const RESTORE_BACKUP = gql` + mutation RESTORE_BACKUP($input: RestoreBackupInput!) { + restoreBackup(input: $input) { + clientMutationId + status { + mangaProgress + state + totalManga + } + } + } +`; diff --git a/src/lib/graphql/mutations/CategoryMutation.ts b/src/lib/graphql/mutations/CategoryMutation.ts new file mode 100644 index 00000000..4081829e --- /dev/null +++ b/src/lib/graphql/mutations/CategoryMutation.ts @@ -0,0 +1,105 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_CATEGORY_FIELDS } from '@/lib/graphql/Fragments'; + +export const CREATE_CATEGORY = gql` + ${FULL_CATEGORY_FIELDS} + mutation CREATE_CATEGORY($input: CreateCategoryInput!) { + createCategory(input: $input) { + clientMutationId + category { + ...FULL_CATEGORY_FIELDS + } + } + } +`; + +export const DELETE_CATEGORY = gql` + ${FULL_CATEGORY_FIELDS} + mutation DELETE_CATEGORY($input: DeleteCategoryInput!) { + deleteCategory(input: $input) { + clientMutationId + category { + ...FULL_CATEGORY_FIELDS + } + } + } +`; + +export const DELETE_CATEGORY_METADATA = gql` + ${FULL_CATEGORY_FIELDS} + mutation DELETE_CATEGORY_METADATA($input: DeleteCategoryMetaInput!) { + deleteCategoryMeta(input: $input) { + clientMutationId + meta { + key + value + category { + ...FULL_CATEGORY_FIELDS + } + } + category { + ...FULL_CATEGORY_FIELDS + } + } + } +`; + +export const SET_CATEGORY_METADATA = gql` + ${FULL_CATEGORY_FIELDS} + mutation SET_CATEGORY_METADATA($input: SetCategoryMetaInput!) { + setCategoryMeta(input: $input) { + clientMutationId + meta { + key + value + category { + ...FULL_CATEGORY_FIELDS + } + } + } + } +`; + +export const UPDATE_CATEGORY = gql` + ${FULL_CATEGORY_FIELDS} + mutation UPDATE_CATEGORY($input: UpdateCategoryInput!) { + updateCategory(input: $input) { + clientMutationId + category { + ...FULL_CATEGORY_FIELDS + } + } + } +`; + +export const UPDATE_CATEGORIES = gql` + ${FULL_CATEGORY_FIELDS} + mutation UPDATE_CATEGORIES($input: UpdateCategoriesInput!) { + updateCategories(input: $input) { + clientMutationId + categories { + ...FULL_CATEGORY_FIELDS + } + } + } +`; + +export const UPDATE_CATEGORY_ORDER = gql` + ${FULL_CATEGORY_FIELDS} + mutation UPDATE_CATEGORY_ORDER($input: UpdateCategoryOrderInput!) { + updateCategoryOrder(input: $input) { + clientMutationId + categories { + ...FULL_CATEGORY_FIELDS + } + } + } +`; diff --git a/src/lib/graphql/mutations/ChapterMutation.ts b/src/lib/graphql/mutations/ChapterMutation.ts new file mode 100644 index 00000000..ecf21292 --- /dev/null +++ b/src/lib/graphql/mutations/ChapterMutation.ts @@ -0,0 +1,96 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_CHAPTER_FIELDS } from '@/lib/graphql/Fragments'; + +export const DELETE_CHAPTER_METADATA = gql` + ${FULL_CHAPTER_FIELDS} + mutation DELETE_CHAPTER_METADATA($input: DeleteChapterMetaInput!) { + deleteChapterMeta(input: $input) { + clientMutationId + meta { + key + value + chapter { + ...FULL_CHAPTER_FIELDS + } + } + chapter { + ...FULL_CHAPTER_FIELDS + } + } + } +`; + +// makes the server fetch and return the pages of a chapter +export const GET_CHAPTER_PAGES_FETCH = gql` + ${FULL_CHAPTER_FIELDS} + mutation GET_CHAPTER_PAGES_FETCH($input: FetchChapterPagesInput!) { + fetchChapterPages(input: $input) { + clientMutationId + chapter { + ...FULL_CHAPTER_FIELDS + } + pages + } + } +`; + +// makes the server fetch and return the chapters of the manga +export const GET_MANGA_CHAPTERS_FETCH = gql` + ${FULL_CHAPTER_FIELDS} + mutation GET_MANGA_CHAPTERS_FETCH($input: FetchChaptersInput!) { + fetchChapters(input: $input) { + clientMutationId + chapters { + ...FULL_CHAPTER_FIELDS + } + } + } +`; + +export const SET_CHAPTER_METADATA = gql` + ${FULL_CHAPTER_FIELDS} + mutation SET_CHAPTER_METADATA($input: SetChapterMetaInput!) { + setChapterMeta(input: $input) { + clientMutationId + meta { + key + value + chapter { + ...FULL_CHAPTER_FIELDS + } + } + } + } +`; + +export const UPDATE_CHAPTER = gql` + ${FULL_CHAPTER_FIELDS} + mutation UPDATE_CHAPTER($input: UpdateChapterInput!) { + updateChapter(input: $input) { + clientMutationId + chapter { + ...FULL_CHAPTER_FIELDS + } + } + } +`; + +export const UPDATE_CHAPTERS = gql` + ${FULL_CHAPTER_FIELDS} + mutation UPDATE_CHAPTERS($input: UpdateChaptersInput!) { + updateChapters(input: $input) { + clientMutationId + chapters { + ...FULL_CHAPTER_FIELDS + } + } + } +`; diff --git a/src/lib/graphql/mutations/DownloaderMutation.ts b/src/lib/graphql/mutations/DownloaderMutation.ts new file mode 100644 index 00000000..1a8e31c5 --- /dev/null +++ b/src/lib/graphql/mutations/DownloaderMutation.ts @@ -0,0 +1,130 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_CHAPTER_FIELDS, FULL_DOWNLOAD_STATUS } from '@/lib/graphql/Fragments'; + +export const CLEAR_DOWNLOADER = gql` + ${FULL_DOWNLOAD_STATUS} + mutation CLEAR_DOWNLOADER($input: ClearDownloaderInput = {}) { + clearDownloader(input: $input) { + clientMutationId + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } + } +`; + +export const DELETE_DOWNLOADED_CHAPTER = gql` + ${FULL_CHAPTER_FIELDS} + mutation DELETE_DOWNLOADED_CHAPTER($input: DeleteDownloadedChapterInput!) { + deleteDownloadedChapter(input: $input) { + clientMutationId + chapters { + ...FULL_CHAPTER_FIELDS + } + } + } +`; + +export const DELETE_DOWNLOADED_CHAPTERS = gql` + ${FULL_CHAPTER_FIELDS} + mutation DELETE_DOWNLOADED_CHAPTERS($input: DeleteDownloadedChaptersInput!) { + deleteDownloadedChapters(input: $input) { + clientMutationId + chapters { + ...FULL_CHAPTER_FIELDS + } + } + } +`; + +export const DEQUEUE_CHAPTER_DOWNLOAD = gql` + ${FULL_DOWNLOAD_STATUS} + mutation DEQUEUE_CHAPTER_DOWNLOAD($input: DequeueChapterDownloadInput!) { + dequeueChapterDownload(input: $input) { + clientMutationId + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } + } +`; + +export const DEQUEUE_CHAPTER_DOWNLOADS = gql` + ${FULL_DOWNLOAD_STATUS} + mutation DEQUEUE_CHAPTER_DOWNLOADS($input: DequeueChapterDownloadsInput!) { + dequeueChapterDownloads(input: $input) { + clientMutationId + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } + } +`; + +export const ENQUEUE_CHAPTER_DOWNLOAD = gql` + ${FULL_DOWNLOAD_STATUS} + mutation ENQUEUE_CHAPTER_DOWNLOAD($input: EnqueueChapterDownloadInput!) { + enqueueChapterDownload(input: $input) { + clientMutationId + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } + } +`; + +export const ENQUEUE_CHAPTER_DOWNLOADS = gql` + ${FULL_DOWNLOAD_STATUS} + mutation ENQUEUE_CHAPTER_DOWNLOADS($input: EnqueueChapterDownloadsInput!) { + enqueueChapterDownloads(input: $input) { + clientMutationId + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } + } +`; + +export const REORDER_CHAPTER_DOWNLOAD = gql` + ${FULL_DOWNLOAD_STATUS} + mutation REORDER_CHAPTER_DOWNLOAD($input: ReorderChapterDownloadInput!) { + reorderChapterDownload(input: $input) { + clientMutationId + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } + } +`; + +export const START_DOWNLOADER = gql` + ${FULL_DOWNLOAD_STATUS} + mutation START_DOWNLOADER($input: StartDownloaderInput = {}) { + startDownloader(input: $input) { + clientMutationId + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } + } +`; + +export const STOP_DOWNLOADER = gql` + ${FULL_DOWNLOAD_STATUS} + mutation STOP_DOWNLOADER($input: StopDownloaderInput = {}) { + stopDownloader(input: $input) { + clientMutationId + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } + } +`; diff --git a/src/lib/graphql/mutations/ExtensionMutation.ts b/src/lib/graphql/mutations/ExtensionMutation.ts new file mode 100644 index 00000000..0277a255 --- /dev/null +++ b/src/lib/graphql/mutations/ExtensionMutation.ts @@ -0,0 +1,59 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_EXTENSION_FIELDS } from '@/lib/graphql/Fragments'; + +// makes the server fetch and return the latest extensions +export const GET_EXTENSIONS_FETCH = gql` + ${FULL_EXTENSION_FIELDS} + mutation GET_EXTENSIONS_FETCH($input: FetchExtensionsInput = {}) { + fetchExtensions(input: $input) { + clientMutationId + extensions { + ...FULL_EXTENSION_FIELDS + } + } + } +`; + +export const UPDATE_EXTENSION = gql` + ${FULL_EXTENSION_FIELDS} + mutation UPDATE_EXTENSION($input: UpdateExtensionInput!) { + updateExtension(input: $input) { + clientMutationId + extension { + ...FULL_EXTENSION_FIELDS + } + } + } +`; + +export const UPDATE_EXTENSIONS = gql` + ${FULL_EXTENSION_FIELDS} + mutation UPDATE_EXTENSIONS($input: UpdateExtensionsInput!) { + updateExtensions(input: $input) { + clientMutationId + extensions { + ...FULL_EXTENSION_FIELDS + } + } + } +`; + +export const INSTALL_EXTERNAL_EXTENSION = gql` + ${FULL_EXTENSION_FIELDS} + mutation INSTALL_EXTERNAL_EXTENSION($file: Upload!) { + installExternalExtension(input: { extensionFile: $file }) { + extension { + ...FULL_EXTENSION_FIELDS + } + clientMutationId + } + } +`; diff --git a/src/lib/graphql/mutations/GlobalMetadataMutation.ts b/src/lib/graphql/mutations/GlobalMetadataMutation.ts new file mode 100644 index 00000000..c02f72ba --- /dev/null +++ b/src/lib/graphql/mutations/GlobalMetadataMutation.ts @@ -0,0 +1,34 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { GLOBAL_METADATA } from '@/lib/graphql/Fragments'; + +export const DELETE_GLOBAL_METADATA = gql` + ${GLOBAL_METADATA} + mutation DELETE_GLOBAL_METADATA($input: DeleteGlobalMetaInput!) { + deleteGlobalMeta(input: $input) { + clientMutationId + meta { + ...GLOBAL_METADATA + } + } + } +`; + +export const SET_GLOBAL_METADATA = gql` + ${GLOBAL_METADATA} + mutation SET_GLOBAL_METADATA($input: SetGlobalMetaInput!) { + setGlobalMeta(input: $input) { + clientMutationId + meta { + ...GLOBAL_METADATA + } + } + } +`; diff --git a/src/lib/graphql/mutations/MangaMutation.ts b/src/lib/graphql/mutations/MangaMutation.ts new file mode 100644 index 00000000..8ff59d2c --- /dev/null +++ b/src/lib/graphql/mutations/MangaMutation.ts @@ -0,0 +1,106 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_MANGA_FIELDS } from '@/lib/graphql/Fragments'; + +export const DELETE_MANGA_METADATA = gql` + ${FULL_MANGA_FIELDS} + mutation DELETE_MANGA_METADATA($input: DeleteMangaMetaInput!) { + deleteMangaMeta(input: $input) { + clientMutationId + meta { + key + value + manga { + ...FULL_MANGA_FIELDS + } + } + manga { + ...FULL_MANGA_FIELDS + } + } + } +`; + +// makes the server fetch and return the manga +export const GET_MANGA_FETCH = gql` + ${FULL_MANGA_FIELDS} + mutation GET_MANGA_FETCH($input: FetchMangaInput!) { + fetchManga(input: $input) { + clientMutationId + manga { + ...FULL_MANGA_FIELDS + } + } + } +`; + +export const SET_MANGA_METADATA = gql` + ${FULL_MANGA_FIELDS} + mutation SET_MANGA_METADATA($input: SetMangaMetaInput!) { + setMangaMeta(input: $input) { + clientMutationId + meta { + key + value + manga { + ...FULL_MANGA_FIELDS + } + } + } + } +`; + +export const UPDATE_MANGA = gql` + ${FULL_MANGA_FIELDS} + mutation UPDATE_MANGA($input: UpdateMangaInput!) { + updateManga(input: $input) { + clientMutationId + manga { + ...FULL_MANGA_FIELDS + } + } + } +`; + +export const UPDATE_MANGA_CATEGORIES = gql` + ${FULL_MANGA_FIELDS} + mutation UPDATE_MANGA_CATEGORIES($input: UpdateMangaCategoriesInput!) { + updateMangaCategories(input: $input) { + clientMutationId + manga { + ...FULL_MANGA_FIELDS + } + } + } +`; + +export const UPDATE_MANGAS = gql` + ${FULL_MANGA_FIELDS} + mutation UPDATE_MANGAS($input: UpdateMangasInput!) { + updateMangas(input: $input) { + clientMutationId + mangas { + ...FULL_MANGA_FIELDS + } + } + } +`; + +export const UPDATE_MANGAS_CATEGORIES = gql` + ${FULL_MANGA_FIELDS} + mutation UPDATE_MANGAS_CATEGORIES($input: UpdateMangasCategoriesInput!) { + updateMangasCategories(input: $input) { + clientMutationId + mangas { + ...FULL_MANGA_FIELDS + } + } + } +`; diff --git a/src/lib/graphql/mutations/ServerInfoMutation.ts b/src/lib/graphql/mutations/ServerInfoMutation.ts new file mode 100644 index 00000000..c040069b --- /dev/null +++ b/src/lib/graphql/mutations/ServerInfoMutation.ts @@ -0,0 +1,23 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { WEBUI_UPDATE_STATUS } from '@/lib/graphql/Fragments'; + +// eslint-disable-next-line import/prefer-default-export +export const UPDATE_WEBUI = gql` + ${WEBUI_UPDATE_STATUS} + mutation UPDATE_WEBUI($input: WebUIUpdateInput = {}) { + updateWebUI(input: $input) { + clientMutationId + updateStatus { + ...WEBUI_UPDATE_STATUS + } + } + } +`; diff --git a/src/lib/graphql/mutations/SettingsMutation.ts b/src/lib/graphql/mutations/SettingsMutation.ts new file mode 100644 index 00000000..df121056 --- /dev/null +++ b/src/lib/graphql/mutations/SettingsMutation.ts @@ -0,0 +1,34 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { SERVER_SETTINGS } from '@/lib/graphql/Fragments'; + +export const RESET_SERVER_SETTINGS = gql` + ${SERVER_SETTINGS} + mutation RESET_SERVER_SETTINGS($input: ResetSettingsInput!) { + resetSettings(input: $input) { + clientMutationId + settings { + ...SERVER_SETTINGS + } + } + } +`; + +export const UPDATE_SERVER_SETTINGS = gql` + ${SERVER_SETTINGS} + mutation UPDATE_SERVER_SETTINGS($input: SetSettingsInput!) { + setSettings(input: $input) { + clientMutationId + settings { + ...SERVER_SETTINGS + } + } + } +`; diff --git a/src/lib/graphql/mutations/SourceMutation.ts b/src/lib/graphql/mutations/SourceMutation.ts new file mode 100644 index 00000000..c258d812 --- /dev/null +++ b/src/lib/graphql/mutations/SourceMutation.ts @@ -0,0 +1,35 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { BASE_MANGA_FIELDS, FULL_SOURCE_FIELDS } from '@/lib/graphql/Fragments'; + +export const GET_SOURCE_MANGAS_FETCH = gql` + ${BASE_MANGA_FIELDS} + mutation GET_SOURCE_MANGAS_FETCH($input: FetchSourceMangaInput!) { + fetchSourceManga(input: $input) { + clientMutationId + hasNextPage + mangas { + ...BASE_MANGA_FIELDS + } + } + } +`; + +export const UPDATE_SOURCE_PREFERENCES = gql` + ${FULL_SOURCE_FIELDS} + mutation UPDATE_SOURCE_PREFERENCES($input: UpdateSourcePreferenceInput!) { + updateSourcePreference(input: $input) { + clientMutationId + source { + ...FULL_SOURCE_FIELDS + } + } + } +`; diff --git a/src/lib/graphql/mutations/UpdaterMutation.ts b/src/lib/graphql/mutations/UpdaterMutation.ts new file mode 100644 index 00000000..c4011433 --- /dev/null +++ b/src/lib/graphql/mutations/UpdaterMutation.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { PARTIAL_UPDATER_STATUS } from '@/lib/graphql/Fragments'; + +export const UPDATE_CATEGORY_MANGAS = gql` + ${PARTIAL_UPDATER_STATUS} + mutation UPDATE_CATEGORY_MANGAS($input: UpdateCategoryMangaInput!) { + updateCategoryManga(input: $input) { + clientMutationId + updateStatus { + ...PARTIAL_UPDATER_STATUS + } + } + } +`; + +export const UPDATE_LIBRARY_MANGAS = gql` + ${PARTIAL_UPDATER_STATUS} + mutation UPDATE_LIBRARY_MANGAS($input: UpdateLibraryMangaInput = {}) { + updateLibraryManga(input: $input) { + clientMutationId + updateStatus { + ...PARTIAL_UPDATER_STATUS + } + } + } +`; + +export const STOP_UPDATER = gql` + mutation STOP_UPDATER($input: UpdateStopInput = {}) { + updateStop(input: $input) { + clientMutationId + } + } +`; diff --git a/src/lib/graphql/queries/BackupQuery.ts b/src/lib/graphql/queries/BackupQuery.ts new file mode 100644 index 00000000..8d09c94c --- /dev/null +++ b/src/lib/graphql/queries/BackupQuery.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; + +export const VALIDATE_BACKUP = gql` + query VALIDATE_BACKUP($input: ValidateBackupInput!) { + validateBackup(input: $input) { + missingSources { + id + name + } + } + } +`; + +export const GET_RESTORE_STATUS = gql` + query GET_RESTORE_STATUS { + restoreStatus { + mangaProgress + state + totalManga + } + } +`; diff --git a/src/lib/graphql/queries/CategoryQuery.ts b/src/lib/graphql/queries/CategoryQuery.ts new file mode 100644 index 00000000..8398cc8d --- /dev/null +++ b/src/lib/graphql/queries/CategoryQuery.ts @@ -0,0 +1,73 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_CATEGORY_FIELDS, FULL_MANGA_FIELDS, PAGE_INFO } from '@/lib/graphql/Fragments'; + +export const GET_CATEGORIES = gql` + ${FULL_CATEGORY_FIELDS} + ${PAGE_INFO} + query GET_CATEGORIES( + $after: Cursor + $before: Cursor + $condition: CategoryConditionInput + $filter: CategoryFilterInput + $first: Int + $last: Int + $offset: Int + $orderBy: CategoryOrderBy + $orderByType: SortOrder + ) { + categories( + after: $after + before: $before + condition: $condition + filter: $filter + first: $first + last: $last + offset: $offset + orderBy: $orderBy + orderByType: $orderByType + ) { + nodes { + ...FULL_CATEGORY_FIELDS + } + pageInfo { + ...PAGE_INFO + } + totalCount + } + } +`; + +export const GET_CATEGORY = gql` + ${FULL_CATEGORY_FIELDS} + query GET_CATEGORY($id: Int!) { + category(id: $id) { + ...FULL_CATEGORY_FIELDS + } + } +`; + +export const GET_CATEGORY_MANGAS = gql` + ${FULL_MANGA_FIELDS} + ${PAGE_INFO} + query GET_CATEGORY_MANGAS($id: Int!) { + category(id: $id) { + mangas { + nodes { + ...FULL_MANGA_FIELDS + } + pageInfo { + ...PAGE_INFO + } + totalCount + } + } + } +`; diff --git a/src/lib/graphql/queries/ChapterQuery.ts b/src/lib/graphql/queries/ChapterQuery.ts new file mode 100644 index 00000000..89e88917 --- /dev/null +++ b/src/lib/graphql/queries/ChapterQuery.ts @@ -0,0 +1,57 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_CHAPTER_FIELDS, PAGE_INFO } from '@/lib/graphql/Fragments'; + +// returns the current chapter from the database +export const GET_CHAPTER = gql` + ${FULL_CHAPTER_FIELDS} + query GET_CHAPTER($id: Int!) { + chapter(id: $id) { + ...FULL_CHAPTER_FIELDS + } + } +`; + +// returns the current chapters from the database +export const GET_CHAPTERS = gql` + ${FULL_CHAPTER_FIELDS} + ${PAGE_INFO} + query GET_CHAPTERS( + $after: Cursor + $before: Cursor + $condition: ChapterConditionInput + $filter: ChapterFilterInput + $first: Int + $last: Int + $offset: Int + $orderBy: ChapterOrderBy + $orderByType: SortOrder + ) { + chapters( + after: $after + before: $before + condition: $condition + filter: $filter + first: $first + last: $last + offset: $offset + orderBy: $orderBy + orderByType: $orderByType + ) { + nodes { + ...FULL_CHAPTER_FIELDS + } + pageInfo { + ...PAGE_INFO + } + totalCount + } + } +`; diff --git a/src/lib/graphql/queries/DownloaderQuery.ts b/src/lib/graphql/queries/DownloaderQuery.ts new file mode 100644 index 00000000..d67cb9a6 --- /dev/null +++ b/src/lib/graphql/queries/DownloaderQuery.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_DOWNLOAD_STATUS } from '@/lib/graphql/Fragments'; + +// eslint-disable-next-line import/prefer-default-export +export const GET_DOWNLOAD_STATUS = gql` + ${FULL_DOWNLOAD_STATUS} + query GET_DOWNLOAD_STATUS { + downloadStatus { + ...FULL_DOWNLOAD_STATUS + } + } +`; diff --git a/src/lib/graphql/queries/ExtensionQuery.ts b/src/lib/graphql/queries/ExtensionQuery.ts new file mode 100644 index 00000000..16d4184d --- /dev/null +++ b/src/lib/graphql/queries/ExtensionQuery.ts @@ -0,0 +1,57 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_EXTENSION_FIELDS, PAGE_INFO } from '@/lib/graphql/Fragments'; + +// returns the current extension from the database +export const GET_EXTENSION = gql` + ${FULL_EXTENSION_FIELDS} + query GET_EXTENSION($pkgName: String!) { + extension(pkgName: $pkgName) { + ...FULL_EXTENSION_FIELDS + } + } +`; + +// returns the current extensions from the database +export const GET_EXTENSIONS = gql` + ${FULL_EXTENSION_FIELDS} + ${PAGE_INFO} + query GET_EXTENSIONS( + $after: Cursor + $before: Cursor + $condition: ExtensionConditionInput + $filter: ExtensionFilterInput + $first: Int + $last: Int + $offset: Int + $orderBy: ExtensionOrderBy + $orderByType: SortOrder + ) { + extensions( + after: $after + before: $before + condition: $condition + filter: $filter + first: $first + last: $last + offset: $offset + orderBy: $orderBy + orderByType: $orderByType + ) { + nodes { + ...FULL_EXTENSION_FIELDS + } + pageInfo { + ...PAGE_INFO + } + totalCount + } + } +`; diff --git a/src/lib/graphql/queries/GlobalMetadataQuery.ts b/src/lib/graphql/queries/GlobalMetadataQuery.ts new file mode 100644 index 00000000..cc3b69c4 --- /dev/null +++ b/src/lib/graphql/queries/GlobalMetadataQuery.ts @@ -0,0 +1,55 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { GLOBAL_METADATA, PAGE_INFO } from '@/lib/graphql/Fragments.ts'; + +export const GET_GLOBAL_METADATA = gql` + ${GLOBAL_METADATA} + query GET_GLOBAL_METADATA($key: String!) { + meta(key: $key) { + ...GLOBAL_METADATA + } + } +`; + +export const GET_GLOBAL_METADATAS = gql` + ${GLOBAL_METADATA} + ${PAGE_INFO} + query GET_GLOBAL_METADATAS( + $after: Cursor + $before: Cursor + $condition: MetaConditionInput + $filter: MetaFilterInput + $first: Int + $last: Int + $offset: Int + $orderBy: MetaOrderBy + $orderByType: SortOrder + ) { + metas( + after: $after + before: $before + condition: $condition + filter: $filter + first: $first + last: $last + offset: $offset + orderBy: $orderBy + orderByType: $orderByType + ) { + nodes { + ...GLOBAL_METADATA + } + pageInfo { + ...PAGE_INFO + } + totalCount + } + } +`; diff --git a/src/lib/graphql/queries/MangaQuery.ts b/src/lib/graphql/queries/MangaQuery.ts new file mode 100644 index 00000000..f4d73e39 --- /dev/null +++ b/src/lib/graphql/queries/MangaQuery.ts @@ -0,0 +1,59 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_CHAPTER_FIELDS, FULL_MANGA_FIELDS, PAGE_INFO } from '@/lib/graphql/Fragments'; + +// returns the current manga from the database +export const GET_MANGA = gql` + ${FULL_MANGA_FIELDS} + ${FULL_CHAPTER_FIELDS} + query GET_MANGA($id: Int!) { + manga(id: $id) { + ...FULL_MANGA_FIELDS + } + } +`; + +// returns the current manga from the database +export const GET_MANGAS = gql` + ${FULL_MANGA_FIELDS} + ${FULL_CHAPTER_FIELDS} + ${PAGE_INFO} + query GET_MANGAS( + $after: Cursor + $before: Cursor + $condition: MangaConditionInput + $filter: MangaFilterInput + $first: Int + $last: Int + $offset: Int + $orderBy: MangaOrderBy + $orderByType: SortOrder + ) { + mangas( + after: $after + before: $before + condition: $condition + filter: $filter + first: $first + last: $last + offset: $offset + orderBy: $orderBy + orderByType: $orderByType + ) { + nodes { + ...FULL_MANGA_FIELDS + } + pageInfo { + ...PAGE_INFO + } + totalCount + } + } +`; diff --git a/src/lib/graphql/queries/ServerInfoQuery.ts b/src/lib/graphql/queries/ServerInfoQuery.ts new file mode 100644 index 00000000..8d10ea2f --- /dev/null +++ b/src/lib/graphql/queries/ServerInfoQuery.ts @@ -0,0 +1,52 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { WEBUI_UPDATE_INFO, WEBUI_UPDATE_STATUS } from '@/lib/graphql/Fragments'; + +export const GET_ABOUT = gql` + query GET_ABOUT { + about { + buildTime + buildType + discord + github + name + revision + version + } + } +`; + +export const CHECK_FOR_SERVER_UPDATES = gql` + query CHECK_FOR_SERVER_UPDATES { + checkForServerUpdates { + channel + tag + url + } + } +`; + +export const CHECK_FOR_WEBUI_UPDATE = gql` + ${WEBUI_UPDATE_INFO} + query CHECK_FOR_WEBUI_UPDATE { + checkForWebUIUpdate { + ...WEBUI_UPDATE_INFO + } + } +`; + +export const GET_WEBUI_UPDATE_STATUS = gql` + ${WEBUI_UPDATE_STATUS} + query GET_WEBUI_UPDATE_STATUS { + getWebUIUpdateStatus { + ...WEBUI_UPDATE_STATUS + } + } +`; diff --git a/src/lib/graphql/queries/SettingsQuery.ts b/src/lib/graphql/queries/SettingsQuery.ts new file mode 100644 index 00000000..227f798e --- /dev/null +++ b/src/lib/graphql/queries/SettingsQuery.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { SERVER_SETTINGS } from '@/lib/graphql/Fragments'; + +// eslint-disable-next-line import/prefer-default-export +export const GET_SERVER_SETTINGS = gql` + ${SERVER_SETTINGS} + query GET_SERVER_SETTINGS { + settings { + ...SERVER_SETTINGS + } + } +`; diff --git a/src/lib/graphql/queries/SourceQuery.ts b/src/lib/graphql/queries/SourceQuery.ts new file mode 100644 index 00000000..6d579211 --- /dev/null +++ b/src/lib/graphql/queries/SourceQuery.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_SOURCE_FIELDS, PARTIAL_SOURCE_FIELDS } from '@/lib/graphql/Fragments'; + +export const GET_SOURCE = gql` + ${FULL_SOURCE_FIELDS} + query GET_SOURCE($id: LongString!) { + source(id: $id) { + ...FULL_SOURCE_FIELDS + } + } +`; + +export const GET_SOURCES = gql` + ${PARTIAL_SOURCE_FIELDS} + query GET_SOURCES { + sources { + nodes { + ...PARTIAL_SOURCE_FIELDS + } + } + } +`; diff --git a/src/lib/graphql/queries/UpdaterQuery.ts b/src/lib/graphql/queries/UpdaterQuery.ts new file mode 100644 index 00000000..36625519 --- /dev/null +++ b/src/lib/graphql/queries/UpdaterQuery.ts @@ -0,0 +1,28 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_UPDATER_STATUS } from '@/lib/graphql/Fragments'; + +// eslint-disable-next-line import/prefer-default-export +export const GET_UPDATE_STATUS = gql` + ${FULL_UPDATER_STATUS} + query GET_UPDATE_STATUS { + updateStatus { + ...FULL_UPDATER_STATUS + } + } +`; + +export const GET_LAST_UPDATE_TIMESTAMP = gql` + query GET_LAST_UPDATE_TIMESTAMP { + lastUpdateTimestamp { + timestamp + } + } +`; diff --git a/src/lib/graphql/subscriptions/DownloaderSubscription.ts b/src/lib/graphql/subscriptions/DownloaderSubscription.ts new file mode 100644 index 00000000..af92bcfe --- /dev/null +++ b/src/lib/graphql/subscriptions/DownloaderSubscription.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_DOWNLOAD_STATUS } from '@/lib/graphql/Fragments'; + +// eslint-disable-next-line import/prefer-default-export +export const DOWNLOAD_STATUS_SUBSCRIPTION = gql` + ${FULL_DOWNLOAD_STATUS} + subscription DOWNLOAD_STATUS_SUBSCRIPTION { + downloadChanged { + ...FULL_DOWNLOAD_STATUS + } + } +`; diff --git a/src/lib/graphql/subscriptions/ServerInfoSubscription.ts b/src/lib/graphql/subscriptions/ServerInfoSubscription.ts new file mode 100644 index 00000000..e95f400f --- /dev/null +++ b/src/lib/graphql/subscriptions/ServerInfoSubscription.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { WEBUI_UPDATE_STATUS } from '@/lib/graphql/Fragments'; + +// eslint-disable-next-line import/prefer-default-export +export const WEBUI_UPDATE_SUBSCRIPTION = gql` + ${WEBUI_UPDATE_STATUS} + subscription WEBUI_UPDATE_SUBSCRIPTION { + webUIUpdateStatusChange { + ...WEBUI_UPDATE_STATUS + } + } +`; diff --git a/src/lib/graphql/subscriptions/UpdaterSubscription.ts b/src/lib/graphql/subscriptions/UpdaterSubscription.ts new file mode 100644 index 00000000..d16d657a --- /dev/null +++ b/src/lib/graphql/subscriptions/UpdaterSubscription.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import gql from 'graphql-tag'; +import { FULL_UPDATER_STATUS } from '@/lib/graphql/Fragments'; + +// eslint-disable-next-line import/prefer-default-export +export const UPDATER_SUBSCRIPTION = gql` + ${FULL_UPDATER_STATUS} + subscription UPDATER_SUBSCRIPTION { + updateStatusChanged { + ...FULL_UPDATER_STATUS + } + } +`; diff --git a/src/lib/requests/CustomCache.ts b/src/lib/requests/CustomCache.ts new file mode 100644 index 00000000..17679218 --- /dev/null +++ b/src/lib/requests/CustomCache.ts @@ -0,0 +1,40 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +// eslint-disable-next-line import/prefer-default-export +export class CustomCache { + private keyToResponseMap = new Map(); + + private keyToFetchTimestampMap = new Map(); + + public readonly createKeyFn = (endpoint: string, data: unknown): string => `${endpoint}_${JSON.stringify(data)}`; + + constructor(createKeyFn?: (endpoint: string, data: unknown) => string) { + this.createKeyFn = createKeyFn ?? this.createKeyFn; + } + + public getKeyFor(key: string, data: unknown): string { + return this.createKeyFn(key, data); + } + + public cacheResponse(endpoint: string, data: unknown, response: unknown) { + const createdKey = this.getKeyFor(endpoint, data); + this.keyToFetchTimestampMap.set(createdKey, Date.now()); + this.keyToResponseMap.set(createdKey, response); + } + + public getFetchTimestampFor(endpoint: string, data: unknown): number | undefined { + const key = this.getKeyFor(endpoint, data); + return this.keyToFetchTimestampMap.get(key); + } + + public getResponseFor(endpoint: string, data: unknown): Response | undefined { + const key = this.getKeyFor(endpoint, data); + return this.keyToResponseMap.get(key) as Response; + } +} diff --git a/src/lib/requests/RequestManager.ts b/src/lib/requests/RequestManager.ts new file mode 100644 index 00000000..ba35c996 --- /dev/null +++ b/src/lib/requests/RequestManager.ts @@ -0,0 +1,1782 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import { AxiosInstance } from 'axios'; +import { + ApolloError, + ApolloQueryResult, + DocumentNode, + FetchResult, + MutationHookOptions as ApolloMutationHookOptions, + MutationOptions as ApolloMutationOptions, + MutationTuple, + QueryHookOptions as ApolloQueryHookOptions, + QueryOptions as ApolloQueryOptions, + QueryResult, + SubscriptionHookOptions as ApolloSubscriptionHookOptions, + SubscriptionResult, + TypedDocumentNode, + useMutation, + useQuery, + useSubscription, +} from '@apollo/client'; +import { OperationVariables } from '@apollo/client/core'; +import { useEffect, useRef, useState } from 'react'; +import { IRestClient, RestClient } from '@/lib/requests/client/RestClient.ts'; +import storage from '@/util/localStorage.tsx'; +import { GraphQLClient } from '@/lib/requests/client/GraphQLClient.ts'; +import { + CategoryOrderBy, + ChapterOrderBy, + CheckForServerUpdatesQuery, + CheckForServerUpdatesQueryVariables, + ClearDownloaderMutation, + ClearDownloaderMutationVariables, + CreateCategoryInput, + CreateCategoryMutation, + CreateCategoryMutationVariables, + DeleteCategoryMutation, + DeleteCategoryMutationVariables, + DeleteDownloadedChapterMutation, + DeleteDownloadedChapterMutationVariables, + DeleteDownloadedChaptersMutation, + DeleteDownloadedChaptersMutationVariables, + DequeueChapterDownloadMutation, + DequeueChapterDownloadMutationVariables, + DequeueChapterDownloadsMutation, + DequeueChapterDownloadsMutationVariables, + DownloadStatusSubscription, + DownloadStatusSubscriptionVariables, + EnqueueChapterDownloadMutation, + EnqueueChapterDownloadMutationVariables, + EnqueueChapterDownloadsMutation, + EnqueueChapterDownloadsMutationVariables, + FetchSourceMangaInput, + FetchSourceMangaType, + FilterChangeInput, + GetAboutQuery, + GetAboutQueryVariables, + GetCategoriesQuery, + GetCategoriesQueryVariables, + GetCategoryMangasQuery, + GetCategoryMangasQueryVariables, + GetChapterPagesFetchMutation, + GetChapterPagesFetchMutationVariables, + GetChaptersQuery, + GetChaptersQueryVariables, + GetExtensionsFetchMutation, + GetExtensionsFetchMutationVariables, + GetExtensionsQuery, + GetExtensionsQueryVariables, + GetGlobalMetadatasQuery, + GetGlobalMetadatasQueryVariables, + GetMangaChaptersFetchMutation, + GetMangaChaptersFetchMutationVariables, + GetMangaFetchMutation, + GetMangaFetchMutationVariables, + GetMangaQuery, + GetMangaQueryVariables, + GetMangasQuery, + GetMangasQueryVariables, + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables, + GetSourceQuery, + GetSourceQueryVariables, + GetSourcesQuery, + GetSourcesQueryVariables, + GetUpdateStatusQuery, + GetUpdateStatusQueryVariables, + InstallExternalExtensionMutation, + InstallExternalExtensionMutationVariables, + ReorderChapterDownloadMutation, + ReorderChapterDownloadMutationVariables, + RestoreBackupMutation, + RestoreBackupMutationVariables, + SetCategoryMetadataMutation, + SetCategoryMetadataMutationVariables, + SetChapterMetadataMutation, + SetChapterMetadataMutationVariables, + SetGlobalMetadataMutation, + SetGlobalMetadataMutationVariables, + SetMangaMetadataMutation, + SetMangaMetadataMutationVariables, + SortOrder, + SourcePreferenceChangeInput, + StartDownloaderMutation, + StartDownloaderMutationVariables, + StopDownloaderMutation, + StopDownloaderMutationVariables, + StopUpdaterMutation, + StopUpdaterMutationVariables, + UpdateCategoryMangasMutation, + UpdateCategoryMangasMutationVariables, + UpdateCategoryMutation, + UpdateCategoryMutationVariables, + UpdateCategoryOrderMutation, + UpdateCategoryOrderMutationVariables, + UpdateCategoryPatchInput, + UpdateChapterMutation, + UpdateChapterMutationVariables, + UpdateChapterPatchInput, + UpdateChaptersMutation, + UpdateChaptersMutationVariables, + UpdateExtensionMutation, + UpdateExtensionMutationVariables, + UpdateExtensionPatchInput, + UpdateLibraryMangasMutation, + UpdateLibraryMangasMutationVariables, + UpdateMangaCategoriesMutation, + UpdateMangaCategoriesMutationVariables, + UpdateMangaMutation, + UpdateMangaMutationVariables, + UpdateMangaPatchInput, + UpdaterSubscription, + UpdaterSubscriptionVariables, + UpdateSourcePreferencesMutation, + UpdateSourcePreferencesMutationVariables, + ValidateBackupQuery, + ValidateBackupQueryVariables, +} from '@/lib/graphql/generated/graphql.ts'; +import { GET_GLOBAL_METADATAS } from '@/lib/graphql/queries/GlobalMetadataQuery.ts'; +import { SET_GLOBAL_METADATA } from '@/lib/graphql/mutations/GlobalMetadataMutation.ts'; +import { CHECK_FOR_SERVER_UPDATES, GET_ABOUT } from '@/lib/graphql/queries/ServerInfoQuery.ts'; +import { GET_EXTENSIONS } from '@/lib/graphql/queries/ExtensionQuery.ts'; +import { + GET_EXTENSIONS_FETCH, + INSTALL_EXTERNAL_EXTENSION, + UPDATE_EXTENSION, +} from '@/lib/graphql/mutations/ExtensionMutation.ts'; +import { GET_SOURCE, GET_SOURCES } from '@/lib/graphql/queries/SourceQuery.ts'; +import { + GET_MANGA_FETCH, + SET_MANGA_METADATA, + UPDATE_MANGA, + UPDATE_MANGA_CATEGORIES, +} from '@/lib/graphql/mutations/MangaMutation.ts'; +import { GET_MANGA, GET_MANGAS } from '@/lib/graphql/queries/MangaQuery.ts'; +import { GET_CATEGORIES, GET_CATEGORY_MANGAS } from '@/lib/graphql/queries/CategoryQuery.ts'; +import { GET_SOURCE_MANGAS_FETCH, UPDATE_SOURCE_PREFERENCES } from '@/lib/graphql/mutations/SourceMutation.ts'; +import { + CLEAR_DOWNLOADER, + DELETE_DOWNLOADED_CHAPTER, + DELETE_DOWNLOADED_CHAPTERS, + DEQUEUE_CHAPTER_DOWNLOAD, + DEQUEUE_CHAPTER_DOWNLOADS, + ENQUEUE_CHAPTER_DOWNLOAD, + ENQUEUE_CHAPTER_DOWNLOADS, + REORDER_CHAPTER_DOWNLOAD, + START_DOWNLOADER, + STOP_DOWNLOADER, +} from '@/lib/graphql/mutations/DownloaderMutation.ts'; +import { GET_CHAPTERS } from '@/lib/graphql/queries/ChapterQuery.ts'; +import { + GET_CHAPTER_PAGES_FETCH, + GET_MANGA_CHAPTERS_FETCH, + SET_CHAPTER_METADATA, + UPDATE_CHAPTER, + UPDATE_CHAPTERS, +} from '@/lib/graphql/mutations/ChapterMutation.ts'; +import { + CREATE_CATEGORY, + DELETE_CATEGORY, + SET_CATEGORY_METADATA, + UPDATE_CATEGORY, + UPDATE_CATEGORY_ORDER, +} from '@/lib/graphql/mutations/CategoryMutation.ts'; +import { + STOP_UPDATER, + UPDATE_CATEGORY_MANGAS, + UPDATE_LIBRARY_MANGAS, +} from '@/lib/graphql/mutations/UpdaterMutation.ts'; +import { GET_UPDATE_STATUS } from '@/lib/graphql/queries/UpdaterQuery.ts'; +import { CustomCache } from '@/lib/requests/CustomCache.ts'; +import { RESTORE_BACKUP } from '@/lib/graphql/mutations/BackupMutation.ts'; +import { VALIDATE_BACKUP } from '@/lib/graphql/queries/BackupQuery.ts'; +import { DOWNLOAD_STATUS_SUBSCRIPTION } from '@/lib/graphql/subscriptions/DownloaderSubscription.ts'; +import { UPDATER_SUBSCRIPTION } from '@/lib/graphql/subscriptions/UpdaterSubscription.ts'; + +enum GQLMethod { + QUERY = 'QUERY', + USE_QUERY = 'USE_QUERY', + USE_MUTATION = 'USE_MUTATION', + MUTATION = 'MUTATION', + USE_SUBSCRIPTION = 'USE_SUBSCRIPTION', +} + +type CustomApolloOptions = { + /** + * This is a workaround for an apollo bug (?). + * + * A new abort signal gets passed on every hook call. + * This causes the passed arguments to change (due to updating the "context" option, which is only relevant for the actual request), + * which - I assume - results in apollo to handle this as a completely new hook call. + * Due to this, when e.g. calling "fetchMore", "loading" and "networkStatus" do not get updated when enabling "notifyOnNetworkStatusChange". + * + * By not passing an abort signal, the states get correctly updated, BUT it won't be possible to abort the request. + */ + omitAbortSignal?: boolean; +}; +type QueryOptions = Partial< + ApolloQueryOptions +> & + CustomApolloOptions; +type QueryHookOptions = Partial< + ApolloQueryHookOptions +> & + CustomApolloOptions; +type MutationHookOptions = Partial< + ApolloMutationHookOptions +> & + CustomApolloOptions; +type MutationOptions = Partial< + ApolloMutationOptions +> & + CustomApolloOptions; +type ApolloPaginatedMutationOptions = Partial< + MutationHookOptions +> & { skipRequest?: boolean }; +type SubscriptionHookOptions = Partial< + ApolloSubscriptionHookOptions +> & + Omit & { omitAbortSignal?: never }; + +type AbortableRequest = { abortRequest: AbortController['abort'] }; + +export type AbortabaleApolloQueryResponse = { + response: Promise>; +} & AbortableRequest; +export type AbortableApolloUseQueryResponse< + Data = any, + Variables extends OperationVariables = OperationVariables, +> = QueryResult & AbortableRequest; +export type AbortableApolloUseMutationResponse< + Data = any, + Variables extends OperationVariables = OperationVariables, +> = [MutationTuple[0], MutationTuple[1] & AbortableRequest]; +export type AbortableApolloUseMutationPaginatedResponse< + Data = any, + Variables extends OperationVariables = OperationVariables, +> = [ + (page: number) => Promise>, + (Omit[1], 'loading'> & + AbortableRequest & { + size: number; + /** + * Indicates whether any request is currently active. + * In case only "isLoading" is true, it means that it's the initial request + */ + isLoading: boolean; + /** + * Indicates if a next page is being fetched, which is not part of the initial pages + */ + isLoadingMore: boolean; + /** + * Indicates if the cached pages are currently getting revalidated + */ + isValidating: boolean; + })[], +]; +export type AbortableApolloMutationResponse = { response: Promise> } & AbortableRequest; + +// TODO - correctly update cache after all mutations instead of refetching queries +export class RequestManager { + public static readonly API_VERSION = '/api/v1/'; + + private readonly graphQLClient = new GraphQLClient(); + + private readonly restClient: RestClient = new RestClient(); + + private readonly cache = new CustomCache(); + + public getClient(): IRestClient { + return this.restClient; + } + + public updateClient(config: Partial): void { + this.restClient.updateConfig(config); + this.graphQLClient.updateConfig(); + } + + public getBaseUrl(): string { + return this.restClient.getClient().defaults.baseURL!; + } + + public getValidUrlFor(endpoint: string, apiVersion: string = RequestManager.API_VERSION): string { + return `${this.getBaseUrl()}${apiVersion}${endpoint}`; + } + + private createAbortController(): { signal: AbortSignal } & AbortableRequest { + const abortController = new AbortController(); + const abortRequest = (reason?: any): void => { + if (!abortController.signal.aborted) { + abortController.abort(reason); + } + }; + + return { signal: abortController.signal, abortRequest }; + } + + private createPaginatedResult( + result: Partial | undefined | null, + defaultPage: number, + page?: number, + ): Result { + const isLoading = !result?.error && (result?.isLoading || !result?.called); + const size = page ?? result?.size ?? defaultPage; + return { + client: this.graphQLClient.client, + abortRequest: () => {}, + reset: () => {}, + called: false, + data: undefined, + error: undefined, + size, + isLoading, + isLoadingMore: isLoading && size > 1, + isValidating: !!result?.isValidating, + ...result, + } as Result; + } + + private async revalidatePage( + cacheResultsKey: string, + cachePagesKey: string, + getVariablesFor: (page: number) => Variables, + options: ApolloPaginatedMutationOptions | undefined, + checkIfCachedPageIsInvalid: ( + cachedResult: AbortableApolloUseMutationPaginatedResponse[1][number] | undefined, + revalidatedResult: FetchResult, + ) => boolean, + hasNextPage: (revalidatedResult: FetchResult) => boolean, + pageToRevalidate: number, + maxPage: number, + signal: AbortSignal, + ): Promise { + const { response: revalidationRequest } = this.doRequest( + GQLMethod.MUTATION, + GET_SOURCE_MANGAS_FETCH, + getVariablesFor(pageToRevalidate), + { + ...options, + context: { fetchOptions: { signal } }, + }, + ); + + const revalidationResponse = await revalidationRequest; + const cachedPageData = this.cache.getResponseFor< + AbortableApolloUseMutationPaginatedResponse[1][number] + >(cacheResultsKey, getVariablesFor(pageToRevalidate)); + + const isCachedPageInvalid = checkIfCachedPageIsInvalid(cachedPageData, revalidationResponse); + if (isCachedPageInvalid) { + this.cache.cacheResponse(cacheResultsKey, getVariablesFor(pageToRevalidate), revalidationResponse); + } + + if (!hasNextPage(revalidationResponse)) { + const currentCachedPages = this.cache.getResponseFor>(cachePagesKey, getVariablesFor(0))!; + this.cache.cacheResponse( + cachePagesKey, + getVariablesFor(0), + [...currentCachedPages].filter((cachedPage) => cachedPage <= pageToRevalidate), + ); + [...currentCachedPages] + .filter((cachedPage) => cachedPage > pageToRevalidate) + .forEach((cachedPage) => + this.cache.cacheResponse(cacheResultsKey, getVariablesFor(cachedPage), undefined), + ); + return; + } + + if (isCachedPageInvalid && pageToRevalidate < maxPage) { + await this.revalidatePage( + cacheResultsKey, + cachePagesKey, + getVariablesFor, + options, + checkIfCachedPageIsInvalid, + hasNextPage, + pageToRevalidate + 1, + maxPage, + signal, + ); + } + } + + private async revalidatePages( + activeRevalidationRef: + | [ForInput: Variables, Request: Promise, AbortRequest: AbortableRequest['abortRequest']] + | null, + setRevalidationDone: (isDone: boolean) => void, + setActiveRevalidation: ( + activeRevalidation: + | [ForInput: Variables, Request: Promise, AbortRequest: AbortableRequest['abortRequest']] + | null, + ) => void, + getVariablesFor: (page: number) => Variables, + setValidating: (isValidating: boolean) => void, + revalidatePage: (pageToRevalidate: number, maxPage: number, signal: AbortSignal) => Promise, + maxPage: number, + abortRequest: AbortableRequest['abortRequest'], + signal: AbortSignal, + ): Promise { + setRevalidationDone(true); + + const [currRevVars, currRevPromise, currRevAbortRequest] = activeRevalidationRef ?? []; + + const isActiveRevalidationForInput = JSON.stringify(currRevVars) === JSON.stringify(getVariablesFor(0)); + + setValidating(true); + + if (!isActiveRevalidationForInput) { + currRevAbortRequest?.(new Error('Abort revalidation for different input')); + } + + let revalidationPromise = currRevPromise; + if (!isActiveRevalidationForInput) { + revalidationPromise = revalidatePage(1, maxPage, signal); + setActiveRevalidation([getVariablesFor(0), revalidationPromise, abortRequest]); + } + + try { + await revalidationPromise; + setActiveRevalidation(null); + } catch (e) { + // ignore + } finally { + setValidating(false); + } + } + + private async fetchPaginatedMutationPage< + Data = any, + Variables extends OperationVariables = OperationVariables, + ResultIdInfo extends Record = any, + >( + getVariablesFor: (page: number) => Variables, + setAbortRequest: (abortRequest: AbortableRequest['abortRequest']) => void, + getResultIdInfo: () => ResultIdInfo, + createPaginatedResult: ( + result: Partial[1][number]>, + ) => AbortableApolloUseMutationPaginatedResponse[1][number], + setResult: ( + result: AbortableApolloUseMutationPaginatedResponse[1][number] & ResultIdInfo, + ) => void, + revalidate: ( + maxPage: number, + abortRequest: AbortableRequest['abortRequest'], + signal: AbortSignal, + ) => Promise, + options: ApolloPaginatedMutationOptions | undefined, + documentNode: DocumentNode, + cachePagesKey: string, + cacheResultsKey: string, + cachedPages: Set, + newPage: number, + ): Promise> { + const basePaginatedResult: Partial[1][number]> = { + size: newPage, + isLoading: false, + isLoadingMore: false, + called: true, + }; + + let response: FetchResult = {}; + try { + const { signal, abortRequest } = this.createAbortController(); + setAbortRequest(abortRequest); + + setResult({ + ...getResultIdInfo(), + ...createPaginatedResult({ isLoading: true, abortRequest, size: newPage, called: true }), + }); + + if (newPage !== 1 && cachedPages.size) { + await revalidate(newPage, abortRequest, signal); + } + + const { response: request } = this.doRequest( + GQLMethod.MUTATION, + documentNode, + getVariablesFor(newPage), + { ...options, context: { fetchOptions: { signal } } }, + ); + + response = await request; + + basePaginatedResult.data = response.data; + } catch (error: any) { + if (error instanceof ApolloError) { + basePaginatedResult.error = error; + } else { + basePaginatedResult.error = new ApolloError({ + errorMessage: error?.message ?? error.toString(), + extraInfo: error, + }); + } + } + + const fetchPaginatedResult = { + ...getResultIdInfo(), + ...createPaginatedResult(basePaginatedResult), + }; + + setResult(fetchPaginatedResult); + + const shouldCacheResult = !fetchPaginatedResult.error; + if (shouldCacheResult) { + const currentCachedPages = this.cache.getResponseFor>(cachePagesKey, getVariablesFor(0)) ?? []; + this.cache.cacheResponse(cachePagesKey, getVariablesFor(0), new Set([...currentCachedPages, newPage])); + this.cache.cacheResponse(cacheResultsKey, getVariablesFor(newPage), fetchPaginatedResult); + } + + return response; + } + + private fetchInitialPages( + options: ApolloPaginatedMutationOptions | undefined, + areFetchingInitialPages: boolean, + areInitialPagesFetched: boolean, + setRevalidationDone: (isDone: boolean) => void, + cacheInitialPagesKey: string, + getVariablesFor: (page: number) => Variables, + initialPages: number, + fetchPage: (page: number) => Promise>, + hasNextPage: (result: FetchResult) => boolean, + ): void { + const shouldFetchInitialPages = !options?.skipRequest && !areFetchingInitialPages && !areInitialPagesFetched; + if (shouldFetchInitialPages) { + setRevalidationDone(true); + this.cache.cacheResponse(cacheInitialPagesKey, getVariablesFor(0), true); + + const loadInitialPages = async (initialPage: number) => { + const areAllPagesFetched = initialPage > initialPages; + if (areAllPagesFetched) { + return; + } + + const pageResult = await fetchPage(initialPage); + + if (hasNextPage(pageResult)) { + await loadInitialPages(initialPage + 1); + } + }; + + loadInitialPages(1); + } + } + + private returnPaginatedMutationResult( + areInitialPagesFetched: boolean, + cachedResults: AbortableApolloUseMutationPaginatedResponse[1][number][], + getVariablesFor: (page: number) => Variables, + paginatedResult: AbortableApolloUseMutationPaginatedResponse[1][number], + fetchPage: (page: number) => Promise>, + hasCachedResult: boolean, + createPaginatedResult: ( + result: Partial[1][number]>, + ) => AbortableApolloUseMutationPaginatedResponse[1][number], + ): AbortableApolloUseMutationPaginatedResponse { + const doCachedResultsExist = areInitialPagesFetched && cachedResults.length; + if (!doCachedResultsExist) { + return [fetchPage, [paginatedResult]]; + } + + const areAllPagesCached = doCachedResultsExist && hasCachedResult; + if (!areAllPagesCached) { + return [fetchPage, [...cachedResults, paginatedResult]]; + } + + return [ + fetchPage, + [ + ...cachedResults.slice(0, cachedResults.length - 1), + createPaginatedResult({ + ...cachedResults[cachedResults.length - 1], + isValidating: paginatedResult.isValidating, + }), + ], + ]; + } + + private revalidateInitialPages( + isRevalidationDone: boolean, + cachedResultsLength: number, + cachedPages: Set, + setRevalidationDone: (isDone: boolean) => void, + getVariablesFor: (page: number) => Variables, + triggerRerender: () => void, + revalidate: ( + maxPage: number, + abortRequest: AbortableRequest['abortRequest'], + signal: AbortSignal, + ) => Promise, + ): void { + const isMountedRef = useRef(false); + + useEffect(() => { + const isRevalidationRequired = isMountedRef.current && cachedResultsLength; + if (!isRevalidationRequired) { + return; + } + + setRevalidationDone(false); + triggerRerender(); + }, [JSON.stringify(getVariablesFor(0))]); + + useEffect(() => { + const shouldRevalidateData = isMountedRef.current && !isRevalidationDone && cachedResultsLength; + if (shouldRevalidateData) { + setRevalidationDone(true); + + const { signal, abortRequest } = this.createAbortController(); + revalidate(Math.max(...cachedPages), abortRequest, signal); + } + }, [isMountedRef.current, isRevalidationDone]); + + useEffect(() => { + isMountedRef.current = true; + }, []); + } + + public getValidImgUrlFor(imageUrl: string, apiVersion: string = ''): string { + const useCache = storage.getItem('useCache', true); + const useCacheQuery = `?useCache=${useCache}`; + // server provided image urls already contain the api version + return `${this.getValidUrlFor(imageUrl, apiVersion)}${useCacheQuery}`; + } + + private doRequest( + method: GQLMethod.QUERY, + operation: DocumentNode | TypedDocumentNode, + variables: Variables | undefined, + options?: QueryOptions, + ): AbortabaleApolloQueryResponse; + + private doRequest( + method: GQLMethod.USE_QUERY, + operation: DocumentNode | TypedDocumentNode, + variables: Variables | undefined, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse; + + private doRequest( + method: GQLMethod.USE_MUTATION, + operation: DocumentNode | TypedDocumentNode, + variables: Variables | undefined, + options?: MutationHookOptions, + ): AbortableApolloUseMutationResponse; + + private doRequest( + method: GQLMethod.MUTATION, + operation: DocumentNode | TypedDocumentNode, + variables: Variables | undefined, + options?: MutationOptions, + ): AbortableApolloMutationResponse; + + private doRequest( + method: GQLMethod.USE_SUBSCRIPTION, + operation: DocumentNode | TypedDocumentNode, + variables: Variables | undefined, + options?: SubscriptionHookOptions, + ): SubscriptionResult; + + private doRequest( + method: GQLMethod, + operation: DocumentNode | TypedDocumentNode, + variables: Variables | undefined, + options?: + | QueryOptions + | QueryHookOptions + | MutationHookOptions + | MutationOptions + | SubscriptionHookOptions, + ): + | AbortabaleApolloQueryResponse + | AbortableApolloUseQueryResponse + | AbortableApolloUseMutationResponse + | AbortableApolloMutationResponse + | SubscriptionResult { + const { signal, abortRequest } = this.createAbortController(); + switch (method) { + case GQLMethod.QUERY: + return { + response: this.graphQLClient.client.query({ + query: operation, + variables, + ...(options as QueryOptions), + context: { + ...options?.context, + fetchOptions: { + signal: options?.omitAbortSignal ? undefined : signal, + ...options?.context?.fetchOptions, + }, + }, + }), + abortRequest, + }; + case GQLMethod.USE_QUERY: + return { + ...useQuery(operation, { + variables, + client: this.graphQLClient.client, + ...options, + context: { + ...options?.context, + fetchOptions: { + signal: options?.omitAbortSignal ? undefined : signal, + ...options?.context?.fetchOptions, + }, + }, + }), + abortRequest, + }; + case GQLMethod.USE_MUTATION: + // eslint-disable-next-line no-case-declarations + const mutationResult = useMutation(operation, { + variables, + client: this.graphQLClient.client, + ...(options as MutationHookOptions), + context: { + ...options?.context, + fetchOptions: { + signal: options?.omitAbortSignal ? undefined : signal, + ...options?.context?.fetchOptions, + }, + }, + }); + + return [mutationResult[0], { ...mutationResult[1], abortRequest }]; + case GQLMethod.MUTATION: + return { + response: this.graphQLClient.client.mutate({ + mutation: operation, + variables, + ...(options as MutationOptions), + context: { + ...options?.context, + fetchOptions: { + signal: options?.omitAbortSignal ? undefined : signal, + ...options?.context?.fetchOptions, + }, + }, + }), + abortRequest, + }; + case GQLMethod.USE_SUBSCRIPTION: + return useSubscription(operation, { + client: this.graphQLClient.client, + variables, + ...(options as SubscriptionHookOptions), + }); + default: + throw new Error(`unexpected GQLRequest type "${method}"`); + } + } + + public useGetGlobalMeta( + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_GLOBAL_METADATAS, {}, options); + } + + public setGlobalMetadata( + key: string, + value: any, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + const result = this.doRequest( + GQLMethod.MUTATION, + SET_GLOBAL_METADATA, + { input: { meta: { key, value: `${value}` } } }, + { + refetchQueries: [GET_GLOBAL_METADATAS], + ...options, + }, + ); + + result.response.then(() => { + this.graphQLClient.client.cache.evict({ fieldName: 'metas' }); + }); + + return result; + } + + public useGetAbout( + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_ABOUT, {}, options); + } + + public useCheckForUpdate( + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, CHECK_FOR_SERVER_UPDATES, {}, options); + } + + public useGetExtensionList( + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_EXTENSIONS, {}, options); + } + + public useExtensionListFetch( + options?: MutationHookOptions, + ): AbortableApolloUseMutationResponse { + return this.doRequest( + GQLMethod.USE_MUTATION, + GET_EXTENSIONS_FETCH, + {}, + { refetchQueries: [GET_EXTENSIONS], ...options }, + ); + } + + public installExternalExtension( + extensionFile: File, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + INSTALL_EXTERNAL_EXTENSION, + { file: extensionFile }, + { refetchQueries: [GET_EXTENSIONS], ...options }, + ); + } + + public updateExtension( + id: string, + patch: UpdateExtensionPatchInput, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + const result = this.doRequest( + GQLMethod.MUTATION, + UPDATE_EXTENSION, + { input: { id, patch } }, + { + refetchQueries: [GET_EXTENSIONS, GET_SOURCES], + ...options, + }, + ); + + result.response.then(() => { + this.graphQLClient.client.cache.evict({ fieldName: 'sources' }); + }); + + return result; + } + + public getExtensionIconUrl(extension: string): string { + return this.getValidImgUrlFor(`extension/icon/${extension}`); + } + + public useGetSourceList( + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_SOURCES, {}, options); + } + + public useGetSource( + id: string, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_SOURCE, { id }, options); + } + + public useGetSourceMangas( + input: FetchSourceMangaInput, + initialPages: number = 1, + options?: ApolloPaginatedMutationOptions, + ): AbortableApolloUseMutationPaginatedResponse< + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables + > { + type MutationResult = AbortableApolloUseMutationPaginatedResponse< + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables + >[1]; + type MutationDataResult = MutationResult[number]; + + const createPaginatedResult = ( + result?: Partial | null, + page?: number, + ) => this.createPaginatedResult(result, input.page, page); + + const getVariablesFor = (page: number): GetSourceMangasFetchMutationVariables => ({ + input: { + ...input, + page, + }, + }); + + const CACHE_INITIAL_PAGES_FETCHING_KEY = 'GET_SOURCE_MANGAS_FETCH_FETCHING_INITIAL_PAGES'; + const CACHE_PAGES_KEY = 'GET_SOURCE_MANGAS_FETCH_PAGES'; + const CACHE_RESULTS_KEY = 'GET_SOURCE_MANGAS_FETCH'; + + const isRevalidationDoneRef = useRef(false); + const activeRevalidationRef = useRef< + | [ + ForInput: GetSourceMangasFetchMutationVariables, + Request: Promise, + AbortRequest: AbortableRequest['abortRequest'], + ] + | null + >(null); + const abortRequestRef = useRef(() => {}); + const resultRef = useRef<(MutationDataResult & { forInput: string }) | null>(null); + const result = resultRef.current; + + const [, setTriggerRerender] = useState(0); + const triggerRerender = () => setTriggerRerender((prev) => prev + 1); + const setResult = (nextResult: typeof resultRef.current) => { + resultRef.current = nextResult; + triggerRerender(); + }; + + const cachedPages = this.cache.getResponseFor>(CACHE_PAGES_KEY, getVariablesFor(0)) ?? new Set(); + const cachedResults = [...cachedPages] + .map( + (cachedPage) => + this.cache.getResponseFor(CACHE_RESULTS_KEY, getVariablesFor(cachedPage))!, + ) + .sort((a, b) => a.size - b.size); + const areFetchingInitialPages = !!this.cache.getResponseFor( + CACHE_INITIAL_PAGES_FETCHING_KEY, + getVariablesFor(0), + ); + + const areInitialPagesFetched = cachedResults.length >= initialPages; + const isResultForCurrentInput = result?.forInput === JSON.stringify(getVariablesFor(0)); + const lastPage = cachedPages.size ? Math.max(...cachedPages) : input.page; + const nextPage = isResultForCurrentInput ? result.size : lastPage; + + const paginatedResult = + isResultForCurrentInput && areInitialPagesFetched ? result : createPaginatedResult(undefined, nextPage); + paginatedResult.abortRequest = abortRequestRef.current; + + // make sure that the result is always for the current input + resultRef.current = { forInput: JSON.stringify(getVariablesFor(0)), ...paginatedResult }; + + const hasCachedResult = !!this.cache.getResponseFor(CACHE_RESULTS_KEY, getVariablesFor(nextPage)); + + const revalidatePage = async (pageToRevalidate: number, maxPage: number, signal: AbortSignal) => + this.revalidatePage( + CACHE_RESULTS_KEY, + CACHE_PAGES_KEY, + getVariablesFor, + options, + (cachedResult, revalidatedResult) => + !cachedResult || + !cachedResult.data?.fetchSourceManga.mangas.length || + cachedResult.data.fetchSourceManga.mangas.some( + (manga, index) => manga.id !== revalidatedResult.data?.fetchSourceManga.mangas[index]?.id, + ), + (revalidatedResult) => !!revalidatedResult.data?.fetchSourceManga.hasNextPage, + pageToRevalidate, + maxPage, + signal, + ); + + const revalidate = async ( + maxPage: number, + abortRequest: AbortableRequest['abortRequest'], + signal: AbortSignal, + ) => + this.revalidatePages( + activeRevalidationRef.current, + (isDone) => { + isRevalidationDoneRef.current = isDone; + }, + (activeRevalidation) => { + activeRevalidationRef.current = activeRevalidation; + }, + getVariablesFor, + (isValidating) => { + setResult({ + ...createPaginatedResult(resultRef.current), + isValidating, + forInput: JSON.stringify(getVariablesFor(0)), + }); + }, + revalidatePage, + maxPage, + abortRequest, + signal, + ); + + // wrap "mutate" function to align with the expected type, which allows only passing a "page" argument + const wrappedMutate = async (newPage: number) => + this.fetchPaginatedMutationPage( + getVariablesFor, + (abortRequest) => { + abortRequestRef.current = abortRequest; + }, + () => ({ forType: input.type, forQuery: input.query }), + createPaginatedResult, + setResult, + revalidate, + options, + GET_SOURCE_MANGAS_FETCH, + CACHE_PAGES_KEY, + CACHE_RESULTS_KEY, + cachedPages, + newPage, + ); + + this.fetchInitialPages( + options, + areFetchingInitialPages, + areInitialPagesFetched, + (isDone) => { + isRevalidationDoneRef.current = isDone; + }, + CACHE_INITIAL_PAGES_FETCHING_KEY, + getVariablesFor, + initialPages, + wrappedMutate, + (fetchedResult) => !!fetchedResult.data?.fetchSourceManga.hasNextPage, + ); + + this.revalidateInitialPages( + isRevalidationDoneRef.current, + cachedResults.length, + cachedPages, + (isDone) => { + isRevalidationDoneRef.current = isDone; + }, + getVariablesFor, + triggerRerender, + revalidate, + ); + + return this.returnPaginatedMutationResult( + areInitialPagesFetched, + cachedResults, + getVariablesFor, + paginatedResult, + wrappedMutate, + hasCachedResult, + createPaginatedResult, + ); + } + + public useGetSourcePopularMangas( + sourceId: string, + initialPages?: number, + options?: ApolloPaginatedMutationOptions, + ): AbortableApolloUseMutationPaginatedResponse< + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables + > { + return this.useGetSourceMangas( + { type: FetchSourceMangaType.Popular, source: sourceId, page: 1 }, + initialPages, + options, + ); + } + + public useGetSourceLatestMangas( + sourceId: string, + initialPages?: number, + options?: ApolloPaginatedMutationOptions, + ): AbortableApolloUseMutationPaginatedResponse< + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables + > { + return this.useGetSourceMangas( + { type: FetchSourceMangaType.Latest, source: sourceId, page: 1 }, + initialPages, + options, + ); + } + + public setSourcePreferences( + source: string, + change: SourcePreferenceChangeInput, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest(GQLMethod.MUTATION, UPDATE_SOURCE_PREFERENCES, { input: { source, change } }, options); + } + + public useSourceSearch( + source: string, + query?: string, + filters?: FilterChangeInput[], + initialPages?: number, + options?: ApolloPaginatedMutationOptions, + ): AbortableApolloUseMutationPaginatedResponse< + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables + > { + return this.useGetSourceMangas( + { type: FetchSourceMangaType.Search, source, query, filters, page: 1 }, + initialPages, + options, + ); + } + + public useGetManga( + mangaId: number | string, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_MANGA, { id: Number(mangaId) }, options); + } + + public getMangaFetch( + mangaId: number | string, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + GET_MANGA_FETCH, + { + input: { + id: Number(mangaId), + }, + }, + options, + ); + } + + public useGetMangas( + variables: GetMangasQueryVariables, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_MANGAS, variables, options); + } + + public getMangaThumbnailUrl(mangaId: number): string { + return this.getValidImgUrlFor(`manga/${mangaId}/thumbnail`); + } + + public useUpdateMangaCategories( + options?: MutationHookOptions, + ): AbortableApolloUseMutationResponse { + const [mutate, result] = this.doRequest(GQLMethod.USE_MUTATION, UPDATE_MANGA_CATEGORIES, undefined, options); + + const wrappedMutate = (mutateOptions: Parameters[0]) => + mutate({ + onCompleted: () => { + this.graphQLClient.client.cache.evict({ fieldName: 'categories' }); + this.graphQLClient.client.cache.evict({ fieldName: 'category' }); + this.graphQLClient.client.cache.evict({ fieldName: 'mangas' }); + }, + ...mutateOptions, + }); + + return [wrappedMutate, result]; + } + + public updateManga( + id: number, + patch: UpdateMangaPatchInput, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + const result = this.doRequest( + GQLMethod.MUTATION, + UPDATE_MANGA, + { input: { id, patch } }, + options, + ); + + result.response.then(() => { + this.graphQLClient.client.cache.evict({ fieldName: 'categories' }); + this.graphQLClient.client.cache.evict({ fieldName: 'category' }); + this.graphQLClient.client.cache.evict({ fieldName: 'mangas' }); + }); + + return result; + } + + public setMangaMeta( + mangaId: number, + key: string, + value: any, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + SET_MANGA_METADATA, + { + input: { meta: { mangaId, key, value: `${value}` } }, + }, + options, + ); + } + + public useGetChapters( + variables: GetChaptersQueryVariables, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_CHAPTERS, variables, options); + } + + public useGetMangaChapters( + mangaId: number | string, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.useGetChapters( + { + condition: { mangaId: Number(mangaId) }, + orderBy: ChapterOrderBy.SourceOrder, + orderByType: SortOrder.Desc, + }, + options, + ); + } + + public getMangaChaptersFetch( + mangaId: number | string, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + GET_MANGA_CHAPTERS_FETCH, + { input: { mangaId: Number(mangaId) } }, + { refetchQueries: [GET_MANGA, GET_CHAPTERS], ...options }, + ); + } + + public useGetMangaChapter( + mangaId: number | string, + chapterIndex: number | string, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse< + Omit & { chapter: GetChaptersQuery['chapters']['nodes'][number] }, + GetChaptersQueryVariables + > { + type Response = AbortableApolloUseQueryResponse< + Omit & { chapter: GetChaptersQuery['chapters']['nodes'][number] }, + GetChaptersQueryVariables + >; + + const chapterResponse = this.useGetChapters( + { condition: { mangaId: Number(mangaId), sourceOrder: Number(chapterIndex) } }, + options, + ); + + if (!chapterResponse.data) { + return chapterResponse as unknown as Response; + } + + return { + ...chapterResponse, + data: { + chapter: chapterResponse.data.chapters.nodes[0], + }, + } as unknown as Response; + } + + public getChapter( + mangaId: number | string, + chapterIndex: number | string, + options?: QueryOptions, + ): AbortabaleApolloQueryResponse< + Omit & { chapter: GetChaptersQuery['chapters']['nodes'][number] } + > { + type ResponseData = Omit & { + chapter: GetChaptersQuery['chapters']['nodes'][number]; + }; + + const chapterRequest = this.doRequest( + GQLMethod.QUERY, + GET_CHAPTERS, + { + condition: { mangaId: Number(mangaId), sourceOrder: Number(chapterIndex) }, + }, + options, + ); + + return { + ...chapterRequest, + response: chapterRequest.response.then((chapterResponse) => { + if (!chapterResponse.data) { + return chapterResponse; + } + + return { + ...chapterResponse, + data: { + chapter: chapterResponse.data.chapters.nodes[0], + }, + }; + }) as Promise>, + }; + } + + public useGetChapterPagesFetch( + chapterId: string | number, + options?: MutationHookOptions, + ): AbortableApolloUseMutationResponse { + return this.doRequest( + GQLMethod.USE_MUTATION, + GET_CHAPTER_PAGES_FETCH, + { + input: { chapterId: Number(chapterId) }, + }, + options, + ); + } + + public deleteDownloadedChapter( + id: number, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + DELETE_DOWNLOADED_CHAPTER, + { input: { id } }, + options, + ); + } + + public deleteDownloadedChapters( + ids: number[], + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + DELETE_DOWNLOADED_CHAPTERS, + { input: { ids } }, + options, + ); + } + + public updateChapter( + id: number, + patch: UpdateChapterPatchInput, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + UPDATE_CHAPTER, + { input: { id, patch } }, + { refetchQueries: [GET_MANGA], ...options }, + ); + } + + public setChapterMeta( + chapterId: number, + key: string, + value: any, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + SET_CHAPTER_METADATA, + { input: { meta: { chapterId, key, value: `${value}` } } }, + options, + ); + } + + public getChapterPageUrl(mangaId: number | string, chapterIndex: number | string, page: number): string { + return this.getValidImgUrlFor( + `manga/${mangaId}/chapter/${chapterIndex}/page/${page}`, + RequestManager.API_VERSION, + ); + } + + public updateChapters( + ids: number[], + patch: UpdateChapterPatchInput, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + UPDATE_CHAPTERS, + { input: { ids, patch } }, + { refetchQueries: [GET_MANGA], ...options }, + ); + } + + public useGetCategories( + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest( + GQLMethod.USE_QUERY, + GET_CATEGORIES, + { + orderBy: CategoryOrderBy.Order, + }, + options, + ); + } + + public createCategory( + input: CreateCategoryInput, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + CREATE_CATEGORY, + { input }, + { refetchQueries: [GET_CATEGORIES], ...options }, + ); + } + + public useReorderCategory( + options?: MutationHookOptions, + ): AbortableApolloUseMutationResponse { + const [mutate, result] = this.doRequest( + GQLMethod.USE_MUTATION, + UPDATE_CATEGORY_ORDER, + undefined, + options, + ); + + const wrappedMutate = (mutateOptions: Parameters[0]) => { + const variables = mutateOptions?.variables?.input; + const cachedCategories = this.graphQLClient.client.readQuery< + GetCategoriesQuery, + GetCategoriesQueryVariables + >({ + query: GET_CATEGORIES, + variables: { orderBy: CategoryOrderBy.Order }, + })?.categories.nodes; + + if (!variables) { + throw new Error('useReorderCategory: no variables passed'); + } + + if (!cachedCategories) { + throw new Error('useReorderCategory: there are no cached results'); + } + + const movedIndex = cachedCategories.findIndex((category) => category.id === variables.id); + const newData = [...cachedCategories.map((category) => ({ ...category }))]; + const [removed] = newData.splice(movedIndex, 1); + newData.splice(variables.position, 0, removed); + removed.order = variables.position; + newData[movedIndex].order = movedIndex; + + return mutate({ + update: (cache) => { + cache.updateQuery( + { + id: cache.identify({ __typename: 'CategoryNodeList' }), + query: GET_CATEGORIES, + variables: { orderBy: CategoryOrderBy.Order }, + }, + (data) => ({ + ...data!, + categories: { + ...data!.categories, + nodes: newData, + }, + }), + ); + }, + optimisticResponse: { + __typename: 'Mutation', + updateCategoryOrder: { + __typename: 'UpdateCategoryOrderPayload', + categories: newData, + }, + }, + ...mutateOptions, + }); + }; + + return [wrappedMutate, result]; + } + + public useGetCategoryMangas( + id: number, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + const isDefaultCategory = id === 0; + if (isDefaultCategory) { + // hacky way of loading the default category mangas - some stuff won't work but since that is not used anyway, it won't be a problem + // can't be loaded via "useGetMangas" because mangas are not actually mapped to the default category in the database + const { data, ...result } = this.doRequest( + GQLMethod.USE_QUERY, + GET_CATEGORY_MANGAS, + { id }, + ); + + return { + ...result, + data: data + ? { + ...data?.category, + __typename: 'Query', + } + : undefined, + } as unknown as AbortableApolloUseQueryResponse; + } + + return this.useGetMangas({ condition: { inLibrary: true, categoryIds: [id] } }, options); + } + + public deleteCategory( + categoryId: number, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + const result = this.doRequest( + GQLMethod.MUTATION, + DELETE_CATEGORY, + { input: { categoryId } }, + { + refetchQueries: [GET_CATEGORIES], + ...options, + }, + ); + + result.response.then(() => { + this.graphQLClient.client.cache.evict({ fieldName: 'category', id: categoryId.toString() }); + }); + + return result; + } + + public updateCategory( + id: number, + patch: UpdateCategoryPatchInput, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + UPDATE_CATEGORY, + { input: { id, patch } }, + options, + ); + } + + public setCategoryMeta( + categoryId: number, + key: string, + value: any, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + SET_CATEGORY_METADATA, + { input: { meta: { categoryId, key, value: `${value}` } } }, + options, + ); + } + + public restoreBackupFile( + file: File, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + const result = this.doRequest( + GQLMethod.MUTATION, + RESTORE_BACKUP, + { input: { backup: file } }, + { + ...options, + }, + ); + + result.response.then(() => { + this.graphQLClient.client.cache.reset(); + }); + + return result; + } + + public useValidateBackupFile( + file: File, + options?: QueryOptions, + ): AbortabaleApolloQueryResponse { + return this.doRequest(GQLMethod.QUERY, VALIDATE_BACKUP, { input: { backup: file } }, options); + } + + public getExportBackupUrl(): string { + return this.getValidUrlFor('backup/export/file'); + } + + public startDownloads( + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + START_DOWNLOADER, + {}, + options, + ); + } + + public stopDownloads( + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + STOP_DOWNLOADER, + {}, + options, + ); + } + + public clearDownloads( + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + CLEAR_DOWNLOADER, + {}, + options, + ); + } + + public addChapterToDownloadQueue( + id: number, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + ENQUEUE_CHAPTER_DOWNLOAD, + { input: { id } }, + options, + ); + } + + public removeChapterFromDownloadQueue( + id: number, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + DEQUEUE_CHAPTER_DOWNLOAD, + { input: { id } }, + options, + ); + } + + public reorderChapterInDownloadQueue( + chapterId: number, + position: number, + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + REORDER_CHAPTER_DOWNLOAD, + { input: { chapterId, to: position } }, + options, + ); + } + + public addChaptersToDownloadQueue( + ids: number[], + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + ENQUEUE_CHAPTER_DOWNLOADS, + { input: { ids } }, + options, + ); + } + + public removeChaptersFromDownloadQueue( + ids: number[], + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + DEQUEUE_CHAPTER_DOWNLOADS, + { input: { ids } }, + options, + ); + } + + public useGetRecentlyUpdatedChapters( + initialPages: number = 1, + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + const PAGE_SIZE = 50; + const CACHE_KEY = 'useGetRecentlyUpdatedChapters'; + + const offset = this.cache.getResponseFor(CACHE_KEY, undefined) ?? 0; + const [lastOffset] = useState(offset); + + const result = this.useGetChapters( + { + filter: { inLibrary: { equalTo: true } }, + orderBy: ChapterOrderBy.FetchedAt, + orderByType: SortOrder.Desc, + first: initialPages * PAGE_SIZE + lastOffset, + }, + options, + ); + + return { + ...result, + fetchMore: (...args: Parameters<(typeof result)['fetchMore']>) => { + const fetchMoreOptions = args[0] ?? {}; + this.cache.cacheResponse(CACHE_KEY, undefined, fetchMoreOptions.variables?.offset); + return result.fetchMore({ + ...fetchMoreOptions, + variables: { first: PAGE_SIZE, ...fetchMoreOptions.variables }, + }); + }, + } as typeof result; + } + + public startGlobalUpdate( + categories?: undefined, + options?: MutationOptions, + ): AbortableApolloMutationResponse; + + public startGlobalUpdate( + categories: number[], + options?: MutationOptions, + ): AbortableApolloMutationResponse; + + public startGlobalUpdate< + Data extends UpdateLibraryMangasMutation | UpdateCategoryMangasMutation, + Variables extends UpdateLibraryMangasMutationVariables | UpdateCategoryMangasMutationVariables, + >(categories?: number[], options?: MutationOptions): AbortableApolloMutationResponse { + if (categories?.length) { + return this.doRequest( + GQLMethod.MUTATION, + UPDATE_CATEGORY_MANGAS, + { input: { categories } }, + options as MutationOptions, + ) as AbortableApolloMutationResponse; + } + + return this.doRequest( + GQLMethod.MUTATION, + UPDATE_LIBRARY_MANGAS, + {}, + options as MutationOptions, + ) as AbortableApolloMutationResponse; + } + + public resetGlobalUpdate( + options?: MutationOptions, + ): AbortableApolloMutationResponse { + return this.doRequest( + GQLMethod.MUTATION, + STOP_UPDATER, + {}, + options, + ); + } + + public useGetGlobalUpdateSummary( + options?: QueryHookOptions, + ): AbortableApolloUseQueryResponse { + return this.doRequest(GQLMethod.USE_QUERY, GET_UPDATE_STATUS, {}, options); + } + + public useDownloadSubscription( + options?: SubscriptionHookOptions, + ): SubscriptionResult { + return this.doRequest(GQLMethod.USE_SUBSCRIPTION, DOWNLOAD_STATUS_SUBSCRIPTION, {}, options); + } + + public useUpdaterSubscription( + options?: SubscriptionHookOptions, + ): SubscriptionResult { + return this.doRequest(GQLMethod.USE_SUBSCRIPTION, UPDATER_SUBSCRIPTION, {}, options); + } +} + +const requestManager = new RequestManager(); +export default requestManager; diff --git a/src/lib/requests/client/BaseClient.ts b/src/lib/requests/client/BaseClient.ts new file mode 100644 index 00000000..8fee7e3f --- /dev/null +++ b/src/lib/requests/client/BaseClient.ts @@ -0,0 +1,32 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import storage from '@/util/localStorage.tsx'; + +// eslint-disable-next-line import/prefer-default-export +export abstract class BaseClient { + protected client!: Client; + + public abstract readonly fetcher: Fetcher; + + constructor() { + this.createClient(); + } + + public getBaseUrl(): string { + const { hostname, port, protocol } = window.location; + + // if port is 3000 it's probably running from webpack development server + const inferredPort = port === '3000' ? '4567' : port; + return storage.getItem('serverBaseURL', `${protocol}//${hostname}:${inferredPort}`); + } + + protected abstract createClient(): void; + + public abstract updateConfig(config: Partial): void; +} diff --git a/src/lib/requests/client/GraphQLClient.ts b/src/lib/requests/client/GraphQLClient.ts new file mode 100644 index 00000000..c2fef6a4 --- /dev/null +++ b/src/lib/requests/client/GraphQLClient.ts @@ -0,0 +1,109 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import { + ApolloClient, + ApolloClientOptions, + InMemoryCache, + NormalizedCacheObject, + Reference, + split, +} from '@apollo/client'; +import { createUploadLink } from 'apollo-upload-client'; +import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; +import { Client, createClient } from 'graphql-ws'; +import { getMainDefinition } from '@apollo/client/utilities'; +import { BaseClient } from '@/lib/requests/client/BaseClient.ts'; +import { StrictTypedTypePolicies } from '@/lib/graphql/generated/apollo-helpers.ts'; + +/* eslint-disable no-underscore-dangle */ +const typePolicies: StrictTypedTypePolicies = { + GlobalMetaType: { keyFields: ['key'] }, + ExtensionType: { keyFields: ['apkName'] }, + AboutPayload: { keyFields: [] }, + Query: { + fields: { + chapters: { + keyArgs: ['condition', 'filter', 'orderBy', 'orderByType'], + merge(existing, incoming) { + const merged = { + ...existing, + ...incoming, + nodes: existing?.nodes ?? [], + }; + const isRefetch = incoming.nodes.some( + (incomingChapter) => + existing?.nodes.some( + (existingChapter) => + (existingChapter as unknown as Reference).__ref === + (incomingChapter as unknown as Reference).__ref, + ), + ); + if (!isRefetch) { + merged.nodes = [...(existing?.nodes ?? []), ...incoming.nodes]; + } + return merged; + }, + }, + }, + }, +}; +/* eslint-enable no-underscore-dangle */ + +// eslint-disable-next-line import/prefer-default-export +export class GraphQLClient extends BaseClient< + ApolloClient, + ApolloClientOptions, + null +> { + readonly fetcher = null; + + public declare client: ApolloClient; + + private wsClient!: Client; + + public override getBaseUrl(): string { + return `${super.getBaseUrl()}/api/graphql`; + } + + private createUploadLink() { + return createUploadLink({ uri: () => this.getBaseUrl() }); + } + + private createWSLink() { + return new GraphQLWsLink(this.wsClient); + } + + private createLink() { + return split( + ({ query }) => { + const definition = getMainDefinition(query); + return definition.kind === 'OperationDefinition' && definition.operation === 'subscription'; + }, + this.createWSLink(), + this.createUploadLink(), + ); + } + + protected createClient() { + this.wsClient = createClient({ + url: () => this.getBaseUrl().replace(/http(|s)/g, 'ws'), + keepAlive: 20000, + }); + + this.client = new ApolloClient({ + cache: new InMemoryCache({ + typePolicies, + }), + connectToDevTools: true, + link: this.createLink(), + }); + } + + public override updateConfig() {} +} diff --git a/src/lib/RestClient.ts b/src/lib/requests/client/RestClient.ts similarity index 85% rename from src/lib/RestClient.ts rename to src/lib/requests/client/RestClient.ts index d4ff8d69..a21adef1 100644 --- a/src/lib/RestClient.ts +++ b/src/lib/requests/client/RestClient.ts @@ -7,7 +7,7 @@ */ import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; -import storage from '@/util/localStorage'; +import { BaseClient } from '@/lib/requests/client/BaseClient.ts'; export enum HttpMethod { GET = 'get', @@ -28,13 +28,10 @@ export interface IRestClient { patch>(url: string, data?: any): Promise; } -export class RestClient implements IRestClient { - protected client!: AxiosInstance; - - constructor() { - this.createClient(); - } - +export class RestClient + extends BaseClient(url: string, data: any) => Promise> + implements IRestClient +{ public readonly fetcher = async ( url: string, { @@ -75,12 +72,8 @@ export class RestClient implements IRestClient { return result.data; }; - private createClient(): void { - const { hostname, port, protocol } = window.location; - - // if port is 3000 it's probably running from webpack development server - const inferredPort = port === '3000' ? '4567' : port; - const baseURL = storage.getItem('serverBaseURL', `${protocol}//${hostname}:${inferredPort}`); + protected override createClient(): void { + const baseURL = this.getBaseUrl(); this.client = axios.create({ // baseURL must not have trailing slash diff --git a/src/screens/DownloadQueue.tsx b/src/screens/DownloadQueue.tsx index ea76fab4..325ecc14 100644 --- a/src/screens/DownloadQueue.tsx +++ b/src/screens/DownloadQueue.tsx @@ -18,31 +18,27 @@ import { DragDropContext, Draggable } from 'react-beautiful-dnd'; import Typography from '@mui/material/Typography'; import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { IChapter, IQueue } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import StrictModeDroppable from '@/lib/StrictModeDroppable'; import makeToast from '@/components/util/Toast'; import { NavbarToolbar } from '@/components/navbar/DefaultNavBar'; import DownloadStateIndicator from '@/components/molecules/DownloadStateIndicator'; -import useSubscription from '@/components/library/useSubscription'; import EmptyView from '@/components/util/EmptyView'; import NavbarContext from '@/components/context/NavbarContext'; - -const initialQueue = { - status: 'Stopped', - queue: [], -} as IQueue; +import { DownloadType } from '@/lib/graphql/generated/graphql.ts'; +import { TChapter } from '@/typings.ts'; const DownloadQueue: React.FC = () => { const { t } = useTranslation(); - const { data: queueState } = useSubscription('downloads'); - const { queue, status } = queueState ?? initialQueue; + const { data: downloaderData } = requestManager.useDownloadSubscription(); + const queue = (downloaderData?.downloadChanged.queue as DownloadType[]) ?? []; + const status = downloaderData?.downloadChanged.state ?? 'STARTED'; const { setTitle, setAction } = useContext(NavbarContext); const toggleQueueStatus = () => { - if (status === 'Stopped') { + if (status === 'STOPPED') { requestManager.startDownloads(); } else { requestManager.stopDownloads(); @@ -60,8 +56,8 @@ const DownloadQueue: React.FC = () => { return ; } - const handleDelete = async (chapter: IChapter) => { - const isRunning = status === 'Started'; + const handleDelete = async (chapter: TChapter) => { + const isRunning = status === 'STARTED'; try { if (isRunning) { @@ -71,10 +67,10 @@ const DownloadQueue: React.FC = () => { await Promise.all([ // remove from download queue - requestManager.removeChapterFromDownloadQueue(chapter.mangaId, chapter.index).response, + requestManager.removeChapterFromDownloadQueue(chapter.id).response, // delete partial download, should be handle server side? // bug: The folder and the last image downloaded are not deleted - requestManager.deleteDownloadedChapter(chapter.mangaId, chapter.index).response, + requestManager.deleteDownloadedChapter(chapter.id).response, ]); } catch (error) { makeToast(t('download.queue.error.label.failed_to_remove'), 'error'); @@ -91,7 +87,7 @@ const DownloadQueue: React.FC = () => { <> - {status === 'Stopped' ? : } + {status === 'STOPPED' ? : } @@ -100,8 +96,8 @@ const DownloadQueue: React.FC = () => { {queue.map((item, index) => ( {(draggableProvided, snapshot) => ( @@ -129,7 +125,7 @@ const DownloadQueue: React.FC = () => { - {item.manga.title} + {item.chapter.manga.title} {item.chapter.name} diff --git a/src/screens/Extensions.tsx b/src/screens/Extensions.tsx index 62ef028e..aeb5172e 100644 --- a/src/screens/Extensions.tsx +++ b/src/screens/Extensions.tsx @@ -14,8 +14,7 @@ import { StringParam, useQueryParam } from 'use-query-params'; import { Virtuoso } from 'react-virtuoso'; import { Typography, useMediaQuery, useTheme } from '@mui/material'; import { useTranslation } from 'react-i18next'; -import { IExtension } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import { extensionDefaultLangs, DefaultLanguage, langSortCmp } from '@/util/language'; import useLocalStorage from '@/util/useLocalStorage'; import { @@ -31,11 +30,12 @@ import { makeToaster } from '@/components/util/Toast'; import LangSelect from '@/components/navbar/action/LangSelect'; import NavbarContext from '@/components/context/NavbarContext'; import ExtensionCard from '@/components/ExtensionCard'; +import { PartialExtension } from '@/typings.ts'; const LANGUAGE = 0; const EXTENSIONS = 1; -function getExtensionsInfo(extensions: IExtension[]): { +function getExtensionsInfo(extensions: PartialExtension[]): { allLangs: string[]; groupedExtensions: GroupedExtensionsResult; } { @@ -55,12 +55,12 @@ function getExtensionsInfo(extensions: IExtension[]): { allLangs.push(extension.lang); } } - if (extension.installed) { + if (extension.isInstalled) { if (extension.hasUpdate) { sortedExtensions[ExtensionState.UPDATE_PENDING].push(extension); return; } - if (extension.obsolete) { + if (extension.isObsolete) { sortedExtensions[ExtensionState.OBSOLETE].push(extension); return; } @@ -100,7 +100,17 @@ export default function MangaExtensions() { const isMobile = useMediaQuery(theme.breakpoints.down('sm')); const [query] = useQueryParam('query', StringParam); - const { data: allExtensions, mutate, isLoading } = requestManager.useGetExtensionList(); + const [extensionsTimestamp, setExtensionsTimestamp] = useLocalStorage('extensionsTimestamp', 0); + const [fetchExtensions, { loading: isFetching }] = requestManager.useExtensionListFetch(); + const { data, loading: isLoading } = requestManager.useGetExtensionList(); + const allExtensions = data?.extensions.nodes; + + useEffect(() => { + const updateExtensionsList = Date.now() - extensionsTimestamp >= 1000 * 60; // update list in case it's older than 1 minute + if (updateExtensionsList) { + fetchExtensions().catch(() => setExtensionsTimestamp(Date.now())); + } + }, []); const filteredExtensions = useMemo( () => @@ -122,7 +132,7 @@ export default function MangaExtensions() { [shownLangs, groupedExtensions], ); - const flatRenderItems: (IExtension | string)[] = filteredGroupedExtensions.flat(2); + const flatRenderItems: (PartialExtension | string)[] = filteredGroupedExtensions.flat(2); const [toasts, makeToast] = makeToaster(useState([])); @@ -134,10 +144,9 @@ export default function MangaExtensions() { makeToast(t('extension.label.installing_file'), 'info'); requestManager - .installExtension(file) + .installExternalExtension(file) .response.then(() => { makeToast(t('extension.label.installed_successfully'), 'success'); - mutate(); }) .catch(() => makeToast(t('extension.label.installation_failed'), 'error')); } else { @@ -156,7 +165,7 @@ export default function MangaExtensions() { , ); - }, [t, shownLangs]); + }, [t, shownLangs, allLangs]); useEffect(() => { const dropHandler = async (e: Event) => { @@ -178,7 +187,7 @@ export default function MangaExtensions() { }; }, []); - if (isLoading) { + if (isLoading || isFetching) { return ; } @@ -220,17 +229,9 @@ export default function MangaExtensions() { ); } - const item = flatRenderItems[index] as IExtension; + const item = flatRenderItems[index] as PartialExtension; - return ( - { - mutate(); - }} - /> - ); + return ; }} /> diff --git a/src/screens/Library.tsx b/src/screens/Library.tsx index b0539cec..dc13bbe3 100644 --- a/src/screens/Library.tsx +++ b/src/screens/Library.tsx @@ -7,10 +7,10 @@ */ import { Chip, Tab, Tabs, styled, Box } from '@mui/material'; -import React, { useContext, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useContext, useEffect, useMemo } from 'react'; import { useQueryParam, NumberParam } from 'use-query-params'; import { useTranslation } from 'react-i18next'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import NavbarContext from '@/components/context/NavbarContext'; import EmptyView from '@/components/util/EmptyView'; import LoadingPlaceholder from '@/components/util/LoadingPlaceholder'; @@ -62,20 +62,34 @@ export default function Library() { const { t } = useTranslation(); const { options } = useLibraryOptionsContext(); - const [lastLibraryUpdate, setLastLibraryUpdate] = useState(Date.now()); - const { data: tabsData, error: tabsError, isLoading: areCategoriesLoading } = requestManager.useGetCategories(); + const { + data: categoriesResponse, + error: tabsError, + loading: areCategoriesLoading, + refetch, + } = requestManager.useGetCategories(); + const tabsData = categoriesResponse?.categories.nodes.filter( + (category) => category.id !== 0 || (category.id === 0 && category.mangas.totalCount), + ); const tabs = tabsData ?? []; - const librarySize = useMemo(() => tabs.map((tab) => tab.size).reduce((prev, curr) => prev + curr, 0), [tabs]); + const librarySize = useMemo( + () => tabs.map((tab) => tab.mangas.totalCount).reduce((prev, curr) => prev + curr, 0), + [tabs], + ); const [tabSearchParam, setTabSearchParam] = useQueryParam('tab', NumberParam); const activeTab = tabs.find((tab) => tab.order === tabSearchParam) ?? tabs[0]; const { - data: mangaData, + data: categoryMangaResponse, error: mangaError, - isLoading: mangaLoading, - } = requestManager.useGetCategoryMangas(activeTab?.id, { skipRequest: !activeTab }); - const mangas = mangaData ?? []; + loading: mangaLoading, + } = requestManager.useGetCategoryMangas(activeTab?.id, { skip: !activeTab, nextFetchPolicy: 'cache-only' }); + const mangas = categoryMangaResponse?.mangas.nodes ?? []; + + const handleFinishedUpdate = useCallback(() => { + refetch(); + }, [refetch]); const { setTitle, setAction } = useContext(NavbarContext); useEffect(() => { @@ -91,7 +105,7 @@ export default function Library() { <> - + , ); return () => { @@ -101,14 +115,14 @@ export default function Library() { }, [t, librarySize, areCategoriesLoading, options]); const handleTabChange = (newTab: number) => { - setTabSearchParam(newTab === 0 ? undefined : newTab); + setTabSearchParam(newTab); }; if (tabsError != null) { return ( ); } @@ -125,7 +139,6 @@ export default function Library() { return ( @@ -154,7 +167,7 @@ export default function Library() { label={ {tab.name} - {options.showTabSize ? : null} + {options.showTabSize ? : null} } value={tab.order} @@ -167,12 +180,11 @@ export default function Library() { (mangaError ? ( ) : ( diff --git a/src/screens/Manga.tsx b/src/screens/Manga.tsx index 3660c23c..7768d0a1 100644 --- a/src/screens/Manga.tsx +++ b/src/screens/Manga.tsx @@ -11,7 +11,8 @@ import { CircularProgress, IconButton, Stack, Tooltip, Box } from '@mui/material import React, { useContext, useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; -import requestManager from '@/lib/RequestManager'; +import { isNetworkRequestInFlight } from '@apollo/client/core/networkStatus'; +import requestManager from '@/lib/requests/RequestManager.ts'; import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext'; import ChapterList from '@/components/manga/ChapterList'; import { useRefreshManga } from '@/components/manga/hooks'; @@ -20,7 +21,7 @@ import MangaToolbarMenu from '@/components/manga/MangaToolbarMenu'; import EmptyView from '@/components/util/EmptyView'; import LoadingPlaceholder from '@/components/util/LoadingPlaceholder'; -const AUTOFETCH_AGE = 60 * 60 * 24; // 24 hours +const AUTOFETCH_AGE = 1000 * 60 * 60 * 24; // 24 hours const Manga: React.FC = () => { const { t } = useTranslation(); @@ -29,21 +30,26 @@ const Manga: React.FC = () => { const { id } = useParams<{ id: string }>(); const autofetchedRef = useRef(false); - const { data: manga, error, isLoading, isValidating, mutate } = requestManager.useGetManga(id); + const { data, error, loading: isLoading, networkStatus, refetch } = requestManager.useGetManga(id); + const isValidating = isNetworkRequestInFlight(networkStatus); + const manga = data?.manga; const [refresh, { loading: refreshing }] = useRefreshManga(id); useSetDefaultBackTo('library'); useEffect(() => { - // Automatically fetch manga from source if data is older then 24 hours + // Automatically fetch manga from source if data is older then 24 hours OR manga is not initialized yet // Automatic fetch is done only once, to prevent issues when server does // not update age for some reason (ie. error on source side) if (manga == null) return; - if ( - manga.inLibrary && - (manga.age > AUTOFETCH_AGE || manga.chaptersAge > AUTOFETCH_AGE) && - autofetchedRef.current === false - ) { + + const isOutdated = + Date.now() - Number(manga.lastFetchedAt) * 1000 > AUTOFETCH_AGE || + Date.now() - Number(manga.chaptersLastFetchedAt) * 1000 > AUTOFETCH_AGE; + const refetchBecauseOutdated = manga.inLibrary && isOutdated; + + const doFetch = !autofetchedRef.current && (refetchBecauseOutdated || !manga.initialized); + if (doFetch) { autofetchedRef.current = true; refresh(); } @@ -67,7 +73,7 @@ const Manga: React.FC = () => { } > - mutate()}> + refetch()}> @@ -80,7 +86,7 @@ const Manga: React.FC = () => { {manga && } , ); - }, [t, error, isValidating, refreshing, mutate, manga, refresh]); + }, [t, error, isValidating, refreshing, manga, refresh]); if (error && !manga) { return ; @@ -90,7 +96,7 @@ const Manga: React.FC = () => { {isLoading && } {manga && } - + {manga && } ); }; diff --git a/src/screens/Reader.tsx b/src/screens/Reader.tsx index 4d19b798..e6baa514 100644 --- a/src/screens/Reader.tsx +++ b/src/screens/Reader.tsx @@ -7,12 +7,12 @@ */ import CircularProgress from '@mui/material/CircularProgress'; -import { useCallback, useContext, useEffect, useState } from 'react'; +import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; import { Box } from '@mui/material'; import { useTranslation } from 'react-i18next'; -import { ChapterOffset, IChapter, IManga, IMangaCard, IReaderSettings, ReaderType, TranslationKey } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import { ChapterOffset, IReaderSettings, ReaderType, TChapter, TManga, TranslationKey } from '@/typings'; +import requestManager from '@/lib/requests/RequestManager.ts'; import { checkAndHandleMissingStoredReaderSettings, getReaderSettingsFor, @@ -28,10 +28,10 @@ import ReaderNavBar from '@/components/navbar/ReaderNavBar'; import NavbarContext from '@/components/context/NavbarContext'; import makeToast from '@/components/util/Toast'; -const isDupChapter = async (chapterIndex: number, currentChapter: IChapter) => { - const nextChapter = await requestManager.getChapter(currentChapter.mangaId, chapterIndex).response; +const isDupChapter = async (chapterIndex: number, currentChapter: TChapter) => { + const nextChapter = await requestManager.getChapter(currentChapter.manga.id, chapterIndex).response; - return nextChapter.chapterNumber === currentChapter.chapterNumber; + return nextChapter.data.chapter.chapterNumber === currentChapter.chapterNumber; }; /** @@ -41,7 +41,7 @@ const isDupChapter = async (chapterIndex: number, currentChapter: IChapter) => { */ const getOffsetChapter = async ( chapterIndex: number, - currentChapter: IChapter, + currentChapter: TChapter, skipDupChapters: boolean, offset: ChapterOffset, ): Promise => { @@ -81,11 +81,11 @@ const getReaderComponent = (readerType: ReaderType) => { const range = (n: number) => Array.from({ length: n }, (value, key) => key); const initialChapter = { pageCount: -1, - index: -1, + sourceOrder: -1, chapterCount: 0, lastPageRead: 0, name: 'Loading...', -}; +} as unknown as TChapter; export default function Reader() { const { t } = useTranslation(); @@ -93,22 +93,58 @@ export default function Reader() { const location = useLocation(); const { chapterIndex, mangaId } = useParams<{ chapterIndex: string; mangaId: string }>(); - const { - data: manga = { - id: +mangaId, - title: '', - thumbnailUrl: '', - genre: [], - inLibraryAt: 0, - lastReadAt: 0, - } as IMangaCard | IManga, - isLoading: isMangaLoading, - } = requestManager.useGetManga(mangaId); - const { data: chapter = initialChapter, isLoading: isChapterLoading } = requestManager.useGetChapter( - mangaId, - chapterIndex, - { disableCache: true, revalidateOnFocus: false }, + + const initialManga = useMemo( + () => + ({ + id: +mangaId, + title: '', + thumbnailUrl: '', + genre: [], + inLibraryAt: 0, + lastReadAt: 0, + chapters: { totalCount: 0 }, + }) as unknown as TManga, + [mangaId], ); + + const { data, loading: isMangaLoading } = requestManager.useGetManga(mangaId); + const loadedChapter = useRef(null); + const isChapterLoaded = + Number(mangaId) === loadedChapter.current?.manga.id && + Number(chapterIndex) === loadedChapter.current?.sourceOrder && + loadedChapter.current?.pageCount !== -1; + const manga = data?.manga ?? initialManga; + const { data: chapterData, loading: isChapterLoading } = requestManager.useGetMangaChapter(mangaId, chapterIndex, { + skip: isChapterLoaded, + }); + + const getLoadedChapter = () => { + const isAChapterLoaded = loadedChapter.current; + + const isSameAsLoadedChapter = isAChapterLoaded && isChapterLoaded; + if (isSameAsLoadedChapter) { + return loadedChapter.current; + } + + if (chapterData?.chapter) { + return chapterData.chapter; + } + + return null; + }; + loadedChapter.current = getLoadedChapter(); + + const chapter = loadedChapter.current ?? initialChapter; + const [fetchPages, { loading: areChapterPagesLoading }] = requestManager.useGetChapterPagesFetch(chapter.id); + + useEffect(() => { + if (!isChapterLoading && chapter.pageCount === -1) { + fetchPages(); + } + }, [chapter.id]); + + const isLoading = isChapterLoading || areChapterPagesLoading || chapter.pageCount === -1; const [wasLastPageReadSet, setWasLastPageReadSet] = useState(false); const [curPage, setCurPage] = useState(0); const [pageToScrollTo, setPageToScrollTo] = useState(undefined); @@ -130,12 +166,7 @@ export default function Reader() { setRetrievingNextChapter(true); try { setHistory( - await getOffsetChapter( - chapter.index + offset, - chapter as IChapter, - settings.skipDupChapters, - offset, - ), + await getOffsetChapter(chapter.sourceOrder + offset, chapter, settings.skipDupChapters, offset), ); } catch (error) { const offsetToTranslationKeyMap: { [chapterOffset in ChapterOffset]: TranslationKey } = { @@ -152,7 +183,7 @@ export default function Reader() { ); useEffect(() => { - if (isChapterLoading || !chapter) { + if (isLoading || !chapter) { return; } @@ -161,13 +192,13 @@ export default function Reader() { // last page, also probably read = true, we will load the first page. setCurPage(0); } else setCurPage(chapter.lastPageRead); - }, [chapter, isChapterLoading]); + }, [chapter, isLoading]); useEffect(() => { - if (!manga?.title || (chapter as IChapter)?.name === t('global.label.loading')) { + if (!manga?.title || chapter.name === t('global.label.loading')) { setTitle(t('reader.title')); } else { - setTitle(`${manga.title}: ${(chapter as IChapter).name}`); + setTitle(`${manga.title}: ${chapter.name}`); } }, [t, manga, chapter]); @@ -187,7 +218,7 @@ export default function Reader() { settings={settings} setSettingValue={setSettingValue} manga={manga} - chapter={chapter as IChapter} + chapter={chapter} curPage={curPage} scrollToPage={setPageToScrollTo} openNextChapter={openNextChapter} @@ -206,20 +237,23 @@ export default function Reader() { } // do not mutate the chapter, this will cause the page to jump around due to always scrolling to the last read page - if (curPage !== -1) { - requestManager.updateChapter(manga.id, chapter.index, { lastPageRead: curPage }); - } + const updateLastPageRead = curPage !== -1; + const updateIsRead = curPage === chapter.pageCount - 1; + const updateChapter = updateLastPageRead || updateIsRead; - if (curPage === chapter.pageCount - 1) { - requestManager.updateChapter(manga.id, chapter.index, { read: true }); + if (updateChapter) { + requestManager.updateChapter(chapter.id, { + lastPageRead: updateLastPageRead ? curPage : undefined, + isRead: updateIsRead ? true : undefined, + }); } }, [curPage]); const nextChapter = useCallback(() => { - if (chapter.index < chapter.chapterCount) { - requestManager.updateChapter(manga.id, chapter.index, { + if (chapter.sourceOrder < manga.chapters.totalCount) { + requestManager.updateChapter(chapter.id, { lastPageRead: chapter.pageCount - 1, - read: true, + isRead: true, }); openNextChapter(ChapterOffset.NEXT, (nextChapterIndex) => @@ -229,10 +263,10 @@ export default function Reader() { }), ); } - }, [chapter.index, chapter.chapterCount, chapter.pageCount, manga.id, settings.skipDupChapters]); + }, [chapter.sourceOrder, manga.chapters.totalCount, chapter.pageCount, manga.id, settings.skipDupChapters]); const prevChapter = useCallback(() => { - if (chapter.index > 1) { + if (chapter.sourceOrder > 1) { openNextChapter(ChapterOffset.PREV, (prevChapterIndex) => navigate(`/manga/${manga.id}/chapter/${prevChapterIndex}`, { replace: true, @@ -240,7 +274,7 @@ export default function Reader() { }), ); } - }, [chapter.index, manga.id, settings.skipDupChapters]); + }, [chapter.sourceOrder, manga.id, settings.skipDupChapters]); // return spinner while chpater data is loading if (chapter.pageCount === -1) { @@ -277,6 +311,7 @@ export default function Reader() { > { const { t } = useTranslation(); - const skipRequest = !searchString; const { id, displayName, lang } = source; - const { - data: searchResult, - isLoading, - error, - abortRequest, - } = requestManager.useSourceQuickSearch(id, searchString ?? '', [], 1, { skipRequest }); - const mangas = !isLoading ? searchResult?.[0]?.mangaList ?? [] : []; + const [, results] = requestManager.useSourceSearch(id, searchString ?? '', undefined, 1, { + skipRequest: !searchString, + }); + const { data: searchResult, isLoading, error, abortRequest } = results[0]!; + const mangas = searchResult?.fetchSourceManga.mangas ?? []; const noMangasFound = !isLoading && !mangas.length; useEffect(() => { @@ -169,7 +166,8 @@ const SearchAll: React.FC = () => { const [shownLangs, setShownLangs] = useLocalStorage('shownSourceLangs', sourceDefualtLangs()); const [showNsfw] = useLocalStorage('showNsfw', true); - const { data: sources = [] } = requestManager.useGetSourceList(); + const { data } = requestManager.useGetSourceList(); + const sources = data?.sources.nodes ?? []; const [sourceToLoadingStateMap, setSourceToLoadingStateMap] = useState(new Map()); const debouncedSourceToLoadingStateMap = useDebounce(sourceToLoadingStateMap, 500); diff --git a/src/screens/Settings.tsx b/src/screens/Settings.tsx index d38bcb00..8cc66045 100644 --- a/src/screens/Settings.tsx +++ b/src/screens/Settings.tsx @@ -35,7 +35,7 @@ import ViewModuleIcon from '@mui/icons-material/ViewModule'; import { useTranslation } from 'react-i18next'; import LanguageIcon from '@mui/icons-material/Language'; import CollectionsOutlinedBookmarkIcon from '@mui/icons-material/CollectionsBookmarkOutlined'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import { langCodeToName } from '@/util/language'; import useLocalStorage from '@/util/useLocalStorage'; import ListItemLink from '@/components/util/ListItemLink'; diff --git a/src/screens/SourceConfigure.tsx b/src/screens/SourceConfigure.tsx index 0b761c66..243106bd 100644 --- a/src/screens/SourceConfigure.tsx +++ b/src/screens/SourceConfigure.tsx @@ -10,19 +10,20 @@ import { createElement, useContext, useEffect } from 'react'; import { useParams } from 'react-router-dom'; import List from '@mui/material/List'; import { useTranslation } from 'react-i18next'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import cloneObject from '@/util/cloneObject'; import NavbarContext from '@/components/context/NavbarContext'; import { SwitchPreferenceCompat, CheckBoxPreference } from '@/components/sourceConfiguration/TwoStatePreference'; import ListPreference from '@/components/sourceConfiguration/ListPreference'; import EditTextPreference from '@/components/sourceConfiguration/EditTextPreference'; import MultiSelectListPreference from '@/components/sourceConfiguration/MultiSelectListPreference'; +import { PreferenceProps } from '@/typings.ts'; function getPrefComponent(type: string) { switch (type) { case 'CheckBoxPreference': return CheckBoxPreference; - case 'SwitchPreferenceCompat': + case 'SwitchPreference': return SwitchPreferenceCompat; case 'ListPreference': return ListPreference; @@ -31,7 +32,7 @@ function getPrefComponent(type: string) { case 'MultiSelectListPreference': return MultiSelectListPreference; default: - return CheckBoxPreference; + throw new Error(`Unexpected preference type "${type}"`); } } @@ -45,33 +46,26 @@ export default function SourceConfigure() { }, [t]); const { sourceId } = useParams<{ sourceId: string }>(); - const { data: sourcePreferences = [], mutate } = requestManager.useGetSourcePreferences(sourceId); + const { data } = requestManager.useGetSource(sourceId); + const sourcePreferences = data?.source.preferences ?? []; - const convertToString = (position: number, value: any): string => { - switch (sourcePreferences[position].props.defaultValueType) { - case 'Set': - return JSON.stringify(value); - default: - return value.toString(); - } - }; - - const updateValue = (position: number) => (value: any) => { - requestManager - .setSourcePreferences(sourceId, position, convertToString(position, value)) - .response.then(() => mutate()); - }; + const updateValue = + (position: number): PreferenceProps['updateValue'] => + (type, value) => { + requestManager.setSourcePreferences(sourceId, { position, [type]: value }); + }; return ( {sourcePreferences.map((it, index) => { - const props = cloneObject(it.props); - props.updateValue = updateValue(index); - props.key = index; + const props = cloneObject(it); // TypeScript is dumb in detecting extra props // @ts-ignore - return createElement(getPrefComponent(it.type), props); + return createElement(getPrefComponent(it.type), { + ...props, + updateValue: updateValue(index), + }); })} ); diff --git a/src/screens/SourceMangas.tsx b/src/screens/SourceMangas.tsx index 8f932627..442a6012 100644 --- a/src/screens/SourceMangas.tsx +++ b/src/screens/SourceMangas.tsx @@ -17,8 +17,8 @@ import { Box, Button, styled, useTheme, useMediaQuery } from '@mui/material'; import FavoriteIcon from '@mui/icons-material/Favorite'; import NewReleasesIcon from '@mui/icons-material/NewReleases'; import FilterListIcon from '@mui/icons-material/FilterList'; -import { IManga, PaginatedMangaList, TranslationKey } from '@/typings'; -import requestManager, { AbortableSWRInfiniteResponse } from '@/lib/RequestManager'; +import { TPartialManga, TranslationKey } from '@/typings'; +import requestManager, { AbortableApolloUseMutationPaginatedResponse } from '@/lib/requests/RequestManager.ts'; import { useDebounce } from '@/components/manga/hooks'; import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext'; import SourceGridLayout from '@/components/source/GridLayouts'; @@ -26,6 +26,10 @@ import AppbarSearch from '@/components/util/AppbarSearch'; import SourceOptions from '@/components/source/SourceOptions'; import NavbarContext from '@/components/context/NavbarContext'; import SourceMangaGrid from '@/components/source/SourceMangaGrid'; +import { + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables, +} from '@/lib/graphql/generated/graphql.ts'; const ContentTypeMenu = styled('div')(({ theme }) => ({ display: 'flex', @@ -69,6 +73,7 @@ export enum SourceContentType { } interface IPos { + type: 'selectState' | 'textState' | 'checkBoxState' | 'triState' | 'sortState'; position: number; state: any; group?: number; @@ -81,15 +86,8 @@ const SOURCE_CONTENT_TYPE_TO_ERROR_MSG_KEY: { [contentType in SourceContentType] [SourceContentType.SEARCH]: 'manga.error.label.no_mangas_found', }; -type SourceMangaResponse = Omit, 'data'> & { - data: { - items: IManga[]; - hasNextPage: boolean; - }; -}; - -const getUniqueMangas = (mangas: IManga[]): IManga[] => { - const uniqueMangas: IManga[] = []; +const getUniqueMangas = (mangas: TPartialManga[]): TPartialManga[] => { + const uniqueMangas: TPartialManga[] = []; mangas.forEach((manga) => { const isDuplicate = uniqueMangas.some((uniqueManga) => uniqueManga.id === manga.id); @@ -106,9 +104,18 @@ const useSourceManga = ( contentType: SourceContentType, searchTerm: string | null | undefined, filters: IPos[], - initialPages = 1, -): SourceMangaResponse => { - let result: AbortableSWRInfiniteResponse; + initialPages: number, +): [ + AbortableApolloUseMutationPaginatedResponse[0], + AbortableApolloUseMutationPaginatedResponse< + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables + >[1][number], +] => { + let result: AbortableApolloUseMutationPaginatedResponse< + GetSourceMangasFetchMutation, + GetSourceMangasFetchMutationVariables + >; switch (contentType) { case SourceContentType.POPULAR: result = requestManager.useGetSourcePopularMangas(sourceId, initialPages); @@ -117,12 +124,12 @@ const useSourceManga = ( result = requestManager.useGetSourceLatestMangas(sourceId, initialPages); break; case SourceContentType.SEARCH: - result = requestManager.useSourceQuickSearch(sourceId, searchTerm ?? '', [], initialPages); + result = requestManager.useSourceSearch(sourceId, searchTerm ?? '', undefined, initialPages); break; case SourceContentType.FILTER: - result = requestManager.useSourceQuickSearch( + result = requestManager.useSourceSearch( sourceId, - '', + undefined, filters.map((filter) => { const { position, state, group } = filter; @@ -130,32 +137,58 @@ const useSourceManga = ( if (isPartOfGroup) { return { position: group, - state: JSON.stringify({ + groupChange: { position, - state, - }), + [filter.type]: state, + }, }; } - return filter; + return { + position, + [filter.type]: state, + }; }), initialPages, - { disableCache: true }, ); break; default: throw new Error(`Unknown ContentType "${contentType}"`); } - const pages = result.data; - const { hasNextPage } = pages?.[pages.length - 1] ?? { hasNextPage: false }; + const pages = result[1]!; + const lastLoadedPageIndex = pages.findLastIndex((page) => !!page.data?.fetchSourceManga); + const lastLoadedPage = pages[lastLoadedPageIndex]; const items = useMemo( - () => (pages ?? []).map((page) => page.mangaList).reduce((prevList, list) => [...prevList, ...list], []), + () => + (pages ?? []) + .map((page) => page.data?.fetchSourceManga.mangas ?? []) + .reduce((prevList, list) => [...prevList, ...list], []), [pages], ); const uniqueItems = useMemo(() => getUniqueMangas(items), [items]); - return { ...result, data: { items: uniqueItems, hasNextPage } }; + if (!uniqueItems.length) { + return [result[0] as any, result[1][result[1].length - 1]]; + } + + return [ + result[0], + { + ...pages[pages.length - 1], + data: { + ...lastLoadedPage!.data, + fetchSourceManga: { + ...lastLoadedPage!.data!.fetchSourceManga, + hasNextPage: + pages.length > lastLoadedPageIndex + 1 + ? false + : lastLoadedPage!.data!.fetchSourceManga.hasNextPage, + mangas: uniqueItems, + }, + }, + }, + ]; }; export default function SourceMangas() { @@ -167,29 +200,35 @@ export default function SourceMangas() { const { sourceId } = useParams<{ sourceId: string }>(); const navigate = useNavigate(); - const { contentType: currentLocationContentType = SourceContentType.POPULAR } = + const { + contentType: currentLocationContentType = SourceContentType.POPULAR, + filtersToApply: currentLocationFiltersToApply = [], + } = useLocation<{ contentType: SourceContentType; + filtersToApply: IPos[]; }>().state ?? {}; const { options } = useLibraryOptionsContext(); const [query] = useQueryParam('query', StringParam); - const [dialogFiltersToApply, setDialogFiltersToApply] = useState([]); - const [filtersToApply, setFiltersToApply] = useState([]); + const [dialogFiltersToApply, setDialogFiltersToApply] = useState(currentLocationFiltersToApply); + const [filtersToApply, setFiltersToApply] = useState(currentLocationFiltersToApply); const searchTerm = useDebounce(query, 1000); const [resetScrollPosition, setResetScrollPosition] = useState(false); const [contentType, setContentType] = useState(currentLocationContentType); - const { - data: { items: mangas, hasNextPage } = { items: [], hasNextPage: false }, - isLoading, - size: lastPageNum, - setSize: setPages, - mutate: refreshData, - abortRequest, - } = useSourceManga(sourceId, contentType, searchTerm, filtersToApply, isLargeScreen ? 2 : 1); - const { data: filters = [], mutate: mutateFilters } = requestManager.useGetSourceFilters(sourceId); - const { data: source } = requestManager.useGetSource(sourceId); - const [triggerDataRefresh, setTriggerDataRefresh] = useState(false); + const [loadPage, { data, isLoading, size: lastPageNum, abortRequest }] = useSourceManga( + sourceId, + contentType, + searchTerm, + filtersToApply, + isLargeScreen ? 2 : 1, + ); + const mangas = data?.fetchSourceManga.mangas ?? []; + const hasNextPage = data?.fetchSourceManga.hasNextPage ?? false; + + const { data: sourceData } = requestManager.useGetSource(sourceId); + const source = sourceData?.source; + const filters = source?.filters ?? []; const message = !isLoading ? t(SOURCE_CONTENT_TYPE_TO_ERROR_MSG_KEY[contentType]) : undefined; const isLocalSource = sourceId === '0'; @@ -214,6 +253,15 @@ export default function SourceMangas() { [setContentType], ); + const updateLocationFilters = useCallback( + (updatedFilters: IPos[]) => { + if (contentType === SourceContentType.FILTER) { + navigate('', { replace: true, state: { contentType, filtersToApply: updatedFilters } }); + } + }, + [contentType], + ); + const isSearchTermAvailable = searchTerm && query?.length; const setSearchContentType = isSearchTermAvailable && contentType !== SourceContentType.SEARCH; if (setSearchContentType) { @@ -230,21 +278,15 @@ export default function SourceMangas() { return; } - setPages(lastPageNum + 1); - }, [setPages, lastPageNum, hasNextPage]); + loadPage(lastPageNum + 1); + }, [lastPageNum, hasNextPage, contentType]); const resetFilters = useCallback(async () => { setDialogFiltersToApply([]); setFiltersToApply([]); - try { - // required since previous implementation used to set the filters on server side (server caches them), thus, it has to be made sure that they are reset - await requestManager.resetSourceFilters(sourceId); - mutateFilters(); - } catch (error) { - // ignore - } - setTriggerDataRefresh(true); - }, [sourceId]); + updateLocationFilters([]); + setResetScrollPosition(true); + }, [sourceId, contentType]); useEffect( () => () => { @@ -261,15 +303,6 @@ export default function SourceMangas() { [searchTerm, contentType], ); - useEffect(() => { - if (!triggerDataRefresh) { - return; - } - - refreshData(); - setTriggerDataRefresh(false); - }, [triggerDataRefresh]); - useEffect(() => { setTitle(source?.displayName ?? t('source.title')); setAction( @@ -326,6 +359,7 @@ export default function SourceMangas() { { setFiltersToApply(dialogFiltersToApply); - setTriggerDataRefresh(true); + updateLocationFilters(dialogFiltersToApply); }} resetFilterValue={resetFilters} update={dialogFiltersToApply} diff --git a/src/screens/Sources.tsx b/src/screens/Sources.tsx index 52ed46e0..c4412c9c 100644 --- a/src/screens/Sources.tsx +++ b/src/screens/Sources.tsx @@ -12,7 +12,7 @@ import TravelExploreIcon from '@mui/icons-material/TravelExplore'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { ISource } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import useLocalStorage from '@/util/useLocalStorage'; import { sourceDefualtLangs, sourceForcedDefaultLangs, langSortCmp } from '@/util/language'; import { translateExtensionLanguage } from '@/screens/util/Extensions'; @@ -53,7 +53,8 @@ export default function Sources() { const [shownLangs, setShownLangs] = useLocalStorage('shownSourceLangs', sourceDefualtLangs()); const [showNsfw] = useLocalStorage('showNsfw', true); - const { data: sources, isLoading } = requestManager.useGetSourceList(); + const { data, loading: isLoading } = requestManager.useGetSourceList(); + const sources = data?.sources.nodes; const navigate = useNavigate(); diff --git a/src/screens/Updates.tsx b/src/screens/Updates.tsx index fcbb5853..2776e252 100644 --- a/src/screens/Updates.tsx +++ b/src/screens/Updates.tsx @@ -13,17 +13,18 @@ import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import IconButton from '@mui/material/IconButton'; import Typography from '@mui/material/Typography'; -import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useContext, useEffect, useMemo } from 'react'; import { Link, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { t as translate } from 'i18next'; import { GroupedVirtuoso } from 'react-virtuoso'; -import { IChapter, IMangaChapter, IQueue } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import LoadingPlaceholder from '@/components/util/LoadingPlaceholder'; import EmptyView from '@/components/util/EmptyView'; import DownloadStateIndicator from '@/components/molecules/DownloadStateIndicator'; import NavbarContext from '@/components/context/NavbarContext'; +import { DownloadType } from '@/lib/graphql/generated/graphql.ts'; +import { TChapter } from '@/typings.ts'; const StyledGroupedVirtuoso = styled(GroupedVirtuoso)(({ theme }) => ({ // 64px header @@ -81,58 +82,41 @@ function getDateString(date: Date) { return date.toLocaleDateString(); } -const groupByDate = (updates: IMangaChapter[]): [date: string, items: number][] => { +const groupByDate = (updates: TChapter[]): [date: string, items: number][] => { if (!updates.length) { return []; } const dateToItemMap = new Map(); updates.forEach((item) => { - const date = getDateString(epochToDate(item.chapter.fetchedAt)); + const date = getDateString(epochToDate(Number(item.fetchedAt))); dateToItemMap.set(date, (dateToItemMap.get(date) ?? 0) + 1); }); return [...dateToItemMap.entries()]; }; -const initialQueue = { - status: 'Stopped', - queue: [], -} as IQueue; - const Updates: React.FC = () => { const { t } = useTranslation(); const location = useLocation(); const { setTitle, setAction } = useContext(NavbarContext); const { - data: pages = [{ hasNextPage: false, page: [] }], - isLoading, - size: loadedPages, - setSize: setPages, - } = requestManager.useGetRecentlyUpdatedChapters(); - const { hasNextPage } = pages[pages.length - 1]; - const updateEntries = useMemo( - () => pages.map((page) => page.page).reduce((lastPageChapters, chapters) => [...lastPageChapters, ...chapters]), - [pages], - ); + data: chapterUpdateData, + loading: isLoading, + fetchMore, + } = requestManager.useGetRecentlyUpdatedChapters(undefined, { + fetchPolicy: 'cache-and-network', + notifyOnNetworkStatusChange: true, + omitAbortSignal: true, + }); + const hasNextPage = !!chapterUpdateData?.chapters.pageInfo.hasNextPage; + const endCursor = chapterUpdateData?.chapters.pageInfo.endCursor; + const updateEntries = chapterUpdateData?.chapters.nodes ?? []; const groupedUpdates = useMemo(() => groupByDate(updateEntries), [updateEntries]); const groupCounts: number[] = useMemo(() => groupedUpdates.map((group) => group[1]), [groupedUpdates]); - - const [, setWsClient] = useState(); - const [{ queue }, setQueueState] = useState(initialQueue); - - useEffect(() => { - const wsc = requestManager.getDownloadWebSocket(); - wsc.onmessage = (e) => { - const data = JSON.parse(e.data) as IQueue; - setQueueState(data); - }; - - setWsClient(wsc); - - return () => wsc.close(); - }, []); + const { data: downloaderData } = requestManager.useDownloadSubscription(); + const queue = (downloaderData?.downloadChanged.queue as DownloadType[]) ?? []; useEffect(() => { setTitle(t('updates.title')); @@ -140,13 +124,16 @@ const Updates: React.FC = () => { setAction(null); }, [t]); - const downloadForChapter = (chapter: IChapter) => { - const { index, mangaId } = chapter; - return queue.find((q) => index === q.chapterIndex && mangaId === q.mangaId); + const downloadForChapter = (chapter: TChapter) => { + const { + sourceOrder, + manga: { id: mangaId }, + } = chapter; + return queue.find((q) => sourceOrder === q.chapter.sourceOrder && mangaId === q.chapter.manga.id); }; - const downloadChapter = (chapter: IChapter) => { - requestManager.addChapterToDownloadQueue(chapter.mangaId, chapter.index); + const downloadChapter = (chapter: TChapter) => { + requestManager.addChapterToDownloadQueue(chapter.id); }; const loadMore = useCallback(() => { @@ -154,8 +141,8 @@ const Updates: React.FC = () => { return; } - setPages(loadedPages + 1); - }, [hasNextPage, loadedPages]); + fetchMore({ variables: { offset: updateEntries.length } }); + }, [hasNextPage, endCursor]); if (!isLoading && updateEntries.length === 0) { return ; @@ -179,7 +166,8 @@ const Updates: React.FC = () => { )} itemContent={(index) => { - const { chapter, manga } = updateEntries[index]; + const chapter = updateEntries[index]; + const { manga } = chapter; const download = downloadForChapter(chapter); return ( @@ -187,7 +175,7 @@ const Updates: React.FC = () => { { marginRight: 2, imageRendering: 'pixelated', }} - src={requestManager.getValidImgUrlFor(manga.thumbnailUrl)} + src={requestManager.getValidImgUrlFor(manga.thumbnailUrl ?? '')} /> @@ -220,7 +208,7 @@ const Updates: React.FC = () => { {download && } - {download == null && !chapter.downloaded && ( + {download == null && !chapter.isDownloaded && ( { e.stopPropagation(); diff --git a/src/screens/settings/About.tsx b/src/screens/settings/About.tsx index db196541..a46289c6 100644 --- a/src/screens/settings/About.tsx +++ b/src/screens/settings/About.tsx @@ -11,7 +11,7 @@ import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import ListItemText from '@mui/material/ListItemText'; import { useTranslation } from 'react-i18next'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import ListItemLink from '@/components/util/ListItemLink'; import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext'; import LoadingPlaceholder from '@/components/util/LoadingPlaceholder'; @@ -25,7 +25,8 @@ export default function About() { setAction(null); }, [t]); - const { data: about } = requestManager.useGetAbout(); + const { data } = requestManager.useGetAbout(); + const about = data?.about; useSetDefaultBackTo('settings'); diff --git a/src/screens/settings/Backup.tsx b/src/screens/settings/Backup.tsx index c4755594..d6171b01 100644 --- a/src/screens/settings/Backup.tsx +++ b/src/screens/settings/Backup.tsx @@ -12,7 +12,7 @@ import ListItemText from '@mui/material/ListItemText'; import { fromEvent } from 'file-selector'; import { useTranslation } from 'react-i18next'; import { ListItemButton } from '@mui/material'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import makeToast from '@/components/util/Toast'; import ListItemLink from '@/components/util/ListItemLink'; import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext'; diff --git a/src/screens/settings/Categories.tsx b/src/screens/settings/Categories.tsx index 5c0dd991..c348a733 100644 --- a/src/screens/settings/Categories.tsx +++ b/src/screens/settings/Categories.tsx @@ -24,11 +24,11 @@ import DialogTitle from '@mui/material/DialogTitle'; import Checkbox from '@mui/material/Checkbox'; import FormControlLabel from '@mui/material/FormControlLabel'; import { useTranslation } from 'react-i18next'; -import { ICategory } from '@/typings'; -import requestManager from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; import StrictModeDroppable from '@/lib/StrictModeDroppable'; import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab'; import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext'; +import { TCategory } from '@/typings.ts'; const getItemStyle = ( isDragging: boolean, @@ -52,9 +52,9 @@ export default function Categories() { setAction(null); }, [t]); - const { data, mutate } = requestManager.useGetCategories(); + const { data } = requestManager.useGetCategories(); const categories = useMemo(() => { - const res = [...(data ?? [])]; + const res = [...(data?.categories.nodes ?? [])]; if (res.length > 0 && res[0].name === 'Default') { res.shift(); } @@ -65,17 +65,17 @@ export default function Categories() { const [dialogOpen, setDialogOpen] = useState(false); const [dialogName, setDialogName] = useState(''); const [dialogDefault, setDialogDefault] = useState(false); + const [reorderCategory, { reset: revertReorder }] = requestManager.useReorderCategory(); const theme = useTheme(); useSetDefaultBackTo('settings'); - const categoryReorder = (list: ICategory[], from: number, to: number) => { - const newData = [...list]; - const [removed] = newData.splice(from, 1); - newData.splice(to, 0, removed); - mutate(newData, { revalidate: false }); + const categoryReorder = (list: TCategory[], from: number, to: number) => { + const reorderedCategory = list[from]; - requestManager.reorderCategory(from + 1, to + 1).response.finally(() => mutate()); + reorderCategory({ variables: { input: { id: reorderedCategory.id, position: to + 1 } } }).catch(() => + revertReorder(), + ); }; const onDragEnd = (result: DropResult) => { @@ -113,18 +113,16 @@ export default function Categories() { setDialogOpen(false); if (categoryToEdit === -1) { - requestManager.createCategory(dialogName).response.finally(() => mutate()); + requestManager.createCategory({ name: dialogName, default: dialogDefault }); } else { const category = categories[categoryToEdit]; - requestManager - .updateCategory(category.id, { name: dialogName, default: dialogDefault }) - .response.finally(() => mutate()); + requestManager.updateCategory(category.id, { name: dialogName, default: dialogDefault }); } }; const deleteCategory = (index: number) => { const category = categories[index]; - requestManager.deleteCategory(category.id).response.finally(() => mutate()); + requestManager.deleteCategory(category.id); }; return ( diff --git a/src/screens/settings/DefaultReaderSettings.tsx b/src/screens/settings/DefaultReaderSettings.tsx index d296a5d7..a71ae4cb 100644 --- a/src/screens/settings/DefaultReaderSettings.tsx +++ b/src/screens/settings/DefaultReaderSettings.tsx @@ -11,7 +11,7 @@ import { Box } from '@mui/material'; import CircularProgress from '@mui/material/CircularProgress'; import { useTranslation } from 'react-i18next'; import { IReaderSettings } from '@/typings'; -import { requestUpdateServerMetadata } from '@/util/metadata'; +import { convertToGqlMeta, requestUpdateServerMetadata } from '@/util/metadata'; import { checkAndHandleMissingStoredReaderSettings, getDefaultSettings, @@ -34,7 +34,7 @@ export default function DefaultReaderSettings() { useSetDefaultBackTo('settings'); const setSettingValue = (key: keyof IReaderSettings, value: string | boolean) => { - requestUpdateServerMetadata(metadata ?? {}, [[key, value]]).catch(() => + requestUpdateServerMetadata(convertToGqlMeta(metadata)! ?? {}, [[key, value]]).catch(() => makeToast(t('reader.settings.error.label.failed_to_save_settings'), 'warning'), ); }; @@ -54,7 +54,11 @@ export default function DefaultReaderSettings() { ); } - checkAndHandleMissingStoredReaderSettings({ meta: metadata }, 'server', getDefaultSettings()).catch(() => {}); + checkAndHandleMissingStoredReaderSettings( + { meta: convertToGqlMeta(metadata)! }, + 'server', + getDefaultSettings(), + ).catch(() => {}); return ( { - if (status === IncludeInGlobalUpdate.UNSET) { - return null; +const booleanToIncludeInStatus = (status: boolean | null | undefined): IncludeInUpdate => { + switch (status) { + case false: + return IncludeInUpdate.Exclude; + case true: + return IncludeInUpdate.Include; + case null: + case undefined: + return IncludeInUpdate.Unset; + default: + throw new Error(`booleanToIncludeInStatus: unexpected IncludeInUpdate status "${status}"`); } +}; - return !!status; +const includeInUpdateStatusToBoolean = (status: IncludeInUpdate): boolean | null => { + switch (status) { + case IncludeInUpdate.Exclude: + return false; + case IncludeInUpdate.Include: + return true; + case IncludeInUpdate.Unset: + return null; + default: + throw new Error(`includeInUpdateStatusToBoolean: unexpected IncludeInUpdate status "${status}"`); + } }; const getCategoryUpdateInfo = ( - categories: ICategory[], + categories: TCategory[], areIncluded: boolean, unsetCategories: number, allCategories: number, @@ -80,20 +100,25 @@ export default function LibrarySettings() { useSetDefaultBackTo('settings'); - const { data: categories = [], error: requestError, mutate } = requestManager.useGetCategories(); - const [dialogCategories, setDialogCategories] = useState(categories); + const { data, error: requestError } = requestManager.useGetCategories(); + const categories = data?.categories.nodes; + const [dialogCategories, setDialogCategories] = useState(categories ?? []); const [isDialogOpen, setIsDialogOpen] = useState(false); useEffect(() => { + if (!categories) { + return; + } + setDialogCategories(categories); }, [categories]); - const unsetCategories: ICategory[] = - categories?.filter((category) => category.includeInUpdate === IncludeInGlobalUpdate.UNSET) ?? []; - const excludedCategories: ICategory[] = - categories?.filter((category) => category.includeInUpdate === IncludeInGlobalUpdate.EXCLUDE) ?? []; - const includedCategories: ICategory[] = - categories?.filter((category) => category.includeInUpdate === IncludeInGlobalUpdate.INCLUDE) ?? []; + const unsetCategories: TCategory[] = + categories?.filter((category) => category.includeInUpdate === IncludeInUpdate.Unset) ?? []; + const excludedCategories: TCategory[] = + categories?.filter((category) => category.includeInUpdate === IncludeInUpdate.Exclude) ?? []; + const includedCategories: TCategory[] = + categories?.filter((category) => category.includeInUpdate === IncludeInUpdate.Include) ?? []; const excludedCategoriesText = getCategoryUpdateInfo( excludedCategories, false, @@ -109,12 +134,12 @@ export default function LibrarySettings() { requestError, ); - const updateCategory = (category: ICategory) => + const updateCategory = (category: TCategory) => requestManager.updateCategory(category.id, { includeInUpdate: category.includeInUpdate }).response; const updateCategories = async () => { const categoriesToUpdate = dialogCategories.filter((category) => { - const currentCategory = categories.find((currCategory) => currCategory.id === category.id); + const currentCategory = categories?.find((currCategory) => currCategory.id === category.id); if (!currentCategory) { return false; @@ -127,10 +152,11 @@ export default function LibrarySettings() { try { await Promise.all(categoriesToUpdate.map((category) => updateCategory(category))); - mutate([...dialogCategories], { revalidate: false }); + // TODO - update cache immediately + // mutate(categoriesEndpoint, [...dialogCategories], { revalidate: false }); } catch (error) { makeToast(t('global.error.label.failed_to_save_changes'), 'error'); - mutate([...categories]); + // mutate(categoriesEndpoint, [...categories]); } }; @@ -192,13 +218,12 @@ export default function LibrarySettings() { label={category.name} checked={includeInUpdateStatusToBoolean(category.includeInUpdate)} onChange={(checked) => { - const newIncludeState: IncludeInGlobalUpdate = - checked == null ? IncludeInGlobalUpdate.UNSET : Number(checked); + const newIncludeState = booleanToIncludeInStatus(checked); const categoryIndex = dialogCategories.findIndex( (category_) => category_ === category, ); - const updatedDialogCategories: ICategory[] = [ + const updatedDialogCategories: TCategory[] = [ ...dialogCategories.slice(0, categoryIndex), { ...category, diff --git a/src/screens/settings/SearchSettings.tsx b/src/screens/settings/SearchSettings.tsx index 9568b6a6..179b22ab 100644 --- a/src/screens/settings/SearchSettings.tsx +++ b/src/screens/settings/SearchSettings.tsx @@ -12,7 +12,7 @@ import ListItemIcon from '@mui/material/ListItemIcon'; import SearchIcon from '@mui/icons-material/Search'; import { useTranslation } from 'react-i18next'; import { SearchMetadataKeys } from '@/typings'; -import { requestUpdateServerMetadata } from '@/util/metadata'; +import { convertToGqlMeta, requestUpdateServerMetadata } from '@/util/metadata'; import { useSearchSettings } from '@/util/searchSettings'; import makeToast from '@/components/util/Toast'; import { useSetDefaultBackTo } from '@/components/context/NavbarContext'; @@ -24,7 +24,7 @@ export default function SearchSettings() { useSetDefaultBackTo('settings'); const setSettingValue = (key: SearchMetadataKeys, value: boolean) => { - requestUpdateServerMetadata(metadata ?? {}, [[key, value]]).catch(() => + requestUpdateServerMetadata(convertToGqlMeta(metadata)! ?? {}, [[key, value]]).catch(() => makeToast(t('search.error.label.failed_to_save_settings'), 'warning'), ); }; diff --git a/src/screens/util/Extensions.ts b/src/screens/util/Extensions.ts index 2ed2dcee..5d83890c 100644 --- a/src/screens/util/Extensions.ts +++ b/src/screens/util/Extensions.ts @@ -7,7 +7,7 @@ */ import { t } from 'i18next'; -import { IExtension, TranslationKey } from '@/typings'; +import { PartialExtension, TranslationKey } from '@/typings'; import { DefaultLanguage, langCodeToName } from '@/util/language'; export enum ExtensionState { @@ -16,16 +16,16 @@ export enum ExtensionState { OBSOLETE = 'OBSOLETE', } -export type GroupedExtensionsResult = [KEY, IExtension[]][]; +export type GroupedExtensionsResult = [KEY, PartialExtension[]][]; export type GroupedByExtensionState = { - [state in ExtensionState]: IExtension[]; + [state in ExtensionState]: PartialExtension[]; }; export type GroupedByLanguage = { - [language in DefaultLanguage]: IExtension[]; + [language in DefaultLanguage]: PartialExtension[]; } & { - [language: string]: IExtension[]; + [language: string]: PartialExtension[]; }; export type GroupedExtensions = GroupedByExtensionState & GroupedByLanguage; diff --git a/src/typings.ts b/src/typings.ts index df8ab19e..589a4b50 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -10,6 +10,31 @@ import { OverridableComponent } from '@mui/material/OverridableComponent'; import { SvgIconTypeMap } from '@mui/material/SvgIcon/SvgIcon'; import { ParseKeys } from 'i18next'; import { Location } from 'react-router-dom'; +import { + GetCategoryQuery, + GetChapterQuery, + GetExtensionQuery, + GetMangaQuery, + GetSourceQuery, + MetaType, + SourcePreferenceChangeInput, +} from '@/lib/graphql/generated/graphql.ts'; + +export type ExtractByKeyValue = T extends + | Record + | Partial> + ? T + : never; + +export type RecursivePartial = { + [P in keyof T]?: T[P] extends (infer U)[] + ? RecursivePartial[] + : T[P] extends object | undefined + ? RecursivePartial + : T[P]; +}; + +export type OptionalProperty = Omit & Partial>; type GenericLocation = Omit & { state?: State }; @@ -21,19 +46,7 @@ declare module 'react-router-dom' { export type TranslationKey = ParseKeys; -export interface IExtension { - name: string; - pkgName: string; - versionName: string; - versionCode: number; - lang: string; - isNsfw: boolean; - apkName: string; - iconUrl: string; - installed: boolean; - hasUpdate: boolean; - obsolete: boolean; -} +export type PartialExtension = GetExtensionQuery['extension']; export interface ISource { id: string; @@ -46,29 +59,7 @@ export interface ISource { displayName: string; } -export interface ISourceFilters { - type: string; - filter: ISourceFilter; -} - -export interface ISourceFilter { - name: string; - state: number | string | boolean | ISourceFilters[] | IState; - values?: string[]; - displayValues?: string[]; - selected?: ISelected; -} - -export interface ISelected { - displayname: string; - value: string; - _value: string; -} - -export interface IState { - ascending: boolean; - index: number; -} +export type SourceFilters = GetSourceQuery['source']['filters'][number]; export interface IMetadataMigration { appKeyPrefix?: { oldPrefix: string; newPrefix: string }; @@ -88,6 +79,8 @@ export type Metadata = { [key in Keys]: Values; }; +export type GqlMetaHolder = { meta?: MetaType[] }; + export type MetadataHolder = { meta?: Metadata; }; @@ -115,6 +108,10 @@ export interface IMangaCard { lastReadAt: number; } +export type TManga = GetMangaQuery['manga']; + +export type TPartialManga = OptionalProperty; + export interface IManga { id: number; sourceId: string; @@ -176,12 +173,7 @@ export interface IMangaChapter { chapter: IChapter; } -export interface IPartialChapter { - pageCount: number; - index: number; - chapterCount: number; - lastPageRead: number; -} +export type TChapter = GetChapterQuery['chapter']; export enum IncludeInGlobalUpdate { EXCLUDE = 0, @@ -189,6 +181,8 @@ export enum IncludeInGlobalUpdate { UNSET = -1, } +export type TCategory = GetCategoryQuery['category']; + export interface ICategory { id: number; order: number; @@ -247,22 +241,12 @@ export interface IReaderProps { curPage: number; initialPage: number; settings: IReaderSettings; - manga: IMangaCard | IManga; - chapter: IChapter | IPartialChapter; + manga: TManga; + chapter: TChapter; nextChapter: () => void; prevChapter: () => void; } -export interface IAbout { - name: string; - version: string; - revision: string; - buildType: 'Stable' | 'Preview'; - buildTime: number; - github: string; - discord: string; -} - export interface IDownloadChapter { chapterIndex: number; mangaId: number; @@ -286,47 +270,34 @@ export interface IUpdateStatus { }; } +export type SourcePreferences = GetSourceQuery['source']['preferences'][number]; + export interface PreferenceProps { - key: string; - title: string; - summary: string; - defaultValue: any; - currentValue: any; - defaultValueType: string; + updateValue: >( + type: Key, + value: SourcePreferenceChangeInput[Key], + ) => void; +} +export type TwoStatePreferenceProps = (CheckBoxPreferenceProps | SwitchPreferenceCompatProps) & { // intetnal props - updateValue: any; -} + twoStateType: 'Switch' | 'Checkbox'; +}; -export interface TwoStatePreferenceProps extends PreferenceProps { - // intetnal props - type: 'Switch' | 'Checkbox'; -} +export type CheckBoxPreferenceProps = PreferenceProps & + ExtractByKeyValue; -export interface CheckBoxPreferenceProps extends PreferenceProps {} +export type SwitchPreferenceCompatProps = PreferenceProps & + ExtractByKeyValue; -export interface SwitchPreferenceCompatProps extends PreferenceProps {} +export type ListPreferenceProps = PreferenceProps & + ExtractByKeyValue; -export interface ListPreferenceProps extends PreferenceProps { - entries: string[]; - entryValues: string[]; -} +export type MultiSelectListPreferenceProps = PreferenceProps & + ExtractByKeyValue; -export interface MultiSelectListPreferenceProps extends PreferenceProps { - entries: string[]; - entryValues: string[]; -} - -export interface EditTextPreferenceProps extends PreferenceProps { - dialogTitle: string; - dialogMessage: string; - text: string; -} - -export interface SourcePreferences { - type: string; - props: any; -} +export type EditTextPreferenceProps = PreferenceProps & + ExtractByKeyValue; export interface NavbarItem { path: string; @@ -389,13 +360,6 @@ export interface LibraryOptions { showTabSize: boolean; } -export interface BatchChaptersChange { - delete?: boolean; - isRead?: boolean; - isBookmarked?: boolean; - lastPageRead?: number; -} - export type UpdateCheck = { channel: 'Stable' | 'Preview'; tag: string; diff --git a/src/util/metadata.ts b/src/util/metadata.ts index 32b0ca94..d16bd040 100644 --- a/src/util/metadata.ts +++ b/src/util/metadata.ts @@ -6,20 +6,20 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { mutate } from 'swr'; import { AllowedMetadataValueTypes, AppMetadataKeys, - ICategory, - IManga, - IMangaCard, - IMangaChapter, + GqlMetaHolder, IMetadataMigration, Metadata, MetadataHolder, MetadataKeyValuePair, + TCategory, + TChapter, + TManga, } from '@/typings'; -import requestManager, { RequestManager } from '@/lib/RequestManager'; +import requestManager from '@/lib/requests/RequestManager.ts'; +import { MetaType } from '@/lib/graphql/generated/graphql.ts'; const APP_METADATA_KEY_PREFIX = 'webUI_'; @@ -117,6 +117,27 @@ const convertValueFromMetadata = { + if (!gqlMetadata) { + return undefined; + } + + const metadata: Metadata = {}; + gqlMetadata.forEach(({ key, value }) => { + metadata[key] = value; + }); + + return metadata; +}; + +export const convertToGqlMeta = (metadata?: Metadata): MetaType[] | undefined => { + if (!metadata) { + return undefined; + } + + return Object.entries(metadata).map(([key, value]) => ({ key, value })); +}; + const getAppMetadataFrom = (meta: Metadata, appPrefix: string = APP_METADATA_KEY_PREFIX): Metadata => { const appMetadata: Metadata = {}; @@ -276,6 +297,8 @@ export const getMetadataFrom = { if (wrap) { return { @@ -293,72 +316,54 @@ const wrapMetadataWithMetaKey = (wrap: boolean, metadata: Metadata): MetadataHol type MetadataHolderType = 'manga' | 'chapter' | 'category' | 'global'; export const requestUpdateMetadataValue = async ( - metadataHolder: MetadataHolder, + metadataHolder: GqlMetaHolder, holderType: MetadataHolderType, key: AppMetadataKeys, value: AllowedMetadataValueTypes, ): Promise => { const metadataKey = getMetadataKey(key); - const mutatedMetadata = { - ...metadataHolder.meta, - [metadataKey]: `${value}`, - }; - let endpoint: string; switch (holderType) { case 'category': - endpoint = `category/${(metadataHolder as ICategory).id}/meta`; - await requestManager.setCategoryMeta((metadataHolder as ICategory).id, metadataKey, value).response; + await requestManager.setCategoryMeta((metadataHolder as TCategory).id, metadataKey, value).response; break; case 'chapter': - // eslint-disable-next-line no-case-declarations - const { manga, chapter } = metadataHolder as IMangaChapter; - endpoint = `manga/${manga.id}/chapter/${chapter.index}/meta`; - await requestManager.setChapterMeta(manga.id, chapter.index, metadataKey, value).response; + await requestManager.setChapterMeta((metadataHolder as TChapter).id, metadataKey, value).response; break; case 'global': - endpoint = 'meta'; await requestManager.setGlobalMetadata(metadataKey, value).response; break; case 'manga': - endpoint = `manga/${(metadataHolder as IManga).id}/meta`; - await requestManager.setMangaMeta((metadataHolder as IManga).id, metadataKey, value).response; + await requestManager.setMangaMeta((metadataHolder as TManga).id, metadataKey, value).response; break; default: throw new Error(`requestUpdateMetadataValue: unknown holderType "${holderType}"`); } - - const urlToMutate = `${RequestManager.API_VERSION}${endpoint}`; - mutate( - urlToMutate, - { ...metadataHolder, ...wrapMetadataWithMetaKey(holderType !== 'global', mutatedMetadata) }, - { revalidate: false }, - ); }; export const requestUpdateMetadata = async ( - metadataHolder: MetadataHolder, + metadataHolder: GqlMetaHolder, holderType: MetadataHolderType, keysToValues: [AppMetadataKeys, AllowedMetadataValueTypes][], ): Promise => Promise.all(keysToValues.map(([key, value]) => requestUpdateMetadataValue(metadataHolder, holderType, key, value))); export const requestUpdateServerMetadata = async ( - serverMetadata: Metadata, + serverMetadata: MetaType[], keysToValues: MetadataKeyValuePair[], ): Promise => requestUpdateMetadata({ meta: serverMetadata }, 'global', keysToValues); export const requestUpdateMangaMetadata = async ( - manga: IMangaCard | IManga, + manga: TManga, keysToValues: MetadataKeyValuePair[], ): Promise => requestUpdateMetadata(manga, 'manga', keysToValues); export const requestUpdateChapterMetadata = async ( - mangaChapter: IMangaChapter, + chapter: TChapter, keysToValues: MetadataKeyValuePair[], -): Promise => requestUpdateMetadata(mangaChapter.chapter, 'chapter', keysToValues); +): Promise => requestUpdateMetadata(chapter, 'chapter', keysToValues); export const requestUpdateCategoryMetadata = async ( - category: ICategory, + category: TCategory, keysToValues: MetadataKeyValuePair[], ): Promise => requestUpdateMetadata(category, 'category', keysToValues); diff --git a/src/util/readerSettings.ts b/src/util/readerSettings.ts index b595181e..bfd61325 100644 --- a/src/util/readerSettings.ts +++ b/src/util/readerSettings.ts @@ -6,9 +6,15 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { IManga, Metadata, MetadataHolder, IReaderSettings, MetadataKeyValuePair } from '@/typings'; -import requestManager from '@/lib/RequestManager'; -import { getMetadataFrom, requestUpdateMangaMetadata, requestUpdateServerMetadata } from '@/util/metadata'; +import { Metadata, IReaderSettings, MetadataKeyValuePair, GqlMetaHolder, TManga } from '@/typings'; +import requestManager from '@/lib/requests/RequestManager.ts'; +import { + convertFromGqlMeta, + getMetadataFrom, + requestUpdateMangaMetadata, + requestUpdateServerMetadata, +} from '@/util/metadata'; +import { MetaType } from '@/lib/graphql/generated/graphql.ts'; type UndefinedReaderSettings = { [setting in keyof IReaderSettings]: IReaderSettings[setting] | undefined; @@ -37,20 +43,21 @@ export const getReaderSettingsFromMetadata = ( ): IReaderSettings => getReaderSettingsWithDefaultValueFallback(meta, defaultSettings, applyMetadataMigration); export const getReaderSettingsFor = ( - { meta }: MetadataHolder, + { meta }: GqlMetaHolder = {}, defaultSettings?: IReaderSettings, applyMetadataMigration?: boolean, -): IReaderSettings => getReaderSettingsFromMetadata(meta, defaultSettings, applyMetadataMigration); +): IReaderSettings => getReaderSettingsFromMetadata(convertFromGqlMeta(meta), defaultSettings, applyMetadataMigration); export const useDefaultReaderSettings = (): { metadata?: Metadata; settings: IReaderSettings; loading: boolean; } => { - const { data: meta, isLoading } = requestManager.useGetGlobalMeta(); - const settings = getReaderSettingsWithDefaultValueFallback(meta); + const { data, loading } = requestManager.useGetGlobalMeta(); + const metadata = convertFromGqlMeta(data?.metas.nodes); + const settings = getReaderSettingsWithDefaultValueFallback(metadata); - return { metadata: meta, settings, loading: isLoading }; + return { metadata, settings, loading }; }; /** @@ -61,11 +68,12 @@ export const useDefaultReaderSettings = (): { * @param defaultSettings */ export const checkAndHandleMissingStoredReaderSettings = async ( - metadataHolder: IManga | MetadataHolder, + metadataHolder: Required | MetaType[], metadataHolderType: 'manga' | 'server', defaultSettings: IReaderSettings, ): Promise => { - const meta = metadataHolder.meta ?? (metadataHolder as Metadata); + const getMeta = () => (Array.isArray(metadataHolder) ? metadataHolder : metadataHolder.meta); + const meta = convertFromGqlMeta(getMeta())!; const settingsToCheck = getReaderSettingsWithDefaultValueFallback( meta, { @@ -79,7 +87,7 @@ export const checkAndHandleMissingStoredReaderSettings = async ( }, false, ); - const newSettings = getReaderSettingsFor({ meta }, defaultSettings); + const newSettings = getReaderSettingsFor({ meta: getMeta() }, defaultSettings); const undefinedSettings = Object.entries(settingsToCheck).filter((setting) => setting[1] === undefined); @@ -95,9 +103,9 @@ export const checkAndHandleMissingStoredReaderSettings = async ( } if (metadataHolderType === 'manga') { - await requestUpdateMangaMetadata(metadataHolder as IManga, settingsToUpdate); + await requestUpdateMangaMetadata(metadataHolder as TManga, settingsToUpdate); return; } - await requestUpdateServerMetadata(meta, settingsToUpdate); + await requestUpdateServerMetadata(metadataHolder as MetaType[], settingsToUpdate); }; diff --git a/src/util/searchSettings.ts b/src/util/searchSettings.ts index 417ebc87..5b8a7fc9 100644 --- a/src/util/searchSettings.ts +++ b/src/util/searchSettings.ts @@ -7,8 +7,8 @@ */ import { Metadata, ISearchSettings } from '@/typings'; -import requestManager from '@/lib/RequestManager'; -import { getMetadataFrom } from '@/util/metadata'; +import requestManager from '@/lib/requests/RequestManager.ts'; +import { convertFromGqlMeta, getMetadataFrom } from '@/util/metadata'; export const getDefaultSettings = (): ISearchSettings => ({ ignoreFilters: false, @@ -24,8 +24,9 @@ export const useSearchSettings = (): { settings: ISearchSettings; loading: boolean; } => { - const { data: meta, isLoading } = requestManager.useGetGlobalMeta(); - const settings = getSearchSettingsWithDefaultValueFallback(meta); + const { data, loading } = requestManager.useGetGlobalMeta(); + const metadata = convertFromGqlMeta(data?.metas.nodes); + const settings = getSearchSettingsWithDefaultValueFallback(metadata); - return { metadata: meta, settings, loading: isLoading }; + return { metadata, settings, loading }; }; diff --git a/tools/scripts/codegenFormatter.ts b/tools/scripts/codegenFormatter.ts new file mode 100644 index 00000000..741db792 --- /dev/null +++ b/tools/scripts/codegenFormatter.ts @@ -0,0 +1,110 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import fs from 'fs'; +import * as path from 'path'; + +const format = (source: string, regex: RegExp | string, replaceValue: string): string => + source.replace(regex, replaceValue); + +let generatedGraphQLFilePath = path.resolve(__dirname, '../../src/lib/graphql/generated/graphql.ts'); +let generatedGraphQLFile = fs.readFileSync(generatedGraphQLFilePath, 'utf8'); + +// add logic to format the codegen generated graphql file + +/* ******************************************* */ +/* */ +/* typescript, typescript-operations */ +/* */ +/* ******************************************* */ + +const fixCursorTyping = format( + generatedGraphQLFile, + /Cursor: \{ input: any; output: any; }/g, + 'Cursor: { input: string; output: string; }', +); + +const fixLongStringTyping = format( + fixCursorTyping, + /LongString: \{ input: any; output: any; }/g, + 'LongString: { input: string; output: string; }', +); + +const fixSubscriptionHookNameSuffix = format(fixLongStringTyping, /SubscriptionSubscription/g, 'Subscription'); + +fs.writeFileSync(generatedGraphQLFilePath, fixSubscriptionHookNameSuffix); + +/* ****************************************** */ +/* */ +/* typescript-apollo-client-helpers */ +/* */ +/* ****************************************** */ + +generatedGraphQLFilePath = path.resolve(__dirname, '../../src/lib/graphql/generated/apollo-helpers.ts'); +generatedGraphQLFile = fs.readFileSync(generatedGraphQLFilePath, 'utf8'); + +const addImports = format( + generatedGraphQLFile, + `import { FieldPolicy, FieldReadFunction, TypePolicies, TypePolicy } from '@apollo/client/cache';`, + `import { FieldPolicy, FieldReadFunction, TypePolicies, TypePolicy } from '@apollo/client/cache'; +import { GetChaptersQuery } from "@/lib/graphql/generated/graphql.ts";`, +); + +const fixTypingOfQueryTypePolicies = format( + addImports, + `export type QueryFieldPolicy = { +\tabout?: FieldPolicy | FieldReadFunction, +\tcategories?: FieldPolicy | FieldReadFunction, +\tcategory?: FieldPolicy | FieldReadFunction, +\tchapter?: FieldPolicy | FieldReadFunction, +\tchapters?: FieldPolicy | FieldReadFunction, +\tcheckForServerUpdates?: FieldPolicy | FieldReadFunction, +\tcheckForWebUIUpdate?: FieldPolicy | FieldReadFunction, +\tdownloadStatus?: FieldPolicy | FieldReadFunction, +\textension?: FieldPolicy | FieldReadFunction, +\textensions?: FieldPolicy | FieldReadFunction, +\tgetWebUIUpdateStatus?: FieldPolicy | FieldReadFunction, +\tlastUpdateTimestamp?: FieldPolicy | FieldReadFunction, +\tmanga?: FieldPolicy | FieldReadFunction, +\tmangas?: FieldPolicy | FieldReadFunction, +\tmeta?: FieldPolicy | FieldReadFunction, +\tmetas?: FieldPolicy | FieldReadFunction, +\trestoreStatus?: FieldPolicy | FieldReadFunction, +\tsettings?: FieldPolicy | FieldReadFunction, +\tsource?: FieldPolicy | FieldReadFunction, +\tsources?: FieldPolicy | FieldReadFunction, +\tupdateStatus?: FieldPolicy | FieldReadFunction, +\tvalidateBackup?: FieldPolicy | FieldReadFunction +};`, + `export type QueryFieldPolicy = { +\tabout?: FieldPolicy | FieldReadFunction, +\tcategories?: FieldPolicy | FieldReadFunction, +\tcategory?: FieldPolicy | FieldReadFunction, +\tchapter?: FieldPolicy | FieldReadFunction, +\tchapters?: FieldPolicy | FieldReadFunction, +\tcheckForServerUpdates?: FieldPolicy | FieldReadFunction, +\tcheckForWebUIUpdate?: FieldPolicy | FieldReadFunction, +\tdownloadStatus?: FieldPolicy | FieldReadFunction, +\textension?: FieldPolicy | FieldReadFunction, +\textensions?: FieldPolicy | FieldReadFunction, +\tgetWebUIUpdateStatus?: FieldPolicy | FieldReadFunction, +\tlastUpdateTimestamp?: FieldPolicy | FieldReadFunction, +\tmanga?: FieldPolicy | FieldReadFunction, +\tmangas?: FieldPolicy | FieldReadFunction, +\tmeta?: FieldPolicy | FieldReadFunction, +\tmetas?: FieldPolicy | FieldReadFunction, +\trestoreStatus?: FieldPolicy | FieldReadFunction, +\tsettings?: FieldPolicy | FieldReadFunction, +\tsource?: FieldPolicy | FieldReadFunction, +\tsources?: FieldPolicy | FieldReadFunction, +\tupdateStatus?: FieldPolicy | FieldReadFunction, +\tvalidateBackup?: FieldPolicy | FieldReadFunction +};`, +); + +fs.writeFileSync(generatedGraphQLFilePath, fixTypingOfQueryTypePolicies); diff --git a/tsconfig.json b/tsconfig.json index d3a3900c..333123b0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,7 @@ /* Bundler mode */ "esModuleInterop": true, "allowSyntheticDefaultImports": true, - "moduleResolution": "bundler", + "moduleResolution": "node", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, diff --git a/tsconfig.node.json b/tsconfig.node.json index 6dae8e70..e9ec28b1 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -8,6 +8,6 @@ }, "include": [ "vite.config.ts", - "vite.config.ts" + "gql_codegen.ts" ] } diff --git a/yarn.lock b/yarn.lock index 93498958..e8009634 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,64 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@babel/code-frame@^7.0.0": +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@apollo/client@^3.7.0", "@apollo/client@^3.8.1": + version "3.8.3" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.8.3.tgz#7cd23307bbc788a0a9eda51e6a76f32db8282933" + integrity sha512-mK86JM6hCpMEBGDgdO9U8ZYS8r9lPjXE1tVGpJMdSFUsIcXpmEfHUAbbFpPtYmxn8Qa7XsYy0dwDaDhpf4UUPw== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + "@wry/context" "^0.7.3" + "@wry/equality" "^0.5.6" + "@wry/trie" "^0.4.3" + graphql-tag "^2.12.6" + hoist-non-react-statics "^3.3.2" + optimism "^0.17.5" + prop-types "^15.7.2" + response-iterator "^0.2.6" + symbol-observable "^4.0.0" + ts-invariant "^0.10.3" + tslib "^2.3.0" + zen-observable-ts "^1.2.5" + +"@ardatan/relay-compiler@12.0.0": + version "12.0.0" + resolved "https://registry.yarnpkg.com/@ardatan/relay-compiler/-/relay-compiler-12.0.0.tgz#2e4cca43088e807adc63450e8cab037020e91106" + integrity sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q== + dependencies: + "@babel/core" "^7.14.0" + "@babel/generator" "^7.14.0" + "@babel/parser" "^7.14.0" + "@babel/runtime" "^7.0.0" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.0.0" + babel-preset-fbjs "^3.4.0" + chalk "^4.0.0" + fb-watchman "^2.0.0" + fbjs "^3.0.0" + glob "^7.1.1" + immutable "~3.7.6" + invariant "^2.2.4" + nullthrows "^1.1.1" + relay-runtime "12.0.0" + signedsource "^1.0.0" + yargs "^15.3.1" + +"@ardatan/sync-fetch@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@ardatan/sync-fetch/-/sync-fetch-0.0.1.tgz#3385d3feedceb60a896518a1db857ec1e945348f" + integrity sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA== + dependencies: + node-fetch "^2.6.1" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.22.13": version "7.22.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== @@ -15,13 +72,162 @@ "@babel/highlight" "^7.22.13" chalk "^2.4.2" -"@babel/helper-module-imports@^7.16.7": +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.9": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.20.tgz#8df6e96661209623f1975d66c35ffca66f3306d0" + integrity sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw== + +"@babel/core@^7.14.0", "@babel/core@^7.22.9": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.20.tgz#e3d0eed84c049e2a2ae0a64d27b6a37edec385b7" + integrity sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.22.15" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.22.20" + "@babel/helpers" "^7.22.15" + "@babel/parser" "^7.22.16" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.22.20" + "@babel/types" "^7.22.19" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.14.0", "@babel/generator@^7.18.13", "@babel/generator@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.15.tgz#1564189c7ec94cb8f77b5e8a90c4d200d21b2339" + integrity sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA== + dependencies: + "@babel/types" "^7.22.15" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" + integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.15" + browserslist "^4.21.9" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.18.6": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" + integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.22.5": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" + integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== + dependencies: + "@babel/template" "^7.22.5" + "@babel/types" "^7.22.5" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-member-expression-to-functions@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz#b95a144896f6d491ca7863576f820f3628818621" + integrity sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== dependencies: "@babel/types" "^7.22.15" +"@babel/helper-module-transforms@^7.22.15", "@babel/helper-module-transforms@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz#da9edc14794babbe7386df438f3768067132f59e" + integrity sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-replace-supers@^7.22.5", "@babel/helper-replace-supers@^7.22.9": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-string-parser@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" @@ -32,6 +238,20 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== + +"@babel/helpers@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.15.tgz#f09c3df31e86e3ea0b7ff7556d85cdebd47ea6f1" + integrity sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.22.15" + "@babel/types" "^7.22.15" + "@babel/highlight@^7.22.13": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" @@ -41,14 +261,258 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.7", "@babel/runtime@^7.22.15", "@babel/runtime@^7.22.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/parser@^7.14.0", "@babel/parser@^7.16.8", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16": + version "7.22.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95" + integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA== + +"@babel/plugin-proposal-class-properties@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-object-rest-spread@^7.0.0": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" + integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.7" + +"@babel/plugin-syntax-class-properties@^7.0.0": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz#163b820b9e7696ce134df3ee716d9c0c98035859" + integrity sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-assertions@^7.20.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz#07d252e2aa0bc6125567f742cd58619cb14dce98" + integrity sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" + integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-transform-arrow-functions@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz#e5ba566d0c58a5b2ba2a8b795450641950b71958" + integrity sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-block-scoped-functions@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz#27978075bfaeb9fa586d3cb63a3d30c1de580024" + integrity sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-block-scoping@^7.0.0": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.15.tgz#494eb82b87b5f8b1d8f6f28ea74078ec0a10a841" + integrity sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-classes@^7.0.0": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz#aaf4753aee262a232bbc95451b4bdf9599c65a0b" + integrity sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-split-export-declaration" "^7.22.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz#cd1e994bf9f316bd1c2dafcd02063ec261bb3869" + integrity sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template" "^7.22.5" + +"@babel/plugin-transform-destructuring@^7.0.0": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.15.tgz#e7404ea5bb3387073b9754be654eecb578324694" + integrity sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-flow-strip-types@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz#0bb17110c7bf5b35a60754b2f00c58302381dee2" + integrity sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-flow" "^7.22.5" + +"@babel/plugin-transform-for-of@^7.0.0": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz#f64b4ccc3a4f131a996388fae7680b472b306b29" + integrity sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-function-name@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz#935189af68b01898e0d6d99658db6b164205c143" + integrity sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg== + dependencies: + "@babel/helper-compilation-targets" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-literals@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz#e9341f4b5a167952576e23db8d435849b1dd7920" + integrity sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-member-expression-literals@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz#4fcc9050eded981a468347dd374539ed3e058def" + integrity sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-modules-commonjs@^7.0.0": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz#b11810117ed4ee7691b29bd29fd9f3f98276034f" + integrity sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg== + dependencies: + "@babel/helper-module-transforms" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + +"@babel/plugin-transform-object-super@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz#794a8d2fcb5d0835af722173c1a9d704f44e218c" + integrity sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.5" + +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz#719ca82a01d177af358df64a514d64c2e3edb114" + integrity sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-property-literals@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz#b5ddabd73a4f7f26cd0e20f5db48290b88732766" + integrity sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz#3c4326f9fce31c7968d6cb9debcaf32d9e279a2b" + integrity sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz#7e6266d88705d7c49f11c98db8b9464531289cd6" + integrity sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/types" "^7.22.15" + +"@babel/plugin-transform-shorthand-properties@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz#6e277654be82b5559fc4b9f58088507c24f0c624" + integrity sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-spread@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz#6487fd29f229c95e284ba6c98d65eafb893fea6b" + integrity sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + +"@babel/plugin-transform-template-literals@^7.0.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz#8f38cf291e5f7a8e60e9f733193f0bcc10909bff" + integrity sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.7", "@babel/runtime@^7.22.15", "@babel/runtime@^7.22.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8" integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA== dependencies: regenerator-runtime "^0.14.0" -"@babel/types@^7.22.15": +"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.22.15", "@babel/template@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.14.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.22.15", "@babel/traverse@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.20.tgz#db572d9cb5c79e02d83e5618b82f6991c07584c9" + integrity sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.22.15" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.22.16" + "@babel/types" "^7.22.19" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.16.8", "@babel/types@^7.18.13", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5": version "7.22.19" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.19.tgz#7425343253556916e440e662bb221a93ddb75684" integrity sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg== @@ -345,6 +809,512 @@ resolved "https://registry.yarnpkg.com/@fontsource/roboto/-/roboto-5.0.8.tgz#613b477a56f21b5705db1a67e995c033ef317f76" integrity sha512-XxPltXs5R31D6UZeLIV1td3wTXU3jzd3f2DLsXI8tytMGBkIsGcc9sIyiupRtA8y73HAhuSCeweOoBqf6DbWCA== +"@graphql-codegen/add@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/add/-/add-5.0.0.tgz#578ebaf4fa87c1e934c381cd679bcedcf79feaba" + integrity sha512-ynWDOsK2yxtFHwcJTB9shoSkUd7YXd6ZE57f0nk7W5cu/nAgxZZpEsnTPEpZB/Mjf14YRGe2uJHQ7AfElHjqUQ== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + tslib "~2.5.0" + +"@graphql-codegen/cli@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/cli/-/cli-5.0.0.tgz#761dcf08cfee88bbdd9cdf8097b2343445ec6f0a" + integrity sha512-A7J7+be/a6e+/ul2KI5sfJlpoqeqwX8EzktaKCeduyVKgOLA6W5t+NUGf6QumBDXU8PEOqXk3o3F+RAwCWOiqA== + dependencies: + "@babel/generator" "^7.18.13" + "@babel/template" "^7.18.10" + "@babel/types" "^7.18.13" + "@graphql-codegen/core" "^4.0.0" + "@graphql-codegen/plugin-helpers" "^5.0.1" + "@graphql-tools/apollo-engine-loader" "^8.0.0" + "@graphql-tools/code-file-loader" "^8.0.0" + "@graphql-tools/git-loader" "^8.0.0" + "@graphql-tools/github-loader" "^8.0.0" + "@graphql-tools/graphql-file-loader" "^8.0.0" + "@graphql-tools/json-file-loader" "^8.0.0" + "@graphql-tools/load" "^8.0.0" + "@graphql-tools/prisma-loader" "^8.0.0" + "@graphql-tools/url-loader" "^8.0.0" + "@graphql-tools/utils" "^10.0.0" + "@whatwg-node/fetch" "^0.8.0" + chalk "^4.1.0" + cosmiconfig "^8.1.3" + debounce "^1.2.0" + detect-indent "^6.0.0" + graphql-config "^5.0.2" + inquirer "^8.0.0" + is-glob "^4.0.1" + jiti "^1.17.1" + json-to-pretty-yaml "^1.2.2" + listr2 "^4.0.5" + log-symbols "^4.0.0" + micromatch "^4.0.5" + shell-quote "^1.7.3" + string-env-interpolation "^1.0.1" + ts-log "^2.2.3" + tslib "^2.4.0" + yaml "^2.3.1" + yargs "^17.0.0" + +"@graphql-codegen/client-preset@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/client-preset/-/client-preset-4.1.0.tgz#81becd32b78b207b0e966876900537ec172d8df1" + integrity sha512-/3Ymb/fjxIF1+HGmaI1YwSZbWsrZAWMSQjh3dU425eBjctjsVQ6gzGRr+l/gE5F1mtmCf+vlbTAT03heAc/QIw== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/template" "^7.20.7" + "@graphql-codegen/add" "^5.0.0" + "@graphql-codegen/gql-tag-operations" "4.0.1" + "@graphql-codegen/plugin-helpers" "^5.0.1" + "@graphql-codegen/typed-document-node" "^5.0.1" + "@graphql-codegen/typescript" "^4.0.1" + "@graphql-codegen/typescript-operations" "^4.0.1" + "@graphql-codegen/visitor-plugin-common" "^4.0.1" + "@graphql-tools/documents" "^1.0.0" + "@graphql-tools/utils" "^10.0.0" + "@graphql-typed-document-node/core" "3.2.0" + tslib "~2.5.0" + +"@graphql-codegen/core@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/core/-/core-4.0.0.tgz#b29c911746a532a675e33720acb4eb2119823e01" + integrity sha512-JAGRn49lEtSsZVxeIlFVIRxts2lWObR+OQo7V2LHDJ7ohYYw3ilv7nJ8pf8P4GTg/w6ptcYdSdVVdkI8kUHB/Q== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-tools/schema" "^10.0.0" + "@graphql-tools/utils" "^10.0.0" + tslib "~2.5.0" + +"@graphql-codegen/gql-tag-operations@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.1.tgz#36c7d40a135b9889d7f225166be323c3d48cee87" + integrity sha512-qF6wIbBzW8BNT+wiVsBxrYOs2oYcsxQ7mRvCpfEI3HnNZMAST/uX76W8MqFEJvj4mw7NIDv7xYJAcAZIWM5LWw== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-codegen/visitor-plugin-common" "4.0.1" + "@graphql-tools/utils" "^10.0.0" + auto-bind "~4.0.0" + tslib "~2.5.0" + +"@graphql-codegen/plugin-helpers@^2.7.2": + version "2.7.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-2.7.2.tgz#6544f739d725441c826a8af6a49519f588ff9bed" + integrity sha512-kln2AZ12uii6U59OQXdjLk5nOlh1pHis1R98cDZGFnfaiAbX9V3fxcZ1MMJkB7qFUymTALzyjZoXXdyVmPMfRg== + dependencies: + "@graphql-tools/utils" "^8.8.0" + change-case-all "1.0.14" + common-tags "1.8.2" + import-from "4.0.0" + lodash "~4.17.0" + tslib "~2.4.0" + +"@graphql-codegen/plugin-helpers@^5.0.0", "@graphql-codegen/plugin-helpers@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.1.tgz#e2429fcfba3f078d5aa18aa062d46c922bbb0d55" + integrity sha512-6L5sb9D8wptZhnhLLBcheSPU7Tg//DGWgc5tQBWX46KYTOTQHGqDpv50FxAJJOyFVJrveN9otWk9UT9/yfY4ww== + dependencies: + "@graphql-tools/utils" "^10.0.0" + change-case-all "1.0.15" + common-tags "1.8.2" + import-from "4.0.0" + lodash "~4.17.0" + tslib "~2.5.0" + +"@graphql-codegen/schema-ast@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/schema-ast/-/schema-ast-4.0.0.tgz#5d60996c87b64f81847da8fcb2d8ef50ede89755" + integrity sha512-WIzkJFa9Gz28FITAPILbt+7A8+yzOyd1NxgwFh7ie+EmO9a5zQK6UQ3U/BviirguXCYnn+AR4dXsoDrSrtRA1g== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-tools/utils" "^10.0.0" + tslib "~2.5.0" + +"@graphql-codegen/typed-document-node@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typed-document-node/-/typed-document-node-5.0.1.tgz#ac90cf67c61554f63ec100d6076b47c9f0b18b27" + integrity sha512-VFkhCuJnkgtbbgzoCAwTdJe2G1H6sd3LfCrDqWUrQe53y2ukfSb5Ov1PhAIkCBStKCMQBUY9YgGz9GKR40qQ8g== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-codegen/visitor-plugin-common" "4.0.1" + auto-bind "~4.0.0" + change-case-all "1.0.15" + tslib "~2.5.0" + +"@graphql-codegen/typescript-apollo-client-helpers@^2.2.6": + version "2.2.6" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-apollo-client-helpers/-/typescript-apollo-client-helpers-2.2.6.tgz#a5a7595fe426bbede4a3946dcac564280c6b641b" + integrity sha512-WEWtjg2D/Clmep7fflKmt6o70rZj/Mqf4ywIO5jF/PI91OHpKhLFM2aWm1ythkqALwQ6wJIFlAjdYqz/EOVYdQ== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.7.2" + "@graphql-codegen/visitor-plugin-common" "2.13.1" + auto-bind "~4.0.0" + change-case-all "1.0.14" + tslib "~2.4.0" + +"@graphql-codegen/typescript-operations@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-operations/-/typescript-operations-4.0.1.tgz#930af3e2d2ae8ff06de696291be28fe7046a2fef" + integrity sha512-GpUWWdBVUec/Zqo23aFLBMrXYxN2irypHqDcKjN78JclDPdreasAEPcIpMfqf4MClvpmvDLy4ql+djVAwmkjbw== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-codegen/typescript" "^4.0.1" + "@graphql-codegen/visitor-plugin-common" "4.0.1" + auto-bind "~4.0.0" + tslib "~2.5.0" + +"@graphql-codegen/typescript@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript/-/typescript-4.0.1.tgz#7481d68f59bea802dd10e278dce73c8a1552b2a4" + integrity sha512-3YziQ21dCVdnHb+Us1uDb3pA6eG5Chjv0uTK+bt9dXeMlwYBU8MbtzvQTo4qvzWVC1AxSOKj0rgfNu1xCXqJyA== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-codegen/schema-ast" "^4.0.0" + "@graphql-codegen/visitor-plugin-common" "4.0.1" + auto-bind "~4.0.0" + tslib "~2.5.0" + +"@graphql-codegen/visitor-plugin-common@2.13.1": + version "2.13.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-2.13.1.tgz#2228660f6692bcdb96b1f6d91a0661624266b76b" + integrity sha512-mD9ufZhDGhyrSaWQGrU1Q1c5f01TeWtSWy/cDwXYjJcHIj1Y/DG2x0tOflEfCvh5WcnmHNIw4lzDsg1W7iFJEg== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.7.2" + "@graphql-tools/optimize" "^1.3.0" + "@graphql-tools/relay-operation-optimizer" "^6.5.0" + "@graphql-tools/utils" "^8.8.0" + auto-bind "~4.0.0" + change-case-all "1.0.14" + dependency-graph "^0.11.0" + graphql-tag "^2.11.0" + parse-filepath "^1.0.2" + tslib "~2.4.0" + +"@graphql-codegen/visitor-plugin-common@4.0.1", "@graphql-codegen/visitor-plugin-common@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-4.0.1.tgz#64e293728b3c186f6767141e41fcdb310e50d367" + integrity sha512-Bi/1z0nHg4QMsAqAJhds+ForyLtk7A3HQOlkrZNm3xEkY7lcBzPtiOTLBtvziwopBsXUxqeSwVjOOFPLS5Yw1Q== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-tools/optimize" "^2.0.0" + "@graphql-tools/relay-operation-optimizer" "^7.0.0" + "@graphql-tools/utils" "^10.0.0" + auto-bind "~4.0.0" + change-case-all "1.0.15" + dependency-graph "^0.11.0" + graphql-tag "^2.11.0" + parse-filepath "^1.0.2" + tslib "~2.5.0" + +"@graphql-tools/apollo-engine-loader@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-8.0.0.tgz#ac1f351cbe41508411784f25757f5557b0f27489" + integrity sha512-axQTbN5+Yxs1rJ6cWQBOfw3AEeC+fvIuZSfJLPLLvFJLj4pUm9fhxey/g6oQZAAQJqKPfw+tLDUQvnfvRK8Kmg== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/utils" "^10.0.0" + "@whatwg-node/fetch" "^0.9.0" + tslib "^2.4.0" + +"@graphql-tools/batch-execute@^9.0.1": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-9.0.2.tgz#5ac3257501e7941fad40661bb5e1110d6312f58b" + integrity sha512-Y2uwdZI6ZnatopD/SYfZ1eGuQFI7OU2KGZ2/B/7G9ISmgMl5K+ZZWz/PfIEXeiHirIDhyk54s4uka5rj2xwKqQ== + dependencies: + "@graphql-tools/utils" "^10.0.5" + dataloader "^2.2.2" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/code-file-loader@^8.0.0": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-8.0.2.tgz#224b9ce29d9229c52d8bd7b6d976038f4ea5d3f4" + integrity sha512-AKNpkElUL2cWocYpC4DzNEpo6qJw8Lp+L3bKQ/mIfmbsQxgLz5uve6zHBMhDaFPdlwfIox41N3iUSvi77t9e8A== + dependencies: + "@graphql-tools/graphql-tag-pluck" "8.0.2" + "@graphql-tools/utils" "^10.0.0" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/delegate@^10.0.0", "@graphql-tools/delegate@^10.0.3": + version "10.0.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-10.0.3.tgz#2d0e133da94ca92c24e0c7360414e5592321cf2d" + integrity sha512-Jor9oazZ07zuWkykD3OOhT/2XD74Zm6Ar0ENZMk75MDD51wB2UWUIMljtHxbJhV5A6UBC2v8x6iY0xdCGiIlyw== + dependencies: + "@graphql-tools/batch-execute" "^9.0.1" + "@graphql-tools/executor" "^1.0.0" + "@graphql-tools/schema" "^10.0.0" + "@graphql-tools/utils" "^10.0.5" + dataloader "^2.2.2" + tslib "^2.5.0" + +"@graphql-tools/documents@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/documents/-/documents-1.0.0.tgz#e3ed97197cc22ec830ca227fd7d17e86d8424bdf" + integrity sha512-rHGjX1vg/nZ2DKqRGfDPNC55CWZBMldEVcH+91BThRa6JeT80NqXknffLLEZLRUxyikCfkwMsk6xR3UNMqG0Rg== + dependencies: + lodash.sortby "^4.7.0" + tslib "^2.4.0" + +"@graphql-tools/executor-graphql-ws@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-1.1.0.tgz#7727159ebaa9df4dc793d0d02e74dd1ca4a7cc60" + integrity sha512-yM67SzwE8rYRpm4z4AuGtABlOp9mXXVy6sxXnTJRoYIdZrmDbKVfIY+CpZUJCqS0FX3xf2+GoHlsj7Qswaxgcg== + dependencies: + "@graphql-tools/utils" "^10.0.2" + "@types/ws" "^8.0.0" + graphql-ws "^5.14.0" + isomorphic-ws "^5.0.0" + tslib "^2.4.0" + ws "^8.13.0" + +"@graphql-tools/executor-http@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-http/-/executor-http-1.0.2.tgz#d7964a6e5ec883842f9a8e3f104f93c9b8f472be" + integrity sha512-JKTB4E3kdQM2/1NEcyrVPyQ8057ZVthCV5dFJiKktqY9IdmF00M8gupFcW3jlbM/Udn78ickeUBsUzA3EouqpA== + dependencies: + "@graphql-tools/utils" "^10.0.2" + "@repeaterjs/repeater" "^3.0.4" + "@whatwg-node/fetch" "^0.9.0" + extract-files "^11.0.0" + meros "^1.2.1" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/executor-legacy-ws@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-1.0.3.tgz#de04eaa816fa27f46b401e8d5c28d9c0562b4993" + integrity sha512-rr3IDeO9Dh+8u8KIro++5kzJJYPHkcrIAWzqXtN663nhInC85iW7Ko91yOYwf7ovBci/7s+4Rqe4ZRyca1LGjQ== + dependencies: + "@graphql-tools/utils" "^10.0.0" + "@types/ws" "^8.0.0" + isomorphic-ws "5.0.0" + tslib "^2.4.0" + ws "8.14.1" + +"@graphql-tools/executor@^1.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor/-/executor-1.2.0.tgz#6c45f4add765769d9820c4c4405b76957ba39c79" + integrity sha512-SKlIcMA71Dha5JnEWlw4XxcaJ+YupuXg0QCZgl2TOLFz4SkGCwU/geAsJvUJFwK2RbVLpQv/UMq67lOaBuwDtg== + dependencies: + "@graphql-tools/utils" "^10.0.0" + "@graphql-typed-document-node/core" "3.2.0" + "@repeaterjs/repeater" "^3.0.4" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/git-loader@^8.0.0": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/git-loader/-/git-loader-8.0.2.tgz#d26d87e176ff0cea86e0acfe7c2072f32fd836c3" + integrity sha512-AuCB0nlPvsHh8u42zRZdlD/ZMaWP9A44yAkQUVCZir1E/LG63fsZ9svTWJ+CbusW3Hd0ZP9qpxEhlHxnd4Tlsg== + dependencies: + "@graphql-tools/graphql-tag-pluck" "8.0.2" + "@graphql-tools/utils" "^10.0.0" + is-glob "4.0.3" + micromatch "^4.0.4" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/github-loader@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/github-loader/-/github-loader-8.0.0.tgz#683195800618364701cfea9bc6f88674486f053b" + integrity sha512-VuroArWKcG4yaOWzV0r19ElVIV6iH6UKDQn1MXemND0xu5TzrFme0kf3U9o0YwNo0kUYEk9CyFM0BYg4he17FA== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/executor-http" "^1.0.0" + "@graphql-tools/graphql-tag-pluck" "^8.0.0" + "@graphql-tools/utils" "^10.0.0" + "@whatwg-node/fetch" "^0.9.0" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/graphql-file-loader@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-8.0.0.tgz#a2026405bce86d974000455647511bf65df4f211" + integrity sha512-wRXj9Z1IFL3+zJG1HWEY0S4TXal7+s1vVhbZva96MSp0kbb/3JBF7j0cnJ44Eq0ClccMgGCDFqPFXty4JlpaPg== + dependencies: + "@graphql-tools/import" "7.0.0" + "@graphql-tools/utils" "^10.0.0" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/graphql-tag-pluck@8.0.2", "@graphql-tools/graphql-tag-pluck@^8.0.0": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.0.2.tgz#c1ce8226c951583a27765dccceea19dc5827a948" + integrity sha512-U6fE4yEHxuk/nqmPixHpw1WhqdS6aYuaV60m1bEmUmGJNbpAhaMBy01JncpvpF15yZR5LZ0UjkHg+A3Lhoc8YQ== + dependencies: + "@babel/core" "^7.22.9" + "@babel/parser" "^7.16.8" + "@babel/plugin-syntax-import-assertions" "^7.20.0" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + "@graphql-tools/utils" "^10.0.0" + tslib "^2.4.0" + +"@graphql-tools/import@7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-7.0.0.tgz#a6a91a90a707d5f46bad0fd3fde2f407b548b2be" + integrity sha512-NVZiTO8o1GZs6OXzNfjB+5CtQtqsZZpQOq+Uu0w57kdUkT4RlQKlwhT8T81arEsbV55KpzkpFsOZP7J1wdmhBw== + dependencies: + "@graphql-tools/utils" "^10.0.0" + resolve-from "5.0.0" + tslib "^2.4.0" + +"@graphql-tools/json-file-loader@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/json-file-loader/-/json-file-loader-8.0.0.tgz#9b1b62902f766ef3f1c9cd1c192813ea4f48109c" + integrity sha512-ki6EF/mobBWJjAAC84xNrFMhNfnUFD6Y0rQMGXekrUgY0NdeYXHU0ZUgHzC9O5+55FslqUmAUHABePDHTyZsLg== + dependencies: + "@graphql-tools/utils" "^10.0.0" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/load@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-8.0.0.tgz#62e00f48c39b4085167a096f66ba6c21fb3fc796" + integrity sha512-Cy874bQJH0FP2Az7ELPM49iDzOljQmK1PPH6IuxsWzLSTxwTqd8dXA09dcVZrI7/LsN26heTY2R8q2aiiv0GxQ== + dependencies: + "@graphql-tools/schema" "^10.0.0" + "@graphql-tools/utils" "^10.0.0" + p-limit "3.1.0" + tslib "^2.4.0" + +"@graphql-tools/merge@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-9.0.0.tgz#b0a3636c82716454bff88e9bb40108b0471db281" + integrity sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q== + dependencies: + "@graphql-tools/utils" "^10.0.0" + tslib "^2.4.0" + +"@graphql-tools/optimize@^1.3.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/optimize/-/optimize-1.4.0.tgz#20d6a9efa185ef8fc4af4fd409963e0907c6e112" + integrity sha512-dJs/2XvZp+wgHH8T5J2TqptT9/6uVzIYvA6uFACha+ufvdMBedkfR4b4GbT8jAKLRARiqRTxy3dctnwkTM2tdw== + dependencies: + tslib "^2.4.0" + +"@graphql-tools/optimize@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/optimize/-/optimize-2.0.0.tgz#7a9779d180824511248a50c5a241eff6e7a2d906" + integrity sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg== + dependencies: + tslib "^2.4.0" + +"@graphql-tools/prisma-loader@^8.0.0": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/prisma-loader/-/prisma-loader-8.0.1.tgz#0a013c69b04e0779b5be15757173d458cdf94e35" + integrity sha512-bl6e5sAYe35Z6fEbgKXNrqRhXlCJYeWKBkarohgYA338/SD9eEhXtg3Cedj7fut3WyRLoQFpHzfiwxKs7XrgXg== + dependencies: + "@graphql-tools/url-loader" "^8.0.0" + "@graphql-tools/utils" "^10.0.0" + "@types/js-yaml" "^4.0.0" + "@types/json-stable-stringify" "^1.0.32" + "@whatwg-node/fetch" "^0.9.0" + chalk "^4.1.0" + debug "^4.3.1" + dotenv "^16.0.0" + graphql-request "^6.0.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" + jose "^4.11.4" + js-yaml "^4.0.0" + json-stable-stringify "^1.0.1" + lodash "^4.17.20" + scuid "^1.1.0" + tslib "^2.4.0" + yaml-ast-parser "^0.0.43" + +"@graphql-tools/relay-operation-optimizer@^6.5.0": + version "6.5.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-6.5.18.tgz#a1b74a8e0a5d0c795b8a4d19629b654cf66aa5ab" + integrity sha512-mc5VPyTeV+LwiM+DNvoDQfPqwQYhPV/cl5jOBjTgSniyaq8/86aODfMkrE2OduhQ5E00hqrkuL2Fdrgk0w1QJg== + dependencies: + "@ardatan/relay-compiler" "12.0.0" + "@graphql-tools/utils" "^9.2.1" + tslib "^2.4.0" + +"@graphql-tools/relay-operation-optimizer@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.0.0.tgz#24367666af87bc5a81748de5e8e9b3c523fd4207" + integrity sha512-UNlJi5y3JylhVWU4MBpL0Hun4Q7IoJwv9xYtmAz+CgRa066szzY7dcuPfxrA7cIGgG/Q6TVsKsYaiF4OHPs1Fw== + dependencies: + "@ardatan/relay-compiler" "12.0.0" + "@graphql-tools/utils" "^10.0.0" + tslib "^2.4.0" + +"@graphql-tools/schema@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-10.0.0.tgz#7b5f6b6a59f51c927de8c9069bde4ebbfefc64b3" + integrity sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg== + dependencies: + "@graphql-tools/merge" "^9.0.0" + "@graphql-tools/utils" "^10.0.0" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/url-loader@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/url-loader/-/url-loader-8.0.0.tgz#8d952d5ebb7325e587cb914aaebded3dbd078cf6" + integrity sha512-rPc9oDzMnycvz+X+wrN3PLrhMBQkG4+sd8EzaFN6dypcssiefgWKToXtRKI8HHK68n2xEq1PyrOpkjHFJB+GwA== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/delegate" "^10.0.0" + "@graphql-tools/executor-graphql-ws" "^1.0.0" + "@graphql-tools/executor-http" "^1.0.0" + "@graphql-tools/executor-legacy-ws" "^1.0.0" + "@graphql-tools/utils" "^10.0.0" + "@graphql-tools/wrap" "^10.0.0" + "@types/ws" "^8.0.0" + "@whatwg-node/fetch" "^0.9.0" + isomorphic-ws "^5.0.0" + tslib "^2.4.0" + value-or-promise "^1.0.11" + ws "^8.12.0" + +"@graphql-tools/utils@^10.0.0", "@graphql-tools/utils@^10.0.2", "@graphql-tools/utils@^10.0.5": + version "10.0.6" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-10.0.6.tgz#8a809d6bc0df27ffe8964696f182af2383b5974b" + integrity sha512-hZMjl/BbX10iagovakgf3IiqArx8TPsotq5pwBld37uIX1JiZoSbgbCIFol7u55bh32o6cfDEiiJgfAD5fbeyQ== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + dset "^3.1.2" + tslib "^2.4.0" + +"@graphql-tools/utils@^8.8.0": + version "8.13.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.13.1.tgz#b247607e400365c2cd87ff54654d4ad25a7ac491" + integrity sha512-qIh9yYpdUFmctVqovwMdheVNJqFh+DQNWIhX87FJStfXYnmweBUDATok9fWPleKeFwxnW8IapKmY8m8toJEkAw== + dependencies: + tslib "^2.4.0" + +"@graphql-tools/utils@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-9.2.1.tgz#1b3df0ef166cfa3eae706e3518b17d5922721c57" + integrity sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + tslib "^2.4.0" + +"@graphql-tools/wrap@^10.0.0": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-10.0.1.tgz#9e3d27d2723962c26c4377d5d7ab0d3038bf728c" + integrity sha512-Cw6hVrKGM2OKBXeuAGltgy4tzuqQE0Nt7t/uAqnuokSXZhMHXJUb124Bnvxc2gPZn5chfJSDafDe4Cp8ZAVJgg== + dependencies: + "@graphql-tools/delegate" "^10.0.3" + "@graphql-tools/schema" "^10.0.0" + "@graphql-tools/utils" "^10.0.0" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-typed-document-node/core@3.2.0", "@graphql-typed-document-node/core@^3.1.1", "@graphql-typed-document-node/core@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@humanwhocodes/config-array@^0.11.11": version "0.11.11" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" @@ -364,12 +1334,26 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== -"@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -382,6 +1366,14 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.19" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" + integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@mui/base@5.0.0-beta.15": version "5.0.0-beta.15" resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.15.tgz#76bebd377cc3b7fdc80924759a4100e5319ed0f9" @@ -494,6 +1486,33 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@peculiar/asn1-schema@^2.3.6": + version "2.3.6" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz#3dd3c2ade7f702a9a94dfb395c192f5fa5d6b922" + integrity sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA== + dependencies: + asn1js "^3.0.5" + pvtsutils "^1.3.2" + tslib "^2.4.0" + +"@peculiar/json-schema@^1.1.12": + version "1.1.12" + resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339" + integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w== + dependencies: + tslib "^2.0.0" + +"@peculiar/webcrypto@^1.4.0": + version "1.4.3" + resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz#078b3e8f598e847b78683dc3ba65feb5029b93a7" + integrity sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A== + dependencies: + "@peculiar/asn1-schema" "^2.3.6" + "@peculiar/json-schema" "^1.1.12" + pvtsutils "^1.3.2" + tslib "^2.5.0" + webcrypto-core "^1.7.7" + "@pkgr/utils@^2.3.1": version "2.4.2" resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" @@ -516,6 +1535,11 @@ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.9.0.tgz#9033238b41c4cbe1e961eccb3f79e2c588328cf6" integrity sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA== +"@repeaterjs/repeater@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca" + integrity sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA== + "@swc/core-darwin-arm64@1.3.85": version "1.3.85" resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.85.tgz#f92d3c2b7f85f7dc0707e4ec06e344c96b26b476" @@ -609,6 +1633,20 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@types/apollo-upload-client@^17.0.2": + version "17.0.2" + resolved "https://registry.yarnpkg.com/@types/apollo-upload-client/-/apollo-upload-client-17.0.2.tgz#15dc737663928be27c768117603dfc23c21514bb" + integrity sha512-NphAiBqzZv3iY8Cq+qWyi0QUFFzJ+nVd7QKI/iKV8RfILrpYDL69F/vlhjn4BNxKlmc3LxJHymcf3gFzLBwuZQ== + dependencies: + "@apollo/client" "^3.7.0" + "@types/extract-files" "*" + graphql "14 - 16" + +"@types/extract-files@*": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/extract-files/-/extract-files-8.1.1.tgz#11b67e795ad2c8b483431e8d4f190db2fd22944b" + integrity sha512-dMJJqBqyhsfJKuK7p7HyyNmki7qj1AlwhUKWx6KrU7i1K2T2SPsUsSUTWFmr/sEM1q8rfR8j5IyUmYrDbrhfjQ== + "@types/hoist-non-react-statics@^3.3.0": version "3.3.2" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#dc1e9ded53375d37603c479cc12c693b0878aa2a" @@ -617,17 +1655,27 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" +"@types/js-yaml@^4.0.0": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.6.tgz#4b3afd5158b8749095b1f096967b6d0f838d862f" + integrity sha512-ACTuifTSIIbyksx2HTon3aFtCKWcID7/h3XEmRpDYdMCXxPbl+m9GteOJeaAkiAta/NJaSFuA7ahZ0NkwajDSw== + "@types/json-schema@^7.0.12": version "7.0.13" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== +"@types/json-stable-stringify@^1.0.32": + version "1.0.34" + resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.34.tgz#c0fb25e4d957e0ee2e497c1f553d7f8bb668fd75" + integrity sha512-s2cfwagOQAS8o06TcwKfr9Wx11dNGbH2E9vJz1cqV+a/LOyhWNLUNd6JSRYNzvB4d29UuJX2M0Dj9vE1T8fRXw== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/node@^20.6.2": +"@types/node@*", "@types/node@^20.6.2": version "20.6.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.2.tgz#a065925409f59657022e9063275cd0b9bd7e1b12" integrity sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw== @@ -692,6 +1740,13 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.2.tgz#31f6eec1ed7ec23f4f05608d3a2d381df041f564" integrity sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw== +"@types/ws@^8.0.0": + version "8.5.5" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb" + integrity sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -796,6 +1851,78 @@ dependencies: "@swc/core" "^1.3.61" +"@whatwg-node/events@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.3.tgz#13a65dd4f5893f55280f766e29ae48074927acad" + integrity sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA== + +"@whatwg-node/events@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.1.1.tgz#0ca718508249419587e130da26d40e29d99b5356" + integrity sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w== + +"@whatwg-node/fetch@^0.8.0": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.8.8.tgz#48c6ad0c6b7951a73e812f09dd22d75e9fa18cae" + integrity sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg== + dependencies: + "@peculiar/webcrypto" "^1.4.0" + "@whatwg-node/node-fetch" "^0.3.6" + busboy "^1.6.0" + urlpattern-polyfill "^8.0.0" + web-streams-polyfill "^3.2.1" + +"@whatwg-node/fetch@^0.9.0": + version "0.9.13" + resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.9.13.tgz#1d084cd546b9cd425ae89cbb1252a3e47a9a2e1c" + integrity sha512-PPtMwhjtS96XROnSpowCQM85gCUG2m7AXZFw0PZlGbhzx2GK7f2iOXilfgIJ0uSlCuuGbOIzfouISkA7C4FJOw== + dependencies: + "@whatwg-node/node-fetch" "^0.4.17" + urlpattern-polyfill "^9.0.0" + +"@whatwg-node/node-fetch@^0.3.6": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz#e28816955f359916e2d830b68a64493124faa6d0" + integrity sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA== + dependencies: + "@whatwg-node/events" "^0.0.3" + busboy "^1.6.0" + fast-querystring "^1.1.1" + fast-url-parser "^1.1.3" + tslib "^2.3.1" + +"@whatwg-node/node-fetch@^0.4.17": + version "0.4.19" + resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.4.19.tgz#29c72ff65a8e450949238612ff17a3d3717736d3" + integrity sha512-AW7/m2AuweAoSXmESrYQr/KBafueScNbn2iNO0u6xFr2JZdPmYsSm5yvAXYk6yDLv+eDmSSKrf7JnFZ0CsJIdA== + dependencies: + "@whatwg-node/events" "^0.1.0" + busboy "^1.6.0" + fast-querystring "^1.1.1" + fast-url-parser "^1.1.3" + tslib "^2.3.1" + +"@wry/context@^0.7.0", "@wry/context@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.7.3.tgz#240f6dfd4db5ef54f81f6597f6714e58d4f476a1" + integrity sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA== + dependencies: + tslib "^2.3.0" + +"@wry/equality@^0.5.6": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.6.tgz#cd4a533c72c3752993ab8cbf682d3d20e3cb601e" + integrity sha512-D46sfMTngaYlrH+OspKf8mIJETntFnf6Hsjb0V41jAXJ7Bx2kB8Rv8RCUujuVWYttFtHkUNp7g+FwxNQAr6mXA== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.4.3.tgz#077d52c22365871bf3ffcbab8e95cb8bc5689af4" + integrity sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w== + dependencies: + tslib "^2.3.0" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -811,6 +1938,21 @@ acorn@^8.4.1, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== + dependencies: + debug "^4.3.4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -821,6 +1963,13 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -840,6 +1989,13 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +apollo-upload-client@^17.0.0: + version "17.0.0" + resolved "https://registry.yarnpkg.com/apollo-upload-client/-/apollo-upload-client-17.0.0.tgz#d9baaff8d14e54510de9f2855b487e75ca63b392" + integrity sha512-pue33bWVbdlXAGFPkgz53TTmxVMrKeQr0mdRcftNY+PoHIdbGZD0hoaXHvO6OePJAkFz7OiCFUf98p1G/9+Ykw== + dependencies: + extract-files "^11.0.0" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -936,11 +2092,30 @@ arraybuffer.prototype.slice@^1.0.2: is-array-buffer "^3.0.2" is-shared-array-buffer "^1.0.2" +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +asn1js@^3.0.1, asn1js@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38" + integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ== + dependencies: + pvtsutils "^1.3.2" + pvutils "^1.1.3" + tslib "^2.4.0" + ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + asynciterator.prototype@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62" @@ -953,6 +2128,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +auto-bind@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" + integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== + available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -988,16 +2168,68 @@ babel-plugin-macros@^3.1.0: cosmiconfig "^7.0.0" resolve "^1.19.0" +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" + integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + +babel-preset-fbjs@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" + integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + big-integer@^1.6.44: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bplist-parser@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" @@ -1020,6 +2252,31 @@ braces@^3.0.2: dependencies: fill-range "^7.0.1" +browserslist@^4.21.9: + version "4.21.10" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.10.tgz#dbbac576628c13d3b2231332cb2ec5a46e015bb0" + integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ== + dependencies: + caniuse-lite "^1.0.30001517" + electron-to-chromium "^1.4.477" + node-releases "^2.0.13" + update-browserslist-db "^1.0.11" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + bundle-name@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" @@ -1027,6 +2284,13 @@ bundle-name@^3.0.0: dependencies: run-applescript "^5.0.0" +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1040,6 +2304,33 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-lite@^1.0.30001517: + version "1.0.30001534" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001534.tgz#f24a9b2a6d39630bac5c132b5dff89b39a12e7dd" + integrity sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q== + +capital-case@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" + integrity sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1049,7 +2340,7 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1057,10 +2348,99 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -client-only@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== +change-case-all@1.0.14: + version "1.0.14" + resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-1.0.14.tgz#bac04da08ad143278d0ac3dda7eccd39280bfba1" + integrity sha512-CWVm2uT7dmSHdO/z1CXT/n47mWonyypzBbuCy5tN7uMg22BsfkhwT6oHmFCAk+gL1LOOxhdbB9SZz3J1KTY3gA== + dependencies: + change-case "^4.1.2" + is-lower-case "^2.0.2" + is-upper-case "^2.0.2" + lower-case "^2.0.2" + lower-case-first "^2.0.2" + sponge-case "^1.0.1" + swap-case "^2.0.2" + title-case "^3.0.3" + upper-case "^2.0.2" + upper-case-first "^2.0.2" + +change-case-all@1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-1.0.15.tgz#de29393167fc101d646cd76b0ef23e27d09756ad" + integrity sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ== + dependencies: + change-case "^4.1.2" + is-lower-case "^2.0.2" + is-upper-case "^2.0.2" + lower-case "^2.0.2" + lower-case-first "^2.0.2" + sponge-case "^1.0.1" + swap-case "^2.0.2" + title-case "^3.0.3" + upper-case "^2.0.2" + upper-case-first "^2.0.2" + +change-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" + integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== + dependencies: + camel-case "^4.1.2" + capital-case "^1.0.4" + constant-case "^3.0.4" + dot-case "^3.0.4" + header-case "^2.0.4" + no-case "^3.0.4" + param-case "^3.0.4" + pascal-case "^3.1.2" + path-case "^3.0.4" + sentence-case "^3.0.4" + snake-case "^3.0.4" + tslib "^2.0.3" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.9.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.1.tgz#9c0b9dad69a6d47cbb4333c14319b060ed395a35" + integrity sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ== + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" cliui@^8.0.1: version "8.0.1" @@ -1071,6 +2451,11 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + clsx@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" @@ -1100,6 +2485,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.16: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1112,6 +2502,11 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +common-tags@1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" + integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1122,7 +2517,16 @@ confusing-browser-globals@^1.0.10: resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== -convert-source-map@^1.5.0: +constant-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" + integrity sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case "^2.0.2" + +convert-source-map@^1.5.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -1138,11 +2542,28 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +cosmiconfig@^8.1.0, cosmiconfig@^8.1.3: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1169,6 +2590,23 @@ damerau-levenshtein@^1.0.8: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +dataloader@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.2.2.tgz#216dc509b5abe39d43a9b9d97e6e5e473dfbe3e0" + integrity sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g== + +debounce@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1176,12 +2614,10 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== deep-is@^0.1.3: version "0.1.4" @@ -1206,6 +2642,13 @@ default-browser@^4.0.0: execa "^7.1.1" titleize "^3.0.0" +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + define-data-property@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.0.tgz#0db13540704e1d8d479a0656cf781267531b9451" @@ -1234,11 +2677,21 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +dependency-graph@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" + integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== + dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +detect-indent@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" + integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -1273,6 +2726,29 @@ dom-helpers@^5.0.1: "@babel/runtime" "^7.8.7" csstype "^3.0.2" +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +dotenv@^16.0.0: + version "16.3.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" + integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== + +dset@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a" + integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q== + +electron-to-chromium@^1.4.477: + version "1.4.523" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.523.tgz#f82f99243c827df05c26776d49712cb284972df6" + integrity sha512-9AreocSUWnzNtvLcbpng6N+GkXnCcBR80IQkxRC9Dfdyg4gaWNUPBujAHUpKkiUkoSoR9UlhA4zD/IgBklmhzg== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1679,6 +3155,25 @@ execa@^7.1.1: signal-exit "^3.0.7" strip-final-newline "^3.0.0" +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extract-files@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a" + integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ== + +fast-decode-uri-component@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" + integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1710,6 +3205,20 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-querystring@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53" + integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg== + dependencies: + fast-decode-uri-component "^1.0.1" + +fast-url-parser@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== + dependencies: + punycode "^1.3.2" + fastq@^1.6.0: version "1.15.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -1717,6 +3226,38 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + +fbjs@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.5.tgz#aa0edb7d5caa6340011790bd9249dbef8a81128d" + integrity sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg== + dependencies: + cross-fetch "^3.1.5" + fbjs-css-vars "^1.0.0" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^1.0.35" + +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1743,6 +3284,14 @@ find-root@^1.1.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -1816,7 +3365,12 @@ functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -get-caller-file@^2.0.5: +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -1858,7 +3412,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -1870,6 +3424,11 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + globals@^13.19.0: version "13.21.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.21.0.tgz#163aae12f34ef502f5153cfbdd3600f36c63c571" @@ -1884,7 +3443,7 @@ globalthis@^1.0.3: dependencies: define-properties "^1.1.3" -globby@^11.1.0: +globby@^11.0.3, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -1913,6 +3472,53 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphql-config@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-5.0.2.tgz#7e962f94ccddcc2ee0aa71d75cf4491ec5092bdb" + integrity sha512-7TPxOrlbiG0JplSZYCyxn2XQtqVhXomEjXUmWJVSS5ET1nPhOJSsIb/WTwqWhcYX6G0RlHXSj9PLtGTKmxLNGg== + dependencies: + "@graphql-tools/graphql-file-loader" "^8.0.0" + "@graphql-tools/json-file-loader" "^8.0.0" + "@graphql-tools/load" "^8.0.0" + "@graphql-tools/merge" "^9.0.0" + "@graphql-tools/url-loader" "^8.0.0" + "@graphql-tools/utils" "^10.0.0" + cosmiconfig "^8.1.0" + jiti "^1.18.2" + minimatch "^4.2.3" + string-env-interpolation "^1.0.1" + tslib "^2.4.0" + +graphql-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f" + integrity sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw== + dependencies: + "@graphql-typed-document-node/core" "^3.2.0" + cross-fetch "^3.1.5" + +graphql-tag@^2.11.0, graphql-tag@^2.12.6: + version "2.12.6" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" + integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== + dependencies: + tslib "^2.1.0" + +graphql-ws@^5.14.0: + version "5.14.0" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.14.0.tgz#766f249f3974fc2c48fae0d1fb20c2c4c79cd591" + integrity sha512-itrUTQZP/TgswR4GSSYuwWUzrE/w5GhbwM2GX3ic2U7aw33jgEsayfIlvaj7/GcIvZgNMzsPTrE5hqPuFUiE5g== + +graphql-ws@^5.14.1: + version "5.14.1" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.14.1.tgz#d05dba9c2cbf1582c990a2dfec4b8f6a55d99da4" + integrity sha512-aqkls1espsygP1PfkAuuLIV96IbztQ6EaADse97pw8wRIMT3+AL/OYfS8V2iCRkc0gzckitoDRGCQEdnySggiA== + +"graphql@14 - 16": + version "16.8.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.0.tgz#374478b7f27b2dc6153c8f42c1b80157f79d79d4" + integrity sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -1959,6 +3565,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +header-case@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" + integrity sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q== + dependencies: + capital-case "^1.0.4" + tslib "^2.0.3" + hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -1973,6 +3587,22 @@ html-parse-stringify@^3.0.1: dependencies: void-elements "3.1.0" +http-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673" + integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +https-proxy-agent@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -1997,12 +3627,29 @@ i18next@^23.5.1: dependencies: "@babel/runtime" "^7.22.5" +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.2.0, ignore@^5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -import-fresh@^3.2.1: +immutable@~3.7.6: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + integrity sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw== + +import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -2010,11 +3657,21 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-from@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-4.0.0.tgz#2710b8d66817d232e16f4166e319248d3d5492e2" + integrity sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -2023,11 +3680,32 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inquirer@^8.0.0: + version "8.2.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" + integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^6.0.1" + internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" @@ -2037,6 +3715,21 @@ internal-slot@^1.0.5: has "^1.0.3" side-channel "^1.0.4" +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" @@ -2126,7 +3819,7 @@ is-generator-function@^1.0.10: dependencies: has-tostringtag "^1.0.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@4.0.3, is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -2140,6 +3833,18 @@ is-inside-container@^1.0.0: dependencies: is-docker "^3.0.0" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-2.0.2.tgz#1c0884d3012c841556243483aa5d522f47396d2a" + integrity sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ== + dependencies: + tslib "^2.0.3" + is-map@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" @@ -2175,6 +3880,13 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + is-set@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" @@ -2218,6 +3930,25 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: dependencies: which-typed-array "^1.1.11" +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-2.0.2.tgz#f1105ced1fe4de906a5f39553e7d3803fd804649" + integrity sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ== + dependencies: + tslib "^2.0.3" + is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -2238,6 +3969,11 @@ is-weakset@^2.0.1: call-bind "^1.0.2" get-intrinsic "^1.1.1" +is-windows@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -2255,6 +3991,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isomorphic-ws@5.0.0, isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + iterator.prototype@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" @@ -2266,18 +4007,33 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" +jiti@^1.17.1, jiti@^1.18.2: + version "1.20.0" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.20.0.tgz#2d823b5852ee8963585c8dd8b7992ffc1ae83b42" + integrity sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA== + +jose@^4.11.4: + version "4.14.6" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.14.6.tgz#94dca1d04a0ad8c6bff0998cdb51220d473cc3af" + integrity sha512-EqJPEUlZD0/CSUMubKtMaYUOtWe91tZXTWMJZoKSbLk+KtdhNdcvppH8lA9XwVu2V4Ailvsj0GBZJ2ZwDjfesQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^4.1.0: +js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -2298,6 +4054,21 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stable-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== + dependencies: + jsonify "^0.0.1" + +json-to-pretty-yaml@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz#f4cd0bd0a5e8fe1df25aaf5ba118b099fd992d5b" + integrity sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A== + dependencies: + remedial "^1.0.7" + remove-trailing-spaces "^1.0.6" + json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -2305,6 +4076,16 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: version "3.3.5" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" @@ -2347,6 +4128,27 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +listr2@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" + integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.5" + through "^2.3.8" + wrap-ansi "^7.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -2359,13 +4161,62 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -loose-envify@^1.1.0, loose-envify@^1.4.0: +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== + +lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^4.0.0, log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" +lower-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-2.0.2.tgz#64c2324a2250bf7c37c5901e76a5b5309301160b" + integrity sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg== + dependencies: + tslib "^2.0.3" + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2378,6 +4229,11 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +map-cache@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + memoize-one@^5.1.1: version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" @@ -2393,7 +4249,12 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.4: +meros@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/meros/-/meros-1.3.0.tgz#c617d2092739d55286bf618129280f362e6242f2" + integrity sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w== + +micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -2430,6 +4291,13 @@ minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.3.tgz#b4dcece1d674dee104bb0fb833ebb85a78cbbca6" + integrity sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng== + dependencies: + brace-expansion "^1.1.7" + minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -2445,6 +4313,11 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nanoid@^3.3.6: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" @@ -2455,6 +4328,38 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-fetch@^2.6.1, node-fetch@^2.6.12: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== + dependencies: + remove-trailing-separator "^1.0.1" + npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -2469,7 +4374,12 @@ npm-run-path@^5.1.0: dependencies: path-key "^4.0.0" -object-assign@^4.1.1: +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -2546,7 +4456,7 @@ once@^1.3.0: dependencies: wrappy "1" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -2570,6 +4480,15 @@ open@^9.1.0: is-inside-container "^1.0.0" is-wsl "^2.2.0" +optimism@^0.17.5: + version "0.17.5" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.17.5.tgz#a4c78b3ad12c58623abedbebb4f2f2c19b8e8816" + integrity sha512-TEcp8ZwK1RczmvMnvktxHSF2tKgMWjJ71xEFGX5ApLh67VsMSTy1ZUlipJw8W+KaqgOmQ+4pqwkeivY89j+4Vw== + dependencies: + "@wry/context" "^0.7.0" + "@wry/trie" "^0.4.3" + tslib "^2.3.0" + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -2582,13 +4501,47 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" -p-limit@^3.0.2: +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-limit@3.1.0, p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -2596,6 +4549,26 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2603,7 +4576,16 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^5.0.0: +parse-filepath@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q== + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -2613,6 +4595,22 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +path-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" + integrity sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -2638,6 +4636,18 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ== + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg== + dependencies: + path-root-regex "^0.1.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -2679,6 +4689,13 @@ prettier@^3.0.3: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -2693,11 +4710,28 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +pvtsutils@^1.3.2: + version "1.3.5" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.5.tgz#b8705b437b7b134cd7fd858f025a23456f1ce910" + integrity sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA== + dependencies: + tslib "^2.6.1" + +pvutils@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" + integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -2801,6 +4835,15 @@ react@^18.2.0: dependencies: loose-envify "^1.1.0" +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + redux@^4.0.0, redux@^4.0.4: version "4.2.1" resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" @@ -2834,11 +4877,45 @@ regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: define-properties "^1.2.0" set-function-name "^2.0.0" +relay-runtime@12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-12.0.0.tgz#1e039282bdb5e0c1b9a7dc7f6b9a09d4f4ff8237" + integrity sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug== + dependencies: + "@babel/runtime" "^7.0.0" + fbjs "^3.0.0" + invariant "^2.2.4" + +remedial@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0" + integrity sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg== + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== + +remove-trailing-spaces@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz#4354d22f3236374702f58ee373168f6d6887ada7" + integrity sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-from@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -2862,11 +4939,29 @@ resolve@^2.0.0-next.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +response-iterator@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/response-iterator/-/response-iterator-0.2.6.tgz#249005fb14d2e4eeb478a3f735a28fd8b4c9f3da" + integrity sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw== + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -2888,6 +4983,11 @@ run-applescript@^5.0.0: dependencies: execa "^5.0.0" +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -2895,6 +4995,13 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@^7.5.5: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + safe-array-concat@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" @@ -2905,6 +5012,11 @@ safe-array-concat@^1.0.1: has-symbols "^1.0.3" isarray "^2.0.5" +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -2914,6 +5026,11 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -2921,6 +5038,11 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" +scuid@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/scuid/-/scuid-1.1.0.tgz#d3f9f920956e737a60f72d0e4ad280bf324d5dab" + integrity sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg== + semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -2933,11 +5055,25 @@ semver@^7.5.4: dependencies: lru-cache "^6.0.0" +sentence-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" + integrity sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + serialize-query-params@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/serialize-query-params/-/serialize-query-params-2.0.2.tgz#598a3fb9e13f4ea1c1992fbd20231aa16b31db81" integrity sha512-1chMo1dST4pFA9RDXAtF0Rbjaut4is7bzFbI1Z26IuMub68pNCILku85aYmeFhvnY//BXUPUhoRMjYcsT93J/Q== +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + set-function-name@^2.0.0, set-function-name@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" @@ -2947,6 +5083,11 @@ set-function-name@^2.0.0, set-function-name@^2.0.1: functions-have-names "^1.2.3" has-property-descriptors "^1.0.0" +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -2959,6 +5100,11 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shell-quote@^1.7.3: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -2968,16 +5114,47 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signedsource@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" + integrity sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" @@ -2988,6 +5165,23 @@ source-map@^0.5.7: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== +sponge-case@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sponge-case/-/sponge-case-1.0.1.tgz#260833b86453883d974f84854cdb63aecc5aef4c" + integrity sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA== + dependencies: + tslib "^2.0.3" + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +string-env-interpolation@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz#ad4397ae4ac53fe6c91d1402ad6f6a52862c7152" + integrity sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg== + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -3039,6 +5233,13 @@ string.prototype.trimstart@^1.0.7: define-properties "^1.2.0" es-abstract "^1.22.1" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -3090,13 +5291,17 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -swr@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/swr/-/swr-2.2.2.tgz#abcb1f9c97e10527789884169d58b878472d4c98" - integrity sha512-CbR41AoMD4TQBQw9ic3GTXspgfM9Y8Mdhb5Ob4uIKXhWqnRLItwA5fpGvB7SmSw3+zEjb0PdhiEumtUvYoQ+bQ== +swap-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-2.0.2.tgz#671aedb3c9c137e2985ef51c51f9e98445bf70d9" + integrity sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw== dependencies: - client-only "^0.0.1" - use-sync-external-store "^1.2.0" + tslib "^2.0.3" + +symbol-observable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" + integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== synckit@^0.8.5: version "0.8.5" @@ -3119,16 +5324,35 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +through@^2.3.6, through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + tiny-invariant@^1.0.6: version "1.3.1" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== +title-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982" + integrity sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA== + dependencies: + tslib "^2.0.3" + titleize@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -3141,11 +5365,28 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-api-utils@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== +ts-invariant@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c" + integrity sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ== + dependencies: + tslib "^2.1.0" + +ts-log@^2.2.3: + version "2.2.5" + resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.2.5.tgz#aef3252f1143d11047e2cb6f7cfaac7408d96623" + integrity sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA== + ts-node@^10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -3180,11 +5421,21 @@ tsconfig-paths@^3.14.2: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.0: +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.0, tslib@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslib@~2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== + +tslib@~2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -3197,6 +5448,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -3241,6 +5497,11 @@ typescript@^5.2.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== +ua-parser-js@^1.0.35: + version "1.0.36" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.36.tgz#a9ab6b9bd3a8efb90bb0816674b412717b7c428c" + integrity sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -3251,11 +5512,45 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== + +unixify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" + integrity sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg== + dependencies: + normalize-path "^2.1.1" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +upper-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324" + integrity sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg== + dependencies: + tslib "^2.0.3" + +upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-2.0.2.tgz#d89810823faab1df1549b7d97a76f8662bae6f7a" + integrity sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg== + dependencies: + tslib "^2.0.3" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -3263,6 +5558,16 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urlpattern-polyfill@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz#99f096e35eff8bf4b5a2aa7d58a1523d6ebc7ce5" + integrity sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ== + +urlpattern-polyfill@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz#bc7e386bb12fd7898b58d1509df21d3c29ab3460" + integrity sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g== + use-memo-one@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99" @@ -3275,16 +5580,21 @@ use-query-params@^2.2.1: dependencies: serialize-query-params "^2.0.2" -use-sync-external-store@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +value-or-promise@^1.0.11, value-or-promise@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c" + integrity sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q== + vite-tsconfig-paths@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.1.tgz#e53b89096b91d31a6d1e26f75999ea8c336a89ed" @@ -3310,6 +5620,42 @@ void-elements@3.1.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +web-streams-polyfill@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + +webcrypto-core@^1.7.7: + version "1.7.7" + resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.7.tgz#06f24b3498463e570fed64d7cab149e5437b162c" + integrity sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g== + dependencies: + "@peculiar/asn1-schema" "^2.3.6" + "@peculiar/json-schema" "^1.1.12" + asn1js "^3.0.1" + pvtsutils "^1.3.2" + tslib "^2.4.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -3349,6 +5695,11 @@ which-collection@^1.0.1: is-weakmap "^2.0.1" is-weakset "^2.0.1" +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + which-typed-array@^1.1.11, which-typed-array@^1.1.9: version "1.1.11" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" @@ -3367,6 +5718,15 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -3381,27 +5741,77 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +ws@8.14.1, ws@^8.12.0, ws@^8.13.0: + version "8.14.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.1.tgz#4b9586b4f70f9e6534c7bb1d3dc0baa8b8cf01e0" + integrity sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml-ast-parser@^0.0.43: + version "0.0.43" + resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" + integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== + yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144" + integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.7.2: +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.0.0, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -3423,3 +5833,15 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zen-observable-ts@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58" + integrity sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg== + dependencies: + zen-observable "0.8.15" + +zen-observable@0.8.15: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==