Services

“Services” are the heart of every Feathers application. Services are JavaScript objects (or instances of ES6 classes) that implement certain methods. Feathers itself will also add some additional methods and functionality to its services.

Service methods

Service methods are pre-defined CRUD methods that your service object can implement (or that have already been implemented by one of the database adapters). Below is a complete example of the Feathers service interface as a normal JavaScript object either returning a Promise or using async/await:

{% codetabs name=”Promise”, type=”js” -%}
const myService = {
find(params) {
return Promise.resolve([]);
},
get(id, params) {},
create(data, params) {},
update(id, data, params) {},
patch(id, data, params) {},
remove(id, params) {},
setup(app, path) {}
}

app.use(‘/my-service’, myService);
{%- language name=”async/await”, type=”js” -%}
const myService = {
async find(params) {
return [];
},
async get(id, params) {},
async create(data, params) {},
async update(id, data, params) {},
async patch(id, data, params) {},
async remove(id, params) {},
setup(app, path) {}
}

app.use(‘/my-service’, myService);
{%- endcodetabs %}

Services can also be an instance of an ES6 class:

{%- codetabs name=”Promise”, type=”js” -%}
class MyService {
find(params) {
return Promise.resolve([]);
}
get(id, params) {}
create(data, params) {}
update(id, data, params) {}
patch(id, data, params) {}
remove(id, params) {}
setup(app, path) {}
}

app.use(‘/my-service’, new MyService());
{%- language name=”async/await”, type=”js” -%}
class MyService {
async find(params) {
return [];
}
async get(id, params) {}
async create(data, params) {}
async update(id, data, params) {}
async patch(id, data, params) {}
async remove(id, params) {}
setup(app, path) {}
}

app.use(‘/my-service’, new MyService());
{%- endcodetabs %}

ProTip: Methods are optional, and if a method is not implemented Feathers will automatically emit a NotImplemented error.

Important: Always use the service returned by app.service(path) not the service object (the myService object above) directly. See the app.service documentation for more information.

Service methods must return a Promise or be declared as async and have the following parameters:

  • id — The identifier for the resource. A resource is the data identified by a unique id.
  • data — The resource data.
  • params - Additional parameters for the method call, see params

Once registered, the service can be retrieved and used via app.service():

  1. const myService = app.service('my-service');
  2. myService.find().then(items => console.log('.find()', items));
  3. myService.get(1).then(item => console.log('.get(1)', item));

Keep in mind that services don’t have to use databases. You could easily replace the database in the example with a package that uses some API to, for example, pull in GitHub stars or stock ticker data.

Important: This section describes the general usage of service methods and how to implement them. They are already implemented by the official Feathers database adapters. For specifics on how to use the database adapters, see the database adapters common API.

params

params contain additional information for the service method call. Some properties in params can be set by Feathers already. Commonly used are:

  • params.query - the query parameters from the client, either passed as URL query parameters (see the REST chapter) or through websockets (see Socket.io or Primus).
  • params.provider - The transport (rest, socketio or primus) used for this service call. Will be undefined for internal calls from the server (unless passed explicitly).
  • params.user - The authenticated user, either set by Feathers authentication or passed explicitly.
  • params.connection - If the service call has been made by a real-time transport (e.g. through websockets), params.connection is the connection object that can be used with channels.

Important: For external calls only params.query will be sent between the client and server. If not passed, params.query will be undefined for internal calls.

.find(params)

service.find(params) -> Promise - Retrieves a list of all resources from the service. Provider parameters will be passed as params.query.

  1. app.use('/messages', {
  2. find(params) {
  3. return Promise.resolve([
  4. {
  5. id: 1,
  6. text: 'Message 1'
  7. }, {
  8. id: 2,
  9. text: 'Message 2'
  10. }
  11. ]);
  12. }
  13. });

Note: find does not have to return an array; it can also return an object. The database adapters already do this for pagination.

.get(id, params)

service.get(id, params) -> Promise - Retrieves a single resource with the given id from the service.

  1. app.use('/messages', {
  2. get(id, params) {
  3. return Promise.resolve({
  4. id,
  5. text: `You have to do ${id}!`
  6. });
  7. }
  8. });

.create(data, params)

service.create(data, params) -> Promise - Creates a new resource with data. The method should return a Promise with the newly created data. data may also be an array.

  1. app.use('/messages', {
  2. messages: [],
  3. create(data, params) {
  4. this.messages.push(data);
  5. return Promise.resolve(data);
  6. }
  7. });

Important: A successful create method call emits the created service event.

.update(id, data, params)

service.update(id, data, params) -> Promise - Replaces the resource identified by id with data. The method should return a Promise with the complete, updated resource data. id can also be null when updating multiple records, with params.query containing the query criteria.

Important: A successful update method call emits the updated service event.

.patch(id, data, params)

patch(id, data, params) -> Promise - Merges the existing data of the resource identified by id with the new data. id can also be null indicating that multiple resources should be patched with params.query containing the query criteria.

The method should return with the complete, updated resource data. Implement patch additionally (or instead of) update if you want to distinguish between partial and full updates and support the PATCH HTTP method.

Important: A successful patch method call emits the patched service event.

.remove(id, params)

service.remove(id, params) -> Promise - Removes the resource with id. The method should return a Promise with the removed resource. id can also be null, which indicates the deletion of multiple resources, with params.query containing the query criteria.

Important: A successful remove method call emits the removed service event.

.setup(app, path)

service.setup(app, path) -> Promise is a special method that initializes the service, passing an instance of the Feathers application and the path it has been registered on.

For services registered before app.listen is invoked, the setup function of each registered service is called on invoking app.listen. For services registered after app.listen is invoked, setup is called automatically by Feathers when a service is registered.

setup is a great place to initialize your service with any special configuration or if connecting services that are very tightly coupled (see below), as opposed to using hooks.

  1. // app.js
  2. 'use strict';
  3. const feathers = require('@feathersjs/feathers');
  4. const rest = require('@feathersjs/express/rest');
  5. class MessageService {
  6. get(id, params) {
  7. return Promise.resolve({
  8. id,
  9. read: false,
  10. text: `Feathers is great!`,
  11. createdAt: new Date.getTime()
  12. });
  13. }
  14. }
  15. class MyService {
  16. setup(app) {
  17. this.app = app;
  18. }
  19. get(name, params) {
  20. const messages = this.app.service('messages');
  21. return messages.get(1)
  22. .then(message => {
  23. return { name, message };
  24. });
  25. }
  26. }
  27. const app = feathers()
  28. .configure(rest())
  29. .use('/messages', new MessageService())
  30. .use('/my-service', new MyService())
  31. app.listen(3030);

Feathers functionality

When registering a service, Feathers (or its plugins) can also add its own methods to a service. Most notably, every service will automatically become an instance of a NodeJS EventEmitter.

.hooks(hooks)

Register hooks for this service.

.publish([event, ] publisher)

Register an event publishing callback. For more information, see the channels chapter.

.mixin(mixin)

service.mixin(mixin) -> service extends the functionality of a service. For more information see the Uberproto project page.

.on(eventname, listener)

Provided by the core NodeJS EventEmitter .on. Registers a listener method (function(data) {}) for the given eventname.

Important: For more information about service events, see the Events chapter.

.emit(eventname, data)

Provided by the core NodeJS EventEmitter .emit. Emits the event eventname to all event listeners.

Important: For more information about service events, see the Events chapter.

.removeListener(eventname, [ listener ])

Provided by the core NodeJS EventEmitter .removeListener. Removes all listeners, or the given listener, for eventname.

Important: For more information about service events, see the Events chapter.