mirror of
https://github.com/supabase/supabase.git
synced 2026-10-12 12:55: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>
53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
import dayjs from 'dayjs'
|
|
import { guessLocalTimezone } from 'lib/dayjs'
|
|
import { ALL_TIMEZONES } from './PITR.constants'
|
|
import type { Time } from './PITR.types'
|
|
import type { ProjectSelectedAddon } from 'data/subscriptions/types'
|
|
|
|
export const getPITRRetentionDuration = (addons: ProjectSelectedAddon[]) => {
|
|
const pitrAddon = addons.find((addon) => addon.type === 'pitr')
|
|
if (!pitrAddon) return 0
|
|
|
|
return (pitrAddon.variant.meta as any)?.backup_duration_days ?? 0
|
|
}
|
|
|
|
export const getDatesBetweenRange = (startDate: dayjs.Dayjs, endDate: dayjs.Dayjs) => {
|
|
const diff = endDate.diff(startDate, 'day')
|
|
|
|
return Array.from({ length: diff }, (_, index) => startDate.add(index, 'day'))
|
|
}
|
|
|
|
export const getClientTimezone = () => {
|
|
const defaultTz = guessLocalTimezone()
|
|
const utcTz = ALL_TIMEZONES.find((option) => option.value === 'UTC')
|
|
const timezone = ALL_TIMEZONES.find((option) => {
|
|
if (option.utc.includes(defaultTz)) return option
|
|
else return undefined
|
|
})
|
|
return timezone ?? (utcTz || ALL_TIMEZONES[0])
|
|
}
|
|
|
|
export const formatNumberToTwoDigits = (number: Number) => {
|
|
return number.toLocaleString('en-US', {
|
|
minimumIntegerDigits: 2,
|
|
useGrouping: false,
|
|
})
|
|
}
|
|
|
|
// Formats Time object to hh:mm:ss
|
|
export const formatTimeToTimeString = (time: Time) => {
|
|
return `${formatNumberToTwoDigits(time.h)}:${formatNumberToTwoDigits(
|
|
time.m
|
|
)}:${formatNumberToTwoDigits(time.s)}`
|
|
}
|
|
|
|
export function constrainDateToRange(current: dayjs.Dayjs, lower: dayjs.Dayjs, upper: dayjs.Dayjs) {
|
|
if (current.isBefore(lower)) {
|
|
return lower
|
|
}
|
|
if (current.isAfter(upper)) {
|
|
return upper
|
|
}
|
|
return current
|
|
}
|