pax_global_header00006660000000000000000000000064141465200100014503gustar00rootroot0000000000000052 comment=7703b7826a284b851edb6f0004d997e8bbe2581c ajv-keywords-5.1.0/000077500000000000000000000000001414652001000141335ustar00rootroot00000000000000ajv-keywords-5.1.0/.eslintrc.js000066400000000000000000000011301414652001000163650ustar00rootroot00000000000000const jsConfig = require("@ajv-validator/config/.eslintrc_js") const tsConfig = require("@ajv-validator/config/.eslintrc") module.exports = { env: { es6: true, node: true, }, overrides: [ jsConfig, { ...tsConfig, files: ["*.ts"], rules: { ...tsConfig.rules, complexity: ["error", 18], "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-unnecessary-condition": "warn", "@typescript-eslint/no-unsafe-assignment": "off", "@typescript-eslint/no-unsafe-member-access": "off", }, }, ], } ajv-keywords-5.1.0/.github/000077500000000000000000000000001414652001000154735ustar00rootroot00000000000000ajv-keywords-5.1.0/.github/FUNDING.yml000066400000000000000000000000611414652001000173050ustar00rootroot00000000000000github: epoberezkin tidelift: "npm/ajv-keywords" ajv-keywords-5.1.0/.github/dependabot.yml000066400000000000000000000006241414652001000203250ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: npm directory: "/" schedule: interval: daily open-pull-requests-limit: 10 ignore: - dependency-name: "@types/node" versions: - 15.0.0 - dependency-name: eslint-config-prettier versions: - 8.0.0 - 8.1.0 - 8.2.0 - dependency-name: husky versions: - 5.0.9 - 5.1.0 - 5.1.1 - 5.1.2 - 5.1.3 - 5.2.0 ajv-keywords-5.1.0/.github/workflows/000077500000000000000000000000001414652001000175305ustar00rootroot00000000000000ajv-keywords-5.1.0/.github/workflows/build.yml000066400000000000000000000011061414652001000213500ustar00rootroot00000000000000name: build on: push: branches: [master] pull_request: branches: ["*"] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [10.x, 12.x, 14.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm install - run: npm test - name: Coveralls uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} ajv-keywords-5.1.0/.github/workflows/publish.yml000066400000000000000000000012461414652001000217240ustar00rootroot00000000000000name: publish on: release: types: [published] jobs: publish-npm: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: node-version: 14 registry-url: https://registry.npmjs.org/ - run: npm install - run: npm test - name: Publish beta version to npm if: "github.event.release.prerelease" run: npm publish --tag beta env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Publish to npm if: "!github.event.release.prerelease" run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ajv-keywords-5.1.0/.gitignore000066400000000000000000000011271414652001000161240ustar00rootroot00000000000000 package-lock.json # Logs logs *.log npm-debug.log* # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory node_modules # Optional npm cache directory .npm # Optional REPL history .node_repl_history .DS_Store # IDE .idea *.iml # compiled JS dist ajv-keywords-5.1.0/.prettierignore000066400000000000000000000000161414652001000171730ustar00rootroot00000000000000dist coverage ajv-keywords-5.1.0/CODE_OF_CONDUCT.md000066400000000000000000000064361414652001000167430ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: - Using welcoming and inclusive language - Being respectful of differing viewpoints and experiences - Gracefully accepting constructive criticism - Focusing on what is best for the community - Showing empathy towards other community members Examples of unacceptable behavior by participants include: - The use of sexualized language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or electronic address, without explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at ajv.validator@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq ajv-keywords-5.1.0/LICENSE000066400000000000000000000020741414652001000151430ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2016 Evgeny Poberezkin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ajv-keywords-5.1.0/README.md000066400000000000000000000574501414652001000154250ustar00rootroot00000000000000# ajv-keywords Custom JSON-Schema keywords for [Ajv](https://github.com/epoberezkin/ajv) validator [![build](https://github.com/ajv-validator/ajv-keywords/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv-keywords/actions?query=workflow%3Abuild) [![npm](https://img.shields.io/npm/v/ajv-keywords.svg)](https://www.npmjs.com/package/ajv-keywords) [![npm downloads](https://img.shields.io/npm/dm/ajv-keywords.svg)](https://www.npmjs.com/package/ajv-keywords) [![coverage](https://coveralls.io/repos/github/ajv-validator/ajv-keywords/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv-keywords?branch=master) [![gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv) **Please note**: This readme file is for [ajv-keywords v5.0.0](https://github.com/ajv-validator/ajv-keywords/releases/tag/v5.0.0) that should be used with [ajv v8](https://github.com/ajv-validator/ajv). [ajv-keywords v3](https://github.com/ajv-validator/ajv-keywords/tree/v3) should be used with [ajv v6](https://github.com/ajv-validator/ajv/tree/v6). ## Contents - [Install](#install) - [Usage](#usage) - [Keywords](#keywords) - [Types](#types) - [typeof](#typeof) - [instanceof](#instanceof)\+ - [Keywords for numbers](#keywords-for-numbers) - [range and exclusiveRange](#range-and-exclusiverange) - [Keywords for strings](#keywords-for-strings) - [regexp](#regexp) - [transform](#transform)\* - [Keywords for arrays](#keywords-for-arrays) - [uniqueItemProperties](#uniqueitemproperties)\+ - [Keywords for objects](#keywords-for-objects) - [allRequired](#allrequired) - [anyRequired](#anyrequired) - [oneRequired](#onerequired) - [patternRequired](#patternrequired) - [prohibited](#prohibited) - [deepProperties](#deepproperties) - [deepRequired](#deeprequired) - [dynamicDefaults](#dynamicdefaults)\*\+ - [Keywords for all types](#keywords-for-all-types) - [select/selectCases/selectDefault](#selectselectcasesselectdefault) - [Security contact](#security-contact) - [Open-source software support](#open-source-software-support) - [License](#license) \* - keywords that modify data \+ - keywords that are not supported in [standalone validation code](https://github.com/ajv-validator/ajv/blob/master/docs/standalone.md) ## Install To install version 4 to use with [Ajv v7](https://github.com/ajv-validator/ajv): ``` npm install ajv-keywords ``` ## Usage To add all available keywords: ```javascript const Ajv = require("ajv") const ajv = new Ajv() require("ajv-keywords")(ajv) ajv.validate({instanceof: "RegExp"}, /.*/) // true ajv.validate({instanceof: "RegExp"}, ".*") // false ``` To add a single keyword: ```javascript require("ajv-keywords")(ajv, "instanceof") ``` To add multiple keywords: ```javascript require("ajv-keywords")(ajv, ["typeof", "instanceof"]) ``` To add a single keyword directly (to avoid adding unused code): ```javascript require("ajv-keywords/dist/keywords/select")(ajv, opts) ``` To add all keywords via Ajv options: ```javascript const ajv = new Ajv({keywords: require("ajv-keywords/dist/definitions")(opts)}) ``` To add one or several keywords via options: ```javascript const ajv = new Ajv({ keywords: [ require("ajv-keywords/dist/definitions/typeof")(), require("ajv-keywords/dist/definitions/instanceof")(), // select exports an array of 3 definitions - see "select" in docs ...require("ajv-keywords/dist/definitions/select")(opts), ], }) ``` `opts` is an optional object with a property `defaultMeta` - URI of meta-schema to use for keywords that use subschemas (`select` and `deepProperties`). The default is `"http://json-schema.org/schema"`. ## Keywords ### Types #### `typeof` Based on JavaScript `typeof` operation. The value of the keyword should be a string (`"undefined"`, `"string"`, `"number"`, `"object"`, `"function"`, `"boolean"` or `"symbol"`) or an array of strings. To pass validation the result of `typeof` operation on the value should be equal to the string (or one of the strings in the array). ```javascript ajv.validate({typeof: "undefined"}, undefined) // true ajv.validate({typeof: "undefined"}, null) // false ajv.validate({typeof: ["undefined", "object"]}, null) // true ``` #### `instanceof` Based on JavaScript `instanceof` operation. The value of the keyword should be a string (`"Object"`, `"Array"`, `"Function"`, `"Number"`, `"String"`, `"Date"`, `"RegExp"` or `"Promise"`) or an array of strings. To pass validation the result of `data instanceof ...` operation on the value should be true: ```javascript ajv.validate({instanceof: "Array"}, []) // true ajv.validate({instanceof: "Array"}, {}) // false ajv.validate({instanceof: ["Array", "Function"]}, function () {}) // true ``` You can add your own constructor function to be recognised by this keyword: ```javascript class MyClass {} const instanceofDef = require("ajv-keywords/dist/definitions/instanceof") instanceofDef.CONSTRUCTORS.MyClass = MyClass ajv.validate({instanceof: "MyClass"}, new MyClass()) // true ``` **Please note**: currently `instanceof` is not supported in [standalone validation code](https://github.com/ajv-validator/ajv/blob/master/docs/standalone.md) - it has to be implemented as [`code` keyword](https://github.com/ajv-validator/ajv/blob/master/docs/keywords.md#define-keyword-with-code-generation-function) to support it (PR is welcome). ### Keywords for numbers #### `range` and `exclusiveRange` Syntax sugar for the combination of minimum and maximum keywords (or exclusiveMinimum and exclusiveMaximum), also fails schema compilation if there are no numbers in the range. The value of these keywords must be an array consisting of two numbers, the second must be greater or equal than the first one. If the validated value is not a number the validation passes, otherwise to pass validation the value should be greater (or equal) than the first number and smaller (or equal) than the second number in the array. ```javascript const schema = {type: "number", range: [1, 3]} ajv.validate(schema, 1) // true ajv.validate(schema, 2) // true ajv.validate(schema, 3) // true ajv.validate(schema, 0.99) // false ajv.validate(schema, 3.01) // false const schema = {type: "number", exclusiveRange: [1, 3]} ajv.validate(schema, 1.01) // true ajv.validate(schema, 2) // true ajv.validate(schema, 2.99) // true ajv.validate(schema, 1) // false ajv.validate(schema, 3) // false ``` ### Keywords for strings #### `regexp` This keyword allows to use regular expressions with flags in schemas, and also without `"u"` flag when needed (the standard `pattern` keyword does not support flags and implies the presence of `"u"` flag). This keyword applies only to strings. If the data is not a string, the validation succeeds. The value of this keyword can be either a string (the result of `regexp.toString()`) or an object with the properties `pattern` and `flags` (the same strings that should be passed to RegExp constructor). ```javascript const schema = { type: "object", properties: { foo: {type: "string", regexp: "/foo/i"}, bar: {type: "string", regexp: {pattern: "bar", flags: "i"}}, }, } const validData = { foo: "Food", bar: "Barmen", } const invalidData = { foo: "fog", bar: "bad", } ``` #### `transform` This keyword allows a string to be modified during validation. This keyword applies only to strings. If the data is not a string, the `transform` keyword is ignored. A standalone string cannot be modified, i.e. `data = 'a'; ajv.validate(schema, data);`, because strings are passed by value **Supported transformations:** - `trim`: remove whitespace from start and end - `trimStart`/`trimLeft`: remove whitespace from start - `trimEnd`/`trimRight`: remove whitespace from end - `toLowerCase`: convert to lower case - `toUpperCase`: convert to upper case - `toEnumCase`: change string case to be equal to one of `enum` values in the schema Transformations are applied in the order they are listed. Note: `toEnumCase` requires that all allowed values are unique when case insensitive. **Example: multiple transformations** ```javascript require("ajv-keywords")(ajv, "transform") const schema = { type: "array", items: { type: "string", transform: ["trim", "toLowerCase"], }, } const data = [" MixCase "] ajv.validate(schema, data) console.log(data) // ['mixcase'] ``` **Example: `enumcase`** ```javascript require("ajv-keywords")(ajv, ["transform"]) const schema = { type: "array", items: { type: "string", transform: ["trim", "toEnumCase"], enum: ["pH"], }, } const data = ["ph", " Ph", "PH", "pH "] ajv.validate(schema, data) console.log(data) // ['pH','pH','pH','pH'] ``` ### Keywords for arrays #### `uniqueItemProperties` The keyword allows to check that some properties in array items are unique. This keyword applies only to arrays. If the data is not an array, the validation succeeds. The value of this keyword must be an array of strings - property names that should have unique values across all items. ```javascript const schema = { type: "array", uniqueItemProperties: ["id", "name"], } const validData = [{id: 1}, {id: 2}, {id: 3}] const invalidData1 = [ {id: 1}, {id: 1}, // duplicate "id" {id: 3}, ] const invalidData2 = [ {id: 1, name: "taco"}, {id: 2, name: "taco"}, // duplicate "name" {id: 3, name: "salsa"}, ] ``` This keyword is contributed by [@blainesch](https://github.com/blainesch). **Please note**: currently `uniqueItemProperties` is not supported in [standalone validation code](https://github.com/ajv-validator/ajv/blob/master/docs/standalone.md) - it has to be implemented as [`code` keyword](https://github.com/ajv-validator/ajv/blob/master/docs/keywords.md#define-keyword-with-code-generation-function) to support it (PR is welcome). ### Keywords for objects #### `allRequired` This keyword allows to require the presence of all properties used in `properties` keyword in the same schema object. This keyword applies only to objects. If the data is not an object, the validation succeeds. The value of this keyword must be boolean. If the value of the keyword is `false`, the validation succeeds. If the value of the keyword is `true`, the validation succeeds if the data contains all properties defined in `properties` keyword (in the same schema object). If the `properties` keyword is not present in the same schema object, schema compilation will throw exception. ```javascript const schema = { type: "object", properties: { foo: {type: "number"}, bar: {type: "number"}, }, allRequired: true, } const validData = {foo: 1, bar: 2} const alsoValidData = {foo: 1, bar: 2, baz: 3} const invalidDataList = [{}, {foo: 1}, {bar: 2}] ``` #### `anyRequired` This keyword allows to require the presence of any (at least one) property from the list. This keyword applies only to objects. If the data is not an object, the validation succeeds. The value of this keyword must be an array of strings, each string being a property name. For data object to be valid at least one of the properties in this array should be present in the object. ```javascript const schema = { type: "object", anyRequired: ["foo", "bar"], } const validData = {foo: 1} const alsoValidData = {foo: 1, bar: 2} const invalidDataList = [{}, {baz: 3}] ``` #### `oneRequired` This keyword allows to require the presence of only one property from the list. This keyword applies only to objects. If the data is not an object, the validation succeeds. The value of this keyword must be an array of strings, each string being a property name. For data object to be valid exactly one of the properties in this array should be present in the object. ```javascript const schema = { type: "object", oneRequired: ["foo", "bar"], } const validData = {foo: 1} const alsoValidData = {bar: 2, baz: 3} const invalidDataList = [{}, {baz: 3}, {foo: 1, bar: 2}] ``` #### `patternRequired` This keyword allows to require the presence of properties that match some pattern(s). This keyword applies only to objects. If the data is not an object, the validation succeeds. The value of this keyword should be an array of strings, each string being a regular expression. For data object to be valid each regular expression in this array should match at least one property name in the data object. If the array contains multiple regular expressions, more than one expression can match the same property name. ```javascript const schema = { type: "object", patternRequired: ["f.*o", "b.*r"], } const validData = {foo: 1, bar: 2} const alsoValidData = {foobar: 3} const invalidDataList = [{}, {foo: 1}, {bar: 2}] ``` #### `prohibited` This keyword allows to prohibit that any of the properties in the list is present in the object. This keyword applies only to objects. If the data is not an object, the validation succeeds. The value of this keyword should be an array of strings, each string being a property name. For data object to be valid none of the properties in this array should be present in the object. ```javascript const schema = { type: "object", prohibited: ["foo", "bar"], } const validData = {baz: 1} const alsoValidData = {} const invalidDataList = [{foo: 1}, {bar: 2}, {foo: 1, bar: 2}] ``` **Please note**: `{prohibited: ['foo', 'bar']}` is equivalent to `{not: {anyRequired: ['foo', 'bar']}}` (i.e. it has the same validation result for any data). #### `deepProperties` This keyword allows to validate deep properties (identified by JSON pointers). This keyword applies only to objects. If the data is not an object, the validation succeeds. The value should be an object, where keys are JSON pointers to the data, starting from the current position in data, and the values are JSON schemas. For data object to be valid the value of each JSON pointer should be valid according to the corresponding schema. ```javascript const schema = { type: "object", deepProperties: { "/users/1/role": {enum: ["admin"]}, }, } const validData = { users: [ {}, { id: 123, role: "admin", }, ], } const alsoValidData = { users: { 1: { id: 123, role: "admin", }, }, } const invalidData = { users: [ {}, { id: 123, role: "user", }, ], } const alsoInvalidData = { users: { 1: { id: 123, role: "user", }, }, } ``` #### `deepRequired` This keyword allows to check that some deep properties (identified by JSON pointers) are available. This keyword applies only to objects. If the data is not an object, the validation succeeds. The value should be an array of JSON pointers to the data, starting from the current position in data. For data object to be valid each JSON pointer should be some existing part of the data. ```javascript const schema = { type: "object", deepRequired: ["/users/1/role"], } const validData = { users: [ {}, { id: 123, role: "admin", }, ], } const invalidData = { users: [ {}, { id: 123, }, ], } ``` See [json-schema-org/json-schema-spec#203](https://github.com/json-schema-org/json-schema-spec/issues/203#issue-197211916) for an example of the equivalent schema without `deepRequired` keyword. ### Keywords for all types #### `select`/`selectCases`/`selectDefault` **Please note**: these keywords are deprecated. It is recommended to use OpenAPI [discriminator](https://ajv.js.org/json-schema.html#discriminator) keyword supported by Ajv v8 instead of `select`. These keywords allow to choose the schema to validate the data based on the value of some property in the validated data. These keywords must be present in the same schema object (`selectDefault` is optional). The value of `select` keyword should be a [\$data reference](https://github.com/ajv-validator/ajv/blob/master/docs/validation.md#data-reference) that points to any primitive JSON type (string, number, boolean or null) in the data that is validated. You can also use a constant of primitive type as the value of this keyword (e.g., for debugging purposes). The value of `selectCases` keyword must be an object where each property name is a possible string representation of the value of `select` keyword and each property value is a corresponding schema (from draft-06 it can be boolean) that must be used to validate the data. The value of `selectDefault` keyword is a schema (also can be boolean) that must be used to validate the data in case `selectCases` has no key equal to the stringified value of `select` keyword. The validation succeeds in one of the following cases: - the validation of data using selected schema succeeds, - none of the schemas is selected for validation, - the value of select is undefined (no property in the data that the data reference points to). If `select` value (in data) is not a primitive type the validation fails. This keyword correctly tracks evaluated properties and items to work with `unevaluatedProperties` and `unevaluatedItems` keywords - only properties and items from the subschema that was used (one of `selectCases` subschemas or `selectDefault` subschema) are marked as evaluated. **Please note**: these keywords require Ajv `$data` option to support [\$data reference](https://github.com/ajv-validator/ajv/blob/master/docs/validation.md#data-reference). ```javascript require("ajv-keywords")(ajv, "select") const schema = { type: "object", required: ["kind"], properties: { kind: {type: "string"}, }, select: {$data: "0/kind"}, selectCases: { foo: { required: ["foo"], properties: { kind: {}, foo: {type: "string"}, }, additionalProperties: false, }, bar: { required: ["bar"], properties: { kind: {}, bar: {type: "number"}, }, additionalProperties: false, }, }, selectDefault: { propertyNames: { not: {enum: ["foo", "bar"]}, }, }, } const validDataList = [ {kind: "foo", foo: "any"}, {kind: "bar", bar: 1}, {kind: "anything_else", not_bar_or_foo: "any value"}, ] const invalidDataList = [ {kind: "foo"}, // no property foo {kind: "bar"}, // no property bar {kind: "foo", foo: "any", another: "any value"}, // additional property {kind: "bar", bar: 1, another: "any value"}, // additional property {kind: "anything_else", foo: "any"}, // property foo not allowed {kind: "anything_else", bar: 1}, // property bar not allowed ] ``` #### `dynamicDefaults` This keyword allows to assign dynamic defaults to properties, such as timestamps, unique IDs etc. This keyword only works if `useDefaults` options is used and not inside `anyOf` keywords etc., in the same way as [default keyword treated by Ajv](https://github.com/epoberezkin/ajv#assigning-defaults). The keyword should be added on the object level. Its value should be an object with each property corresponding to a property name, in the same way as in standard `properties` keyword. The value of each property can be: - an identifier of dynamic default function (a string) - an object with properties `func` (an identifier) and `args` (an object with parameters that will be passed to this function during schema compilation - see examples). The properties used in `dynamicDefaults` should not be added to `required` keyword in the same schema (or validation will fail), because unlike `default` this keyword is processed after validation. There are several predefined dynamic default functions: - `"timestamp"` - current timestamp in milliseconds - `"datetime"` - current date and time as string (ISO, valid according to `date-time` format) - `"date"` - current date as string (ISO, valid according to `date` format) - `"time"` - current time as string (ISO, valid according to `time` format) - `"random"` - pseudo-random number in [0, 1) interval - `"randomint"` - pseudo-random integer number. If string is used as a property value, the function will randomly return 0 or 1. If object `{ func: 'randomint', args: { max: N } }` is used then the default will be an integer number in [0, N) interval. - `"seq"` - sequential integer number starting from 0. If string is used as a property value, the default sequence will be used. If object `{ func: 'seq', args: { name: 'foo'} }` is used then the sequence with name `"foo"` will be used. Sequences are global, even if different ajv instances are used. ```javascript const schema = { type: "object", dynamicDefaults: { ts: "datetime", r: {func: "randomint", args: {max: 100}}, id: {func: "seq", args: {name: "id"}}, }, properties: { ts: { type: "string", format: "date-time", }, r: { type: "integer", minimum: 0, exclusiveMaximum: 100, }, id: { type: "integer", minimum: 0, }, }, } const data = {} ajv.validate(data) // true data // { ts: '2016-12-01T22:07:28.829Z', r: 25, id: 0 } const data1 = {} ajv.validate(data1) // true data1 // { ts: '2016-12-01T22:07:29.832Z', r: 68, id: 1 } ajv.validate(data1) // true data1 // didn't change, as all properties were defined ``` When using the `useDefaults` option value `"empty"`, properties and items equal to `null` or `""` (empty string) will be considered missing and assigned defaults. Use `allOf` [compound keyword](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#compound-keywords) to execute `dynamicDefaults` before validation. ```javascript const schema = { type: "object", allOf: [ { dynamicDefaults: { ts: "datetime", r: {func: "randomint", args: {min: 5, max: 100}}, id: {func: "seq", args: {name: "id"}}, }, }, { properties: { ts: { type: "string", }, r: { type: "number", minimum: 5, exclusiveMaximum: 100, }, id: { type: "integer", minimum: 0, }, }, }, ], } const data = {ts: "", r: null} ajv.validate(data) // true data // { ts: '2016-12-01T22:07:28.829Z', r: 25, id: 0 } ``` You can add your own dynamic default function to be recognised by this keyword: ```javascript const uuid = require("uuid") const def = require("ajv-keywords/dist/definitions/dynamicDefaults") def.DEFAULTS.uuid = () => uuid.v4 const schema = { dynamicDefaults: {id: "uuid"}, properties: {id: {type: "string", format: "uuid"}}, } const data = {} ajv.validate(schema, data) // true data // { id: 'a1183fbe-697b-4030-9bcc-cfeb282a9150' }; const data1 = {} ajv.validate(schema, data1) // true data1 // { id: '5b008de7-1669-467a-a5c6-70fa244d7209' } ``` You also can define dynamic default that accept parameters, e.g. version of uuid: ```javascript const uuid = require("uuid") function getUuid(args) { const version = "v" + ((arvs && args.v) || "4") return uuid[version] } const def = require("ajv-keywords/dist/definitions/dynamicDefaults") def.DEFAULTS.uuid = getUuid const schema = { dynamicDefaults: { id1: "uuid", // v4 id2: {func: "uuid", v: 4}, // v4 id3: {func: "uuid", v: 1}, // v1 }, } ``` **Please note**: dynamic default functions are differentiated by the number of parameters they have (`function.length`). Functions that do not expect default must have one non-optional argument so that `function.length` > 0. `dynamicDefaults` is not supported in [standalone validation code](https://github.com/ajv-validator/ajv/blob/master/docs/standalone.md). ## Security contact To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues. ## Open-source software support Ajv-keywords is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv-keywords?utm_source=npm-ajv-keywords&utm_medium=referral&utm_campaign=readme) - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers. ## License [MIT](https://github.com/epoberezkin/ajv-keywords/blob/master/LICENSE) ajv-keywords-5.1.0/jest.config.js000066400000000000000000000001561414652001000167040ustar00rootroot00000000000000module.exports = { preset: "ts-jest", testEnvironment: "node", collectCoverageFrom: ["dist/**/*.js"], } ajv-keywords-5.1.0/package.json000066400000000000000000000037701414652001000164300ustar00rootroot00000000000000{ "name": "ajv-keywords", "version": "5.1.0", "description": "Additional JSON-Schema keywords for Ajv JSON validator", "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { "build": "rm -rf dist && tsc", "prepublish": "npm run build", "prettier:write": "prettier --write \"./**/*.{md,json,yaml,js,ts}\"", "prettier:check": "prettier --list-different \"./**/*.{md,json,yaml,js,ts}\"", "test": "npm link && npm link ajv-keywords && npm run eslint && npm run test-cov", "eslint": "eslint \"src/**/*.*s\" \"spec/**/*.*s\"", "test-spec": "jest spec/*.ts", "test-cov": "jest spec/*.ts --coverage" }, "repository": { "type": "git", "url": "git+https://github.com/epoberezkin/ajv-keywords.git" }, "keywords": [ "JSON-Schema", "ajv", "keywords" ], "files": [ "src", "dist", "ajv-keywords.d.ts" ], "author": "Evgeny Poberezkin", "license": "MIT", "bugs": { "url": "https://github.com/epoberezkin/ajv-keywords/issues" }, "homepage": "https://github.com/epoberezkin/ajv-keywords#readme", "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" }, "devDependencies": { "@ajv-validator/config": "^0.2.3", "@types/chai": "^4.2.14", "@types/jest": "^26.0.14", "@types/node": "^16.4.10", "@types/uuid": "^8.3.0", "@typescript-eslint/eslint-plugin": "^4.4.1", "@typescript-eslint/parser": "^4.4.1", "ajv": "^8.8.2", "ajv-formats": "^2.0.0", "chai": "^4.2.0", "eslint": "^7.2.0", "eslint-config-prettier": "^7.0.0", "husky": "^7.0.1", "jest": "^26.5.3", "json-schema-test": "^2.0.0", "lint-staged": "^11.1.1", "prettier": "^2.1.2", "ts-jest": "^26.4.1", "typescript": "^4.2.0", "uuid": "^8.1.0" }, "prettier": "@ajv-validator/config/prettierrc.json", "husky": { "hooks": { "pre-commit": "lint-staged && npm test" } }, "lint-staged": { "*.{md,json,yaml,js,ts}": "prettier --write" } } ajv-keywords-5.1.0/spec/000077500000000000000000000000001414652001000150655ustar00rootroot00000000000000ajv-keywords-5.1.0/spec/.eslintrc.js000066400000000000000000000010061414652001000173210ustar00rootroot00000000000000module.exports = { globals: { it: false, describe: false, }, overrides: [ { files: ["*.ts"], parserOptions: { project: ["./spec/tsconfig.json"], }, rules: { "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-extraneous-class": "off", "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/no-unsafe-call": "off", }, }, ], rules: { "no-console": "off", "no-new-wrappers": "off", }, } ajv-keywords-5.1.0/spec/ajv_instances.ts000066400000000000000000000013651414652001000202710ustar00rootroot00000000000000import Ajv from "ajv" import type {Plugin, Options, KeywordDefinition} from "ajv" import type {GetDefinition} from "../dist/definitions/_types" import ajvKeywordsPlugin from "../dist" import ajvKeywords from "../dist/definitions" type GetDef = GetDefinition export default function getAjvInstances( keyword: string | string[], kwdDef: GetDef | GetDef[], kwdPlugin: Plugin, opts?: Options ): Ajv[] { return [ kwdPlugin(new Ajv(opts)), new Ajv({...opts, keywords: Array.isArray(kwdDef) ? kwdDef.map((d) => d()) : [kwdDef()]}), ajvKeywordsPlugin(new Ajv(opts), keyword), ajvKeywordsPlugin(new Ajv(opts)), new Ajv({...opts, keywords: ajvKeywords()}), new Ajv(opts).addVocabulary(ajvKeywords()), ] } ajv-keywords-5.1.0/spec/ajv_pack.ts000066400000000000000000000004011414652001000172060ustar00rootroot00000000000000import Ajv, {Options} from "ajv/dist/2019" import AjvPack from "ajv/dist/standalone/instance" export default function ajvPack(opts: Options = {}): Ajv { opts.code ||= {} opts.code.source = true return (new AjvPack(new Ajv(opts)) as unknown) as Ajv } ajv-keywords-5.1.0/spec/allRequired.spec.ts000066400000000000000000000023421414652001000206400ustar00rootroot00000000000000import allRequiredPlugin from "../dist/keywords/allRequired" import allRequiredDef from "../dist/definitions/allRequired" import getAjvInstances from "./ajv_instances" import chai from "chai" import ajvPack from "./ajv_pack" const should = chai.should() describe('keyword "allRequired"', () => { const ajvs = getAjvInstances("allRequired", allRequiredDef, allRequiredPlugin) ajvs.push(allRequiredPlugin(ajvPack())) ajvs.forEach((ajv, i) => { it(`should validate that all defined properties are present #${i}`, () => { const schema = { type: "object", properties: { foo: true, bar: true, }, allRequired: true, } ajv.validate(schema, {foo: 1, bar: 2}).should.equal(true) ajv.validate(schema, {foo: 1}).should.equal(false) }) }) ajvs.forEach((ajv, i) => { it(`should throw when properties is absent #${i}`, () => { should.throw(() => { ajv.compile({type: "object", allRequired: true}) }) }) }) ajvs.forEach((ajv, i) => { it(`should throw when allRequired schema is invalid #${i}`, () => { should.throw(() => { ajv.compile({type: "object", properties: {foo: true}, allRequired: 1}) }) }) }) }) ajv-keywords-5.1.0/spec/define_keywords.spec.ts000066400000000000000000000014301414652001000215450ustar00rootroot00000000000000import Ajv from "ajv" import ajvKeywordsPlugin from "../dist" import chai from "chai" const should = chai.should() describe("defineKeywords", () => { const ajv = new Ajv() it("should allow defining multiple keywords", () => { ajvKeywordsPlugin(ajv, ["typeof", "instanceof"]) ajv.validate({typeof: "undefined"}, undefined).should.equal(true) ajv.validate({typeof: "undefined"}, {}).should.equal(false) ajv.validate({instanceof: "Array"}, []).should.equal(true) ajv.validate({instanceof: "Array"}, {}).should.equal(false) }) it("should throw when unknown keyword is passed", () => { should.throw(() => { ajvKeywordsPlugin(ajv, "unknownKeyword") }) should.throw(() => { ajvKeywordsPlugin(ajv, ["typeof", "unknownKeyword"]) }) }) }) ajv-keywords-5.1.0/spec/dynamicDefaults.spec.ts000066400000000000000000000161431414652001000215070ustar00rootroot00000000000000import dynamicDefaults from "../dist/keywords/dynamicDefaults" import dynamicDefaultsDef from "../dist/definitions/dynamicDefaults" import getAjvInstances from "./ajv_instances" import Ajv from "ajv" import {fullFormats} from "ajv-formats/dist/formats" import chai from "chai" import assert from "assert" import {v4 as uuidv4} from "uuid" const should = chai.should() describe('keyword "dynamicDefaults"', () => { const ajvs = getAjvInstances("dynamicDefaults", dynamicDefaultsDef, dynamicDefaults, { useDefaults: true, formats: fullFormats, }) ajvs.forEach((ajv, i) => { it(`should assign defaults #${i}`, (done) => { const schema = { type: "object", dynamicDefaults: { ts: "timestamp", dt: "datetime", d: "date", t: "time", r: "random", ri: "randomint", riN: {func: "randomint", args: {max: 1000000}}, s: "seq", sN: {func: "seq", args: {name: "foo"}}, }, } const validate = ajv.compile(schema) const data: Record = {} validate(data).should.equal(true) test(data) data.s.should.equal(2 * i) data.sN.should.equal(2 * i) setTimeout(() => { const data1: Record = {} validate(data1).should.equal(true) test(data1) assert(data.ts < data1.ts) assert.notStrictEqual(data.dt, data1.dt) assert.strictEqual(data.d, data1.d) assert.notStrictEqual(data.t, data1.t) assert.notStrictEqual(data.r, data1.r) assert.notStrictEqual(data.riN, data1.riN) data1.s.should.equal(2 * i + 1) data1.sN.should.equal(2 * i + 1) done() }, 100) function test(_data: Record): void { _data.ts.should.be.a("number") assert(_data.ts <= Date.now()) ajv.validate({type: "string", format: "date-time"}, _data.dt).should.equal(true) new Date(_data.dt).should.be.a("Date") ajv.validate({type: "string", format: "date"}, _data.d).should.equal(true) new Date().toISOString().indexOf(_data.d).should.equal(0) ajv.validate({type: "string", format: "time"}, _data.t).should.equal(true) _data.r.should.be.a("number") assert(_data.r < 1) assert(_data.r >= 0) assert(_data.ri === 0 || _data.ri === 1) _data.riN.should.be.a("number") assert.strictEqual(Math.floor(_data.riN), _data.riN) assert(_data.riN < 1000000) assert(_data.riN >= 0) _data.s.should.be.a("number") _data.sN.should.be.a("number") } }) it(`should NOT assign default if property is present #${i}`, () => { const schema = { type: "object", dynamicDefaults: { ts: "timestamp", }, } const validate = ajv.compile(schema) const data = {ts: 123} validate(data).should.equal(true) data.ts.should.equal(123) }) it(`should NOT assign default inside anyOf etc. #${i}`, () => { const schema = { anyOf: [ { type: "object", dynamicDefaults: { ts: "timestamp", }, }, { type: "string", }, ], } const validate = ajv.compile(schema) const data: Record = {} validate(data).should.equal(true) should.not.exist(data.ts) }) it(`should fail schema compilation on unknown default #${i}`, () => { const schema = { type: "object", dynamicDefaults: { ts: "unknown", }, } should.throw(() => { ajv.compile(schema) }) }) it(`should allow adding dynamic default functions #${i}`, () => { const schema = { type: "object", dynamicDefaults: { id: "uuid", }, properties: { id: {type: "string"}, }, } should.throw(() => { ajv.compile(schema) }) dynamicDefaultsDef.DEFAULTS.uuid = () => uuidv4 const data: Record = {} test(data) const data1: Record = {} test(data1) assert.notStrictEqual(data.id, data1.id) delete dynamicDefaultsDef.DEFAULTS.uuid function test(_data: Record): void { ajv.validate(schema, _data).should.equal(true) ajv.validate({format: "uuid", type: "string"}, _data.id).should.equal(true) ajv.removeSchema() } }) }) it('should NOT assign defaults when useDefaults is true/"shared and properties are null, empty or contain a value"', () => { const schema = { type: "object", allOf: [ { dynamicDefaults: { ts: "datetime", r: {func: "randomint", args: {min: 5, max: 100000}}, id: {func: "seq", args: {name: "id"}}, }, }, { type: "object", properties: { ts: { type: "string", }, r: { type: "number", minimum: 5, exclusiveMaximum: 100000, }, id: { type: "integer", minimum: 0, }, }, }, ], } const data = { ts: "", r: null, id: 3, } test(new Ajv({useDefaults: true})) function test(testAjv: Ajv): void { const validate = dynamicDefaults(testAjv).compile(schema) validate(data).should.equal(false) data.ts.should.equal("") should.equal(data.r, null) data.id.should.equal(3) } }) it('should assign defaults when useDefaults = "empty" for properties that are undefined, null or empty strings', (done) => { const schema = { type: "object", allOf: [ { dynamicDefaults: { ts: "datetime", r: {func: "randomint", args: {min: 5, max: 100000}}, id: {func: "seq", args: {name: "id"}}, }, }, { type: "object", properties: { ts: { type: "string", }, r: { type: "number", minimum: 5, exclusiveMaximum: 100000, }, id: { type: "integer", minimum: 0, }, }, }, ], } const data: Record = { ts: "", r: null, } const data1: Record = Object.assign({}, data) test(new Ajv({useDefaults: "empty"})) function test(testAjv: Ajv): void { const validate = dynamicDefaults(testAjv).compile(schema) validate(data).should.equal(true) const tsRegex = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z/ data.ts.should.match(tsRegex) data.r.should.be.a("number") data.id.should.be.a("number") setTimeout(() => { validate(data1).should.equal(true) data.ts.should.not.equal(data1.ts) data1.r.should.be.a("number") //data.r and data1.r could match, but unlikely data.id.should.not.equal(data1.id) done() }, 100) } }) }) ajv-keywords-5.1.0/spec/instanceof.spec.ts000066400000000000000000000060341414652001000205220ustar00rootroot00000000000000import instanceofPlugin from "../dist/keywords/instanceof" import instanceofDef from "../dist/definitions/instanceof" import getAjvInstances from "./ajv_instances" import chai from "chai" const should = chai.should() describe('keyword "instanceof"', () => { const ajvs = getAjvInstances("instanceof", instanceofDef, instanceofPlugin) ajvs.forEach((ajv, i) => { it(`should validate classes # ${i}`, () => { ajv.validate({instanceof: "Object"}, {}).should.equal(true) ajv.validate({instanceof: "Object"}, []).should.equal(true) ajv.validate({instanceof: "Object"}, "foo").should.equal(false) ajv.validate({instanceof: "Array"}, {}).should.equal(false) ajv.validate({instanceof: "Array"}, []).should.equal(true) ajv.validate({instanceof: "Array"}, "foo").should.equal(false) ajv.validate({instanceof: "Function"}, () => {}).should.equal(true) ajv.validate({instanceof: "Function"}, []).should.equal(false) ajv.validate({instanceof: "Number"}, new Number(42)).should.equal(true) ajv.validate({instanceof: "Number"}, 42).should.equal(false) ajv.validate({instanceof: "Number"}, "foo").should.equal(false) ajv.validate({instanceof: "String"}, new String("foo")).should.equal(true) ajv.validate({instanceof: "String"}, "foo").should.equal(false) ajv.validate({instanceof: "String"}, 42).should.equal(false) ajv.validate({instanceof: "Date"}, new Date()).should.equal(true) ajv.validate({instanceof: "Date"}, {}).should.equal(false) ajv.validate({instanceof: "RegExp"}, /.*/).should.equal(true) ajv.validate({instanceof: "RegExp"}, {}).should.equal(false) ajv.validate({instanceof: "Buffer"}, new Buffer("foo")).should.equal(true) ajv.validate({instanceof: "Buffer"}, "foo").should.equal(false) ajv.validate({instanceof: "Buffer"}, {}).should.equal(false) ajv.validate({instanceof: "Buffer"}, {}).should.equal(false) ajv.validate({instanceof: "Promise"}, Promise.resolve()).should.equal(true) ajv.validate({instanceof: "Promise"}, () => {}).should.equal(false) }) it(`should validate multiple classes #${i}`, () => { ajv.validate({instanceof: ["Array", "Function"]}, []).should.equal(true) ajv.validate({instanceof: ["Array", "Function"]}, () => {}).should.equal(true) ajv.validate({instanceof: ["Array", "Function"]}, {}).should.equal(false) }) it(`should allow adding classes #${i}`, () => { class MyClass {} should.throw(() => { ajv.compile({instanceof: "MyClass"}) }) instanceofDef.CONSTRUCTORS.MyClass = MyClass ajv.validate({instanceof: "MyClass"}, new MyClass()).should.equal(true) ajv.validate({instanceof: "Object"}, new MyClass()).should.equal(true) ajv.validate({instanceof: "MyClass"}, {}).should.equal(false) delete instanceofDef.CONSTRUCTORS.MyClass ajv.removeSchema() }) it(`should throw when not string or array is passed #${i}`, () => { should.throw(() => { ajv.compile({instanceof: 1}) }) }) }) }) ajv-keywords-5.1.0/spec/patternRequired.spec.ts000066400000000000000000000024601414652001000215460ustar00rootroot00000000000000import patternRequired from "../dist/keywords/patternRequired" import patternRequiredDef from "../dist/definitions/patternRequired" import getAjvInstances from "./ajv_instances" import chai from "chai" // import ajvPack from "./ajv_pack" chai.should() describe('keywords "patternRequired"', () => { const opts = {allErrors: true} const ajvs = getAjvInstances("patternRequired", patternRequiredDef, patternRequired, opts) // ajvs.push(patternRequired(ajvPack(opts))) const optsOP = {allErrors: true, ownProperties: true} const ajvsOP = getAjvInstances("patternRequired", patternRequiredDef, patternRequired, optsOP) // ajvsOP.push(patternRequired(ajvPack(optsOP))) ajvs.forEach((ajv, i) => { it(`should only validate against own properties when using patternRequired #${i}`, () => { const ajvOP = ajvsOP[i] const schema = {type: "object", patternRequired: ["f.*o"]} const baz = {foooo: false, fooooooo: 42.31} type Constructor = new () => any function FooThing(this: any): any { this.bar = 123 } FooThing.prototype = baz const object = new ((FooThing as unknown) as Constructor)() ajv.validate(schema, object).should.equal(true) ajvOP.validate(schema, object).should.equal(false) ajvOP.errors?.should.have.length(1) }) }) }) ajv-keywords-5.1.0/spec/range.spec.ts000066400000000000000000000042361414652001000174670ustar00rootroot00000000000000import type Ajv from "ajv" import rangePlugin from "../dist/keywords/range" import rangeDef from "../dist/definitions/range" import exclusiveRangePlugin from "../dist/keywords/exclusiveRange" import exclusiveRangeDef from "../dist/definitions/exclusiveRange" import getAjvInstances from "./ajv_instances" import chai from "chai" import ajvPack from "./ajv_pack" const should = chai.should() describe('keyword "range"', () => { const ajvs = getAjvInstances( ["range", "exclusiveRange"], [rangeDef, exclusiveRangeDef], (ajv: Ajv) => exclusiveRangePlugin(rangePlugin(ajv)) ) ajvs.push(exclusiveRangePlugin(rangePlugin(ajvPack()))) ajvs.forEach((ajv, i) => { it(`should validate that value is in range #${i}`, () => { const schema = {type: "number", range: [1, 3]} ajv.validate(schema, 1).should.equal(true) ajv.validate(schema, 2).should.equal(true) ajv.validate(schema, 3).should.equal(true) ajv.validate(schema, 0.99).should.equal(false) ajv.validate(schema, 3.01).should.equal(false) ajv.validate({type: "number", range: [1, 1]}, 1).should.equal(true) const schemaExcl = {type: "number", exclusiveRange: [1, 3]} ajv.validate(schemaExcl, 1).should.equal(false) ajv.validate(schemaExcl, 2).should.equal(true) ajv.validate(schemaExcl, 3).should.equal(false) ajv.validate(schemaExcl, 1.01).should.equal(true) ajv.validate(schemaExcl, 2.99).should.equal(true) }) }) ajvs.forEach((ajv, i) => { it(`should throw when range schema is invalid #${i}`, () => { ;[ {type: "number", range: [1, "3"]}, {type: "number", range: [1]}, {type: "number", range: [1, 2, 3]}, {type: "number", range: {}}, {type: "number", range: [3, 1]}, {type: "number", exclusiveRange: [1, "3"]}, {type: "number", exclusiveRange: [1]}, {type: "number", exclusiveRange: [1, 2, 3]}, {type: "number", exclusiveRange: {}}, {type: "number", exclusiveRange: [3, 1]}, {type: "number", exclusiveRange: [1, 1]}, ].forEach((schema) => { should.throw(() => { ajv.compile(schema) }) }) }) }) }) ajv-keywords-5.1.0/spec/regexp.spec.ts000066400000000000000000000034761414652001000176720ustar00rootroot00000000000000import regexpPlugin from "../dist/keywords/regexp" import regexpDef from "../dist/definitions/regexp" import getAjvInstances from "./ajv_instances" import chai from "chai" import ajvPack from "./ajv_pack" const should = chai.should() describe('keyword "regexp"', () => { const ajvs = getAjvInstances("regexp", regexpDef, regexpPlugin, {logger: false}) ajvs.push(regexpPlugin(ajvPack())) ajvs.forEach((ajv, i) => { it(`should validate that values match regular expressions with flags #${i}`, () => { const schema = { type: "object", properties: { foo: {type: "string", regexp: "/foo/i"}, bar: {type: "string", regexp: {pattern: "bar", flags: "i"}}, }, } const validData = { foo: "Food", bar: "Barmen", } const invalidData = { foo: "fog", bar: "bad", } ajv.validate(schema, {}).should.equal(true) ajv.validate(schema, validData).should.equal(true) ajv.validate(schema, invalidData).should.equal(false) }) }) ajvs.forEach((ajv, i) => { it(`should throw when regexp schema is invalid #${i}`, () => { ;[ {type: "string", regexp: "/foo"}, // invalid regexp {type: "string", regexp: "/foo/a"}, // invalid regexp 2 {type: "string", regexp: {pattern: "[a-z"}}, // invalid regexp {type: "string", regexp: {pattern: "[a-z]", flags: "a"}}, // invalid flag {type: "string", regexp: {flag: "i"}}, // missing pattern {type: "string", regexp: {pattern: "[a-z]", flag: "i", foo: 1}}, // extra property {type: "string", regexp: 1}, // incorrect type {type: "string", regexp: {pattern: 1, flags: "i"}}, // incorrect type ].forEach((schema) => { should.throw(() => { ajv.compile(schema) }) }) }) }) }) ajv-keywords-5.1.0/spec/schema-tests.spec.ts000066400000000000000000000026121414652001000207670ustar00rootroot00000000000000import Ajv from "ajv/dist/2019" import type {Vocabulary} from "ajv" import ajvKeywordsPlugin from "../dist" import ajvKeywords from "../dist/definitions" const jsonSchemaTest = require("json-schema-test") const ajvs = [ ajvKeywordsPlugin(getAjv(), [ "uniqueItemProperties", "allRequired", "anyRequired", "oneRequired", "patternRequired", "prohibited", "deepProperties", "deepRequired", "select", ]), ajvKeywordsPlugin(getAjv()), ajvKeywordsPlugin(getAjv(true)), getAjv(undefined, ajvKeywords()), getAjv(true, ajvKeywords()), // ajvKeywordsPlugin(getAjvNoMeta()), getAjvNoMeta(ajvKeywords({defaultMeta: false})), ] jsonSchemaTest(ajvs, { description: `json test suite with ${ajvs.length} ajv instances`, suites: { tests: "./tests/{**/,}*.json", }, only: [], // afterError: after.error, // afterEach: after.each, cwd: __dirname, hideFolder: "tests/", }) function getAjv(extras?: boolean, keywords?: Vocabulary): Ajv { return new Ajv({ $data: true, allErrors: extras, verbose: extras, keywords, formats: {allowedUnknown: true}, strictTypes: false, strictTuples: false, }) } function getAjvNoMeta(keywords?: Vocabulary): Ajv { return new Ajv({ $data: true, keywords, formats: {allowedUnknown: true}, meta: false, validateSchema: false, strictTypes: false, strictTuples: false, }) } ajv-keywords-5.1.0/spec/select.spec.ts000066400000000000000000000030021414652001000176400ustar00rootroot00000000000000import selectPlugin from "../dist/keywords/select" import selectDef from "../dist/definitions/select" import ajvKeywordsPlugin from "../dist" import ajvKeywords from "../dist/definitions" import Ajv from "ajv" import chai from "chai" import ajvPack from "./ajv_pack" const should = chai.should() describe('keyword "select"', () => { describe("invalid schema", () => { const ajvs = [ selectPlugin(new Ajv({$data: true})), selectPlugin(new Ajv({$data: true, allErrors: true})), new Ajv({$data: true, keywords: selectDef()}), ajvKeywordsPlugin(new Ajv({$data: true}), "select"), ajvKeywordsPlugin(new Ajv({$data: true})), new Ajv({$data: true, keywords: ajvKeywords()}), new Ajv({$data: true}).addVocabulary(ajvKeywords()), selectPlugin(ajvPack({$data: true})), ] ajvs.forEach((ajv, i) => { it(`should throw - "select" requires "selectCases" #${i}`, () => { should.throw(() => { ajv.compile({ select: {$data: "0/type"}, }) }) }) it(`should NOT throw during validation #${i}`, () => { const validate = ajv.compile({ select: {$data: "0/type"}, selectCases: { foo: true, bar: true, }, selectDefault: false, }) validate({type: "foo"}).should.equal(true) validate({type: "bar"}).should.equal(true) validate({type: "unknown"}).should.equal(false) validate({}).should.equal(true) }) }) }) }) ajv-keywords-5.1.0/spec/standalone.spec.ts000066400000000000000000000011461414652001000205200ustar00rootroot00000000000000import ajvKeywordsPlugin from "../dist" import ajvPack from "./ajv_pack" const jsonSchemaTest = require("json-schema-test") const options = { $data: true, strictTuples: false, allowUnionTypes: true, } jsonSchemaTest(ajvKeywordsPlugin(ajvPack(options)), { description: `json test suite with standalone code`, suites: { tests: "./tests/{**/,}*.json", }, only: [ // "uniqueItemProperties", "allRequired", "anyRequired", "oneRequired", "patternRequired", "prohibited", "deepProperties", "deepRequired", "select", ], cwd: __dirname, hideFolder: "tests/", }) ajv-keywords-5.1.0/spec/tests/000077500000000000000000000000001414652001000162275ustar00rootroot00000000000000ajv-keywords-5.1.0/spec/tests/allRequired.json000066400000000000000000000050071414652001000213750ustar00rootroot00000000000000[ { "description": "allRequired: true requires the presense of all defined properties", "schema": { "type": "object", "properties": { "foo": true, "bar": true }, "allRequired": true }, "tests": [ { "description": "all defined properties present is valid", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "all defined properties present with an additional property is valid", "data": {"foo": 1, "bar": 2, "baz": 3}, "valid": true }, { "description": "some of defined properties present is invalid", "data": {"foo": 1}, "valid": false }, { "description": "some of defined properties present with an additional property is invalid", "data": {"foo": 1, "baz": 3}, "valid": false }, { "description": "none of defined properties present is invalid", "data": {"baz": 3}, "valid": false }, { "description": "empty object is invalid", "data": {}, "valid": false } ] }, { "description": "allRequired: false is always ignored", "schema": { "type": "object", "properties": { "foo": true, "bar": true }, "allRequired": false }, "tests": [ { "description": "all defined properties present is valid", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "all defined properties present with an additional property is valid", "data": {"foo": 1, "bar": 2, "baz": 3}, "valid": true }, { "description": "some of defined properties present is valid", "data": {"foo": 1}, "valid": true }, { "description": "some of defined properties present with an additional property is valid", "data": {"foo": 1, "baz": 3}, "valid": true }, { "description": "none of defined properties present is valid", "data": {"baz": 3}, "valid": true }, { "description": "empty object is valid", "data": {}, "valid": true } ] }, { "description": "allRequired with empty properties is valid", "schema": { "type": "object", "properties": {}, "allRequired": true }, "tests": [ { "description": "any object is valid", "data": {}, "valid": true } ] } ] ajv-keywords-5.1.0/spec/tests/anyRequired.json000066400000000000000000000040301414652001000214070ustar00rootroot00000000000000[ { "description": "anyRequired requires that at least on property in the list is present", "schema": { "type": "object", "anyRequired": ["foo"] }, "tests": [ { "description": "property present is valid", "data": {"foo": 1}, "valid": true }, { "description": "property present with an additional property is valid", "data": {"foo": 1, "baz": 3}, "valid": true }, { "description": "no property present is invalid", "data": {"baz": 1}, "valid": false }, { "description": "empty object is invalid", "data": {}, "valid": false } ] }, { "description": "multiple properties in prohibited", "schema": { "type": "object", "anyRequired": ["foo", "bar"] }, "tests": [ { "description": "property present is valid", "data": {"foo": 1}, "valid": true }, { "description": "property present with an additional property is valid", "data": {"foo": 1, "baz": 3}, "valid": true }, { "description": "all properties present is valid", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "all properties present with an additional property is valid", "data": {"foo": 1, "bar": 2, "baz": 3}, "valid": true }, { "description": "no property present is invalid", "data": {"baz": 3}, "valid": false }, { "description": "empty object is invalid", "data": {}, "valid": false } ] }, { "description": "anyRequired: [] is always valid", "schema": { "type": "object", "anyRequired": [] }, "tests": [ { "description": "any object is valid", "data": {"foo": 1}, "valid": true }, { "description": "empty object is valid", "data": {}, "valid": true } ] } ] ajv-keywords-5.1.0/spec/tests/deepProperties.json000066400000000000000000000157021414652001000221210ustar00rootroot00000000000000[ { "description": "deepProperties keyword validation", "schema": { "type": "object", "deepProperties": { "/foo/bar": {"type": "number"}, "/foo/baz": {"type": "string"}, "/quux": {"type": "boolean"} } }, "tests": [ { "description": "object with all valid properties is valid", "data": { "foo": { "bar": 1, "baz": "2" }, "quux": true }, "valid": true }, { "description": "object with some valid properties is valid", "data": { "foo": { "bar": 1 }, "quux": true }, "valid": true }, { "description": "object with all invalid properties is invalid", "data": { "foo": { "bar": null, "baz": null }, "quux": null }, "valid": false }, { "description": "object with one invalid property is invalid", "data": { "quux": null }, "valid": false }, { "description": "object with one invalid sub-property is invalid", "data": { "foo": { "bar": null }, "quux": true }, "valid": false } ] }, { "description": "deepProperties keyword with items", "schema": { "type": "object", "properties": { "inside": { "type": "object", "deepProperties": { "/foo/1/bar": {"type": "number"}, "/foo/2/baz": {"type": "string"}, "/quux/3": {"type": "boolean"} } } } }, "tests": [ { "description": "object with all valid properties/items is valid", "data": { "inside": { "foo": [{}, {"bar": 1}, {"baz": "2"}], "quux": [0, 0, 0, true] } }, "valid": true }, { "description": "object with some valid properties/items is valid", "data": { "inside": { "foo": [{}, {"bar": 1}], "quux": [0, 0, 0, true] } }, "valid": true }, { "description": "object with all invalid properties is invalid", "data": { "inside": { "foo": [{}, {"bar": null}, {"baz": null}], "quux": [0, 0, 0, null] } }, "valid": false }, { "description": "object with one invalid property is invalid", "data": { "inside": { "foo": [{}, {"bar": 1}, {"baz": "2"}], "quux": [0, 0, 0, null] } }, "valid": false }, { "description": "object with one invalid sub-property is invalid", "data": { "inside": { "foo": [{}, {"bar": 1}, {"baz": null}], "quux": [0, 0, 0, true] } }, "valid": false } ] }, { "description": "deepProperties keyword with empty sub-properties", "schema": { "type": "array", "items": { "type": "object", "deepProperties": { "/": {"type": "number"}, "/foo/": {"type": "string"}, "/bar//baz": {"type": "boolean"} } } }, "tests": [ { "description": "object with all valid properties is valid", "data": [ { "": 1, "foo": { "": "2" }, "bar": { "": { "baz": true } } } ], "valid": true }, { "description": "object with some valid properties is valid", "data": [ { "": 1, "bar": { "": { "baz": true } } } ], "valid": true }, { "description": "object with all invalid properties is invalid", "data": [ { "": null, "foo": { "": null }, "bar": { "": { "baz": null } } } ], "valid": false }, { "description": "object with one invalid property is invalid", "data": [ { "": null, "foo": { "": "2" }, "bar": { "": { "baz": true } } } ], "valid": false }, { "description": "object with one invalid sub-property is invalid", "data": [ { "": 1, "foo": { "": "2" }, "bar": { "": { "baz": null } } } ], "valid": false } ] }, { "description": "deepProperties keyword with numbered properties", "schema": { "type": "object", "properties": { "inside": { "type": "object", "deepProperties": { "/foo/1/bar": {"type": "number"}, "/foo/2/baz": {"type": "string"}, "/quux/3": {"type": "boolean"} } } } }, "tests": [ { "description": "object with all valid properties is valid", "data": { "inside": { "foo": { "1": {"bar": 1}, "2": {"baz": "2"} }, "quux": { "3": true } } }, "valid": true }, { "description": "object with some valid properties is valid", "data": { "inside": { "foo": { "1": {"bar": 1} }, "quux": { "3": true } } }, "valid": true }, { "description": "object with all invalid properties is invalid", "data": { "inside": { "foo": { "1": {"bar": null}, "2": {"baz": null} }, "quux": { "3": null } } }, "valid": false }, { "description": "object with one invalid property is invalid", "data": { "inside": { "foo": { "1": {"bar": 1}, "2": {"baz": "2"} }, "quux": { "3": null } } }, "valid": false }, { "description": "object with one invalid sub-property is invalid", "data": { "inside": { "foo": { "1": {"bar": 1}, "2": {"baz": null} }, "quux": { "3": true } } }, "valid": false } ] } ] ajv-keywords-5.1.0/spec/tests/deepRequired.json000066400000000000000000000070151414652001000215430ustar00rootroot00000000000000[ { "description": "deepRequired keyword validation", "schema": { "type": "object", "deepRequired": ["/foo/bar", "/foo/baz", "/quux"] }, "tests": [ { "description": "object with all required properties is valid", "data": { "foo": { "bar": 1, "baz": 2 }, "quux": 3 }, "valid": true }, { "description": "object without any required properties is invalid", "data": { "foo": {} }, "valid": false }, { "description": "object with one required property is invalid", "data": { "quux": 3 }, "valid": false }, { "description": "object with one required sub-property is invalid", "data": { "foo": { "bar": 1 }, "quux": 3 }, "valid": false } ] }, { "description": "deepRequired keyword with items", "schema": { "type": "object", "properties": { "inside": { "type": "object", "deepRequired": ["/foo/1/bar", "/foo/2/baz", "/quux/3"] } } }, "tests": [ { "description": "object with all required properties/items is valid", "data": { "inside": { "foo": [{}, {"bar": 1}, {"baz": 2}], "quux": [0, 1, 2, 3] } }, "valid": true }, { "description": "object without any required properties is invalid", "data": { "inside": { "foo": [{}, {}, {}], "quux": [0, 1, 2] } }, "valid": false }, { "description": "object with one required property is invalid", "data": { "inside": { "quux": [0, 1, 2, 3] } }, "valid": false }, { "description": "object with one required sub-property is invalid", "data": { "inside": { "foo": [{}, {"bar": 1}, {}], "quux": [0, 1, 2, 3] } }, "valid": false } ] }, { "description": "deepRequired keyword with empty sub-properties", "schema": { "type": "array", "items": { "type": "object", "deepRequired": ["/", "/foo/", "/bar//baz"] } }, "tests": [ { "description": "object with required properties is valid", "data": [ { "": 0, "foo": { "": 1 }, "bar": { "": { "baz": 2 } } } ], "valid": true }, { "description": "object without any required properties is invalid", "data": [ { "foo": {}, "bar": { "": {} } } ], "valid": false }, { "description": "object with one required property is invalid", "data": [ { "": 0, "foo": {}, "bar": { "": {} } } ], "valid": false }, { "description": "object with one required sub-property is invalid", "data": [ { "": 0, "foo": { "": 1 }, "bar": { "": {} } } ], "valid": false } ] } ] ajv-keywords-5.1.0/spec/tests/oneRequired.json000066400000000000000000000035641414652001000214140ustar00rootroot00000000000000[ { "description": "oneRequired requires that at least on property in the list is present", "schema": { "type": "object", "oneRequired": ["foo"] }, "tests": [ { "description": "property present is valid", "data": {"foo": 1}, "valid": true }, { "description": "property present with an additional property is valid", "data": {"foo": 1, "baz": 3}, "valid": true }, { "description": "no property present is invalid", "data": {"baz": 1}, "valid": false }, { "description": "empty object is invalid", "data": {}, "valid": false } ] }, { "description": "multiple properties are prohibited", "schema": { "type": "object", "oneRequired": ["foo", "bar"] }, "tests": [ { "description": "property present is valid", "data": {"foo": 1}, "valid": true }, { "description": "property present with an additional property is valid", "data": {"foo": 1, "baz": 3}, "valid": true }, { "description": "multiple properties present is invalid", "data": {"foo": 1, "bar": 2}, "valid": false }, { "description": "no property present is invalid", "data": {"baz": 3}, "valid": false }, { "description": "empty object is invalid", "data": {}, "valid": false } ] }, { "description": "oneRequired: [] is always valid", "schema": { "type": "object", "oneRequired": [] }, "tests": [ { "description": "any object is valid", "data": {"foo": 1}, "valid": true }, { "description": "empty object is valid", "data": {}, "valid": true } ] } ] ajv-keywords-5.1.0/spec/tests/patternRequired.json000066400000000000000000000047671414652001000223160ustar00rootroot00000000000000[ { "description": "patternRequired requires that some property matching pattern is present", "schema": { "type": "object", "patternRequired": ["f.*o"] }, "tests": [ { "description": "property matching required pattern is valid", "data": {"foo": 1}, "valid": true }, { "description": "one of properties matching required pattern is valid", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "non-present property matching required pattern is invalid", "data": {"bar": 1}, "valid": false } ] }, { "description": "multiple patterns in patternRequired", "schema": { "type": "object", "patternRequired": ["a+", "b+"] }, "tests": [ { "description": "both patterns matched with one property is valid", "data": {"ab": 2}, "valid": true }, { "description": "both patterns matched with separate properties is valid", "data": {"aa": 1, "bb": 2}, "valid": true }, { "description": "both patterns matched with multiple properties is valid", "data": {"a": 1, "aa": 2, "ab": 3, "b": 4, "bb": 5}, "valid": true }, { "description": "one pattern not matched is invalid", "data": {"aa": 1}, "valid": false }, { "description": "another pattern not matched is invalid", "data": {"bb": 2}, "valid": false }, { "description": "both patterns not matched is invalid", "data": {"c": 3}, "valid": false } ] }, { "description": "regexes in patternRequired are not anchored by default and are case sensitive", "schema": { "type": "object", "patternRequired": ["X_[0-9]{2,}"] }, "tests": [ { "description": "regexes are not anchored", "data": {"aX_25b": 1}, "valid": true }, { "description": "regexes are case sensitive", "data": {"X_25": 2}, "valid": true }, { "description": "regexes are case sensitive, 2", "data": {"x_25": 3}, "valid": false } ] }, { "description": "patternRequired with empty array is valid", "schema": { "type": "object", "patternRequired": [] }, "tests": [ { "description": "any object is valid", "data": {}, "valid": true } ] } ] ajv-keywords-5.1.0/spec/tests/prohibited.json000066400000000000000000000030731414652001000212560ustar00rootroot00000000000000[ { "description": "prohibited requires that no property in the list is present", "schema": { "type": "object", "prohibited": ["foo"] }, "tests": [ { "description": "no property present is valid", "data": {"baz": 1}, "valid": true }, { "description": "empty object is valid", "data": {}, "valid": true }, { "description": "property is present is invalid", "data": {"foo": 1}, "valid": false } ] }, { "description": "multiple properties in prohibited", "schema": { "type": "object", "prohibited": ["foo", "bar"] }, "tests": [ { "description": "no property present is valid", "data": {"baz": 1}, "valid": true }, { "description": "empty object is valid", "data": {}, "valid": true }, { "description": "one of properties present is invalid", "data": {"foo": 1}, "valid": false }, { "description": "both properties present is invalid", "data": {"foo": 1, "bar": 2}, "valid": false } ] }, { "description": "prohibited with the empty list of properties", "schema": { "type": "object", "prohibited": [] }, "tests": [ { "description": "any object is valid", "data": {"foo": 1}, "valid": true }, { "description": "empty object is valid", "data": {}, "valid": true } ] } ] ajv-keywords-5.1.0/spec/tests/select.json000066400000000000000000000265361414652001000204150ustar00rootroot00000000000000[ { "description": "select keyword", "schema": { "type": "object", "properties": { "type": {"type": "string"} }, "select": {"$data": "0/type"}, "selectCases": { "foo": { "properties": { "type": {}, "foo": {"type": "string"} }, "additionalProperties": false }, "bar": { "properties": { "type": {}, "bar": {"type": "number"} }, "additionalProperties": false } } }, "tests": [ { "description": "valid object, type=foo", "data": { "type": "foo", "foo": "anything" }, "valid": true }, { "description": "valid object, type=bar", "data": { "type": "bar", "bar": 123 }, "valid": true }, { "description": "invalid object, type=foo", "data": { "type": "foo", "foo": 123 }, "valid": false }, { "description": "invalid object, type=bar", "data": { "type": "bar", "bar": "anything" }, "valid": false }, { "description": "invalid object with additional property, type=foo", "data": { "type": "foo", "foo": "anything", "another": 1 }, "valid": false }, { "description": "valid object with unknown type", "data": { "type": "another", "foo": 123 }, "valid": true }, { "description": "valid object without type", "data": { "foo": 123 }, "valid": true } ] }, { "description": "select keyword with selectDefault", "schema": { "type": "object", "properties": { "type": {"type": "string"} }, "select": {"$data": "0/type"}, "selectCases": { "foo": { "properties": { "type": {}, "foo": {"type": "string"} }, "additionalProperties": false }, "bar": { "properties": { "type": {}, "bar": {"type": "number"} }, "additionalProperties": false } }, "selectDefault": { "propertyNames": { "not": {"enum": ["foo", "bar"]} } } }, "tests": [ { "description": "valid object, type=foo", "data": { "type": "foo", "foo": "anything" }, "valid": true }, { "description": "valid object, type=bar", "data": { "type": "bar", "bar": 123 }, "valid": true }, { "description": "invalid object, type=foo", "data": { "type": "foo", "foo": 123 }, "valid": false }, { "description": "invalid object, type=bar", "data": { "type": "bar", "bar": "anything" }, "valid": false }, { "description": "invalid object with additional property, type=foo", "data": { "type": "foo", "foo": "anything", "another": 1 }, "valid": false }, { "description": "valid object with unknown type", "data": { "type": "another", "another": 123 }, "valid": true }, { "description": "invalid object with unknown type", "data": { "type": "another", "foo": "anything" }, "valid": false }, { "description": "valid object without type", "data": { "foo": 123 }, "valid": true } ] }, { "description": "select keyword with fixed selector value", "schema": { "type": "object", "select": "foo", "selectCases": { "foo": { "properties": { "type": {"const": "foo"}, "foo": {"type": "string"} }, "additionalProperties": false }, "bar": { "properties": { "type": {"const": "bar"}, "bar": {"type": "number"} }, "additionalProperties": false } } }, "tests": [ { "description": "valid object, type=foo", "data": { "type": "foo", "foo": "anything" }, "valid": true }, { "description": "invalid object, type=bar", "data": { "type": "bar", "bar": 123 }, "valid": false }, { "description": "invalid object, type=foo", "data": { "type": "foo", "foo": 123 }, "valid": false }, { "description": "invalid object, type=bar", "data": { "type": "bar", "bar": "anything" }, "valid": false }, { "description": "invalid object with additional property, type=foo", "data": { "type": "foo", "foo": "anything", "another": 1 }, "valid": false }, { "description": "invalid object with unknown type", "data": { "type": "another", "foo": 123 }, "valid": false }, { "description": "invalid object without type", "data": { "foo": 123 }, "valid": false } ] }, { "description": "select keyword with relative URIs in $ref (supported from v4 / ajv v7)", "schema": { "type": "object", "definitions": { "num": {"type": "number"}, "str": {"type": "string"} }, "properties": { "type": {"type": "string"} }, "select": {"$data": "0/type"}, "selectCases": { "foo": { "properties": { "type": {}, "foo": {"$ref": "#/definitions/str"} }, "additionalProperties": false }, "bar": { "properties": { "type": {}, "bar": {"$ref": "#/definitions/num"} }, "additionalProperties": false } } }, "tests": [ { "description": "valid object, type=foo", "data": { "type": "foo", "foo": "anything" }, "valid": true }, { "description": "invalid object, type=foo", "data": { "type": "foo", "foo": 123 }, "valid": false } ] }, { "description": "select keyword with absolute URIs in $ref (supported)", "schema": { "$id": "select_test.json", "type": "object", "definitions": { "num": {"type": "number"}, "str": {"type": "string"} }, "properties": { "type": {"type": "string"} }, "select": {"$data": "0/type"}, "selectCases": { "foo": { "properties": { "type": {}, "foo": {"$ref": "select_test.json#/definitions/str"} }, "additionalProperties": false }, "bar": { "properties": { "type": {}, "bar": {"$ref": "select_test.json#/definitions/num"} }, "additionalProperties": false } } }, "tests": [ { "description": "valid object, type=foo", "data": { "type": "foo", "foo": "anything" }, "valid": true }, { "description": "valid object, type=bar", "data": { "type": "bar", "bar": 123 }, "valid": true }, { "description": "invalid object, type=foo", "data": { "type": "foo", "foo": 123 }, "valid": false }, { "description": "invalid object, type=bar", "data": { "type": "bar", "bar": "anything" }, "valid": false } ] }, { "description": "select keyword with unevaluatedProperties", "schema": { "type": "object", "required": ["type"], "properties": { "type": {"type": "string"} }, "unevaluatedProperties": false, "select": {"$data": "0/type"}, "selectCases": { "foo": { "properties": { "foo": {"type": "string"} } }, "bar": { "properties": { "bar": {"type": "number"} } } }, "selectDefault": { "properties": { "unknown": {"type": "string"} } } }, "tests": [ { "description": "valid object, type=foo", "data": { "type": "foo", "foo": "anything" }, "valid": true }, { "description": "valid object, type=bar", "data": { "type": "bar", "bar": 123 }, "valid": true }, { "description": "invalid object, type=foo", "data": { "type": "foo", "foo": 123 }, "valid": false }, { "description": "invalid object, type=bar", "data": { "type": "bar", "bar": "anything" }, "valid": false }, { "description": "invalid object with additional property, type=foo", "data": { "type": "foo", "foo": "anything", "another": 1 }, "valid": false }, { "description": "valid object with unknown type", "data": { "type": "another", "unknown": "anything" }, "valid": true }, { "description": "invalid object with unknown type", "data": { "type": "another", "unknown": 1 }, "valid": false }, { "description": "invalid object with additional property, unknown type", "data": { "type": "another", "unknown": "anything", "another": 1 }, "valid": false } ] }, { "description": "select keyword with boolean selector tag (issue #150)", "schema": { "type": "object", "properties": { "tag": {"type": "boolean"} }, "select": { "$data": "0/tag" }, "selectCases": { "false": { "not": {"required": ["foo"]} }, "true": { "required": ["foo"] } }, "selectDefault": false }, "tests": [ { "description": "false tag: valid", "data": {"tag": false}, "valid": true }, { "description": "false tag: invalid", "data": {"tag": false, "foo": 1}, "valid": false }, { "description": "true tag: valid", "data": {"tag": true, "foo": 1}, "valid": true }, { "description": "true tag: invalid", "data": {"tag": true}, "valid": false }, { "description": "no tag - select not validated 1 (valid)", "data": {"foo": 1}, "valid": true }, { "description": "no tag - select not validated 1 (valid)", "data": {}, "valid": true } ] } ] ajv-keywords-5.1.0/spec/tests/uniqueItemProperties.json000066400000000000000000000247731414652001000233410ustar00rootroot00000000000000[ { "description": "uniqueItemProperties keyword validation with single property", "schema": { "uniqueItemProperties": ["id"] }, "tests": [ { "description": "with all unique ids", "data": [{"id": 1}, {"id": 2}, {"id": 3}], "valid": true }, { "description": "without unique ids", "data": [{"id": 1}, {"id": 1}, {"id": 3}], "valid": false }, { "description": "with all unique object-ids", "data": [ {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 2, "date": 1495213151727}}, {"id": {"_id": 3, "date": 1495213151728}} ], "valid": true }, { "description": "without unique object-ids", "data": [ {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 3, "date": 1495213151728}} ], "valid": false }, { "description": "non-array is valid", "data": 1, "valid": true }, { "description": "non-array is valid even for pseudo-arrays", "data": { "0": {"id": 1}, "1": {"id": 1}, "length": 2 }, "valid": true }, { "description": "array with one item is valid", "data": [{"id": 1}], "valid": true }, { "description": "empty array is valid", "data": [], "valid": true }, { "description": "array with non-objects is valid", "data": [1, 1], "valid": true } ] }, { "description": "uniqueItemProperties keyword validation with multiple properties", "schema": { "type": "array", "uniqueItemProperties": ["id", "name"] }, "tests": [ { "description": "with all unique ids and names", "data": [ {"id": 1, "name": "taco"}, {"id": 2, "name": "burrito"}, {"id": 3, "name": "salsa"} ], "valid": true }, { "description": "with unique ids but not unique names", "data": [ {"id": 1, "name": "taco"}, {"id": 2, "name": "taco"}, {"id": 3, "name": "salsa"} ], "valid": false } ] }, { "description": "uniqueItemProperties keyword validation with no properties", "schema": { "type": "array", "uniqueItemProperties": [] }, "tests": [ { "description": "with deepEqual like objects", "data": [{"id": 1}, {"id": 1}, {"id": 1}], "valid": true } ] }, { "description": "uniqueItemProperties keyword validation with single property of scalar type", "schema": { "uniqueItemProperties": ["id"], "items": { "properties": { "id": {"type": "number"} } } }, "tests": [ { "description": "with all unique ids", "data": [{"id": 1}, {"id": 2}, {"id": 3}], "valid": true }, { "description": "without unique ids", "data": [{"id": 1}, {"id": 1}, {"id": 3}], "valid": false }, { "description": "with all unique object-ids", "data": [ {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 2, "date": 1495213151727}}, {"id": {"_id": 3, "date": 1495213151728}} ], "valid": false }, { "description": "without unique object-ids", "data": [ {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 3, "date": 1495213151728}} ], "valid": false }, { "description": "non-array is valid", "data": 1, "valid": true }, { "description": "non-array is valid even for pseudo-arrays", "data": { "0": {"id": 1}, "1": {"id": 1}, "length": 2 }, "valid": true }, { "description": "array with one item is valid", "data": [{"id": 1}], "valid": true }, { "description": "empty array is valid", "data": [], "valid": true }, { "description": "array with non-objects is valid", "data": [1, 1], "valid": true } ] }, { "description": "uniqueItemProperties keyword validation with single property of non-scalar type", "schema": { "uniqueItemProperties": ["id"], "items": { "properties": { "id": {"type": "object"} } } }, "tests": [ { "description": "with all unique object-ids", "data": [ {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 2, "date": 1495213151727}}, {"id": {"_id": 3, "date": 1495213151728}} ], "valid": true }, { "description": "without unique object-ids", "data": [ {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 3, "date": 1495213151728}} ], "valid": false } ] }, { "description": "uniqueItemProperties keyword validation with single property of multiple scalar types", "schema": { "uniqueItemProperties": ["id"], "items": { "properties": { "id": {"type": ["number", "string"]} } } }, "tests": [ { "description": "with all unique ids", "data": [{"id": 1}, {"id": 2}, {"id": 3}, {"id": "1"}, {"id": "2"}, {"id": "3"}], "valid": true }, { "description": "without unique ids", "data": [{"id": 1}, {"id": 1}, {"id": 3}, {"id": "1"}, {"id": "2"}, {"id": "3"}], "valid": false } ] }, { "description": "uniqueItemProperties keyword validation with single property of multiple types", "schema": { "uniqueItemProperties": ["id"], "items": { "properties": { "id": {"type": ["number", "object"]} } } }, "tests": [ { "description": "with all unique ids", "data": [ {"id": 1}, {"id": 2}, {"id": 3}, {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 2, "date": 1495213151727}}, {"id": {"_id": 3, "date": 1495213151728}} ], "valid": true }, { "description": "without unique ids", "data": [ {"id": 1}, {"id": 2}, {"id": 3}, {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 1, "date": 1495213151726}}, {"id": {"_id": 3, "date": 1495213151728}} ], "valid": false } ] }, { "description": "uniqueItemProperties keyword validation with multiple properties", "schema": { "type": "array", "uniqueItemProperties": ["id", "name"] }, "tests": [ { "description": "with all unique ids and names", "data": [ {"id": 1, "name": "taco"}, {"id": 2, "name": "burrito"}, {"id": 3, "name": "salsa"} ], "valid": true }, { "description": "with unique ids but not unique names", "data": [ {"id": 1, "name": "taco"}, {"id": 2, "name": "taco"}, {"id": 3, "name": "salsa"} ], "valid": false } ] }, { "description": "uniqueItemProperties keyword validation with multiple properties of scalar types", "schema": { "type": "array", "uniqueItemProperties": ["id", "name"], "items": { "properties": { "id": {"type": "number"}, "name": {"type": "string"} } } }, "tests": [ { "description": "with all unique ids and names", "data": [ {"id": 1, "name": "taco"}, {"id": 2, "name": "burrito"}, {"id": 3, "name": "salsa"} ], "valid": true }, { "description": "with unique ids but not unique names", "data": [ {"id": 1, "name": "taco"}, {"id": 2, "name": "taco"}, {"id": 3, "name": "salsa"} ], "valid": false } ] }, { "description": "uniqueItemProperties keyword validation with multiple properties with some scalar types", "schema": { "type": "array", "uniqueItemProperties": ["id", "name"], "items": { "properties": { "id": {"type": "object"}, "name": {"type": "string"} } } }, "tests": [ { "description": "with all unique ids and names", "data": [ {"id": {"_id": 1, "date": 1495213151726}, "name": "taco"}, {"id": {"_id": 2, "date": 1495213151727}, "name": "burrito"}, {"id": {"_id": 3, "date": 1495213151728}, "name": "salsa"} ], "valid": true }, { "description": "with non-unique ids but unique names", "data": [ {"id": {"_id": 1, "date": 1495213151726}, "name": "taco"}, {"id": {"_id": 1, "date": 1495213151726}, "name": "burrito"}, {"id": {"_id": 3, "date": 1495213151727}, "name": "salsa"} ], "valid": false } ] }, { "description": "uniqueItemProperties keyword with null item(s)", "schema": { "type": "array", "uniqueItemProperties": ["id"], "items": { "properties": { "id": {"type": "integer"} } } }, "tests": [ { "description": "with all unique ids and null items is valid", "data": [{"id": 1}, {"id": 2}, null, null], "valid": true }, { "description": "with non-unique ids and null item is invalid", "data": [{"id": 1}, {"id": 1}, null, null], "valid": false } ] }, { "description": "uniqueItemProperties keyword with null item(s) and object keys", "schema": { "type": "array", "uniqueItemProperties": ["id"], "items": { "properties": { "id": {"type": "object"} } } }, "tests": [ { "description": "with all unique ids and null items is valid", "data": [{"id": {"_id": 1}}, {"id": {"_id": 2}}, null, null], "valid": true }, { "description": "with non-unique ids and null item is invalid", "data": [{"id": {"_id": 1}}, {"id": {"_id": 1}}, null, null], "valid": false } ] } ] ajv-keywords-5.1.0/spec/transform.spec.ts000066400000000000000000000117701414652001000204070ustar00rootroot00000000000000import transformPlugin from "../dist/keywords/transform" import transformDef from "../dist/definitions/transform" import getAjvInstances from "./ajv_instances" import ajvPack from "./ajv_pack" import chai from "chai" chai.should() describe('keyword "transform"', () => { const ajvs = getAjvInstances("transform", transformDef, transformPlugin, {allowUnionTypes: true}) ajvs.push(transformPlugin(ajvPack({allowUnionTypes: true}))) ajvs.forEach((ajv, i) => { it(`should transform by wrapper #${i}`, () => { let schema, data data = {o: " Object "} schema = { type: "object", properties: {o: {type: "string", transform: ["trim", "toLowerCase"]}}, } ajv.validate(schema, data).should.equal(true) data.should.deep.equal({o: "object"}) data = [" Array "] schema = {type: "array", items: {type: "string", transform: ["trim", "toUpperCase"]}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["ARRAY"]) data = " String " schema = {type: "string", transform: ["trim", "toLowerCase"]} ajv.validate(schema, data).should.equal(true) // Note: Doesn't work on plain strings due to object being undefined data.should.equal(" String ") }) }) ajvs.forEach((ajv, i) => { it(`should not transform non-strings #${i}`, () => { const data = ["a", 1, null, [], {}] const schema = {type: "array", items: {type: "string", transform: ["toUpperCase"]}} ajv.validate(schema, data).should.equal(false) data.should.deep.equal(["A", 1, null, [], {}]) }) }) ajvs.forEach((ajv, i) => { it(`should transform trim #${i}`, () => { let schema, data data = [" trimObject "] schema = {type: "array", items: {type: "string", transform: ["trimLeft"]}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["trimObject "]) data = [" trimObject "] schema = {type: "array", items: {type: "string", transform: ["trimRight"]}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal([" trimObject"]) data = [" trimObject "] schema = {type: "array", items: {type: "string", transform: ["trimStart", "trimEnd"]}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["trimObject"]) data = [" trimObject "] schema = {type: "array", items: {type: "string", transform: ["trim"]}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["trimObject"]) }) }) ajvs.forEach((ajv, i) => { it(`should transform text case #${i}`, () => { let schema, data data = ["MixCase"] schema = {type: "array", items: {type: "string", transform: ["toLowerCase"]}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["mixcase"]) data = ["MixCase"] schema = {type: "array", items: {type: "string", transform: ["toUpperCase"]}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["MIXCASE"]) data = ["ph", "PH", "pH", "Ph"] schema = {type: "array", items: {type: "string", transform: ["toEnumCase"], enum: ["pH"]}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["pH", "pH", "pH", "pH"]) data = ["ph", "PH", "pH", "Ph", 7] schema = { type: "array", items: {type: ["string", "integer"], transform: ["toEnumCase"], enum: ["pH", 7]}, } ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["pH", "pH", "pH", "pH", 7]) data = ["ph"] schema = {type: "array", items: {type: "string", transform: ["toEnumCase"]}} try { ajv.validate(schema, data).should.equal(false) } catch (e) { ;(e as Error).message.should.match(/transform.*enum/) } data = ["ph"] schema = { type: "array", items: {type: "string", transform: ["toEnumCase"], enum: ["pH", "PH"]}, } try { ajv.validate(schema, data).should.equal(false) } catch (e) { ;(e as Error).message.should.match(/transform.*unique/) } data = [" ph "] schema = { type: "array", items: {type: "string", transform: ["trim", "toEnumCase"], enum: ["pH"]}, } ajv.validate(schema, data).should.equal(true) data.should.deep.equal(["pH"]) data = ["ab"] schema = {type: "array", items: {type: "string", transform: ["toEnumCase"], enum: ["pH"]}} ajv.validate(schema, data).should.equal(false) data.should.deep.equal(["ab"]) }) }) ajvs.forEach((ajv, i) => { it(`shouldn't mutate the transform array of the schema while compiling it #${i}`, () => { const data = {p: " trimObject "} const schema = {type: "object", properties: {p: {type: "string", transform: ["trimLeft"]}}} ajv.validate(schema, data).should.equal(true) data.should.deep.equal({p: "trimObject "}) schema.properties.p.transform.should.deep.equal(["trimLeft"]) }) }) }) ajv-keywords-5.1.0/spec/tsconfig.json000066400000000000000000000001441414652001000175730ustar00rootroot00000000000000{ "extends": "..", "include": ["."], "compilerOptions": { "types": ["node", "jest"] } } ajv-keywords-5.1.0/spec/typeof.spec.ts000066400000000000000000000034561414652001000177040ustar00rootroot00000000000000import typeofPlugin from "../dist/keywords/typeof" import typeofDef from "../dist/definitions/typeof" import getAjvInstances from "./ajv_instances" import ajvPack from "./ajv_pack" import chai from "chai" const should = chai.should() describe('keyword "typeof"', () => { const ajvs = getAjvInstances("typeof", typeofDef, typeofPlugin) ajvs.push(typeofPlugin(ajvPack())) ajvs.forEach((ajv, i) => { it(`should validate value types #${i}`, () => { ajv.validate({typeof: "undefined"}, undefined).should.equal(true) ajv.validate({typeof: "undefined"}, null).should.equal(false) ajv.validate({typeof: "undefined"}, "foo").should.equal(false) ajv.validate({typeof: "function"}, () => {}).should.equal(true) ajv.validate({typeof: "function"}, {}).should.equal(false) ajv.validate({typeof: "object"}, {}).should.equal(true) ajv.validate({typeof: "object"}, null).should.equal(true) ajv.validate({typeof: "object"}, "foo").should.equal(false) ajv.validate({typeof: "symbol"}, Symbol()).should.equal(true) ajv.validate({typeof: "symbol"}, {}).should.equal(false) }) it(`should validate multiple types #${i}`, () => { ajv.validate({typeof: ["string", "function"]}, "foo").should.equal(true) ajv.validate({typeof: ["string", "function"]}, () => {}).should.equal(true) ajv.validate({typeof: ["string", "function"]}, {}).should.equal(false) }) it(`should throw when unknown type is passed #${i}`, () => { should.throw(() => { ajv.compile({typeof: "unknownType"}) }) should.throw(() => { ajv.compile({typeof: ["string", "unknownType"]}) }) }) it(`should throw when not string or array is passed #${i}`, () => { should.throw(() => { ajv.compile({typeof: 1}) }) }) }) }) ajv-keywords-5.1.0/src/000077500000000000000000000000001414652001000147225ustar00rootroot00000000000000ajv-keywords-5.1.0/src/definitions/000077500000000000000000000000001414652001000172355ustar00rootroot00000000000000ajv-keywords-5.1.0/src/definitions/_range.ts000066400000000000000000000015311414652001000210400ustar00rootroot00000000000000import type {MacroKeywordDefinition} from "ajv" import type {GetDefinition} from "./_types" type RangeKwd = "range" | "exclusiveRange" export default function getRangeDef(keyword: RangeKwd): GetDefinition { return () => ({ keyword, type: "number", schemaType: "array", macro: function ([min, max]: [number, number]) { validateRangeSchema(min, max) return keyword === "range" ? {minimum: min, maximum: max} : {exclusiveMinimum: min, exclusiveMaximum: max} }, metaSchema: { type: "array", minItems: 2, maxItems: 2, items: {type: "number"}, }, }) function validateRangeSchema(min: number, max: number): void { if (min > max || (keyword === "exclusiveRange" && min === max)) { throw new Error("There are no numbers in range") } } } ajv-keywords-5.1.0/src/definitions/_required.ts000066400000000000000000000012371414652001000215670ustar00rootroot00000000000000import type {MacroKeywordDefinition} from "ajv" import type {GetDefinition} from "./_types" type RequiredKwd = "anyRequired" | "oneRequired" export default function getRequiredDef( keyword: RequiredKwd ): GetDefinition { return () => ({ keyword, type: "object", schemaType: "array", macro(schema: string[]) { if (schema.length === 0) return true if (schema.length === 1) return {required: schema} const comb = keyword === "anyRequired" ? "anyOf" : "oneOf" return {[comb]: schema.map((p) => ({required: [p]}))} }, metaSchema: { type: "array", items: {type: "string"}, }, }) } ajv-keywords-5.1.0/src/definitions/_types.ts000066400000000000000000000003161414652001000211100ustar00rootroot00000000000000import type {KeywordDefinition} from "ajv" export interface DefinitionOptions { defaultMeta?: string | boolean } export type GetDefinition = (opts?: DefinitionOptions) => T ajv-keywords-5.1.0/src/definitions/_util.ts000066400000000000000000000012321414652001000207170ustar00rootroot00000000000000import type {DefinitionOptions} from "./_types" import type {SchemaObject, KeywordCxt, Name} from "ajv" import {_} from "ajv/dist/compile/codegen" const META_SCHEMA_ID = "http://json-schema.org/schema" export function metaSchemaRef({defaultMeta}: DefinitionOptions = {}): SchemaObject { return defaultMeta === false ? {} : {$ref: defaultMeta || META_SCHEMA_ID} } export function usePattern( {gen, it: {opts}}: KeywordCxt, pattern: string, flags = opts.unicodeRegExp ? "u" : "" ): Name { const rx = new RegExp(pattern, flags) return gen.scopeValue("pattern", { key: rx.toString(), ref: rx, code: _`new RegExp(${pattern}, ${flags})`, }) } ajv-keywords-5.1.0/src/definitions/allRequired.ts000066400000000000000000000007251414652001000220620ustar00rootroot00000000000000import type {MacroKeywordDefinition} from "ajv" export default function getDef(): MacroKeywordDefinition { return { keyword: "allRequired", type: "object", schemaType: "boolean", macro(schema: boolean, parentSchema) { if (!schema) return true const required = Object.keys(parentSchema.properties) if (required.length === 0) return true return {required} }, dependencies: ["properties"], } } module.exports = getDef ajv-keywords-5.1.0/src/definitions/anyRequired.ts000066400000000000000000000004111414652001000220710ustar00rootroot00000000000000import type {MacroKeywordDefinition} from "ajv" import type {GetDefinition} from "./_types" import getRequiredDef from "./_required" const getDef: GetDefinition = getRequiredDef("anyRequired") export default getDef module.exports = getDef ajv-keywords-5.1.0/src/definitions/deepProperties.ts000066400000000000000000000032541414652001000226030ustar00rootroot00000000000000import type {MacroKeywordDefinition, SchemaObject, Schema} from "ajv" import type {DefinitionOptions} from "./_types" import {metaSchemaRef} from "./_util" export default function getDef(opts?: DefinitionOptions): MacroKeywordDefinition { return { keyword: "deepProperties", type: "object", schemaType: "object", macro: function (schema: Record) { const allOf = [] for (const pointer in schema) allOf.push(getSchema(pointer, schema[pointer])) return {allOf} }, metaSchema: { type: "object", propertyNames: {type: "string", format: "json-pointer"}, additionalProperties: metaSchemaRef(opts), }, } } function getSchema(jsonPointer: string, schema: SchemaObject): SchemaObject { const segments = jsonPointer.split("/") const rootSchema: SchemaObject = {} let pointerSchema: SchemaObject = rootSchema for (let i = 1; i < segments.length; i++) { let segment: string = segments[i] const isLast = i === segments.length - 1 segment = unescapeJsonPointer(segment) const properties: Record = (pointerSchema.properties = {}) let items: SchemaObject[] | undefined if (/[0-9]+/.test(segment)) { let count = +segment items = pointerSchema.items = [] pointerSchema.type = ["object", "array"] while (count--) items.push({}) } else { pointerSchema.type = "object" } pointerSchema = isLast ? schema : {} properties[segment] = pointerSchema if (items) items.push(pointerSchema) } return rootSchema } function unescapeJsonPointer(str: string): string { return str.replace(/~1/g, "/").replace(/~0/g, "~") } module.exports = getDef ajv-keywords-5.1.0/src/definitions/deepRequired.ts000066400000000000000000000020511414652001000222210ustar00rootroot00000000000000import type {CodeKeywordDefinition, KeywordCxt} from "ajv" import {_, or, and, getProperty, Code} from "ajv/dist/compile/codegen" export default function getDef(): CodeKeywordDefinition { return { keyword: "deepRequired", type: "object", schemaType: "array", code(ctx: KeywordCxt) { const {schema, data} = ctx const props = (schema as string[]).map((jp: string) => _`(${getData(jp)}) === undefined`) ctx.fail(or(...props)) function getData(jsonPointer: string): Code { if (jsonPointer === "") throw new Error("empty JSON pointer not allowed") const segments = jsonPointer.split("/") let x: Code = data const xs = segments.map((s, i) => i ? (x = _`${x}${getProperty(unescapeJPSegment(s))}`) : x ) return and(...xs) } }, metaSchema: { type: "array", items: {type: "string", format: "json-pointer"}, }, } } function unescapeJPSegment(s: string): string { return s.replace(/~1/g, "/").replace(/~0/g, "~") } module.exports = getDef ajv-keywords-5.1.0/src/definitions/dynamicDefaults.ts000066400000000000000000000054641414652001000227320ustar00rootroot00000000000000import type {FuncKeywordDefinition, SchemaCxt} from "ajv" const sequences: Record = {} export type DynamicDefaultFunc = (args?: Record) => () => any const DEFAULTS: Record = { timestamp: () => () => Date.now(), datetime: () => () => new Date().toISOString(), date: () => () => new Date().toISOString().slice(0, 10), time: () => () => new Date().toISOString().slice(11), random: () => () => Math.random(), randomint: (args?: {max?: number}) => { const max = args?.max ?? 2 return () => Math.floor(Math.random() * max) }, seq: (args?: {name?: string}) => { const name = args?.name ?? "" sequences[name] ||= 0 return () => (sequences[name] as number)++ }, } interface PropertyDefaultSchema { func: string args: Record } type DefaultSchema = Record const getDef: (() => FuncKeywordDefinition) & { DEFAULTS: typeof DEFAULTS } = Object.assign(_getDef, {DEFAULTS}) function _getDef(): FuncKeywordDefinition { return { keyword: "dynamicDefaults", type: "object", schemaType: ["string", "object"], modifying: true, valid: true, compile(schema: DefaultSchema, _parentSchema, it: SchemaCxt) { if (!it.opts.useDefaults || it.compositeRule) return () => true const fs: Record any> = {} for (const key in schema) fs[key] = getDefault(schema[key]) const empty = it.opts.useDefaults === "empty" return (data: Record) => { for (const prop in schema) { if (data[prop] === undefined || (empty && (data[prop] === null || data[prop] === ""))) { data[prop] = fs[prop]() } } return true } }, metaSchema: { type: "object", additionalProperties: { anyOf: [ {type: "string"}, { type: "object", additionalProperties: false, required: ["func", "args"], properties: { func: {type: "string"}, args: {type: "object"}, }, }, ], }, }, } } function getDefault(d: string | PropertyDefaultSchema | undefined): () => any { return typeof d == "object" ? getObjDefault(d) : getStrDefault(d) } function getObjDefault({func, args}: PropertyDefaultSchema): () => any { const def = DEFAULTS[func] assertDefined(func, def) return def(args) } function getStrDefault(d = ""): () => any { const def = DEFAULTS[d] assertDefined(d, def) return def() } function assertDefined(name: string, def?: DynamicDefaultFunc): asserts def is DynamicDefaultFunc { if (!def) throw new Error(`invalid "dynamicDefaults" keyword property value: ${name}`) } export default getDef module.exports = getDef ajv-keywords-5.1.0/src/definitions/exclusiveRange.ts000066400000000000000000000004031414652001000225660ustar00rootroot00000000000000import type {MacroKeywordDefinition} from "ajv" import type {GetDefinition} from "./_types" import getRangeDef from "./_range" const getDef: GetDefinition = getRangeDef("exclusiveRange") export default getDef module.exports = getDef ajv-keywords-5.1.0/src/definitions/index.ts000066400000000000000000000032161414652001000207160ustar00rootroot00000000000000import type {Vocabulary, KeywordDefinition, ErrorNoParams} from "ajv" import type {DefinitionOptions, GetDefinition} from "./_types" import typeofDef from "./typeof" import instanceofDef from "./instanceof" import range from "./range" import exclusiveRange from "./exclusiveRange" import regexp from "./regexp" import transform from "./transform" import uniqueItemProperties from "./uniqueItemProperties" import allRequired from "./allRequired" import anyRequired from "./anyRequired" import oneRequired from "./oneRequired" import patternRequired, {PatternRequiredError} from "./patternRequired" import prohibited from "./prohibited" import deepProperties from "./deepProperties" import deepRequired from "./deepRequired" import dynamicDefaults from "./dynamicDefaults" import selectDef, {SelectError} from "./select" const definitions: GetDefinition[] = [ typeofDef, instanceofDef, range, exclusiveRange, regexp, transform, uniqueItemProperties, allRequired, anyRequired, oneRequired, patternRequired, prohibited, deepProperties, deepRequired, dynamicDefaults, ] export default function ajvKeywords(opts?: DefinitionOptions): Vocabulary { return definitions.map((d) => d(opts)).concat(selectDef(opts)) } export type AjvKeywordsError = | PatternRequiredError | SelectError | ErrorNoParams< | "range" | "exclusiveRange" | "anyRequired" | "oneRequired" | "allRequired" | "deepProperties" | "deepRequired" | "dynamicDefaults" | "instanceof" | "prohibited" | "regexp" | "transform" | "uniqueItemProperties" > module.exports = ajvKeywords ajv-keywords-5.1.0/src/definitions/instanceof.ts000066400000000000000000000027351414652001000217450ustar00rootroot00000000000000import type {FuncKeywordDefinition} from "ajv" type Constructor = new (...args: any[]) => any const CONSTRUCTORS: Record = { Object, Array, Function, Number, String, Date, RegExp, } /* istanbul ignore else */ if (typeof Buffer != "undefined") CONSTRUCTORS.Buffer = Buffer /* istanbul ignore else */ if (typeof Promise != "undefined") CONSTRUCTORS.Promise = Promise const getDef: (() => FuncKeywordDefinition) & { CONSTRUCTORS: typeof CONSTRUCTORS } = Object.assign(_getDef, {CONSTRUCTORS}) function _getDef(): FuncKeywordDefinition { return { keyword: "instanceof", schemaType: ["string", "array"], compile(schema: string | string[]) { if (typeof schema == "string") { const C = getConstructor(schema) return (data) => data instanceof C } if (Array.isArray(schema)) { const constructors = schema.map(getConstructor) return (data) => { for (const C of constructors) { if (data instanceof C) return true } return false } } /* istanbul ignore next */ throw new Error("ajv implementation error") }, metaSchema: { anyOf: [{type: "string"}, {type: "array", items: {type: "string"}}], }, } } function getConstructor(c: string): Constructor { const C = CONSTRUCTORS[c] if (C) return C throw new Error(`invalid "instanceof" keyword value ${c}`) } export default getDef module.exports = getDef ajv-keywords-5.1.0/src/definitions/oneRequired.ts000066400000000000000000000004111414652001000220630ustar00rootroot00000000000000import type {MacroKeywordDefinition} from "ajv" import type {GetDefinition} from "./_types" import getRequiredDef from "./_required" const getDef: GetDefinition = getRequiredDef("oneRequired") export default getDef module.exports = getDef ajv-keywords-5.1.0/src/definitions/patternRequired.ts000066400000000000000000000026441414652001000227710ustar00rootroot00000000000000import type {CodeKeywordDefinition, KeywordCxt, KeywordErrorDefinition, ErrorObject} from "ajv" import {_, str, and} from "ajv/dist/compile/codegen" import {usePattern} from "./_util" export type PatternRequiredError = ErrorObject<"patternRequired", {missingPattern: string}> const error: KeywordErrorDefinition = { message: ({params: {missingPattern}}) => str`should have property matching pattern '${missingPattern}'`, params: ({params: {missingPattern}}) => _`{missingPattern: ${missingPattern}}`, } export default function getDef(): CodeKeywordDefinition { return { keyword: "patternRequired", type: "object", schemaType: "array", error, code(cxt: KeywordCxt) { const {gen, schema, data} = cxt if (schema.length === 0) return const valid = gen.let("valid", true) for (const pat of schema) validateProperties(pat) function validateProperties(pattern: string): void { const matched = gen.let("matched", false) gen.forIn("key", data, (key) => { gen.assign(matched, _`${usePattern(cxt, pattern)}.test(${key})`) gen.if(matched, () => gen.break()) }) cxt.setParams({missingPattern: pattern}) gen.assign(valid, and(valid, matched)) cxt.pass(valid) } }, metaSchema: { type: "array", items: {type: "string", format: "regex"}, uniqueItems: true, }, } } module.exports = getDef ajv-keywords-5.1.0/src/definitions/prohibited.ts000066400000000000000000000010101414652001000217260ustar00rootroot00000000000000import type {MacroKeywordDefinition} from "ajv" export default function getDef(): MacroKeywordDefinition { return { keyword: "prohibited", type: "object", schemaType: "array", macro: function (schema: string[]) { if (schema.length === 0) return true if (schema.length === 1) return {not: {required: schema}} return {not: {anyOf: schema.map((p) => ({required: [p]}))}} }, metaSchema: { type: "array", items: {type: "string"}, }, } } module.exports = getDef ajv-keywords-5.1.0/src/definitions/range.ts000066400000000000000000000003721414652001000207030ustar00rootroot00000000000000import type {MacroKeywordDefinition} from "ajv" import type {GetDefinition} from "./_types" import getRangeDef from "./_range" const getDef: GetDefinition = getRangeDef("range") export default getDef module.exports = getDef ajv-keywords-5.1.0/src/definitions/regexp.ts000066400000000000000000000022651414652001000211040ustar00rootroot00000000000000import type {CodeKeywordDefinition, KeywordCxt, JSONSchemaType, Name} from "ajv" import {_} from "ajv/dist/compile/codegen" import {usePattern} from "./_util" interface RegexpSchema { pattern: string flags?: string } const regexpMetaSchema: JSONSchemaType = { type: "object", properties: { pattern: {type: "string"}, flags: {type: "string", nullable: true}, }, required: ["pattern"], additionalProperties: false, } const metaRegexp = /^\/(.*)\/([gimuy]*)$/ export default function getDef(): CodeKeywordDefinition { return { keyword: "regexp", type: "string", schemaType: ["string", "object"], code(cxt: KeywordCxt) { const {data, schema} = cxt const regx = getRegExp(schema) cxt.pass(_`${regx}.test(${data})`) function getRegExp(sch: string | RegexpSchema): Name { if (typeof sch == "object") return usePattern(cxt, sch.pattern, sch.flags) const rx = metaRegexp.exec(sch) if (rx) return usePattern(cxt, rx[1], rx[2]) throw new Error("cannot parse string into RegExp") } }, metaSchema: { anyOf: [{type: "string"}, regexpMetaSchema], }, } } module.exports = getDef ajv-keywords-5.1.0/src/definitions/select.ts000066400000000000000000000045501414652001000210700ustar00rootroot00000000000000import type {KeywordDefinition, KeywordErrorDefinition, KeywordCxt, ErrorObject} from "ajv" import {_, str, nil, Name} from "ajv/dist/compile/codegen" import type {DefinitionOptions} from "./_types" import {metaSchemaRef} from "./_util" export type SelectError = ErrorObject<"select", {failingCase?: string; failingDefault?: true}> const error: KeywordErrorDefinition = { message: ({params: {schemaProp}}) => schemaProp ? str`should match case "${schemaProp}" schema` : str`should match default case schema`, params: ({params: {schemaProp}}) => schemaProp ? _`{failingCase: ${schemaProp}}` : _`{failingDefault: true}`, } export default function getDef(opts?: DefinitionOptions): KeywordDefinition[] { const metaSchema = metaSchemaRef(opts) return [ { keyword: "select", schemaType: ["string", "number", "boolean", "null"], $data: true, error, dependencies: ["selectCases"], code(cxt: KeywordCxt) { const {gen, schemaCode, parentSchema} = cxt cxt.block$data(nil, () => { const valid = gen.let("valid", true) const schValid = gen.name("_valid") const value = gen.const("value", _`${schemaCode} === null ? "null" : ${schemaCode}`) gen.if(false) // optimizer should remove it from generated code for (const schemaProp in parentSchema.selectCases) { cxt.setParams({schemaProp}) gen.elseIf(_`"" + ${value} == ${schemaProp}`) // intentional ==, to match numbers and booleans const schCxt = cxt.subschema({keyword: "selectCases", schemaProp}, schValid) cxt.mergeEvaluated(schCxt, Name) gen.assign(valid, schValid) } gen.else() if (parentSchema.selectDefault !== undefined) { cxt.setParams({schemaProp: undefined}) const schCxt = cxt.subschema({keyword: "selectDefault"}, schValid) cxt.mergeEvaluated(schCxt, Name) gen.assign(valid, schValid) } gen.endIf() cxt.pass(valid) }) }, }, { keyword: "selectCases", dependencies: ["select"], metaSchema: { type: "object", additionalProperties: metaSchema, }, }, { keyword: "selectDefault", dependencies: ["select", "selectCases"], metaSchema, }, ] } module.exports = getDef ajv-keywords-5.1.0/src/definitions/transform.ts000066400000000000000000000060011414652001000216150ustar00rootroot00000000000000import type {CodeKeywordDefinition, AnySchemaObject, KeywordCxt, Code, Name} from "ajv" import {_, stringify, getProperty} from "ajv/dist/compile/codegen" type TransformName = | "trimStart" | "trimEnd" | "trimLeft" | "trimRight" | "trim" | "toLowerCase" | "toUpperCase" | "toEnumCase" interface TransformConfig { hash: Record } type Transform = (s: string, cfg?: TransformConfig) => string const transform: {[key in TransformName]: Transform} = { trimStart: (s) => s.trimStart(), trimEnd: (s) => s.trimEnd(), trimLeft: (s) => s.trimStart(), trimRight: (s) => s.trimEnd(), trim: (s) => s.trim(), toLowerCase: (s) => s.toLowerCase(), toUpperCase: (s) => s.toUpperCase(), toEnumCase: (s, cfg) => cfg?.hash[configKey(s)] || s, } const getDef: (() => CodeKeywordDefinition) & { transform: typeof transform } = Object.assign(_getDef, {transform}) function _getDef(): CodeKeywordDefinition { return { keyword: "transform", schemaType: "array", before: "enum", code(cxt: KeywordCxt) { const {gen, data, schema, parentSchema, it} = cxt const {parentData, parentDataProperty} = it const tNames: string[] = schema if (!tNames.length) return let cfg: Name | undefined if (tNames.includes("toEnumCase")) { const config = getEnumCaseCfg(parentSchema) cfg = gen.scopeValue("obj", {ref: config, code: stringify(config)}) } gen.if(_`typeof ${data} == "string" && ${parentData} !== undefined`, () => { gen.assign(data, transformExpr(tNames.slice())) gen.assign(_`${parentData}[${parentDataProperty}]`, data) }) function transformExpr(ts: string[]): Code { if (!ts.length) return data const t = ts.pop() as string if (!(t in transform)) throw new Error(`transform: unknown transformation ${t}`) const func = gen.scopeValue("func", { ref: transform[t as TransformName], code: _`require("ajv-keywords/dist/definitions/transform").transform${getProperty(t)}`, }) const arg = transformExpr(ts) return cfg && t === "toEnumCase" ? _`${func}(${arg}, ${cfg})` : _`${func}(${arg})` } }, metaSchema: { type: "array", items: {type: "string", enum: Object.keys(transform)}, }, } } function getEnumCaseCfg(parentSchema: AnySchemaObject): TransformConfig { // build hash table to enum values const cfg: TransformConfig = {hash: {}} // requires `enum` in the same schema as transform if (!parentSchema.enum) throw new Error('transform: "toEnumCase" requires "enum"') for (const v of parentSchema.enum) { if (typeof v !== "string") continue const k = configKey(v) // requires all `enum` values have unique keys if (cfg.hash[k]) { throw new Error('transform: "toEnumCase" requires all lowercased "enum" values to be unique') } cfg.hash[k] = v } return cfg } function configKey(s: string): string { return s.toLowerCase() } export default getDef module.exports = getDef ajv-keywords-5.1.0/src/definitions/typeof.ts000066400000000000000000000013521414652001000211140ustar00rootroot00000000000000import type {CodeKeywordDefinition, KeywordCxt} from "ajv" import {_} from "ajv/dist/compile/codegen" const TYPES = ["undefined", "string", "number", "object", "function", "boolean", "symbol"] export default function getDef(): CodeKeywordDefinition { return { keyword: "typeof", schemaType: ["string", "array"], code(cxt: KeywordCxt) { const {data, schema, schemaValue} = cxt cxt.fail( typeof schema == "string" ? _`typeof ${data} != ${schema}` : _`${schemaValue}.indexOf(typeof ${data}) < 0` ) }, metaSchema: { anyOf: [ {type: "string", enum: TYPES}, {type: "array", items: {type: "string", enum: TYPES}}, ], }, } } module.exports = getDef ajv-keywords-5.1.0/src/definitions/uniqueItemProperties.ts000066400000000000000000000033441414652001000240130ustar00rootroot00000000000000import type {FuncKeywordDefinition, AnySchemaObject} from "ajv" import equal = require("fast-deep-equal") const SCALAR_TYPES = ["number", "integer", "string", "boolean", "null"] export default function getDef(): FuncKeywordDefinition { return { keyword: "uniqueItemProperties", type: "array", schemaType: "array", compile(keys: string[], parentSchema: AnySchemaObject) { const scalar = getScalarKeys(keys, parentSchema) return (data) => { if (data.length <= 1) return true for (let k = 0; k < keys.length; k++) { const key = keys[k] if (scalar[k]) { const hash: Record = {} for (const x of data) { if (!x || typeof x != "object") continue let p = x[key] if (p && typeof p == "object") continue if (typeof p == "string") p = '"' + p if (hash[p]) return false hash[p] = true } } else { for (let i = data.length; i--; ) { const x = data[i] if (!x || typeof x != "object") continue for (let j = i; j--; ) { const y = data[j] if (y && typeof y == "object" && equal(x[key], y[key])) return false } } } } return true } }, metaSchema: { type: "array", items: {type: "string"}, }, } } function getScalarKeys(keys: string[], schema: AnySchemaObject): boolean[] { return keys.map((key) => { const t = schema.items?.properties?.[key]?.type return Array.isArray(t) ? !t.includes("object") && !t.includes("array") : SCALAR_TYPES.includes(t) }) } module.exports = getDef ajv-keywords-5.1.0/src/index.ts000066400000000000000000000014371414652001000164060ustar00rootroot00000000000000import type Ajv from "ajv" import type {Plugin} from "ajv" import plugins from "./keywords" export {AjvKeywordsError} from "./definitions" const ajvKeywords: Plugin = (ajv: Ajv, keyword?: string | string[]): Ajv => { if (Array.isArray(keyword)) { for (const k of keyword) get(k)(ajv) return ajv } if (keyword) { get(keyword)(ajv) return ajv } for (keyword in plugins) get(keyword)(ajv) return ajv } ajvKeywords.get = get function get(keyword: string): Plugin { const defFunc = plugins[keyword] if (!defFunc) throw new Error("Unknown keyword " + keyword) return defFunc } export default ajvKeywords module.exports = ajvKeywords // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access module.exports.default = ajvKeywords ajv-keywords-5.1.0/src/keywords/000077500000000000000000000000001414652001000165715ustar00rootroot00000000000000ajv-keywords-5.1.0/src/keywords/allRequired.ts000066400000000000000000000003231414652001000214100ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/allRequired" const allRequired: Plugin = (ajv) => ajv.addKeyword(getDef()) export default allRequired module.exports = allRequired ajv-keywords-5.1.0/src/keywords/anyRequired.ts000066400000000000000000000003231414652001000214270ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/anyRequired" const anyRequired: Plugin = (ajv) => ajv.addKeyword(getDef()) export default anyRequired module.exports = anyRequired ajv-keywords-5.1.0/src/keywords/deepProperties.ts000066400000000000000000000005041414652001000221320ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/deepProperties" import type {DefinitionOptions} from "../definitions/_types" const deepProperties: Plugin = (ajv, opts?: DefinitionOptions) => ajv.addKeyword(getDef(opts)) export default deepProperties module.exports = deepProperties ajv-keywords-5.1.0/src/keywords/deepRequired.ts000066400000000000000000000003271414652001000215610ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/deepRequired" const deepRequired: Plugin = (ajv) => ajv.addKeyword(getDef()) export default deepRequired module.exports = deepRequired ajv-keywords-5.1.0/src/keywords/dynamicDefaults.ts000066400000000000000000000003431414652001000222550ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/dynamicDefaults" const dynamicDefaults: Plugin = (ajv) => ajv.addKeyword(getDef()) export default dynamicDefaults module.exports = dynamicDefaults ajv-keywords-5.1.0/src/keywords/exclusiveRange.ts000066400000000000000000000003371414652001000221300ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/exclusiveRange" const exclusiveRange: Plugin = (ajv) => ajv.addKeyword(getDef()) export default exclusiveRange module.exports = exclusiveRange ajv-keywords-5.1.0/src/keywords/index.ts000066400000000000000000000021011414652001000202420ustar00rootroot00000000000000import type {Plugin} from "ajv" import typeofPlugin from "./typeof" import instanceofPlugin from "./instanceof" import range from "./range" import exclusiveRange from "./exclusiveRange" import regexp from "./regexp" import transform from "./transform" import uniqueItemProperties from "./uniqueItemProperties" import allRequired from "./allRequired" import anyRequired from "./anyRequired" import oneRequired from "./oneRequired" import patternRequired from "./patternRequired" import prohibited from "./prohibited" import deepProperties from "./deepProperties" import deepRequired from "./deepRequired" import dynamicDefaults from "./dynamicDefaults" import select from "./select" // TODO type const ajvKeywords: Record | undefined> = { typeof: typeofPlugin, instanceof: instanceofPlugin, range, exclusiveRange, regexp, transform, uniqueItemProperties, allRequired, anyRequired, oneRequired, patternRequired, prohibited, deepProperties, deepRequired, dynamicDefaults, select, } export default ajvKeywords module.exports = ajvKeywords ajv-keywords-5.1.0/src/keywords/instanceof.ts000066400000000000000000000003411414652001000212700ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/instanceof" const instanceofPlugin: Plugin = (ajv) => ajv.addKeyword(getDef()) export default instanceofPlugin module.exports = instanceofPlugin ajv-keywords-5.1.0/src/keywords/oneRequired.ts000066400000000000000000000003231414652001000214210ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/oneRequired" const oneRequired: Plugin = (ajv) => ajv.addKeyword(getDef()) export default oneRequired module.exports = oneRequired ajv-keywords-5.1.0/src/keywords/patternRequired.ts000066400000000000000000000003431414652001000223170ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/patternRequired" const patternRequired: Plugin = (ajv) => ajv.addKeyword(getDef()) export default patternRequired module.exports = patternRequired ajv-keywords-5.1.0/src/keywords/prohibited.ts000066400000000000000000000003171414652001000212730ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/prohibited" const prohibited: Plugin = (ajv) => ajv.addKeyword(getDef()) export default prohibited module.exports = prohibited ajv-keywords-5.1.0/src/keywords/range.ts000066400000000000000000000002731414652001000202370ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/range" const range: Plugin = (ajv) => ajv.addKeyword(getDef()) export default range module.exports = range ajv-keywords-5.1.0/src/keywords/regexp.ts000066400000000000000000000002771414652001000204410ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/regexp" const regexp: Plugin = (ajv) => ajv.addKeyword(getDef()) export default regexp module.exports = regexp ajv-keywords-5.1.0/src/keywords/select.ts000066400000000000000000000005111414652001000204150ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDefs from "../definitions/select" import type {DefinitionOptions} from "../definitions/_types" const select: Plugin = (ajv, opts?: DefinitionOptions) => { getDefs(opts).forEach((d) => ajv.addKeyword(d)) return ajv } export default select module.exports = select ajv-keywords-5.1.0/src/keywords/transform.ts000066400000000000000000000003131414652001000211510ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/transform" const transform: Plugin = (ajv) => ajv.addKeyword(getDef()) export default transform module.exports = transform ajv-keywords-5.1.0/src/keywords/typeof.ts000066400000000000000000000003211414652001000204430ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/typeof" const typeofPlugin: Plugin = (ajv) => ajv.addKeyword(getDef()) export default typeofPlugin module.exports = typeofPlugin ajv-keywords-5.1.0/src/keywords/uniqueItemProperties.ts000066400000000000000000000003671414652001000233510ustar00rootroot00000000000000import type {Plugin} from "ajv" import getDef from "../definitions/uniqueItemProperties" const uniqueItemProperties: Plugin = (ajv) => ajv.addKeyword(getDef()) export default uniqueItemProperties module.exports = uniqueItemProperties ajv-keywords-5.1.0/tsconfig.json000066400000000000000000000002051414652001000166370ustar00rootroot00000000000000{ "extends": "@ajv-validator/config", "include": ["src"], "compilerOptions": { "outDir": "dist", "allowJs": true } }