mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Fixup ssr fetch
This commit is contained in:
parent
13cc334785
commit
cd519998a7
@ -1,6 +1,5 @@
|
|||||||
import { HydrationBoundary } from "@tanstack/react-query";
|
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
import { Slot, getServerData } from "one";
|
import { Slot } from "one";
|
||||||
import { useServerHeadInsertion } from "one";
|
import { useServerHeadInsertion } from "one";
|
||||||
import { StyleRegistryProvider, createStyleRegistry, useTheme } from "yoshiki/web";
|
import { StyleRegistryProvider, createStyleRegistry, useTheme } from "yoshiki/web";
|
||||||
import { Providers } from "~/providers";
|
import { Providers } from "~/providers";
|
||||||
@ -63,8 +62,6 @@ export default function Layout() {
|
|||||||
const registry = createStyleRegistry();
|
const registry = createStyleRegistry();
|
||||||
useServerHeadInsertion(() => registry.flushToComponent());
|
useServerHeadInsertion(() => registry.flushToComponent());
|
||||||
|
|
||||||
const queryState = getServerData("queryState");
|
|
||||||
|
|
||||||
// TODO: change this lang attr
|
// TODO: change this lang attr
|
||||||
return (
|
return (
|
||||||
<html lang="en-US">
|
<html lang="en-US">
|
||||||
@ -82,12 +79,10 @@ export default function Layout() {
|
|||||||
|
|
||||||
<body className="hoverEnabled">
|
<body className="hoverEnabled">
|
||||||
<StyleRegistryProvider registry={registry}>
|
<StyleRegistryProvider registry={registry}>
|
||||||
<HydrationBoundary state={queryState}>
|
<Providers>
|
||||||
<Providers>
|
<Slot />
|
||||||
<Slot />
|
<ReactQueryDevtools initialIsOpen={false} />
|
||||||
<ReactQueryDevtools initialIsOpen={false} />
|
</Providers>
|
||||||
</Providers>
|
|
||||||
</HydrationBoundary>
|
|
||||||
</StyleRegistryProvider>
|
</StyleRegistryProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
7
front/app/_middleware.ts
Normal file
7
front/app/_middleware.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { createMiddleware, setServerData } from "one";
|
||||||
|
|
||||||
|
export default createMiddleware(({ request, next }) => {
|
||||||
|
console.log(request);
|
||||||
|
setServerData("cookies", request.headers.get("Cookies") ?? "");
|
||||||
|
return next();
|
||||||
|
});
|
@ -8,12 +8,14 @@ import { removeAccounts, updateAccount } from "./account-store";
|
|||||||
import { useSetError } from "./error-provider";
|
import { useSetError } from "./error-provider";
|
||||||
import { useStoreValue } from "./settings";
|
import { useStoreValue } from "./settings";
|
||||||
|
|
||||||
|
export const ssrApiUrl = process.env.KYOO_URL ?? "http://back/api";
|
||||||
|
|
||||||
export const AccountContext = createContext<{
|
export const AccountContext = createContext<{
|
||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
authToken: Token | null;
|
authToken: Token | null;
|
||||||
selectedAccount?: Account;
|
selectedAccount: Account | null;
|
||||||
accounts: (Account & { select: () => void; remove: () => void })[];
|
accounts: (Account & { select: () => void; remove: () => void })[];
|
||||||
}>(undefined!);
|
}>({ apiUrl: ssrApiUrl, authToken: null, selectedAccount: null, accounts: [] });
|
||||||
|
|
||||||
export const AccountProvider = ({ children }: { children: ReactNode }) => {
|
export const AccountProvider = ({ children }: { children: ReactNode }) => {
|
||||||
const [setError, clearError] = useSetError("account");
|
const [setError, clearError] = useSetError("account");
|
||||||
|
@ -39,7 +39,8 @@ export const ErrorConsumer = ({ children, scope }: { children: ReactNode; scope:
|
|||||||
};
|
};
|
||||||
export const useSetError = (key: string) => {
|
export const useSetError = (key: string) => {
|
||||||
const { error, setError } = useContext(ErrorContext);
|
const { error, setError } = useContext(ErrorContext);
|
||||||
const set = (obj: Omit<Error, "key">) => setError({ key, ...obj });
|
const set = ({ key: nKey, ...obj }: Error & { key?: Error["key"] }) =>
|
||||||
|
setError({ key: nKey ?? key, ...obj });
|
||||||
const clearError = () => {
|
const clearError = () => {
|
||||||
if (error?.key === key) setError(null);
|
if (error?.key === key) setError(null);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
import { HydrationBoundary, QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
import { getServerData } from "one";
|
||||||
import { type ReactNode, useState } from "react";
|
import { type ReactNode, useState } from "react";
|
||||||
// import { useUserTheme } from "@kyoo/models";
|
// import { useUserTheme } from "@kyoo/models";
|
||||||
import { ThemeSelector } from "~/primitives/theme";
|
import { ThemeSelector } from "~/primitives/theme";
|
||||||
@ -8,7 +9,11 @@ import { ErrorConsumer, ErrorProvider } from "./error-provider";
|
|||||||
|
|
||||||
const QueryProvider = ({ children }: { children: ReactNode }) => {
|
const QueryProvider = ({ children }: { children: ReactNode }) => {
|
||||||
const [queryClient] = useState(() => createQueryClient());
|
const [queryClient] = useState(() => createQueryClient());
|
||||||
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
return (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<HydrationBoundary state={getServerData("queryState")}>{children}</HydrationBoundary>
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ThemeProvider = ({ children }: { children: ReactNode }) => {
|
const ThemeProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { getServerData } from "one";
|
||||||
|
import { Platform } from "react-native";
|
||||||
import { MMKV, useMMKVString } from "react-native-mmkv";
|
import { MMKV, useMMKVString } from "react-native-mmkv";
|
||||||
import type { ZodTypeAny, z } from "zod";
|
import type { ZodTypeAny, z } from "zod";
|
||||||
|
|
||||||
@ -22,12 +24,9 @@ export const setCookie = (key: string, val?: unknown) => {
|
|||||||
document.cookie = `${key}=${value};${expires};path=/;samesite=strict`;
|
document.cookie = `${key}=${value};${expires};path=/;samesite=strict`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const readCookie = <T extends ZodTypeAny>(
|
export const readCookie = <T extends ZodTypeAny>(key: string, parser: T) => {
|
||||||
cookies: string | undefined,
|
const cookies = getServerData("cookies");
|
||||||
key: string,
|
console.log("cookies", cookies);
|
||||||
parser?: T,
|
|
||||||
) => {
|
|
||||||
if (!cookies) return undefined;
|
|
||||||
const decodedCookie = decodeURIComponent(cookies);
|
const decodedCookie = decodeURIComponent(cookies);
|
||||||
const ca = decodedCookie.split(";");
|
const ca = decodedCookie.split(";");
|
||||||
|
|
||||||
@ -35,10 +34,13 @@ export const readCookie = <T extends ZodTypeAny>(
|
|||||||
const ret = ca.find((x) => x.trimStart().startsWith(name));
|
const ret = ca.find((x) => x.trimStart().startsWith(name));
|
||||||
if (ret === undefined) return undefined;
|
if (ret === undefined) return undefined;
|
||||||
const str = fromBase64(ret.substring(name.length));
|
const str = fromBase64(ret.substring(name.length));
|
||||||
return parser ? (parser.parse(JSON.parse(str)) as z.infer<T>) : str;
|
return parser.parse(JSON.parse(str)) as z.infer<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useStoreValue = <T extends ZodTypeAny>(key: string, parser: T) => {
|
export const useStoreValue = <T extends ZodTypeAny>(key: string, parser: T) => {
|
||||||
|
if (Platform.OS === "web" && typeof window === "undefined") {
|
||||||
|
return readCookie(key, parser);
|
||||||
|
}
|
||||||
const [val] = useMMKVString(key);
|
const [val] = useMMKVString(key);
|
||||||
if (val === undefined) return val;
|
if (val === undefined) return val;
|
||||||
return parser.parse(JSON.parse(val)) as z.infer<T>;
|
return parser.parse(JSON.parse(val)) as z.infer<T>;
|
||||||
@ -49,6 +51,9 @@ export const storeValue = (key: string, value: unknown) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const readValue = <T extends ZodTypeAny>(key: string, parser: T) => {
|
export const readValue = <T extends ZodTypeAny>(key: string, parser: T) => {
|
||||||
|
if (Platform.OS === "web" && typeof window === "undefined") {
|
||||||
|
return readCookie(key, parser);
|
||||||
|
}
|
||||||
const val = storage.getString(key);
|
const val = storage.getString(key);
|
||||||
if (val === undefined) return val;
|
if (val === undefined) return val;
|
||||||
return parser.parse(JSON.parse(val)) as z.infer<T>;
|
return parser.parse(JSON.parse(val)) as z.infer<T>;
|
||||||
|
@ -13,7 +13,7 @@ export const Fetch = <Data,>({
|
|||||||
Loader: () => ReactElement;
|
Loader: () => ReactElement;
|
||||||
}): JSX.Element | null => {
|
}): JSX.Element | null => {
|
||||||
const { data, isPaused, error } = useFetch(query);
|
const { data, isPaused, error } = useFetch(query);
|
||||||
const setError = useSetError();
|
const [setError] = useSetError("fetch");
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error.status === 401 || error.status === 403) {
|
if (error.status === 401 || error.status === 403) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { QueryClient, dehydrate, useInfiniteQuery, useQuery } from "@tanstack/react-query";
|
import { QueryClient, dehydrate, useInfiniteQuery, useQuery } from "@tanstack/react-query";
|
||||||
import { setServerData } from "one";
|
import { setServerData } from "one";
|
||||||
import { type ComponentType, type ReactElement, useContext } from "react";
|
import { useContext } from "react";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
import { type KyooError, type Page, Paged } from "~/models";
|
import { type KyooError, type Page, Paged } from "~/models";
|
||||||
import { AccountContext } from "~/providers/account-provider";
|
import { AccountContext, ssrApiUrl } from "~/providers/account-provider";
|
||||||
|
|
||||||
const cleanSlash = (str: string | null, keepFirst = false) => {
|
const cleanSlash = (str: string | null, keepFirst = false) => {
|
||||||
if (!str) return null;
|
if (!str) return null;
|
||||||
@ -129,18 +129,6 @@ export type QueryIdentifier<T = unknown, Ret = T> = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type QueryPage<Props = {}, Items = unknown> = ComponentType<
|
|
||||||
Props & { randomItems: Items[] }
|
|
||||||
> & {
|
|
||||||
getFetchUrls?: (route: { [key: string]: string }, randomItems: Items[]) => QueryIdentifier<any>[];
|
|
||||||
getLayout?:
|
|
||||||
| QueryPage<{ page: ReactElement }>
|
|
||||||
| { Layout: QueryPage<{ page: ReactElement }>; props: object };
|
|
||||||
requiredPermissions?: string[];
|
|
||||||
randomItems?: Items[];
|
|
||||||
isPublic?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toQueryKey = (query: {
|
export const toQueryKey = (query: {
|
||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
path: (string | undefined)[];
|
path: (string | undefined)[];
|
||||||
@ -212,7 +200,11 @@ export const prefetch = async (...queries: QueryIdentifier[]) => {
|
|||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
queries.map((query) => {
|
queries.map((query) => {
|
||||||
const key = toQueryKey({ apiUrl: "/api", path: query.path, params: query.params });
|
const key = toQueryKey({
|
||||||
|
apiUrl: ssrApiUrl,
|
||||||
|
path: query.path,
|
||||||
|
params: query.params,
|
||||||
|
});
|
||||||
|
|
||||||
if (query.infinite) {
|
if (query.infinite) {
|
||||||
return client.prefetchInfiniteQuery({
|
return client.prefetchInfiniteQuery({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user