Comparing version 0.4.2 to 0.5.0
@@ -35,2 +35,19 @@ ## [Unreleased] | ||
## [0.5.0] - 2017-12-27 | ||
### Changed | ||
* Document constructor now return a Promise due the validation function on the Schema fields which can be async functions. The validation checking is done at the moment you create the Document. | ||
* Passed the entire data payload normalized to the validate function instead of the value of the field is validating. In case further checking are neccesary. | ||
* Documentaion about: | ||
* Create a new Document | ||
* Schema option fields | ||
* Promise functions | ||
## [0.4.3] - 2017-12-27 | ||
### Fixed | ||
* Added support for async functions in the Schema fields validation function. | ||
## [0.4.2] - 2017-12-27 | ||
@@ -242,2 +259,4 @@ | ||
[0.5.0]: https://github.com/Yonirt/moltyjs/compare/v0.4.3...v0.5.0 | ||
[0.4.3]: https://github.com/Yonirt/moltyjs/compare/v0.4.2...v0.4.3 | ||
[0.4.2]: https://github.com/Yonirt/moltyjs/compare/v0.4.1...v0.4.2 | ||
@@ -244,0 +263,0 @@ [0.4.1]: https://github.com/Yonirt/moltyjs/compare/v0.4.0...v0.4.1 |
167
lib/model.js
'use strict'; | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } | ||
const mongoClient = require('./clients/mongoClient'); | ||
const Document = require('./document'); | ||
var _require = require('./validators'); | ||
var _require = require('await-to-js'); | ||
const isValidType = _require.isValidType, | ||
isObject = _require.isObject, | ||
isArray = _require.isArray, | ||
isEmptyValue = _require.isEmptyValue, | ||
isString = _require.isString, | ||
isInEnum = _require.isInEnum, | ||
isNumber = _require.isNumber; | ||
const to = _require.to; | ||
var _require2 = require('./validators'); | ||
const isValidType = _require2.isValidType, | ||
isObject = _require2.isObject, | ||
isArray = _require2.isArray, | ||
isEmptyValue = _require2.isEmptyValue, | ||
isString = _require2.isString, | ||
isInEnum = _require2.isInEnum, | ||
isNumber = _require2.isNumber; | ||
class Model { | ||
@@ -46,2 +54,4 @@ /** | ||
this._normalizedPayload = null; | ||
mongoClient.addModel(this); | ||
@@ -99,14 +109,24 @@ } | ||
new(payload, tenant) { | ||
if (!tenant) throw new Error('Tenant name is required, got ' + tenant); | ||
var _this = this; | ||
// Check if paylaod field names are correct | ||
this._validatePayloadFieldNames(payload, this._schemaNormalized); | ||
// Normalize the payload with the model schema | ||
let data = this._normalizePayload(payload, this._schemaNormalized); | ||
return _asyncToGenerator(function* () { | ||
if (!tenant) throw new Error('Tenant name is required, got ' + tenant); | ||
// Validate all the values | ||
this._validatePayloadFieldValues(data, this._schemaNormalized, tenant); | ||
// Check if paylaod field names are correct | ||
_this._validatePayloadFieldNames(payload, _this._schemaNormalized); | ||
// Normalize the payload with the model schema | ||
_this._normalizedPayload = _this._normalizePayload(payload, _this._schemaNormalized); | ||
// Returning the new document created | ||
return new Document(data, this._preHooks, this._postHooks, this._methods, this._schemaOptions, this._modelName, this._discriminator, tenant); | ||
try { | ||
// Validate all the values | ||
yield _this._validatePayloadFieldValues(_this._normalizedPayload, _this._schemaNormalized, tenant); | ||
// Returning the new document created | ||
return new Document(_this._normalizedPayload, _this._preHooks, _this._postHooks, _this._methods, _this._schemaOptions, _this._modelName, _this._discriminator, tenant); | ||
} catch (err) { | ||
throw err; | ||
} finally { | ||
_this._normalizedPayload = null; | ||
} | ||
})(); | ||
} | ||
@@ -204,47 +224,88 @@ | ||
_validatePayloadFieldValues(payload, schema, tenant = null) { | ||
Object.keys(schema).forEach(key => { | ||
// No required values | ||
if (payload[key] === undefined && !schema[key].required) return; | ||
var _this2 = this; | ||
// Objects nested | ||
if (!schema[key].type && isObject(payload[key])) { | ||
payload[key] = this._validatePayloadFieldValues(payload[key], schema[key]); | ||
return; | ||
} | ||
return _asyncToGenerator(function* () { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
// Validation type | ||
if (!isValidType(payload[key], schema[key].type)) { | ||
throw new Error('Unsuported value (' + payload[key] + ') for type ' + schema[key].type); | ||
} | ||
try { | ||
for (var _iterator = Object.keys(schema)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
const key = _step.value; | ||
// Reg exp validation | ||
if (schema[key].match && isString(payload[key]) && !schema[key].match.test(payload[key])) { | ||
throw new Error('Value assigned to ' + key + ' does not match the regex/string ' + schema[key].match.toString() + '. Value was ' + payload[key]); | ||
} | ||
// No required values | ||
if (payload[key] === undefined && !schema[key].required) continue; | ||
// Enum validation | ||
if (!isInEnum(schema[key].enum, payload[key])) { | ||
throw new Error('Value assigned to ' + key + ' should be in enum [' + schema[key].enum.join(', ') + '], got ' + payload[key]); | ||
} | ||
// Objects nested | ||
if (!schema[key].type && isObject(payload[key])) { | ||
payload[key] = _this2._validatePayloadFieldValues(payload[key], schema[key]); | ||
continue; | ||
} | ||
// Min value validation | ||
if (isNumber(schema[key].min) && payload[key] < schema[key].min) { | ||
throw new Error('Value assigned to ' + key + ' is less than min, ' + schema[key].min + ', got ' + payload[key]); | ||
} | ||
// Validation type | ||
if (!isValidType(payload[key], schema[key].type)) { | ||
throw new Error('Unsuported value (' + payload[key] + ') for type ' + schema[key].type); | ||
} | ||
// Max value validation | ||
if (isNumber(schema[key].max) && payload[key] > schema[key].max) { | ||
throw new Error('Value assigned to ' + key + ' is less than max, ' + schema[key].max + ', got ' + payload[key]); | ||
} | ||
// Reg exp validation | ||
if (schema[key].match && isString(payload[key]) && !schema[key].match.test(payload[key])) { | ||
throw new Error('Value assigned to ' + key + ' does not match the regex/string ' + schema[key].match.toString() + '. Value was ' + payload[key]); | ||
} | ||
// Max lenght validation | ||
if (schema[key].maxlength && isString(payload[key]) && payload[key].length > schema[key].maxlength) { | ||
throw new Error('Value assigned to ' + key + ' is bigger than ' + schema[key].maxlength.toString() + '. Value was ' + payload[key].length); | ||
} | ||
// Enum validation | ||
if (!isInEnum(schema[key].enum, payload[key])) { | ||
throw new Error('Value assigned to ' + key + ' should be in enum [' + schema[key].enum.join(', ') + '], got ' + payload[key]); | ||
} | ||
// Custom validation | ||
if (typeof schema[key].validate === 'function' && !schema[key].validate(mongoClient, tenant, payload[key])) { | ||
throw new Error('Value assigned to ' + key + ' failed custom validator. Value was ' + payload[key]); | ||
// Min value validation | ||
if (isNumber(schema[key].min) && payload[key] < schema[key].min) { | ||
throw new Error('Value assigned to ' + key + ' is less than min, ' + schema[key].min + ', got ' + payload[key]); | ||
} | ||
// Max value validation | ||
if (isNumber(schema[key].max) && payload[key] > schema[key].max) { | ||
throw new Error('Value assigned to ' + key + ' is less than max, ' + schema[key].max + ', got ' + payload[key]); | ||
} | ||
// Max lenght validation | ||
if (schema[key].maxlength && isString(payload[key]) && payload[key].length > schema[key].maxlength) { | ||
throw new Error('Value assigned to ' + key + ' is bigger than ' + schema[key].maxlength.toString() + '. Value was ' + payload[key].length); | ||
} | ||
// Custom validation | ||
if (typeof schema[key].validate === 'function') { | ||
let error, isValid; | ||
if (schema[key].validate.constructor.name === 'AsyncFunction') { | ||
var _ref = yield to(schema[key].validate(mongoClient, tenant, _this2._normalizedPayload)); | ||
var _ref2 = _slicedToArray(_ref, 2); | ||
error = _ref2[0]; | ||
isValid = _ref2[1]; | ||
} else { | ||
isValid = schema[key].validate(mongoClient, tenant, _this2._normalizedPayload); | ||
} | ||
if (!isValid || error) { | ||
let err = new Error('Value assigned to ' + key + ' failed custom validator. Value was ' + payload[key]); | ||
err.code = 'VALIDATION_FAILED'; | ||
throw err; | ||
} | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
}); | ||
})(); | ||
} | ||
@@ -251,0 +312,0 @@ |
{ | ||
"name": "moltyjs", | ||
"version": "0.4.2", | ||
"version": "0.5.0", | ||
"description": "A tiny ODM for MongoDB with multy tenancy support.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -114,3 +114,3 @@ [![npm version](https://badge.fury.io/js/moltyjs.svg)](https://badge.fury.io/js/moltyjs) | ||
* _maxlength_: Optional, maximum length of a **String** | ||
* _validate_: Optional, function to perform a custom validation. Value of the field, connection instance and tenant name is passing through the function args: | ||
* _validate_: Optional, function to perform a custom validation. Payload of the document, connection instance and tenant name is passing through the function args: | ||
@@ -123,9 +123,10 @@ ```javascript | ||
type: String, | ||
validate: async (connection, tenant, value) => { | ||
validate: async (connection, tenant, payload) => { | ||
const exists = await connection.find(tenant, 'TestModel', { | ||
job: value, | ||
job: payload.job, | ||
}); | ||
// If the document already exists we | ||
// propagate an error returning false | ||
// propagate an error with error.code = 'VALIDATION_FAILED' | ||
// by returning false | ||
if (exists) return false; | ||
@@ -308,3 +309,3 @@ | ||
### `.new(payload, tenant)` | ||
### `.new(payload, tenant) {Promise}` | ||
@@ -316,3 +317,3 @@ ```javascript | ||
newDoc = TestModel.new( | ||
newDoc = await TestModel.new( | ||
{ | ||
@@ -324,3 +325,3 @@ email: 'test@moltyjs.com', | ||
'test', | ||
); | ||
); // Document // Error | ||
``` | ||
@@ -381,3 +382,3 @@ | ||
### `insertOne(doc, options = {})` | ||
### `insertOne(doc, options = {}) {Promise}` | ||
@@ -395,3 +396,3 @@ * {Document} `doc` Document instance object | ||
### `insertMany(docs, options = {})` | ||
### `insertMany(docs, options = {}) {Promise}` | ||
@@ -417,3 +418,3 @@ * [{Document}] `docs` Array of Document instances of the same model and for the same tenant | ||
### `find(tenant, collection, query = {}, options = {})` | ||
### `find(tenant, collection, query = {}, options = {}) {Promise}` | ||
@@ -443,3 +444,3 @@ * {String} `tanant` Tenant name | ||
### `updateOne(tenant, collection, filter, payload, options = {})` | ||
### `updateOne(tenant, collection, filter, payload, options = {}) {Promise}` | ||
@@ -446,0 +447,0 @@ ```javascript |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
82915
1433
453