Comparing version 0.1.3 to 0.1.4
@@ -6,3 +6,3 @@ module.exports = { | ||
// Support for rttc() and infer() | ||
// Support for rttc() and infer(). | ||
// (these are here for compatibility and will likely | ||
@@ -13,4 +13,4 @@ // be removed in a future version) | ||
// Also expose `types` object for compat. | ||
// Also expose `types` object for compatibility. | ||
types: require('./lib/types') | ||
}; |
@@ -10,5 +10,9 @@ /** | ||
module.exports = function coerce (expected, actual) { | ||
return rttc(expected, actual, { | ||
return rttc({ | ||
x: expected | ||
}, { | ||
x: actual | ||
}, { | ||
coerce: true | ||
}); | ||
}; |
@@ -11,3 +11,3 @@ /** | ||
/** | ||
* Given a tuple value, check it for primitives | ||
* Given a primitive value, return its type. | ||
* ________________________________________________________________________________ | ||
@@ -19,3 +19,3 @@ * @param {*} val there's that "mystery meat" again | ||
function checkTuple(val) { | ||
function getTypeOfPrimitive(val) { | ||
@@ -38,24 +38,31 @@ var type; | ||
/** | ||
* Recursively perform a destructive mutatation on an object | ||
* to set tuple types. | ||
* Recursively create a new schema object from an example object. | ||
* ________________________________________________________________________________ | ||
* @param {Object} obj | ||
* ________________________________________________________________________________ | ||
* @returns {Object} Always. | ||
* @returns {Object} If this is an object, returns a new schema object. | ||
* @returns {undefined} If `obj` is not an object | ||
*/ | ||
function parseObject(obj) { | ||
function getObjectSchema(obj) { | ||
if(!types.obj.is(obj)) return; | ||
var newObj = {}; | ||
_.each(_.keys(obj), function(key) { | ||
var val = obj[key]; | ||
var type; | ||
if(types.arr.is(val)) type = 'array'; | ||
if(types.obj.is(val)) return parseObject(val); | ||
type = checkTuple(val); | ||
obj[key] = type; | ||
if(types.arr.is(val)) { | ||
type = inferSchema(val); | ||
} | ||
else if(types.obj.is(val)) { | ||
type = getObjectSchema(val); | ||
} | ||
else { | ||
type = getTypeOfPrimitive(val); | ||
} | ||
newObj[key] = type; | ||
}); | ||
return obj; | ||
return newObj; | ||
} | ||
@@ -67,36 +74,39 @@ | ||
/** | ||
* Given an example, parse it to infer it's primitive type. | ||
* Given an example, parse it to infer its schema. | ||
* ________________________________________________________________________________ | ||
* @param {*} example | ||
* ________________________________________________________________________________ | ||
* @returns {Object} | ||
* @returns {*} a schema object | ||
*/ | ||
function inferPrimitiveType(example) { | ||
function inferSchema(example) { | ||
// If the example isn't an object or array we can run through the primatives and see | ||
// if any match. | ||
// If the example isn't an object or array, we will derive its primitive type. | ||
if(!types.obj.is(example) && !types.arr.is(example)) { | ||
return checkTuple(example); | ||
return getTypeOfPrimitive(example); | ||
} | ||
// If the example is an array, figure out what to do. For now just check that it's an array | ||
// If the example is an array, figure out what to do. | ||
// For now just check that it's an array. | ||
if(types.arr.is(example)) { | ||
// Parse arrays of arrays | ||
if (_.isArray(example[0])) { | ||
return [inferSchema(example[0])]; | ||
} | ||
// Parse arrays of objects | ||
if (_.isObject(example[0])) { | ||
return [parseObject(example[0])]; | ||
return [getObjectSchema(example[0])]; | ||
} | ||
// TODO -- Parse arrays of arrays | ||
// --- | ||
// Parse arrays of primitives | ||
return [checkTuple(example[0])]; | ||
return [getTypeOfPrimitive(example[0])]; | ||
} | ||
// Otherwise parse the object | ||
return parseObject(example); | ||
return getObjectSchema(example); | ||
} | ||
module.exports = inferPrimitiveType; | ||
module.exports = inferSchema; |
{ | ||
"name": "rttc", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"description": "Runtime type-checking for JavaScript.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -0,6 +1,51 @@ | ||
var util = require('util'); | ||
var assert = require('assert'); | ||
var infer = require('../lib/infer'); | ||
describe('Inferring types from example', function() { | ||
describe('Inferring schema from example', function() { | ||
describe('when an array of primitives is used', function() { | ||
it('should parse an array with a single string', function() { | ||
var arr = ['foo']; | ||
var schema = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert.strictEqual(schema[0], 'string'); | ||
}); | ||
it('should parse an array with a single number', function() { | ||
var arr = [1]; | ||
var schema = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert.strictEqual(schema[0], 'number'); | ||
}); | ||
it('should parse an array with a single `true`', function() { | ||
var arr = [true]; | ||
var schema = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert.strictEqual(schema[0], 'boolean'); | ||
}); | ||
it('should parse an array with a single `false`', function() { | ||
var arr = [false]; | ||
var schema = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert.strictEqual(schema[0], 'boolean'); | ||
}); | ||
}); | ||
describe('when an array of objects is used', function() { | ||
@@ -15,13 +60,13 @@ | ||
var types = infer(arr); | ||
var schema = infer(arr); | ||
assert(Array.isArray(types)); | ||
assert.strictEqual(types.length, 1); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert(types[0].foo); | ||
assert(types[0].bar); | ||
assert(types[0].baz); | ||
assert.strictEqual(types[0].foo, 'string'); | ||
assert.strictEqual(types[0].bar, 'number'); | ||
assert.strictEqual(types[0].baz, 'boolean'); | ||
assert(schema[0].foo); | ||
assert(schema[0].bar); | ||
assert(schema[0].baz); | ||
assert.strictEqual(schema[0].foo, 'string'); | ||
assert.strictEqual(schema[0].bar, 'number'); | ||
assert.strictEqual(schema[0].baz, 'boolean'); | ||
}); | ||
@@ -40,44 +85,179 @@ | ||
var types = infer(arr); | ||
var schema = infer(arr); | ||
assert(Array.isArray(types)); | ||
assert.strictEqual(types.length, 1); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert(types[0].foo); | ||
assert(types[0].bar); | ||
assert(types[0].bar.foo); | ||
assert(types[0].bar.baz); | ||
assert(types[0].bar.baz.foo); | ||
assert(schema[0].foo); | ||
assert(schema[0].bar); | ||
assert(schema[0].bar.foo); | ||
assert(schema[0].bar.baz); | ||
assert(schema[0].bar.baz.foo); | ||
assert.strictEqual(types[0].foo, 'string'); | ||
assert.strictEqual(types[0].bar.foo, 'boolean'); | ||
assert.strictEqual(types[0].bar.baz.foo, 'number'); | ||
assert.strictEqual(schema[0].foo, 'string'); | ||
assert.strictEqual(schema[0].bar.foo, 'boolean'); | ||
assert.strictEqual(schema[0].bar.baz.foo, 'number'); | ||
}); | ||
}); | ||
it('should parse an array with many nested objects', function() { | ||
var arr = [{ | ||
foo: 'bar', | ||
bar: { | ||
foo: false, | ||
baz: { | ||
foo: 3, | ||
bar: { | ||
baz: 'hi' | ||
} | ||
} | ||
} | ||
}]; | ||
describe('when an array of primitives is used', function() { | ||
var schema = infer(arr); | ||
it('should parse an array with a single string', function() { | ||
var arr = ['foo']; | ||
var types = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert(Array.isArray(types)); | ||
assert.strictEqual(types.length, 1); | ||
assert(schema[0].foo); | ||
assert(schema[0].bar); | ||
assert(schema[0].bar.foo); | ||
assert(schema[0].bar.baz); | ||
assert(schema[0].bar.baz.foo); | ||
assert(schema[0].bar.baz.bar); | ||
assert(schema[0].bar.baz.bar.baz); | ||
assert.strictEqual(types[0], 'string'); | ||
assert.strictEqual(schema[0].foo, 'string'); | ||
assert.strictEqual(schema[0].bar.foo, 'boolean'); | ||
assert.strictEqual(schema[0].bar.baz.foo, 'number'); | ||
assert.strictEqual(schema[0].bar.baz.bar.baz, 'string'); | ||
}); | ||
it('should parse an array with a single number', function() { | ||
var arr = [1]; | ||
var types = infer(arr); | ||
assert(Array.isArray(types)); | ||
assert.strictEqual(types.length, 1); | ||
it('should parse an array with a nested array', function() { | ||
var arr = [['foo']]; | ||
assert.strictEqual(types[0], 'number'); | ||
var schema = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert(Array.isArray(schema[0]), 'expected [0] to exist in:'+util.inspect(schema, false, null)); | ||
assert.strictEqual(schema[0].length, 1); | ||
assert(schema[0][0],'expected [0][0] to exist in:'+util.inspect(schema, false, null)); | ||
assert.strictEqual(schema[0][0], 'string'); | ||
}); | ||
it('should parse an array with a nested array of nested objects', function() { | ||
var arr = [ | ||
[{ | ||
foo: { | ||
bar: false, | ||
baz: 235, | ||
mom: { | ||
name: 'Melinda' | ||
} | ||
} | ||
}] | ||
]; | ||
var schema = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert(Array.isArray(schema[0])); | ||
assert.strictEqual(schema[0].length, 1); | ||
assert(schema[0][0].foo); | ||
assert(schema[0][0].foo.bar); | ||
assert(schema[0][0].foo.baz); | ||
assert(schema[0][0].foo.mom); | ||
assert(schema[0][0].foo.mom.name); | ||
assert.strictEqual(schema[0][0].foo.bar, 'boolean'); | ||
assert.strictEqual(schema[0][0].foo.baz, 'number'); | ||
assert.strictEqual(schema[0][0].foo.mom.name, 'string'); | ||
}); | ||
it('should parse an array with many nested objects containing more arrays', function() { | ||
var arr = [{ | ||
foo: 'bar', | ||
bar: { | ||
foo: false, | ||
baz: { | ||
foo: 3, | ||
bar: { | ||
baz: ['hi'] | ||
} | ||
} | ||
} | ||
}]; | ||
var schema = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert(schema[0].foo); | ||
assert(schema[0].bar); | ||
assert(schema[0].bar.foo); | ||
assert(schema[0].bar.baz); | ||
assert(schema[0].bar.baz.foo); | ||
assert(schema[0].bar.baz.bar); | ||
assert(schema[0].bar.baz.bar.baz, 'expected [0].bar.baz.bar.baz to exist in:'+util.inspect(schema, false, null)); | ||
assert(schema[0].bar.baz.bar.baz[0]); | ||
assert.strictEqual(schema[0].foo, 'string'); | ||
assert.strictEqual(schema[0].bar.foo, 'boolean'); | ||
assert.strictEqual(schema[0].bar.baz.foo, 'number'); | ||
assert(Array.isArray(schema[0].bar.baz.bar.baz)); | ||
assert.strictEqual(schema[0].bar.baz.bar.baz.length, 1); | ||
assert.strictEqual(schema[0].bar.baz.bar.baz[0], 'string'); | ||
}); | ||
it('should parse an array with many nested objects containing more arrays of nested objects', function() { | ||
var arr = [{ | ||
foo: 'bar', | ||
bar: { | ||
foo: false, | ||
baz: { | ||
foo: 3, | ||
bar: { | ||
baz: [{ | ||
message: 'hi' | ||
}] | ||
} | ||
} | ||
} | ||
}]; | ||
var schema = infer(arr); | ||
assert(Array.isArray(schema)); | ||
assert.strictEqual(schema.length, 1); | ||
assert(schema[0].foo); | ||
assert(schema[0].bar); | ||
assert(schema[0].bar.foo); | ||
assert(schema[0].bar.baz); | ||
assert(schema[0].bar.baz.foo); | ||
assert(schema[0].bar.baz.bar); | ||
assert(schema[0].bar.baz.bar.baz); | ||
assert(schema[0].bar.baz.bar.baz[0]); | ||
assert(schema[0].bar.baz.bar.baz[0].message); | ||
assert.strictEqual(schema[0].foo, 'string'); | ||
assert.strictEqual(schema[0].bar.foo, 'boolean'); | ||
assert.strictEqual(schema[0].bar.baz.foo, 'number'); | ||
assert(Array.isArray(schema[0].bar.baz.bar.baz)); | ||
assert.strictEqual(schema[0].bar.baz.bar.baz.length, 1); | ||
assert.strictEqual(schema[0].bar.baz.bar.baz[0].message, 'string'); | ||
}); | ||
}); | ||
}); |
@@ -15,10 +15,10 @@ var assert = require('assert'); | ||
var types = infer(obj); | ||
var schema = infer(obj); | ||
assert(types.foo); | ||
assert(types.bar); | ||
assert(types.baz); | ||
assert.strictEqual(types.foo, 'string'); | ||
assert.strictEqual(types.bar, 'number'); | ||
assert.strictEqual(types.baz, 'boolean'); | ||
assert(schema.foo); | ||
assert(schema.bar); | ||
assert(schema.baz); | ||
assert.strictEqual(schema.foo, 'string'); | ||
assert.strictEqual(schema.bar, 'number'); | ||
assert.strictEqual(schema.baz, 'boolean'); | ||
}); | ||
@@ -37,13 +37,13 @@ | ||
var types = infer(obj); | ||
var schema = infer(obj); | ||
assert(types.foo); | ||
assert(types.bar); | ||
assert(types.bar.foo); | ||
assert(types.bar.baz); | ||
assert(types.bar.baz.foo); | ||
assert(schema.foo); | ||
assert(schema.bar); | ||
assert(schema.bar.foo); | ||
assert(schema.bar.baz); | ||
assert(schema.bar.baz.foo); | ||
assert.strictEqual(types.foo, 'string'); | ||
assert.strictEqual(types.bar.foo, 'boolean'); | ||
assert.strictEqual(types.bar.baz.foo, 'number'); | ||
assert.strictEqual(schema.foo, 'string'); | ||
assert.strictEqual(schema.bar.foo, 'boolean'); | ||
assert.strictEqual(schema.bar.baz.foo, 'number'); | ||
}); | ||
@@ -50,0 +50,0 @@ |
@@ -11,2 +11,5 @@ var assert = require('assert'); | ||
assert.strictEqual(type, 'string'); | ||
type = infer(''); | ||
assert.strictEqual(type, 'string'); | ||
}); | ||
@@ -17,2 +20,14 @@ | ||
assert.strictEqual(type, 'number'); | ||
infer(-5); | ||
assert.strictEqual(type, 'number'); | ||
infer(0); | ||
assert.strictEqual(type, 'number'); | ||
infer(5.3); | ||
assert.strictEqual(type, 'number'); | ||
infer(-5.2); | ||
assert.strictEqual(type, 'number'); | ||
}); | ||
@@ -19,0 +34,0 @@ |
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
50006
21
1605