Feathers hook for outputting data in a JSON-API-compliant way.
Currently works great with Sequelize as an adapter. There are plans to support more adapters in the future.
Simply run npm install --save feathers-hooks-jsonapify and you're good to go!
This hook is intended to use with feathers-rest, since it'll convert that provider's response to a JSON-API compliant document.
Require the hook:
const jsonapify = require('feathers-hooks-jsonapify');Then choose how to implement it.
app.service('messages').hooks({ after: { find: [ jsonapify() ], get: [ jsonapify() ] } });app.hooks({ after: { find: [ jsonapify() ], get: [ jsonapify() ] } });Available since: v0.1.4
feathers-hooks-jsonapify will automatically detect metadata for relationships in the model. It'll create an included top-level array in the document when the hook is called via find.
Currently working and tested with
belongsToandhasManyassociations. This feature works only with a Sequelize adapter.
{ "data": { "type": "topics", "id": "sports-cars", "attributes": { "name": "Cars", "created-at": "2017-04-14T22:22:03.000Z", "updated-at": null }, "relationships": { "parent-topic": { "data": { "type": "topics", "id": "sports" } } }, "links": { "self": "/topics/sports-cars", "parent": "/topics" } }, "included": [ { "type": "topics", "id": "sports", "attributes": { "name": "Sports", "parent-topic-id": null, "created-at": "2017-04-14T22:22:03.000Z", "updated-at": null }, "links": { "self": "/topics/sports" } } ] }Available since: v0.1.4
The hook will also detect if hook.result.skip, hook.result.limit and hook.result.total are available as part of the feathers-rest provider. If available, it'll create first, prev, next and last links accordingly.
The raw pagination data is moved to a meta object.
{ "data": [ { "type": "topics", "id": "cinema", "attributes": { "name": "Cinema", "show-role-title": null, "created-at": "2017-04-14T22:22:03.000Z", "updated-at": null }, "links": { "self": "/topics/cinema" } }, { "type": "topics", "id": "comedy", "attributes": { "name": "Comedy", "show-role-title": null, "created-at": "2017-04-14T22:22:03.000Z", "updated-at": null }, "links": { "self": "/topics/comedy" } } ], "links": { "next": "/topics?$skip=2", "last": "/topics?$skip=14" }, "meta": { "total": 15, "limit": 2, "skip": 0 } }Available since: v0.1.8
Common Object arrays can also be jsonapified for any custom service's result:
// Sample hook result, with multiple objects, from a `person` custom service. hook.result = [{ firstName: 'Joel', lastName: 'Villarreal', isEnabled: true }, { firstName: 'Alejandro', lastName: 'Bertoldi', isEnabled: false }];JSONAPIfied result:
{ "data": [ { "id": "2f1faeefc0edc081b012113e08cd9960773a70eb4d16626fade328adb9be4477", "type": "person", "attributes": { "first-name": "Joel", "last-name": "Villarreal", "isEnabled": true }, "links": { "self": "/person/2f1faeefc0edc081b012113e08cd9960773a70eb4d16626fade328adb9be4477" } }, { "id": "5ad0e862ce3db03640bb696d1ca77a0905ef4400070549622e577c4001f3e96d", "type": "person", "attributes": { "first-name": "Alejandro", "last-name": "Bertoldi", "isEnabled": false }, "links": { "self": "/person/5ad0e862ce3db03640bb696d1ca77a0905ef4400070549622e577c4001f3e96d" } } ] }// Sample hook result, with a single object in an array, from a `person` custom service. hook.result = [{ firstName: 'Joel', lastName: 'Villarreal', isEnabled: true }]; // same as: hook.result = { firstName: 'Joel', lastName: 'Villarreal', isEnabled: true };JSONAPIfied result:
{ "data": { "id": "2f1faeefc0edc081b012113e08cd9960773a70eb4d16626fade328adb9be4477", "type": "person", "attributes": { "first-name": "Joel", "last-name": "Villarreal", "isEnabled": true }, "links": { "self": "/person/2f1faeefc0edc081b012113e08cd9960773a70eb4d16626fade328adb9be4477" } } }The jsonapify hook receives an options object that accepts two settings for POS:
identifierKey: the name of the property to convert intoidtypeKey: the name of the property to convert intotype
The hook's got your back. Using crypto.createHash, it creates a unique SHA-256 digest using the contents of the object.
The hook will use the service's name (hook.service.options.name) as each model's type.
Check out the issues.
Knock yourself out! Fork the repo and make a PR.
MIT