diff --git a/lib/contracts/contribution.js b/lib/contracts/contribution.js index 6398458..e49591a 100644 --- a/lib/contracts/contribution.js +++ b/lib/contracts/contribution.js @@ -1,20 +1,5 @@ const ethers = require('ethers'); -const schemas = require('kosmos-schemas'); -const tv4 = require('tv4'); -const validator = tv4.freshApi(); - -validator.addFormat({ - 'date': function(value) { - const dateRegexp = /^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/; - return dateRegexp.test(value) ? null : "A valid ISO 8601 full-date string is expected"; - }, - 'time': function(value) { - const timeRegexp = /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))$/; - return timeRegexp.test(value) ? null : "A valid ISO 8601 full-time string is expected"; - } -}) - const ContributionSerializer = require('../serializers/contribution'); const Base = require('./base'); @@ -62,12 +47,13 @@ class Contribution extends Base { }); } - addContribution(contributionAttr, callOptions = {}) { - let jsonStr = ContributionSerializer.serialize(contributionAttr); + async addContribution(contributionAttr, callOptions = {}) { + const contribution = new ContributionSerializer(contributionAttr); - // Validate JSON document against schema - let result = validator.validate(JSON.parse(jsonStr), schemas['contribution']); - if (!result) { return Promise.reject(validator.error); } + try { await contribution.validate(); } + catch (error) { return Promise.reject(error); } + + const jsonStr = contribution.serialize(); return this.ipfs .add(jsonStr) diff --git a/lib/serializers/contribution.js b/lib/serializers/contribution.js index 6cdc279..8ed8dee 100644 --- a/lib/serializers/contribution.js +++ b/lib/serializers/contribution.js @@ -1,45 +1,24 @@ +const schemas = require('kosmos-schemas'); +const validator = require('../utils/validator'); + /** - * Handle serialization for JSON-LD object of the contribution, according to - * https://github.com/67P/kosmos-schemas/blob/master/schemas/contribution.json + * Serialization and validation for JSON-LD document of the contribution. * * @class * @public */ class Contribution { - /** - * Deserialize JSON to object - * - * @method - * @public - */ - static deserialize(serialized) { - let { - date, - time, - kind, - description, - details, - url, - } = JSON.parse(serialized.toString('utf8')); - return { - date, - time, - kind, - description, - details, - url, - ipfsData: serialized, - }; + constructor(attrs) { + Object.keys(attrs).forEach(a => this[a] = attrs[a]); } - /** - * Serialize object to JSON - * - * @method - * @public - */ - static serialize(deserialized) { + /** + * Serialize object to JSON + * + * @public + */ + serialize () { let { contributorIpfsHash, date, @@ -48,7 +27,7 @@ class Contribution { description, url, details - } = deserialized; + } = this; let data = { "@context": "https://schema.kosmos.org", @@ -70,6 +49,44 @@ class Contribution { // Write it pretty to ipfs return JSON.stringify(data, null, 2); } + + /** + * Validate serialized data against schema + * + * @public + */ + validate () { + const serialized = JSON.parse(this.serialize()); + const valid = validator.validate(serialized, schemas['contribution']); + return valid ? Promise.resolve() : Promise.reject(validator.error); + } + + /** + * Deserialize JSON to object + * + * @public + */ + static deserialize (serialized) { + let { + date, + time, + kind, + description, + details, + url, + } = JSON.parse(serialized.toString('utf8')); + + return { + date, + time, + kind, + description, + details, + url, + ipfsData: serialized, + }; + } + } module.exports = Contribution; diff --git a/lib/utils/validator.js b/lib/utils/validator.js new file mode 100644 index 0000000..1dde313 --- /dev/null +++ b/lib/utils/validator.js @@ -0,0 +1,15 @@ +const tv4 = require('tv4'); +const validator = tv4.freshApi(); + +validator.addFormat({ + 'date': function(value) { + const dateRegexp = /^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/; + return dateRegexp.test(value) ? null : "A valid ISO 8601 full-date string is expected"; + }, + 'time': function(value) { + const timeRegexp = /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))$/; + return timeRegexp.test(value) ? null : "A valid ISO 8601 full-time string is expected"; + } +}) + +module.exports = validator;