mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Query rework part1
This commit is contained in:
parent
32ecf25321
commit
7a4e203cdd
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kyoo - A portable and vast media library solution.
|
|
||||||
* Copyright (c) Kyoo.
|
|
||||||
*
|
|
||||||
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
|
||||||
*
|
|
||||||
* Kyoo is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* Kyoo is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The list of errors that where made in the request.
|
|
||||||
*/
|
|
||||||
export interface KyooErrors {
|
|
||||||
/**
|
|
||||||
* The list of errors that where made in the request.
|
|
||||||
*
|
|
||||||
* @example `["InvalidFilter: no field 'startYear' on a collection"]`
|
|
||||||
*/
|
|
||||||
errors: string[];
|
|
||||||
|
|
||||||
status?: number | "aborted" | "parse" | "json";
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kyoo - A portable and vast media library solution.
|
|
||||||
* Copyright (c) Kyoo.
|
|
||||||
*
|
|
||||||
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
|
||||||
*
|
|
||||||
* Kyoo is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* Kyoo is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A page of resource that contains information about the pagination of resources.
|
|
||||||
*/
|
|
||||||
export interface Page<T> {
|
|
||||||
/**
|
|
||||||
* The link of the current page.
|
|
||||||
*
|
|
||||||
* @format uri
|
|
||||||
*/
|
|
||||||
this: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The link of the first page.
|
|
||||||
*
|
|
||||||
* @format uri
|
|
||||||
*/
|
|
||||||
first: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The link of the next page.
|
|
||||||
*
|
|
||||||
* @format uri
|
|
||||||
*/
|
|
||||||
next: string | null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of items in the current page.
|
|
||||||
*/
|
|
||||||
count: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The list of items in the page.
|
|
||||||
*/
|
|
||||||
items: T[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Paged = <Item>(item: z.ZodType<Item>): z.ZodSchema<Page<Item>> =>
|
|
||||||
z.object({
|
|
||||||
this: z.string(),
|
|
||||||
first: z.string(),
|
|
||||||
next: z.string().nullable(),
|
|
||||||
count: z.number(),
|
|
||||||
items: z.array(item),
|
|
||||||
});
|
|
5
front/src/models/kyoo-error.ts
Normal file
5
front/src/models/kyoo-error.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface KyooError {
|
||||||
|
status: number | string;
|
||||||
|
message: string;
|
||||||
|
details?: any;
|
||||||
|
}
|
46
front/src/models/page.ts
Normal file
46
front/src/models/page.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A page of resource that contains information about the pagination of resources.
|
||||||
|
*/
|
||||||
|
export interface Page<T> {
|
||||||
|
/**
|
||||||
|
* The link of the current page.
|
||||||
|
*
|
||||||
|
* @format uri
|
||||||
|
*/
|
||||||
|
this: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The link of the first page.
|
||||||
|
*
|
||||||
|
* @format uri
|
||||||
|
*/
|
||||||
|
first: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The link of the next page.
|
||||||
|
*
|
||||||
|
* @format uri
|
||||||
|
*/
|
||||||
|
next: string | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of items in the current page.
|
||||||
|
*/
|
||||||
|
count: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of items in the page.
|
||||||
|
*/
|
||||||
|
items: T[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Paged = <Item>(item: z.ZodType<Item>): z.ZodSchema<Page<Item>> =>
|
||||||
|
z.object({
|
||||||
|
this: z.string(),
|
||||||
|
first: z.string(),
|
||||||
|
next: z.string().nullable(),
|
||||||
|
count: z.number(),
|
||||||
|
items: z.array(item),
|
||||||
|
});
|
@ -1,23 +1,3 @@
|
|||||||
/*
|
|
||||||
* Kyoo - A portable and vast media library solution.
|
|
||||||
* Copyright (c) Kyoo.
|
|
||||||
*
|
|
||||||
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
|
||||||
*
|
|
||||||
* Kyoo is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* Kyoo is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
QueryClient,
|
QueryClient,
|
||||||
type QueryFunctionContext,
|
type QueryFunctionContext,
|
||||||
@ -26,9 +6,8 @@ import {
|
|||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
import type { ComponentType, ReactElement } from "react";
|
import type { ComponentType, ReactElement } from "react";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
import { getCurrentApiUrl } from ".";
|
import type { KyooError } from "./kyoo-error";
|
||||||
import type { KyooErrors } from "./kyoo-errors";
|
// import { getToken, getTokenWJ } from "./login";
|
||||||
import { getToken, getTokenWJ } from "./login";
|
|
||||||
import { type Page, Paged } from "./page";
|
import { type Page, Paged } from "./page";
|
||||||
|
|
||||||
export let lastUsedUrl: string = null!;
|
export let lastUsedUrl: string = null!;
|
||||||
@ -89,12 +68,12 @@ export const queryFn = async <Parser extends z.ZodTypeAny>(
|
|||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (typeof e === "object" && e && "name" in e && e.name === "AbortError")
|
if (typeof e === "object" && e && "name" in e && e.name === "AbortError")
|
||||||
throw { errors: ["Aborted"] } as KyooErrors;
|
throw { message: "Aborted", status: "aborted" } as KyooError;
|
||||||
console.log("Fetch error", e, path);
|
console.log("Fetch error", e, path);
|
||||||
throw { errors: ["Could not reach Kyoo's server."], status: "aborted" } as KyooErrors;
|
throw { message: "Could not reach Kyoo's server.", status: "aborted" } as KyooError;
|
||||||
}
|
}
|
||||||
if (resp.status === 404) {
|
if (resp.status === 404) {
|
||||||
throw { errors: ["Resource not found."], status: 404 } as KyooErrors;
|
throw { message: "Resource not found.", status: 404 } as KyooError;
|
||||||
}
|
}
|
||||||
// If we got a forbidden, try to refresh the token
|
// If we got a forbidden, try to refresh the token
|
||||||
// if we got a token as an argument, it either means we already retried or we go one provided that's fresh
|
// if we got a token as an argument, it either means we already retried or we go one provided that's fresh
|
||||||
@ -110,7 +89,7 @@ export const queryFn = async <Parser extends z.ZodTypeAny>(
|
|||||||
try {
|
try {
|
||||||
data = JSON.parse(error);
|
data = JSON.parse(error);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
data = { errors: [error] } as KyooErrors;
|
data = { message: error } as KyooError;
|
||||||
}
|
}
|
||||||
data.status = resp.status;
|
data.status = resp.status;
|
||||||
console.trace(
|
console.trace(
|
||||||
@ -120,7 +99,7 @@ export const queryFn = async <Parser extends z.ZodTypeAny>(
|
|||||||
data,
|
data,
|
||||||
resp.status,
|
resp.status,
|
||||||
);
|
);
|
||||||
throw data as KyooErrors;
|
throw data as KyooError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.status === 204) return null;
|
if (resp.status === 204) return null;
|
||||||
@ -132,18 +111,17 @@ export const queryFn = async <Parser extends z.ZodTypeAny>(
|
|||||||
data = await resp.json();
|
data = await resp.json();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Invalid json from kyoo", e);
|
console.error("Invalid json from kyoo", e);
|
||||||
throw { errors: ["Invalid response from kyoo"], status: "json" };
|
throw { message: "Invalid response from kyoo", status: "json" } as KyooError;
|
||||||
}
|
}
|
||||||
if (!type) return data;
|
if (!type) return data;
|
||||||
const parsed = await type.safeParseAsync(data);
|
const parsed = await type.safeParseAsync(data);
|
||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
console.log("Path: ", path, " Response: ", resp.status, " Parse error: ", parsed.error);
|
console.log("Path: ", path, " Response: ", resp.status, " Parse error: ", parsed.error);
|
||||||
throw {
|
throw {
|
||||||
errors: [
|
|
||||||
"Invalid response from kyoo. Possible version mismatch between the server and the application.",
|
|
||||||
],
|
|
||||||
status: "parse",
|
status: "parse",
|
||||||
} as KyooErrors;
|
message:
|
||||||
|
"Invalid response from kyoo. Possible version mismatch between the server and the application.",
|
||||||
|
} as KyooError;
|
||||||
}
|
}
|
||||||
return parsed.data;
|
return parsed.data;
|
||||||
};
|
};
|
||||||
@ -218,7 +196,7 @@ export const toQueryKey = (query: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useFetch = <Data,>(query: QueryIdentifier<Data>) => {
|
export const useFetch = <Data,>(query: QueryIdentifier<Data>) => {
|
||||||
return useQuery<Data, KyooErrors>({
|
return useQuery<Data, KyooError>({
|
||||||
queryKey: toQueryKey(query),
|
queryKey: toQueryKey(query),
|
||||||
queryFn: (ctx) =>
|
queryFn: (ctx) =>
|
||||||
queryFn(
|
queryFn(
|
||||||
@ -235,7 +213,7 @@ export const useFetch = <Data,>(query: QueryIdentifier<Data>) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useInfiniteFetch = <Data, Ret>(query: QueryIdentifier<Data, Ret>) => {
|
export const useInfiniteFetch = <Data, Ret>(query: QueryIdentifier<Data, Ret>) => {
|
||||||
const ret = useInfiniteQuery<Page<Data>, KyooErrors>({
|
const ret = useInfiniteQuery<Page<Data>, KyooError>({
|
||||||
queryKey: toQueryKey(query),
|
queryKey: toQueryKey(query),
|
||||||
queryFn: (ctx) =>
|
queryFn: (ctx) =>
|
||||||
queryFn(
|
queryFn(
|
||||||
@ -258,10 +236,6 @@ export const useInfiniteFetch = <Data, Ret>(query: QueryIdentifier<Data, Ret>) =
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const fetchQuery = async (queries: QueryIdentifier[], authToken?: string | null) => {
|
export const fetchQuery = async (queries: QueryIdentifier[], authToken?: string | null) => {
|
||||||
// we can't put this check in a function because we want build time optimizations
|
|
||||||
// see https://github.com/vercel/next.js/issues/5354 for details
|
|
||||||
if (typeof window !== "undefined") return null;
|
|
||||||
|
|
||||||
const client = createQueryClient();
|
const client = createQueryClient();
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
queries.map((query) => {
|
queries.map((query) => {
|
@ -1,12 +1,11 @@
|
|||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { ComponentType, type ReactNode, useState } from "react";
|
import { type ReactNode, useState } from "react";
|
||||||
|
import { createQueryClient } from "~/models/query";
|
||||||
// import { useUserTheme } from "@kyoo/models";
|
// import { useUserTheme } from "@kyoo/models";
|
||||||
// import { createQueryClient } from "@kyoo/models";
|
|
||||||
import { ThemeSelector } from "~/primitives/theme";
|
import { ThemeSelector } from "~/primitives/theme";
|
||||||
|
|
||||||
const QueryProvider = ({ children }: { children: ReactNode }) => {
|
const QueryProvider = ({ children }: { children: ReactNode }) => {
|
||||||
// const [queryClient] = useState(() => createQueryClient());
|
const [queryClient] = useState(() => createQueryClient());
|
||||||
const [queryClient] = useState(() => new QueryClient({}));
|
|
||||||
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user