diff --git a/.eslintrc.yml b/.eslintrc.yml index f8ed3b2c3..7fc6b7b44 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,6 +1,7 @@ extends: eslint:recommended parserOptions: ecmaVersion: 6 + sourceType: module env: node: true browser: true @@ -24,7 +25,6 @@ rules: no-trailing-spaces: 2 no-use-before-define: [2, nofunc] semi: 0 - strict: [2, global] valid-jsdoc: [2, requireReturn: false] no-control-regex: 0 no-useless-escape: 2 diff --git a/lib/ajv.js b/lib/ajv.js index 32147440d..cf3264541 100644 --- a/lib/ajv.js +++ b/lib/ajv.js @@ -1,5 +1,3 @@ -"use strict" - var compileSchema = require("./compile"), resolve = require("./compile/resolve"), Cache = require("./cache"), @@ -27,10 +25,10 @@ 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 +Ajv.prototype.addKeyword = customKeyword.addKeyword +Ajv.prototype.getKeyword = customKeyword.getKeyword +Ajv.prototype.removeKeyword = customKeyword.removeKeyword +Ajv.prototype.validateKeyword = customKeyword.validateKeyword var errorClasses = require("./compile/error_classes") Ajv.ValidationError = errorClasses.Validation diff --git a/lib/cache.js b/lib/cache.js index 2539362d2..b970862ef 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -1,5 +1,3 @@ -"use strict" - module.exports = Cache function Cache() { diff --git a/lib/compile/async.js b/lib/compile/async.js index bb758d767..270b9df07 100644 --- a/lib/compile/async.js +++ b/lib/compile/async.js @@ -1,5 +1,3 @@ -"use strict" - var MissingRefError = require("./error_classes").MissingRef module.exports = compileAsync diff --git a/lib/compile/equal.js b/lib/compile/equal.js index 4d060f849..b67591643 100644 --- a/lib/compile/equal.js +++ b/lib/compile/equal.js @@ -1,5 +1,3 @@ -"use strict" - // do NOT remove this file - it would break pre-compiled schemas // https://github.com/ajv-validator/ajv/issues/889 module.exports = require("fast-deep-equal") diff --git a/lib/compile/error_classes.js b/lib/compile/error_classes.js index cd6f59a5f..32cdf81e9 100644 --- a/lib/compile/error_classes.js +++ b/lib/compile/error_classes.js @@ -1,5 +1,3 @@ -"use strict" - var resolve = require("./resolve") module.exports = { diff --git a/lib/compile/index.js b/lib/compile/index.js index 2eb4750d2..3757e6d2c 100644 --- a/lib/compile/index.js +++ b/lib/compile/index.js @@ -1,5 +1,3 @@ -"use strict" - var resolve = require("./resolve"), util = require("./util"), errorClasses = require("./error_classes"), diff --git a/lib/compile/resolve.js b/lib/compile/resolve.js index 73891d270..78e270825 100644 --- a/lib/compile/resolve.js +++ b/lib/compile/resolve.js @@ -1,5 +1,3 @@ -"use strict" - var URI = require("uri-js"), equal = require("fast-deep-equal"), util = require("./util"), diff --git a/lib/compile/rules.js b/lib/compile/rules.js index b54dc2dca..12ffa6630 100644 --- a/lib/compile/rules.js +++ b/lib/compile/rules.js @@ -1,5 +1,3 @@ -"use strict" - var ruleModules = require("../dotjs"), toHash = require("./util").toHash @@ -9,16 +7,14 @@ module.exports = function rules() { type: "number", rules: ["multipleOf", "format"], }, - {type: "string", rules: ["maxLength", "minLength", "pattern", "format"]}, + {type: "string", rules: ["pattern", "format"]}, { type: "array", - rules: ["maxItems", "minItems", "items", "contains", "uniqueItems"], + rules: ["items", "contains", "uniqueItems"], }, { type: "object", rules: [ - "maxProperties", - "minProperties", "required", "dependencies", "propertyNames", diff --git a/lib/compile/schema_obj.js b/lib/compile/schema_obj.js index 0d771e545..41dfb69ef 100644 --- a/lib/compile/schema_obj.js +++ b/lib/compile/schema_obj.js @@ -1,5 +1,3 @@ -"use strict" - var util = require("./util") module.exports = SchemaObject diff --git a/lib/compile/ucs2length.js b/lib/compile/ucs2length.js index 81cee8b8c..935703e5e 100644 --- a/lib/compile/ucs2length.js +++ b/lib/compile/ucs2length.js @@ -1,5 +1,3 @@ -"use strict" - // https://mathiasbynens.be/notes/javascript-encoding // https://github.com/bestiejs/punycode.js - punycode.ucs2.decode module.exports = function ucs2length(str) { diff --git a/lib/compile/util.js b/lib/compile/util.js index e4930cb6d..e1fdc1851 100644 --- a/lib/compile/util.js +++ b/lib/compile/util.js @@ -1,5 +1,3 @@ -"use strict" - module.exports = { copy: copy, checkDataType: checkDataType, @@ -25,6 +23,8 @@ module.exports = { escapeJsonPointer: escapeJsonPointer, appendSchema: ($data, schemaCode) => $data ? `" + ${schemaCode}` : `${schemaCode}"`, + concatSchema: ($data, schemaCode) => + $data ? `" + ${schemaCode} + "` : schemaCode, dataNotType: ($data, schemaCode, schemaType) => $data ? `(${schemaCode}!==undefined && typeof ${schemaCode}!=="${schemaType}") || ` diff --git a/lib/data.js b/lib/data.js index 69b55b2b5..76b6b92e9 100644 --- a/lib/data.js +++ b/lib/data.js @@ -1,5 +1,3 @@ -"use strict" - // TODO use $data in keyword definitions var KEYWORDS = [ "multipleOf", diff --git a/lib/definition_schema.js b/lib/definition_schema.js index e82c4bbbc..18b0f2552 100644 --- a/lib/definition_schema.js +++ b/lib/definition_schema.js @@ -1,5 +1,3 @@ -"use strict" - var metaSchema = require("./refs/json-schema-draft-07.json") module.exports = { diff --git a/lib/dot/_limitItems.jst b/lib/dot/_limitItems.jst deleted file mode 100644 index 741329e77..000000000 --- a/lib/dot/_limitItems.jst +++ /dev/null @@ -1,12 +0,0 @@ -{{# def.definitions }} -{{# def.errors }} -{{# def.setupKeyword }} -{{# def.$data }} - -{{# def.numberKeyword }} - -{{ var $op = $keyword == 'maxItems' ? '>' : '<'; }} -if ({{# def.$dataNotType:'number' }} {{=$data}}.length {{=$op}} {{=$schemaValue}}) { - {{ var $errorKeyword = $keyword; }} - {{# def.error:'_limitItems' }} -} {{? $breakOnError }} else { {{?}} diff --git a/lib/dot/_limitLength.jst b/lib/dot/_limitLength.jst deleted file mode 100644 index 285c66bd2..000000000 --- a/lib/dot/_limitLength.jst +++ /dev/null @@ -1,12 +0,0 @@ -{{# def.definitions }} -{{# def.errors }} -{{# def.setupKeyword }} -{{# def.$data }} - -{{# def.numberKeyword }} - -{{ var $op = $keyword == 'maxLength' ? '>' : '<'; }} -if ({{# def.$dataNotType:'number' }} {{# def.strLength }} {{=$op}} {{=$schemaValue}}) { - {{ var $errorKeyword = $keyword; }} - {{# def.error:'_limitLength' }} -} {{? $breakOnError }} else { {{?}} diff --git a/lib/dot/_limitProperties.jst b/lib/dot/_limitProperties.jst deleted file mode 100644 index c4c21551a..000000000 --- a/lib/dot/_limitProperties.jst +++ /dev/null @@ -1,12 +0,0 @@ -{{# def.definitions }} -{{# def.errors }} -{{# def.setupKeyword }} -{{# def.$data }} - -{{# def.numberKeyword }} - -{{ var $op = $keyword == 'maxProperties' ? '>' : '<'; }} -if ({{# def.$dataNotType:'number' }} Object.keys({{=$data}}).length {{=$op}} {{=$schemaValue}}) { - {{ var $errorKeyword = $keyword; }} - {{# def.error:'_limitProperties' }} -} {{? $breakOnError }} else { {{?}} diff --git a/lib/dot/errors.def b/lib/dot/errors.def index 99f93e245..3090a24ee 100644 --- a/lib/dot/errors.def +++ b/lib/dot/errors.def @@ -101,10 +101,6 @@ 'enum': "'should be equal to one of the allowed values'", format: "'should match format \"{{#def.concatSchemaEQ}}\"'", 'if': "'should match \"' + {{=$ifClause}} + '\" schema'", - _exclusiveLimit: "'should be {{=$op}} {{#def.appendSchema}}", - _limitItems: "'should NOT have {{?$keyword=='maxItems'}}more{{??}}fewer{{?}} than {{#def.concatSchema}} items'", - _limitLength: "'should NOT be {{?$keyword=='maxLength'}}longer{{??}}shorter{{?}} than {{#def.concatSchema}} characters'", - _limitProperties:"'should NOT have {{?$keyword=='maxProperties'}}more{{??}}fewer{{?}} than {{#def.concatSchema}} properties'", multipleOf: "'should be multiple of {{#def.appendSchema}}", not: "'should NOT be valid'", oneOf: "'should match exactly one schema in oneOf'", @@ -135,9 +131,6 @@ 'enum': "validate.schema{{=$schemaPath}}", format: "{{#def.schemaRefOrQS}}", 'if': "validate.schema{{=$schemaPath}}", - _limitItems: "{{#def.schemaRefOrVal}}", - _limitLength: "{{#def.schemaRefOrVal}}", - _limitProperties:"{{#def.schemaRefOrVal}}", multipleOf: "{{#def.schemaRefOrVal}}", not: "validate.schema{{=$schemaPath}}", oneOf: "validate.schema{{=$schemaPath}}", @@ -167,9 +160,6 @@ 'enum': "{ allowedValues: schema{{=$lvl}} }", format: "{ format: {{#def.schemaValueQS}} }", 'if': "{ failingKeyword: {{=$ifClause}} }", - _limitItems: "{ limit: {{=$schemaValue}} }", - _limitLength: "{ limit: {{=$schemaValue}} }", - _limitProperties:"{ limit: {{=$schemaValue}} }", multipleOf: "{ multipleOf: {{=$schemaValue}} }", not: "{}", oneOf: "{ passingSchemas: {{=$passingSchemas}} }", diff --git a/lib/dotjs/index.js b/lib/dotjs/index.js index 93da591c0..42e0d193b 100644 --- a/lib/dotjs/index.js +++ b/lib/dotjs/index.js @@ -12,12 +12,6 @@ module.exports = { format: require("./format"), if: require("./if"), items: require("./items"), - maxItems: require("./_limitItems"), - minItems: require("./_limitItems"), - maxLength: require("./_limitLength"), - minLength: require("./_limitLength"), - maxProperties: require("./_limitProperties"), - minProperties: require("./_limitProperties"), multipleOf: require("./multipleOf"), not: require("./not"), oneOf: require("./oneOf"), diff --git a/lib/keyword.js b/lib/keyword.js index 8ac16af1a..14a809e2d 100644 --- a/lib/keyword.js +++ b/lib/keyword.js @@ -3,13 +3,6 @@ var customRuleCode = require("./dotjs/custom") var definitionSchema = require("./definition_schema") var util = require("./compile/util") -module.exports = { - add: addKeyword, - get: getKeyword, - remove: removeKeyword, - validate: validateKeyword, -} - /** * Define custom keyword * @this Ajv @@ -18,7 +11,7 @@ module.exports = { * @param {Boolean} _skipValidation of keyword definition * @return {Ajv} this for method chaining */ -function addKeyword(keyword, definition, _skipValidation) { +export function addKeyword(keyword, definition, _skipValidation) { /* jshint validthis: true */ /* eslint no-shadow: 0 */ var RULES = this.RULES @@ -116,7 +109,7 @@ function ruleCode(it, keyword /*, ruleType */) { schemaCode = schemaRefOrVal() } const data = "data" + (it.dataLevel || "") - const cxt = {fail, keyword, data, $data, schemaCode, schemaType} + const cxt = {fail, keyword, data, $data, schemaCode, opts: it.opts} // TODO check that code called "fail" or another valid way to return code code(cxt) return out @@ -173,7 +166,7 @@ function ruleCode(it, keyword /*, ruleType */) { * @param {String} keyword pre-defined or custom keyword. * @return {Object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise. */ -function getKeyword(keyword) { +export function getKeyword(keyword) { /* jshint validthis: true */ var rule = this.RULES.custom[keyword] return rule ? rule.definition : this.RULES.keywords[keyword] || false @@ -185,7 +178,7 @@ function getKeyword(keyword) { * @param {String} keyword pre-defined or custom keyword. * @return {Ajv} this for method chaining */ -function removeKeyword(keyword) { +export function removeKeyword(keyword) { /* jshint validthis: true */ var RULES = this.RULES delete RULES.keywords[keyword] @@ -210,7 +203,7 @@ function removeKeyword(keyword) { * @param {Boolean} throwError true to throw exception if definition is invalid * @return {boolean} validation result */ -function validateKeyword(definition, throwError) { +export function validateKeyword(definition, throwError) { validateKeyword.errors = null var v = (this._validateKeyword = this._validateKeyword || this.compile(definitionSchema, true)) diff --git a/lib/keywords/const.js b/lib/keywords/const.js index 6ac308eb1..c5e2f09b5 100644 --- a/lib/keywords/const.js +++ b/lib/keywords/const.js @@ -4,6 +4,6 @@ module.exports = { code: ({fail, data, schemaCode}) => fail(`!equal(${data}, ${schemaCode})`), error: { message: () => '"should be equal to constant"', - params: ({schemaCode}) => `{ allowedValue: ${schemaCode} }`, + params: ({schemaCode}) => `{allowedValue: ${schemaCode}}`, }, } diff --git a/lib/keywords/index.js b/lib/keywords/index.js index f756f9773..efc0c0db1 100644 --- a/lib/keywords/index.js +++ b/lib/keywords/index.js @@ -4,4 +4,10 @@ module.exports = { exclusiveMinimum: require("./limit"), maximum: require("./limit"), minimum: require("./limit"), + maxItems: require("./limitItems"), + minItems: require("./limitItems"), + maxProperties: require("./limitProperties"), + minProperties: require("./limitProperties"), + maxLength: require("./limitLength"), + minLength: require("./limitLength"), } diff --git a/lib/keywords/limit.js b/lib/keywords/limit.js index 41db52a61..09f03be6e 100644 --- a/lib/keywords/limit.js +++ b/lib/keywords/limit.js @@ -7,19 +7,21 @@ const OPS = { exclusiveMinimum: {fail: "<=", ok: ">"}, } +const SCHEMA_TYPE = "number" + module.exports = { keywords: ["maximum", "minimum", "exclusiveMaximum", "exclusiveMinimum"], type: "number", - schemaType: "number", + schemaType: SCHEMA_TYPE, $data: true, - code: ({keyword, fail, data, $data, schemaCode, schemaType}) => { - const dnt = dataNotType($data, schemaCode, schemaType) + code({fail, keyword, data, $data, schemaCode}) { + const dnt = dataNotType($data, schemaCode, SCHEMA_TYPE) fail(dnt + data + OPS[keyword].fail + schemaCode + ` || ${data}!==${data}`) }, error: { message: ({keyword, $data, schemaCode}) => `"should be ${OPS[keyword].ok} ${appendSchema($data, schemaCode)}`, params: ({keyword, schemaCode}) => - `{ comparison: "${OPS[keyword].ok}", limit: ${schemaCode} }`, + `{comparison: "${OPS[keyword].ok}", limit: ${schemaCode}}`, }, } diff --git a/lib/keywords/limitItems.js b/lib/keywords/limitItems.js new file mode 100644 index 000000000..a62a43725 --- /dev/null +++ b/lib/keywords/limitItems.js @@ -0,0 +1,23 @@ +const {concatSchema, dataNotType} = require("../compile/util") + +const SCHEMA_TYPE = "number" + +module.exports = { + keywords: ["maxItems", "minItems"], + type: "array", + schemaType: SCHEMA_TYPE, + $data: true, + code({fail, keyword, data, $data, schemaCode}) { + const op = keyword == "maxItems" ? ">" : "<" + const dnt = dataNotType($data, schemaCode, SCHEMA_TYPE) + fail(dnt + `${data}.length` + op + schemaCode) + }, + error: { + message({keyword, $data, schemaCode}) { + const comp = keyword == "maxItems" ? "more" : "fewer" + const sch = concatSchema($data, schemaCode) + return `"should NOT have ${comp} than ${sch} items"` + }, + params: ({schemaCode}) => `{limit: ${schemaCode}}`, + }, +} diff --git a/lib/keywords/limitLength.js b/lib/keywords/limitLength.js new file mode 100644 index 000000000..1b865f739 --- /dev/null +++ b/lib/keywords/limitLength.js @@ -0,0 +1,25 @@ +const {concatSchema, dataNotType} = require("../compile/util") + +const SCHEMA_TYPE = "number" + +module.exports = { + keywords: ["maxLength", "minLength"], + type: "string", + schemaType: SCHEMA_TYPE, + $data: true, + code({fail, keyword, data, $data, schemaCode, opts}) { + const op = keyword == "maxLength" ? ">" : "<" + const dnt = dataNotType($data, schemaCode, SCHEMA_TYPE) + const len = + opts.unicode === false ? `${data}.length` : `ucs2length(${data})` + fail(dnt + len + op + schemaCode) + }, + error: { + message({keyword, $data, schemaCode}) { + const comp = keyword == "maxLength" ? "more" : "fewer" + const sch = concatSchema($data, schemaCode) + return `"should NOT have ${comp} than ${sch} items"` + }, + params: ({schemaCode}) => `{limit: ${schemaCode}}`, + }, +} diff --git a/lib/keywords/limitProperties.js b/lib/keywords/limitProperties.js new file mode 100644 index 000000000..86d42066a --- /dev/null +++ b/lib/keywords/limitProperties.js @@ -0,0 +1,23 @@ +const {concatSchema, dataNotType} = require("../compile/util") + +const SCHEMA_TYPE = "number" + +module.exports = { + keywords: ["maxProperties", "minProperties"], + type: "object", + schemaType: SCHEMA_TYPE, + $data: true, + code({fail, keyword, data, $data, schemaCode}) { + const op = keyword == "maxProperties" ? ">" : "<" + const dnt = dataNotType($data, schemaCode, SCHEMA_TYPE) + fail(dnt + `Object.keys(${data}).length` + op + schemaCode) + }, + error: { + message({keyword, $data, schemaCode}) { + const comp = keyword == "maxProperties" ? "more" : "fewer" + const sch = concatSchema($data, schemaCode) + return `"should NOT have ${comp} than ${sch} items"` + }, + params: ({schemaCode}) => `{limit: ${schemaCode}}`, + }, +} diff --git a/package.json b/package.json index f75db5577..6b1141c5d 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "bundle": "del-cli dist && node ./scripts/bundle.js . Ajv pure_getters", "bundle-beautify": "node ./scripts/bundle.js js-beautify", "dot": "del-cli lib/dotjs/*.js \"!lib/dotjs/index.js\" && node scripts/compile-dots.js", - "tsc": "tsc && cp -r lib/refs dist/refs", + "tsc": "tsc || true && cp -r lib/refs dist/refs", "build": "npm run dot && npm run tsc", "test-karma": "karma start", "test-browser": "del-cli .browser && npm run bundle && scripts/prepare-tests && npm run test-karma", @@ -72,6 +72,7 @@ }, "devDependencies": { "@ajv-validator/config": "^0.1.0", + "@types/node": "^14.0.27", "ajv-async": "^1.0.0", "ajv-formats": "^0.1.0", "bluebird": "^3.5.3", diff --git a/scripts/.eslintrc.yml b/scripts/.eslintrc.yml index 493d7d312..16d8b308a 100644 --- a/scripts/.eslintrc.yml +++ b/scripts/.eslintrc.yml @@ -1,3 +1,5 @@ +parserOptions: + sourceType: script rules: no-console: 0 no-empty: [2, allowEmptyCatch: true] diff --git a/spec/.eslintrc.yml b/spec/.eslintrc.yml index f9c66d538..6ba17543a 100644 --- a/spec/.eslintrc.yml +++ b/spec/.eslintrc.yml @@ -1,3 +1,5 @@ +parserOptions: + sourceType: script rules: no-console: 0 no-empty: [2, allowEmptyCatch: true] diff --git a/tsconfig.json b/tsconfig.json index a151db8a5..24a0045bd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,9 @@ "compilerOptions": { "outDir": "dist", "lib": ["ES2018", "DOM"], + "types": ["node"], "noImplicitAny": false, + "noImplicitThis": false, "allowJs": true, "declaration": false }