Skip to content

feat: add afterHandleMessage hook to run after message handling completion#1112

Merged
janthurau merged 1 commit into
mainfrom
feat/after-handle-message-hook
Jun 18, 2026
Merged

feat: add afterHandleMessage hook to run after message handling completion#1112
janthurau merged 1 commit into
mainfrom
feat/after-handle-message-hook

Conversation

@janthurau

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new server hook, afterHandleMessage, intended to run after inbound messages have finished being handled, and adds test coverage to validate ordering, invocation count, and error behavior.

Changes:

  • Added afterHandleMessage hook to the server extension API/types and hook dispatching.
  • Invoked the new hook from Connection.processMessages() after message handling completes (including when handling throws).
  • Added AVA tests covering expected afterHandleMessage semantics.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/server/afterHandleMessage.ts Adds tests validating hook ordering/counting and error handling behavior.
packages/server/src/types.ts Extends hook type definitions/unions and documents the new hook payload.
packages/server/src/Hocuspocus.ts Wires the new hook into the configuration/extension hook chain.
packages/server/src/Connection.ts Executes afterHandleMessage in a finally after MessageReceiver.apply().
packages/server/src/ClientConnection.ts Constructs and dispatches afterHandleMessage hook payloads via this.hooks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +101 to +106
/**
* Fired after an inbound message has been handled (i.e. after the Yjs
* update has been applied to the document). Fires whether the apply
* resolved or threw, but not when `beforeHandleMessage` rejected the
* message.
*/
Comment on lines +6 to +22
await new Promise(async resolve => {
const server = await newHocuspocus(t, {
async afterHandleMessage({ document }) {
// contrary to beforeHandleMessage, the update is already applied here
if (document.getArray('foo').get(0) === 'bar') {
t.pass()
resolve('done')
}
},
})

const provider = newHocuspocusProvider(t, server, {
onSynced() {
provider.document.getArray('foo').insert(0, ['bar'])
},
})
})
Comment on lines +29 to +51
await new Promise(async resolve => {
const server = await newHocuspocus(t, {
async beforeHandleMessage() {
beforeHandleMessageCount += 1
},
async afterHandleMessage() {
afterHandleMessageCount += 1
},
})

newHocuspocusProvider(t, server, {
onClose() {
t.fail()
},
})
newHocuspocusProvider(t, server, {
onClose() {
t.fail()
},
})

resolve('done')
})
Comment on lines +62 to +77
await new Promise(async resolve => {
const server = await newHocuspocus(t, {
async beforeHandleMessage() {
throw new Error()
},
async afterHandleMessage() {
afterHandleMessageCount += 1
},
})

newHocuspocusProvider(t, server, {
onClose() {
resolve('done')
},
})
})
Comment on lines +85 to +101
await new Promise(async resolve => {
const server = await newHocuspocus(t, {
async afterHandleMessage() {
throw new Error()
},
})

const provider = newHocuspocusProvider(t, server, {
onClose() {
t.fail()
},
onSynced() {
t.pass()
setTimeout(() => resolve('done'), 100)
},
})
})
@janthurau
janthurau merged commit abec66d into main Jun 18, 2026
7 checks passed
@janthurau
janthurau deleted the feat/after-handle-message-hook branch June 18, 2026 07:04
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