devour-js / devour-client

Don't just consume your JSON API, Devour it...
https://www.npmjs.com/package/devour-client
ISC License
429 stars 89 forks source link

Optionally do not attach relationship metadata on unresolved includes #263

Open ibustosatlegalzoom opened 4 months ago

ibustosatlegalzoom commented 4 months ago

Source of the problem

A JSON:API response may not resolve a relationship correctly and fail to include it in the "includes" section. In Drupal's JSON:API implementation for instance, an entity may not be resolved if a user has no permissions to access such object.

Example response:

{
   "jsonapi":{
      "version":"1.0",
      "meta":{
         "links":{
            "self":{
               "href":"http:\/\/jsonapi.org\/format\/1.0\/"
            }
         }
      }
   },
   "data":{
      "type":"article_category",
      "id":"9d937365-490b-4f5e-96f3-3b3cc57f9098",
      "links":{
         "self":{
            "href":"http:\/\/localhost:8080\/api\/article_categories\/9d937365-490b-4f5e-96f3-3b3cc57f9098?resourceVersion=id%3A663"
         }
      },
      "relationships":{
         "recommended_articles":{
            "data":[
               {
                  "type":"article",
                  "id":"bfe14d24-50a5-45ce-9602-fc74dd6fe23a",
                  "meta":{
                     "drupal_internal__target_id":7357
                  }
               }
            ],
            "links":{
               "related":{
                  "href":"http:\/\/localhost:8080\/api\/article_categories\/9d937365-490b-4f5e-96f3-3b3cc57f9098\/recommended_articles?resourceVersion=id%3A663"
               },
               "self":{
                  "href":"http:\/\/localhost:8080\/api\/article_categories\/9d937365-490b-4f5e-96f3-3b3cc57f9098\/relationships\/recommended_articles?resourceVersion=id%3A663"
               }
            }
         }
      }
   },
   "meta":{
      "omitted":{
         "detail":"Some resources have been omitted because of insufficient authorization.",
         "links":{
            "help":{
               "href":"https:\/\/www.drupal.org\/docs\/8\/modules\/json-api\/filtering#filters-access-control"
            },
            "item--VtXH6qK":{
               "href":"http:\/\/localhost:8080\/api\/articles\/bfe14d24-50a5-45ce-9602-fc74dd6fe23a",
               "meta":{
                  "rel":"item",
                  "detail":"The current user is not allowed to GET the selected resource. The \u0027view any unpublished content\u0027 permission is required."
               }
            }
         }
      }
   },
   "links":{
      "self":{
         "href":"http:\/\/localhost:8080\/api\/article_categories\/9d937365-490b-4f5e-96f3-3b3cc57f9098?fields%5Barticle_category%5D=recommended_articles\u0026include=recommended_articles"
      }
   }
}

Notice that the "included" section is nowhere to be found in the response.

Problem

With this, the output of the following lines of code

jsonApi.define('article', {
  'title': '',
})
jsonApi.define('article_category', {
  'title': '',
  'recommended_articles': {
    jsonApi: 'hasMany',
    type: 'article',
  }
})
jsonApi.find('article_category', '9d937365-490b-4f5e-96f3-3b3cc57f9098', {
  include: 'recommended_articles'
})
  .then(response => {
    console.log(response.data.recommended_articles)
  })

will be:

[
   {
      "type":"article",
      "id":"bfe14d24-50a5-45ce-9602-fc74dd6fe23a",
      "meta":{
         "drupal_internal__target_id":7357
      }
   }
]

This effectively includes relationship metadata but it doesn't include any of the fields related to the related entity as it was not resolved by the backend. This may be fine for some implementations but for others, it makes it difficult to do parsing/validation. For those scenarios, the recommended_articles attribute should be represented as an empty array instead.

Proposal

Optionally allow users to opt out of having relationship metadata when includes are not resolved by the backend.