Skip to content

fix(server): wrap awareness origin as TransactionOrigin#1094

Merged
janthurau merged 2 commits into
ueberdosis:mainfrom
dschmidt:fix/awareness-update-origin
May 18, 2026
Merged

fix(server): wrap awareness origin as TransactionOrigin#1094
janthurau merged 2 commits into
ueberdosis:mainfrom
dschmidt:fix/awareness-update-origin

Conversation

@dschmidt
Copy link
Copy Markdown
Contributor

@dschmidt dschmidt commented May 17, 2026

Problem

onAwarenessUpdate({ connection }) is always undefined in v4. The awareness listener in Hocuspocus.ts reads it via isTransactionOrigin(origin), but the producers (MessageReceiver awareness branch and Document.applyAwarenessUpdate) pass the raw Connection. The type guard returns false, so the connection is never forwarded to the hook and server-side awareness work that depends on the per-update authenticated user cannot function.

Fix

Wrap origin as { source: 'connection', connection } at the producer sites, matching the sync handlers in the same MessageReceiver. Update Document.handleAwarenessUpdate to extract the connection through the existing type guard. Tighten the related parameter types with satisfies ConnectionTransactionOrigin and TransactionOrigin | null so future producers cannot regress.

I suspect this matches the original v4 intent: Hocuspocus.ts's awareness listener was already written for TransactionOrigin, the sync handlers already wrap, and the previous originConnection: Connection | null parameter on handleAwarenessUpdate looks like a leftover pre-v4 signature. The y-protocols origin: any typing hid the inconsistency from the compiler.

Soft API break

Listeners attached directly via document.awareness.on('update', ...) now receive a TransactionOrigin (or { source: 'local' } for non-connection origins) instead of a raw Connection. Migration:

const conn = isTransactionOrigin(origin) && origin.source === 'connection'
  ? origin.connection
  : null

The supported onAwarenessUpdate hook is unaffected and gains the resolved payload.connection.

Alternative

If full backwards compatibility is preferred, I can instead make the consumer side tolerant of both raw Connection and wrapped TransactionOrigin, leaving the producers untouched. Happy to switch.

dschmidt added 2 commits May 17, 2026 02:43
The v4 awareness listener in Hocuspocus.ts uses isTransactionOrigin to
read payload.connection, but MessageReceiver and
Document.applyAwarenessUpdate pass the raw Connection, so the guard
fails and payload.connection is always undefined.

Mirror the sync-handler pattern in the same file: wrap origin as
{ source: 'connection', connection } at the producer sites, extract
via the type guard in Document.handleAwarenessUpdate, and tighten the
related parameter types so future producers cannot regress.

Soft API break: listeners attached directly via
document.awareness.on('update', ...) now receive a TransactionOrigin
instead of a raw Connection. The recommended onAwarenessUpdate hook
keeps exposing the resolved connection via payload.connection.
@janthurau janthurau merged commit bb24de0 into ueberdosis:main May 18, 2026
6 checks passed
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.

2 participants