Skip to content

Commit cc9e83d

Browse files
committed
feat: add data option on relationships
1 parent b016d08 commit cc9e83d

File tree

5 files changed

+56
-1
lines changed

5 files changed

+56
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Serializer.register(type, options);
4545
* **type**: A _string_ or a _function_ `function(relationshipData, data) { ... }` for the type to use for serializing the relationship (type need to be register).
4646
* **alternativeKey** (optional): An alternative key (string or path) to use if relationship key not exist (example: 'author_id' as an alternative key for 'author' relationship). See [issue #12](https://github.com/danivek/json-api-serializer/issues/12).
4747
* **schema** (optional): A custom schema for serializing the relationship. If no schema define, it use the default one.
48+
* **data** (optional): A _function_ `function(data) { ... }` that returns the data to serialize for the relationship.
4849
* **links** (optional): Describes the links for the relationship. It can be:
4950
* An _object_ (values can be string or function).
5051
* A _function_ with one argument `function(data) { ... }` or with two arguments `function(data, extraData) { ... }`

lib/JSONAPISerializer.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -716,13 +716,17 @@ module.exports = class JSONAPISerializer {
716716
relationshipKey = relationshipOptions.alternativeKey;
717717
}
718718

719+
const dataFn = relationshipOptions.data
720+
? relationshipOptions.data
721+
: (relationshipData) => relationshipData;
722+
719723
const serializeRelationship = {
720724
links: this.processOptionsValues(data, extraData, relationshipOptions.links),
721725
meta: this.processOptionsValues(data, extraData, relationshipOptions.meta),
722726
data: this.serializeRelationship(
723727
relationshipOptions.type,
724728
relationshipOptions.schema,
725-
get(data, relationshipKey),
729+
dataFn(get(data, relationshipKey)),
726730
included,
727731
data,
728732
extraData,
@@ -996,6 +1000,7 @@ module.exports = class JSONAPISerializer {
9961000
* @property {string|Function} type a string or a function for the type to use for serializing the relationship (type need to be register)
9971001
* @property {string} [alternativeKey] an alternative key (string or path) to use if relationship key not exist (example: 'author_id' as an alternative key for 'author' relationship)
9981002
* @property {string} [schema] a custom schema for serializing the relationship. If no schema define, it use the default one.
1003+
* @property {Function} [data] a function that returns the data to serialize for the relationship
9991004
* @property {Function|object} [links] describes the links for the relationship
10001005
* @property {Function|object} [meta] describes meta that contains non-standard meta-information about the relationship
10011006
* @property {Function} [deserialize] describes the function which should be used to deserialize a related property which is not included in the JSON:API document

lib/validator.js

+3
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ function validateOptions(options) {
102102

103103
if (relationships[key].deserialize && typeof relationships[key].deserialize !== 'function')
104104
throw new Error(`option 'deserialize' for relationship '${key}' must be a function`);
105+
106+
if (relationships[key].data && typeof relationships[key].data !== 'function')
107+
throw new Error(`option 'data' for relationship '${key}' must be a function`);
105108
});
106109

107110
return options;

test/unit/JSONAPISerializer.test.js

+31
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,37 @@ describe('JSONAPISerializer', function() {
644644
expect(serializedRelationships.author).to.have.property('links').to.be.undefined;
645645
done();
646646
});
647+
648+
it('should return relationships with data option', function(done) {
649+
const Serializer = new JSONAPISerializer();
650+
651+
Serializer.register('article', {
652+
relationships: {
653+
comments: {
654+
type: 'comment',
655+
data: (data) => data.data
656+
}
657+
}
658+
});
659+
Serializer.register('comment');
660+
661+
const serializedRelationships = Serializer.serializeRelationships({
662+
id: '1',
663+
comments: {
664+
total: 2,
665+
data: [{id: '1', title: 'comment 1'}, {id: '2', title: 'comment 2'}]
666+
}
667+
}, Serializer.schemas.article.default);
668+
console.log(JSON.stringify(serializedRelationships, null, 2));
669+
expect(serializedRelationships).to.have.property('comments');
670+
expect(serializedRelationships.comments).to.have.property('data');
671+
expect(serializedRelationships.comments.data).to.be.instanceof(Array).to.have.length(2);
672+
expect(serializedRelationships.comments.data[0]).to.have.property('type').to.eql('comment');
673+
expect(serializedRelationships.comments.data[0]).to.have.property('id').to.be.a('string').to.eql('1');
674+
expect(serializedRelationships.comments.data[1]).to.have.property('id').to.be.a('string').to.eql('2');
675+
expect(serializedRelationships.comments).to.have.property('links').to.be.undefined;
676+
done();
677+
});
647678
});
648679

649680
describe('serializeAttributes', function() {

test/unit/validator.test.js

+15
Original file line numberDiff line numberDiff line change
@@ -291,5 +291,20 @@ describe('validator', function () {
291291

292292
done();
293293
});
294+
295+
it('incorrect data on relationship', (done) => {
296+
expect(function () {
297+
validator.validateOptions({
298+
relationships: {
299+
test: {
300+
type: 'test',
301+
data: 'test',
302+
},
303+
},
304+
});
305+
}).to.throw(Error, "option 'data' for relationship 'test' must be a function");
306+
307+
done();
308+
});
294309
});
295310
});

0 commit comments

Comments
 (0)