summaryrefslogtreecommitdiff
path: root/app/node_modules/okschema/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/node_modules/okschema/index.js')
-rw-r--r--app/node_modules/okschema/index.js178
1 files changed, 160 insertions, 18 deletions
diff --git a/app/node_modules/okschema/index.js b/app/node_modules/okschema/index.js
index 8871a99..0048fc5 100644
--- a/app/node_modules/okschema/index.js
+++ b/app/node_modules/okschema/index.js
@@ -1,4 +1,4 @@
-var assign = require('object-assign');
+var cloneDeep = require('lodash.clonedeep');
var mschema = require('mschema');
var v = require('validator');
@@ -41,36 +41,99 @@ var types = {
}
},
'captioned-image-list': {
+ isArray: true,
parent: [{
uri: { type: 'string' }, // TODO Implement URI type
caption: { type: 'string' }
}],
- assertValid: function(spec, value) {
- var message;
- var actual;
- if (!value || !value.length) {
- throw [{
- message: 'Not an array',
- expected: JSON.stringify(this.parent),
- actual: value
- }];
- }
- }
+ assertValid: function(spec, value) {}
+ },
+ 'gallery': {
+ isArray: true,
+ parent: [{
+ uri: { type: 'string' }, // TODO Implement URI type
+ caption: { type: 'string' }
+ }],
+ assertValid: function(spec, value) {}
+ },
+ // Special type for resource meta information
+ 'meta': {
+ parent: 'string',
+ assertValid: function(spec, value) {}
+ },
+ 'link-list': {
+ isArray: true,
+ parent: [{
+ uri: { type: 'string' },
+ text: { type: 'string' }
+ }],
+ assertValid: function(spec, value) {}
+ },
+ 'date': {
+ parent: 'string',
+ assertValid: function(spec, value) {}
+ },
+ 'flag': {
+ parent: 'boolean',
+ assertValid: function(spec, value) {}
+ },
+ 'foreign-key': {
+ parent: 'enum',
+ assertValid: function(spec, value) {}
+ },
+ 'media-list': {
+ isArray: true,
+ parent: [],
+ assertValid: function(spec, value) {}
+ },
+ 'media': {
+ isArray: true,
+ parent: [],
+ assertValid: function(spec, value) {}
+ },
+ 'double-captioned-image-list': {
+ isArray: true,
+ parent: [],
+ assertValid: function(spec, value) {}
+ },
+ 'triple-captioned-image-list': {
+ isArray: true,
+ parent: [],
+ assertValid: function(spec, value) {}
+ },
+}
+
+/*
+function checkArrayLength (spec, value) {
+ var message;
+ var actual;
+ if (!value || !value.length) {
+ throw [{
+ message: 'Not an array',
+ expected: JSON.stringify(this.parent),
+ actual: value
+ }];
}
}
+*/
+
/**
* OKSchema!
* Meant as a thin wrapper around some existing schema validation
* module, mostly to allow for the extension of types.
+ *
+ * NOTE: Currently just assumes spec is valid. If you give a bad spec
+ * strange things may or may not happen
*/
function OKSchema(spec) {
if (!(this instanceof OKSchema)) return new OKSchema(spec);
if (!spec)
throw new Error('No spec provided to OKSchema');
- spec = assign({}, spec);
+ spec = cloneDeep(spec);
+ var specKeys = Object.keys(spec);
// Cache the mschema version of our spec
- this._mschemaSpec = Object.keys(spec).reduce(function(cache, prop) {
+ this._mschemaSpec = specKeys.reduce(function(cache, prop) {
// If custom type, return its parent spec
var type = spec[prop].type;
if (types[type]) {
@@ -82,25 +145,104 @@ function OKSchema(spec) {
return cache;
}, {});
+ // Find ID field
+ var idField;
+ specKeys.every(function(prop) {
+ if (prop === 'id' || spec[prop].id) {
+ idField = prop;
+ return false;
+ } else {
+ return true;
+ }
+ });
+
+ // Register autoincrement fields
+ // NOTE Does not work for nested fields
+ var autoIncrementFields = specKeys.reduce(function(arr, prop) {
+ var specProp = spec[prop];
+ if (specProp.autoincrement) {
+ arr.push(prop);
+ }
+ return arr;
+ }, []);
+
Object.defineProperty(this, 'spec', {
- value: spec,
- writable: false
+ get: function() {
+ return cloneDeep(spec);
+ },
+ enumerable: true
+ });
+
+ Object.defineProperty(this, 'idField', {
+ value: idField,
+ writable: true,
+ enumerable: true
});
+
+ Object.defineProperty(this, 'autoIncrementFields',{
+ get: function() {
+ return cloneDeep(autoIncrementFields);
+ },
+ enumerable: true
+ });
+}
+
+OKSchema.prototype.fixMissingLists = function(data) {
+ var spec = this.spec;
+
+ // The qs body-parser module does not have a way to represent
+ // empty lists. If you delete all elements from a list,
+ // check against the spec so we know to replace with an empty list.
+ Object.keys(spec).forEach(function(prop){
+ var type = spec[prop].type;
+ if (types[type] && types[type].isArray && ! data[prop]) {
+ data[prop] = []
+ }
+ })
+}
+
+OKSchema.prototype.fixIndexField = function(data) {
+ // Likewise numbers always come in as strings. The field used to sort
+ // records, __index, is of type "meta", so the parseFloat in
+ // assertValid (below) never fires and we end up with sorting issues.
+ if (data.__index && typeof data.__index == "string") {
+ var __index = parseInt(data.__index)
+ if (! isNaN(__index)) {
+ data.__index = __index
+ }
+ }
}
OKSchema.prototype.assertValid = function(data) {
data = data || {};
var spec = this.spec;
+
// Run through custom validators, they'll throw if invalid
Object.keys(data).forEach(function(prop) {
var type = spec[prop].type;
- if (types[type]) {
+
+ // Check if it's a number/boolean and try to cast it
+ // otherwise pass and let mschema handle
+ if (type === 'number') {
+ try {
+ data[prop] = parseFloat(data[prop]);
+ } catch (err) {}
+ } else if (type === 'flag') {
+ data[prop] = data[prop] == "true" ? true : false
+ } else if (types[type]) {
types[type].assertValid(spec[prop], data[prop]);
}
});
var result = mschema.validate(data, this.toMschema());
- if (!result.valid)
+ if (!result.valid) {
throw result.errors;
+ }
+
+ // Fix various issues with our data, having to do
+ // with use of the "qs" body-parser module.
+ // TODO: just send JSON?
+ this.fixMissingLists(data)
+ this.fixIndexField(data)
};
/**