Files
supabase/apps/studio/components/interfaces/Realtime/Inspector/SelectedRealtimeMessagePanel.tsx
Eduardo GurgelandAli Waseem 1984de70f1 feat(studio): add support to display realtime binary payloads (#46408)
## 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?

Add support to displaying binary payloads while displaying realtime
messages

<img width="2073" height="694"
alt="Realtime_Inspector___Realtime___29_APR___eduardo_gurgel_supabase_io_s_Org___Supabase"
src="https://github.com/user-attachments/assets/fcb5c3d2-f880-484b-97a9-b0ca3b939a3f"
/>

JSON payloads are untouched:

<img width="1744" height="625"
alt="Realtime_Inspector___Realtime___29_APR___eduardo_gurgel_supabase_io_s_Org___Supabase"
src="https://github.com/user-attachments/assets/8227d0af-21ee-4444-b8ca-4ebeeda11f75"
/>


How to test on staging:

```
   select
  realtime.send(
    '\x48656C6C6F2066726F6D205265616C74696D65'::bytea, -- Binary Payload
    'event', -- Event name
    'main', -- Topic
    false -- Public / Private flag
  );
```

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

* **New Features**
* Binary payloads in real-time message inspection show compact
placeholders with byte counts instead of raw binary.
* Added an inline hexdump viewer to inspect binary payload contents with
offsets, grouped hex bytes, and ASCII gutter.
* Message list and details view now use the placeholder/hexdump behavior
for payload rendering.

* **Tests**
* Added comprehensive tests for binary detection, hexdump formatting,
and placeholder substitution.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46408?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-06-02 13:03:13 +12:00

59 lines
1.8 KiB
TypeScript

import type { LogData } from './Messages.types'
import {
formatHexdump,
isBinaryPayload,
jsonSyntaxHighlight,
SelectionDetailedTimestampRow,
withBinaryPayloadPlaceholder,
} from './MessagesFormatters'
const LogsDivider = () => {
return (
<div className="h-px w-full bg-panel-border-interior-light in-data-[theme*=dark]:bg-panel-border-interior-dark" />
)
}
export const SelectedRealtimeMessagePanel = ({ log }: { log: LogData }) => {
const payload = log.metadata?.payload
const binary = isBinaryPayload(payload)
const envelope = withBinaryPayloadPlaceholder(log.metadata)
return (
<>
<div className="px-8">
<span className="col-span-4 text-sm text-scale-900">Message</span>
<p className="text-wrap mt-2 overflow-x-auto whitespace-pre-wrap font-mono text-xs text-scale-1200">
{log.message}
</p>
</div>
<LogsDivider />
<div className="px-8 space-y-2">
<SelectionDetailedTimestampRow hideCopy value={log.timestamp} />
</div>
<LogsDivider />
<div className="px-8 space-y-4">
<div>
<h3 className="mb-4 text-sm text-foreground-lighter">Payload</h3>
<pre className="syntax-highlight overflow-x-auto text-sm">
<div
className="text-wrap"
dangerouslySetInnerHTML={{
__html: envelope ? jsonSyntaxHighlight(envelope) : '',
}}
/>
</pre>
</div>
{binary && (
<div>
<h3 className="mb-4 text-sm text-foreground-lighter">Binary payload</h3>
<pre className="overflow-x-auto whitespace-pre font-mono text-xs text-scale-1200">
{formatHexdump(payload as ArrayBuffer | ArrayBufferView)}
</pre>
</div>
)}
</div>
</>
)
}