feat: async loading of meta-schema, #334
parent
f95b83d890
commit
84b0531e39
|
@ -8,20 +8,25 @@ module.exports = compileAsync;
|
|||
* `loadSchema` option should be a function that accepts schema uri and returns promise that resolves with the schema.
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema object
|
||||
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
|
||||
* @param {Function} callback an optional node-style callback, it is called with 2 parameters: error (or null) and validating function.
|
||||
* @return {Promise} promise that resolves with a validating function.
|
||||
*/
|
||||
function compileAsync(schema, callback) {
|
||||
function compileAsync(schema, meta, callback) {
|
||||
/* eslint no-shadow: 0 */
|
||||
/* global Promise */
|
||||
/* jshint validthis: true */
|
||||
var schemaObj;
|
||||
var self = this;
|
||||
if (typeof this._opts.loadSchema != 'function')
|
||||
throw new Error('options.loadSchema should be a function');
|
||||
|
||||
var p = Promise.resolve().then(function () {
|
||||
schemaObj = self._addSchema(schema);
|
||||
if (typeof meta == 'function') {
|
||||
callback = meta;
|
||||
meta = undefined;
|
||||
}
|
||||
|
||||
var p = loadMetaSchemaOf(schema).then(function () {
|
||||
var schemaObj = self._addSchema(schema, undefined, meta);
|
||||
return schemaObj.validate || _compileAsync(schemaObj);
|
||||
});
|
||||
|
||||
|
@ -35,6 +40,14 @@ function compileAsync(schema, callback) {
|
|||
return p;
|
||||
|
||||
|
||||
function loadMetaSchemaOf(sch) {
|
||||
var $schema = sch.$schema;
|
||||
return $schema && !self.getSchema($schema)
|
||||
? compileAsync.call(self, { $ref: $schema }, true)
|
||||
: Promise.resolve();
|
||||
}
|
||||
|
||||
|
||||
function _compileAsync(schemaObj) {
|
||||
try { return self._compile(schemaObj); }
|
||||
catch(e) {
|
||||
|
@ -54,7 +67,12 @@ function compileAsync(schema, callback) {
|
|||
}
|
||||
|
||||
return schemaPromise.then(function (sch) {
|
||||
if (!added(ref)) self.addSchema(sch, ref);
|
||||
if (!added(ref)) {
|
||||
return loadMetaSchemaOf(sch).then(function () {
|
||||
if (!added(ref)) self.addSchema(sch, ref, undefined, meta);
|
||||
});
|
||||
}
|
||||
}).then(function() {
|
||||
return _compileAsync(schemaObj);
|
||||
});
|
||||
|
||||
|
|
|
@ -177,9 +177,16 @@ describe('compileAsync method', function() {
|
|||
});
|
||||
|
||||
|
||||
describe.skip('loading metaschemas (#334)', function() {
|
||||
describe('loading metaschemas (#334)', function() {
|
||||
it('should load metaschema if not available', function() {
|
||||
var schema = { "$ref": "http://example.com/foobar.json" };
|
||||
return test(SCHEMAS['http://example.com/foobar.json'], 1);
|
||||
});
|
||||
|
||||
it('should load metaschema of referenced schema if not available', function() {
|
||||
return test({ "$ref": "http://example.com/foobar.json" }, 2);
|
||||
});
|
||||
|
||||
function test(schema, expectedLoadCallCount) {
|
||||
ajv.addKeyword('myFooBar', {
|
||||
type: 'string',
|
||||
validate: function (sch, data) {
|
||||
|
@ -188,12 +195,12 @@ describe('compileAsync method', function() {
|
|||
});
|
||||
|
||||
return ajv.compileAsync(schema).then(function (validate) {
|
||||
should.equal(loadCallCount, 2);
|
||||
should.equal(loadCallCount, expectedLoadCallCount);
|
||||
validate .should.be.a('function');
|
||||
validate('foo') .should.equal(true);
|
||||
validate('bar') .should.equal(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
@ -237,13 +244,14 @@ describe('compileAsync method', function() {
|
|||
}
|
||||
};
|
||||
|
||||
return Promise.all[
|
||||
return Promise.all([
|
||||
ajv.compileAsync(schema).then(spec),
|
||||
ajv.compileAsync(schema).then(spec),
|
||||
ajv.compileAsync(schema).then(spec)
|
||||
];
|
||||
]);
|
||||
|
||||
function spec(validate) {
|
||||
should.equal(loadCallCount, 2);
|
||||
validate .should.be.a('function');
|
||||
validate({ a: { b: 2 } }) .should.equal(true);
|
||||
validate({ a: { b: 1 } }) .should.equal(false);
|
||||
|
|
Loading…
Reference in New Issue