From 63b98c055d01ac1e9dbb983995742db2e7a82422 Mon Sep 17 00:00:00 2001 From: Alaister Young <10985857+alaister@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:32:02 +0800 Subject: [PATCH] chore(studio): port remaining auth pages to TanStack routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-exports sign-up, sign-in-sso, sign-in-partner, sign-in-mfa, forgot-password(-mfa), reset-password, cli/login, and the Stripe partners login page under `routes/_auth/`. Each wrapper replicates the page's `getLayout` treatment; pages that inline their own layout are rendered directly. `withAuth`-wrapped default exports stay intact. Also hardens `compat/next/link.tsx` to accept Next's `UrlObject` (`{pathname, query, hash}`) href form — sign-in.tsx uses this to forward `router.query` into SSO/sign-up links, and the old shim was coercing it to "[object Object]". Anchor attrs and `replace` now spread through; remaining Next-only props are dropped silently. --- apps/studio/TANSTACK_MIGRATION.md | 18 +- apps/studio/compat/next/link.tsx | 71 ++++++- apps/studio/routeTree.gen.ts | 190 ++++++++++++++++++ apps/studio/routes/_auth/cli/login.tsx | 12 ++ .../routes/_auth/forgot-password-mfa.tsx | 12 ++ apps/studio/routes/_auth/forgot-password.tsx | 19 ++ .../_auth/partners/stripe/projects/login.tsx | 12 ++ apps/studio/routes/_auth/reset-password.tsx | 20 ++ apps/studio/routes/_auth/sign-in-mfa.tsx | 12 ++ apps/studio/routes/_auth/sign-in-partner.tsx | 25 +++ apps/studio/routes/_auth/sign-in-sso.tsx | 20 ++ apps/studio/routes/_auth/sign-up.tsx | 16 ++ 12 files changed, 411 insertions(+), 16 deletions(-) create mode 100644 apps/studio/routes/_auth/cli/login.tsx create mode 100644 apps/studio/routes/_auth/forgot-password-mfa.tsx create mode 100644 apps/studio/routes/_auth/forgot-password.tsx create mode 100644 apps/studio/routes/_auth/partners/stripe/projects/login.tsx create mode 100644 apps/studio/routes/_auth/reset-password.tsx create mode 100644 apps/studio/routes/_auth/sign-in-mfa.tsx create mode 100644 apps/studio/routes/_auth/sign-in-partner.tsx create mode 100644 apps/studio/routes/_auth/sign-in-sso.tsx create mode 100644 apps/studio/routes/_auth/sign-up.tsx diff --git a/apps/studio/TANSTACK_MIGRATION.md b/apps/studio/TANSTACK_MIGRATION.md index d6e23a70c87..7e0d9efcad1 100644 --- a/apps/studio/TANSTACK_MIGRATION.md +++ b/apps/studio/TANSTACK_MIGRATION.md @@ -290,15 +290,15 @@ These are the layout-only TanStack files. Most hold a single product layout comp ### Auth shell — `/sign-in`, `/sign-up`, etc. - [x] A `routes/_auth/sign-in.tsx` ← `pages/sign-in.tsx` -- [ ] `routes/_auth/sign-up.tsx` ← `pages/sign-up.tsx` -- [ ] `routes/_auth/sign-in-sso.tsx` ← `pages/sign-in-sso.tsx` -- [ ] `routes/_auth/sign-in-partner.tsx` ← `pages/sign-in-partner.tsx` -- [ ] `routes/_auth/sign-in-mfa.tsx` ← `pages/sign-in-mfa.tsx` -- [ ] `routes/_auth/forgot-password.tsx` ← `pages/forgot-password.tsx` -- [ ] `routes/_auth/forgot-password-mfa.tsx` ← `pages/forgot-password-mfa.tsx` -- [ ] `routes/_auth/reset-password.tsx` ← `pages/reset-password.tsx` -- [ ] `routes/_auth/cli/login.tsx` ← `pages/cli/login.tsx` -- [ ] `routes/_auth/partners/stripe/projects/login.tsx` ← `pages/partners/stripe/projects/login.tsx` +- [x] A `routes/_auth/sign-up.tsx` ← `pages/sign-up.tsx` +- [x] A `routes/_auth/sign-in-sso.tsx` ← `pages/sign-in-sso.tsx` +- [x] A `routes/_auth/sign-in-partner.tsx` ← `pages/sign-in-partner.tsx` +- [x] A `routes/_auth/sign-in-mfa.tsx` ← `pages/sign-in-mfa.tsx` (page inlines SignInLayout) +- [x] A `routes/_auth/forgot-password.tsx` ← `pages/forgot-password.tsx` +- [x] A `routes/_auth/forgot-password-mfa.tsx` ← `pages/forgot-password-mfa.tsx` (page inlines ForgotPasswordLayout) +- [x] A `routes/_auth/reset-password.tsx` ← `pages/reset-password.tsx` (page default already withAuth-wrapped) +- [x] A `routes/_auth/cli/login.tsx` ← `pages/cli/login.tsx` (page inlines APIAuthorizationLayout, withAuth) +- [x] A `routes/_auth/partners/stripe/projects/login.tsx` ← `pages/partners/stripe/projects/login.tsx` (page inlines APIAuthorizationLayout, withAuth) ### Standalone (no shared shell) diff --git a/apps/studio/compat/next/link.tsx b/apps/studio/compat/next/link.tsx index 41e3cd6f807..7c04f5231c6 100644 --- a/apps/studio/compat/next/link.tsx +++ b/apps/studio/compat/next/link.tsx @@ -1,16 +1,73 @@ import { Link as TanStackLink } from '@tanstack/react-router' -import type { ReactNode } from 'react' +import type { AnchorHTMLAttributes, ReactNode } from 'react' -interface LinkProps { - href: string - className?: string - children?: ReactNode +// Next's Link accepts either a string `href` or a `UrlObject` ({pathname, query, hash}). +// Workspace source does both — `pages/sign-in.tsx` uses the object form to forward +// `router.query` into the SSO/sign-up links. The TanStackLink `to` prop takes a +// route string, so we flatten `UrlObject` into `pathname?search#hash` first. + +type QueryValue = string | number | boolean | string[] | undefined | null +type UrlObject = { + pathname?: string + query?: Record | string + hash?: string + search?: string } -export default function Link({ href, className, children }: LinkProps) { +interface LinkProps extends Omit, 'href'> { + href: string | UrlObject + children?: ReactNode + replace?: boolean + // Next-specific props that have no TanStack equivalent; we drop them silently. + as?: string | UrlObject + scroll?: boolean + shallow?: boolean + passHref?: boolean + prefetch?: boolean | null + locale?: string | false + legacyBehavior?: boolean +} + +function serializeQuery(query: UrlObject['query']): string { + if (!query) return '' + if (typeof query === 'string') return query.startsWith('?') ? query : `?${query}` + const params = new URLSearchParams() + for (const [key, raw] of Object.entries(query)) { + if (raw == null) continue + if (Array.isArray(raw)) { + for (const item of raw) if (item != null) params.append(key, String(item)) + } else { + params.set(key, String(raw)) + } + } + const s = params.toString() + return s ? `?${s}` : '' +} + +function resolveHref(href: string | UrlObject): string { + if (typeof href === 'string') return href + const pathname = href.pathname ?? '' + const search = href.search ?? serializeQuery(href.query) + const hash = href.hash ? (href.hash.startsWith('#') ? href.hash : `#${href.hash}`) : '' + return `${pathname}${search}${hash}` +} + +export default function Link({ + href, + as: _as, + scroll: _scroll, + shallow: _shallow, + passHref: _passHref, + prefetch: _prefetch, + locale: _locale, + legacyBehavior: _legacyBehavior, + children, + ...rest +}: LinkProps) { + const to = resolveHref(href) return ( // eslint-disable-next-line @typescript-eslint/no-explicit-any - + {children} ) diff --git a/apps/studio/routeTree.gen.ts b/apps/studio/routeTree.gen.ts index 77e7c05d953..4bafa360f67 100644 --- a/apps/studio/routeTree.gen.ts +++ b/apps/studio/routeTree.gen.ts @@ -22,13 +22,21 @@ import { Route as ApiGenerateAttachmentUrlRouteImport } from './routes/api/gener import { Route as ApiEnabledFeaturesOverridesRouteImport } from './routes/api/enabled-features-overrides' import { Route as ApiCliReleaseVersionRouteImport } from './routes/api/cli-release-version' import { Route as ApiCheckCnameRouteImport } from './routes/api/check-cname' +import { Route as AuthSignUpRouteImport } from './routes/_auth/sign-up' +import { Route as AuthSignInSsoRouteImport } from './routes/_auth/sign-in-sso' +import { Route as AuthSignInPartnerRouteImport } from './routes/_auth/sign-in-partner' +import { Route as AuthSignInMfaRouteImport } from './routes/_auth/sign-in-mfa' import { Route as AuthSignInRouteImport } from './routes/_auth/sign-in' +import { Route as AuthResetPasswordRouteImport } from './routes/_auth/reset-password' +import { Route as AuthForgotPasswordMfaRouteImport } from './routes/_auth/forgot-password-mfa' +import { Route as AuthForgotPasswordRouteImport } from './routes/_auth/forgot-password' import { Route as AppAccountRouteImport } from './routes/_app/account' import { Route as ApiConnectIndexRouteImport } from './routes/api/connect/index' import { Route as ApiIntegrationsStripeSyncRouteImport } from './routes/api/integrations/stripe-sync' import { Route as ApiEdgeFunctionsTestRouteImport } from './routes/api/edge-functions/test' import { Route as ApiContentGraphqlRouteImport } from './routes/api/content/graphql' import { Route as ApiAiDocsRouteImport } from './routes/api/ai/docs' +import { Route as AuthCliLoginRouteImport } from './routes/_auth/cli/login' import { Route as AppAccountMeRouteImport } from './routes/_app/account/me' import { Route as ApiPlatformProjectsIndexRouteImport } from './routes/api/platform/projects/index' import { Route as ApiPlatformProfileIndexRouteImport } from './routes/api/platform/profile/index' @@ -70,6 +78,7 @@ import { Route as ApiPlatformAuthRefRecoverRouteImport } from './routes/api/plat import { Route as ApiPlatformAuthRefOtpRouteImport } from './routes/api/platform/auth/$ref/otp' import { Route as ApiPlatformAuthRefMagiclinkRouteImport } from './routes/api/platform/auth/$ref/magiclink' import { Route as ApiPlatformAuthRefInviteRouteImport } from './routes/api/platform/auth/$ref/invite' +import { Route as AuthPartnersStripeProjectsLoginRouteImport } from './routes/_auth/partners/stripe/projects/login' import { Route as ApiV1ProjectsRefFunctionsIndexRouteImport } from './routes/api/v1/projects/$ref/functions/index' import { Route as ApiPlatformStorageRefBucketsIndexRouteImport } from './routes/api/platform/storage/$ref/buckets/index' import { Route as ApiPlatformPropsProjectRefIndexRouteImport } from './routes/api/platform/props/project/$ref/index' @@ -171,11 +180,46 @@ const ApiCheckCnameRoute = ApiCheckCnameRouteImport.update({ path: '/api/check-cname', getParentRoute: () => rootRouteImport, } as any) +const AuthSignUpRoute = AuthSignUpRouteImport.update({ + id: '/sign-up', + path: '/sign-up', + getParentRoute: () => AuthRoute, +} as any) +const AuthSignInSsoRoute = AuthSignInSsoRouteImport.update({ + id: '/sign-in-sso', + path: '/sign-in-sso', + getParentRoute: () => AuthRoute, +} as any) +const AuthSignInPartnerRoute = AuthSignInPartnerRouteImport.update({ + id: '/sign-in-partner', + path: '/sign-in-partner', + getParentRoute: () => AuthRoute, +} as any) +const AuthSignInMfaRoute = AuthSignInMfaRouteImport.update({ + id: '/sign-in-mfa', + path: '/sign-in-mfa', + getParentRoute: () => AuthRoute, +} as any) const AuthSignInRoute = AuthSignInRouteImport.update({ id: '/sign-in', path: '/sign-in', getParentRoute: () => AuthRoute, } as any) +const AuthResetPasswordRoute = AuthResetPasswordRouteImport.update({ + id: '/reset-password', + path: '/reset-password', + getParentRoute: () => AuthRoute, +} as any) +const AuthForgotPasswordMfaRoute = AuthForgotPasswordMfaRouteImport.update({ + id: '/forgot-password-mfa', + path: '/forgot-password-mfa', + getParentRoute: () => AuthRoute, +} as any) +const AuthForgotPasswordRoute = AuthForgotPasswordRouteImport.update({ + id: '/forgot-password', + path: '/forgot-password', + getParentRoute: () => AuthRoute, +} as any) const AppAccountRoute = AppAccountRouteImport.update({ id: '/account', path: '/account', @@ -207,6 +251,11 @@ const ApiAiDocsRoute = ApiAiDocsRouteImport.update({ path: '/api/ai/docs', getParentRoute: () => rootRouteImport, } as any) +const AuthCliLoginRoute = AuthCliLoginRouteImport.update({ + id: '/cli/login', + path: '/cli/login', + getParentRoute: () => AuthRoute, +} as any) const AppAccountMeRoute = AppAccountMeRouteImport.update({ id: '/me', path: '/me', @@ -438,6 +487,12 @@ const ApiPlatformAuthRefInviteRoute = path: '/api/platform/auth/$ref/invite', getParentRoute: () => rootRouteImport, } as any) +const AuthPartnersStripeProjectsLoginRoute = + AuthPartnersStripeProjectsLoginRouteImport.update({ + id: '/partners/stripe/projects/login', + path: '/partners/stripe/projects/login', + getParentRoute: () => AuthRoute, + } as any) const ApiV1ProjectsRefFunctionsIndexRoute = ApiV1ProjectsRefFunctionsIndexRouteImport.update({ id: '/api/v1/projects/$ref/functions/', @@ -652,7 +707,14 @@ const ApiPlatformStorageRefBucketsIdObjectsDownloadRoute = export interface FileRoutesByFullPath { '/': typeof IndexRoute '/account': typeof AppAccountRouteWithChildren + '/forgot-password': typeof AuthForgotPasswordRoute + '/forgot-password-mfa': typeof AuthForgotPasswordMfaRoute + '/reset-password': typeof AuthResetPasswordRoute '/sign-in': typeof AuthSignInRoute + '/sign-in-mfa': typeof AuthSignInMfaRoute + '/sign-in-partner': typeof AuthSignInPartnerRoute + '/sign-in-sso': typeof AuthSignInSsoRoute + '/sign-up': typeof AuthSignUpRoute '/api/check-cname': typeof ApiCheckCnameRoute '/api/cli-release-version': typeof ApiCliReleaseVersionRoute '/api/enabled-features-overrides': typeof ApiEnabledFeaturesOverridesRoute @@ -664,6 +726,7 @@ export interface FileRoutesByFullPath { '/api/incident-status': typeof ApiIncidentStatusRoute '/api/status-override': typeof ApiStatusOverrideRoute '/account/me': typeof AppAccountMeRoute + '/cli/login': typeof AuthCliLoginRoute '/api/ai/docs': typeof ApiAiDocsRoute '/api/content/graphql': typeof ApiContentGraphqlRoute '/api/edge-functions/test': typeof ApiEdgeFunctionsTestRoute @@ -684,6 +747,7 @@ export interface FileRoutesByFullPath { '/api/platform/organizations/': typeof ApiPlatformOrganizationsIndexRoute '/api/platform/profile/': typeof ApiPlatformProfileIndexRoute '/api/platform/projects/': typeof ApiPlatformProjectsIndexRoute + '/partners/stripe/projects/login': typeof AuthPartnersStripeProjectsLoginRoute '/api/platform/auth/$ref/invite': typeof ApiPlatformAuthRefInviteRoute '/api/platform/auth/$ref/magiclink': typeof ApiPlatformAuthRefMagiclinkRoute '/api/platform/auth/$ref/otp': typeof ApiPlatformAuthRefOtpRoute @@ -748,7 +812,14 @@ export interface FileRoutesByFullPath { export interface FileRoutesByTo { '/': typeof IndexRoute '/account': typeof AppAccountRouteWithChildren + '/forgot-password': typeof AuthForgotPasswordRoute + '/forgot-password-mfa': typeof AuthForgotPasswordMfaRoute + '/reset-password': typeof AuthResetPasswordRoute '/sign-in': typeof AuthSignInRoute + '/sign-in-mfa': typeof AuthSignInMfaRoute + '/sign-in-partner': typeof AuthSignInPartnerRoute + '/sign-in-sso': typeof AuthSignInSsoRoute + '/sign-up': typeof AuthSignUpRoute '/api/check-cname': typeof ApiCheckCnameRoute '/api/cli-release-version': typeof ApiCliReleaseVersionRoute '/api/enabled-features-overrides': typeof ApiEnabledFeaturesOverridesRoute @@ -760,6 +831,7 @@ export interface FileRoutesByTo { '/api/incident-status': typeof ApiIncidentStatusRoute '/api/status-override': typeof ApiStatusOverrideRoute '/account/me': typeof AppAccountMeRoute + '/cli/login': typeof AuthCliLoginRoute '/api/ai/docs': typeof ApiAiDocsRoute '/api/content/graphql': typeof ApiContentGraphqlRoute '/api/edge-functions/test': typeof ApiEdgeFunctionsTestRoute @@ -780,6 +852,7 @@ export interface FileRoutesByTo { '/api/platform/organizations': typeof ApiPlatformOrganizationsIndexRoute '/api/platform/profile': typeof ApiPlatformProfileIndexRoute '/api/platform/projects': typeof ApiPlatformProjectsIndexRoute + '/partners/stripe/projects/login': typeof AuthPartnersStripeProjectsLoginRoute '/api/platform/auth/$ref/invite': typeof ApiPlatformAuthRefInviteRoute '/api/platform/auth/$ref/magiclink': typeof ApiPlatformAuthRefMagiclinkRoute '/api/platform/auth/$ref/otp': typeof ApiPlatformAuthRefOtpRoute @@ -847,7 +920,14 @@ export interface FileRoutesById { '/_app': typeof AppRouteWithChildren '/_auth': typeof AuthRouteWithChildren '/_app/account': typeof AppAccountRouteWithChildren + '/_auth/forgot-password': typeof AuthForgotPasswordRoute + '/_auth/forgot-password-mfa': typeof AuthForgotPasswordMfaRoute + '/_auth/reset-password': typeof AuthResetPasswordRoute '/_auth/sign-in': typeof AuthSignInRoute + '/_auth/sign-in-mfa': typeof AuthSignInMfaRoute + '/_auth/sign-in-partner': typeof AuthSignInPartnerRoute + '/_auth/sign-in-sso': typeof AuthSignInSsoRoute + '/_auth/sign-up': typeof AuthSignUpRoute '/api/check-cname': typeof ApiCheckCnameRoute '/api/cli-release-version': typeof ApiCliReleaseVersionRoute '/api/enabled-features-overrides': typeof ApiEnabledFeaturesOverridesRoute @@ -859,6 +939,7 @@ export interface FileRoutesById { '/api/incident-status': typeof ApiIncidentStatusRoute '/api/status-override': typeof ApiStatusOverrideRoute '/_app/account/me': typeof AppAccountMeRoute + '/_auth/cli/login': typeof AuthCliLoginRoute '/api/ai/docs': typeof ApiAiDocsRoute '/api/content/graphql': typeof ApiContentGraphqlRoute '/api/edge-functions/test': typeof ApiEdgeFunctionsTestRoute @@ -879,6 +960,7 @@ export interface FileRoutesById { '/api/platform/organizations/': typeof ApiPlatformOrganizationsIndexRoute '/api/platform/profile/': typeof ApiPlatformProfileIndexRoute '/api/platform/projects/': typeof ApiPlatformProjectsIndexRoute + '/_auth/partners/stripe/projects/login': typeof AuthPartnersStripeProjectsLoginRoute '/api/platform/auth/$ref/invite': typeof ApiPlatformAuthRefInviteRoute '/api/platform/auth/$ref/magiclink': typeof ApiPlatformAuthRefMagiclinkRoute '/api/platform/auth/$ref/otp': typeof ApiPlatformAuthRefOtpRoute @@ -945,7 +1027,14 @@ export interface FileRouteTypes { fullPaths: | '/' | '/account' + | '/forgot-password' + | '/forgot-password-mfa' + | '/reset-password' | '/sign-in' + | '/sign-in-mfa' + | '/sign-in-partner' + | '/sign-in-sso' + | '/sign-up' | '/api/check-cname' | '/api/cli-release-version' | '/api/enabled-features-overrides' @@ -957,6 +1046,7 @@ export interface FileRouteTypes { | '/api/incident-status' | '/api/status-override' | '/account/me' + | '/cli/login' | '/api/ai/docs' | '/api/content/graphql' | '/api/edge-functions/test' @@ -977,6 +1067,7 @@ export interface FileRouteTypes { | '/api/platform/organizations/' | '/api/platform/profile/' | '/api/platform/projects/' + | '/partners/stripe/projects/login' | '/api/platform/auth/$ref/invite' | '/api/platform/auth/$ref/magiclink' | '/api/platform/auth/$ref/otp' @@ -1041,7 +1132,14 @@ export interface FileRouteTypes { to: | '/' | '/account' + | '/forgot-password' + | '/forgot-password-mfa' + | '/reset-password' | '/sign-in' + | '/sign-in-mfa' + | '/sign-in-partner' + | '/sign-in-sso' + | '/sign-up' | '/api/check-cname' | '/api/cli-release-version' | '/api/enabled-features-overrides' @@ -1053,6 +1151,7 @@ export interface FileRouteTypes { | '/api/incident-status' | '/api/status-override' | '/account/me' + | '/cli/login' | '/api/ai/docs' | '/api/content/graphql' | '/api/edge-functions/test' @@ -1073,6 +1172,7 @@ export interface FileRouteTypes { | '/api/platform/organizations' | '/api/platform/profile' | '/api/platform/projects' + | '/partners/stripe/projects/login' | '/api/platform/auth/$ref/invite' | '/api/platform/auth/$ref/magiclink' | '/api/platform/auth/$ref/otp' @@ -1139,7 +1239,14 @@ export interface FileRouteTypes { | '/_app' | '/_auth' | '/_app/account' + | '/_auth/forgot-password' + | '/_auth/forgot-password-mfa' + | '/_auth/reset-password' | '/_auth/sign-in' + | '/_auth/sign-in-mfa' + | '/_auth/sign-in-partner' + | '/_auth/sign-in-sso' + | '/_auth/sign-up' | '/api/check-cname' | '/api/cli-release-version' | '/api/enabled-features-overrides' @@ -1151,6 +1258,7 @@ export interface FileRouteTypes { | '/api/incident-status' | '/api/status-override' | '/_app/account/me' + | '/_auth/cli/login' | '/api/ai/docs' | '/api/content/graphql' | '/api/edge-functions/test' @@ -1171,6 +1279,7 @@ export interface FileRouteTypes { | '/api/platform/organizations/' | '/api/platform/profile/' | '/api/platform/projects/' + | '/_auth/partners/stripe/projects/login' | '/api/platform/auth/$ref/invite' | '/api/platform/auth/$ref/magiclink' | '/api/platform/auth/$ref/otp' @@ -1421,6 +1530,34 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ApiCheckCnameRouteImport parentRoute: typeof rootRouteImport } + '/_auth/sign-up': { + id: '/_auth/sign-up' + path: '/sign-up' + fullPath: '/sign-up' + preLoaderRoute: typeof AuthSignUpRouteImport + parentRoute: typeof AuthRoute + } + '/_auth/sign-in-sso': { + id: '/_auth/sign-in-sso' + path: '/sign-in-sso' + fullPath: '/sign-in-sso' + preLoaderRoute: typeof AuthSignInSsoRouteImport + parentRoute: typeof AuthRoute + } + '/_auth/sign-in-partner': { + id: '/_auth/sign-in-partner' + path: '/sign-in-partner' + fullPath: '/sign-in-partner' + preLoaderRoute: typeof AuthSignInPartnerRouteImport + parentRoute: typeof AuthRoute + } + '/_auth/sign-in-mfa': { + id: '/_auth/sign-in-mfa' + path: '/sign-in-mfa' + fullPath: '/sign-in-mfa' + preLoaderRoute: typeof AuthSignInMfaRouteImport + parentRoute: typeof AuthRoute + } '/_auth/sign-in': { id: '/_auth/sign-in' path: '/sign-in' @@ -1428,6 +1565,27 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthSignInRouteImport parentRoute: typeof AuthRoute } + '/_auth/reset-password': { + id: '/_auth/reset-password' + path: '/reset-password' + fullPath: '/reset-password' + preLoaderRoute: typeof AuthResetPasswordRouteImport + parentRoute: typeof AuthRoute + } + '/_auth/forgot-password-mfa': { + id: '/_auth/forgot-password-mfa' + path: '/forgot-password-mfa' + fullPath: '/forgot-password-mfa' + preLoaderRoute: typeof AuthForgotPasswordMfaRouteImport + parentRoute: typeof AuthRoute + } + '/_auth/forgot-password': { + id: '/_auth/forgot-password' + path: '/forgot-password' + fullPath: '/forgot-password' + preLoaderRoute: typeof AuthForgotPasswordRouteImport + parentRoute: typeof AuthRoute + } '/_app/account': { id: '/_app/account' path: '/account' @@ -1470,6 +1628,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ApiAiDocsRouteImport parentRoute: typeof rootRouteImport } + '/_auth/cli/login': { + id: '/_auth/cli/login' + path: '/cli/login' + fullPath: '/cli/login' + preLoaderRoute: typeof AuthCliLoginRouteImport + parentRoute: typeof AuthRoute + } '/_app/account/me': { id: '/_app/account/me' path: '/me' @@ -1757,6 +1922,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ApiPlatformAuthRefInviteRouteImport parentRoute: typeof rootRouteImport } + '/_auth/partners/stripe/projects/login': { + id: '/_auth/partners/stripe/projects/login' + path: '/partners/stripe/projects/login' + fullPath: '/partners/stripe/projects/login' + preLoaderRoute: typeof AuthPartnersStripeProjectsLoginRouteImport + parentRoute: typeof AuthRoute + } '/api/v1/projects/$ref/functions/': { id: '/api/v1/projects/$ref/functions/' path: '/api/v1/projects/$ref/functions' @@ -2028,11 +2200,29 @@ const AppRouteChildren: AppRouteChildren = { const AppRouteWithChildren = AppRoute._addFileChildren(AppRouteChildren) interface AuthRouteChildren { + AuthForgotPasswordRoute: typeof AuthForgotPasswordRoute + AuthForgotPasswordMfaRoute: typeof AuthForgotPasswordMfaRoute + AuthResetPasswordRoute: typeof AuthResetPasswordRoute AuthSignInRoute: typeof AuthSignInRoute + AuthSignInMfaRoute: typeof AuthSignInMfaRoute + AuthSignInPartnerRoute: typeof AuthSignInPartnerRoute + AuthSignInSsoRoute: typeof AuthSignInSsoRoute + AuthSignUpRoute: typeof AuthSignUpRoute + AuthCliLoginRoute: typeof AuthCliLoginRoute + AuthPartnersStripeProjectsLoginRoute: typeof AuthPartnersStripeProjectsLoginRoute } const AuthRouteChildren: AuthRouteChildren = { + AuthForgotPasswordRoute: AuthForgotPasswordRoute, + AuthForgotPasswordMfaRoute: AuthForgotPasswordMfaRoute, + AuthResetPasswordRoute: AuthResetPasswordRoute, AuthSignInRoute: AuthSignInRoute, + AuthSignInMfaRoute: AuthSignInMfaRoute, + AuthSignInPartnerRoute: AuthSignInPartnerRoute, + AuthSignInSsoRoute: AuthSignInSsoRoute, + AuthSignUpRoute: AuthSignUpRoute, + AuthCliLoginRoute: AuthCliLoginRoute, + AuthPartnersStripeProjectsLoginRoute: AuthPartnersStripeProjectsLoginRoute, } const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren) diff --git a/apps/studio/routes/_auth/cli/login.tsx b/apps/studio/routes/_auth/cli/login.tsx new file mode 100644 index 00000000000..ea50cb77a3f --- /dev/null +++ b/apps/studio/routes/_auth/cli/login.tsx @@ -0,0 +1,12 @@ +import { createFileRoute } from '@tanstack/react-router' + +import CliLoginPage from '@/pages/cli/login' + +export const Route = createFileRoute('/_auth/cli/login')({ + component: CliLogin, +}) + +function CliLogin() { + // Next page default export is already wrapped in withAuth and inlines APIAuthorizationLayout. + return +} diff --git a/apps/studio/routes/_auth/forgot-password-mfa.tsx b/apps/studio/routes/_auth/forgot-password-mfa.tsx new file mode 100644 index 00000000000..7cf36e9e381 --- /dev/null +++ b/apps/studio/routes/_auth/forgot-password-mfa.tsx @@ -0,0 +1,12 @@ +import { createFileRoute } from '@tanstack/react-router' + +import ForgotPasswordMfaPage from '@/pages/forgot-password-mfa' + +export const Route = createFileRoute('/_auth/forgot-password-mfa')({ + component: ForgotPasswordMfa, +}) + +function ForgotPasswordMfa() { + // The Next page inlines its own ForgotPasswordLayout; just render it. + return +} diff --git a/apps/studio/routes/_auth/forgot-password.tsx b/apps/studio/routes/_auth/forgot-password.tsx new file mode 100644 index 00000000000..972fca8403e --- /dev/null +++ b/apps/studio/routes/_auth/forgot-password.tsx @@ -0,0 +1,19 @@ +import { createFileRoute } from '@tanstack/react-router' + +import ForgotPasswordLayout from '@/components/layouts/SignInLayout/ForgotPasswordLayout' +import ForgotPasswordPage from '@/pages/forgot-password' + +export const Route = createFileRoute('/_auth/forgot-password')({ + component: ForgotPassword, +}) + +function ForgotPassword() { + return ( + + + + ) +} diff --git a/apps/studio/routes/_auth/partners/stripe/projects/login.tsx b/apps/studio/routes/_auth/partners/stripe/projects/login.tsx new file mode 100644 index 00000000000..401e9bff32f --- /dev/null +++ b/apps/studio/routes/_auth/partners/stripe/projects/login.tsx @@ -0,0 +1,12 @@ +import { createFileRoute } from '@tanstack/react-router' + +import StripeProjectsLoginPage from '@/pages/partners/stripe/projects/login' + +export const Route = createFileRoute('/_auth/partners/stripe/projects/login')({ + component: StripeProjectsLogin, +}) + +function StripeProjectsLogin() { + // Next page default export is already wrapped in withAuth and inlines APIAuthorizationLayout. + return +} diff --git a/apps/studio/routes/_auth/reset-password.tsx b/apps/studio/routes/_auth/reset-password.tsx new file mode 100644 index 00000000000..1dfa162a0b9 --- /dev/null +++ b/apps/studio/routes/_auth/reset-password.tsx @@ -0,0 +1,20 @@ +import { createFileRoute } from '@tanstack/react-router' + +import ForgotPasswordLayout from '@/components/layouts/SignInLayout/ForgotPasswordLayout' +import ResetPasswordPage from '@/pages/reset-password' + +export const Route = createFileRoute('/_auth/reset-password')({ + component: ResetPassword, +}) + +function ResetPassword() { + // Next page default export is already wrapped in withAuth — session guard runs inline. + return ( + + + + ) +} diff --git a/apps/studio/routes/_auth/sign-in-mfa.tsx b/apps/studio/routes/_auth/sign-in-mfa.tsx new file mode 100644 index 00000000000..b6d80932270 --- /dev/null +++ b/apps/studio/routes/_auth/sign-in-mfa.tsx @@ -0,0 +1,12 @@ +import { createFileRoute } from '@tanstack/react-router' + +import SignInMfaPage from '@/pages/sign-in-mfa' + +export const Route = createFileRoute('/_auth/sign-in-mfa')({ + component: SignInMfa, +}) + +function SignInMfa() { + // The Next page inlines its own SignInLayout; just render it. + return +} diff --git a/apps/studio/routes/_auth/sign-in-partner.tsx b/apps/studio/routes/_auth/sign-in-partner.tsx new file mode 100644 index 00000000000..a2fe1fbcdb5 --- /dev/null +++ b/apps/studio/routes/_auth/sign-in-partner.tsx @@ -0,0 +1,25 @@ +import { createFileRoute } from '@tanstack/react-router' +import { cn } from 'ui' + +import ForgotPasswordLayout from '@/components/layouts/SignInLayout/ForgotPasswordLayout' +import SignInPartnerPage from '@/pages/sign-in-partner' + +export const Route = createFileRoute('/_auth/sign-in-partner')({ + component: SignInPartner, +}) + +function SignInPartner() { + return ( + // [Joshen] Just using this layout for the styling + div:first-child]:absolute [&>div:first-child]:!px-0', + '[&>div:last-child]:flex-grow [&>div:last-child>main]:!px-0' + )} + > + + + ) +} diff --git a/apps/studio/routes/_auth/sign-in-sso.tsx b/apps/studio/routes/_auth/sign-in-sso.tsx new file mode 100644 index 00000000000..28b894c309b --- /dev/null +++ b/apps/studio/routes/_auth/sign-in-sso.tsx @@ -0,0 +1,20 @@ +import { createFileRoute } from '@tanstack/react-router' + +import SignInLayout from '@/components/layouts/SignInLayout/SignInLayout' +import SignInSSOPage from '@/pages/sign-in-sso' + +export const Route = createFileRoute('/_auth/sign-in-sso')({ + component: SignInSSO, +}) + +function SignInSSO() { + return ( + + + + ) +} diff --git a/apps/studio/routes/_auth/sign-up.tsx b/apps/studio/routes/_auth/sign-up.tsx new file mode 100644 index 00000000000..60b17cfa4c0 --- /dev/null +++ b/apps/studio/routes/_auth/sign-up.tsx @@ -0,0 +1,16 @@ +import { createFileRoute } from '@tanstack/react-router' + +import SignInLayout from '@/components/layouts/SignInLayout/SignInLayout' +import SignUpPage from '@/pages/sign-up' + +export const Route = createFileRoute('/_auth/sign-up')({ + component: SignUp, +}) + +function SignUp() { + return ( + + + + ) +}