Skip to content

Extract PassageRouteRegistry to deduplicate handler discovery - #228

Merged
morcen merged 1 commit into
mainfrom
fix/issue-88-route-registry
Sep 6, 2026
Merged

Extract PassageRouteRegistry to deduplicate handler discovery#228
morcen merged 1 commit into
mainfrom
fix/issue-88-route-registry

Conversation

@morcen

@morcen morcen commented Sep 5, 2026

Copy link
Copy Markdown
Owner

What was broken

PassageController::handle(), PassageHealthCommand::passageRoutes(), and PassageListCommand::handle() each independently implemented the same four steps: find Passage routes, read the _passage_handler route default, validate it against PassageControllerInterface, resolve it through the container, and merge config('passage.options') with the handler's getOptions().

Because this logic was duplicated three times instead of shared, the implementations had already drifted apart twice in the past:

  • PassageListCommand used to resolve handlers with new $handler instead of going through the container, which broke for handlers with constructor dependencies (later fixed to match the other two call sites).
  • PassageListCommand used to match routes by a partial action-name substring instead of the fully-qualified controller class (later fixed to match PassageHealthCommand's approach).

Nothing prevented a future change to any one of the three call sites from silently diverging from the other two again in the same way.

What changed

  • Added Morcen\Passage\Support\PassageRouteRegistry, the single place that:
    • finds all routes registered through the Passage facade (routes())
    • reads a route's configured handler class (handlerClassFor())
    • validates a handler class against PassageControllerInterface (isValidHandler())
    • resolves a handler through the container (resolveHandler())
    • merges config('passage.options') with the handler's own options (optionsFor())
  • Updated PassageController::handle(), PassageHealthCommand, and PassageListCommand to use the registry instead of their own copies of this logic.
  • As part of unifying the three call sites, PassageListCommand's target resolution now merges config('passage.options') with the handler's own options the same way the controller and health command already did, instead of using the handler's raw getOptions() alone.
  • Removed the now-unused Illuminate\Contracts\Foundation\Application $app dependency from PassageController's constructor, since handler resolution now goes through the registry.
  • Added tests/Unit/PassageRouteRegistryTest.php covering the registry directly, and updated the existing controller tests that construct PassageController manually to pass the new PassageRouteRegistry dependency.

Testing

  • vendor/bin/pint --dirty — passed, no changes needed
  • vendor/bin/pest — 250 passed (631 assertions), full suite green

Fixes #88

🤖 Generated with Claude Code

https://claude.ai/code/session_01DGa5tuhzv66zYWhZ6PWXXr


Generated by Claude Code

PassageController::handle(), PassageHealthCommand::passageRoutes(), and
PassageListCommand::handle() each independently found Passage routes,
read the _passage_handler route default, validated it against
PassageControllerInterface, resolved it through the container, and
merged config('passage.options') with the handler's getOptions(). The
three implementations had already drifted apart twice before being
reconciled (PassageListCommand resolving handlers with `new $handler`
instead of the container, and matching routes by a partial action-name
string instead of the fully-qualified class), so a future change to
any one of them could silently diverge from the other two again.

Add Morcen\Passage\Support\PassageRouteRegistry as the single place
that finds Passage routes, reads/validates/resolves their handler, and
merges options, and use it from all three call sites. As part of this,
PassageListCommand's target resolution now merges config('passage.options')
with the handler's own options like the controller and health command
already did, instead of using the handler's raw getOptions() alone.

Fixes #88

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DGa5tuhzv66zYWhZ6PWXXr
@morcen
morcen merged commit 80b9404 into main Sep 6, 2026
19 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.

Extract PassageRouteRegistry to deduplicate handler discovery

1 participant