Socket
Socket
Sign inDemoInstall

ajv

Package Overview
Dependencies
Maintainers
2
Versions
355
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ajv - npm Package Compare versions

Comparing version 7.0.0-beta.2 to 7.0.0-beta.3

dist/vocabularies/applicator/dependentSchemas.d.ts

2

dist/ajv.d.ts

@@ -27,2 +27,4 @@ export { Format, FormatDefinition, AsyncFormatDefinition, KeywordDefinition, KeywordErrorDefinition, CodeKeywordDefinition, MacroKeywordDefinition, FuncKeywordDefinition, Vocabulary, Schema, SchemaObject, AnySchemaObject, AsyncSchema, AnySchema, ValidateFunction, AsyncValidateFunction, ErrorObject, } from "./types";

validateFormats?: boolean;
next?: boolean;
unevaluated?: boolean;
$data?: boolean;

@@ -29,0 +31,0 @@ allErrors?: boolean;

@@ -27,2 +27,4 @@ "use strict";

const metadata_1 = require("./vocabularies/metadata");
const next_1 = __importDefault(require("./vocabularies/next"));
const unevaluated_1 = __importDefault(require("./vocabularies/unevaluated"));
const util_1 = require("./compile/util");

@@ -120,2 +122,6 @@ const data_json_1 = __importDefault(require("./refs/data.json"));

this.addVocabulary(metadata_1.contentVocabulary);
if (opts.next)
this.addVocabulary(next_1.default);
if (opts.unevaluated)
this.addVocabulary(unevaluated_1.default);
addDefaultMetaSchema.call(this);

@@ -122,0 +128,0 @@ if (opts.keywords)

6

dist/compile/context.d.ts
import type { AddedKeywordDefinition, KeywordErrorCxt, KeywordCxtParams, AnySchemaObject } from "../types";
import { SchemaObjCxt } from "./index";
import { SchemaCxt, SchemaObjCxt } from "./index";
import { JSONType } from "./rules";

@@ -34,3 +34,5 @@ import { CodeGen, Code, Name } from "./codegen";

invalid$data(): Code;
subschema(appl: SubschemaArgs, valid: Name): void;
subschema(appl: SubschemaArgs, valid: Name): SchemaCxt;
mergeEvaluated(schemaCxt: SchemaCxt, toName?: typeof Name): void;
mergeValidEvaluated(schemaCxt: SchemaCxt, valid: Name): boolean | void;
}

@@ -147,4 +147,22 @@ "use strict";

subschema(appl, valid) {
subschema_1.applySubschema(this.it, appl, valid);
return subschema_1.applySubschema(this.it, appl, valid);
}
mergeEvaluated(schemaCxt, toName) {
const { it, gen } = this;
if (!it.opts.unevaluated)
return;
if (it.props !== true && schemaCxt.props !== undefined) {
it.props = util_1.mergeEvaluated.props(gen, schemaCxt.props, it.props, toName);
}
if (it.items !== true && schemaCxt.items !== undefined) {
it.items = util_1.mergeEvaluated.items(gen, schemaCxt.items, it.items, toName);
}
}
mergeValidEvaluated(schemaCxt, valid) {
const { it, gen } = this;
if (it.opts.unevaluated && (it.props !== true || it.items !== true)) {
gen.if(valid, () => this.mergeEvaluated(schemaCxt, codegen_1.Name));
return true;
}
}
}

@@ -151,0 +169,0 @@ exports.default = KeywordCxt;

@@ -1,2 +0,2 @@

import type { AnySchema, AnySchemaObject, AnyValidateFunction } from "../types";
import type { AnySchema, AnySchemaObject, AnyValidateFunction, EvaluatedProperties, EvaluatedItems } from "../types";
import type Ajv from "../ajv";

@@ -22,2 +22,3 @@ import type { InstanceOptions } from "../ajv";

readonly validateName: Name;
evaluated?: Name;
readonly ValidationError?: Name;

@@ -34,2 +35,4 @@ readonly schema: AnySchema;

readonly compositeRule?: boolean;
props?: EvaluatedProperties | Name;
items?: EvaluatedItems | Name;
readonly createErrors?: boolean;

@@ -36,0 +39,0 @@ readonly opts: InstanceOptions;

@@ -101,2 +101,11 @@ "use strict";

}
if (this.opts.unevaluated) {
const { props, items } = schemaCxt;
validate.evaluated = {
props: props instanceof codegen_1.Name ? undefined : props,
items: items instanceof codegen_1.Name ? undefined : items,
dynamicProps: props instanceof codegen_1.Name,
dynamicItems: items instanceof codegen_1.Name,
};
}
sch.validate = validate;

@@ -103,0 +112,0 @@ return sch;

@@ -19,3 +19,3 @@ "use strict";

types: { ...groups, integer: true, boolean: true, null: true },
rules: [groups.number, groups.string, groups.array, groups.object, { rules: [] }],
rules: [groups.number, groups.string, { rules: [] }, groups.array, groups.object],
all: { type: true, $comment: true },

@@ -22,0 +22,0 @@ keywords: { type: true, $comment: true },

import type { AnySchema } from "../types";
import type { SchemaObjCxt } from "./index";
import type { SchemaObjCxt, SchemaCxt } from "./index";
import { Code, Name } from "./codegen";

@@ -26,2 +26,2 @@ import { JSONType } from "./rules";

}>;
export declare function applySubschema(it: SchemaObjCxt, appl: SubschemaArgs, valid: Name): void;
export declare function applySubschema(it: SchemaObjCxt, appl: SubschemaArgs, valid: Name): SchemaCxt;

@@ -16,4 +16,5 @@ "use strict";

extendSubschemaMode(subschema, appl);
const nextContext = { ...it, ...subschema };
const nextContext = { ...it, ...subschema, items: undefined, props: undefined };
validate_1.subschemaCode(nextContext, valid);
return nextContext;
}

@@ -20,0 +21,0 @@ exports.applySubschema = applySubschema;

@@ -1,4 +0,4 @@

import type { AnySchema } from "../types";
import type { AnySchema, EvaluatedProperties, EvaluatedItems } from "../types";
import type { SchemaCxt, SchemaObjCxt } from ".";
import { Code } from "./codegen";
import { Code, Name, CodeGen } from "./codegen";
import type { Rule, ValidationRules } from "./rules";

@@ -21,1 +21,13 @@ export declare function toHash<T extends string = string>(arr: T[]): {

export declare function ucs2length(str: string): number;
declare type SomeEvaluated = EvaluatedProperties | EvaluatedItems;
declare type MergeEvaluatedFunc<T extends SomeEvaluated> = (gen: CodeGen, from: Name | T, to: Name | Exclude<T, true> | undefined, toName?: typeof Name) => Name | T;
interface MergeEvaluated {
props: MergeEvaluatedFunc<EvaluatedProperties>;
items: MergeEvaluatedFunc<EvaluatedItems>;
}
export declare const mergeEvaluated: MergeEvaluated;
export declare function evaluatedPropsToName(gen: CodeGen, ps?: EvaluatedProperties): Name;
export declare function setEvaluated(gen: CodeGen, props: Name, ps: {
[K in string]?: true;
}): void;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ucs2length = exports.eachItem = exports.unescapeJsonPointer = exports.escapeJsonPointer = exports.escapeFragment = exports.unescapeFragment = exports.schemaRefOrVal = exports.schemaHasRulesButRef = exports.schemaHasRules = exports.checkUnknownRules = exports.alwaysValidSchema = exports.toHash = void 0;
exports.setEvaluated = exports.evaluatedPropsToName = exports.mergeEvaluated = exports.ucs2length = exports.eachItem = exports.unescapeJsonPointer = exports.escapeJsonPointer = exports.escapeFragment = exports.unescapeFragment = exports.schemaRefOrVal = exports.schemaHasRulesButRef = exports.schemaHasRules = exports.checkUnknownRules = exports.alwaysValidSchema = exports.toHash = void 0;
const codegen_1 = require("./codegen");

@@ -112,2 +112,51 @@ const validate_1 = require("./validate");

exports.ucs2length = ucs2length;
function makeMergeEvaluated({ mergeNames, mergeToName, mergeValues, resultToName, }) {
return (gen, from, to, toName) => {
const res = to === undefined
? from
: to instanceof codegen_1.Name
? (from instanceof codegen_1.Name ? mergeNames(gen, from, to) : mergeToName(gen, from, to), to)
: from instanceof codegen_1.Name
? (mergeToName(gen, to, from), from)
: mergeValues(from, to);
return toName === codegen_1.Name && !(res instanceof codegen_1.Name) ? resultToName(gen, res) : res;
};
}
exports.mergeEvaluated = {
props: makeMergeEvaluated({
mergeNames: (gen, from, to) => gen.if(codegen_1._ `${to} !== true && ${from} !== undefined`, () => {
gen.if(codegen_1._ `${from} === true`, () => gen.assign(to, true), () => gen.code(codegen_1._ `Object.assign(${to}, ${from})`));
}),
mergeToName: (gen, from, to) => gen.if(codegen_1._ `${to} !== true`, () => {
if (from === true) {
gen.assign(to, true);
}
else {
gen.assign(to, codegen_1._ `${to} || {}`);
setEvaluated(gen, to, from);
}
}),
mergeValues: (from, to) => (from === true ? true : { ...from, ...to }),
resultToName: evaluatedPropsToName,
}),
items: makeMergeEvaluated({
mergeNames: (gen, from, to) => gen.if(codegen_1._ `${to} !== true && ${from} !== undefined`, () => gen.assign(to, codegen_1._ `${from} === true ? true : ${to} > ${from} ? ${to} : ${from}`)),
mergeToName: (gen, from, to) => gen.if(codegen_1._ `${to} !== true`, () => gen.assign(to, from === true ? true : codegen_1._ `${to} > ${from} ? ${to} : ${from}`)),
mergeValues: (from, to) => (from === true ? true : Math.max(from, to)),
resultToName: (gen, items) => gen.var("items", items),
}),
};
function evaluatedPropsToName(gen, ps) {
if (ps === true)
return gen.var("props", true);
const props = gen.var("props", codegen_1._ `{}`);
if (ps !== undefined)
setEvaluated(gen, props, ps);
return props;
}
exports.evaluatedPropsToName = evaluatedPropsToName;
function setEvaluated(gen, props, ps) {
Object.keys(ps).forEach((p) => gen.assign(codegen_1._ `${props}${codegen_1.getProperty(p)}`, true));
}
exports.setEvaluated = setEvaluated;
//# sourceMappingURL=util.js.map

@@ -56,2 +56,4 @@ "use strict";

gen.let(names_1.default.errors, 0);
if (opts.unevaluated)
resetEvaluated(it);
typeAndKeywords(it);

@@ -62,2 +64,9 @@ returnResults(it);

}
function resetEvaluated(it) {
// TODO maybe some hook to execute it in the end to check whether props/items are Name, as in assignEvaluated
const { gen, validateName } = it;
it.evaluated = gen.const("evaluated", codegen_1._ `${validateName}.evaluated`);
gen.if(codegen_1._ `${it.evaluated}.dynamicProps`, () => gen.assign(codegen_1._ `${it.evaluated}.props`, codegen_1._ `undefined`));
gen.if(codegen_1._ `${it.evaluated}.dynamicItems`, () => gen.assign(codegen_1._ `${it.evaluated}.items`, codegen_1._ `undefined`));
}
function funcSourceUrl(schema, opts) {

@@ -143,4 +152,6 @@ return typeof schema == "object" && schema.$id && (opts.code.source || opts.code.process)

}
function returnResults({ gen, schemaEnv, validateName, ValidationError }) {
function returnResults(it) {
const { gen, schemaEnv, validateName, ValidationError, opts } = it;
if (schemaEnv.$async) {
// TODO assign unevaluated
gen.if(codegen_1._ `${names_1.default.errors} === 0`, () => gen.return(names_1.default.data), () => gen.throw(codegen_1._ `new ${ValidationError}(${names_1.default.vErrors})`));

@@ -150,5 +161,13 @@ }

gen.assign(codegen_1._ `${validateName}.errors`, names_1.default.vErrors);
if (opts.unevaluated)
assignEvaluated(it);
gen.return(codegen_1._ `${names_1.default.errors} === 0`);
}
}
function assignEvaluated({ gen, evaluated, props, items }) {
if (props instanceof codegen_1.Name)
gen.assign(codegen_1._ `${evaluated}.props`, props);
if (items instanceof codegen_1.Name)
gen.assign(codegen_1._ `${evaluated}.items`, items);
}
function checkStrictMode(it, msg, mode = it.opts.strict) {

@@ -155,0 +174,0 @@ if (!mode)

@@ -39,2 +39,3 @@ import type { CodeGen, Code, Name, Scope } from "../compile/codegen";

errors?: null | ErrorObject[];
evaluated?: Evaluated;
schema: AnySchema;

@@ -44,2 +45,12 @@ schemaEnv: SchemaEnv;

}
export declare type EvaluatedProperties = {
[K in string]?: true;
} | true;
export declare type EvaluatedItems = number | true;
export interface Evaluated {
props?: EvaluatedProperties;
items?: EvaluatedItems;
dynamicProps: boolean;
dynamicItems: boolean;
}
export interface AsyncValidateFunction<T = unknown> extends ValidateFunction<T> {

@@ -46,0 +57,0 @@ (...args: Parameters<ValidateFunction<T>>): Promise<T>;

@@ -19,3 +19,2 @@ "use strict";

const { gen, schema, parentSchema, data, it } = cxt;
const len = gen.const("len", codegen_1._ `${data}.length`);
const { items } = parentSchema;

@@ -26,2 +25,4 @@ if (!Array.isArray(items)) {

}
it.items = true;
const len = gen.const("len", codegen_1._ `${data}.length`);
if (schema === false) {

@@ -28,0 +29,0 @@ cxt.setParams({ len: items.length });

@@ -28,2 +28,3 @@ "use strict";

const { allErrors, opts } = it;
it.props = true;
if (opts.removeAdditional !== "all" && util_1.alwaysValidSchema(it, schema))

@@ -34,4 +35,3 @@ return;

checkAdditionalProperties();
if (!allErrors)
gen.if(codegen_1._ `${errsCount} === ${names_1.default.errors}`);
cxt.ok(codegen_1._ `${errsCount} === ${names_1.default.errors}`);
function checkAdditionalProperties() {

@@ -38,0 +38,0 @@ gen.forIn("key", data, (key) => {

@@ -16,4 +16,5 @@ "use strict";

return;
cxt.subschema({ keyword: "allOf", schemaProp: i }, valid);
const schCxt = cxt.subschema({ keyword: "allOf", schemaProp: i }, valid);
cxt.ok(valid);
cxt.mergeEvaluated(schCxt);
});

@@ -20,0 +21,0 @@ },

@@ -15,17 +15,19 @@ "use strict";

const alwaysValid = schema.some((sch) => util_1.alwaysValidSchema(it, sch));
if (alwaysValid)
if (alwaysValid && !it.opts.unevaluated)
return;
const valid = gen.let("valid", false);
const schValid = gen.name("_valid");
gen.block(() => {
schema.forEach((_sch, i) => {
cxt.subschema({
keyword: "anyOf",
schemaProp: i,
compositeRule: true,
}, schValid);
gen.assign(valid, codegen_1._ `${valid} || ${schValid}`);
gen.block(() => schema.forEach((_sch, i) => {
const schCxt = cxt.subschema({
keyword: "anyOf",
schemaProp: i,
compositeRule: true,
}, schValid);
gen.assign(valid, codegen_1._ `${valid} || ${schValid}`);
const merged = cxt.mergeValidEvaluated(schCxt, schValid);
// can short-circuit if `unevaluatedProperties/Items` not supported (opts.unevaluated !== true)
// or if all properties and items were evaluated (it.props === true && it.items === true)
if (!merged)
gen.if(codegen_1.not(valid));
});
}, schema.length);
}));
cxt.result(valid, () => cxt.reset(), () => cxt.error(true));

@@ -32,0 +34,0 @@ },

@@ -1,3 +0,7 @@

import type { CodeKeywordDefinition } from "../../types";
import type { CodeKeywordDefinition, ErrorObject } from "../../types";
export declare type ContainsError = ErrorObject<"contains", {
minContains: number;
maxContains?: number;
}>;
declare const def: CodeKeywordDefinition;
export default def;

@@ -6,2 +6,9 @@ "use strict";

const util_1 = require("../../compile/util");
const validate_1 = require("../../compile/validate");
const error = {
message: ({ params: { min, max } }) => max === undefined
? codegen_1.str `should contain at least ${min} valid item(s)`
: codegen_1.str `should contain at least ${min} and no more than ${max} valid item(s)`,
params: ({ params: { min, max } }) => max === undefined ? codegen_1._ `{minContains: ${min}}` : codegen_1._ `{minContains: ${min}, maxContains: ${max}}`,
};
const def = {

@@ -13,25 +20,72 @@ keyword: "contains",

trackErrors: true,
error,
code(cxt) {
const { gen, schema, data, it } = cxt;
const { gen, schema, parentSchema, data, it } = cxt;
let min;
let max;
const { minContains, maxContains } = parentSchema;
if (it.opts.next) {
min = minContains === undefined ? 1 : minContains;
max = maxContains;
}
else {
min = 1;
}
const len = gen.const("len", codegen_1._ `${data}.length`);
cxt.setParams({ min, max });
if (max === undefined && min === 0) {
validate_1.checkStrictMode(it, `"minContains" == 0 without "maxContains": "contains" keyword ignored`);
return;
}
if (max !== undefined && min > max) {
validate_1.checkStrictMode(it, `"minContains" > "maxContains" is always invalid`);
cxt.fail();
return;
}
if (util_1.alwaysValidSchema(it, schema)) {
cxt.fail(codegen_1._ `${data}.length === 0`);
let cond = codegen_1._ `${len} >= ${min}`;
if (max !== undefined)
cond = codegen_1._ `${cond} && ${len} <= ${max}`;
cxt.pass(cond);
return;
}
it.items = true;
const valid = gen.name("valid");
gen.forRange("i", 0, codegen_1._ `${data}.length`, (i) => {
cxt.subschema({
keyword: "contains",
dataProp: i,
dataPropType: subschema_1.Type.Num,
compositeRule: true,
}, valid);
gen.if(valid, () => gen.break());
});
if (max === undefined && min === 1) {
validateItems(valid, () => gen.if(valid, () => gen.break()));
}
else {
gen.let(valid, false);
const schValid = gen.name("_valid");
const count = gen.let("count", 0);
validateItems(schValid, () => gen.if(schValid, () => checkLimits(count)));
}
cxt.result(valid, () => cxt.reset());
function validateItems(_valid, block) {
gen.forRange("i", 0, len, (i) => {
cxt.subschema({
keyword: "contains",
dataProp: i,
dataPropType: subschema_1.Type.Num,
compositeRule: true,
}, _valid);
block();
});
}
function checkLimits(count) {
gen.code(codegen_1._ `${count}++`);
if (max === undefined) {
gen.if(codegen_1._ `${count} >= ${min}`, () => gen.assign(valid, true).break());
}
else {
gen.if(codegen_1._ `${count} > ${max}`, () => gen.assign(valid, false).break());
if (min === 1)
gen.assign(valid, true);
else
gen.if(codegen_1._ `${count} >= ${min}`, () => gen.assign(valid, true));
}
}
},
error: {
message: "should contain a valid item",
},
};
exports.default = def;
//# sourceMappingURL=contains.js.map

@@ -1,2 +0,3 @@

import type { CodeKeywordDefinition, ErrorObject } from "../../types";
import type { CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition, SchemaMap } from "../../types";
import type KeywordCxt from "../../compile/context";
export declare type DependenciesError = ErrorObject<"dependencies", {

@@ -8,3 +9,8 @@ property: string;

}>;
export declare const error: KeywordErrorDefinition;
declare const def: CodeKeywordDefinition;
export declare function validatePropertyDeps(cxt: KeywordCxt, propertyDeps?: {
[x: string]: string[];
}): void;
export declare function validateSchemaDeps(cxt: KeywordCxt, schemaDeps?: SchemaMap): void;
export default def;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateSchemaDeps = exports.validatePropertyDeps = exports.error = void 0;
const codegen_1 = require("../../compile/codegen");
const util_1 = require("../../compile/util");
const code_1 = require("../code");
const error = {
exports.error = {
message: ({ params: { property, depsCount, deps } }) => {

@@ -20,60 +21,66 @@ const property_ies = depsCount === 1 ? "property" : "properties";

schemaType: "object",
error,
error: exports.error,
code(cxt) {
const { gen, schema, data, it } = cxt;
const [propDeps, schDeps] = splitDependencies();
const valid = gen.name("valid");
validatePropertyDeps(propDeps);
validateSchemaDeps(schDeps);
function splitDependencies() {
const propertyDeps = {};
const schemaDeps = {};
for (const key in schema) {
if (key === "__proto__")
continue;
const deps = Array.isArray(schema[key]) ? propertyDeps : schemaDeps;
deps[key] = schema[key];
}
return [propertyDeps, schemaDeps];
}
function validatePropertyDeps(propertyDeps) {
if (Object.keys(propertyDeps).length === 0)
return;
const missing = gen.let("missing");
for (const prop in propertyDeps) {
const deps = propertyDeps[prop];
if (deps.length === 0)
continue;
const hasProperty = code_1.propertyInData(data, prop, it.opts.ownProperties);
cxt.setParams({
property: prop,
depsCount: deps.length,
deps: deps.join(", "),
});
if (it.allErrors) {
gen.if(hasProperty, () => {
for (const depProp of deps) {
code_1.checkReportMissingProp(cxt, depProp);
}
});
const [propDeps, schDeps] = splitDependencies(cxt);
validatePropertyDeps(cxt, propDeps);
validateSchemaDeps(cxt, schDeps);
},
};
function splitDependencies({ schema }) {
const propertyDeps = {};
const schemaDeps = {};
for (const key in schema) {
if (key === "__proto__")
continue;
const deps = Array.isArray(schema[key]) ? propertyDeps : schemaDeps;
deps[key] = schema[key];
}
return [propertyDeps, schemaDeps];
}
function validatePropertyDeps(cxt, propertyDeps = cxt.schema) {
const { gen, data, it } = cxt;
if (Object.keys(propertyDeps).length === 0)
return;
const missing = gen.let("missing");
for (const prop in propertyDeps) {
const deps = propertyDeps[prop];
if (deps.length === 0)
continue;
const hasProperty = code_1.propertyInData(data, prop, it.opts.ownProperties);
cxt.setParams({
property: prop,
depsCount: deps.length,
deps: deps.join(", "),
});
if (it.allErrors) {
gen.if(hasProperty, () => {
for (const depProp of deps) {
code_1.checkReportMissingProp(cxt, depProp);
}
else {
gen.if(codegen_1._ `${hasProperty} && (${code_1.checkMissingProp(cxt, deps, missing)})`);
code_1.reportMissingProp(cxt, missing);
gen.else();
}
}
});
}
function validateSchemaDeps(schemaDeps) {
for (const prop in schemaDeps) {
if (util_1.alwaysValidSchema(it, schemaDeps[prop]))
continue;
gen.if(code_1.propertyInData(data, prop, it.opts.ownProperties), () => cxt.subschema({ keyword: "dependencies", schemaProp: prop }, valid), () => gen.var(valid, true) // TODO var
);
cxt.ok(valid);
}
else {
gen.if(codegen_1._ `${hasProperty} && (${code_1.checkMissingProp(cxt, deps, missing)})`);
code_1.reportMissingProp(cxt, missing);
gen.else();
}
},
};
}
}
exports.validatePropertyDeps = validatePropertyDeps;
function validateSchemaDeps(cxt, schemaDeps = cxt.schema) {
const { gen, data, keyword, it } = cxt;
const valid = gen.name("valid");
for (const prop in schemaDeps) {
if (util_1.alwaysValidSchema(it, schemaDeps[prop]))
continue;
gen.if(code_1.propertyInData(data, prop, it.opts.ownProperties), () => {
const schCxt = cxt.subschema({ keyword, schemaProp: prop }, valid);
cxt.mergeValidEvaluated(schCxt, valid);
}, () => gen.var(valid, true) // TODO var
);
cxt.ok(valid);
}
}
exports.validateSchemaDeps = validateSchemaDeps;
exports.default = def;
//# sourceMappingURL=dependencies.js.map

@@ -41,3 +41,3 @@ "use strict";

function validateIf() {
cxt.subschema({
const schCxt = cxt.subschema({
keyword: "if",

@@ -48,7 +48,9 @@ compositeRule: true,

}, schValid);
cxt.mergeEvaluated(schCxt);
}
function validateClause(keyword, ifClause) {
return () => {
cxt.subschema({ keyword }, schValid);
const schCxt = cxt.subschema({ keyword }, schValid);
gen.assign(valid, schValid);
cxt.mergeValidEvaluated(schCxt, valid);
if (ifClause)

@@ -55,0 +57,0 @@ gen.assign(ifClause, codegen_1._ `${keyword}`);

import type { ErrorObject, Vocabulary } from "../../types";
import { AdditionalItemsError } from "./additionalItems";
import { ContainsError } from "./contains";
import { DependenciesError } from "./dependencies";

@@ -10,3 +11,3 @@ import { PropertyNamesError } from "./propertyNames";

export default applicator;
export declare type ApplicatorKeywordError = ErrorWithoutParams | AdditionalItemsError | AdditionalPropertiesError | DependenciesError | IfKeywordError | OneOfError | PropertyNamesError;
export declare type ErrorWithoutParams = ErrorObject<"anyOf" | "contains" | "not" | "false schema", Record<string, never>>;
export declare type ApplicatorKeywordError = ErrorWithoutParams | AdditionalItemsError | ContainsError | AdditionalPropertiesError | DependenciesError | IfKeywordError | OneOfError | PropertyNamesError;
export declare type ErrorWithoutParams = ErrorObject<"anyOf" | "not" | "false schema", Record<string, never>>;

@@ -21,2 +21,9 @@ "use strict";

const applicator = [
// any
not_1.default,
anyOf_1.default,
oneOf_1.default,
allOf_1.default,
if_1.default,
thenElse_1.default,
// array

@@ -27,16 +34,9 @@ additionalItems_1.default,

// object
dependencies_1.default,
propertyNames_1.default,
additionalProperties_1.default,
dependencies_1.default,
properties_1.default,
patternProperties_1.default,
// any
not_1.default,
anyOf_1.default,
oneOf_1.default,
allOf_1.default,
if_1.default,
thenElse_1.default,
];
exports.default = applicator;
//# sourceMappingURL=index.js.map

@@ -16,6 +16,11 @@ "use strict";

if (Array.isArray(schema)) {
if (it.opts.unevaluated && schema.length && it.items !== true) {
it.items = util_1.mergeEvaluated.items(gen, schema.length, it.items);
}
validateTuple(schema);
}
else if (!util_1.alwaysValidSchema(it, schema)) {
validateArray();
else {
it.items = true;
if (!util_1.alwaysValidSchema(it, schema))
validateArray();
}

@@ -22,0 +27,0 @@ function validateTuple(schArr) {

@@ -29,2 +29,3 @@ "use strict";

schArr.forEach((sch, i) => {
let schCxt;
if (util_1.alwaysValidSchema(it, sch)) {

@@ -34,3 +35,3 @@ gen.var(schValid, true);

else {
cxt.subschema({
schCxt = cxt.subschema({
keyword: "oneOf",

@@ -48,3 +49,8 @@ schemaProp: i,

}
gen.if(schValid, () => gen.assign(valid, true).assign(passing, i));
gen.if(schValid, () => {
gen.assign(valid, true);
gen.assign(passing, i);
if (schCxt)
cxt.mergeEvaluated(schCxt, codegen_1.Name);
});
});

@@ -51,0 +57,0 @@ }

@@ -7,2 +7,3 @@ "use strict";

const validate_1 = require("../../compile/validate");
const util_1 = require("../../compile/util");
const def = {

@@ -16,2 +17,3 @@ keyword: "patternProperties",

const patterns = code_1.schemaProperties(it, schema);
// TODO mark properties matching patterns with always valid schemas as evaluated
if (patterns.length === 0)

@@ -21,2 +23,6 @@ return;

const valid = gen.name("valid");
if (it.props !== true && !(it.props instanceof codegen_1.Name)) {
it.props = util_1.evaluatedPropsToName(gen, it.props);
}
const { props } = it;
validatePatternProperties();

@@ -54,4 +60,10 @@ function validatePatternProperties() {

}, valid);
if (!it.allErrors)
if (it.opts.unevaluated && props !== true) {
gen.assign(codegen_1._ `${props}[${key}]`, true);
}
else if (!it.allErrors) {
// can short-circuit if `unevaluatedProperties` is not supported (opts.next === false)
// or if all properties were evaluated (props === true)
gen.if(codegen_1.not(valid), () => gen.break());
}
});

@@ -58,0 +70,0 @@ });

@@ -8,2 +8,3 @@ "use strict";

const code_1 = require("../code");
const util_1 = require("../../compile/util");
const additionalProperties_1 = __importDefault(require("./additionalProperties"));

@@ -19,3 +20,7 @@ const def = {

}
const properties = code_1.schemaProperties(it, schema);
const allProps = code_1.allSchemaProperties(schema);
if (it.opts.unevaluated && allProps.length && it.props !== true) {
it.props = util_1.mergeEvaluated.props(gen, util_1.toHash(allProps), it.props);
}
const properties = allProps.filter((p) => !util_1.alwaysValidSchema(it, schema[p]));
if (properties.length === 0)

@@ -22,0 +27,0 @@ return;

@@ -11,2 +11,3 @@ "use strict";

const compile_1 = require("../../compile");
const util_1 = require("../../compile/util");
const def = {

@@ -29,5 +30,5 @@ keyword: "$ref",

if (env === env.root)
return callRef(validateName, env.$async);
return callRef(validateName, env, env.$async);
const rootName = gen.scopeValue("root", { ref: env.root });
return callRef(codegen_1._ `${rootName}.validate`, env.root.$async);
return callRef(codegen_1._ `${rootName}.validate`, env.root, env.root.$async);
}

@@ -44,9 +45,9 @@ function callValidate(sch) {

}
callRef(v, sch.$async);
callRef(v, sch, sch.$async);
}
function callRef(v, $async) {
function callRef(v, sch, $async) {
if ($async)
callAsyncRef(v);
callAsyncRef(v, sch);
else
callSyncRef(v);
callSyncRef(v, sch);
}

@@ -56,3 +57,3 @@ function inlineRefSchema(sch) {

const valid = gen.name("valid");
cxt.subschema({
const schCxt = cxt.subschema({
schema: sch,

@@ -65,5 +66,6 @@ strictSchema: true,

}, valid);
cxt.mergeEvaluated(schCxt);
cxt.ok(valid);
}
function callAsyncRef(v) {
function callAsyncRef(v, sch) {
if (!env.$async)

@@ -74,2 +76,3 @@ throw new Error("async schema referenced by sync schema");

gen.code(codegen_1._ `await ${code_1.callValidateCode(cxt, v, passCxt)}`);
addEvaluatedFrom(v, sch);
if (!allErrors)

@@ -85,4 +88,4 @@ gen.assign(valid, true);

}
function callSyncRef(v) {
cxt.pass(code_1.callValidateCode(cxt, v, passCxt), () => addErrorsFrom(v));
function callSyncRef(v, sch) {
cxt.result(code_1.callValidateCode(cxt, v, passCxt), () => addEvaluatedFrom(v, sch), () => addErrorsFrom(v));
}

@@ -94,2 +97,31 @@ function addErrorsFrom(source) {

}
function addEvaluatedFrom(source, sch) {
var _a;
if (!it.opts.unevaluated)
return;
const schEvaluated = (_a = sch.validate) === null || _a === void 0 ? void 0 : _a.evaluated;
// TODO refactor
if (it.props !== true) {
if (schEvaluated && !schEvaluated.dynamicProps) {
if (schEvaluated.props !== undefined) {
it.props = util_1.mergeEvaluated.props(gen, schEvaluated.props, it.props);
}
}
else {
const props = gen.var("props", codegen_1._ `${source}.evaluated.props`);
it.props = util_1.mergeEvaluated.props(gen, props, it.props, codegen_1.Name);
}
}
if (it.items !== true) {
if (schEvaluated && !schEvaluated.dynamicItems) {
if (schEvaluated.items !== undefined) {
it.items = util_1.mergeEvaluated.items(gen, schEvaluated.items, it.items);
}
}
else {
const items = gen.var("items", codegen_1._ `${source}.evaluated.items`);
it.items = util_1.mergeEvaluated.items(gen, items, it.items, codegen_1.Name);
}
}
}
},

@@ -96,0 +128,0 @@ };

@@ -5,2 +5,5 @@ import type { TypeError } from "../compile/validate/dataType";

import type { FormatError } from "./format/format";
export declare type DefinedError = TypeError | ApplicatorKeywordError | ValidationKeywordError | FormatError;
import type { UnevaluatedPropertiesError } from "./applicator/unevaluatedProperties";
import type { UnevaluatedItemsError } from "./applicator/unevaluatedItems";
import type { DependentRequiredError } from "./validation/dependentRequired";
export declare type DefinedError = TypeError | ApplicatorKeywordError | ValidationKeywordError | FormatError | UnevaluatedPropertiesError | UnevaluatedItemsError | DependentRequiredError;

@@ -21,2 +21,3 @@ "use strict";

});
// TODO optimize for scalar values in schema
cxt.fail$data(codegen_1._ `!${eql}(${cxt.data}, ${cxt.schemaCode})`);

@@ -23,0 +24,0 @@ },

@@ -260,2 +260,4 @@ # API Reference

// validation and reporting options:
next: false,
unevaluated: false,
$data: false,

@@ -317,2 +319,4 @@ allErrors: false,

- _next_: add support for the keywords from the next JSON-Schema draft (currently it is draft 2019-09): [`dependentRequired`](./json-schema.md#dependentrequired), [`dependentSchemas`](./json-schema.md#dependentschemas), [`maxContains`/`minContain`](./json-schema.md#maxcontains--mincontains). This option will be removed once the next draft is fully supported.
- _unevaluated_: to track evaluated properties/items and support keywords [`unevaluatedProperties`](./json-schema.md#unevaluatedproperties) and [`unevaluatedItems`](./json-schema.md#unevaluateditems). Supporting these keywords may add additional validation-time logic even to validation functions where these keywords are not used. When possible, Ajv determines which properties/items are "unevaluated" at compilation time.
- _\$data_: support [\$data references](./validation.md#data-reference). Draft 6 meta-schema that is added by default will be extended to allow them. If you want to use another meta-schema you need to use $dataMetaSchema method to add support for $data reference. See [API](#ajv-constructor-and-methods).

@@ -319,0 +323,0 @@ - _allErrors_: check all rules collecting all errors. Default is to return after the first error.

@@ -22,3 +22,5 @@ # JSON Schema validation keywords

- [additionalItems](#additionalitems)
- [contains](#contains) (added in draft-06)
- [contains](#contains)
- [maxContains/minContains](#maxcontains--mincontains)
- [unevaluatedItems](#unevaluateditems) (NEW: added in draft 2019-09)
- [Keywords for objects](#keywords-for-objects)

@@ -30,4 +32,7 @@ - [maxProperties/minProperties](#maxproperties--minproperties)

- [additionalProperties](#additionalproperties)
- [dependencies](#dependencies)
- [propertyNames](#propertynames) (added in draft-06)
- [dependencies](#dependencies) (deprecated from draft 2019-09)
- [dependentRequired](#dependentrequired) (NEW: added in draft 2019-09)
- [dependentSchemas](#dependentschemas) (NEW: added in draft 2019-09)
- [propertyNames](#propertynames)
- [unevaluatedProperties](#unevaluatedproperties) (NEW: added in draft 2019-09)
- [Keywords for all types](#keywords-for-all-types)

@@ -41,3 +46,3 @@ - [enum](#enum)

- [allOf](#allof)
- [if/then/else](#ifthenelse) (NEW in draft-07)
- [if/then/else](#ifthenelse)

@@ -302,2 +307,70 @@ ## `type`

### `maxContains` / `minContains`
The value of these keywords should be an integer.
Without `contains` keyword they are ignored (logs error or throws exception in ajv [strict mode](./strict-mode.md)).
The array is valid if it contains at least `minContains` items and no more than `maxContains` items that are valid against the schema in `contains` keyword.
**Example**
_schema_:
```javascript
{
type: "array",
contains: {type: "integer"},
minContains: 2,
maxContains: 3
}
```
_valid_: `[1, 2]`, `[1, 2, 3, "foo"]`, any array with 2 or 3 integers
_invalid_: `[]`, `[1, "foo"]`, `[1, 2, 3, 4]`, any array with fewer than 2 or more than 3 integers
### `unevaluatedItems`
The value of this keyword is a JSON Schema (can be a boolean).
This schema will be applied to all array items that were not evaluated by other keywords for items (`items`, `additionalItems` and `contains`) in the current schema and all sub-schemas that were valid for this data instance. It includes:
- all subschemas schemas in `allOf` and `$ref` keywords
- valid sub-schemas in `oneOf` and `anyOf` keywords
- sub-schema in `if` keyword
- sub-schemas in `then` or `else` keywords that were applied based on the validation result by `if` keyword.
The only scenario when this keyword would be applied to some items is when `items` keyword value is an array of schemas and `additionalItems` was not present (or did not apply, in case it was present in some invalid subschema).
Some user-defined keywords can also make items "evaluated".
**Example**
_schema_:
```javascript
{
type: "array",
items: [
{type: "number"},
{type: "number"}
],
unevaluatedItems: false,
anyOf: [
{items: [true, true, {type: "number"}]},
{items: [true, true, {type: "boolean"}]}
]
}
```
_valid_: `[1, 2, 3]`, `[1, 2, true]`
_invalid_:
- `[1, 2]` - the third item is not present
- `[1, 2, "3"]` - the third item is "unevaluated"
See [tests](https://github.com/json-schema-org/JSON-Schema-Test-Suite/blob/master/tests/draft2019-09/unevaluatedItems.json) for `unevaluatedItems` keyword for other examples.
## Keywords for objects

@@ -465,4 +538,6 @@

The value of the keyword is a map with keys equal to data object properties. Each value in the map should be either an array of unique property names ("property dependency") or a JSON Schema ("schema dependency").
This keyword is deprecated. The same functionality is available with keywords `dependentRequired` and `dependentSchemas`.
The value of the keyword is a map with keys equal to data object properties. Each value in the map should be either an array of unique property names ("property dependency" - see [`dependentRequired`](#`dependentrequired`) keyword) or a JSON Schema ("schema dependency" - see [`dependentSchemas`](#`dependentschemas`) keyword).
For property dependency, if the data object contains a property that is a key in the keyword value, then to be valid the data object should also contain all properties from the array of properties.

@@ -489,3 +564,3 @@

2) _schema (schema dependency)_:
2. _schema (schema dependency)_:

@@ -509,2 +584,52 @@ ```javascript

### `dependentRequired`
The value of this keyword should be a map with keys equal to data object properties. Each value in the map should be an array of unique property names.
If the data object contains a property that is a key in the keyword value, then to be valid the data object should also contain all properties from the corresponding array of properties in this keyword.
**Example**
_schema_:
```javascript
{
type: "object",
dependentRequired: {
foo: ["bar", "baz"]
}
}
```
_valid_: `{foo: 1, bar: 2, baz: 3}`, `{}`, `{a: 1}`
_invalid_: `{foo: 1}`, `{foo: 1, bar: 2}`, `{foo: 1, baz: 3}`
### `dependentSchemas`
The value of the keyword should be a map with keys equal to data object properties. Each value in the map should be a JSON Schema.
If the data object contains a property that is a key in the keyword value, then to be valid the data object itself (NOT the property value) should be valid according to the corresponding schema in this keyword.
**Example**
_schema_:
```javascript
{
type: "object",
dependentSchemas: {
foo: {
properties: {
bar: {type: "number"}
}
}
}
}
```
_valid_: `{}`, `{foo: 1}`, `{foo: 1, bar: 2}`, `{a: 1}`
_invalid_: `{foo: 1, bar: "a"}`
### `propertyNames`

@@ -533,2 +658,48 @@

### `unevaluatedProperties`
The value of this keyword is a JSON Schema (can be a boolean).
This schema will be applied to all properties that were not evaluated by other keywords for properties (`properties`, `patternProperties` and `additionalProperties`) in the current schema and all sub-schemas that were valid for this data instance. It includes:
- all subschemas schemas in `allOf` and `$ref` keywords
- valid sub-schemas in `oneOf` and `anyOf` keywords
- sub-schema in `if` keyword
- sub-schemas in `then` or `else` keywords that were applied based on the validation result by `if` keyword.
Some user-defined keywords can also make properties "evaluated".
**Example**
_schema_:
```javascript
{
type: "object",
required: ["foo"],
properties: {foo: {type: "number"}},
unevaluatedProperties: false,
anyOf: [
{
required: ["bar"],
properties: {bar: {type: "number"}}
}
{
required: ["baz"],
properties: {baz: {type: "number"}}
}
]
}
```
_valid_: `{foo: 1, bar: 2}`, `{foo: 1, baz: 2}`, `{foo: 1, bar: 2, baz: 3}`
_invalid_:
- `{foo: 1}` - neither `bar` nor `baz` are present
- `{foo: 1, bar: 2, boo: 3}` - `boo` is unevaluated
- `{foo: 1, bar: 2, baz: "3"}` - not valid against the 2nd subschema, so `baz` is "unevaluated".
See [tests](https://github.com/json-schema-org/JSON-Schema-Test-Suite/blob/master/tests/draft2019-09/unevaluatedProperties.json) for `unevaluatedProperties` keyword for other examples.
## Keywords for all types

@@ -535,0 +706,0 @@

@@ -11,2 +11,3 @@ ## Strict mode

- ignored "if", "then", "else" keywords
- ignored "contains", "maxContains" and "minContains" keywords
- unknown formats

@@ -58,2 +59,10 @@ - ignored defaults

#### Prohibit ignored "contains", "maxContains" and "minContains" keywords
JSON Schema sections [6.4.4, 6.4.5](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.4.4) require to ignore keywords "maxContains" and "minContains" if "contains" keyword is absent.
It is also implied that when "minContains" is 0 and "maxContains" is absent, "contains" keyword is always valid.
By default Ajv fails schema compilation in these cases.
#### Prohibit unknown formats

@@ -60,0 +69,0 @@

@@ -62,2 +62,4 @@ export {

import {metadataVocabulary, contentVocabulary} from "./vocabularies/metadata"
import nextVocabulary from "./vocabularies/next"
import unevaluatedVocabulary from "./vocabularies/unevaluated"
import {eachItem} from "./compile/util"

@@ -95,2 +97,4 @@ import $dataRefSchema from "./refs/data.json"

// validation and reporting options:
next?: boolean
unevaluated?: boolean
$data?: boolean

@@ -280,2 +284,4 @@ allErrors?: boolean

this.addVocabulary(contentVocabulary)
if (opts.next) this.addVocabulary(nextVocabulary)
if (opts.unevaluated) this.addVocabulary(unevaluatedVocabulary)
addDefaultMetaSchema.call(this)

@@ -282,0 +288,0 @@ if (opts.keywords) addInitialKeywords.call(this, opts.keywords)

@@ -10,3 +10,3 @@ import type {

import {checkDataTypes, DataType} from "./validate/dataType"
import {schemaRefOrVal, unescapeJsonPointer} from "./util"
import {schemaRefOrVal, unescapeJsonPointer, mergeEvaluated} from "./util"
import {

@@ -170,5 +170,24 @@ reportError,

subschema(appl: SubschemaArgs, valid: Name): void {
applySubschema(this.it, appl, valid)
subschema(appl: SubschemaArgs, valid: Name): SchemaCxt {
return applySubschema(this.it, appl, valid)
}
mergeEvaluated(schemaCxt: SchemaCxt, toName?: typeof Name): void {
const {it, gen} = this
if (!it.opts.unevaluated) return
if (it.props !== true && schemaCxt.props !== undefined) {
it.props = mergeEvaluated.props(gen, schemaCxt.props, it.props, toName)
}
if (it.items !== true && schemaCxt.items !== undefined) {
it.items = mergeEvaluated.items(gen, schemaCxt.items, it.items, toName)
}
}
mergeValidEvaluated(schemaCxt: SchemaCxt, valid: Name): boolean | void {
const {it, gen} = this
if (it.opts.unevaluated && (it.props !== true || it.items !== true)) {
gen.if(valid, () => this.mergeEvaluated(schemaCxt, Name))
return true
}
}
}

@@ -175,0 +194,0 @@

@@ -1,2 +0,9 @@

import type {AnySchema, AnySchemaObject, AnyValidateFunction, AsyncValidateFunction} from "../types"
import type {
AnySchema,
AnySchemaObject,
AnyValidateFunction,
AsyncValidateFunction,
EvaluatedProperties,
EvaluatedItems,
} from "../types"
import type Ajv from "../ajv"

@@ -30,2 +37,3 @@ import type {InstanceOptions} from "../ajv"

readonly validateName: Name
evaluated?: Name
readonly ValidationError?: Name

@@ -45,2 +53,4 @@ readonly schema: AnySchema // current schema object - equal to parentSchema passed via KeywordCxt

// You only need to use it if you have many steps in your keywords and potentially can define multiple errors.
props?: EvaluatedProperties | Name // properties evaluated by this schema - used by parent schema or assigned to validation function
items?: EvaluatedItems | Name // last item evaluated by this schema - used by parent schema or assigned to validation function
readonly createErrors?: boolean

@@ -158,2 +168,11 @@ readonly opts: InstanceOptions // Ajv instance option.

}
if (this.opts.unevaluated) {
const {props, items} = schemaCxt
validate.evaluated = {
props: props instanceof Name ? undefined : props,
items: items instanceof Name ? undefined : items,
dynamicProps: props instanceof Name,
dynamicItems: items instanceof Name,
}
}
sch.validate = validate

@@ -160,0 +179,0 @@ return sch

@@ -44,3 +44,3 @@ import type {AddedKeywordDefinition} from "../types"

types: {...groups, integer: true, boolean: true, null: true},
rules: [groups.number, groups.string, groups.array, groups.object, {rules: []}],
rules: [groups.number, groups.string, {rules: []}, groups.array, groups.object],
all: {type: true, $comment: true},

@@ -47,0 +47,0 @@ keywords: {type: true, $comment: true},

import type {AnySchema} from "../types"
import type {SchemaObjCxt} from "./index"
import type {SchemaObjCxt, SchemaCxt} from "./index"
import {subschemaCode} from "./validate"

@@ -52,8 +52,9 @@ import {escapeFragment, escapeJsonPointer} from "./util"

export function applySubschema(it: SchemaObjCxt, appl: SubschemaArgs, valid: Name): void {
export function applySubschema(it: SchemaObjCxt, appl: SubschemaArgs, valid: Name): SchemaCxt {
const subschema = getSubschema(it, appl)
extendSubschemaData(subschema, it, appl)
extendSubschemaMode(subschema, appl)
const nextContext = {...it, ...subschema}
const nextContext = {...it, ...subschema, items: undefined, props: undefined}
subschemaCode(nextContext, valid)
return nextContext
}

@@ -60,0 +61,0 @@

@@ -1,4 +0,4 @@

import type {AnySchema} from "../types"
import type {AnySchema, EvaluatedProperties, EvaluatedItems} from "../types"
import type {SchemaCxt, SchemaObjCxt} from "."
import {_, getProperty, Code} from "./codegen"
import {_, getProperty, Code, Name, CodeGen} from "./codegen"
import type {Rule, ValidationRules} from "./rules"

@@ -102,1 +102,88 @@ import {checkStrictMode} from "./validate"

}
type SomeEvaluated = EvaluatedProperties | EvaluatedItems
type MergeEvaluatedFunc<T extends SomeEvaluated> = (
gen: CodeGen,
from: Name | T,
to: Name | Exclude<T, true> | undefined,
toName?: typeof Name
) => Name | T
interface MakeMergeFuncArgs<T extends SomeEvaluated> {
mergeNames: (gen: CodeGen, from: Name, to: Name) => void
mergeToName: (gen: CodeGen, from: T, to: Name) => void
mergeValues: (from: T, to: Exclude<T, true>) => T
resultToName: (gen: CodeGen, res?: T) => Name
}
function makeMergeEvaluated<T extends SomeEvaluated>({
mergeNames,
mergeToName,
mergeValues,
resultToName,
}: MakeMergeFuncArgs<T>): MergeEvaluatedFunc<T> {
return (gen, from, to, toName) => {
const res =
to === undefined
? from
: to instanceof Name
? (from instanceof Name ? mergeNames(gen, from, to) : mergeToName(gen, from, to), to)
: from instanceof Name
? (mergeToName(gen, to, from), from)
: mergeValues(from, to)
return toName === Name && !(res instanceof Name) ? resultToName(gen, res) : res
}
}
interface MergeEvaluated {
props: MergeEvaluatedFunc<EvaluatedProperties>
items: MergeEvaluatedFunc<EvaluatedItems>
}
export const mergeEvaluated: MergeEvaluated = {
props: makeMergeEvaluated({
mergeNames: (gen, from, to) =>
gen.if(_`${to} !== true && ${from} !== undefined`, () => {
gen.if(
_`${from} === true`,
() => gen.assign(to, true),
() => gen.code(_`Object.assign(${to}, ${from})`)
)
}),
mergeToName: (gen, from, to) =>
gen.if(_`${to} !== true`, () => {
if (from === true) {
gen.assign(to, true)
} else {
gen.assign(to, _`${to} || {}`)
setEvaluated(gen, to, from)
}
}),
mergeValues: (from, to) => (from === true ? true : {...from, ...to}),
resultToName: evaluatedPropsToName,
}),
items: makeMergeEvaluated({
mergeNames: (gen, from, to) =>
gen.if(_`${to} !== true && ${from} !== undefined`, () =>
gen.assign(to, _`${from} === true ? true : ${to} > ${from} ? ${to} : ${from}`)
),
mergeToName: (gen, from, to) =>
gen.if(_`${to} !== true`, () =>
gen.assign(to, from === true ? true : _`${to} > ${from} ? ${to} : ${from}`)
),
mergeValues: (from, to) => (from === true ? true : Math.max(from, to)),
resultToName: (gen, items) => gen.var("items", items),
}),
}
export function evaluatedPropsToName(gen: CodeGen, ps?: EvaluatedProperties): Name {
if (ps === true) return gen.var("props", true)
const props = gen.var("props", _`{}`)
if (ps !== undefined) setEvaluated(gen, props, ps)
return props
}
export function setEvaluated(gen: CodeGen, props: Name, ps: {[K in string]?: true}): void {
Object.keys(ps).forEach((p) => gen.assign(_`${props}${getProperty(p)}`, true))
}

@@ -69,2 +69,3 @@ import type {AnySchema} from "../../types"

gen.let(N.errors, 0)
if (opts.unevaluated) resetEvaluated(it)
typeAndKeywords(it)

@@ -76,2 +77,10 @@ returnResults(it)

function resetEvaluated(it: SchemaObjCxt): void {
// TODO maybe some hook to execute it in the end to check whether props/items are Name, as in assignEvaluated
const {gen, validateName} = it
it.evaluated = gen.const("evaluated", _`${validateName}.evaluated`)
gen.if(_`${it.evaluated}.dynamicProps`, () => gen.assign(_`${it.evaluated}.props`, _`undefined`))
gen.if(_`${it.evaluated}.dynamicItems`, () => gen.assign(_`${it.evaluated}.items`, _`undefined`))
}
function funcSourceUrl(schema: AnySchema, opts: InstanceOptions): Code {

@@ -160,4 +169,6 @@ return typeof schema == "object" && schema.$id && (opts.code.source || opts.code.process)

function returnResults({gen, schemaEnv, validateName, ValidationError}: SchemaCxt): void {
function returnResults(it: SchemaCxt): void {
const {gen, schemaEnv, validateName, ValidationError, opts} = it
if (schemaEnv.$async) {
// TODO assign unevaluated
gen.if(

@@ -170,2 +181,3 @@ _`${N.errors} === 0`,

gen.assign(_`${validateName}.errors`, N.vErrors)
if (opts.unevaluated) assignEvaluated(it)
gen.return(_`${N.errors} === 0`)

@@ -175,2 +187,7 @@ }

function assignEvaluated({gen, evaluated, props, items}: SchemaCxt): void {
if (props instanceof Name) gen.assign(_`${evaluated}.props`, props)
if (items instanceof Name) gen.assign(_`${evaluated}.items`, items)
}
export function checkStrictMode(it: SchemaCxt, msg: string, mode = it.opts.strict): void {

@@ -177,0 +194,0 @@ if (!mode) return

@@ -49,2 +49,3 @@ import type {CodeGen, Code, Name, Scope} from "../compile/codegen"

errors?: null | ErrorObject[]
evaluated?: Evaluated
schema: AnySchema

@@ -55,2 +56,15 @@ schemaEnv: SchemaEnv

export type EvaluatedProperties = {[K in string]?: true} | true
export type EvaluatedItems = number | true
export interface Evaluated {
// determined at compile time if staticProps/Items is true
props?: EvaluatedProperties
items?: EvaluatedItems
// whether props/items determined at compile time
dynamicProps: boolean
dynamicItems: boolean
}
export interface AsyncValidateFunction<T = unknown> extends ValidateFunction<T> {

@@ -57,0 +71,0 @@ (...args: Parameters<ValidateFunction<T>>): Promise<T>

@@ -23,3 +23,2 @@ import type {CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition} from "../../types"

const {gen, schema, parentSchema, data, it} = cxt
const len = gen.const("len", _`${data}.length`)
const {items} = parentSchema

@@ -30,2 +29,4 @@ if (!Array.isArray(items)) {

}
it.items = true
const len = gen.const("len", _`${data}.length`)
if (schema === false) {

@@ -32,0 +33,0 @@ cxt.setParams({len: items.length})

@@ -35,2 +35,3 @@ import type {

const {allErrors, opts} = it
it.props = true
if (opts.removeAdditional !== "all" && alwaysValidSchema(it, schema)) return

@@ -40,3 +41,3 @@ const props = allSchemaProperties(parentSchema.properties)

checkAdditionalProperties()
if (!allErrors) gen.if(_`${errsCount} === ${N.errors}`)
cxt.ok(_`${errsCount} === ${N.errors}`)

@@ -43,0 +44,0 @@ function checkAdditionalProperties(): void {

@@ -15,4 +15,5 @@ import type {CodeKeywordDefinition, AnySchema} from "../../types"

if (alwaysValidSchema(it, sch)) return
cxt.subschema({keyword: "allOf", schemaProp: i}, valid)
const schCxt = cxt.subschema({keyword: "allOf", schemaProp: i}, valid)
cxt.ok(valid)
cxt.mergeEvaluated(schCxt)
})

@@ -19,0 +20,0 @@ },

@@ -15,3 +15,3 @@ import type {CodeKeywordDefinition, AnySchema} from "../../types"

const alwaysValid = schema.some((sch: AnySchema) => alwaysValidSchema(it, sch))
if (alwaysValid) return
if (alwaysValid && !it.opts.unevaluated) return

@@ -21,5 +21,5 @@ const valid = gen.let("valid", false)

gen.block(() => {
gen.block(() =>
schema.forEach((_sch: AnySchema, i: number) => {
cxt.subschema(
const schCxt = cxt.subschema(
{

@@ -33,5 +33,8 @@ keyword: "anyOf",

gen.assign(valid, _`${valid} || ${schValid}`)
gen.if(not(valid))
const merged = cxt.mergeValidEvaluated(schCxt, schValid)
// can short-circuit if `unevaluatedProperties/Items` not supported (opts.unevaluated !== true)
// or if all properties and items were evaluated (it.props === true && it.items === true)
if (!merged) gen.if(not(valid))
})
}, schema.length)
)

@@ -38,0 +41,0 @@ cxt.result(

@@ -1,7 +0,19 @@

import type {CodeKeywordDefinition} from "../../types"
import type {CodeKeywordDefinition, KeywordErrorDefinition, ErrorObject} from "../../types"
import type KeywordCxt from "../../compile/context"
import {_} from "../../compile/codegen"
import {_, str, Name} from "../../compile/codegen"
import {Type} from "../../compile/subschema"
import {alwaysValidSchema} from "../../compile/util"
import {checkStrictMode} from "../../compile/validate"
export type ContainsError = ErrorObject<"contains", {minContains: number; maxContains?: number}>
const error: KeywordErrorDefinition = {
message: ({params: {min, max}}) =>
max === undefined
? str`should contain at least ${min} valid item(s)`
: str`should contain at least ${min} and no more than ${max} valid item(s)`,
params: ({params: {min, max}}) =>
max === undefined ? _`{minContains: ${min}}` : _`{minContains: ${min}, maxContains: ${max}}`,
}
const def: CodeKeywordDefinition = {

@@ -13,31 +25,72 @@ keyword: "contains",

trackErrors: true,
error,
code(cxt: KeywordCxt) {
const {gen, schema, data, it} = cxt
const {gen, schema, parentSchema, data, it} = cxt
let min: number
let max: number | undefined
const {minContains, maxContains} = parentSchema
if (it.opts.next) {
min = minContains === undefined ? 1 : minContains
max = maxContains
} else {
min = 1
}
const len = gen.const("len", _`${data}.length`)
cxt.setParams({min, max})
if (max === undefined && min === 0) {
checkStrictMode(it, `"minContains" == 0 without "maxContains": "contains" keyword ignored`)
return
}
if (max !== undefined && min > max) {
checkStrictMode(it, `"minContains" > "maxContains" is always invalid`)
cxt.fail()
return
}
if (alwaysValidSchema(it, schema)) {
cxt.fail(_`${data}.length === 0`)
let cond = _`${len} >= ${min}`
if (max !== undefined) cond = _`${cond} && ${len} <= ${max}`
cxt.pass(cond)
return
}
it.items = true
const valid = gen.name("valid")
gen.forRange("i", 0, _`${data}.length`, (i) => {
cxt.subschema(
{
keyword: "contains",
dataProp: i,
dataPropType: Type.Num,
compositeRule: true,
},
valid
)
gen.if(valid, () => gen.break())
})
if (max === undefined && min === 1) {
validateItems(valid, () => gen.if(valid, () => gen.break()))
} else {
gen.let(valid, false)
const schValid = gen.name("_valid")
const count = gen.let("count", 0)
validateItems(schValid, () => gen.if(schValid, () => checkLimits(count)))
}
cxt.result(valid, () => cxt.reset())
cxt.result(valid, () => cxt.reset())
function validateItems(_valid: Name, block: () => void): void {
gen.forRange("i", 0, len, (i) => {
cxt.subschema(
{
keyword: "contains",
dataProp: i,
dataPropType: Type.Num,
compositeRule: true,
},
_valid
)
block()
})
}
function checkLimits(count: Name): void {
gen.code(_`${count}++`)
if (max === undefined) {
gen.if(_`${count} >= ${min}`, () => gen.assign(valid, true).break())
} else {
gen.if(_`${count} > ${max}`, () => gen.assign(valid, false).break())
if (min === 1) gen.assign(valid, true)
else gen.if(_`${count} >= ${min}`, () => gen.assign(valid, true))
}
}
},
error: {
message: "should contain a valid item",
},
}
export default def

@@ -29,3 +29,3 @@ import type {

const error: KeywordErrorDefinition = {
export const error: KeywordErrorDefinition = {
message: ({params: {property, depsCount, deps}}) => {

@@ -48,59 +48,66 @@ const property_ies = depsCount === 1 ? "property" : "properties"

code(cxt: KeywordCxt) {
const {gen, schema, data, it} = cxt
const [propDeps, schDeps] = splitDependencies()
const valid = gen.name("valid")
validatePropertyDeps(propDeps)
validateSchemaDeps(schDeps)
const [propDeps, schDeps] = splitDependencies(cxt)
validatePropertyDeps(cxt, propDeps)
validateSchemaDeps(cxt, schDeps)
},
}
function splitDependencies(): [PropertyDependencies, SchemaDependencies] {
const propertyDeps: PropertyDependencies = {}
const schemaDeps: SchemaDependencies = {}
for (const key in schema) {
if (key === "__proto__") continue
const deps = Array.isArray(schema[key]) ? propertyDeps : schemaDeps
deps[key] = schema[key]
}
return [propertyDeps, schemaDeps]
}
function splitDependencies({schema}: KeywordCxt): [PropertyDependencies, SchemaDependencies] {
const propertyDeps: PropertyDependencies = {}
const schemaDeps: SchemaDependencies = {}
for (const key in schema) {
if (key === "__proto__") continue
const deps = Array.isArray(schema[key]) ? propertyDeps : schemaDeps
deps[key] = schema[key]
}
return [propertyDeps, schemaDeps]
}
function validatePropertyDeps(propertyDeps: {[x: string]: string[]}): void {
if (Object.keys(propertyDeps).length === 0) return
const missing = gen.let("missing")
for (const prop in propertyDeps) {
const deps = propertyDeps[prop]
if (deps.length === 0) continue
const hasProperty = propertyInData(data, prop, it.opts.ownProperties)
cxt.setParams({
property: prop,
depsCount: deps.length,
deps: deps.join(", "),
})
if (it.allErrors) {
gen.if(hasProperty, () => {
for (const depProp of deps) {
checkReportMissingProp(cxt, depProp)
}
})
} else {
gen.if(_`${hasProperty} && (${checkMissingProp(cxt, deps, missing)})`)
reportMissingProp(cxt, missing)
gen.else()
export function validatePropertyDeps(
cxt: KeywordCxt,
propertyDeps: {[x: string]: string[]} = cxt.schema
): void {
const {gen, data, it} = cxt
if (Object.keys(propertyDeps).length === 0) return
const missing = gen.let("missing")
for (const prop in propertyDeps) {
const deps = propertyDeps[prop]
if (deps.length === 0) continue
const hasProperty = propertyInData(data, prop, it.opts.ownProperties)
cxt.setParams({
property: prop,
depsCount: deps.length,
deps: deps.join(", "),
})
if (it.allErrors) {
gen.if(hasProperty, () => {
for (const depProp of deps) {
checkReportMissingProp(cxt, depProp)
}
}
})
} else {
gen.if(_`${hasProperty} && (${checkMissingProp(cxt, deps, missing)})`)
reportMissingProp(cxt, missing)
gen.else()
}
}
}
function validateSchemaDeps(schemaDeps: SchemaMap): void {
for (const prop in schemaDeps) {
if (alwaysValidSchema(it, schemaDeps[prop] as AnySchema)) continue
gen.if(
propertyInData(data, prop, it.opts.ownProperties),
() => cxt.subschema({keyword: "dependencies", schemaProp: prop}, valid),
() => gen.var(valid, true) // TODO var
)
cxt.ok(valid)
}
}
},
export function validateSchemaDeps(cxt: KeywordCxt, schemaDeps: SchemaMap = cxt.schema): void {
const {gen, data, keyword, it} = cxt
const valid = gen.name("valid")
for (const prop in schemaDeps) {
if (alwaysValidSchema(it, schemaDeps[prop] as AnySchema)) continue
gen.if(
propertyInData(data, prop, it.opts.ownProperties),
() => {
const schCxt = cxt.subschema({keyword, schemaProp: prop}, valid)
cxt.mergeValidEvaluated(schCxt, valid)
},
() => gen.var(valid, true) // TODO var
)
cxt.ok(valid)
}
}
export default def

@@ -47,3 +47,3 @@ import type {CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition} from "../../types"

function validateIf(): void {
cxt.subschema(
const schCxt = cxt.subschema(
{

@@ -57,2 +57,3 @@ keyword: "if",

)
cxt.mergeEvaluated(schCxt)
}

@@ -62,4 +63,5 @@

return () => {
cxt.subschema({keyword}, schValid)
const schCxt = cxt.subschema({keyword}, schValid)
gen.assign(valid, schValid)
cxt.mergeValidEvaluated(schCxt, valid)
if (ifClause) gen.assign(ifClause, _`${keyword}`)

@@ -66,0 +68,0 @@ else cxt.setParams({ifClause: keyword})

import type {ErrorObject, Vocabulary} from "../../types"
import additionalItems, {AdditionalItemsError} from "./additionalItems"
import items from "./items"
import contains from "./contains"
import contains, {ContainsError} from "./contains"
import dependencies, {DependenciesError} from "./dependencies"

@@ -18,2 +18,9 @@ import propertyNames, {PropertyNamesError} from "./propertyNames"

const applicator: Vocabulary = [
// any
notKeyword,
anyOf,
oneOf,
allOf,
ifKeyword,
thenElse,
// array

@@ -24,14 +31,7 @@ additionalItems,

// object
dependencies,
propertyNames,
additionalProperties,
dependencies,
properties,
patternProperties,
// any
notKeyword,
anyOf,
oneOf,
allOf,
ifKeyword,
thenElse,
]

@@ -44,2 +44,3 @@

| AdditionalItemsError
| ContainsError
| AdditionalPropertiesError

@@ -52,4 +53,4 @@ | DependenciesError

export type ErrorWithoutParams = ErrorObject<
"anyOf" | "contains" | "not" | "false schema",
"anyOf" | "not" | "false schema",
Record<string, never>
>

@@ -5,3 +5,3 @@ import type {CodeKeywordDefinition, AnySchema} from "../../types"

import {Type} from "../../compile/subschema"
import {alwaysValidSchema} from "../../compile/util"
import {alwaysValidSchema, mergeEvaluated} from "../../compile/util"
import {checkStrictMode} from "../../compile/validate"

@@ -18,5 +18,9 @@

if (Array.isArray(schema)) {
if (it.opts.unevaluated && schema.length && it.items !== true) {
it.items = mergeEvaluated.items(gen, schema.length, it.items)
}
validateTuple(schema)
} else if (!alwaysValidSchema(it, schema)) {
validateArray()
} else {
it.items = true
if (!alwaysValidSchema(it, schema)) validateArray()
}

@@ -23,0 +27,0 @@

@@ -8,4 +8,5 @@ import type {

import type KeywordCxt from "../../compile/context"
import {_} from "../../compile/codegen"
import {_, Name} from "../../compile/codegen"
import {alwaysValidSchema} from "../../compile/util"
import {SchemaCxt} from "../../compile"

@@ -45,6 +46,7 @@ export type OneOfError = ErrorObject<"oneOf", {passingSchemas: [number, number]}>

schArr.forEach((sch: AnySchema, i: number) => {
let schCxt: SchemaCxt | undefined
if (alwaysValidSchema(it, sch)) {
gen.var(schValid, true)
} else {
cxt.subschema(
schCxt = cxt.subschema(
{

@@ -67,3 +69,7 @@ keyword: "oneOf",

gen.if(schValid, () => gen.assign(valid, true).assign(passing, i))
gen.if(schValid, () => {
gen.assign(valid, true)
gen.assign(passing, i)
if (schCxt) cxt.mergeEvaluated(schCxt, Name)
})
})

@@ -70,0 +76,0 @@ }

import type {CodeKeywordDefinition} from "../../types"
import type KeywordCxt from "../../compile/context"
import {schemaProperties, usePattern} from "../code"
import {_, not} from "../../compile/codegen"
import {_, not, Name} from "../../compile/codegen"
import {Type} from "../../compile/subschema"
import {checkStrictMode} from "../../compile/validate"
import {evaluatedPropsToName} from "../../compile/util"

@@ -16,5 +17,10 @@ const def: CodeKeywordDefinition = {

const patterns = schemaProperties(it, schema)
// TODO mark properties matching patterns with always valid schemas as evaluated
if (patterns.length === 0) return
const checkProperties = opts.strict && !opts.allowMatchingProperties && parentSchema.properties
const valid = gen.name("valid")
if (it.props !== true && !(it.props instanceof Name)) {
it.props = evaluatedPropsToName(gen, it.props)
}
const {props} = it
validatePatternProperties()

@@ -59,3 +65,9 @@

)
if (!it.allErrors) gen.if(not(valid), () => gen.break())
if (it.opts.unevaluated && props !== true) {
gen.assign(_`${props}[${key}]`, true)
} else if (!it.allErrors) {
// can short-circuit if `unevaluatedProperties` is not supported (opts.next === false)
// or if all properties were evaluated (props === true)
gen.if(not(valid), () => gen.break())
}
})

@@ -62,0 +74,0 @@ })

import type {CodeKeywordDefinition} from "../../types"
import KeywordCxt from "../../compile/context"
import {propertyInData, schemaProperties} from "../code"
import {propertyInData, allSchemaProperties} from "../code"
import {alwaysValidSchema, toHash, mergeEvaluated} from "../../compile/util"
import apDef from "./additionalProperties"

@@ -15,3 +16,7 @@

}
const properties = schemaProperties(it, schema)
const allProps = allSchemaProperties(schema)
if (it.opts.unevaluated && allProps.length && it.props !== true) {
it.props = mergeEvaluated.props(gen, toHash(allProps), it.props)
}
const properties = allProps.filter((p) => !alwaysValidSchema(it, schema[p]))
if (properties.length === 0) return

@@ -18,0 +23,0 @@ const valid = gen.name("valid")

@@ -8,2 +8,3 @@ import type {CodeKeywordDefinition, AnySchema} from "../../types"

import {SchemaEnv, resolveRef} from "../../compile"
import {mergeEvaluated} from "../../compile/util"

@@ -24,5 +25,5 @@ const def: CodeKeywordDefinition = {

function callRootRef(): void {
if (env === env.root) return callRef(validateName, env.$async)
if (env === env.root) return callRef(validateName, env, env.$async)
const rootName = gen.scopeValue("root", {ref: env.root})
return callRef(_`${rootName}.validate`, env.root.$async)
return callRef(_`${rootName}.validate`, env.root, env.root.$async)
}

@@ -39,8 +40,8 @@

}
callRef(v, sch.$async)
callRef(v, sch, sch.$async)
}
function callRef(v: Code, $async?: boolean): void {
if ($async) callAsyncRef(v)
else callSyncRef(v)
function callRef(v: Code, sch: SchemaEnv, $async?: boolean): void {
if ($async) callAsyncRef(v, sch)
else callSyncRef(v, sch)
}

@@ -51,3 +52,3 @@

const valid = gen.name("valid")
cxt.subschema(
const schCxt = cxt.subschema(
{

@@ -63,6 +64,7 @@ schema: sch,

)
cxt.mergeEvaluated(schCxt)
cxt.ok(valid)
}
function callAsyncRef(v: Code): void {
function callAsyncRef(v: Code, sch: SchemaEnv): void {
if (!env.$async) throw new Error("async schema referenced by sync schema")

@@ -73,2 +75,3 @@ const valid = gen.let("valid")

gen.code(_`await ${callValidateCode(cxt, v, passCxt)}`)
addEvaluatedFrom(v, sch)
if (!allErrors) gen.assign(valid, true)

@@ -85,4 +88,8 @@ },

function callSyncRef(v: Code): void {
cxt.pass(callValidateCode(cxt, v, passCxt), () => addErrorsFrom(v))
function callSyncRef(v: Code, sch: SchemaEnv): void {
cxt.result(
callValidateCode(cxt, v, passCxt),
() => addEvaluatedFrom(v, sch),
() => addErrorsFrom(v)
)
}

@@ -95,2 +102,28 @@

}
function addEvaluatedFrom(source: Code, sch: SchemaEnv): void {
if (!it.opts.unevaluated) return
const schEvaluated = sch.validate?.evaluated
// TODO refactor
if (it.props !== true) {
if (schEvaluated && !schEvaluated.dynamicProps) {
if (schEvaluated.props !== undefined) {
it.props = mergeEvaluated.props(gen, schEvaluated.props, it.props)
}
} else {
const props = gen.var("props", _`${source}.evaluated.props`)
it.props = mergeEvaluated.props(gen, props, it.props, Name)
}
}
if (it.items !== true) {
if (schEvaluated && !schEvaluated.dynamicItems) {
if (schEvaluated.items !== undefined) {
it.items = mergeEvaluated.items(gen, schEvaluated.items, it.items)
}
} else {
const items = gen.var("items", _`${source}.evaluated.items`)
it.items = mergeEvaluated.items(gen, items, it.items, Name)
}
}
}
},

@@ -97,0 +130,0 @@ }

@@ -5,3 +5,13 @@ import type {TypeError} from "../compile/validate/dataType"

import type {FormatError} from "./format/format"
import type {UnevaluatedPropertiesError} from "./applicator/unevaluatedProperties"
import type {UnevaluatedItemsError} from "./applicator/unevaluatedItems"
import type {DependentRequiredError} from "./validation/dependentRequired"
export type DefinedError = TypeError | ApplicatorKeywordError | ValidationKeywordError | FormatError
export type DefinedError =
| TypeError
| ApplicatorKeywordError
| ValidationKeywordError
| FormatError
| UnevaluatedPropertiesError
| UnevaluatedItemsError
| DependentRequiredError

@@ -22,2 +22,3 @@ import type {CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition} from "../../types"

})
// TODO optimize for scalar values in schema
cxt.fail$data(_`!${eql}(${cxt.data}, ${cxt.schemaCode})`)

@@ -24,0 +25,0 @@ },

{
"name": "ajv",
"version": "7.0.0-beta.2",
"version": "7.0.0-beta.3",
"description": "Another JSON Schema Validator",

@@ -5,0 +5,0 @@ "main": "dist/ajv.js",

@@ -9,3 +9,3 @@ <img align="right" alt="Ajv logo" width="160" src="https://ajv.js.org/images/ajv_logo.png">

[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)
[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.2)
[![npm (beta)](https://img.shields.io/npm/v/ajv/beta)](https://www.npmjs.com/package/ajv/v/7.0.0-beta.3)
[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)

@@ -12,0 +12,0 @@ [![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)

@@ -6,2 +6,3 @@ "use strict"

draft7: "spec/JSON-Schema-Test-Suite/tests/draft7/",
draft2019: "spec/JSON-Schema-Test-Suite/tests/draft2019-09/",
tests: "spec/tests/",

@@ -8,0 +9,0 @@ security: "spec/security/",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc