JSPM

  • Created
  • Published
  • Downloads 32138
  • Score
    100M100P100Q152592F
  • License MIT

Useful hooks for use with Feathersjs services.

Package Exports

  • feathers-hooks-common
  • feathers-hooks-common/lib/bundled
  • feathers-hooks-common/lib/index
  • feathers-hooks-common/lib/utils

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (feathers-hooks-common) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

feathers-hooks-common

Useful hooks for use with Feathersjs services.

Build Status Coverage Status

Code Examples

Data Items

(1) Join a related item to result (after hook).

  • Supports multiple result items, including paginated find.
  • Supports key field with an array of keys.
  • Supports multiple joins.
const hooks = require('feathers-hooks-common');
module.exports.after = {
  // add prop 'user' containing the user item who's key is in 'senderId'.
  all: [ hooks.populate('user', { field: 'senderId', service: '/users' }) ]
};

(2) Remove fields from data.

  • Field names support dot notation e.g. 'name.address.city'
  • Supports multiple data items, including paginated find.
  • May be dynamically disabled, using either a sync or promise based function.
module.exports.after = {
  all: [ hooks.remove('verifyToken', 'verifyExpires', (hook) => true) ]
};

(3) Retain only selected fields in data.

  • Field names support dot notation
  • Supports multiple data items, including paginated find.
  • May be dynamically disabled, using either a sync or promise based function.
module.exports.after = {
  all: [ hooks.pluck('employee.name', 'employee.email',
           (hook) => new Promise(resolve => setTimeout(() => resolve(true), 100)) ]
};

(4) Convert fields to lower case.

  • Field names support dot notation
  • Supports multiple data items, including paginated find.
  • May be dynamically disabled, using either a sync or promise based function.
module.exports.after = {
  all: [ hooks.lowerCase('email') ]
};

(5) Add created at timestamp.

  • Field names support dot notation
  • Supports multiple data items, including paginated find.
  • May be dynamically disabled, using either a sync or promise based function.
module.exports.before = {
  create: [ hooks.setCreatedAt('createdAt') ]
};

(6) Add or update the updated at timestamp.

  • Field names support dot notation
  • Supports multiple data items, including paginated find.
  • May be dynamically disabled, using either a sync or promise based function.
module.exports.before = {
  create: [ hooks.setUpdatedAt('updatedAt') ]
};

Query Params

(1) Remove criteria from query (before hook).

  • Field names support dot notation
  • Supports multiple data items, including paginated find.
  • May be dynamically disabled, using either a sync or promise based function.
module.exports.before = {
  all: [ hooks.removeQuery('sex') ]
};

(2) Retain only selected criteria in query (before hook).

  • Field names support dot notation.
  • Supports multiple data items, including paginated find.
  • May be dynamically disabled, using either a sync or promise based function.
module.exports.before = {
  all: [ hooks.removeQuery('employee.dept') ]
};

Validation

Fidelity and code reuse are improved if the server can rerun validation code written for the front-end.

  • Support is provided for sync, callback and promise based validation routines.
  • Optionally replace the data with sanitized values.

(1) Invoke a synchronous validation routine (before; create, update, patch).

const usersClientValidation = (values) => values.email ? null : { email: 'Email is invalid' };

module.exports.before = {
  create: [ hooks.validateSync(usersClientValidations) ] // redo client sync validation
};

(2) Invoke a callback based validation routine (before; create, update, patch).

const usersServerValidation = (values, param2, cb) => {
  setTimeout(() => {
    values.email.trim()
      ? cb(null, { ...values, email: values.email.trim() }) // sanitize data
      : cb({ email: 'Email is invalid' });
  }, 100);
};

module.exports.before = {
  create: [ hooks.validateUsingCallback(usersServerValidations, 'value4param2') ] // server only
};

(3) Invoke a promise based validation routine (before; create, update, patch).

const usersServerValidation = (values, ...rest) => (
  new Promise((resolve, reject) => {
    setTimeout(() => {
      values.email.trim()
        ? resolve({ ...values, email: values.email.trim() })
        : reject(new errors.BadRequest({ email: 'Email is invalid' }));
    }, 100);
  })
);

module.exports.before = {
  create: [ hooks.validateUsingPromise(usersClientAsync) ] // redo client async validation
};

Note:

The structure of the data object should be checked before any validation is performed. Several schema validation packages are available.

Authorization

(1) Disable hook

  • Disable service completely, from all external providers, or from certain providers.
  • Service be dynamically disabled, using either a sync or promise based function.
module.exports.before = {
  patch: [ hooks.disable('socketio', 'rest') ],
  create: [ hooks.disable((hook) => new Promise(resolve => resolve(true) )) ]
};

(2) Authorize access by role. Convenience wrapper for feathers-authentication.hooks.restrictToRoles.

  • Clean, clear and DRY.
const authorizer = hooks.restrictToRoles(['inv', 'ship'], 'userAuthorizedRoles', false, 'userId');

module.exports.before = {
  all: [ authorizer() ]
  create: [ authorizer(['purch']) ]
};

Database

(1) Mark items as deleted rather than removing them from the database. (ALPHA)

export.before = {
  remove: [ softDelete() ], // update item flagging it as deleted
  find: [ softDelete() ] // ignore deleted items
};

Utilities

(1) Normalize the URL slug (before).

Copy the slug from raw HTTP requests, e.g. https://.../stores/:storeid/... to where other providers typically store it. Dot notation is supported.

module.exports.before = {
  create: [ hooks.setSlug('storeid') ]
};

(2) Display current info about the hook to console.

module.exports.after = {
  create: [ hooks.setUpdatedAt('step 1') ]
};
// * step 1
// type: before, method: create
// data: { name: 'Joe Doe' }
// query: { sex: 'm' }
// result: { assigned: true }

Utilities for Writing Hooks

These utilities may be useful when you are writing your own hooks. You can import them from feathers-hooks-common/lib/utils.

(1) Get and replace the items in the hook.

  • Handles before and after types.
  • Handles paginated and non-paginated results from find.

javascript import { getItems, replaceItems } from 'feathers-hooks-common/lib/utils'; export.before = { create: [ (hook) => { ... const items = getItems(hook); Array.isArray(items) ? items[0].code = 'a' : items.code = 'a'; replaceItems(hook, items); ... }]};


(2) Throw if a hook is used wrongly.

```javascript
import { checkContext } from 'feathers-hooks-common/lib/utils';
function myHook(hook) {
  checkContext(hook, 'before', ['create', 'remove']);
  ...
}
export.after = { create: [ myHook ]}; // throws

(3) Support dot notation in field access.

  • Optionally deletes properties in object.
import { getByDot, setByDot } from 'feathers-hooks-common/lib/utils';
export.before = { create: [ (hook) => {
  ...
  const city = getByDot(hook.data, 'person.address.city');
  setByDot(hook, 'data.person.address.city', 'London');
  ...
}]};

Motivation

Feathers services can be developed faster if the hooks you need are at hand.

This package provides some commonly needed hooks.

Installation

Install Nodejs.

Run npm install feathers-hooks-common --save in your project folder.

/src on GitHub contains the ES6 source. It will run on Node 6+ without transpiling.

API Reference

Each file in /src fully documents its exports.

See also the Featherjs docs.

Tests

npm test to run tests.

npm run cover to run tests plus coverage.

Contributing

Contribute to this repo.

Guide to ideomatic contributing.

Change Log

List of notable changes.

License

MIT. See LICENSE.