Skip to content

Commit

Permalink
Merge dd76307 into 8f9c1bf
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Aug 19, 2020
2 parents 8f9c1bf + dd76307 commit 85c0daf
Show file tree
Hide file tree
Showing 141 changed files with 3,732 additions and 2,866 deletions.
93 changes: 69 additions & 24 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,75 @@
extends: eslint:recommended
parserOptions:
ecmaVersion: 6
env:
es6: true
node: true
browser: true
extends:
- "eslint:recommended"
- prettier
parserOptions:
ecmaVersion: 2018
sourceType: module
overrides:
- files: ["*.ts"]
extends:
- "eslint:recommended"
- "plugin:@typescript-eslint/recommended"
- "plugin:@typescript-eslint/recommended-requiring-type-checking"
- "prettier/@typescript-eslint"
parser: "@typescript-eslint/parser"
parserOptions:
project: ["./tsconfig.json"]
plugins: ["@typescript-eslint"]
rules:
no-var: 0
"@typescript-eslint/restrict-template-expressions":
[error, allowBoolean: true]
"@typescript-eslint/ban-types": off
"@typescript-eslint/no-empty-interface": off
"@typescript-eslint/no-explicit-any": off
"@typescript-eslint/no-unsafe-call": off
"@typescript-eslint/no-unsafe-member-access": off
"@typescript-eslint/no-unsafe-assignment": off
"@typescript-eslint/restrict-plus-operands": off
"@typescript-eslint/no-unsafe-return": off
"@typescript-eslint/no-var-requires": off
"@typescript-eslint/no-empty-function": off
"@typescript-eslint/no-this-alias": off
"@typescript-eslint/no-implied-eval": off
rules:
block-scoped-var: 2
callback-return: 2
complexity: [2, 16]
curly: [2, multi-or-nest, consistent]
dot-location: [2, property]
dot-notation: 2
linebreak-style: [2, unix]
new-cap: 2
no-console: [2, allow: [warn, error]]
no-else-return: 2
no-eq-null: 2
no-extra-semi: 0
no-fallthrough: 2
no-invalid-this: 2
no-return-assign: 2
no-shadow: 1
no-trailing-spaces: 2
no-use-before-define: [2, nofunc]
block-scoped-var: error
callback-return: error
complexity: [error, 16]
curly: [error, multi-line, consistent]
dot-location: [error, property]
dot-notation: error
eqeqeq: [error, smart]
id-match: error
linebreak-style: [error, unix]
new-cap: error
no-console: [error, allow: [warn, error]]
no-debugger: error
no-duplicate-imports: error
no-else-return: error
no-eq-null: error
no-eval: error
no-fallthrough: error
no-invalid-this: error
no-new-wrappers: error
no-path-concat: error
no-redeclare: error
no-return-assign: error
no-sequences: error
no-shadow: warn
no-template-curly-in-string: error
no-trailing-spaces: error
no-undef-init: error
no-use-before-define: [error, nofunc]
prefer-arrow-callback: error
prefer-const: error
radix: error
semi: 0
strict: [2, global]
valid-jsdoc: [2, requireReturn: false]
valid-jsdoc: [error, requireReturn: false]
no-control-regex: 0
no-useless-escape: 2
no-useless-escape: error
no-void: error
# no-var: error
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,7 @@ Defaults:
inlineRefs: true,
passContext: false,
loopRequired: Infinity,
loopEnum: Infinity,
ownProperties: false,
multipleOfPrecision: false,
errorDataPath: 'object', // deprecated
Expand Down Expand Up @@ -1230,6 +1231,7 @@ Defaults:
- integer number - to limit the maximum number of keywords of the schema that will be inlined.
- _passContext_: pass validation context to custom keyword functions. If this option is `true` and you pass some context to the compiled validation function with `validate.call(context, data)`, the `context` will be available as `this` in your custom keywords. By default `this` is Ajv instance.
- _loopRequired_: by default `required` keyword is compiled into a single expression (or a sequence of statements in `allErrors` mode). In case of a very large number of properties in this keyword it may result in a very big validation function. Pass integer to set the number of properties above which `required` keyword will be validated in a loop - smaller validation function size but also worse performance.
- _loopEnum_: by default `enum` keyword is compiled into a single expression. In case of a very large number of allowed values it may result in a large validation function. Pass integer to set the number of values above which `enum` keyword will be validated in a loop.
- _ownProperties_: by default Ajv iterates over all enumerable object properties; when this option is `true` only own enumerable object properties (i.e. found directly on the object rather than on its prototype) are iterated. Contributed by @mbroadst.
- _multipleOfPrecision_: by default `multipleOf` keyword is validated by comparing the result of division with parseInt() of that result. It works for dividers that are bigger than 1. For small dividers such as 0.01 the result of the division is usually not integer (even when it should be integer, see issue [#84](https://github.com/ajv-validator/ajv/issues/84)). If you need to use fractional dividers set this option to some positive integer N to have `multipleOf` validated using this formula: `Math.abs(Math.round(division) - division) < 1e-N` (it is slower but allows for float arithmetics deviations).
- _errorDataPath_ (deprecated): set `dataPath` to point to 'object' (default) or to 'property' when validating keywords `required`, `additionalProperties` and `dependencies`.
Expand Down
16 changes: 8 additions & 8 deletions lib/ajv.d.ts → lib/ajv.d._ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
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>)
Expand All @@ -26,6 +18,14 @@ declare namespace AjvErrors {
}
}

declare const ajv: {
(options?: ajv.Options): ajv.Ajv
new (options?: ajv.Options): ajv.Ajv
ValidationError: typeof AjvErrors.ValidationError
MissingRefError: typeof AjvErrors.MissingRefError
$dataMetaSchema: object
}

declare namespace ajv {
type ValidationError = AjvErrors.ValidationError

Expand Down
111 changes: 59 additions & 52 deletions lib/ajv.js → lib/ajv.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
"use strict"
import SchemaObject from "./compile/schema_obj"
import Cache from "./cache"
import {ValidationError, MissingRefError} from "./compile/error_classes"
import rules from "./compile/rules"
import $dataMetaSchema from "./data"
import {Vocabulary, Options} from "./types"

var compileSchema = require("./compile"),
resolve = require("./compile/resolve"),
Cache = require("./cache"),
SchemaObject = require("./compile/schema_obj"),
stableStringify = require("fast-json-stable-stringify"),
rules = require("./compile/rules"),
$dataMetaSchema = require("./data"),
util = require("./compile/util")
stableStringify = require("fast-json-stable-stringify")

const validationVocabulary: Vocabulary = require("./vocabularies/validation")
const applicatorVocabulary: Vocabulary = require("./vocabularies/applicator")

module.exports = Ajv

Expand All @@ -26,35 +29,30 @@ 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.prototype.addVocabulary = customKeyword.addVocabulary
Ajv.prototype.addKeyword = customKeyword.addKeyword
Ajv.prototype.getKeyword = customKeyword.getKeyword
Ajv.prototype.removeKeyword = customKeyword.removeKeyword
Ajv.prototype.validateKeyword = customKeyword.validateKeyword

Ajv.ValidationError = ValidationError
Ajv.MissingRefError = MissingRefError
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"]
var META_IGNORE_OPTIONS = ["removeAdditional", "useDefaults", "coerceTypes", "strictDefaults"]
const META_SUPPORT_DATA = ["/properties"]

/**
* Creates validator instance.
* Usage: `Ajv(opts)`
* @param {Object} opts optional options
* @return {Object} ajv instance
*/
function Ajv(opts) {
export default function Ajv(opts: Options): void {
if (!(this instanceof Ajv)) return new Ajv(opts)
opts = this._opts = util.copy(opts) || {}
opts = this._opts = {...(opts || {})}
setLogger(this)
this._schemas = {}
this._refs = {}
Expand All @@ -67,20 +65,25 @@ function Ajv(opts) {
this._loadingSchemas = {}
this._compilations = []
this.RULES = rules()
if (opts.schemaId !== undefined && opts.schemaId !== "$id")
if (opts.schemaId !== undefined && opts.schemaId !== "$id") {
throw new Error("option schemaId is not supported from v7")
}

opts.loopRequired = opts.loopRequired || Infinity
if (opts.errorDataPath == "property") opts._errorDataPathProperty = true
opts.loopEnum = opts.loopEnum || Infinity
if (opts.errorDataPath === "property") opts._errorDataPathProperty = true
if (opts.serialize === undefined) opts.serialize = stableStringify
this._metaOpts = getMetaSchemaOptions(this)

if (opts.formats) addInitialFormats(this)
if (opts.keywords) addInitialKeywords(this)
this.addVocabulary(applicatorVocabulary, true)
this.addVocabulary(validationVocabulary, true)
if (opts.keywords) addInitialKeywords(this, opts.keywords)
addDefaultMetaSchema(this)
if (typeof opts.meta == "object") this.addMetaSchema(opts.meta)
if (opts.nullable)
if (opts.nullable) {
this.addKeyword("nullable", {metaSchema: {type: "boolean"}})
}
addInitialSchemas(this)
opts.format = formatOpt
}
Expand Down Expand Up @@ -131,13 +134,15 @@ function compile(schema, _meta) {
*/
function addSchema(schema, key, _skipValidation, _meta) {
if (Array.isArray(schema)) {
for (var i = 0; i < schema.length; i++)
for (var i = 0; i < schema.length; i++) {
this.addSchema(schema[i], undefined, _skipValidation, _meta)
}
return this
}
var id = schema.$id
if (id !== undefined && typeof id != "string")
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)
Expand Down Expand Up @@ -167,8 +172,9 @@ function addMetaSchema(schema, key, skipValidation) {
*/
function validateSchema(schema, throwOrLogError) {
var $schema = schema.$schema
if ($schema !== undefined && typeof $schema != "string")
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")
Expand All @@ -178,7 +184,7 @@ function validateSchema(schema, throwOrLogError) {
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)
if (this._opts.validateSchema === "log") this.logger.error(message)
else throw new Error(message)
}
return valid
Expand Down Expand Up @@ -278,7 +284,7 @@ function removeSchema(schemaKeyRef) {
return this
}

function _removeAllSchemas(self, schemas, regex) {
function _removeAllSchemas(self, schemas, regex?: RegExp) {
for (var keyRef in schemas) {
var schemaObj = schemas[keyRef]
if (!schemaObj.meta && (!regex || regex.test(keyRef))) {
Expand All @@ -290,8 +296,9 @@ function _removeAllSchemas(self, schemas, regex) {

/* @this Ajv */
function _addSchema(schema, skipValidation, meta, shouldAddSchema) {
if (typeof schema != "object" && typeof schema != "boolean")
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)
Expand All @@ -304,11 +311,9 @@ function _addSchema(schema, skipValidation, meta, shouldAddSchema) {

var willValidate = this._opts.validateSchema !== false && !skipValidation
var recursiveMeta
if (
willValidate &&
!(recursiveMeta = id && id == resolve.normalizeId(schema.$schema))
)
if (willValidate && !(recursiveMeta = id && id === resolve.normalizeId(schema.$schema))) {
this.validateSchema(schema, true)
}

var localRefs = resolve.ids.call(this, schema)

Expand All @@ -320,7 +325,7 @@ function _addSchema(schema, skipValidation, meta, shouldAddSchema) {
meta: meta,
})

if (id[0] != "#" && shouldAddSchema) this._refs[id] = schemaObj
if (id[0] !== "#" && shouldAddSchema) this._refs[id] = schemaObj
this._cache.put(cacheKey, schemaObj)

if (willValidate && recursiveMeta) this.validateSchema(schema, true)
Expand Down Expand Up @@ -364,10 +369,10 @@ function _compile(schemaObj, root) {
return v

/* @this {*} - custom context, see passContext option */
function callValidate() {
function callValidate(...args) {
/* jshint validthis: true */
var _validate = schemaObj.validate
var result = _validate.apply(this, arguments)
var result = _validate.apply(this, args)
callValidate.errors = _validate.errors
return result
}
Expand Down Expand Up @@ -416,8 +421,9 @@ function addDefaultMetaSchema(self) {
}
if (self._opts.meta === false) return
var metaSchema = require("./refs/json-schema-draft-07.json")
if (self._opts.$data)
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
}
Expand All @@ -436,22 +442,24 @@ function addInitialFormats(self) {
}
}

function addInitialKeywords(self) {
for (var name in self._opts.keywords) {
var keyword = self._opts.keywords[name]
self.addKeyword(name, keyword)
function addInitialKeywords(self, keywords, skipValidation?: boolean) {
for (var name in keywords) {
var keyword = keywords[name]
self.addKeyword(name, keyword, skipValidation)
}
}

function checkUnique(self, id) {
if (self._schemas[id] || self._refs[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++)
var metaOpts = {...self._opts}
for (var i = 0; i < META_IGNORE_OPTIONS.length; i++) {
delete metaOpts[META_IGNORE_OPTIONS[i]]
}
return metaOpts
}

Expand All @@ -461,10 +469,9 @@ function setLogger(self) {
self.logger = {log: noop, warn: noop, error: noop}
} else {
if (logger === undefined) logger = console
if (
!(typeof logger == "object" && logger.log && logger.warn && logger.error)
)
if (!(typeof logger == "object" && logger.log && logger.warn && logger.error)) {
throw new Error("logger must implement log, warn and error methods")
}
self.logger = logger
}
}
Expand Down
Loading

0 comments on commit 85c0daf

Please sign in to comment.