Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(#71): add getRelated() method #202

Merged
merged 3 commits into from
Oct 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/small-snakes-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"druxt": minor
---

Added getRelated() method
32 changes: 32 additions & 0 deletions packages/druxt/src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,38 @@ class DruxtClient {
return this.index
}

/**
* Get the related resources from a specified JSON:API resource.
*
* @example @lang js
* const related = this.$druxt.getRelated('node--page', id, 'uid')
*
* @param {string} type - The JSON:API Resource type.
* @param {string} id - The Drupal resource UUID.
* @param {string} related - The relationship name.
* @param {DruxtClientQuery} [query] - A correctly formatted JSON:API query string or object.
*
* @returns {object} The related JSON:API resource(s).
*/
async getRelated(type, id, related, query) {
if (!id || !type || !related) {
return false
}

let { href } = await this.getIndex(type)
if (!href) {
href = this.options.endpoint + '/' + type.replace('--', '/')
}

const url = this.buildQueryUrl(`${href}/${id}/${related}`, query)
try {
const related = await this.axios.get(url)
return related.data
} catch (e) {
return false
}
}

/**
* Get a JSON:API resource by type and ID.
*
Expand Down
17 changes: 17 additions & 0 deletions packages/druxt/test/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,23 @@ describe('DruxtClient', () => {
expect(cachedResourceIndex).toHaveProperty('href')
})

test('getRelated', async () => {
expect((await druxt.getRelated())).toBe(false)

const mockArticle = await getMockResource('node--article')

const { type, id } = mockArticle.data
const related = await druxt.getRelated(type, id, 'field_media_image')
expect(mockAxios.get).toHaveBeenCalledWith(`${baseUrl}/en/jsonapi/node/article/${id}/field_media_image`)
expect(related.data).toHaveProperty('type')

try {
await druxt.getRelated('node--fake', id, 'field_media_image')
} catch(err) {
expect(mockAxios.get).toHaveBeenCalledWith(`/jsonapi/node/fake/${id}/field_media_image`)
}
})

test('getResource', async () => {
const mockArticle = await getMockResource('node--article')
const entity = await druxt.getResource(mockArticle.data.type, mockArticle.data.id)
Expand Down
7 changes: 7 additions & 0 deletions packages/router/test/router.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,5 +235,12 @@ describe('DruxtRouter', () => {
route = await router.getRoute('/node/1')

expect(route).toHaveProperty('isHomePath', false)

try {
await router.getRoute('/error')
} catch(err) {
expect(err.response.status).toBe(404)
expect(err.response.data.message).toBe('Unable to resolve path /error.')
}
})
})
157 changes: 157 additions & 0 deletions test/__fixtures__/get/080ff38ba635ce6e565912bb104ad858.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
{
"data": {
"jsonapi": {
"version": "1.0",
"meta": {
"links": {
"self": {
"href": "http://jsonapi.org/format/1.0/"
}
}
}
},
"data": {
"type": "media--image",
"id": "201869c2-0cc4-405a-b596-93f488a48316",
"links": {
"self": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316?resourceVersion=id%3A10"
}
},
"attributes": {
"drupal_internal__mid": 10,
"drupal_internal__vid": 10,
"langcode": "en",
"revision_created": "2021-05-01T06:24:09+00:00",
"revision_log_message": null,
"status": true,
"name": "Home Grown Herbs",
"created": "2021-05-01T06:24:09+00:00",
"changed": "2021-05-01T06:24:09+00:00",
"default_langcode": true,
"revision_translation_affected": true,
"path": {
"alias": null,
"pid": null,
"langcode": "en"
},
"content_translation_source": "und",
"content_translation_outdated": false
},
"relationships": {
"field_media_image": {
"data": {
"type": "file--file",
"id": "515d2bee-d29a-4bcb-a4ac-70b2c4faa5e3",
"meta": {
"alt": "Fresh cut herbs including mint, parsley, thyme and dill",
"title": null,
"width": 768,
"height": 512
}
},
"links": {
"related": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/field_media_image?resourceVersion=id%3A10"
},
"self": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/relationships/field_media_image?resourceVersion=id%3A10"
}
}
},
"bundle": {
"data": {
"type": "media_type--media_type",
"id": "93c226a8-6e72-4caf-aae5-493066ef4f94"
},
"links": {
"related": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/bundle?resourceVersion=id%3A10"
},
"self": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/relationships/bundle?resourceVersion=id%3A10"
}
}
},
"revision_user": {
"data": null,
"links": {
"related": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/revision_user?resourceVersion=id%3A10"
},
"self": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/relationships/revision_user?resourceVersion=id%3A10"
}
}
},
"uid": {
"data": {
"type": "user--user",
"id": "f9e06c84-0999-4123-b1f1-b46b18590be4"
},
"links": {
"related": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/uid?resourceVersion=id%3A10"
},
"self": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/relationships/uid?resourceVersion=id%3A10"
}
}
},
"thumbnail": {
"data": {
"type": "file--file",
"id": "515d2bee-d29a-4bcb-a4ac-70b2c4faa5e3",
"meta": {
"alt": "Fresh cut herbs including mint, parsley, thyme and dill",
"title": null,
"width": 768,
"height": 512
}
},
"links": {
"related": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/thumbnail?resourceVersion=id%3A10"
},
"self": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/media/image/201869c2-0cc4-405a-b596-93f488a48316/relationships/thumbnail?resourceVersion=id%3A10"
}
}
}
}
},
"links": {
"self": {
"href": "https://demo-api.druxtjs.org/en/jsonapi/node/article/e4ced3c1-e14b-48f1-8c0a-c909e808de68/field_media_image"
}
}
},
"status": 200,
"statusText": "OK",
"headers": {
"content-type": "application/vnd.api+json",
"cache-control": "must-revalidate, no-cache, private",
"content-language": "en",
"expires": "Sun, 19 Nov 1978 05:00:00 GMT"
},
"config": {
"url": "https://demo-api.druxtjs.org/en/jsonapi/node/article/e4ced3c1-e14b-48f1-8c0a-c909e808de68/field_media_image",
"method": "get",
"headers": {
"Accept": "application/json, text/plain, */*"
},
"baseURL": "https://demo-api.druxtjs.org",
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1
},
"request": {}
}
31 changes: 31 additions & 0 deletions test/__fixtures__/get/5bee0d1fd2e0ecabbfae045266e65729.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"data": "<!DOCTYPE html>\n<html lang=\"en\" dir=\"ltr\" prefix=\"content: http://purl.org/rss/1.0/modules/content/ dc: http://purl.org/dc/terms/ foaf: http://xmlns.com/foaf/0.1/ og: http://ogp.me/ns# rdfs: http://www.w3.org/2000/01/rdf-schema# schema: http://schema.org/ sioc: http://rdfs.org/sioc/ns# sioct: http://rdfs.org/sioc/types# skos: http://www.w3.org/2004/02/skos/core# xsd: http://www.w3.org/2001/XMLSchema# \">\n <head>\n <meta charset=\"utf-8\" />\n<meta name=\"Generator\" content=\"Drupal 9 (https://www.drupal.org)\" />\n<meta name=\"MobileOptimized\" content=\"width\" />\n<meta name=\"HandheldFriendly\" content=\"true\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<link rel=\"shortcut icon\" href=\"/core/profiles/demo_umami/themes/umami/favicon.ico\" type=\"image/vnd.microsoft.icon\" />\n\n <title>Page not found | Drupal</title>\n <link rel=\"stylesheet\" media=\"all\" href=\"/sites/default/files/css/css_DWtrEQx8SQyouvUgYmZ2aOY0oPzZuIyHjIpC7PdW0IQ.css\" />\n<link rel=\"stylesheet\" media=\"all\" href=\"/sites/default/files/css/css_xgOCZkTn7w-n_AH3WZoEL04KfMY94GvEqDKfm0D7Kms.css\" />\n<link rel=\"stylesheet\" media=\"all\" href=\"/sites/default/files/css/css_YAVGA7Afc09503_MRf-aV4oyQQ9EH-infM-F3O_HHdE.css\" />\n\n <script src=\"/themes/contrib/gin/dist/js/gin_init.js?v=9.1.7\"></script>\n<script src=\"/core/assets/vendor/modernizr/modernizr.min.js?v=3.8.0\"></script>\n<script src=\"/core/misc/modernizr-additional-tests.js?v=3.8.0\"></script>\n\n </head>\n <body data-gin-accent=\"blue\" class=\"path-jsonapi\">\n <a href=\"#main-content\" class=\"visually-hidden focusable skip-link\">\n Skip to main content\n </a>\n \n <div class=\"page-wrapper dialog-off-canvas-main-canvas\" data-off-canvas-main-canvas>\n \n<div class=\"region region-meta layout-container\">\n <div class=\"breadcrumb-wrapper\">\n <div class=\"region region-breadcrumb\">\n <div id=\"block-gin-breadcrumbs\" class=\"block block-system block-system-breadcrumb-block\">\n \n \n <nav class=\"breadcrumb\" role=\"navigation\" aria-labelledby=\"system-breadcrumb\">\n <h2 id=\"system-breadcrumb\" class=\"visually-hidden\">Breadcrumb</h2>\n <ol class=\"breadcrumb__list\">\n <li class=\"breadcrumb__item\">\n <a href=\"/en\" class=\"breadcrumb__link\">Home</a>\n </li>\n <li class=\"breadcrumb__item\">\n <a href=\"/en/jsonapi\" class=\"breadcrumb__link\">Jsonapi</a>\n </li>\n </ol>\n </nav>\n\n </div>\n\n</div>\n\n </div>\n \n</div>\n\n<header class=\"region region-sticky\">\n <div class=\"layout-container region-sticky__items\">\n <div id=\"block-gin-page-title\" class=\"block block-core block-page-title-block\">\n \n \n \n <h1 class=\"page-title\">Page not found</h1>\n\n\n </div>\n\n \n </div>\n</header>\n\n<div class=\"content-header clearfix\">\n <div class=\"layout-container\">\n \n\n </div>\n</div>\n\n<div class=\"sticky-shadow\"></div>\n\n<div class=\"layout-container\">\n \n\n <main class=\"page-content clearfix\" role=\"main\">\n <div class=\"visually-hidden\"><a id=\"main-content\" tabindex=\"-1\"></a></div>\n \n <div class=\"region region-highlighted\">\n <div data-drupal-messages-fallback class=\"hidden messages-list\"></div>\n\n </div>\n\n <div class=\"help\">\n \n\n </div>\n \n <div class=\"region region-content\">\n <div id=\"block-gin-content\" class=\"block block-system block-system-main-block\">\n \n \n The requested page could not be found.\n </div>\n\n </div>\n\n </main>\n</div>\n\n </div>\n\n \n <script type=\"application/json\" data-drupal-selector=\"drupal-settings-json\">{\"path\":{\"baseUrl\":\"\\/\",\"scriptPath\":null,\"pathPrefix\":\"en\\/\",\"currentPath\":\"\",\"currentPathIsAdmin\":false,\"isFront\":false,\"currentLanguage\":\"en\"},\"pluralDelimiter\":\"\\u0003\",\"suppressDeprecationErrors\":true,\"search_api_lunr\":{\"servers\":{\"druxt\":{\"indexes\":{\"default\":{\"fileList\":[\"https:\\/\\/demo-api.druxtjs.org\\/sites\\/default\\/files\\/search-api-js\\/druxt\\/default\\/index-0.json\",\"https:\\/\\/demo-api.druxtjs.org\\/sites\\/default\\/files\\/search-api-js\\/druxt\\/default\\/index-1.json\",\"https:\\/\\/demo-api.druxtjs.org\\/sites\\/default\\/files\\/search-api-js\\/druxt\\/default\\/index-2.json\",\"https:\\/\\/demo-api.druxtjs.org\\/sites\\/default\\/files\\/search-api-js\\/druxt\\/default\\/index-3.json\",\"https:\\/\\/demo-api.druxtjs.org\\/sites\\/default\\/files\\/search-api-js\\/druxt\\/default\\/index-4.json\"],\"fields\":{\"body\":{\"boost\":1},\"field_ingredients\":{\"boost\":1},\"field_recipe_category\":{\"boost\":1},\"field_recipe_instruction\":{\"boost\":1},\"title\":{\"boost\":1,\"special_type\":\"label\"},\"type\":{\"boost\":1},\"url\":{\"boost\":1,\"special_type\":\"url\"},\"uuid\":{\"boost\":1}},\"version\":1}}}}},\"gin\":{\"darkmode\":false,\"darkmode_class\":\"gin--dark-mode\",\"preset_accent_color\":\"blue\",\"accent_color\":null,\"preset_focus_color\":\"gin\",\"focus_color\":null,\"highcontrastmode\":false,\"highcontrastmode_class\":\"gin--high-contrast-mode\",\"accent_css_path\":\"https:\\/\\/demo-api.druxtjs.org\\/enthemes\\/contrib\\/gin\\/dist\\/css\\/gin_accent.css\",\"ckeditor_css_path\":\"https:\\/\\/demo-api.druxtjs.org\\/enthemes\\/contrib\\/gin\\/dist\\/css\\/gin_ckeditor.css\",\"default_darkmode\":false,\"default_accent_color\":null,\"default_preset_accent_color\":\"blue\",\"default_high_contrast_mode\":false},\"user\":{\"uid\":0,\"permissionsHash\":\"7751d387c0ded69281679aaedf9a31a37d3ebab4fca9c9ec5a0ccf9ef12c5421\"}}</script>\n<script src=\"/sites/default/files/js/js_N_CyDjS0-4iXXLXDxhQLcLV2Fx9Yc007XbHQk7LQ9TE.js\"></script>\n<script src=\"/modules/contrib/search_api_lunr/js/build/api.index.js?0\" type=\"module\"></script>\n<script src=\"/sites/default/files/js/js_GdkMuOxaZcCe7IbJWSnmwDIHyceuKfn_7Ugv6N-B44k.js\"></script>\n\n </body>\n</html>\n",
"status": 404,
"statusText": "Not Found",
"headers": {
"content-type": "text/html; charset=UTF-8",
"cache-control": "must-revalidate, no-cache, private",
"content-language": "en",
"expires": "Sun, 19 Nov 1978 05:00:00 GMT"
},
"config": {
"url": "/jsonapi/node/fake/e4ced3c1-e14b-48f1-8c0a-c909e808de68/field_media_image",
"method": "get",
"headers": {
"Accept": "application/json, text/plain, */*"
},
"baseURL": "https://demo-api.druxtjs.org",
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1
},
"request": {}
}
Loading