Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

rttc

Package Overview
Dependencies
Maintainers
4
Versions
108
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rttc - npm Package Compare versions

Comparing version 0.5.0 to 0.6.0

10

lib/coerce.js

@@ -9,3 +9,2 @@ /**

/**

@@ -21,8 +20,9 @@ * Coerce value to type schema

// Avoid damaging the provided parameters.
var errors = [];
// Avoid damaging `expected`
expected = _.cloneDeep(expected);
actual = _.cloneDeep(actual);
var errors = [];
var result = validateRecursive(expected, actual, errors);
// Jump into recursive validation
var result = validateRecursive(expected, actual, errors, true);

@@ -29,0 +29,0 @@ // Strip out "E_INVALID_TYPE" errors- they are ok if we're just coercing.

@@ -21,22 +21,4 @@ /**

// NaN
nan: {
is: _.isNaN,
to: function () { return NaN; }
},
// Null
'null': {
is: _.isNull,
to: function () { return null; }
},
// Undefined
'undefined': {
is: _.isUndefined,
to: function () { return undefined; }
},
// Boolean
bool: {
boolean: {
is: _.isBoolean,

@@ -59,3 +41,2 @@ to: function(v) {

},
base: false,
getBase: function (){

@@ -66,28 +47,4 @@ return false;

// Defined
defined: {
is: function(v) {
return !( type.nan.is(v) || type.undefined.is(v) || type.null.is(v) );
},
to: function(v) {
return (type.defined.is(v)) ? v : true;
}
},
// Integer
'int': {
is: function(v) { return (v == v + 0 && v == ~~v); },
to: function(v) {
var value = parseInt(v, 10);
if (!isNaN(value)) return value;
return 1;
},
base: 0,
getBase: function (){
return 0;
}
},
// String
str: {
string: {
is: _.isString,

@@ -134,10 +91,8 @@ to: function(v) {

if(v === null) {
if(_.isNull(v)) {
throw new Error('E_runtimeInputTypeCoercionError');
}
if(type.defined.is(v)) return String(v);
return '';
return String(v);
},
base: '',
getBase: function (){

@@ -148,6 +103,9 @@ return '';

// Object
obj: {
// Dictionary
dictionary: {
is: function(v) {
return _.isObject(v) && !type.arr.is(v);
if (!_.isObject(v)) return false;
if (type.arr.is(v)) return false;
if (!_.isPlainObject(v)) return false;
return true;
},

@@ -161,5 +119,8 @@ to: function(v) {

}
return {};
if (_.isPlainObject(v)){
return v;
}
throw new Error('E_runtimeInputTypeCoercionError');
},
base: {},
getBase: function (){

@@ -170,9 +131,12 @@ return {};

// Array
arr: {
array: {
is: _.isArray,
to: function(v) {
return _.toArray(v);
if (!_.isArray(v)) {
throw new Error('E_runtimeInputTypeCoercionError');
}
return v;
},
base: [],
getBase: function (){

@@ -183,18 +147,6 @@ return [];

// Date
'date': {
is: _.isDate,
to: function(v) {
return new Date(v);
},
base: new Date(),
getBase: function (){
return new Date();
}
},
// Numeric
'number': {
// Nuber
number: {
is: function(v) {
return _.isNumber(v) && !type.nan.is(parseFloat(v)) && v!==Infinity && v!==-Infinity;
return _.isNumber(v) && !_.isNaN(parseFloat(v)) && v!==Infinity && v!==-Infinity;
},

@@ -218,6 +170,7 @@ to: function(v) {

if (_.isObject(v)) return 0;
if(type.number.is(v)) return v;
if(type.bool.is(v)) return v ? 1 : 0;
if(type.str.is(v)) {
if(type.boolean.is(v)) return v ? 1 : 0;
if(type.string.is(v)) {

@@ -243,19 +196,24 @@ // Is this a string that appears to be a number?

// Check for Infinity
if (v === 'Infinity' || v === '-Infinity') {
throw new Error('E_runtimeInputTypeCoercionError');
}
return +v;
}
// // Check for Infinity
// if(v === 'Infinity' || v === '-Infinity') {
// throw new Error('E_runtimeInputTypeCoercionError');
// }
// var num = v * 1;
// if(!_.isNumber(num)) {
// throw new Error('E_runtimeInputTypeCoercionError');
// }
var num = v * 1;
if(!_.isNumber(num)) {
throw new Error('E_runtimeInputTypeCoercionError');
}
// return (num === 0 && !v.match(/^0+$/)) ? 0 : num;
if (_.isNaN(num)) {
return 0;
}
return (num === 0 && !v.match(/^0+$/)) ? 0 : num;
},
base: 0,
getBase: function (){

@@ -271,6 +229,8 @@ return 0;

// Aliases
type.string = type.email = type.url = type.str;
type.boolean = type.bool;
type.str = type.email = type.url = type.string;
type.bool = type.boolean;
type.arr = type.array;
type.integer = type.int;
type.float = type.number;
type.object = type.obj = type.dictionary;

@@ -277,0 +237,0 @@ module.exports = type;

@@ -6,2 +6,3 @@ /**

var util = require('util');
var Stream = require('stream').Stream;
var _ = require('lodash');

@@ -12,3 +13,11 @@ var types = require('./types');

module.exports = function _validateRecursive (expected, actual, errors){
/**
*
* @param {*} expected
* @param {*} actual
* @param {Array} errors [errors encountered along the way are pushed here]
* @param {Boolean} ensureSerializable
* @return {*} coerced value
*/
module.exports = function _validateRecursive (expected, actual, errors, ensureSerializable){

@@ -19,17 +28,36 @@ // Look up expected type from `types` object using `expected`.

var isExpectingDictionary;
var allowAnyArray;
var allowAnyDictionary;
// console.log('\n');
// console.log('expecting:',expected, util.format('(a %s)', getDisplayType(actual)));
// console.log('actual:',require('util').inspect(actual, false, null), require('util').format('(a %s)', getDisplayType(actual)));
function getDisplayType(x){
var displayType;
displayType = typeof x;
try {
displayType = x.constructor.name;
}
catch (e){}
return displayType;
}
// "*" (allow anything)
if (expected === '*'){
// TODO: reconsider this-- might be confusing... probably better just to pass through `undefined`
return _.isUndefined(actual) ? '' : actual;
}
// ["*"] (allow any array)
if (_.isArray(expected) && expected[0] === '*') {
return _.isUndefined(actual) ? [] : actual;
// Normalize: ["*"] or [] or "array" (allow any array)
if (expected === 'array' || (_.isArray(expected) && (expected[0] === '*' || expected.length === 0))) {
expected = ['*'];
allowAnyArray = true;
}
// {} (allow any dictionary)
if (_.isPlainObject(expected) && _.keys(expected).length === 0) {
return _.isUndefined(actual) ? {} : actual;
// Normalize: "dictionary" or {} (allow any dictionary)
if (expected === 'dictionary' || (_.isPlainObject(expected) && _.keys(expected).length === 0)) {
expected = {};
allowAnyDictionary = true;
}
// Arrays

@@ -59,6 +87,55 @@ if (_.isArray(expected)) {

}
}
// Ensure that `actual` is JSON-serializable, unless one of the following is true:
// - the `ensureSerializable` flag is disabled
// - we're expecting a "machine", "buffer", or "stream" and the mystery meat looks right enough
//
// Notes:
// + this can be disabled by setting the `ensureSerializable` argument to false (i.e. for performance)
// + this will strip all functions
// + cloning buffers breaks them-- also it is potentially a huge waste of RAM)
// + cloning streams is a bad idea because it disregards the state they're in, event listeners, etc.)
if (ensureSerializable &&
expected !== 'machine' &&
expected !== 'buffer' &&
expected !== 'stream'
) {
// if (
// // If we're not expecting a buffer, but it looks like we got one, don't serialize it to JSON and back
// // (it will end up looking like an array, which is confusing)
// // !(expected !== 'buffer' && _.isObject(actual) && actual instanceof Buffer)
// ) {
try {
actual = JSON.parse(JSON.stringify(actual));
}
catch (e){
// Push an E_INVALID_TYPE error
errors.push((function (){
var err = new Error(util.format(
'An invalid value was specified: \n' + util.inspect(actual, false, null) + '\n\n' +
'This doesn\'t match the specified type: \n' + util.inspect(expected, false, null)
));
err.code = 'E_INVALID_TYPE';
// if not expecting a dictionary or an array, and actual value is not
// a dictionary or array, then this is just a "minor" thing.
// No big deal, you know.
if (!isExpectingDictionary && !isExpectingArray && !_.isObject(actual)) {
err.minor = true;
}
return err;
})());
actual = {};
}
// }
}
// TODO: probably should clone machine defs as well.
// Default the coercedValue to the actual value.

@@ -69,9 +146,10 @@ var coercedValue = actual;

// appropriate base type.
if(types.undefined.is(actual)) {
if(_.isUndefined(actual)) {
coercedValue = expectedType.getBase();
}
// Check `actual` value against expectedType
// Check `actual` value using `expectedType.is()`
if (!expectedType.is(actual)){
// Push an E_INVALID_TYPE error

@@ -99,2 +177,3 @@ errors.push((function (){

catch (e) {
// If that doesn't work, use the base type:

@@ -115,12 +194,28 @@ coercedValue = expectedType.getBase();

// console.log('coercedValue:',util.inspect(coercedValue, false, null), util.format('(a %s)', (function(){
// var displayType;
// displayType = typeof coercedValue;
// try {
// displayType = coercedValue.constructor.name;
// }
// catch (e){}
// return displayType;
// })()));
// Build partial result
// (taking recursive step if necessary)
if (isExpectingArray) {
if (allowAnyArray){
return coercedValue;
}
var arrayItemTpl = expected[0];
return [_validateRecursive(arrayItemTpl, coercedValue[0], errors)];
return [_validateRecursive(arrayItemTpl, coercedValue[0], errors, ensureSerializable)];
}
if (isExpectingDictionary) {
if (allowAnyDictionary){
return coercedValue;
}
return _.reduce(expected, function (memo, expectedVal, expectedKey) {
console.log('recursively diving into dictionary at key %s...', expectedKey);
memo[expectedKey] = _validateRecursive(expected[expectedKey], coercedValue[expectedKey], errors);
memo[expectedKey] = _validateRecursive(expected[expectedKey], coercedValue[expectedKey], errors, ensureSerializable);
return memo;

@@ -127,0 +222,0 @@ }, {});

@@ -89,2 +89,11 @@ /**

// Ensure empty arrays are not recursively parsed.
if (example.length === 0) {
return [];
}
// Handle special case of [*]
else if (example.length === 1 && example[0] === '*') {
return [];
}
// Parse arrays of arrays

@@ -91,0 +100,0 @@ if (_.isArray(example[0])) {

@@ -79,3 +79,3 @@ /**

// Check if the input is required and missing
if(types.undefined.is(value)) {
if(_.isUndefined(value)) {

@@ -82,0 +82,0 @@ if (input.required) {

@@ -23,6 +23,5 @@ /**

expected = _.cloneDeep(expected);
actual = _.cloneDeep(actual);
var errors = [];
var result = validateRecursive(expected, actual, errors);
var result = validateRecursive(expected, actual, errors, true);

@@ -33,3 +32,9 @@ if (errors.length) {

err.code = errors[0].code;
err.minor = errors[0].minor;
// If any of the errors are not "minor", then this is not a "minor" error.
err.minor = _.reduce(errors, function(memo, subError) {
if (!memo || !subError.minor) {
return false;
}
return true;
}, true);
err.errors = errors;

@@ -36,0 +41,0 @@ return err;

{
"name": "rttc",
"version": "0.5.0",
"version": "0.6.0",
"description": "Runtime type-checking for JavaScript.",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc