feathers-hooks-jsonapify
v0.1.11
Published
Feathers hook for outputting data in a JSON-API-compliant way.
Downloads
25
Readme
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.
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
andhasMany
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) :new:
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 intoid
typeKey
: the name of the property to convert intotype
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