From 046638359c5ef6b91d5383fb9d57aa2d89d1bfdf Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Thu, 24 Nov 2016 21:56:48 +0000 Subject: [PATCH] feat: support async schema/fragment loading, closes #5 --- keywords/add_keyword.js | 5 ++- package.json | 2 +- spec/async.spec.js | 68 +++++++++++++++++++++++++++++++++++++++++ spec/patch.spec.js | 8 ++--- 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 spec/async.spec.js diff --git a/keywords/add_keyword.js b/keywords/add_keyword.js index 2b5f556..b61a3cb 100644 --- a/keywords/add_keyword.js +++ b/keywords/add_keyword.js @@ -20,7 +20,10 @@ module.exports = function (ajv, keyword, jsonPatch, patchSchema) { : $ref; var validate = ajv.getSchema(id); if (validate) return validate.schema; - throw new Error('can\'t resolve reference ' + $ref + ' from id ' + it.baseId); + var err = new Error('can\'t resolve reference ' + $ref + ' from id ' + it.baseId); + err.missingRef = it.resolve.url(it.baseId, $ref); + err.missingSchema = it.resolve.normalizeId(it.resolve.fullPath(err.missingRef)); + throw err; } }, metaSchema: { diff --git a/package.json b/package.json index 4a66edb..734a2e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ajv-merge-patch", - "version": "2.0.2", + "version": "2.1.0", "description": "$merge and $patch keywords for Ajv JSON-Schema validator to extend schemas", "main": "index.js", "scripts": { diff --git a/spec/async.spec.js b/spec/async.spec.js new file mode 100644 index 0000000..5565be7 --- /dev/null +++ b/spec/async.spec.js @@ -0,0 +1,68 @@ +'use strict'; + +var Ajv = require('ajv'); +var addKeywords = require('..'); +var test = require('./test_validate'); +var assert = require('assert'); + +describe('async schema loading', function() { + var ajv, loadCount; + + beforeEach(function() { + ajv = new Ajv({v5: true, loadSchema: loadSchema}); + addKeywords(ajv); + loadCount = 0; + }); + + describe('$merge', function() { + it('should load missing schemas', function (done) { + var schema = { + "$merge": { + "source": { "$ref": "obj.json#" }, + "with": { + "properties": { "q": { "type": "number" } } + } + } + }; + + testAsync(schema, '$merge', done); + }); + }); + + describe('$patch', function() { + it('should load missing schemas', function (done) { + var schema = { + "$patch": { + "source": { "$ref": "obj.json#" }, + "with": [ + { "op": "add", "path": "/properties/q", "value": { "type": "number" } } + ] + } + }; + + testAsync(schema, '$patch', done); + }); + }); + + function testAsync(schema, keyword, done) { + ajv.compileAsync(schema, function (err, validate) { + if (err) done(err); + assert.strictEqual(loadCount, 1); + test(validate, keyword); + done(); + }); + } + + function loadSchema(ref, callback) { + if (ref == 'obj.json') { + loadCount++; + return callback(null, { + "id": "obj.json#", + "type": "object", + "properties": { "p": { "type": "string" } }, + "additionalProperties": false + }); + } + callback(new Error('404: ' + ref)); + } +}); diff --git a/spec/patch.spec.js b/spec/patch.spec.js index 22e145e..42f7b09 100644 --- a/spec/patch.spec.js +++ b/spec/patch.spec.js @@ -37,9 +37,9 @@ describe('keyword $patch', function() { }); it('should extend schema defined in $ref', function() { - ajvInstances.forEach(testMerge); + ajvInstances.forEach(testPatch); - function testMerge(ajv) { + function testPatch(ajv) { var sourceSchema = { "id": "obj.json#", "type": "object", @@ -64,9 +64,9 @@ describe('keyword $patch', function() { }); it('should extend schema defined with relative $ref', function() { - ajvInstances.forEach(testMerge); + ajvInstances.forEach(testPatch); - function testMerge(ajv) { + function testPatch(ajv) { var schema = { "id": "obj.json#", "definitions": {