// File validator constructor to validate against a specific schema object. function fileIsJsonSchemaValid(schema) { if(_.isString(schema)) { schema = tv4.getSchema(schema); } return function (packageDir, filename, callback) { fs.exists(filename, function (exists) { if (!exists) { return callback(null, []); } fs.readFile(filename, function (err, data) { if (err) { return callback(err); } var json; try { json = JSON.parse(data.toString().trim()); } catch (ex) { return callback(null, [ fmt($('Unable to parse json file %s: line %s: %s'), filename, ex.lineNumber, ex.message) ]); } var result = tv4.validateMultiple(json, schema); var errors = (result.errors || []).map(function(e) { return fmt('%s: #%s: %s', filename, e.dataPath, e.message); }); return callback(null, errors); }); }); }; }
new : function(classkey, qid) { var schm = tv4.getSchema(classkey); if (!schm) return linkCallback('unable to find definition '+classkey, null, qid); var instance = create(schm); if (!instance) return linkCallback('error generating new '+classkey, null, qid); linkCallback(null, instance, qid); },
schemaFromPath: function(schema, path) { var parts = path.split('/').slice(1); while (parts.length) { if (typeof schema['$ref'] == 'string') { schema = tv4.getSchema(schema['$ref']); } var part = parts.shift().replace(/~1/g, '/').replace(/~0/g, '~'); schema = schema[part]; } return schema; },
/** * create a minimal instance described by a schema */ function create(s) { if (!s) return null else if (s.type=='array') return [create(s.items)]; else if (s.type=='array') return []; else if (s.type=='object'){ var r = {}; for (var p in s.properties){ if (s.properties[p].type=='object') r[p] = create(s.properties[p]); else if (s.properties[p].type=='number') r[p] = 0; else if (s.properties[p].type=='array') r[p] = create(s.properties[p]); else if (s.properties[p].type=='string') r[p]=''; else if (s.properties[p].$ref && tv4.getSchema(s.properties[p].$ref)) r[p] = create(tv4.getSchema(s.properties[p].$ref)); else r[p] = null; //else if schemas[s.properties[p].type] r[p] = create(schemas[s.properties[p].type]); // <-- search referenced schemas here } return r } else return ''; }
return Promise.resolve().then(function() { var basename; // If a schemaName is specified, then validate against that if(schemaName) { basename = schemaName.split('#')[0]; if (!_.has(schemaNsMap, basename)) { return Promise.reject(schemaName + ' is not loaded'); } return tv4.validateResult(obj, tv4.getSchema(schemaNsMap[basename] + schemaName)); } }).then(function(result) {
function makeRelativeSchemaPath(path, schema) { /* * Shortens schema paths by replacing with #id whenever possible. * * :param path: the path to shorten * :param schema: the schema object the path is referring to * and must be traversed * :returns the relative schema path * :rtype string */ var relSchemaPath = ''; if (schema['$ref']) { relSchemaPath += schema['$ref']; schema = tv4.getSchema(schema['$ref']); } var turtle = schema; // where we are now path = path.split('/'); for (var i in path) { var seg = path[i]; if (seg === '') continue; relSchemaPath += '/' + seg; turtle = turtle[seg]; // works for arrays too! if (turtle === undefined) { relSchemaPath += "<N/A>"; return relSchemaPath; } if (turtle['$ref']) turtle = tv4.getSchema(turtle['$ref']); // if found something with an schema id // assumes that an id field set to a string is a schema id, and // not, say, a property, which must be a object. if (turtle.id !== undefined && typeof turtle.id === 'string') { relSchemaPath = turtle.id; } } return relSchemaPath; };
possibleSchemas: function (schema, dataPath) { var parts = dataPath.split('/').slice(1); var options = [schema]; while (parts.length) { var part = parts.shift().replace(/~1/g, '/').replace(/~0/g, '~'); // Expand all $refs, anyOf, allOf, oneOf var expandedOptions = []; while (options.length) { var option = options.shift(); if (typeof option['$ref'] == 'string') { option = tv4.getSchema(option['$ref']); } if (expandedOptions.indexOf(option) !== -1) continue; if (option.allOf) { options = [].concat(option.allOf).concat(options); } if (option.anyOf) { options = [].concat(option.anyOf).concat(options); } if (option.oneOf) { options = [].concat(option.oneOf).concat(options); } expandedOptions.push(option); } var newOptions = []; while (expandedOptions.length) { var option = expandedOptions.shift(); if (/^(0|[1-9][0-9]*)$/.test(part)) { if (Array.isArray(option.items)) { if (option.items[part]) { newOptions.push(option.items[part]); } else if (option.additionalItems) { newOptions.push(option.additionalItems); } } else if (option.items) { newOptions.push(option.items); } } if (option.properties && option.properties[part]) { newOptions.push(option.properties[part]); } else if (option.additionalProperties) { newOptions.push(option.additionalProperties); } } options = newOptions; } return options; },
/** * when applying the command, make sure the api schema is satisfied * otherwise notify of the error */ function applyCommand(cmd, args, id, cb) { var op = service.api[cmd], schm = tv4.getSchema('#'+cmd); //console.log('expressionEvaluator applycmd', cmd, Boolean(op), schm, args); if (op && schm && tv4.validate(args, schm)) { // <-- won't validate zero alength arrays args.push(id); // <-- ?? op.apply(applyCommand, args); } else { var err = schm && tv4.error ? tv4.error.message : 'unknown command : '+ cmd; linkCallback(err, null, id); } return id; }
Schemas.prototype.getSchema = function(schema, baseUri, urlHistory) { if (typeof schema === 'string') { var uri = schema; baseUri = baseUri || 'http://schema.ninjablocks.com/'; var resolvedUri = tv4.resolveUrl(baseUri, uri); schema = tv4.getSchema(resolvedUri); if (!schema) { throw new Error('Failed to resolve schema $ref. ' + (urlHistory? Object.keys(urlHistory).join(', ') : uri)); } } if (schema.$ref !== undefined) { urlHistory = urlHistory || {}; if (urlHistory[schema.$ref]) { throw new Error('Circular reference in schema refs. ' + Object.keys(urlHistory).join(', ')); } urlHistory[schema.$ref] = true; schema = this.getSchema(schema.$ref, baseUri, urlHistory); } return schema; };
return function (msg, next) { var err = ''; if ((typeof msg !== 'object') || (Array.isArray(msg))) { err = 'message received is not an object.'; onfail(err, type, msg); return next(false, err); } if (type === 'activity-object') { var _schema = tv4.getSchema('http://sockethub.org/schemas/v0/activity-object#'); if (! tv4.validate({ object:msg }, 'http://sockethub.org/schemas/v0/activity-object#')) { err = 'activity-object schema validation failed: ' + tv4.error.dataPath + ' = ' + tv4.error.message; onfail(err, type, msg); return next(false, err); } } else { if (typeof msg.context !== 'string') { err = 'message must contain a context property.'; onfail(err, type, msg); return next(false, err); } else if (! init.platforms.exists(msg.context)) { err = 'context ' + msg.context+ ' not registered with this sockethub instance.'; onfail(err, type, msg); return next(false, err); } else if ((type === 'message') && (typeof msg['@type'] !== 'string')) { err = 'message must contain a @type property.'; onfail(err, type, msg); return next(false, err); } var stream = activity.Stream(msg); if (type === 'credentials') { if (! tv4.getSchema('http://sockethub.org/schemas/v0/context/' + stream.context + '/credentials')) { err = 'no credentials schema found for ' + stream.context + ' context'; onfail(err, type, stream); return next(false, err); } else if (! tv4.validate(stream, 'http://sockethub.org/schemas/v0/context/' + stream.context + '/credentials')) { err = 'credentials schema validation failed: ' + tv4.error.dataPath + ' = ' + tv4.error.message; onfail(err, type, stream); return next(false, err); } } else { if (! tv4.validate(stream, 'http://sockethub.org/schemas/v0/activity-stream#')) { // TODO figure out a way to allow for special objects from platforms, without ignoring failed activity stream schema checks if (! tv4.getSchema('http://sockethub.org/schemas/v0/context/' + stream.context + '/messages')) { err = 'actvity-stream schema validation failed: ' + tv4.error.dataPath + ': ' + tv4.error.message; onfail(err, type, stream); return next(false, err); } } } } // passed validation next(); };
it('should work', function () { var schema = {}; MongoWrapper.SchemaStorage.addSchema('http://zzz', schema); assert.deepEqual(schema, TV4.getSchema('http://zzz')); });
exports.uriIsValid = function(uri) { if (typeof uri !== 'string') return false; if (!tv4.getSchema(uri)) return false; return true; };
schema : function(schemaName, qid) { var schema = tv4.getSchema(schemaName); linkCallback(tv4.error ? tv4.error : schema ? null : 'unknown schema id', schema, qid); // <-- will tv4 throw this error for us? },
.map(function(item) { if(_.has(schemaTitle, item['@odata.type'])) { schemaName = schemaTitle[item['@odata.type']]; return tv4.validateResult(item, tv4.getSchema(schemaName)); } })
SchemaApiService.prototype.getSchema = function( identifier ) { var schemaContent = tv4.getSchema(identifier); return schemaContent; };