devour-js / devour-client Goto Github PK
View Code? Open in Web Editor NEWDon't just consume your JSON API, Devour it...
Home Page: https://www.npmjs.com/package/devour-client
License: ISC License
Don't just consume your JSON API, Devour it...
Home Page: https://www.npmjs.com/package/devour-client
License: ISC License
Hi.
When you try to perform an arbitrary request with methods PATCH
or POST
, you end up getting an error: TypeError: Cannot read property 'options' of undefined
.
I've tracked this down to the _serialize.js
file, method resource
. The problem is that in line 11 let model = this.modelFor(modelName)
since we are not providing a model, the model variable is undefined and when we call model.options
latter, the error is triggered.
Ex of calling code: jsonApi.request('https://example.com', 'POST', { a_query_param: 3 }, { some_payload_item: 'blah' })
Thanks
I was going to create a PR to add a constructor option for building URLs with trailing slashes, but I wanted to check first if there was another solution I was missing.
It would be nice to be able to set null for the value of include
for example, and have the resulting request just not include that param. That way it would be possible to concisely decide to specify an include or not.
Hey,
I am trying to send a create action with a relationship but the relationship does not include the data under it. This is what I did:
jsonApi.create('user/properties', {
address: {
street_number: '1',
street_name: 'name',
},
headline: 'something'),
description: 'description'),
photos: [],
floorplans: [],
})
What I get on the server side is this:
'data': {
'type': "user/properties"
'attributes': "the attributes - everything is fine here"
'relationships': {
'address': {
'data': {
'type': 'addresses'
}
}
}
}
As you can see the data is missing under the address. Am I doing something wrong?
Thanks!
I'm trying to have devour (v2.0.7) receive following response in an RN app:
{
"errors":[
{
"title":"Authentication failed",
"detail":"Invalid username and/or password",
"code":"101",
"status":"400"
}
]
}
but, I'm seeing the following error:
undefined is not an object (evaluating 'source.pointer')
- node_modules/devour-client/lib/middleware/json-api/res-errors.js:46:13 in errorKey
- node_modules/devour-client/lib/middleware/json-api/res-errors.js:24:24 in buildErrors
- ... 10 more stack frames from framework internals
I'm new to JSON API, so looking at the docs (http://jsonapi.org/format/#error-objects) I noticed it said an error object MAY have one or more attributes, instead of MUST as used elsewhere. So just wondering if this is still correct?
Otherwise, looking at that code, maybe it's worth checking if source is present as well?
function errorKey(index, source) {
if (!source || source.pointer == null) {
return index;
}
return source.pointer.split('/').pop();
}
Devour 2.0.7
RN 0.50.3
@themarkappleby pointed out an issue that we need to figure out – especially since it's a valid JSON-API convention.
When fetching a resource, it's perfectly valid to do so through a nested URL, you can see a clear example of this articulated in the specification here.
And the following request fetches an article’s author:
GET /articles/1/author HTTP/1.1
Right now, our find calls just accept the name of the model jsonApi.find('author', 1)
... so what's the best way to support this feature?
@themarkappleby was thinking we could parse a raw string jsonApi.find('articles/1/author')
, but I'd be a little worried about model names vs urls and figuring out how to map all that back.
I was thinking we could maybe pass an object in some instances:
jsonApi.find({model: 'author', url: 'articles/1/author'}, 1)
Or maybe an options object?
jsonApi.find('author', 1, {nested: 'articles/1'})
Happy to hear any thoughts about this – @derek-watson I know you are questioning the requirements of having defined models all together (I still need to respond to that)
We need a logo. Thinking we can just buy one off vector stock or something... Drop your suggestions in here.
I'm not sure I understand the way the singleton pattern is used here. In the readme I'm encouraged to
let jsonApi = JsonApi.getInstance()
jsonApi.setup('http://your-api-here.com')
which made me think I'm getting a new instance of JsonApi and configuring it with an endpoint URL (I realized later that's not the case). If we're getting and configuring instances, I think it would be most appropriate to use the new
keyword and pass options to the constructor:
const jsonApi = new JsonApi({baseUrl: 'http://your-api-here.com'})
I looked at the code to double-check and saw this, which confirmed my suspicions:
class JsonApi {
...
but when I looked into the code for the getInstance()
method, I realized we're forcing a singleton pattern.
getInstance()
methodDemo: https://runkit.com/jon-hall/59b966684249c500125ad282 (see the terminal output for the actual error)
When making a findAll
request that has filters, and any of the filter values has a space in, the following error is being thrown:
devour error TypeError: Request path contains unescaped characters
at new ClientRequest (_http_client.js:52:11)
at Object.exports.request (http.js:31:10)
at Writable.RedirectableRequest._performRequest (/app/available_modules/1505322364000/devour-client/node_modules/axios/node_modules/follow-redirects/index.js:73:20)
at Writable.RedirectableRequest (/app/available_modules/1505322364000/devour-client/node_modules/axios/node_modules/follow-redirects/index.js:57:7)
at Object.wrappedProtocol.request (/app/available_modules/1505322364000/devour-client/node_modules/axios/node_modules/follow-redirects/index.js:229:10)
at dispatchHttpRequest (/app/available_modules/1505322364000/devour-client/node_modules/axios/lib/adapters/http.js:131:25)
at httpAdapter (/app/available_modules/1505322364000/devour-client/node_modules/axios/lib/adapters/http.js:18:10)
at dispatchRequest (/app/available_modules/1505322364000/devour-client/node_modules/axios/lib/core/dispatchRequest.js:52:10)
at process._tickCallback (internal/process/next_tick.js:109:7)
at Module.runMain (module.js:606:11)
at run (bootstrap_node.js:389:7)
at startup (bootstrap_node.js:149:9)
at bootstrap_node.js:504:3
I'm trying to use your client, I'm using promises but have no idea how to handle errors back from the API, your documentation isn;t very clear, could someone point me in the right direction?
I'm currently implementing like this:
jsonApi.create('genre', genre).then((response) => {
console.log(response)
})
If there is an error returned from the API then no response is consoled. I tried using catch but that doesn't return the response from the serve.
Any help would be greatly appreciated!
According to the JSON API spec here a valid response to an PATCH
request is status 204
and an empty body. This is how the fortune-json-api
library handles these requests.
I will be looking into how to patch this, but would appreciate help/advice.
// Define Model
jsonApi.define('post', {
title: '',
content: '',
tags: []
})
@Emerson why is this step necessary? I'm unable to find any reference to the models and attributes being used in the codebase. Are there roadmap features that will make use of this? Is it useful on the client?
I just started a JSPM angular 2 project (according to this project).
Installing devour client: jspm install npm:devour-client
works. When I need it in a component it only works when I use import JsonApi from 'devour-client/lib';
Am I missing something or is there something wrong regarding the packaging of this module?
I'm trying to use v.1.3.9 in a react-native(0.35.0-rc.0) project but I get an error that it can't find the es2015 preset. Any ideas?
According to the jsonapi format its possible to have DELETE requests with payload http://jsonapi.org/format/#crud-updating-to-many-relationships (scroll down to see the DELETE request example)
Currently devour client destroy
method doesn't support a payload and even the req-delete
middleware removes any data that is about to be sent to the server.
Thanks
The npm installation guide refers to "devour-api-client", but I believe the new name is "devour-client".. There are two areas of the Quick Start guide that should be updated:
npm install devour-api-client --save
import JsonApi from 'devour-api-client'
Regardng the JSON API Spec (http://jsonapi.org/format/#errors) this is a valid error response:
{"errors":["ForbiddenAccessException"]}
It looks like devour require the optional parameter pointer
TypeError: Cannot read property 'pointer' of undefined
Would it be a good idea to use fetch
under the hood instead of axios
?
fetch is a better networking API being worked on by the standards committee and is already available in Chrome. It is available in React Native by default.
https://fetch.spec.whatwg.org/
https://facebook.github.io/react-native/docs/network.html
Here's a polyfill that can be used until native runtime support for fetch is widespread, which comes in at 11kb of unminified code instead of 32kb for axios, with the upside that the dependency disappears completely at some point in the future:
Hi,
Do you have any example of multiple model definition of model reuse? How and where to move models definition out of the main logic to use them multiple times in different files?
Thanks
I'd like to consider removing the pull request template from this project. I find clear and concise english to be a much more expressive way to describe the intention of your PR, and in many cases the template is getting in the way of clarity.
Here is a full-screen desktop screenshot of a recent pull request. In my mind that amount of screen real estate should contain a lot more information.
Your API have a wrong Accept
Header
payload.req.headers = {
'Content-Type': 'application/vnd.api+json',
'Accept': 'application/vnd.api+json'
}
Accept
should be e.g. application/json
otherwise it returns a 406 Not Acceptable
see Specification: http://jsonapi.org/format/#content-negotiation-servers
jsonApi.headers['Accept'] = 'application/json';
We should probably be using the encodeURIComponent
function on ids we are building URIs from. I don't see anywhere in the JSON API spec that restricts id characters.
Hi
According to JSON API spec, you can update a relationship by using the "relationships" link ex post/1/relationships/comments
.
Currently Devour only allows this through the resource link post/1
by adding the respective relationship
object in the data sent to the server.
If we add a method similar in behavior to all
and one
to the url builder we could allow relationships
links to work.
Ex
relationships () {
this.builderStack.push({path: 'relationships'})
return this
}
After this we could do something like jsonApi.one('post', 1).relationships().all('comments').post([{id: comment1Id}, {id: comment2Id}])
The "relationships" url could be configurable to allow more flexibility.
What do you think?
Not sure if this is the right place to report this - I'm trying to use this library in a react native app started with create-react-native-app
(to host in Expo), and the very first statement:
import JsonApi from 'devour-client';
is erroring when trying to open the app in a device with:
console.error: "There was a problem sending log messages to your development environment",
{
"line":53577,
"column":38,
"sourceURL":"http://192.168.8.100:19003/node_modules/react-native-scripts/build/bin/crna-entry.bundle?platform=ios&dev=true&strict=false&minify=false&hot=false&assetPlugin=/Users/erik/Coding/rn-devour-app/node_modules/expo/tools/hashAssetFiles"}
<unknown>
RemoteConsole.js:121:6
tryCatch
es6-promise.js:410:20
invokeCallback
es6-promise.js:425:21
publish
es6-promise.js:393:21
publishRejection
es6-promise.js:335:10
flush
es6-promise.js:121:13
_callTimer
JSTimers.js:154:6
callTimers
JSTimers.js:411:17
__callFunction
MessageQueue.js:302:47
<unknown>
MessageQueue.js:116:26
__guard
MessageQueue.js:265:6
callFunctionReturnFlushedQueue
MessageQueue.js:115:17
I noticed in the docs I can pass logger: true|false
to new JsonApi(), but are there calls to log already during the import itself?
Devour: 2.0.7
Sample app: https://github.com/erikse/rn-devour-app
In Devour documentation I can't find way to add Sparse Fields to my request. I tried something like this:
jsonApi.all(teams).get({fields: '[team]=name'})
but this generate http address:
http://apiurl/teams/?fields=[team]=name
instead of http://apiurl/teams/?fields[team]=name
This additional '=' in url (between fields and [team]) isn't according with JsonApi specification. How can I generate proper arguments in url as below:
http://apiurl/teams/?fields[team]=name
While investigating #82 I found another bug
If you ask for an entity, e.g. clan
with `id: 21´,
all releations are inserted correctly, except the entity itself
relatedItemsFor
only checks the include
part of response, not the cache ...
rails controller actions that respond to both html and json require a .json appended to the end of the url to signify that a json response is expected.
addressing this by adding a 'trailingJson' option for the new JsonApi constructor is straightforward and I can add a PR, but is there something wrong w/ this approach?
Initializer should be an option.
Current:
new JsonApi('http://example.com', listOfMiddleware)
The issue with this is that the minute we want to pass in additional option, maybe a header, or enable or disable logging, it becomes a headache to manage, and any other calls of the initializer will need to be changed. Where as with an option, we can easily add a key.
Heyhey,
at first: Thank you very much for this great library!
I have the following question and thought that maybe someone has an easy answer because I am actually quite new to this jsonApi thing.
My api formats the dates according to this standard: https://www.w3.org/TR/NOTE-datetime (which i could change if that would help)
I've got a datepicker that needs the date as JavaScript Date Object.
Now I convert the dates, everytime i make a get request and everytime i make an update request.
I also tried using a custom derserializer but than I have to do the whole deserializing process on my own, even though i only need to manipulate one or two attributes.
should i maybe build a middleware for this?
Thank you in advance :)
I have the following schema:
ApiStore.define("user", {
email: "",
first_name: "",
last_name: "",
external_avatar_url: "",
phone_numbers: {
jsonApi: "hasMany",
type: "phone_number"
},
geo_points: {
jsonApi: "hasMany",
type: "geo_point"
}
});
ApiStore.define("phone_number", {
number: "",
dont_call: "",
users: {jsonApi: "hasMany", type: "user"}
});
ApiStore.define("ttc_interaction", {
kind: "",
telemarketer_id: "",
phone_number_id: "",
metadata: {},
date: "",
telemarketer: {jsonApi: "hasOne", type: "user"},
customer: {jsonApi: "hasOne", type: "user"},
phone_number: {jsonApi: "hasOne", type: "phone_number"}
});
When retrieving ttc_interaction
, devour explodes with a RangeError: Maximum call stack size exceeded(…). I assume this is due to a loop caused by the way devour deserializes data, since removing users
from phone_numbers
"solves" the issue.
Right now I don't see how I can use the url builder to get the url for a resource of hasOne relationship. For instance, if an author has one bio, I would expect the url (for author id 1) to be
authors/1/bio
.
I would like to get this url via the url builder methods by doing something like
jsonApi.one('authors', author.id).only('bio').get();
.
In the meantime, I can get around this by defining a collectionPath for bio of bio, and doing 'jsonApi.one('authors', author.id).all('bio').get()
but that feels like a bit of a hack.
I'd be happy to do the work on this, but wanted to see if you thought it was worthwhile before pursuing it. Also not sure how this might relate to #46.
First up: thanks for the work on this library; it's proving very useful 😄 🎉
I've noticed something that isn't quite to spec when attempting to create/update a resource, specifically how the serializer deals with relationships that either aren't present or are explicitly set to null.
Based on my interpretation of the spec for creating resources and updating relationships, an API expects relationships in a payload, null or otherwise, to contain a data
key.
If a relationship is provided in the relationships member of the resource object, its value MUST be a relationship object with a data member
The current serializer, however, omits the data
part, causing the payload to not be valid under version 1 of the spec.
As a quick example, I have two resources (comment, thread) declared as such:
jsonApi.define('thread', {
thread: {
jsonApi: 'hasMany',
type: 'comment'
}
});
jsonApi.define('comment', {
body: '',
thread: {
jsonApi: 'hasOne',
type: 'thread'
}
});
and I want to create a comment that isn't in any thread by doing the following:
jsonApi.all('comment').post({ body: "An orphaned comment", thread: null });
I'd expect the following to be sent to the server
{
"data": {
"type": "comments",
"attributes": { "body": "An orphaned comment" },
"relationships": {
"thread": {
"data": null
}
}
}
}
However what is sent is slightly different (lack of data
in the relationship)
{
"data": {
"type": "comments",
"attributes": { "body": "An orphaned comment" },
"relationships": {
"thread": null
}
}
}
And omitting the relationship entirely:
jsonApi.all('comment').post({ body: "An ambiguous comment" });
Expected:
{
"data": {
"type": "comments",
"attributes": { "body": "An ambiguous comment" }
}
}
results in the same invalid payload being sent.
I'm having a think about some ways to change this behaviour in the serializer for the two cases here (deliberately setting it to null, and omitting it entirely). This'll come in a PR at some point in the future, but for now do any thoughts or concerns come to mind if the serializer does get changed to produce the expected behaviour?
This is implemented in PR #30, any feedback or design queries are 👍 👌 😄
The specification states that both the top level document and any resource may contain meta and links members. However, the deserialization here will nuke any resource specified meta or links members via the top level document's data attribute when deserializing a single resource. (e.g. jsonApi.get('posts', 1))
data: {
attributes:{
someAttribute: 'a'
},
type: 'posts',
id: '1'
meta: {
postMeta: 'some meta data for this individual post'
}
},
meta: {
docMeta: 'document meta'
}
Note how both the document and resource have meta members.
As of this PR: #24
resources are deserialized with an understanding of meta and links members. This works fine when handing a collection of resources or resources in included.
However, when defining meta data on a single resource response as shown in example 1 above,
the res-deserialize middleware will replace any resource level meta data with top level meta, or undefined no top level meta data is specified.
https://github.com/twg/devour/blob/master/src/middleware/json-api/res-deserialize.js#L35
The payload from example 1 above deserializes to the following object:
{
id: '1',
someAttribute: 'a',
meta: {
docMeta: 'document meta'
}
}
Note how the resource level meta is replaced with the document level meta data.
data: {
attributes:{
someAttribute: 'a'
},
type: 'posts',
id: '1'
meta: {
postMeta: 'some meta data for this individual post'
}
}
The payload for example 2 deserialized to the following object:
{
id: '1',
someAttribute: 'a'
meta: undefined
}
The examples above also apply to resource/document level links members.
This is a non-backwards compatible change. While it does provide an arguably more accurate data structure I would be cautious of forcing existing users to rewrite their applications.
{
resource: {
attributes: {},
meta: {},
links: {}
},
meta: {},
links: {}
}
collections would continue to add meta and links attributes to the array of resources.
This allows backwards compatibility and help to highlight that there are document level meta and links members.
{
attributes: {},
meta: {},
links: {}
docMeta: {},
docLinks: {}
}
collections would add docMeta and docLinks attributes to the array of resources.
Too risky as there could easily be meta or link members with identical names.
I'm currently working off a fork that utilizes docMeta and docLinks, but before considering a PR I'd like to get some feedback or alternative proposals from the maintainers.
This library is awesome!
I wonder if it would hit the ear better if it were named simply devour.js
. The name as it stands, while descriptive, is a little bit hard to say.
Apologies if I'm doing something wrong here, but I can't figure out what that might be. I have models user
and character
:
this.jsonApi.define('user', {
name: '',
about: '',
waifuOrHusbando: '',
waifu: {
jsonApi: 'hasOne',
type: 'characters'
},
gender: '',
location: '',
birthday: '',
createdAt: '',
followersCount: '',
followingCount: '',
avatar: { medium: '' }
})
this.jsonApi.define('character', {
name: ''
})
When I attempt to find the user based on id, the returned user object has null
for waifu
:
this.jsonApi.find('user', id, {
include: 'waifu',
fields: {...}
})
Here is what the actual resource looks like:
{
"data": {
"id": "78332",
"type": "users",
"links": {
"self": "https://kitsu.io/api/edge/users/78332"
},
"attributes": {
"name": "matthewdias",
"pastNames": [],
"about": "People call me an anime normie and a music elitist. I program shit.\n\nI use advanced ratings.",
"bio": "",
"aboutFormatted": "I should probably put something here...",
"location": "Austin, TX",
"waifuOrHusbando": "Waifu",
"followersCount": 108,
"createdAt": "2015-02-03T22:13:20.776Z",
"facebookId": "1457594844",
"followingCount": 144,
"lifeSpentOnAnime": 67445,
"birthday": "1995-10-25",
"gender": "male",
"updatedAt": "2017-05-05T03:57:05.912Z",
"commentsCount": 460,
"favoritesCount": 70,
"likesGivenCount": 1507,
"reviewsCount": 0,
"likesReceivedCount": 201,
"postsCount": 124,
"ratingsCount": 289,
"proExpiresAt": null,
"title": null,
"profileCompleted": true,
"feedCompleted": true,
"website": null,
"avatar": {...},
"coverImage": {...},
"ratingSystem": "advanced",
"theme": "light"
},
"relationships": {
"waifu": {
"links": {
"self": "https://kitsu.io/api/edge/users/78332/relationships/waifu",
"related": "https://kitsu.io/api/edge/users/78332/waifu"
},
"data": {
"type": "characters",
"id": "29496"
}
},
...
}
},
"included": [
{
"id": "29496",
"type": "characters",
"links": {
"self": "https://kitsu.io/api/edge/characters/29496"
},
"attributes": {
"slug": "togame",
"name": "Togame",
"malId": 28523,
...
},
"relationships": {...}
}
]
}
Hi guys,
I've never used npm/node. I would love to use this library for my browser app. Could you give me some hints how I can get this library into pure javascript thats runnable in any browser? Or just pass me some built .js files ;)?
Greetings Florian
Hi
Is it possible to compose models without having to specify them as a JSONAPI relationship?
Thanks
Ben
I think this aligns with our values:
I believe it requires an email address in case community members need to get ahold of someone.
thoughts?
Hello,
First of all, I thanks for your DEVOUR.
devour json api is a great package, I think. I've seen all approaches in the JavaScript client implementations but jsonapi-datastore and json-api-store are a little useful and the others not.
Finally, I 've determined to use your package DEVOUR.
it works fine so far. but one issue.
In my database, there is "categories" table and it represents both category and subcategory using parent_id field(Arc Model).
and with ruby on rails, I've built JSON API Server.
when hits the url http://192.168.0.124:3003/api/v1/categories?include="sub-categories", it returns as follows. ( "id" : "1", category, in the sub-categories section, it has sub categories information)
{
"data": [
{
"id": "1",
"type": "categories",
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/1"
},
"attributes": {
"name": "Cat1",
"category-type": 0,
"sort": 1,
"deleted": false,
"created-at": "2017-07-31T10:48:48.000Z",
"updated-at": "2017-07-31T10:48:50.000Z"
},
"relationships": {
"sub-categories": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/1/relationships/sub-categories",
"related": "http://192.168.0.124:3003/api/v1/categories/1/sub-categories"
},
"data": [
{
"type": "categories",
"id": "3"
},
{
"type": "categories",
"id": "4"
}
]
},
"parent": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/1/relationships/parent",
"related": "http://192.168.0.124:3003/api/v1/categories/1/parent"
}
},
"items": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/1/relationships/items",
"related": "http://192.168.0.124:3003/api/v1/categories/1/items"
}
}
}
},
{
"id": "2",
"type": "categories",
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/2"
},
"attributes": {
"name": "Cat2",
"category-type": 0,
"sort": 2,
"deleted": false,
"created-at": "2017-07-31T11:21:14.000Z",
"updated-at": "2017-07-31T11:21:15.000Z"
},
"relationships": {
"sub-categories": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/2/relationships/sub-categories",
"related": "http://192.168.0.124:3003/api/v1/categories/2/sub-categories"
},
"data": []
},
"parent": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/2/relationships/parent",
"related": "http://192.168.0.124:3003/api/v1/categories/2/parent"
}
},
"items": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/2/relationships/items",
"related": "http://192.168.0.124:3003/api/v1/categories/2/items"
}
}
}
},
{
"id": "3",
"type": "categories",
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/3"
},
"attributes": {
"name": "Sub Cat1",
"category-type": 1,
"sort": 1,
"deleted": false,
"created-at": "2017-07-31T11:27:21.000Z",
"updated-at": "2017-07-31T11:27:22.000Z"
},
"relationships": {
"sub-categories": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/3/relationships/sub-categories",
"related": "http://192.168.0.124:3003/api/v1/categories/3/sub-categories"
},
"data": []
},
"parent": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/3/relationships/parent",
"related": "http://192.168.0.124:3003/api/v1/categories/3/parent"
}
},
"items": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/3/relationships/items",
"related": "http://192.168.0.124:3003/api/v1/categories/3/items"
}
}
}
},
{
"id": "4",
"type": "categories",
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/4"
},
"attributes": {
"name": "Sub Cat2",
"category-type": 1,
"sort": 1,
"deleted": false,
"created-at": "2017-07-31T11:27:54.000Z",
"updated-at": "2017-07-31T11:27:55.000Z"
},
"relationships": {
"sub-categories": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/4/relationships/sub-categories",
"related": "http://192.168.0.124:3003/api/v1/categories/4/sub-categories"
},
"data": []
},
"parent": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/4/relationships/parent",
"related": "http://192.168.0.124:3003/api/v1/categories/4/parent"
}
},
"items": {
"links": {
"self": "http://192.168.0.124:3003/api/v1/categories/4/relationships/items",
"related": "http://192.168.0.124:3003/api/v1/categories/4/items"
}
}
}
}
]
}
and in the client side,
this.jsonApi.define('category',{
name: '',
categoryType: '',
sort: '',
deleted: '',
createdAt: '',
updatedAt: '',
items:{
jsonApi: 'hasMany',
type: 'items'
},
subCategories:{
jsonApi: 'hasMany',
type: 'categories'
},
parent:{
jsonApi: 'hasOne',
type: 'category'
}
})
and when I call below function it returns unexpected results.
this.jsonApi.findAll('category', {include: ['sub-categories']})
[{
id: '1',
type: 'categories',
name: 'Cat1',
categoryType: 0,
sort: 1,
deleted: false,
createdAt: '2017-07-31T10:48:48.000Z',
updatedAt: '2017-07-31T10:48:50.000Z',
subCategories: [],
parent: null,
items: [],
links: { self: 'http://192.168.0.124:3003/api/v1/categories/1' }
},
{
id: '2',
type: 'categories',
name: 'Cat2',
categoryType: 0,
sort: 2,
deleted: false,
createdAt: '2017-07-31T11:21:14.000Z',
updatedAt: '2017-07-31T11:21:15.000Z',
subCategories: [],
parent: null,
items: [],
links: { self: 'http://192.168.0.124:3003/api/v1/categories/2' }
},
{
id: '3',
type: 'categories',
name: 'Sub Cat1',
categoryType: 1,
sort: 1,
deleted: false,
createdAt: '2017-07-31T11:27:21.000Z',
updatedAt: '2017-07-31T11:27:22.000Z',
subCategories: [],
parent: null,
items: [],
links: { self: 'http://192.168.0.124:3003/api/v1/categories/3' }
},
{
id: '4',
type: 'categories',
name: 'Sub Cat2',
categoryType: 1,
sort: 1,
deleted: false,
createdAt: '2017-07-31T11:27:54.000Z',
updatedAt: '2017-07-31T11:27:55.000Z',
subCategories: [],
parent: null,
items: [],
links: { self: 'http://192.168.0.124:3003/api/v1/categories/4' }
}]
as you can see, it doesn't take sub categories from server.
what's missing? and wrong?
Hope your help.
Best Regards.
Per API spec here: http://jsonapi.org/format/#crud-updating-to-many-relationships
hasMany relationships can be bound via a POST action to the relationship URL:
implementation example (this is a sync action which adds all available 'devices' to a 'project')
addDevicesToProject() {
this.startEvent();
return new Promise((resolve, reject) => {
//const create = [];
const create = this.availableDevices.map((device) => {
return {type: 'devices', id: device.id}
});
JsonApi.one('project', this.project.id).all('device').post(create)
.then((responses) => {
this.successEvent(responses);
console.log('addDevices', responses);
resolve(responses);
})
.catch((error) => {
this.errorEvent(error);
reject(error);
});
});
}
In the above, the "create" const is prepared with an array of relationship objects.
The prepared payload is:
{"data":[{"type":"devices","attributes":{},"id":"27"},{"type":"devices","attributes":{},"id":"28"}],"meta":{}}
The 'attributes' fields are unnecessary and cause problems.
I am testing with a version 2.0.3.
We are trying to use this in browser using browserify looks like its fails in IE with Object.assign is not defined.
e.g. src\middleware\json-api\req-headers.js
By looking at the code it seems there is no way of doing this, but I thought I would ask: is there any way of silencing the console
statements in the code of this library?
JSON API's responses look like:
{
data: [...],
links: {...},
meta: {...}
}
Devour ends up storing the links
and meta
information as properties on the data
array:
{
data: [
...,
links: {...},
meta: {...}
]
}
Since storing properties on arrays isn't very conventional I've found it can lead to unpredictable results.
One such instance of this unpredictable behaviour is with Lodash's cloneDeep
method, which ends up removing these array properties entirely.
So jsonApi let's you include nested relationships like /author?include=comments,comments.author
Questions can devour accommodate this, and if so how would I define my model? I'd expect something like:
{
'comments': {
'type': 'comments',
'jsonApi': 'hasMany'.
'author': {
'type': 'users',
'jsonApi': 'hasOne'
}
}
}
I've tried that but doesn't seem to work, if anyone could shed some light?
thanks
Some version of IE doesn't like console log when the developer tool isn't open.
I suggest we either use a library that is browser + server compatible OR stub out our own console log.
Deserializer converts attribute names from "kebab-case" to camel case when fetching data; on the way back, the serializer does nothing. JSONAPI spec recommends kebab-case, I believe.
So, for example, my API returns { client_id: "1" }, but when asked, devour updates the API with { clientId: "1" }.
Further, there is no way to force devour to send attributes dasherized. E.g. $jsapi.update('matter', { id: "2864", 'client_id': '1'})
will not work.
Deserialize: https://github.com/twg/devour/blob/master/src/middleware/json-api/_deserialize.js#L46
Serialize: https://github.com/twg/devour/blob/master/src/middleware/json-api/_serialize.js#L27
Since GET and DELETE are not required to have bodies per the JSON API spec, having even an empty JSON object for the body can cause some servers to not respond properly.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.