From cd519998a71c28030c569801bb8012b65d1de183 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 7 Feb 2025 18:51:50 +0100 Subject: [PATCH] Fixup ssr fetch --- front/app/_layout.tsx | 15 +++++---------- front/app/_middleware.ts | 7 +++++++ front/src/providers/account-provider.tsx | 6 ++++-- front/src/providers/error-provider.tsx | 3 ++- front/src/providers/index.tsx | 9 +++++++-- front/src/providers/settings.ts | 19 ++++++++++++------- front/src/query/fetch.tsx | 2 +- front/src/query/query.tsx | 22 +++++++--------------- 8 files changed, 45 insertions(+), 38 deletions(-) create mode 100644 front/app/_middleware.ts diff --git a/front/app/_layout.tsx b/front/app/_layout.tsx index f6b8fb94..2eab9e0e 100644 --- a/front/app/_layout.tsx +++ b/front/app/_layout.tsx @@ -1,6 +1,5 @@ -import { HydrationBoundary } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; -import { Slot, getServerData } from "one"; +import { Slot } from "one"; import { useServerHeadInsertion } from "one"; import { StyleRegistryProvider, createStyleRegistry, useTheme } from "yoshiki/web"; import { Providers } from "~/providers"; @@ -63,8 +62,6 @@ export default function Layout() { const registry = createStyleRegistry(); useServerHeadInsertion(() => registry.flushToComponent()); - const queryState = getServerData("queryState"); - // TODO: change this lang attr return ( @@ -82,12 +79,10 @@ export default function Layout() { - - - - - - + + + + diff --git a/front/app/_middleware.ts b/front/app/_middleware.ts new file mode 100644 index 00000000..51d61f9a --- /dev/null +++ b/front/app/_middleware.ts @@ -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(); +}); diff --git a/front/src/providers/account-provider.tsx b/front/src/providers/account-provider.tsx index d66e8188..58bc6aaa 100644 --- a/front/src/providers/account-provider.tsx +++ b/front/src/providers/account-provider.tsx @@ -8,12 +8,14 @@ import { removeAccounts, updateAccount } from "./account-store"; import { useSetError } from "./error-provider"; import { useStoreValue } from "./settings"; +export const ssrApiUrl = process.env.KYOO_URL ?? "http://back/api"; + export const AccountContext = createContext<{ apiUrl: string; authToken: Token | null; - selectedAccount?: Account; + selectedAccount: Account | null; accounts: (Account & { select: () => void; remove: () => void })[]; -}>(undefined!); +}>({ apiUrl: ssrApiUrl, authToken: null, selectedAccount: null, accounts: [] }); export const AccountProvider = ({ children }: { children: ReactNode }) => { const [setError, clearError] = useSetError("account"); diff --git a/front/src/providers/error-provider.tsx b/front/src/providers/error-provider.tsx index 1afe794e..901e9c02 100644 --- a/front/src/providers/error-provider.tsx +++ b/front/src/providers/error-provider.tsx @@ -39,7 +39,8 @@ export const ErrorConsumer = ({ children, scope }: { children: ReactNode; scope: }; export const useSetError = (key: string) => { const { error, setError } = useContext(ErrorContext); - const set = (obj: Omit) => setError({ key, ...obj }); + const set = ({ key: nKey, ...obj }: Error & { key?: Error["key"] }) => + setError({ key: nKey ?? key, ...obj }); const clearError = () => { if (error?.key === key) setError(null); }; diff --git a/front/src/providers/index.tsx b/front/src/providers/index.tsx index 8ce49f39..f96dfb24 100644 --- a/front/src/providers/index.tsx +++ b/front/src/providers/index.tsx @@ -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 { useUserTheme } from "@kyoo/models"; import { ThemeSelector } from "~/primitives/theme"; @@ -8,7 +9,11 @@ import { ErrorConsumer, ErrorProvider } from "./error-provider"; const QueryProvider = ({ children }: { children: ReactNode }) => { const [queryClient] = useState(() => createQueryClient()); - return {children}; + return ( + + {children} + + ); }; const ThemeProvider = ({ children }: { children: ReactNode }) => { diff --git a/front/src/providers/settings.ts b/front/src/providers/settings.ts index bf93b4fe..b401a4a9 100644 --- a/front/src/providers/settings.ts +++ b/front/src/providers/settings.ts @@ -1,3 +1,5 @@ +import { getServerData } from "one"; +import { Platform } from "react-native"; import { MMKV, useMMKVString } from "react-native-mmkv"; 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`; }; -export const readCookie = ( - cookies: string | undefined, - key: string, - parser?: T, -) => { - if (!cookies) return undefined; +export const readCookie = (key: string, parser: T) => { + const cookies = getServerData("cookies"); + console.log("cookies", cookies); const decodedCookie = decodeURIComponent(cookies); const ca = decodedCookie.split(";"); @@ -35,10 +34,13 @@ export const readCookie = ( const ret = ca.find((x) => x.trimStart().startsWith(name)); if (ret === undefined) return undefined; const str = fromBase64(ret.substring(name.length)); - return parser ? (parser.parse(JSON.parse(str)) as z.infer) : str; + return parser.parse(JSON.parse(str)) as z.infer; }; export const useStoreValue = (key: string, parser: T) => { + if (Platform.OS === "web" && typeof window === "undefined") { + return readCookie(key, parser); + } const [val] = useMMKVString(key); if (val === undefined) return val; return parser.parse(JSON.parse(val)) as z.infer; @@ -49,6 +51,9 @@ export const storeValue = (key: string, value: unknown) => { }; export const readValue = (key: string, parser: T) => { + if (Platform.OS === "web" && typeof window === "undefined") { + return readCookie(key, parser); + } const val = storage.getString(key); if (val === undefined) return val; return parser.parse(JSON.parse(val)) as z.infer; diff --git a/front/src/query/fetch.tsx b/front/src/query/fetch.tsx index 3d400714..e41ff10a 100644 --- a/front/src/query/fetch.tsx +++ b/front/src/query/fetch.tsx @@ -13,7 +13,7 @@ export const Fetch = ({ Loader: () => ReactElement; }): JSX.Element | null => { const { data, isPaused, error } = useFetch(query); - const setError = useSetError(); + const [setError] = useSetError("fetch"); if (error) { if (error.status === 401 || error.status === 403) { diff --git a/front/src/query/query.tsx b/front/src/query/query.tsx index fa55971e..ace2d699 100644 --- a/front/src/query/query.tsx +++ b/front/src/query/query.tsx @@ -1,9 +1,9 @@ import { QueryClient, dehydrate, useInfiniteQuery, useQuery } from "@tanstack/react-query"; import { setServerData } from "one"; -import { type ComponentType, type ReactElement, useContext } from "react"; +import { useContext } from "react"; import type { z } from "zod"; 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) => { if (!str) return null; @@ -129,18 +129,6 @@ export type QueryIdentifier = { }; }; -export type QueryPage = ComponentType< - Props & { randomItems: Items[] } -> & { - getFetchUrls?: (route: { [key: string]: string }, randomItems: Items[]) => QueryIdentifier[]; - getLayout?: - | QueryPage<{ page: ReactElement }> - | { Layout: QueryPage<{ page: ReactElement }>; props: object }; - requiredPermissions?: string[]; - randomItems?: Items[]; - isPublic?: boolean; -}; - export const toQueryKey = (query: { apiUrl: string; path: (string | undefined)[]; @@ -212,7 +200,11 @@ export const prefetch = async (...queries: QueryIdentifier[]) => { await Promise.all( 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) { return client.prefetchInfiniteQuery({