Comparing version 0.5.0 to 0.6.1
Version history | ||
=============== | ||
### 0.6.1 (2012-08-19) ### | ||
* Minor bugfixes | ||
### 0.6.0 (2012-08-18) ### | ||
* Support for general purpose referencing (with JSON Schema serialization/deserialization) | ||
* Property description support | ||
* Splitting out random generation into a separate library (molnarg/random.js) | ||
* Removal of the premature compilation system (optimizations will reappear in a future release) | ||
* Cleaner codebase | ||
* Js-schema is now self-contained: it has no dependencies | ||
* Reduced size: 15kb -> 5kb (minified and gzipped) | ||
### 0.5.0 (2012-06-27) ### | ||
@@ -5,0 +17,0 @@ * Support for self-referencing |
module.exports = require('./lib/schema') | ||
// Core schemas | ||
// Patterns | ||
require('./lib/patterns/reference') | ||
@@ -12,2 +12,3 @@ require('./lib/patterns/nothing') | ||
require('./lib/patterns/class') | ||
require('./lib/patterns/schema') | ||
@@ -21,1 +22,2 @@ // Extensions | ||
require('./lib/extensions/Function') | ||
require('./lib/extensions/Schema') |
@@ -1,95 +0,55 @@ | ||
var schema = require('../schema') | ||
var Schema = require('../Schema') | ||
, EqualitySchema = require('../patterns/equality') | ||
, anything = require('../patterns/anything') | ||
, _ = require('underscore') | ||
, RandExp = require('randexp') | ||
, anything = require('../patterns/anything').instance | ||
var ArraySchema = module.exports = function(itemSchema, max, min) { | ||
this.itemSchema = itemSchema || anything | ||
this.min = min || 0 | ||
this.max = max || Infinity | ||
return new schema(this) | ||
} | ||
var ArraySchema = module.exports = Schema.extensions.ArraySchema = Schema.extend({ | ||
initialize : function(itemSchema, max, min) { | ||
this.itemSchema = itemSchema || anything | ||
this.min = min || 0 | ||
this.max = max || Infinity | ||
}, | ||
ArraySchema.prototype = { | ||
compile : function() { | ||
var compiled = { } | ||
validate : function(instance) { | ||
// Instance must be an instance of Array | ||
compiled.fn = 'if (!(instance instanceof Array)) return false;' | ||
if (!(instance instanceof Array)) return false | ||
// Checking length | ||
if (this.min > 0 || this.max < Infinity) { | ||
var checks = [] | ||
if (this.min === this.max) { | ||
checks.push('instance.length !== ' + this.min) | ||
} else { | ||
if (this.min > 0 ) checks.push('instance.length < ' + this.min) | ||
if (this.max < Infinity) checks.push('instance.length > ' + this.max) | ||
} | ||
compiled.fn += 'if (' + checks.join(' || ') + ') return false;' | ||
if (this.min === this.max) { | ||
if (instance.length !== this.min) return false | ||
} else { | ||
if (this.min > 0 && instance.length < this.min) return false | ||
if (this.max < Infinity && instance.length > this.max) return false | ||
} | ||
// Checking conformance to the given item schema | ||
if (this.itemSchema !== anything) { | ||
compiled.references = [this.itemSchema] | ||
compiled.fn += 'for (var i = 0; i < instance.length; i++) {' | ||
+ ' if (!{0}(instance[i])) return false;' | ||
+ '}' | ||
for (var i = 0; i < instance.length; i++) { | ||
if (!this.itemSchema.validate(instance[i])) return false; | ||
} | ||
// If every check passes, return true | ||
compiled.fn += 'return true;' | ||
return compiled | ||
return true | ||
}, | ||
generate : function() { | ||
var array = [] | ||
while (array.length < this.min || (array.length < this.max && Math.random() < 0.666)) { | ||
array.push(this.itemSchema.generate()) | ||
} | ||
return array | ||
}, | ||
leafs : function() { | ||
var item_leafs = this.itemSchema.leafs ? this.itemSchema.leafs() | ||
: { certain : [ this.itemSchema ], uncertain : [] } | ||
if (this.min > 0) return item_leafs | ||
return { certain : [] | ||
, uncertain : _.union(item_leafs.certain, item_leafs.uncertain) | ||
} | ||
}, | ||
getId : function() { | ||
if (!this.id) this.id = new RandExp(/^[a-zA-Z]{4,6}$/).gen() | ||
return this.id | ||
}, | ||
toJSON : function() { | ||
var schema = { type : 'array' } | ||
if (this.min > 0 ) schema.minItems = this.min | ||
if (this.max < Infinity) schema.maxItems = this.max | ||
if (this.itemSchema !== anything) schema.items = this.itemSchema.toJSON() | ||
if (this.id) schema.id = this.id | ||
return schema | ||
} | ||
} | ||
schema.fromJSON.def(function(sch) { | ||
toJSON : Schema.session(function() { | ||
var json = Schema.prototype.toJSON.call(this, true) | ||
if (json['$ref'] != null) return json | ||
json.tpye = 'array' | ||
if (this.min > 0) json.minItems = this.min | ||
if (this.max < Infinity) json.maxItems = this.max | ||
if (this.itemSchema !== anything) json.items = this.itemSchema.toJSON() | ||
return json | ||
}) | ||
}) | ||
Schema.fromJSON.def(function(sch) { | ||
if (!sch || sch.type !== 'array') return | ||
// Tuple typing is not yet supported | ||
if (sch.items instanceof Array) return | ||
return new ArraySchema(schema.fromJSON(sch.items), sch.maxItems, sch.minItems) | ||
return new ArraySchema(Schema.fromJSON(sch.items), sch.maxItems, sch.minItems) | ||
}) | ||
@@ -101,12 +61,11 @@ | ||
// (minLength, maxLength, schema) | ||
var args = Array.prototype.reverse.call(arguments) | ||
var args = Array.prototype.slice.call(arguments).reverse() | ||
if (args.length === 2) args[2] = args[1] | ||
return new ArraySchema(schema.fromJS(args[0]), args[1], args[2]) | ||
return new ArraySchema(Schema.fromJS(args[0]), args[1], args[2]).wrap() | ||
} | ||
Array.like = function(other) { | ||
return new EqualitySchema(other) | ||
return new EqualitySchema(other).wrap() | ||
} | ||
Array.schema = new ArraySchema() | ||
Array.schema = new ArraySchema().wrap() |
@@ -1,11 +0,7 @@ | ||
var schema = require('../schema') | ||
var Schema = require('../Schema') | ||
var booleanSchema = module.exports = new schema({ | ||
compile : function() { | ||
return { expression : 'Object(instance) instanceof Boolean' } | ||
var BooleanSchema = module.exports = Schema.extensions.BooleanSchema = new Schema.extend({ | ||
validate : function(instance) { | ||
return Object(instance) instanceof Boolean | ||
}, | ||
generate : function() { | ||
return Math.random() < 0.5 | ||
}, | ||
@@ -17,5 +13,7 @@ toJSON : function() { | ||
schema.fromJSON.def(function(sch) { | ||
var booleanSchema = module.exports = new BooleanSchema().wrap() | ||
Schema.fromJSON.def(function(sch) { | ||
if (!sch || sch.type !== 'boolean') return | ||
return booleanSchema | ||
@@ -22,0 +20,0 @@ }) |
var ReferenceSchema = require('../patterns/reference') | ||
, ClassSchema = require('../patterns/class') | ||
// Function creation is not possible the way patterns/class.js does, | ||
// so overriding it here | ||
Function.schema = new ClassSchema(Function) | ||
Function.schema.generate = function() { | ||
return function() {} | ||
} | ||
Function.reference = function(f) { | ||
return new ReferenceSchema(f) | ||
return new ReferenceSchema(f).wrap() | ||
} |
@@ -1,122 +0,82 @@ | ||
var schema = require('../schema') | ||
var Schema = require('../Schema') | ||
var NumberSchema = module.exports = function(minimum, exclusiveMinimum, maximum, exclusiveMaximum, divisibleBy) { | ||
this.minimum = minimum != null ? minimum : -Infinity | ||
this.exclusiveMinimum = exclusiveMinimum | ||
this.maximum = minimum != null ? maximum : Infinity | ||
this.exclusiveMaximum = exclusiveMaximum | ||
this.divisibleBy = divisibleBy || 0 | ||
return new schema(this) | ||
} | ||
var NumberSchema = module.exports = Schema.extensions.NumberSchema = Schema.extend({ | ||
initialize : function(minimum, exclusiveMinimum, maximum, exclusiveMaximum, divisibleBy) { | ||
this.minimum = minimum != null ? minimum : -Infinity | ||
this.exclusiveMinimum = exclusiveMinimum | ||
this.maximum = minimum != null ? maximum : Infinity | ||
this.exclusiveMaximum = exclusiveMaximum | ||
this.divisibleBy = divisibleBy || 0 | ||
}, | ||
NumberSchema.prototype = { | ||
min : function(minimum) { | ||
return new NumberSchema(minimum, false, this.maximum, this.exclusiveMaximum, this.divisibleBy) | ||
return new NumberSchema( minimum, false | ||
, this.maximum, this.exclusiveMaximum | ||
, this.divisibleBy | ||
).wrap() | ||
}, | ||
above : function(minimum) { | ||
return new NumberSchema(minimum, true, this.maximum, this.exclusiveMaximum, this.divisibleBy) | ||
return new NumberSchema( minimum, true | ||
, this.maximum, this.exclusiveMaximum | ||
, this.divisibleBy | ||
).wrap() | ||
}, | ||
max : function(maximum) { | ||
return new NumberSchema(this.minimum, this.exclusiveMinimum, maximum, false, this.divisibleBy) | ||
return new NumberSchema( this.minimum, this.exclusiveMinimum | ||
, maximum, false | ||
, this.divisibleBy | ||
).wrap() | ||
}, | ||
below : function(maximum) { | ||
return new NumberSchema(this.minimum, this.exclusiveMinimum, maximum, true, this.divisibleBy) | ||
return new NumberSchema( this.minimum, this.exclusiveMinimum | ||
, maximum, true | ||
, this.divisibleBy | ||
).wrap() | ||
}, | ||
step : function(divisibleBy) { | ||
return new NumberSchema(this.minimum, this.exclusiveMinimum, this.maximum, this.exclusiveMaximum, divisibleBy) | ||
return new NumberSchema( this.minimum, this.exclusiveMinimum | ||
, this.maximum, this.exclusiveMaximum | ||
, divisibleBy | ||
).wrap() | ||
}, | ||
compile : function() { | ||
var references = [this.minimum, this.maximum, this.divisibleBy] | ||
, checks = ['Object(instance) instanceof Number'] | ||
if (this.minimum !== -Infinity) { | ||
checks.push('instance ' + (this.exclusiveMinimum ? '>' : '>=') + ' {0}') | ||
} | ||
if (this.maximum !== Infinity) { | ||
checks.push('instance ' + (this.exclusiveMaximum ? '<' : '<=') + ' {1}') | ||
} | ||
if (this.divisibleBy !== 0) { | ||
checks.push('instance % {2} === 0') | ||
} | ||
return { references : references, expression : checks.join(' && ') } | ||
publicFunctions : [ 'min', 'above', 'max', 'below', 'step' ], | ||
validate : function(instance) { | ||
return (Object(instance) instanceof Number) && | ||
(this.exclusiveMinimum ? instance > this.minimum | ||
: instance >= this.minimum) && | ||
(this.exclusiveMaximum ? instance < this.maximum | ||
: instance <= this.maximum) && | ||
(this.divisibleBy === 0 || instance % this.divisibleBy === 0) | ||
}, | ||
generate : function() { | ||
var length, random | ||
, min = this.minimum | ||
, max = this.maximum | ||
, step = this.divisibleBy | ||
// If there's no declared maximum or minimum then assigning a reasonable value | ||
if (min === -Infinity || max === Infinity) { | ||
length = 10 | ||
while (Math.random() < 0.5) length = length * 10 | ||
toJSON : function() { | ||
var json = Schema.prototype.toJSON.call(this) | ||
if (min === -Infinity && max === Infinity) { | ||
min = length / -2 | ||
max = length / +2 | ||
} else if (min === -Infinity) { | ||
min = max - length | ||
} else if (max === Infinity) { | ||
max = min + length | ||
} | ||
} | ||
// Choosing random number from a continuous set | ||
if (step === 0) { | ||
length = max - min | ||
do { | ||
random = min + Math.random()*length | ||
} while ((this.exclusiveMinimum && random === min) || (this.exclusiveMaximum && random === max)) | ||
// Choosing random number from a discrete set | ||
} else { | ||
min = Math.ceil(min / step) * step | ||
max = Math.floor(max / step) * step | ||
if (this.exclusiveMinimum && min === this.minimum) min += step | ||
if (this.exclusiveMaximum && max === this.maximum) max -= step | ||
if (min > max) return undefined | ||
length = Math.round((max - min) / step) + 1 | ||
random = min + step * Math.floor(Math.random()*length) | ||
} | ||
return random | ||
}, | ||
json.type = ( this.divisibleBy !== 0 && this.divisibleBy % 1 === 0 ) ? 'integer' : 'number' | ||
toJSON : function() { | ||
var step = this.divisibleBy | ||
, integer = ( step !== 0 && step === Math.floor(step) ) | ||
, schema = { type : integer ? 'integer' : 'number' } | ||
if (step !== 0 && step !== 1) schema.divisibleBy = step | ||
if (this.divisibleBy !== 0 && this.divisibleBy !== 1) json.divisibleBy = this.divisibleBy | ||
if (this.minimum !== -Infinity) { | ||
schema.minimum = this.minimum | ||
if (this.exclusiveMinimum === true) schema.exclusiveMinimum = true | ||
json.minimum = this.minimum | ||
if (this.exclusiveMinimum === true) json.exclusiveMinimum = true | ||
} | ||
if (this.maximum !== Infinity) { | ||
schema.maximum = this.maximum | ||
if (this.exclusiveMaximum === true) schema.exclusiveMaximum = true | ||
json.maximum = this.maximum | ||
if (this.exclusiveMaximum === true) json.exclusiveMaximum = true | ||
} | ||
return schema | ||
return json | ||
} | ||
} | ||
}) | ||
schema.fromJSON.def(function(sch) { | ||
Schema.fromJSON.def(function(sch) { | ||
if (!sch || (sch.type !== 'number' && sch.type !== 'integer')) return | ||
return new NumberSchema( sch.minimum, sch.exclusiveMinimum | ||
@@ -128,3 +88,3 @@ , sch.maximum, sch.exclusiveMaximum | ||
Number.schema = new NumberSchema() | ||
Number.schema = new NumberSchema().wrap() | ||
Number.min = Number.schema.min | ||
@@ -131,0 +91,0 @@ Number.above = Number.schema.above |
@@ -6,9 +6,9 @@ var ReferenceSchema = require('../patterns/reference') | ||
Object.like = function(other) { | ||
return new EqualitySchema(other) | ||
return new EqualitySchema(other).wrap() | ||
} | ||
Object.reference = function(o) { | ||
return new ReferenceSchema(o) | ||
return new ReferenceSchema(o).wrap() | ||
} | ||
Object.schema = new ObjectSchema() | ||
Object.schema = new ObjectSchema().wrap() |
@@ -7,3 +7,3 @@ var RegexpSchema = require('../patterns/regexp') | ||
// (minLength, maxLength, charset) | ||
var args = Array.prototype.reverse.call(arguments) | ||
var args = Array.prototype.slice.call(arguments).reverse() | ||
, charset = args[0] ? ('[' + args[0] + ']') : '[a-zA-Z0-9]' | ||
@@ -13,6 +13,6 @@ , max = args[1] | ||
, regexp = '^' + charset + '{' + (min || 0) + ',' + (max || '') + '}$' | ||
return new RegexpSchema(RegExp(regexp)) | ||
return new RegexpSchema(RegExp(regexp)).wrap() | ||
} | ||
String.schema = new RegexpSchema() | ||
String.schema = new RegexpSchema().wrap() |
@@ -1,13 +0,7 @@ | ||
var schema = require('../schema') | ||
, nothing = require('./nothing') | ||
var Schema = require('../Schema') | ||
var anything = module.exports = new schema({ | ||
compile : function() { | ||
return { expression : 'instance != null' } | ||
var AnythingSchema = module.exports = Schema.patterns.AnythingSchema = Schema.extend({ | ||
validate : function(instance) { | ||
return instance != null | ||
}, | ||
generate : function() { | ||
var type = [nothing, Boolean, Number, String, Array, Object][Math.floor(Math.random()*6)] | ||
return type.schema.generate() | ||
}, | ||
@@ -19,8 +13,10 @@ toJSON : function() { | ||
schema.fromJS.def(function(sch) { | ||
var anything = AnythingSchema.instance = new AnythingSchema() | ||
Schema.fromJS.def(function(sch) { | ||
if (sch === undefined) return anything | ||
}) | ||
schema.fromJSON.def(function(sch) { | ||
Schema.fromJSON.def(function(sch) { | ||
if (sch.type === 'any') return anything | ||
}) |
@@ -1,28 +0,19 @@ | ||
var schema = require('../schema') | ||
var Schema = require('../Schema') | ||
var ClassSchema = module.exports = function(constructor) { | ||
this.constructor = constructor | ||
return new schema(this) | ||
} | ||
var ClassSchema = module.exports = Schema.patterns.ClassSchema = Schema.extend({ | ||
initialize : function(constructor) { | ||
this.constructor = constructor | ||
}, | ||
ClassSchema.prototype = { | ||
compile : function() { | ||
return { references : [this.constructor], expression : 'instance instanceof {0}' } | ||
}, | ||
generate : function() { | ||
var Constructor = function() {} | ||
Constructor.prototype = this.constructor.prototype | ||
return new Constructor() | ||
validate : function(instance) { | ||
return instance instanceof this.constructor | ||
} | ||
} | ||
}) | ||
schema.fromJS.def(function(constructor) { | ||
Schema.fromJS.def(function(constructor) { | ||
if (!(constructor instanceof Function)) return | ||
if (constructor.schema instanceof Function) { | ||
return constructor.schema | ||
return constructor.schema.unwrap() | ||
} else { | ||
@@ -29,0 +20,0 @@ return new ClassSchema(constructor) |
@@ -1,2 +0,2 @@ | ||
var schema = require('../schema') | ||
var Schema = require('../Schema') | ||
@@ -7,11 +7,9 @@ // Object deep equality | ||
if (Object(a) !== a || Object(b) !== b) return a === b | ||
// both a and b must be Array, or none of them | ||
if ((a instanceof Array && !(b instanceof Array)) || (!(a instanceof Array) && b instanceof Array)) { | ||
return false | ||
} | ||
if ((a instanceof Array) !== (b instanceof Array)) return false | ||
// they must have the same number of properties | ||
if (Object.keys(a).length !== Object.keys(b).length) return false | ||
// and every property should be equal | ||
@@ -21,3 +19,3 @@ for (var key in a) { | ||
} | ||
// if every check succeeded, they are deep equal | ||
@@ -27,21 +25,23 @@ return true | ||
var EqualitySchema = module.exports = function(object) { | ||
this.object = object | ||
return new schema(this) | ||
} | ||
var EqualitySchema = module.exports = Schema.patterns.EqualitySchema = Schema.extend({ | ||
initialize : function(object) { | ||
this.object = object | ||
}, | ||
EqualitySchema.prototype = { | ||
validate : function(instance) { | ||
return equal(instance, this.object) | ||
}, | ||
toJSON : function() { | ||
return { 'enum' : [this.object] } | ||
var json = Schema.prototype.toJSON.call(this) | ||
json['enum'] = [this.object] | ||
return json | ||
} | ||
} | ||
}) | ||
schema.fromJS.def(function(sch) { | ||
Schema.fromJS.def(function(sch) { | ||
if (sch instanceof Array && sch.length === 1) return new EqualitySchema(sch[0]) | ||
}) |
@@ -1,12 +0,8 @@ | ||
var schema = require('../schema') | ||
var Schema = require('../Schema') | ||
var nothing = module.exports = new schema({ | ||
compile : function() { | ||
return { expression : 'instance == null' } | ||
var NothingSchema = module.exports = Schema.patterns.NothingSchema = Schema.extend({ | ||
validate : function(instance) { | ||
return instance == null | ||
}, | ||
generate : function() { | ||
return Math.random() < 0.5 ? null : undefined | ||
}, | ||
toJSON : function() { | ||
@@ -17,8 +13,10 @@ return { type : 'null' } | ||
schema.fromJS.def(function(sch) { | ||
var nothing = NothingSchema.instance = new NothingSchema() | ||
Schema.fromJS.def(function(sch) { | ||
if (sch === null) return nothing | ||
}) | ||
schema.fromJSON.def(function(sch) { | ||
Schema.fromJSON.def(function(sch) { | ||
if (sch.type === 'null') return nothing | ||
}) |
@@ -1,152 +0,68 @@ | ||
var schema = require('../schema') | ||
, RandExp = require('randexp') | ||
, utils = require('../utils') | ||
, anything = require('./anything') | ||
, nothing = require('./nothing') | ||
, _ = require('underscore') | ||
var Schema = require('../Schema') | ||
, anything = require('./anything').instance | ||
, nothing = require('./nothing').instance | ||
var ObjectSchema = module.exports = function(properties, other) { | ||
var self = this | ||
this.other = other || anything | ||
this.properties = properties || [] | ||
// Sorting properties into two groups | ||
this.stringProps = {}, this.regexpProps = [] | ||
this.properties.forEach(function(property) { | ||
if (typeof property.key === 'string') { | ||
self.stringProps[property.key] = property | ||
} else { | ||
self.regexpProps.push(property) | ||
} | ||
}) | ||
return new schema(this) | ||
} | ||
var ObjectSchema = module.exports = Schema.patterns.ObjectSchema = Schema.extend({ | ||
initialize : function(properties, other) { | ||
var self = this | ||
ObjectSchema.prototype = { | ||
compile : function() { | ||
var checks = ['instance != null'] | ||
, references = [] | ||
, ref = utils.referenceHandler(references) | ||
this.other = other || anything | ||
this.properties = properties || [] | ||
// Sorting properties into two groups | ||
this.stringProps = {}, this.regexpProps = [] | ||
this.properties.forEach(function(property) { | ||
if (typeof property.key === 'string') { | ||
self.stringProps[property.key] = property | ||
} else { | ||
self.regexpProps.push(property) | ||
} | ||
}) | ||
}, | ||
validate : function(instance) { | ||
var self = this | ||
if (instance == null) return false | ||
// Simple string properties | ||
var check | ||
for (var key in this.stringProps) { | ||
check = '{schema}(instance[{key}])'.replace('{schema}', ref(this.stringProps[key].value)) | ||
.replace('{key}', ref(key)) | ||
if (this.stringProps[key].min === 0) { | ||
check = '(instance[{key}] === undefined || {check})'.replace('{key}', ref(key)) | ||
.replace('{check}', check) | ||
} | ||
checks.push(check) | ||
} | ||
if (!this.regexpProps.length && this.other === anything) { | ||
return { references : references, expression : checks.join(' && ') } | ||
} | ||
var stringPropsValid = Object.keys(this.stringProps).every(function(key) { | ||
return (self.stringProps[key].min === 0 && !(key in instance)) || | ||
(self.stringProps[key].value.validate(instance[key])) | ||
}) | ||
if (!stringPropsValid) return false | ||
// If there are no RegExp and other validator, that's all | ||
if (!this.regexpProps.length && this.other === anything) return true | ||
// Regexp and other properties | ||
var stringPropNames = Object.keys(this.stringProps) | ||
var fn = 'if (!( {checks} )) return false;'.replace('{checks}', checks.join(' && ')) | ||
if (this.other !== anything) fn += 'var checked;' | ||
// Iterating over the keys in the instance | ||
fn += 'for (var key in instance) {' | ||
var checked | ||
for (var key in instance) { | ||
// Checking the key against every key regexps | ||
if (this.other !== anything) fn += 'checked = false;' | ||
for (var i = 0; i < this.regexpProps.length; i++) { | ||
if (this.other !== anything) { | ||
check = 'if (({regexp}.test(key) && (checked = true)) && !{schema}(instance[key])) return false;' | ||
} else { | ||
check = 'if ({regexp}.test(key) && !{schema}(instance[key])) return false;' | ||
} | ||
fn += check.replace('{regexp}', ref(this.regexpProps[i].key)) | ||
.replace('{schema}', ref(this.regexpProps[i].value)) | ||
} | ||
// If the key is not matched by regexps and by simple string checks, check it against this.other | ||
if (this.other !== anything) { | ||
check = 'if (!checked && {stringProps}.indexOf(key) === -1 && !{other}(instance[key])) return false;' | ||
fn += check.replace('{stringProps}', ref(stringPropNames)) | ||
.replace('{other}', ref(this.other)) | ||
} | ||
fn += '}' | ||
// Iteration ends | ||
checked = false | ||
var regexpPropsValid = Object.keys(this.regexpProps).every(function(key) { | ||
return (!self.regexpProps[key].key.test(key) || | ||
((checked = true) && self.regexpProps[key].value.validate(instance[key])) | ||
) | ||
}) | ||
if (!regexpPropsValid) return false | ||
// If the key is not matched by regexps and by simple string checks | ||
// then check it against this.other | ||
if (!checked && !(key in this.stringProps) && !this.other.validate(instance[key])) return false | ||
} | ||
// If all checks passed, the instance conforms to the schema | ||
fn += 'return true;' | ||
return { references : references, fn : fn } | ||
return true | ||
}, | ||
generate : function() { | ||
var object = {} | ||
for (var key in this.stringProps) { | ||
if (this.stringProps[key].min === 1 || Math.random() < 0.5) { | ||
object[key] = this.stringProps[key].value.generate() | ||
} | ||
} | ||
var n, property, randexp | ||
for (var i = 0; i < this.regexpProps.length; i++) { | ||
property = this.regexpProps[i] | ||
n = Object.keys(object).filter(function(ikey){ return property.key.test(ikey) }).length | ||
randexp = new RandExp(property.key) | ||
while (n < property.min || (n < property.max && Math.random() < 0.5)) { | ||
key = randexp.gen() | ||
if (key in object) continue | ||
object[key] = property.value.generate() | ||
n += 1 | ||
} | ||
} | ||
toJSON : Schema.session(function() { | ||
var i, property, regexp, json = Schema.prototype.toJSON.call(this, true) | ||
if (this.other !== nothing) { | ||
while (Math.random() < 0.5) { | ||
key = String.schema.generate() | ||
if (!(key in object)) object[key] = this.other.generate() | ||
} | ||
} | ||
if (json['$ref'] != null) return json | ||
return object | ||
}, | ||
leafs : function() { | ||
var certain = [], uncertain = [] | ||
this.properties.forEach(function(property) { | ||
var property_leafs = property.value.leafs ? property.value.leafs() | ||
: { certain : [ property.value ], uncertain : [] } | ||
if (property.min > 0) { | ||
certain.push(property_leafs.certain) | ||
uncertain.push(property_leafs.uncertain) | ||
} else { | ||
uncertain.push(property_leafs.uncertain) | ||
uncertain.push(property_leafs.certain) | ||
} | ||
}) | ||
return { certain : _.union.apply(null, certain) | ||
, uncertain : _.union.apply(null, uncertain.concat([this.other])) | ||
} | ||
}, | ||
getId : function() { | ||
if (!this.id) this.id = new RandExp(/^[a-zA-Z]{4,6}$/).gen() | ||
return this.id | ||
}, | ||
toJSON : function() { | ||
var i, property, regexp, json = { type : 'object' } | ||
json.type = 'object' | ||
for (i in this.stringProps) { | ||
@@ -157,4 +73,5 @@ property = this.stringProps[i] | ||
if (property.min === 1) json.properties[property.key].required = true | ||
if (property.title) json.properties[property.key].title = property.title | ||
} | ||
for (i = 0; i < this.regexpProps.length; i++) { | ||
@@ -166,13 +83,12 @@ property = this.regexpProps[i] | ||
json.patternProperties[regexp] = property.value.toJSON() | ||
if (property.title) json.patternProperties[regexp].title = property.title | ||
} | ||
if (this.other !== anything) { | ||
json.additionalProperties = (this.other === nothing) ? false : this.other.toJSON() | ||
} | ||
if (this.id) json.id = this.id | ||
return json | ||
} | ||
} | ||
}) | ||
}) | ||
@@ -190,6 +106,6 @@ // Testing if a given string is a real regexp or just a single string escaped | ||
}) | ||
return function(string) { | ||
var i, j, match | ||
for (i = 0; i < shouldBeEscaped.length; i++) { | ||
@@ -211,3 +127,3 @@ match = string.match(shouldBeEscaped[i]) | ||
} | ||
// It is not a real regexp. Removing the escaping. | ||
@@ -219,3 +135,3 @@ for (i = 0; i < shouldBeEscaped.length; i++) { | ||
} | ||
return string | ||
@@ -225,52 +141,62 @@ } | ||
schema.fromJS.def(function(object) { | ||
Schema.fromJS.def(function(object) { | ||
if (!(object instanceof Object)) return | ||
var first, min, max, value, properties = [], other | ||
var other, property, properties = [] | ||
for (var key in object) { | ||
value = schema.fromJS(object[key]) | ||
property = { value : Schema.fromJS(object[key]) } | ||
// '*' as property name means 'every other property should match this schema' | ||
if (key === '*') { | ||
other = value | ||
other = property.value | ||
continue | ||
} | ||
first = key[0] | ||
min = (first === '*' || first === '?') ? 0 : 1 | ||
max = (first === '*' || first === '+') ? Infinity : 1 | ||
if (first === '*' || first === '?' || first === '+') key = key.substr(1) | ||
key = regexpString(key) | ||
properties.push({ min : min, max : max, key : key, value : value }) | ||
// Handling special chars at the beginning of the property name | ||
property.min = (key[0] === '*' || key[0] === '?') ? 0 : 1 | ||
property.max = (key[0] === '*' || key[0] === '+') ? Infinity : 1 | ||
key = key.replace(/^[*?+]/, '') | ||
// Handling property title that looks like: { 'a : an important property' : Number } | ||
key = key.replace(/\s*:[^:]+$/, function(match) { | ||
property.title = match.replace(/^\s*:\s*/, '') | ||
return '' | ||
}) | ||
// Testing if it is regexp-like or not. If it is, then converting to a regexp object | ||
property.key = regexpString(key) | ||
properties.push(property) | ||
} | ||
return new ObjectSchema(properties, other) | ||
}) | ||
schema.fromJSON.def(function(sch) { | ||
if (!sch || sch.type !== 'object') return | ||
Schema.fromJSON.def(function(json) { | ||
if (!json || json.type !== 'object') return | ||
var key, properties = [] | ||
for (key in sch.properties) { | ||
properties.push({ min : sch.properties[key].required ? 1 : 0 | ||
for (key in json.properties) { | ||
properties.push({ min : json.properties[key].required ? 1 : 0 | ||
, max : 1 | ||
, key : key | ||
, value : schema.fromJSON(sch.properties[key]) | ||
, value : Schema.fromJSON(json.properties[key]) | ||
, title : json.properties[key].title | ||
}) | ||
} | ||
for (key in sch.patternProperties) { | ||
for (key in json.patternProperties) { | ||
properties.push({ min : 0 | ||
, max : Infinity | ||
, key : RegExp('^' + key + '$') | ||
, value : schema.fromJSON(sch.properties[key]) | ||
, value : Schema.fromJSON(json.patternProperties[key]) | ||
, title : json.patternProperties[key].title | ||
}) | ||
} | ||
var other | ||
if (sch.additionalProperties !== undefined) { | ||
other = sch.additionalProperties === false ? nothing : schema.fromJSON(sch.additionalProperties) | ||
if (json.additionalProperties !== undefined) { | ||
other = json.additionalProperties === false ? nothing : Schema.fromJSON(json.additionalProperties) | ||
} | ||
return new ObjectSchema(properties, other) | ||
}) |
@@ -1,82 +0,50 @@ | ||
var schema = require('../schema') | ||
var Schema = require('../Schema') | ||
, EqualitySchema = require('../patterns/equality') | ||
, _ = require('underscore') | ||
, RandExp = require('randexp') | ||
var OrSchema = module.exports = function(schemas) { | ||
this.schemas = schemas | ||
return new schema(this) | ||
} | ||
var OrSchema = module.exports = Schema.patterns.OrSchema = Schema.extend({ | ||
initialize : function(schemas) { | ||
this.schemas = schemas | ||
}, | ||
OrSchema.prototype = { | ||
compile : function() { | ||
var compiled = { references : this.schemas.slice() } | ||
var checks = this.schemas.map(function(sch, i) { return '{' + i + '}(instance)' }) | ||
compiled.expression = checks.join(' || ') | ||
return compiled | ||
validate : function(instance) { | ||
return this.schemas.some(function(sch) { | ||
return sch.validate(instance) | ||
}) | ||
}, | ||
generate : function() { | ||
return this.schemas[Math.floor(Math.random()*this.schemas.length)].generate() | ||
}, | ||
leafs : function() { | ||
// Certain and uncertain leafs of subschemas | ||
var subschema_leafs = this.schemas.map(function(sub) { | ||
return sub.leafs ? sub.leafs() | ||
: { certain : [ sub ], uncertain : [] } | ||
}) | ||
subschema_leafs.certain = subschema_leafs.map(function(leafs){ return leafs.certain }) | ||
subschema_leafs.uncertain = subschema_leafs.map(function(leafs){ return leafs.uncertain }) | ||
// If some leaf appears in all subschemas as certain then it is certain. Otherwise uncertain. | ||
var all = _.union.apply(null, subschema_leafs.certain.concat(subschema_leafs.uncertain)) | ||
var certain = _.intersection.apply(null, subschema_leafs.certain) | ||
var uncertain = _.difference(all, certain) | ||
return { certain : certain, uncertain : uncertain } | ||
}, | ||
getId : function() { | ||
if (!this.id) this.id = new RandExp(/^[a-zA-Z]{4,6}$/).gen() | ||
return this.id | ||
}, | ||
toJSON : function() { | ||
var jsons = this.schemas.map(schema.toJSON) | ||
var onlyEquality = true | ||
for (var i = 0; i < jsons.length; i++) { | ||
if (!(jsons[i]['enum'] instanceof Array && jsons[i]['enum'].length === 1)) { | ||
onlyEquality = false | ||
break | ||
} | ||
toJSON : Schema.session(function() { | ||
var json = Schema.prototype.toJSON.call(this, true) | ||
, subjsons = this.schemas.map(function(sch) { return sch.toJSON() }) | ||
, onlyEquality = subjsons.every(function(json) { | ||
return json['enum'] instanceof Array && json['enum'].length === 1 | ||
}) | ||
if (json['$ref'] != null) return json | ||
if (onlyEquality) { | ||
json['enum'] = subjsons.map(function(json) { | ||
return json['enum'][0] | ||
}) | ||
} else { | ||
json['type'] = subjsons.map(function(json) { | ||
var simpleType = typeof json.type === 'string' && Object.keys(json).length === 1 | ||
return simpleType ? json.type : json | ||
}) | ||
} | ||
if (onlyEquality) return { 'enum' : jsons.map(function(json) { return json['enum'][0] }) } | ||
var json = { 'type' : jsons.map(function(json) { | ||
var simpleType = typeof json.type === 'string' && Object.keys(json).length === 1 | ||
return simpleType ? json.type : json | ||
})} | ||
if (this.id) schema.id = this.id | ||
return json | ||
} | ||
} | ||
}) | ||
}) | ||
schema.fromJS.def(function(schemas) { | ||
Schema.fromJS.def(function(schemas) { | ||
if (schemas instanceof Array) return new OrSchema(schemas.map(function(sch) { | ||
return sch === undefined ? schema.self : schema.fromJS(sch) | ||
return sch === undefined ? Schema.self : Schema.fromJS(sch) | ||
})) | ||
}) | ||
schema.fromJSON.def(function(sch) { | ||
Schema.fromJSON.def(function(sch) { | ||
if (!sch) return | ||
if (sch['enum'] instanceof Array) { | ||
@@ -87,8 +55,8 @@ return new OrSchema(sch['enum'].map(function(object) { | ||
} | ||
if (sch['type'] instanceof Array) { | ||
return new OrSchema(sch['type'].map(function(type) { | ||
return schema.fromJSON(typeof type === 'string' ? { type : type } : type) | ||
return Schema.fromJSON(typeof type === 'string' ? { type : type } : type) | ||
})) | ||
} | ||
}) |
@@ -1,26 +0,24 @@ | ||
var schema = require('../schema') | ||
var Schema = require('../Schema') | ||
var ReferenceSchema = module.exports = function(value) { | ||
this.value = value | ||
return new schema(this) | ||
} | ||
var ReferenceSchema = module.exports = Schema.patterns.ReferenceSchema = Schema.extend({ | ||
initialize : function(value) { | ||
this.value = value | ||
}, | ||
ReferenceSchema.prototype = { | ||
compile : function() { | ||
return { references : [this.value], expression : 'instance === {0}' } | ||
validate : function(instance) { | ||
return instance === this.value | ||
}, | ||
generate : function() { | ||
return this.value | ||
}, | ||
toJSON : function() { | ||
return { 'enum' : [this.value] } | ||
var json = Schema.prototype.toJSON.call(this) | ||
json['enum'] = [this.value] | ||
return json | ||
} | ||
} | ||
}) | ||
schema.fromJS.def(function(value) { | ||
Schema.fromJS.def(function(value) { | ||
return new ReferenceSchema(value) | ||
}) |
@@ -1,45 +0,33 @@ | ||
var schema = require('../schema') | ||
, RandExp = require('randexp') | ||
var Schema = require('../Schema') | ||
var defaultRandExp = new RandExp(/^[a-zA-Z0-9]{1,10}$/) | ||
var RegexpSchema = module.exports = Schema.patterns.RegexpSchema = Schema.extend({ | ||
initialize : function(regexp) { | ||
this.regexp = regexp | ||
}, | ||
var RegexpSchema = module.exports = function(regexp) { | ||
this.regexp = regexp | ||
this.randexp = this.regexp ? new RandExp(this.regexp) : defaultRandExp | ||
return new schema(this) | ||
} | ||
validate : function(instance) { | ||
return Object(instance) instanceof String && (!this.regexp || this.regexp.test(instance)) | ||
}, | ||
RegexpSchema.prototype = { | ||
compile : function() { | ||
return { references : [this.regexp] | ||
, expression : 'Object(instance) instanceof String' | ||
+ (this.regexp ? ' && {0}.test(instance)' : '') | ||
} | ||
}, | ||
generate : function() { | ||
return this.randexp.gen() | ||
}, | ||
toJSON : function() { | ||
var sch = { type : 'string' } | ||
var json = Schema.prototype.toJSON.call(this) | ||
json.type = 'string' | ||
if (this.regexp) { | ||
console.log(this.regexp.toString()) | ||
sch.pattern = this.regexp.toString() | ||
sch.pattern = sch.pattern.substr(1, sch.pattern.length - 2) | ||
json.pattern = this.regexp.toString() | ||
json.pattern = json.pattern.substr(1, json.pattern.length - 2) | ||
} | ||
return sch | ||
return json | ||
} | ||
} | ||
}) | ||
schema.fromJSON.def(function(sch) { | ||
Schema.fromJSON.def(function(sch) { | ||
if (!sch || sch.type !== 'string') return | ||
if ('pattern' in sch) { | ||
return new RegexpSchema(RegExp('^' + sch.pattern + '$')) | ||
} else if ('minLength' in sch || 'maxLength' in sch) { | ||
return new RegexpSchema(RegExp('^.{' + (sch.minLength || 0) + ',' + (sch.maxLength || '') + '}$')) | ||
return new RegexpSchema(RegExp('^.{' + [ sch.minLength || 0, sch.maxLength ].join(',') + '}$')) | ||
} else { | ||
@@ -50,4 +38,4 @@ return new RegexpSchema() | ||
schema.fromJS.def(function(regexp) { | ||
Schema.fromJS.def(function(regexp) { | ||
if (regexp instanceof RegExp) return new RegexpSchema(regexp) | ||
}) |
@@ -1,92 +0,41 @@ | ||
var def = require('def.js') | ||
, linker = require('./linker') | ||
var Schema = require('./Schema') | ||
var schema = module.exports = function(schemaObject) { | ||
// When called as simple function, forward everything to fromJS, and then seal the resulting schema | ||
if (!(this instanceof schema)) return schema.fromJS.apply(null, arguments).seal() | ||
// When called with new, transform the parameter schema object to a compiled schema function | ||
if (!schemaObject.compile && !schemaObject.validate) { | ||
throw new Error('Schema definition objects must have either compile or validate function.') | ||
var schema = module.exports = function(schemaDescription) { | ||
var doc, schemaObject | ||
if (arguments.length === 2) { | ||
doc = schemaDescription | ||
schemaDescription = arguments[1] | ||
} | ||
var validate = schemaObject.compile ? linker.link(schemaObject.compile()) | ||
: schemaObject.validate.bind(schemaObject) | ||
validate.seal = function() { | ||
if (schemaObject.sealed) return validate | ||
schemaObject.sealed = true | ||
if (schemaObject.leafs) { | ||
var leafs = schemaObject.leafs() | ||
if (leafs.certain.indexOf(schema.self) !== -1) { | ||
throw new Error('There\'s no object that satisfies this schema because of necessary recursion.') | ||
} | ||
if (leafs.uncertain.indexOf(schema.self) !== -1) { | ||
// If the validate function is compiled then recompiling it with self inlining | ||
if (validate.assembly) { | ||
var newValidate = linker.link(schemaObject.compile(), schema.self) | ||
for (var key in validate) newValidate[key] = validate[key] | ||
newValidate.schema = newValidate | ||
validate = newValidate | ||
} | ||
// schema.self needs to be pointed to this schema, and then it must be reset | ||
schema.self.set(validate) | ||
schema.self = new SelfSchema() | ||
} | ||
} | ||
delete validate.assembly | ||
return validate | ||
if (this instanceof schema) { | ||
// When called with new, create a schema object and then return the schema function | ||
var constructor = Schema.extend(schemaDescription) | ||
schemaObject = new constructor() | ||
if (doc) schemaObject.doc = doc | ||
return schemaObject.wrap() | ||
} else { | ||
// When called as simple function, forward everything to fromJS | ||
// and then resolve schema.self to the resulting schema object | ||
schemaObject = Schema.fromJS(schemaDescription) | ||
schema.self.resolve(schemaObject) | ||
if (doc) schemaObject.doc = doc | ||
return schemaObject.wrap() | ||
} | ||
validate.schema = validate | ||
for (var key in schemaObject) { | ||
if (schemaObject[key] instanceof Function && !schemaObject[key].schema) { | ||
validate[key] = schemaObject[key].bind(schemaObject) | ||
} | ||
} | ||
return validate | ||
} | ||
schema.Schema = Schema | ||
var SelfSchema = function() { | ||
return new schema(this) | ||
schema.toJSON = function(sch) { | ||
return Schema.fromJS(sch).toJSON() | ||
} | ||
SelfSchema.prototype = { | ||
set : function(target) { | ||
if (!this.target) this.target = target | ||
}, | ||
validate : function(instance) { | ||
return this.target(instance) | ||
}, | ||
generate : function() { | ||
return this.target.generate() | ||
}, | ||
toJSON : function() { | ||
return { '$ref' : this.target.getId() } | ||
} | ||
schema.fromJS = function(sch) { | ||
return Schema.fromJS(sch).wrap() | ||
} | ||
schema.self = new SelfSchema() | ||
schema.fromJS = def() | ||
schema.fromJSON = def() | ||
schema.toJSON = function(sch) { | ||
return schema(sch).toJSON() | ||
schema.fromJSON = function(sch) { | ||
return Schema.fromJSON(sch).wrap() | ||
} | ||
schema.generate = function(sch) { | ||
return schema(sch).generate() | ||
} |
{ | ||
"author": "Gábor Molnár <gabor.molnar@sch.bme.hu>", | ||
"name": "js-schema", | ||
"description": "A simple and easy to use schema library.", | ||
"description": "A simple and intuitive object validation library", | ||
"keywords": [ | ||
"schema", | ||
"JSON Schema", | ||
"random generator", | ||
"object generation", | ||
"testing" | ||
"validation", | ||
"validator" | ||
], | ||
"version": "0.5.0", | ||
"version": "0.6.1", | ||
"homepage": "https://github.com/molnarg/js-schema", | ||
@@ -19,7 +18,7 @@ "repository": { | ||
"dependencies": { | ||
"def.js" : "*", | ||
"randexp" : "*", | ||
"underscore" : "*" | ||
}, | ||
"devDependencies": {}, | ||
"devDependencies": { | ||
"browserify": "*", | ||
"uglify-js": "*" | ||
}, | ||
"engines": { | ||
@@ -26,0 +25,0 @@ "node": "*" |
@@ -5,5 +5,7 @@ js-schema | ||
js-schema is a new way of describing object schemas in JavaScript. It has a clean and simple syntax, | ||
and it is capable of serializing to/from the popular JSON Schema format. Typical usecases include | ||
object validation and random object generation. | ||
and it is capable of serializing to/from the popular JSON Schema format. The typical usecase is | ||
decalartive object validation. | ||
**Latest release**: 0.6.1 (2012/08/19) | ||
Features | ||
@@ -15,5 +17,2 @@ ======== | ||
```javascript | ||
var schema = require('js-schema'); | ||
// or <script src="js-schema.min.js"></script> in the browser | ||
var Duck = schema({ // A duck | ||
@@ -27,12 +26,15 @@ swim : Function, // - can swim | ||
The resulting function (`Duck`) can be used for checking or validating objects: | ||
The resulting function (`Duck`) can be used to check objects against the declared schema: | ||
```javascript | ||
var myDuck = { quack : function() {}, swim : function() {}, age : 2, color : 'yellow' }, | ||
myCat = { purr : function() {}, walk : function() {}, age : 3, color : 'black' }, | ||
// Some animals | ||
var myDuck = { swim : function() {}, quack : function() {}, age : 2, color : 'yellow' }, | ||
myCat = { walk : function() {}, purr : function() {}, age : 3, color : 'black' }, | ||
animals = [ myDuck, myCat, {}, /*...*/ ]; | ||
// Simple checks | ||
console.log( Duck(myDuck) ); // true | ||
console.log( Duck(myCat) ); // false | ||
// Using the schema function with filter | ||
var ducks = animals.filter( Duck ); // every Duck-like animal | ||
@@ -42,9 +44,2 @@ var walking = animals.filter( schema({ walk : Function }) ); // every animal that can walk | ||
js-schema can generate random objects for a given schema for testing purposes: | ||
```javascript | ||
var duck = schema.generate( Duck ); | ||
var testcases = schema.generate( Array.of(5, Duck) ); | ||
``` | ||
It is also possible to define self-referencing data structures: | ||
@@ -54,14 +49,6 @@ | ||
var Tree = schema({ left : [ Number, Tree ], right : [ Number, Tree ] }); | ||
var tree = schema.generate( Tree ); | ||
``` | ||
The schema description is _compiled_ into validation function for achieving maximal performance. | ||
```javascript | ||
console.log( Tree.toString() ); | ||
// function self(instance) { | ||
// return instance != null && | ||
// ((Object(instance["left" ]) instanceof Number) || self(instance["left" ])) && | ||
// ((Object(instance["right"]) instanceof Number) || self(instance["right"])); | ||
// } | ||
console.log( Tree({ left : 3, right : 3 }) ); // true | ||
console.log( Tree({ left : 3, right : { left: 5, right: 5 } }) ); // true | ||
console.log( Tree({ left : 3, right : { left: 5, right: 's' } }) ); // false | ||
``` | ||
@@ -72,2 +59,5 @@ | ||
Include js-schema in your project with `var schema = require('js-schema');` in node.js or with | ||
`<script src="js-schema.min.js"></script>` in the browser. | ||
The first parameter passed to the `schema` function describes the schema, and the return value | ||
@@ -132,3 +122,3 @@ is a new function called validator. Then the validator can be used to check any object against | ||
b : Number, // (1) 'class schema' pattern | ||
c : /The meaning of life is \d+/, // (3) regexp pattern | ||
c : /The meaning of life is \d+/, // (3) 'regexp' pattern | ||
d : undefined, // (9) 'anything' pattern | ||
@@ -255,5 +245,2 @@ e : [null, schema.self] // (5) 'or' pattern | ||
Using the random object generation, it should be possible to build a QucikCheck-like testing | ||
framework, which could be used to generate testcases for js-schema (yes, I like resursion). | ||
Contributing | ||
@@ -264,4 +251,4 @@ ============ | ||
Installation | ||
============ | ||
Installation on node.js | ||
======================= | ||
@@ -272,2 +259,9 @@ Using [npm](http://npmjs.org): | ||
Build | ||
===== | ||
To build the browser verison you will need node.js and two node.js packages: browserify | ||
and uglifyjs installed globally (`npm install -g browserify uglify-js`). `build.sh` | ||
assembles a debug version using browserify and then minifies it using uglify. | ||
License | ||
@@ -274,0 +268,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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
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
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 3 instances in 1 package
92806
0
30
2118
1
2
263
8
2
- Removeddef.js@*
- Removedrandexp@*
- Removedunderscore@*
- Removeddef.js@0.1.6(transitive)
- Removeddrange@1.1.1(transitive)
- Removedrandexp@0.5.3(transitive)
- Removedret@0.2.2(transitive)
- Removedunderscore@1.13.7(transitive)