Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add tanstack/router #1141

Draft
wants to merge 9 commits into
base: staging
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions apps/console/src/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type User, useAuth0 } from '@auth0/auth0-react'
import { GTMProvider } from '@elgorditosalsero/react-gtm-hook'
import { RouterProvider, createRouter } from '@tanstack/react-router'
import axios from 'axios'
import LogRocket from 'logrocket'
import posthog from 'posthog-js'
Expand All @@ -12,16 +13,31 @@ import { DarkModeEnabler, Layout } from '@qovery/pages/layout'
import { PageLogin, PageLogoutFeature } from '@qovery/pages/login'
import { AssistantContext } from '@qovery/shared/assistant/feature'
import { useAuth, useInviteMember } from '@qovery/shared/auth'
import { ProtectedRoute } from '@qovery/shared/router'
import { routeTree } from '@qovery/shared/router'
import { HELM_DEFAULT_VALUES, KUBECONFIG, LOGIN_URL, LOGOUT_URL, PREVIEW_CODE } from '@qovery/shared/routes'
import { LoadingScreen } from '@qovery/shared/ui'
import { useDocumentTitle } from '@qovery/shared/util-hooks'
import { GTM, LOGROCKET, NODE_ENV, NX_GIT_SHA, QOVERY_API } from '@qovery/shared/util-node-env'
import { useAuthInterceptor } from '@qovery/shared/utils'
import { queryClient } from '../query-client'
import PreviewCode from './components/preview-code'
import { ProtectedRoute } from './components/protected-route'
import ScrollToTop from './components/scroll-to-top'
import { ROUTER } from './router/main.router'

const router = createRouter({
routeTree,
context: { queryClient },
defaultNotFoundComponent: () => <Navigate replace to={LOGIN_URL} />,
})

// Register things for typesafety
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}

export function App() {
useDocumentTitle('Loading...')
const { isLoading } = useAuth()
Expand Down Expand Up @@ -158,7 +174,8 @@ export function App() {
/>
)
)}
<Route path="*" element={<Navigate replace to={LOGIN_URL} />} />
{/** NOTE: Delegate remaining routing to @tanstack/router **/}
<Route path="*" element={<RouterProvider router={router} />} />
</Routes>
</AssistantContext.Provider>
</GTMProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { render } from '__tests__/utils/setup-jest'
import ProtectedRoute from '../protected-route/protected-route'
import ProtectedRoute from './protected-route'

describe('ProtectedRoute', () => {
const ProtectedComponent = () => {
Expand Down
116 changes: 3 additions & 113 deletions apps/console/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { Auth0Provider } from '@auth0/auth0-react'
import { Provider as TooltipProvider } from '@radix-ui/react-tooltip'
import {
type Mutation,
MutationCache,
type Query,
QueryCache,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
import { QueryClientProvider } from '@tanstack/react-query'
import posthog from 'posthog-js'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
Expand All @@ -17,8 +10,7 @@ import { BrowserRouter } from 'react-router-dom'
import { IntercomProvider } from 'react-use-intercom'
import { InstantSearchProvider } from '@qovery/shared/assistant/feature'
import { LOGIN_AUTH_REDIRECT_URL, LOGIN_URL } from '@qovery/shared/routes'
import { ModalProvider, ToastBehavior, toastError } from '@qovery/shared/ui'
import { ToastEnum, toast } from '@qovery/shared/ui'
import { ModalProvider, ToastBehavior } from '@qovery/shared/ui'
import {
INTERCOM,
OAUTH_AUDIENCE,
Expand All @@ -28,39 +20,7 @@ import {
POSTHOG_APIHOST,
} from '@qovery/shared/util-node-env'
import App from './app/app'

type ToastArgs = {
status?: ToastEnum
title: string
description?: string
callback?: () => void
iconAction?: string
labelAction?: string
externalLink?: string
}

interface _QueryMeta {
notifyOnSuccess?: boolean | ((data: unknown, query: Query<unknown, unknown, unknown>) => ToastArgs) | ToastArgs
notifyOnError?: boolean | { title: string; description?: string }
}

interface _MutationMeta {
notifyOnSuccess?:
| boolean
| ((
data: unknown,
variables: unknown,
context: unknown,
mutation: Mutation<unknown, unknown, unknown>
) => ToastArgs)
| ToastArgs
notifyOnError?: boolean | { title: string; description?: string }
}

declare module '@tanstack/react-query' {
interface MutationMeta extends _MutationMeta {}
interface QueryMeta extends _QueryMeta {}
}
import { queryClient } from './query-client'

// posthog init
posthog.init(POSTHOG, {
Expand All @@ -70,76 +30,6 @@ posthog.init(POSTHOG, {
const container = document.getElementById('root') || document.createElement('div')
const root = createRoot(container)

const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 60_000,
},
},
mutationCache: new MutationCache({
onSuccess(data, variables, context, mutation) {
if (mutation.meta?.notifyOnSuccess) {
if (mutation.meta.notifyOnSuccess === true) {
toast(ToastEnum.SUCCESS, JSON.stringify(data))
} else {
const {
status = ToastEnum.SUCCESS,
title,
description,
callback,
iconAction,
labelAction,
externalLink,
} = typeof mutation.meta.notifyOnSuccess === 'function'
? mutation.meta.notifyOnSuccess(data, variables, context, mutation)
: mutation.meta.notifyOnSuccess
toast(status, title, description, callback, iconAction, labelAction, externalLink)
}
}
},
onError(error, _variables, _context, mutation) {
if (mutation.meta?.notifyOnError) {
if (mutation.meta.notifyOnError === true) {
toastError(error as Error)
} else {
toastError(error as Error, mutation.meta.notifyOnError.title, mutation.meta.notifyOnError.description)
}
}
},
}),
queryCache: new QueryCache({
onSuccess(data, query) {
if (query.meta?.notifyOnSuccess) {
if (query.meta.notifyOnSuccess === true) {
toast(ToastEnum.SUCCESS, JSON.stringify(data))
} else {
const {
status = ToastEnum.SUCCESS,
title,
description,
callback,
iconAction,
labelAction,
externalLink,
} = typeof query.meta.notifyOnSuccess === 'function'
? query.meta.notifyOnSuccess(data, query)
: query.meta.notifyOnSuccess
toast(status, title, description, callback, iconAction, labelAction, externalLink)
}
}
},
onError(error, query) {
if (query.meta?.notifyOnError) {
if (query.meta.notifyOnError === true) {
toastError(error as Error)
} else {
toastError(error as Error, query.meta.notifyOnError.title, query.meta.notifyOnError.description)
}
}
},
}),
})

root.render(
<StrictMode>
<FlatProviders
Expand Down
105 changes: 105 additions & 0 deletions apps/console/src/query-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { type Mutation, MutationCache, type Query, QueryCache, QueryClient } from '@tanstack/react-query'
import { ToastEnum, toast, toastError } from '@qovery/shared/ui'

type ToastArgs = {
status?: ToastEnum
title: string
description?: string
callback?: () => void
iconAction?: string
labelAction?: string
externalLink?: string
}

interface _QueryMeta {
notifyOnSuccess?: boolean | ((data: unknown, query: Query<unknown, unknown, unknown>) => ToastArgs) | ToastArgs
notifyOnError?: boolean | { title: string; description?: string }
}

interface _MutationMeta {
notifyOnSuccess?:
| boolean
| ((
data: unknown,
variables: unknown,
context: unknown,
mutation: Mutation<unknown, unknown, unknown>
) => ToastArgs)
| ToastArgs
notifyOnError?: boolean | { title: string; description?: string }
}

declare module '@tanstack/react-query' {
interface MutationMeta extends _MutationMeta {}
interface QueryMeta extends _QueryMeta {}
}

export const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 60_000,
},
},
mutationCache: new MutationCache({
onSuccess(data, variables, context, mutation) {
if (mutation.meta?.notifyOnSuccess) {
if (mutation.meta.notifyOnSuccess === true) {
toast(ToastEnum.SUCCESS, JSON.stringify(data))
} else {
const {
status = ToastEnum.SUCCESS,
title,
description,
callback,
iconAction,
labelAction,
externalLink,
} = typeof mutation.meta.notifyOnSuccess === 'function'
? mutation.meta.notifyOnSuccess(data, variables, context, mutation)
: mutation.meta.notifyOnSuccess
toast(status, title, description, callback, iconAction, labelAction, externalLink)
}
}
},
onError(error, _variables, _context, mutation) {
if (mutation.meta?.notifyOnError) {
if (mutation.meta.notifyOnError === true) {
toastError(error as Error)
} else {
toastError(error as Error, mutation.meta.notifyOnError.title, mutation.meta.notifyOnError.description)
}
}
},
}),
queryCache: new QueryCache({
onSuccess(data, query) {
if (query.meta?.notifyOnSuccess) {
if (query.meta.notifyOnSuccess === true) {
toast(ToastEnum.SUCCESS, JSON.stringify(data))
} else {
const {
status = ToastEnum.SUCCESS,
title,
description,
callback,
iconAction,
labelAction,
externalLink,
} = typeof query.meta.notifyOnSuccess === 'function'
? query.meta.notifyOnSuccess(data, query)
: query.meta.notifyOnSuccess
toast(status, title, description, callback, iconAction, labelAction, externalLink)
}
}
},
onError(error, query) {
if (query.meta?.notifyOnError) {
if (query.meta.notifyOnError === true) {
toastError(error as Error)
} else {
toastError(error as Error, query.meta.notifyOnError.title, query.meta.notifyOnError.description)
}
}
},
}),
})
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { type ITerminalAddon } from '@xterm/xterm'
import {
type KeyboardEvent,
type MouseEvent as MouseDownEvent,
memo,
useCallback,
useContext,
useEffect,
Expand All @@ -18,8 +17,6 @@ import { useRunningStatus } from '../..'
import { InputSearch } from './input-search/input-search'
import { ServiceTerminalContext } from './service-terminal-provider'

const MemoizedXTerm = memo(XTerm)

export interface ServiceTerminalProps {
organizationId: string
clusterId: string
Expand Down Expand Up @@ -180,7 +177,7 @@ export function ServiceTerminal({
<LoaderSpinner />
</div>
) : (
<MemoizedXTerm className="h-full" onKeyUp={onKeyUpHandler} addons={addons} />
<XTerm className="h-full" onKeyUp={onKeyUpHandler} addons={addons} />
)}
</div>
</div>,
Expand Down
2 changes: 1 addition & 1 deletion libs/shared/router/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './lib/protected-route/protected-route'
export { routeTree } from './lib/route-tree.gen'
Loading
Loading