Search code examples
javascriptnode.jsexpressfeathersjs

Feathers calling custom API method


I define my api with something like the below:

class MyFeathersApi {
  feathersClient: any;
  accountsAPI: any;
  productsAPI: any;

  constructor(app) {
    var port: number = app.get('port');

    this.accountsAPI = app.service('/api/accounts');
    this.productsAPI = app.service('/api/products');
  }

  findAdminAccounts(filter: any, cb: (err:Error, accounts:Models.IAccount[]) => void) {
    filter = { query: { adminProfile: { $exists: true } } }
    this.accountsAPI.find(filter, cb);
  }

When I want to use database adapter methods, from the client, i.e. find and/or create, I do the below:

var accountsAPIService = app.service('/api/accounts');
accountsAPIService.find( function(error, accounts) {
  ...
});

How I call custom methods, such as findAdminAccounts() from the client?


Solution

  • You can only use the normal service interface on the client. We found that support for custom methods (and all the issues it brings with it going from a clearly defined interface to arbitrary method names and parameters) is not really necessary because everything in itself can be described as a resource (service).

    The benefits (like security, predictability and sending well defined real-time events) so far have heavily outweighed the slight change in thinking required when conceptualizing your application logic.

    In your example you could make a wrapper service that gets the admin accounts like this:

    class AdminAccounts {
      find(params) {
        const accountService = this.app.service('/api/accounts');
    
        return accountService.find({ query: { adminProfile: { $exists: true } } });
      }
    
      setup(app) {
        this.app = app;
      }
    }
    
    app.use('/api/adminAccounts', new AdminAccounts());
    

    Alternatively you could implement a hook that maps query parameters to larger queries like this:

    app.service('/api/accounts').hooks({
      before: {
        find(hook) {
          if(hook.params.query.admin) {
            hook.params.query.adminProfile = { $exists: true };
          }
        }
      }
    });
    

    This would now allow calling something like /api/accounts?admin.

    For more information see this FAQ.