Skip to content

Return chainable resource routes from jsonApiResource - #23

Merged
evoactivity merged 2 commits into
mainfrom
feat/resource-route-middleware
Oct 13, 2026
Merged

evoactivity merged 2 commits into
mainfrom
feat/resource-route-middleware

Conversation

@evoactivity

Copy link
Copy Markdown
Owner

router.jsonApiResource() now returns the routes it registered, so middleware can be attached to some actions only. Before this it returned nothing, and the only way to add middleware was a group around the whole resource, which reached every action.

router
  .jsonApiResource('articles', {
    resource: () => import('#controllers/articles_controller'),
    relationships: () => import('#controllers/article_relationships_controller'),
  })
  .use(['store', 'update', 'destroy'], middleware.auth())
  .useRelationships(['replace', 'add', 'remove'], middleware.auth())

What changed

  • registerJsonApiResource() keeps each route it creates, keyed by action, and returns a JsonApiResourceRoutes. It is modelled on AdonisJS RouteResource.use().
  • use(actions | '*', middleware) attaches to resource routes, with the same tokens as only.
  • useRelationships(actions | '*', middleware) attaches to relationship routes, with the same tokens as relationshipsOnly. It is a separate method because both sets have a show.
  • Both return the same object, so calls chain. An action that was not registered (left out by only or relationshipsOnly) is ignored.
  • The macro's type returns JsonApiResourceRoutes<RouteMiddleware>, where RouteMiddleware is Parameters<Route['use']>[0], so it accepts exactly what an AdonisJS route's own use() accepts.
  • JsonApiResourceRoutes is exported.
  • docs/reference.md has a new "Route middleware" section.

The change is additive. Callers that ignore the return value behave as before.

Why

Ekto's server needs per-action middleware on resources registered this way, to mark which routes a scoped API token may use (ekto monorepo #159).

Testing

  • 182 tests pass. Five new tests in tests/unit/register_resource.spec.ts cover attaching to chosen actions, '*', keeping the resource and relationship show apart, ignoring unregistered actions, and middleware order across calls.
  • Typecheck, lint, Prettier and pnpm build are clean.
  • The tests use a recording router. The real AdonisJS Route is checked against the new route type through the provider's typecheck.

🤖 Generated with Claude Code

router.jsonApiResource() now returns the routes it registered, so
middleware can be attached to some actions only. use() covers resource
actions and useRelationships() covers relationship actions, each taking
a list of action names or '*', modelled on AdonisJS RouteResource.use().
Middleware types come from the AdonisJS route's own use(), and actions
that were not registered are ignored. Existing callers are unaffected.
@evoactivity evoactivity added the enhancement New feature or request label Oct 13, 2026
@evoactivity
evoactivity merged commit f492275 into main Oct 13, 2026
2 checks passed
@github-actions github-actions Bot mentioned this pull request Oct 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant