Calling JsonApi.request() does not work
When making a custom request, at least while making a POST request, there are multiple issues. One is avoidable with some hacking but the other renders the function useless.
When a request goes through the req-post middleware, it makes the following call serialize.resource.call(jsonApi, payload.req.model, payload.req.data). From here, it enters _serialize.js where the issues are based.
-
Since we are making a custom request,
modelNameisundefinedat this point so making this callthis.pluralize(modelName)on line 13 leads to an exception being thrown. This, I was able to avoid by changing the pluralize option on the JsonApi instance just before making the request, and changing it back after. -
Since we are making a custom request, there is no model and
this.modelFor(modelName)returns an empty model. Because of this, on line 20, when the data for the request is supposed to be added to theserializedAttributesvariable nothing is added and no data is added to the POST request. Unfortunately, I was unable to find a work-around for this.
I can confirm this. There is a workaround by using runMiddleware directly, but this doesn't seem clean since runMiddleware sounds more like internal API.
jsonApi.runMiddleware({url: '...', method: 'POST', params: {}, data: {...}, model: 'yourmodelname'}).then(...)
So I think jsonApi.request(...) should get an additional argument 'model'.
Can you please elaborate on what 'custom request' is? Is it possible that you provide an example for this, or even better - add s test use case in the devour package, that is expected to pass but breaks?
Hi @tomers, I faced the same issue today. I think @Josta is referring to the "arbitrary" requests that's documented in the readme.
Below is the code I am trying to run
import JsonApi from 'devour-client';
export const api = new JsonApi({apiUrl: 'http://192.168.1.235:3000/'})
let user = api.define('user', {
email: '',
password: '',
token: ''
}, {
readOnly: ['token']
})
api.request('/users/signup', 'POST', {}, {data: {type: "users",attributes: {email: email,password: password}}, "meta": {}})
When I run this, I get the following error
devour error [Error: API resource definition for model "undefined" not found. Available models: user]
Let me know if you need more information.
I also ran into this exact same issue today. Any updates on this?
This seems like an issue with the deserializer not understanding what model to use. We could add a model parameter to the request function. AFAIK request is intended to be used externally (ie. it's not a "private" function).
When you say externally, do you mean a different API than the one being targeted by the models?
I would say request should take a model name as parameter and be a part of the model ecosystem of devour.
If someone wants to make an external request they can just use axios directly.
@Auspicus are you the only contributor at the moment?
That's a good point about clarifying "external". I think maybe this language in the readme is a bit confusing:
// To make arbitrary requests through the middleware stack
jsonApi.request('https://example.com', 'GET', { a_query_param: 3 }, { some_payload_item: 'blah' })
Both the comment and the code could be interpreted as being able to use any endpoint 🤷♂
@daure Myself and @tomers are taking care of this project at the moment. I'm able to merge pull requests and deploy to npm but don't have the throughput to contribute my own code.
I see two ways of solving this.
Either encouraging developers to always use the API methods, eg. find, findAll by making the request function internal only (could use new ES6 Symbols or simply prefix with _ to signify private function, and remove from documentation).
OR
Committing to the function being used externally and adding a parameter to tell the request function what model it is fetching.
FWIW you can access the underlying axios client using jsonApi.axios
Thanks, I think we will just used vanillar axios and transform the data ourselves in the cases where find/findAll/etc. doesn't map well to our endpoint URL structure.
@Auspicus or @daure is there any update on this bug/request? Do you guys anticipate resolving it in the near future. To me this is a fairly common problem. In our company we leverage the JSON api to create standardized structures for communicating between the front end and back end. Sometimes we need to make slight deviations from the JSON api standard for business reasons. One of the things that drew me to this library was the ease of use and lack of opinion about how the data models work after the request has responded. Additionally, I'll echo that when I read:
// To make arbitrary requests through the middleware stack
jsonApi.request('https://example.com', 'GET', { a_query_param: 3 }, { some_payload_item: 'blah' })
I expected to be able to make one-off requests. Not necessarily to another api, but to our own api where we chose to break the JSON api standard (or in the case of legacy code; non JSON api end points).
Let me know if there is anything I can do to help flesh out the exact requirements around this. I believe that this library should be able to make one-off requests for the purpose of flexibility and understanding that not all endpoints in a real life company will be built to JSON api standard.
Thanks again for this robust library. Here to help. Sebastian Kline
#208