Skip to content

refactor(realtime)!: rename conn family and onConnMessage#1404

Draft
spydon wants to merge 17 commits into
mainfrom
lukasklingsbo/sdk-583-realtime-v3-renames
Draft

refactor(realtime)!: rename conn family and onConnMessage#1404
spydon wants to merge 17 commits into
mainfrom
lukasklingsbo/sdk-583-realtime-v3-renames

Conversation

@spydon

@spydon spydon commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

What

Renames the breaking public API on RealtimeClient, split out of #1397 so that PR carries only the protocol 2.0.0 feature.

  • RealtimeClient.connconnection
  • RealtimeClient.connStateconnectionStatus
  • onConnMessageonConnectionMessage
  • private _onConnOpen / _onConnClose / _onConnError_onConnection*

Consumers updated: supabase_flutter (supabase.dart, lifecycle_test.dart).

Stacking / target

Breaking changes

  • RealtimeClient.conn / connState renamed to connection / connectionStatus.
  • onConnMessage renamed to onConnectionMessage.

Tests

realtime_client 121 passing; analyze clean.

spydon added 17 commits June 12, 2026 14:08
Implements Realtime protocol 2.0.0 for the Dart/Flutter SDK (SDK-583).

- Add a `Serializer` ported from the supabase-js reference that encodes
  text frames as the positional JSON array `[join_ref, ref, topic, event,
  payload]` and handles binary frames (`userBroadcastPush` kind 3 encode,
  `userBroadcast` kind 4 decode) with the JSON/binary encoding flag and
  `allowedMetadataKeys`.
- Default the connection to `vsn=2.0.0` and wire the serializer as the
  default encode/decode.
- Decode incoming binary broadcast frames and send broadcasts whose payload
  is a `Uint8List`/`TypedData` as binary frames.
- Loosen `RealtimeEncode`/`RealtimeDecode` to carry `String` or bytes and
  let the connection listener accept binary frames.
- Rename the `conn` family to avoid abbreviations: `conn` -> `connection`,
  `connState` -> `connectionStatus`, `onConnMessage` -> `onConnectionMessage`,
  `_onConn*` -> `_onConnection*`.
- Update realtime frame mocks/tests to the 2.0.0 array format and add
  `serializer_test.dart`.

BREAKING CHANGE: the default Realtime protocol is now 2.0.0, and the
`RealtimeClient.conn`/`connState` fields are renamed to
`connection`/`connectionStatus`.
…allback

The callback form was a port artifact from the realtime-js/Phoenix
serializer. Both encode and decode are synchronous here, so return the
result directly: RealtimeEncode is now Object Function(Map<String,
dynamic>) and RealtimeDecode is Map<String, dynamic> Function(Object).
Remove the custom encode/decode constructor hook and the RealtimeEncode/
RealtimeDecode typedefs. With the protocol pinned to 2.0.0, a custom codec
that does not emit valid frames would only break the connection, and the
hook was unused. The client now holds a private Serializer directly.

BREAKING CHANGE: the RealtimeClient encode/decode constructor parameters,
the encode/decode fields, and the RealtimeEncode/RealtimeDecode typedefs
are removed.
Add a RealtimeProtocolVersion enum (v1/v2) and a version constructor
parameter on RealtimeClient, defaulting to v2. v1 uses the legacy
object-shaped JSON frames; v2 uses the serializer. The enum carries the
wire vsn string sent as the connection parameter.

Also drop the porting references from the doc comments.
Re-add optional encode/decode constructor arguments (and the
RealtimeEncode/RealtimeDecode typedefs). They default to the codec
selected by version, so consumers can swap in a faster serializer.
- decode() validates the 2.0.0 text frame shape and throws a clear
  FormatException instead of an obscure cast error
- onConnectionMessage drops malformed frames instead of crashing the
  connection, and guards the status log against non-map payloads
- set the web binaryType explicitly to arraybuffer/list
- document the ASCII assumption for binary frame string fields
…et constant

Avoid copying frame slices during binary decode, name the userBroadcast
header offset, and add an end-to-end test for dispatching a received
binary broadcast to onBroadcast.
Write the header directly into the final frame buffer instead of
allocating a separate header and copying it, removing one allocation and
one copy per binary broadcast push.
Make encode/decode plain final fields resolved in the initializer list
instead of late, using a shared static serializer and static legacy
codec helpers. Removes the late modifier and a per-client serializer
allocation.
Rename obj -> source in the serializer, msg -> message in the logger
and log(), and res -> response in the channel HTTP helpers.
The mock_test suites now exercise v2; add a v1 decode + dispatch test so
the legacy object-frame path keeps coverage alongside the existing v1
endpointURL and encode tests.
Keep the original conn/connState fields, the onConnMessage method, and the
_onConn* handlers in this PR so it carries only the protocol 2.0.0 feature
and RealtimeProtocolVersion. The breaking renames move to a follow-up PR
targeting v3.
BREAKING CHANGE: RealtimeClient.conn -> connection, connState ->
connectionStatus, onConnMessage -> onConnectionMessage, and the private
_onConn* handlers -> _onConnection*.
spydon added a commit that referenced this pull request Jun 12, 2026
## What

Adds Realtime protocol **2.0.0** support to the Dart/Flutter SDK and
makes the protocol version selectable.

Closes
[SDK-583](https://linear.app/supabase/issue/SDK-583/realtime-add-support-to-protocol-format-200-flutter).

Protocol 2.0.0 changes the WebSocket frame format:
- **Text frames** use the positional JSON array `[join_ref, ref, topic,
event, payload]` instead of the 1.0.0 object layout, reducing JSON work
on the backend (lower latency).
- **Binary frames** allow raw binary payloads for broadcast user events.

## Changes

### Serializer (`serializer.dart`, new)
- Text encode/decode as the positional array `[join_ref, ref, topic,
event, payload]`.
- Binary encode for broadcast pushes (`userBroadcastPush`, kind `3`).
- Binary decode for incoming broadcasts (`userBroadcast`, kind `4`).
- JSON/binary encoding flag and `allowedMetadataKeys`.
- `decode` validates the text frame shape and throws a clear
`FormatException` on malformed input; `onConnMessage` logs and drops
such frames instead of crashing the connection.

### Selectable protocol version
- New `RealtimeProtocolVersion` enum (`v1` → `1.0.0`, `v2` → `2.0.0`);
each carries the `vsn` value sent as the connection parameter.
- `RealtimeClient` takes a `version` parameter, **defaulting to `v2`**.
`v2` uses the serializer; `v1` uses the legacy object-shaped JSON
frames.

### Codec override
- Optional `encode` / `decode` constructor arguments (and the
`RealtimeEncode` / `RealtimeDecode` typedefs) let consumers swap in a
custom serializer; they default to the codec for the selected `version`.
- Return-based signatures: `RealtimeEncode` = `Object
Function(Map<String, dynamic>)`, `RealtimeDecode` = `Map<String,
dynamic> Function(Object)` (synchronous — async/isolate codec is a
follow-up, see below).

### Binary broadcasts
Incoming binary broadcast frames are decoded into the same map shape as
JSON broadcasts. To send binary, provide a `Uint8List` (or any
`TypedData`) under the `payload` key:

\`\`\`dart
channel.sendBroadcastMessage(event: 'file', payload: {'payload':
myUint8List});
\`\`\`

Binary frames are delivered as `Uint8List` on every platform; the web
transport sets `binaryType` to arraybuffer explicitly.

### Misc
- Expanded a few abbreviated identifiers (`obj`/`msg`/`res`) in touched
code.

## Breaking changes

- **Default Realtime protocol is now `2.0.0`** (pass `version:
RealtimeProtocolVersion.v1` to keep the old behavior).
- `RealtimeEncode` / `RealtimeDecode` changed from callback-based to
return-based signatures.

## Related

- The breaking field/method renames (`conn` → `connection`, `connState`
→ `connectionStatus`, `onConnMessage` → `onConnectionMessage`) are split
into #1404, which stacks on this PR and will be retargeted to `v3` after
this merges.
- Follow-up: async codec path for isolate offloading — #1401.

## Tests

- `realtime_client`: 121 passing (new `serializer_test.dart`,
endpointURL `v1`, legacy encode, legacy decode + dispatch,
custom-`encode` override, malformed-frame, binary-broadcast receive).
- `supabase`: 83 passing.
- `supabase_flutter/test/lifecycle_test.dart`: analyze clean.
Base automatically changed from lukasklingsbo/sdk-583-realtime-protocol-200 to main June 12, 2026 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant