robodev 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/package.json +1 -1
  2. package/src/emit-starter.test.ts +14 -0
  3. package/src/index.ts +54 -45
  4. package/src/parse-create-args.test.ts +26 -0
  5. package/src/parse-create-args.ts +63 -0
  6. package/templates/auth-chat/.config/local.spa.template.yml +27 -0
  7. package/templates/auth-chat/.oxlint-base.json +29 -0
  8. package/templates/auth-chat/.oxlintrc.json +78 -0
  9. package/templates/auth-chat/.rulesync/rules/frontend-api-boundary.md +36 -0
  10. package/templates/auth-chat/.rulesync/rules/frontend-component-structure.md +38 -0
  11. package/templates/auth-chat/.rulesync/rules/frontend-forms.md +32 -0
  12. package/templates/auth-chat/.rulesync/rules/frontend-notifications.md +24 -0
  13. package/templates/auth-chat/.rulesync/rules/frontend-povio-components.md +42 -0
  14. package/templates/auth-chat/.rulesync/rules/frontend-povio-ui.md +45 -0
  15. package/templates/auth-chat/.rulesync/rules/frontend-query-autocomplete.md +29 -0
  16. package/templates/auth-chat/.rulesync/rules/frontend-tables-and-lists.md +34 -0
  17. package/templates/auth-chat/.rulesync/rules/frontend-translations.md +26 -0
  18. package/templates/auth-chat/.rulesync/rules/project-overview.md +32 -0
  19. package/templates/auth-chat/.rulesync/rules/robodev-api.md +30 -0
  20. package/templates/auth-chat/.rulesync/rules/robodev-auth.md +40 -0
  21. package/templates/auth-chat/.rulesync/rules/robodev-database.md +22 -0
  22. package/templates/auth-chat/.rulesync/rules/role-based-app-structure.md +36 -0
  23. package/templates/auth-chat/.rulesync/skills/media-feature/SKILL.md +21 -0
  24. package/templates/auth-chat/.rulesync/skills/povio-ui-styling/SKILL.md +208 -0
  25. package/templates/auth-chat/.rulesync/skills/povio-ui-styling/agents/openai.yaml +4 -0
  26. package/templates/auth-chat/.rulesync/skills/robodev-api-route/SKILL.md +13 -0
  27. package/templates/auth-chat/.rulesync/skills/robodev-table/SKILL.md +12 -0
  28. package/templates/auth-chat/README.md +26 -7
  29. package/templates/auth-chat/api/invite.ts +43 -0
  30. package/templates/auth-chat/apps/fe/index.html +24 -0
  31. package/templates/auth-chat/apps/fe/openapi-codegen.config.ts +37 -0
  32. package/templates/auth-chat/apps/fe/package.json +82 -0
  33. package/templates/auth-chat/apps/fe/public/apple-touch-icon.png +0 -0
  34. package/templates/auth-chat/apps/fe/public/favicon-96x96.png +0 -0
  35. package/templates/auth-chat/apps/fe/public/favicon.ico +0 -0
  36. package/templates/auth-chat/apps/fe/public/favicon.svg +3 -0
  37. package/templates/auth-chat/apps/fe/public/site.webmanifest +21 -0
  38. package/templates/auth-chat/apps/fe/public/web-app-manifest-192x192.png +0 -0
  39. package/templates/auth-chat/apps/fe/public/web-app-manifest-512x512.png +0 -0
  40. package/templates/auth-chat/apps/fe/src/assets/fonts/GeneralSans-Bold.otf +0 -0
  41. package/templates/auth-chat/apps/fe/src/assets/fonts/GeneralSans-Medium.otf +0 -0
  42. package/templates/auth-chat/apps/fe/src/assets/fonts/GeneralSans-Regular.otf +0 -0
  43. package/templates/auth-chat/apps/fe/src/assets/fonts/GeneralSans-Semibold.otf +0 -0
  44. package/templates/auth-chat/apps/fe/src/assets/locales/en/translation.json +202 -0
  45. package/templates/auth-chat/apps/fe/src/assets/locales/sl/translation.json +202 -0
  46. package/templates/auth-chat/apps/fe/src/clients/app-rest-client.ts +15 -0
  47. package/templates/auth-chat/apps/fe/src/clients/auth-token-store.ts +101 -0
  48. package/templates/auth-chat/apps/fe/src/clients/rest/app-error-handler.ts +31 -0
  49. package/templates/auth-chat/apps/fe/src/clients/rest/interceptors/authorization-header.interceptor.ts +15 -0
  50. package/templates/auth-chat/apps/fe/src/clients/rest/interceptors/refresh-token.interceptor.ts +37 -0
  51. package/templates/auth-chat/apps/fe/src/clients/rest/interceptors/response.interceptor.ts +17 -0
  52. package/templates/auth-chat/apps/fe/src/components/404.tsx +18 -0
  53. package/templates/auth-chat/apps/fe/src/components/features/auth/AuthBrandPanel.tsx +60 -0
  54. package/templates/auth-chat/apps/fe/src/components/features/auth/AuthLayout.tsx +23 -0
  55. package/templates/auth-chat/apps/fe/src/components/features/auth/LoginPage.tsx +111 -0
  56. package/templates/auth-chat/apps/fe/src/components/features/auth/RegisterPage.tsx +143 -0
  57. package/templates/auth-chat/apps/fe/src/components/features/chat/ChatPage.tsx +105 -0
  58. package/templates/auth-chat/apps/fe/src/components/features/chat/InviteForm.tsx +84 -0
  59. package/templates/auth-chat/apps/fe/src/components/features/profile/ProfilePage.tsx +96 -0
  60. package/templates/auth-chat/apps/fe/src/components/googleAnalytics/GoogleAnalytics.tsx +35 -0
  61. package/templates/auth-chat/apps/fe/src/components/layout/AppLayout.tsx +19 -0
  62. package/templates/auth-chat/apps/fe/src/components/layout/app-header/AppHeader.tsx +91 -0
  63. package/templates/auth-chat/apps/fe/src/components/layout/app-header/MobileNavigation.tsx +51 -0
  64. package/templates/auth-chat/apps/fe/src/components/layout/app-header/NavLink.tsx +29 -0
  65. package/templates/auth-chat/apps/fe/src/components/shared/branding/BrandLogo.tsx +13 -0
  66. package/templates/auth-chat/apps/fe/src/components/shared/error/ErrorFallback.tsx +43 -0
  67. package/templates/auth-chat/apps/fe/src/components/shared/error/ErrorText.tsx +20 -0
  68. package/templates/auth-chat/apps/fe/src/components/shared/error/NotFound.tsx +36 -0
  69. package/templates/auth-chat/apps/fe/src/components/shared/forms/RequiredLabel.tsx +21 -0
  70. package/templates/auth-chat/apps/fe/src/components/shared/forms/RowInputWrapper.tsx +50 -0
  71. package/templates/auth-chat/apps/fe/src/components/shared/head/AppHead.tsx +32 -0
  72. package/templates/auth-chat/apps/fe/src/components/shared/head/DefaultAppHead.tsx +34 -0
  73. package/templates/auth-chat/apps/fe/src/components/shared/layout/LoadingState.tsx +9 -0
  74. package/templates/auth-chat/apps/fe/src/components/shared/layout/ThinPageWrapper.tsx +5 -0
  75. package/templates/auth-chat/apps/fe/src/components/shared/page/PageHeader.tsx +69 -0
  76. package/templates/auth-chat/apps/fe/src/components/shared/ui/Card.tsx +60 -0
  77. package/templates/auth-chat/apps/fe/src/components/shared/ui/GoogleLoginButton.tsx +19 -0
  78. package/templates/auth-chat/apps/fe/src/components/shared/ui/RequiredLabel.tsx +22 -0
  79. package/templates/auth-chat/apps/fe/src/components/shared/ui/TableActions.tsx +22 -0
  80. package/templates/auth-chat/apps/fe/src/config/app.config.ts +35 -0
  81. package/templates/auth-chat/apps/fe/src/config/i18n.ts +43 -0
  82. package/templates/auth-chat/apps/fe/src/config/inits/a11y.ts +14 -0
  83. package/templates/auth-chat/apps/fe/src/config/inits/logger.ts +7 -0
  84. package/templates/auth-chat/apps/fe/src/config/inits/sentry.ts +21 -0
  85. package/templates/auth-chat/apps/fe/src/config/jwt.config.ts +2 -0
  86. package/templates/auth-chat/apps/fe/src/config/query.config.ts +20 -0
  87. package/templates/auth-chat/apps/fe/src/hooks/useAuth.ts +5 -0
  88. package/templates/auth-chat/apps/fe/src/main.tsx +52 -0
  89. package/templates/auth-chat/apps/fe/src/pages/(guest)/login.tsx +23 -0
  90. package/templates/auth-chat/apps/fe/src/pages/(guest)/register.tsx +23 -0
  91. package/templates/auth-chat/apps/fe/src/pages/(guest)/route.tsx +18 -0
  92. package/templates/auth-chat/apps/fe/src/pages/(private)/index.tsx +23 -0
  93. package/templates/auth-chat/apps/fe/src/pages/(private)/profile.tsx +23 -0
  94. package/templates/auth-chat/apps/fe/src/pages/(private)/route.tsx +18 -0
  95. package/templates/auth-chat/apps/fe/src/pages/(public)/auth.tsx +37 -0
  96. package/templates/auth-chat/apps/fe/src/pages/(public)/route.tsx +9 -0
  97. package/templates/auth-chat/apps/fe/src/pages/__root.tsx +164 -0
  98. package/templates/auth-chat/apps/fe/src/providers/AppErrorBoundary.tsx +10 -0
  99. package/templates/auth-chat/apps/fe/src/providers/OpenApiRuntimeProvider.tsx +31 -0
  100. package/templates/auth-chat/apps/fe/src/providers/index.tsx +44 -0
  101. package/templates/auth-chat/apps/fe/src/providers/jwt.provider.tsx +95 -0
  102. package/templates/auth-chat/apps/fe/src/routeTree.gen.ts +225 -0
  103. package/templates/auth-chat/apps/fe/src/styles/base.css +103 -0
  104. package/templates/auth-chat/apps/fe/src/styles/fonts/fonts.tsx +10 -0
  105. package/templates/auth-chat/apps/fe/src/styles/fonts/general-sans.css +31 -0
  106. package/templates/auth-chat/apps/fe/src/styles/globals.css +28 -0
  107. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/button.override.ts +536 -0
  108. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/checkbox.override.ts +71 -0
  109. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/input.override.ts +252 -0
  110. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/label.override.ts +91 -0
  111. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/modal.override.ts +57 -0
  112. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/radio.override.ts +46 -0
  113. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/table.override.ts +104 -0
  114. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/tag.override.ts +66 -0
  115. package/templates/auth-chat/apps/fe/src/styles/overrides/defaults/typography.override.ts +115 -0
  116. package/templates/auth-chat/apps/fe/src/styles/overrides/outline.clsx.ts +10 -0
  117. package/templates/auth-chat/apps/fe/src/styles/overrides/uiOverrides.override.ts +60 -0
  118. package/templates/auth-chat/apps/fe/src/styles/theme.css +2177 -0
  119. package/templates/auth-chat/apps/fe/src/types/i18next.d.ts +12 -0
  120. package/templates/auth-chat/apps/fe/src/types/table.d.ts +17 -0
  121. package/templates/auth-chat/apps/fe/src/types/ui.d.ts +26 -0
  122. package/templates/auth-chat/apps/fe/src/types/vite-env.d.ts +20 -0
  123. package/templates/auth-chat/apps/fe/src/utils/date.utils.ts +17 -0
  124. package/templates/auth-chat/apps/fe/src/utils/number.utils.ts +12 -0
  125. package/templates/auth-chat/apps/fe/src/utils/string.utils.ts +5 -0
  126. package/templates/auth-chat/apps/fe/src/vite-env.d.ts +1 -0
  127. package/templates/auth-chat/apps/fe/tsconfig.app.json +32 -0
  128. package/templates/auth-chat/apps/fe/tsconfig.json +9 -0
  129. package/templates/auth-chat/apps/fe/tsconfig.node.json +31 -0
  130. package/templates/auth-chat/apps/fe/vite.config.ts +94 -0
  131. package/templates/auth-chat/openapi.json +1016 -0
  132. package/templates/auth-chat/oxfmt.config.js +23 -0
  133. package/templates/auth-chat/package.json +6 -13
  134. package/templates/auth-chat/rulesync.jsonc +18 -0
  135. package/templates/auth-chat/tsconfig.json +2 -4
  136. package/templates/backend/README.md +2 -2
  137. package/templates/backend/api/_lib.ts +359 -0
  138. package/templates/backend/api/aliens/labels.ts +19 -0
  139. package/templates/backend/api/files/presigned-url.ts +48 -0
  140. package/templates/backend/api/files/upload.ts +29 -0
  141. package/templates/backend/api/planets/[id]/like.ts +36 -0
  142. package/templates/backend/api/planets/[id].ts +56 -13
  143. package/templates/backend/api/planets/paginate.ts +36 -0
  144. package/templates/backend/api/planets.ts +52 -44
  145. package/templates/backend/database.ts +33 -13
  146. package/templates/backend/package.json +1 -1
  147. package/templates/catalog.json +2 -2
  148. package/templates/empty/package.json +1 -1
  149. package/templates/space/package.json +1 -1
  150. package/templates/auth-chat/index.html +0 -201
  151. package/templates/auth-chat/src/main.tsx +0 -282
  152. package/templates/auth-chat/vite.config.ts +0 -7
  153. package/templates/backend/api/health.ts +0 -7
  154. package/templates/backend/api/launch.ts +0 -29
  155. package/templates/backend/api/me.ts +0 -14
  156. package/templates/backend/api/motto.ts +0 -9
  157. package/templates/backend/api/rockets.ts +0 -43
@@ -0,0 +1,164 @@
1
+ import { OpenApiRouter } from "@povio/openapi-codegen-cli";
2
+ import { Confirmation, ToastContainer, UIConfig, UIOverrides, UIRouter } from "@povio/ui";
3
+ import { TanStackDevtools } from "@tanstack/react-devtools";
4
+ import { ReactQueryDevtoolsPanel } from "@tanstack/react-query-devtools";
5
+ import { Outlet, createRootRoute, useNavigate, useRouterState } from "@tanstack/react-router";
6
+ import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools";
7
+ import { useCallback, useEffect } from "react";
8
+ import { useTranslation } from "react-i18next";
9
+ import { onCLS, onINP, onLCP } from "web-vitals";
10
+
11
+ import { NotFoundPage } from "@/components/404";
12
+ import GoogleAnalytics from "@/components/googleAnalytics/GoogleAnalytics";
13
+ import { DefaultAppHead } from "@/components/shared/head/DefaultAppHead";
14
+ import { AppConfig } from "@/config/app.config";
15
+ import { initA11y } from "@/config/inits/a11y";
16
+ import { initLogger } from "@/config/inits/logger";
17
+ import { initSentry } from "@/config/inits/sentry";
18
+ import Providers from "@/providers";
19
+ import { AppErrorBoundary } from "@/providers/AppErrorBoundary";
20
+ import { OpenApiRuntimeProvider } from "@/providers/OpenApiRuntimeProvider";
21
+ import { Fonts } from "@/styles/fonts/fonts";
22
+ import { uiOverrides } from "@/styles/overrides/uiOverrides.override";
23
+
24
+ import "@/config/i18n";
25
+ initLogger();
26
+ initSentry();
27
+ initA11y();
28
+
29
+ const Root = () => {
30
+ const { i18n } = useTranslation();
31
+
32
+ const navigate = useNavigate();
33
+ const searchString = useRouterState({
34
+ select: (state) => state.location.searchStr,
35
+ });
36
+
37
+ const push = useCallback(
38
+ async (to: string, params?: Record<string, unknown>) => {
39
+ await navigate({ to, search: params });
40
+ return true;
41
+ },
42
+ [navigate],
43
+ );
44
+
45
+ const replace = useCallback(
46
+ async (to: string, params?: Record<string, unknown>) => {
47
+ await navigate({ to, replace: true, search: params });
48
+ return true;
49
+ },
50
+ [navigate],
51
+ );
52
+
53
+ useEffect(() => {
54
+ const handler = (lng: string) => {
55
+ if (typeof document !== "undefined") {
56
+ document.documentElement.setAttribute("lang", lng);
57
+ }
58
+ };
59
+ i18n.on("languageChanged", handler);
60
+ return () => {
61
+ i18n.off("languageChanged", handler);
62
+ };
63
+ }, [i18n]);
64
+
65
+ if (AppConfig.enableWebVitals) {
66
+ onCLS(console.log);
67
+ onINP(console.log);
68
+ onLCP(console.log);
69
+ }
70
+
71
+ return (
72
+ <>
73
+ <GoogleAnalytics />
74
+ <AppErrorBoundary>
75
+ <Providers
76
+ providers={[
77
+ // { provider: ThemeContext.ThemeContextProvider }, // Uncomment for dark theme support
78
+ { provider: UIRouter.UIRouterProvider, props: { push, replace, searchString } },
79
+ { provider: OpenApiRouter.Provider, props: { replace } },
80
+ {
81
+ provider: UIConfig.Provider,
82
+ props: {
83
+ config: {
84
+ input: {
85
+ size: "small",
86
+ },
87
+ tableCellText: {
88
+ size: "label-2",
89
+ variant: "default",
90
+ },
91
+ tableHeaderText: {
92
+ size: "label-2",
93
+ variant: "prominent-1",
94
+ },
95
+ tag: {
96
+ textSize: "label-3",
97
+ },
98
+ },
99
+ },
100
+ },
101
+ {
102
+ provider: UIOverrides.Provider,
103
+ props: {
104
+ config: uiOverrides,
105
+ },
106
+ },
107
+ { provider: OpenApiRuntimeProvider },
108
+ { provider: Confirmation.Provider },
109
+ ]}
110
+ >
111
+ <Fonts />
112
+ <DefaultAppHead />
113
+
114
+ <RootLayout />
115
+
116
+ <ToastContainer />
117
+ <TanStackDevtools
118
+ plugins={[
119
+ {
120
+ name: "TanStack Query",
121
+ render: <ReactQueryDevtoolsPanel />,
122
+ defaultOpen: true,
123
+ },
124
+ {
125
+ name: "TanStack Router",
126
+ render: <TanStackRouterDevtoolsPanel />,
127
+ defaultOpen: false,
128
+ },
129
+ ]}
130
+ />
131
+ </Providers>
132
+ </AppErrorBoundary>
133
+ </>
134
+ );
135
+ };
136
+
137
+ function RootLayout() {
138
+ return (
139
+ <main className="font-primary">
140
+ <Outlet />
141
+ </main>
142
+ );
143
+ }
144
+
145
+ export const Route = createRootRoute({
146
+ head: () => ({
147
+ meta: [
148
+ { charSet: "utf8" },
149
+ { name: "viewport", content: "width=device-width, initial-scale=1" },
150
+ { name: "theme-color", content: "#ffffff" },
151
+ { title: "Auth chat" },
152
+ { name: "msapplication-TileColor", content: "#da532c" },
153
+ ],
154
+ links: [
155
+ { rel: "apple-touch-icon", sizes: "180x180", href: "/apple-touch-icon.png" },
156
+ { rel: "icon", type: "image/png", sizes: "96x96", href: "/favicon-96x96.png" },
157
+ { rel: "icon", type: "image/svg+xml", href: "/favicon.svg" },
158
+ { rel: "shortcut icon", href: "/favicon.ico" },
159
+ { rel: "manifest", href: "/site.webmanifest" },
160
+ ],
161
+ }),
162
+ component: Root,
163
+ notFoundComponent: NotFoundPage,
164
+ });
@@ -0,0 +1,10 @@
1
+ import { ErrorBoundary } from "@sentry/react";
2
+ import type { PropsWithChildren } from "react";
3
+
4
+ import { ErrorFallback, type ErrorFallbackProps } from "@/components/shared/error/ErrorFallback";
5
+
6
+ const Fallback = (props: ErrorFallbackProps) => <ErrorFallback {...props} />;
7
+
8
+ export const AppErrorBoundary = ({ children }: PropsWithChildren) => {
9
+ return <ErrorBoundary fallback={Fallback}>{children}</ErrorBoundary>;
10
+ };
@@ -0,0 +1,31 @@
1
+ import { ErrorHandler, OpenApiQueryConfig } from "@povio/openapi-codegen-cli";
2
+ import { useToast } from "@povio/ui";
3
+ import type { PropsWithChildren } from "react";
4
+ import { useCallback } from "react";
5
+ import { useTranslation } from "react-i18next";
6
+
7
+ export function OpenApiRuntimeProvider({ children }: PropsWithChildren) {
8
+ const { t } = useTranslation();
9
+ const { errorToast } = useToast();
10
+
11
+ const handleError = useCallback(
12
+ (error: unknown) => {
13
+ console.error(error);
14
+ errorToast({
15
+ text: t(($) => $.shared.apiErrors.requestFailed, {
16
+ error: ErrorHandler.getErrorMessage(error) ?? t(($) => $.shared.apiErrors.unknown),
17
+ }),
18
+ });
19
+ },
20
+ [errorToast, t],
21
+ );
22
+
23
+ return (
24
+ <OpenApiQueryConfig.Provider
25
+ allowInvalidResponseData={import.meta.env.DEV}
26
+ onError={handleError}
27
+ >
28
+ {children}
29
+ </OpenApiQueryConfig.Provider>
30
+ );
31
+ }
@@ -0,0 +1,44 @@
1
+ import type { ComponentProps, JSX, ReactNode } from "react";
2
+
3
+ type HasRequiredProperty<T> = {
4
+ [K in keyof T]-?: Record<string, never> extends Pick<T, K> ? never : K;
5
+ }[keyof T];
6
+
7
+ interface ProviderBase<T> {
8
+ provider: T;
9
+ }
10
+
11
+ interface ProviderProps<T extends keyof JSX.IntrinsicElements> {
12
+ props: Omit<ComponentProps<T>, "children">;
13
+ }
14
+
15
+ // oxlint-disable-next-line no-explicit-any
16
+ type ProvidersArray<T extends any[]> = [
17
+ ...{
18
+ [K in keyof T]: HasRequiredProperty<Omit<ComponentProps<T[K]>, "children">> extends never
19
+ ? ProviderBase<T[K]> & Partial<ProviderProps<T[K]>>
20
+ : ProviderBase<T[K]> & ProviderProps<T[K]>;
21
+ },
22
+ ];
23
+
24
+ // oxlint-disable-next-line no-explicit-any
25
+ interface Props<T extends any[]> {
26
+ providers: ProvidersArray<T>;
27
+ children: ReactNode;
28
+ }
29
+
30
+ // oxlint-disable-next-line no-explicit-any
31
+ function Providers<T extends any[]>({ providers, children }: Props<T>) {
32
+ return (
33
+ <>
34
+ {providers.reduceRight(
35
+ (child, { provider: Provider, props }) => (
36
+ <Provider {...props}>{child}</Provider>
37
+ ),
38
+ children,
39
+ )}
40
+ </>
41
+ );
42
+ }
43
+
44
+ export default Providers;
@@ -0,0 +1,95 @@
1
+ import { AuthContext } from "@povio/openapi-codegen-cli";
2
+ import { useQueryClient } from "@tanstack/react-query";
3
+ import { type PropsWithChildren, useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
4
+
5
+ import { authTokenStore } from "@/clients/auth-token-store";
6
+ import { LoadingState } from "@/components/shared/layout/LoadingState";
7
+ import { UserApi } from "@/openapi/user/user.api";
8
+ import type { UserModels } from "@/openapi/user/user.models";
9
+ import { UserQueries } from "@/openapi/user/user.queries";
10
+
11
+ const routes: AuthContext.Routes = {
12
+ authenticated: "/",
13
+ unauthenticated: "/login",
14
+ };
15
+
16
+ export const JWTProvider = ({ children }: PropsWithChildren) => {
17
+ const queryClient = useQueryClient();
18
+
19
+ const previousAccessToken = useRef<string | null>(null);
20
+ const accessToken = useSyncExternalStore(
21
+ authTokenStore.subscribe,
22
+ authTokenStore.getAccessToken,
23
+ authTokenStore.getServerSnapshot,
24
+ );
25
+
26
+ const authenticated = !!accessToken;
27
+ const isInitializing = false;
28
+
29
+ const { data: user } = UserQueries.useGet({
30
+ enabled: authenticated,
31
+ staleTime: 10 * 60 * 1000,
32
+ });
33
+
34
+ const onAccessTokenChange = useCallback((token: string | null) => {
35
+ authTokenStore.setAccessToken(token);
36
+ }, []);
37
+
38
+ const onRefreshTokenChange = useCallback((token: string | null) => {
39
+ authTokenStore.setRefreshToken(token);
40
+ }, []);
41
+
42
+ const logout = useCallback(() => {
43
+ authTokenStore.clear();
44
+ queryClient.clear();
45
+ }, [queryClient]);
46
+
47
+ useEffect(() => {
48
+ if (previousAccessToken.current && !accessToken) {
49
+ queryClient.clear();
50
+ }
51
+
52
+ previousAccessToken.current = accessToken;
53
+ }, [accessToken, queryClient]);
54
+
55
+ const userPromise = useCallback(async () => {
56
+ try {
57
+ const user = await UserApi.get();
58
+ queryClient.setQueryData<UserModels.UserMeResponse>(UserQueries.keys.get(), user);
59
+ return user;
60
+ } catch {
61
+ logout();
62
+ return null;
63
+ }
64
+ }, [logout, queryClient]);
65
+
66
+ const updateTokens = useCallback(
67
+ (accessToken: string | null, refreshToken?: string | null) => {
68
+ if (accessToken !== null) {
69
+ onAccessTokenChange(accessToken);
70
+ }
71
+ if (refreshToken !== null && refreshToken !== undefined) {
72
+ onRefreshTokenChange(refreshToken);
73
+ }
74
+ },
75
+ [onAccessTokenChange, onRefreshTokenChange],
76
+ );
77
+
78
+ const loadingState = useMemo(() => <LoadingState />, []);
79
+
80
+ return (
81
+ <AuthContext.Provider
82
+ isAuthenticated={authenticated}
83
+ isInitializing={isInitializing}
84
+ logout={logout}
85
+ updateTokens={updateTokens}
86
+ accessToken={accessToken}
87
+ user={user}
88
+ userPromise={userPromise}
89
+ routes={routes}
90
+ loadingState={loadingState}
91
+ >
92
+ {children}
93
+ </AuthContext.Provider>
94
+ );
95
+ };
@@ -0,0 +1,225 @@
1
+ /* eslint-disable */
2
+
3
+ // @ts-nocheck
4
+
5
+ // noinspection JSUnusedGlobalSymbols
6
+
7
+ // This file was automatically generated by TanStack Router.
8
+ // You should NOT make any changes in this file as it will be overwritten.
9
+ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
10
+
11
+ import { Route as rootRouteImport } from './pages/__root'
12
+ import { Route as publicRouteRouteImport } from './pages/(public)/route'
13
+ import { Route as privateRouteRouteImport } from './pages/(private)/route'
14
+ import { Route as guestRouteRouteImport } from './pages/(guest)/route'
15
+ import { Route as privateIndexRouteImport } from './pages/(private)/index'
16
+ import { Route as publicAuthRouteImport } from './pages/(public)/auth'
17
+ import { Route as privateProfileRouteImport } from './pages/(private)/profile'
18
+ import { Route as guestRegisterRouteImport } from './pages/(guest)/register'
19
+ import { Route as guestLoginRouteImport } from './pages/(guest)/login'
20
+
21
+ const publicRouteRoute = publicRouteRouteImport.update({
22
+ id: '/(public)',
23
+ getParentRoute: () => rootRouteImport,
24
+ } as any)
25
+ const privateRouteRoute = privateRouteRouteImport.update({
26
+ id: '/(private)',
27
+ getParentRoute: () => rootRouteImport,
28
+ } as any)
29
+ const guestRouteRoute = guestRouteRouteImport.update({
30
+ id: '/(guest)',
31
+ getParentRoute: () => rootRouteImport,
32
+ } as any)
33
+ const privateIndexRoute = privateIndexRouteImport.update({
34
+ id: '/',
35
+ path: '/',
36
+ getParentRoute: () => privateRouteRoute,
37
+ } as any)
38
+ const publicAuthRoute = publicAuthRouteImport.update({
39
+ id: '/auth',
40
+ path: '/auth',
41
+ getParentRoute: () => publicRouteRoute,
42
+ } as any)
43
+ const privateProfileRoute = privateProfileRouteImport.update({
44
+ id: '/profile',
45
+ path: '/profile',
46
+ getParentRoute: () => privateRouteRoute,
47
+ } as any)
48
+ const guestRegisterRoute = guestRegisterRouteImport.update({
49
+ id: '/register',
50
+ path: '/register',
51
+ getParentRoute: () => guestRouteRoute,
52
+ } as any)
53
+ const guestLoginRoute = guestLoginRouteImport.update({
54
+ id: '/login',
55
+ path: '/login',
56
+ getParentRoute: () => guestRouteRoute,
57
+ } as any)
58
+
59
+ export interface FileRoutesByFullPath {
60
+ '/login': typeof guestLoginRoute
61
+ '/register': typeof guestRegisterRoute
62
+ '/profile': typeof privateProfileRoute
63
+ '/auth': typeof publicAuthRoute
64
+ '/': typeof privateIndexRoute
65
+ }
66
+ export interface FileRoutesByTo {
67
+ '/login': typeof guestLoginRoute
68
+ '/register': typeof guestRegisterRoute
69
+ '/profile': typeof privateProfileRoute
70
+ '/auth': typeof publicAuthRoute
71
+ '/': typeof privateIndexRoute
72
+ }
73
+ export interface FileRoutesById {
74
+ __root__: typeof rootRouteImport
75
+ '/(guest)': typeof guestRouteRouteWithChildren
76
+ '/(private)': typeof privateRouteRouteWithChildren
77
+ '/(public)': typeof publicRouteRouteWithChildren
78
+ '/(guest)/login': typeof guestLoginRoute
79
+ '/(guest)/register': typeof guestRegisterRoute
80
+ '/(private)/profile': typeof privateProfileRoute
81
+ '/(public)/auth': typeof publicAuthRoute
82
+ '/(private)/': typeof privateIndexRoute
83
+ }
84
+ export interface FileRouteTypes {
85
+ fileRoutesByFullPath: FileRoutesByFullPath
86
+ fullPaths:
87
+ | '/login'
88
+ | '/register'
89
+ | '/profile'
90
+ | '/auth'
91
+ | '/'
92
+ fileRoutesByTo: FileRoutesByTo
93
+ to:
94
+ | '/login'
95
+ | '/register'
96
+ | '/profile'
97
+ | '/auth'
98
+ | '/'
99
+ id:
100
+ | '__root__'
101
+ | '/(guest)'
102
+ | '/(private)'
103
+ | '/(public)'
104
+ | '/(guest)/login'
105
+ | '/(guest)/register'
106
+ | '/(private)/profile'
107
+ | '/(public)/auth'
108
+ | '/(private)/'
109
+ fileRoutesById: FileRoutesById
110
+ }
111
+ export interface RootRouteChildren {
112
+ guestRouteRoute: typeof guestRouteRouteWithChildren
113
+ privateRouteRoute: typeof privateRouteRouteWithChildren
114
+ publicRouteRoute: typeof publicRouteRouteWithChildren
115
+ }
116
+
117
+ declare module '@tanstack/react-router' {
118
+ interface FileRoutesByPath {
119
+ '/(public)': {
120
+ id: '/(public)'
121
+ path: ''
122
+ fullPath: ''
123
+ preLoaderRoute: typeof publicRouteRouteImport
124
+ parentRoute: typeof rootRouteImport
125
+ }
126
+ '/(private)': {
127
+ id: '/(private)'
128
+ path: ''
129
+ fullPath: ''
130
+ preLoaderRoute: typeof privateRouteRouteImport
131
+ parentRoute: typeof rootRouteImport
132
+ }
133
+ '/(guest)': {
134
+ id: '/(guest)'
135
+ path: ''
136
+ fullPath: ''
137
+ preLoaderRoute: typeof guestRouteRouteImport
138
+ parentRoute: typeof rootRouteImport
139
+ }
140
+ '/(private)/': {
141
+ id: '/(private)/'
142
+ path: '/'
143
+ fullPath: '/'
144
+ preLoaderRoute: typeof privateIndexRouteImport
145
+ parentRoute: typeof privateRouteRoute
146
+ }
147
+ '/(public)/auth': {
148
+ id: '/(public)/auth'
149
+ path: '/auth'
150
+ fullPath: '/auth'
151
+ preLoaderRoute: typeof publicAuthRouteImport
152
+ parentRoute: typeof publicRouteRoute
153
+ }
154
+ '/(private)/profile': {
155
+ id: '/(private)/profile'
156
+ path: '/profile'
157
+ fullPath: '/profile'
158
+ preLoaderRoute: typeof privateProfileRouteImport
159
+ parentRoute: typeof privateRouteRoute
160
+ }
161
+ '/(guest)/register': {
162
+ id: '/(guest)/register'
163
+ path: '/register'
164
+ fullPath: '/register'
165
+ preLoaderRoute: typeof guestRegisterRouteImport
166
+ parentRoute: typeof guestRouteRoute
167
+ }
168
+ '/(guest)/login': {
169
+ id: '/(guest)/login'
170
+ path: '/login'
171
+ fullPath: '/login'
172
+ preLoaderRoute: typeof guestLoginRouteImport
173
+ parentRoute: typeof guestRouteRoute
174
+ }
175
+ }
176
+ }
177
+
178
+ interface guestRouteRouteChildren {
179
+ guestLoginRoute: typeof guestLoginRoute
180
+ guestRegisterRoute: typeof guestRegisterRoute
181
+ }
182
+
183
+ const guestRouteRouteChildren: guestRouteRouteChildren = {
184
+ guestLoginRoute: guestLoginRoute,
185
+ guestRegisterRoute: guestRegisterRoute,
186
+ }
187
+
188
+ const guestRouteRouteWithChildren = guestRouteRoute._addFileChildren(
189
+ guestRouteRouteChildren,
190
+ )
191
+
192
+ interface privateRouteRouteChildren {
193
+ privateProfileRoute: typeof privateProfileRoute
194
+ privateIndexRoute: typeof privateIndexRoute
195
+ }
196
+
197
+ const privateRouteRouteChildren: privateRouteRouteChildren = {
198
+ privateProfileRoute: privateProfileRoute,
199
+ privateIndexRoute: privateIndexRoute,
200
+ }
201
+
202
+ const privateRouteRouteWithChildren = privateRouteRoute._addFileChildren(
203
+ privateRouteRouteChildren,
204
+ )
205
+
206
+ interface publicRouteRouteChildren {
207
+ publicAuthRoute: typeof publicAuthRoute
208
+ }
209
+
210
+ const publicRouteRouteChildren: publicRouteRouteChildren = {
211
+ publicAuthRoute: publicAuthRoute,
212
+ }
213
+
214
+ const publicRouteRouteWithChildren = publicRouteRoute._addFileChildren(
215
+ publicRouteRouteChildren,
216
+ )
217
+
218
+ const rootRouteChildren: RootRouteChildren = {
219
+ guestRouteRoute: guestRouteRouteWithChildren,
220
+ privateRouteRoute: privateRouteRouteWithChildren,
221
+ publicRouteRoute: publicRouteRouteWithChildren,
222
+ }
223
+ export const routeTree = rootRouteImport
224
+ ._addFileChildren(rootRouteChildren)
225
+ ._addFileTypes<FileRouteTypes>()
@@ -0,0 +1,103 @@
1
+ @plugin "tailwindcss-react-aria-components";
2
+
3
+ @layer base {
4
+ button:not(:disabled),
5
+ [role="button"]:not(:disabled) {
6
+ cursor: pointer;
7
+ }
8
+ }
9
+
10
+ @theme static {
11
+ --color-*: initial;
12
+ --color-inherit: inherit;
13
+ --color-transparent: transparent;
14
+ --color-current: currentColor;
15
+ --radius-*: initial;
16
+ --radius-none: 0rem;
17
+ --container-*: initial;
18
+ --container-none: none;
19
+ --container-modal: 32.5rem;
20
+ --container-toast: 45rem;
21
+ --spacing-*: initial;
22
+ --spacing-0: 0rem;
23
+ --shadow-*: initial;
24
+ --shadow-none: none;
25
+ --text-*: initial;
26
+ --text-inherit: inherit;
27
+ --text-inherit--line-height: inherit;
28
+ --text-inherit--letter-spacing: inherit;
29
+ --breakpoint-*: initial;
30
+ --breakpoint-sm: 23.75rem;
31
+ --breakpoint-md: 37.5rem;
32
+ --breakpoint-lg: 80rem;
33
+ --breakpoint-xl: 105rem;
34
+ --rotate-*: initial;
35
+ --rotate-0: 0deg;
36
+ --rotate-45: 45deg;
37
+ --rotate-90: 90deg;
38
+ --rotate-180: 180deg;
39
+ --rotate-270: 270deg;
40
+ --rotate-360: 360deg;
41
+ --animate-drawer-enter-right: drawer-slide-right 0.3s;
42
+ --animate-drawer-exit-right: drawer-slide-right 0.3s reverse;
43
+ --animate-drawer-enter-left: drawer-slide-left 0.3s;
44
+ --animate-drawer-exit-left: drawer-slide-left 0.3s reverse;
45
+ --animate-loader-spin: loader-spin 1s linear infinite;
46
+ --z-index-base: 0;
47
+ --z-index-raised: 1;
48
+ --z-index-sticky: 10;
49
+ --z-index-drawer: 20;
50
+ --z-index-modal: 30;
51
+ --z-index-bottom-sheet: 40;
52
+ --z-index-drop-target: 50;
53
+ --z-index-overlay-above: 100;
54
+
55
+ @keyframes drawer-slide-right {
56
+ from {
57
+ transform: translateX(100%);
58
+ }
59
+ to {
60
+ transform: translateX(0);
61
+ }
62
+ }
63
+ @keyframes drawer-slide-left {
64
+ from {
65
+ transform: translateX(-100%);
66
+ }
67
+ to {
68
+ transform: translateX(0);
69
+ }
70
+ }
71
+ @keyframes loader-spin {
72
+ to {
73
+ transform: rotate(360deg);
74
+ }
75
+ }
76
+ }
77
+
78
+ html {
79
+ -webkit-font-smoothing: antialiased;
80
+ }
81
+
82
+ .flex-fill {
83
+ flex: 1 0 0;
84
+ }
85
+
86
+ :root {
87
+ --elevation-fill-default-2-base: 248 249 249;
88
+ --elevation-outline-default-1-base: 218 220 221;
89
+ --elevation-outline-default-2-base: 198 200 201;
90
+ --interactive-contained-primary-idle-base: 0 90 154;
91
+ --interactive-contained-primary-hover-base: 46 142 210;
92
+ --interactive-contained-primary-pressed-base: 95 170 224;
93
+ --interactive-contained-primary-disabled-base: 155 194 221;
94
+ --interactive-contained-primary-focus-base: 95 170 224;
95
+ --interactive-outlined-primary-on-idle-base: 0 90 154;
96
+ --interactive-outlined-primary-outline-idle-base: 0 90 154;
97
+ --interactive-outlined-primary-outline-hover-base: 46 142 210;
98
+ --interactive-text-primary-idle-base: 0 90 154;
99
+ --interactive-text-primary-hover-base: 46 142 210;
100
+ --text-default-1-base: 25 26 27;
101
+ --text-default-2-base: 79 85 88;
102
+ --text-default-3-base: 111 114 116;
103
+ }
@@ -0,0 +1,10 @@
1
+ export const globalFontClass = "font-primary";
2
+
3
+ export const Fonts = () => (
4
+ <style>{`
5
+ :root {
6
+ --font-inter-base: "General Sans";
7
+ --font-geist-base: "Geist Variable";
8
+ }
9
+ `}</style>
10
+ );