Update dependency "apollo-client" to v4.x

v4.1.6
This commit is contained in:
schroda
2026-03-09 22:18:08 +01:00
parent 1f323baff4
commit c6343e24a5
21 changed files with 964 additions and 1686 deletions

View File

@@ -39,7 +39,7 @@
"@swc/core": "1.15.11"
},
"dependencies": {
"@apollo/client": "3.13.9",
"@apollo/client": "4.1.6",
"@dnd-kit/core": "6.3.1",
"@dnd-kit/sortable": "10.0.0",
"@dnd-kit/utilities": "3.2.2",
@@ -58,7 +58,7 @@
"@mui/x-date-pickers": "8.27.2",
"@redux-devtools/extension": "3.3.0",
"@vibrant/color": "4.0.4",
"apollo-upload-client": "18.0.1",
"apollo-upload-client": "19.0.0",
"awaitable-component": "1.0.0",
"csstype": "3.2.3",
"dayjs": "1.11.19",
@@ -83,6 +83,7 @@
"react-lazily": "0.9.2",
"react-router-dom": "6.26.1",
"react-virtuoso": "4.18.3",
"rxjs": "7.8.2",
"stylis": "4.3.6",
"stylis-plugin-rtl": "2.1.1",
"use-long-press": "3.3.0",
@@ -91,15 +92,14 @@
"zustand": "5.0.11"
},
"devDependencies": {
"@graphql-codegen/cli": "5.0.7",
"@graphql-codegen/client-preset": "4.8.3",
"@graphql-codegen/typescript-apollo-client-helpers": "3.0.1",
"@graphql-codegen/typescript-operations": "4.6.1",
"@graphql-codegen/cli": "6.1.3",
"@graphql-codegen/client-preset": "5.2.4",
"@graphql-codegen/typescript-apollo-client-helpers": "4.0.0",
"@graphql-codegen/typescript-operations": "5.0.9",
"@lingui/cli": "5.9.2",
"@lingui/format-po": "5.9.2",
"@lingui/swc-plugin": "5.11.0",
"@lingui/vite-plugin": "5.9.2",
"@types/apollo-upload-client": "18.0.0",
"@types/node": "24.10.1",
"@types/react": "19.2.14",
"@types/react-beautiful-dnd": "13.1.8",

17
src/apollo-upload-client.d.ts vendored Normal file
View File

@@ -0,0 +1,17 @@
/*
* 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/.
*/
declare module 'apollo-upload-client/UploadHttpLink.mjs' {
import { ApolloLink } from '@apollo/client';
import type { BaseHttpLink } from '@apollo/client/link/http';
// eslint-disable-next-line import/no-default-export
export default class UploadHttpLink extends ApolloLink {
constructor(options?: BaseHttpLink.ConstructorOptions);
}
}

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { ReactNode } from 'react';
import { ReactNode, useEffect } from 'react';
import { SplashScreen } from '@/features/authentication/components/SplashScreen.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { AuthManager } from '@/features/authentication/AuthManager.ts';
@@ -14,19 +14,20 @@ import { AuthManager } from '@/features/authentication/AuthManager.ts';
export const AuthGuard = ({ children }: { children: ReactNode }) => {
const { isAuthRequired } = AuthManager.useSession();
requestManager.useGetAbout({
const { data } = requestManager.useGetAbout({
skip: isAuthRequired !== null,
onCompleted: () => {
if (AuthManager.isAuthInitialized()) {
return;
}
AuthManager.setAuthRequired(false);
AuthManager.setAuthInitialized(true);
requestManager.processQueues();
},
});
useEffect(() => {
if (!data || AuthManager.isAuthInitialized()) {
return;
}
AuthManager.setAuthRequired(false);
AuthManager.setAuthInitialized(true);
requestManager.processQueues();
}, [data]);
if (isAuthRequired === null) {
return <SplashScreen />;
}

View File

@@ -132,7 +132,7 @@ export function Backup() {
const backupFileUrl = backupFileResponse.data?.createBackup.url;
if (!backupFileUrl) {
makeToast(t`Could not create backup`, 'error', getErrorMessage(backupFileResponse.errors));
makeToast(t`Could not create backup`, 'error', getErrorMessage(backupFileResponse.error));
return;
}
@@ -149,9 +149,14 @@ export function Backup() {
const validateBackup = async (file: File) => {
try {
const {
data: { validateBackup: validateBackupData },
} = await requestManager.validateBackupFile(file, { fetchPolicy: 'network-only' }).response;
const validateBackupResponse = await requestManager.validateBackupFile(file, {
fetchPolicy: 'network-only',
}).response;
const validateBackupData = validateBackupResponse.data?.validateBackup;
if (!validateBackupData) {
return false;
}
if (validateBackupData.missingSources.length || validateBackupData.missingTrackers.length) {
try {

View File

@@ -110,6 +110,11 @@ const handleDownload = async (
order: [{ by: ChapterOrderBy.SourceOrder, byType: SortOrder.Desc }],
},
).response;
if (!chapters.data) {
return;
}
const filteredChapters = filterChapters(chapters.data.chapters.nodes, meta);
const doNecessaryDownloadAheadDownloadsExist =

View File

@@ -6,7 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { DocumentNode, MaybeMasked, Unmasked, useFragment } from '@apollo/client';
import { DocumentNode, MaybeMasked, Unmasked } from '@apollo/client';
import { useFragment } from '@apollo/client/react';
import { t } from '@lingui/core/macro';
import { makeToast } from '@/base/utils/Toast.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';

View File

@@ -49,6 +49,10 @@ const removeNonLibraryMangasFromCategories = async (): Promise<void> => {
{ fetchPolicy: 'no-cache' },
).response;
if (!nonLibraryMangas.data) {
return;
}
const mangaIdsToRemove = Mangas.getIds(nonLibraryMangas.data.mangas.nodes);
if (mangaIdsToRemove.length) {

View File

@@ -103,6 +103,10 @@ export const useManageMangaLibraryState = (
makeToast(t`Could not load categories`, 'error', getErrorMessage(e));
return;
}
if (!categories.data) {
return;
}
const userCreatedCategories = Categories.getUserCreated(categories.data.categories.nodes);
let duplicatedLibraryMangas:
@@ -135,8 +139,8 @@ export const useManageMangaLibraryState = (
);
}
const doDuplicatesExist = duplicatedLibraryMangas?.data.mangas.totalCount;
if (doDuplicatesExist) {
const duplicateMangas = duplicatedLibraryMangas?.data?.mangas;
if (duplicateMangas?.totalCount) {
await Confirmation.show(
{
title: t`Are you sure?`,
@@ -146,7 +150,7 @@ export const useManageMangaLibraryState = (
show: true,
title: t`Show entry`,
contain: true,
link: AppRoutes.manga.path(duplicatedLibraryMangas!.data.mangas.nodes[0].id),
link: AppRoutes.manga.path(duplicateMangas.nodes[0].id),
},
confirm: {
title: t`Add`,

View File

@@ -7,7 +7,7 @@
*/
import { useCallback, useState } from 'react';
import { ApolloError } from '@apollo/client';
import { CombinedGraphQLErrors } from '@apollo/client';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { baseCleanup } from '@/base/utils/Strings.ts';
@@ -23,7 +23,7 @@ export const useRefreshManga = (mangaId: string) => {
requestManager.getMangaChaptersFetch(mangaId, { awaitRefetchQueries: true }).response,
])
.catch((e) => {
if (e instanceof ApolloError && baseCleanup(e.message) === 'no chapters found') {
if (CombinedGraphQLErrors.is(e) && baseCleanup(e.message) === 'no chapters found') {
return;
}

View File

@@ -13,7 +13,7 @@ import Stack from '@mui/material/Stack';
import Box from '@mui/material/Box';
import React, { useEffect, useRef } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { isNetworkRequestInFlight } from '@apollo/client/core/networkStatus';
import { isNetworkRequestInFlight } from '@apollo/client/utilities';
import { useLingui } from '@lingui/react/macro';
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts';

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { DocumentNode, Unmasked } from '@apollo/client/core';
import { DocumentNode, Unmasked } from '@apollo/client';
import { t } from '@lingui/core/macro';
import { i18n } from '@/i18n';
import { requestManager } from '@/lib/requests/RequestManager.ts';
@@ -197,7 +197,7 @@ export class Mangas {
state: Pick<ChapterConditionInput, 'isRead' | 'isDownloaded' | 'isBookmarked'>,
): Promise<GetMangasChapterIdsWithStateQuery['chapters']['nodes']> {
const { data } = await requestManager.getMangasChapterIdsWithState(mangaIds, state).response;
return data.chapters.nodes;
return data?.chapters.nodes ?? [];
}
static async downloadChapters(
@@ -519,7 +519,7 @@ export class Mangas {
getMetadataServerSettings(),
]);
if (!mangaToMigrateData.manga || !mangaToMigrateToData?.fetchManga?.manga) {
if (!mangaToMigrateData?.manga || !mangaToMigrateToData?.fetchManga?.manga) {
throw new Error('Mangas::migrate: missing manga data');
}

View File

@@ -6,10 +6,12 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { ReadFieldFunction } from '@apollo/client/cache/core/types/common';
import { FieldFunctionOptions } from '@apollo/client/cache';
import { Reference } from '@apollo/client/utilities';
import { MetaType } from '@/lib/graphql/generated/graphql.ts';
type ReadFieldFunction = FieldFunctionOptions['readField'];
export const updateMetadataList = (
meta: MetaType[],
existingMetas: Reference[] | undefined,

View File

@@ -28,7 +28,10 @@ export const ImagesSettings = () => {
const clearCache = async () => {
try {
await Promise.all([triggerClearServerCache(), ImageCache.clearAll()]);
await Promise.all([
triggerClearServerCache({ variables: { input: { cachedPages: true, cachedThumbnails: true } } }),
ImageCache.clearAll(),
]);
makeToast(t`Cleared the cache`, 'success');
} catch (e) {
makeToast(t`Could not clear the cache`, 'error', getErrorMessage(e));

View File

@@ -51,6 +51,7 @@ export const getMetadataServerSettings = async (): Promise<MetadataServerSetting
const { data, error } = await requestManager.getGlobalMeta().response;
if (error) {
// eslint-disable-next-line @typescript-eslint/no-throw-literal
throw error;
}

View File

@@ -6,6 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { CombinedGraphQLErrors } from '@apollo/client';
import { ReactNode } from 'react';
export const jsonSaveParse = <T = any>(...args: Parameters<typeof JSON.parse>): T | null => {
@@ -17,7 +18,7 @@ export const jsonSaveParse = <T = any>(...args: Parameters<typeof JSON.parse>):
};
export const getErrorMessage = (error: unknown): string => {
if (error instanceof Error) {
if (error instanceof Error || CombinedGraphQLErrors.is(error)) {
return error.message;
}

View File

@@ -3,7 +3,7 @@ import {
GetChaptersMangaQuery, GetDownloadStatusQueryVariables, GetGlobalMetadataQueryVariables,
GetMangaScreenQueryVariables, GetSourceBrowseQueryVariables, GetUpdateStatusQueryVariables, GetWebuiUpdateStatusQueryVariables,
} from "@/lib/graphql/generated/graphql.ts";
import {FieldFunctionOptions} from "@apollo/client/cache/inmemory/policies";
import {FieldFunctionOptions} from "@apollo/client/cache";
export type AboutServerPayloadKeySpecifier = ('buildTime' | 'buildType' | 'discord' | 'github' | 'name' | 'revision' | 'version' | AboutServerPayloadKeySpecifier)[];
export type AboutServerPayloadFieldPolicy = {
buildTime?: FieldPolicy<any> | FieldReadFunction<any>,

View File

@@ -4189,9 +4189,33 @@ export type SourceMigratableFieldsFragment = { __typename?: 'SourceType', lang:
export type SourceListFieldsFragment = { __typename?: 'SourceType', lang: string, iconUrl: string, isNsfw: boolean, isConfigurable: boolean, supportsLatest: boolean, id: string, name: string, displayName: string, meta: Array<{ __typename?: 'SourceMetaType', sourceId: string, key: string, value: string }>, extension: { __typename?: 'ExtensionType', pkgName: string, repo?: string | null } };
export type SourceBrowseFieldsFragment = { __typename?: 'SourceType', baseUrl?: string | null, isConfigurable: boolean, supportsLatest: boolean, id: string, name: string, displayName: string, lang: string, meta: Array<{ __typename?: 'SourceMetaType', sourceId: string, key: string, value: 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<string>, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', name: string, values: Array<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 }> } | { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' } | { __typename?: 'SelectFilter', name: string, values: Array<string>, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', name: string, values: Array<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 SourceBrowseFieldsFragment = { __typename?: 'SourceType', baseUrl?: string | null, isConfigurable: boolean, supportsLatest: boolean, id: string, name: string, displayName: string, lang: string, meta: Array<{ __typename?: 'SourceMetaType', sourceId: string, key: string, value: 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<string>, type: 'SelectFilter', SelectFilterDefault: number }
| { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' }
| { __typename?: 'SortFilter', name: string, values: Array<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 }
> }
| { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' }
| { __typename?: 'SelectFilter', name: string, values: Array<string>, type: 'SelectFilter', SelectFilterDefault: number }
| { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' }
| { __typename?: 'SortFilter', name: string, values: Array<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 SourceSettingFieldsFragment = { __typename?: 'SourceType', id: string, name: string, displayName: string, lang: string, preferences: Array<{ __typename?: 'CheckBoxPreference', summary?: string | null, key?: string | null, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle?: string | null } | { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key?: string | null, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null } | { __typename?: 'ListPreference', summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null } | { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array<string> | null, MultiSelectListPreferenceCurrentValue?: Array<string> | null } | { __typename?: 'SwitchPreference', summary?: string | null, key?: string | null, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle?: string | null }> };
export type SourceSettingFieldsFragment = { __typename?: 'SourceType', id: string, name: string, displayName: string, lang: string, preferences: Array<
| { __typename?: 'CheckBoxPreference', summary?: string | null, key?: string | null, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle?: string | null }
| { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key?: string | null, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null }
| { __typename?: 'ListPreference', summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null }
| { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array<string> | null, MultiSelectListPreferenceCurrentValue?: Array<string> | null }
| { __typename?: 'SwitchPreference', summary?: string | null, key?: string | null, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle?: string | null }
> };
export type GetSourceMangasFetchMutationVariables = Exact<{
input: FetchSourceMangaInput;
@@ -4205,7 +4229,13 @@ export type UpdateSourcePreferencesMutationVariables = Exact<{
}>;
export type UpdateSourcePreferencesMutation = { __typename?: 'Mutation', updateSourcePreference?: { __typename?: 'UpdateSourcePreferencePayload', source: { __typename?: 'SourceType', id: string, name: string, displayName: string, lang: string, preferences: Array<{ __typename?: 'CheckBoxPreference', summary?: string | null, key?: string | null, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle?: string | null } | { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key?: string | null, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null } | { __typename?: 'ListPreference', summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null } | { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array<string> | null, MultiSelectListPreferenceCurrentValue?: Array<string> | null } | { __typename?: 'SwitchPreference', summary?: string | null, key?: string | null, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle?: string | null }> } } | null };
export type UpdateSourcePreferencesMutation = { __typename?: 'Mutation', updateSourcePreference?: { __typename?: 'UpdateSourcePreferencePayload', source: { __typename?: 'SourceType', id: string, name: string, displayName: string, lang: string, preferences: Array<
| { __typename?: 'CheckBoxPreference', summary?: string | null, key?: string | null, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle?: string | null }
| { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key?: string | null, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null }
| { __typename?: 'ListPreference', summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null }
| { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array<string> | null, MultiSelectListPreferenceCurrentValue?: Array<string> | null }
| { __typename?: 'SwitchPreference', summary?: string | null, key?: string | null, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle?: string | null }
> } } | null };
export type UpdateSourceMetadataMutationVariables = Exact<{
preUpdateDeleteInput: DeleteSourceMetasInput;
@@ -4226,14 +4256,38 @@ export type GetSourceBrowseQueryVariables = Exact<{
}>;
export type GetSourceBrowseQuery = { __typename?: 'Query', source: { __typename?: 'SourceType', baseUrl?: string | null, isConfigurable: boolean, supportsLatest: boolean, id: string, name: string, displayName: string, lang: string, meta: Array<{ __typename?: 'SourceMetaType', sourceId: string, key: string, value: 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<string>, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', name: string, values: Array<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 }> } | { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' } | { __typename?: 'SelectFilter', name: string, values: Array<string>, type: 'SelectFilter', SelectFilterDefault: number } | { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' } | { __typename?: 'SortFilter', name: string, values: Array<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 GetSourceBrowseQuery = { __typename?: 'Query', source: { __typename?: 'SourceType', baseUrl?: string | null, isConfigurable: boolean, supportsLatest: boolean, id: string, name: string, displayName: string, lang: string, meta: Array<{ __typename?: 'SourceMetaType', sourceId: string, key: string, value: 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<string>, type: 'SelectFilter', SelectFilterDefault: number }
| { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' }
| { __typename?: 'SortFilter', name: string, values: Array<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 }
> }
| { __typename?: 'HeaderFilter', name: string, type: 'HeaderFilter' }
| { __typename?: 'SelectFilter', name: string, values: Array<string>, type: 'SelectFilter', SelectFilterDefault: number }
| { __typename?: 'SeparatorFilter', name: string, type: 'SeparatorFilter' }
| { __typename?: 'SortFilter', name: string, values: Array<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 GetSourceSettingsQueryVariables = Exact<{
id: Scalars['LongString']['input'];
}>;
export type GetSourceSettingsQuery = { __typename?: 'Query', source: { __typename?: 'SourceType', id: string, name: string, displayName: string, lang: string, preferences: Array<{ __typename?: 'CheckBoxPreference', summary?: string | null, key?: string | null, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle?: string | null } | { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key?: string | null, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null } | { __typename?: 'ListPreference', summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null } | { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array<string> | null, MultiSelectListPreferenceCurrentValue?: Array<string> | null } | { __typename?: 'SwitchPreference', summary?: string | null, key?: string | null, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle?: string | null }> } };
export type GetSourceSettingsQuery = { __typename?: 'Query', source: { __typename?: 'SourceType', id: string, name: string, displayName: string, lang: string, preferences: Array<
| { __typename?: 'CheckBoxPreference', summary?: string | null, key?: string | null, type: 'CheckBoxPreference', CheckBoxCheckBoxCurrentValue?: boolean | null, CheckBoxDefault: boolean, CheckBoxTitle?: string | null }
| { __typename?: 'EditTextPreference', text?: string | null, summary?: string | null, key?: string | null, dialogTitle?: string | null, dialogMessage?: string | null, type: 'EditTextPreference', EditTextPreferenceCurrentValue?: string | null, EditTextPreferenceDefault?: string | null, EditTextPreferenceTitle?: string | null }
| { __typename?: 'ListPreference', summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'ListPreference', ListPreferenceCurrentValue?: string | null, ListPreferenceDefault?: string | null, ListPreferenceTitle?: string | null }
| { __typename?: 'MultiSelectListPreference', dialogMessage?: string | null, dialogTitle?: string | null, summary?: string | null, key?: string | null, entryValues: Array<string>, entries: Array<string>, type: 'MultiSelectListPreference', MultiSelectListPreferenceTitle?: string | null, MultiSelectListPreferenceDefault?: Array<string> | null, MultiSelectListPreferenceCurrentValue?: Array<string> | null }
| { __typename?: 'SwitchPreference', summary?: string | null, key?: string | null, type: 'SwitchPreference', SwitchPreferenceCurrentValue?: boolean | null, SwitchPreferenceDefault: boolean, SwitchPreferenceTitle?: string | null }
> } };
export type GetSourceMigratableQueryVariables = Exact<{
id: Scalars['LongString']['input'];

View File

@@ -7,25 +7,15 @@
*/
import {
ApolloError,
ApolloQueryResult,
ApolloClient,
DocumentNode,
FetchResult,
MutationHookOptions as ApolloMutationHookOptions,
MutationOptions as ApolloMutationOptions,
MutationResult,
MutationTuple,
QueryHookOptions as ApolloQueryHookOptions,
QueryOptions as ApolloQueryOptions,
QueryResult,
SubscriptionHookOptions as ApolloSubscriptionHookOptions,
SubscriptionResult,
MaybeMasked,
OperationVariables,
TypedDocumentNode,
useMutation,
useQuery,
useSubscription,
} from '@apollo/client';
import { MaybeMasked, OperationVariables, Reference } from '@apollo/client/core';
CombinedGraphQLErrors,
} from '@apollo/client/core';
import { useMutation, useQuery, useSubscription } from '@apollo/client/react';
import { Reference } from '@apollo/client/utilities';
import { useEffect, useMemo, useRef, useState } from 'react';
import { d } from 'koration';
import { IRestClient, RestClient } from '@/lib/requests/client/RestClient.ts';
@@ -39,7 +29,6 @@ import {
CheckForServerUpdatesQueryVariables,
CheckForWebuiUpdateQuery,
CheckForWebuiUpdateQueryVariables,
ClearCachedImagesInput,
ClearDownloaderMutation,
ClearDownloaderMutationVariables,
ClearServerCacheMutation,
@@ -372,26 +361,26 @@ type CustomApolloOptions = {
addAbortSignal?: boolean;
};
type QueryOptions<Variables extends OperationVariables = OperationVariables, Data = any> = Partial<
ApolloQueryOptions<Variables, Data>
ApolloClient.QueryOptions<Data, Variables>
> &
CustomApolloOptions;
type QueryHookOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
ApolloQueryHookOptions<Data, Variables>
useQuery.Options<Data, Variables>
> &
CustomApolloOptions;
type MutationHookOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
ApolloMutationHookOptions<Data, Variables>
useMutation.Options<Data, Variables>
> &
CustomApolloOptions;
type MutationOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
ApolloMutationOptions<Data, Variables>
ApolloClient.MutateOptions<Data, Variables>
> &
CustomApolloOptions;
type ApolloPaginatedMutationOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
MutationHookOptions<Data, Variables>
> & { skipRequest?: boolean };
type SubscriptionHookOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
ApolloSubscriptionHookOptions<Data, Variables>
useSubscription.Options<Data, Variables>
> &
Omit<CustomApolloOptions, 'addAbortSignal'> & { addAbortSignal?: never };
@@ -406,22 +395,22 @@ type ImageRequestOptions = {
};
export type AbortabaleApolloQueryResponse<Data = any> = {
response: Promise<ApolloQueryResult<MaybeMasked<Data>>>;
response: Promise<ApolloClient.QueryResult<MaybeMasked<Data>>>;
} & AbortableRequest;
export type AbortableApolloUseQueryResponse<
Data = any,
Variables extends OperationVariables = OperationVariables,
> = QueryResult<MaybeMasked<Data>, Variables> & AbortableRequest;
> = useQuery.Result<MaybeMasked<Data>, Variables, 'empty' | 'complete' | 'streaming'> & AbortableRequest;
export type AbortableApolloUseMutationResponse<
Data = any,
Variables extends OperationVariables = OperationVariables,
> = [MutationTuple<Data, Variables>[0], MutationTuple<Data, Variables>[1] & AbortableRequest];
> = [useMutation.ResultTuple<Data, Variables>[0], useMutation.ResultTuple<Data, Variables>[1] & AbortableRequest];
export type AbortableApolloUseMutationPaginatedResponse<
Data = any,
Variables extends OperationVariables = OperationVariables,
> = [
(page: number) => Promise<FetchResult<MaybeMasked<Data>>>,
(Omit<MutationTuple<Data, Variables>[1], 'loading'> &
(page: number) => Promise<ApolloClient.MutateResult<MaybeMasked<Data>>>,
(Omit<useMutation.ResultTuple<Data, Variables>[1], 'loading'> &
AbortableRequest & {
size: number;
/**
@@ -440,7 +429,7 @@ export type AbortableApolloUseMutationPaginatedResponse<
})[],
];
export type AbortableApolloMutationResponse<Data = any> = {
response: Promise<FetchResult<MaybeMasked<Data>>>;
response: Promise<ApolloClient.MutateResult<MaybeMasked<Data>>>;
} & AbortableRequest;
const EXTENSION_LIST_CACHE_KEY = 'useExtensionListFetch';
@@ -585,9 +574,9 @@ export class RequestManager {
options: ApolloPaginatedMutationOptions<Data, Variables> | undefined,
checkIfCachedPageIsInvalid: (
cachedResult: AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number] | undefined,
revalidatedResult: FetchResult<MaybeMasked<Data>>,
revalidatedResult: ApolloClient.MutateResult<MaybeMasked<Data>>,
) => boolean,
hasNextPage: (revalidatedResult: FetchResult<MaybeMasked<Data>>) => boolean,
hasNextPage: (revalidatedResult: ApolloClient.MutateResult<MaybeMasked<Data>>) => boolean,
pageToRevalidate: number,
maxPage: number,
signal: AbortSignal,
@@ -605,14 +594,14 @@ export class RequestManager {
return;
}
const { response: revalidationRequest } = this.doRequest(
const { response: revalidationRequest } = this.doRequest<Data, Variables>(
GQLMethod.MUTATION,
GET_SOURCE_MANGAS_FETCH,
getVariablesFor(pageToRevalidate),
{
...options,
context: { fetchOptions: { signal } },
},
} as MutationOptions<Data, Variables>,
);
const revalidationResponse = await revalidationRequest;
@@ -729,7 +718,7 @@ export class RequestManager {
cacheResultsKey: string,
cachedPages: Set<number>,
newPage: number,
): Promise<FetchResult<MaybeMasked<Data>>> {
): Promise<ApolloClient.MutateResult<MaybeMasked<Data>>> {
const basePaginatedResult: Partial<AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number]> = {
size: newPage,
isLoading: false,
@@ -737,7 +726,7 @@ export class RequestManager {
called: true,
};
let response: FetchResult<MaybeMasked<Data>> = {};
let response: ApolloClient.MutateResult<MaybeMasked<Data>> = { data: undefined };
try {
const { signal, abortRequest } = this.createAbortController();
setAbortRequest(abortRequest);
@@ -765,7 +754,7 @@ export class RequestManager {
GQLMethod.MUTATION,
documentNode,
getVariablesFor(newPage),
{ ...options, context: { fetchOptions: { signal } } },
{ ...options, context: { fetchOptions: { signal } } } as MutationOptions<Data, Variables>,
);
response = await request;
@@ -773,14 +762,9 @@ export class RequestManager {
basePaginatedResult.data = response.data;
} catch (error: any) {
defaultPromiseErrorHandler('RequestManager::fetchPaginatedMutationPage')(error);
if (error instanceof ApolloError) {
basePaginatedResult.error = error;
} else {
basePaginatedResult.error = new ApolloError({
errorMessage: error?.message ?? error.toString(),
extraInfo: error,
});
}
basePaginatedResult.error = CombinedGraphQLErrors.is(error)
? error
: new Error(error?.message ?? String(error));
}
const fetchPaginatedResult = {
@@ -805,8 +789,8 @@ export class RequestManager {
cacheFetchingInitialPagesKey: string,
getVariablesFor: (page: number) => Variables,
initialPages: number,
fetchPage: (page: number) => Promise<FetchResult<Data>>,
hasNextPage: (result: FetchResult<Data>) => boolean,
fetchPage: (page: number) => Promise<ApolloClient.MutateResult<Data>>,
hasNextPage: (result: ApolloClient.MutateResult<Data>) => boolean,
): void {
useEffect(() => {
const shouldFetchInitialPages =
@@ -842,7 +826,7 @@ export class RequestManager {
cachedResults: AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number][],
getVariablesFor: (page: number) => Variables,
paginatedResult: AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number],
fetchPage: (page: number) => Promise<FetchResult<MaybeMasked<Data>>>,
fetchPage: (page: number) => Promise<ApolloClient.MutateResult<MaybeMasked<Data>>>,
hasCachedResult: boolean,
createPaginatedResult: (
result: Partial<AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number]>,
@@ -1173,7 +1157,7 @@ export class RequestManager {
operation: DocumentNode | TypedDocumentNode<Data, Variables>,
variables: Variables | undefined,
options?: SubscriptionHookOptions<Data, Variables>,
): SubscriptionResult<Data, Variables>;
): useSubscription.Result<Data>;
private doRequest<Data, Variables extends OperationVariables = OperationVariables>(
method: GQLMethod,
@@ -1190,84 +1174,100 @@ export class RequestManager {
| AbortableApolloUseQueryResponse<Data, Variables>
| AbortableApolloUseMutationResponse<Data, Variables>
| AbortableApolloMutationResponse<Data>
| SubscriptionResult<Data, Variables> {
| useSubscription.Result<Data> {
const { signal, abortRequest } = this.createAbortController();
switch (method) {
case GQLMethod.QUERY:
case GQLMethod.QUERY: {
const { addAbortSignal: addSignal, ...queryOptions } = (options ?? {}) as QueryOptions<Variables, Data>;
return {
response: this.graphQLClient.client.query<Data, Variables>({
response: this.graphQLClient.client.query({
query: operation,
variables,
...(options as QueryOptions<Variables, Data>),
...queryOptions,
context: {
...options?.context,
...queryOptions?.context,
fetchOptions: {
signal: options?.addAbortSignal ? signal : undefined,
...options?.context?.fetchOptions,
signal: addSignal ? signal : undefined,
...queryOptions?.context?.fetchOptions,
},
},
}),
} as ApolloClient.QueryOptions<Data, Variables>),
abortRequest,
};
case GQLMethod.USE_QUERY:
}
case GQLMethod.USE_QUERY: {
const { addAbortSignal: addSignal, ...queryHookOptions } = (options ?? {}) as QueryHookOptions<
Data,
Variables
>;
return {
...useQuery<Data, Variables>(operation, {
variables,
client: this.graphQLClient.client,
...options,
...queryHookOptions,
context: {
...options?.context,
...queryHookOptions?.context,
fetchOptions: {
signal: options?.addAbortSignal ? signal : undefined,
...options?.context?.fetchOptions,
signal: addSignal ? signal : undefined,
...queryHookOptions?.context?.fetchOptions,
},
},
}),
} as useQuery.Options<Data, Variables>),
abortRequest,
};
case GQLMethod.USE_MUTATION:
// eslint-disable-next-line no-case-declarations
} as AbortableApolloUseQueryResponse<Data, Variables>;
}
case GQLMethod.USE_MUTATION: {
const { addAbortSignal: addSignal, ...mutationHookOptions } = (options ?? {}) as MutationHookOptions<
Data,
Variables
>;
const mutationResult = useMutation<Data, Variables>(operation, {
variables,
client: this.graphQLClient.client,
...(options as MutationHookOptions<Data, Variables>),
...mutationHookOptions,
context: {
...options?.context,
...mutationHookOptions?.context,
fetchOptions: {
signal: options?.addAbortSignal ? signal : undefined,
...options?.context?.fetchOptions,
signal: addSignal ? signal : undefined,
...mutationHookOptions?.context?.fetchOptions,
},
},
});
return [mutationResult[0], { ...mutationResult[1], abortRequest }];
case GQLMethod.MUTATION:
}
case GQLMethod.MUTATION: {
const { addAbortSignal: addSignal, ...mutationOptions } = (options ?? {}) as MutationOptions<
Data,
Variables
>;
return {
response: this.graphQLClient.client.mutate<Data, Variables>({
response: this.graphQLClient.client.mutate({
mutation: operation,
variables,
...(options as MutationOptions<Data, Variables>),
...mutationOptions,
context: {
...options?.context,
...mutationOptions?.context,
fetchOptions: {
signal: options?.addAbortSignal ? signal : undefined,
...options?.context?.fetchOptions,
signal: addSignal ? signal : undefined,
...mutationOptions?.context?.fetchOptions,
},
},
}),
} as ApolloClient.MutateOptions<Data, Variables>),
abortRequest,
};
case GQLMethod.USE_SUBSCRIPTION:
// eslint-disable-next-line no-case-declarations
}
case GQLMethod.USE_SUBSCRIPTION: {
const subscription = useSubscription<Data, Variables>(operation, {
client: this.graphQLClient.client,
variables,
...(options as SubscriptionHookOptions<Data, Variables>),
});
} as useSubscription.Options<Data, Variables>);
this.graphQLClient.useRestartSubscription(subscription.restart);
return subscription;
}
default:
throw new Error(`unexpected GQLRequest type "${method}"`);
}
@@ -1502,7 +1502,10 @@ export class RequestManager {
return mutate(mutateOptions);
};
return [wrappedMutate, normalizedCachedResult];
return [wrappedMutate, normalizedCachedResult] as AbortableApolloUseMutationResponse<
GetExtensionsFetchMutation,
GetExtensionsFetchMutationVariables
>;
}
public installExternalExtension(
@@ -1522,7 +1525,7 @@ export class RequestManager {
}
this.graphQLClient.client.cache.evict({ fieldName: 'sources' });
const cachedExtensions = this.cache.getResponseFor<MutationResult<GetExtensionsFetchMutation>>(
const cachedExtensions = this.cache.getResponseFor<useMutation.Result<GetExtensionsFetchMutation>>(
EXTENSION_LIST_CACHE_KEY,
undefined,
);
@@ -1544,7 +1547,7 @@ export class RequestManager {
(extension) => installedExtension?.pkgName === extension.pkgName,
);
const updatedCachedExtensions: MutationResult<GetExtensionsFetchMutation> = {
const updatedCachedExtensions: useMutation.Result<GetExtensionsFetchMutation> = {
...cachedExtensions,
data: {
...cachedExtensions.data,
@@ -1592,12 +1595,12 @@ export class RequestManager {
);
result.response.then((response) => {
if (response.errors) {
if (response.error) {
return;
}
this.graphQLClient.client.cache.evict({ fieldName: 'sources' });
const cachedExtensions = this.cache.getResponseFor<MutationResult<GetExtensionsFetchMutation>>(
const cachedExtensions = this.cache.getResponseFor<useMutation.Result<GetExtensionsFetchMutation>>(
EXTENSION_LIST_CACHE_KEY,
undefined,
);
@@ -1606,7 +1609,7 @@ export class RequestManager {
return;
}
const updatedCachedExtensions: MutationResult<GetExtensionsFetchMutation> = {
const updatedCachedExtensions: useMutation.Result<GetExtensionsFetchMutation> = {
...cachedExtensions,
data: {
...cachedExtensions.data,
@@ -1656,12 +1659,12 @@ export class RequestManager {
);
result.response.then((response) => {
if (response.errors) {
if (response.error) {
return;
}
this.graphQLClient.client.cache.evict({ fieldName: 'sources' });
const cachedExtensions = this.cache.getResponseFor<MutationResult<GetExtensionsFetchMutation>>(
const cachedExtensions = this.cache.getResponseFor<useMutation.Result<GetExtensionsFetchMutation>>(
EXTENSION_LIST_CACHE_KEY,
undefined,
);
@@ -1670,7 +1673,7 @@ export class RequestManager {
return;
}
const updatedCachedExtensions: MutationResult<GetExtensionsFetchMutation> = {
const updatedCachedExtensions: useMutation.Result<GetExtensionsFetchMutation> = {
...cachedExtensions,
data: {
...cachedExtensions.data,
@@ -2506,11 +2509,11 @@ export class RequestManager {
return this.doRequest(
GQLMethod.QUERY,
GET_MANGAS_CHAPTER_IDS_WITH_STATE,
{ mangaIds, ...states },
{ mangaIds, ...states } as GetMangasChapterIdsWithStateQueryVariables,
{
fetchPolicy: 'no-cache',
...options,
},
} as QueryOptions<GetMangasChapterIdsWithStateQueryVariables, GetMangasChapterIdsWithStateQuery>,
);
}
@@ -3394,8 +3397,8 @@ export class RequestManager {
public useDownloadSubscription(
options?: SubscriptionHookOptions<DownloadStatusSubscription, DownloadStatusSubscriptionVariables>,
): SubscriptionResult<DownloadStatusSubscription, DownloadStatusSubscriptionVariables> {
return this.doRequest(
): useSubscription.Result<DownloadStatusSubscription> {
return this.doRequest<DownloadStatusSubscription, DownloadStatusSubscriptionVariables>(
GQLMethod.USE_SUBSCRIPTION,
DOWNLOAD_STATUS_SUBSCRIPTION,
{ input: { maxUpdates: 30 } },
@@ -3484,14 +3487,14 @@ export class RequestManager {
});
});
},
},
);
} as SubscriptionHookOptions<DownloadStatusSubscription, DownloadStatusSubscriptionVariables>,
) as useSubscription.Result<DownloadStatusSubscription>;
}
public useUpdaterSubscription(
options?: SubscriptionHookOptions<UpdaterSubscription, UpdaterSubscriptionVariables>,
): SubscriptionResult<UpdaterSubscription, UpdaterSubscriptionVariables> {
return this.doRequest(
): useSubscription.Result<UpdaterSubscription> {
return this.doRequest<UpdaterSubscription, UpdaterSubscriptionVariables>(
GQLMethod.USE_SUBSCRIPTION,
UPDATER_SUBSCRIPTION,
{ input: { maxUpdates: 30 } },
@@ -3510,8 +3513,8 @@ export class RequestManager {
cache.evict({ broadcast: true, id: 'LibraryUpdateStatus' });
cache.evict({ broadcast: true, fieldName: 'libraryUpdateStatus' });
},
},
);
} as SubscriptionHookOptions<UpdaterSubscription, UpdaterSubscriptionVariables>,
) as useSubscription.Result<UpdaterSubscription>;
}
public useGetServerSettings(
@@ -3550,15 +3553,14 @@ export class RequestManager {
}
public useClearServerCache(
input: ClearCachedImagesInput = { cachedPages: true, cachedThumbnails: true },
options?: MutationHookOptions<ClearServerCacheMutation, ClearServerCacheMutationVariables>,
): AbortableApolloUseMutationResponse<ClearServerCacheMutation, ClearServerCacheMutationVariables> {
return this.doRequest(GQLMethod.USE_MUTATION, CLEAR_SERVER_CACHE, { input }, options);
return this.doRequest(GQLMethod.USE_MUTATION, CLEAR_SERVER_CACHE, { input: {} }, options);
}
public useWebUIUpdateSubscription(
options?: SubscriptionHookOptions<WebuiUpdateSubscription, WebuiUpdateSubscription>,
): SubscriptionResult<WebuiUpdateSubscription, WebuiUpdateSubscription> {
): useSubscription.Result<WebuiUpdateSubscription> {
return this.doRequest(GQLMethod.USE_SUBSCRIPTION, WEBUI_UPDATE_SUBSCRIPTION, undefined, options);
}
@@ -3654,7 +3656,10 @@ export class RequestManager {
GQLMethod.MUTATION,
TRACKER_UNBIND,
{ input: { recordId, deleteRemoteTrack } },
{ refetchQueries: [GET_MANGA_TRACK_RECORDS], ...options },
{ refetchQueries: [GET_MANGA_TRACK_RECORDS], ...options } as MutationOptions<
TrackerUnbindMutation,
TrackerUnbindMutationVariables
>,
);
}

View File

@@ -6,25 +6,16 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { onError } from '@apollo/client/link/error';
import { setContext } from '@apollo/client/link/context';
import {
ApolloClient,
ApolloClientOptions,
ApolloLink,
from,
fromPromise,
InMemoryCache,
NormalizedCacheObject,
split,
toPromise,
} from '@apollo/client';
import createUploadLink from 'apollo-upload-client/createUploadLink.mjs';
import { ErrorLink } from '@apollo/client/link/error';
import { SetContextLink } from '@apollo/client/link/context';
import { ApolloClient, ApolloLink, CombinedGraphQLErrors, InMemoryCache } from '@apollo/client';
import { from, filter, map, switchMap, firstValueFrom } from 'rxjs';
import UploadHttpLink from 'apollo-upload-client/UploadHttpLink.mjs';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { Client, createClient } from 'graphql-ws';
import { getMainDefinition } from '@apollo/client/utilities';
import { TypePolicies } from '@apollo/client/cache';
import { removeTypenameFromVariables } from '@apollo/client/link/remove-typename';
import { RemoveTypenameFromVariablesLink } from '@apollo/client/link/remove-typename';
import { d } from 'koration';
import { useId } from '@mantine/hooks';
import { useEffect } from 'react';
@@ -188,14 +179,10 @@ const typePolicies: StrictTypedTypePolicies = {
};
/* eslint-enable no-underscore-dangle */
export class GraphQLClient extends BaseClient<
ApolloClient<NormalizedCacheObject>,
ApolloClientOptions<NormalizedCacheObject>,
null
> {
export class GraphQLClient extends BaseClient<ApolloClient, ApolloClient.Options, null> {
readonly fetcher = null;
public client!: ApolloClient<NormalizedCacheObject>;
public client!: ApolloClient;
private wsClient!: Client;
@@ -255,7 +242,7 @@ export class GraphQLClient extends BaseClient<
const { operationName } = operation;
if (this.shouldQueueRequest(operationName)) {
return fromPromise(this.enqueueRequest(() => toPromise(forward(operation)), operationName));
return from(this.enqueueRequest(() => firstValueFrom(forward(operation)), operationName));
}
return forward(operation);
@@ -269,27 +256,27 @@ export class GraphQLClient extends BaseClient<
}
private createErrorLink() {
return onError(({ graphQLErrors, operation, forward }) => {
if (!graphQLErrors) {
return new ErrorLink(({ error, operation, forward }) => {
if (!CombinedGraphQLErrors.is(error)) {
return undefined;
}
if (!this.isAuthError(graphQLErrors)) {
if (!this.isAuthError(error.errors)) {
return undefined;
}
return fromPromise(BaseClient.refreshAccessToken(this.handleRefreshToken))
.filter(Boolean)
.map((result) => {
return from(BaseClient.refreshAccessToken(this.handleRefreshToken)).pipe(
filter(Boolean),
map((result) => {
this.restartAllSubscriptions();
return result;
})
.flatMap(() => forward(operation));
}),
switchMap(() => forward(operation)),
);
});
}
private createAuthLink() {
return setContext((_, { headers }) => {
return new SetContextLink(({ headers }) => {
const isAuthRequired = AuthManager.isAuthRequired();
const accessToken = AuthManager.getAccessToken();
@@ -304,7 +291,7 @@ export class GraphQLClient extends BaseClient<
}
private createUploadLink() {
return createUploadLink({ uri: () => this.getBaseUrl() });
return new UploadHttpLink({ uri: () => this.getBaseUrl() });
}
private createWSLink() {
@@ -312,21 +299,20 @@ export class GraphQLClient extends BaseClient<
}
private createLink() {
const removeTypenameLink = removeTypenameFromVariables();
const removeTypenameLink = new RemoveTypenameFromVariablesLink();
return split(
return ApolloLink.split(
({ query }) => {
const definition = getMainDefinition(query);
return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
},
this.createWSLink(),
from([
ApolloLink.from([
this.createAuthGuardLink(),
this.createErrorLink(),
this.createAuthLink(),
removeTypenameLink,
// apollo-upload-client dependency is outdated (see 134e47763faae9e62db4d4e3a8387a74e32e5568) and thus types are not matching, but they are still correct
this.createUploadLink() as unknown as ApolloLink,
this.createUploadLink(),
]),
);
}
@@ -408,7 +394,7 @@ export class GraphQLClient extends BaseClient<
// the TypeError can just be ignored
typePolicies: typePolicies as TypePolicies,
}),
connectToDevTools: true,
devtools: { enabled: true },
link: this.createLink(),
});
}

View File

@@ -44,7 +44,7 @@ import {
\tGetChaptersMangaQuery, GetDownloadStatusQueryVariables, GetGlobalMetadataQueryVariables,
\tGetMangaScreenQueryVariables, GetSourceBrowseQueryVariables, GetUpdateStatusQueryVariables, GetWebuiUpdateStatusQueryVariables,
} from "@/lib/graphql/generated/graphql.ts";
import {FieldFunctionOptions} from "@apollo/client/cache/inmemory/policies";`,
import {FieldFunctionOptions} from "@apollo/client/cache";`,
);
const fixTypingOfQueryTypePolicies = format(

2195
yarn.lock

File diff suppressed because it is too large Load Diff