Files
supabase/apps/studio/data/realtime/realtime-config-query.ts
Sean GeogheganandJoshen Lim f2ff4ec0e9 fix(realtime): display banner when realtime has been suspended by admin (#50497)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

If Realtime's admin_suspended_at is set we display a banner.

## What is the current behavior?

REAL-1095

## What is the new behavior?

<img width="1160" height="442" alt="Screenshot 2026-09-17 at 12 06
30 pm"
src="https://github.com/user-attachments/assets/f5abe900-a163-48c9-ab55-945fc62df0d1"
/>


## Additional context

Depends on https://github.com/supabase/platform/pull/38476


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

## Summary by CodeRabbit

- **New Features**
- Added a notice to Realtime settings when the service is suspended,
with instructions to contact support.
- **Bug Fixes**
- Improved invitation resending and role updates for roles without a
linked base role.
- **Tests**
- Added coverage to verify the suspension notice appears only when
applicable.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-28 15:17:24 +08:00

67 lines
2.1 KiB
TypeScript

import { useQuery } from '@tanstack/react-query'
import type { components } from 'api-types'
import { realtimeKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import { IS_PLATFORM } from '@/lib/constants'
import type { ResponseError, UseCustomQueryOptions } from '@/types'
type RealtimeConfigResponse = components['schemas']['RealtimeConfigResponse_Output']
export type RealtimeConfigurationVariables = {
projectRef?: string
}
export const REALTIME_DEFAULT_CONFIG = {
private_only: false,
connection_pool: 2,
postgres_changes_pool: 2,
max_concurrent_users: 200,
max_events_per_second: 100,
max_bytes_per_second: 100000,
max_channels_per_client: 100,
max_joins_per_second: 100,
max_presence_events_per_second: 100,
max_payload_size_in_kb: 100,
suspend: false,
presence_enabled: true,
admin_suspended_at: null,
} as const satisfies RealtimeConfigResponse
export async function getRealtimeConfiguration(
{ projectRef }: RealtimeConfigurationVariables,
signal?: AbortSignal
) {
if (!projectRef) throw new Error('Project ref is required')
const { data, error } = await get(`/platform/projects/{ref}/config/realtime`, {
params: { path: { ref: projectRef } },
signal,
})
if (error) {
if ((error as ResponseError).message === 'Custom realtime config for a project not found') {
return REALTIME_DEFAULT_CONFIG
} else {
handleError(error)
}
}
return data
}
export type RealtimeConfigurationData = Awaited<ReturnType<typeof getRealtimeConfiguration>>
export type RealtimeConfigurationError = ResponseError
export const useRealtimeConfigurationQuery = <TData = RealtimeConfigurationData>(
{ projectRef }: RealtimeConfigurationVariables,
{
enabled = true,
...options
}: UseCustomQueryOptions<RealtimeConfigurationData, RealtimeConfigurationError, TData> = {}
) =>
useQuery<RealtimeConfigurationData, RealtimeConfigurationError, TData>({
queryKey: realtimeKeys.configuration(projectRef),
queryFn: ({ signal }) => getRealtimeConfiguration({ projectRef }, signal),
enabled: enabled && IS_PLATFORM && typeof projectRef !== 'undefined',
...options,
})