Skip to content

joelalejandro/feathers-hooks-jsonapify

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

feathers-hooks-jsonapify

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.

npm version

Installing

Simply run npm install --save feathers-hooks-jsonapify and you're good to go!

Usage

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.

Tied up to a service

app.service('messages').hooks({ after: { find: [ jsonapify() ], get: [ jsonapify() ] } });

As a global hook

app.hooks({ after: { find: [ jsonapify() ], get: [ jsonapify() ] } });

Relationships

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 belongsTo and hasMany associations. This feature works only with a Sequelize adapter.

Example document for a self-referencing model

{ "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" } } ] }

Pagination

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.

Example document with pagination links

{ "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 } }

Plain Object Serialization (POS) 🆕

Available since: v0.1.8

Common Object arrays can also be jsonapified for any custom service's result:

Multiple objects

// 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" } } ] }

Single object

// 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" } } }

Identifier and type mapping

The jsonapify hook receives an options object that accepts two settings for POS:

  • identifierKey: the name of the property to convert into id
  • typeKey: the name of the property to convert into type

What happens if I don't use identifierKey?

The hook's got your back. Using crypto.createHash, it creates a unique SHA-256 digest using the contents of the object.

What happens if I don't use typeKey?

The hook will use the service's name (hook.service.options.name) as each model's type.

TODOs

Check out the issues.

Feel like contributing?

Knock yourself out! Fork the repo and make a PR.

Licence

MIT

About

Feathers hook for outputting data in a JSON-API-compliant way.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •