Skip to content
File

Blob: src/client/router.ts

typescript104 lines
1import { createRootRoute, createRoute, createRouter, redirect } from "@tanstack/react-router";
2 
3import { AppShell } from "@/client/components/app-shell";
4import { meQueryOptions } from "@/client/auth/use-me";
5import { paths } from "@/client/lib/paths";
6import { queryClient } from "@/client/query";
7import { AddressbooksPage } from "@/client/pages/addressbooks";
8import { CalendarsPage } from "@/client/pages/calendars";
9import { FilesPage } from "@/client/pages/files";
10import { LoginPage } from "@/client/pages/login";
11import { MePage } from "@/client/pages/me";
12import { NotFoundPage } from "@/client/pages/not-found";
13import { PatsPage } from "@/client/pages/pats";
14 
15const rootRoute = createRootRoute({ component: AppShell, notFoundComponent: NotFoundPage });
16 
17async function requireSession({ location }: { location: { pathname: string } }): Promise<void> {
18 const me = await queryClient.ensureQueryData(meQueryOptions);
19 if (!me) {
20 throw redirect({
21 to: paths.login,
22 search: { return_to: location.pathname },
23 });
24 }
25}
26 
27const loginRoute = createRoute({
28 getParentRoute: () => rootRoute,
29 path: paths.login,
30 validateSearch: (search: Record<string, unknown>) => ({
31 return_to: typeof search.return_to === "string" ? search.return_to : paths.home,
32 }),
33 component: LoginPage,
34});
35 
36const homeRoute = createRoute({
37 getParentRoute: () => rootRoute,
38 path: paths.home,
39 beforeLoad: async ({ location }) => {
40 await requireSession({ location });
41 throw redirect({ to: paths.me, replace: true });
42 },
43});
44 
45const meRoute = createRoute({
46 getParentRoute: () => rootRoute,
47 path: paths.me,
48 beforeLoad: ({ location }) => requireSession({ location }),
49 component: MePage,
50});
51 
52const patsRoute = createRoute({
53 getParentRoute: () => rootRoute,
54 path: paths.pats,
55 beforeLoad: ({ location }) => requireSession({ location }),
56 component: PatsPage,
57});
58 
59const calendarsRoute = createRoute({
60 getParentRoute: () => rootRoute,
61 path: paths.calendars,
62 beforeLoad: ({ location }) => requireSession({ location }),
63 component: CalendarsPage,
64});
65 
66const addressbooksRoute = createRoute({
67 getParentRoute: () => rootRoute,
68 path: paths.addressbooks,
69 beforeLoad: ({ location }) => requireSession({ location }),
70 component: AddressbooksPage,
71});
72 
73const filesRoute = createRoute({
74 getParentRoute: () => rootRoute,
75 path: paths.files,
76 beforeLoad: ({ location }) => requireSession({ location }),
77 validateSearch: (search: Record<string, unknown>) => ({
78 path: typeof search.path === "string" ? search.path : "/files/",
79 }),
80 component: FilesPage,
81});
82 
83const routeTree = rootRoute.addChildren([
84 homeRoute,
85 loginRoute,
86 meRoute,
87 patsRoute,
88 calendarsRoute,
89 addressbooksRoute,
90 filesRoute,
91]);
92 
93export const router = createRouter({
94 routeTree,
95 context: { queryClient },
96 defaultPreload: "intent",
97});
98 
99declare module "@tanstack/react-router" {
100 interface Register {
101 router: typeof router;
102 }
103}