From 4d62c6d509c449be683d5b27fe3dc45c11052115 Mon Sep 17 00:00:00 2001 From: Ali Waseem Date: Thu, 6 Nov 2025 14:37:11 -0800 Subject: [PATCH 1/7] Fix: updated critical path errors within studio (#40216) * updated Sentry critical path erroring * removed unneeded return --- .../interfaces/SignIn/ResetPasswordForm.tsx | 11 +- .../interfaces/SignIn/SignInForm.tsx | 4 +- .../interfaces/SignIn/SignInSSOForm.tsx | 9 +- .../interfaces/SignIn/SignInWithCustom.tsx | 4 +- .../interfaces/SignIn/SignInWithGitHub.tsx | 4 +- .../data/misc/reset-password-mutation.ts | 8 +- apps/studio/data/misc/signup-mutation.ts | 14 +-- .../mfa-challenge-and-verify-mutation.ts | 8 +- .../data/projects/project-create-mutation.ts | 16 +-- apps/studio/lib/error-reporting.ts | 115 ++++++++++++++++++ 10 files changed, 133 insertions(+), 60 deletions(-) create mode 100644 apps/studio/lib/error-reporting.ts diff --git a/apps/studio/components/interfaces/SignIn/ResetPasswordForm.tsx b/apps/studio/components/interfaces/SignIn/ResetPasswordForm.tsx index 48e513fe0e82a..2d2955982c7eb 100644 --- a/apps/studio/components/interfaces/SignIn/ResetPasswordForm.tsx +++ b/apps/studio/components/interfaces/SignIn/ResetPasswordForm.tsx @@ -1,5 +1,4 @@ import { zodResolver } from '@hookform/resolvers/zod' -import * as Sentry from '@sentry/nextjs' import { Eye, EyeOff } from 'lucide-react' import { useRouter } from 'next/router' import { useState } from 'react' @@ -7,6 +6,7 @@ import { useForm } from 'react-hook-form' import { toast } from 'sonner' import { z } from 'zod' +import { captureCriticalError } from 'lib/error-reporting' import { auth, getReturnToPath } from 'lib/gotrue' import { Button, @@ -20,11 +20,6 @@ import { import PasswordConditionsHelper from './PasswordConditionsHelper' -const WHITELIST_ERRORS = [ - 'New password should be different from the old password', - 'Password is known to be weak and easy to guess, please choose a different one', -] - // Convert the existing yup passwordSchema to Zod const passwordSchema = z.object({ password: z @@ -70,9 +65,7 @@ const ResetPasswordForm = () => { await router.push(getReturnToPath('/organizations')) } else { toast.error(`Failed to save password: ${error.message}`, { id: toastId }) - if (!WHITELIST_ERRORS.some((e) => error.message.includes(e))) { - Sentry.captureMessage('[CRITICAL] Failed to reset password: ' + error.message) - } + captureCriticalError(error, 'reset password') } } diff --git a/apps/studio/components/interfaces/SignIn/SignInForm.tsx b/apps/studio/components/interfaces/SignIn/SignInForm.tsx index 80ebf5f4923e2..e753bd354033c 100644 --- a/apps/studio/components/interfaces/SignIn/SignInForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInForm.tsx @@ -1,6 +1,5 @@ import HCaptcha from '@hcaptcha/react-hcaptcha' import { zodResolver } from '@hookform/resolvers/zod' -import * as Sentry from '@sentry/nextjs' import type { AuthError } from '@supabase/supabase-js' import { useQueryClient } from '@tanstack/react-query' import Link from 'next/link' @@ -14,6 +13,7 @@ import { useAddLoginEvent } from 'data/misc/audit-login-mutation' import { getMfaAuthenticatorAssuranceLevel } from 'data/profile/mfa-authenticator-assurance-level-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useLastSignIn } from 'hooks/misc/useLastSignIn' +import { captureCriticalError } from 'lib/error-reporting' import { auth, buildPathWithParams, getReturnToPath } from 'lib/gotrue' import { Button, Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, Input_Shadcn_ } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' @@ -101,7 +101,7 @@ export const SignInForm = () => { router.push(redirectPath) } catch (error: any) { toast.error(`Failed to sign in: ${(error as AuthError).message}`, { id: toastId }) - Sentry.captureMessage('[CRITICAL] Failed to sign in via EP: ' + error.message) + captureCriticalError(error, 'sign in via EP') } } else { setCaptchaToken(null) diff --git a/apps/studio/components/interfaces/SignIn/SignInSSOForm.tsx b/apps/studio/components/interfaces/SignIn/SignInSSOForm.tsx index e013886331799..854fcae40f58a 100644 --- a/apps/studio/components/interfaces/SignIn/SignInSSOForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInSSOForm.tsx @@ -1,6 +1,5 @@ import HCaptcha from '@hcaptcha/react-hcaptcha' import { zodResolver } from '@hookform/resolvers/zod' -import * as Sentry from '@sentry/nextjs' import { useQueryClient } from '@tanstack/react-query' import { useRef, useState } from 'react' import { type SubmitHandler, useForm } from 'react-hook-form' @@ -9,12 +8,11 @@ import z from 'zod' import { useLastSignIn } from 'hooks/misc/useLastSignIn' import { BASE_PATH } from 'lib/constants' +import { captureCriticalError } from 'lib/error-reporting' import { auth, buildPathWithParams } from 'lib/gotrue' import { Button, Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, Input_Shadcn_ } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' -const WHITELIST_ERRORS = ['No SSO provider assigned for this domain'] - const schema = z.object({ email: z.string().min(1, 'Email is required').email('Must be a valid email'), }) @@ -69,10 +67,7 @@ export const SignInSSOForm = () => { setCaptchaToken(null) captchaRef.current?.resetCaptcha() toast.error(`Failed to sign in: ${error.message}`, { id: toastId }) - - if (!WHITELIST_ERRORS.includes(error.message)) { - Sentry.captureMessage('[CRITICAL] Failed to sign in via SSO: ' + error.message) - } + captureCriticalError(error, 'sign in via SSO') } } diff --git a/apps/studio/components/interfaces/SignIn/SignInWithCustom.tsx b/apps/studio/components/interfaces/SignIn/SignInWithCustom.tsx index 03730971fce64..f5959dd23ceed 100644 --- a/apps/studio/components/interfaces/SignIn/SignInWithCustom.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInWithCustom.tsx @@ -1,8 +1,8 @@ -import * as Sentry from '@sentry/nextjs' import { useState } from 'react' import { toast } from 'sonner' import { BASE_PATH } from 'lib/constants' +import { captureCriticalError } from 'lib/error-reporting' import { auth, buildPathWithParams } from 'lib/gotrue' import { Button } from 'ui' @@ -35,7 +35,7 @@ export const SignInWithCustom = ({ providerName }: SignInWithCustomProps) => { if (error) throw error } catch (error: any) { toast.error(`Failed to sign in via ${providerName}: ${error.message}`) - Sentry.captureMessage('[CRITICAL] Failed to sign in via GH: ' + error.message) + captureCriticalError(error, `sign in via ${providerName}`) setLoading(false) } } diff --git a/apps/studio/components/interfaces/SignIn/SignInWithGitHub.tsx b/apps/studio/components/interfaces/SignIn/SignInWithGitHub.tsx index 715b945721a5d..3431b56c89ef2 100644 --- a/apps/studio/components/interfaces/SignIn/SignInWithGitHub.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInWithGitHub.tsx @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/nextjs' import { Github } from 'lucide-react' import { useState } from 'react' import { toast } from 'sonner' @@ -6,6 +5,7 @@ import { toast } from 'sonner' import { BASE_PATH } from 'lib/constants' import { useLastSignIn } from 'hooks/misc/useLastSignIn' +import { captureCriticalError } from 'lib/error-reporting' import { auth, buildPathWithParams } from 'lib/gotrue' import { Button } from 'ui' import { LastSignInWrapper } from './LastSignInWrapper' @@ -36,7 +36,7 @@ export const SignInWithGitHub = () => { else setLastSignInUsed('github') } catch (error: any) { toast.error(`Failed to sign in via GitHub: ${error.message}`) - Sentry.captureMessage('[CRITICAL] Failed to sign in via GH: ' + error.message) + captureCriticalError(error, 'sign in via GitHub') setLoading(false) } } diff --git a/apps/studio/data/misc/reset-password-mutation.ts b/apps/studio/data/misc/reset-password-mutation.ts index 1b302852661b4..3fc03ce8fef8b 100644 --- a/apps/studio/data/misc/reset-password-mutation.ts +++ b/apps/studio/data/misc/reset-password-mutation.ts @@ -1,12 +1,10 @@ -import * as Sentry from '@sentry/nextjs' import { useMutation } from '@tanstack/react-query' import { toast } from 'sonner' import { handleError, post } from 'data/fetchers' +import { captureCriticalError } from 'lib/error-reporting' import type { ResponseError, UseCustomMutationOptions } from 'types' -const WHITELIST_ERRORS = ['email must be an email'] - export type ResetPasswordVariables = { email: string hcaptchaToken: string | null @@ -44,9 +42,7 @@ export const useResetPasswordMutation = ({ } else { onError(data, variables, context) } - if (!WHITELIST_ERRORS.some((error) => data.message.includes(error))) { - Sentry.captureMessage('[CRITICAL] Failed to send reset password email: ' + data.message) - } + captureCriticalError(data, 'send reset password email') }, ...options, }) diff --git a/apps/studio/data/misc/signup-mutation.ts b/apps/studio/data/misc/signup-mutation.ts index 73530e341fa23..bb06a6a82d7b6 100644 --- a/apps/studio/data/misc/signup-mutation.ts +++ b/apps/studio/data/misc/signup-mutation.ts @@ -1,18 +1,10 @@ -import * as Sentry from '@sentry/nextjs' import { useMutation } from '@tanstack/react-query' import { toast } from 'sonner' import { handleError, post } from 'data/fetchers' +import { captureCriticalError } from 'lib/error-reporting' import type { ResponseError, UseCustomMutationOptions } from 'types' -const WHITELIST_ERRORS = [ - 'A user with this email already exists', - 'Password should contain at least one character of each', - 'You attempted to send email to an inactive recipient', - 'email must be an email', - 'Password is known to be weak and easy to guess, please choose a different one', -] - export type SignUpVariables = { email: string password: string @@ -51,9 +43,7 @@ export const useSignUpMutation = ({ } else { onError(data, variables, context) } - if (!WHITELIST_ERRORS.some((error) => data.message.includes(error))) { - Sentry.captureMessage('[CRITICAL] Failed to sign up: ' + data.message) - } + captureCriticalError(data, 'sign up') }, ...options, }) diff --git a/apps/studio/data/profile/mfa-challenge-and-verify-mutation.ts b/apps/studio/data/profile/mfa-challenge-and-verify-mutation.ts index 6cb56b6a441ca..ad89d2332e93b 100644 --- a/apps/studio/data/profile/mfa-challenge-and-verify-mutation.ts +++ b/apps/studio/data/profile/mfa-challenge-and-verify-mutation.ts @@ -1,14 +1,12 @@ -import * as Sentry from '@sentry/nextjs' import type { AuthMFAVerifyResponse, MFAChallengeAndVerifyParams } from '@supabase/supabase-js' import { useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' +import { captureCriticalError } from 'lib/error-reporting' import { auth } from 'lib/gotrue' import { profileKeys } from './keys' import { UseCustomMutationOptions } from 'types' -const WHITELIST_ERRORS = ['Invalid TOTP code entered'] - interface MFAChallengeAndVerifyVariables extends MFAChallengeAndVerifyParams { refreshFactors?: boolean } @@ -60,9 +58,7 @@ export const useMfaChallengeAndVerifyMutation = ({ } else { onError(data, variables, context) } - if (!WHITELIST_ERRORS.some((error) => data.message.includes(error))) { - Sentry.captureMessage('[CRITICAL] Failed to sign in via MFA: ' + data.message) - } + captureCriticalError(data, 'sign in via MFA') }, ...options, }) diff --git a/apps/studio/data/projects/project-create-mutation.ts b/apps/studio/data/projects/project-create-mutation.ts index 77fa75b68f066..aedbed0152531 100644 --- a/apps/studio/data/projects/project-create-mutation.ts +++ b/apps/studio/data/projects/project-create-mutation.ts @@ -1,24 +1,14 @@ -import * as Sentry from '@sentry/nextjs' import { useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' import type { components } from 'data/api' import { handleError, post } from 'data/fetchers' +import { captureCriticalError } from 'lib/error-reporting' import { PROVIDERS } from 'lib/constants' import type { ResponseError, UseCustomMutationOptions } from 'types' import { projectKeys } from './keys' import { DesiredInstanceSize, PostgresEngine, ReleaseChannel } from './new-project.constants' -const WHITELIST_ERRORS = [ - 'The following organization members have reached their maximum limits for the number of active free projects', - 'db_pass must be longer than or equal to 4 characters', - 'There are overdue invoices in the organization(s)', - 'name should not contain a . string', - 'Project creation in the Supabase dashboard is disabled for this Vercel-managed organization.', - 'Your account, which is handled by the Fly Supabase extension, cannot access this endpoint.', - 'already exists in your organization.', -] - type CreateProjectBody = components['schemas']['CreateProjectBody'] type CloudProvider = CreateProjectBody['cloud_provider'] @@ -112,9 +102,7 @@ export const useProjectCreateMutation = ({ } else { onError(data, variables, context) } - if (!WHITELIST_ERRORS.some((error) => data.message.includes(error))) { - Sentry.captureMessage('[CRITICAL] Failed to create project: ' + data.message) - } + captureCriticalError(data, 'create project') }, ...options, }) diff --git a/apps/studio/lib/error-reporting.ts b/apps/studio/lib/error-reporting.ts new file mode 100644 index 0000000000000..d4b719d454070 --- /dev/null +++ b/apps/studio/lib/error-reporting.ts @@ -0,0 +1,115 @@ +import * as Sentry from '@sentry/nextjs' + +import { ResponseError } from 'types' + +type CaptureMessageOptions = { + context: string + message: string +} + +const WHITELIST_ERRORS = [ + // Common validation errors + 'email must be an email', + 'Password is known to be weak and easy to guess, please choose a different one', + // Authentication errors + 'A user with this email already exists', + 'Password should contain at least one character of each', + 'You attempted to send email to an inactive recipient', + 'New password should be different from the old password', + 'Invalid TOTP code entered', + 'No SSO provider assigned for this domain', + // Project creation errors + 'The following organization members have reached their maximum limits for the number of active free projects', + 'db_pass must be longer than or equal to 4 characters', + 'There are overdue invoices in the organization(s)', + 'name should not contain a . string', + 'Project creation in the Supabase dashboard is disabled for this Vercel-managed organization.', + 'Your account, which is handled by the Fly Supabase extension, cannot access this endpoint.', + 'already exists in your organization.', +] + +/** + * Captures a critical error message to Sentry, filtering out whitelisted errors. + * + * @param error - The error object (ResponseError, Error, or any object with a message property) + * @param context - The context/action that failed (e.g., 'reset password', 'sign up', 'create project') + * + * @example + * captureCriticalError(error, 'reset password') + * // Captures: '[CRITICAL][reset password] Failed: ' + * + * @example + * captureCriticalError(error, 'sign up') + * // Captures: '[CRITICAL][sign up] Failed: ' + */ +export function captureCriticalError( + error: ResponseError | Error | { message: string }, + context: string +): void { + const errorMessage = error instanceof Error ? error.message : error.message + if (!errorMessage) { + return + } + + if (error instanceof ResponseError) { + handleResponseError(error, context) + return + } + if (error instanceof Error) { + handleError(error, context) + return + } + + handleUnknownError(error, context) +} + +function handleResponseError(error: ResponseError, context: string) { + const { code, message, requestPathname } = error + if (!requestPathname || !code) { + captureMessage({ + message: `[CRITICAL][${context}] Failed w/ Response Error (no code or requestPathname): ${error.message}`, + context, + }) + return + } + + if (code >= 500) { + // Only capture 5XX errors as critical errors + captureMessage({ + context, + message: `[CRITICAL][${context}] Failed requestPathname: ${requestPathname}: ${message}`, + }) + return + } +} + +function handleError(error: Error, context: string) { + const errorMessage = error.message + if (!errorMessage) { + return + } + + captureMessage({ + message: `[CRITICAL][${context}] Failed: ${errorMessage}`, + context, + }) +} + +function handleUnknownError(error: unknown, context: string) { + const hasMessage = + error && typeof error === 'object' && 'message' in error && typeof error.message === 'string' + + if (hasMessage) { + captureMessage({ + message: `[CRITICAL][${context}] Failed: ${error.message}`, + context, + }) + } +} + +function captureMessage({ message, context }: CaptureMessageOptions) { + if (WHITELIST_ERRORS.some((whitelisted) => message.includes(whitelisted))) { + return + } + Sentry.captureMessage(`[CRITICAL][${context}] ${message}`) +} From 4a4ccc30f565dc42f2c2ab6055711563add53cc1 Mon Sep 17 00:00:00 2001 From: Danny White <3104761+dnywh@users.noreply.github.com> Date: Fri, 7 Nov 2025 10:00:49 +1100 Subject: [PATCH 2/7] chore: remove sidebar labels (#39924) * basics * draft docs * remove labels * restore needed pills * remove extraneous diff * vault beta status * remove audit logs beta * minor fix * fix integration status --- apps/studio/components/interfaces/Auth/AuditLogsForm.tsx | 3 ++- .../Integrations/Landing/Integrations.constants.tsx | 2 +- .../components/layouts/AuthLayout/AuthLayout.utils.ts | 1 - .../layouts/DatabaseLayout/DatabaseMenu.utils.tsx | 2 -- .../layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx | 4 +--- apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx | 6 +++--- apps/www/data/features.tsx | 2 +- 7 files changed, 8 insertions(+), 12 deletions(-) diff --git a/apps/studio/components/interfaces/Auth/AuditLogsForm.tsx b/apps/studio/components/interfaces/Auth/AuditLogsForm.tsx index dab27c252cedc..7eace1cfe1d9a 100644 --- a/apps/studio/components/interfaces/Auth/AuditLogsForm.tsx +++ b/apps/studio/components/interfaces/Auth/AuditLogsForm.tsx @@ -139,8 +139,9 @@ export const AuditLogsForm = () => { - Auth logs. + Auth logs + .

} > diff --git a/apps/studio/components/interfaces/Integrations/Landing/Integrations.constants.tsx b/apps/studio/components/interfaces/Integrations/Landing/Integrations.constants.tsx index e95efa48267d4..9bbbe0fd53f02 100644 --- a/apps/studio/components/interfaces/Integrations/Landing/Integrations.constants.tsx +++ b/apps/studio/components/interfaces/Integrations/Landing/Integrations.constants.tsx @@ -172,7 +172,7 @@ const supabaseIntegrations: IntegrationDefinition[] = [ requiredExtensions: ['supabase_vault'], missingExtensionsAlert: , name: `Vault`, - status: 'alpha', + status: 'beta', icon: ({ className, ...props } = {}) => ( ), diff --git a/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts b/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts index 95a2ea263a889..f220bda36d339 100644 --- a/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts +++ b/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts @@ -164,7 +164,6 @@ export const generateAuthMenu = ( key: 'audit-logs', url: `/project/${ref}/auth/audit-logs`, items: [], - label: 'BETA', }, ...(authenticationAdvanced ? [ diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx index e6e76113a188b..a3e5dc09b7ea3 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx @@ -81,7 +81,6 @@ export const generateDatabaseMenu = ( name: 'Replication', key: 'replication', url: `/project/${ref}/database/replication`, - label: !enablePgReplicate ? 'Coming soon' : undefined, items: [], }, ] @@ -101,7 +100,6 @@ export const generateDatabaseMenu = ( key: 'column-privileges', url: `/project/${ref}/database/column-privileges`, items: [], - label: 'ALPHA', }, ] : []), diff --git a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx index dc87caee7d66d..046adda409b1f 100644 --- a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx +++ b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx @@ -86,7 +86,6 @@ export const generateSettingsMenu = ( key: 'api-keys', url: `/project/${ref}/settings/api-keys`, items: [], - label: 'NEW', }, { name: 'JWT Keys', @@ -95,7 +94,6 @@ export const generateSettingsMenu = ( ? `/project/${ref}/settings/jwt` : `/project/${ref}/settings/jwt/signing-keys`, items: [], - label: 'NEW', }, { @@ -116,7 +114,7 @@ export const generateSettingsMenu = ( url: isProjectBuilding ? buildingUrl : `/project/${ref}/integrations/vault/overview`, items: [], rightIcon: , - label: 'ALPHA', + label: 'BETA', }, ], }, diff --git a/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx b/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx index e6d439aa03d41..debb227544661 100644 --- a/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx +++ b/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx @@ -34,11 +34,11 @@ const ProductMenuItem = ({
- {name} + {name} {label !== undefined && ( - + {label} )} diff --git a/apps/www/data/features.tsx b/apps/www/data/features.tsx index 7ddd5894727fb..8cdf5850ce873 100644 --- a/apps/www/data/features.tsx +++ b/apps/www/data/features.tsx @@ -578,7 +578,7 @@ This feature is particularly useful for teams looking to enhance their security docsUrl: 'https://supabase.com/docs/guides/database/vault', slug: 'vault', status: { - stage: PRODUCT_STAGES.PUBLIC_ALPHA, + stage: PRODUCT_STAGES.PUBLIC_BETA, availableOnSelfHosted: true, }, }, From ab1b7220cea8a8d98db3391d564c97240a31fbef Mon Sep 17 00:00:00 2001 From: Ali Waseem Date: Thu, 6 Nov 2025 15:44:14 -0800 Subject: [PATCH 3/7] Fix: Double words for errors within Sentry for capture message (#40223) updated error messages --- apps/studio/lib/error-reporting.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/apps/studio/lib/error-reporting.ts b/apps/studio/lib/error-reporting.ts index d4b719d454070..3b27543953b11 100644 --- a/apps/studio/lib/error-reporting.ts +++ b/apps/studio/lib/error-reporting.ts @@ -67,7 +67,7 @@ function handleResponseError(error: ResponseError, context: string) { const { code, message, requestPathname } = error if (!requestPathname || !code) { captureMessage({ - message: `[CRITICAL][${context}] Failed w/ Response Error (no code or requestPathname): ${error.message}`, + message: `Response Error (no code or requestPathname) w/ message: ${error.message}`, context, }) return @@ -77,31 +77,33 @@ function handleResponseError(error: ResponseError, context: string) { // Only capture 5XX errors as critical errors captureMessage({ context, - message: `[CRITICAL][${context}] Failed requestPathname: ${requestPathname}: ${message}`, + message: `requestPathname ${requestPathname} w/ message: ${message}`, }) return } } function handleError(error: Error, context: string) { - const errorMessage = error.message - if (!errorMessage) { + const message = error.message + if (!message) { return } captureMessage({ - message: `[CRITICAL][${context}] Failed: ${errorMessage}`, + message, context, }) } function handleUnknownError(error: unknown, context: string) { - const hasMessage = - error && typeof error === 'object' && 'message' in error && typeof error.message === 'string' - - if (hasMessage) { + if ( + error && + typeof error === 'object' && + 'message' in error && + typeof error.message === 'string' + ) { captureMessage({ - message: `[CRITICAL][${context}] Failed: ${error.message}`, + message: error.message, context, }) } @@ -111,5 +113,5 @@ function captureMessage({ message, context }: CaptureMessageOptions) { if (WHITELIST_ERRORS.some((whitelisted) => message.includes(whitelisted))) { return } - Sentry.captureMessage(`[CRITICAL][${context}] ${message}`) + Sentry.captureMessage(`[CRITICAL][${context}] ${message} Failed: ${message}`) } From 364f743054d34dc5adcba27329c7becb84da7fbb Mon Sep 17 00:00:00 2001 From: Sean Oliver <882952+seanoliver@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:51:56 -0800 Subject: [PATCH 4/7] Fix PostHog user identification persisting after signout (#40158) - Add reset() method to PostHogClient class to clear user identification - Call posthogClient.reset() before clearLocalStorage() in signout flow - Include proper error handling and memory leak prevention - Clear all pending state (identification, groups, events) Resolves GROWTH-535 --- apps/studio/lib/auth.tsx | 2 ++ packages/common/posthog-client.ts | 14 ++++++++++++++ packages/common/telemetry.tsx | 2 ++ 3 files changed, 18 insertions(+) diff --git a/apps/studio/lib/auth.tsx b/apps/studio/lib/auth.tsx index fc40622efa61a..7ac8442b23a0e 100644 --- a/apps/studio/lib/auth.tsx +++ b/apps/studio/lib/auth.tsx @@ -6,6 +6,7 @@ import { AuthProvider as AuthProviderInternal, clearLocalStorage, gotrueClient, + posthogClient, useAuthError, } from 'common' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' @@ -45,6 +46,7 @@ export function useSignOut() { return useCallback(async () => { const result = await gotrueClient.signOut() + posthogClient.reset() clearLocalStorage() // Clear Assistant IndexedDB await clearAssistantStorage() diff --git a/packages/common/posthog-client.ts b/packages/common/posthog-client.ts index b27e104efa316..1ce1a8f5ad97b 100644 --- a/packages/common/posthog-client.ts +++ b/packages/common/posthog-client.ts @@ -142,6 +142,20 @@ class PostHogClient { console.error('PostHog identify failed:', error) } } + + reset() { + this.pendingIdentification = null + this.pendingGroups = {} + this.pendingEvents = [] + + if (!this.initialized) return + + try { + posthog.reset() + } catch (error) { + console.error('PostHog reset failed:', error) + } + } } export const posthogClient = new PostHogClient() diff --git a/packages/common/telemetry.tsx b/packages/common/telemetry.tsx index 2a316aca01053..64f77f1d503da 100644 --- a/packages/common/telemetry.tsx +++ b/packages/common/telemetry.tsx @@ -17,6 +17,8 @@ import { TelemetryEvent } from './telemetry-constants' import { getSharedTelemetryData } from './telemetry-utils' import { posthogClient } from './posthog-client' +export { posthogClient } + const { TELEMETRY_DATA } = LOCAL_STORAGE_KEYS // Reexports GoogleTagManager with the right API key set From 2fdba9098dccec7d0284428350cda8db15e3c0dc Mon Sep 17 00:00:00 2001 From: Ali Waseem Date: Thu, 6 Nov 2025 18:08:58 -0800 Subject: [PATCH 5/7] remove duplicate message in sentry trace (#40226) --- apps/studio/lib/error-reporting.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/studio/lib/error-reporting.ts b/apps/studio/lib/error-reporting.ts index 3b27543953b11..d6b0e6d904916 100644 --- a/apps/studio/lib/error-reporting.ts +++ b/apps/studio/lib/error-reporting.ts @@ -113,5 +113,5 @@ function captureMessage({ message, context }: CaptureMessageOptions) { if (WHITELIST_ERRORS.some((whitelisted) => message.includes(whitelisted))) { return } - Sentry.captureMessage(`[CRITICAL][${context}] ${message} Failed: ${message}`) + Sentry.captureMessage(`[CRITICAL][${context}] Failed: ${message}`) } From 50255605ec340d1c0b48f18f301df21f15c2b685 Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Fri, 7 Nov 2025 13:04:37 +1000 Subject: [PATCH 6/7] Moves inline editor from feature preview to setting (#39892) * sidebar-manager * storage keys * tests * more ai spots * test fix * revert to default * remove ref * Update apps/studio/state/sidebar-manager-state.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix ts * fix * fux * fux query param * clean * fix * more * mock local storage * simplify * remove provider test * remve useopensidebar * fix(new homepage): open ai assistant on advisor card button clicks * Update apps/studio/components/layouts/ProjectLayout/LayoutSidebar/index.tsx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/studio/state/sidebar-manager-state.tsx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * refine * editor sidebar manager * reset results * move inline editor to account setting * update analytics to standard * copy * add tracking * update copy * fixes * Update apps/studio/pages/project/[ref]/database/functions.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update apps/studio/pages/project/[ref]/auth/policies.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * zod resolver * Nit refacotr * Small fixes * missed two pieces * change event --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> Co-authored-by: Joshen Lim --- .../Account/Preferences/AnalyticsSettings.tsx | 58 ++++++-- .../Account/Preferences/HotkeySettings.tsx | 137 +++++++++++++----- .../Preferences/InlineEditorSettings.tsx | 86 +++++++++++ .../FeaturePreview.constants.tsx | 7 - .../FeaturePreview/FeaturePreviewContext.tsx | 5 - .../FeaturePreview/FeaturePreviewModal.tsx | 2 - .../ui/QueryBlock/EditQueryButton.tsx | 11 +- apps/studio/pages/account/me.tsx | 5 + .../pages/project/[ref]/auth/policies.tsx | 4 +- .../project/[ref]/database/functions.tsx | 11 +- .../pages/project/[ref]/database/triggers.tsx | 2 +- packages/common/telemetry-constants.ts | 19 +++ 12 files changed, 273 insertions(+), 74 deletions(-) create mode 100644 apps/studio/components/interfaces/Account/Preferences/InlineEditorSettings.tsx diff --git a/apps/studio/components/interfaces/Account/Preferences/AnalyticsSettings.tsx b/apps/studio/components/interfaces/Account/Preferences/AnalyticsSettings.tsx index f9928a5b2788c..35267f776f675 100644 --- a/apps/studio/components/interfaces/Account/Preferences/AnalyticsSettings.tsx +++ b/apps/studio/components/interfaces/Account/Preferences/AnalyticsSettings.tsx @@ -1,8 +1,17 @@ -import { Toggle } from 'ui' +import { zodResolver } from '@hookform/resolvers/zod' +import { useForm } from 'react-hook-form' import { toast } from 'sonner' +import * as z from 'zod' + import { useConsentState } from 'common' import Panel from 'components/ui/Panel' import { useSendResetMutation } from 'data/telemetry/send-reset-mutation' +import { FormControl_Shadcn_, FormField_Shadcn_, Form_Shadcn_, Switch } from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' + +const AnalyticsSchema = z.object({ + telemetryEnabled: z.boolean(), +}) export const AnalyticsSettings = () => { const { hasAccepted, acceptAll, denyAll, categories } = useConsentState() @@ -10,31 +19,54 @@ export const AnalyticsSettings = () => { const { mutate: sendReset } = useSendResetMutation() - const onToggleOptIn = () => { + const form = useForm>({ + resolver: zodResolver(AnalyticsSchema), + values: { telemetryEnabled: hasAccepted }, + }) + + const handleToggle = (value: boolean) => { if (!hasLoaded) { - toast.error( + return toast.error( "We couldn't load the privacy settings due to an ad blocker or network error. Please disable any ad blockers and try again. If the problem persists, please contact support." ) - return } - if (hasAccepted) { + if (value) { + acceptAll() + } else { denyAll() sendReset() - } else { - acceptAll() } + + form.setValue('telemetryEnabled', value) } return ( Analytics and Marketing}> - + + ( + + + { + field.onChange(value) + handleToggle(value) + }} + /> + + + )} + /> + ) diff --git a/apps/studio/components/interfaces/Account/Preferences/HotkeySettings.tsx b/apps/studio/components/interfaces/Account/Preferences/HotkeySettings.tsx index cf89c8a4d1d78..b97f3d0a19c0d 100644 --- a/apps/studio/components/interfaces/Account/Preferences/HotkeySettings.tsx +++ b/apps/studio/components/interfaces/Account/Preferences/HotkeySettings.tsx @@ -1,8 +1,19 @@ +import { zodResolver } from '@hookform/resolvers/zod' +import { useForm } from 'react-hook-form' +import * as z from 'zod' + import { LOCAL_STORAGE_KEYS } from 'common' import { SIDEBAR_KEYS } from 'components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider' import Panel from 'components/ui/Panel' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { KeyboardShortcut, Toggle } from 'ui' +import { FormControl_Shadcn_, FormField_Shadcn_, Form_Shadcn_, KeyboardShortcut, Switch } from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' + +const HotkeySchema = z.object({ + commandMenuEnabled: z.boolean(), + aiAssistantEnabled: z.boolean(), + inlineEditorEnabled: z.boolean(), +}) export const HotkeySettings = () => { const [inlineEditorEnabled, setInlineEditorEnabled] = useLocalStorageQuery( @@ -18,6 +29,15 @@ export const HotkeySettings = () => { true ) + const form = useForm>({ + resolver: zodResolver(HotkeySchema), + values: { + commandMenuEnabled: commandMenuEnabled ?? true, + aiAssistantEnabled: aiAssistantEnabled ?? true, + inlineEditorEnabled: inlineEditorEnabled ?? true, + }, + }) + return ( {
} > - - setCommandMenuEnabled(!commandMenuEnabled)} - label={ -
- - Command menu -
- } - /> - setAiAssistantEnabled(!aiAssistantEnabled)} - label={ -
- - AI Assistant Panel -
- } - /> - setInlineEditorEnabled(!inlineEditorEnabled)} - label={ -
- - Inline SQL Editor Panel -
- } - /> -
+ + + ( + + + Command menu +
+ } + > + + { + field.onChange(value) + setCommandMenuEnabled(value) + }} + /> + + + )} + /> + + + ( + + + AI Assistant Panel + + } + > + + { + field.onChange(value) + setAiAssistantEnabled(value) + }} + /> + + + )} + /> + + + ( + + + Inline SQL Editor Panel + + } + > + + { + field.onChange(value) + setInlineEditorEnabled(value) + }} + /> + + + )} + /> + + ) } diff --git a/apps/studio/components/interfaces/Account/Preferences/InlineEditorSettings.tsx b/apps/studio/components/interfaces/Account/Preferences/InlineEditorSettings.tsx new file mode 100644 index 0000000000000..c28bcaa39e6c7 --- /dev/null +++ b/apps/studio/components/interfaces/Account/Preferences/InlineEditorSettings.tsx @@ -0,0 +1,86 @@ +import { zodResolver } from '@hookform/resolvers/zod' +import { useForm } from 'react-hook-form' +import * as z from 'zod' + +import { LOCAL_STORAGE_KEYS } from 'common' +import Panel from 'components/ui/Panel' +import { useSendEventMutation } from 'data/telemetry/send-event-mutation' +import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { FormControl_Shadcn_, FormField_Shadcn_, Form_Shadcn_, Switch } from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' + +const InlineEditorSchema = z.object({ + inlineEditorEnabled: z.boolean(), +}) + +export const useIsInlineEditorEnabled = () => { + const [inlineEditorEnabled] = useLocalStorageQuery( + LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR, + false + ) + + return inlineEditorEnabled ?? false +} + +export const InlineEditorSettings = () => { + const [inlineEditorEnabled, setInlineEditorEnabled] = useLocalStorageQuery( + LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR, + false + ) + const { data: org } = useSelectedOrganizationQuery() + + const { mutate: sendEvent } = useSendEventMutation() + + const form = useForm>({ + resolver: zodResolver(InlineEditorSchema), + values: { + inlineEditorEnabled: inlineEditorEnabled ?? false, + }, + }) + + const handleToggle = (value: boolean) => { + setInlineEditorEnabled(value) + form.setValue('inlineEditorEnabled', value) + + sendEvent({ + action: 'inline_editor_setting_clicked', + properties: { + enabled: value, + }, + groups: { + organization: org?.slug, + }, + }) + } + + return ( + Dashboard}> + + + ( + + + { + field.onChange(value) + handleToggle(value) + }} + /> + + + )} + /> + + + + ) +} diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx index ce8d859e7852c..89c110dd04d69 100644 --- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx +++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx @@ -29,13 +29,6 @@ export const FEATURE_PREVIEWS = [ isNew: true, isPlatformOnly: true, }, - { - key: LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR, - name: 'Directly edit database entities', - discussionsUrl: 'https://github.com/orgs/supabase/discussions/33690', - isNew: false, - isPlatformOnly: false, - }, { key: LOCAL_STORAGE_KEYS.UI_PREVIEW_API_SIDE_PANEL, name: 'Project API documentation', diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx index 248d731e5a705..79351481b7ff4 100644 --- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx +++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx @@ -84,11 +84,6 @@ export const useIsColumnLevelPrivilegesEnabled = () => { return flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_CLS] } -export const useIsInlineEditorEnabled = () => { - const { flags } = useFeaturePreviewContext() - return flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR] -} - export const useUnifiedLogsPreview = () => { const { flags, onUpdateFlag } = useFeaturePreviewContext() diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx index 524e7cd28e5af..18b5755d2b26e 100644 --- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx +++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx @@ -13,7 +13,6 @@ import { Branching2Preview } from './Branching2Preview' import { CLSPreview } from './CLSPreview' import { FEATURE_PREVIEWS } from './FeaturePreview.constants' import { useFeaturePreviewContext, useFeaturePreviewModal } from './FeaturePreviewContext' -import { InlineEditorPreview } from './InlineEditorPreview' import { SecurityNotificationsPreview } from './SecurityNotificationsPreview' import { UnifiedLogsPreview } from './UnifiedLogsPreview' @@ -22,7 +21,6 @@ const FEATURE_PREVIEW_KEY_TO_CONTENT: { } = { [LOCAL_STORAGE_KEYS.UI_PREVIEW_BRANCHING_2_0]: , [LOCAL_STORAGE_KEYS.UI_PREVIEW_ADVISOR_RULES]: , - [LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR]: , [LOCAL_STORAGE_KEYS.UI_PREVIEW_API_SIDE_PANEL]: , [LOCAL_STORAGE_KEYS.UI_PREVIEW_CLS]: , [LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS]: , diff --git a/apps/studio/components/ui/QueryBlock/EditQueryButton.tsx b/apps/studio/components/ui/QueryBlock/EditQueryButton.tsx index 3637ef1edf7c6..5e514a60979a6 100644 --- a/apps/studio/components/ui/QueryBlock/EditQueryButton.tsx +++ b/apps/studio/components/ui/QueryBlock/EditQueryButton.tsx @@ -1,15 +1,16 @@ import { Edit } from 'lucide-react' +import Link from 'next/link' import { useRouter } from 'next/router' +import { ComponentProps } from 'react' import { useParams } from 'common' -import { useIsInlineEditorEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import { useIsInlineEditorEnabled } from 'components/interfaces/Account/Preferences/InlineEditorSettings' import { DiffType } from 'components/interfaces/SQLEditor/SQLEditor.types' import useNewQuery from 'components/interfaces/SQLEditor/hooks' +import { SIDEBAR_KEYS } from 'components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' -import Link from 'next/link' -import { ComponentProps } from 'react' -import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' +import { useSidebarManagerSnapshot } from 'state/sidebar-manager-state' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' import { cn, @@ -20,8 +21,6 @@ import { TooltipContent, } from 'ui' import { ButtonTooltip } from '../ButtonTooltip' -import { SIDEBAR_KEYS } from 'components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider' -import { useSidebarManagerSnapshot } from 'state/sidebar-manager-state' interface EditQueryButtonProps { id?: string diff --git a/apps/studio/pages/account/me.tsx b/apps/studio/pages/account/me.tsx index d41b1b1b1e7eb..c805527453f00 100644 --- a/apps/studio/pages/account/me.tsx +++ b/apps/studio/pages/account/me.tsx @@ -3,6 +3,7 @@ import { AccountDeletion } from 'components/interfaces/Account/Preferences/Accou import { AccountIdentities } from 'components/interfaces/Account/Preferences/AccountIdentities' import { AnalyticsSettings } from 'components/interfaces/Account/Preferences/AnalyticsSettings' import { HotkeySettings } from 'components/interfaces/Account/Preferences/HotkeySettings' +import { InlineEditorSettings } from 'components/interfaces/Account/Preferences/InlineEditorSettings' import { ProfileInformation } from 'components/interfaces/Account/Preferences/ProfileInformation' import { ThemeSettings } from 'components/interfaces/Account/Preferences/ThemeSettings' import AccountLayout from 'components/layouts/AccountLayout/AccountLayout' @@ -88,6 +89,10 @@ const ProfileCard = () => { +
+ +
+ {profileShowAnalyticsAndMarketing && (
diff --git a/apps/studio/pages/project/[ref]/auth/policies.tsx b/apps/studio/pages/project/[ref]/auth/policies.tsx index e5c05ebbb4412..d5a939e214374 100644 --- a/apps/studio/pages/project/[ref]/auth/policies.tsx +++ b/apps/studio/pages/project/[ref]/auth/policies.tsx @@ -1,9 +1,10 @@ import type { PostgresPolicy, PostgresTable } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Search } from 'lucide-react' +import { parseAsString, useQueryState } from 'nuqs' import { useCallback, useDeferredValue, useMemo, useState } from 'react' -import { useIsInlineEditorEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import { useIsInlineEditorEnabled } from 'components/interfaces/Account/Preferences/InlineEditorSettings' import { Policies } from 'components/interfaces/Auth/Policies/Policies' import { PoliciesDataProvider } from 'components/interfaces/Auth/Policies/PoliciesDataContext' import { getGeneralPolicyTemplates } from 'components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants' @@ -26,7 +27,6 @@ import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { DOCS_URL } from 'lib/constants' -import { parseAsString, useQueryState } from 'nuqs' import { useEditorPanelStateSnapshot } from 'state/editor-panel-state' import { useSidebarManagerSnapshot } from 'state/sidebar-manager-state' import type { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/project/[ref]/database/functions.tsx b/apps/studio/pages/project/[ref]/database/functions.tsx index 02e68b6ee1489..d1446917a0ebb 100644 --- a/apps/studio/pages/project/[ref]/database/functions.tsx +++ b/apps/studio/pages/project/[ref]/database/functions.tsx @@ -1,7 +1,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useState } from 'react' -import { useIsInlineEditorEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import { useIsInlineEditorEnabled } from 'components/interfaces/Account/Preferences/InlineEditorSettings' import { CreateFunction } from 'components/interfaces/Database/Functions/CreateFunction' import { DeleteFunction } from 'components/interfaces/Database/Functions/DeleteFunction' import FunctionsList from 'components/interfaces/Database/Functions/FunctionsList/FunctionsList' @@ -19,10 +19,6 @@ import { useSidebarManagerSnapshot } from 'state/sidebar-manager-state' import type { NextPageWithLayout } from 'types' const DatabaseFunctionsPage: NextPageWithLayout = () => { - const [selectedFunction, setSelectedFunction] = useState() - const [showCreateFunctionForm, setShowCreateFunctionForm] = useState(false) - const [showDeleteFunctionForm, setShowDeleteFunctionForm] = useState(false) - const [isDuplicating, setIsDuplicating] = useState(false) const isInlineEditorEnabled = useIsInlineEditorEnabled() const { openSidebar } = useSidebarManagerSnapshot() const { @@ -36,6 +32,11 @@ const DatabaseFunctionsPage: NextPageWithLayout = () => { 'functions' ) + const [isDuplicating, setIsDuplicating] = useState(false) + const [selectedFunction, setSelectedFunction] = useState() + const [showCreateFunctionForm, setShowCreateFunctionForm] = useState(false) + const [showDeleteFunctionForm, setShowDeleteFunctionForm] = useState(false) + const createFunction = () => { setIsDuplicating(false) if (isInlineEditorEnabled) { diff --git a/apps/studio/pages/project/[ref]/database/triggers.tsx b/apps/studio/pages/project/[ref]/database/triggers.tsx index 90e0ef8065902..3b1c35ed6583f 100644 --- a/apps/studio/pages/project/[ref]/database/triggers.tsx +++ b/apps/studio/pages/project/[ref]/database/triggers.tsx @@ -2,7 +2,7 @@ import { PostgresTrigger } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useState } from 'react' -import { useIsInlineEditorEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import { useIsInlineEditorEnabled } from 'components/interfaces/Account/Preferences/InlineEditorSettings' import { DeleteTrigger } from 'components/interfaces/Database/Triggers/DeleteTrigger' import { TriggerSheet } from 'components/interfaces/Database/Triggers/TriggerSheet' import { generateTriggerCreateSQL } from 'components/interfaces/Database/Triggers/TriggersList/TriggerList.utils' diff --git a/packages/common/telemetry-constants.ts b/packages/common/telemetry-constants.ts index b5a0869c31654..03e4b5989021e 100644 --- a/packages/common/telemetry-constants.ts +++ b/packages/common/telemetry-constants.ts @@ -2181,6 +2181,24 @@ export interface TableQuickstartAssistantOpenedEvent { groups: TelemetryGroups } +/** + * User toggled the inline editor setting in account preferences. + * + * @group Events + * @source studio + * @page /dashboard/account/preferences + */ +export interface InlineEditorSettingClickedEvent { + action: 'inline_editor_setting_clicked' + properties: { + /** + * Whether the inline editor was enabled or disabled + */ + enabled: boolean + } + groups: Partial +} + /** * User clicked the save destination button in add log drains sheet. * @@ -2340,6 +2358,7 @@ export type TelemetryEvent = | CommandMenuOpenedEvent | CommandMenuSearchSubmittedEvent | CommandMenuCommandClickedEvent + | InlineEditorSettingClickedEvent | SidebarOpenedEvent | LogDrainSaveButtonClickedEvent | LogDrainConfirmButtonSubmittedEvent From 91464b8fe881f5b73a77bbb8d8ad41407c20152d Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Fri, 7 Nov 2025 05:02:40 +0100 Subject: [PATCH 7/7] ref(etl): Rename Replication to ETL Replication (#40202) * ref(etl): Rename Replication to ETL Replication * Fix --------- Co-authored-by: Joshen Lim --- .../Database/{Replication => ETL}/ComingSoon.tsx | 0 .../{Replication => ETL}/DeleteDestination.tsx | 0 .../DestinationPanel/AdvancedSettings.tsx | 0 .../DestinationPanel/DestinationNameInput.tsx | 0 .../DestinationPanel/DestinationPanel.constants.ts | 0 .../DestinationPanel/DestinationPanel.schema.ts | 0 .../DestinationPanel/DestinationPanel.tsx | 12 ++++++------ .../DestinationPanel/DestinationPanelFields.tsx | 0 .../DestinationPanel/DestinationTypeSelection.tsx | 0 .../DestinationPanel/NoDestinationsAvailable.tsx | 0 .../DestinationPanel/PublicationSelection.tsx | 2 +- .../{Replication => ETL}/DestinationRow.tsx | 14 +++++++------- .../Database/{Replication => ETL}/Destinations.tsx | 10 +++++----- .../EnableReplicationModal.tsx | 2 +- .../{Replication => ETL}/ErroredTableDetails.tsx | 0 .../{Replication => ETL}/NewPublicationPanel.tsx | 4 ++-- .../{Replication => ETL}/Pipeline.utils.ts | 2 +- .../{Replication => ETL}/PipelineStatus.tsx | 2 +- .../{Replication => ETL}/PublicationsComboBox.tsx | 0 .../{Replication => ETL}/Replication.constants.ts | 0 .../ReplicationDisclaimerDialog.tsx | 0 .../ReplicationPipelineStatus.tsx | 14 +++++++------- .../ReplicationPipelineStatus.types.ts | 0 .../ReplicationPipelineStatus.utils.tsx | 2 +- .../ReplicationPipelineStatus/SlotLagMetrics.tsx | 0 .../{Replication => ETL}/RetryCountdown.tsx | 0 .../{Replication => ETL}/RetryOptionsDropdown.tsx | 4 ++-- .../Database/{Replication => ETL}/RowMenu.tsx | 8 ++++---- .../{Replication => ETL}/UpdateVersionModal.tsx | 10 +++++----- .../AnalyticsBucketDetails/ConnectTablesDialog.tsx | 8 ++++---- .../AnalyticsBucketDetails/NamespaceWithTables.tsx | 2 +- .../useAnalyticsBucketAssociatedEntities.tsx | 4 ++-- .../layouts/DatabaseLayout/Database.Commands.tsx | 8 ++++---- .../layouts/DatabaseLayout/DatabaseMenu.utils.tsx | 6 +++--- .../layouts/LogsLayout/LogsSidebarMenuV2.tsx | 2 +- .../create-destination-pipeline-mutation.ts | 0 .../create-publication-mutation.ts | 0 .../create-tenant-source-mutation.ts | 0 .../delete-destination-pipeline-mutation.ts | 0 .../destination-by-id-query.ts | 0 .../{replication => etl}/destinations-query.ts | 0 apps/studio/data/{replication => etl}/keys.ts | 0 .../{replication => etl}/pipeline-by-id-query.ts | 0 .../pipeline-replication-status-query.ts | 0 .../{replication => etl}/pipeline-status-query.ts | 0 .../{replication => etl}/pipeline-version-query.ts | 0 .../data/{replication => etl}/pipelines-query.ts | 0 .../publication-delete-mutation.ts | 0 .../{replication => etl}/publications-query.ts | 0 .../rollback-table-mutation.ts | 0 .../data/{replication => etl}/sources-query.ts | 0 .../start-pipeline-mutation.ts | 0 .../{replication => etl}/stop-pipeline-mutation.ts | 0 .../data/{replication => etl}/tables-query.ts | 0 .../update-destination-pipeline-mutation.ts | 0 .../update-pipeline-version-mutation.ts | 0 .../database/{replication => etl}/[pipelineId].tsx | 8 ++++---- .../[ref]/database/{replication => etl}/index.tsx | 10 +++++----- 58 files changed, 67 insertions(+), 67 deletions(-) rename apps/studio/components/interfaces/Database/{Replication => ETL}/ComingSoon.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DeleteDestination.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/AdvancedSettings.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/DestinationNameInput.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/DestinationPanel.constants.ts (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/DestinationPanel.schema.ts (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/DestinationPanel.tsx (97%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/DestinationPanelFields.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/DestinationTypeSelection.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/NoDestinationsAvailable.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationPanel/PublicationSelection.tsx (98%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/DestinationRow.tsx (93%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/Destinations.tsx (95%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/EnableReplicationModal.tsx (96%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/ErroredTableDetails.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/NewPublicationPanel.tsx (97%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/Pipeline.utils.ts (97%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/PipelineStatus.tsx (98%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/PublicationsComboBox.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/Replication.constants.ts (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/ReplicationDisclaimerDialog.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/ReplicationPipelineStatus/ReplicationPipelineStatus.tsx (97%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/ReplicationPipelineStatus/ReplicationPipelineStatus.types.ts (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/ReplicationPipelineStatus/ReplicationPipelineStatus.utils.tsx (98%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/ReplicationPipelineStatus/SlotLagMetrics.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/RetryCountdown.tsx (100%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/RetryOptionsDropdown.tsx (95%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/RowMenu.tsx (95%) rename apps/studio/components/interfaces/Database/{Replication => ETL}/UpdateVersionModal.tsx (90%) rename apps/studio/data/{replication => etl}/create-destination-pipeline-mutation.ts (100%) rename apps/studio/data/{replication => etl}/create-publication-mutation.ts (100%) rename apps/studio/data/{replication => etl}/create-tenant-source-mutation.ts (100%) rename apps/studio/data/{replication => etl}/delete-destination-pipeline-mutation.ts (100%) rename apps/studio/data/{replication => etl}/destination-by-id-query.ts (100%) rename apps/studio/data/{replication => etl}/destinations-query.ts (100%) rename apps/studio/data/{replication => etl}/keys.ts (100%) rename apps/studio/data/{replication => etl}/pipeline-by-id-query.ts (100%) rename apps/studio/data/{replication => etl}/pipeline-replication-status-query.ts (100%) rename apps/studio/data/{replication => etl}/pipeline-status-query.ts (100%) rename apps/studio/data/{replication => etl}/pipeline-version-query.ts (100%) rename apps/studio/data/{replication => etl}/pipelines-query.ts (100%) rename apps/studio/data/{replication => etl}/publication-delete-mutation.ts (100%) rename apps/studio/data/{replication => etl}/publications-query.ts (100%) rename apps/studio/data/{replication => etl}/rollback-table-mutation.ts (100%) rename apps/studio/data/{replication => etl}/sources-query.ts (100%) rename apps/studio/data/{replication => etl}/start-pipeline-mutation.ts (100%) rename apps/studio/data/{replication => etl}/stop-pipeline-mutation.ts (100%) rename apps/studio/data/{replication => etl}/tables-query.ts (100%) rename apps/studio/data/{replication => etl}/update-destination-pipeline-mutation.ts (100%) rename apps/studio/data/{replication => etl}/update-pipeline-version-mutation.ts (100%) rename apps/studio/pages/project/[ref]/database/{replication => etl}/[pipelineId].tsx (85%) rename apps/studio/pages/project/[ref]/database/{replication => etl}/index.tsx (86%) diff --git a/apps/studio/components/interfaces/Database/Replication/ComingSoon.tsx b/apps/studio/components/interfaces/Database/ETL/ComingSoon.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/ComingSoon.tsx rename to apps/studio/components/interfaces/Database/ETL/ComingSoon.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/DeleteDestination.tsx b/apps/studio/components/interfaces/Database/ETL/DeleteDestination.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/DeleteDestination.tsx rename to apps/studio/components/interfaces/Database/ETL/DeleteDestination.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/AdvancedSettings.tsx b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/AdvancedSettings.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/AdvancedSettings.tsx rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/AdvancedSettings.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationNameInput.tsx b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationNameInput.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationNameInput.tsx rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationNameInput.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanel.constants.ts b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanel.constants.ts similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanel.constants.ts rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanel.constants.ts diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanel.schema.ts b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanel.schema.ts similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanel.schema.ts rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanel.schema.ts diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanel.tsx b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanel.tsx similarity index 97% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanel.tsx rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanel.tsx index 1699b811e592d..344861e48084b 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanel.tsx +++ b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanel.tsx @@ -10,12 +10,12 @@ import { getCatalogURI } from 'components/interfaces/Storage/StorageSettings/Sto import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useCheckPrimaryKeysExists } from 'data/database/primary-keys-exists-query' -import { useCreateDestinationPipelineMutation } from 'data/replication/create-destination-pipeline-mutation' -import { useReplicationDestinationByIdQuery } from 'data/replication/destination-by-id-query' -import { useReplicationPipelineByIdQuery } from 'data/replication/pipeline-by-id-query' -import { useReplicationPublicationsQuery } from 'data/replication/publications-query' -import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' -import { useUpdateDestinationPipelineMutation } from 'data/replication/update-destination-pipeline-mutation' +import { useCreateDestinationPipelineMutation } from 'data/etl/create-destination-pipeline-mutation' +import { useReplicationDestinationByIdQuery } from 'data/etl/destination-by-id-query' +import { useReplicationPipelineByIdQuery } from 'data/etl/pipeline-by-id-query' +import { useReplicationPublicationsQuery } from 'data/etl/publications-query' +import { useStartPipelineMutation } from 'data/etl/start-pipeline-mutation' +import { useUpdateDestinationPipelineMutation } from 'data/etl/update-destination-pipeline-mutation' import { useIcebergNamespaceCreateMutation } from 'data/storage/iceberg-namespace-create-mutation' import { useS3AccessKeyCreateMutation } from 'data/storage/s3-access-key-create-mutation' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanelFields.tsx b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanelFields.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationPanelFields.tsx rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationPanelFields.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationTypeSelection.tsx b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationTypeSelection.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationTypeSelection.tsx rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/DestinationTypeSelection.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/NoDestinationsAvailable.tsx b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/NoDestinationsAvailable.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/NoDestinationsAvailable.tsx rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/NoDestinationsAvailable.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/PublicationSelection.tsx b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/PublicationSelection.tsx similarity index 98% rename from apps/studio/components/interfaces/Database/Replication/DestinationPanel/PublicationSelection.tsx rename to apps/studio/components/interfaces/Database/ETL/DestinationPanel/PublicationSelection.tsx index ad2a00a53b161..7c23c1ded6427 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/PublicationSelection.tsx +++ b/apps/studio/components/interfaces/Database/ETL/DestinationPanel/PublicationSelection.tsx @@ -4,7 +4,7 @@ import type { UseFormReturn } from 'react-hook-form' import { useParams } from 'common' import { InlineLink } from 'components/ui/InlineLink' import { useCheckPrimaryKeysExists } from 'data/database/primary-keys-exists-query' -import { useReplicationPublicationsQuery } from 'data/replication/publications-query' +import { useReplicationPublicationsQuery } from 'data/etl/publications-query' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { FormControl_Shadcn_, FormField_Shadcn_ } from 'ui' import { Admonition } from 'ui-patterns' diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx b/apps/studio/components/interfaces/Database/ETL/DestinationRow.tsx similarity index 93% rename from apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx rename to apps/studio/components/interfaces/Database/ETL/DestinationRow.tsx index 0fbb5df2f9178..dda49fe9ef9f5 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx +++ b/apps/studio/components/interfaces/Database/ETL/DestinationRow.tsx @@ -6,12 +6,12 @@ import { toast } from 'sonner' import { useParams } from 'common' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' -import { useDeleteDestinationPipelineMutation } from 'data/replication/delete-destination-pipeline-mutation' -import { useReplicationPipelineReplicationStatusQuery } from 'data/replication/pipeline-replication-status-query' -import { useReplicationPipelineStatusQuery } from 'data/replication/pipeline-status-query' -import { useReplicationPipelineVersionQuery } from 'data/replication/pipeline-version-query' -import { Pipeline } from 'data/replication/pipelines-query' -import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation' +import { useDeleteDestinationPipelineMutation } from 'data/etl/delete-destination-pipeline-mutation' +import { useReplicationPipelineReplicationStatusQuery } from 'data/etl/pipeline-replication-status-query' +import { useReplicationPipelineStatusQuery } from 'data/etl/pipeline-status-query' +import { useReplicationPipelineVersionQuery } from 'data/etl/pipeline-version-query' +import { Pipeline } from 'data/etl/pipelines-query' +import { useStopPipelineMutation } from 'data/etl/stop-pipeline-mutation' import { PipelineStatusRequestStatus, usePipelineRequestStatus, @@ -176,7 +176,7 @@ export const DestinationRow = ({

{destinationName || 'Pipeline'}

diff --git a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus/ReplicationPipelineStatus.types.ts b/apps/studio/components/interfaces/Database/ETL/ReplicationPipelineStatus/ReplicationPipelineStatus.types.ts similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus/ReplicationPipelineStatus.types.ts rename to apps/studio/components/interfaces/Database/ETL/ReplicationPipelineStatus/ReplicationPipelineStatus.types.ts diff --git a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus/ReplicationPipelineStatus.utils.tsx b/apps/studio/components/interfaces/Database/ETL/ReplicationPipelineStatus/ReplicationPipelineStatus.utils.tsx similarity index 98% rename from apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus/ReplicationPipelineStatus.utils.tsx rename to apps/studio/components/interfaces/Database/ETL/ReplicationPipelineStatus/ReplicationPipelineStatus.utils.tsx index 76552b4d1df98..6270223b61540 100644 --- a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus/ReplicationPipelineStatus.utils.tsx +++ b/apps/studio/components/interfaces/Database/ETL/ReplicationPipelineStatus/ReplicationPipelineStatus.utils.tsx @@ -1,7 +1,7 @@ import dayjs from 'dayjs' import { Activity, Clock, HelpCircle, Loader2, XCircle } from 'lucide-react' -import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query' +import { ReplicationPipelineStatusData } from 'data/etl/pipeline-status-query' import { formatBytes } from 'lib/helpers' import { PipelineStatusRequestStatus } from 'state/replication-pipeline-request-status' import { Badge } from 'ui' diff --git a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus/SlotLagMetrics.tsx b/apps/studio/components/interfaces/Database/ETL/ReplicationPipelineStatus/SlotLagMetrics.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus/SlotLagMetrics.tsx rename to apps/studio/components/interfaces/Database/ETL/ReplicationPipelineStatus/SlotLagMetrics.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/RetryCountdown.tsx b/apps/studio/components/interfaces/Database/ETL/RetryCountdown.tsx similarity index 100% rename from apps/studio/components/interfaces/Database/Replication/RetryCountdown.tsx rename to apps/studio/components/interfaces/Database/ETL/RetryCountdown.tsx diff --git a/apps/studio/components/interfaces/Database/Replication/RetryOptionsDropdown.tsx b/apps/studio/components/interfaces/Database/ETL/RetryOptionsDropdown.tsx similarity index 95% rename from apps/studio/components/interfaces/Database/Replication/RetryOptionsDropdown.tsx rename to apps/studio/components/interfaces/Database/ETL/RetryOptionsDropdown.tsx index 147f8cc5befb3..aba8f87b58843 100644 --- a/apps/studio/components/interfaces/Database/Replication/RetryOptionsDropdown.tsx +++ b/apps/studio/components/interfaces/Database/ETL/RetryOptionsDropdown.tsx @@ -3,8 +3,8 @@ import { useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { RollbackType, useRollbackTableMutation } from 'data/replication/rollback-table-mutation' -import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' +import { RollbackType, useRollbackTableMutation } from 'data/etl/rollback-table-mutation' +import { useStartPipelineMutation } from 'data/etl/start-pipeline-mutation' import { Button, DropdownMenu, diff --git a/apps/studio/components/interfaces/Database/Replication/RowMenu.tsx b/apps/studio/components/interfaces/Database/ETL/RowMenu.tsx similarity index 95% rename from apps/studio/components/interfaces/Database/Replication/RowMenu.tsx rename to apps/studio/components/interfaces/Database/ETL/RowMenu.tsx index d20934b379a1e..9a02bb49c425d 100644 --- a/apps/studio/components/interfaces/Database/Replication/RowMenu.tsx +++ b/apps/studio/components/interfaces/Database/ETL/RowMenu.tsx @@ -3,10 +3,10 @@ import { toast } from 'sonner' import { useParams } from 'common' import AlertError from 'components/ui/AlertError' -import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query' -import { Pipeline } from 'data/replication/pipelines-query' -import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' -import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation' +import { ReplicationPipelineStatusData } from 'data/etl/pipeline-status-query' +import { Pipeline } from 'data/etl/pipelines-query' +import { useStartPipelineMutation } from 'data/etl/start-pipeline-mutation' +import { useStopPipelineMutation } from 'data/etl/stop-pipeline-mutation' import { PipelineStatusRequestStatus, usePipelineRequestStatus, diff --git a/apps/studio/components/interfaces/Database/Replication/UpdateVersionModal.tsx b/apps/studio/components/interfaces/Database/ETL/UpdateVersionModal.tsx similarity index 90% rename from apps/studio/components/interfaces/Database/Replication/UpdateVersionModal.tsx rename to apps/studio/components/interfaces/Database/ETL/UpdateVersionModal.tsx index bcf0a86e7896e..585241a7adbf7 100644 --- a/apps/studio/components/interfaces/Database/Replication/UpdateVersionModal.tsx +++ b/apps/studio/components/interfaces/Database/ETL/UpdateVersionModal.tsx @@ -1,11 +1,11 @@ import { toast } from 'sonner' import { useParams } from 'common' -import { useReplicationPipelineStatusQuery } from 'data/replication/pipeline-status-query' -import { useReplicationPipelineVersionQuery } from 'data/replication/pipeline-version-query' -import { Pipeline } from 'data/replication/pipelines-query' -import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' -import { useUpdatePipelineVersionMutation } from 'data/replication/update-pipeline-version-mutation' +import { useReplicationPipelineStatusQuery } from 'data/etl/pipeline-status-query' +import { useReplicationPipelineVersionQuery } from 'data/etl/pipeline-version-query' +import { Pipeline } from 'data/etl/pipelines-query' +import { useStartPipelineMutation } from 'data/etl/start-pipeline-mutation' +import { useUpdatePipelineVersionMutation } from 'data/etl/update-pipeline-version-mutation' import { PipelineStatusRequestStatus, usePipelineRequestStatus, diff --git a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/ConnectTablesDialog.tsx b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/ConnectTablesDialog.tsx index 536f577160a44..95ef50311d939 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/ConnectTablesDialog.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/ConnectTablesDialog.tsx @@ -12,10 +12,10 @@ import { getCatalogURI } from 'components/interfaces/Storage/StorageSettings/Sto import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' -import { useCreateDestinationPipelineMutation } from 'data/replication/create-destination-pipeline-mutation' -import { useCreatePublicationMutation } from 'data/replication/create-publication-mutation' -import { useReplicationSourcesQuery } from 'data/replication/sources-query' -import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' +import { useCreateDestinationPipelineMutation } from 'data/etl/create-destination-pipeline-mutation' +import { useCreatePublicationMutation } from 'data/etl/create-publication-mutation' +import { useReplicationSourcesQuery } from 'data/etl/sources-query' +import { useStartPipelineMutation } from 'data/etl/start-pipeline-mutation' import { useIcebergNamespaceCreateMutation } from 'data/storage/iceberg-namespace-create-mutation' import { useTablesQuery } from 'data/tables/tables-query' import { getDecryptedValues } from 'data/vault/vault-secret-decrypted-value-query' diff --git a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/NamespaceWithTables.tsx b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/NamespaceWithTables.tsx index 7c85ce811bf5a..0d7e433b598bd 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/NamespaceWithTables.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/NamespaceWithTables.tsx @@ -125,7 +125,7 @@ const TableRowComponent = ({

Query in SQL Editor

- +

View replication status

diff --git a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/useAnalyticsBucketAssociatedEntities.tsx b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/useAnalyticsBucketAssociatedEntities.tsx index 539aa0a836f14..c869502e2b095 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/useAnalyticsBucketAssociatedEntities.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/useAnalyticsBucketAssociatedEntities.tsx @@ -6,8 +6,8 @@ import { FDW } from 'data/fdw/fdws-query' import { ReplicationPublication, useReplicationPublicationsQuery, -} from 'data/replication/publications-query' -import { useReplicationSourcesQuery } from 'data/replication/sources-query' +} from 'data/etl/publications-query' +import { useReplicationSourcesQuery } from 'data/etl/sources-query' import { useS3AccessKeyDeleteMutation } from 'data/storage/s3-access-key-delete-mutation' import { S3AccessKey, useStorageCredentialsQuery } from 'data/storage/s3-access-key-query' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' diff --git a/apps/studio/components/layouts/DatabaseLayout/Database.Commands.tsx b/apps/studio/components/layouts/DatabaseLayout/Database.Commands.tsx index 1ccb9a81ad2ef..4ce4ab5e08368 100644 --- a/apps/studio/components/layouts/DatabaseLayout/Database.Commands.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/Database.Commands.tsx @@ -81,10 +81,10 @@ export function useDatabaseGotoCommands(options?: CommandOptions) { ...(databaseReplication ? [ { - id: 'nav-database-replication', - name: 'Replication', - value: 'Database: Replication', - route: `/project/${ref}/database/replication`, + id: 'nav-database-etl', + name: 'ETL Replication', + value: 'Database: ETL Replication', + route: `/project/${ref}/database/etl`, defaultHidden: true, } as IRouteCommand, ] diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx index a3e5dc09b7ea3..9d3640e2dbce8 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.tsx @@ -78,9 +78,9 @@ export const generateDatabaseMenu = ( ...(showPgReplicate ? [ { - name: 'Replication', - key: 'replication', - url: `/project/${ref}/database/replication`, + name: 'ETL Replication', + key: 'etl', + url: `/project/${ref}/database/etl`, items: [], }, ] diff --git a/apps/studio/components/layouts/LogsLayout/LogsSidebarMenuV2.tsx b/apps/studio/components/layouts/LogsLayout/LogsSidebarMenuV2.tsx index 7c7a149b5da26..a615a9562c2d7 100644 --- a/apps/studio/components/layouts/LogsLayout/LogsSidebarMenuV2.tsx +++ b/apps/studio/components/layouts/LogsLayout/LogsSidebarMenuV2.tsx @@ -12,7 +12,7 @@ import SavedQueriesItem from 'components/interfaces/Settings/Logs/Logs.SavedQuer import { LogsSidebarItem } from 'components/interfaces/Settings/Logs/SidebarV2/SidebarItem' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useContentQuery } from 'data/content/content-query' -import { useReplicationSourcesQuery } from 'data/replication/sources-query' +import { useReplicationSourcesQuery } from 'data/etl/sources-query' import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { diff --git a/apps/studio/data/replication/create-destination-pipeline-mutation.ts b/apps/studio/data/etl/create-destination-pipeline-mutation.ts similarity index 100% rename from apps/studio/data/replication/create-destination-pipeline-mutation.ts rename to apps/studio/data/etl/create-destination-pipeline-mutation.ts diff --git a/apps/studio/data/replication/create-publication-mutation.ts b/apps/studio/data/etl/create-publication-mutation.ts similarity index 100% rename from apps/studio/data/replication/create-publication-mutation.ts rename to apps/studio/data/etl/create-publication-mutation.ts diff --git a/apps/studio/data/replication/create-tenant-source-mutation.ts b/apps/studio/data/etl/create-tenant-source-mutation.ts similarity index 100% rename from apps/studio/data/replication/create-tenant-source-mutation.ts rename to apps/studio/data/etl/create-tenant-source-mutation.ts diff --git a/apps/studio/data/replication/delete-destination-pipeline-mutation.ts b/apps/studio/data/etl/delete-destination-pipeline-mutation.ts similarity index 100% rename from apps/studio/data/replication/delete-destination-pipeline-mutation.ts rename to apps/studio/data/etl/delete-destination-pipeline-mutation.ts diff --git a/apps/studio/data/replication/destination-by-id-query.ts b/apps/studio/data/etl/destination-by-id-query.ts similarity index 100% rename from apps/studio/data/replication/destination-by-id-query.ts rename to apps/studio/data/etl/destination-by-id-query.ts diff --git a/apps/studio/data/replication/destinations-query.ts b/apps/studio/data/etl/destinations-query.ts similarity index 100% rename from apps/studio/data/replication/destinations-query.ts rename to apps/studio/data/etl/destinations-query.ts diff --git a/apps/studio/data/replication/keys.ts b/apps/studio/data/etl/keys.ts similarity index 100% rename from apps/studio/data/replication/keys.ts rename to apps/studio/data/etl/keys.ts diff --git a/apps/studio/data/replication/pipeline-by-id-query.ts b/apps/studio/data/etl/pipeline-by-id-query.ts similarity index 100% rename from apps/studio/data/replication/pipeline-by-id-query.ts rename to apps/studio/data/etl/pipeline-by-id-query.ts diff --git a/apps/studio/data/replication/pipeline-replication-status-query.ts b/apps/studio/data/etl/pipeline-replication-status-query.ts similarity index 100% rename from apps/studio/data/replication/pipeline-replication-status-query.ts rename to apps/studio/data/etl/pipeline-replication-status-query.ts diff --git a/apps/studio/data/replication/pipeline-status-query.ts b/apps/studio/data/etl/pipeline-status-query.ts similarity index 100% rename from apps/studio/data/replication/pipeline-status-query.ts rename to apps/studio/data/etl/pipeline-status-query.ts diff --git a/apps/studio/data/replication/pipeline-version-query.ts b/apps/studio/data/etl/pipeline-version-query.ts similarity index 100% rename from apps/studio/data/replication/pipeline-version-query.ts rename to apps/studio/data/etl/pipeline-version-query.ts diff --git a/apps/studio/data/replication/pipelines-query.ts b/apps/studio/data/etl/pipelines-query.ts similarity index 100% rename from apps/studio/data/replication/pipelines-query.ts rename to apps/studio/data/etl/pipelines-query.ts diff --git a/apps/studio/data/replication/publication-delete-mutation.ts b/apps/studio/data/etl/publication-delete-mutation.ts similarity index 100% rename from apps/studio/data/replication/publication-delete-mutation.ts rename to apps/studio/data/etl/publication-delete-mutation.ts diff --git a/apps/studio/data/replication/publications-query.ts b/apps/studio/data/etl/publications-query.ts similarity index 100% rename from apps/studio/data/replication/publications-query.ts rename to apps/studio/data/etl/publications-query.ts diff --git a/apps/studio/data/replication/rollback-table-mutation.ts b/apps/studio/data/etl/rollback-table-mutation.ts similarity index 100% rename from apps/studio/data/replication/rollback-table-mutation.ts rename to apps/studio/data/etl/rollback-table-mutation.ts diff --git a/apps/studio/data/replication/sources-query.ts b/apps/studio/data/etl/sources-query.ts similarity index 100% rename from apps/studio/data/replication/sources-query.ts rename to apps/studio/data/etl/sources-query.ts diff --git a/apps/studio/data/replication/start-pipeline-mutation.ts b/apps/studio/data/etl/start-pipeline-mutation.ts similarity index 100% rename from apps/studio/data/replication/start-pipeline-mutation.ts rename to apps/studio/data/etl/start-pipeline-mutation.ts diff --git a/apps/studio/data/replication/stop-pipeline-mutation.ts b/apps/studio/data/etl/stop-pipeline-mutation.ts similarity index 100% rename from apps/studio/data/replication/stop-pipeline-mutation.ts rename to apps/studio/data/etl/stop-pipeline-mutation.ts diff --git a/apps/studio/data/replication/tables-query.ts b/apps/studio/data/etl/tables-query.ts similarity index 100% rename from apps/studio/data/replication/tables-query.ts rename to apps/studio/data/etl/tables-query.ts diff --git a/apps/studio/data/replication/update-destination-pipeline-mutation.ts b/apps/studio/data/etl/update-destination-pipeline-mutation.ts similarity index 100% rename from apps/studio/data/replication/update-destination-pipeline-mutation.ts rename to apps/studio/data/etl/update-destination-pipeline-mutation.ts diff --git a/apps/studio/data/replication/update-pipeline-version-mutation.ts b/apps/studio/data/etl/update-pipeline-version-mutation.ts similarity index 100% rename from apps/studio/data/replication/update-pipeline-version-mutation.ts rename to apps/studio/data/etl/update-pipeline-version-mutation.ts diff --git a/apps/studio/pages/project/[ref]/database/replication/[pipelineId].tsx b/apps/studio/pages/project/[ref]/database/etl/[pipelineId].tsx similarity index 85% rename from apps/studio/pages/project/[ref]/database/replication/[pipelineId].tsx rename to apps/studio/pages/project/[ref]/database/etl/[pipelineId].tsx index 03ffa0ba6f0b4..81846f1fe9ce0 100644 --- a/apps/studio/pages/project/[ref]/database/replication/[pipelineId].tsx +++ b/apps/studio/pages/project/[ref]/database/etl/[pipelineId].tsx @@ -2,7 +2,7 @@ import { useRouter } from 'next/router' import { useContext, useEffect } from 'react' import { FeatureFlagContext, useFlag, useParams } from 'common' -import { ReplicationPipelineStatus } from 'components/interfaces/Database/Replication/ReplicationPipelineStatus/ReplicationPipelineStatus' +import { ReplicationPipelineStatus } from 'components/interfaces/Database/ETL/ReplicationPipelineStatus/ReplicationPipelineStatus' import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout' import DefaultLayout from 'components/layouts/DefaultLayout' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' @@ -18,7 +18,7 @@ const DatabaseReplicationPage: NextPageWithLayout = () => { useEffect(() => { if (hasLoaded && !enablePgReplicate) { - router.replace(`/project/${ref}/database/replication}`) + router.replace(`/project/${ref}/database/etl}`) } }, [router, hasLoaded, ref, enablePgReplicate]) @@ -29,7 +29,7 @@ const DatabaseReplicationPage: NextPageWithLayout = () => {
- +
@@ -42,7 +42,7 @@ const DatabaseReplicationPage: NextPageWithLayout = () => { DatabaseReplicationPage.getLayout = (page) => ( - {page} + {page} ) diff --git a/apps/studio/pages/project/[ref]/database/replication/index.tsx b/apps/studio/pages/project/[ref]/database/etl/index.tsx similarity index 86% rename from apps/studio/pages/project/[ref]/database/replication/index.tsx rename to apps/studio/pages/project/[ref]/database/etl/index.tsx index b47f8257ff428..33c232dd83bac 100644 --- a/apps/studio/pages/project/[ref]/database/replication/index.tsx +++ b/apps/studio/pages/project/[ref]/database/etl/index.tsx @@ -1,6 +1,6 @@ import { useFlag, useParams } from 'common' -import { ReplicationComingSoon } from 'components/interfaces/Database/Replication/ComingSoon' -import { Destinations } from 'components/interfaces/Database/Replication/Destinations' +import { ReplicationComingSoon } from 'components/interfaces/Database/ETL/ComingSoon' +import { Destinations } from 'components/interfaces/Database/ETL/Destinations' import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout' import DefaultLayout from 'components/layouts/DefaultLayout' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' @@ -28,7 +28,7 @@ const DatabaseReplicationPage: NextPageWithLayout = () => {
@@ -41,7 +41,7 @@ const DatabaseReplicationPage: NextPageWithLayout = () => {
- +
@@ -54,7 +54,7 @@ const DatabaseReplicationPage: NextPageWithLayout = () => { DatabaseReplicationPage.getLayout = (page) => ( - {page} + {page} )