Skip to content

Commit

Permalink
feat: add in new keyword coerce
Browse files Browse the repository at this point in the history
Supports: trim, trimLeft, trimRight, lowercase, uppercase, enumcase
  • Loading branch information
willfarrell committed Apr 16, 2018
1 parent 847c781 commit bca7627
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 1 deletion.
7 changes: 7 additions & 0 deletions .gitignore
@@ -1,3 +1,6 @@

package-lock.json

# Logs
logs
*.log
Expand Down Expand Up @@ -36,3 +39,7 @@ node_modules
keywords/dotjs/*.js

.DS_Store

# IDE
.idea
*.iml
77 changes: 77 additions & 0 deletions keywords/coerce.js
@@ -0,0 +1,77 @@
'use strict';

module.exports = function defFunc (ajv) {
defFunc.definition = {
type: 'string',
errors: false,
modifying: true,
schema: false,
valid: true,
compile: function (schema, parentSchema) {

// build hash table to enum values
var hashtable = {};

if (schema.indexOf('enumcase') !== -1) {
// requires `enum` in schema
if (!parentSchema.enum)
throw new Error('Missing enum. To use `coerce:["enumcase"]`, `enum:[...]` is required.');
for (var i = parentSchema.enum.length; i--; i) {
var v = parentSchema.enum[i];
var k = makeHashTableKey(v);
// requires all `enum` values have unique keys
if (hashtable[k])
throw new Error('Invalid enum uniqueness. To use `coerce:["enumcase"]`, all values must be unique when case insensitive.');
hashtable[k] = v;
}
}

var coerce = {
trimLeft: function (value) {
return value.replace(/^[\s]+/, '');
},
trimRight: function (value) {
return value.replace(/[\s]+$/, '');
},
trim: function (value) {
return value.trim();
},
lowercase: function (value) {
return value.toLowerCase();
},
uppercase: function (value) {
return value.toUpperCase();
},
enumcase: function (value) {
return hashtable[makeHashTableKey(value)] || value;
}
};

return function (value, objectKey, object, key) {
// skip if value only
if (!object) return;

// apply coerce in order provided
for (var j = 0, l = schema.length; j < l; j++)
object[key] = coerce[schema[j]](object[key]);
};
},
metaSchema: {
type: 'array',
items: {
type: 'string',
enum: [
'trimLeft', 'trimRight', 'trim',
'lowercase', 'uppercase', 'enumcase'
]
}
}
};

ajv.addKeyword('coerce', defFunc.definition);
return ajv;

function makeHashTableKey (value) {
return value.toLowerCase();
}
};
3 changes: 2 additions & 1 deletion keywords/index.js
Expand Up @@ -14,5 +14,6 @@ module.exports = {
formatMaximum: require('./formatMaximum'),
patternRequired: require('./patternRequired'),
'switch': require('./switch'),
select: require('./select')
select: require('./select'),
coerce: require('./coerce')
};
93 changes: 93 additions & 0 deletions spec/coerce.spec.js
@@ -0,0 +1,93 @@
'use strict'

var Ajv = require('ajv')
var ajvPack = require('ajv-pack')
var defFunc = require('../keywords/coerce')
var defineKeywords = require('..')
var should = require('chai').should()

describe('keyword "coerce"', function () {
var ajvs = [
defFunc(new Ajv),
defineKeywords(new Ajv, 'coerce'),
defineKeywords(new Ajv),
//defFunc(ajvPack.instance(new Ajv({sourceCode: true})))
]


ajvs.forEach(function (ajv, i) {
it('should coerce by wrapper #' + i, function () {
var schema, data

data = {o: ' Object '};
schema = {type: 'object', properties: {o: {type: 'string', coerce: ['trim', 'lowercase']}}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal({o:'object'});

data = [' Array '];
schema = {type: 'array', items: {type: 'string', coerce: ['trim','uppercase']}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal(['ARRAY']);


data = ' String ';
schema = {type: 'string', coerce: ['trim', 'lowercase']};
ajv.validate(schema, data) .should.equal(true);
// Note: Doesn't work on plain strings due to object being undefined
// data.should.deep.equal('string');
})
})

ajvs.forEach(function (ajv, i) {
it('should coerce trim #' + i, function () {
var schema, data

data = [' trimObject '];
schema = {type: 'array', items: {type: 'string', coerce: ['trimLeft']}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal(['trimObject ']);

data = [' trimObject '];
schema = {type: 'array', items: {type: 'string', coerce: ['trimRight']}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal([' trimObject']);

data = [' trimObject '];
schema = {type: 'array', items: {type: 'string', coerce: ['trimLeft','trimRight']}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal(['trimObject']);

data = [' trimObject '];
schema = {type: 'array', items: {type: 'string', coerce: ['trim']}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal(['trimObject']);
})
})

ajvs.forEach(function (ajv, i) {
it('should coerce text case #' + i, function () {
var schema, data

data = ['MixCase'];
schema = {type: 'array', items: {type: 'string', coerce: ['lowercase']}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal(['mixcase']);

data = ['MixCase'];
schema = {type: 'array', items: {type: 'string', coerce: ['uppercase']}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal(['MIXCASE']);

data = ['ph', 'PH','pH','Ph'];
schema = {type: 'array', items: {type: 'string', coerce: ['enumcase'], enum:['pH']}};
ajv.validate(schema, data) .should.equal(true);
data.should.deep.equal(['pH','pH','pH','pH']);

data = ['ab'];
schema = {type: 'array', items: {type: 'string', coerce: ['enumcase'], enum:['pH']}};
ajv.validate(schema, data) .should.equal(false);
data.should.deep.equal(['ab']);
})
})

})

0 comments on commit bca7627

Please sign in to comment.