diff --git a/frontend/AGENTS.md b/frontend/AGENTS.md index 4913a47..e755984 100644 --- a/frontend/AGENTS.md +++ b/frontend/AGENTS.md @@ -27,7 +27,7 @@ Also follow the repository root guide at `../AGENTS.md`. - Avoid custom class names in JSX `className` values unless the Tailwind lint config already allows them. - For decorative icons in inputs or labels, disable hover styling via the icon component API rather than overriding it ad hoc. - Prefer `LoadingState` for result-area loading indicators (the single loading convention); avoid early returns that unmount search/filter forms during fetches. React Query `isLoading` is initial-load-only (false on background refetches), so a full-page early-return on `isLoading` is fine for pages with no persistent filter form. -- For mutations, use `useMutationWithToast` (declarative `.mutate(vars, options)` for fire-and-forget) or its imperative sibling `useToastMutation` (awaited, returns a success `boolean`) instead of hand-rolling `mutateAsync` → `getResponseError` → toast blocks. +- For mutations, use `useMutationWithToast` (declarative `.mutate(vars, options)` for fire-and-forget) or its imperative sibling `useToastMutation` (awaited, returns a success `boolean`) instead of hand-rolling `mutateAsync` → toast/catch blocks. - Use `SegmentedControl` for active/inactive toggle groups (view mode, period, reader theme/font) rather than re-implementing `option.map` + ternary class toggling; pass per-call `activeClassName`/`inactiveClassName`. - For a persistent/progress toast that resolves in place (long-running actions), create it with `showInfo(msg, 0)` and finish with `updateToast(id, { message, type, duration })`. - Use theme tokens defined in `src/index.css` `@theme` (`bg-surface`, `text-content`, `border-border`, `primary`, etc.) for new UI work instead of adding raw light/dark color pairs. There is no `tailwind.config.js` — Tailwind v4 config is CSS-first. @@ -43,10 +43,10 @@ Also follow the repository root guide at `../AGENTS.md`. ### Important behavior -- The generated client returns `{ data, status, headers }` for both success and error responses. -- Do not assume non-2xx responses throw. -- Trust the generated discriminated-union response types and narrow on `status`; avoid hand-rolled re-validation of fields the schema already guarantees. -- Centralize mutation/reqest error handling via `useMutationWithToast` (toast options) or `getResponseError` (`utils/errors`) for imperative flows — don't re-implement inline `status` checks or `'message' in response.data` extraction. +- The generated client returns the documented **success body directly** and throws `ApiError` (`src/utils/apiFetch.ts`) for non-2xx responses. +- Use React Query's native error flow (`isError`, `error`, `onError`) instead of status narrowing. +- Use `getErrorMessage` (`src/utils/errors.ts`) to display caught errors; `ApiError.message` already contains the server-provided error message when present. +- Centralize mutation error/success feedback via `useMutationWithToast` or `useToastMutation` rather than inline toast/catch duplication. ## 4) Auth / Query State diff --git a/frontend/orval.config.ts b/frontend/orval.config.ts index 7cbd58b..3e12734 100644 --- a/frontend/orval.config.ts +++ b/frontend/orval.config.ts @@ -8,10 +8,16 @@ export default defineConfig({ target: 'src/generated', schemas: 'src/generated/model', client: 'react-query', + httpClient: 'fetch', mock: false, override: { - useQuery: true, - mutations: true, + fetch: { + includeHttpResponseReturnType: false, + }, + mutator: { + path: './src/utils/apiFetch.ts', + name: 'apiFetch', + }, }, }, input: { diff --git a/frontend/src/auth/AuthContext.tsx b/frontend/src/auth/AuthContext.tsx index 065b4b2..dff94df 100644 --- a/frontend/src/auth/AuthContext.tsx +++ b/frontend/src/auth/AuthContext.tsx @@ -12,9 +12,7 @@ import { type AuthState, getUnauthenticatedAuthState, resolveAuthStateFromMe, - authUserFromMutation, } from './authHelpers'; -import { getResponseError } from '../utils/errors'; interface AuthContextType extends AuthState { login: (_username: string, _password: string) => Promise; @@ -50,19 +48,14 @@ export function AuthProvider({ children }: { children: ReactNode }) { const login = useCallback( async (username: string, password: string) => { try { - const response = await loginMutation.mutateAsync({ + const user = await loginMutation.mutateAsync({ data: { username, password, }, }); - const user = authUserFromMutation(response); - if (!user) { - throw new Error(getResponseError(response) ?? 'Login failed'); - } - - queryClient.setQueryData(getGetMeQueryKey(), response); + queryClient.setQueryData(getGetMeQueryKey(), user); await queryClient.invalidateQueries({ queryKey: getGetMeQueryKey() }); navigate('/'); } catch (error) { @@ -76,19 +69,14 @@ export function AuthProvider({ children }: { children: ReactNode }) { const register = useCallback( async (username: string, password: string) => { try { - const response = await registerMutation.mutateAsync({ + const user = await registerMutation.mutateAsync({ data: { username, password, }, }); - const user = authUserFromMutation(response); - if (!user) { - throw new Error(getResponseError(response) ?? 'Registration failed'); - } - - queryClient.setQueryData(getGetMeQueryKey(), response); + queryClient.setQueryData(getGetMeQueryKey(), user); await queryClient.invalidateQueries({ queryKey: getGetMeQueryKey() }); navigate('/'); } catch (error) { diff --git a/frontend/src/auth/authHelpers.test.ts b/frontend/src/auth/authHelpers.test.ts index 99236d3..b676166 100644 --- a/frontend/src/auth/authHelpers.test.ts +++ b/frontend/src/auth/authHelpers.test.ts @@ -3,7 +3,6 @@ import { getCheckingAuthState, getUnauthenticatedAuthState, resolveAuthStateFromMe, - authUserFromMutation, type AuthState, } from './authHelpers'; @@ -31,11 +30,7 @@ describe('authHelpers', () => { it('resolves auth state from a successful /auth/me response', () => { expect( resolveAuthStateFromMe({ - meData: { - status: 200, - data: { username: 'evan', is_admin: false }, - headers: new Headers(), - }, + meData: { username: 'evan', is_admin: false }, meError: undefined, meLoading: false, previousState, @@ -47,20 +42,7 @@ describe('authHelpers', () => { }); }); - it('resolves auth state to unauthenticated on 401 or query error', () => { - expect( - resolveAuthStateFromMe({ - meData: { - status: 401, - data: { code: 401, message: 'unauthorized' }, - headers: new Headers(), - }, - meError: undefined, - meLoading: false, - previousState, - }) - ).toEqual(getUnauthenticatedAuthState()); - + it('resolves auth state to unauthenticated when the me query errors (e.g. 401)', () => { expect( resolveAuthStateFromMe({ meData: undefined, @@ -108,32 +90,4 @@ describe('authHelpers', () => { isCheckingAuth: false, }); }); - - it('extracts the user from successful login and register responses', () => { - expect( - authUserFromMutation({ - status: 200, - data: { username: 'evan', is_admin: false }, - headers: new Headers(), - }) - ).toEqual({ username: 'evan', is_admin: false }); - - expect( - authUserFromMutation({ - status: 201, - data: { username: 'evan', is_admin: true }, - headers: new Headers(), - }) - ).toEqual({ username: 'evan', is_admin: true }); - }); - - it('returns null for unsuccessful auth mutation responses', () => { - expect( - authUserFromMutation({ - status: 401, - data: { code: 401, message: 'unauthorized' }, - headers: new Headers(), - }) - ).toBeNull(); - }); }); diff --git a/frontend/src/auth/authHelpers.ts b/frontend/src/auth/authHelpers.ts index 9a98c44..451afa6 100644 --- a/frontend/src/auth/authHelpers.ts +++ b/frontend/src/auth/authHelpers.ts @@ -1,4 +1,3 @@ -import type { getMeResponse, loginResponse, registerResponse } from '../generated/anthoLumeAPIV1'; import type { LoginResponse } from '../generated/model'; export type AuthUser = LoginResponse; @@ -34,7 +33,7 @@ export function getAuthenticatedAuthState(user: AuthUser): AuthState { } export function resolveAuthStateFromMe(params: { - meData?: getMeResponse; + meData?: LoginResponse; meError?: unknown; meLoading: boolean; previousState: AuthState; @@ -45,11 +44,11 @@ export function resolveAuthStateFromMe(params: { return getCheckingAuthState(previousState); } - if (meData?.status === 200) { - return getAuthenticatedAuthState(meData.data); + if (meData) { + return getAuthenticatedAuthState(meData); } - if (meError || meData?.status === 401) { + if (meError) { return getUnauthenticatedAuthState(); } @@ -58,7 +57,3 @@ export function resolveAuthStateFromMe(params: { isCheckingAuth: false, }; } - -export function authUserFromMutation(response: loginResponse | registerResponse): AuthUser | null { - return response.status === 200 || response.status === 201 ? response.data : null; -} diff --git a/frontend/src/components/HamburgerMenu.tsx b/frontend/src/components/HamburgerMenu.tsx index 6a3c2cd..14094a2 100644 --- a/frontend/src/components/HamburgerMenu.tsx +++ b/frontend/src/components/HamburgerMenu.tsx @@ -4,7 +4,6 @@ import { SettingsIcon, GitIcon } from '../icons'; import { useAuth } from '../auth/AuthContext'; import { useGetInfo } from '../generated/anthoLumeAPIV1'; import { navItems, adminNavItems } from './navigation'; -import { dataForStatus } from '../utils/apiResponses'; import { cn } from '../utils/cn'; function hasPrefix(path: string, prefix: string): boolean { @@ -47,7 +46,7 @@ export default function HamburgerMenu() { staleTime: Infinity, }, }); - const version = dataForStatus(infoData, 200)?.version ?? 'v1.0.0'; + const version = infoData?.version ?? 'v1.0.0'; const closeMenu = () => setIsOpen(false); return ( diff --git a/frontend/src/generated/anthoLumeAPIV1.ts b/frontend/src/generated/anthoLumeAPIV1.ts index bfad9be..418e22f 100644 --- a/frontend/src/generated/anthoLumeAPIV1.ts +++ b/frontend/src/generated/anthoLumeAPIV1.ts @@ -66,37 +66,16 @@ import type { UsersResponse } from './model'; +import { apiFetch } from '../utils/apiFetch'; +type SecondParameter unknown> = Parameters[1]; + /** * @summary List documents */ -export type getDocumentsResponse200 = { - data: DocumentsResponse - status: 200 -} - -export type getDocumentsResponse401 = { - data: ErrorResponse - status: 401 -} - -export type getDocumentsResponse500 = { - data: ErrorResponse - status: 500 -} - -export type getDocumentsResponseSuccess = (getDocumentsResponse200) & { - headers: Headers; -}; -export type getDocumentsResponseError = (getDocumentsResponse401 | getDocumentsResponse500) & { - headers: Headers; -}; - -export type getDocumentsResponse = (getDocumentsResponseSuccess | getDocumentsResponseError) - export const getGetDocumentsUrl = (params?: GetDocumentsParams,) => { const normalizedParams = new URLSearchParams(); @@ -112,22 +91,16 @@ export const getGetDocumentsUrl = (params?: GetDocumentsParams,) => { return stringifiedParams.length > 0 ? `/api/v1/documents?${stringifiedParams}` : `/api/v1/documents` } -export const getDocuments = async (params?: GetDocumentsParams, options?: RequestInit): Promise => { +export const getDocuments = async (params?: GetDocumentsParams, options?: RequestInit): Promise => { - const res = await fetch(getGetDocumentsUrl(params), + return apiFetch(getGetDocumentsUrl(params), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getDocumentsResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getDocumentsResponse -} +);} @@ -140,16 +113,16 @@ export const getGetDocumentsQueryKey = (params?: GetDocumentsParams,) => { } -export const getGetDocumentsQueryOptions = >, TError = ErrorResponse>(params?: GetDocumentsParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetDocumentsQueryOptions = >, TError = ErrorResponse>(params?: GetDocumentsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetDocumentsQueryKey(params); - const queryFn: QueryFunction>> = ({ signal }) => getDocuments(params, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getDocuments(params, { signal, ...requestOptions }); @@ -169,7 +142,7 @@ export function useGetDocuments> TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetDocuments>, TError = ErrorResponse>( @@ -179,11 +152,11 @@ export function useGetDocuments> TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetDocuments>, TError = ErrorResponse>( - params?: GetDocumentsParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetDocumentsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -191,7 +164,7 @@ export function useGetDocuments> */ export function useGetDocuments>, TError = ErrorResponse>( - params?: GetDocumentsParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetDocumentsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -209,35 +182,6 @@ export function useGetDocuments> /** * @summary Upload a new document */ -export type createDocumentResponse200 = { - data: DocumentResponse - status: 200 -} - -export type createDocumentResponse400 = { - data: ErrorResponse - status: 400 -} - -export type createDocumentResponse401 = { - data: ErrorResponse - status: 401 -} - -export type createDocumentResponse500 = { - data: ErrorResponse - status: 500 -} - -export type createDocumentResponseSuccess = (createDocumentResponse200) & { - headers: Headers; -}; -export type createDocumentResponseError = (createDocumentResponse400 | createDocumentResponse401 | createDocumentResponse500) & { - headers: Headers; -}; - -export type createDocumentResponse = (createDocumentResponseSuccess | createDocumentResponseError) - export const getCreateDocumentUrl = () => { @@ -246,11 +190,11 @@ export const getCreateDocumentUrl = () => { return `/api/v1/documents` } -export const createDocument = async (createDocumentBody: CreateDocumentBody, options?: RequestInit): Promise => { +export const createDocument = async (createDocumentBody: CreateDocumentBody, options?: RequestInit): Promise => { const formData = new FormData(); formData.append(`document_file`, createDocumentBody.document_file); - const res = await fetch(getCreateDocumentUrl(), + return apiFetch(getCreateDocumentUrl(), { ...options, method: 'POST' @@ -258,27 +202,21 @@ formData.append(`document_file`, createDocumentBody.document_file); body: formData, } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: createDocumentResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as createDocumentResponse -} +);} export const getCreateDocumentMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: CreateDocumentBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: CreateDocumentBody}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: CreateDocumentBody}, TContext> => { const mutationKey = ['createDocument']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -286,7 +224,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: CreateDocumentBody}> = (props) => { const {data} = props ?? {}; - return createDocument(data,fetchOptions) + return createDocument(data,requestOptions) } @@ -304,7 +242,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Upload a new document */ export const useCreateDocument = (options?: { mutation?:UseMutationOptions>, TError,{data: CreateDocumentBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: CreateDocumentBody}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -317,35 +255,6 @@ export const useCreateDocument = { @@ -354,22 +263,16 @@ export const getGetDocumentUrl = (id: string,) => { return `/api/v1/documents/${id}` } -export const getDocument = async (id: string, options?: RequestInit): Promise => { +export const getDocument = async (id: string, options?: RequestInit): Promise => { - const res = await fetch(getGetDocumentUrl(id), + return apiFetch(getGetDocumentUrl(id), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getDocumentResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getDocumentResponse -} +);} @@ -382,16 +285,16 @@ export const getGetDocumentQueryKey = (id: string,) => { } -export const getGetDocumentQueryOptions = >, TError = ErrorResponse>(id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetDocumentQueryOptions = >, TError = ErrorResponse>(id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetDocumentQueryKey(id); - const queryFn: QueryFunction>> = ({ signal }) => getDocument(id, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getDocument(id, { signal, ...requestOptions }); @@ -411,7 +314,7 @@ export function useGetDocument>, TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetDocument>, TError = ErrorResponse>( @@ -421,11 +324,11 @@ export function useGetDocument>, TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetDocument>, TError = ErrorResponse>( - id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -433,7 +336,7 @@ export function useGetDocument>, */ export function useGetDocument>, TError = ErrorResponse>( - id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -451,40 +354,6 @@ export function useGetDocument>, /** * @summary Update document editable fields */ -export type editDocumentResponse200 = { - data: DocumentResponse - status: 200 -} - -export type editDocumentResponse400 = { - data: ErrorResponse - status: 400 -} - -export type editDocumentResponse401 = { - data: ErrorResponse - status: 401 -} - -export type editDocumentResponse404 = { - data: ErrorResponse - status: 404 -} - -export type editDocumentResponse500 = { - data: ErrorResponse - status: 500 -} - -export type editDocumentResponseSuccess = (editDocumentResponse200) & { - headers: Headers; -}; -export type editDocumentResponseError = (editDocumentResponse400 | editDocumentResponse401 | editDocumentResponse404 | editDocumentResponse500) & { - headers: Headers; -}; - -export type editDocumentResponse = (editDocumentResponseSuccess | editDocumentResponseError) - export const getEditDocumentUrl = (id: string,) => { @@ -494,9 +363,9 @@ export const getEditDocumentUrl = (id: string,) => { } export const editDocument = async (id: string, - editDocumentBody: EditDocumentBody, options?: RequestInit): Promise => { + editDocumentBody: EditDocumentBody, options?: RequestInit): Promise => { - const res = await fetch(getEditDocumentUrl(id), + return apiFetch(getEditDocumentUrl(id), { ...options, method: 'POST', @@ -504,27 +373,21 @@ export const editDocument = async (id: string, body: JSON.stringify( editDocumentBody,) } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: editDocumentResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as editDocumentResponse -} +);} export const getEditDocumentMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{id: string;data: EditDocumentBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{id: string;data: EditDocumentBody}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{id: string;data: EditDocumentBody}, TContext> => { const mutationKey = ['editDocument']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -532,7 +395,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {id: string;data: EditDocumentBody}> = (props) => { const {id,data} = props ?? {}; - return editDocument(id,data,fetchOptions) + return editDocument(id,data,requestOptions) } @@ -550,7 +413,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Update document editable fields */ export const useEditDocument = (options?: { mutation?:UseMutationOptions>, TError,{id: string;data: EditDocumentBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{id: string;data: EditDocumentBody}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -563,40 +426,6 @@ export const useEditDocument = { @@ -605,22 +434,16 @@ export const getGetDocumentCoverUrl = (id: string,) => { return `/api/v1/documents/${id}/cover` } -export const getDocumentCover = async (id: string, options?: RequestInit): Promise => { +export const getDocumentCover = async (id: string, options?: RequestInit): Promise => { - const res = await fetch(getGetDocumentCoverUrl(id), + return apiFetch(getGetDocumentCoverUrl(id), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getDocumentCoverResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getDocumentCoverResponse -} +);} @@ -633,16 +456,16 @@ export const getGetDocumentCoverQueryKey = (id: string,) => { } -export const getGetDocumentCoverQueryOptions = >, TError = ErrorResponse>(id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetDocumentCoverQueryOptions = >, TError = ErrorResponse>(id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetDocumentCoverQueryKey(id); - const queryFn: QueryFunction>> = ({ signal }) => getDocumentCover(id, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getDocumentCover(id, { signal, ...requestOptions }); @@ -662,7 +485,7 @@ export function useGetDocumentCover> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetDocumentCover>, TError = ErrorResponse>( @@ -672,11 +495,11 @@ export function useGetDocumentCover> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetDocumentCover>, TError = ErrorResponse>( - id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -684,7 +507,7 @@ export function useGetDocumentCover>, TError = ErrorResponse>( - id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -702,40 +525,6 @@ export function useGetDocumentCover { @@ -745,11 +534,11 @@ export const getUploadDocumentCoverUrl = (id: string,) => { } export const uploadDocumentCover = async (id: string, - uploadDocumentCoverBody: UploadDocumentCoverBody, options?: RequestInit): Promise => { + uploadDocumentCoverBody: UploadDocumentCoverBody, options?: RequestInit): Promise => { const formData = new FormData(); formData.append(`cover_file`, uploadDocumentCoverBody.cover_file); - const res = await fetch(getUploadDocumentCoverUrl(id), + return apiFetch(getUploadDocumentCoverUrl(id), { ...options, method: 'POST' @@ -757,27 +546,21 @@ formData.append(`cover_file`, uploadDocumentCoverBody.cover_file); body: formData, } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: uploadDocumentCoverResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as uploadDocumentCoverResponse -} +);} export const getUploadDocumentCoverMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{id: string;data: UploadDocumentCoverBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{id: string;data: UploadDocumentCoverBody}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{id: string;data: UploadDocumentCoverBody}, TContext> => { const mutationKey = ['uploadDocumentCover']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -785,7 +568,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {id: string;data: UploadDocumentCoverBody}> = (props) => { const {id,data} = props ?? {}; - return uploadDocumentCover(id,data,fetchOptions) + return uploadDocumentCover(id,data,requestOptions) } @@ -803,7 +586,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Upload document cover image */ export const useUploadDocumentCover = (options?: { mutation?:UseMutationOptions>, TError,{id: string;data: UploadDocumentCoverBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{id: string;data: UploadDocumentCoverBody}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -816,35 +599,6 @@ export const useUploadDocumentCover = { @@ -853,22 +607,16 @@ export const getGetDocumentFileUrl = (id: string,) => { return `/api/v1/documents/${id}/file` } -export const getDocumentFile = async (id: string, options?: RequestInit): Promise => { +export const getDocumentFile = async (id: string, options?: RequestInit): Promise => { - const res = await fetch(getGetDocumentFileUrl(id), + return apiFetch(getGetDocumentFileUrl(id), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getDocumentFileResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getDocumentFileResponse -} +);} @@ -881,16 +629,16 @@ export const getGetDocumentFileQueryKey = (id: string,) => { } -export const getGetDocumentFileQueryOptions = >, TError = ErrorResponse>(id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetDocumentFileQueryOptions = >, TError = ErrorResponse>(id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetDocumentFileQueryKey(id); - const queryFn: QueryFunction>> = ({ signal }) => getDocumentFile(id, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getDocumentFile(id, { signal, ...requestOptions }); @@ -910,7 +658,7 @@ export function useGetDocumentFile> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetDocumentFile>, TError = ErrorResponse>( @@ -920,11 +668,11 @@ export function useGetDocumentFile> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetDocumentFile>, TError = ErrorResponse>( - id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -932,7 +680,7 @@ export function useGetDocumentFile>, TError = ErrorResponse>( - id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -950,30 +698,6 @@ export function useGetDocumentFile { const normalizedParams = new URLSearchParams(); @@ -989,22 +713,16 @@ export const getGetProgressListUrl = (params?: GetProgressListParams,) => { return stringifiedParams.length > 0 ? `/api/v1/progress?${stringifiedParams}` : `/api/v1/progress` } -export const getProgressList = async (params?: GetProgressListParams, options?: RequestInit): Promise => { +export const getProgressList = async (params?: GetProgressListParams, options?: RequestInit): Promise => { - const res = await fetch(getGetProgressListUrl(params), + return apiFetch(getGetProgressListUrl(params), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getProgressListResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getProgressListResponse -} +);} @@ -1017,16 +735,16 @@ export const getGetProgressListQueryKey = (params?: GetProgressListParams,) => { } -export const getGetProgressListQueryOptions = >, TError = ErrorResponse>(params?: GetProgressListParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetProgressListQueryOptions = >, TError = ErrorResponse>(params?: GetProgressListParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetProgressListQueryKey(params); - const queryFn: QueryFunction>> = ({ signal }) => getProgressList(params, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getProgressList(params, { signal, ...requestOptions }); @@ -1046,7 +764,7 @@ export function useGetProgressList> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetProgressList>, TError = ErrorResponse>( @@ -1056,11 +774,11 @@ export function useGetProgressList> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetProgressList>, TError = ErrorResponse>( - params?: GetProgressListParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetProgressListParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -1068,7 +786,7 @@ export function useGetProgressList>, TError = ErrorResponse>( - params?: GetProgressListParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetProgressListParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -1086,35 +804,6 @@ export function useGetProgressList { @@ -1123,9 +812,9 @@ export const getUpdateProgressUrl = () => { return `/api/v1/progress` } -export const updateProgress = async (updateProgressRequest: UpdateProgressRequest, options?: RequestInit): Promise => { +export const updateProgress = async (updateProgressRequest: UpdateProgressRequest, options?: RequestInit): Promise => { - const res = await fetch(getUpdateProgressUrl(), + return apiFetch(getUpdateProgressUrl(), { ...options, method: 'PUT', @@ -1133,27 +822,21 @@ export const updateProgress = async (updateProgressRequest: UpdateProgressReques body: JSON.stringify( updateProgressRequest,) } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: updateProgressResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as updateProgressResponse -} +);} export const getUpdateProgressMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: UpdateProgressRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: UpdateProgressRequest}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: UpdateProgressRequest}, TContext> => { const mutationKey = ['updateProgress']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -1161,7 +844,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: UpdateProgressRequest}> = (props) => { const {data} = props ?? {}; - return updateProgress(data,fetchOptions) + return updateProgress(data,requestOptions) } @@ -1179,7 +862,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Update document progress */ export const useUpdateProgress = (options?: { mutation?:UseMutationOptions>, TError,{data: UpdateProgressRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: UpdateProgressRequest}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -1192,35 +875,6 @@ export const useUpdateProgress = { @@ -1229,22 +883,16 @@ export const getGetProgressUrl = (id: string,) => { return `/api/v1/progress/${id}` } -export const getProgress = async (id: string, options?: RequestInit): Promise => { +export const getProgress = async (id: string, options?: RequestInit): Promise => { - const res = await fetch(getGetProgressUrl(id), + return apiFetch(getGetProgressUrl(id), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getProgressResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getProgressResponse -} +);} @@ -1257,16 +905,16 @@ export const getGetProgressQueryKey = (id: string,) => { } -export const getGetProgressQueryOptions = >, TError = ErrorResponse>(id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetProgressQueryOptions = >, TError = ErrorResponse>(id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetProgressQueryKey(id); - const queryFn: QueryFunction>> = ({ signal }) => getProgress(id, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getProgress(id, { signal, ...requestOptions }); @@ -1286,7 +934,7 @@ export function useGetProgress>, TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetProgress>, TError = ErrorResponse>( @@ -1296,11 +944,11 @@ export function useGetProgress>, TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetProgress>, TError = ErrorResponse>( - id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -1308,7 +956,7 @@ export function useGetProgress>, */ export function useGetProgress>, TError = ErrorResponse>( - id: string, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + id: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -1326,30 +974,6 @@ export function useGetProgress>, /** * @summary Get activity data */ -export type getActivityResponse200 = { - data: ActivityResponse - status: 200 -} - -export type getActivityResponse401 = { - data: ErrorResponse - status: 401 -} - -export type getActivityResponse500 = { - data: ErrorResponse - status: 500 -} - -export type getActivityResponseSuccess = (getActivityResponse200) & { - headers: Headers; -}; -export type getActivityResponseError = (getActivityResponse401 | getActivityResponse500) & { - headers: Headers; -}; - -export type getActivityResponse = (getActivityResponseSuccess | getActivityResponseError) - export const getGetActivityUrl = (params?: GetActivityParams,) => { const normalizedParams = new URLSearchParams(); @@ -1365,22 +989,16 @@ export const getGetActivityUrl = (params?: GetActivityParams,) => { return stringifiedParams.length > 0 ? `/api/v1/activity?${stringifiedParams}` : `/api/v1/activity` } -export const getActivity = async (params?: GetActivityParams, options?: RequestInit): Promise => { +export const getActivity = async (params?: GetActivityParams, options?: RequestInit): Promise => { - const res = await fetch(getGetActivityUrl(params), + return apiFetch(getGetActivityUrl(params), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getActivityResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getActivityResponse -} +);} @@ -1393,16 +1011,16 @@ export const getGetActivityQueryKey = (params?: GetActivityParams,) => { } -export const getGetActivityQueryOptions = >, TError = ErrorResponse>(params?: GetActivityParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetActivityQueryOptions = >, TError = ErrorResponse>(params?: GetActivityParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetActivityQueryKey(params); - const queryFn: QueryFunction>> = ({ signal }) => getActivity(params, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getActivity(params, { signal, ...requestOptions }); @@ -1422,7 +1040,7 @@ export function useGetActivity>, TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetActivity>, TError = ErrorResponse>( @@ -1432,11 +1050,11 @@ export function useGetActivity>, TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetActivity>, TError = ErrorResponse>( - params?: GetActivityParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetActivityParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -1444,7 +1062,7 @@ export function useGetActivity>, */ export function useGetActivity>, TError = ErrorResponse>( - params?: GetActivityParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetActivityParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -1462,35 +1080,6 @@ export function useGetActivity>, /** * @summary Create activity records */ -export type createActivityResponse200 = { - data: CreateActivityResponse - status: 200 -} - -export type createActivityResponse400 = { - data: ErrorResponse - status: 400 -} - -export type createActivityResponse401 = { - data: ErrorResponse - status: 401 -} - -export type createActivityResponse500 = { - data: ErrorResponse - status: 500 -} - -export type createActivityResponseSuccess = (createActivityResponse200) & { - headers: Headers; -}; -export type createActivityResponseError = (createActivityResponse400 | createActivityResponse401 | createActivityResponse500) & { - headers: Headers; -}; - -export type createActivityResponse = (createActivityResponseSuccess | createActivityResponseError) - export const getCreateActivityUrl = () => { @@ -1499,9 +1088,9 @@ export const getCreateActivityUrl = () => { return `/api/v1/activity` } -export const createActivity = async (createActivityRequest: CreateActivityRequest, options?: RequestInit): Promise => { +export const createActivity = async (createActivityRequest: CreateActivityRequest, options?: RequestInit): Promise => { - const res = await fetch(getCreateActivityUrl(), + return apiFetch(getCreateActivityUrl(), { ...options, method: 'POST', @@ -1509,27 +1098,21 @@ export const createActivity = async (createActivityRequest: CreateActivityReques body: JSON.stringify( createActivityRequest,) } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: createActivityResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as createActivityResponse -} +);} export const getCreateActivityMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: CreateActivityRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: CreateActivityRequest}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: CreateActivityRequest}, TContext> => { const mutationKey = ['createActivity']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -1537,7 +1120,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: CreateActivityRequest}> = (props) => { const {data} = props ?? {}; - return createActivity(data,fetchOptions) + return createActivity(data,requestOptions) } @@ -1555,7 +1138,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Create activity records */ export const useCreateActivity = (options?: { mutation?:UseMutationOptions>, TError,{data: CreateActivityRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: CreateActivityRequest}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -1568,30 +1151,6 @@ export const useCreateActivity = { @@ -1600,22 +1159,16 @@ export const getGetSettingsUrl = () => { return `/api/v1/settings` } -export const getSettings = async ( options?: RequestInit): Promise => { +export const getSettings = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetSettingsUrl(), + return apiFetch(getGetSettingsUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getSettingsResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getSettingsResponse -} +);} @@ -1628,16 +1181,16 @@ export const getGetSettingsQueryKey = () => { } -export const getGetSettingsQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetSettingsQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetSettingsQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getSettings({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getSettings({ signal, ...requestOptions }); @@ -1657,7 +1210,7 @@ export function useGetSettings>, TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetSettings>, TError = ErrorResponse>( @@ -1667,11 +1220,11 @@ export function useGetSettings>, TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetSettings>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -1679,7 +1232,7 @@ export function useGetSettings>, */ export function useGetSettings>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -1697,35 +1250,6 @@ export function useGetSettings>, /** * @summary Update user settings */ -export type updateSettingsResponse200 = { - data: SettingsResponse - status: 200 -} - -export type updateSettingsResponse400 = { - data: ErrorResponse - status: 400 -} - -export type updateSettingsResponse401 = { - data: ErrorResponse - status: 401 -} - -export type updateSettingsResponse500 = { - data: ErrorResponse - status: 500 -} - -export type updateSettingsResponseSuccess = (updateSettingsResponse200) & { - headers: Headers; -}; -export type updateSettingsResponseError = (updateSettingsResponse400 | updateSettingsResponse401 | updateSettingsResponse500) & { - headers: Headers; -}; - -export type updateSettingsResponse = (updateSettingsResponseSuccess | updateSettingsResponseError) - export const getUpdateSettingsUrl = () => { @@ -1734,9 +1258,9 @@ export const getUpdateSettingsUrl = () => { return `/api/v1/settings` } -export const updateSettings = async (updateSettingsRequest: UpdateSettingsRequest, options?: RequestInit): Promise => { +export const updateSettings = async (updateSettingsRequest: UpdateSettingsRequest, options?: RequestInit): Promise => { - const res = await fetch(getUpdateSettingsUrl(), + return apiFetch(getUpdateSettingsUrl(), { ...options, method: 'PUT', @@ -1744,27 +1268,21 @@ export const updateSettings = async (updateSettingsRequest: UpdateSettingsReques body: JSON.stringify( updateSettingsRequest,) } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: updateSettingsResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as updateSettingsResponse -} +);} export const getUpdateSettingsMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: UpdateSettingsRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: UpdateSettingsRequest}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: UpdateSettingsRequest}, TContext> => { const mutationKey = ['updateSettings']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -1772,7 +1290,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: UpdateSettingsRequest}> = (props) => { const {data} = props ?? {}; - return updateSettings(data,fetchOptions) + return updateSettings(data,requestOptions) } @@ -1790,7 +1308,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Update user settings */ export const useUpdateSettings = (options?: { mutation?:UseMutationOptions>, TError,{data: UpdateSettingsRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: UpdateSettingsRequest}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -1803,35 +1321,6 @@ export const useUpdateSettings = { @@ -1840,9 +1329,9 @@ export const getLoginUrl = () => { return `/api/v1/auth/login` } -export const login = async (loginRequest: LoginRequest, options?: RequestInit): Promise => { +export const login = async (loginRequest: LoginRequest, options?: RequestInit): Promise => { - const res = await fetch(getLoginUrl(), + return apiFetch(getLoginUrl(), { ...options, method: 'POST', @@ -1850,27 +1339,21 @@ export const login = async (loginRequest: LoginRequest, options?: RequestInit): body: JSON.stringify( loginRequest,) } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: loginResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as loginResponse -} +);} export const getLoginMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: LoginRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: LoginRequest}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: LoginRequest}, TContext> => { const mutationKey = ['login']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -1878,7 +1361,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: LoginRequest}> = (props) => { const {data} = props ?? {}; - return login(data,fetchOptions) + return login(data,requestOptions) } @@ -1896,7 +1379,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary User login */ export const useLogin = (options?: { mutation?:UseMutationOptions>, TError,{data: LoginRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: LoginRequest}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -1909,35 +1392,6 @@ export const useLogin = { @@ -1946,9 +1400,9 @@ export const getRegisterUrl = () => { return `/api/v1/auth/register` } -export const register = async (loginRequest: LoginRequest, options?: RequestInit): Promise => { +export const register = async (loginRequest: LoginRequest, options?: RequestInit): Promise => { - const res = await fetch(getRegisterUrl(), + return apiFetch(getRegisterUrl(), { ...options, method: 'POST', @@ -1956,27 +1410,21 @@ export const register = async (loginRequest: LoginRequest, options?: RequestInit body: JSON.stringify( loginRequest,) } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: registerResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as registerResponse -} +);} export const getRegisterMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: LoginRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: LoginRequest}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: LoginRequest}, TContext> => { const mutationKey = ['register']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -1984,7 +1432,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: LoginRequest}> = (props) => { const {data} = props ?? {}; - return register(data,fetchOptions) + return register(data,requestOptions) } @@ -2002,7 +1450,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary User registration */ export const useRegister = (options?: { mutation?:UseMutationOptions>, TError,{data: LoginRequest}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: LoginRequest}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -2015,25 +1463,6 @@ export const useRegister = { @@ -2042,36 +1471,30 @@ export const getLogoutUrl = () => { return `/api/v1/auth/logout` } -export const logout = async ( options?: RequestInit): Promise => { +export const logout = async ( options?: RequestInit): Promise => { - const res = await fetch(getLogoutUrl(), + return apiFetch(getLogoutUrl(), { ...options, method: 'POST' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: logoutResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as logoutResponse -} +);} export const getLogoutMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,void, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,void, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,void, TContext> => { const mutationKey = ['logout']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -2079,7 +1502,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, void> = () => { - return logout(fetchOptions) + return logout(requestOptions) } @@ -2097,7 +1520,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary User logout */ export const useLogout = (options?: { mutation?:UseMutationOptions>, TError,void, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,void, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -2110,25 +1533,6 @@ export const useLogout = { @@ -2137,22 +1541,16 @@ export const getGetMeUrl = () => { return `/api/v1/auth/me` } -export const getMe = async ( options?: RequestInit): Promise => { +export const getMe = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetMeUrl(), + return apiFetch(getGetMeUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getMeResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getMeResponse -} +);} @@ -2165,16 +1563,16 @@ export const getGetMeQueryKey = () => { } -export const getGetMeQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetMeQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetMeQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getMe({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getMe({ signal, ...requestOptions }); @@ -2194,7 +1592,7 @@ export function useGetMe>, TError = Err TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetMe>, TError = ErrorResponse>( @@ -2204,11 +1602,11 @@ export function useGetMe>, TError = Err TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetMe>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -2216,7 +1614,7 @@ export function useGetMe>, TError = Err */ export function useGetMe>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -2234,25 +1632,6 @@ export function useGetMe>, TError = Err /** * @summary Get server information */ -export type getInfoResponse200 = { - data: InfoResponse - status: 200 -} - -export type getInfoResponse500 = { - data: ErrorResponse - status: 500 -} - -export type getInfoResponseSuccess = (getInfoResponse200) & { - headers: Headers; -}; -export type getInfoResponseError = (getInfoResponse500) & { - headers: Headers; -}; - -export type getInfoResponse = (getInfoResponseSuccess | getInfoResponseError) - export const getGetInfoUrl = () => { @@ -2261,22 +1640,16 @@ export const getGetInfoUrl = () => { return `/api/v1/info` } -export const getInfo = async ( options?: RequestInit): Promise => { +export const getInfo = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetInfoUrl(), + return apiFetch(getGetInfoUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getInfoResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getInfoResponse -} +);} @@ -2289,16 +1662,16 @@ export const getGetInfoQueryKey = () => { } -export const getGetInfoQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetInfoQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetInfoQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getInfo({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getInfo({ signal, ...requestOptions }); @@ -2318,7 +1691,7 @@ export function useGetInfo>, TError = TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetInfo>, TError = ErrorResponse>( @@ -2328,11 +1701,11 @@ export function useGetInfo>, TError = TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetInfo>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -2340,7 +1713,7 @@ export function useGetInfo>, TError = */ export function useGetInfo>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -2358,30 +1731,6 @@ export function useGetInfo>, TError = /** * @summary Get home page data */ -export type getHomeResponse200 = { - data: HomeResponse - status: 200 -} - -export type getHomeResponse401 = { - data: ErrorResponse - status: 401 -} - -export type getHomeResponse500 = { - data: ErrorResponse - status: 500 -} - -export type getHomeResponseSuccess = (getHomeResponse200) & { - headers: Headers; -}; -export type getHomeResponseError = (getHomeResponse401 | getHomeResponse500) & { - headers: Headers; -}; - -export type getHomeResponse = (getHomeResponseSuccess | getHomeResponseError) - export const getGetHomeUrl = () => { @@ -2390,22 +1739,16 @@ export const getGetHomeUrl = () => { return `/api/v1/home` } -export const getHome = async ( options?: RequestInit): Promise => { +export const getHome = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetHomeUrl(), + return apiFetch(getGetHomeUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getHomeResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getHomeResponse -} +);} @@ -2418,16 +1761,16 @@ export const getGetHomeQueryKey = () => { } -export const getGetHomeQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetHomeQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetHomeQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getHome({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getHome({ signal, ...requestOptions }); @@ -2447,7 +1790,7 @@ export function useGetHome>, TError = TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetHome>, TError = ErrorResponse>( @@ -2457,11 +1800,11 @@ export function useGetHome>, TError = TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetHome>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -2469,7 +1812,7 @@ export function useGetHome>, TError = */ export function useGetHome>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -2487,30 +1830,6 @@ export function useGetHome>, TError = /** * @summary Get user streaks */ -export type getStreaksResponse200 = { - data: StreaksResponse - status: 200 -} - -export type getStreaksResponse401 = { - data: ErrorResponse - status: 401 -} - -export type getStreaksResponse500 = { - data: ErrorResponse - status: 500 -} - -export type getStreaksResponseSuccess = (getStreaksResponse200) & { - headers: Headers; -}; -export type getStreaksResponseError = (getStreaksResponse401 | getStreaksResponse500) & { - headers: Headers; -}; - -export type getStreaksResponse = (getStreaksResponseSuccess | getStreaksResponseError) - export const getGetStreaksUrl = () => { @@ -2519,22 +1838,16 @@ export const getGetStreaksUrl = () => { return `/api/v1/home/streaks` } -export const getStreaks = async ( options?: RequestInit): Promise => { +export const getStreaks = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetStreaksUrl(), + return apiFetch(getGetStreaksUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getStreaksResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getStreaksResponse -} +);} @@ -2547,16 +1860,16 @@ export const getGetStreaksQueryKey = () => { } -export const getGetStreaksQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetStreaksQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetStreaksQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getStreaks({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getStreaks({ signal, ...requestOptions }); @@ -2576,7 +1889,7 @@ export function useGetStreaks>, TE TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetStreaks>, TError = ErrorResponse>( @@ -2586,11 +1899,11 @@ export function useGetStreaks>, TE TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetStreaks>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -2598,7 +1911,7 @@ export function useGetStreaks>, TE */ export function useGetStreaks>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -2616,30 +1929,6 @@ export function useGetStreaks>, TE /** * @summary Get daily read stats graph data */ -export type getGraphDataResponse200 = { - data: GraphDataResponse - status: 200 -} - -export type getGraphDataResponse401 = { - data: ErrorResponse - status: 401 -} - -export type getGraphDataResponse500 = { - data: ErrorResponse - status: 500 -} - -export type getGraphDataResponseSuccess = (getGraphDataResponse200) & { - headers: Headers; -}; -export type getGraphDataResponseError = (getGraphDataResponse401 | getGraphDataResponse500) & { - headers: Headers; -}; - -export type getGraphDataResponse = (getGraphDataResponseSuccess | getGraphDataResponseError) - export const getGetGraphDataUrl = () => { @@ -2648,22 +1937,16 @@ export const getGetGraphDataUrl = () => { return `/api/v1/home/graph` } -export const getGraphData = async ( options?: RequestInit): Promise => { +export const getGraphData = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetGraphDataUrl(), + return apiFetch(getGetGraphDataUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getGraphDataResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getGraphDataResponse -} +);} @@ -2676,16 +1959,16 @@ export const getGetGraphDataQueryKey = () => { } -export const getGetGraphDataQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetGraphDataQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetGraphDataQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getGraphData({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getGraphData({ signal, ...requestOptions }); @@ -2705,7 +1988,7 @@ export function useGetGraphData> TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetGraphData>, TError = ErrorResponse>( @@ -2715,11 +1998,11 @@ export function useGetGraphData> TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetGraphData>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -2727,7 +2010,7 @@ export function useGetGraphData> */ export function useGetGraphData>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -2745,30 +2028,6 @@ export function useGetGraphData> /** * @summary Get user statistics (leaderboards) */ -export type getUserStatisticsResponse200 = { - data: UserStatisticsResponse - status: 200 -} - -export type getUserStatisticsResponse401 = { - data: ErrorResponse - status: 401 -} - -export type getUserStatisticsResponse500 = { - data: ErrorResponse - status: 500 -} - -export type getUserStatisticsResponseSuccess = (getUserStatisticsResponse200) & { - headers: Headers; -}; -export type getUserStatisticsResponseError = (getUserStatisticsResponse401 | getUserStatisticsResponse500) & { - headers: Headers; -}; - -export type getUserStatisticsResponse = (getUserStatisticsResponseSuccess | getUserStatisticsResponseError) - export const getGetUserStatisticsUrl = () => { @@ -2777,22 +2036,16 @@ export const getGetUserStatisticsUrl = () => { return `/api/v1/home/statistics` } -export const getUserStatistics = async ( options?: RequestInit): Promise => { +export const getUserStatistics = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetUserStatisticsUrl(), + return apiFetch(getGetUserStatisticsUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getUserStatisticsResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getUserStatisticsResponse -} +);} @@ -2805,16 +2058,16 @@ export const getGetUserStatisticsQueryKey = () => { } -export const getGetUserStatisticsQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetUserStatisticsQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetUserStatisticsQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getUserStatistics({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getUserStatistics({ signal, ...requestOptions }); @@ -2834,7 +2087,7 @@ export function useGetUserStatistics> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetUserStatistics>, TError = ErrorResponse>( @@ -2844,11 +2097,11 @@ export function useGetUserStatistics> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetUserStatistics>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -2856,7 +2109,7 @@ export function useGetUserStatistics>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -2874,35 +2127,6 @@ export function useGetUserStatistics { const normalizedParams = new URLSearchParams(); @@ -2918,22 +2142,16 @@ export const getGetSearchUrl = (params: GetSearchParams,) => { return stringifiedParams.length > 0 ? `/api/v1/search?${stringifiedParams}` : `/api/v1/search` } -export const getSearch = async (params: GetSearchParams, options?: RequestInit): Promise => { +export const getSearch = async (params: GetSearchParams, options?: RequestInit): Promise => { - const res = await fetch(getGetSearchUrl(params), + return apiFetch(getGetSearchUrl(params), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getSearchResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getSearchResponse -} +);} @@ -2946,16 +2164,16 @@ export const getGetSearchQueryKey = (params?: GetSearchParams,) => { } -export const getGetSearchQueryOptions = >, TError = ErrorResponse>(params: GetSearchParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetSearchQueryOptions = >, TError = ErrorResponse>(params: GetSearchParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetSearchQueryKey(params); - const queryFn: QueryFunction>> = ({ signal }) => getSearch(params, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getSearch(params, { signal, ...requestOptions }); @@ -2975,7 +2193,7 @@ export function useGetSearch>, TErr TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetSearch>, TError = ErrorResponse>( @@ -2985,11 +2203,11 @@ export function useGetSearch>, TErr TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetSearch>, TError = ErrorResponse>( - params: GetSearchParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params: GetSearchParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -2997,7 +2215,7 @@ export function useGetSearch>, TErr */ export function useGetSearch>, TError = ErrorResponse>( - params: GetSearchParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params: GetSearchParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -3015,30 +2233,6 @@ export function useGetSearch>, TErr /** * @summary Download search result */ -export type postSearchResponse200 = { - data: void - status: 200 -} - -export type postSearchResponse401 = { - data: ErrorResponse - status: 401 -} - -export type postSearchResponse500 = { - data: ErrorResponse - status: 500 -} - -export type postSearchResponseSuccess = (postSearchResponse200) & { - headers: Headers; -}; -export type postSearchResponseError = (postSearchResponse401 | postSearchResponse500) & { - headers: Headers; -}; - -export type postSearchResponse = (postSearchResponseSuccess | postSearchResponseError) - export const getPostSearchUrl = () => { @@ -3047,14 +2241,14 @@ export const getPostSearchUrl = () => { return `/api/v1/search` } -export const postSearch = async (postSearchBody: PostSearchBody, options?: RequestInit): Promise => { +export const postSearch = async (postSearchBody: PostSearchBody, options?: RequestInit): Promise => { const formUrlEncoded = new URLSearchParams(); formUrlEncoded.append(`source`, postSearchBody.source); formUrlEncoded.append(`title`, postSearchBody.title); formUrlEncoded.append(`author`, postSearchBody.author); formUrlEncoded.append(`id`, postSearchBody.id); - const res = await fetch(getPostSearchUrl(), + return apiFetch(getPostSearchUrl(), { ...options, method: 'POST', @@ -3062,27 +2256,21 @@ formUrlEncoded.append(`id`, postSearchBody.id); body: formUrlEncoded, } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: postSearchResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as postSearchResponse -} +);} export const getPostSearchMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: PostSearchBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: PostSearchBody}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: PostSearchBody}, TContext> => { const mutationKey = ['postSearch']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -3090,7 +2278,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: PostSearchBody}> = (props) => { const {data} = props ?? {}; - return postSearch(data,fetchOptions) + return postSearch(data,requestOptions) } @@ -3108,7 +2296,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Download search result */ export const usePostSearch = (options?: { mutation?:UseMutationOptions>, TError,{data: PostSearchBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: PostSearchBody}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -3121,25 +2309,6 @@ export const usePostSearch = { @@ -3148,22 +2317,16 @@ export const getGetAdminUrl = () => { return `/api/v1/admin` } -export const getAdmin = async ( options?: RequestInit): Promise => { +export const getAdmin = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetAdminUrl(), + return apiFetch(getGetAdminUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getAdminResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getAdminResponse -} +);} @@ -3176,16 +2339,16 @@ export const getGetAdminQueryKey = () => { } -export const getGetAdminQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetAdminQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetAdminQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getAdmin({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getAdmin({ signal, ...requestOptions }); @@ -3205,7 +2368,7 @@ export function useGetAdmin>, TError TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetAdmin>, TError = ErrorResponse>( @@ -3215,11 +2378,11 @@ export function useGetAdmin>, TError TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetAdmin>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -3227,7 +2390,7 @@ export function useGetAdmin>, TError */ export function useGetAdmin>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -3245,40 +2408,6 @@ export function useGetAdmin>, TError /** * @summary Perform admin action (backup, restore, etc.) */ -export type postAdminActionResponse200ApplicationJson = { - data: MessageResponse - status: 200 -} - -export type postAdminActionResponse200ApplicationOctetStream = { - data: Blob - status: 200 -} - -export type postAdminActionResponse400 = { - data: ErrorResponse - status: 400 -} - -export type postAdminActionResponse401 = { - data: ErrorResponse - status: 401 -} - -export type postAdminActionResponse500 = { - data: ErrorResponse - status: 500 -} - -export type postAdminActionResponseSuccess = (postAdminActionResponse200ApplicationJson | postAdminActionResponse200ApplicationOctetStream) & { - headers: Headers; -}; -export type postAdminActionResponseError = (postAdminActionResponse400 | postAdminActionResponse401 | postAdminActionResponse500) & { - headers: Headers; -}; - -export type postAdminActionResponse = (postAdminActionResponseSuccess | postAdminActionResponseError) - export const getPostAdminActionUrl = () => { @@ -3287,7 +2416,7 @@ export const getPostAdminActionUrl = () => { return `/api/v1/admin` } -export const postAdminAction = async (postAdminActionBody: PostAdminActionBody, options?: RequestInit): Promise => { +export const postAdminAction = async (postAdminActionBody: PostAdminActionBody, options?: RequestInit): Promise => { const formData = new FormData(); formData.append(`action`, postAdminActionBody.action); if(postAdminActionBody.backup_types !== undefined) { @@ -3297,7 +2426,7 @@ if(postAdminActionBody.restore_file !== undefined) { formData.append(`restore_file`, postAdminActionBody.restore_file); } - const res = await fetch(getPostAdminActionUrl(), + return apiFetch(getPostAdminActionUrl(), { ...options, method: 'POST' @@ -3305,27 +2434,21 @@ if(postAdminActionBody.restore_file !== undefined) { body: formData, } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: postAdminActionResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as postAdminActionResponse -} +);} export const getPostAdminActionMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: PostAdminActionBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: PostAdminActionBody}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: PostAdminActionBody}, TContext> => { const mutationKey = ['postAdminAction']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -3333,7 +2456,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: PostAdminActionBody}> = (props) => { const {data} = props ?? {}; - return postAdminAction(data,fetchOptions) + return postAdminAction(data,requestOptions) } @@ -3351,7 +2474,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Perform admin action (backup, restore, etc.) */ export const usePostAdminAction = (options?: { mutation?:UseMutationOptions>, TError,{data: PostAdminActionBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: PostAdminActionBody}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -3364,30 +2487,6 @@ export const usePostAdminAction = { @@ -3396,22 +2495,16 @@ export const getGetUsersUrl = () => { return `/api/v1/admin/users` } -export const getUsers = async ( options?: RequestInit): Promise => { +export const getUsers = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetUsersUrl(), + return apiFetch(getGetUsersUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getUsersResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getUsersResponse -} +);} @@ -3424,16 +2517,16 @@ export const getGetUsersQueryKey = () => { } -export const getGetUsersQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetUsersQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetUsersQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getUsers({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getUsers({ signal, ...requestOptions }); @@ -3453,7 +2546,7 @@ export function useGetUsers>, TError TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetUsers>, TError = ErrorResponse>( @@ -3463,11 +2556,11 @@ export function useGetUsers>, TError TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetUsers>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -3475,7 +2568,7 @@ export function useGetUsers>, TError */ export function useGetUsers>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -3493,35 +2586,6 @@ export function useGetUsers>, TError /** * @summary Create, update, or delete user */ -export type updateUserResponse200 = { - data: UsersResponse - status: 200 -} - -export type updateUserResponse400 = { - data: ErrorResponse - status: 400 -} - -export type updateUserResponse401 = { - data: ErrorResponse - status: 401 -} - -export type updateUserResponse500 = { - data: ErrorResponse - status: 500 -} - -export type updateUserResponseSuccess = (updateUserResponse200) & { - headers: Headers; -}; -export type updateUserResponseError = (updateUserResponse400 | updateUserResponse401 | updateUserResponse500) & { - headers: Headers; -}; - -export type updateUserResponse = (updateUserResponseSuccess | updateUserResponseError) - export const getUpdateUserUrl = () => { @@ -3530,7 +2594,7 @@ export const getUpdateUserUrl = () => { return `/api/v1/admin/users` } -export const updateUser = async (updateUserBody: UpdateUserBody, options?: RequestInit): Promise => { +export const updateUser = async (updateUserBody: UpdateUserBody, options?: RequestInit): Promise => { const formUrlEncoded = new URLSearchParams(); formUrlEncoded.append(`operation`, updateUserBody.operation); formUrlEncoded.append(`user`, updateUserBody.user); @@ -3541,7 +2605,7 @@ if(updateUserBody.is_admin !== undefined) { formUrlEncoded.append(`is_admin`, updateUserBody.is_admin.toString()) } - const res = await fetch(getUpdateUserUrl(), + return apiFetch(getUpdateUserUrl(), { ...options, method: 'POST', @@ -3549,27 +2613,21 @@ if(updateUserBody.is_admin !== undefined) { body: formUrlEncoded, } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: updateUserResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as updateUserResponse -} +);} export const getUpdateUserMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: UpdateUserBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: UpdateUserBody}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: UpdateUserBody}, TContext> => { const mutationKey = ['updateUser']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -3577,7 +2635,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: UpdateUserBody}> = (props) => { const {data} = props ?? {}; - return updateUser(data,fetchOptions) + return updateUser(data,requestOptions) } @@ -3595,7 +2653,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Create, update, or delete user */ export const useUpdateUser = (options?: { mutation?:UseMutationOptions>, TError,{data: UpdateUserBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: UpdateUserBody}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -3608,30 +2666,6 @@ export const useUpdateUser = { const normalizedParams = new URLSearchParams(); @@ -3647,22 +2681,16 @@ export const getGetImportDirectoryUrl = (params?: GetImportDirectoryParams,) => return stringifiedParams.length > 0 ? `/api/v1/admin/import?${stringifiedParams}` : `/api/v1/admin/import` } -export const getImportDirectory = async (params?: GetImportDirectoryParams, options?: RequestInit): Promise => { +export const getImportDirectory = async (params?: GetImportDirectoryParams, options?: RequestInit): Promise => { - const res = await fetch(getGetImportDirectoryUrl(params), + return apiFetch(getGetImportDirectoryUrl(params), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getImportDirectoryResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getImportDirectoryResponse -} +);} @@ -3675,16 +2703,16 @@ export const getGetImportDirectoryQueryKey = (params?: GetImportDirectoryParams, } -export const getGetImportDirectoryQueryOptions = >, TError = ErrorResponse>(params?: GetImportDirectoryParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetImportDirectoryQueryOptions = >, TError = ErrorResponse>(params?: GetImportDirectoryParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetImportDirectoryQueryKey(params); - const queryFn: QueryFunction>> = ({ signal }) => getImportDirectory(params, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getImportDirectory(params, { signal, ...requestOptions }); @@ -3704,7 +2732,7 @@ export function useGetImportDirectory> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetImportDirectory>, TError = ErrorResponse>( @@ -3714,11 +2742,11 @@ export function useGetImportDirectory> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetImportDirectory>, TError = ErrorResponse>( - params?: GetImportDirectoryParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetImportDirectoryParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -3726,7 +2754,7 @@ export function useGetImportDirectory>, TError = ErrorResponse>( - params?: GetImportDirectoryParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetImportDirectoryParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -3744,35 +2772,6 @@ export function useGetImportDirectory { @@ -3781,12 +2780,12 @@ export const getPostImportUrl = () => { return `/api/v1/admin/import` } -export const postImport = async (postImportBody: PostImportBody, options?: RequestInit): Promise => { +export const postImport = async (postImportBody: PostImportBody, options?: RequestInit): Promise => { const formUrlEncoded = new URLSearchParams(); formUrlEncoded.append(`directory`, postImportBody.directory); formUrlEncoded.append(`type`, postImportBody.type); - const res = await fetch(getPostImportUrl(), + return apiFetch(getPostImportUrl(), { ...options, method: 'POST', @@ -3794,27 +2793,21 @@ formUrlEncoded.append(`type`, postImportBody.type); body: formUrlEncoded, } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: postImportResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as postImportResponse -} +);} export const getPostImportMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: PostImportBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: PostImportBody}, TContext>, request?: SecondParameter} ): UseMutationOptions>, TError,{data: PostImportBody}, TContext> => { const mutationKey = ['postImport']; -const {mutation: mutationOptions, fetch: fetchOptions} = options ? +const {mutation: mutationOptions, request: requestOptions} = options ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? options : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, fetch: undefined}; + : {mutation: { mutationKey, }, request: undefined}; @@ -3822,7 +2815,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? const mutationFn: MutationFunction>, {data: PostImportBody}> = (props) => { const {data} = props ?? {}; - return postImport(data,fetchOptions) + return postImport(data,requestOptions) } @@ -3840,7 +2833,7 @@ const {mutation: mutationOptions, fetch: fetchOptions} = options ? * @summary Perform import */ export const usePostImport = (options?: { mutation?:UseMutationOptions>, TError,{data: PostImportBody}, TContext>, fetch?: RequestInit} + TContext = unknown>(options?: { mutation?:UseMutationOptions>, TError,{data: PostImportBody}, TContext>, request?: SecondParameter} , queryClient?: QueryClient): UseMutationResult< Awaited>, TError, @@ -3853,30 +2846,6 @@ export const usePostImport = { @@ -3885,22 +2854,16 @@ export const getGetImportResultsUrl = () => { return `/api/v1/admin/import-results` } -export const getImportResults = async ( options?: RequestInit): Promise => { +export const getImportResults = async ( options?: RequestInit): Promise => { - const res = await fetch(getGetImportResultsUrl(), + return apiFetch(getGetImportResultsUrl(), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getImportResultsResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getImportResultsResponse -} +);} @@ -3913,16 +2876,16 @@ export const getGetImportResultsQueryKey = () => { } -export const getGetImportResultsQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetImportResultsQueryOptions = >, TError = ErrorResponse>( options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetImportResultsQueryKey(); - const queryFn: QueryFunction>> = ({ signal }) => getImportResults({ signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getImportResults({ signal, ...requestOptions }); @@ -3942,7 +2905,7 @@ export function useGetImportResults> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetImportResults>, TError = ErrorResponse>( @@ -3952,11 +2915,11 @@ export function useGetImportResults> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetImportResults>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -3964,7 +2927,7 @@ export function useGetImportResults>, TError = ErrorResponse>( - options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { @@ -3982,30 +2945,6 @@ export function useGetImportResults { const normalizedParams = new URLSearchParams(); @@ -4021,22 +2960,16 @@ export const getGetLogsUrl = (params?: GetLogsParams,) => { return stringifiedParams.length > 0 ? `/api/v1/admin/logs?${stringifiedParams}` : `/api/v1/admin/logs` } -export const getLogs = async (params?: GetLogsParams, options?: RequestInit): Promise => { +export const getLogs = async (params?: GetLogsParams, options?: RequestInit): Promise => { - const res = await fetch(getGetLogsUrl(params), + return apiFetch(getGetLogsUrl(params), { ...options, method: 'GET' } -) - - const body = [204, 205, 304].includes(res.status) ? null : await res.text(); - - const data: getLogsResponse['data'] = body ? JSON.parse(body) : {} - return { data, status: res.status, headers: res.headers } as getLogsResponse -} +);} @@ -4049,16 +2982,16 @@ export const getGetLogsQueryKey = (params?: GetLogsParams,) => { } -export const getGetLogsQueryOptions = >, TError = ErrorResponse>(params?: GetLogsParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} +export const getGetLogsQueryOptions = >, TError = ErrorResponse>(params?: GetLogsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} ) => { -const {query: queryOptions, fetch: fetchOptions} = options ?? {}; +const {query: queryOptions, request: requestOptions} = options ?? {}; const queryKey = queryOptions?.queryKey ?? getGetLogsQueryKey(params); - const queryFn: QueryFunction>> = ({ signal }) => getLogs(params, { signal, ...fetchOptions }); + const queryFn: QueryFunction>> = ({ signal }) => getLogs(params, { signal, ...requestOptions }); @@ -4078,7 +3011,7 @@ export function useGetLogs>, TError = TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): DefinedUseQueryResult & { queryKey: DataTag } export function useGetLogs>, TError = ErrorResponse>( @@ -4088,11 +3021,11 @@ export function useGetLogs>, TError = TError, Awaited> > , 'initialData' - >, fetch?: RequestInit} + >, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } export function useGetLogs>, TError = ErrorResponse>( - params?: GetLogsParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetLogsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } /** @@ -4100,7 +3033,7 @@ export function useGetLogs>, TError = */ export function useGetLogs>, TError = ErrorResponse>( - params?: GetLogsParams, options?: { query?:Partial>, TError, TData>>, fetch?: RequestInit} + params?: GetLogsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} , queryClient?: QueryClient ): UseQueryResult & { queryKey: DataTag } { diff --git a/frontend/src/hooks/useAuthForm.ts b/frontend/src/hooks/useAuthForm.ts index 84e7a0c..e97ac8f 100644 --- a/frontend/src/hooks/useAuthForm.ts +++ b/frontend/src/hooks/useAuthForm.ts @@ -3,7 +3,6 @@ import { useGetInfo } from '../generated/anthoLumeAPIV1'; import { useAuth } from '../auth/AuthContext'; import { useToasts } from '../components/ToastContext'; import { getErrorMessage } from '../utils/errors'; -import { dataForStatus } from '../utils/apiResponses'; export interface UseAuthFormResult { username: string; @@ -29,7 +28,7 @@ export function useAuthForm(mode: 'login' | 'register'): UseAuthFormResult { const { data: infoData, isLoading: isLoadingInfo } = useGetInfo({ query: { staleTime: Infinity }, }); - const registrationEnabled = dataForStatus(infoData, 200)?.registration_enabled ?? false; + const registrationEnabled = infoData?.registration_enabled ?? false; const submit = useCallback( async (e: SyntheticEvent) => { diff --git a/frontend/src/hooks/useEpubReader.ts b/frontend/src/hooks/useEpubReader.ts index 109bdc4..726d635 100644 --- a/frontend/src/hooks/useEpubReader.ts +++ b/frontend/src/hooks/useEpubReader.ts @@ -5,7 +5,7 @@ import type { UpdateProgressRequest } from '../generated/model/updateProgressReq import { EBookReader, type ReaderStats, type ReaderTocItem } from '../lib/reader/EBookReader'; import type { ReaderColorScheme, ReaderFontFamily } from '../utils/localSettings'; import { useToasts } from '../components/ToastContext'; -import { getErrorMessage, getResponseError } from '../utils/errors'; +import { getErrorMessage } from '../utils/errors'; interface UseEpubReaderOptions { documentId: string; @@ -96,11 +96,7 @@ export function useEpubReader({ // Swallow Save Failures - Transient progress-save errors must not take down the reader // (they previously routed to onError, which hides the whole book behind an error overlay). try { - const response = await updateProgress(payload); - const message = getResponseError(response); - if (message) { - showError(`Failed to save progress: ${message}`); - } + await updateProgress(payload); } catch (err) { showError(`Failed to save progress: ${getErrorMessage(err)}`); } @@ -108,11 +104,7 @@ export function useEpubReader({ const saveActivity = async (payload: CreateActivityRequest) => { try { - const response = await createActivity(payload); - const message = getResponseError(response); - if (message) { - showError(`Failed to save activity: ${message}`); - } + await createActivity(payload); } catch (err) { showError(`Failed to save activity: ${getErrorMessage(err)}`); } diff --git a/frontend/src/hooks/useMutationWithToast.ts b/frontend/src/hooks/useMutationWithToast.ts index 081e756..482dfb4 100644 --- a/frontend/src/hooks/useMutationWithToast.ts +++ b/frontend/src/hooks/useMutationWithToast.ts @@ -1,5 +1,5 @@ import { useToasts } from '../components/ToastContext'; -import { getErrorMessage, getResponseError, type ApiResponseLike } from '../utils/errors'; +import { getErrorMessage } from '../utils/errors'; interface ToastMutationOptions { success: string; @@ -9,19 +9,15 @@ interface ToastMutationOptions { /** * Builds `{ onSuccess, onError }` for a generated mutation's `.mutate(vars, options)` call, - * centralizing the shared "toast success / toast error / treat non-2xx as failure" pattern. + * centralizing the shared "toast success / toast error" pattern. The generated client throws on + * non-2xx, so success and failure map cleanly onto React Query's onSuccess/onError. */ export function useMutationWithToast() { const { showInfo, showError } = useToasts(); return function toastMutationOptions({ success, error, onSuccess }: ToastMutationOptions) { return { - onSuccess: (response: ApiResponseLike) => { - const message = getResponseError(response); - if (message) { - showError(`${error}: ${message}`); - return; - } + onSuccess: () => { onSuccess?.(); showInfo(success); }, @@ -33,29 +29,24 @@ export function useMutationWithToast() { interface RunToastMutationOptions { error: string; success?: string; - onSuccess?: (response: T) => void; + onSuccess?: (result: T) => void; } /** * Imperative sibling of `useMutationWithToast` for flows that must `await` a result (e.g. keep an - * editor open on failure). Runs the action, treats non-2xx as failure, toasts accordingly, and - * resolves to `true` only on success. + * editor open on failure). Runs the action, toasts on success/failure, and resolves to `true` only + * when the action succeeds. */ export function useToastMutation() { const { showInfo, showError } = useToasts(); - return async function runWithToast( + return async function runWithToast( action: () => Promise, { error, success, onSuccess }: RunToastMutationOptions ): Promise { try { - const response = await action(); - const message = getResponseError(response); - if (message) { - showError(`${error}: ${message}`); - return false; - } - onSuccess?.(response); + const result = await action(); + onSuccess?.(result); if (success) { showInfo(success); } diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index f6cb638..1c85316 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ToastProvider } from './components/ToastContext'; import { ThemeProvider, initializeThemeMode } from './theme/ThemeProvider'; import App from './App'; +import { ApiError } from './utils/apiFetch'; import './index.css'; initializeThemeMode(); @@ -13,7 +14,14 @@ const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60 * 5, - retry: 1, + // 4xx responses are deterministic (e.g. /auth/me 401 when logged out); only retry transient + // network/5xx failures. + retry: (failureCount, error) => { + if (error instanceof ApiError && error.status < 500) { + return false; + } + return failureCount < 1; + }, }, mutations: { retry: 0, diff --git a/frontend/src/pages/ActivityPage.tsx b/frontend/src/pages/ActivityPage.tsx index 1b6736a..17d45de 100644 --- a/frontend/src/pages/ActivityPage.tsx +++ b/frontend/src/pages/ActivityPage.tsx @@ -6,7 +6,6 @@ import { Table, type Column } from '../components/Table'; import { documentColumn } from '../components/documentColumn'; import { usePaginatedList } from '../hooks/usePaginatedList'; import { formatDuration, formatDateTime } from '../utils/formatters'; -import { dataForStatus } from '../utils/apiResponses'; const ACTIVITY_PAGE_SIZE = 25; @@ -22,7 +21,7 @@ export default function ActivityPage() { page, limit, }); - const response = dataForStatus(data, 200); + const response = data; const activities = response?.activities ?? []; const columns: Column[] = [ diff --git a/frontend/src/pages/AdminImportPage.tsx b/frontend/src/pages/AdminImportPage.tsx index 75dbf4d..3c02152 100644 --- a/frontend/src/pages/AdminImportPage.tsx +++ b/frontend/src/pages/AdminImportPage.tsx @@ -6,7 +6,6 @@ import type { DirectoryItem } from '../generated/model'; import { Button } from '../components/Button'; import { FolderOpenIcon } from '../icons'; import { useMutationWithToast } from '../hooks/useMutationWithToast'; -import { dataForStatus } from '../utils/apiResponses'; export default function AdminImportPage() { const [currentPath, setCurrentPath] = useState(''); @@ -21,7 +20,7 @@ export default function AdminImportPage() { const postImport = usePostImport(); - const directoryResponse = dataForStatus(directoryData, 200); + const directoryResponse = directoryData; const directories = directoryResponse?.items ?? []; const currentPathDisplay = directoryResponse?.current_path ?? currentPath ?? '/data'; diff --git a/frontend/src/pages/AdminImportResultsPage.tsx b/frontend/src/pages/AdminImportResultsPage.tsx index 5734f2e..85ca4b2 100644 --- a/frontend/src/pages/AdminImportResultsPage.tsx +++ b/frontend/src/pages/AdminImportResultsPage.tsx @@ -2,11 +2,10 @@ import { useGetImportResults } from '../generated/anthoLumeAPIV1'; import { Table, type Column } from '../components'; import type { ImportResult } from '../generated/model'; import { Link } from 'react-router-dom'; -import { dataForStatus } from '../utils/apiResponses'; export default function AdminImportResultsPage() { const { data: resultsData, isLoading } = useGetImportResults(); - const results = dataForStatus(resultsData, 200)?.results ?? []; + const results = resultsData?.results ?? []; const columns: Column[] = [ { diff --git a/frontend/src/pages/AdminLogsPage.tsx b/frontend/src/pages/AdminLogsPage.tsx index 84868a2..52fae06 100644 --- a/frontend/src/pages/AdminLogsPage.tsx +++ b/frontend/src/pages/AdminLogsPage.tsx @@ -3,14 +3,13 @@ import { useGetLogs } from '../generated/anthoLumeAPIV1'; import { Button, LoadingState, TextInput, IconInput } from '../components'; import { useDebouncedState } from '../hooks/useDebouncedState'; import { Search2Icon } from '../icons'; -import { dataForStatus } from '../utils/apiResponses'; export default function AdminLogsPage() { const [filter, setFilter, activeFilter, flushFilter] = useDebouncedState('', 300); const { data: logsData, isLoading } = useGetLogs(activeFilter ? { filter: activeFilter } : {}); - const logs = dataForStatus(logsData, 200)?.logs ?? []; + const logs = logsData?.logs ?? []; const handleFilterSubmit = (e: SyntheticEvent) => { e.preventDefault(); diff --git a/frontend/src/pages/AdminPage.tsx b/frontend/src/pages/AdminPage.tsx index f9c3728..fead197 100644 --- a/frontend/src/pages/AdminPage.tsx +++ b/frontend/src/pages/AdminPage.tsx @@ -3,7 +3,7 @@ import { usePostAdminAction } from '../generated/anthoLumeAPIV1'; import { Button } from '../components/Button'; import { useToasts } from '../components/ToastContext'; import { useMutationWithToast } from '../hooks/useMutationWithToast'; -import { getErrorMessage, getResponseError } from '../utils/errors'; +import { getErrorMessage } from '../utils/errors'; import { streamResponseToFile, backupFilename } from '../utils/download'; interface BackupTypes { @@ -65,23 +65,13 @@ export default function AdminPage() { const toastId = showInfo('Restore started', 0); try { - const response = await postAdminAction.mutateAsync({ + await postAdminAction.mutateAsync({ data: { action: 'RESTORE', restore_file: restoreFile, }, }); - const message = getResponseError(response); - if (message) { - updateToast(toastId, { - type: 'error', - message: `Restore failed: ${message}`, - duration: 5000, - }); - return; - } - updateToast(toastId, { message: 'Restore completed successfully', duration: 5000 }); } catch (error) { updateToast(toastId, { diff --git a/frontend/src/pages/AdminUsersPage.tsx b/frontend/src/pages/AdminUsersPage.tsx index 1db1e52..ba368cf 100644 --- a/frontend/src/pages/AdminUsersPage.tsx +++ b/frontend/src/pages/AdminUsersPage.tsx @@ -8,7 +8,6 @@ import { AddIcon, DeleteIcon } from '../icons'; import { useMutationWithToast } from '../hooks/useMutationWithToast'; import { useToasts } from '../components/ToastContext'; import { formatDate } from '../utils/formatters'; -import { dataForStatus } from '../utils/apiResponses'; interface AddUserFormProps { onCreate: (_username: string, _password: string, _isAdmin: boolean) => void; @@ -117,7 +116,7 @@ export default function AdminUsersPage() { const [showAddForm, setShowAddForm] = useState(false); const [resetUserId, setResetUserId] = useState(null); - const users = dataForStatus(usersData, 200)?.users ?? []; + const users = usersData?.users ?? []; const handleCreateUser = (username: string, password: string, isAdmin: boolean) => { if (!username || !password) { diff --git a/frontend/src/pages/DocumentPage.tsx b/frontend/src/pages/DocumentPage.tsx index 2b98528..70dde01 100644 --- a/frontend/src/pages/DocumentPage.tsx +++ b/frontend/src/pages/DocumentPage.tsx @@ -8,7 +8,6 @@ import { } from '../generated/anthoLumeAPIV1'; import type { EditDocumentBody } from '../generated/model'; import { formatDuration } from '../utils/formatters'; -import { dataForStatus } from '../utils/apiResponses'; import { useToastMutation } from '../hooks/useMutationWithToast'; import { ActivityIcon, DownloadIcon, EditIcon, InfoIcon, CloseIcon, CheckIcon } from '../icons'; import { Field, FieldLabel, FieldValue, FieldActions, LoadingState } from '../components'; @@ -122,7 +121,7 @@ export default function DocumentPage() { return ; } - const doc = dataForStatus(docData, 200)?.document; + const doc = docData?.document; if (!doc) { return
Document not found
; diff --git a/frontend/src/pages/DocumentsPage.tsx b/frontend/src/pages/DocumentsPage.tsx index 156fc36..5e88f31 100644 --- a/frontend/src/pages/DocumentsPage.tsx +++ b/frontend/src/pages/DocumentsPage.tsx @@ -11,7 +11,6 @@ import { cn } from '../utils/cn'; import { useDebouncedState } from '../hooks/useDebouncedState'; import { usePaginatedList } from '../hooks/usePaginatedList'; import { useLocalSetting, type DocumentsViewMode } from '../utils/localSettings'; -import { dataForStatus } from '../utils/apiResponses'; const DOCUMENTS_PAGE_SIZE = 9; @@ -117,7 +116,7 @@ export default function DocumentsPage() { const { data, isLoading, refetch } = useGetDocuments({ page, limit, search: debouncedSearch }); const createMutation = useCreateDocument(); - const documentsResponse = dataForStatus(data, 200); + const documentsResponse = data; const docs = documentsResponse?.documents; const previousPage = documentsResponse?.previous_page; const nextPage = documentsResponse?.next_page; diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 2516a0e..946a122 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -5,7 +5,6 @@ import { useGetHome } from '../generated/anthoLumeAPIV1'; import type { LeaderboardData, LeaderboardEntry, UserStreak } from '../generated/model'; import ReadingHistoryGraph from '../components/ReadingHistoryGraph'; import { formatNumber, formatDuration } from '../utils/formatters'; -import { dataForStatus } from '../utils/apiResponses'; interface InfoCardProps { title: string; @@ -156,7 +155,7 @@ function LeaderboardCard({ name, data }: LeaderboardCardProps) { export default function HomePage() { const { data: homeData, isLoading: homeLoading } = useGetHome(); - const homeResponse = dataForStatus(homeData, 200); + const homeResponse = homeData; const dbInfo = homeResponse?.database_info; const streaks = homeResponse?.streaks?.streaks; const graphData = homeResponse?.graph_data?.graph_data; diff --git a/frontend/src/pages/LoginPage.test.tsx b/frontend/src/pages/LoginPage.test.tsx index aa6def8..c28f80f 100644 --- a/frontend/src/pages/LoginPage.test.tsx +++ b/frontend/src/pages/LoginPage.test.tsx @@ -57,10 +57,7 @@ describe('LoginPage', () => { mockedUseGetInfo.mockReturnValue({ data: { - status: 200, - data: { - registration_enabled: false, - }, + registration_enabled: false, }, } as ReturnType); }); @@ -155,10 +152,7 @@ describe('LoginPage', () => { it('shows the registration link only when registration is enabled', () => { mockedUseGetInfo.mockReturnValue({ data: { - status: 200, - data: { - registration_enabled: true, - }, + registration_enabled: true, }, } as ReturnType); @@ -172,10 +166,7 @@ describe('LoginPage', () => { mockedUseGetInfo.mockReturnValue({ data: { - status: 200, - data: { - registration_enabled: false, - }, + registration_enabled: false, }, } as ReturnType); diff --git a/frontend/src/pages/ProgressPage.tsx b/frontend/src/pages/ProgressPage.tsx index 541b045..56ab47f 100644 --- a/frontend/src/pages/ProgressPage.tsx +++ b/frontend/src/pages/ProgressPage.tsx @@ -5,7 +5,6 @@ import { Table, type Column } from '../components/Table'; import { documentColumn } from '../components/documentColumn'; import { usePaginatedList } from '../hooks/usePaginatedList'; import { formatDate } from '../utils/formatters'; -import { dataForStatus } from '../utils/apiResponses'; const PROGRESS_PAGE_SIZE = 15; @@ -13,7 +12,7 @@ export default function ProgressPage() { const { page, setPage } = usePaginatedList(); const limit = PROGRESS_PAGE_SIZE; const { data, isLoading } = useGetProgressList({ page, limit }); - const response = dataForStatus(data, 200); + const response = data; const progress = response?.progress ?? []; const columns: Column[] = [ diff --git a/frontend/src/pages/ReaderPage.tsx b/frontend/src/pages/ReaderPage.tsx index d9f481f..9fa5e53 100644 --- a/frontend/src/pages/ReaderPage.tsx +++ b/frontend/src/pages/ReaderPage.tsx @@ -13,7 +13,6 @@ import { useLocalSetting, } from '../utils/localSettings'; import { useEpubReader } from '../hooks/useEpubReader'; -import { dataForStatus } from '../utils/apiResponses'; const READER_SEGMENT_BUTTON = 'rounded border px-2 py-1.5 text-xs sm:text-sm'; const READER_SEGMENT_ACTIVE = 'border-primary-500 bg-primary-500/10 text-content'; @@ -40,8 +39,8 @@ export default function ReaderPage() { enabled: Boolean(id), }, }); - const doc = dataForStatus(documentResponse, 200)?.document; - const progress = dataForStatus(progressResponse, 200)?.progress; + const doc = documentResponse?.document; + const progress = progressResponse?.progress; const deviceId = defaultDeviceId; const deviceName = defaultDeviceName; diff --git a/frontend/src/pages/RegisterPage.test.tsx b/frontend/src/pages/RegisterPage.test.tsx index d54b1d8..5e4e03f 100644 --- a/frontend/src/pages/RegisterPage.test.tsx +++ b/frontend/src/pages/RegisterPage.test.tsx @@ -57,10 +57,7 @@ describe('RegisterPage', () => { mockedUseGetInfo.mockReturnValue({ data: { - status: 200, - data: { - registration_enabled: true, - }, + registration_enabled: true, }, isLoading: false, } as ReturnType); @@ -156,10 +153,7 @@ describe('RegisterPage', () => { it('redirects to login when registration is disabled', async () => { mockedUseGetInfo.mockReturnValue({ data: { - status: 200, - data: { - registration_enabled: false, - }, + registration_enabled: false, }, isLoading: false, } as ReturnType); @@ -178,10 +172,7 @@ describe('RegisterPage', () => { it('disables the form when registration is disabled', () => { mockedUseGetInfo.mockReturnValue({ data: { - status: 200, - data: { - registration_enabled: false, - }, + registration_enabled: false, }, isLoading: false, } as ReturnType); diff --git a/frontend/src/pages/SearchPage.test.tsx b/frontend/src/pages/SearchPage.test.tsx index 601fbcb..c5de1a3 100644 --- a/frontend/src/pages/SearchPage.test.tsx +++ b/frontend/src/pages/SearchPage.test.tsx @@ -15,10 +15,7 @@ describe('SearchPage', () => { vi.clearAllMocks(); mockedUseGetSearch.mockReturnValue({ data: { - status: 200, - data: { - results: [], - }, + results: [], }, isLoading: false, } as ReturnType); @@ -67,19 +64,16 @@ describe('SearchPage', () => { it('renders search results from the generated hook response', () => { mockedUseGetSearch.mockReturnValue({ data: { - status: 200, - data: { - results: [ - { - id: 'doc-1', - author: 'Ursula Le Guin', - title: 'A Wizard of Earthsea', - series: 'Earthsea', - file_type: 'epub', - file_size: '1 MB', - }, - ], - }, + results: [ + { + id: 'doc-1', + author: 'Ursula Le Guin', + title: 'A Wizard of Earthsea', + series: 'Earthsea', + file_type: 'epub', + file_size: '1 MB', + }, + ], }, isLoading: false, } as ReturnType); diff --git a/frontend/src/pages/SearchPage.tsx b/frontend/src/pages/SearchPage.tsx index a180aa9..a697036 100644 --- a/frontend/src/pages/SearchPage.tsx +++ b/frontend/src/pages/SearchPage.tsx @@ -6,7 +6,6 @@ import { Button, Table, type Column, TextInput, IconInput } from '../components' import { inputClassName } from '../components/TextInput'; import { useDebouncedState } from '../hooks/useDebouncedState'; import { Search2Icon, BookIcon } from '../icons'; -import { dataForStatus } from '../utils/apiResponses'; const searchColumns: Column[] = [ { @@ -87,7 +86,7 @@ export default function SearchPage() { }, } ); - const results = dataForStatus(data, 200)?.results ?? []; + const results = data?.results ?? []; const handleSubmit = (e: SyntheticEvent) => { e.preventDefault(); diff --git a/frontend/src/pages/SettingsPage.tsx b/frontend/src/pages/SettingsPage.tsx index b151749..60d8072 100644 --- a/frontend/src/pages/SettingsPage.tsx +++ b/frontend/src/pages/SettingsPage.tsx @@ -9,7 +9,6 @@ import { useMutationWithToast, useToastMutation } from '../hooks/useMutationWith import { useTheme } from '../theme/ThemeProvider'; import type { ThemeMode } from '../utils/localSettings'; import { formatDateTime } from '../utils/formatters'; -import { dataForStatus } from '../utils/apiResponses'; const deviceColumns: Column[] = [ { @@ -192,7 +191,7 @@ function DevicesSection({ devices }: { devices: Device[] }) { export default function SettingsPage() { const { data, isLoading } = useGetSettings(); const updateSettings = useUpdateSettings(); - const settingsData = dataForStatus(data, 200); + const settingsData = data; const { showError } = useToasts(); const toastMutationOptions = useMutationWithToast(); const runWithToast = useToastMutation(); diff --git a/frontend/src/utils/apiFetch.ts b/frontend/src/utils/apiFetch.ts new file mode 100644 index 0000000..bb09ee7 --- /dev/null +++ b/frontend/src/utils/apiFetch.ts @@ -0,0 +1,55 @@ +import type { ErrorResponse } from '../generated/model'; + +// Thrown by the generated API client for any non-2xx response. `body` is the parsed error payload +// (the API's ErrorResponse for documented failures); `message` is the server-provided message when +// present, so `error.message` is always display-ready. +export class ApiError extends Error { + readonly status: number; + readonly body: TBody; + + constructor(status: number, body: TBody, message: string) { + super(message); + this.name = 'ApiError'; + this.status = status; + this.body = body; + } +} + +const EMPTY_BODY_STATUSES = new Set([204, 205, 304]); + +function messageFromBody(body: unknown, fallback: string): string { + if (body && typeof body === 'object' && 'message' in body) { + const { message } = body as { message?: unknown }; + if (typeof message === 'string' && message.trim() !== '') { + return message; + } + } + return fallback; +} + +async function parseBody(response: Response): Promise { + if (EMPTY_BODY_STATUSES.has(response.status)) { + return undefined; + } + + const raw = await response.text(); + if (!raw) { + return undefined; + } + + const contentType = response.headers.get('content-type') ?? ''; + return contentType.includes('application/json') ? JSON.parse(raw) : raw; +} + +// Orval mutator - The generated client calls this for every request. Returns the parsed success +// body directly and throws ApiError on non-2xx, so React Query surfaces failures via isError/onError. +export async function apiFetch(url: string, options?: RequestInit): Promise { + const response = await fetch(url, options); + const body = await parseBody(response); + + if (!response.ok) { + throw new ApiError(response.status, body, messageFromBody(body, response.statusText || 'Request failed')); + } + + return body as T; +} diff --git a/frontend/src/utils/apiResponses.ts b/frontend/src/utils/apiResponses.ts deleted file mode 100644 index c22117c..0000000 --- a/frontend/src/utils/apiResponses.ts +++ /dev/null @@ -1,13 +0,0 @@ -type ApiResponse = { - status: number; - data: unknown; -}; - -export function dataForStatus( - response: TResponse | undefined, - status: TStatus -): Extract['data'] | undefined { - return response?.status === status - ? (response.data as Extract['data']) - : undefined; -} diff --git a/frontend/src/utils/errors.ts b/frontend/src/utils/errors.ts index 32cb4ca..c62f25f 100644 --- a/frontend/src/utils/errors.ts +++ b/frontend/src/utils/errors.ts @@ -1,3 +1,6 @@ +// Extracts a display message from a caught error. The generated client throws ApiError (an Error +// subclass whose `message` is the server-provided message), so this covers both API and unexpected +// failures in a single catch path. export function getErrorMessage(error: unknown, fallback = 'Unknown error'): string { if (error instanceof Error && error.message) { return error.message; @@ -12,20 +15,3 @@ export function getErrorMessage(error: unknown, fallback = 'Unknown error'): str return fallback; } - -export interface ApiResponseLike { - status: number; - data: unknown; -} - -/** - * Non-2xx Check - The generated client resolves non-2xx instead of throwing; this returns the - * extracted error message for failure responses, or null for success (2xx) so callers can branch. - */ -export function getResponseError(response: ApiResponseLike): string | null { - if (response.status >= 200 && response.status < 300) { - return null; - } - - return getErrorMessage(response.data, 'Request failed'); -}