Skip to content

Commit 62fd2ea

Browse files
committed
Add includes to writeRelated methods (configurable).
1 parent b5a11df commit 62fd2ea

File tree

7 files changed

+74
-6
lines changed

7 files changed

+74
-6
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,8 @@ For many of these options, more information is provided in the [Usage](#usage) s
771771
- `cleanPatchProps` - If cleanPatch is enabled, an array of `_jv` properties that should be preserved - `links`, `meta`, and/or `relationships`. (defaults to `[]`).
772772
- `recurseRelationships` - If `false`, replaces recursive relationships with a normalised resource identifier (i.e `{ _jv: { type: 'x', id: 'y' } }`). (defaults to `false`).
773773
- `maxStatusID` - Sets the highest status ID that will be used in `status` before rolling round to 1 again. (defaults to `-1` - no limit).
774+
- `relatedIncludes` - When returning the original object from `patch|post|deleteRelated` methods, also include related objects (defaults to `true`).
775+
774776

775777
## Endpoints
776778

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jsonapi-vuex",
3-
"version": "5.9.1",
3+
"version": "5.10.0",
44
"description": "Access restructured JSONAPI data from a Vuex Store.",
55
"author": "Matthew Richardson <[email protected]>",
66
"scripts": {
@@ -40,7 +40,7 @@
4040
"babel-polyfill": "^6.26.0",
4141
"chai": "^4.3.4",
4242
"chai-as-promised": "^7.1.1",
43-
"chromedriver": "^103",
43+
"chromedriver": "^106",
4444
"concurrently": "^6.2.1",
4545
"core-js": "^3.16.1",
4646
"eslint": "^7.32.0",

src/actions.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ const actions = (api, conf) => {
4646

4747
// Iterate over all records in rels
4848
let relPromises = []
49+
let includes = []
4950
for (let [relName, relItems] of Object.entries(rels)) {
51+
includes.push(relName)
5052
if (utils.hasProperty(relItems, 'data')) {
5153
let path = `${type}/${id}/relationships/${relName}`
5254
const apiConf = {
@@ -61,7 +63,12 @@ const actions = (api, conf) => {
6163
// Wait for all individual API calls to complete
6264
await Promise.all(relPromises)
6365
// Get the updated object from the API
64-
return context.dispatch('get', `${type}/${id}`)
66+
let params = {}
67+
// Also include related objects
68+
if (conf.relatedIncludes) {
69+
params['include'] = includes.join()
70+
}
71+
return context.dispatch('get', [`${type}/${id}`, { params: params }])
6572
}
6673

6774
return {
@@ -208,7 +215,6 @@ const actions = (api, conf) => {
208215
* @memberof module:jsonapi-vuex.jsonapiModule.actions
209216
* @param {object} context - Vuex context object
210217
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
211-
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
212218
* @return {object} Restructured representation of the 'parent' item
213219
*/
214220
deleteRelated: (context, args) => {
@@ -221,7 +227,6 @@ const actions = (api, conf) => {
221227
* @memberof module:jsonapi-vuex.jsonapiModule.actions
222228
* @param {object} context - Vuex context object
223229
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
224-
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
225230
* @return {object} Restructured representation of the 'parent' item
226231
*/
227232
patchRelated: async (context, args) => {
@@ -234,7 +239,6 @@ const actions = (api, conf) => {
234239
* @memberof module:jsonapi-vuex.jsonapiModule.actions
235240
* @param {object} context - Vuex context object
236241
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
237-
* @param {object} args - A restructured object, specifying relationship(s) - e.g. `{ _jv: { type: "endpoint", id: "1", relationships: {...} } }`
238242
* @return {object} Restructured representation of the 'parent' item
239243
*/
240244
postRelated: async (context, args) => {

src/config.js

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* @property {string[]} cleanPatchProps='[]' - If cleanPatch is enabled, which _jv props (links, meta, rels) should be kept?
1313
* @property {boolean} recurseRelationships=false - Allow relationships to be recursive?
1414
* @property {integer} maxStatusID=-1 - The maximum number of status IDs to generate before looping. Default is unlimited.
15+
* @property {boolean} relatedIncludes=true - When returning the original object from *related 'write' methods, also include related objects. Default is true.
1516
*/
1617

1718
export default {
@@ -24,4 +25,5 @@ export default {
2425
cleanPatchProps: [],
2526
recurseRelationships: false,
2627
maxStatusID: -1,
28+
relatedIncludes: true,
2729
}

tests/unit/actions/deleteRelated.spec.js

+20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { expect } from 'chai'
22

33
import createStubContext from '../stubs/context'
44
import createJsonapiModule from '../utils/createJsonapiModule'
5+
import { config } from '../../../src/jsonapi-vuex'
56
import { jsonFormat as createJsonWidget1, normFormat as createNormWidget1 } from '../fixtures/widget1'
67

78
describe('deleteRelated', function () {
@@ -44,6 +45,24 @@ describe('deleteRelated', function () {
4445
// Expect a delete call to rel url, with rel payload, then get object to update store
4546
expect(this.mockApi.history.delete[0].url).to.equal('widget/1/relationships/widgets')
4647
expect(this.mockApi.history.delete[0].data).to.deep.equal(JSON.stringify(rel))
48+
expect(this.mockApi.history.get[0].params).to.have.property('include')
49+
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
50+
})
51+
52+
it('should make a delete request for the object passed in.', async function () {
53+
this.mockApi.onDelete().replyOnce(204)
54+
this.mockApi.onGet().replyOnce(200, { data: jsonWidget1 })
55+
56+
const rel = { data: { type: 'widget', id: '2' } }
57+
normWidget1['_jv']['relationships'] = { widgets: rel }
58+
59+
config.relatedIncludes = false
60+
61+
await jsonapiModule.actions.deleteRelated(stubContext, normWidget1)
62+
// Expect a delete call to rel url, with rel payload, then get object to update store
63+
expect(this.mockApi.history.delete[0].url).to.equal('widget/1/relationships/widgets')
64+
expect(this.mockApi.history.delete[0].data).to.deep.equal(JSON.stringify(rel))
65+
expect(this.mockApi.history.get[0].params).to.not.have.property('include')
4766
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
4867
})
4968

@@ -60,6 +79,7 @@ describe('deleteRelated', function () {
6079
expect(this.mockApi.history.delete[0].data).to.deep.equal(JSON.stringify(rel1))
6180
expect(this.mockApi.history.delete[1].url).to.equal('widget/1/relationships/doohickeys')
6281
expect(this.mockApi.history.delete[1].data).to.deep.equal(JSON.stringify(rel2))
82+
expect(this.mockApi.history.get[0].params).to.have.property('include')
6383
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
6484
// Only get the object once at end
6585
expect(this.mockApi.history.get.length).to.equal(1)

tests/unit/actions/patchRelated.spec.js

+20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { expect } from 'chai'
22

33
import createStubContext from '../stubs/context'
44
import createJsonapiModule from '../utils/createJsonapiModule'
5+
import { config } from '../../../src/jsonapi-vuex'
56
import { jsonFormat as createJsonWidget1, normFormat as createNormWidget1 } from '../fixtures/widget1'
67

78
describe('patchRelated', function () {
@@ -44,6 +45,24 @@ describe('patchRelated', function () {
4445
// Expect a patch call to rel url, with rel payload, then get object to update store
4546
expect(this.mockApi.history.patch[0].url).to.equal('widget/1/relationships/widgets')
4647
expect(this.mockApi.history.patch[0].data).to.deep.equal(JSON.stringify(rel))
48+
expect(this.mockApi.history.get[0].params).to.have.property('include')
49+
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
50+
})
51+
52+
it('should make a patch request without includes.', async function () {
53+
this.mockApi.onPatch().replyOnce(204)
54+
this.mockApi.onGet().replyOnce(200, { data: jsonWidget1 })
55+
56+
const rel = { data: { type: 'widget', id: '2' } }
57+
normWidget1['_jv']['relationships'] = { widgets: rel }
58+
59+
config.relatedIncludes = false
60+
61+
await jsonapiModule.actions.patchRelated(stubContext, normWidget1)
62+
// Expect a patch call to rel url, with rel payload, then get object to update store
63+
expect(this.mockApi.history.patch[0].url).to.equal('widget/1/relationships/widgets')
64+
expect(this.mockApi.history.patch[0].data).to.deep.equal(JSON.stringify(rel))
65+
expect(this.mockApi.history.get[0].params).to.not.have.property('include')
4766
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
4867
})
4968

@@ -60,6 +79,7 @@ describe('patchRelated', function () {
6079
expect(this.mockApi.history.patch[0].data).to.deep.equal(JSON.stringify(rel1))
6180
expect(this.mockApi.history.patch[1].url).to.equal('widget/1/relationships/doohickeys')
6281
expect(this.mockApi.history.patch[1].data).to.deep.equal(JSON.stringify(rel2))
82+
expect(this.mockApi.history.get[0].params).to.have.property('include')
6383
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
6484
// Only get the object once at end
6585
expect(this.mockApi.history.get.length).to.equal(1)

tests/unit/actions/postRelated.spec.js

+20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { expect } from 'chai'
22

33
import createStubContext from '../stubs/context'
44
import createJsonapiModule from '../utils/createJsonapiModule'
5+
import { config } from '../../../src/jsonapi-vuex'
56
import { jsonFormat as createJsonWidget1, normFormat as createNormWidget1 } from '../fixtures/widget1'
67

78
describe('postRelated', function () {
@@ -44,6 +45,24 @@ describe('postRelated', function () {
4445
// Expect a post call to rel url, with rel payload, then get object to update store
4546
expect(this.mockApi.history.post[0].url).to.equal('widget/1/relationships/widgets')
4647
expect(this.mockApi.history.post[0].data).to.deep.equal(JSON.stringify(rel))
48+
expect(this.mockApi.history.get[0].params).to.have.property('include')
49+
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
50+
})
51+
52+
it('should make a post request without returning includes.', async function () {
53+
this.mockApi.onPost().replyOnce(204)
54+
this.mockApi.onGet().replyOnce(200, { data: jsonWidget1 })
55+
56+
const rel = { data: { type: 'widget', id: '2' } }
57+
normWidget1['_jv']['relationships'] = { widgets: rel }
58+
59+
config.relatedIncludes = false
60+
61+
await jsonapiModule.actions.postRelated(stubContext, normWidget1)
62+
// Expect a post call to rel url, with rel payload, then get object to update store
63+
expect(this.mockApi.history.post[0].url).to.equal('widget/1/relationships/widgets')
64+
expect(this.mockApi.history.post[0].data).to.deep.equal(JSON.stringify(rel))
65+
expect(this.mockApi.history.get[0].params).to.not.have.property('include')
4766
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
4867
})
4968

@@ -60,6 +79,7 @@ describe('postRelated', function () {
6079
expect(this.mockApi.history.post[0].data).to.deep.equal(JSON.stringify(rel1))
6180
expect(this.mockApi.history.post[1].url).to.equal('widget/1/relationships/doohickeys')
6281
expect(this.mockApi.history.post[1].data).to.deep.equal(JSON.stringify(rel2))
82+
expect(this.mockApi.history.get[0].params).to.have.property('include')
6383
expect(this.mockApi.history.get[0].url).to.equal('widget/1')
6484
// Only get the object once at end
6585
expect(this.mockApi.history.get.length).to.equal(1)

0 commit comments

Comments
 (0)