GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — feat: Allow hooks on all methods and add externalMethods option (#3457) by marshallswain · Pull Request #3638 · feathersjs/feathers

Conversation

@marshallswain

@marshallswain marshallswain commented Jan 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Summary

This PR implements the feature requested in #3457, allowing hooks to run on all service methods while providing fine-grained control over which methods are exposed externally.

Changes

@feathersjs/feathers

Type Declarations (declarations.ts)

  • Updated methods description to clarify it controls which methods all hooks apply to
  • Added new externalMethods option to control HTTP transport exposure

Service (service.ts)

  • Added getExternalMethods() function (defaults to methods for backwards compatibility)
  • Updated normalizeServiceOptions() to include externalMethods

Hooks (hooks.ts)

  • Added allMethods to hook store to track which methods receive all hooks
  • Modified collectHooks() to only include all hooks for methods in allMethods
  • Updated hookMixin() to allow lazy creation of hook managers for any service method

HTTP Transport (http/index.ts)

  • Updated to use getExternalMethods() for HTTP access control

Tests

  • Added tests for lazy hook registration on unconfigured methods
  • Added tests for all hooks scoping
  • Added tests for externalMethods HTTP behavior

Features

1. Individual method hooks work without configuration

// Can register hooks on ANY method, even if not in `methods`
service.hooks({
  helperMethod: [myHook]  // works!
})

methods controls which methods receive all hooks

app.use('myService', new MyService(), {
  methods: ['find', 'get', 'create']
})

service.hooks({
  around: {
    all: [loggingHook]  // only runs on find, get, create
  }
})

3. externalMethods controls HTTP exposure

app.use('myService', new MyService(), {
  methods: ['find', 'get', 'create', 'internalAction'],  // all get hooks
  externalMethods: ['find', 'get', 'create']  // only these exposed via HTTP
})

Backwards Compatibility

  • If externalMethods is not specified, it defaults to methods
  • Existing code works without modification
  • All 354 existing tests pass

Related

  • Fixes Hooks should run on non-enabled methods #3457
  • Companion PR for dove (v5.x): feat: Add externalMethods option for transport exposure (#3457) #3637

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@marshallswain
feat: Allow hooks on all methods and add externalMethods option (#3457)
caa0d75
- Individual method hook chains now work without prior configuration
- Add externalMethods option to control HTTP/transport exposure
- methods option now controls which methods receive 'all' hooks
- Backwards compatible: externalMethods defaults to methods
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jan 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Deploying feathers-eagle with  Cloudflare Pages  Cloudflare Pages

Latest commit: 09bb238
Status: ✅  Deploy successful!
Preview URL: https://2c692814.feathers-a8l.pages.dev
Branch Preview URL: https://v6-hooks-all-methods.feathers-a8l.pages.dev

View logs

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@marshallswain
fix: ESLint errors - remove this aliasing and unused import
da29174
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jan 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Deploying feathers-dove with  Cloudflare Pages  Cloudflare Pages

Latest commit: 09bb238
Status: ✅  Deploy successful!
Preview URL: https://09e7e607.feathers.pages.dev
Branch Preview URL: https://v6-hooks-all-methods.feathers.pages.dev

View logs

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@marshallswain
marshallswain force-pushed the v6-hooks-all-methods branch from 9d59599 to da29174 Compare January 10, 2026 08:40
@marshallswain
fix: Remove unused service parameter from createServiceHooksMethod
09bb238
@daffl

daffl commented Jan 10, 2026

Copy link
Copy Markdown
Member

I'm wondering if we need to add a new API if we are promoting using decorators going forward. For internal methods you need to list the parameter names of the method anyway to make it useful (to have things like context.message).

This already works and lets you register hooks on any method:

import { hooks } from 'feathers'

class MyService {
  @hooks([]).params('message')
  internalMethod(message: string) {}
  
  @hooks([])
  find() {
  }
}
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@marshallswain

marshallswain commented Jan 10, 2026

Copy link
Copy Markdown
Member Author

There are still use cases where decorators will not work well, like when using built-in services from a database manager instance. It's a bit verbose to do custom adapter classes just to be able to add hooks.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@marshallswain

marshallswain commented Jan 10, 2026

Copy link
Copy Markdown
Member Author

I forgot about the .params() calls

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@daffl

daffl commented Jan 11, 2026

Copy link
Copy Markdown
Member

Wouldn't that work with the object wrapper?

import { hooks } from 'feathers'
import { MemoryService } from 'feathers-memory'

const messageService = hooks(new MemoryService(), {
  myMethod: middleware([]).params('message')
})

app.use('messages', messageService)
marshallswain reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@marshallswain
marshallswain marked this pull request as draft January 28, 2026 07:12
marshallswain added a commit that referenced this pull request Jan 28, 2026
@marshallswain
feat: Enhanced custom methods with @method decorator
d4b41ac
- Add @method decorator for configuring custom service methods
- Support different argument signatures (not just data, params)
- Support different HTTP verbs (GET, POST, PUT, PATCH, DELETE)
- Support clean URL paths (e.g., /messages/:id/status)
- Support internal-only methods with external: false
- Add buildMethodConfig() helper for client configuration
- Add InferServiceTypes type helper for typed clients
- Update REST client to support custom method paths and verbs
- Update services and REST client documentation

The @method decorator allows custom methods to be first-class citizens
with flexible signatures, proper HTTP verb mapping, and clean URLs
instead of relying on X-Service-Method headers.

Closes #1976
Replaces #3638
This was referenced Jan 28, 2026
feat: Enhanced custom methods with @method decorator #3642
Closed
feat: Chainable @hooks().params() decorator with hookMixin support #3650
Closed
feat: Chainable @hooks().params() decorator with hookMixin support #3651
Closed
@marshallswain marshallswain closed this Jan 31, 2026
@jamesvillarrubia jamesvillarrubia mentioned this pull request Oct 20, 2026
feat: allow hooks on all methods and add externalMethods option jamesvillarrubia/feathers#1
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@marshallswain @daffl
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.