Merge branch 'forge' of http://bdgit.educoder.net/Hjqreturn/educoder into forge
commit
a4ac805ef7
@ -0,0 +1,2 @@
|
||||
// Place all the behaviors and hooks related to the matching controller here.
|
||||
// All this logic will automatically be available in application.js.
|
@ -0,0 +1,2 @@
|
||||
// Place all the behaviors and hooks related to the matching controller here.
|
||||
// All this logic will automatically be available in application.js.
|
@ -0,0 +1,3 @@
|
||||
// Place all the styles related to the issue_depends controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
@ -0,0 +1,3 @@
|
||||
// Place all the styles related to the issue_times controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
@ -0,0 +1,47 @@
|
||||
class IssueDependsController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :set_issue
|
||||
before_action :check_issue_permission
|
||||
|
||||
def create
|
||||
issue_depend = {
|
||||
user_id: current_user.id,
|
||||
depend_issue_id: params[:depend_issue_id].to_i,
|
||||
issue_id: @issue.id
|
||||
}
|
||||
save_issue_depend = IssueDepend.new(issue_depend)
|
||||
if save_issue_depend.save
|
||||
@issue.custom_journal_detail("issue_depend","", @issue.id)
|
||||
normal_status(0, "添加依赖成功")
|
||||
else
|
||||
normal_status(0, "添加依赖失败")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def destroy
|
||||
depend_issue_params = params[:id]
|
||||
depend_issue = IssueDepend.find(depend_issue_params)
|
||||
if depend_issue&.destroy
|
||||
@issue.custom_journal_detail("destroy_issue_depend","", @issue.id)
|
||||
normal_status(0, "删除依赖成功")
|
||||
else
|
||||
normal_status(-1, "删除依赖失败")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def set_issue
|
||||
@issue = Issue.find_by_id(params[:issue_id])
|
||||
unless @issue.present?
|
||||
normal_status(-1, "标签不存在")
|
||||
end
|
||||
end
|
||||
|
||||
def check_issue_permission
|
||||
@project = @issue.project
|
||||
unless @project.member?(current_user) || current_user.admin?
|
||||
normal_status(-1, "您没有权限")
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,55 @@
|
||||
class IssueTimesController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :set_issue
|
||||
before_action :check_issue_permission
|
||||
|
||||
def create
|
||||
issue_time = {
|
||||
user_id: current_user.id,
|
||||
start_time: params[:start_time].to_s.to_time || Time.now,
|
||||
issue_id: @issue.id
|
||||
}
|
||||
save_issue_time = IssueTime.new(issue_time)
|
||||
if save_issue_time.save
|
||||
@issue.custom_journal_detail("work_time",save_issue_time.id, "开始工作")
|
||||
normal_status(0, "开始成功")
|
||||
else
|
||||
normal_status(0, "开始失败")
|
||||
end
|
||||
end
|
||||
|
||||
def end_work
|
||||
end_type = params[:end_type].to_i
|
||||
end_work_time = end_type == 0 ? "" : Time.now
|
||||
last_work_time = @issue.issue_times.where(user_id: current_user.id, end_time: nil)
|
||||
Rails.logger.info("######________last_work_time&.last.try(:id)_____###########{last_work_time&.first.try(:id)}")
|
||||
|
||||
if last_work_time.update_all(end_time: end_work_time)
|
||||
if end_type == 0
|
||||
message = "取消时间跟踪"
|
||||
@issue.custom_journal_detail("cancel_time",last_work_time&.first.try(:id), "取消时间跟踪")
|
||||
else
|
||||
message = "停止工作"
|
||||
@issue.custom_journal_detail("end_time",last_work_time&.first.try(:id), "停止工作")
|
||||
end
|
||||
normal_status(0, message)
|
||||
else
|
||||
normal_status(0, "操作失败")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def set_issue
|
||||
@issue = Issue.find_by_id(params[:issue_id])
|
||||
unless @issue.present?
|
||||
normal_status(-1, "标签不存在")
|
||||
end
|
||||
end
|
||||
|
||||
def check_issue_permission
|
||||
@project = @issue.project
|
||||
unless @project.member?(current_user) || current_user.admin?
|
||||
normal_status(-1, "您没有权限")
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,2 @@
|
||||
module IssueDependsHelper
|
||||
end
|
@ -0,0 +1,2 @@
|
||||
module IssueTimesHelper
|
||||
end
|
@ -0,0 +1,3 @@
|
||||
class IssueDepend < ApplicationRecord
|
||||
belongs_to :issue
|
||||
end
|
@ -0,0 +1,4 @@
|
||||
class IssueTime < ApplicationRecord
|
||||
belongs_to :issue
|
||||
belongs_to :user
|
||||
end
|
@ -0,0 +1,2 @@
|
||||
json.extract! @journal, :id,:notes
|
||||
json.issue_id @journal.journalized_id
|
@ -0,0 +1,13 @@
|
||||
class CreateIssueTimes < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :issue_times do |t|
|
||||
t.integer :issue_id
|
||||
t.integer :user_id
|
||||
t.datetime :start_time
|
||||
t.datetime :end_time
|
||||
t.string :cost_time
|
||||
t.timestamps
|
||||
end
|
||||
add_index :issue_times, [:issue_id, :user_id]
|
||||
end
|
||||
end
|
@ -0,0 +1,12 @@
|
||||
class CreateIssueDepends < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :issue_depends do |t|
|
||||
t.integer :user_id
|
||||
t.integer :issue_id
|
||||
t.integer :depend_issue_id
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :issue_depends, [:user_id, :issue_id, :depend_issue_id]
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
class AddIsLockToIssue < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :issues, :is_lock, :boolean, default: false
|
||||
end
|
||||
end
|
@ -0,0 +1,51 @@
|
||||
/**
|
||||
Create an error from multiple errors.
|
||||
*/
|
||||
declare class AggregateError extends Error implements Iterable<Error> {
|
||||
readonly name: 'AggregateError';
|
||||
|
||||
/**
|
||||
@param errors - If a string, a new `Error` is created with the string as the error message. If a non-Error object, a new `Error` is created with all properties from the object copied over.
|
||||
@returns An Error that is also an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Iterables) for the individual errors.
|
||||
|
||||
@example
|
||||
```
|
||||
import AggregateError = require('aggregate-error');
|
||||
|
||||
const error = new AggregateError([new Error('foo'), 'bar', {message: 'baz'}]);
|
||||
|
||||
throw error;
|
||||
|
||||
// AggregateError:
|
||||
// Error: foo
|
||||
// at Object.<anonymous> (/Users/sindresorhus/dev/aggregate-error/example.js:3:33)
|
||||
// Error: bar
|
||||
// at Object.<anonymous> (/Users/sindresorhus/dev/aggregate-error/example.js:3:13)
|
||||
// Error: baz
|
||||
// at Object.<anonymous> (/Users/sindresorhus/dev/aggregate-error/example.js:3:13)
|
||||
// at AggregateError (/Users/sindresorhus/dev/aggregate-error/index.js:19:3)
|
||||
// at Object.<anonymous> (/Users/sindresorhus/dev/aggregate-error/example.js:3:13)
|
||||
// at Module._compile (module.js:556:32)
|
||||
// at Object.Module._extensions..js (module.js:565:10)
|
||||
// at Module.load (module.js:473:32)
|
||||
// at tryModuleLoad (module.js:432:12)
|
||||
// at Function.Module._load (module.js:424:3)
|
||||
// at Module.runMain (module.js:590:10)
|
||||
// at run (bootstrap_node.js:394:7)
|
||||
// at startup (bootstrap_node.js:149:9)
|
||||
|
||||
|
||||
for (const individualError of error) {
|
||||
console.log(individualError);
|
||||
}
|
||||
//=> [Error: foo]
|
||||
//=> [Error: bar]
|
||||
//=> [Error: baz]
|
||||
```
|
||||
*/
|
||||
constructor(errors: ReadonlyArray<Error | {[key: string]: any} | string>);
|
||||
|
||||
[Symbol.iterator](): IterableIterator<Error>;
|
||||
}
|
||||
|
||||
export = AggregateError;
|
@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
const indentString = require('indent-string');
|
||||
const cleanStack = require('clean-stack');
|
||||
|
||||
const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, '');
|
||||
|
||||
class AggregateError extends Error {
|
||||
constructor(errors) {
|
||||
if (!Array.isArray(errors)) {
|
||||
throw new TypeError(`Expected input to be an Array, got ${typeof errors}`);
|
||||
}
|
||||
|
||||
errors = [...errors].map(error => {
|
||||
if (error instanceof Error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (error !== null && typeof error === 'object') {
|
||||
// Handle plain error objects with message property and/or possibly other metadata
|
||||
return Object.assign(new Error(error.message), error);
|
||||
}
|
||||
|
||||
return new Error(error);
|
||||
});
|
||||
|
||||
let message = errors
|
||||
.map(error => {
|
||||
// The `stack` property is not standardized, so we can't assume it exists
|
||||
return typeof error.stack === 'string' ? cleanInternalStack(cleanStack(error.stack)) : String(error);
|
||||
})
|
||||
.join('\n');
|
||||
message = '\n' + indentString(message, 4);
|
||||
super(message);
|
||||
|
||||
this.name = 'AggregateError';
|
||||
|
||||
Object.defineProperty(this, '_errors', {value: errors});
|
||||
}
|
||||
|
||||
* [Symbol.iterator]() {
|
||||
for (const error of this._errors) {
|
||||
yield error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AggregateError;
|
@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
public/node_modules/_aggregate-error@3.0.1@aggregate-error/node_modules/clean-stack
generated
vendored
1
public/node_modules/_aggregate-error@3.0.1@aggregate-error/node_modules/clean-stack
generated
vendored
@ -0,0 +1 @@
|
||||
../../_clean-stack@2.2.0@clean-stack
|
@ -0,0 +1 @@
|
||||
../../_indent-string@4.0.0@indent-string
|
@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "aggregate-error",
|
||||
"version": "3.0.1",
|
||||
"description": "Create an error from multiple errors",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/aggregate-error",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava && tsd"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts"
|
||||
],
|
||||
"keywords": [
|
||||
"aggregate",
|
||||
"error",
|
||||
"combine",
|
||||
"multiple",
|
||||
"many",
|
||||
"collection",
|
||||
"iterable",
|
||||
"iterator"
|
||||
],
|
||||
"dependencies": {
|
||||
"clean-stack": "^2.0.0",
|
||||
"indent-string": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^2.4.0",
|
||||
"tsd": "^0.7.1",
|
||||
"xo": "^0.25.3"
|
||||
},
|
||||
"__npminstall_done": "Fri Jan 03 2020 18:02:10 GMT+0800 (GMT+08:00)",
|
||||
"_from": "aggregate-error@3.0.1",
|
||||
"_resolved": "https://registry.npm.taobao.org/aggregate-error/download/aggregate-error-3.0.1.tgz"
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
# aggregate-error [![Build Status](https://travis-ci.org/sindresorhus/aggregate-error.svg?branch=master)](https://travis-ci.org/sindresorhus/aggregate-error)
|
||||
|
||||
> Create an error from multiple errors
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install aggregate-error
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const AggregateError = require('aggregate-error');
|
||||
|
||||
const error = new AggregateError([new Error('foo'), 'bar', {message: 'baz'}]);
|
||||
|
||||
throw error;
|
||||
/*
|
||||
AggregateError:
|
||||
Error: foo
|
||||
at Object.<anonymous> (/Users/sindresorhus/dev/aggregate-error/example.js:3:33)
|
||||
Error: bar
|
||||
at Object.<anonymous> (/Users/sindresorhus/dev/aggregate-error/example.js:3:13)
|
||||
Error: baz
|
||||
at Object.<anonymous> (/Users/sindresorhus/dev/aggregate-error/example.js:3:13)
|
||||
at AggregateError (/Users/sindresorhus/dev/aggregate-error/index.js:19:3)
|
||||
at Object.<anonymous> (/Users/sindresorhus/dev/aggregate-error/example.js:3:13)
|
||||
at Module._compile (module.js:556:32)
|
||||
at Object.Module._extensions..js (module.js:565:10)
|
||||
at Module.load (module.js:473:32)
|
||||
at tryModuleLoad (module.js:432:12)
|
||||
at Function.Module._load (module.js:424:3)
|
||||
at Module.runMain (module.js:590:10)
|
||||
at run (bootstrap_node.js:394:7)
|
||||
at startup (bootstrap_node.js:149:9)
|
||||
*/
|
||||
|
||||
for (const individualError of error) {
|
||||
console.log(individualError);
|
||||
}
|
||||
//=> [Error: foo]
|
||||
//=> [Error: bar]
|
||||
//=> [Error: baz]
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### AggregateError(errors)
|
||||
|
||||
Returns an `Error` that is also an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Iterables) for the individual errors.
|
||||
|
||||
#### errors
|
||||
|
||||
Type: `Array<Error|Object|string>`
|
||||
|
||||
If a string, a new `Error` is created with the string as the error message.<br>
|
||||
If a non-Error object, a new `Error` is created with all properties from the object copied over.
|
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Evgeny Poberezkin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,820 @@
|
||||
# ajv-keywords
|
||||
|
||||
Custom JSON-Schema keywords for [Ajv](https://github.com/epoberezkin/ajv) validator
|
||||
|
||||
[![Build Status](https://travis-ci.org/epoberezkin/ajv-keywords.svg?branch=master)](https://travis-ci.org/epoberezkin/ajv-keywords)
|
||||
[![npm](https://img.shields.io/npm/v/ajv-keywords.svg)](https://www.npmjs.com/package/ajv-keywords)
|
||||
[![npm downloads](https://img.shields.io/npm/dm/ajv-keywords.svg)](https://www.npmjs.com/package/ajv-keywords)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/epoberezkin/ajv-keywords/badge.svg?branch=master)](https://coveralls.io/github/epoberezkin/ajv-keywords?branch=master)
|
||||
[![Greenkeeper badge](https://badges.greenkeeper.io/epoberezkin/ajv-keywords.svg)](https://greenkeeper.io/)
|
||||
[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)
|
||||
|
||||
|
||||
## Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Usage](#usage)
|
||||
- [Keywords](#keywords)
|
||||
- [Types](#types)
|
||||
- [typeof](#typeof)
|
||||
- [instanceof](#instanceof)
|
||||
- [Keywords for numbers](#keywords-for-numbers)
|
||||
- [range and exclusiveRange](#range-and-exclusiverange)
|
||||
- [Keywords for strings](#keywords-for-strings)
|
||||
- [regexp](#regexp)
|
||||
- [formatMaximum / formatMinimum and formatExclusiveMaximum / formatExclusiveMinimum](#formatmaximum--formatminimum-and-formatexclusivemaximum--formatexclusiveminimum)
|
||||
- [transform](#transform)<sup>\*</sup>
|
||||
- [Keywords for arrays](#keywords-for-arrays)
|
||||
- [uniqueItemProperties](#uniqueitemproperties)
|
||||
- [Keywords for objects](#keywords-for-objects)
|
||||
- [allRequired](#allrequired)
|
||||
- [anyRequired](#anyrequired)
|
||||
- [oneRequired](#onerequired)
|
||||
- [patternRequired](#patternrequired)
|
||||
- [prohibited](#prohibited)
|
||||
- [deepProperties](#deepproperties)
|
||||
- [deepRequired](#deeprequired)
|
||||
- [Compound keywords](#compound-keywords)
|
||||
- [switch](#switch) (deprecated)
|
||||
- [select/selectCases/selectDefault](#selectselectcasesselectdefault) (BETA)
|
||||
- [Keywords for all types](#keywords-for-all-types)
|
||||
- [dynamicDefaults](#dynamicdefaults)<sup>\*</sup>
|
||||
- [License](#license)
|
||||
|
||||
<sup>\*</sup> - keywords that modify data
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install ajv-keywords
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
To add all available keywords:
|
||||
|
||||
```javascript
|
||||
var Ajv = require('ajv');
|
||||
var ajv = new Ajv;
|
||||
require('ajv-keywords')(ajv);
|
||||
|
||||
ajv.validate({ instanceof: 'RegExp' }, /.*/); // true
|
||||
ajv.validate({ instanceof: 'RegExp' }, '.*'); // false
|
||||
```
|
||||
|
||||
To add a single keyword:
|
||||
|
||||
```javascript
|
||||
require('ajv-keywords')(ajv, 'instanceof');
|
||||
```
|
||||
|
||||
To add multiple keywords:
|
||||
|
||||
```javascript
|
||||
require('ajv-keywords')(ajv, ['typeof', 'instanceof']);
|
||||
```
|
||||
|
||||
To add a single keyword in browser (to avoid adding unused code):
|
||||
|
||||
```javascript
|
||||
require('ajv-keywords/keywords/instanceof')(ajv);
|
||||
```
|
||||
|
||||
|
||||
## Keywords
|
||||
|
||||
### Types
|
||||
|
||||
#### `typeof`
|
||||
|
||||
Based on JavaScript `typeof` operation.
|
||||
|
||||
The value of the keyword should be a string (`"undefined"`, `"string"`, `"number"`, `"object"`, `"function"`, `"boolean"` or `"symbol"`) or array of strings.
|
||||
|
||||
To pass validation the result of `typeof` operation on the value should be equal to the string (or one of the strings in the array).
|
||||
|
||||
```
|
||||
ajv.validate({ typeof: 'undefined' }, undefined); // true
|
||||
ajv.validate({ typeof: 'undefined' }, null); // false
|
||||
ajv.validate({ typeof: ['undefined', 'object'] }, null); // true
|
||||
```
|
||||
|
||||
|
||||
#### `instanceof`
|
||||
|
||||
Based on JavaScript `instanceof` operation.
|
||||
|
||||
The value of the keyword should be a string (`"Object"`, `"Array"`, `"Function"`, `"Number"`, `"String"`, `"Date"`, `"RegExp"`, `"Promise"` or `"Buffer"`) or array of strings.
|
||||
|
||||
To pass validation the result of `data instanceof ...` operation on the value should be true:
|
||||
|
||||
```
|
||||
ajv.validate({ instanceof: 'Array' }, []); // true
|
||||
ajv.validate({ instanceof: 'Array' }, {}); // false
|
||||
ajv.validate({ instanceof: ['Array', 'Function'] }, function(){}); // true
|
||||
```
|
||||
|
||||
You can add your own constructor function to be recognised by this keyword:
|
||||
|
||||
```javascript
|
||||
function MyClass() {}
|
||||
var instanceofDefinition = require('ajv-keywords').get('instanceof').definition;
|
||||
// or require('ajv-keywords/keywords/instanceof').definition;
|
||||
instanceofDefinition.CONSTRUCTORS.MyClass = MyClass;
|
||||
|
||||
ajv.validate({ instanceof: 'MyClass' }, new MyClass); // true
|
||||
```
|
||||
|
||||
|
||||
### Keywords for numbers
|
||||
|
||||
#### `range` and `exclusiveRange`
|
||||
|
||||
Syntax sugar for the combination of minimum and maximum keywords, also fails schema compilation if there are no numbers in the range.
|
||||
|
||||
The value of this keyword must be the array consisting of two numbers, the second must be greater or equal than the first one.
|
||||
|
||||
If the validated value is not a number the validation passes, otherwise to pass validation the value should be greater (or equal) than the first number and smaller (or equal) than the second number in the array. If `exclusiveRange` keyword is present in the same schema and its value is true, the validated value must not be equal to the range boundaries.
|
||||
|
||||
```javascript
|
||||
var schema = { range: [1, 3] };
|
||||
ajv.validate(schema, 1); // true
|
||||
ajv.validate(schema, 2); // true
|
||||
ajv.validate(schema, 3); // true
|
||||
ajv.validate(schema, 0.99); // false
|
||||
ajv.validate(schema, 3.01); // false
|
||||
|
||||
var schema = { range: [1, 3], exclusiveRange: true };
|
||||
ajv.validate(schema, 1.01); // true
|
||||
ajv.validate(schema, 2); // true
|
||||
ajv.validate(schema, 2.99); // true
|
||||
ajv.validate(schema, 1); // false
|
||||
ajv.validate(schema, 3); // false
|
||||
```
|
||||
|
||||
|
||||
### Keywords for strings
|
||||
|
||||
#### `regexp`
|
||||
|
||||
This keyword allows to use regular expressions with flags in schemas (the standard `pattern` keyword does not support flags).
|
||||
|
||||
This keyword applies only to strings. If the data is not a string, the validation succeeds.
|
||||
|
||||
The value of this keyword can be either a string (the result of `regexp.toString()`) or an object with the properties `pattern` and `flags` (the same strings that should be passed to RegExp constructor).
|
||||
|
||||
```javascript
|
||||
var schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: { regexp: '/foo/i' },
|
||||
bar: { regexp: { pattern: 'bar', flags: 'i' } }
|
||||
}
|
||||
};
|
||||
|
||||
var validData = {
|
||||
foo: 'Food',
|
||||
bar: 'Barmen'
|
||||
};
|
||||
|
||||
var invalidData = {
|
||||
foo: 'fog',
|
||||
bar: 'bad'
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
#### `formatMaximum` / `formatMinimum` and `formatExclusiveMaximum` / `formatExclusiveMinimum`
|
||||
|
||||
These keywords allow to define minimum/maximum constraints when the format keyword defines ordering.
|
||||
|
||||
These keywords apply only to strings. If the data is not a string, the validation succeeds.
|
||||
|
||||
The value of keyword `formatMaximum` (`formatMinimum`) should be a string. This value is the maximum (minimum) allowed value for the data to be valid as determined by `format` keyword. If `format` is not present schema compilation will throw exception.
|
||||
|
||||
When this keyword is added, it defines comparison rules for formats `"date"`, `"time"` and `"date-time"`. Custom formats also can have comparison rules. See [addFormat](https://github.com/epoberezkin/ajv#api-addformat) method.
|
||||
|
||||
The value of keyword `formatExclusiveMaximum` (`formatExclusiveMinimum`) should be a boolean value. These keyword cannot be used without `formatMaximum` (`formatMinimum`). If this keyword value is equal to `true`, the data to be valid should not be equal to the value in `formatMaximum` (`formatMinimum`) keyword.
|
||||
|
||||
```javascript
|
||||
require('ajv-keywords')(ajv, ['formatMinimum', 'formatMaximum']);
|
||||
|
||||
var schema = {
|
||||
format: 'date',
|
||||
formatMinimum: '2016-02-06',
|
||||
formatMaximum: '2016-12-27',
|
||||
formatExclusiveMaximum: true
|
||||
}
|
||||
|
||||
var validDataList = ['2016-02-06', '2016-12-26', 1];
|
||||
|
||||
var invalidDataList = ['2016-02-05', '2016-12-27', 'abc'];
|
||||
```
|
||||
|
||||
|
||||
#### `transform`
|
||||
|
||||
This keyword allows a string to be modified before validation.
|
||||
|
||||
These keywords apply only to strings. If the data is not a string, the transform is skipped.
|
||||
|
||||
There are limitation due to how ajv is written:
|
||||
- a stand alone string cannot be transformed. ie `data = 'a'; ajv.validate(schema, data);`
|
||||
- currently cannot work with `ajv-pack`
|
||||
|
||||
**Supported options:**
|
||||
- `trim`: remove whitespace from start and end
|
||||
- `trimLeft`: remove whitespace from start
|
||||
- `trimRight`: remove whitespace from end
|
||||
- `toLowerCase`: case string to all lower case
|
||||
- `toUpperCase`: case string to all upper case
|
||||
- `toEnumCase`: case string to match case in schema
|
||||
|
||||
Options are applied in the order they are listed.
|
||||
|
||||
Note: `toEnumCase` requires that all allowed values are unique when case insensitive.
|
||||
|
||||
**Example: multiple options**
|
||||
```javascript
|
||||
require('ajv-keywords')(ajv, ['transform']);
|
||||
|
||||
var schema = {
|
||||
type: 'array',
|
||||
items: {
|
||||
type:'string',
|
||||
transform:['trim','toLowerCase']
|
||||
}
|
||||
};
|
||||
|
||||
var data = [' MixCase '];
|
||||
ajv.validate(schema, data);
|
||||
console.log(data); // ['mixcase']
|
||||
|
||||
```
|
||||
|
||||
**Example: `enumcase`**
|
||||
```javascript
|
||||
require('ajv-keywords')(ajv, ['transform']);
|
||||
|
||||
var schema = {
|
||||
type: 'array',
|
||||
items: {
|
||||
type:'string',
|
||||
transform:['trim','toEnumCase'],
|
||||
enum:['pH']
|
||||
}
|
||||
};
|
||||
|
||||
var data = ['ph',' Ph','PH','pH '];
|
||||
ajv.validate(schema, data);
|
||||
console.log(data); // ['pH','pH','pH','pH']
|
||||
```
|
||||
|
||||
|
||||
### Keywords for arrays
|
||||
|
||||
#### `uniqueItemProperties`
|
||||
|
||||
The keyword allows to check that some properties in array items are unique.
|
||||
|
||||
This keyword applies only to arrays. If the data is not an array, the validation succeeds.
|
||||
|
||||
The value of this keyword must be an array of strings - property names that should have unique values across all items.
|
||||
|
||||
```javascript
|
||||
var schema = { uniqueItemProperties: [ "id", "name" ] };
|
||||
|
||||
var validData = [
|
||||
{ id: 1 },
|
||||
{ id: 2 },
|
||||
{ id: 3 }
|
||||
];
|
||||
|
||||
var invalidData1 = [
|
||||
{ id: 1 },
|
||||
{ id: 1 }, // duplicate "id"
|
||||
{ id: 3 }
|
||||
];
|
||||
|
||||
var invalidData2 = [
|
||||
{ id: 1, name: "taco" },
|
||||
{ id: 2, name: "taco" }, // duplicate "name"
|
||||
{ id: 3, name: "salsa" }
|
||||
];
|
||||
```
|
||||
|
||||
This keyword is contributed by [@blainesch](https://github.com/blainesch).
|
||||
|
||||
|
||||
### Keywords for objects
|
||||
|
||||
#### `allRequired`
|
||||
|
||||
This keyword allows to require the presence of all properties used in `properties` keyword in the same schema object.
|
||||
|
||||
This keyword applies only to objects. If the data is not an object, the validation succeeds.
|
||||
|
||||
The value of this keyword must be boolean.
|
||||
|
||||
If the value of the keyword is `false`, the validation succeeds.
|
||||
|
||||
If the value of the keyword is `true`, the validation succeeds if the data contains all properties defined in `properties` keyword (in the same schema object).
|
||||
|
||||
If the `properties` keyword is not present in the same schema object, schema compilation will throw exception.
|
||||
|
||||
```javascript
|
||||
var schema = {
|
||||
properties: {
|
||||
foo: {type: 'number'},
|
||||
bar: {type: 'number'}
|
||||
}
|
||||
allRequired: true
|
||||
};
|
||||
|
||||
var validData = { foo: 1, bar: 2 };
|
||||
var alsoValidData = { foo: 1, bar: 2, baz: 3 };
|
||||
|
||||
var invalidDataList = [ {}, { foo: 1 }, { bar: 2 } ];
|
||||
```
|
||||
|
||||
|
||||
#### `anyRequired`
|
||||
|
||||
This keyword allows to require the presence of any (at least one) property from the list.
|
||||
|
||||
This keyword applies only to objects. If the data is not an object, the validation succeeds.
|
||||
|
||||
The value of this keyword must be an array of strings, each string being a property name. For data object to be valid at least one of the properties in this array should be present in the object.
|
||||
|
||||
```javascript
|
||||
var schema = {
|
||||
anyRequired: ['foo', 'bar']
|
||||
};
|
||||
|
||||
var validData = { foo: 1 };
|
||||
var alsoValidData = { foo: 1, bar: 2 };
|
||||
|
||||
var invalidDataList = [ {}, { baz: 3 } ];
|
||||
```
|
||||
|
||||
|
||||
#### `oneRequired`
|
||||
|
||||
This keyword allows to require the presence of only one property from the list.
|
||||
|
||||
This keyword applies only to objects. If the data is not an object, the validation succeeds.
|
||||
|
||||
The value of this keyword must be an array of strings, each string being a property name. For data object to be valid exactly one of the properties in this array should be present in the object.
|
||||
|
||||
```javascript
|
||||
var schema = {
|
||||
oneRequired: ['foo', 'bar']
|
||||
};
|
||||
|
||||
var validData = { foo: 1 };
|
||||
var alsoValidData = { bar: 2, baz: 3 };
|
||||
|
||||
var invalidDataList = [ {}, { baz: 3 }, { foo: 1, bar: 2 } ];
|
||||
```
|
||||
|
||||
|
||||
#### `patternRequired`
|
||||
|
||||
This keyword allows to require the presence of properties that match some pattern(s).
|
||||
|
||||
This keyword applies only to objects. If the data is not an object, the validation succeeds.
|
||||
|
||||
The value of this keyword should be an array of strings, each string being a regular expression. For data object to be valid each regular expression in this array should match at least one property name in the data object.
|
||||
|
||||
If the array contains multiple regular expressions, more than one expression can match the same property name.
|
||||
|
||||
```javascript
|
||||
var schema = { patternRequired: [ 'f.*o', 'b.*r' ] };
|
||||
|
||||
var validData = { foo: 1, bar: 2 };
|
||||
var alsoValidData = { foobar: 3 };
|
||||
|
||||
var invalidDataList = [ {}, { foo: 1 }, { bar: 2 } ];
|
||||
```
|
||||
|
||||
|
||||
#### `prohibited`
|
||||
|
||||
This keyword allows to prohibit that any of the properties in the list is present in the object.
|
||||
|
||||
This keyword applies only to objects. If the data is not an object, the validation succeeds.
|
||||
|
||||
The value of this keyword should be an array of strings, each string being a property name. For data object to be valid none of the properties in this array should be present in the object.
|
||||
|
||||
```
|
||||
var schema = { prohibited: ['foo', 'bar']};
|
||||
|
||||
var validData = { baz: 1 };
|
||||
var alsoValidData = {};
|
||||
|
||||
var invalidDataList = [
|
||||
{ foo: 1 },
|
||||
{ bar: 2 },
|
||||
{ foo: 1, bar: 2}
|
||||
];
|
||||
```
|
||||
|
||||
__Please note__: `{prohibited: ['foo', 'bar']}` is equivalent to `{not: {anyRequired: ['foo', 'bar']}}` (i.e. it has the same validation result for any data).
|
||||
|
||||
|
||||
#### `deepProperties`
|
||||
|
||||
This keyword allows to validate deep properties (identified by JSON pointers).
|
||||
|
||||
This keyword applies only to objects. If the data is not an object, the validation succeeds.
|
||||
|
||||
The value should be an object, where keys are JSON pointers to the data, starting from the current position in data, and the values are JSON schemas. For data object to be valid the value of each JSON pointer should be valid according to the corresponding schema.
|
||||
|
||||
```javascript
|
||||
var schema = {
|
||||
type: 'object',
|
||||
deepProperties: {
|
||||
"/users/1/role": { "enum": ["admin"] }
|
||||
}
|
||||
};
|
||||
|
||||
var validData = {
|
||||
users: [
|
||||
{},
|
||||
{
|
||||
id: 123,
|
||||
role: 'admin'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var alsoValidData = {
|
||||
users: {
|
||||
"1": {
|
||||
id: 123,
|
||||
role: 'admin'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var invalidData = {
|
||||
users: [
|
||||
{},
|
||||
{
|
||||
id: 123,
|
||||
role: 'user'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var alsoInvalidData = {
|
||||
users: {
|
||||
"1": {
|
||||
id: 123,
|
||||
role: 'user'
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
#### `deepRequired`
|
||||
|
||||
This keyword allows to check that some deep properties (identified by JSON pointers) are available.
|
||||
|
||||
This keyword applies only to objects. If the data is not an object, the validation succeeds.
|
||||
|
||||
The value should be an array of JSON pointers to the data, starting from the current position in data. For data object to be valid each JSON pointer should be some existing part of the data.
|
||||
|
||||
```javascript
|
||||
var schema = {
|
||||
type: 'object',
|
||||
deepRequired: ["/users/1/role"]
|
||||
};
|
||||
|
||||
var validData = {
|
||||
users: [
|
||||
{},
|
||||
{
|
||||
id: 123,
|
||||
role: 'admin'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var invalidData = {
|
||||
users: [
|
||||
{},
|
||||
{
|
||||
id: 123
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
See [json-schema-org/json-schema-spec#203](https://github.com/json-schema-org/json-schema-spec/issues/203#issue-197211916) for an example of the equivalent schema without `deepRequired` keyword.
|
||||
|
||||
|
||||
### Compound keywords
|
||||
|
||||
#### `switch` (deprecated)
|
||||
|
||||
__Please note__: this keyword is provided to preserve backward compatibility with previous versions of Ajv. It is strongly recommended to use `if`/`then`/`else` keywords instead, as they have been added to the draft-07 of JSON Schema specification.
|
||||
|
||||
This keyword allows to perform advanced conditional validation.
|
||||
|
||||
The value of the keyword is the array of if/then clauses. Each clause is the object with the following properties:
|
||||
|
||||
- `if` (optional) - the value is JSON-schema
|
||||
- `then` (required) - the value is JSON-schema or boolean
|
||||
- `continue` (optional) - the value is boolean
|
||||
|
||||
The validation process is dynamic; all clauses are executed sequentially in the following way:
|
||||
|
||||
1. `if`:
|
||||
1. `if` property is JSON-schema according to which the data is:
|
||||
1. valid => go to step 2.
|
||||
2. invalid => go to the NEXT clause, if this was the last clause the validation of `switch` SUCCEEDS.
|
||||
2. `if` property is absent => go to step 2.
|
||||
2. `then`:
|
||||
1. `then` property is `true` or it is JSON-schema according to which the data is valid => go to step 3.
|
||||
2. `then` property is `false` or it is JSON-schema according to which the data is invalid => the validation of `switch` FAILS.
|
||||
3. `continue`:
|
||||
1. `continue` property is `true` => go to the NEXT clause, if this was the last clause the validation of `switch` SUCCEEDS.
|
||||
2. `continue` property is `false` or absent => validation of `switch` SUCCEEDS.
|
||||
|
||||
```javascript
|
||||
require('ajv-keywords')(ajv, 'switch');
|
||||
|
||||
var schema = {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'integer',
|
||||
'switch': [
|
||||
{ if: { not: { minimum: 1 } }, then: false },
|
||||
{ if: { maximum: 10 }, then: true },
|
||||
{ if: { maximum: 100 }, then: { multipleOf: 10 } },
|
||||
{ if: { maximum: 1000 }, then: { multipleOf: 100 } },
|
||||
{ then: false }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var validItems = [1, 5, 10, 20, 50, 100, 200, 500, 1000];
|
||||
|
||||
var invalidItems = [1, 0, 2000, 11, 57, 123, 'foo'];
|
||||
```
|
||||
|
||||
The above schema is equivalent to (for example):
|
||||
|
||||
```javascript
|
||||
{
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'integer',
|
||||
if: { minimum: 1, maximum: 10 },
|
||||
then: true,
|
||||
else: {
|
||||
if: { maximum: 100 },
|
||||
then: { multipleOf: 10 },
|
||||
else: {
|
||||
if: { maximum: 1000 },
|
||||
then: { multipleOf: 100 },
|
||||
else: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### `select`/`selectCases`/`selectDefault`
|
||||
|
||||
These keywords allow to choose the schema to validate the data based on the value of some property in the validated data.
|
||||
|
||||
These keywords must be present in the same schema object (`selectDefault` is optional).
|
||||
|
||||
The value of `select` keyword should be a [$data reference](https://github.com/epoberezkin/ajv/tree/5.0.2-beta.0#data-reference) that points to any primitive JSON type (string, number, boolean or null) in the data that is validated. You can also use a constant of primitive type as the value of this keyword (e.g., for debugging purposes).
|
||||
|
||||
The value of `selectCases` keyword must be an object where each property name is a possible string representation of the value of `select` keyword and each property value is a corresponding schema (from draft-06 it can be boolean) that must be used to validate the data.
|
||||
|
||||
The value of `selectDefault` keyword is a schema (from draft-06 it can be boolean) that must be used to validate the data in case `selectCases` has no key equal to the stringified value of `select` keyword.
|
||||
|
||||
The validation succeeds in one of the following cases:
|
||||
- the validation of data using selected schema succeeds,
|
||||
- none of the schemas is selected for validation,
|
||||
- the value of select is undefined (no property in the data that the data reference points to).
|
||||
|
||||
If `select` value (in data) is not a primitive type the validation fails.
|
||||
|
||||
__Please note__: these keywords require Ajv `$data` option to support [$data reference](https://github.com/epoberezkin/ajv/tree/5.0.2-beta.0#data-reference).
|
||||
|
||||
|
||||
```javascript
|
||||
require('ajv-keywords')(ajv, 'select');
|
||||
|
||||
var schema = {
|
||||
type: object,
|
||||
required: ['kind'],
|
||||
properties: {
|
||||
kind: { type: 'string' }
|
||||
},
|
||||
select: { $data: '0/kind' },
|
||||
selectCases: {
|
||||
foo: {
|
||||
required: ['foo'],
|
||||
properties: {
|
||||
kind: {},
|
||||
foo: { type: 'string' }
|
||||
},
|
||||
additionalProperties: false
|
||||
},
|
||||
bar: {
|
||||
required: ['bar'],
|
||||
properties: {
|
||||
kind: {},
|
||||
bar: { type: 'number' }
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
},
|
||||
selectDefault: {
|
||||
propertyNames: {
|
||||
not: { enum: ['foo', 'bar'] }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var validDataList = [
|
||||
{ kind: 'foo', foo: 'any' },
|
||||
{ kind: 'bar', bar: 1 },
|
||||
{ kind: 'anything_else', not_bar_or_foo: 'any value' }
|
||||
];
|
||||
|
||||
var invalidDataList = [
|
||||
{ kind: 'foo' }, // no propery foo
|
||||
{ kind: 'bar' }, // no propery bar
|
||||
{ kind: 'foo', foo: 'any', another: 'any value' }, // additional property
|
||||
{ kind: 'bar', bar: 1, another: 'any value' }, // additional property
|
||||
{ kind: 'anything_else', foo: 'any' } // property foo not allowed
|
||||
{ kind: 'anything_else', bar: 1 } // property bar not allowed
|
||||
];
|
||||
```
|
||||
|
||||
__Please note__: the current implementation is BETA. It does not allow using relative URIs in $ref keywords in schemas in `selectCases` and `selectDefault` that point outside of these schemas. The workaround is to use absolute URIs (that can point to any (sub-)schema added to Ajv, including those inside the current root schema where `select` is used). See [tests](https://github.com/epoberezkin/ajv-keywords/blob/v2.0.0/spec/tests/select.json#L314).
|
||||
|
||||
|
||||
### Keywords for all types
|
||||
|
||||
#### `dynamicDefaults`
|
||||
|
||||
This keyword allows to assign dynamic defaults to properties, such as timestamps, unique IDs etc.
|
||||
|
||||
This keyword only works if `useDefaults` options is used and not inside `anyOf` keywords etc., in the same way as [default keyword treated by Ajv](https://github.com/epoberezkin/ajv#assigning-defaults).
|
||||
|
||||
The keyword should be added on the object level. Its value should be an object with each property corresponding to a property name, in the same way as in standard `properties` keyword. The value of each property can be:
|
||||
|
||||
- an identifier of default function (a string)
|
||||
- an object with properties `func` (an identifier) and `args` (an object with parameters that will be passed to this function during schema compilation - see examples).
|
||||
|
||||
The properties used in `dynamicDefaults` should not be added to `required` keyword (or validation will fail), because unlike `default` this keyword is processed after validation.
|
||||
|
||||
There are several predefined dynamic default functions:
|
||||
|
||||
- `"timestamp"` - current timestamp in milliseconds
|
||||
- `"datetime"` - current date and time as string (ISO, valid according to `date-time` format)
|
||||
- `"date"` - current date as string (ISO, valid according to `date` format)
|
||||
- `"time"` - current time as string (ISO, valid according to `time` format)
|
||||
- `"random"` - pseudo-random number in [0, 1) interval
|
||||
- `"randomint"` - pseudo-random integer number. If string is used as a property value, the function will randomly return 0 or 1. If object `{ func: 'randomint', args: { max: N } }` is used then the default will be an integer number in [0, N) interval.
|
||||
- `"seq"` - sequential integer number starting from 0. If string is used as a property value, the default sequence will be used. If object `{ func: 'seq', args: { name: 'foo'} }` is used then the sequence with name `"foo"` will be used. Sequences are global, even if different ajv instances are used.
|
||||
|
||||
```javascript
|
||||
var schema = {
|
||||
type: 'object',
|
||||
dynamicDefaults: {
|
||||
ts: 'datetime',
|
||||
r: { func: 'randomint', args: { max: 100 } },
|
||||
id: { func: 'seq', args: { name: 'id' } }
|
||||
},
|
||||
properties: {
|
||||
ts: {
|
||||
type: 'string',
|
||||
format: 'date-time'
|
||||
},
|
||||
r: {
|
||||
type: 'integer',
|
||||
minimum: 0,
|
||||
exclusiveMaximum: 100
|
||||
},
|
||||
id: {
|
||||
type: 'integer',
|
||||
minimum: 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var data = {};
|
||||
ajv.validate(data); // true
|
||||
data; // { ts: '2016-12-01T22:07:28.829Z', r: 25, id: 0 }
|
||||
|
||||
var data1 = {};
|
||||
ajv.validate(data1); // true
|
||||
data1; // { ts: '2016-12-01T22:07:29.832Z', r: 68, id: 1 }
|
||||
|
||||
ajv.validate(data1); // true
|
||||
data1; // didn't change, as all properties were defined
|
||||
```
|
||||
|
||||
When using the `useDefaults` option value `"empty"`, properties and items equal to `null` or `""` (empty string) will be considered missing and assigned defaults. Use the `allOf` [compound keyword](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#compound-keywords) to execute `dynamicDefaults` before validation.
|
||||
|
||||
```javascript
|
||||
var schema = {
|
||||
allOf: [
|
||||
{
|
||||
dynamicDefaults: {
|
||||
ts: 'datetime',
|
||||
r: { func: 'randomint', args: { min: 5, max: 100 } },
|
||||
id: { func: 'seq', args: { name: 'id' } }
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
ts: {
|
||||
type: 'string'
|
||||
},
|
||||
r: {
|
||||
type: 'number',
|
||||
minimum: 5,
|
||||
exclusiveMaximum: 100
|
||||
},
|
||||
id: {
|
||||
type: 'integer',
|
||||
minimum: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var data = { ts: '', r: null };
|
||||
ajv.validate(data); // true
|
||||
data; // { ts: '2016-12-01T22:07:28.829Z', r: 25, id: 0 }
|
||||
```
|
||||
|
||||
You can add your own dynamic default function to be recognised by this keyword:
|
||||
|
||||
```javascript
|
||||
var uuid = require('uuid');
|
||||
|
||||
function uuidV4() { return uuid.v4(); }
|
||||
|
||||
var definition = require('ajv-keywords').get('dynamicDefaults').definition;
|
||||
// or require('ajv-keywords/keywords/dynamicDefaults').definition;
|
||||
definition.DEFAULTS.uuid = uuidV4;
|
||||
|
||||
var schema = {
|
||||
dynamicDefaults: { id: 'uuid' },
|
||||
properties: { id: { type: 'string', format: 'uuid' } }
|
||||
};
|
||||
|
||||
var data = {};
|
||||
ajv.validate(schema, data); // true
|
||||
data; // { id: 'a1183fbe-697b-4030-9bcc-cfeb282a9150' };
|
||||
|
||||
var data1 = {};
|
||||
ajv.validate(schema, data1); // true
|
||||
data1; // { id: '5b008de7-1669-467a-a5c6-70fa244d7209' }
|
||||
```
|
||||
|
||||
You also can define dynamic default that accepts parameters, e.g. version of uuid:
|
||||
|
||||
```javascript
|
||||
var uuid = require('uuid');
|
||||
|
||||
function getUuid(args) {
|
||||
var version = 'v' + (arvs && args.v || 4);
|
||||
return function() {
|
||||
return uuid[version]();
|
||||
};
|
||||
}
|
||||
|
||||
var definition = require('ajv-keywords').get('dynamicDefaults').definition;
|
||||
definition.DEFAULTS.uuid = getUuid;
|
||||
|
||||
var schema = {
|
||||
dynamicDefaults: {
|
||||
id1: 'uuid', // v4
|
||||
id2: { func: 'uuid', v: 4 }, // v4
|
||||
id3: { func: 'uuid', v: 1 } // v1
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/epoberezkin/ajv-keywords/blob/master/LICENSE)
|
@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
|
||||
var KEYWORDS = require('./keywords');
|
||||
|
||||
module.exports = defineKeywords;
|
||||
|
||||
|
||||
/**
|
||||
* Defines one or several keywords in ajv instance
|
||||
* @param {Ajv} ajv validator instance
|
||||
* @param {String|Array<String>|undefined} keyword keyword(s) to define
|
||||
* @return {Ajv} ajv instance (for chaining)
|
||||
*/
|
||||
function defineKeywords(ajv, keyword) {
|
||||
if (Array.isArray(keyword)) {
|
||||
for (var i=0; i<keyword.length; i++)
|
||||
get(keyword[i])(ajv);
|
||||
return ajv;
|
||||
}
|
||||
if (keyword) {
|
||||
get(keyword)(ajv);
|
||||
return ajv;
|
||||
}
|
||||
for (keyword in KEYWORDS) get(keyword)(ajv);
|
||||
return ajv;
|
||||
}
|
||||
|
||||
|
||||
defineKeywords.get = get;
|
||||
|
||||
function get(keyword) {
|
||||
var defFunc = KEYWORDS[keyword];
|
||||
if (!defFunc) throw new Error('Unknown keyword ' + keyword);
|
||||
return defFunc;
|
||||
}
|
101
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/_formatLimit.js
generated
vendored
101
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/_formatLimit.js
generated
vendored
@ -0,0 +1,101 @@
|
||||
'use strict';
|
||||
|
||||
var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i;
|
||||
var DATE_TIME_SEPARATOR = /t|\s/i;
|
||||
|
||||
var COMPARE_FORMATS = {
|
||||
date: compareDate,
|
||||
time: compareTime,
|
||||
'date-time': compareDateTime
|
||||
};
|
||||
|
||||
var $dataMetaSchema = {
|
||||
type: 'object',
|
||||
required: [ '$data' ],
|
||||
properties: {
|
||||
$data: {
|
||||
type: 'string',
|
||||
anyOf: [
|
||||
{ format: 'relative-json-pointer' },
|
||||
{ format: 'json-pointer' }
|
||||
]
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
};
|
||||
|
||||
module.exports = function (minMax) {
|
||||
var keyword = 'format' + minMax;
|
||||
return function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'string',
|
||||
inline: require('./dotjs/_formatLimit'),
|
||||
statements: true,
|
||||
errors: 'full',
|
||||
dependencies: ['format'],
|
||||
metaSchema: {
|
||||
anyOf: [
|
||||
{type: 'string'},
|
||||
$dataMetaSchema
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword(keyword, defFunc.definition);
|
||||
ajv.addKeyword('formatExclusive' + minMax, {
|
||||
dependencies: ['format' + minMax],
|
||||
metaSchema: {
|
||||
anyOf: [
|
||||
{type: 'boolean'},
|
||||
$dataMetaSchema
|
||||
]
|
||||
}
|
||||
});
|
||||
extendFormats(ajv);
|
||||
return ajv;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
function extendFormats(ajv) {
|
||||
var formats = ajv._formats;
|
||||
for (var name in COMPARE_FORMATS) {
|
||||
var format = formats[name];
|
||||
// the last condition is needed if it's RegExp from another window
|
||||
if (typeof format != 'object' || format instanceof RegExp || !format.validate)
|
||||
format = formats[name] = { validate: format };
|
||||
if (!format.compare)
|
||||
format.compare = COMPARE_FORMATS[name];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function compareDate(d1, d2) {
|
||||
if (!(d1 && d2)) return;
|
||||
if (d1 > d2) return 1;
|
||||
if (d1 < d2) return -1;
|
||||
if (d1 === d2) return 0;
|
||||
}
|
||||
|
||||
|
||||
function compareTime(t1, t2) {
|
||||
if (!(t1 && t2)) return;
|
||||
t1 = t1.match(TIME);
|
||||
t2 = t2.match(TIME);
|
||||
if (!(t1 && t2)) return;
|
||||
t1 = t1[1] + t1[2] + t1[3] + (t1[4]||'');
|
||||
t2 = t2[1] + t2[2] + t2[3] + (t2[4]||'');
|
||||
if (t1 > t2) return 1;
|
||||
if (t1 < t2) return -1;
|
||||
if (t1 === t2) return 0;
|
||||
}
|
||||
|
||||
|
||||
function compareDateTime(dt1, dt2) {
|
||||
if (!(dt1 && dt2)) return;
|
||||
dt1 = dt1.split(DATE_TIME_SEPARATOR);
|
||||
dt2 = dt2.split(DATE_TIME_SEPARATOR);
|
||||
var res = compareDate(dt1[0], dt2[0]);
|
||||
if (res === undefined) return;
|
||||
return res || compareTime(dt1[1], dt2[1]);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
metaSchemaRef: metaSchemaRef
|
||||
};
|
||||
|
||||
var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema';
|
||||
|
||||
function metaSchemaRef(ajv) {
|
||||
var defaultMeta = ajv._opts.defaultMeta;
|
||||
if (typeof defaultMeta == 'string') return { $ref: defaultMeta };
|
||||
if (ajv.getSchema(META_SCHEMA_ID)) return { $ref: META_SCHEMA_ID };
|
||||
console.warn('meta schema not defined');
|
||||
return {};
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'object',
|
||||
macro: function (schema, parentSchema) {
|
||||
if (!schema) return true;
|
||||
var properties = Object.keys(parentSchema.properties);
|
||||
if (properties.length == 0) return true;
|
||||
return {required: properties};
|
||||
},
|
||||
metaSchema: {type: 'boolean'},
|
||||
dependencies: ['properties']
|
||||
};
|
||||
|
||||
ajv.addKeyword('allRequired', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'object',
|
||||
macro: function (schema) {
|
||||
if (schema.length == 0) return true;
|
||||
if (schema.length == 1) return {required: schema};
|
||||
var schemas = schema.map(function (prop) {
|
||||
return {required: [prop]};
|
||||
});
|
||||
return {anyOf: schemas};
|
||||
},
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('anyRequired', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
54
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/deepProperties.js
generated
vendored
54
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/deepProperties.js
generated
vendored
@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('./_util');
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'object',
|
||||
macro: function (schema) {
|
||||
var schemas = [];
|
||||
for (var pointer in schema)
|
||||
schemas.push(getSchema(pointer, schema[pointer]));
|
||||
return {'allOf': schemas};
|
||||
},
|
||||
metaSchema: {
|
||||
type: 'object',
|
||||
propertyNames: {
|
||||
type: 'string',
|
||||
format: 'json-pointer'
|
||||
},
|
||||
additionalProperties: util.metaSchemaRef(ajv)
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('deepProperties', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
||||
|
||||
|
||||
function getSchema(jsonPointer, schema) {
|
||||
var segments = jsonPointer.split('/');
|
||||
var rootSchema = {};
|
||||
var pointerSchema = rootSchema;
|
||||
for (var i=1; i<segments.length; i++) {
|
||||
var segment = segments[i];
|
||||
var isLast = i == segments.length - 1;
|
||||
segment = unescapeJsonPointer(segment);
|
||||
var properties = pointerSchema.properties = {};
|
||||
var items = undefined;
|
||||
if (/[0-9]+/.test(segment)) {
|
||||
var count = +segment;
|
||||
items = pointerSchema.items = [];
|
||||
while (count--) items.push({});
|
||||
}
|
||||
pointerSchema = isLast ? schema : {};
|
||||
properties[segment] = pointerSchema;
|
||||
if (items) items.push(pointerSchema);
|
||||
}
|
||||
return rootSchema;
|
||||
}
|
||||
|
||||
|
||||
function unescapeJsonPointer(str) {
|
||||
return str.replace(/~1/g, '/').replace(/~0/g, '~');
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'object',
|
||||
inline: function (it, keyword, schema) {
|
||||
var expr = '';
|
||||
for (var i=0; i<schema.length; i++) {
|
||||
if (i) expr += ' && ';
|
||||
expr += '(' + getData(schema[i], it.dataLevel) + ' !== undefined)';
|
||||
}
|
||||
return expr;
|
||||
},
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
format: 'json-pointer'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('deepRequired', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
||||
|
||||
|
||||
function getData(jsonPointer, lvl) {
|
||||
var data = 'data' + (lvl || '');
|
||||
if (!jsonPointer) return data;
|
||||
|
||||
var expr = data;
|
||||
var segments = jsonPointer.split('/');
|
||||
for (var i=1; i<segments.length; i++) {
|
||||
var segment = segments[i];
|
||||
data += getProperty(unescapeJsonPointer(segment));
|
||||
expr += ' && ' + data;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
|
||||
var INTEGER = /^[0-9]+$/;
|
||||
var SINGLE_QUOTE = /'|\\/g;
|
||||
function getProperty(key) {
|
||||
return INTEGER.test(key)
|
||||
? '[' + key + ']'
|
||||
: IDENTIFIER.test(key)
|
||||
? '.' + key
|
||||
: "['" + key.replace(SINGLE_QUOTE, '\\$&') + "']";
|
||||
}
|
||||
|
||||
|
||||
function unescapeJsonPointer(str) {
|
||||
return str.replace(/~1/g, '/').replace(/~0/g, '~');
|
||||
}
|
116
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dot/_formatLimit.jst
generated
vendored
116
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dot/_formatLimit.jst
generated
vendored
@ -0,0 +1,116 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
|
||||
var {{=$valid}} = undefined;
|
||||
|
||||
{{## def.skipFormatLimit:
|
||||
{{=$valid}} = true;
|
||||
{{ return out; }}
|
||||
#}}
|
||||
|
||||
{{## def.compareFormat:
|
||||
{{? $isData }}
|
||||
if ({{=$schemaValue}} === undefined) {{=$valid}} = true;
|
||||
else if (typeof {{=$schemaValue}} != 'string') {{=$valid}} = false;
|
||||
else {
|
||||
{{ $closingBraces += '}'; }}
|
||||
{{?}}
|
||||
|
||||
{{? $isDataFormat }}
|
||||
if (!{{=$compare}}) {{=$valid}} = true;
|
||||
else {
|
||||
{{ $closingBraces += '}'; }}
|
||||
{{?}}
|
||||
|
||||
var {{=$result}} = {{=$compare}}({{=$data}}, {{# def.schemaValueQS }});
|
||||
|
||||
if ({{=$result}} === undefined) {{=$valid}} = false;
|
||||
#}}
|
||||
|
||||
|
||||
{{? it.opts.format === false }}{{# def.skipFormatLimit }}{{?}}
|
||||
|
||||
{{
|
||||
var $schemaFormat = it.schema.format
|
||||
, $isDataFormat = it.opts.$data && $schemaFormat.$data
|
||||
, $closingBraces = '';
|
||||
}}
|
||||
|
||||
{{? $isDataFormat }}
|
||||
{{
|
||||
var $schemaValueFormat = it.util.getData($schemaFormat.$data, $dataLvl, it.dataPathArr)
|
||||
, $format = 'format' + $lvl
|
||||
, $compare = 'compare' + $lvl;
|
||||
}}
|
||||
|
||||
var {{=$format}} = formats[{{=$schemaValueFormat}}]
|
||||
, {{=$compare}} = {{=$format}} && {{=$format}}.compare;
|
||||
{{??}}
|
||||
{{ var $format = it.formats[$schemaFormat]; }}
|
||||
{{? !($format && $format.compare) }}
|
||||
{{# def.skipFormatLimit }}
|
||||
{{?}}
|
||||
{{ var $compare = 'formats' + it.util.getProperty($schemaFormat) + '.compare'; }}
|
||||
{{?}}
|
||||
|
||||
{{
|
||||
var $isMax = $keyword == 'formatMaximum'
|
||||
, $exclusiveKeyword = 'formatExclusive' + ($isMax ? 'Maximum' : 'Minimum')
|
||||
, $schemaExcl = it.schema[$exclusiveKeyword]
|
||||
, $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data
|
||||
, $op = $isMax ? '<' : '>'
|
||||
, $result = 'result' + $lvl;
|
||||
}}
|
||||
|
||||
{{# def.$data }}
|
||||
|
||||
|
||||
{{? $isDataExcl }}
|
||||
{{
|
||||
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr)
|
||||
, $exclusive = 'exclusive' + $lvl
|
||||
, $opExpr = 'op' + $lvl
|
||||
, $opStr = '\' + ' + $opExpr + ' + \'';
|
||||
}}
|
||||
var schemaExcl{{=$lvl}} = {{=$schemaValueExcl}};
|
||||
{{ $schemaValueExcl = 'schemaExcl' + $lvl; }}
|
||||
|
||||
if (typeof {{=$schemaValueExcl}} != 'boolean' && {{=$schemaValueExcl}} !== undefined) {
|
||||
{{=$valid}} = false;
|
||||
{{ var $errorKeyword = $exclusiveKeyword; }}
|
||||
{{# def.error:'_formatExclusiveLimit' }}
|
||||
}
|
||||
|
||||
{{# def.elseIfValid }}
|
||||
|
||||
{{# def.compareFormat }}
|
||||
var {{=$exclusive}} = {{=$schemaValueExcl}} === true;
|
||||
|
||||
if ({{=$valid}} === undefined) {
|
||||
{{=$valid}} = {{=$exclusive}}
|
||||
? {{=$result}} {{=$op}} 0
|
||||
: {{=$result}} {{=$op}}= 0;
|
||||
}
|
||||
|
||||
if (!{{=$valid}}) var op{{=$lvl}} = {{=$exclusive}} ? '{{=$op}}' : '{{=$op}}=';
|
||||
{{??}}
|
||||
{{
|
||||
var $exclusive = $schemaExcl === true
|
||||
, $opStr = $op; /*used in error*/
|
||||
if (!$exclusive) $opStr += '=';
|
||||
var $opExpr = '\'' + $opStr + '\''; /*used in error*/
|
||||
}}
|
||||
|
||||
{{# def.compareFormat }}
|
||||
|
||||
if ({{=$valid}} === undefined)
|
||||
{{=$valid}} = {{=$result}} {{=$op}}{{?!$exclusive}}={{?}} 0;
|
||||
{{?}}
|
||||
|
||||
{{= $closingBraces }}
|
||||
|
||||
if (!{{=$valid}}) {
|
||||
{{ var $errorKeyword = $keyword; }}
|
||||
{{# def.error:'_formatLimit' }}
|
||||
}
|
33
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dot/patternRequired.jst
generated
vendored
33
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dot/patternRequired.jst
generated
vendored
@ -0,0 +1,33 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
|
||||
{{
|
||||
var $key = 'key' + $lvl
|
||||
, $idx = 'idx' + $lvl
|
||||
, $matched = 'patternMatched' + $lvl
|
||||
, $dataProperties = 'dataProperties' + $lvl
|
||||
, $closingBraces = ''
|
||||
, $ownProperties = it.opts.ownProperties;
|
||||
}}
|
||||
|
||||
var {{=$valid}} = true;
|
||||
{{? $ownProperties }}
|
||||
var {{=$dataProperties}} = undefined;
|
||||
{{?}}
|
||||
|
||||
{{~ $schema:$pProperty }}
|
||||
var {{=$matched}} = false;
|
||||
{{# def.iterateProperties }}
|
||||
{{=$matched}} = {{= it.usePattern($pProperty) }}.test({{=$key}});
|
||||
if ({{=$matched}}) break;
|
||||
}
|
||||
|
||||
{{ var $missingPattern = it.util.escapeQuotes($pProperty); }}
|
||||
if (!{{=$matched}}) {
|
||||
{{=$valid}} = false;
|
||||
{{# def.addError:'patternRequired' }}
|
||||
} {{# def.elseIfValid }}
|
||||
{{~}}
|
||||
|
||||
{{= $closingBraces }}
|
@ -0,0 +1,73 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.setupNextLevel }}
|
||||
|
||||
|
||||
{{## def.validateIf:
|
||||
{{# def.setCompositeRule }}
|
||||
{{ $it.createErrors = false; }}
|
||||
{{# def._validateSwitchRule:if }}
|
||||
{{ $it.createErrors = true; }}
|
||||
{{# def.resetCompositeRule }}
|
||||
{{=$ifPassed}} = {{=$nextValid}};
|
||||
#}}
|
||||
|
||||
{{## def.validateThen:
|
||||
{{? typeof $sch.then == 'boolean' }}
|
||||
{{? $sch.then === false }}
|
||||
{{# def.error:'switch' }}
|
||||
{{?}}
|
||||
var {{=$nextValid}} = {{= $sch.then }};
|
||||
{{??}}
|
||||
{{# def._validateSwitchRule:then }}
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
{{## def._validateSwitchRule:_clause:
|
||||
{{
|
||||
$it.schema = $sch._clause;
|
||||
$it.schemaPath = $schemaPath + '[' + $caseIndex + ']._clause';
|
||||
$it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/_clause';
|
||||
}}
|
||||
{{# def.insertSubschemaCode }}
|
||||
#}}
|
||||
|
||||
{{## def.switchCase:
|
||||
{{? $sch.if && {{# def.nonEmptySchema:$sch.if }} }}
|
||||
var {{=$errs}} = errors;
|
||||
{{# def.validateIf }}
|
||||
if ({{=$ifPassed}}) {
|
||||
{{# def.validateThen }}
|
||||
} else {
|
||||
{{# def.resetErrors }}
|
||||
}
|
||||
{{??}}
|
||||
{{=$ifPassed}} = true;
|
||||
{{# def.validateThen }}
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{
|
||||
var $ifPassed = 'ifPassed' + it.level
|
||||
, $currentBaseId = $it.baseId
|
||||
, $shouldContinue;
|
||||
}}
|
||||
var {{=$ifPassed}};
|
||||
|
||||
{{~ $schema:$sch:$caseIndex }}
|
||||
{{? $caseIndex && !$shouldContinue }}
|
||||
if (!{{=$ifPassed}}) {
|
||||
{{ $closingBraces+= '}'; }}
|
||||
{{?}}
|
||||
|
||||
{{# def.switchCase }}
|
||||
{{ $shouldContinue = $sch.continue }}
|
||||
{{~}}
|
||||
|
||||
{{= $closingBraces }}
|
||||
|
||||
var {{=$valid}} = {{=$nextValid}};
|
||||
|
||||
{{# def.cleanUp }}
|
@ -0,0 +1,3 @@
|
||||
These files are compiled dot templates from dot folder.
|
||||
|
||||
Do NOT edit them directly, edit the templates and run `npm run build` from main ajv-keywords folder.
|
178
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dotjs/_formatLimit.js
generated
vendored
178
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dotjs/_formatLimit.js
generated
vendored
@ -0,0 +1,178 @@
|
||||
'use strict';
|
||||
module.exports = function generate__formatLimit(it, $keyword, $ruleType) {
|
||||
var out = ' ';
|
||||
var $lvl = it.level;
|
||||
var $dataLvl = it.dataLevel;
|
||||
var $schema = it.schema[$keyword];
|
||||
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
|
||||
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
|
||||
var $breakOnError = !it.opts.allErrors;
|
||||
var $errorKeyword;
|
||||
var $data = 'data' + ($dataLvl || '');
|
||||
var $valid = 'valid' + $lvl;
|
||||
out += 'var ' + ($valid) + ' = undefined;';
|
||||
if (it.opts.format === false) {
|
||||
out += ' ' + ($valid) + ' = true; ';
|
||||
return out;
|
||||
}
|
||||
var $schemaFormat = it.schema.format,
|
||||
$isDataFormat = it.opts.$data && $schemaFormat.$data,
|
||||
$closingBraces = '';
|
||||
if ($isDataFormat) {
|
||||
var $schemaValueFormat = it.util.getData($schemaFormat.$data, $dataLvl, it.dataPathArr),
|
||||
$format = 'format' + $lvl,
|
||||
$compare = 'compare' + $lvl;
|
||||
out += ' var ' + ($format) + ' = formats[' + ($schemaValueFormat) + '] , ' + ($compare) + ' = ' + ($format) + ' && ' + ($format) + '.compare;';
|
||||
} else {
|
||||
var $format = it.formats[$schemaFormat];
|
||||
if (!($format && $format.compare)) {
|
||||
out += ' ' + ($valid) + ' = true; ';
|
||||
return out;
|
||||
}
|
||||
var $compare = 'formats' + it.util.getProperty($schemaFormat) + '.compare';
|
||||
}
|
||||
var $isMax = $keyword == 'formatMaximum',
|
||||
$exclusiveKeyword = 'formatExclusive' + ($isMax ? 'Maximum' : 'Minimum'),
|
||||
$schemaExcl = it.schema[$exclusiveKeyword],
|
||||
$isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data,
|
||||
$op = $isMax ? '<' : '>',
|
||||
$result = 'result' + $lvl;
|
||||
var $isData = it.opts.$data && $schema && $schema.$data,
|
||||
$schemaValue;
|
||||
if ($isData) {
|
||||
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; ';
|
||||
$schemaValue = 'schema' + $lvl;
|
||||
} else {
|
||||
$schemaValue = $schema;
|
||||
}
|
||||
if ($isDataExcl) {
|
||||
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr),
|
||||
$exclusive = 'exclusive' + $lvl,
|
||||
$opExpr = 'op' + $lvl,
|
||||
$opStr = '\' + ' + $opExpr + ' + \'';
|
||||
out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; ';
|
||||
$schemaValueExcl = 'schemaExcl' + $lvl;
|
||||
out += ' if (typeof ' + ($schemaValueExcl) + ' != \'boolean\' && ' + ($schemaValueExcl) + ' !== undefined) { ' + ($valid) + ' = false; ';
|
||||
var $errorKeyword = $exclusiveKeyword;
|
||||
var $$outStack = $$outStack || [];
|
||||
$$outStack.push(out);
|
||||
out = ''; /* istanbul ignore else */
|
||||
if (it.createErrors !== false) {
|
||||
out += ' { keyword: \'' + ($errorKeyword || '_formatExclusiveLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
|
||||
if (it.opts.messages !== false) {
|
||||
out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' ';
|
||||
}
|
||||
if (it.opts.verbose) {
|
||||
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
|
||||
}
|
||||
out += ' } ';
|
||||
} else {
|
||||
out += ' {} ';
|
||||
}
|
||||
var __err = out;
|
||||
out = $$outStack.pop();
|
||||
if (!it.compositeRule && $breakOnError) {
|
||||
/* istanbul ignore if */
|
||||
if (it.async) {
|
||||
out += ' throw new ValidationError([' + (__err) + ']); ';
|
||||
} else {
|
||||
out += ' validate.errors = [' + (__err) + ']; return false; ';
|
||||
}
|
||||
} else {
|
||||
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
|
||||
}
|
||||
out += ' } ';
|
||||
if ($breakOnError) {
|
||||
$closingBraces += '}';
|
||||
out += ' else { ';
|
||||
}
|
||||
if ($isData) {
|
||||
out += ' if (' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'string\') ' + ($valid) + ' = false; else { ';
|
||||
$closingBraces += '}';
|
||||
}
|
||||
if ($isDataFormat) {
|
||||
out += ' if (!' + ($compare) + ') ' + ($valid) + ' = true; else { ';
|
||||
$closingBraces += '}';
|
||||
}
|
||||
out += ' var ' + ($result) + ' = ' + ($compare) + '(' + ($data) + ', ';
|
||||
if ($isData) {
|
||||
out += '' + ($schemaValue);
|
||||
} else {
|
||||
out += '' + (it.util.toQuotedString($schema));
|
||||
}
|
||||
out += ' ); if (' + ($result) + ' === undefined) ' + ($valid) + ' = false; var ' + ($exclusive) + ' = ' + ($schemaValueExcl) + ' === true; if (' + ($valid) + ' === undefined) { ' + ($valid) + ' = ' + ($exclusive) + ' ? ' + ($result) + ' ' + ($op) + ' 0 : ' + ($result) + ' ' + ($op) + '= 0; } if (!' + ($valid) + ') var op' + ($lvl) + ' = ' + ($exclusive) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\';';
|
||||
} else {
|
||||
var $exclusive = $schemaExcl === true,
|
||||
$opStr = $op;
|
||||
if (!$exclusive) $opStr += '=';
|
||||
var $opExpr = '\'' + $opStr + '\'';
|
||||
if ($isData) {
|
||||
out += ' if (' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'string\') ' + ($valid) + ' = false; else { ';
|
||||
$closingBraces += '}';
|
||||
}
|
||||
if ($isDataFormat) {
|
||||
out += ' if (!' + ($compare) + ') ' + ($valid) + ' = true; else { ';
|
||||
$closingBraces += '}';
|
||||
}
|
||||
out += ' var ' + ($result) + ' = ' + ($compare) + '(' + ($data) + ', ';
|
||||
if ($isData) {
|
||||
out += '' + ($schemaValue);
|
||||
} else {
|
||||
out += '' + (it.util.toQuotedString($schema));
|
||||
}
|
||||
out += ' ); if (' + ($result) + ' === undefined) ' + ($valid) + ' = false; if (' + ($valid) + ' === undefined) ' + ($valid) + ' = ' + ($result) + ' ' + ($op);
|
||||
if (!$exclusive) {
|
||||
out += '=';
|
||||
}
|
||||
out += ' 0;';
|
||||
}
|
||||
out += '' + ($closingBraces) + 'if (!' + ($valid) + ') { ';
|
||||
var $errorKeyword = $keyword;
|
||||
var $$outStack = $$outStack || [];
|
||||
$$outStack.push(out);
|
||||
out = ''; /* istanbul ignore else */
|
||||
if (it.createErrors !== false) {
|
||||
out += ' { keyword: \'' + ($errorKeyword || '_formatLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { comparison: ' + ($opExpr) + ', limit: ';
|
||||
if ($isData) {
|
||||
out += '' + ($schemaValue);
|
||||
} else {
|
||||
out += '' + (it.util.toQuotedString($schema));
|
||||
}
|
||||
out += ' , exclusive: ' + ($exclusive) + ' } ';
|
||||
if (it.opts.messages !== false) {
|
||||
out += ' , message: \'should be ' + ($opStr) + ' "';
|
||||
if ($isData) {
|
||||
out += '\' + ' + ($schemaValue) + ' + \'';
|
||||
} else {
|
||||
out += '' + (it.util.escapeQuotes($schema));
|
||||
}
|
||||
out += '"\' ';
|
||||
}
|
||||
if (it.opts.verbose) {
|
||||
out += ' , schema: ';
|
||||
if ($isData) {
|
||||
out += 'validate.schema' + ($schemaPath);
|
||||
} else {
|
||||
out += '' + (it.util.toQuotedString($schema));
|
||||
}
|
||||
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
|
||||
}
|
||||
out += ' } ';
|
||||
} else {
|
||||
out += ' {} ';
|
||||
}
|
||||
var __err = out;
|
||||
out = $$outStack.pop();
|
||||
if (!it.compositeRule && $breakOnError) {
|
||||
/* istanbul ignore if */
|
||||
if (it.async) {
|
||||
out += ' throw new ValidationError([' + (__err) + ']); ';
|
||||
} else {
|
||||
out += ' validate.errors = [' + (__err) + ']; return false; ';
|
||||
}
|
||||
} else {
|
||||
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
|
||||
}
|
||||
out += '}';
|
||||
return out;
|
||||
}
|
58
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dotjs/patternRequired.js
generated
vendored
58
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dotjs/patternRequired.js
generated
vendored
@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
module.exports = function generate_patternRequired(it, $keyword, $ruleType) {
|
||||
var out = ' ';
|
||||
var $lvl = it.level;
|
||||
var $dataLvl = it.dataLevel;
|
||||
var $schema = it.schema[$keyword];
|
||||
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
|
||||
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
|
||||
var $breakOnError = !it.opts.allErrors;
|
||||
var $data = 'data' + ($dataLvl || '');
|
||||
var $valid = 'valid' + $lvl;
|
||||
var $key = 'key' + $lvl,
|
||||
$idx = 'idx' + $lvl,
|
||||
$matched = 'patternMatched' + $lvl,
|
||||
$dataProperties = 'dataProperties' + $lvl,
|
||||
$closingBraces = '',
|
||||
$ownProperties = it.opts.ownProperties;
|
||||
out += 'var ' + ($valid) + ' = true;';
|
||||
if ($ownProperties) {
|
||||
out += ' var ' + ($dataProperties) + ' = undefined;';
|
||||
}
|
||||
var arr1 = $schema;
|
||||
if (arr1) {
|
||||
var $pProperty, i1 = -1,
|
||||
l1 = arr1.length - 1;
|
||||
while (i1 < l1) {
|
||||
$pProperty = arr1[i1 += 1];
|
||||
out += ' var ' + ($matched) + ' = false; ';
|
||||
if ($ownProperties) {
|
||||
out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; ';
|
||||
} else {
|
||||
out += ' for (var ' + ($key) + ' in ' + ($data) + ') { ';
|
||||
}
|
||||
out += ' ' + ($matched) + ' = ' + (it.usePattern($pProperty)) + '.test(' + ($key) + '); if (' + ($matched) + ') break; } ';
|
||||
var $missingPattern = it.util.escapeQuotes($pProperty);
|
||||
out += ' if (!' + ($matched) + ') { ' + ($valid) + ' = false; var err = '; /* istanbul ignore else */
|
||||
if (it.createErrors !== false) {
|
||||
out += ' { keyword: \'' + ('patternRequired') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingPattern: \'' + ($missingPattern) + '\' } ';
|
||||
if (it.opts.messages !== false) {
|
||||
out += ' , message: \'should have property matching pattern \\\'' + ($missingPattern) + '\\\'\' ';
|
||||
}
|
||||
if (it.opts.verbose) {
|
||||
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
|
||||
}
|
||||
out += ' } ';
|
||||
} else {
|
||||
out += ' {} ';
|
||||
}
|
||||
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } ';
|
||||
if ($breakOnError) {
|
||||
$closingBraces += '}';
|
||||
out += ' else { ';
|
||||
}
|
||||
}
|
||||
}
|
||||
out += '' + ($closingBraces);
|
||||
return out;
|
||||
}
|
130
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dotjs/switch.js
generated
vendored
130
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dotjs/switch.js
generated
vendored
@ -0,0 +1,130 @@
|
||||
'use strict';
|
||||
module.exports = function generate_switch(it, $keyword, $ruleType) {
|
||||
var out = ' ';
|
||||
var $lvl = it.level;
|
||||
var $dataLvl = it.dataLevel;
|
||||
var $schema = it.schema[$keyword];
|
||||
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
|
||||
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
|
||||
var $breakOnError = !it.opts.allErrors;
|
||||
var $data = 'data' + ($dataLvl || '');
|
||||
var $valid = 'valid' + $lvl;
|
||||
var $errs = 'errs__' + $lvl;
|
||||
var $it = it.util.copy(it);
|
||||
var $closingBraces = '';
|
||||
$it.level++;
|
||||
var $nextValid = 'valid' + $it.level;
|
||||
var $ifPassed = 'ifPassed' + it.level,
|
||||
$currentBaseId = $it.baseId,
|
||||
$shouldContinue;
|
||||
out += 'var ' + ($ifPassed) + ';';
|
||||
var arr1 = $schema;
|
||||
if (arr1) {
|
||||
var $sch, $caseIndex = -1,
|
||||
l1 = arr1.length - 1;
|
||||
while ($caseIndex < l1) {
|
||||
$sch = arr1[$caseIndex += 1];
|
||||
if ($caseIndex && !$shouldContinue) {
|
||||
out += ' if (!' + ($ifPassed) + ') { ';
|
||||
$closingBraces += '}';
|
||||
}
|
||||
if ($sch.if && it.util.schemaHasRules($sch.if, it.RULES.all)) {
|
||||
out += ' var ' + ($errs) + ' = errors; ';
|
||||
var $wasComposite = it.compositeRule;
|
||||
it.compositeRule = $it.compositeRule = true;
|
||||
$it.createErrors = false;
|
||||
$it.schema = $sch.if;
|
||||
$it.schemaPath = $schemaPath + '[' + $caseIndex + '].if';
|
||||
$it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/if';
|
||||
out += ' ' + (it.validate($it)) + ' ';
|
||||
$it.baseId = $currentBaseId;
|
||||
$it.createErrors = true;
|
||||
it.compositeRule = $it.compositeRule = $wasComposite;
|
||||
out += ' ' + ($ifPassed) + ' = ' + ($nextValid) + '; if (' + ($ifPassed) + ') { ';
|
||||
if (typeof $sch.then == 'boolean') {
|
||||
if ($sch.then === false) {
|
||||
var $$outStack = $$outStack || [];
|
||||
$$outStack.push(out);
|
||||
out = ''; /* istanbul ignore else */
|
||||
if (it.createErrors !== false) {
|
||||
out += ' { keyword: \'' + ('switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { caseIndex: ' + ($caseIndex) + ' } ';
|
||||
if (it.opts.messages !== false) {
|
||||
out += ' , message: \'should pass "switch" keyword validation\' ';
|
||||
}
|
||||
if (it.opts.verbose) {
|
||||
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
|
||||
}
|
||||
out += ' } ';
|
||||
} else {
|
||||
out += ' {} ';
|
||||
}
|
||||
var __err = out;
|
||||
out = $$outStack.pop();
|
||||
if (!it.compositeRule && $breakOnError) {
|
||||
/* istanbul ignore if */
|
||||
if (it.async) {
|
||||
out += ' throw new ValidationError([' + (__err) + ']); ';
|
||||
} else {
|
||||
out += ' validate.errors = [' + (__err) + ']; return false; ';
|
||||
}
|
||||
} else {
|
||||
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
|
||||
}
|
||||
}
|
||||
out += ' var ' + ($nextValid) + ' = ' + ($sch.then) + '; ';
|
||||
} else {
|
||||
$it.schema = $sch.then;
|
||||
$it.schemaPath = $schemaPath + '[' + $caseIndex + '].then';
|
||||
$it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/then';
|
||||
out += ' ' + (it.validate($it)) + ' ';
|
||||
$it.baseId = $currentBaseId;
|
||||
}
|
||||
out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } } ';
|
||||
} else {
|
||||
out += ' ' + ($ifPassed) + ' = true; ';
|
||||
if (typeof $sch.then == 'boolean') {
|
||||
if ($sch.then === false) {
|
||||
var $$outStack = $$outStack || [];
|
||||
$$outStack.push(out);
|
||||
out = ''; /* istanbul ignore else */
|
||||
if (it.createErrors !== false) {
|
||||
out += ' { keyword: \'' + ('switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { caseIndex: ' + ($caseIndex) + ' } ';
|
||||
if (it.opts.messages !== false) {
|
||||
out += ' , message: \'should pass "switch" keyword validation\' ';
|
||||
}
|
||||
if (it.opts.verbose) {
|
||||
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
|
||||
}
|
||||
out += ' } ';
|
||||
} else {
|
||||
out += ' {} ';
|
||||
}
|
||||
var __err = out;
|
||||
out = $$outStack.pop();
|
||||
if (!it.compositeRule && $breakOnError) {
|
||||
/* istanbul ignore if */
|
||||
if (it.async) {
|
||||
out += ' throw new ValidationError([' + (__err) + ']); ';
|
||||
} else {
|
||||
out += ' validate.errors = [' + (__err) + ']; return false; ';
|
||||
}
|
||||
} else {
|
||||
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
|
||||
}
|
||||
}
|
||||
out += ' var ' + ($nextValid) + ' = ' + ($sch.then) + '; ';
|
||||
} else {
|
||||
$it.schema = $sch.then;
|
||||
$it.schemaPath = $schemaPath + '[' + $caseIndex + '].then';
|
||||
$it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/then';
|
||||
out += ' ' + (it.validate($it)) + ' ';
|
||||
$it.baseId = $currentBaseId;
|
||||
}
|
||||
}
|
||||
$shouldContinue = $sch.continue
|
||||
}
|
||||
}
|
||||
out += '' + ($closingBraces) + 'var ' + ($valid) + ' = ' + ($nextValid) + '; ';
|
||||
out = it.util.cleanUpCode(out);
|
||||
return out;
|
||||
}
|
72
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dynamicDefaults.js
generated
vendored
72
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/dynamicDefaults.js
generated
vendored
@ -0,0 +1,72 @@
|
||||
'use strict';
|
||||
|
||||
var sequences = {};
|
||||
|
||||
var DEFAULTS = {
|
||||
timestamp: function() { return Date.now(); },
|
||||
datetime: function() { return (new Date).toISOString(); },
|
||||
date: function() { return (new Date).toISOString().slice(0, 10); },
|
||||
time: function() { return (new Date).toISOString().slice(11); },
|
||||
random: function() { return Math.random(); },
|
||||
randomint: function (args) {
|
||||
var limit = args && args.max || 2;
|
||||
return function() { return Math.floor(Math.random() * limit); };
|
||||
},
|
||||
seq: function (args) {
|
||||
var name = args && args.name || '';
|
||||
sequences[name] = sequences[name] || 0;
|
||||
return function() { return sequences[name]++; };
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
compile: function (schema, parentSchema, it) {
|
||||
var funcs = {};
|
||||
|
||||
for (var key in schema) {
|
||||
var d = schema[key];
|
||||
var func = getDefault(typeof d == 'string' ? d : d.func);
|
||||
funcs[key] = func.length ? func(d.args) : func;
|
||||
}
|
||||
|
||||
return it.opts.useDefaults && !it.compositeRule
|
||||
? assignDefaults
|
||||
: noop;
|
||||
|
||||
function assignDefaults(data) {
|
||||
for (var prop in schema){
|
||||
if (data[prop] === undefined
|
||||
|| (it.opts.useDefaults == 'empty'
|
||||
&& (data[prop] === null || data[prop] === '')))
|
||||
data[prop] = funcs[prop]();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function noop() { return true; }
|
||||
},
|
||||
DEFAULTS: DEFAULTS,
|
||||
metaSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
type: ['string', 'object'],
|
||||
additionalProperties: false,
|
||||
required: ['func', 'args'],
|
||||
properties: {
|
||||
func: { type: 'string' },
|
||||
args: { type: 'object' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('dynamicDefaults', defFunc.definition);
|
||||
return ajv;
|
||||
|
||||
function getDefault(d) {
|
||||
var def = DEFAULTS[d];
|
||||
if (def) return def;
|
||||
throw new Error('invalid "dynamicDefaults" keyword property value: ' + d);
|
||||
}
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = require('./_formatLimit')('Maximum');
|
@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = require('./_formatLimit')('Minimum');
|
@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
'instanceof': require('./instanceof'),
|
||||
range: require('./range'),
|
||||
regexp: require('./regexp'),
|
||||
'typeof': require('./typeof'),
|
||||
dynamicDefaults: require('./dynamicDefaults'),
|
||||
allRequired: require('./allRequired'),
|
||||
anyRequired: require('./anyRequired'),
|
||||
oneRequired: require('./oneRequired'),
|
||||
prohibited: require('./prohibited'),
|
||||
uniqueItemProperties: require('./uniqueItemProperties'),
|
||||
deepProperties: require('./deepProperties'),
|
||||
deepRequired: require('./deepRequired'),
|
||||
formatMinimum: require('./formatMinimum'),
|
||||
formatMaximum: require('./formatMaximum'),
|
||||
patternRequired: require('./patternRequired'),
|
||||
'switch': require('./switch'),
|
||||
select: require('./select'),
|
||||
transform: require('./transform')
|
||||
};
|
@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
var CONSTRUCTORS = {
|
||||
Object: Object,
|
||||
Array: Array,
|
||||
Function: Function,
|
||||
Number: Number,
|
||||
String: String,
|
||||
Date: Date,
|
||||
RegExp: RegExp
|
||||
};
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
/* istanbul ignore else */
|
||||
if (typeof Buffer != 'undefined')
|
||||
CONSTRUCTORS.Buffer = Buffer;
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (typeof Promise != 'undefined')
|
||||
CONSTRUCTORS.Promise = Promise;
|
||||
|
||||
defFunc.definition = {
|
||||
compile: function (schema) {
|
||||
if (typeof schema == 'string') {
|
||||
var Constructor = getConstructor(schema);
|
||||
return function (data) {
|
||||
return data instanceof Constructor;
|
||||
};
|
||||
}
|
||||
|
||||
var constructors = schema.map(getConstructor);
|
||||
return function (data) {
|
||||
for (var i=0; i<constructors.length; i++)
|
||||
if (data instanceof constructors[i]) return true;
|
||||
return false;
|
||||
};
|
||||
},
|
||||
CONSTRUCTORS: CONSTRUCTORS,
|
||||
metaSchema: {
|
||||
anyOf: [
|
||||
{ type: 'string' },
|
||||
{
|
||||
type: 'array',
|
||||
items: { type: 'string' }
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('instanceof', defFunc.definition);
|
||||
return ajv;
|
||||
|
||||
function getConstructor(c) {
|
||||
var Constructor = CONSTRUCTORS[c];
|
||||
if (Constructor) return Constructor;
|
||||
throw new Error('invalid "instanceof" keyword value ' + c);
|
||||
}
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'object',
|
||||
macro: function (schema) {
|
||||
if (schema.length == 0) return true;
|
||||
if (schema.length == 1) return {required: schema};
|
||||
var schemas = schema.map(function (prop) {
|
||||
return {required: [prop]};
|
||||
});
|
||||
return {oneOf: schemas};
|
||||
},
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('oneRequired', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
21
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/patternRequired.js
generated
vendored
21
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/patternRequired.js
generated
vendored
@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'object',
|
||||
inline: require('./dotjs/patternRequired'),
|
||||
statements: true,
|
||||
errors: 'full',
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
format: 'regex'
|
||||
},
|
||||
uniqueItems: true
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('patternRequired', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'object',
|
||||
macro: function (schema) {
|
||||
if (schema.length == 0) return true;
|
||||
if (schema.length == 1) return {not: {required: schema}};
|
||||
var schemas = schema.map(function (prop) {
|
||||
return {required: [prop]};
|
||||
});
|
||||
return {not: {anyOf: schemas}};
|
||||
},
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('prohibited', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'number',
|
||||
macro: function (schema, parentSchema) {
|
||||
var min = schema[0]
|
||||
, max = schema[1]
|
||||
, exclusive = parentSchema.exclusiveRange;
|
||||
|
||||
validateRangeSchema(min, max, exclusive);
|
||||
|
||||
return exclusive === true
|
||||
? {exclusiveMinimum: min, exclusiveMaximum: max}
|
||||
: {minimum: min, maximum: max};
|
||||
},
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
minItems: 2,
|
||||
maxItems: 2,
|
||||
items: { type: 'number' }
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('range', defFunc.definition);
|
||||
ajv.addKeyword('exclusiveRange');
|
||||
return ajv;
|
||||
|
||||
function validateRangeSchema(min, max, exclusive) {
|
||||
if (exclusive !== undefined && typeof exclusive != 'boolean')
|
||||
throw new Error('Invalid schema for exclusiveRange keyword, should be boolean');
|
||||
|
||||
if (min > max || (exclusive && min == max))
|
||||
throw new Error('There are no numbers in range');
|
||||
}
|
||||
};
|
@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'string',
|
||||
inline: function (it, keyword, schema) {
|
||||
return getRegExp() + '.test(data' + (it.dataLevel || '') + ')';
|
||||
|
||||
function getRegExp() {
|
||||
try {
|
||||
if (typeof schema == 'object')
|
||||
return new RegExp(schema.pattern, schema.flags);
|
||||
|
||||
var rx = schema.match(/^\/(.*)\/([gimuy]*)$/);
|
||||
if (rx) return new RegExp(rx[1], rx[2]);
|
||||
throw new Error('cannot parse string into RegExp');
|
||||
} catch(e) {
|
||||
console.error('regular expression', schema, 'is invalid');
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
},
|
||||
metaSchema: {
|
||||
type: ['string', 'object'],
|
||||
properties: {
|
||||
pattern: { type: 'string' },
|
||||
flags: { type: 'string' }
|
||||
},
|
||||
required: ['pattern'],
|
||||
additionalProperties: false
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('regexp', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('./_util');
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
if (!ajv._opts.$data) {
|
||||
console.warn('keyword select requires $data option');
|
||||
return ajv;
|
||||
}
|
||||
var metaSchemaRef = util.metaSchemaRef(ajv);
|
||||
var compiledCaseSchemas = [];
|
||||
|
||||
defFunc.definition = {
|
||||
validate: function v(schema, data, parentSchema) {
|
||||
if (parentSchema.selectCases === undefined)
|
||||
throw new Error('keyword "selectCases" is absent');
|
||||
var compiled = getCompiledSchemas(parentSchema, false);
|
||||
var validate = compiled.cases[schema];
|
||||
if (validate === undefined) validate = compiled.default;
|
||||
if (typeof validate == 'boolean') return validate;
|
||||
var valid = validate(data);
|
||||
if (!valid) v.errors = validate.errors;
|
||||
return valid;
|
||||
},
|
||||
$data: true,
|
||||
metaSchema: { type: ['string', 'number', 'boolean', 'null'] }
|
||||
};
|
||||
|
||||
ajv.addKeyword('select', defFunc.definition);
|
||||
ajv.addKeyword('selectCases', {
|
||||
compile: function (schemas, parentSchema) {
|
||||
var compiled = getCompiledSchemas(parentSchema);
|
||||
for (var value in schemas)
|
||||
compiled.cases[value] = compileOrBoolean(schemas[value]);
|
||||
return function() { return true; };
|
||||
},
|
||||
valid: true,
|
||||
metaSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: metaSchemaRef
|
||||
}
|
||||
});
|
||||
ajv.addKeyword('selectDefault', {
|
||||
compile: function (schema, parentSchema) {
|
||||
var compiled = getCompiledSchemas(parentSchema);
|
||||
compiled.default = compileOrBoolean(schema);
|
||||
return function() { return true; };
|
||||
},
|
||||
valid: true,
|
||||
metaSchema: metaSchemaRef
|
||||
});
|
||||
return ajv;
|
||||
|
||||
|
||||
function getCompiledSchemas(parentSchema, create) {
|
||||
var compiled;
|
||||
compiledCaseSchemas.some(function (c) {
|
||||
if (c.parentSchema === parentSchema) {
|
||||
compiled = c;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!compiled && create !== false) {
|
||||
compiled = {
|
||||
parentSchema: parentSchema,
|
||||
cases: {},
|
||||
default: true
|
||||
};
|
||||
compiledCaseSchemas.push(compiled);
|
||||
}
|
||||
return compiled;
|
||||
}
|
||||
|
||||
function compileOrBoolean(schema) {
|
||||
return typeof schema == 'boolean'
|
||||
? schema
|
||||
: ajv.compile(schema);
|
||||
}
|
||||
};
|
@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('./_util');
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
if (ajv.RULES.keywords.switch && ajv.RULES.keywords.if) return;
|
||||
|
||||
var metaSchemaRef = util.metaSchemaRef(ajv);
|
||||
|
||||
defFunc.definition = {
|
||||
inline: require('./dotjs/switch'),
|
||||
statements: true,
|
||||
errors: 'full',
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
required: [ 'then' ],
|
||||
properties: {
|
||||
'if': metaSchemaRef,
|
||||
'then': {
|
||||
anyOf: [
|
||||
{ type: 'boolean' },
|
||||
metaSchemaRef
|
||||
]
|
||||
},
|
||||
'continue': { type: 'boolean' }
|
||||
},
|
||||
additionalProperties: false,
|
||||
dependencies: {
|
||||
'continue': [ 'if' ]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('switch', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
@ -0,0 +1,80 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function defFunc (ajv) {
|
||||
var transform = {
|
||||
trimLeft: function (value) {
|
||||
return value.replace(/^[\s]+/, '');
|
||||
},
|
||||
trimRight: function (value) {
|
||||
return value.replace(/[\s]+$/, '');
|
||||
},
|
||||
trim: function (value) {
|
||||
return value.trim();
|
||||
},
|
||||
toLowerCase: function (value) {
|
||||
return value.toLowerCase();
|
||||
},
|
||||
toUpperCase: function (value) {
|
||||
return value.toUpperCase();
|
||||
},
|
||||
toEnumCase: function (value, cfg) {
|
||||
return cfg.hash[makeHashTableKey(value)] || value;
|
||||
}
|
||||
};
|
||||
|
||||
defFunc.definition = {
|
||||
type: 'string',
|
||||
errors: false,
|
||||
modifying: true,
|
||||
valid: true,
|
||||
compile: function (schema, parentSchema) {
|
||||
var cfg;
|
||||
|
||||
if (schema.indexOf('toEnumCase') !== -1) {
|
||||
// build hash table to enum values
|
||||
cfg = {hash: {}};
|
||||
|
||||
// requires `enum` in schema
|
||||
if (!parentSchema.enum)
|
||||
throw new Error('Missing enum. To use `transform:["toEnumCase"]`, `enum:[...]` is required.');
|
||||
for (var i = parentSchema.enum.length; i--; i) {
|
||||
var v = parentSchema.enum[i];
|
||||
if (typeof v !== 'string') continue;
|
||||
var k = makeHashTableKey(v);
|
||||
// requires all `enum` values have unique keys
|
||||
if (cfg.hash[k])
|
||||
throw new Error('Invalid enum uniqueness. To use `transform:["toEnumCase"]`, all values must be unique when case insensitive.');
|
||||
cfg.hash[k] = v;
|
||||
}
|
||||
}
|
||||
|
||||
return function (data, dataPath, object, key) {
|
||||
// skip if value only
|
||||
if (!object) return;
|
||||
|
||||
// apply transform in order provided
|
||||
for (var j = 0, l = schema.length; j < l; j++)
|
||||
data = transform[schema[j]](data, cfg);
|
||||
|
||||
object[key] = data;
|
||||
};
|
||||
},
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
enum: [
|
||||
'trimLeft', 'trimRight', 'trim',
|
||||
'toLowerCase', 'toUpperCase', 'toEnumCase'
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('transform', defFunc.definition);
|
||||
return ajv;
|
||||
|
||||
function makeHashTableKey (value) {
|
||||
return value.toLowerCase();
|
||||
}
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
var KNOWN_TYPES = ['undefined', 'string', 'number', 'object', 'function', 'boolean', 'symbol'];
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
inline: function (it, keyword, schema) {
|
||||
var data = 'data' + (it.dataLevel || '');
|
||||
if (typeof schema == 'string') return 'typeof ' + data + ' == "' + schema + '"';
|
||||
schema = 'validate.schema' + it.schemaPath + '.' + keyword;
|
||||
return schema + '.indexOf(typeof ' + data + ') >= 0';
|
||||
},
|
||||
metaSchema: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string',
|
||||
enum: KNOWN_TYPES
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
enum: KNOWN_TYPES
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('typeof', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
59
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/uniqueItemProperties.js
generated
vendored
59
public/node_modules/_ajv-keywords@3.4.1@ajv-keywords/keywords/uniqueItemProperties.js
generated
vendored
@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
|
||||
var SCALAR_TYPES = ['number', 'integer', 'string', 'boolean', 'null'];
|
||||
|
||||
module.exports = function defFunc(ajv) {
|
||||
defFunc.definition = {
|
||||
type: 'array',
|
||||
compile: function(keys, parentSchema, it) {
|
||||
var equal = it.util.equal;
|
||||
var scalar = getScalarKeys(keys, parentSchema);
|
||||
|
||||
return function(data) {
|
||||
if (data.length > 1) {
|
||||
for (var k=0; k < keys.length; k++) {
|
||||
var i, key = keys[k];
|
||||
if (scalar[k]) {
|
||||
var hash = {};
|
||||
for (i = data.length; i--;) {
|
||||
if (!data[i] || typeof data[i] != 'object') continue;
|
||||
var prop = data[i][key];
|
||||
if (prop && typeof prop == 'object') continue;
|
||||
if (typeof prop == 'string') prop = '"' + prop;
|
||||
if (hash[prop]) return false;
|
||||
hash[prop] = true;
|
||||
}
|
||||
} else {
|
||||
for (i = data.length; i--;) {
|
||||
if (!data[i] || typeof data[i] != 'object') continue;
|
||||
for (var j = i; j--;) {
|
||||
if (data[j] && typeof data[j] == 'object' && equal(data[i][key], data[j][key]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
},
|
||||
metaSchema: {
|
||||
type: 'array',
|
||||
items: {type: 'string'}
|
||||
}
|
||||
};
|
||||
|
||||
ajv.addKeyword('uniqueItemProperties', defFunc.definition);
|
||||
return ajv;
|
||||
};
|
||||
|
||||
|
||||
function getScalarKeys(keys, schema) {
|
||||
return keys.map(function(key) {
|
||||
var properties = schema.items && schema.items.properties;
|
||||
var propType = properties && properties[key] && properties[key].type;
|
||||
return Array.isArray(propType)
|
||||
? propType.indexOf('object') < 0 && propType.indexOf('array') < 0
|
||||
: SCALAR_TYPES.indexOf(propType) >= 0;
|
||||
});
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "ajv-keywords",
|
||||
"version": "3.4.1",
|
||||
"description": "Custom JSON-Schema keywords for Ajv validator",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "node node_modules/ajv/scripts/compile-dots.js node_modules/ajv/lib keywords",
|
||||
"prepublish": "npm run build",
|
||||
"test": "npm run build && npm run eslint && npm run test-cov",
|
||||
"eslint": "eslint index.js keywords/*.js spec",
|
||||
"test-spec": "mocha spec/*.spec.js -R spec",
|
||||
"test-cov": "istanbul cover -x 'spec/**' node_modules/mocha/bin/_mocha -- spec/*.spec.js -R spec"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/epoberezkin/ajv-keywords.git"
|
||||
},
|
||||
"keywords": [
|
||||
"JSON-Schema",
|
||||
"ajv",
|
||||
"keywords"
|
||||
],
|
||||
"files": [
|
||||
"index.js",
|
||||
"keywords"
|
||||
],
|
||||
"author": "Evgeny Poberezkin",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/epoberezkin/ajv-keywords/issues"
|
||||
},
|
||||
"homepage": "https://github.com/epoberezkin/ajv-keywords#readme",
|
||||
"peerDependencies": {
|
||||
"ajv": "^6.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ajv": "^6.9.1",
|
||||
"ajv-pack": "^0.3.0",
|
||||
"chai": "^4.2.0",
|
||||
"coveralls": "^3.0.2",
|
||||
"dot": "^1.1.1",
|
||||
"eslint": "^6.0.0",
|
||||
"glob": "^7.1.3",
|
||||
"istanbul": "^0.4.3",
|
||||
"js-beautify": "^1.8.9",
|
||||
"json-schema-test": "^2.0.0",
|
||||
"mocha": "^6.0.0",
|
||||
"pre-commit": "^1.1.3",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"__npminstall_done": "Fri Jan 03 2020 18:02:09 GMT+0800 (GMT+08:00)",
|
||||
"_from": "ajv-keywords@3.4.1",
|
||||
"_resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.4.1.tgz"
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
var Ajv = require('ajv');
|
||||
var ajv = new Ajv({allErrors: true});
|
||||
|
||||
var schema = {
|
||||
"properties": {
|
||||
"foo": { "type": "string" },
|
||||
"bar": { "type": "number", "maximum": 3 }
|
||||
}
|
||||
};
|
||||
|
||||
var validate = ajv.compile(schema);
|
||||
|
||||
test({"foo": "abc", "bar": 2});
|
||||
test({"foo": 2, "bar": 4});
|
||||
|
||||
function test(data) {
|
||||
var valid = validate(data);
|
||||
if (valid) console.log('Valid!');
|
||||
else console.log('Invalid: ' + ajv.errorsText(validate.errors));
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2017 Evgeny Poberezkin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,390 @@
|
||||
declare var ajv: {
|
||||
(options?: ajv.Options): ajv.Ajv;
|
||||
new(options?: ajv.Options): ajv.Ajv;
|
||||
ValidationError: typeof AjvErrors.ValidationError;
|
||||
MissingRefError: typeof AjvErrors.MissingRefError;
|
||||
$dataMetaSchema: object;
|
||||
}
|
||||
|
||||
declare namespace AjvErrors {
|
||||
class ValidationError extends Error {
|
||||
constructor(errors: Array<ajv.ErrorObject>);
|
||||
|
||||
message: string;
|
||||
errors: Array<ajv.ErrorObject>;
|
||||
ajv: true;
|
||||
validation: true;
|
||||
}
|
||||
|
||||
class MissingRefError extends Error {
|
||||
constructor(baseId: string, ref: string, message?: string);
|
||||
static message: (baseId: string, ref: string) => string;
|
||||
|
||||
message: string;
|
||||
missingRef: string;
|
||||
missingSchema: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace ajv {
|
||||
type ValidationError = AjvErrors.ValidationError;
|
||||
|
||||
type MissingRefError = AjvErrors.MissingRefError;
|
||||
|
||||
interface Ajv {
|
||||
/**
|
||||
* Validate data using schema
|
||||
* Schema will be compiled and cached (using serialized JSON as key, [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize by default).
|
||||
* @param {string|object|Boolean} schemaKeyRef key, ref or schema object
|
||||
* @param {Any} data to be validated
|
||||
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
|
||||
*/
|
||||
validate(schemaKeyRef: object | string | boolean, data: any): boolean | PromiseLike<any>;
|
||||
/**
|
||||
* Create validating function for passed schema.
|
||||
* @param {object|Boolean} schema schema object
|
||||
* @return {Function} validating function
|
||||
*/
|
||||
compile(schema: object | boolean): ValidateFunction;
|
||||
/**
|
||||
* Creates validating function for passed schema with asynchronous loading of missing schemas.
|
||||
* `loadSchema` option should be a function that accepts schema uri and node-style callback.
|
||||
* @this Ajv
|
||||
* @param {object|Boolean} schema schema object
|
||||
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
|
||||
* @param {Function} callback optional node-style callback, it is always called with 2 parameters: error (or null) and validating function.
|
||||
* @return {PromiseLike<ValidateFunction>} validating function
|
||||
*/
|
||||
compileAsync(schema: object | boolean, meta?: Boolean, callback?: (err: Error, validate: ValidateFunction) => any): PromiseLike<ValidateFunction>;
|
||||
/**
|
||||
* Adds schema to the instance.
|
||||
* @param {object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
|
||||
* @param {string} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
addSchema(schema: Array<object> | object, key?: string): Ajv;
|
||||
/**
|
||||
* Add schema that will be used to validate other schemas
|
||||
* options in META_IGNORE_OPTIONS are alway set to false
|
||||
* @param {object} schema schema object
|
||||
* @param {string} key optional schema key
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
addMetaSchema(schema: object, key?: string): Ajv;
|
||||
/**
|
||||
* Validate schema
|
||||
* @param {object|Boolean} schema schema to validate
|
||||
* @return {Boolean} true if schema is valid
|
||||
*/
|
||||
validateSchema(schema: object | boolean): boolean;
|
||||
/**
|
||||
* Get compiled schema from the instance by `key` or `ref`.
|
||||
* @param {string} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
|
||||
* @return {Function} schema validating function (with property `schema`).
|
||||
*/
|
||||
getSchema(keyRef: string): ValidateFunction;
|
||||
/**
|
||||
* Remove cached schema(s).
|
||||
* If no parameter is passed all schemas but meta-schemas are removed.
|
||||
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
|
||||
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
|
||||
* @param {string|object|RegExp|Boolean} schemaKeyRef key, ref, pattern to match key/ref or schema object
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
removeSchema(schemaKeyRef?: object | string | RegExp | boolean): Ajv;
|
||||
/**
|
||||
* Add custom format
|
||||
* @param {string} name format name
|
||||
* @param {string|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
addFormat(name: string, format: FormatValidator | FormatDefinition): Ajv;
|
||||
/**
|
||||
* Define custom keyword
|
||||
* @this Ajv
|
||||
* @param {string} keyword custom keyword, should be a valid identifier, should be different from all standard, custom and macro keywords.
|
||||
* @param {object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`.
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
addKeyword(keyword: string, definition: KeywordDefinition): Ajv;
|
||||
/**
|
||||
* Get keyword definition
|
||||
* @this Ajv
|
||||
* @param {string} keyword pre-defined or custom keyword.
|
||||
* @return {object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise.
|
||||
*/
|
||||
getKeyword(keyword: string): object | boolean;
|
||||
/**
|
||||
* Remove keyword
|
||||
* @this Ajv
|
||||
* @param {string} keyword pre-defined or custom keyword.
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
removeKeyword(keyword: string): Ajv;
|
||||
/**
|
||||
* Validate keyword
|
||||
* @this Ajv
|
||||
* @param {object} definition keyword definition object
|
||||
* @param {boolean} throwError true to throw exception if definition is invalid
|
||||
* @return {boolean} validation result
|
||||
*/
|
||||
validateKeyword(definition: KeywordDefinition, throwError: boolean): boolean;
|
||||
/**
|
||||
* Convert array of error message objects to string
|
||||
* @param {Array<object>} errors optional array of validation errors, if not passed errors from the instance are used.
|
||||
* @param {object} options optional options with properties `separator` and `dataVar`.
|
||||
* @return {string} human readable string with all errors descriptions
|
||||
*/
|
||||
errorsText(errors?: Array<ErrorObject> | null, options?: ErrorsTextOptions): string;
|
||||
errors?: Array<ErrorObject> | null;
|
||||
}
|
||||
|
||||
interface CustomLogger {
|
||||
log(...args: any[]): any;
|
||||
warn(...args: any[]): any;
|
||||
error(...args: any[]): any;
|
||||
}
|
||||
|
||||
interface ValidateFunction {
|
||||
(
|
||||
data: any,
|
||||
dataPath?: string,
|
||||
parentData?: object | Array<any>,
|
||||
parentDataProperty?: string | number,
|
||||
rootData?: object | Array<any>
|
||||
): boolean | PromiseLike<any>;
|
||||
schema?: object | boolean;
|
||||
errors?: null | Array<ErrorObject>;
|
||||
refs?: object;
|
||||
refVal?: Array<any>;
|
||||
root?: ValidateFunction | object;
|
||||
$async?: true;
|
||||
source?: object;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
$data?: boolean;
|
||||
allErrors?: boolean;
|
||||
verbose?: boolean;
|
||||
jsonPointers?: boolean;
|
||||
uniqueItems?: boolean;
|
||||
unicode?: boolean;
|
||||
format?: string;
|
||||
formats?: object;
|
||||
unknownFormats?: true | string[] | 'ignore';
|
||||
schemas?: Array<object> | object;
|
||||
schemaId?: '$id' | 'id' | 'auto';
|
||||
missingRefs?: true | 'ignore' | 'fail';
|
||||
extendRefs?: true | 'ignore' | 'fail';
|
||||
loadSchema?: (uri: string, cb?: (err: Error, schema: object) => void) => PromiseLike<object | boolean>;
|
||||
removeAdditional?: boolean | 'all' | 'failing';
|
||||
useDefaults?: boolean | 'empty' | 'shared';
|
||||
coerceTypes?: boolean | 'array';
|
||||
strictDefaults?: boolean | 'log';
|
||||
strictKeywords?: boolean | 'log';
|
||||
async?: boolean | string;
|
||||
transpile?: string | ((code: string) => string);
|
||||
meta?: boolean | object;
|
||||
validateSchema?: boolean | 'log';
|
||||
addUsedSchema?: boolean;
|
||||
inlineRefs?: boolean | number;
|
||||
passContext?: boolean;
|
||||
loopRequired?: number;
|
||||
ownProperties?: boolean;
|
||||
multipleOfPrecision?: boolean | number;
|
||||
errorDataPath?: string,
|
||||
messages?: boolean;
|
||||
sourceCode?: boolean;
|
||||
processCode?: (code: string) => string;
|
||||
cache?: object;
|
||||
logger?: CustomLogger | false;
|
||||
nullable?: boolean;
|
||||
serialize?: ((schema: object | boolean) => any) | false;
|
||||
}
|
||||
|
||||
type FormatValidator = string | RegExp | ((data: string) => boolean | PromiseLike<any>);
|
||||
type NumberFormatValidator = ((data: number) => boolean | PromiseLike<any>);
|
||||
|
||||
interface NumberFormatDefinition {
|
||||
type: "number",
|
||||
validate: NumberFormatValidator;
|
||||
compare?: (data1: number, data2: number) => number;
|
||||
async?: boolean;
|
||||
}
|
||||
|
||||
interface StringFormatDefinition {
|
||||
type?: "string",
|
||||
validate: FormatValidator;
|
||||
compare?: (data1: string, data2: string) => number;
|
||||
async?: boolean;
|
||||
}
|
||||
|
||||
type FormatDefinition = NumberFormatDefinition | StringFormatDefinition;
|
||||
|
||||
interface KeywordDefinition {
|
||||
type?: string | Array<string>;
|
||||
async?: boolean;
|
||||
$data?: boolean;
|
||||
errors?: boolean | string;
|
||||
metaSchema?: object;
|
||||
// schema: false makes validate not to expect schema (ValidateFunction)
|
||||
schema?: boolean;
|
||||
statements?: boolean;
|
||||
dependencies?: Array<string>;
|
||||
modifying?: boolean;
|
||||
valid?: boolean;
|
||||
// one and only one of the following properties should be present
|
||||
validate?: SchemaValidateFunction | ValidateFunction;
|
||||
compile?: (schema: any, parentSchema: object, it: CompilationContext) => ValidateFunction;
|
||||
macro?: (schema: any, parentSchema: object, it: CompilationContext) => object | boolean;
|
||||
inline?: (it: CompilationContext, keyword: string, schema: any, parentSchema: object) => string;
|
||||
}
|
||||
|
||||
interface CompilationContext {
|
||||
level: number;
|
||||
dataLevel: number;
|
||||
schema: any;
|
||||
schemaPath: string;
|
||||
baseId: string;
|
||||
async: boolean;
|
||||
opts: Options;
|
||||
formats: {
|
||||
[index: string]: FormatDefinition | undefined;
|
||||
};
|
||||
compositeRule: boolean;
|
||||
validate: (schema: object) => boolean;
|
||||
util: {
|
||||
copy(obj: any, target?: any): any;
|
||||
toHash(source: string[]): { [index: string]: true | undefined };
|
||||
equal(obj: any, target: any): boolean;
|
||||
getProperty(str: string): string;
|
||||
schemaHasRules(schema: object, rules: any): string;
|
||||
escapeQuotes(str: string): string;
|
||||
toQuotedString(str: string): string;
|
||||
getData(jsonPointer: string, dataLevel: number, paths: string[]): string;
|
||||
escapeJsonPointer(str: string): string;
|
||||
unescapeJsonPointer(str: string): string;
|
||||
escapeFragment(str: string): string;
|
||||
unescapeFragment(str: string): string;
|
||||
};
|
||||
self: Ajv;
|
||||
}
|
||||
|
||||
interface SchemaValidateFunction {
|
||||
(
|
||||
schema: any,
|
||||
data: any,
|
||||
parentSchema?: object,
|
||||
dataPath?: string,
|
||||
parentData?: object | Array<any>,
|
||||
parentDataProperty?: string | number,
|
||||
rootData?: object | Array<any>
|
||||
): boolean | PromiseLike<any>;
|
||||
errors?: Array<ErrorObject>;
|
||||
}
|
||||
|
||||
interface ErrorsTextOptions {
|
||||
separator?: string;
|
||||
dataVar?: string;
|
||||
}
|
||||
|
||||
interface ErrorObject {
|
||||
keyword: string;
|
||||
dataPath: string;
|
||||
schemaPath: string;
|
||||
params: ErrorParameters;
|
||||
// Added to validation errors of propertyNames keyword schema
|
||||
propertyName?: string;
|
||||
// Excluded if messages set to false.
|
||||
message?: string;
|
||||
// These are added with the `verbose` option.
|
||||
schema?: any;
|
||||
parentSchema?: object;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
type ErrorParameters = RefParams | LimitParams | AdditionalPropertiesParams |
|
||||
DependenciesParams | FormatParams | ComparisonParams |
|
||||
MultipleOfParams | PatternParams | RequiredParams |
|
||||
TypeParams | UniqueItemsParams | CustomParams |
|
||||
PatternRequiredParams | PropertyNamesParams |
|
||||
IfParams | SwitchParams | NoParams | EnumParams;
|
||||
|
||||
interface RefParams {
|
||||
ref: string;
|
||||
}
|
||||
|
||||
interface LimitParams {
|
||||
limit: number;
|
||||
}
|
||||
|
||||
interface AdditionalPropertiesParams {
|
||||
additionalProperty: string;
|
||||
}
|
||||
|
||||
interface DependenciesParams {
|
||||
property: string;
|
||||
missingProperty: string;
|
||||
depsCount: number;
|
||||
deps: string;
|
||||
}
|
||||
|
||||
interface FormatParams {
|
||||
format: string
|
||||
}
|
||||
|
||||
interface ComparisonParams {
|
||||
comparison: string;
|
||||
limit: number | string;
|
||||
exclusive: boolean;
|
||||
}
|
||||
|
||||
interface MultipleOfParams {
|
||||
multipleOf: number;
|
||||
}
|
||||
|
||||
interface PatternParams {
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
interface RequiredParams {
|
||||
missingProperty: string;
|
||||
}
|
||||
|
||||
interface TypeParams {
|
||||
type: string;
|
||||
}
|
||||
|
||||
interface UniqueItemsParams {
|
||||
i: number;
|
||||
j: number;
|
||||
}
|
||||
|
||||
interface CustomParams {
|
||||
keyword: string;
|
||||
}
|
||||
|
||||
interface PatternRequiredParams {
|
||||
missingPattern: string;
|
||||
}
|
||||
|
||||
interface PropertyNamesParams {
|
||||
propertyName: string;
|
||||
}
|
||||
|
||||
interface IfParams {
|
||||
failingKeyword: string;
|
||||
}
|
||||
|
||||
interface SwitchParams {
|
||||
caseIndex: number;
|
||||
}
|
||||
|
||||
interface NoParams { }
|
||||
|
||||
interface EnumParams {
|
||||
allowedValues: Array<any>;
|
||||
}
|
||||
}
|
||||
|
||||
export = ajv;
|
@ -0,0 +1,497 @@
|
||||
'use strict';
|
||||
|
||||
var compileSchema = require('./compile')
|
||||
, resolve = require('./compile/resolve')
|
||||
, Cache = require('./cache')
|
||||
, SchemaObject = require('./compile/schema_obj')
|
||||
, stableStringify = require('fast-json-stable-stringify')
|
||||
, formats = require('./compile/formats')
|
||||
, rules = require('./compile/rules')
|
||||
, $dataMetaSchema = require('./data')
|
||||
, util = require('./compile/util');
|
||||
|
||||
module.exports = Ajv;
|
||||
|
||||
Ajv.prototype.validate = validate;
|
||||
Ajv.prototype.compile = compile;
|
||||
Ajv.prototype.addSchema = addSchema;
|
||||
Ajv.prototype.addMetaSchema = addMetaSchema;
|
||||
Ajv.prototype.validateSchema = validateSchema;
|
||||
Ajv.prototype.getSchema = getSchema;
|
||||
Ajv.prototype.removeSchema = removeSchema;
|
||||
Ajv.prototype.addFormat = addFormat;
|
||||
Ajv.prototype.errorsText = errorsText;
|
||||
|
||||
Ajv.prototype._addSchema = _addSchema;
|
||||
Ajv.prototype._compile = _compile;
|
||||
|
||||
Ajv.prototype.compileAsync = require('./compile/async');
|
||||
var customKeyword = require('./keyword');
|
||||
Ajv.prototype.addKeyword = customKeyword.add;
|
||||
Ajv.prototype.getKeyword = customKeyword.get;
|
||||
Ajv.prototype.removeKeyword = customKeyword.remove;
|
||||
Ajv.prototype.validateKeyword = customKeyword.validate;
|
||||
|
||||
var errorClasses = require('./compile/error_classes');
|
||||
Ajv.ValidationError = errorClasses.Validation;
|
||||
Ajv.MissingRefError = errorClasses.MissingRef;
|
||||
Ajv.$dataMetaSchema = $dataMetaSchema;
|
||||
|
||||
var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema';
|
||||
|
||||
var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes', 'strictDefaults' ];
|
||||
var META_SUPPORT_DATA = ['/properties'];
|
||||
|
||||
/**
|
||||
* Creates validator instance.
|
||||
* Usage: `Ajv(opts)`
|
||||
* @param {Object} opts optional options
|
||||
* @return {Object} ajv instance
|
||||
*/
|
||||
function Ajv(opts) {
|
||||
if (!(this instanceof Ajv)) return new Ajv(opts);
|
||||
opts = this._opts = util.copy(opts) || {};
|
||||
setLogger(this);
|
||||
this._schemas = {};
|
||||
this._refs = {};
|
||||
this._fragments = {};
|
||||
this._formats = formats(opts.format);
|
||||
|
||||
this._cache = opts.cache || new Cache;
|
||||
this._loadingSchemas = {};
|
||||
this._compilations = [];
|
||||
this.RULES = rules();
|
||||
this._getId = chooseGetId(opts);
|
||||
|
||||
opts.loopRequired = opts.loopRequired || Infinity;
|
||||
if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true;
|
||||
if (opts.serialize === undefined) opts.serialize = stableStringify;
|
||||
this._metaOpts = getMetaSchemaOptions(this);
|
||||
|
||||
if (opts.formats) addInitialFormats(this);
|
||||
addDefaultMetaSchema(this);
|
||||
if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta);
|
||||
if (opts.nullable) this.addKeyword('nullable', {metaSchema: {type: 'boolean'}});
|
||||
addInitialSchemas(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Validate data using schema
|
||||
* Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize.
|
||||
* @this Ajv
|
||||
* @param {String|Object} schemaKeyRef key, ref or schema object
|
||||
* @param {Any} data to be validated
|
||||
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
|
||||
*/
|
||||
function validate(schemaKeyRef, data) {
|
||||
var v;
|
||||
if (typeof schemaKeyRef == 'string') {
|
||||
v = this.getSchema(schemaKeyRef);
|
||||
if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"');
|
||||
} else {
|
||||
var schemaObj = this._addSchema(schemaKeyRef);
|
||||
v = schemaObj.validate || this._compile(schemaObj);
|
||||
}
|
||||
|
||||
var valid = v(data);
|
||||
if (v.$async !== true) this.errors = v.errors;
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create validating function for passed schema.
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema object
|
||||
* @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords.
|
||||
* @return {Function} validating function
|
||||
*/
|
||||
function compile(schema, _meta) {
|
||||
var schemaObj = this._addSchema(schema, undefined, _meta);
|
||||
return schemaObj.validate || this._compile(schemaObj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds schema to the instance.
|
||||
* @this Ajv
|
||||
* @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
|
||||
* @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
|
||||
* @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead.
|
||||
* @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead.
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
function addSchema(schema, key, _skipValidation, _meta) {
|
||||
if (Array.isArray(schema)){
|
||||
for (var i=0; i<schema.length; i++) this.addSchema(schema[i], undefined, _skipValidation, _meta);
|
||||
return this;
|
||||
}
|
||||
var id = this._getId(schema);
|
||||
if (id !== undefined && typeof id != 'string')
|
||||
throw new Error('schema id must be string');
|
||||
key = resolve.normalizeId(key || id);
|
||||
checkUnique(this, key);
|
||||
this._schemas[key] = this._addSchema(schema, _skipValidation, _meta, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add schema that will be used to validate other schemas
|
||||
* options in META_IGNORE_OPTIONS are alway set to false
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema object
|
||||
* @param {String} key optional schema key
|
||||
* @param {Boolean} skipValidation true to skip schema validation, can be used to override validateSchema option for meta-schema
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
function addMetaSchema(schema, key, skipValidation) {
|
||||
this.addSchema(schema, key, skipValidation, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate schema
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema to validate
|
||||
* @param {Boolean} throwOrLogError pass true to throw (or log) an error if invalid
|
||||
* @return {Boolean} true if schema is valid
|
||||
*/
|
||||
function validateSchema(schema, throwOrLogError) {
|
||||
var $schema = schema.$schema;
|
||||
if ($schema !== undefined && typeof $schema != 'string')
|
||||
throw new Error('$schema must be a string');
|
||||
$schema = $schema || this._opts.defaultMeta || defaultMeta(this);
|
||||
if (!$schema) {
|
||||
this.logger.warn('meta-schema not available');
|
||||
this.errors = null;
|
||||
return true;
|
||||
}
|
||||
var valid = this.validate($schema, schema);
|
||||
if (!valid && throwOrLogError) {
|
||||
var message = 'schema is invalid: ' + this.errorsText();
|
||||
if (this._opts.validateSchema == 'log') this.logger.error(message);
|
||||
else throw new Error(message);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
function defaultMeta(self) {
|
||||
var meta = self._opts.meta;
|
||||
self._opts.defaultMeta = typeof meta == 'object'
|
||||
? self._getId(meta) || meta
|
||||
: self.getSchema(META_SCHEMA_ID)
|
||||
? META_SCHEMA_ID
|
||||
: undefined;
|
||||
return self._opts.defaultMeta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get compiled schema from the instance by `key` or `ref`.
|
||||
* @this Ajv
|
||||
* @param {String} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
|
||||
* @return {Function} schema validating function (with property `schema`).
|
||||
*/
|
||||
function getSchema(keyRef) {
|
||||
var schemaObj = _getSchemaObj(this, keyRef);
|
||||
switch (typeof schemaObj) {
|
||||
case 'object': return schemaObj.validate || this._compile(schemaObj);
|
||||
case 'string': return this.getSchema(schemaObj);
|
||||
case 'undefined': return _getSchemaFragment(this, keyRef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _getSchemaFragment(self, ref) {
|
||||
var res = resolve.schema.call(self, { schema: {} }, ref);
|
||||
if (res) {
|
||||
var schema = res.schema
|
||||
, root = res.root
|
||||
, baseId = res.baseId;
|
||||
var v = compileSchema.call(self, schema, root, undefined, baseId);
|
||||
self._fragments[ref] = new SchemaObject({
|
||||
ref: ref,
|
||||
fragment: true,
|
||||
schema: schema,
|
||||
root: root,
|
||||
baseId: baseId,
|
||||
validate: v
|
||||
});
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _getSchemaObj(self, keyRef) {
|
||||
keyRef = resolve.normalizeId(keyRef);
|
||||
return self._schemas[keyRef] || self._refs[keyRef] || self._fragments[keyRef];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove cached schema(s).
|
||||
* If no parameter is passed all schemas but meta-schemas are removed.
|
||||
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
|
||||
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
|
||||
* @this Ajv
|
||||
* @param {String|Object|RegExp} schemaKeyRef key, ref, pattern to match key/ref or schema object
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
function removeSchema(schemaKeyRef) {
|
||||
if (schemaKeyRef instanceof RegExp) {
|
||||
_removeAllSchemas(this, this._schemas, schemaKeyRef);
|
||||
_removeAllSchemas(this, this._refs, schemaKeyRef);
|
||||
return this;
|
||||
}
|
||||
switch (typeof schemaKeyRef) {
|
||||
case 'undefined':
|
||||
_removeAllSchemas(this, this._schemas);
|
||||
_removeAllSchemas(this, this._refs);
|
||||
this._cache.clear();
|
||||
return this;
|
||||
case 'string':
|
||||
var schemaObj = _getSchemaObj(this, schemaKeyRef);
|
||||
if (schemaObj) this._cache.del(schemaObj.cacheKey);
|
||||
delete this._schemas[schemaKeyRef];
|
||||
delete this._refs[schemaKeyRef];
|
||||
return this;
|
||||
case 'object':
|
||||
var serialize = this._opts.serialize;
|
||||
var cacheKey = serialize ? serialize(schemaKeyRef) : schemaKeyRef;
|
||||
this._cache.del(cacheKey);
|
||||
var id = this._getId(schemaKeyRef);
|
||||
if (id) {
|
||||
id = resolve.normalizeId(id);
|
||||
delete this._schemas[id];
|
||||
delete this._refs[id];
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
function _removeAllSchemas(self, schemas, regex) {
|
||||
for (var keyRef in schemas) {
|
||||
var schemaObj = schemas[keyRef];
|
||||
if (!schemaObj.meta && (!regex || regex.test(keyRef))) {
|
||||
self._cache.del(schemaObj.cacheKey);
|
||||
delete schemas[keyRef];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* @this Ajv */
|
||||
function _addSchema(schema, skipValidation, meta, shouldAddSchema) {
|
||||
if (typeof schema != 'object' && typeof schema != 'boolean')
|
||||
throw new Error('schema should be object or boolean');
|
||||
var serialize = this._opts.serialize;
|
||||
var cacheKey = serialize ? serialize(schema) : schema;
|
||||
var cached = this._cache.get(cacheKey);
|
||||
if (cached) return cached;
|
||||
|
||||
shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false;
|
||||
|
||||
var id = resolve.normalizeId(this._getId(schema));
|
||||
if (id && shouldAddSchema) checkUnique(this, id);
|
||||
|
||||
var willValidate = this._opts.validateSchema !== false && !skipValidation;
|
||||
var recursiveMeta;
|
||||
if (willValidate && !(recursiveMeta = id && id == resolve.normalizeId(schema.$schema)))
|
||||
this.validateSchema(schema, true);
|
||||
|
||||
var localRefs = resolve.ids.call(this, schema);
|
||||
|
||||
var schemaObj = new SchemaObject({
|
||||
id: id,
|
||||
schema: schema,
|
||||
localRefs: localRefs,
|
||||
cacheKey: cacheKey,
|
||||
meta: meta
|
||||
});
|
||||
|
||||
if (id[0] != '#' && shouldAddSchema) this._refs[id] = schemaObj;
|
||||
this._cache.put(cacheKey, schemaObj);
|
||||
|
||||
if (willValidate && recursiveMeta) this.validateSchema(schema, true);
|
||||
|
||||
return schemaObj;
|
||||
}
|
||||
|
||||
|
||||
/* @this Ajv */
|
||||
function _compile(schemaObj, root) {
|
||||
if (schemaObj.compiling) {
|
||||
schemaObj.validate = callValidate;
|
||||
callValidate.schema = schemaObj.schema;
|
||||
callValidate.errors = null;
|
||||
callValidate.root = root ? root : callValidate;
|
||||
if (schemaObj.schema.$async === true)
|
||||
callValidate.$async = true;
|
||||
return callValidate;
|
||||
}
|
||||
schemaObj.compiling = true;
|
||||
|
||||
var currentOpts;
|
||||
if (schemaObj.meta) {
|
||||
currentOpts = this._opts;
|
||||
this._opts = this._metaOpts;
|
||||
}
|
||||
|
||||
var v;
|
||||
try { v = compileSchema.call(this, schemaObj.schema, root, schemaObj.localRefs); }
|
||||
catch(e) {
|
||||
delete schemaObj.validate;
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
schemaObj.compiling = false;
|
||||
if (schemaObj.meta) this._opts = currentOpts;
|
||||
}
|
||||
|
||||
schemaObj.validate = v;
|
||||
schemaObj.refs = v.refs;
|
||||
schemaObj.refVal = v.refVal;
|
||||
schemaObj.root = v.root;
|
||||
return v;
|
||||
|
||||
|
||||
/* @this {*} - custom context, see passContext option */
|
||||
function callValidate() {
|
||||
/* jshint validthis: true */
|
||||
var _validate = schemaObj.validate;
|
||||
var result = _validate.apply(this, arguments);
|
||||
callValidate.errors = _validate.errors;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function chooseGetId(opts) {
|
||||
switch (opts.schemaId) {
|
||||
case 'auto': return _get$IdOrId;
|
||||
case 'id': return _getId;
|
||||
default: return _get$Id;
|
||||
}
|
||||
}
|
||||
|
||||
/* @this Ajv */
|
||||
function _getId(schema) {
|
||||
if (schema.$id) this.logger.warn('schema $id ignored', schema.$id);
|
||||
return schema.id;
|
||||
}
|
||||
|
||||
/* @this Ajv */
|
||||
function _get$Id(schema) {
|
||||
if (schema.id) this.logger.warn('schema id ignored', schema.id);
|
||||
return schema.$id;
|
||||
}
|
||||
|
||||
|
||||
function _get$IdOrId(schema) {
|
||||
if (schema.$id && schema.id && schema.$id != schema.id)
|
||||
throw new Error('schema $id is different from id');
|
||||
return schema.$id || schema.id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert array of error message objects to string
|
||||
* @this Ajv
|
||||
* @param {Array<Object>} errors optional array of validation errors, if not passed errors from the instance are used.
|
||||
* @param {Object} options optional options with properties `separator` and `dataVar`.
|
||||
* @return {String} human readable string with all errors descriptions
|
||||
*/
|
||||
function errorsText(errors, options) {
|
||||
errors = errors || this.errors;
|
||||
if (!errors) return 'No errors';
|
||||
options = options || {};
|
||||
var separator = options.separator === undefined ? ', ' : options.separator;
|
||||
var dataVar = options.dataVar === undefined ? 'data' : options.dataVar;
|
||||
|
||||
var text = '';
|
||||
for (var i=0; i<errors.length; i++) {
|
||||
var e = errors[i];
|
||||
if (e) text += dataVar + e.dataPath + ' ' + e.message + separator;
|
||||
}
|
||||
return text.slice(0, -separator.length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add custom format
|
||||
* @this Ajv
|
||||
* @param {String} name format name
|
||||
* @param {String|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
function addFormat(name, format) {
|
||||
if (typeof format == 'string') format = new RegExp(format);
|
||||
this._formats[name] = format;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
function addDefaultMetaSchema(self) {
|
||||
var $dataSchema;
|
||||
if (self._opts.$data) {
|
||||
$dataSchema = require('./refs/data.json');
|
||||
self.addMetaSchema($dataSchema, $dataSchema.$id, true);
|
||||
}
|
||||
if (self._opts.meta === false) return;
|
||||
var metaSchema = require('./refs/json-schema-draft-07.json');
|
||||
if (self._opts.$data) metaSchema = $dataMetaSchema(metaSchema, META_SUPPORT_DATA);
|
||||
self.addMetaSchema(metaSchema, META_SCHEMA_ID, true);
|
||||
self._refs['http://json-schema.org/schema'] = META_SCHEMA_ID;
|
||||
}
|
||||
|
||||
|
||||
function addInitialSchemas(self) {
|
||||
var optsSchemas = self._opts.schemas;
|
||||
if (!optsSchemas) return;
|
||||
if (Array.isArray(optsSchemas)) self.addSchema(optsSchemas);
|
||||
else for (var key in optsSchemas) self.addSchema(optsSchemas[key], key);
|
||||
}
|
||||
|
||||
|
||||
function addInitialFormats(self) {
|
||||
for (var name in self._opts.formats) {
|
||||
var format = self._opts.formats[name];
|
||||
self.addFormat(name, format);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkUnique(self, id) {
|
||||
if (self._schemas[id] || self._refs[id])
|
||||
throw new Error('schema with key or id "' + id + '" already exists');
|
||||
}
|
||||
|
||||
|
||||
function getMetaSchemaOptions(self) {
|
||||
var metaOpts = util.copy(self._opts);
|
||||
for (var i=0; i<META_IGNORE_OPTIONS.length; i++)
|
||||
delete metaOpts[META_IGNORE_OPTIONS[i]];
|
||||
return metaOpts;
|
||||
}
|
||||
|
||||
|
||||
function setLogger(self) {
|
||||
var logger = self._opts.logger;
|
||||
if (logger === false) {
|
||||
self.logger = {log: noop, warn: noop, error: noop};
|
||||
} else {
|
||||
if (logger === undefined) logger = console;
|
||||
if (!(typeof logger == 'object' && logger.log && logger.warn && logger.error))
|
||||
throw new Error('logger must implement log, warn and error methods');
|
||||
self.logger = logger;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function noop() {}
|
@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
var Cache = module.exports = function Cache() {
|
||||
this._cache = {};
|
||||
};
|
||||
|
||||
|
||||
Cache.prototype.put = function Cache_put(key, value) {
|
||||
this._cache[key] = value;
|
||||
};
|
||||
|
||||
|
||||
Cache.prototype.get = function Cache_get(key) {
|
||||
return this._cache[key];
|
||||
};
|
||||
|
||||
|
||||
Cache.prototype.del = function Cache_del(key) {
|
||||
delete this._cache[key];
|
||||
};
|
||||
|
||||
|
||||
Cache.prototype.clear = function Cache_clear() {
|
||||
this._cache = {};
|
||||
};
|
@ -0,0 +1,90 @@
|
||||
'use strict';
|
||||
|
||||
var MissingRefError = require('./error_classes').MissingRef;
|
||||
|
||||
module.exports = compileAsync;
|
||||
|
||||
|
||||
/**
|
||||
* Creates validating function for passed schema with asynchronous loading of missing schemas.
|
||||
* `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, meta, callback) {
|
||||
/* eslint no-shadow: 0 */
|
||||
/* global Promise */
|
||||
/* jshint validthis: true */
|
||||
var self = this;
|
||||
if (typeof this._opts.loadSchema != 'function')
|
||||
throw new Error('options.loadSchema should be a function');
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
p.then(
|
||||
function(v) { callback(null, v); },
|
||||
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) {
|
||||
if (e instanceof MissingRefError) return loadMissingSchema(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
function loadMissingSchema(e) {
|
||||
var ref = e.missingSchema;
|
||||
if (added(ref)) throw new Error('Schema ' + ref + ' is loaded but ' + e.missingRef + ' cannot be resolved');
|
||||
|
||||
var schemaPromise = self._loadingSchemas[ref];
|
||||
if (!schemaPromise) {
|
||||
schemaPromise = self._loadingSchemas[ref] = self._opts.loadSchema(ref);
|
||||
schemaPromise.then(removePromise, removePromise);
|
||||
}
|
||||
|
||||
return schemaPromise.then(function (sch) {
|
||||
if (!added(ref)) {
|
||||
return loadMetaSchemaOf(sch).then(function () {
|
||||
if (!added(ref)) self.addSchema(sch, ref, undefined, meta);
|
||||
});
|
||||
}
|
||||
}).then(function() {
|
||||
return _compileAsync(schemaObj);
|
||||
});
|
||||
|
||||
function removePromise() {
|
||||
delete self._loadingSchemas[ref];
|
||||
}
|
||||
|
||||
function added(ref) {
|
||||
return self._refs[ref] || self._schemas[ref];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
// do NOT remove this file - it would break pre-compiled schemas
|
||||
// https://github.com/epoberezkin/ajv/issues/889
|
||||
module.exports = require('fast-deep-equal');
|
@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
var resolve = require('./resolve');
|
||||
|
||||
module.exports = {
|
||||
Validation: errorSubclass(ValidationError),
|
||||
MissingRef: errorSubclass(MissingRefError)
|
||||
};
|
||||
|
||||
|
||||
function ValidationError(errors) {
|
||||
this.message = 'validation failed';
|
||||
this.errors = errors;
|
||||
this.ajv = this.validation = true;
|
||||
}
|
||||
|
||||
|
||||
MissingRefError.message = function (baseId, ref) {
|
||||
return 'can\'t resolve reference ' + ref + ' from id ' + baseId;
|
||||
};
|
||||
|
||||
|
||||
function MissingRefError(baseId, ref, message) {
|
||||
this.message = message || MissingRefError.message(baseId, ref);
|
||||
this.missingRef = resolve.url(baseId, ref);
|
||||
this.missingSchema = resolve.normalizeId(resolve.fullPath(this.missingRef));
|
||||
}
|
||||
|
||||
|
||||
function errorSubclass(Subclass) {
|
||||
Subclass.prototype = Object.create(Error.prototype);
|
||||
Subclass.prototype.constructor = Subclass;
|
||||
return Subclass;
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('./util');
|
||||
|
||||
var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
||||
var DAYS = [0,31,28,31,30,31,30,31,31,30,31,30,31];
|
||||
var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i;
|
||||
var HOSTNAME = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*$/i;
|
||||
var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
|
||||
var URIREF = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
|
||||
// uri-template: https://tools.ietf.org/html/rfc6570
|
||||
var URITEMPLATE = /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i;
|
||||
// For the source: https://gist.github.com/dperini/729294
|
||||
// For test cases: https://mathiasbynens.be/demo/url-regex
|
||||
// @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983.
|
||||
// var URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)(?:\.(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu;
|
||||
var URL = /^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i;
|
||||
var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i;
|
||||
var JSON_POINTER = /^(?:\/(?:[^~/]|~0|~1)*)*$/;
|
||||
var JSON_POINTER_URI_FRAGMENT = /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i;
|
||||
var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;
|
||||
|
||||
|
||||
module.exports = formats;
|
||||
|
||||
function formats(mode) {
|
||||
mode = mode == 'full' ? 'full' : 'fast';
|
||||
return util.copy(formats[mode]);
|
||||
}
|
||||
|
||||
|
||||
formats.fast = {
|
||||
// date: http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/,
|
||||
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
time: /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i,
|
||||
'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i,
|
||||
// uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js
|
||||
uri: /^(?:[a-z][a-z0-9+-.]*:)(?:\/?\/)?[^\s]*$/i,
|
||||
'uri-reference': /^(?:(?:[a-z][a-z0-9+-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,
|
||||
'uri-template': URITEMPLATE,
|
||||
url: URL,
|
||||
// email (sources from jsen validator):
|
||||
// http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363
|
||||
// http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation')
|
||||
email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,
|
||||
hostname: HOSTNAME,
|
||||
// optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
|
||||
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
|
||||
// optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
|
||||
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
|
||||
regex: regex,
|
||||
// uuid: http://tools.ietf.org/html/rfc4122
|
||||
uuid: UUID,
|
||||
// JSON-pointer: https://tools.ietf.org/html/rfc6901
|
||||
// uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A
|
||||
'json-pointer': JSON_POINTER,
|
||||
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT,
|
||||
// relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00
|
||||
'relative-json-pointer': RELATIVE_JSON_POINTER
|
||||
};
|
||||
|
||||
|
||||
formats.full = {
|
||||
date: date,
|
||||
time: time,
|
||||
'date-time': date_time,
|
||||
uri: uri,
|
||||
'uri-reference': URIREF,
|
||||
'uri-template': URITEMPLATE,
|
||||
url: URL,
|
||||
email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
|
||||
hostname: hostname,
|
||||
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
|
||||
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
|
||||
regex: regex,
|
||||
uuid: UUID,
|
||||
'json-pointer': JSON_POINTER,
|
||||
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT,
|
||||
'relative-json-pointer': RELATIVE_JSON_POINTER
|
||||
};
|
||||
|
||||
|
||||
function isLeapYear(year) {
|
||||
// https://tools.ietf.org/html/rfc3339#appendix-C
|
||||
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
||||
}
|
||||
|
||||
|
||||
function date(str) {
|
||||
// full-date from http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
var matches = str.match(DATE);
|
||||
if (!matches) return false;
|
||||
|
||||
var year = +matches[1];
|
||||
var month = +matches[2];
|
||||
var day = +matches[3];
|
||||
|
||||
return month >= 1 && month <= 12 && day >= 1 &&
|
||||
day <= (month == 2 && isLeapYear(year) ? 29 : DAYS[month]);
|
||||
}
|
||||
|
||||
|
||||
function time(str, full) {
|
||||
var matches = str.match(TIME);
|
||||
if (!matches) return false;
|
||||
|
||||
var hour = matches[1];
|
||||
var minute = matches[2];
|
||||
var second = matches[3];
|
||||
var timeZone = matches[5];
|
||||
return ((hour <= 23 && minute <= 59 && second <= 59) ||
|
||||
(hour == 23 && minute == 59 && second == 60)) &&
|
||||
(!full || timeZone);
|
||||
}
|
||||
|
||||
|
||||
var DATE_TIME_SEPARATOR = /t|\s/i;
|
||||
function date_time(str) {
|
||||
// http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
var dateTime = str.split(DATE_TIME_SEPARATOR);
|
||||
return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true);
|
||||
}
|
||||
|
||||
|
||||
function hostname(str) {
|
||||
// https://tools.ietf.org/html/rfc1034#section-3.5
|
||||
// https://tools.ietf.org/html/rfc1123#section-2
|
||||
return str.length <= 255 && HOSTNAME.test(str);
|
||||
}
|
||||
|
||||
|
||||
var NOT_URI_FRAGMENT = /\/|:/;
|
||||
function uri(str) {
|
||||
// http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "."
|
||||
return NOT_URI_FRAGMENT.test(str) && URI.test(str);
|
||||
}
|
||||
|
||||
|
||||
var Z_ANCHOR = /[^\\]\\Z/;
|
||||
function regex(str) {
|
||||
if (Z_ANCHOR.test(str)) return false;
|
||||
try {
|
||||
new RegExp(str);
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,387 @@
|
||||
'use strict';
|
||||
|
||||
var resolve = require('./resolve')
|
||||
, util = require('./util')
|
||||
, errorClasses = require('./error_classes')
|
||||
, stableStringify = require('fast-json-stable-stringify');
|
||||
|
||||
var validateGenerator = require('../dotjs/validate');
|
||||
|
||||
/**
|
||||
* Functions below are used inside compiled validations function
|
||||
*/
|
||||
|
||||
var ucs2length = util.ucs2length;
|
||||
var equal = require('fast-deep-equal');
|
||||
|
||||
// this error is thrown by async schemas to return validation errors via exception
|
||||
var ValidationError = errorClasses.Validation;
|
||||
|
||||
module.exports = compile;
|
||||
|
||||
|
||||
/**
|
||||
* Compiles schema to validation function
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema object
|
||||
* @param {Object} root object with information about the root schema for this schema
|
||||
* @param {Object} localRefs the hash of local references inside the schema (created by resolve.id), used for inline resolution
|
||||
* @param {String} baseId base ID for IDs in the schema
|
||||
* @return {Function} validation function
|
||||
*/
|
||||
function compile(schema, root, localRefs, baseId) {
|
||||
/* jshint validthis: true, evil: true */
|
||||
/* eslint no-shadow: 0 */
|
||||
var self = this
|
||||
, opts = this._opts
|
||||
, refVal = [ undefined ]
|
||||
, refs = {}
|
||||
, patterns = []
|
||||
, patternsHash = {}
|
||||
, defaults = []
|
||||
, defaultsHash = {}
|
||||
, customRules = [];
|
||||
|
||||
root = root || { schema: schema, refVal: refVal, refs: refs };
|
||||
|
||||
var c = checkCompiling.call(this, schema, root, baseId);
|
||||
var compilation = this._compilations[c.index];
|
||||
if (c.compiling) return (compilation.callValidate = callValidate);
|
||||
|
||||
var formats = this._formats;
|
||||
var RULES = this.RULES;
|
||||
|
||||
try {
|
||||
var v = localCompile(schema, root, localRefs, baseId);
|
||||
compilation.validate = v;
|
||||
var cv = compilation.callValidate;
|
||||
if (cv) {
|
||||
cv.schema = v.schema;
|
||||
cv.errors = null;
|
||||
cv.refs = v.refs;
|
||||
cv.refVal = v.refVal;
|
||||
cv.root = v.root;
|
||||
cv.$async = v.$async;
|
||||
if (opts.sourceCode) cv.source = v.source;
|
||||
}
|
||||
return v;
|
||||
} finally {
|
||||
endCompiling.call(this, schema, root, baseId);
|
||||
}
|
||||
|
||||
/* @this {*} - custom context, see passContext option */
|
||||
function callValidate() {
|
||||
/* jshint validthis: true */
|
||||
var validate = compilation.validate;
|
||||
var result = validate.apply(this, arguments);
|
||||
callValidate.errors = validate.errors;
|
||||
return result;
|
||||
}
|
||||
|
||||
function localCompile(_schema, _root, localRefs, baseId) {
|
||||
var isRoot = !_root || (_root && _root.schema == _schema);
|
||||
if (_root.schema != root.schema)
|
||||
return compile.call(self, _schema, _root, localRefs, baseId);
|
||||
|
||||
var $async = _schema.$async === true;
|
||||
|
||||
var sourceCode = validateGenerator({
|
||||
isTop: true,
|
||||
schema: _schema,
|
||||
isRoot: isRoot,
|
||||
baseId: baseId,
|
||||
root: _root,
|
||||
schemaPath: '',
|
||||
errSchemaPath: '#',
|
||||
errorPath: '""',
|
||||
MissingRefError: errorClasses.MissingRef,
|
||||
RULES: RULES,
|
||||
validate: validateGenerator,
|
||||
util: util,
|
||||
resolve: resolve,
|
||||
resolveRef: resolveRef,
|
||||
usePattern: usePattern,
|
||||
useDefault: useDefault,
|
||||
useCustomRule: useCustomRule,
|
||||
opts: opts,
|
||||
formats: formats,
|
||||
logger: self.logger,
|
||||
self: self
|
||||
});
|
||||
|
||||
sourceCode = vars(refVal, refValCode) + vars(patterns, patternCode)
|
||||
+ vars(defaults, defaultCode) + vars(customRules, customRuleCode)
|
||||
+ sourceCode;
|
||||
|
||||
if (opts.processCode) sourceCode = opts.processCode(sourceCode);
|
||||
// console.log('\n\n\n *** \n', JSON.stringify(sourceCode));
|
||||
var validate;
|
||||
try {
|
||||
var makeValidate = new Function(
|
||||
'self',
|
||||
'RULES',
|
||||
'formats',
|
||||
'root',
|
||||
'refVal',
|
||||
'defaults',
|
||||
'customRules',
|
||||
'equal',
|
||||
'ucs2length',
|
||||
'ValidationError',
|
||||
sourceCode
|
||||
);
|
||||
|
||||
validate = makeValidate(
|
||||
self,
|
||||
RULES,
|
||||
formats,
|
||||
root,
|
||||
refVal,
|
||||
defaults,
|
||||
customRules,
|
||||
equal,
|
||||
ucs2length,
|
||||
ValidationError
|
||||
);
|
||||
|
||||
refVal[0] = validate;
|
||||
} catch(e) {
|
||||
self.logger.error('Error compiling schema, function code:', sourceCode);
|
||||
throw e;
|
||||
}
|
||||
|
||||
validate.schema = _schema;
|
||||
validate.errors = null;
|
||||
validate.refs = refs;
|
||||
validate.refVal = refVal;
|
||||
validate.root = isRoot ? validate : _root;
|
||||
if ($async) validate.$async = true;
|
||||
if (opts.sourceCode === true) {
|
||||
validate.source = {
|
||||
code: sourceCode,
|
||||
patterns: patterns,
|
||||
defaults: defaults
|
||||
};
|
||||
}
|
||||
|
||||
return validate;
|
||||
}
|
||||
|
||||
function resolveRef(baseId, ref, isRoot) {
|
||||
ref = resolve.url(baseId, ref);
|
||||
var refIndex = refs[ref];
|
||||
var _refVal, refCode;
|
||||
if (refIndex !== undefined) {
|
||||
_refVal = refVal[refIndex];
|
||||
refCode = 'refVal[' + refIndex + ']';
|
||||
return resolvedRef(_refVal, refCode);
|
||||
}
|
||||
if (!isRoot && root.refs) {
|
||||
var rootRefId = root.refs[ref];
|
||||
if (rootRefId !== undefined) {
|
||||
_refVal = root.refVal[rootRefId];
|
||||
refCode = addLocalRef(ref, _refVal);
|
||||
return resolvedRef(_refVal, refCode);
|
||||
}
|
||||
}
|
||||
|
||||
refCode = addLocalRef(ref);
|
||||
var v = resolve.call(self, localCompile, root, ref);
|
||||
if (v === undefined) {
|
||||
var localSchema = localRefs && localRefs[ref];
|
||||
if (localSchema) {
|
||||
v = resolve.inlineRef(localSchema, opts.inlineRefs)
|
||||
? localSchema
|
||||
: compile.call(self, localSchema, root, localRefs, baseId);
|
||||
}
|
||||
}
|
||||
|
||||
if (v === undefined) {
|
||||
removeLocalRef(ref);
|
||||
} else {
|
||||
replaceLocalRef(ref, v);
|
||||
return resolvedRef(v, refCode);
|
||||
}
|
||||
}
|
||||
|
||||
function addLocalRef(ref, v) {
|
||||
var refId = refVal.length;
|
||||
refVal[refId] = v;
|
||||
refs[ref] = refId;
|
||||
return 'refVal' + refId;
|
||||
}
|
||||
|
||||
function removeLocalRef(ref) {
|
||||
delete refs[ref];
|
||||
}
|
||||
|
||||
function replaceLocalRef(ref, v) {
|
||||
var refId = refs[ref];
|
||||
refVal[refId] = v;
|
||||
}
|
||||
|
||||
function resolvedRef(refVal, code) {
|
||||
return typeof refVal == 'object' || typeof refVal == 'boolean'
|
||||
? { code: code, schema: refVal, inline: true }
|
||||
: { code: code, $async: refVal && !!refVal.$async };
|
||||
}
|
||||
|
||||
function usePattern(regexStr) {
|
||||
var index = patternsHash[regexStr];
|
||||
if (index === undefined) {
|
||||
index = patternsHash[regexStr] = patterns.length;
|
||||
patterns[index] = regexStr;
|
||||
}
|
||||
return 'pattern' + index;
|
||||
}
|
||||
|
||||
function useDefault(value) {
|
||||
switch (typeof value) {
|
||||
case 'boolean':
|
||||
case 'number':
|
||||
return '' + value;
|
||||
case 'string':
|
||||
return util.toQuotedString(value);
|
||||
case 'object':
|
||||
if (value === null) return 'null';
|
||||
var valueStr = stableStringify(value);
|
||||
var index = defaultsHash[valueStr];
|
||||
if (index === undefined) {
|
||||
index = defaultsHash[valueStr] = defaults.length;
|
||||
defaults[index] = value;
|
||||
}
|
||||
return 'default' + index;
|
||||
}
|
||||
}
|
||||
|
||||
function useCustomRule(rule, schema, parentSchema, it) {
|
||||
if (self._opts.validateSchema !== false) {
|
||||
var deps = rule.definition.dependencies;
|
||||
if (deps && !deps.every(function(keyword) {
|
||||
return Object.prototype.hasOwnProperty.call(parentSchema, keyword);
|
||||
}))
|
||||
throw new Error('parent schema must have all required keywords: ' + deps.join(','));
|
||||
|
||||
var validateSchema = rule.definition.validateSchema;
|
||||
if (validateSchema) {
|
||||
var valid = validateSchema(schema);
|
||||
if (!valid) {
|
||||
var message = 'keyword schema is invalid: ' + self.errorsText(validateSchema.errors);
|
||||
if (self._opts.validateSchema == 'log') self.logger.error(message);
|
||||
else throw new Error(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var compile = rule.definition.compile
|
||||
, inline = rule.definition.inline
|
||||
, macro = rule.definition.macro;
|
||||
|
||||
var validate;
|
||||
if (compile) {
|
||||
validate = compile.call(self, schema, parentSchema, it);
|
||||
} else if (macro) {
|
||||
validate = macro.call(self, schema, parentSchema, it);
|
||||
if (opts.validateSchema !== false) self.validateSchema(validate, true);
|
||||
} else if (inline) {
|
||||
validate = inline.call(self, it, rule.keyword, schema, parentSchema);
|
||||
} else {
|
||||
validate = rule.definition.validate;
|
||||
if (!validate) return;
|
||||
}
|
||||
|
||||
if (validate === undefined)
|
||||
throw new Error('custom keyword "' + rule.keyword + '"failed to compile');
|
||||
|
||||
var index = customRules.length;
|
||||
customRules[index] = validate;
|
||||
|
||||
return {
|
||||
code: 'customRule' + index,
|
||||
validate: validate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the schema is currently compiled
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema to compile
|
||||
* @param {Object} root root object
|
||||
* @param {String} baseId base schema ID
|
||||
* @return {Object} object with properties "index" (compilation index) and "compiling" (boolean)
|
||||
*/
|
||||
function checkCompiling(schema, root, baseId) {
|
||||
/* jshint validthis: true */
|
||||
var index = compIndex.call(this, schema, root, baseId);
|
||||
if (index >= 0) return { index: index, compiling: true };
|
||||
index = this._compilations.length;
|
||||
this._compilations[index] = {
|
||||
schema: schema,
|
||||
root: root,
|
||||
baseId: baseId
|
||||
};
|
||||
return { index: index, compiling: false };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the schema from the currently compiled list
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema to compile
|
||||
* @param {Object} root root object
|
||||
* @param {String} baseId base schema ID
|
||||
*/
|
||||
function endCompiling(schema, root, baseId) {
|
||||
/* jshint validthis: true */
|
||||
var i = compIndex.call(this, schema, root, baseId);
|
||||
if (i >= 0) this._compilations.splice(i, 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Index of schema compilation in the currently compiled list
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema to compile
|
||||
* @param {Object} root root object
|
||||
* @param {String} baseId base schema ID
|
||||
* @return {Integer} compilation index
|
||||
*/
|
||||
function compIndex(schema, root, baseId) {
|
||||
/* jshint validthis: true */
|
||||
for (var i=0; i<this._compilations.length; i++) {
|
||||
var c = this._compilations[i];
|
||||
if (c.schema == schema && c.root == root && c.baseId == baseId) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
function patternCode(i, patterns) {
|
||||
return 'var pattern' + i + ' = new RegExp(' + util.toQuotedString(patterns[i]) + ');';
|
||||
}
|
||||
|
||||
|
||||
function defaultCode(i) {
|
||||
return 'var default' + i + ' = defaults[' + i + '];';
|
||||
}
|
||||
|
||||
|
||||
function refValCode(i, refVal) {
|
||||
return refVal[i] === undefined ? '' : 'var refVal' + i + ' = refVal[' + i + '];';
|
||||
}
|
||||
|
||||
|
||||
function customRuleCode(i) {
|
||||
return 'var customRule' + i + ' = customRules[' + i + '];';
|
||||
}
|
||||
|
||||
|
||||
function vars(arr, statement) {
|
||||
if (!arr.length) return '';
|
||||
var code = '';
|
||||
for (var i=0; i<arr.length; i++)
|
||||
code += statement(i, arr);
|
||||
return code;
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
'use strict';
|
||||
|
||||
var URI = require('uri-js')
|
||||
, equal = require('fast-deep-equal')
|
||||
, util = require('./util')
|
||||
, SchemaObject = require('./schema_obj')
|
||||
, traverse = require('json-schema-traverse');
|
||||
|
||||
module.exports = resolve;
|
||||
|
||||
resolve.normalizeId = normalizeId;
|
||||
resolve.fullPath = getFullPath;
|
||||
resolve.url = resolveUrl;
|
||||
resolve.ids = resolveIds;
|
||||
resolve.inlineRef = inlineRef;
|
||||
resolve.schema = resolveSchema;
|
||||
|
||||
/**
|
||||
* [resolve and compile the references ($ref)]
|
||||
* @this Ajv
|
||||
* @param {Function} compile reference to schema compilation funciton (localCompile)
|
||||
* @param {Object} root object with information about the root schema for the current schema
|
||||
* @param {String} ref reference to resolve
|
||||
* @return {Object|Function} schema object (if the schema can be inlined) or validation function
|
||||
*/
|
||||
function resolve(compile, root, ref) {
|
||||
/* jshint validthis: true */
|
||||
var refVal = this._refs[ref];
|
||||
if (typeof refVal == 'string') {
|
||||
if (this._refs[refVal]) refVal = this._refs[refVal];
|
||||
else return resolve.call(this, compile, root, refVal);
|
||||
}
|
||||
|
||||
refVal = refVal || this._schemas[ref];
|
||||
if (refVal instanceof SchemaObject) {
|
||||
return inlineRef(refVal.schema, this._opts.inlineRefs)
|
||||
? refVal.schema
|
||||
: refVal.validate || this._compile(refVal);
|
||||
}
|
||||
|
||||
var res = resolveSchema.call(this, root, ref);
|
||||
var schema, v, baseId;
|
||||
if (res) {
|
||||
schema = res.schema;
|
||||
root = res.root;
|
||||
baseId = res.baseId;
|
||||
}
|
||||
|
||||
if (schema instanceof SchemaObject) {
|
||||
v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId);
|
||||
} else if (schema !== undefined) {
|
||||
v = inlineRef(schema, this._opts.inlineRefs)
|
||||
? schema
|
||||
: compile.call(this, schema, root, undefined, baseId);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve schema, its root and baseId
|
||||
* @this Ajv
|
||||
* @param {Object} root root object with properties schema, refVal, refs
|
||||
* @param {String} ref reference to resolve
|
||||
* @return {Object} object with properties schema, root, baseId
|
||||
*/
|
||||
function resolveSchema(root, ref) {
|
||||
/* jshint validthis: true */
|
||||
var p = URI.parse(ref)
|
||||
, refPath = _getFullPath(p)
|
||||
, baseId = getFullPath(this._getId(root.schema));
|
||||
if (Object.keys(root.schema).length === 0 || refPath !== baseId) {
|
||||
var id = normalizeId(refPath);
|
||||
var refVal = this._refs[id];
|
||||
if (typeof refVal == 'string') {
|
||||
return resolveRecursive.call(this, root, refVal, p);
|
||||
} else if (refVal instanceof SchemaObject) {
|
||||
if (!refVal.validate) this._compile(refVal);
|
||||
root = refVal;
|
||||
} else {
|
||||
refVal = this._schemas[id];
|
||||
if (refVal instanceof SchemaObject) {
|
||||
if (!refVal.validate) this._compile(refVal);
|
||||
if (id == normalizeId(ref))
|
||||
return { schema: refVal, root: root, baseId: baseId };
|
||||
root = refVal;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!root.schema) return;
|
||||
baseId = getFullPath(this._getId(root.schema));
|
||||
}
|
||||
return getJsonPointer.call(this, p, baseId, root.schema, root);
|
||||
}
|
||||
|
||||
|
||||
/* @this Ajv */
|
||||
function resolveRecursive(root, ref, parsedRef) {
|
||||
/* jshint validthis: true */
|
||||
var res = resolveSchema.call(this, root, ref);
|
||||
if (res) {
|
||||
var schema = res.schema;
|
||||
var baseId = res.baseId;
|
||||
root = res.root;
|
||||
var id = this._getId(schema);
|
||||
if (id) baseId = resolveUrl(baseId, id);
|
||||
return getJsonPointer.call(this, parsedRef, baseId, schema, root);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var PREVENT_SCOPE_CHANGE = util.toHash(['properties', 'patternProperties', 'enum', 'dependencies', 'definitions']);
|
||||
/* @this Ajv */
|
||||
function getJsonPointer(parsedRef, baseId, schema, root) {
|
||||
/* jshint validthis: true */
|
||||
parsedRef.fragment = parsedRef.fragment || '';
|
||||
if (parsedRef.fragment.slice(0,1) != '/') return;
|
||||
var parts = parsedRef.fragment.split('/');
|
||||
|
||||
for (var i = 1; i < parts.length; i++) {
|
||||
var part = parts[i];
|
||||
if (part) {
|
||||
part = util.unescapeFragment(part);
|
||||
schema = schema[part];
|
||||
if (schema === undefined) break;
|
||||
var id;
|
||||
if (!PREVENT_SCOPE_CHANGE[part]) {
|
||||
id = this._getId(schema);
|
||||
if (id) baseId = resolveUrl(baseId, id);
|
||||
if (schema.$ref) {
|
||||
var $ref = resolveUrl(baseId, schema.$ref);
|
||||
var res = resolveSchema.call(this, root, $ref);
|
||||
if (res) {
|
||||
schema = res.schema;
|
||||
root = res.root;
|
||||
baseId = res.baseId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (schema !== undefined && schema !== root.schema)
|
||||
return { schema: schema, root: root, baseId: baseId };
|
||||
}
|
||||
|
||||
|
||||
var SIMPLE_INLINED = util.toHash([
|
||||
'type', 'format', 'pattern',
|
||||
'maxLength', 'minLength',
|
||||
'maxProperties', 'minProperties',
|
||||
'maxItems', 'minItems',
|
||||
'maximum', 'minimum',
|
||||
'uniqueItems', 'multipleOf',
|
||||
'required', 'enum'
|
||||
]);
|
||||
function inlineRef(schema, limit) {
|
||||
if (limit === false) return false;
|
||||
if (limit === undefined || limit === true) return checkNoRef(schema);
|
||||
else if (limit) return countKeys(schema) <= limit;
|
||||
}
|
||||
|
||||
|
||||
function checkNoRef(schema) {
|
||||
var item;
|
||||
if (Array.isArray(schema)) {
|
||||
for (var i=0; i<schema.length; i++) {
|
||||
item = schema[i];
|
||||
if (typeof item == 'object' && !checkNoRef(item)) return false;
|
||||
}
|
||||
} else {
|
||||
for (var key in schema) {
|
||||
if (key == '$ref') return false;
|
||||
item = schema[key];
|
||||
if (typeof item == 'object' && !checkNoRef(item)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function countKeys(schema) {
|
||||
var count = 0, item;
|
||||
if (Array.isArray(schema)) {
|
||||
for (var i=0; i<schema.length; i++) {
|
||||
item = schema[i];
|
||||
if (typeof item == 'object') count += countKeys(item);
|
||||
if (count == Infinity) return Infinity;
|
||||
}
|
||||
} else {
|
||||
for (var key in schema) {
|
||||
if (key == '$ref') return Infinity;
|
||||
if (SIMPLE_INLINED[key]) {
|
||||
count++;
|
||||
} else {
|
||||
item = schema[key];
|
||||
if (typeof item == 'object') count += countKeys(item) + 1;
|
||||
if (count == Infinity) return Infinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
function getFullPath(id, normalize) {
|
||||
if (normalize !== false) id = normalizeId(id);
|
||||
var p = URI.parse(id);
|
||||
return _getFullPath(p);
|
||||
}
|
||||
|
||||
|
||||
function _getFullPath(p) {
|
||||
return URI.serialize(p).split('#')[0] + '#';
|
||||
}
|
||||
|
||||
|
||||
var TRAILING_SLASH_HASH = /#\/?$/;
|
||||
function normalizeId(id) {
|
||||
return id ? id.replace(TRAILING_SLASH_HASH, '') : '';
|
||||
}
|
||||
|
||||
|
||||
function resolveUrl(baseId, id) {
|
||||
id = normalizeId(id);
|
||||
return URI.resolve(baseId, id);
|
||||
}
|
||||
|
||||
|
||||
/* @this Ajv */
|
||||
function resolveIds(schema) {
|
||||
var schemaId = normalizeId(this._getId(schema));
|
||||
var baseIds = {'': schemaId};
|
||||
var fullPaths = {'': getFullPath(schemaId, false)};
|
||||
var localRefs = {};
|
||||
var self = this;
|
||||
|
||||
traverse(schema, {allKeys: true}, function(sch, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
|
||||
if (jsonPtr === '') return;
|
||||
var id = self._getId(sch);
|
||||
var baseId = baseIds[parentJsonPtr];
|
||||
var fullPath = fullPaths[parentJsonPtr] + '/' + parentKeyword;
|
||||
if (keyIndex !== undefined)
|
||||
fullPath += '/' + (typeof keyIndex == 'number' ? keyIndex : util.escapeFragment(keyIndex));
|
||||
|
||||
if (typeof id == 'string') {
|
||||
id = baseId = normalizeId(baseId ? URI.resolve(baseId, id) : id);
|
||||
|
||||
var refVal = self._refs[id];
|
||||
if (typeof refVal == 'string') refVal = self._refs[refVal];
|
||||
if (refVal && refVal.schema) {
|
||||
if (!equal(sch, refVal.schema))
|
||||
throw new Error('id "' + id + '" resolves to more than one schema');
|
||||
} else if (id != normalizeId(fullPath)) {
|
||||
if (id[0] == '#') {
|
||||
if (localRefs[id] && !equal(sch, localRefs[id]))
|
||||
throw new Error('id "' + id + '" resolves to more than one schema');
|
||||
localRefs[id] = sch;
|
||||
} else {
|
||||
self._refs[id] = fullPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
baseIds[jsonPtr] = baseId;
|
||||
fullPaths[jsonPtr] = fullPath;
|
||||
});
|
||||
|
||||
return localRefs;
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
|
||||
var ruleModules = require('../dotjs')
|
||||
, toHash = require('./util').toHash;
|
||||
|
||||
module.exports = function rules() {
|
||||
var RULES = [
|
||||
{ type: 'number',
|
||||
rules: [ { 'maximum': ['exclusiveMaximum'] },
|
||||
{ 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format'] },
|
||||
{ type: 'string',
|
||||
rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] },
|
||||
{ type: 'array',
|
||||
rules: [ 'maxItems', 'minItems', 'items', 'contains', 'uniqueItems' ] },
|
||||
{ type: 'object',
|
||||
rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames',
|
||||
{ 'properties': ['additionalProperties', 'patternProperties'] } ] },
|
||||
{ rules: [ '$ref', 'const', 'enum', 'not', 'anyOf', 'oneOf', 'allOf', 'if' ] }
|
||||
];
|
||||
|
||||
var ALL = [ 'type', '$comment' ];
|
||||
var KEYWORDS = [
|
||||
'$schema', '$id', 'id', '$data', '$async', 'title',
|
||||
'description', 'default', 'definitions',
|
||||
'examples', 'readOnly', 'writeOnly',
|
||||
'contentMediaType', 'contentEncoding',
|
||||
'additionalItems', 'then', 'else'
|
||||
];
|
||||
var TYPES = [ 'number', 'integer', 'string', 'array', 'object', 'boolean', 'null' ];
|
||||
RULES.all = toHash(ALL);
|
||||
RULES.types = toHash(TYPES);
|
||||
|
||||
RULES.forEach(function (group) {
|
||||
group.rules = group.rules.map(function (keyword) {
|
||||
var implKeywords;
|
||||
if (typeof keyword == 'object') {
|
||||
var key = Object.keys(keyword)[0];
|
||||
implKeywords = keyword[key];
|
||||
keyword = key;
|
||||
implKeywords.forEach(function (k) {
|
||||
ALL.push(k);
|
||||
RULES.all[k] = true;
|
||||
});
|
||||
}
|
||||
ALL.push(keyword);
|
||||
var rule = RULES.all[keyword] = {
|
||||
keyword: keyword,
|
||||
code: ruleModules[keyword],
|
||||
implements: implKeywords
|
||||
};
|
||||
return rule;
|
||||
});
|
||||
|
||||
RULES.all.$comment = {
|
||||
keyword: '$comment',
|
||||
code: ruleModules.$comment
|
||||
};
|
||||
|
||||
if (group.type) RULES.types[group.type] = group;
|
||||
});
|
||||
|
||||
RULES.keywords = toHash(ALL.concat(KEYWORDS));
|
||||
RULES.custom = {};
|
||||
|
||||
return RULES;
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('./util');
|
||||
|
||||
module.exports = SchemaObject;
|
||||
|
||||
function SchemaObject(obj) {
|
||||
util.copy(obj, this);
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
// https://mathiasbynens.be/notes/javascript-encoding
|
||||
// https://github.com/bestiejs/punycode.js - punycode.ucs2.decode
|
||||
module.exports = function ucs2length(str) {
|
||||
var length = 0
|
||||
, len = str.length
|
||||
, pos = 0
|
||||
, value;
|
||||
while (pos < len) {
|
||||
length++;
|
||||
value = str.charCodeAt(pos++);
|
||||
if (value >= 0xD800 && value <= 0xDBFF && pos < len) {
|
||||
// high surrogate, and there is a next character
|
||||
value = str.charCodeAt(pos);
|
||||
if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate
|
||||
}
|
||||
}
|
||||
return length;
|
||||
};
|
@ -0,0 +1,274 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
module.exports = {
|
||||
copy: copy,
|
||||
checkDataType: checkDataType,
|
||||
checkDataTypes: checkDataTypes,
|
||||
coerceToTypes: coerceToTypes,
|
||||
toHash: toHash,
|
||||
getProperty: getProperty,
|
||||
escapeQuotes: escapeQuotes,
|
||||
equal: require('fast-deep-equal'),
|
||||
ucs2length: require('./ucs2length'),
|
||||
varOccurences: varOccurences,
|
||||
varReplace: varReplace,
|
||||
cleanUpCode: cleanUpCode,
|
||||
finalCleanUpCode: finalCleanUpCode,
|
||||
schemaHasRules: schemaHasRules,
|
||||
schemaHasRulesExcept: schemaHasRulesExcept,
|
||||
schemaUnknownRules: schemaUnknownRules,
|
||||
toQuotedString: toQuotedString,
|
||||
getPathExpr: getPathExpr,
|
||||
getPath: getPath,
|
||||
getData: getData,
|
||||
unescapeFragment: unescapeFragment,
|
||||
unescapeJsonPointer: unescapeJsonPointer,
|
||||
escapeFragment: escapeFragment,
|
||||
escapeJsonPointer: escapeJsonPointer
|
||||
};
|
||||
|
||||
|
||||
function copy(o, to) {
|
||||
to = to || {};
|
||||
for (var key in o) to[key] = o[key];
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
function checkDataType(dataType, data, negate) {
|
||||
var EQUAL = negate ? ' !== ' : ' === '
|
||||
, AND = negate ? ' || ' : ' && '
|
||||
, OK = negate ? '!' : ''
|
||||
, NOT = negate ? '' : '!';
|
||||
switch (dataType) {
|
||||
case 'null': return data + EQUAL + 'null';
|
||||
case 'array': return OK + 'Array.isArray(' + data + ')';
|
||||
case 'object': return '(' + OK + data + AND +
|
||||
'typeof ' + data + EQUAL + '"object"' + AND +
|
||||
NOT + 'Array.isArray(' + data + '))';
|
||||
case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND +
|
||||
NOT + '(' + data + ' % 1)' +
|
||||
AND + data + EQUAL + data + ')';
|
||||
default: return 'typeof ' + data + EQUAL + '"' + dataType + '"';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkDataTypes(dataTypes, data) {
|
||||
switch (dataTypes.length) {
|
||||
case 1: return checkDataType(dataTypes[0], data, true);
|
||||
default:
|
||||
var code = '';
|
||||
var types = toHash(dataTypes);
|
||||
if (types.array && types.object) {
|
||||
code = types.null ? '(': '(!' + data + ' || ';
|
||||
code += 'typeof ' + data + ' !== "object")';
|
||||
delete types.null;
|
||||
delete types.array;
|
||||
delete types.object;
|
||||
}
|
||||
if (types.number) delete types.integer;
|
||||
for (var t in types)
|
||||
code += (code ? ' && ' : '' ) + checkDataType(t, data, true);
|
||||
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]);
|
||||
function coerceToTypes(optionCoerceTypes, dataTypes) {
|
||||
if (Array.isArray(dataTypes)) {
|
||||
var types = [];
|
||||
for (var i=0; i<dataTypes.length; i++) {
|
||||
var t = dataTypes[i];
|
||||
if (COERCE_TO_TYPES[t]) types[types.length] = t;
|
||||
else if (optionCoerceTypes === 'array' && t === 'array') types[types.length] = t;
|
||||
}
|
||||
if (types.length) return types;
|
||||
} else if (COERCE_TO_TYPES[dataTypes]) {
|
||||
return [dataTypes];
|
||||
} else if (optionCoerceTypes === 'array' && dataTypes === 'array') {
|
||||
return ['array'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function toHash(arr) {
|
||||
var hash = {};
|
||||
for (var i=0; i<arr.length; i++) hash[arr[i]] = true;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
|
||||
var SINGLE_QUOTE = /'|\\/g;
|
||||
function getProperty(key) {
|
||||
return typeof key == 'number'
|
||||
? '[' + key + ']'
|
||||
: IDENTIFIER.test(key)
|
||||
? '.' + key
|
||||
: "['" + escapeQuotes(key) + "']";
|
||||
}
|
||||
|
||||
|
||||
function escapeQuotes(str) {
|
||||
return str.replace(SINGLE_QUOTE, '\\$&')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/\f/g, '\\f')
|
||||
.replace(/\t/g, '\\t');
|
||||
}
|
||||
|
||||
|
||||
function varOccurences(str, dataVar) {
|
||||
dataVar += '[^0-9]';
|
||||
var matches = str.match(new RegExp(dataVar, 'g'));
|
||||
return matches ? matches.length : 0;
|
||||
}
|
||||
|
||||
|
||||
function varReplace(str, dataVar, expr) {
|
||||
dataVar += '([^0-9])';
|
||||
expr = expr.replace(/\$/g, '$$$$');
|
||||
return str.replace(new RegExp(dataVar, 'g'), expr + '$1');
|
||||
}
|
||||
|
||||
|
||||
var EMPTY_ELSE = /else\s*{\s*}/g
|
||||
, EMPTY_IF_NO_ELSE = /if\s*\([^)]+\)\s*\{\s*\}(?!\s*else)/g
|
||||
, EMPTY_IF_WITH_ELSE = /if\s*\(([^)]+)\)\s*\{\s*\}\s*else(?!\s*if)/g;
|
||||
function cleanUpCode(out) {
|
||||
return out.replace(EMPTY_ELSE, '')
|
||||
.replace(EMPTY_IF_NO_ELSE, '')
|
||||
.replace(EMPTY_IF_WITH_ELSE, 'if (!($1))');
|
||||
}
|
||||
|
||||
|
||||
var ERRORS_REGEXP = /[^v.]errors/g
|
||||
, REMOVE_ERRORS = /var errors = 0;|var vErrors = null;|validate.errors = vErrors;/g
|
||||
, REMOVE_ERRORS_ASYNC = /var errors = 0;|var vErrors = null;/g
|
||||
, RETURN_VALID = 'return errors === 0;'
|
||||
, RETURN_TRUE = 'validate.errors = null; return true;'
|
||||
, RETURN_ASYNC = /if \(errors === 0\) return data;\s*else throw new ValidationError\(vErrors\);/
|
||||
, RETURN_DATA_ASYNC = 'return data;'
|
||||
, ROOTDATA_REGEXP = /[^A-Za-z_$]rootData[^A-Za-z0-9_$]/g
|
||||
, REMOVE_ROOTDATA = /if \(rootData === undefined\) rootData = data;/;
|
||||
|
||||
function finalCleanUpCode(out, async) {
|
||||
var matches = out.match(ERRORS_REGEXP);
|
||||
if (matches && matches.length == 2) {
|
||||
out = async
|
||||
? out.replace(REMOVE_ERRORS_ASYNC, '')
|
||||
.replace(RETURN_ASYNC, RETURN_DATA_ASYNC)
|
||||
: out.replace(REMOVE_ERRORS, '')
|
||||
.replace(RETURN_VALID, RETURN_TRUE);
|
||||
}
|
||||
|
||||
matches = out.match(ROOTDATA_REGEXP);
|
||||
if (!matches || matches.length !== 3) return out;
|
||||
return out.replace(REMOVE_ROOTDATA, '');
|
||||
}
|
||||
|
||||
|
||||
function schemaHasRules(schema, rules) {
|
||||
if (typeof schema == 'boolean') return !schema;
|
||||
for (var key in schema) if (rules[key]) return true;
|
||||
}
|
||||
|
||||
|
||||
function schemaHasRulesExcept(schema, rules, exceptKeyword) {
|
||||
if (typeof schema == 'boolean') return !schema && exceptKeyword != 'not';
|
||||
for (var key in schema) if (key != exceptKeyword && rules[key]) return true;
|
||||
}
|
||||
|
||||
|
||||
function schemaUnknownRules(schema, rules) {
|
||||
if (typeof schema == 'boolean') return;
|
||||
for (var key in schema) if (!rules[key]) return key;
|
||||
}
|
||||
|
||||
|
||||
function toQuotedString(str) {
|
||||
return '\'' + escapeQuotes(str) + '\'';
|
||||
}
|
||||
|
||||
|
||||
function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
|
||||
var path = jsonPointers // false by default
|
||||
? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')')
|
||||
: (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\'');
|
||||
return joinPaths(currentPath, path);
|
||||
}
|
||||
|
||||
|
||||
function getPath(currentPath, prop, jsonPointers) {
|
||||
var path = jsonPointers // false by default
|
||||
? toQuotedString('/' + escapeJsonPointer(prop))
|
||||
: toQuotedString(getProperty(prop));
|
||||
return joinPaths(currentPath, path);
|
||||
}
|
||||
|
||||
|
||||
var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
|
||||
var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
|
||||
function getData($data, lvl, paths) {
|
||||
var up, jsonPointer, data, matches;
|
||||
if ($data === '') return 'rootData';
|
||||
if ($data[0] == '/') {
|
||||
if (!JSON_POINTER.test($data)) throw new Error('Invalid JSON-pointer: ' + $data);
|
||||
jsonPointer = $data;
|
||||
data = 'rootData';
|
||||
} else {
|
||||
matches = $data.match(RELATIVE_JSON_POINTER);
|
||||
if (!matches) throw new Error('Invalid JSON-pointer: ' + $data);
|
||||
up = +matches[1];
|
||||
jsonPointer = matches[2];
|
||||
if (jsonPointer == '#') {
|
||||
if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl);
|
||||
return paths[lvl - up];
|
||||
}
|
||||
|
||||
if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl);
|
||||
data = 'data' + ((lvl - up) || '');
|
||||
if (!jsonPointer) return data;
|
||||
}
|
||||
|
||||
var expr = data;
|
||||
var segments = jsonPointer.split('/');
|
||||
for (var i=0; i<segments.length; i++) {
|
||||
var segment = segments[i];
|
||||
if (segment) {
|
||||
data += getProperty(unescapeJsonPointer(segment));
|
||||
expr += ' && ' + data;
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
function joinPaths (a, b) {
|
||||
if (a == '""') return b;
|
||||
return (a + ' + ' + b).replace(/' \+ '/g, '');
|
||||
}
|
||||
|
||||
|
||||
function unescapeFragment(str) {
|
||||
return unescapeJsonPointer(decodeURIComponent(str));
|
||||
}
|
||||
|
||||
|
||||
function escapeFragment(str) {
|
||||
return encodeURIComponent(escapeJsonPointer(str));
|
||||
}
|
||||
|
||||
|
||||
function escapeJsonPointer(str) {
|
||||
return str.replace(/~/g, '~0').replace(/\//g, '~1');
|
||||
}
|
||||
|
||||
|
||||
function unescapeJsonPointer(str) {
|
||||
return str.replace(/~1/g, '/').replace(/~0/g, '~');
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
|
||||
var KEYWORDS = [
|
||||
'multipleOf',
|
||||
'maximum',
|
||||
'exclusiveMaximum',
|
||||
'minimum',
|
||||
'exclusiveMinimum',
|
||||
'maxLength',
|
||||
'minLength',
|
||||
'pattern',
|
||||
'additionalItems',
|
||||
'maxItems',
|
||||
'minItems',
|
||||
'uniqueItems',
|
||||
'maxProperties',
|
||||
'minProperties',
|
||||
'required',
|
||||
'additionalProperties',
|
||||
'enum',
|
||||
'format',
|
||||
'const'
|
||||
];
|
||||
|
||||
module.exports = function (metaSchema, keywordsJsonPointers) {
|
||||
for (var i=0; i<keywordsJsonPointers.length; i++) {
|
||||
metaSchema = JSON.parse(JSON.stringify(metaSchema));
|
||||
var segments = keywordsJsonPointers[i].split('/');
|
||||
var keywords = metaSchema;
|
||||
var j;
|
||||
for (j=1; j<segments.length; j++)
|
||||
keywords = keywords[segments[j]];
|
||||
|
||||
for (j=0; j<KEYWORDS.length; j++) {
|
||||
var key = KEYWORDS[j];
|
||||
var schema = keywords[key];
|
||||
if (schema) {
|
||||
keywords[key] = {
|
||||
anyOf: [
|
||||
schema,
|
||||
{ $ref: 'https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/data.json#' }
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return metaSchema;
|
||||
};
|
@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
var metaSchema = require('./refs/json-schema-draft-07.json');
|
||||
|
||||
module.exports = {
|
||||
$id: 'https://github.com/epoberezkin/ajv/blob/master/lib/definition_schema.js',
|
||||
definitions: {
|
||||
simpleTypes: metaSchema.definitions.simpleTypes
|
||||
},
|
||||
type: 'object',
|
||||
dependencies: {
|
||||
schema: ['validate'],
|
||||
$data: ['validate'],
|
||||
statements: ['inline'],
|
||||
valid: {not: {required: ['macro']}}
|
||||
},
|
||||
properties: {
|
||||
type: metaSchema.properties.type,
|
||||
schema: {type: 'boolean'},
|
||||
statements: {type: 'boolean'},
|
||||
dependencies: {
|
||||
type: 'array',
|
||||
items: {type: 'string'}
|
||||
},
|
||||
metaSchema: {type: 'object'},
|
||||
modifying: {type: 'boolean'},
|
||||
valid: {type: 'boolean'},
|
||||
$data: {type: 'boolean'},
|
||||
async: {type: 'boolean'},
|
||||
errors: {
|
||||
anyOf: [
|
||||
{type: 'boolean'},
|
||||
{const: 'full'}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
@ -0,0 +1,104 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{## def.setExclusiveLimit:
|
||||
$exclusive = true;
|
||||
$errorKeyword = $exclusiveKeyword;
|
||||
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
|
||||
#}}
|
||||
|
||||
{{
|
||||
var $isMax = $keyword == 'maximum'
|
||||
, $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum'
|
||||
, $schemaExcl = it.schema[$exclusiveKeyword]
|
||||
, $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data
|
||||
, $op = $isMax ? '<' : '>'
|
||||
, $notOp = $isMax ? '>' : '<'
|
||||
, $errorKeyword = undefined;
|
||||
}}
|
||||
|
||||
{{? $isDataExcl }}
|
||||
{{
|
||||
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr)
|
||||
, $exclusive = 'exclusive' + $lvl
|
||||
, $exclType = 'exclType' + $lvl
|
||||
, $exclIsNumber = 'exclIsNumber' + $lvl
|
||||
, $opExpr = 'op' + $lvl
|
||||
, $opStr = '\' + ' + $opExpr + ' + \'';
|
||||
}}
|
||||
var schemaExcl{{=$lvl}} = {{=$schemaValueExcl}};
|
||||
{{ $schemaValueExcl = 'schemaExcl' + $lvl; }}
|
||||
|
||||
var {{=$exclusive}};
|
||||
var {{=$exclType}} = typeof {{=$schemaValueExcl}};
|
||||
if ({{=$exclType}} != 'boolean' && {{=$exclType}} != 'undefined' && {{=$exclType}} != 'number') {
|
||||
{{ var $errorKeyword = $exclusiveKeyword; }}
|
||||
{{# def.error:'_exclusiveLimit' }}
|
||||
} else if ({{# def.$dataNotType:'number' }}
|
||||
{{=$exclType}} == 'number'
|
||||
? (
|
||||
({{=$exclusive}} = {{=$schemaValue}} === undefined || {{=$schemaValueExcl}} {{=$op}}= {{=$schemaValue}})
|
||||
? {{=$data}} {{=$notOp}}= {{=$schemaValueExcl}}
|
||||
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
|
||||
)
|
||||
: (
|
||||
({{=$exclusive}} = {{=$schemaValueExcl}} === true)
|
||||
? {{=$data}} {{=$notOp}}= {{=$schemaValue}}
|
||||
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
|
||||
)
|
||||
|| {{=$data}} !== {{=$data}}) {
|
||||
var op{{=$lvl}} = {{=$exclusive}} ? '{{=$op}}' : '{{=$op}}=';
|
||||
{{
|
||||
if ($schema === undefined) {
|
||||
$errorKeyword = $exclusiveKeyword;
|
||||
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
|
||||
$schemaValue = $schemaValueExcl;
|
||||
$isData = $isDataExcl;
|
||||
}
|
||||
}}
|
||||
{{??}}
|
||||
{{
|
||||
var $exclIsNumber = typeof $schemaExcl == 'number'
|
||||
, $opStr = $op; /*used in error*/
|
||||
}}
|
||||
|
||||
{{? $exclIsNumber && $isData }}
|
||||
{{ var $opExpr = '\'' + $opStr + '\''; /*used in error*/ }}
|
||||
if ({{# def.$dataNotType:'number' }}
|
||||
( {{=$schemaValue}} === undefined
|
||||
|| {{=$schemaExcl}} {{=$op}}= {{=$schemaValue}}
|
||||
? {{=$data}} {{=$notOp}}= {{=$schemaExcl}}
|
||||
: {{=$data}} {{=$notOp}} {{=$schemaValue}} )
|
||||
|| {{=$data}} !== {{=$data}}) {
|
||||
{{??}}
|
||||
{{
|
||||
if ($exclIsNumber && $schema === undefined) {
|
||||
{{# def.setExclusiveLimit }}
|
||||
$schemaValue = $schemaExcl;
|
||||
$notOp += '=';
|
||||
} else {
|
||||
if ($exclIsNumber)
|
||||
$schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema);
|
||||
|
||||
if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) {
|
||||
{{# def.setExclusiveLimit }}
|
||||
$notOp += '=';
|
||||
} else {
|
||||
$exclusive = false;
|
||||
$opStr += '=';
|
||||
}
|
||||
}
|
||||
|
||||
var $opExpr = '\'' + $opStr + '\''; /*used in error*/
|
||||
}}
|
||||
|
||||
if ({{# def.$dataNotType:'number' }}
|
||||
{{=$data}} {{=$notOp}} {{=$schemaValue}}
|
||||
|| {{=$data}} !== {{=$data}}) {
|
||||
{{?}}
|
||||
{{?}}
|
||||
{{ $errorKeyword = $errorKeyword || $keyword; }}
|
||||
{{# def.error:'_limit' }}
|
||||
} {{? $breakOnError }} else { {{?}}
|
@ -0,0 +1,10 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{ var $op = $keyword == 'maxItems' ? '>' : '<'; }}
|
||||
if ({{# def.$dataNotType:'number' }} {{=$data}}.length {{=$op}} {{=$schemaValue}}) {
|
||||
{{ var $errorKeyword = $keyword; }}
|
||||
{{# def.error:'_limitItems' }}
|
||||
} {{? $breakOnError }} else { {{?}}
|
@ -0,0 +1,10 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{ var $op = $keyword == 'maxLength' ? '>' : '<'; }}
|
||||
if ({{# def.$dataNotType:'number' }} {{# def.strLength }} {{=$op}} {{=$schemaValue}}) {
|
||||
{{ var $errorKeyword = $keyword; }}
|
||||
{{# def.error:'_limitLength' }}
|
||||
} {{? $breakOnError }} else { {{?}}
|
@ -0,0 +1,10 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{ var $op = $keyword == 'maxProperties' ? '>' : '<'; }}
|
||||
if ({{# def.$dataNotType:'number' }} Object.keys({{=$data}}).length {{=$op}} {{=$schemaValue}}) {
|
||||
{{ var $errorKeyword = $keyword; }}
|
||||
{{# def.error:'_limitProperties' }}
|
||||
} {{? $breakOnError }} else { {{?}}
|
@ -0,0 +1,34 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.setupNextLevel }}
|
||||
|
||||
{{
|
||||
var $currentBaseId = $it.baseId
|
||||
, $allSchemasEmpty = true;
|
||||
}}
|
||||
|
||||
{{~ $schema:$sch:$i }}
|
||||
{{? {{# def.nonEmptySchema:$sch }} }}
|
||||
{{
|
||||
$allSchemasEmpty = false;
|
||||
$it.schema = $sch;
|
||||
$it.schemaPath = $schemaPath + '[' + $i + ']';
|
||||
$it.errSchemaPath = $errSchemaPath + '/' + $i;
|
||||
}}
|
||||
|
||||
{{# def.insertSubschemaCode }}
|
||||
|
||||
{{# def.ifResultValid }}
|
||||
{{?}}
|
||||
{{~}}
|
||||
|
||||
{{? $breakOnError }}
|
||||
{{? $allSchemasEmpty }}
|
||||
if (true) {
|
||||
{{??}}
|
||||
{{= $closingBraces.slice(0,-1) }}
|
||||
{{?}}
|
||||
{{?}}
|
||||
|
||||
{{# def.cleanUp }}
|
@ -0,0 +1,48 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.setupNextLevel }}
|
||||
|
||||
{{
|
||||
var $noEmptySchema = $schema.every(function($sch) {
|
||||
return {{# def.nonEmptySchema:$sch }};
|
||||
});
|
||||
}}
|
||||
{{? $noEmptySchema }}
|
||||
{{ var $currentBaseId = $it.baseId; }}
|
||||
var {{=$errs}} = errors;
|
||||
var {{=$valid}} = false;
|
||||
|
||||
{{# def.setCompositeRule }}
|
||||
|
||||
{{~ $schema:$sch:$i }}
|
||||
{{
|
||||
$it.schema = $sch;
|
||||
$it.schemaPath = $schemaPath + '[' + $i + ']';
|
||||
$it.errSchemaPath = $errSchemaPath + '/' + $i;
|
||||
}}
|
||||
|
||||
{{# def.insertSubschemaCode }}
|
||||
|
||||
{{=$valid}} = {{=$valid}} || {{=$nextValid}};
|
||||
|
||||
if (!{{=$valid}}) {
|
||||
{{ $closingBraces += '}'; }}
|
||||
{{~}}
|
||||
|
||||
{{# def.resetCompositeRule }}
|
||||
|
||||
{{= $closingBraces }}
|
||||
|
||||
if (!{{=$valid}}) {
|
||||
{{# def.extraError:'anyOf' }}
|
||||
} else {
|
||||
{{# def.resetErrors }}
|
||||
{{? it.opts.allErrors }} } {{?}}
|
||||
|
||||
{{# def.cleanUp }}
|
||||
{{??}}
|
||||
{{? $breakOnError }}
|
||||
if (true) {
|
||||
{{?}}
|
||||
{{?}}
|
@ -0,0 +1,61 @@
|
||||
{{## def.coerceType:
|
||||
{{
|
||||
var $dataType = 'dataType' + $lvl
|
||||
, $coerced = 'coerced' + $lvl;
|
||||
}}
|
||||
var {{=$dataType}} = typeof {{=$data}};
|
||||
{{? it.opts.coerceTypes == 'array'}}
|
||||
if ({{=$dataType}} == 'object' && Array.isArray({{=$data}})) {{=$dataType}} = 'array';
|
||||
{{?}}
|
||||
|
||||
var {{=$coerced}} = undefined;
|
||||
|
||||
{{ var $bracesCoercion = ''; }}
|
||||
{{~ $coerceToTypes:$type:$i }}
|
||||
{{? $i }}
|
||||
if ({{=$coerced}} === undefined) {
|
||||
{{ $bracesCoercion += '}'; }}
|
||||
{{?}}
|
||||
|
||||
{{? it.opts.coerceTypes == 'array' && $type != 'array' }}
|
||||
if ({{=$dataType}} == 'array' && {{=$data}}.length == 1) {
|
||||
{{=$coerced}} = {{=$data}} = {{=$data}}[0];
|
||||
{{=$dataType}} = typeof {{=$data}};
|
||||
/*if ({{=$dataType}} == 'object' && Array.isArray({{=$data}})) {{=$dataType}} = 'array';*/
|
||||
}
|
||||
{{?}}
|
||||
|
||||
{{? $type == 'string' }}
|
||||
if ({{=$dataType}} == 'number' || {{=$dataType}} == 'boolean')
|
||||
{{=$coerced}} = '' + {{=$data}};
|
||||
else if ({{=$data}} === null) {{=$coerced}} = '';
|
||||
{{?? $type == 'number' || $type == 'integer' }}
|
||||
if ({{=$dataType}} == 'boolean' || {{=$data}} === null
|
||||
|| ({{=$dataType}} == 'string' && {{=$data}} && {{=$data}} == +{{=$data}}
|
||||
{{? $type == 'integer' }} && !({{=$data}} % 1){{?}}))
|
||||
{{=$coerced}} = +{{=$data}};
|
||||
{{?? $type == 'boolean' }}
|
||||
if ({{=$data}} === 'false' || {{=$data}} === 0 || {{=$data}} === null)
|
||||
{{=$coerced}} = false;
|
||||
else if ({{=$data}} === 'true' || {{=$data}} === 1)
|
||||
{{=$coerced}} = true;
|
||||
{{?? $type == 'null' }}
|
||||
if ({{=$data}} === '' || {{=$data}} === 0 || {{=$data}} === false)
|
||||
{{=$coerced}} = null;
|
||||
{{?? it.opts.coerceTypes == 'array' && $type == 'array' }}
|
||||
if ({{=$dataType}} == 'string' || {{=$dataType}} == 'number' || {{=$dataType}} == 'boolean' || {{=$data}} == null)
|
||||
{{=$coerced}} = [{{=$data}}];
|
||||
{{?}}
|
||||
{{~}}
|
||||
|
||||
{{= $bracesCoercion }}
|
||||
|
||||
if ({{=$coerced}} === undefined) {
|
||||
{{# def.error:'type' }}
|
||||
} else {
|
||||
{{# def.setParentData }}
|
||||
{{=$data}} = {{=$coerced}};
|
||||
{{? !$dataLvl }}if ({{=$parentData}} !== undefined){{?}}
|
||||
{{=$parentData}}[{{=$parentDataProperty}}] = {{=$coerced}};
|
||||
}
|
||||
#}}
|
@ -0,0 +1,9 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.setupKeyword }}
|
||||
|
||||
{{ var $comment = it.util.toQuotedString($schema); }}
|
||||
{{? it.opts.$comment === true }}
|
||||
console.log({{=$comment}});
|
||||
{{?? typeof it.opts.$comment == 'function' }}
|
||||
self._opts.$comment({{=$comment}}, {{=it.util.toQuotedString($errSchemaPath)}}, validate.root.schema);
|
||||
{{?}}
|
@ -0,0 +1,11 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{? !$isData }}
|
||||
var schema{{=$lvl}} = validate.schema{{=$schemaPath}};
|
||||
{{?}}
|
||||
var {{=$valid}} = equal({{=$data}}, schema{{=$lvl}});
|
||||
{{# def.checkError:'const' }}
|
||||
{{? $breakOnError }} else { {{?}}
|
@ -0,0 +1,57 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.setupNextLevel }}
|
||||
|
||||
|
||||
{{
|
||||
var $idx = 'i' + $lvl
|
||||
, $dataNxt = $it.dataLevel = it.dataLevel + 1
|
||||
, $nextData = 'data' + $dataNxt
|
||||
, $currentBaseId = it.baseId
|
||||
, $nonEmptySchema = {{# def.nonEmptySchema:$schema }};
|
||||
}}
|
||||
|
||||
var {{=$errs}} = errors;
|
||||
var {{=$valid}};
|
||||
|
||||
{{? $nonEmptySchema }}
|
||||
{{# def.setCompositeRule }}
|
||||
|
||||
{{
|
||||
$it.schema = $schema;
|
||||
$it.schemaPath = $schemaPath;
|
||||
$it.errSchemaPath = $errSchemaPath;
|
||||
}}
|
||||
|
||||
var {{=$nextValid}} = false;
|
||||
|
||||
for (var {{=$idx}} = 0; {{=$idx}} < {{=$data}}.length; {{=$idx}}++) {
|
||||
{{
|
||||
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true);
|
||||
var $passData = $data + '[' + $idx + ']';
|
||||
$it.dataPathArr[$dataNxt] = $idx;
|
||||
}}
|
||||
|
||||
{{# def.generateSubschemaCode }}
|
||||
{{# def.optimizeValidate }}
|
||||
|
||||
if ({{=$nextValid}}) break;
|
||||
}
|
||||
|
||||
{{# def.resetCompositeRule }}
|
||||
{{= $closingBraces }}
|
||||
|
||||
if (!{{=$nextValid}}) {
|
||||
{{??}}
|
||||
if ({{=$data}}.length == 0) {
|
||||
{{?}}
|
||||
|
||||
{{# def.error:'contains' }}
|
||||
} else {
|
||||
{{? $nonEmptySchema }}
|
||||
{{# def.resetErrors }}
|
||||
{{?}}
|
||||
{{? it.opts.allErrors }} } {{?}}
|
||||
|
||||
{{# def.cleanUp }}
|
@ -0,0 +1,191 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{
|
||||
var $rule = this
|
||||
, $definition = 'definition' + $lvl
|
||||
, $rDef = $rule.definition
|
||||
, $closingBraces = '';
|
||||
var $validate = $rDef.validate;
|
||||
var $compile, $inline, $macro, $ruleValidate, $validateCode;
|
||||
}}
|
||||
|
||||
{{? $isData && $rDef.$data }}
|
||||
{{
|
||||
$validateCode = 'keywordValidate' + $lvl;
|
||||
var $validateSchema = $rDef.validateSchema;
|
||||
}}
|
||||
var {{=$definition}} = RULES.custom['{{=$keyword}}'].definition;
|
||||
var {{=$validateCode}} = {{=$definition}}.validate;
|
||||
{{??}}
|
||||
{{
|
||||
$ruleValidate = it.useCustomRule($rule, $schema, it.schema, it);
|
||||
if (!$ruleValidate) return;
|
||||
$schemaValue = 'validate.schema' + $schemaPath;
|
||||
$validateCode = $ruleValidate.code;
|
||||
$compile = $rDef.compile;
|
||||
$inline = $rDef.inline;
|
||||
$macro = $rDef.macro;
|
||||
}}
|
||||
{{?}}
|
||||
|
||||
{{
|
||||
var $ruleErrs = $validateCode + '.errors'
|
||||
, $i = 'i' + $lvl
|
||||
, $ruleErr = 'ruleErr' + $lvl
|
||||
, $asyncKeyword = $rDef.async;
|
||||
|
||||
if ($asyncKeyword && !it.async)
|
||||
throw new Error('async keyword in sync schema');
|
||||
}}
|
||||
|
||||
|
||||
{{? !($inline || $macro) }}{{=$ruleErrs}} = null;{{?}}
|
||||
var {{=$errs}} = errors;
|
||||
var {{=$valid}};
|
||||
|
||||
{{## def.callRuleValidate:
|
||||
{{=$validateCode}}.call(
|
||||
{{? it.opts.passContext }}this{{??}}self{{?}}
|
||||
{{? $compile || $rDef.schema === false }}
|
||||
, {{=$data}}
|
||||
{{??}}
|
||||
, {{=$schemaValue}}
|
||||
, {{=$data}}
|
||||
, validate.schema{{=it.schemaPath}}
|
||||
{{?}}
|
||||
, {{# def.dataPath }}
|
||||
{{# def.passParentData }}
|
||||
, rootData
|
||||
)
|
||||
#}}
|
||||
|
||||
{{## def.extendErrors:_inline:
|
||||
for (var {{=$i}}={{=$errs}}; {{=$i}}<errors; {{=$i}}++) {
|
||||
var {{=$ruleErr}} = vErrors[{{=$i}}];
|
||||
if ({{=$ruleErr}}.dataPath === undefined)
|
||||
{{=$ruleErr}}.dataPath = (dataPath || '') + {{= it.errorPath }};
|
||||
{{# _inline ? 'if (\{\{=$ruleErr\}\}.schemaPath === undefined) {' : '' }}
|
||||
{{=$ruleErr}}.schemaPath = "{{=$errSchemaPath}}";
|
||||
{{# _inline ? '}' : '' }}
|
||||
{{? it.opts.verbose }}
|
||||
{{=$ruleErr}}.schema = {{=$schemaValue}};
|
||||
{{=$ruleErr}}.data = {{=$data}};
|
||||
{{?}}
|
||||
}
|
||||
#}}
|
||||
|
||||
|
||||
{{? $isData && $rDef.$data }}
|
||||
{{ $closingBraces += '}'; }}
|
||||
if ({{=$schemaValue}} === undefined) {
|
||||
{{=$valid}} = true;
|
||||
} else {
|
||||
{{? $validateSchema }}
|
||||
{{ $closingBraces += '}'; }}
|
||||
{{=$valid}} = {{=$definition}}.validateSchema({{=$schemaValue}});
|
||||
if ({{=$valid}}) {
|
||||
{{?}}
|
||||
{{?}}
|
||||
|
||||
{{? $inline }}
|
||||
{{? $rDef.statements }}
|
||||
{{= $ruleValidate.validate }}
|
||||
{{??}}
|
||||
{{=$valid}} = {{= $ruleValidate.validate }};
|
||||
{{?}}
|
||||
{{?? $macro }}
|
||||
{{# def.setupNextLevel }}
|
||||
{{
|
||||
$it.schema = $ruleValidate.validate;
|
||||
$it.schemaPath = '';
|
||||
}}
|
||||
{{# def.setCompositeRule }}
|
||||
{{ var $code = it.validate($it).replace(/validate\.schema/g, $validateCode); }}
|
||||
{{# def.resetCompositeRule }}
|
||||
{{= $code }}
|
||||
{{??}}
|
||||
{{# def.beginDefOut}}
|
||||
{{# def.callRuleValidate }}
|
||||
{{# def.storeDefOut:def_callRuleValidate }}
|
||||
|
||||
{{? $rDef.errors === false }}
|
||||
{{=$valid}} = {{? $asyncKeyword }}await {{?}}{{= def_callRuleValidate }};
|
||||
{{??}}
|
||||
{{? $asyncKeyword }}
|
||||
{{ $ruleErrs = 'customErrors' + $lvl; }}
|
||||
var {{=$ruleErrs}} = null;
|
||||
try {
|
||||
{{=$valid}} = await {{= def_callRuleValidate }};
|
||||
} catch (e) {
|
||||
{{=$valid}} = false;
|
||||
if (e instanceof ValidationError) {{=$ruleErrs}} = e.errors;
|
||||
else throw e;
|
||||
}
|
||||
{{??}}
|
||||
{{=$ruleErrs}} = null;
|
||||
{{=$valid}} = {{= def_callRuleValidate }};
|
||||
{{?}}
|
||||
{{?}}
|
||||
{{?}}
|
||||
|
||||
{{? $rDef.modifying }}
|
||||
if ({{=$parentData}}) {{=$data}} = {{=$parentData}}[{{=$parentDataProperty}}];
|
||||
{{?}}
|
||||
|
||||
{{= $closingBraces }}
|
||||
|
||||
{{## def.notValidationResult:
|
||||
{{? $rDef.valid === undefined }}
|
||||
!{{? $macro }}{{=$nextValid}}{{??}}{{=$valid}}{{?}}
|
||||
{{??}}
|
||||
{{= !$rDef.valid }}
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
{{? $rDef.valid }}
|
||||
{{? $breakOnError }} if (true) { {{?}}
|
||||
{{??}}
|
||||
if ({{# def.notValidationResult }}) {
|
||||
{{ $errorKeyword = $rule.keyword; }}
|
||||
{{# def.beginDefOut}}
|
||||
{{# def.error:'custom' }}
|
||||
{{# def.storeDefOut:def_customError }}
|
||||
|
||||
{{? $inline }}
|
||||
{{? $rDef.errors }}
|
||||
{{? $rDef.errors != 'full' }}
|
||||
{{# def.extendErrors:true }}
|
||||
{{?}}
|
||||
{{??}}
|
||||
{{? $rDef.errors === false}}
|
||||
{{= def_customError }}
|
||||
{{??}}
|
||||
if ({{=$errs}} == errors) {
|
||||
{{= def_customError }}
|
||||
} else {
|
||||
{{# def.extendErrors:true }}
|
||||
}
|
||||
{{?}}
|
||||
{{?}}
|
||||
{{?? $macro }}
|
||||
{{# def.extraError:'custom' }}
|
||||
{{??}}
|
||||
{{? $rDef.errors === false}}
|
||||
{{= def_customError }}
|
||||
{{??}}
|
||||
if (Array.isArray({{=$ruleErrs}})) {
|
||||
if (vErrors === null) vErrors = {{=$ruleErrs}};
|
||||
else vErrors = vErrors.concat({{=$ruleErrs}});
|
||||
errors = vErrors.length;
|
||||
{{# def.extendErrors:false }}
|
||||
} else {
|
||||
{{= def_customError }}
|
||||
}
|
||||
{{?}}
|
||||
{{?}}
|
||||
|
||||
} {{? $breakOnError }} else { {{?}}
|
||||
{{?}}
|
@ -0,0 +1,47 @@
|
||||
{{## def.assignDefault:
|
||||
{{? it.compositeRule }}
|
||||
{{
|
||||
if (it.opts.strictDefaults) {
|
||||
var $defaultMsg = 'default is ignored for: ' + $passData;
|
||||
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg);
|
||||
else throw new Error($defaultMsg);
|
||||
}
|
||||
}}
|
||||
{{??}}
|
||||
if ({{=$passData}} === undefined
|
||||
{{? it.opts.useDefaults == 'empty' }}
|
||||
|| {{=$passData}} === null
|
||||
|| {{=$passData}} === ''
|
||||
{{?}}
|
||||
)
|
||||
{{=$passData}} = {{? it.opts.useDefaults == 'shared' }}
|
||||
{{= it.useDefault($sch.default) }}
|
||||
{{??}}
|
||||
{{= JSON.stringify($sch.default) }}
|
||||
{{?}};
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.defaultProperties:
|
||||
{{
|
||||
var $schema = it.schema.properties
|
||||
, $schemaKeys = Object.keys($schema); }}
|
||||
{{~ $schemaKeys:$propertyKey }}
|
||||
{{ var $sch = $schema[$propertyKey]; }}
|
||||
{{? $sch.default !== undefined }}
|
||||
{{ var $passData = $data + it.util.getProperty($propertyKey); }}
|
||||
{{# def.assignDefault }}
|
||||
{{?}}
|
||||
{{~}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.defaultItems:
|
||||
{{~ it.schema.items:$sch:$i }}
|
||||
{{? $sch.default !== undefined }}
|
||||
{{ var $passData = $data + '[' + $i + ']'; }}
|
||||
{{# def.assignDefault }}
|
||||
{{?}}
|
||||
{{~}}
|
||||
#}}
|
@ -0,0 +1,201 @@
|
||||
{{## def.setupKeyword:
|
||||
{{
|
||||
var $lvl = it.level;
|
||||
var $dataLvl = it.dataLevel;
|
||||
var $schema = it.schema[$keyword];
|
||||
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
|
||||
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
|
||||
var $breakOnError = !it.opts.allErrors;
|
||||
var $errorKeyword;
|
||||
|
||||
var $data = 'data' + ($dataLvl || '');
|
||||
var $valid = 'valid' + $lvl;
|
||||
var $errs = 'errs__' + $lvl;
|
||||
}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.setCompositeRule:
|
||||
{{
|
||||
var $wasComposite = it.compositeRule;
|
||||
it.compositeRule = $it.compositeRule = true;
|
||||
}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.resetCompositeRule:
|
||||
{{ it.compositeRule = $it.compositeRule = $wasComposite; }}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.setupNextLevel:
|
||||
{{
|
||||
var $it = it.util.copy(it);
|
||||
var $closingBraces = '';
|
||||
$it.level++;
|
||||
var $nextValid = 'valid' + $it.level;
|
||||
}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.ifValid:
|
||||
{{? $breakOnError }}
|
||||
if ({{=$valid}}) {
|
||||
{{ $closingBraces += '}'; }}
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.ifResultValid:
|
||||
{{? $breakOnError }}
|
||||
if ({{=$nextValid}}) {
|
||||
{{ $closingBraces += '}'; }}
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.elseIfValid:
|
||||
{{? $breakOnError }}
|
||||
{{ $closingBraces += '}'; }}
|
||||
else {
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.nonEmptySchema:_schema:
|
||||
(it.opts.strictKeywords
|
||||
? typeof _schema == 'object' && Object.keys(_schema).length > 0
|
||||
: it.util.schemaHasRules(_schema, it.RULES.all))
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.strLength:
|
||||
{{? it.opts.unicode === false }}
|
||||
{{=$data}}.length
|
||||
{{??}}
|
||||
ucs2length({{=$data}})
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.willOptimize:
|
||||
it.util.varOccurences($code, $nextData) < 2
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.generateSubschemaCode:
|
||||
{{
|
||||
var $code = it.validate($it);
|
||||
$it.baseId = $currentBaseId;
|
||||
}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.insertSubschemaCode:
|
||||
{{= it.validate($it) }}
|
||||
{{ $it.baseId = $currentBaseId; }}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def._optimizeValidate:
|
||||
it.util.varReplace($code, $nextData, $passData)
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.optimizeValidate:
|
||||
{{? {{# def.willOptimize}} }}
|
||||
{{= {{# def._optimizeValidate }} }}
|
||||
{{??}}
|
||||
var {{=$nextData}} = {{=$passData}};
|
||||
{{= $code }}
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.cleanUp: {{ out = it.util.cleanUpCode(out); }} #}}
|
||||
|
||||
|
||||
{{## def.finalCleanUp: {{ out = it.util.finalCleanUpCode(out, $async); }} #}}
|
||||
|
||||
|
||||
{{## def.$data:
|
||||
{{
|
||||
var $isData = it.opts.$data && $schema && $schema.$data
|
||||
, $schemaValue;
|
||||
}}
|
||||
{{? $isData }}
|
||||
var schema{{=$lvl}} = {{= it.util.getData($schema.$data, $dataLvl, it.dataPathArr) }};
|
||||
{{ $schemaValue = 'schema' + $lvl; }}
|
||||
{{??}}
|
||||
{{ $schemaValue = $schema; }}
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.$dataNotType:_type:
|
||||
{{?$isData}} ({{=$schemaValue}} !== undefined && typeof {{=$schemaValue}} != _type) || {{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.check$dataIsArray:
|
||||
if (schema{{=$lvl}} === undefined) {{=$valid}} = true;
|
||||
else if (!Array.isArray(schema{{=$lvl}})) {{=$valid}} = false;
|
||||
else {
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.beginDefOut:
|
||||
{{
|
||||
var $$outStack = $$outStack || [];
|
||||
$$outStack.push(out);
|
||||
out = '';
|
||||
}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.storeDefOut:_variable:
|
||||
{{
|
||||
var _variable = out;
|
||||
out = $$outStack.pop();
|
||||
}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.dataPath:(dataPath || ''){{? it.errorPath != '""'}} + {{= it.errorPath }}{{?}}#}}
|
||||
|
||||
{{## def.setParentData:
|
||||
{{
|
||||
var $parentData = $dataLvl ? 'data' + (($dataLvl-1)||'') : 'parentData'
|
||||
, $parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty';
|
||||
}}
|
||||
#}}
|
||||
|
||||
{{## def.passParentData:
|
||||
{{# def.setParentData }}
|
||||
, {{= $parentData }}
|
||||
, {{= $parentDataProperty }}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.iterateProperties:
|
||||
{{? $ownProperties }}
|
||||
{{=$dataProperties}} = {{=$dataProperties}} || Object.keys({{=$data}});
|
||||
for (var {{=$idx}}=0; {{=$idx}}<{{=$dataProperties}}.length; {{=$idx}}++) {
|
||||
var {{=$key}} = {{=$dataProperties}}[{{=$idx}}];
|
||||
{{??}}
|
||||
for (var {{=$key}} in {{=$data}}) {
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.noPropertyInData:
|
||||
{{=$useData}} === undefined
|
||||
{{? $ownProperties }}
|
||||
|| !{{# def.isOwnProperty }}
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{## def.isOwnProperty:
|
||||
Object.prototype.hasOwnProperty.call({{=$data}}, '{{=it.util.escapeQuotes($propertyKey)}}')
|
||||
#}}
|
@ -0,0 +1,80 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.missing }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.setupNextLevel }}
|
||||
|
||||
|
||||
{{## def.propertyInData:
|
||||
{{=$data}}{{= it.util.getProperty($property) }} !== undefined
|
||||
{{? $ownProperties }}
|
||||
&& Object.prototype.hasOwnProperty.call({{=$data}}, '{{=it.util.escapeQuotes($property)}}')
|
||||
{{?}}
|
||||
#}}
|
||||
|
||||
|
||||
{{
|
||||
var $schemaDeps = {}
|
||||
, $propertyDeps = {}
|
||||
, $ownProperties = it.opts.ownProperties;
|
||||
|
||||
for ($property in $schema) {
|
||||
var $sch = $schema[$property];
|
||||
var $deps = Array.isArray($sch) ? $propertyDeps : $schemaDeps;
|
||||
$deps[$property] = $sch;
|
||||
}
|
||||
}}
|
||||
|
||||
var {{=$errs}} = errors;
|
||||
|
||||
{{ var $currentErrorPath = it.errorPath; }}
|
||||
|
||||
var missing{{=$lvl}};
|
||||
{{ for (var $property in $propertyDeps) { }}
|
||||
{{ $deps = $propertyDeps[$property]; }}
|
||||
{{? $deps.length }}
|
||||
if ({{# def.propertyInData }}
|
||||
{{? $breakOnError }}
|
||||
&& ({{# def.checkMissingProperty:$deps }})) {
|
||||
{{# def.errorMissingProperty:'dependencies' }}
|
||||
{{??}}
|
||||
) {
|
||||
{{~ $deps:$propertyKey }}
|
||||
{{# def.allErrorsMissingProperty:'dependencies' }}
|
||||
{{~}}
|
||||
{{?}}
|
||||
} {{# def.elseIfValid }}
|
||||
{{?}}
|
||||
{{ } }}
|
||||
|
||||
{{
|
||||
it.errorPath = $currentErrorPath;
|
||||
var $currentBaseId = $it.baseId;
|
||||
}}
|
||||
|
||||
|
||||
{{ for (var $property in $schemaDeps) { }}
|
||||
{{ var $sch = $schemaDeps[$property]; }}
|
||||
{{? {{# def.nonEmptySchema:$sch }} }}
|
||||
{{=$nextValid}} = true;
|
||||
|
||||
if ({{# def.propertyInData }}) {
|
||||
{{
|
||||
$it.schema = $sch;
|
||||
$it.schemaPath = $schemaPath + it.util.getProperty($property);
|
||||
$it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($property);
|
||||
}}
|
||||
|
||||
{{# def.insertSubschemaCode }}
|
||||
}
|
||||
|
||||
{{# def.ifResultValid }}
|
||||
{{?}}
|
||||
{{ } }}
|
||||
|
||||
{{? $breakOnError }}
|
||||
{{= $closingBraces }}
|
||||
if ({{=$errs}} == errors) {
|
||||
{{?}}
|
||||
|
||||
{{# def.cleanUp }}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue