'use strict'; var urilib = require('url'); var attribute = require('./attribute'); var helpers = require('./helpers'); var scanSchema = require('./scan').scan; var ValidatorResult = helpers.ValidatorResult; var ValidatorResultError = helpers.ValidatorResultError; var SchemaError = helpers.SchemaError; var SchemaContext = helpers.SchemaContext; //var anonymousBase = 'vnd.jsonschema:///'; var anonymousBase = '/'; /** * Creates a new Validator object * @name Validator * @constructor */ var Validator = function Validator () { // Allow a validator instance to override global custom formats or to have their // own custom formats. this.customFormats = Object.create(Validator.prototype.customFormats); this.schemas = {}; this.unresolvedRefs = []; // Use Object.create to make this extensible without Validator instances stepping on each other's toes. this.types = Object.create(types); this.attributes = Object.create(attribute.validators); }; // Allow formats to be registered globally. Validator.prototype.customFormats = {}; // Hint at the presence of a property Validator.prototype.schemas = null; Validator.prototype.types = null; Validator.prototype.attributes = null; Validator.prototype.unresolvedRefs = null; /** * Adds a schema with a certain urn to the Validator instance. * @param schema * @param urn * @return {Object} */ Validator.prototype.addSchema = function addSchema (schema, base) { var self = this; if (!schema) { return null; } var scan = scanSchema(base||anonymousBase, schema); var ourUri = base || schema.$id || schema.id; for(var uri in scan.id){ this.schemas[uri] = scan.id[uri]; } for(var uri in scan.ref){ // If this schema is already defined, it will be filtered out by the next step this.unresolvedRefs.push(uri); } // Remove newly defined schemas from unresolvedRefs this.unresolvedRefs = this.unresolvedRefs.filter(function(uri){ return typeof self.schemas[uri]==='undefined'; }); return this.schemas[ourUri]; }; Validator.prototype.addSubSchemaArray = function addSubSchemaArray(baseuri, schemas) { if(!Array.isArray(schemas)) return; for(var i=0; i", schema); } var subschema = helpers.objectGetPath(ctx.schemas[document], fragment.substr(1)); if(subschema===undefined){ throw new SchemaError("no such schema " + fragment + " located in <" + document + ">", schema); } return {subschema: subschema, switchSchema: switchSchema}; }; /** * Tests whether the instance if of a certain type. * @private * @param instance * @param schema * @param options * @param ctx * @param type * @return {boolean} */ Validator.prototype.testType = function validateType (instance, schema, options, ctx, type) { if(type===undefined){ return; }else if(type===null){ throw new SchemaError('Unexpected null in "type" keyword'); } if (typeof this.types[type] == 'function') { return this.types[type].call(this, instance); } if (type && typeof type == 'object') { var res = this.validateSchema(instance, type, options, ctx); return res === undefined || !(res && res.errors.length); } // Undefined or properties not on the list are acceptable, same as not being defined return true; }; var types = Validator.prototype.types = {}; types.string = function testString (instance) { return typeof instance == 'string'; }; types.number = function testNumber (instance) { // isFinite returns false for NaN, Infinity, and -Infinity return typeof instance == 'number' && isFinite(instance); }; types.integer = function testInteger (instance) { return (typeof instance == 'number') && instance % 1 === 0; }; types.boolean = function testBoolean (instance) { return typeof instance == 'boolean'; }; types.array = function testArray (instance) { return Array.isArray(instance); }; types['null'] = function testNull (instance) { return instance === null; }; types.date = function testDate (instance) { return instance instanceof Date; }; types.any = function testAny (instance) { return true; }; types.object = function testObject (instance) { // TODO: fix this - see #15 return instance && (typeof instance === 'object') && !(Array.isArray(instance)) && !(instance instanceof Date); }; module.exports = Validator;