noahzgordon / elm-jsonapi Goto Github PK
View Code? Open in Web Editor NEWdecoders and helper functions for handling JSON API compliant server payloads
License: MIT License
decoders and helper functions for handling JSON API compliant server payloads
License: MIT License
We should support supplying an array of "included" resources for all of our query methods.
We should also handle the 400 Bad Request
response code when an endpoint does support resource inclusion
They should be moved into a separate module, perhaps JsonApi.Data.
Having spoken to @noahzgordon there already seems good support for traversing the side-loaded resources. It would be great to have a couple of examples demonstrating how this works.
According to the spec, the document's primary data may be one or many resource identifiers. We do not support this currently; we always represent the primary data as a fully-structure resource object. See: http://jsonapi.org/format/#document-top-level
I'm having trouble with the following jsonapi document.
{
"included": [
{
"type": "org",
"relationships": {
"members": {
"links": {
"related": "/api/orgs/1/members"
}
}
}
}
]
}
Decoding fails because some of the relationships do not contain a data attribute. I'm not entirely sure that this is "valid" json-api, but it seems to work with other json-api libraries.
Use the resource's self link to reload the resource's properties
version and any meta information
Right now we only support the decoding of the primary resource and its links. The spec also supports metadata and links at the top level of the document. See: http://jsonapi.org/format/#document-top-level
The code is updated to Elm 0.19, but the README still uses Json.Decode
's (:=)
, an old version of Http.get
, and backtick syntax.
I'm still trying to figure out how to use the library, but when I do, I might create a PR for this, unless someone (hopefully) beats me to it
In the case that two resources have references to one another, the decoder will break as it tries to recur infinitely. We should figure out a way to be smart about this and have the two resources reference one another without looping infinitely
relatedResource
should have a distinct result for the case that the resource can't be found in the included resources:
relatedResource : String -> Resource -> Result String (Maybe Resource)
I'm writing some an admin frontend over the top of a jsonapi backend. As part of this, I need to be able to make updates to some models via http patch. One of the requirements of a jsonapi patch is:
The PATCH request MUST include a single resource object as primary data. The resource object MUST contain type and id members.
However, elm-jsonapi doesn't seem to provide a way to set an ID on data to be sent to the server. The only method in JsonApi.Encode
is clientResource
, and there is no way to set a non-UUID ID on a ClientResource
.
relatedResource
and relatedResourceCollection
return resources side-loaded in the include
part of a compound document. The documentation should probably make a clear statement about this.
The Resource data type should be publicly exposed to the end user. Therefore it should be an opaque data type. See: http://package.elm-lang.org/help/design-guidelines#keep-tags-and-record-constructors-secret
Current implementation: type alias Resource = { record }
Desired implementation: type Resource = Resource ResourceId ResourceObject
When you start with more complex endpoints, you end up concatting strings to URLs quite heavily.
It would be kinda nice to have a type safe URL builder specific for jsonapi.
Just some idea what kind of data structures could be useful (Note: this is still in flow for my own project)
module App.JsonApiHelper exposing (..)
type alias Url =
{ path : String
, filter : Maybe (List Filter)
, include : Maybe (List Include)
, field : Maybe (List Field)
, sort : Maybe (List Sort)
, pager : Maybe (List Pager)
}
url : String -> Url
url path =
Url
{ path = path
, filter = Nothing
, include = Nothing
, field = Nothing
, sort = Nothing
, pager = Nothing
}
withFilter : Filter -> Url -> Url
withFilter filter url =
{ url
| filter =
Maybe.map url.filter
|> (::) filter
}
withInclude : Include -> Url -> Url
withInclude include url =
{ url
| include =
Maybe.map url.include
|> (::) include
}
withField : Field -> Url -> Url
withField field url =
{ url
| field =
Maybe.map url.field
|> (::) field
}
withSort : Sort -> Url -> Url
withSort sort url =
{ url
| sort =
Maybe.map url.sort
|> (::) sort
}
withPager : Pager -> Url -> Url
withPager pager url =
{ url
| pager =
Maybe.map url.pager
|> (::) pager
}
type alias Sort =
{ keys : List String
, direction : SortDirection
}
type SortDirection
= ASC
| DESC
sortAsc : String -> Sort
sortAsc string =
{ keys = [ string ]
, direction = ASC
}
sortDesc : String -> Sort
sortDesc string =
{ keys = [ string ]
, direction = DESC
}
sortAscWithPath : List String -> Sort
sortAscWithPath keys =
{ keys = keys
, direction = ASC
}
sortDescWithPath : List String -> Sort
sortDescWithPath keys =
{ keys = keys
, direction = DESC
}
type alias Filter =
{ keys : List String
, operator : Maybe String
, value : String
}
filter : List String -> String -> Filter
filter keys value =
{ keys = keys
, operator = Nothing
, value = value
}
type Include
= Meh2
type Field
= Meh3
type Pager
= PagerNumber Int
| PagerSize Int
| PagerOffset Int
| PagerLimit Int
| PagerCursor Int
So that the use doesn't have to destructure the Resource
If an error appears at the top level of the document, we should return an appropriate error type containing the errors (which take the form of an array). We should define our own error type which wraps an array of string as well.
Right now we only support link strings. We should figure out a sane way to handle link objects, which capture meta information in addition to an href. See: http://jsonapi.org/format/#document-links
Perhaps something like this?
type alias Link = { href : String, meta : Maybe Value }
404 Not Found in response to one of our query methods means that the server is not responding correctly.
Let's make a custom error type for this situation.
http://jsonapi.org/format/#fetching-resources-responses-404
Use relationship links to load a resource that is not yet loaded. This resource should include references to the original resource and any related resources.
I'm creating this as a ticket related to noahzgordon/elm-jsonapi-http#2
I looked at this last night, and one of the things ran into is that the shape of data for creating a resource with a json api.
From the json api spec doc, a create should look like this:
POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "photos",
"attributes": {
"title": "Ember Hamster",
"src": "http://example.com/images/productivity.png"
},
"relationships": {
"photographer": {
"data": { "type": "people", "id": "9" }
}
}
}
}
Some differences
There are more, though.
I'm feeling that the JSON api spec is a little unclear/ambiguous in places, especially for creating/updating resources.
Relationships should be able to store meta information. We might already have this?
Use the resource's self link to update the resource using a PUT request and reload its attributes
If one of the included resources has a relationship to the primary resource, it will not be hydrated correctly
Eliminate a ton of boilerplate by creating a function to fetch a related resource given another resource. Right now this is pretty cumbersome for the user to handle.
Hi,
I want to do some testing on my update function and it is kind of weird to test it when my model use a JsonApi.Resource
as one of its field.
Let say, my model is
type alias Model =
{ vehicle : JsonApi.Resource
}
Here is how I make my test
suite : Test
suite =
let
vehicle =
decodeString
JsonApi.Decode.document
"""{"data": {"type": "vehicle", "id": "1"}}"""
|> Result.andThen JsonApi.Documents.primaryResource
in
describe "Internal update function"
(case vehicle of
Err err ->
[ test "Couldn't create JsonApi.Resource" <| \_ -> Expect.fail err ]
Ok vehicle ->
let
model = { vehicle = vehicle }
in
[ test "NoOp should not change the model" <|
\_ ->
model
|> Main.update Main.NoOp
|> Tuple.first
|> Expect.equal model
]
)
It seems awkward to have a case of
in my tests and to manage the error case when I clearly know what I have in input. And I feel that I'm kind of abusing the test in my error case.
Is there something I missed, or a cleaner way of doing that?
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.