Skip to content

Commit

Permalink
More review omplementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Startouf committed Aug 15, 2018
1 parent de5883a commit 26ce70c
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 45 deletions.
10 changes: 6 additions & 4 deletions src/builders/JsonapiResourceBuilder.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { merge } from 'lodash';

export default class JsonapiResourceBuilder {
/**
* @param {String} options.jsonapiType - json:api document type
* @param {Object} options.meta - Meta relevant for json:api orchestrator
* @param {Object} params - Additional params relevant to the resource
*/
constructor({ jsonapiType = null, meta = {}, params = {} }) {
this.jsonapiType = jsonapiType;
this.meta = meta;
this.params = params;
this.meta = meta;
}

/* merges additional resource meta */
addMeta(meta) { this.meta = merge(this.meta, meta); }
}
6 changes: 4 additions & 2 deletions src/builders/JsonapiResourceReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ export default class JsonapiResourceReader extends JsonapiResourceBuilder {
this.mustBeFresherThan = date;
}

/***************************
/**
***************************
*** Sorting & Filtering ***
***************************/
***************************
*/

/**
* @param {Iterable<Object>} sortings - as many objects as you want, in sort order,
Expand Down
117 changes: 91 additions & 26 deletions src/builders/JsonapiResourceWriter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,38 @@ import Uuid from 'uuid/v4';
import JsonapiResourceBuilder from './JsonapiResourceBuilder';

export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
/**
* @param {Object} args See inherited params from @JsonapiResourceBuilder
* @param {Object} args.dataMeta - Meta object under data
* @param {Object} args.attributes - Attributes of the document to be written or updated
* @param {Object} args.associations - See {@link #associate()}
* @param {Object} args.disassociations - See {@link #disassociate()}
* @param {Object} args.sideposts - See {@link #sidepost()}
*/
constructor(args = {}) {
super(args);

const {
dataMeta = {}, attributes = {},
associations = {}, disassociations = {}, sideposts = {},
id= null,
} = args;

this.attributes = attributes;
this.dataMeta = dataMeta;

this.sideposts = {};
forOwn(sideposts, (val, key) => this.sidepost(key, val));
this.associations = {};
forOwn(associations, (val, key) => this.associate(key, val));
this.disassociations = {};
forOwn(disassociations, (val, key) => this.disassociate(key, val));
this.dataMeta = dataMeta;
this.tempid = Uuid();

if (id) {
this.id = id;
} else {
this.tempid = Uuid();
}
}

/*
Expand All @@ -39,12 +54,13 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
}

/**
****************************************
** Relationship linking
****************************************
**********************
* Relationship linking
**********************
*/

/* @param sidepost {Object<String, Composite>}
/**
* @param sidepost {Object<String, Composite>}
* - end values must be
* - either JsonapiResourceWriters (to-one relationships)
* - ... or Array<JsonapiResourceWriters> (to-many relationships)
Expand All @@ -56,21 +72,36 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
* ))
*
* feedBackWriter.sidepost('message', toOneMessageSidepost)
* # => Will record message for sidepost#create
* # => Will record message for a sideposting #create operation
*
*/
sidepost(key, valueOrValues) {
this._addRelationship(key, valueOrValues, 'create', 'sideposts');
}

/**
* Associates the given resource
* See {@link #sidepost()}
*/
associate(key, valueOrValues) {
this._addRelationship(key, valueOrValues, 'associate', 'associations');
}

/**
* Disassociates the given resource
* See {@link #sidepost()}
*/
disassociate(key, valueOrValues) {
this._addRelationship(key, valueOrValues, 'disassociate', 'disassociations');
}

/**
* @api private
* @param {String} name Name of the relationship
* @param {Object[] or Object} valueOrValues List or single value
* @param {String} method Value of the method key
* @param {[type]} iVarName Name of iVar holding the related resources
*/
_addRelationship(name, valueOrValues, method, iVarName) {
const iVar = this[iVarName];
if (valueOrValues instanceof Array) {
Expand All @@ -82,22 +113,22 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
}
}


/**
****************************************
** Jsonapi JSON resource Representations
****************************************
*/

/*
/**
* Represent this resource as the main json:api `data` document
*
* @return {Object} - Object ready for serialization under .data or .included
* @return {Object.type}
* @return {Object.id} - Optional
* @return {Object.temp-id} - temporary ID created for matching nested objects
* @return {Object.attributes} - list of attributes
* @return {Object.relationships} - list of relationships
* @return {Object.meta} - Metadata associated with the object and this request
*
*/
asJsonapiDataJson() {
return this.addIdOrTempId({
Expand All @@ -108,7 +139,10 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
});
}

/* Our Jsonapi relationship serialization is compatible with the sidepost draft
/**
* Represent this resource as a json:api `included` document
*
* Our Jsonapi relationship serialization is compatible with the sidepost draft
* (https://github.com/json-api/json-api/pull/1197)
*
* @return {Object} - Object ready for serialization as relationship
Expand All @@ -117,7 +151,6 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
* @return {Object.temp-id} - temporary ID created for matching nested objects
* @return {Object.method} - method used for updating the relationship
* (associate, disassociate, create, update)
*
*/
asJsonapiRelationshipJson() {
return this.addIdOrTempId({
Expand All @@ -126,6 +159,10 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
});
}

/**
* Automatically add a tempid or an id to the payload currently being build
* @param {Object} payload - Payload updated with a tempid or the id of the resource
*/
addIdOrTempId(payload) {
const payloadWithId = { ...payload };
if (this.inferMethod() === 'create') {
Expand All @@ -136,30 +173,46 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
return payloadWithId;
}

/* @api private */
/**
* @api private
* @return {String}
*/
requestActionTypePrefix() {
return this.inferMethod() === 'create' ? 'CREATE' : 'UPDATE';
}

/**
* Setter for the persistence method
* (supported by jsonapi_suite: create/update/associate/disassociate)
* @param {String} method
*/
setMethod(method) {
this.method = method;
}

/**
* Automatically infer create or update if the method is not provided
* based on the presence or absence of the resource ID
* @return {String}
*/
inferMethod() {
if (this.method) {
return this.method;
} else if (!this.id) {
return 'CREATE';
return 'create';
}
return 'UPDATE';
return 'update';
}

/**
**********************************
** Relationship payload generation
**********************************
*********************************************
** Relationship & Included payload generation
*********************************************
*/

/**
* @return {Object} Object whose keys are all the relationships to be updated whatever the method
*/
relationshipsIterable() {
return ({
...this.sideposts,
Expand All @@ -168,10 +221,16 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
});
}

/**
* @return {Array<Object>} List of resources that should be serialized under the included key
*/
includedIterable() {
return this.sideposts;
}

/**
* @return {Object} json:api `data.relationship` object
*/
jsonapiJsonForDataRelationships() {
const relationshipsJson = {};
const iterable = this.relationshipsIterable();
Expand All @@ -188,20 +247,26 @@ export default class JsonapiResourceWriter extends JsonapiResourceBuilder {
return relationshipsJson;
}

/**
* @return {Array<Object>} json:api `included` array of included resources
*/
jsonapiJsonForIncluded() {
const included = [];
let included = [];
const iterable = this.includedIterable();
Object.keys(iterable).forEach((key) => {
const val = iterable[key];
if (val instanceof Array) {
merge(included, val.map(includedResource => includedResource.asJsonapiDataJson()));
merge(
included,
flatMap(val, includedResource => includedResource.jsonapiJsonForIncluded()),
);
included = [
...included,
...val.map(includedResource => includedResource.asJsonapiDataJson()),
...flatMap(val, includedResource => includedResource.jsonapiJsonForIncluded()),
];
} else {
included.push(val.asJsonapiDataJson());
merge(included, val.jsonapiJsonForIncluded());
included = [
...included,
val.asJsonapiDataJson(),
...val.jsonapiJsonForIncluded()
]
}
});
return included;
Expand Down
Loading

0 comments on commit 26ce70c

Please sign in to comment.