feat(middleware)!: guard a component the way a command is guarded - #22
Merged
Conversation
The same question — may this person do this — is asked by a subcommand and by the button that does the same thing, and until now only the subcommand could answer it with middleware. A button restated the check at the top of its handler, which is how the two answers drift apart. #[Button], #[SelectMenu] and #[ModalSubmit] now take middleware, compiled and validated by the same rule the command path uses, and ComponentDispatcher runs the chain before resolving anything. The middleware is handed the interaction in the shape that kind of component is answered with, built by the dispatcher rather than taken from the handler's arguments — a guard has to be able to refuse even when the handler it guards never asked for an interaction at all. Also documents the whole thing, with every example pulled from a fixture the suite compiles and exercises. BREAKING CHANGE: Middleware::__invoke now takes CommandInteraction|ButtonInteraction|ComponentInteraction|ModalSubmitInteraction rather than CommandInteraction. A middleware typed for the old signature has to widen its parameter; nothing else about it changes, and the interaction it receives for a command is the same object as before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
🎉 This PR is included in version 1.0.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Middleware landed for commands in #21. A button could not use it, so the check stayed at the top of the handler — and "may this person do this" is one question whether it arrives as a subcommand or as the button that does the same thing.
#[Button],#[SelectMenu]and#[ModalSubmit]now takemiddleware, compiled and validated by the same rule the command path uses — the validator moved intoDeclaredMiddlewareso a button and a subcommand are held to the same rule and refused in the same words.ComponentDispatcherruns the chain before resolving arguments, and hands the middleware the interaction in the shape that kind of component is answered with —ButtonInteraction,ComponentInteraction,ModalSubmitInteraction. It builds that itself rather than taking it from the handler's arguments: a guard has to be able to refuse even when the handler it guards never asked for an interaction at all.Middleware runs before the handler, so nothing has been deferred yet and a refusal answers with an ordinary ephemeral reply. The
defer()stays in the handler, where the slow work is.Breaking
Middleware::__invoketakes a union now:A middleware written against 0.14 widens its parameter and nothing else changes — the interaction it receives for a command is the same object as before.
A union rather than a shared interface is a deliberate trade: the four interaction classes have no common ancestor, and giving them one means changing
discord-phptoo. Worth revisiting if the union grows.Docs
tools/guides/09-middleware.md, with every example pulled from a fixture the suite compiles and exercises — includingSuggestionCommand, the mixed-audience case that is the whole reason this exists, and a test asserting the guard lands on one subcommand and not the other.🤖 Generated with Claude Code
https://claude.ai/code/session_01MQ51VhJ8GmnJdfHrj6Mz7D