mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
## Summary Fixes several high-impact Sentry errors reported in production. ### Fixed Issues - **[SUPABASE-APP-EJ3](https://supabase.sentry.io/issues/7356937474/)** — `TypeError: Cannot read properties of undefined (reading 'direct')`. `connectionStringPooler` could be `undefined` when the connection source doesn't match any key in the connection strings map. Added an early return guard in `resolveConnectionString`. - **[SUPABASE-APP-B17](https://supabase.sentry.io/issues/7117468199/)** — `RangeError: Invalid time zone specified: Etc/Unknown`. `dayjs.tz.guess()` returns `"Etc/Unknown"` for some users with misconfigured browser/OS timezones. Added a shared `guessLocalTimezone()` helper that validates the guessed timezone via `Intl.DateTimeFormat` and falls back to UTC. Applied across all 4 call sites. - **[SUPABASE-APP-BCM](https://supabase.sentry.io/issues/7192934901/)** — `TypeError: Cannot convert undefined or null to object`. `Object.entries(definition.properties)` crashed when a JSON schema definition existed but had no `properties` field. Updated the guard to check `definition?.properties` instead of just `definition`. - https://supabase.sentry.io/issues/7357780302/?project=5459134 - https://supabase.sentry.io/issues/7358344652/?project=5459134 - https://supabase.sentry.io/issues/7096737077/?project=5459134 ## Test plan - [ ] Verify connect dialog renders without errors when connection data is still loading - [ ] Verify API docs Entity view handles schema definitions without properties - [ ] Verify charts/tooltips display correct timezone labels --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
91 lines
2.2 KiB
TypeScript
91 lines
2.2 KiB
TypeScript
import type { ConnectionStringPooler } from './Connect.types'
|
|
import type { ConnectionStringMethod } from './Connect.constants'
|
|
|
|
export const DEFAULT_PORT = '5432'
|
|
export const PASSWORD_PLACEHOLDER = '[YOUR-PASSWORD]'
|
|
|
|
export type ConnectionParams = {
|
|
host: string
|
|
port: string
|
|
user: string
|
|
database: string
|
|
}
|
|
|
|
export const resolveConnectionString = ({
|
|
connectionMethod,
|
|
useSharedPooler,
|
|
connectionStringPooler,
|
|
}: {
|
|
connectionMethod: ConnectionStringMethod
|
|
useSharedPooler: boolean
|
|
connectionStringPooler: ConnectionStringPooler | undefined
|
|
}) => {
|
|
if (!connectionStringPooler) return ''
|
|
|
|
if (connectionMethod === 'direct') {
|
|
return connectionStringPooler.direct ?? ''
|
|
}
|
|
|
|
if (connectionMethod === 'session') {
|
|
return connectionStringPooler.sessionShared ?? ''
|
|
}
|
|
|
|
if (useSharedPooler || !connectionStringPooler.transactionDedicated) {
|
|
return connectionStringPooler.transactionShared ?? ''
|
|
}
|
|
|
|
return connectionStringPooler.transactionDedicated ?? ''
|
|
}
|
|
|
|
export const parseConnectionParams = (connectionString: string): ConnectionParams => {
|
|
if (!connectionString) {
|
|
return {
|
|
host: 'hidden',
|
|
port: DEFAULT_PORT,
|
|
user: 'hidden',
|
|
database: 'hidden',
|
|
}
|
|
}
|
|
|
|
try {
|
|
const parsed = new URL(connectionString)
|
|
return {
|
|
host: parsed.hostname || 'hidden',
|
|
port: parsed.port || DEFAULT_PORT,
|
|
user: parsed.username || 'hidden',
|
|
database: parsed.pathname?.replace(/^\//, '') || 'hidden',
|
|
}
|
|
} catch (error) {
|
|
return {
|
|
host: 'hidden',
|
|
port: DEFAULT_PORT,
|
|
user: 'hidden',
|
|
database: 'hidden',
|
|
}
|
|
}
|
|
}
|
|
|
|
export const buildSafeConnectionString = (
|
|
connectionString: string,
|
|
params: ConnectionParams
|
|
): string => {
|
|
if (!connectionString) return ''
|
|
|
|
const search = (() => {
|
|
try {
|
|
return new URL(connectionString).search
|
|
} catch (error) {
|
|
return ''
|
|
}
|
|
})()
|
|
|
|
return `postgresql://${params.user}:${PASSWORD_PLACEHOLDER}@${params.host}:${params.port}/${params.database}${search}`
|
|
}
|
|
|
|
export const buildConnectionParameters = (params: ConnectionParams) => [
|
|
{ key: 'host', value: params.host },
|
|
{ key: 'port', value: params.port },
|
|
{ key: 'database', value: params.database },
|
|
{ key: 'user', value: params.user },
|
|
]
|