Files
supabase/apps/studio/components/interfaces/ConnectSheet/ConnectStepsSection.utils.ts
Joshen Lim 66bfc5fdc3 Refactor ConnectSheet + Add unit tests to cover various logic (#47764)
## Context

PR here mainly breaks up the files under `ConnectSheet` to separate the
functional logic so that we can write unit tests.
No behavior changes intended beyond the bug fixes

## Changes involved

- **Test organization:** moved all root-level `ConnectSheet` test files
into `ConnectSheet/__tests__/` for consistency with other parts of the
codebase that use this convention.
- **Bug fix:** read replica label had a stray `}` / missing `)`,
rendering as e.g. `Read Replica (us-east-1 - abc123})` instead of `Read
Replica (us-east-1 - abc123)`.
- **`ConnectSheet.tsx`:** extracted the "hydrate sheet state on open"
`useEffect` logic (mode/field/URL param resolution from URL vs.
localStorage) into a new `ConnectSheet.utils.ts`, with unit tests
- **`useConnectServerEnv.ts`:** fixed two race conditions in the secret
reveal/hide flow:
- `toggle()` and `getValue()` could each fire a separate reveal request
if triggered close together — now deduped to share one in-flight
request.
- `getValue()` could hide a secret that had just been explicitly
revealed by a concurrent `toggle()`, due to reading a stale closure
value — now reads the live state via `useLatest`.
- Also stopped swallowing the original error on reveal failure (now
attached via `cause`).
- Added tests for the above, plus the 10s auto-hide timer (previously
untested).
- **`ConnectStepsSection.tsx`:** extracted `resolveContentPath` and the
three inline "show notice" booleans (IPv4 addon, session pooler,
self-hosted MCP) into `ConnectStepsSection.utils.ts`, matching the
existing pattern for the Data API notice. Added unit tests for all of
them.

## To test
- [ ] Just a basic smoke test of the Connect sheet should do

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Improved connect setup hydration so saved preferences and URL values
are applied more consistently when opening the sheet, including
automatic URL backfilling where needed.
* Refreshed connection guidance notices (IPv4 add-on, session pooler,
and self-hosted MCP) with more consistent logic.
* **Bug Fixes**
* Fixed secret reveal behavior to keep concurrent reveal actions in
sync, handle failures more safely, and ensure auto-hide works reliably.
  * Corrected the read-replica option label formatting.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 15:24:34 +08:00

82 lines
2.1 KiB
TypeScript

import type { ConnectMode, ConnectState } from './Connect.types'
type FieldValue = ConnectState[string]
/**
* Resolves a content path template by replacing {{key}} placeholders with state values.
* Empty segments are filtered out to handle optional state values like frameworkVariant.
*
* Examples:
* - '{{framework}}/{{frameworkVariant}}/{{library}}' with state {framework: 'nextjs', frameworkVariant: 'app', library: 'supabasejs'}
* → 'nextjs/app/supabasejs'
* - '{{orm}}' with state {orm: 'prisma'}
* → 'prisma'
* - 'steps/install' (no templates)
* → 'steps/install'
*/
export function resolveContentPath(template: string, state: ConnectState): string {
return template
.replace(/\{\{(\w+)\}\}/g, (_, key) => String(state[key] ?? ''))
.split('/')
.filter(Boolean)
.join('/')
}
export function shouldShowIpv4AddonNotice({
isPlatform,
mode,
connectionMethod,
useSharedPooler,
hasIpv4Addon,
}: {
isPlatform: boolean
mode: ConnectMode
connectionMethod: FieldValue
useSharedPooler: FieldValue
hasIpv4Addon: boolean
}): boolean {
if (!isPlatform || mode !== 'direct' || hasIpv4Addon) return false
return connectionMethod === 'direct' || (connectionMethod === 'transaction' && !useSharedPooler)
}
export function shouldShowSessionPoolerNotice({
isPlatform,
mode,
connectionMethod,
}: {
isPlatform: boolean
mode: ConnectMode
connectionMethod: FieldValue
}): boolean {
return isPlatform && mode === 'direct' && connectionMethod === 'session'
}
export function shouldShowSelfHostedMcpNotice({
isSelfHosted,
mode,
}: {
isSelfHosted: boolean
mode: ConnectMode
}): boolean {
return isSelfHosted && mode === 'mcp'
}
export function shouldFetchDataApiConfig({ mode }: { mode: ConnectMode }): boolean {
return mode === 'framework'
}
export function shouldShowDataApiDisabledWarning({
mode,
isDataApiEnabled,
isPending,
isError,
}: {
mode: ConnectMode
isDataApiEnabled: boolean
isPending: boolean
isError: boolean
}): boolean {
if (isPending || isError || isDataApiEnabled) return false
return shouldFetchDataApiConfig({ mode })
}