diff --git a/apps/studio/components/interfaces/ConnectSheet/ConnectSheet.tsx b/apps/studio/components/interfaces/ConnectSheet/ConnectSheet.tsx
index 94e88691cbf..cc0b4ff7fff 100644
--- a/apps/studio/components/interfaces/ConnectSheet/ConnectSheet.tsx
+++ b/apps/studio/components/interfaces/ConnectSheet/ConnectSheet.tsx
@@ -23,25 +23,17 @@ export const ConnectSheet = ({ open, onOpenChange, connectTab }: ConnectSheetPro
const {
projectConnectionShowAppFrameworks: showAppFrameworks,
projectConnectionShowMobileFrameworks: showMobileFrameworks,
- projectConnectionShowOrms: showOrms,
} = useIsFeatureEnabled([
'project_connection:show_app_frameworks',
'project_connection:show_mobile_frameworks',
- 'project_connection:show_orms',
])
// Filter available modes based on feature flags
const availableModeIds = useMemo(() => {
- const modes: string[] = []
const showFrameworks = showAppFrameworks || showMobileFrameworks
- if (showFrameworks) modes.push('framework')
- modes.push('direct')
- if (showOrms) modes.push('orm')
- modes.push('mcp')
-
- return modes
- }, [showAppFrameworks, showMobileFrameworks, showOrms])
+ return showFrameworks ? ['framework'] : []
+ }, [showAppFrameworks, showMobileFrameworks])
const { state, updateField, setMode, activeFields, resolvedSteps, getFieldOptions, schema } =
useConnectState()
@@ -90,10 +82,7 @@ export const ConnectSheet = ({ open, onOpenChange, connectTab }: ConnectSheetPro
useEffect(() => {
if (!open) return
if (typeof connectTab === 'string') {
- if (connectTab === 'mcp') setMode('mcp')
- else if (connectTab === 'orms') setMode('orm')
- else if (connectTab === 'direct') setMode('direct')
- else if (connectTab === 'frameworks' || connectTab === 'mobiles') setMode('framework')
+ if (connectTab === 'frameworks' || connectTab === 'mobiles') setMode('framework')
}
}, [connectTab, open, setMode])
@@ -123,7 +112,9 @@ export const ConnectSheet = ({ open, onOpenChange, connectTab }: ConnectSheetPro
{/* Configuration Section */}
-
+ {availableModes.length > 1 && (
+
+ )}
{
test('should have all required modes', () => {
const modeIds = connectSchema.modes.map((m) => m.id)
- expect(modeIds).toContain('framework')
- expect(modeIds).toContain('direct')
- expect(modeIds).toContain('orm')
- expect(modeIds).toContain('mcp')
+ expect(modeIds).toEqual(['framework'])
})
test('each mode should have required properties', () => {
@@ -34,23 +31,19 @@ describe('connect.schema:structure', () => {
expect(frameworkMode?.fields).toContain('frameworkUi')
})
- test('direct mode should have correct fields', () => {
+ test('direct mode should be removed', () => {
const directMode = connectSchema.modes.find((m) => m.id === 'direct')
- expect(directMode?.fields).toContain('connectionMethod')
- expect(directMode?.fields).toContain('useSharedPooler')
- expect(directMode?.fields).toContain('connectionType')
+ expect(directMode).toBeUndefined()
})
- test('orm mode should have correct fields', () => {
+ test('orm mode should be removed', () => {
const ormMode = connectSchema.modes.find((m) => m.id === 'orm')
- expect(ormMode?.fields).toContain('orm')
+ expect(ormMode).toBeUndefined()
})
- test('mcp mode should have correct fields', () => {
+ test('mcp mode should be removed', () => {
const mcpMode = connectSchema.modes.find((m) => m.id === 'mcp')
- expect(mcpMode?.fields).toContain('mcpClient')
- expect(mcpMode?.fields).toContain('mcpReadonly')
- expect(mcpMode?.fields).toContain('mcpFeatures')
+ expect(mcpMode).toBeUndefined()
})
test('all mode fields should exist in fields definition', () => {
@@ -89,37 +82,29 @@ describe('connect.schema:fields', () => {
expect(field.dependsOn).toEqual({ framework: ['nextjs', 'react'] })
})
- test('connectionMethod field should have radio-list type', () => {
+ test('connectionMethod field should be removed', () => {
const field = connectSchema.fields.connectionMethod
- expect(field.type).toBe('radio-list')
- expect(field.options).toEqual({ source: 'connectionMethods' })
- expect(field.defaultValue).toBe('direct')
+ expect(field).toBeUndefined()
})
- test('useSharedPooler field should depend on transaction connection method', () => {
+ test('useSharedPooler field should be removed', () => {
const field = connectSchema.fields.useSharedPooler
- expect(field.type).toBe('switch')
- expect(field.dependsOn).toEqual({ connectionMethod: ['transaction'] })
+ expect(field).toBeUndefined()
})
- test('orm field should have radio-list type', () => {
+ test('orm field should be removed', () => {
const field = connectSchema.fields.orm
- expect(field.type).toBe('radio-list')
- expect(field.options).toEqual({ source: 'orms' })
- expect(field.defaultValue).toBe('prisma')
+ expect(field).toBeUndefined()
})
- test('mcpClient field should have select type', () => {
+ test('mcpClient field should be removed', () => {
const field = connectSchema.fields.mcpClient
- expect(field.type).toBe('select')
- expect(field.options).toEqual({ source: 'mcpClients' })
- expect(field.defaultValue).toBe('cursor')
+ expect(field).toBeUndefined()
})
- test('mcpFeatures field should have multi-select type', () => {
+ test('mcpFeatures field should be removed', () => {
const field = connectSchema.fields.mcpFeatures
- expect(field.type).toBe('multi-select')
- expect(field.options).toEqual({ source: 'mcpFeatures' })
+ expect(field).toBeUndefined()
})
})
@@ -198,101 +183,35 @@ describe('connect.schema:steps resolution', () => {
})
describe('direct mode steps', () => {
- test('should resolve connection step for default direct mode', () => {
+ test('should not resolve steps for direct mode', () => {
const state: ConnectState = { mode: 'direct' }
const steps = resolveSteps(connectSchema, state)
- expect(steps.find((s) => s.id === 'connection')).toBeDefined()
- })
-
- test('should resolve install and files steps for nodejs connection type', () => {
- const state: ConnectState = { mode: 'direct', connectionType: 'nodejs' }
- const steps = resolveSteps(connectSchema, state)
-
- expect(steps.find((s) => s.id === 'direct-install')).toBeDefined()
- expect(steps.find((s) => s.id === 'direct-files')).toBeDefined()
- })
-
- test('should resolve install and files steps for golang connection type', () => {
- const state: ConnectState = { mode: 'direct', connectionType: 'golang' }
- const steps = resolveSteps(connectSchema, state)
-
- expect(steps.find((s) => s.id === 'direct-install')).toBeDefined()
- expect(steps.find((s) => s.id === 'direct-files')).toBeDefined()
- })
-
- test('should resolve install and files steps for python connection type', () => {
- const state: ConnectState = { mode: 'direct', connectionType: 'python' }
- const steps = resolveSteps(connectSchema, state)
-
- expect(steps.find((s) => s.id === 'direct-install')).toBeDefined()
- })
-
- test('should resolve install and files steps for dotnet connection type', () => {
- const state: ConnectState = { mode: 'direct', connectionType: 'dotnet' }
- const steps = resolveSteps(connectSchema, state)
-
- expect(steps.find((s) => s.id === 'direct-install')).toBeDefined()
+ expect(steps.length).toBe(0)
})
})
describe('orm mode steps', () => {
- test('should resolve install and configure steps for prisma', () => {
+ test('should not resolve steps for orm mode', () => {
const state: ConnectState = { mode: 'orm', orm: 'prisma' }
const steps = resolveSteps(connectSchema, state)
- expect(steps.find((s) => s.id === 'install')).toBeDefined()
- expect(steps.find((s) => s.id === 'configure')).toBeDefined()
- expect(steps.find((s) => s.id === 'install-skills')).toBeDefined()
- })
-
- test('should resolve install and configure steps for drizzle', () => {
- const state: ConnectState = { mode: 'orm', orm: 'drizzle' }
- const steps = resolveSteps(connectSchema, state)
-
- expect(steps.find((s) => s.id === 'install')).toBeDefined()
- expect(steps.find((s) => s.id === 'configure')).toBeDefined()
+ expect(steps.length).toBe(0)
})
})
describe('mcp mode steps', () => {
- test('should resolve configure step for cursor client', () => {
+ test('should not resolve steps for mcp mode', () => {
const state: ConnectState = { mode: 'mcp', mcpClient: 'cursor' }
const steps = resolveSteps(connectSchema, state)
- expect(steps.find((s) => s.id === 'configure-mcp')).toBeDefined()
- expect(steps.find((s) => s.id === 'install-skills')).toBeDefined()
- })
-
- test('should resolve codex-specific steps for codex client', () => {
- const state: ConnectState = { mode: 'mcp', mcpClient: 'codex' }
- const steps = resolveSteps(connectSchema, state)
-
- expect(steps.find((s) => s.id === 'codex-add-server')).toBeDefined()
- expect(steps.find((s) => s.id === 'codex-enable-remote')).toBeDefined()
- expect(steps.find((s) => s.id === 'codex-authenticate')).toBeDefined()
- expect(steps.find((s) => s.id === 'codex-verify')).toBeDefined()
- })
-
- test('should resolve claude-code-specific steps for claude-code client', () => {
- const state: ConnectState = { mode: 'mcp', mcpClient: 'claude-code' }
- const steps = resolveSteps(connectSchema, state)
-
- expect(steps.find((s) => s.id === 'claude-add-server')).toBeDefined()
- expect(steps.find((s) => s.id === 'claude-authenticate')).toBeDefined()
- })
-
- test('should resolve default mcp steps for other clients', () => {
- const state: ConnectState = { mode: 'mcp', mcpClient: 'unknown-client' }
- const steps = resolveSteps(connectSchema, state)
-
- expect(steps.find((s) => s.id === 'configure-mcp')).toBeDefined()
+ expect(steps.length).toBe(0)
})
})
describe('skills install step', () => {
test('should include skills install step in all modes', () => {
- const modes: ConnectState['mode'][] = ['framework', 'direct', 'orm', 'mcp']
+ const modes: ConnectState['mode'][] = ['framework']
modes.forEach((mode) => {
const state: ConnectState = { mode }
@@ -336,12 +255,11 @@ describe('connect.schema:step content paths', () => {
expect(exploreStep?.content).toBe('steps/shadcn/explore')
})
- test('direct connection step should have valid content path', () => {
+ test('direct connection step should not be resolved', () => {
const state: ConnectState = { mode: 'direct' }
const steps = resolveSteps(connectSchema, state)
- const connectionStep = steps.find((s) => s.id === 'connection')
- expect(connectionStep?.content).toBe('steps/direct-connection')
+ expect(steps.length).toBe(0)
})
test('skills install step should have valid content path', () => {
@@ -352,50 +270,31 @@ describe('connect.schema:step content paths', () => {
expect(skillsStep?.content).toBe('steps/skills-install')
})
- test('orm configure step should use template content path', () => {
- // The ORM configure step uses a template {{orm}} that gets resolved
- // by the dynamic import system, not the resolver
+ test('orm configure step should not be resolved', () => {
const state: ConnectState = { mode: 'orm', orm: 'prisma' }
const steps = resolveSteps(connectSchema, state)
- const configureStep = steps.find((s) => s.id === 'configure')
- // The content path uses template syntax for the component loader
- expect(configureStep?.content).toBe('{{orm}}')
+ expect(steps.length).toBe(0)
})
- test('mcp cursor configure step should have valid content path', () => {
+ test('mcp cursor configure step should not be resolved', () => {
const state: ConnectState = { mode: 'mcp', mcpClient: 'cursor' }
const steps = resolveSteps(connectSchema, state)
- const configureStep = steps.find((s) => s.id === 'configure-mcp')
- expect(configureStep?.content).toBe('steps/mcp/cursor')
+ expect(steps.length).toBe(0)
})
- test('codex steps should have valid content paths', () => {
+ test('codex steps should not be resolved', () => {
const state: ConnectState = { mode: 'mcp', mcpClient: 'codex' }
const steps = resolveSteps(connectSchema, state)
- expect(steps.find((s) => s.id === 'codex-add-server')?.content).toBe(
- 'steps/mcp/codex/add-server'
- )
- expect(steps.find((s) => s.id === 'codex-enable-remote')?.content).toBe(
- 'steps/mcp/codex/enable-remote'
- )
- expect(steps.find((s) => s.id === 'codex-authenticate')?.content).toBe(
- 'steps/mcp/codex/authenticate'
- )
- expect(steps.find((s) => s.id === 'codex-verify')?.content).toBe('steps/mcp/codex/verify')
+ expect(steps.length).toBe(0)
})
- test('claude-code steps should have valid content paths', () => {
+ test('claude-code steps should not be resolved', () => {
const state: ConnectState = { mode: 'mcp', mcpClient: 'claude-code' }
const steps = resolveSteps(connectSchema, state)
- expect(steps.find((s) => s.id === 'claude-add-server')?.content).toBe(
- 'steps/mcp/claude-code/add-server'
- )
- expect(steps.find((s) => s.id === 'claude-authenticate')?.content).toBe(
- 'steps/mcp/claude-code/authenticate'
- )
+ expect(steps.length).toBe(0)
})
})
diff --git a/apps/studio/components/interfaces/ConnectSheet/connect.schema.ts b/apps/studio/components/interfaces/ConnectSheet/connect.schema.ts
index f4171d1877b..a33703373df 100644
--- a/apps/studio/components/interfaces/ConnectSheet/connect.schema.ts
+++ b/apps/studio/components/interfaces/ConnectSheet/connect.schema.ts
@@ -60,92 +60,6 @@ const frameworkShadcnExploreStep: StepDefinition = {
content: 'steps/shadcn/explore',
}
-const directConnectionStep: StepDefinition = {
- id: 'connection',
- title: 'Connection string',
- description: 'Copy the connection details for your database.',
- content: 'steps/direct-connection',
-}
-
-const directInstallStep: StepDefinition = {
- id: 'direct-install',
- title: 'Install dependencies',
- description: 'Run this command to install the required dependencies.',
- content: 'steps/direct-install',
-}
-
-const directFilesStep: StepDefinition = {
- id: 'direct-files',
- title: 'Add files',
- description: 'Add the following files to your project.',
- content: 'steps/direct-files',
-}
-
-const mcpConfigureStep: StepDefinition = {
- id: 'configure-mcp',
- title: 'Configure MCP',
- description: 'Set up your MCP client.',
- content: 'steps/mcp/cursor',
-}
-
-// Codex-specific MCP steps
-const codexAddServerStep: StepDefinition = {
- id: 'codex-add-server',
- title: 'Add the Supabase MCP server to Codex',
- description: 'Run this command to add the server.',
- content: 'steps/mcp/codex/add-server',
-}
-
-const codexEnableRemoteStep: StepDefinition = {
- id: 'codex-enable-remote',
- title: 'Enable remote MCP client support',
- description: 'Add this to your ~/.codex/config.toml file.',
- content: 'steps/mcp/codex/enable-remote',
-}
-
-const codexAuthenticateStep: StepDefinition = {
- id: 'codex-authenticate',
- title: 'Authenticate',
- description: 'Run the authentication command.',
- content: 'steps/mcp/codex/authenticate',
-}
-
-const codexVerifyStep: StepDefinition = {
- id: 'codex-verify',
- title: 'Verify authentication',
- description: 'Run /mcp inside Codex to verify.',
- content: 'steps/mcp/codex/verify',
-}
-
-const claudeAddServerStep: StepDefinition = {
- id: 'claude-add-server',
- title: 'Add MCP server',
- description: 'Add the MCP server to your project config using the command line.',
- content: 'steps/mcp/claude-code/add-server',
-}
-
-const claudeAuthenticateStep: StepDefinition = {
- id: 'claude-authenticate',
- title: 'Authenticate',
- description:
- 'After configuring the MCP server, you need to authenticate. In a regular terminal (not the IDE extension) run:',
- content: 'steps/mcp/claude-code/authenticate',
-}
-
-const ormInstallStep: StepDefinition = {
- id: 'install',
- title: 'Install ORM',
- description: 'Add the ORM to your project.',
- content: 'steps/orm-install',
-}
-
-const ormConfigureStep: StepDefinition = {
- id: 'configure',
- title: 'Configure ORM',
- description: 'Set up your ORM configuration.',
- content: '{{orm}}',
-}
-
const skillsInstallStep: StepDefinition = {
id: 'install-skills',
title: 'Install Agent Skills (Optional)',
@@ -169,24 +83,6 @@ export const connectSchema: ConnectSchema = {
description: 'Use a client library',
fields: ['framework', 'frameworkVariant', 'library', 'frameworkUi'],
},
- {
- id: 'direct',
- label: 'Direct',
- description: 'Connection string',
- fields: ['connectionMethod', 'useSharedPooler', 'connectionType'],
- },
- {
- id: 'orm',
- label: 'ORM',
- description: 'Third-party library',
- fields: ['orm'],
- },
- {
- id: 'mcp',
- label: 'MCP',
- description: 'Connect your agent',
- fields: ['mcpClient', 'mcpReadonly', 'mcpFeatures'],
- },
],
// -------------------------------------------------------------------------
@@ -224,64 +120,6 @@ export const connectSchema: ConnectSchema = {
defaultValue: false,
dependsOn: { framework: ['nextjs', 'react'] },
},
-
- // Direct connection fields
- connectionMethod: {
- id: 'connectionMethod',
- type: 'radio-list',
- label: 'Connection Method',
- options: { source: 'connectionMethods' },
- defaultValue: 'direct',
- },
- useSharedPooler: {
- id: 'useSharedPooler',
- type: 'switch',
- label: 'Use IPv4 connection (Shared Pooler)',
- description: 'Only recommended when your network does not support IPv6',
- defaultValue: false,
- dependsOn: { connectionMethod: ['transaction'] },
- },
- connectionType: {
- id: 'connectionType',
- type: 'select',
- label: 'Type',
- options: { source: 'connectionTypes' },
- defaultValue: 'uri',
- },
-
- // ORM fields
- orm: {
- id: 'orm',
- type: 'radio-list',
- label: 'ORM',
- options: { source: 'orms' },
- defaultValue: 'prisma',
- },
-
- // MCP fields
- mcpClient: {
- id: 'mcpClient',
- type: 'select',
- label: 'Client',
- description: 'Choose the MCP client you are using.',
- options: { source: 'mcpClients' },
- defaultValue: 'cursor',
- },
- mcpReadonly: {
- id: 'mcpReadonly',
- type: 'switch',
- label: 'Read-only',
- description: 'Only allow read operations on your database',
- defaultValue: false,
- },
- mcpFeatures: {
- id: 'mcpFeatures',
- type: 'multi-select',
- label: 'Feature groups',
- description:
- 'Only enable a subset of features. Helps keep the number of tools within MCP client limits.',
- options: { source: 'mcpFeatures' },
- },
},
// -------------------------------------------------------------------------
@@ -317,31 +155,6 @@ export const connectSchema: ConnectSchema = {
DEFAULT: [frameworkInstallStep, frameworkConfigureStep, skillsInstallStep],
},
},
- direct: {
- connectionType: {
- nodejs: [directInstallStep, directFilesStep, skillsInstallStep],
- golang: [directInstallStep, directFilesStep, skillsInstallStep],
- dotnet: [directInstallStep, directFilesStep, skillsInstallStep],
- python: [directInstallStep, directFilesStep, skillsInstallStep],
- sqlalchemy: [directInstallStep, directFilesStep, skillsInstallStep],
- DEFAULT: [directConnectionStep, skillsInstallStep],
- },
- },
- orm: [ormInstallStep, ormConfigureStep, skillsInstallStep],
- mcp: {
- mcpClient: {
- codex: [
- codexAddServerStep,
- codexEnableRemoteStep,
- codexAuthenticateStep,
- codexVerifyStep,
- skillsInstallStep,
- ],
- 'claude-code': [claudeAddServerStep, claudeAuthenticateStep, skillsInstallStep],
- DEFAULT: [mcpConfigureStep, skillsInstallStep],
- },
- },
- DEFAULT: [skillsInstallStep],
},
},
}
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/drizzle/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/drizzle/content.tsx
deleted file mode 100644
index 1a693850624..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/drizzle/content.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { MultipleCodeBlock } from 'ui-patterns/MultipleCodeBlock'
-
-import type { ContentFileProps } from '@/components/interfaces/ConnectSheet/Connect.types'
-
-const ContentFile = ({ connectionStringPooler }: ContentFileProps) => {
- const files = [
- {
- name: '.env',
- language: 'bash',
- code:
- connectionStringPooler.ipv4SupportedForDedicatedPooler &&
- connectionStringPooler.transactionDedicated
- ? `
-DATABASE_URL="${connectionStringPooler.transactionDedicated}"
- `
- : connectionStringPooler.transactionDedicated &&
- !connectionStringPooler.ipv4SupportedForDedicatedPooler
- ? `
-# Use Shared connection pooler (supports both IPv4/IPv6)
-DATABASE_URL="${connectionStringPooler.transactionShared}"
-
-# If your network supports IPv6 or you purchased IPv4 addon, use dedicated pooler
-# DATABASE_URL="${connectionStringPooler.transactionDedicated}"
- `
- : `
-DATABASE_URL="${connectionStringPooler.transactionShared}"
-`,
- },
- {
- name: 'drizzle/schema.tsx',
- language: 'tsx',
- code: `
-import { pgTable, serial, text, varchar } from "drizzle-orm/pg-core";
-
-export const users = pgTable('users', {
- id: serial('id').primaryKey(),
- fullName: text('full_name'),
- phone: varchar('phone', { length: 256 }),
-});
- `,
- },
- {
- name: 'index.tsx',
- language: 'tsx',
- code: `
-import { drizzle } from 'drizzle-orm/postgres-js'
-import postgres from 'postgres'
-import { users } from './schema'
-
-const connectionString = process.env.DATABASE_URL
-
-// Disable prefetch as it is not supported for "Transaction" pool mode
-const client = postgres(connectionString, { prepare: false })
-const db = drizzle(client);
-
-const allUsers = await db.select().from(users);
- `,
- },
- ]
-
- return
-}
-
-export default ContentFile
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/prisma/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/prisma/content.tsx
deleted file mode 100644
index 27ec291ce63..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/prisma/content.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { IS_PLATFORM } from 'lib/constants'
-import { MultipleCodeBlock } from 'ui-patterns/MultipleCodeBlock'
-
-import type { ContentFileProps } from '@/components/interfaces/ConnectSheet/Connect.types'
-
-const ContentFile = ({ connectionStringPooler }: ContentFileProps) => {
- const files = [
- {
- name: '.env.local',
- language: 'bash',
- code:
- connectionStringPooler.ipv4SupportedForDedicatedPooler &&
- connectionStringPooler.transactionDedicated
- ? `
-# Connect to Supabase via connection pooling.
-DATABASE_URL="${connectionStringPooler.transactionDedicated}?pgbouncer=true"
-
-# Direct connection to the database. Used for migrations.
-DIRECT_URL="${connectionStringPooler.sessionDedicated}"
- `
- : connectionStringPooler.transactionDedicated &&
- !connectionStringPooler.ipv4SupportedForDedicatedPooler
- ? `
-# Connect to Supabase via Shared Connection Pooler
-DATABASE_URL="${connectionStringPooler.transactionShared}?pgbouncer=true"
-
-# Direct connection to the database through Shared Pooler (supports IPv4/IPv6). Used for migrations.
-DIRECT_URL="${connectionStringPooler.sessionShared}"
-
-# If your network supports IPv6 or you purchased IPv4 addon, use dedicated pooler
-# DATABASE_URL="${connectionStringPooler.transactionDedicated}?pgbouncer=true"
-# DIRECT_URL="${connectionStringPooler.sessionDedicated}"
- `
- : `
-# Connect to Supabase ${IS_PLATFORM ? 'via connection pooling' : ''}
-DATABASE_URL="${IS_PLATFORM ? `${connectionStringPooler.transactionShared}?pgbouncer=true` : connectionStringPooler.direct}"
-
-# Direct connection to the database. Used for migrations
-DIRECT_URL="${IS_PLATFORM ? connectionStringPooler.sessionShared : connectionStringPooler.direct}"
-`,
- },
- {
- name: 'prisma/schema.prisma',
- language: 'bash',
- code: `
-generator client {
- provider = "prisma-client-js"
-}
-
-datasource db {
- provider = "postgresql"
- url = env("DATABASE_URL")
- directUrl = env("DIRECT_URL")
-}
- `,
- },
- ]
-
- return
-}
-
-export default ContentFile
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-connection/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-connection/content.tsx
deleted file mode 100644
index ec404cfc90d..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-connection/content.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import { useMemo } from 'react'
-import { CodeBlock } from 'ui'
-import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
-
-import {
- type ConnectionStringMethod,
- type DatabaseConnectionType,
-} from '../../../Connect.constants'
-import type { StepContentProps } from '../../../Connect.types'
-import { ConnectionParameters } from '../../../ConnectionParameters'
-import {
- PASSWORD_PLACEHOLDER,
- buildConnectionParameters,
- buildSafeConnectionString,
- parseConnectionParams,
- resolveConnectionString,
-} from '../../../ConnectionString.utils'
-
-const buildPsqlCommand = (params: { host: string; port: string; database: string; user: string }) =>
- `psql -h ${params.host} -p ${params.port} -d ${params.database} -U ${params.user}`
-
-const buildJdbcString = (params: { host: string; port: string; database: string; user: string }) =>
- `jdbc:postgresql://${params.host}:${params.port}/${params.database}?user=${params.user}&password=${PASSWORD_PLACEHOLDER}`
-
-/**
- * Step component for direct database connections.
- * Uses state to determine which connection string to show.
- */
-function DirectConnectionContent({ state, connectionStringPooler }: StepContentProps) {
- const connectionType = (state.connectionType as DatabaseConnectionType) ?? 'uri'
- const connectionMethod = (state.connectionMethod as ConnectionStringMethod) ?? 'direct'
- const useSharedPooler = Boolean(state.useSharedPooler)
-
- // Determine which connection string to use
- const resolvedConnectionString = useMemo(
- () =>
- resolveConnectionString({
- connectionMethod,
- useSharedPooler,
- connectionStringPooler,
- }),
- [connectionMethod, useSharedPooler, connectionStringPooler]
- )
-
- const connectionParams = useMemo(
- () => parseConnectionParams(resolvedConnectionString),
- [resolvedConnectionString]
- )
-
- const safeConnectionString = useMemo(
- () => buildSafeConnectionString(resolvedConnectionString, connectionParams),
- [resolvedConnectionString, connectionParams]
- )
-
- const connectionString = useMemo(() => {
- switch (connectionType) {
- case 'psql':
- return buildPsqlCommand(connectionParams)
- case 'jdbc':
- return buildJdbcString(connectionParams)
- case 'php':
- return `DATABASE_URL=${safeConnectionString}`
- case 'uri':
- default:
- return safeConnectionString
- }
- }, [connectionType, connectionParams, safeConnectionString])
-
- if (!resolvedConnectionString) {
- return (
-
-
-
- )
- }
-
- return (
-
-
- {connectionString}
-
-
-
- )
-}
-
-export default DirectConnectionContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-files/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-files/content.tsx
deleted file mode 100644
index 7d8602fafa3..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-files/content.tsx
+++ /dev/null
@@ -1,264 +0,0 @@
-import { useEffect, useMemo, useState } from 'react'
-import { CodeBlock } from 'ui'
-import { MultipleCodeBlock } from 'ui-patterns/MultipleCodeBlock'
-import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
-
-import {
- type ConnectionStringMethod,
- type DatabaseConnectionType,
-} from '../../../Connect.constants'
-import type { StepContentProps } from '../../../Connect.types'
-import { ConnectionParameters } from '../../../ConnectionParameters'
-import {
- PASSWORD_PLACEHOLDER,
- buildConnectionParameters,
- buildSafeConnectionString,
- parseConnectionParams,
- resolveConnectionString,
-} from '../../../ConnectionString.utils'
-
-const DOTNET_CONFIG_COMMAND =
- 'dotnet add package Microsoft.Extensions.Configuration.Json --version YOUR_DOTNET_VERSION'
-
-type DirectFilesConfig = {
- files: {
- name: string
- language?: string
- code: string
- }[]
- connectionStringFile?: string
- postCommands?: { label: string; command: string }[]
-}
-
-function DirectFilesContent({ state, connectionStringPooler }: StepContentProps) {
- const connectionType = (state.connectionType as DatabaseConnectionType) ?? 'uri'
- const connectionMethod = (state.connectionMethod as ConnectionStringMethod) ?? 'direct'
- const useSharedPooler = Boolean(state.useSharedPooler)
-
- const resolvedConnectionString = useMemo(
- () =>
- resolveConnectionString({
- connectionMethod,
- useSharedPooler,
- connectionStringPooler,
- }),
- [connectionMethod, useSharedPooler, connectionStringPooler]
- )
-
- const connectionParams = useMemo(
- () => parseConnectionParams(resolvedConnectionString),
- [resolvedConnectionString]
- )
-
- const safeConnectionString = useMemo(
- () => buildSafeConnectionString(resolvedConnectionString, connectionParams),
- [resolvedConnectionString, connectionParams]
- )
-
- const config: DirectFilesConfig | null = useMemo(() => {
- const envFile = {
- name: '.env',
- language: 'bash',
- code: `DATABASE_URL=${safeConnectionString}`,
- }
-
- switch (connectionType) {
- case 'nodejs':
- return {
- files: [
- {
- name: 'db.js',
- language: 'js',
- code: `import postgres from 'postgres'
-
-const connectionString = process.env.DATABASE_URL
-const sql = postgres(connectionString)
-
-export default sql`,
- },
- envFile,
- ],
- connectionStringFile: envFile.name,
- }
-
- case 'golang':
- return {
- files: [
- {
- name: 'main.go',
- language: 'go',
- code: `package main
-
-import (
-\t"context"
-\t"log"
-\t"os"
-\t"github.com/jackc/pgx/v5"
-)
-
-func main() {
-\tconn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL"))
-\tif err != nil {
-\t\tlog.Fatalf("Failed to connect to the database: %v", err)
-\t}
-\tdefer conn.Close(context.Background())
-
-\t// Example query to test connection
-\tvar version string
-\tif err := conn.QueryRow(context.Background(), "SELECT version()").Scan(&version); err != nil {
-\t\tlog.Fatalf("Query failed: %v", err)
-\t}
-
-\tlog.Println("Connected to:", version)
-}`,
- },
- envFile,
- ],
- connectionStringFile: envFile.name,
- }
-
- case 'dotnet':
- return {
- files: [
- {
- name: 'appsettings.json',
- language: 'json',
- code: `{
- "ConnectionStrings": {
- "DefaultConnection": "Host=${connectionParams.host};Database=${connectionParams.database};Username=${connectionParams.user};Password=${PASSWORD_PLACEHOLDER};SSL Mode=Require;Trust Server Certificate=true"
- }
-}`,
- },
- ],
- connectionStringFile: 'appsettings.json',
- postCommands: [
- {
- label: 'Add the configuration package to read the settings.',
- command: DOTNET_CONFIG_COMMAND,
- },
- ],
- }
-
- case 'python':
- return {
- files: [
- {
- name: 'main.py',
- language: 'python',
- code: `import psycopg2
-from dotenv import load_dotenv
-import os
-
-# Load environment variables from .env
-load_dotenv()
-
-# Fetch variables
-DATABASE_URL = os.getenv("DATABASE_URL")
-
-# Connect to the database
-connection = psycopg2.connect(DATABASE_URL)`,
- },
- envFile,
- ],
- connectionStringFile: envFile.name,
- }
-
- case 'sqlalchemy':
- return {
- files: [
- {
- name: 'main.py',
- language: 'python',
- code: `from sqlalchemy import create_engine
-# from sqlalchemy.pool import NullPool
-from dotenv import load_dotenv
-import os
-
-# Load environment variables from .env
-load_dotenv()
-
-# Fetch variables
-USER = os.getenv("user")
-PASSWORD = os.getenv("password")
-HOST = os.getenv("host")
-PORT = os.getenv("port")
-DBNAME = os.getenv("dbname")
-
-# Construct the SQLAlchemy connection string
-DATABASE_URL = f"postgresql+psycopg2://{USER}:{PASSWORD}@{HOST}:{PORT}/{DBNAME}?sslmode=require"
-
-# Create the SQLAlchemy engine
-engine = create_engine(DATABASE_URL)
-# If using Transaction Pooler or Session Pooler, we want to ensure we disable SQLAlchemy client side pooling -
-# https://docs.sqlalchemy.org/en/20/core/pooling.html#switching-pool-implementations
-# engine = create_engine(DATABASE_URL, poolclass=NullPool)
-
-# Test the connection
-try:
- with engine.connect() as connection:
- print("Connection successful!")
-except Exception as e:
- print(f"Failed to connect: {e}")`,
- },
- {
- name: '.env',
- language: 'bash',
- code: [
- `user=${connectionParams.user}`,
- `password=${PASSWORD_PLACEHOLDER}`,
- `host=${connectionParams.host}`,
- `port=${connectionParams.port}`,
- `dbname=${connectionParams.database}`,
- ].join('\n'),
- },
- ],
- connectionStringFile: '.env',
- }
-
- default:
- return null
- }
- }, [connectionType, safeConnectionString, connectionParams])
-
- const defaultFile = config?.files[0]?.name ?? ''
- const [activeFile, setActiveFile] = useState(defaultFile)
-
- useEffect(() => {
- setActiveFile(defaultFile)
- }, [connectionType, defaultFile])
-
- if (!resolvedConnectionString) {
- return (
-
-
-
- )
- }
-
- if (!config?.files.length) {
- return null
- }
-
- return (
-
-
-
- {(config.postCommands ?? []).map((command) => (
-
-
{command.label}
-
- {command.command}
-
-
- ))}
-
- )
-}
-
-export default DirectFilesContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-install/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-install/content.tsx
deleted file mode 100644
index e66e2a7359e..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/direct-install/content.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { CodeBlock } from 'ui'
-
-import type { StepContentProps } from '../../../Connect.types'
-import examples from '../../../DirectConnectionExamples'
-
-/**
- * Step component for direct connection install commands.
- */
-function DirectInstallContent({ state }: StepContentProps) {
- const connectionType = (state.connectionType as string) ?? 'uri'
- const example = examples[connectionType as keyof typeof examples]
- const exampleInstallCommands = example?.installCommands ?? []
-
- if (exampleInstallCommands.length === 0) {
- return null
- }
-
- return (
-
- {exampleInstallCommands.map((cmd) => (
-
- {cmd}
-
- ))}
-
- )
-}
-
-export default DirectInstallContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/claude-code/add-server/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/claude-code/add-server/content.tsx
deleted file mode 100644
index 00d1d68013e..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/claude-code/add-server/content.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import { useMemo } from 'react'
-import { CodeBlock } from 'ui'
-
-import { IS_PLATFORM } from 'lib/constants'
-import { FEATURE_GROUPS_NON_PLATFORM, FEATURE_GROUPS_PLATFORM } from 'ui-patterns/McpUrlBuilder'
-import type { StepContentProps } from '../../../../../Connect.types'
-
-function useMcpUrl(
- state: StepContentProps['state'],
- projectKeys: StepContentProps['projectKeys']
-): string {
- const readonly = Boolean(state.mcpReadonly)
- const selectedFeatures = Array.isArray(state.mcpFeatures) ? state.mcpFeatures : []
- const baseUrl = IS_PLATFORM ? 'https://mcp.supabase.com' : projectKeys.apiUrl ?? ''
-
- return useMemo(() => {
- const params = new URLSearchParams()
- if (readonly) params.set('readonly', 'true')
-
- const supportedFeatures = IS_PLATFORM ? FEATURE_GROUPS_PLATFORM : FEATURE_GROUPS_NON_PLATFORM
- const validFeatures = selectedFeatures.filter((f) =>
- supportedFeatures.some((group) => group.id === f)
- )
- if (validFeatures.length > 0) {
- params.set('features', validFeatures.join(','))
- }
-
- const queryString = params.toString()
- return queryString ? `${baseUrl}?${queryString}` : baseUrl
- }, [baseUrl, readonly, selectedFeatures])
-}
-
-function ClaudeAddServerContent({ state, projectKeys }: StepContentProps) {
- const mcpUrl = useMcpUrl(state, projectKeys)
- const command = `claude mcp add --scope project --transport http supabase "${mcpUrl}"`
-
- return (
-
- )
-}
-
-export default ClaudeAddServerContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/claude-code/authenticate/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/claude-code/authenticate/content.tsx
deleted file mode 100644
index 298140ef247..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/claude-code/authenticate/content.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { CodeBlock } from 'ui'
-
-import type { StepContentProps } from '../../../../../Connect.types'
-
-function ClaudeAuthenticateContent(_props: StepContentProps) {
- return (
-
-
-
- Select the supabase{' '}
- server, then Authenticate to begin the flow.
-
-
- )
-}
-
-export default ClaudeAuthenticateContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/add-server/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/add-server/content.tsx
deleted file mode 100644
index 4a6ade248eb..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/add-server/content.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import { useMemo } from 'react'
-import { CodeBlock } from 'ui'
-
-import { IS_PLATFORM } from 'lib/constants'
-import { FEATURE_GROUPS_NON_PLATFORM, FEATURE_GROUPS_PLATFORM } from 'ui-patterns/McpUrlBuilder'
-import type { StepContentProps } from '../../../../../Connect.types'
-
-function useMcpUrl(
- state: StepContentProps['state'],
- projectKeys: StepContentProps['projectKeys']
-): string {
- const readonly = Boolean(state.mcpReadonly)
- const selectedFeatures = Array.isArray(state.mcpFeatures) ? state.mcpFeatures : []
- const baseUrl = IS_PLATFORM ? 'https://mcp.supabase.com' : projectKeys.apiUrl ?? ''
-
- return useMemo(() => {
- const params = new URLSearchParams()
- if (readonly) params.set('readonly', 'true')
-
- const supportedFeatures = IS_PLATFORM ? FEATURE_GROUPS_PLATFORM : FEATURE_GROUPS_NON_PLATFORM
- const validFeatures = selectedFeatures.filter((f) =>
- supportedFeatures.some((group) => group.id === f)
- )
- if (validFeatures.length > 0) {
- params.set('features', validFeatures.join(','))
- }
-
- const queryString = params.toString()
- return queryString ? `${baseUrl}?${queryString}` : baseUrl
- }, [baseUrl, readonly, selectedFeatures])
-}
-
-function CodexAddServerContent({ state, projectKeys }: StepContentProps) {
- const mcpUrl = useMcpUrl(state, projectKeys)
- const command = `codex mcp add supabase --url ${mcpUrl}`
-
- return (
-
- )
-}
-
-export default CodexAddServerContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/authenticate/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/authenticate/content.tsx
deleted file mode 100644
index 979eb58049f..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/authenticate/content.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { CodeBlock } from 'ui'
-
-import type { StepContentProps } from '../../../../../Connect.types'
-
-function CodexAuthenticateContent(_props: StepContentProps) {
- const command = 'codex mcp login supabase'
-
- return (
-
- )
-}
-
-export default CodexAuthenticateContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/enable-remote/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/enable-remote/content.tsx
deleted file mode 100644
index ee6e8bd59ef..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/enable-remote/content.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { CodeBlock } from 'ui'
-
-import type { StepContentProps } from '../../../../../Connect.types'
-
-function CodexEnableRemoteContent(_props: StepContentProps) {
- const configContent = `[mcp]
-remote_mcp_client_enabled = true`
-
- return (
-
- )
-}
-
-export default CodexEnableRemoteContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/verify/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/verify/content.tsx
deleted file mode 100644
index 2f2d55e6ab7..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/codex/verify/content.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { StepContentProps } from '../../../../../Connect.types'
-
-function CodexVerifyContent(_props: StepContentProps) {
- return (
-
-
- Run /mcp inside Codex to
- verify authentication.
-
-
- )
-}
-
-export default CodexVerifyContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/cursor/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/cursor/content.tsx
deleted file mode 100644
index c6acbea846e..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/mcp/cursor/content.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import { useParams } from 'common'
-import { BASE_PATH, IS_PLATFORM } from 'lib/constants'
-import { useTrack } from 'lib/telemetry/track'
-import { useMemo } from 'react'
-import {
- createMcpCopyHandler,
- FEATURE_GROUPS_NON_PLATFORM,
- FEATURE_GROUPS_PLATFORM,
- getMcpUrl,
- MCP_CLIENTS,
- McpConfigurationDisplay,
-} from 'ui-patterns/McpUrlBuilder'
-import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
-
-import type { StepContentProps } from '../../../../Connect.types'
-
-function McpCursorContent({ state, projectKeys }: StepContentProps) {
- const { ref: projectRef } = useParams()
-
- if (!projectRef) {
- return (
-
-
-
-
- )
- }
-
- return
-}
-
-function McpCursorContentInner({
- projectRef,
- projectKeys,
- state,
-}: {
- projectRef: string
- projectKeys: StepContentProps['projectKeys']
- state: StepContentProps['state']
-}) {
- const track = useTrack()
-
- const selectedClient = useMemo(() => {
- const clientKey = String(state.mcpClient ?? '')
- return MCP_CLIENTS.find((c) => c.key === clientKey) ?? MCP_CLIENTS[0]
- }, [state.mcpClient])
-
- const readonly = Boolean(state.mcpReadonly)
- const selectedFeatures = Array.isArray(state.mcpFeatures) ? state.mcpFeatures : []
-
- const selectedFeaturesSupported = useMemo(() => {
- const supportedFeatures = IS_PLATFORM ? FEATURE_GROUPS_PLATFORM : FEATURE_GROUPS_NON_PLATFORM
- return selectedFeatures.filter((feature) =>
- supportedFeatures.some((group) => group.id === feature)
- )
- }, [selectedFeatures])
-
- const handleCopy = useMemo(
- () =>
- createMcpCopyHandler({
- selectedClient,
- source: 'studio',
- onTrack: (event) => track(event.action, event.properties, event.groups),
- projectRef,
- }),
- [selectedClient, track, projectRef]
- )
-
- const { clientConfig } = getMcpUrl({
- projectRef,
- isPlatform: IS_PLATFORM,
- apiUrl: projectKeys.apiUrl ?? undefined,
- readonly,
- features: selectedFeaturesSupported,
- selectedClient,
- })
-
- return (
-
- )
-}
-
-export default McpCursorContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/content/steps/orm-install/content.tsx b/apps/studio/components/interfaces/ConnectSheet/content/steps/orm-install/content.tsx
deleted file mode 100644
index a07c6b404a5..00000000000
--- a/apps/studio/components/interfaces/ConnectSheet/content/steps/orm-install/content.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { CodeBlock } from 'ui'
-
-import type { StepContentProps } from '../../../Connect.types'
-
-const ORM_INSTALL_COMMANDS: Record = {
- prisma: ['npm install prisma --save-dev', 'npx prisma init'],
- drizzle: ['npm install drizzle-orm', 'npm install drizzle-kit --save-dev'],
-}
-
-function OrmInstallContent({ state }: StepContentProps) {
- const ormKey = String(state.orm ?? '')
- const commands = ORM_INSTALL_COMMANDS[ormKey]
-
- if (!commands?.length) {
- return null
- }
-
- return (
-
- {commands.map((cmd, index) => (
-
- {cmd}
-
- ))}
-
- )
-}
-
-export default OrmInstallContent
diff --git a/apps/studio/components/interfaces/ConnectSheet/useConnectState.test.ts b/apps/studio/components/interfaces/ConnectSheet/useConnectState.test.ts
index 6741601c7f6..80f3c128a8b 100644
--- a/apps/studio/components/interfaces/ConnectSheet/useConnectState.test.ts
+++ b/apps/studio/components/interfaces/ConnectSheet/useConnectState.test.ts
@@ -30,10 +30,11 @@ describe('useConnectState', () => {
test('should accept initial state override', () => {
const { result } = renderHook(() =>
- useConnectState({ mode: 'direct', connectionMethod: 'transaction' })
+ useConnectState({ framework: 'react', frameworkVariant: 'vite' })
)
- expect(result.current.state.mode).toBe('direct')
- expect(result.current.state.connectionMethod).toBe('transaction')
+ expect(result.current.state.mode).toBe('framework')
+ expect(result.current.state.framework).toBe('react')
+ expect(result.current.state.frameworkVariant).toBe('vite')
})
test('should merge initial state with defaults', () => {
@@ -48,50 +49,7 @@ describe('useConnectState', () => {
// ============================================================================
describe('setMode', () => {
- test('should switch to direct mode', () => {
- const { result } = renderHook(() => useConnectState())
-
- act(() => {
- result.current.setMode('direct')
- })
-
- expect(result.current.state.mode).toBe('direct')
- })
-
- test('should initialize direct mode defaults when switching', () => {
- const { result } = renderHook(() => useConnectState())
-
- act(() => {
- result.current.setMode('direct')
- })
-
- expect(result.current.state.connectionMethod).toBeDefined()
- expect(result.current.state.connectionType).toBeDefined()
- })
-
- test('should switch to orm mode and initialize defaults', () => {
- const { result } = renderHook(() => useConnectState())
-
- act(() => {
- result.current.setMode('orm')
- })
-
- expect(result.current.state.mode).toBe('orm')
- expect(result.current.state.orm).toBe('prisma')
- })
-
- test('should switch to mcp mode and initialize defaults', () => {
- const { result } = renderHook(() => useConnectState())
-
- act(() => {
- result.current.setMode('mcp')
- })
-
- expect(result.current.state.mode).toBe('mcp')
- expect(result.current.state.mcpClient).toBeDefined()
- })
-
- test('should preserve framework state when switching back to framework mode', () => {
+ test('should preserve framework state when setting framework mode', () => {
const { result } = renderHook(() => useConnectState())
// Change framework
@@ -99,12 +57,7 @@ describe('useConnectState', () => {
result.current.updateField('framework', 'react')
})
- // Switch to direct
- act(() => {
- result.current.setMode('direct')
- })
-
- // Switch back to framework
+ // Set framework mode again
act(() => {
result.current.setMode('framework')
})
@@ -167,44 +120,6 @@ describe('useConnectState', () => {
expect(result.current.state.library).toBe('supabasejs')
})
- test('should update connection method', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'direct' }))
-
- act(() => {
- result.current.updateField('connectionMethod', 'transaction')
- })
-
- expect(result.current.state.connectionMethod).toBe('transaction')
- })
-
- test('should clear useSharedPooler when connectionMethod changes to direct', () => {
- const { result } = renderHook(() =>
- useConnectState({
- mode: 'direct',
- connectionMethod: 'transaction',
- useSharedPooler: true,
- })
- )
-
- act(() => {
- result.current.updateField('connectionMethod', 'direct')
- })
-
- // useSharedPooler is cleared because it depends on connectionMethod: ['transaction']
- // When the dependency is not satisfied, the field is removed from state
- expect(result.current.state.useSharedPooler).toBeUndefined()
- })
-
- test('should update MCP client', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'mcp' }))
-
- act(() => {
- result.current.updateField('mcpClient', 'codex')
- })
-
- expect(result.current.state.mcpClient).toBe('codex')
- })
-
test('should update boolean fields', () => {
const { result } = renderHook(() => useConnectState())
@@ -214,16 +129,6 @@ describe('useConnectState', () => {
expect(result.current.state.frameworkUi).toBe(true)
})
-
- test('should update ORM selection', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'orm' }))
-
- act(() => {
- result.current.updateField('orm', 'drizzle')
- })
-
- expect(result.current.state.orm).toBe('drizzle')
- })
})
// ============================================================================
@@ -258,47 +163,6 @@ describe('useConnectState', () => {
const fieldIds = result.current.activeFields.map((f) => f.id)
expect(fieldIds).not.toContain('frameworkUi')
})
-
- test('should return direct mode fields', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'direct' }))
-
- const fieldIds = result.current.activeFields.map((f) => f.id)
- expect(fieldIds).toContain('connectionMethod')
- expect(fieldIds).toContain('connectionType')
- })
-
- test('should show useSharedPooler only for transaction connection method', () => {
- const { result } = renderHook(() =>
- useConnectState({ mode: 'direct', connectionMethod: 'transaction' })
- )
-
- const fieldIds = result.current.activeFields.map((f) => f.id)
- expect(fieldIds).toContain('useSharedPooler')
- })
-
- test('should hide useSharedPooler for direct connection method', () => {
- const { result } = renderHook(() =>
- useConnectState({ mode: 'direct', connectionMethod: 'direct' })
- )
-
- const fieldIds = result.current.activeFields.map((f) => f.id)
- expect(fieldIds).not.toContain('useSharedPooler')
- })
-
- test('should return orm mode fields', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'orm' }))
-
- const fieldIds = result.current.activeFields.map((f) => f.id)
- expect(fieldIds).toContain('orm')
- })
-
- test('should return mcp mode fields', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'mcp' }))
-
- const fieldIds = result.current.activeFields.map((f) => f.id)
- expect(fieldIds).toContain('mcpClient')
- expect(fieldIds).toContain('mcpReadonly')
- })
})
// ============================================================================
@@ -319,28 +183,6 @@ describe('useConnectState', () => {
expect(stepIds).toContain('install')
})
- test('should resolve different steps for mcp mode', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'mcp' }))
-
- const stepIds = result.current.resolvedSteps.map((s) => s.id)
- // MCP mode should have configure step
- expect(stepIds.some((id) => id.includes('configure') || id.includes('mcp'))).toBe(true)
- })
-
- test('should resolve different steps for different mcp clients', () => {
- const { result: cursorResult } = renderHook(() =>
- useConnectState({ mode: 'mcp', mcpClient: 'cursor' })
- )
- const { result: codexResult } = renderHook(() =>
- useConnectState({ mode: 'mcp', mcpClient: 'codex' })
- )
-
- // Codex has more steps than cursor
- expect(codexResult.current.resolvedSteps.length).toBeGreaterThanOrEqual(
- cursorResult.current.resolvedSteps.length
- )
- })
-
test('should include skills install step', () => {
const { result } = renderHook(() => useConnectState())
@@ -348,21 +190,6 @@ describe('useConnectState', () => {
expect(stepIds).toContain('install-skills')
})
- test('should resolve steps for direct mode', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'direct' }))
-
- expect(result.current.resolvedSteps.length).toBeGreaterThan(0)
- })
-
- test('should resolve steps for orm mode', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'orm' }))
-
- expect(result.current.resolvedSteps.length).toBeGreaterThan(0)
- const stepIds = result.current.resolvedSteps.map((s) => s.id)
- expect(stepIds).toContain('install')
- expect(stepIds).toContain('configure')
- })
-
test('should resolve shadcn steps when frameworkUi is true', () => {
const { result } = renderHook(() =>
useConnectState({ framework: 'nextjs', frameworkUi: true })
@@ -403,41 +230,6 @@ describe('useConnectState', () => {
expect(options).toEqual([])
})
- test('should return connection method options', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'direct' }))
-
- const options = result.current.getFieldOptions('connectionMethod')
- expect(options.length).toBeGreaterThan(0)
- expect(options.some((o) => o.value === 'direct')).toBe(true)
- expect(options.some((o) => o.value === 'transaction')).toBe(true)
- })
-
- test('should return connection type options', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'direct' }))
-
- const options = result.current.getFieldOptions('connectionType')
- expect(options.length).toBeGreaterThan(0)
- expect(options.some((o) => o.value === 'uri')).toBe(true)
- expect(options.some((o) => o.value === 'psql')).toBe(true)
- })
-
- test('should return ORM options', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'orm' }))
-
- const options = result.current.getFieldOptions('orm')
- expect(options.length).toBeGreaterThan(0)
- expect(options.some((o) => o.value === 'prisma')).toBe(true)
- expect(options.some((o) => o.value === 'drizzle')).toBe(true)
- })
-
- test('should return MCP client options', () => {
- const { result } = renderHook(() => useConnectState({ mode: 'mcp' }))
-
- const options = result.current.getFieldOptions('mcpClient')
- expect(options.length).toBeGreaterThan(0)
- expect(options.some((o) => o.value === 'cursor')).toBe(true)
- })
-
test('should return empty array for unknown field', () => {
const { result } = renderHook(() => useConnectState())
@@ -473,10 +265,7 @@ describe('useConnectState', () => {
const { result } = renderHook(() => useConnectState())
const modeIds = result.current.schema.modes.map((m) => m.id)
- expect(modeIds).toContain('framework')
- expect(modeIds).toContain('direct')
- expect(modeIds).toContain('orm')
- expect(modeIds).toContain('mcp')
+ expect(modeIds).toEqual(['framework'])
})
})
})