Liking cljdoc? Tell your friends :D

supabase.realtime

Public API for Supabase Realtime: WebSocket-based postgres_changes, broadcast, and presence subscriptions.

Quick start

(require '[supabase.core.client :as sc]
         '[supabase.realtime :as rt])

(def client (sc/make-client "https://abc.supabase.co" "anon-key"))
(def conn   (rt/connect client {:on-error println}))

(def ch (rt/channel conn "room:lobby"
                    {:config {:broadcast {:self false}}}))

(rt/on ch :postgres-changes
       {:event :insert :schema "public" :table "users"}
       (fn [payload] (println "row" payload)))

(rt/on ch :broadcast {:event "typing"}
       (fn [payload] (println "typing" payload)))

(rt/subscribe ch)
(rt/broadcast ch "typing" {:user "alice"})
(rt/track    ch {:online_at (System/currentTimeMillis)})

(rt/unsubscribe ch)
(rt/disconnect conn)

v0.1.0 scope

In: postgres_changes, broadcast send/receive, basic presence, manual set-auth, heartbeat, multi-channel per connection.

Out (deferred): broadcast ack/wait_for_ack, HTTP fallback, binary v2 protocol.

Public API for Supabase Realtime: WebSocket-based postgres_changes,
broadcast, and presence subscriptions.

## Quick start

    (require '[supabase.core.client :as sc]
             '[supabase.realtime :as rt])

    (def client (sc/make-client "https://abc.supabase.co" "anon-key"))
    (def conn   (rt/connect client {:on-error println}))

    (def ch (rt/channel conn "room:lobby"
                        {:config {:broadcast {:self false}}}))

    (rt/on ch :postgres-changes
           {:event :insert :schema "public" :table "users"}
           (fn [payload] (println "row" payload)))

    (rt/on ch :broadcast {:event "typing"}
           (fn [payload] (println "typing" payload)))

    (rt/subscribe ch)
    (rt/broadcast ch "typing" {:user "alice"})
    (rt/track    ch {:online_at (System/currentTimeMillis)})

    (rt/unsubscribe ch)
    (rt/disconnect conn)

## v0.1.0 scope

In:  postgres_changes, broadcast send/receive, basic presence,
     manual `set-auth`, heartbeat, multi-channel per connection.

Out (deferred): broadcast ack/wait_for_ack, HTTP fallback,
     binary v2 protocol.
raw docstring

broadcastclj/s

(broadcast ch event payload)

Sends a broadcast message on ch. Buffered until the channel joins. Returns ch.

When the connection was opened with :http-fallback? true and the socket is not :open, the broadcast is sent over HTTP POST to /api/broadcast instead of buffering — mirrors realtime-ex. In that case returns ch on HTTP success, or the anomaly from the failed request (ClojureScript: a js/Promise of that value). Broadcasts sent via broadcast-with-ack never fall back; they buffer like today.

Sends a broadcast message on `ch`. Buffered until the channel joins.
Returns `ch`.

When the connection was opened with `:http-fallback? true` and the socket
is not `:open`, the broadcast is sent over HTTP POST to `/api/broadcast`
instead of buffering — mirrors realtime-ex. In that case returns `ch` on
HTTP success, or the anomaly from the failed request (ClojureScript: a
`js/Promise` of that value). Broadcasts sent via `broadcast-with-ack`
never fall back; they buffer like today.
sourceraw docstring

broadcast-with-ackclj/s

(broadcast-with-ack ch event payload)

Sends a broadcast and returns the ack-ref (string) identifying it. The server replies with a phx_reply carrying that ref once the broadcast is accepted — requires :config {:broadcast {:ack true}} on the channel.

(let [ack (rt/broadcast-with-ack ch "typing" {:user "a"})]
  (rt/wait-for-ack ch ack {:timeout-ms 3000}))

Buffered like broadcast until the channel joins.

Sends a broadcast and returns the ack-ref (string) identifying it. The
server replies with a `phx_reply` carrying that ref once the broadcast is
accepted — requires `:config {:broadcast {:ack true}}` on the channel.

    (let [ack (rt/broadcast-with-ack ch "typing" {:user "a"})]
      (rt/wait-for-ack ch ack {:timeout-ms 3000}))

Buffered like `broadcast` until the channel joins.
sourceraw docstring

buildclj/s

source

channelclj/s

(channel conn topic)
(channel conn topic opts)

Returns a channel value bound to conn + topic. No network I/O.

opts may include :config (broadcast/presence/private). The channel is registered in connection state so subsequent on / subscribe calls can find it. Returns the channel map or an anomaly.

Returns a channel value bound to `conn` + `topic`. No network I/O.

`opts` may include `:config` (broadcast/presence/private). The channel
is registered in connection state so subsequent `on` / `subscribe` calls
can find it. Returns the channel map or an anomaly.
sourceraw docstring

connectclj/s

(connect client)
(connect client opts)

Opens a Realtime connection for client. See supabase.realtime.connection/connect for options.

Opens a Realtime connection for `client`. See
`supabase.realtime.connection/connect` for options.
sourceraw docstring

disconnectclj/s

(disconnect c)

Closes the connection. Idempotent.

Closes the connection. Idempotent.
sourceraw docstring

eqclj/s

source

gtclj/s

source

gteclj/s

source

ilikeclj/s

source

imatchclj/s

source

inclj/s

source

isclj/s

source

isdistinctclj/s

source

likeclj/s

source

ltclj/s

source

lteclj/s

source

matchclj/s

source

neqclj/s

source

notclj/s

source

onclj/s

(on ch binding-type filter callback)

Registers a binding on ch. Returns the channel value (for threading) or an anomaly on validation failure.

Binding types: :postgres-changes — filter {:event :insert/:update/:delete/:all :schema "public" :table "users" :filter "id=eq.42" (optional) :select ["id" "email"] (optional)} :broadcast — filter {:event "typing"} (use "*" for all) :presence — filter {:event :sync | :join | :leave}

The postgres_changes :filter also accepts a builder from supabase.realtime.filters — it is serialized to its wire string at registration time:

(rt/on ch :postgres-changes
       {:event :update :schema "public" :table "orders"
        :filter (-> (f/gt "amount" 100) (f/eq "status" "open"))}
       handle-order)

:select narrows the payload to the listed columns (the primary key always comes through). Registering the same postgres_changes filter twice is a no-op (the duplicate is dropped and the connection's :on-error is notified with a :duplicate-binding anomaly): the server collapses identical filters into one subscription, so keeping the duplicate would desync client and server binding lists and fail subscribe with a mismatch.

Must be called BEFORE subscribe for postgres_changes — server-side binding ids are correlated at join time.

Registers a binding on `ch`. Returns the channel value (for threading)
or an anomaly on validation failure.

Binding types:
  :postgres-changes  — filter `{:event :insert/:update/:delete/:all
                                :schema "public" :table "users"
                                :filter "id=eq.42" (optional)
                                :select ["id" "email"] (optional)}`
  :broadcast         — filter `{:event "typing"}` (use `"*"` for all)
  :presence          — filter `{:event :sync | :join | :leave}`

The postgres_changes `:filter` also accepts a builder from
`supabase.realtime.filters` — it is serialized to its wire string at
registration time:

    (rt/on ch :postgres-changes
           {:event :update :schema "public" :table "orders"
            :filter (-> (f/gt "amount" 100) (f/eq "status" "open"))}
           handle-order)

`:select` narrows the payload to the listed columns (the primary key
always comes through). Registering the same postgres_changes filter twice
is a no-op (the duplicate is dropped and the connection's `:on-error` is
notified with a `:duplicate-binding` anomaly): the server collapses
identical filters into one subscription, so keeping the duplicate would
desync client and server binding lists and fail `subscribe` with a
mismatch.

Must be called BEFORE `subscribe` for postgres_changes — server-side
binding ids are correlated at join time.
sourceraw docstring

presence-stateclj/s

(presence-state ch)

Returns the latest presence map captured for ch. Empty if no presence_state received yet.

Returns the latest presence map captured for `ch`. Empty if no
`presence_state` received yet.
sourceraw docstring

set-authclj/s

(set-auth ch-or-conn token)

Refreshes the auth token for a channel or every joined channel on a connection. Sends an access_token event per joined channel.

The token is recorded on the connection and resolved into subsequent join/rejoin payloads (unless an :access-token-fn is set — its result always wins). Pass nil to clear it on sign-out, so a stale token no longer leaks into later join payloads.

Refreshes the auth token for a channel or every joined channel on a
connection. Sends an `access_token` event per joined channel.

The token is recorded on the connection and resolved into subsequent
join/rejoin payloads (unless an `:access-token-fn` is set — its result
always wins). Pass nil to clear it on sign-out, so a stale token no
longer leaks into later join payloads.
sourceraw docstring

subscribeclj/s

(subscribe ch)
(subscribe ch opts)

Sends phx_join for ch and transitions to :joining. The channel receives :joined asynchronously when the server replies. Returns ch, or an anomaly when opts is invalid.

Options

  • :postgres-changes-options: {:wait bool :timeout ms}.

By default the server acks the join as soon as the channel is up, which can precede the postgres_changes subscription actually streaming. With {:wait true} the server holds its reply until the subscription is confirmed active, and rejects the join when it cannot be established (surfaced via the connection's :on-error, with the channel left in :errored). :timeout (ms) bounds the server-side wait; it defaults to 15000 server-side and is clamped to the server's configured maximum, so asking for more waits less. No effect on a channel without postgres_changes bindings.

The options are stored on the channel and reused on reconnect rejoins.

Note: joins in this client are fire-and-forget with the reply awaited asynchronously, so there is no client-side join timeout to extend (in realtime-js wait also extends the join timeout past the server's held reply).

Sends `phx_join` for `ch` and transitions to `:joining`. The channel
receives `:joined` asynchronously when the server replies. Returns `ch`,
or an anomaly when `opts` is invalid.

## Options

  * `:postgres-changes-options`: `{:wait bool :timeout ms}`.

By default the server acks the join as soon as the channel is up, which
can precede the postgres_changes subscription actually streaming. With
`{:wait true}` the server holds its reply until the subscription is
confirmed active, and rejects the join when it cannot be established
(surfaced via the connection's `:on-error`, with the channel left in
`:errored`). `:timeout` (ms) bounds the server-side wait; it defaults to
15000 server-side and is clamped to the server's configured maximum, so
asking for more waits less. No effect on a channel without
postgres_changes bindings.

The options are stored on the channel and reused on reconnect rejoins.

Note: joins in this client are fire-and-forget with the reply awaited
asynchronously, so there is no client-side join timeout to extend (in
realtime-js `wait` also extends the join timeout past the server's held
reply).
sourceraw docstring

trackclj/s

(track ch state)

Sends a presence track message with state. Returns ch.

Sends a presence `track` message with `state`. Returns `ch`.
sourceraw docstring

unsubscribeclj/s

(unsubscribe ch)

Sends phx_leave and transitions to :leaving. Channel state is removed when the server acks.

Sends `phx_leave` and transitions to `:leaving`. Channel state is removed
when the server acks.
sourceraw docstring

untrackclj/s

(untrack ch)

Sends a presence untrack message. Returns ch.

Sends a presence `untrack` message. Returns `ch`.
sourceraw docstring

wait-for-ackclj/s

(wait-for-ack ch ack-ref)
(wait-for-ack ch ack-ref {:keys [timeout-ms] :or {timeout-ms 5000}})

Waits for the server ack of ack-ref from broadcast-with-ack, up to timeout-ms (default 5000). Returns :acknowledged, or an anomaly: :ack-timeout when the wait expires, :ack-not-found for an unknown ref.

Blocks the calling thread on the JVM. On ClojureScript returns a js/Promise resolving to the same values.

Waits for the server ack of `ack-ref` from `broadcast-with-ack`, up to
`timeout-ms` (default 5000). Returns `:acknowledged`, or an anomaly:
`:ack-timeout` when the wait expires, `:ack-not-found` for an unknown ref.

Blocks the calling thread on the JVM. On ClojureScript returns a
`js/Promise` resolving to the same values.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close