mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
feat(studio): TanStack project routes — auth/logs/settings/functions (stack 5.2/6, from #46424) (#47118)
**Stack 5.2/6** of the TanStack Start migration (#46424) — second half of the project routes (S5 was split for CodeRabbit's 150-file cap). Stacked on **#47117** (5.1). > [!NOTE] > Same shape as 5.1 — thin route wrappers over the existing pages-router components. With this PR every route is present, so `routeTree.gen.ts` is now **byte-identical to the migration branch**. ## What's in this PR - **Remaining project routes:** auth, logs, settings, observability, functions, advisors, project-level integrations. - **Supporting edits:** hoist `EdgeFunctionsIndexPageWrapper` out of `getLayout`, `functions/secrets`, and move `DefaultLayout` to the root for the logs page. - `routeTree.gen.ts` regenerated for the full set. ## Verification On top of S1–5.1: `studio` typecheck ✓, lint (0 errors) ✓, **Next build ✓ (181/181 pages)**. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Reorganized internal routing and page structure to improve navigation and maintainability across project settings, logs, functions, authentication, integrations, and observability sections. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
This commit is contained in:
97 files changed
+3637
-76
No files matched your search
@@ -2,7 +2,7 @@ import { useFlag, useParams } from 'common'
|
||||
import { ExternalLink, RefreshCw, Search, X } from 'lucide-react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { parseAsString, parseAsStringLiteral, useQueryState } from 'nuqs'
|
||||
import React, { useMemo, useRef } from 'react'
|
||||
import React, { useMemo, useRef, type PropsWithChildren } from 'react'
|
||||
import { Button, Card, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
|
||||
import { Admonition } from 'ui-patterns/admonition'
|
||||
import { Input } from 'ui-patterns/DataInputs/Input'
|
||||
@@ -231,41 +231,45 @@ const EdgeFunctionsPage: NextPageWithLayout = () => {
|
||||
)
|
||||
}
|
||||
|
||||
EdgeFunctionsPage.getLayout = (page: React.ReactElement) => {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<EdgeFunctionsLayout title="Edge Functions">
|
||||
<div className="w-full min-h-full flex flex-col items-stretch">
|
||||
<PageHeader size="large">
|
||||
<PageHeaderMeta>
|
||||
<PageHeaderSummary>
|
||||
<PageHeaderTitle>Edge Functions</PageHeaderTitle>
|
||||
<PageHeaderDescription>
|
||||
Run server-side logic close to your users
|
||||
</PageHeaderDescription>
|
||||
</PageHeaderSummary>
|
||||
<PageHeaderAside>
|
||||
<DocsButton href={`${DOCS_URL}/guides/functions`} />
|
||||
<Button asChild variant="default" icon={<ExternalLink />}>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions"
|
||||
>
|
||||
Examples
|
||||
</a>
|
||||
</Button>
|
||||
{IS_PLATFORM && <DeployEdgeFunctionButton />}
|
||||
</PageHeaderAside>
|
||||
</PageHeaderMeta>
|
||||
</PageHeader>
|
||||
// Hoisted out of `getLayout` so the TanStack route can import it
|
||||
// directly. Same body — accepts the page content as `children`.
|
||||
export const EdgeFunctionsIndexPageWrapper = ({ children }: PropsWithChildren) => (
|
||||
<>
|
||||
<div className="w-full min-h-full flex flex-col items-stretch">
|
||||
<PageHeader size="large">
|
||||
<PageHeaderMeta>
|
||||
<PageHeaderSummary>
|
||||
<PageHeaderTitle>Edge Functions</PageHeaderTitle>
|
||||
<PageHeaderDescription>Run server-side logic close to your users</PageHeaderDescription>
|
||||
</PageHeaderSummary>
|
||||
<PageHeaderAside>
|
||||
<DocsButton href={`${DOCS_URL}/guides/functions`} />
|
||||
<Button asChild variant="default" icon={<ExternalLink />}>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions"
|
||||
>
|
||||
Examples
|
||||
</a>
|
||||
</Button>
|
||||
{IS_PLATFORM && <DeployEdgeFunctionButton />}
|
||||
</PageHeaderAside>
|
||||
</PageHeaderMeta>
|
||||
</PageHeader>
|
||||
|
||||
{page}
|
||||
</div>
|
||||
</EdgeFunctionsLayout>
|
||||
<TerminalInstructionsDialog />
|
||||
</DefaultLayout>
|
||||
)
|
||||
}
|
||||
{children}
|
||||
</div>
|
||||
<TerminalInstructionsDialog />
|
||||
</>
|
||||
)
|
||||
|
||||
EdgeFunctionsPage.getLayout = (page: React.ReactElement) => (
|
||||
<DefaultLayout>
|
||||
<EdgeFunctionsLayout title="Edge Functions">
|
||||
<EdgeFunctionsIndexPageWrapper>{page}</EdgeFunctionsIndexPageWrapper>
|
||||
</EdgeFunctionsLayout>
|
||||
</DefaultLayout>
|
||||
)
|
||||
|
||||
export default EdgeFunctionsPage
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import { Admonition } from 'ui-patterns/admonition'
|
||||
import { PageContainer } from 'ui-patterns/PageContainer'
|
||||
import {
|
||||
@@ -91,27 +92,29 @@ const SecretsPage: NextPageWithLayout = () => {
|
||||
)
|
||||
}
|
||||
|
||||
SecretsPage.getLayout = (page) => {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<EdgeFunctionsLayout title="Secrets">
|
||||
<div className="w-full min-h-full flex flex-col items-stretch">
|
||||
<PageHeader size="large">
|
||||
<PageHeaderMeta>
|
||||
<PageHeaderSummary>
|
||||
<PageHeaderTitle>Edge Function Secrets</PageHeaderTitle>
|
||||
<PageHeaderDescription>
|
||||
Manage encrypted values for your functions
|
||||
</PageHeaderDescription>
|
||||
</PageHeaderSummary>
|
||||
</PageHeaderMeta>
|
||||
</PageHeader>
|
||||
// Hoisted out of `getLayout` so the TanStack route can import it
|
||||
// directly. Same body — accepts the page content as `children`.
|
||||
export const SecretsPageWrapper = ({ children }: PropsWithChildren) => (
|
||||
<div className="w-full min-h-full flex flex-col items-stretch">
|
||||
<PageHeader size="large">
|
||||
<PageHeaderMeta>
|
||||
<PageHeaderSummary>
|
||||
<PageHeaderTitle>Edge Function Secrets</PageHeaderTitle>
|
||||
<PageHeaderDescription>Manage encrypted values for your functions</PageHeaderDescription>
|
||||
</PageHeaderSummary>
|
||||
</PageHeaderMeta>
|
||||
</PageHeader>
|
||||
|
||||
{page}
|
||||
</div>
|
||||
</EdgeFunctionsLayout>
|
||||
</DefaultLayout>
|
||||
)
|
||||
}
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
SecretsPage.getLayout = (page) => (
|
||||
<DefaultLayout>
|
||||
<EdgeFunctionsLayout title="Secrets">
|
||||
<SecretsPageWrapper>{page}</SecretsPageWrapper>
|
||||
</EdgeFunctionsLayout>
|
||||
</DefaultLayout>
|
||||
)
|
||||
|
||||
export default SecretsPage
|
||||
@@ -26,29 +26,29 @@ export const LogPage: NextPageWithLayout = () => {
|
||||
|
||||
if (!logsEnabled) {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<ProjectLayout browserTitle={{ section: 'Logs' }}>
|
||||
<UnknownInterface urlBack={`/project/${ref}`} />
|
||||
</ProjectLayout>
|
||||
</DefaultLayout>
|
||||
<ProjectLayout browserTitle={{ section: 'Logs' }}>
|
||||
<UnknownInterface urlBack={`/project/${ref}`} />
|
||||
</ProjectLayout>
|
||||
)
|
||||
}
|
||||
|
||||
if (isUnifiedLogsEnabled) {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
{/* Omit the generic product segment here; project/org context already makes the route clear. */}
|
||||
<ProjectLayout browserTitle={{ section: 'Unified Logs' }}>
|
||||
<UnifiedLogs />
|
||||
</ProjectLayout>
|
||||
</DefaultLayout>
|
||||
// Omit the generic product segment here; project/org context already makes the route clear.
|
||||
<ProjectLayout browserTitle={{ section: 'Unified Logs' }}>
|
||||
<UnifiedLogs />
|
||||
</ProjectLayout>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// Don't use getLayout since we're handling layouts conditionally within the component
|
||||
LogPage.getLayout = (page) => page
|
||||
// DefaultLayout lives at the framework wrapper level, not in the page
|
||||
// body — both runtimes provide it externally (Next via `getLayout`,
|
||||
// TanStack via the parent `routes/project/$ref.tsx` shell). Wrapping it
|
||||
// inline would double-mount its SidebarProvider/ProjectContextProvider
|
||||
// chain under TanStack since the shell already supplies one.
|
||||
LogPage.getLayout = (page) => <DefaultLayout>{page}</DefaultLayout>
|
||||
|
||||
export default LogPage
|
||||
+2110
-2
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,7 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import { DefaultLayout } from '@/components/layouts/DefaultLayout'
|
||||
import { PageLayout } from '@/components/layouts/PageLayout/PageLayout'
|
||||
import WizardLayout from '@/components/layouts/WizardLayout'
|
||||
import Wizard from '@/pages/new/[slug]'
|
||||
|
||||
export const Route = createFileRoute('/new/$slug')({
|
||||
@@ -9,13 +9,18 @@ export const Route = createFileRoute('/new/$slug')({
|
||||
})
|
||||
|
||||
// Placed at top-level rather than under _app — the Next getLayout omits
|
||||
// AppLayout, and uses PageLayout (not WizardLayout) inside DefaultLayout.
|
||||
// AppLayout. The Next page wraps the wizard in a local `PageLayout` that is
|
||||
// just `withAuth(WizardLayoutWithoutAuth)` (NOT the shared PageLayout), giving
|
||||
// the centered, max-w-2xl wizard column. WizardLayout's default export is the
|
||||
// same `withAuth(WizardLayout)`, so we use it here to preserve both the auth
|
||||
// guard and that constrained width — the shared PageLayout rendered the form
|
||||
// full-width.
|
||||
function NewProjectRoute() {
|
||||
return (
|
||||
<DefaultLayout hideMobileMenu headerTitle="New project">
|
||||
<PageLayout>
|
||||
<WizardLayout>
|
||||
<Wizard dehydratedState={undefined} />
|
||||
</PageLayout>
|
||||
</WizardLayout>
|
||||
</DefaultLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { createFileRoute, Outlet, useMatches } from '@tanstack/react-router'
|
||||
|
||||
import AdvisorsLayout from '@/components/layouts/AdvisorsLayout/AdvisorsLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/advisors')({
|
||||
component: AdvisorsShell,
|
||||
})
|
||||
|
||||
type AdvisorsStaticData = {
|
||||
advisorsLayoutTitle?: string
|
||||
// The `advisors/rules` sub-shell wraps in its own <AdvisorsLayout>
|
||||
// (mirroring the existing AdvisorRulesLayout component). Without
|
||||
// opting out here we'd double-wrap.
|
||||
skipAdvisorsLayout?: boolean
|
||||
}
|
||||
|
||||
function AdvisorsShell() {
|
||||
// Scan the whole match chain — `skipAdvisorsLayout` is set on the
|
||||
// sub-shell route, not on the leaf. Same pattern as functions.tsx.
|
||||
const skip = useMatches({
|
||||
select: (matches) =>
|
||||
matches.some((m) => (m.staticData as AdvisorsStaticData | undefined)?.skipAdvisorsLayout),
|
||||
})
|
||||
const title = useMatches({
|
||||
select: (matches) =>
|
||||
(matches[matches.length - 1]?.staticData as AdvisorsStaticData | undefined)
|
||||
?.advisorsLayoutTitle ?? '',
|
||||
})
|
||||
|
||||
if (skip) return <Outlet />
|
||||
|
||||
return (
|
||||
<AdvisorsLayout title={title}>
|
||||
<Outlet />
|
||||
</AdvisorsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import AdvisorsPerformancePage from '@/pages/project/[ref]/advisors/performance'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/advisors/performance')({
|
||||
component: AdvisorsPerformanceRoute,
|
||||
staticData: {
|
||||
advisorsLayoutTitle: 'Linter',
|
||||
},
|
||||
})
|
||||
|
||||
function AdvisorsPerformanceRoute() {
|
||||
return <AdvisorsPerformancePage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
||||
import { LOCAL_STORAGE_KEYS, useParams } from 'common'
|
||||
|
||||
import { useIsAdvisorRulesEnabled } from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext'
|
||||
import AdvisorsLayout from '@/components/layouts/AdvisorsLayout/AdvisorsLayout'
|
||||
import { PageLayout } from '@/components/layouts/PageLayout/PageLayout'
|
||||
import { FeaturePreviewBadge } from '@/components/ui/FeaturePreviewBadge'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/advisors/rules')({
|
||||
component: AdvisorRulesShell,
|
||||
// Opt out of the parent advisors.tsx shell's <AdvisorsLayout> wrap
|
||||
// — we render our own with no title, plus a PageLayout tab strip,
|
||||
// mirroring the existing AdvisorRulesLayout component.
|
||||
staticData: {
|
||||
skipAdvisorsLayout: true,
|
||||
},
|
||||
})
|
||||
|
||||
// Body inlined from `components/layouts/AdvisorsLayout/AdvisorRulesLayout.tsx`
|
||||
// minus its outer <DefaultLayout> wrap (already provided by the
|
||||
// `routes/project/$ref.tsx` shell). The Next-side AdvisorRulesLayout
|
||||
// keeps working unchanged for the pages router; we duplicate the
|
||||
// PageLayout config here so the TanStack route can re-use the same
|
||||
// title + nav + feature-preview badge without coupling to the
|
||||
// component's DefaultLayout-wrapping shape.
|
||||
function AdvisorRulesShell() {
|
||||
const { ref } = useParams()
|
||||
const isAdvisorRulesEnabled = useIsAdvisorRulesEnabled()
|
||||
|
||||
return (
|
||||
<AdvisorsLayout>
|
||||
<PageLayout
|
||||
title={
|
||||
<span className="flex items-center gap-x-4">
|
||||
Advisor Settings
|
||||
{isAdvisorRulesEnabled && (
|
||||
<FeaturePreviewBadge featureKey={LOCAL_STORAGE_KEYS.UI_PREVIEW_ADVISOR_RULES} />
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
subtitle="Disable specific advisor categories or rules"
|
||||
navigationItems={[
|
||||
{
|
||||
label: 'Security',
|
||||
href: `/project/${ref}/advisors/rules/security`,
|
||||
},
|
||||
{
|
||||
label: 'Performance',
|
||||
href: `/project/${ref}/advisors/rules/performance`,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Outlet />
|
||||
</PageLayout>
|
||||
</AdvisorsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import AdvisorPerformanceRulesPage from '@/pages/project/[ref]/advisors/rules/performance'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/advisors/rules/performance')({
|
||||
component: AdvisorRulesPerformanceRoute,
|
||||
})
|
||||
|
||||
function AdvisorRulesPerformanceRoute() {
|
||||
return <AdvisorPerformanceRulesPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import AdvisorSecurityRulesPage from '@/pages/project/[ref]/advisors/rules/security'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/advisors/rules/security')({
|
||||
component: AdvisorRulesSecurityRoute,
|
||||
})
|
||||
|
||||
function AdvisorRulesSecurityRoute() {
|
||||
return <AdvisorSecurityRulesPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import AdvisorsSecurityPage from '@/pages/project/[ref]/advisors/security'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/advisors/security')({
|
||||
component: AdvisorsSecurityRoute,
|
||||
staticData: {
|
||||
advisorsLayoutTitle: 'Linter',
|
||||
},
|
||||
})
|
||||
|
||||
function AdvisorsSecurityRoute() {
|
||||
return <AdvisorsSecurityPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ApiDocsRedirect from '@/pages/project/[ref]/api/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/api/')({
|
||||
component: ProjectApiIndexRoute,
|
||||
})
|
||||
|
||||
function ProjectApiIndexRoute() {
|
||||
return <ApiDocsRedirect dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { createFileRoute, Outlet, useMatches } from '@tanstack/react-router'
|
||||
|
||||
import AuthLayout from '@/components/layouts/AuthLayout/AuthLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth')({
|
||||
component: AuthShell,
|
||||
})
|
||||
|
||||
function AuthShell() {
|
||||
// Read the two staticData fields via `select` so the shell only re-renders
|
||||
// when the actual selected values change. See routes/_app.tsx for why the
|
||||
// bare `useMatches()` form is unsafe here.
|
||||
const skipAuthLayout = useMatches({
|
||||
select: (matches) =>
|
||||
(matches[matches.length - 1]?.staticData as { skipAuthLayout?: boolean } | undefined)
|
||||
?.skipAuthLayout ?? false,
|
||||
})
|
||||
const title = useMatches({
|
||||
select: (matches) =>
|
||||
(matches[matches.length - 1]?.staticData as { authLayoutTitle?: string } | undefined)
|
||||
?.authLayoutTitle ?? '',
|
||||
})
|
||||
|
||||
// Some auth leaves wrap themselves in a sub-layout that internally already
|
||||
// includes <AuthLayout> (AuthProvidersLayout, AuthEmailsLayout, and pages
|
||||
// like third-party that inline that wrapping). Those routes set
|
||||
// `staticData.skipAuthLayout: true` and render their own Outlet chain;
|
||||
// otherwise we'd double-wrap with AuthLayout (and AuthLayout pulls in
|
||||
// withAuth + ProjectLayout, so a double-wrap is observable beyond just
|
||||
// visual nesting).
|
||||
if (skipAuthLayout) {
|
||||
return <Outlet />
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthLayout title={title}>
|
||||
<Outlet />
|
||||
</AuthLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import AuditLogsPage from '@/pages/project/[ref]/auth/audit-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/audit-logs')({
|
||||
component: AuthAuditLogsRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Audit Logs',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthAuditLogsRoute() {
|
||||
return <AuditLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import Hooks from '@/pages/project/[ref]/auth/hooks'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/hooks')({
|
||||
component: AuthHooksRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Auth Hooks',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthHooksRoute() {
|
||||
return <Hooks dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import MfaPage from '@/pages/project/[ref]/auth/mfa'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/mfa')({
|
||||
component: AuthMfaRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Multi-Factor',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthMfaRoute() {
|
||||
return <MfaPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import OAuthApps from '@/pages/project/[ref]/auth/oauth-apps'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/oauth-apps')({
|
||||
component: AuthOAuthAppsRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'OAuth Apps',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthOAuthAppsRoute() {
|
||||
return <OAuthApps dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import OAuthServerPage from '@/pages/project/[ref]/auth/oauth-server'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/oauth-server')({
|
||||
component: AuthOAuthServerRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'OAuth Server',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthOAuthServerRoute() {
|
||||
return <OAuthServerPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import AuthOverview from '@/pages/project/[ref]/auth/overview'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/overview')({
|
||||
component: AuthOverviewRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Overview',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthOverviewRoute() {
|
||||
return <AuthOverview dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PasskeysPage from '@/pages/project/[ref]/auth/passkeys'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/passkeys')({
|
||||
component: AuthPasskeysRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Passkeys',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthPasskeysRoute() {
|
||||
return <PasskeysPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PerformancePage from '@/pages/project/[ref]/auth/performance'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/performance')({
|
||||
component: AuthPerformanceRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Performance',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthPerformanceRoute() {
|
||||
return <PerformancePage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ProtectionPage from '@/pages/project/[ref]/auth/protection'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/protection')({
|
||||
component: AuthProtectionRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Attack Protection',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthProtectionRoute() {
|
||||
return <ProtectionPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import { AuthProvidersLayout } from '@/components/layouts/AuthLayout/AuthProvidersLayout'
|
||||
import ProvidersPage from '@/pages/project/[ref]/auth/providers'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/providers')({
|
||||
component: AuthProvidersRoute,
|
||||
// AuthProvidersLayout wraps in <AuthLayout> internally; the auth.tsx
|
||||
// shell skips its own AuthLayout wrap so we don't double-wrap (and
|
||||
// double withAuth + ProjectLayout).
|
||||
staticData: {
|
||||
skipAuthLayout: true,
|
||||
},
|
||||
})
|
||||
|
||||
function AuthProvidersRoute() {
|
||||
return (
|
||||
<AuthProvidersLayout>
|
||||
<ProvidersPage dehydratedState={undefined} />
|
||||
</AuthProvidersLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import RateLimitsPage from '@/pages/project/[ref]/auth/rate-limits'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/rate-limits')({
|
||||
component: AuthRateLimitsRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Rate Limits',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthRateLimitsRoute() {
|
||||
return <RateLimitsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import SessionsPage from '@/pages/project/[ref]/auth/sessions'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/sessions')({
|
||||
component: AuthSessionsRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Sessions',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthSessionsRoute() {
|
||||
return <SessionsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import { AuthEmailsLayout } from '@/components/layouts/AuthLayout/AuthEmailsLayout'
|
||||
import SmtpPage from '@/pages/project/[ref]/auth/smtp'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/smtp')({
|
||||
component: AuthSmtpRoute,
|
||||
// AuthEmailsLayout wraps in <AuthLayout> internally; opt out of the
|
||||
// auth.tsx shell wrap to avoid double-wrapping.
|
||||
staticData: {
|
||||
skipAuthLayout: true,
|
||||
},
|
||||
})
|
||||
|
||||
function AuthSmtpRoute() {
|
||||
return (
|
||||
<AuthEmailsLayout>
|
||||
<SmtpPage dehydratedState={undefined} />
|
||||
</AuthEmailsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import TemplatePage from '@/pages/project/[ref]/auth/templates/[templateId]'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/templates/$templateId')({
|
||||
component: AuthTemplateDetailRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Emails',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthTemplateDetailRoute() {
|
||||
return <TemplatePage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import { AuthEmailsLayout } from '@/components/layouts/AuthLayout/AuthEmailsLayout'
|
||||
import TemplatesPage from '@/pages/project/[ref]/auth/templates/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/templates/')({
|
||||
component: AuthTemplatesIndexRoute,
|
||||
// AuthEmailsLayout wraps in <AuthLayout> internally; opt out of the
|
||||
// auth.tsx shell wrap to avoid double-wrapping. Sibling
|
||||
// templates/$templateId.tsx does NOT use AuthEmailsLayout, so we
|
||||
// can't share a templates.tsx sub-shell — each leaf wraps itself.
|
||||
staticData: {
|
||||
skipAuthLayout: true,
|
||||
},
|
||||
})
|
||||
|
||||
function AuthTemplatesIndexRoute() {
|
||||
return (
|
||||
<AuthEmailsLayout>
|
||||
<TemplatesPage dehydratedState={undefined} />
|
||||
</AuthEmailsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ThirdPartyPage from '@/pages/project/[ref]/auth/third-party'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/third-party')({
|
||||
component: AuthThirdPartyRoute,
|
||||
// The page body wraps itself in <AuthProvidersLayout>, which already
|
||||
// includes <AuthLayout>. Tell the auth.tsx shell to skip its own
|
||||
// AuthLayout wrap so we don't double-wrap (and double withAuth +
|
||||
// ProjectLayout).
|
||||
staticData: {
|
||||
skipAuthLayout: true,
|
||||
},
|
||||
})
|
||||
|
||||
function AuthThirdPartyRoute() {
|
||||
return <ThirdPartyPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import URLConfiguration from '@/pages/project/[ref]/auth/url-configuration'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/url-configuration')({
|
||||
component: AuthUrlConfigurationRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'URL Configuration',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthUrlConfigurationRoute() {
|
||||
return <URLConfiguration dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import UsersPage from '@/pages/project/[ref]/auth/users'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/auth/users')({
|
||||
component: AuthUsersRoute,
|
||||
staticData: {
|
||||
authLayoutTitle: 'Users',
|
||||
},
|
||||
})
|
||||
|
||||
function AuthUsersRoute() {
|
||||
return <UsersPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PoliciesPage from '@/pages/project/[ref]/database/policies'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/database/policies')({
|
||||
component: DatabasePoliciesRoute,
|
||||
staticData: {
|
||||
databaseLayoutTitle: 'Policies',
|
||||
},
|
||||
})
|
||||
|
||||
function DatabasePoliciesRoute() {
|
||||
return <PoliciesPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { createFileRoute, Outlet, useMatches } from '@tanstack/react-router'
|
||||
|
||||
import EdgeFunctionsLayout from '@/components/layouts/EdgeFunctionsLayout/EdgeFunctionsLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions')({
|
||||
component: FunctionsShell,
|
||||
})
|
||||
|
||||
type FunctionsStaticData = {
|
||||
functionsLayoutTitle?: string
|
||||
// The $functionSlug routes wrap themselves in <EdgeFunctionDetailsLayout>,
|
||||
// which already renders <EdgeFunctionsLayout> internally. Without
|
||||
// opting out here we'd double-wrap.
|
||||
skipFunctionsLayout?: boolean
|
||||
}
|
||||
|
||||
function FunctionsShell() {
|
||||
// `skipFunctionsLayout` is set on the $functionSlug sub-shell's
|
||||
// staticData, not on the leaf — so checking only the leaf misses it
|
||||
// and we end up double-wrapping (`functions.tsx` adds
|
||||
// EdgeFunctionsLayout, then the sub-shell's EdgeFunctionDetailsLayout
|
||||
// wraps EdgeFunctionsLayout again internally → duplicated sidebar).
|
||||
// Scan the whole match chain instead.
|
||||
const skip = useMatches({
|
||||
select: (matches) =>
|
||||
matches.some((m) => (m.staticData as FunctionsStaticData | undefined)?.skipFunctionsLayout),
|
||||
})
|
||||
const title = useMatches({
|
||||
select: (matches) =>
|
||||
(matches[matches.length - 1]?.staticData as FunctionsStaticData | undefined)
|
||||
?.functionsLayoutTitle ?? '',
|
||||
})
|
||||
|
||||
if (skip) return <Outlet />
|
||||
|
||||
return (
|
||||
<EdgeFunctionsLayout title={title}>
|
||||
<Outlet />
|
||||
</EdgeFunctionsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { createFileRoute, Outlet, useMatches } from '@tanstack/react-router'
|
||||
|
||||
import EdgeFunctionDetailsLayout from '@/components/layouts/EdgeFunctionsLayout/EdgeFunctionDetailsLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/$functionSlug')({
|
||||
component: FunctionDetailsShell,
|
||||
// EdgeFunctionDetailsLayout already wraps <EdgeFunctionsLayout>
|
||||
// internally. Tell the parent functions.tsx shell to skip its own
|
||||
// EdgeFunctionsLayout wrap so we don't double-wrap.
|
||||
staticData: {
|
||||
skipFunctionsLayout: true,
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionDetailsShell() {
|
||||
const title = useMatches({
|
||||
select: (matches) =>
|
||||
(matches[matches.length - 1]?.staticData as { edgeFunctionDetailsTitle?: string } | undefined)
|
||||
?.edgeFunctionDetailsTitle ?? '',
|
||||
})
|
||||
|
||||
return (
|
||||
<EdgeFunctionDetailsLayout title={title}>
|
||||
<Outlet />
|
||||
</EdgeFunctionDetailsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import CodePage from '@/pages/project/[ref]/functions/[functionSlug]/code'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/$functionSlug/code')({
|
||||
component: FunctionCodeRoute,
|
||||
staticData: {
|
||||
edgeFunctionDetailsTitle: 'Code',
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionCodeRoute() {
|
||||
return <CodePage />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import FunctionDetailsPage from '@/pages/project/[ref]/functions/[functionSlug]/details'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/$functionSlug/details')({
|
||||
component: FunctionDetailsRoute,
|
||||
staticData: {
|
||||
edgeFunctionDetailsTitle: 'Settings',
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionDetailsRoute() {
|
||||
return <FunctionDetailsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import FunctionOverviewPage from '@/pages/project/[ref]/functions/[functionSlug]/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/$functionSlug/')({
|
||||
component: FunctionOverviewRoute,
|
||||
staticData: {
|
||||
edgeFunctionDetailsTitle: 'Overview',
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionOverviewRoute() {
|
||||
return <FunctionOverviewPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import FunctionInvocationsPage from '@/pages/project/[ref]/functions/[functionSlug]/invocations'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/$functionSlug/invocations')({
|
||||
component: FunctionInvocationsRoute,
|
||||
staticData: {
|
||||
edgeFunctionDetailsTitle: 'Invocations',
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionInvocationsRoute() {
|
||||
return <FunctionInvocationsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import FunctionLogsPage from '@/pages/project/[ref]/functions/[functionSlug]/logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/$functionSlug/logs')({
|
||||
component: FunctionLogsRoute,
|
||||
staticData: {
|
||||
edgeFunctionDetailsTitle: 'Logs',
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionLogsRoute() {
|
||||
return <FunctionLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import EdgeFunctionsPage, {
|
||||
EdgeFunctionsIndexPageWrapper,
|
||||
} from '@/pages/project/[ref]/functions/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/')({
|
||||
component: FunctionsIndexRoute,
|
||||
staticData: {
|
||||
functionsLayoutTitle: 'Edge Functions',
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionsIndexRoute() {
|
||||
return (
|
||||
<EdgeFunctionsIndexPageWrapper>
|
||||
<EdgeFunctionsPage dehydratedState={undefined} />
|
||||
</EdgeFunctionsIndexPageWrapper>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import NewFunctionPage from '@/pages/project/[ref]/functions/new'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/new')({
|
||||
component: FunctionsNewRoute,
|
||||
staticData: {
|
||||
functionsLayoutTitle: 'New',
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionsNewRoute() {
|
||||
return <NewFunctionPage />
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import SecretsPage, { SecretsPageWrapper } from '@/pages/project/[ref]/functions/secrets'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/functions/secrets')({
|
||||
component: FunctionsSecretsRoute,
|
||||
staticData: {
|
||||
functionsLayoutTitle: 'Secrets',
|
||||
},
|
||||
})
|
||||
|
||||
function FunctionsSecretsRoute() {
|
||||
return (
|
||||
<SecretsPageWrapper>
|
||||
<SecretsPage dehydratedState={undefined} />
|
||||
</SecretsPageWrapper>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import { ProjectLayoutWithAuth } from '@/components/layouts/ProjectLayout'
|
||||
import HomePage from '@/pages/project/[ref]/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/')({
|
||||
component: ProjectHomeRoute,
|
||||
})
|
||||
|
||||
function ProjectHomeRoute() {
|
||||
return (
|
||||
<ProjectLayoutWithAuth>
|
||||
<HomePage dehydratedState={undefined} />
|
||||
</ProjectLayoutWithAuth>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
||||
|
||||
import { ProjectIntegrationsLayout } from '@/components/layouts/ProjectIntegrationsLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/integrations')({
|
||||
component: IntegrationsShell,
|
||||
})
|
||||
|
||||
function IntegrationsShell() {
|
||||
return (
|
||||
<ProjectIntegrationsLayout>
|
||||
<Outlet />
|
||||
</ProjectIntegrationsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import IntegrationPage from '@/pages/project/[ref]/integrations/[id]/[pageId]/[childId]/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/integrations/$id/$pageId/$childId/')({
|
||||
component: IntegrationChildIdRoute,
|
||||
})
|
||||
|
||||
function IntegrationChildIdRoute() {
|
||||
return <IntegrationPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import IntegrationPage from '@/pages/project/[ref]/integrations/[id]/[pageId]/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/integrations/$id/$pageId/')({
|
||||
component: IntegrationPageIdRoute,
|
||||
})
|
||||
|
||||
function IntegrationPageIdRoute() {
|
||||
return <IntegrationPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import IntegrationPage from '@/pages/project/[ref]/integrations/[id]/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/integrations/$id/')({
|
||||
component: IntegrationIdRoute,
|
||||
})
|
||||
|
||||
function IntegrationIdRoute() {
|
||||
return <IntegrationPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import IntegrationsPage from '@/pages/project/[ref]/integrations/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/integrations/')({
|
||||
component: IntegrationsIndexRoute,
|
||||
})
|
||||
|
||||
function IntegrationsIndexRoute() {
|
||||
return <IntegrationsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createFileRoute, Outlet, useMatches } from '@tanstack/react-router'
|
||||
|
||||
import LogsLayout from '@/components/layouts/LogsLayout/LogsLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs')({
|
||||
component: LogsShell,
|
||||
})
|
||||
|
||||
type LogsStaticData = {
|
||||
logsLayoutTitle?: string
|
||||
// `logs/index` handles its own ProjectLayout-wrapped content
|
||||
// (UnifiedLogs view or no-permission interface) and only needs the
|
||||
// parent project shell's DefaultLayout — not LogsLayout. Opt out.
|
||||
skipLogsLayout?: boolean
|
||||
}
|
||||
|
||||
function LogsShell() {
|
||||
const skip = useMatches({
|
||||
select: (matches) =>
|
||||
matches.some((m) => (m.staticData as LogsStaticData | undefined)?.skipLogsLayout),
|
||||
})
|
||||
const title = useMatches({
|
||||
select: (matches) =>
|
||||
(matches[matches.length - 1]?.staticData as LogsStaticData | undefined)?.logsLayoutTitle ??
|
||||
'',
|
||||
})
|
||||
|
||||
if (skip) return <Outlet />
|
||||
|
||||
return (
|
||||
<LogsLayout title={title}>
|
||||
<Outlet />
|
||||
</LogsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import AuthLogsPage from '@/pages/project/[ref]/logs/auth-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/auth-logs')({
|
||||
component: AuthLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Auth Logs' },
|
||||
})
|
||||
|
||||
function AuthLogsRoute() {
|
||||
return <AuthLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import CronLogsPage from '@/pages/project/[ref]/logs/cron-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/cron-logs')({
|
||||
component: CronLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Cron Logs' },
|
||||
})
|
||||
|
||||
function CronLogsRoute() {
|
||||
return <CronLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import DedicatedPoolerLogsPage from '@/pages/project/[ref]/logs/dedicated-pooler-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/dedicated-pooler-logs')({
|
||||
component: DedicatedPoolerLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Dedicated Pooler Logs' },
|
||||
})
|
||||
|
||||
function DedicatedPoolerLogsRoute() {
|
||||
return <DedicatedPoolerLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import EdgeFunctionsLogsPage from '@/pages/project/[ref]/logs/edge-functions-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/edge-functions-logs')({
|
||||
component: EdgeFunctionsLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Edge Functions Logs' },
|
||||
})
|
||||
|
||||
function EdgeFunctionsLogsRoute() {
|
||||
return <EdgeFunctionsLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import EdgeLogsPage from '@/pages/project/[ref]/logs/edge-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/edge-logs')({
|
||||
component: EdgeLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Edge Logs' },
|
||||
})
|
||||
|
||||
function EdgeLogsRoute() {
|
||||
return <EdgeLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import LogsExplorerPage from '@/pages/project/[ref]/logs/explorer/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/explorer/')({
|
||||
component: LogsExplorerIndexRoute,
|
||||
staticData: { logsLayoutTitle: 'Explorer' },
|
||||
})
|
||||
|
||||
function LogsExplorerIndexRoute() {
|
||||
return <LogsExplorerPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import LogsRecentPage from '@/pages/project/[ref]/logs/explorer/recent'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/explorer/recent')({
|
||||
component: LogsExplorerRecentRoute,
|
||||
staticData: { logsLayoutTitle: 'Recent' },
|
||||
})
|
||||
|
||||
function LogsExplorerRecentRoute() {
|
||||
return <LogsRecentPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import LogsSavedPage from '@/pages/project/[ref]/logs/explorer/saved'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/explorer/saved')({
|
||||
component: LogsExplorerSavedRoute,
|
||||
staticData: { logsLayoutTitle: 'Saved' },
|
||||
})
|
||||
|
||||
function LogsExplorerSavedRoute() {
|
||||
return <LogsSavedPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import LogsTemplatesPage from '@/pages/project/[ref]/logs/explorer/templates'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/explorer/templates')({
|
||||
component: LogsExplorerTemplatesRoute,
|
||||
staticData: { logsLayoutTitle: 'Templates' },
|
||||
})
|
||||
|
||||
function LogsExplorerTemplatesRoute() {
|
||||
return <LogsTemplatesPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import LogPage from '@/pages/project/[ref]/logs/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/')({
|
||||
component: LogsIndexRoute,
|
||||
staticData: {
|
||||
// Page body wraps in its own <ProjectLayout> conditionally; LogsLayout
|
||||
// is not appropriate here.
|
||||
skipLogsLayout: true,
|
||||
},
|
||||
})
|
||||
|
||||
function LogsIndexRoute() {
|
||||
return <LogPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import MultigresLogsPage from '@/pages/project/[ref]/logs/multigres-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/multigres-logs')({
|
||||
component: MultigresLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Multigres Logs' },
|
||||
})
|
||||
|
||||
function MultigresLogsRoute() {
|
||||
return <MultigresLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PgUpgradeLogsPage from '@/pages/project/[ref]/logs/pg-upgrade-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/pg-upgrade-logs')({
|
||||
component: PgUpgradeLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Postgres Version Upgrade' },
|
||||
})
|
||||
|
||||
function PgUpgradeLogsRoute() {
|
||||
return <PgUpgradeLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PgCronLogsPage from '@/pages/project/[ref]/logs/pgcron-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/pgcron-logs')({
|
||||
component: PgCronLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'PgCron Logs' },
|
||||
})
|
||||
|
||||
function PgCronLogsRoute() {
|
||||
return <PgCronLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PoolerLogsPage from '@/pages/project/[ref]/logs/pooler-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/pooler-logs')({
|
||||
component: PoolerLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Pooler Logs' },
|
||||
})
|
||||
|
||||
function PoolerLogsRoute() {
|
||||
return <PoolerLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PostgresLogsPage from '@/pages/project/[ref]/logs/postgres-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/postgres-logs')({
|
||||
component: PostgresLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Postgres Logs' },
|
||||
})
|
||||
|
||||
function PostgresLogsRoute() {
|
||||
return <PostgresLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PostgrestLogsPage from '@/pages/project/[ref]/logs/postgrest-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/postgrest-logs')({
|
||||
component: PostgrestLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Postgrest Logs' },
|
||||
})
|
||||
|
||||
function PostgrestLogsRoute() {
|
||||
return <PostgrestLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import RealtimeLogsPage from '@/pages/project/[ref]/logs/realtime-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/realtime-logs')({
|
||||
component: RealtimeLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Realtime Logs' },
|
||||
})
|
||||
|
||||
function RealtimeLogsRoute() {
|
||||
return <RealtimeLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ReplicationLogsPage from '@/pages/project/[ref]/logs/replication-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/replication-logs')({
|
||||
component: ReplicationLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Replication Logs' },
|
||||
})
|
||||
|
||||
function ReplicationLogsRoute() {
|
||||
return <ReplicationLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import StorageLogsPage from '@/pages/project/[ref]/logs/storage-logs'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/logs/storage-logs')({
|
||||
component: StorageLogsRoute,
|
||||
staticData: { logsLayoutTitle: 'Storage Logs' },
|
||||
})
|
||||
|
||||
function StorageLogsRoute() {
|
||||
return <StorageLogsPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { createFileRoute, Outlet, useMatches } from '@tanstack/react-router'
|
||||
|
||||
import ObservabilityLayout from '@/components/layouts/ObservabilityLayout/ObservabilityLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability')({
|
||||
component: ObservabilityShell,
|
||||
})
|
||||
|
||||
function ObservabilityShell() {
|
||||
const title = useMatches({
|
||||
select: (matches) =>
|
||||
(matches[matches.length - 1]?.staticData as { observabilityLayoutTitle?: string } | undefined)
|
||||
?.observabilityLayoutTitle ?? '',
|
||||
})
|
||||
|
||||
return (
|
||||
<ObservabilityLayout title={title}>
|
||||
<Outlet />
|
||||
</ObservabilityLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ObservabilityReportPage from '@/pages/project/[ref]/observability/[id]'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/$id')({
|
||||
component: ObservabilityReportRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Report',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityReportRoute() {
|
||||
return <ObservabilityReportPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ApiReport from '@/pages/project/[ref]/observability/api-overview'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/api-overview')({
|
||||
component: ObservabilityApiOverviewRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'API Gateway',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityApiOverviewRoute() {
|
||||
return <ApiReport dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import AuthReport from '@/pages/project/[ref]/observability/auth'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/auth')({
|
||||
component: ObservabilityAuthRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Auth',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityAuthRoute() {
|
||||
return <AuthReport dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import DatabaseReport from '@/pages/project/[ref]/observability/database'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/database')({
|
||||
component: ObservabilityDatabaseRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Database',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityDatabaseRoute() {
|
||||
return <DatabaseReport dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import EdgeFunctionsReportV2 from '@/pages/project/[ref]/observability/edge-functions'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/edge-functions')({
|
||||
component: ObservabilityEdgeFunctionsRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Edge Functions',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityEdgeFunctionsRoute() {
|
||||
return <EdgeFunctionsReportV2 dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import UserReportPage from '@/pages/project/[ref]/observability/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/')({
|
||||
component: ObservabilityIndexRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Overview',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityIndexRoute() {
|
||||
return <UserReportPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import PostgRESTReport from '@/pages/project/[ref]/observability/postgrest'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/postgrest')({
|
||||
component: ObservabilityPostgRESTRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'PostgREST',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityPostgRESTRoute() {
|
||||
return <PostgRESTReport dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import QueryInsightsReport from '@/pages/project/[ref]/observability/query-insights'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/query-insights')({
|
||||
component: ObservabilityQueryInsightsRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Query insights',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityQueryInsightsRoute() {
|
||||
return <QueryInsightsReport dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import QueryPerformanceReport from '@/pages/project/[ref]/observability/query-performance'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/query-performance')({
|
||||
component: ObservabilityQueryPerformanceRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Query Performance',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityQueryPerformanceRoute() {
|
||||
return <QueryPerformanceReport dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import RealtimeReport from '@/pages/project/[ref]/observability/realtime'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/realtime')({
|
||||
component: ObservabilityRealtimeRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Realtime',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityRealtimeRoute() {
|
||||
return <RealtimeReport dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import StorageReport from '@/pages/project/[ref]/observability/storage'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/observability/storage')({
|
||||
component: ObservabilityStorageRoute,
|
||||
staticData: {
|
||||
observabilityLayoutTitle: 'Storage',
|
||||
},
|
||||
})
|
||||
|
||||
function ObservabilityStorageRoute() {
|
||||
return <StorageReport dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { createFileRoute, Outlet, useMatches } from '@tanstack/react-router'
|
||||
|
||||
import SettingsLayout from '@/components/layouts/ProjectSettingsLayout/SettingsLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings')({
|
||||
component: SettingsShell,
|
||||
})
|
||||
|
||||
type SettingsStaticData = {
|
||||
settingsLayoutTitle?: string
|
||||
// settings/api is a redirect-only page; skip the SettingsLayout wrap
|
||||
// so we don't render the sidebar around a `return null`.
|
||||
skipSettingsLayout?: boolean
|
||||
}
|
||||
|
||||
function SettingsShell() {
|
||||
const skip = useMatches({
|
||||
select: (matches) =>
|
||||
matches.some((m) => (m.staticData as SettingsStaticData | undefined)?.skipSettingsLayout),
|
||||
})
|
||||
const title = useMatches({
|
||||
select: (matches) =>
|
||||
(matches[matches.length - 1]?.staticData as SettingsStaticData | undefined)
|
||||
?.settingsLayoutTitle ?? '',
|
||||
})
|
||||
|
||||
if (skip) return <Outlet />
|
||||
|
||||
return (
|
||||
<SettingsLayout title={title}>
|
||||
<Outlet />
|
||||
</SettingsLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ProjectAddons from '@/pages/project/[ref]/settings/addons'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/addons')({
|
||||
component: SettingsAddonsRoute,
|
||||
staticData: { settingsLayoutTitle: 'Add-ons' },
|
||||
})
|
||||
|
||||
function SettingsAddonsRoute() {
|
||||
return <ProjectAddons dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
||||
|
||||
import ApiKeysLayout from '@/components/layouts/APIKeys/APIKeysLayout'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/api-keys')({
|
||||
component: ApiKeysShell,
|
||||
})
|
||||
|
||||
// Sub-shell mirroring the existing pages-router pattern: both
|
||||
// api-keys/index and api-keys/legacy wrap their content in
|
||||
// <SettingsLayout title=...><ApiKeysLayout>{page}</ApiKeysLayout></SettingsLayout>.
|
||||
// The parent settings.tsx shell handles SettingsLayout (title via the
|
||||
// leaf's `settingsLayoutTitle` staticData); this sub-shell adds the
|
||||
// ApiKeysLayout tab strip both leaves share.
|
||||
function ApiKeysShell() {
|
||||
return (
|
||||
<ApiKeysLayout>
|
||||
<Outlet />
|
||||
</ApiKeysLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ApiKeysNewPage from '@/pages/project/[ref]/settings/api-keys/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/api-keys/')({
|
||||
component: SettingsApiKeysIndexRoute,
|
||||
staticData: { settingsLayoutTitle: 'API Keys' },
|
||||
})
|
||||
|
||||
function SettingsApiKeysIndexRoute() {
|
||||
return <ApiKeysNewPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ApiKeysLegacyPage from '@/pages/project/[ref]/settings/api-keys/legacy'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/api-keys/legacy')({
|
||||
component: SettingsApiKeysLegacyRoute,
|
||||
staticData: { settingsLayoutTitle: 'API Keys (Legacy)' },
|
||||
})
|
||||
|
||||
function SettingsApiKeysLegacyRoute() {
|
||||
return <ApiKeysLegacyPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ApiSettings from '@/pages/project/[ref]/settings/api'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/api')({
|
||||
component: SettingsApiRoute,
|
||||
// Page is a useEffect redirect that returns null; SettingsLayout
|
||||
// (the sidebar shell) shouldn't render around it.
|
||||
staticData: { skipSettingsLayout: true },
|
||||
})
|
||||
|
||||
function SettingsApiRoute() {
|
||||
return <ApiSettings dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ProjectBillingUsage from '@/pages/project/[ref]/settings/billing/usage'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/billing/usage')({
|
||||
component: SettingsBillingUsageRoute,
|
||||
staticData: { settingsLayoutTitle: 'Usage' },
|
||||
})
|
||||
|
||||
function SettingsBillingUsageRoute() {
|
||||
return <ProjectBillingUsage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ComputeAndDiskPage from '@/pages/project/[ref]/settings/compute-and-disk'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/compute-and-disk')({
|
||||
component: SettingsComputeAndDiskRoute,
|
||||
staticData: { settingsLayoutTitle: 'Compute and Disk' },
|
||||
})
|
||||
|
||||
function SettingsComputeAndDiskRoute() {
|
||||
return <ComputeAndDiskPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import Preferences from '@/pages/project/[ref]/settings/dashboard'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/dashboard')({
|
||||
component: SettingsDashboardRoute,
|
||||
staticData: { settingsLayoutTitle: 'General' },
|
||||
})
|
||||
|
||||
function SettingsDashboardRoute() {
|
||||
return <Preferences dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ProjectSettings from '@/pages/project/[ref]/settings/general'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/general')({
|
||||
component: SettingsGeneralRoute,
|
||||
staticData: { settingsLayoutTitle: 'General' },
|
||||
})
|
||||
|
||||
function SettingsGeneralRoute() {
|
||||
return <ProjectSettings dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ProjectInfrastructure from '@/pages/project/[ref]/settings/infrastructure'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/infrastructure')({
|
||||
component: SettingsInfrastructureRoute,
|
||||
staticData: { settingsLayoutTitle: 'Infrastructure' },
|
||||
})
|
||||
|
||||
function SettingsInfrastructureRoute() {
|
||||
return <ProjectInfrastructure dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ProjectSettingsIntegrations from '@/pages/project/[ref]/settings/integrations'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/integrations')({
|
||||
component: SettingsIntegrationsRoute,
|
||||
staticData: { settingsLayoutTitle: 'Integrations' },
|
||||
})
|
||||
|
||||
function SettingsIntegrationsRoute() {
|
||||
return <ProjectSettingsIntegrations dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import JWTKeysLayout from '@/components/layouts/JWTKeys/JWTKeysLayout'
|
||||
import JWTSigningKeysPage from '@/pages/project/[ref]/settings/jwt/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/jwt/')({
|
||||
component: SettingsJwtIndexRoute,
|
||||
staticData: { settingsLayoutTitle: 'JWT Keys' },
|
||||
})
|
||||
|
||||
// Inline the JWTKeysLayout wrap here rather than via a `settings/jwt.tsx`
|
||||
// sub-shell — jwt/legacy doesn't use JWTKeysLayout, so a shared
|
||||
// sub-shell would wrap legacy in the wrong layout.
|
||||
function SettingsJwtIndexRoute() {
|
||||
return (
|
||||
<JWTKeysLayout>
|
||||
<JWTSigningKeysPage dehydratedState={undefined} />
|
||||
</JWTKeysLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import JWTKeysLegacyPage from '@/pages/project/[ref]/settings/jwt/legacy'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/jwt/legacy')({
|
||||
component: SettingsJwtLegacyRoute,
|
||||
staticData: { settingsLayoutTitle: 'JWT Keys (Legacy)' },
|
||||
})
|
||||
|
||||
function SettingsJwtLegacyRoute() {
|
||||
return <JWTKeysLegacyPage dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import LogDrainsSettings from '@/pages/project/[ref]/settings/log-drains'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/log-drains')({
|
||||
component: SettingsLogDrainsRoute,
|
||||
staticData: { settingsLayoutTitle: 'Log Drains' },
|
||||
})
|
||||
|
||||
function SettingsLogDrainsRoute() {
|
||||
return <LogDrainsSettings dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ProjectWebhookEndpointSettings from '@/pages/project/[ref]/settings/webhooks/[endpointId]'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/webhooks/$endpointId')({
|
||||
component: SettingsWebhooksEndpointRoute,
|
||||
staticData: { settingsLayoutTitle: 'Webhooks' },
|
||||
})
|
||||
|
||||
function SettingsWebhooksEndpointRoute() {
|
||||
return <ProjectWebhookEndpointSettings dehydratedState={undefined} />
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import ProjectWebhooksSettings from '@/pages/project/[ref]/settings/webhooks/index'
|
||||
|
||||
export const Route = createFileRoute('/project/$ref/settings/webhooks/')({
|
||||
component: SettingsWebhooksIndexRoute,
|
||||
staticData: { settingsLayoutTitle: 'Webhooks' },
|
||||
})
|
||||
|
||||
function SettingsWebhooksIndexRoute() {
|
||||
return <ProjectWebhooksSettings dehydratedState={undefined} />
|
||||
}
|
||||
Reference in new issue
Block a user