Showing preview only (1,939K chars total). Download the full file or copy to clipboard to get everything.
Repository: ajv-validator/ajv
Branch: master
Commit: 142ce84b807c
Files: 433
Total size: 1.8 MB
Directory structure:
gitextract_hfo2xbb4/
├── .eslintrc.js
├── .github/
│ ├── CODEOWNERS
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-or-error-report.md
│ │ ├── change.md
│ │ ├── compatibility.md
│ │ ├── installation.md
│ │ └── typescript.md
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── config.yml
│ ├── dependabot.yml
│ └── workflows/
│ ├── build.yml
│ └── publish.yml
├── .gitignore
├── .gitmodules
├── .npmrc
├── .prettierignore
├── .runkit_example.js
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── benchmark/
│ ├── jtd.js
│ └── package.json
├── bower.json
├── docs/
│ ├── .vuepress/
│ │ ├── components/
│ │ │ ├── Button.vue
│ │ │ ├── Column.vue
│ │ │ ├── Columns.vue
│ │ │ ├── Contributors.vue
│ │ │ ├── Feature.vue
│ │ │ ├── Features.vue
│ │ │ ├── FooterColumn.vue
│ │ │ ├── FooterColumns.vue
│ │ │ ├── GitHub.vue
│ │ │ ├── HeroSection.vue
│ │ │ ├── HomePage.vue
│ │ │ ├── HomeSection.vue
│ │ │ ├── NewsHome.vue
│ │ │ ├── NewsIndex.vue
│ │ │ ├── NewsPost.vue
│ │ │ ├── NewsPostMeta.vue
│ │ │ ├── Projects.vue
│ │ │ ├── Sponsors.vue
│ │ │ ├── Subscribe.vue
│ │ │ ├── Testimonial.vue
│ │ │ └── Testimonials.vue
│ │ ├── config.js
│ │ ├── styles/
│ │ │ ├── index.styl
│ │ │ └── palette.styl
│ │ └── theme/
│ │ ├── LICENSE
│ │ ├── components/
│ │ │ ├── AlgoliaSearchBox.vue
│ │ │ ├── DropdownLink.vue
│ │ │ ├── DropdownTransition.vue
│ │ │ ├── Home.vue
│ │ │ ├── NavLink.vue
│ │ │ ├── NavLinks.vue
│ │ │ ├── Navbar.vue
│ │ │ ├── Page.vue
│ │ │ ├── PageEdit.vue
│ │ │ ├── PageNav.vue
│ │ │ ├── Sidebar.vue
│ │ │ ├── SidebarButton.vue
│ │ │ ├── SidebarGroup.vue
│ │ │ ├── SidebarLink.vue
│ │ │ └── SidebarLinks.vue
│ │ ├── global-components/
│ │ │ ├── Badge.vue
│ │ │ ├── CodeBlock.vue
│ │ │ └── CodeGroup.vue
│ │ ├── index.js
│ │ ├── layouts/
│ │ │ ├── 404.vue
│ │ │ └── Layout.vue
│ │ ├── noopModule.js
│ │ ├── styles/
│ │ │ ├── arrow.styl
│ │ │ ├── code.styl
│ │ │ ├── config.styl
│ │ │ ├── custom-blocks.styl
│ │ │ ├── index.styl
│ │ │ ├── mobile.styl
│ │ │ ├── toc.styl
│ │ │ └── wrapper.styl
│ │ └── util/
│ │ └── index.js
│ ├── README.md
│ ├── api.md
│ ├── codegen.md
│ ├── coercion.md
│ ├── components.md
│ ├── faq.md
│ ├── guide/
│ │ ├── async-validation.md
│ │ ├── combining-schemas.md
│ │ ├── environments.md
│ │ ├── formats.md
│ │ ├── getting-started.md
│ │ ├── managing-schemas.md
│ │ ├── modifying-data.md
│ │ ├── schema-language.md
│ │ ├── typescript.md
│ │ ├── user-keywords.md
│ │ └── why-ajv.md
│ ├── json-schema.md
│ ├── json-type-definition.md
│ ├── keywords.md
│ ├── news/
│ │ ├── 2020-08-14-mozilla-grant-openjs-foundation.md
│ │ ├── 2020-12-15-ajv-version-7-released.md
│ │ ├── 2021-03-07-ajv-supports-json-type-definition.md
│ │ ├── 2021-03-27-ajv-version-8-released.md
│ │ ├── 2021-04-24-ajv-online-event.md
│ │ ├── 2021-05-24-ajv-online-event-video.md
│ │ ├── 2021-07-22-ajv-microsoft-foss-fund-award.md
│ │ └── README.md
│ ├── options.md
│ ├── packages/
│ │ └── README.md
│ ├── security.md
│ ├── standalone.md
│ ├── strict-mode.md
│ ├── testimonials.md
│ └── v6-to-v8-migration.md
├── karma.conf.js
├── lib/
│ ├── 2019.ts
│ ├── 2020.ts
│ ├── ajv.ts
│ ├── compile/
│ │ ├── codegen/
│ │ │ ├── code.ts
│ │ │ ├── index.ts
│ │ │ └── scope.ts
│ │ ├── errors.ts
│ │ ├── index.ts
│ │ ├── jtd/
│ │ │ ├── parse.ts
│ │ │ ├── serialize.ts
│ │ │ └── types.ts
│ │ ├── names.ts
│ │ ├── ref_error.ts
│ │ ├── resolve.ts
│ │ ├── rules.ts
│ │ ├── util.ts
│ │ └── validate/
│ │ ├── applicability.ts
│ │ ├── boolSchema.ts
│ │ ├── dataType.ts
│ │ ├── defaults.ts
│ │ ├── index.ts
│ │ ├── keyword.ts
│ │ └── subschema.ts
│ ├── core.ts
│ ├── jtd.ts
│ ├── refs/
│ │ ├── data.json
│ │ ├── json-schema-2019-09/
│ │ │ ├── index.ts
│ │ │ ├── meta/
│ │ │ │ ├── applicator.json
│ │ │ │ ├── content.json
│ │ │ │ ├── core.json
│ │ │ │ ├── format.json
│ │ │ │ ├── meta-data.json
│ │ │ │ └── validation.json
│ │ │ └── schema.json
│ │ ├── json-schema-2020-12/
│ │ │ ├── index.ts
│ │ │ ├── meta/
│ │ │ │ ├── applicator.json
│ │ │ │ ├── content.json
│ │ │ │ ├── core.json
│ │ │ │ ├── format-annotation.json
│ │ │ │ ├── meta-data.json
│ │ │ │ ├── unevaluated.json
│ │ │ │ └── validation.json
│ │ │ └── schema.json
│ │ ├── json-schema-draft-06.json
│ │ ├── json-schema-draft-07.json
│ │ ├── json-schema-secure.json
│ │ └── jtd-schema.ts
│ ├── runtime/
│ │ ├── equal.ts
│ │ ├── parseJson.ts
│ │ ├── quote.ts
│ │ ├── re2.ts
│ │ ├── timestamp.ts
│ │ ├── ucs2length.ts
│ │ ├── uri.ts
│ │ └── validation_error.ts
│ ├── standalone/
│ │ ├── index.ts
│ │ └── instance.ts
│ ├── types/
│ │ ├── index.ts
│ │ ├── json-schema.ts
│ │ └── jtd-schema.ts
│ └── vocabularies/
│ ├── applicator/
│ │ ├── additionalItems.ts
│ │ ├── additionalProperties.ts
│ │ ├── allOf.ts
│ │ ├── anyOf.ts
│ │ ├── contains.ts
│ │ ├── dependencies.ts
│ │ ├── dependentSchemas.ts
│ │ ├── if.ts
│ │ ├── index.ts
│ │ ├── items.ts
│ │ ├── items2020.ts
│ │ ├── not.ts
│ │ ├── oneOf.ts
│ │ ├── patternProperties.ts
│ │ ├── prefixItems.ts
│ │ ├── properties.ts
│ │ ├── propertyNames.ts
│ │ └── thenElse.ts
│ ├── code.ts
│ ├── core/
│ │ ├── id.ts
│ │ ├── index.ts
│ │ └── ref.ts
│ ├── discriminator/
│ │ ├── index.ts
│ │ └── types.ts
│ ├── draft2020.ts
│ ├── draft7.ts
│ ├── dynamic/
│ │ ├── dynamicAnchor.ts
│ │ ├── dynamicRef.ts
│ │ ├── index.ts
│ │ ├── recursiveAnchor.ts
│ │ └── recursiveRef.ts
│ ├── errors.ts
│ ├── format/
│ │ ├── format.ts
│ │ └── index.ts
│ ├── jtd/
│ │ ├── discriminator.ts
│ │ ├── elements.ts
│ │ ├── enum.ts
│ │ ├── error.ts
│ │ ├── index.ts
│ │ ├── metadata.ts
│ │ ├── nullable.ts
│ │ ├── optionalProperties.ts
│ │ ├── properties.ts
│ │ ├── ref.ts
│ │ ├── type.ts
│ │ ├── union.ts
│ │ └── values.ts
│ ├── metadata.ts
│ ├── next.ts
│ ├── unevaluated/
│ │ ├── index.ts
│ │ ├── unevaluatedItems.ts
│ │ └── unevaluatedProperties.ts
│ └── validation/
│ ├── const.ts
│ ├── dependentRequired.ts
│ ├── enum.ts
│ ├── index.ts
│ ├── limitContains.ts
│ ├── limitItems.ts
│ ├── limitLength.ts
│ ├── limitNumber.ts
│ ├── limitProperties.ts
│ ├── multipleOf.ts
│ ├── pattern.ts
│ ├── required.ts
│ └── uniqueItems.ts
├── package.json
├── rollup.config.js
├── scripts/
│ ├── .eslintrc.yml
│ ├── bundle.js
│ ├── get-ajv-packages
│ ├── get-contributors.js
│ ├── jsontests.js
│ ├── prepare-site
│ ├── prepare-tests
│ ├── publish-bundles
│ └── publish-site
├── spec/
│ ├── .eslintrc.yml
│ ├── _json/
│ │ └── README.md
│ ├── after_test.ts
│ ├── ajv.spec.ts
│ ├── ajv.ts
│ ├── ajv2019.ts
│ ├── ajv2020.ts
│ ├── ajv_all_instances.ts
│ ├── ajv_async_instances.ts
│ ├── ajv_instances.ts
│ ├── ajv_jtd.ts
│ ├── ajv_options.ts
│ ├── ajv_standalone.ts
│ ├── async/
│ │ ├── boolean.json
│ │ ├── compound.json
│ │ ├── format.json
│ │ ├── items.json
│ │ ├── keyword.json
│ │ ├── no_async.json
│ │ └── properties.json
│ ├── async.spec.ts
│ ├── async_schemas.spec.ts
│ ├── async_validate.spec.ts
│ ├── boolean.spec.ts
│ ├── chai.ts
│ ├── chai_type.ts
│ ├── codegen.spec.ts
│ ├── coercion.spec.ts
│ ├── discriminator.spec.ts
│ ├── dynamic-ref.spec.ts
│ ├── errors.spec.ts
│ ├── extras/
│ │ ├── $data/
│ │ │ ├── absolute_ref.json
│ │ │ ├── const.json
│ │ │ ├── enum.json
│ │ │ ├── exclusiveMaximum.json
│ │ │ ├── exclusiveMinimum.json
│ │ │ ├── format.json
│ │ │ ├── maxItems.json
│ │ │ ├── maxLength.json
│ │ │ ├── maxProperties.json
│ │ │ ├── maximum.json
│ │ │ ├── minItems.json
│ │ │ ├── minLength.json
│ │ │ ├── minProperties.json
│ │ │ ├── minimum.json
│ │ │ ├── multipleOf.json
│ │ │ ├── pattern.json
│ │ │ ├── required.json
│ │ │ └── uniqueItems.json
│ │ ├── const.json
│ │ ├── contains.json
│ │ ├── exclusiveMaximum.json
│ │ └── exclusiveMinimum.json
│ ├── extras.spec.ts
│ ├── issues/
│ │ ├── 1001_addKeyword_and_schema_without_id.spec.ts
│ │ ├── 1344_non_root_recursive_ref_standalone.spec.ts
│ │ ├── 1414_base_uri_change.spec.ts
│ │ ├── 1501_jtd_many_properties.spec.ts
│ │ ├── 1515_evaluated_properties_nested_anyof.spec.ts
│ │ ├── 1539_add_keyword_name_to_validation_error.spec.ts
│ │ ├── 1625_evaluated_truthy_pattern_properties.spec.ts
│ │ ├── 1683_re2_engine.spec.ts
│ │ ├── 1819_mincontains.spec.ts
│ │ ├── 181_allErrors_custom_keyword_skipped.spec.ts
│ │ ├── 182_nan_validation.spec.ts
│ │ ├── 1935_integer_narrowing_subschema.spec.ts
│ │ ├── 1949_jtd_empty_values.spec.ts
│ │ ├── 1971_jtd_discriminator.spec.ts
│ │ ├── 2001_jtd_only_optional_properties.spec.ts
│ │ ├── 204_options_schemas_data_together.spec.ts
│ │ ├── 210_mutual_recur_frags.spec.ts
│ │ ├── 240_mutual_recur_frags_common_ref.spec.ts
│ │ ├── 259_validate_meta_against_itself.spec.ts
│ │ ├── 273_error_schemaPath_refd_schema.spec.ts
│ │ ├── 342_uniqueItems_non-json_objects.spec.ts
│ │ ├── 485_type_validation_priority.spec.ts
│ │ ├── 50_refs_with_definitions.spec.ts
│ │ ├── 521_wrong_warning_id_property.spec.ts
│ │ ├── 743_removeAdditional_to_remove_proto.spec.ts
│ │ ├── 768_passContext_recursive_ref.spec.ts
│ │ ├── 815_id_updates_ref_base.spec.ts
│ │ ├── 8_shared_refs.spec.ts
│ │ ├── 955_removeAdditional_custom_keywords.spec.ts
│ │ ├── cve_2025_69873_redos_attack.spec.ts
│ │ └── re2.ts
│ ├── javacript.spec.js
│ ├── json-schema.spec.ts
│ ├── json_parse_tests.json
│ ├── jtd-schema.spec.ts
│ ├── jtd-timestamps.spec.ts
│ ├── keyword.spec.ts
│ ├── options/
│ │ ├── comment.spec.ts
│ │ ├── int32range.spec.ts
│ │ ├── meta_validateSchema.spec.ts
│ │ ├── nullable.spec.ts
│ │ ├── options_add_schemas.spec.ts
│ │ ├── options_code.spec.ts
│ │ ├── options_refs.spec.ts
│ │ ├── options_reporting.spec.ts
│ │ ├── options_validation.spec.ts
│ │ ├── ownProperties.spec.ts
│ │ ├── removeAdditional.spec.ts
│ │ ├── schemaId.spec.ts
│ │ ├── strict.spec.ts
│ │ ├── strictDefaults.spec.ts
│ │ ├── strictKeywords.spec.ts
│ │ ├── strictNumbers.spec.ts
│ │ ├── unicodeRegExp.spec.ts
│ │ ├── unknownFormats.spec.ts
│ │ └── useDefaults.spec.ts
│ ├── remotes/
│ │ ├── bar.json
│ │ ├── buu.json
│ │ ├── first.json
│ │ ├── foo.json
│ │ ├── hyper-schema.json
│ │ ├── name.json
│ │ ├── node.json
│ │ ├── scope_change.json
│ │ ├── second.json
│ │ └── tree.json
│ ├── resolve.spec.ts
│ ├── schema-tests.spec.ts
│ ├── security/
│ │ ├── array.json
│ │ ├── object.json
│ │ └── string.json
│ ├── security.spec.ts
│ ├── standalone.spec.ts
│ ├── tests/
│ │ ├── issues/
│ │ │ ├── 12_restoring_root_after_resolve.json
│ │ │ ├── 13_root_ref_in_ref_in_remote_ref.json
│ │ │ ├── 14_ref_in_remote_ref_with_id.json
│ │ │ ├── 1668_not_with_other_keywords.json
│ │ │ ├── 170_ref_and_id_in_sibling.json
│ │ │ ├── 17_escaping_pattern_property.json
│ │ │ ├── 19_required_many_properties.json
│ │ │ ├── 1_ids_in_refs.json
│ │ │ ├── 20_failing_to_parse_schema.json
│ │ │ ├── 226_json_with_control_chars.json
│ │ │ ├── 27_1_recursive_raml_schema.json
│ │ │ ├── 27_recursive_reference.json
│ │ │ ├── 28_escaping_pattern_error.json
│ │ │ ├── 2_root_ref_in_ref.json
│ │ │ ├── 311_quotes_in_refs.json
│ │ │ ├── 33_json_schema_latest.json
│ │ │ ├── 413_dependencies_with_quote.json
│ │ │ ├── 490_integer_validation.json
│ │ │ ├── 502_contains_empty_array_with_ref_in_another_property.json
│ │ │ ├── 5_adding_dependency_after.json
│ │ │ ├── 5_recursive_references.json
│ │ │ ├── 62_resolution_scope_change.json
│ │ │ ├── 63_id_property_not_in_schema.json
│ │ │ ├── 70_1_recursive_hash_ref_in_remote_ref.json
│ │ │ ├── 70_swagger_schema.json
│ │ │ ├── 861_empty_propertynames.json
│ │ │ ├── 87_$_property.json
│ │ │ └── 94_dependencies_fail.json
│ │ ├── rules/
│ │ │ ├── allOf.json
│ │ │ ├── anyOf.json
│ │ │ ├── comment.json
│ │ │ ├── dependencies.json
│ │ │ ├── format.json
│ │ │ ├── if.json
│ │ │ ├── items.json
│ │ │ ├── oneOf.json
│ │ │ ├── required.json
│ │ │ ├── type.json
│ │ │ └── uniqueItems.json
│ │ └── schemas/
│ │ ├── advanced.json
│ │ ├── basic.json
│ │ ├── complex.json
│ │ ├── complex2.json
│ │ ├── complex3.json
│ │ ├── cosmicrealms.json
│ │ └── medium.json
│ ├── tsconfig.json
│ └── types/
│ ├── async-validate.spec.ts
│ ├── error-parameters.spec.ts
│ ├── json-schema.spec.ts
│ └── jtd-schema.spec.ts
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintrc.js
================================================
const 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", 17],
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/no-implied-eval": "off",
"@typescript-eslint/no-invalid-this": "off",
"@typescript-eslint/no-parameter-properties": "off",
"@typescript-eslint/no-unnecessary-condition": "warn",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/restrict-template-expressions": "off",
},
},
],
}
================================================
FILE: .github/CODEOWNERS
================================================
@epoberezkin
================================================
FILE: .github/FUNDING.yml
================================================
github: epoberezkin
tidelift: "npm/ajv"
open_collective: "ajv"
================================================
FILE: .github/ISSUE_TEMPLATE/bug-or-error-report.md
================================================
---
name: Bug or error report
about: Please use for issues related to incorrect validation behaviour
title: ""
labels: "bug report"
assignees: ""
---
<!--
Frequently Asked Questions: https://ajv.js.org/faq.html
Please provide all info and reduce your schema and data to the smallest possible size.
This template is for bug or error reports.
For other issues please see https://ajv.js.org/contributing/
-->
**What version of Ajv are you using? Does the issue happen if you use the latest version?**
**Ajv options object**
<!-- See https://ajv.js.org/options.html -->
```javascript
```
**JSON Schema**
<!-- Please make it as small as possible to reproduce the issue -->
```json
```
**Sample data**
<!-- Please make it as small as possible to reproduce the issue -->
```json
```
**Your code**
<!--
Please:
- make it as small as possible to reproduce the issue
- use one of the usage patterns from https://ajv.js.org/guide/getting-started.html
- use `options`, `schema` and `data` as variables, do not repeat their values here
- post a working code sample in RunKit notebook cloned from https://runkit.com/esp/ajv-issue and include the link here.
It would make understanding your problem easier and the issue more useful to others.
Thank you!
-->
```javascript
```
**Validation result, data AFTER validation, error messages**
```
```
**What results did you expect?**
**Are you going to resolve the issue?**
================================================
FILE: .github/ISSUE_TEMPLATE/change.md
================================================
---
name: Feature or change proposal
about: For proposals of new features, options or some other improvements
title: ""
labels: "enhancement"
assignees: ""
---
<!--
Frequently Asked Questions: https://ajv.js.org/faq.html
Please provide all info and reduce your schema and data to the smallest possible size.
This template is for change proposals.
For other issues please see https://ajv.js.org/contributing/
-->
**What version of Ajv you are you using?**
**What problem do you want to solve?**
**What do you think is the correct solution to problem?**
**Will you be able to implement it?**
================================================
FILE: .github/ISSUE_TEMPLATE/compatibility.md
================================================
---
name: Browser and compatibility issue
about: For issues that only happen in a specific environment
title: ""
labels: "compatibility"
assignees: ""
---
<!--
Frequently Asked Questions: https://ajv.js.org/faq.html
Please provide all info and reduce your schema and data to the smallest possible size.
This template is for compatibility issues.
For other issues please see https://ajv.js.org/contributing/
-->
**The version of Ajv you are using**
**The environment you have the problem with**
**Your code (please make it as small as possible to reproduce the issue)**
**If your issue is in the browser, please list the other packages loaded in the page in the order they are loaded. Please check if the issue gets resolved (or results change) if you move Ajv bundle closer to the top**
**Results in node.js v8+**
**Results and error messages in your platform**
================================================
FILE: .github/ISSUE_TEMPLATE/installation.md
================================================
---
name: Installation and dependency issue
about: For issues that happen during installation
title: ""
labels: "installation"
assignees: ""
---
<!--
Frequently Asked Questions: https://ajv.js.org/faq.html
Please provide all info and reduce your schema and data to the smallest possible size.
This template is for installation and dependency issues.
For other issues please see https://ajv.js.org/contributing/
Before submitting the issue, please try the following:
- use the latest stable Node.js and npm
- use yarn instead of npm - the issue can be related to https://github.com/npm/npm/issues/19877
- remove node_modules and package-lock.json and run install again
-->
**The version of Ajv you are using**
**Operating system and node.js version**
**Package manager and its version**
**Link to (or contents of) package.json**
**Error messages**
**The output of `npm ls`**
================================================
FILE: .github/ISSUE_TEMPLATE/typescript.md
================================================
---
name: Missing or incorrect type definition
about: Please use for issues related to typescript types
title: ""
labels: "typescript"
assignees: ""
---
<!--
Frequently Asked Questions: https://ajv.js.org/faq.html
This template is for issues about missing or incorrect type definition and other typescript-related issues.
For other issues please see https://ajv.js.org/contributing/
-->
**What version of Ajv are you using? Does the issue happen if you use the latest version?**
**Your typescript code**
<!--
Please make it as small as possible to reproduce the issue
-->
```typescript
```
**Typescript compiler error messages**
```
```
**Describe the change that should be made to address the issue?**
**Are you going to resolve the issue?**
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!--
Frequently Asked Questions: https://ajv.js.org/faq.html
Please provide all info and reduce your schema and data to the smallest possible size.
This template is for bug or error reports. For other issues please use:
- security vulnerability: https://tidelift.com/security)
- a new feature/improvement: https://ajv.js.org/contributing/#changes
- browser/compatibility issues: https://ajv.js.org/contributing/#compatibility
- JSON-Schema standard: https://ajv.js.org/contributing/#json-schema
- Ajv usage questions: https://gitter.im/ajv-validator/ajv
-->
**What version of Ajv are you using? Does the issue happen if you use the latest version?**
**Ajv options object**
<!-- See https://ajv.js.org/options.html -->
```javascript
```
**JSON Schema**
<!-- Please make it as small as possible to reproduce the issue -->
```json
```
**Sample data**
<!-- Please make it as small as possible to reproduce the issue -->
```json
```
**Your code**
<!--
Please:
- make it as small as possible to reproduce the issue
- use one of the usage patterns from https://ajv.js.org/guide/getting-started.html
- use `options`, `schema` and `data` as variables, do not repeat their values here
- post a working code sample in RunKit notebook cloned from https://runkit.com/esp/ajv-issue and include the link here.
It would make understanding your problem easier and the issue more useful to others.
Thank you!
-->
```javascript
```
**Validation result, data AFTER validation, error messages**
```
```
**What results did you expect?**
**Are you going to resolve the issue?**
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
Thank you for submitting a pull request to Ajv.
Before continuing, please read the guidelines:
https://github.com/ajv-validator/ajv/blob/master/CONTRIBUTING.md#pull-requests
If the pull request contains code please make sure there is an issue that we agreed to resolve (if it is a documentation improvement there is no need for an issue).
Please answer the questions below.
-->
**What issue does this pull request resolve?**
**What changes did you make?**
**Is there anything that requires more attention while reviewing?**
================================================
FILE: .github/config.yml
================================================
# Please supply comments to be used for GitHub labels
githubLabels:
bug: >
Bug confirmed - to be fixed. PR is welcome!
# duplicate: >
# enhancement: >
# good first issue: >
# help wanted: >
# invalid: >
# question: >
# wont fix: >
bug report: >
Thank you for the report! If you didn't post a code sample to RunKit yet,
please clone this notebook https://runkit.com/esp/ajv-issue,
post the code sample that demonstrates the bug and post the link here.
It will speed up the investigation and fixing!
json schema: >
This question is about the usage of JSON Schema specification - it is not specific to Ajv.
Please use JSON Schema reference materials or [submit the question to Stack Overflow](https://stackoverflow.com/questions/ask?tags=jsonschema,ajv).
- [JSON Schema specification](http://json-schema.org/)
- [Tutorial by Space Telescope Science Institute](http://json-schema.org/understanding-json-schema/)
- [validation keywords](https://github.com/ajv-validator/ajv#validation-keywords) (in Ajv docs)
- [combining schemas](https://github.com/ajv-validator/ajv#ref) (in Ajv docs)
- [Tutorial by @epoberezkin](https://code.tutsplus.com/tutorials/validating-data-with-json-schema-part-1--cms-25343)
================================================
FILE: .github/dependabot.yml
================================================
version: 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: karma
versions:
- 6.0.3
- 6.0.4
- 6.1.0
- 6.1.1
- 6.1.2
- 6.2.0
- 6.3.0
- 6.3.1
================================================
FILE: .github/workflows/build.yml
================================================
name: build
on:
push:
branches: [master]
pull_request:
branches: ["*"]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x, 21.x]
steps:
- uses: actions/checkout@v4
- name: use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: git submodule update --init
- name: update website
if: ${{ github.event_name == 'push' && matrix.node-version == '18.x' }}
run: ./scripts/publish-site
env:
GH_TOKEN_PUBLIC: ${{ secrets.GH_TOKEN_PUBLIC }}
GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}
GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}
- run: npm run build
- run: npm run test-ci
- name: coveralls
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/publish.yml
================================================
name: publish
on:
release:
types: [published]
jobs:
publish-npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
registry-url: https://registry.npmjs.org/
- run: npm install
- run: git submodule update --init
- run: npm run test-ci
- 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 }}
- name: Commit bundles to ajv-dist
run: ./scripts/publish-bundles
env:
GH_TOKEN_PUBLIC: ${{ secrets.GH_TOKEN_PUBLIC }}
GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}
GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}
================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
.nyc_output
# 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
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
.DS_Store
# Browserified tests
.browser
# compiled typescript
dist/
# browser bundles
bundle/
package-lock.json
spec/_json/*.js
# docs
docs/code_of_conduct.md
docs/contributing.md
docs/license.md
docs/.vuepress/components/Contributors/
docs/packages/*
!docs/packages/README.md
================================================
FILE: .gitmodules
================================================
[submodule "spec/JSON-Schema-Test-Suite"]
path = spec/JSON-Schema-Test-Suite
url = https://github.com/json-schema/JSON-Schema-Test-Suite.git
[submodule "spec/json-typedef-spec"]
path = spec/json-typedef-spec
url = https://github.com/jsontypedef/json-typedef-spec.git
================================================
FILE: .npmrc
================================================
package-lock=false
================================================
FILE: .prettierignore
================================================
spec/JSON-Schema-Test-Suite
spec/json-typedef-spec
.browser
coverage
dist
bundle
.nyc_output
spec/_json
docs/.vuepress/components/_contributors.js
================================================
FILE: .runkit_example.js
================================================
const Ajv = require("ajv")
const ajv = new Ajv({allErrors: true})
const schema = {
type: "object",
properties: {
foo: {type: "string"},
bar: {type: "number", maximum: 3},
},
required: ["foo", "bar"],
additionalProperties: false,
}
const validate = ajv.compile(schema)
test({foo: "abc", bar: 2})
test({foo: 2, bar: 4})
function test(data) {
const valid = validate(data)
if (valid) console.log("Valid!")
else console.log("Invalid: " + ajv.errorsText(validate.errors))
}
================================================
FILE: CODE_OF_CONDUCT.md
================================================
---
permalink: /code_of_conduct
---
# Contributor Covenant Code of Conduct
### Our Pledge
We commit to creating and maintaining an open and welcoming environment. We, as contributors and maintainers, commit to building 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
**Behaviour that contributes to creating a positive environment include**:
- Using welcoming and inclusive language
- Consider when identity words like race or ethnicity matter
- Be conscious of language with discriminatory connotations (e.g. gendered, ableist, racialized phrases)
- Be open to being corrected if you make a mistake - it’s okay to mess up, what matters is your follow up
- Gracefully accepting constructive criticism
- Showing empathy towards other community members
- Treat other community members and project team members with respect
- Report if you witness harassment or wrongdoing in our spaces
**Unacceptable behaviour 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 behaviour and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behaviour.
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
The goal of this Code of Conduct is to set standards and expectations around how we interact within this community. It’s scope applies to all project participants and covers all interactions within the community associated with this project including, but not limited to, email communication, issue trackers, source code repositories, forums, and social media.
Examples of representing a project or community include:
- Using an official project e-mail address
- Posting via an official social media account
- 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
We will not tolerate abuse, harassment, or any other unacceptable behaviour made against community members, project maintainers, or members of our project team, either online or offline.
Violations of our Code of Conduct may be reported by contacting the project team at [ajv.validator@gmail.com](mailto:ajv.validator@gmail.com). The project team will review and investigate all complaints, to the best of our ability, and will respond in a way that it deems appropriate to the circumstances.
Reports of violations will be investigated in a respectful, professional manner as promptly and confidentially as possible. We will have zero tolerance for intimidation or retaliation against anyone who raises a concern, makes a report or cooperates in an investigation around a violation of our code of conduct. 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 or removal as determined by other members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4,
available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html)
For answers to common questions about this code of conduct, see
[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq)
================================================
FILE: CONTRIBUTING.md
================================================
---
permalink: /contributing
---
# Contributing guide
Thank you for your help making Ajv better! Every contribution is appreciated. There are many areas where you can contribute.
More than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.
At Ajv, we are committed to creating more equitable and inclusive spaces for our community and team members to contribute to discussions that affect both this project and our ongoing work in the open source ecosystem.
We strive to create an environment of respect and healthy discourse by setting standards for our interactions and we expect it from all members of our community - from long term project member to first time visitor. For more information, review our [code of conduct](./CODE_OF_CONDUCT.md) and values.
::: tip Submit issue first
If you plan to implement a new feature or some other change please create an issue first, to make sure that your work is not lost.
:::
[[toc]]
## Documentation
Ajv has a lot of features and maintaining documentation takes time. If anything is unclear, or could be explained better, we appreciate the time you spend correcting or clarifying it.
There is a link in the bottom of each website page to quickly edit it.
## Issues
Before submitting the issue:
- Search the existing issues
- Review [Frequently Asked Questions](./docs/faq.md).
- Provide all the relevant information, reducing both your schema and data to the smallest possible size when they still have the issue.
We value simplicity - simplifying the example that shows the issue makes it more valuable for other users. This process helps us reduce situations where an error is occurring due to incorrect usage rather than a bug.
### Bug reports
Please make sure to include the following information in the issue:
1. What version of Ajv are you using?
2. Does the issue happen if you use the latest version?
3. Ajv [options object](./docs/options)
4. Schema and the data you are validating (please make it as small as possible to reproduce the issue).
5. Your code sample (please use `options`, `schema` and `data` as variables).
6. Validation result, data AFTER validation, error messages.
7. What results did you expect?
To speed up investigation and fixes, please include the link to the working code sample at runkit.com (please clone https://runkit.com/esp/ajv-issue).
[Create bug report](https://github.com/ajv-validator/ajv/issues/new?template=bug-or-error-report.md).
### Security vulnerabilities
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.
<a name="changes"></a>
### Change proposals
[Create a proposal](https://github.com/ajv-validator/ajv/issues/new?template=change.md) for a new feature, option or some other improvement.
Please include this information:
1. The version of Ajv you are using.
2. The problem you want to solve.
3. Your solution to the problem.
4. Would you like to implement it?
If you’re requesting a change, it would be helpful to include this as well:
1. What you did.
2. What happened.
3. What you would like to happen.
Please include as much details as possible - the more information, the better.
<a name="compatibility"></a>
### Browser and compatibility issues
[Create an issue](https://github.com/ajv-validator/ajv/issues/new?template=compatibility.md) to report a compatibility problem that only happens in a particular environment (when your code works correctly in the latest stable Node.js in linux systems but fails in some other environment).
Please include this information:
1. The version of Ajv you are using.
2. The environment you have the problem with.
3. Your code (please make it as small as possible to reproduce the issue).
4. If your issue is in the browser, please list the other packages loaded in the page in the order they are loaded. Please check if the issue gets resolved (or results change) if you move Ajv bundle closer to the top.
5. Results in the latest stable Node.js.
6. Results and error messages in your platform.
<a name="installation"></a>
### Installation and dependency issues
[Create an issue](https://github.com/ajv-validator/ajv/issues/new?template=installation.md) to report problems that happen during Ajv installation or when Ajv is missing some dependency.
Before submitting the issue, please try the following:
- use the latest stable Node.js and `npm`
- try using `yarn` instead of `npm` - the issue can be related to https://github.com/npm/npm/issues/19877
- remove `node_modules` and `package-lock.json` and run `npm install` again
If nothing helps, please submit:
1. The version of Ajv you are using
2. Operating system and Node.js version
3. Package manager and its version
4. Link to (or contents of) package.json and package-lock.json
5. Error messages
6. The output of `npm ls`
<a name="json-schema"></a>
### Using JSON Schema standard
Ajv implements JSON Schema standard draft-04 and draft-06/07.
If it is a general issue related to using the standard keywords included in JSON Schema specification or implementing some advanced validation logic please ask the question on [Stack Overflow](https://stackoverflow.com/questions/ask?tags=jsonschema,ajv) (my account is [esp](https://stackoverflow.com/users/1816503/esp)) or submit the question to [json-schema.org](https://github.com/json-schema-org/json-schema-spec/issues/new). Please mention @epoberezkin.
<a name="usage"></a>
### Ajv usage questions
The best place to ask a question about using Ajv is [Gitter chat](https://gitter.im/ajv-validator/ajv).
If the question is advanced, it can be submitted to [Stack Overflow](http://stackoverflow.com/questions/ask?tags=jsonschema,ajv).
## Code
Thanks a lot for considering contributing to Ajv! Our users have created many great features, and we look forward to your contributions.
For help navigating the code, please review the [Code components](./docs/components.md) document.
### How we make decisions
We value conscious curation of our library size, and balancing performance and functionality. To that end, we cannot accept every suggestion. When evaluating pull requests we consider:
- Will this benefit many users or a niche use case?
- How will this impact the performance of Ajv?
- How will this expand our library size?
To help us evaluate and understand, when you submit an issue and pull request:
- Explain why this feature is important to the user base
- Include documentation
- Include test coverage with any new feature implementations
Please include documentation and test coverage with any new feature implementations.
### Development
Running tests:
```bash
npm install
git submodule update --init
npm test
```
`npm run build` - compiles typescript to dist folder.
`npm run watch` - automatically compiles typescript when files on lib folder changes.
### Pull requests
We want to iterate on the code efficiently. To speed up the process, please follow these steps:
1. Submit an [issue with the bug](https://github.com/ajv-validator/ajv/issues/new) or with the proposed change (unless the contribution is to fix the documentation typos and mistakes).
2. Describe the proposed api and implementation plan (unless the issue is a relatively simple bug and fixing it doesn't change any api).
3. Once agreed, please write as little code as possible to achieve the desired result. We are passionate about keeping our library size optimized.
4. Please add the tests both for the added feature and, if you are submitting an option, for the existing behaviour when this option is turned off or not passed.
5. Please avoid unnecessary changes, refactoring or changing coding styles as part of your change (unless the change was proposed as refactoring).
6. Follow the coding conventions even if they are not validated.
7. Please run the tests before committing your code.
8. If tests fail in CI build after you make a PR please investigate and fix the issue.
### Contributions license
When contributing the code you confirm that:
1. Your contribution is created by you.
2. You have the right to submit it under the MIT license.
3. You understand and agree that your contribution is public, will be stored indefinitely, can be redistributed as the part of Ajv or another related package under MIT license, modified or completely removed from Ajv.
4. You grant irrevocable MIT license to use your contribution as part of Ajv or any other package.
5. You waive all rights to your contribution.
6. Unless you request otherwise, you can be mentioned as the author of the contribution in the Ajv documentation and change log.
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015-2021 Evgeny Poberezkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<img align="right" alt="Ajv logo" width="160" src="https://ajv.js.org/img/ajv.svg">
# Ajv JSON schema validator
The fastest JSON validator for Node.js and browser.
Supports JSON Schema draft-04/06/07/2019-09/2020-12 ([draft-04 support](https://ajv.js.org/json-schema.html#draft-04) requires ajv-draft-04 package) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).
[](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)
[](https://www.npmjs.com/package/ajv)
[](https://www.npmjs.com/package/ajv)
[](https://coveralls.io/github/ajv-validator/ajv?branch=master)
[](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2F8KvvURM6J38Gdq9dCuPswMOkMny0xCOJ%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAr8rPVRuMOXv6kwF2yUAap-eoVg-9ssOFCi1fIrxTUw0%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%224pwLRgWHU9tlroMWHz0uOg%3D%3D%22%7D)
[](https://gitter.im/ajv-validator/ajv)
[](https://github.com/sponsors/epoberezkin)
## Ajv sponsors
[<img src="https://ajv.js.org/img/mozilla.svg" width="45%" alt="Mozilla">](https://www.mozilla.org)<img src="https://ajv.js.org/img/gap.svg" width="9%">[<img src="https://ajv.js.org/img/reserved.svg" width="45%">](https://opencollective.com/ajv)
[<img src="https://ajv.js.org/img/microsoft.png" width="31%" alt="Microsoft">](https://opensource.microsoft.com)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/reserved.svg" width="31%">](https://opencollective.com/ajv)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/reserved.svg" width="31%">](https://opencollective.com/ajv)
[<img src="https://ajv.js.org/img/retool.svg" width="22.5%" alt="Retool">](https://retool.com/?utm_source=sponsor&utm_campaign=ajv)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/tidelift.svg" width="22.5%" alt="Tidelift">](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=enterprise)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/simplex.svg" width="22.5%" alt="SimpleX">](https://github.com/simplex-chat/simplex-chat)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/reserved.svg" width="22.5%">](https://opencollective.com/ajv)
## Contributing
More than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.
Please review [Contributing guidelines](./CONTRIBUTING.md) and [Code components](https://ajv.js.org/components.html).
## Documentation
All documentation is available on the [Ajv website](https://ajv.js.org).
Some useful site links:
- [Getting started](https://ajv.js.org/guide/getting-started.html)
- [JSON Schema vs JSON Type Definition](https://ajv.js.org/guide/schema-language.html)
- [API reference](https://ajv.js.org/api.html)
- [Strict mode](https://ajv.js.org/strict-mode.html)
- [Standalone validation code](https://ajv.js.org/standalone.html)
- [Security considerations](https://ajv.js.org/security.html)
- [Command line interface](https://ajv.js.org/packages/ajv-cli.html)
- [Frequently Asked Questions](https://ajv.js.org/faq.html)
## <a name="sponsors"></a>Please [sponsor Ajv development](https://github.com/sponsors/epoberezkin)
Since I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!
Your continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.
Please sponsor Ajv via:
- [GitHub sponsors page](https://github.com/sponsors/epoberezkin) (GitHub will match it)
- [Ajv Open Collective](https://opencollective.com/ajv)
Thank you.
#### Open Collective sponsors
<a href="https://opencollective.com/ajv"><img src="https://opencollective.com/ajv/individuals.svg?width=890"></a>
<a href="https://opencollective.com/ajv/organization/0/website"><img src="https://opencollective.com/ajv/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/1/website"><img src="https://opencollective.com/ajv/organization/1/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/2/website"><img src="https://opencollective.com/ajv/organization/2/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/3/website"><img src="https://opencollective.com/ajv/organization/3/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/4/website"><img src="https://opencollective.com/ajv/organization/4/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/5/website"><img src="https://opencollective.com/ajv/organization/5/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/6/website"><img src="https://opencollective.com/ajv/organization/6/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/7/website"><img src="https://opencollective.com/ajv/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/8/website"><img src="https://opencollective.com/ajv/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/9/website"><img src="https://opencollective.com/ajv/organization/9/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/10/website"><img src="https://opencollective.com/ajv/organization/10/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/11/website"><img src="https://opencollective.com/ajv/organization/11/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/12/website"><img src="https://opencollective.com/ajv/organization/12/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/13/website"><img src="https://opencollective.com/ajv/organization/13/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/14/website"><img src="https://opencollective.com/ajv/organization/14/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/15/website"><img src="https://opencollective.com/ajv/organization/15/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/16/website"><img src="https://opencollective.com/ajv/organization/16/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/17/website"><img src="https://opencollective.com/ajv/organization/17/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/18/website"><img src="https://opencollective.com/ajv/organization/18/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/19/website"><img src="https://opencollective.com/ajv/organization/19/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/20/website"><img src="https://opencollective.com/ajv/organization/20/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/21/website"><img src="https://opencollective.com/ajv/organization/21/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/22/website"><img src="https://opencollective.com/ajv/organization/22/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/23/website"><img src="https://opencollective.com/ajv/organization/23/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/24/website"><img src="https://opencollective.com/ajv/organization/24/avatar.svg"></a>
## Performance
Ajv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.
Currently Ajv is the fastest and the most standard compliant validator according to these benchmarks:
- [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - 50% faster than the second place
- [jsck benchmark](https://github.com/pandastrike/jsck#benchmarks) - 20-190% faster
- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)
- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)
Performance of different validators by [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark):
[](https://github.com/ebdrup/json-schema-benchmark/blob/master/README.md#performance)
## Features
- Ajv implements JSON Schema [draft-06/07/2019-09/2020-12](http://json-schema.org/) standards (draft-04 is supported in v6):
- all validation keywords (see [JSON Schema validation keywords](https://ajv.js.org/json-schema.html))
- [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md) extensions:
- NEW: keyword [discriminator](https://ajv.js.org/json-schema.html#discriminator).
- keyword [nullable](https://ajv.js.org/json-schema.html#nullable).
- full support of remote references (remote schemas have to be added with `addSchema` or compiled to be available)
- support of recursive references between schemas
- correct string lengths for strings with unicode pairs
- JSON Schema [formats](https://ajv.js.org/guide/formats.html) (with [ajv-formats](https://github.com/ajv-validator/ajv-formats) plugin).
- [validates schemas against meta-schema](https://ajv.js.org/api.html#api-validateschema)
- NEW: supports [JSON Type Definition](https://datatracker.ietf.org/doc/rfc8927/):
- all keywords (see [JSON Type Definition schema forms](https://ajv.js.org/json-type-definition.html))
- meta-schema for JTD schemas
- "union" keyword and user-defined keywords (can be used inside "metadata" member of the schema)
- supports [browsers](https://ajv.js.org/guide/environments.html#browsers) and Node.js 10.x - current
- [asynchronous loading](https://ajv.js.org/guide/managing-schemas.html#asynchronous-schema-loading) of referenced schemas during compilation
- "All errors" validation mode with [option allErrors](https://ajv.js.org/options.html#allerrors)
- [error messages with parameters](https://ajv.js.org/api.html#validation-errors) describing error reasons to allow error message generation
- i18n error messages support with [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package
- [removing-additional-properties](https://ajv.js.org/guide/modifying-data.html#removing-additional-properties)
- [assigning defaults](https://ajv.js.org/guide/modifying-data.html#assigning-defaults) to missing properties and items
- [coercing data](https://ajv.js.org/guide/modifying-data.html#coercing-data-types) to the types specified in `type` keywords
- [user-defined keywords](https://ajv.js.org/guide/user-keywords.html)
- additional extension keywords with [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package
- [\$data reference](https://ajv.js.org/guide/combining-schemas.html#data-reference) to use values from the validated data as values for the schema keywords
- [asynchronous validation](https://ajv.js.org/guide/async-validation.html) of user-defined formats and keywords
## Install
To install version 8:
```
npm install ajv
```
## <a name="usage"></a>Getting started
Try it in the Node.js REPL: https://runkit.com/npm/ajv
In JavaScript:
```javascript
// or ESM/TypeScript import
import Ajv from "ajv"
// Node.js require:
const Ajv = require("ajv")
const ajv = new Ajv() // options can be passed, e.g. {allErrors: true}
const schema = {
type: "object",
properties: {
foo: {type: "integer"},
bar: {type: "string"},
},
required: ["foo"],
additionalProperties: false,
}
const data = {
foo: 1,
bar: "abc",
}
const validate = ajv.compile(schema)
const valid = validate(data)
if (!valid) console.log(validate.errors)
```
Learn how to use Ajv and see more examples in the [Guide: getting started](https://ajv.js.org/guide/getting-started.html)
## Changes history
See [https://github.com/ajv-validator/ajv/releases](https://github.com/ajv-validator/ajv/releases)
**Please note**: [Changes in version 8.0.0](https://github.com/ajv-validator/ajv/releases/tag/v8.0.0)
[Version 7.0.0](https://github.com/ajv-validator/ajv/releases/tag/v7.0.0)
[Version 6.0.0](https://github.com/ajv-validator/ajv/releases/tag/v6.0.0).
## Code of conduct
Please review and follow the [Code of conduct](./CODE_OF_CONDUCT.md).
Please report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.
## 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 is a part of [Tidelift subscription](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&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](./LICENSE)
================================================
FILE: benchmark/jtd.js
================================================
/* eslint-disable no-empty */
/* eslint-disable no-console */
const Ajv = require("ajv/dist/jtd")
const Benchmark = require("benchmark")
const jtdValidationTests = require("../spec/json-typedef-spec/tests/validation.json")
const ajv = new Ajv()
const suite = new Benchmark.Suite()
const tests = []
for (const testName in jtdValidationTests) {
const {schema, instance, errors} = jtdValidationTests[testName]
const valid = errors.length === 0
if (!valid) continue
tests.push({
validate: ajv.compile(schema),
serialize: ajv.compileSerializer(schema),
parse: ajv.compileParser(schema),
data: instance,
json: JSON.stringify(instance),
})
}
// suite.add("JTD test suite: compiled JTD serializers", () => {
// for (const test of tests) {
// test.serialize(test.data)
// }
// })
// suite.add("JTD test suite: JSON.stringify", () => {
// for (const test of tests) {
// JSON.stringify(test.data)
// }
// })
const testSchema = {
definitions: {
obj: {
properties: {
foo: {type: "string"},
bar: {type: "int8"},
},
},
},
properties: {
a: {ref: "obj"},
},
optionalProperties: {
b: {ref: "obj"},
},
}
const testData = {
a: {
foo: "foo1",
bar: 1,
},
b: {
foo: "foo2",
bar: 2,
},
}
// const serializer = ajv.compileSerializer(testSchema)
// suite.add("test data: compiled JTD serializer", () => serializer(testData))
// suite.add("test data: JSON.stringify", () => JSON.stringify(testData))
suite.add("JTD test suite: compiled JTD parsers", () => {
for (const test of tests) {
test.parse(test.json)
}
})
suite.add("JTD test suite: JSON.parse", () => {
for (const test of tests) {
JSON.parse(test.json)
}
})
suite.add("JTD test suite: JSON.parse + validate", () => {
for (const test of tests) {
JSON.parse(test.json)
}
})
const validTestData = JSON.stringify(testData)
const invalidTestData = JSON.stringify({
a: {
foo: "foo1",
bar: "1",
},
b: {
foo: "foo2",
bar: 2,
},
})
const parse = ajv.compileParser(testSchema)
const validate = ajv.compile(testSchema)
suite.add("valid test data: compiled JTD parser", () => parse(validTestData))
suite.add("valid test data: JSON.parse", () => JSON.parse(validTestData))
suite.add("valid test data: JSON.parse + validate", () => validate(JSON.parse(validTestData)))
suite.add("invalid test data: compiled JTD parser", () => parse(invalidTestData))
suite.add("invalid test data: JSON.parse", () => JSON.parse(invalidTestData))
suite.add("invalid test data: JSON.parse + validate", () => validate(JSON.parse(invalidTestData)))
console.log()
suite
.on("cycle", (event) => console.log(String(event.target)))
.on("complete", function () {
// eslint-disable-next-line no-invalid-this
console.log('The fastest is "' + this.filter("fastest").map("name") + '"')
})
.run({async: true})
================================================
FILE: benchmark/package.json
================================================
{
"private": true,
"devDependencies": {
"benchmark": "^2.1.4"
}
}
================================================
FILE: bower.json
================================================
{
"name": "ajv",
"description": "Another JSON Schema Validator",
"main": "bundle/ajv.min.js",
"authors": ["Evgeny Poberezkin"],
"license": "MIT",
"keywords": ["JSON", "schema", "validator"],
"homepage": "https://github.com/ajv-validator/ajv",
"moduleType": ["amd", "globals", "node"],
"ignore": ["node_modules", "bower_components", "spec"]
}
================================================
FILE: docs/.vuepress/components/Button.vue
================================================
<template>
<a :href="link" :class="cssClass" class="button"><slot /></a>
</template>
<script>
export default {
props: {
link: {
type: String,
},
cssClass: {
type: String,
},
},
}
</script>
<style lang="stylus" scoped>
a.button
display block
width 114px
height 38px
line-height 38px
background-color $ajvGreenColor
border-radius 6px
color white
text-align center
font-weight 600
</style>
================================================
FILE: docs/.vuepress/components/Column.vue
================================================
<template>
<div :class="side" class="column">
<slot />
</div>
</template>
<script>
export default {
props: {
side: {
type: String,
},
},
}
</script>
<style lang="stylus" scoped>
.column
margin-bottom 22px
@media only screen and (min-width: $MQMobile)
&.left
width 33%
margin-right 5%
&.right
width 62%
</style>
================================================
FILE: docs/.vuepress/components/Columns.vue
================================================
<template>
<div class="columns">
<slot />
</div>
</template>
<style lang="stylus" scoped>
@media only screen and (min-width: $MQMobile)
.columns
display flex
</style>
================================================
FILE: docs/.vuepress/components/Contributors.vue
================================================
<template>
<div>
<a
v-for="(contributor, i) in contributors"
class="contributor"
:style="'background-position: ' + (100 * i) / (contributors.length - 1) + '% 0'"
:href="'https://github.com/' + contributor"
>
{{ contributor }}
</a>
</div>
</template>
<script>
import contributors from "./Contributors/_contributors.js"
export default {
data() {
return {
contributors: contributors,
}
},
}
</script>
<style lang="stylus" scoped>
.contributor
width 3.26em
height 3.26em
border-radius 50%
text-indent -9999px
display inline-block
background no-repeat url('./Contributors/contributors.jpg')
background-size auto 102%
margin 0 0.67em 0.67em 0
border 2px solid var(--second)
@media only screen and (min-width: $MQMobileSmall)
width 3.625em
height 3.625em
margin 0 0.8em 0.8em 0
</style>
================================================
FILE: docs/.vuepress/components/Feature.vue
================================================
<template>
<div :class="type">
<slot />
<a class="read-more" :href="link">
<img src="./Feature/arrow.svg" />
</a>
</div>
</template>
<script>
export default {
props: {
type: {
type: String,
},
link: {
type: String,
},
},
}
</script>
<style lang="stylus" scoped>
div
height 200px
box-sizing border-box
padding 28px
border-radius 8px
position relative
color #fff
margin-bottom 25px
@media only screen and (min-width: $MQMobileNarrow)
height 160px
@media only screen and (min-width: $MQMobile)
width 31.25%
height 225px
margin-right 3%
margin-bottom 0
h3
margin 0 0
@media only screen and (min-width: $MQNarrow)
font-size 1.75em
.header-anchor
display none
p
@media only screen and (min-width: $MQNarrow)
font-size 1.25em
&.less-code
background-color $ajvGreenColor
&.fast-secure
background-color $ajvBlueColor
&.multi-spec
background-color $ajvRedColor
@media only screen and (min-width: $MQMobile)
div:last-child
margin-right 0
a
position absolute
bottom 24px
right 24px
color #fff
</style>
================================================
FILE: docs/.vuepress/components/Features.vue
================================================
<template>
<div class="features">
<slot />
</div>
</template>
<style lang="stylus" scoped>
.features
padding 60px 0
@media only screen and (min-width: $MQMobile)
display flex
</style>
================================================
FILE: docs/.vuepress/components/FooterColumn.vue
================================================
<template>
<div :class="type" class="column">
<slot />
</div>
</template>
<script>
export default {
props: {
type: {
type: String,
},
},
}
</script>
<style lang="stylus" scoped>
div
@media only screen and (min-width: $MQMobile)
width 25%
p
a
color $textColor
font-weight normal
&:hover
text-decoration underline
@media only screen and (max-width: $MQMobile)
margin 0
line-height 30px
.column
img
display block
margin 0 auto
&.ajv
img
margin 0 0
width 100px
@media only screen and (max-width: $MQMobile)
margin-bottom 34px
&.links a
color $textColor
font-weight normal
&.sponsors
@media only screen and (max-width: $MQMobile)
a:first-child
display block
margin-top 80px
img
width 140px
padding 0 20px 15px
</style>
================================================
FILE: docs/.vuepress/components/FooterColumns.vue
================================================
<template>
<div class="footer-columns">
<slot />
</div>
</template>
<style lang="stylus" scoped>
.footer-columns
padding 20px 0 60px
border-bottom 1px solid #C4C4C4
@media only screen and (min-width: $MQMobile)
display flex
</style>
================================================
FILE: docs/.vuepress/components/GitHub.vue
================================================
<template>
<ClientOnly>
<span>
<a
class="github-button"
href="https://github.com/ajv-validator/ajv"
data-show-count="true"
data-size="large"
aria-label="Star ajv-validator/ajv on GitHub"
>
Star
</a>
</span>
</ClientOnly>
</template>
<script>
export default {
mounted() {
let githubScript = document.createElement("script")
githubScript.setAttribute("src", "https://buttons.github.io/buttons.js")
document.head.appendChild(githubScript)
},
}
</script>
<style lang="stylus" scoped>
span
vertical-align -8px
padding-left 20px
@media only screen and (max-width: $MQMobile)
vertical-align -21px
</style>
================================================
FILE: docs/.vuepress/components/HeroSection.vue
================================================
<template>
<div class="hero-section">
<div class="section-content">
<img src="./HeroSection/hero-image.svg" class="hero-image" />
<div class="section-content-wrapper">
<slot />
</div>
</div>
</div>
</template>
<style lang="stylus" scoped>
.hero-section
width 100%
padding 50px 0
padding-top $navbarHeight
overflow hidden
.section-content
position relative
max-width 1000px
padding 0 50px
margin 0 auto
@media only screen and (max-width: $MQMobile)
padding 0 40px
@media only screen and (max-width: $MQMobileNarrow)
padding 0 30px
.section-content-wrapper
position relative
z-index 2
.hero-image
position absolute
z-index 1
width 658px
top -400px
left -25px
@media only screen and (min-width: $MQMobileNarrow)
width 823px
top -500px
left 50px
@media only screen and (min-width: $MQMobile)
top -430px
left 330px
@media only screen and (min-width: $MQNarrow)
width 1097px
top -575px
left 425px
background linear-gradient(304.33deg, rgba(237, 237, 237, 0.31) -7.48%, #C6E1FF 30.07%, rgba(237, 237, 237, 0.26) 82.76%)
.header-anchor
display none
h1
font-size 2em
margin-top 200px
h2
border-bottom none
@media only screen and (min-width: $MQMobileNarrow)
h1
font-size 3em
h2
font-size 1.75em
@media only screen and (min-width: $MQMobile)
h1, h2
margin-left 48px
@media only screen and (min-width: $MQNarrow)
h1
font-size 4em
h2
font-size 2.25em
h1, h2
margin-left 64px
</style>
================================================
FILE: docs/.vuepress/components/HomePage.vue
================================================
<template>
<main class="homepage">
<slot name="top" />
<Content />
<slot name="bottom" />
</main>
</template>
<style lang="stylus" scoped>
@require '../theme/styles/wrapper.styl'
.homepage
padding 0 0 0 0
box-sizing content-box
</style>
================================================
FILE: docs/.vuepress/components/HomeSection.vue
================================================
<template>
<div class="home-section" :class="section">
<div class="section-content">
<slot />
</div>
</div>
</template>
<script>
export default {
props: {
section: {
type: String,
},
},
}
</script>
<style lang="stylus" scoped>
.home-section
width 100%
padding 50px 0
padding-top $navbarHeight
.section-content
max-width 1000px
padding 0 50px
margin 0 auto
@media only screen and (max-width: $MQMobile)
padding 0 40px
@media only screen and (max-width: $MQMobileNarrow)
padding 0 30px
& >>> .theme-code-group
button
position relative
outline none
z-index 1
&.testimonials
background linear-gradient(295.26deg, rgba(232, 232, 232, 0.8) 26.65%, rgba(255, 255, 255, 0.04) 83.48%)
&.contributors
background linear-gradient(295.26deg, rgba(232, 232, 232, 0.8) 26.65%, rgba(255, 255, 255, 0.04) 83.48%)
&.footer
background linear-gradient(295.26deg, rgba(232, 232, 232, 0.8) 26.65%, rgba(255, 255, 255, 0.04) 83.48%)
p
padding 20px 0 0
text-align center
color #292828
a
color $textColor
font-weight normal
&:hover
text-decoration underline
</style>
================================================
FILE: docs/.vuepress/components/NewsHome.vue
================================================
<template>
<div>
<div v-for="(post, i) in posts" class="post">
<Columns>
<Column side="left">
<h3>{{ post.frontmatter.title }}</h3>
<NewsPostMeta :date="post.frontmatter.date" />
</Column>
<Column side="right">
<div v-html="post.excerpt"></div>
<Button :link="post.path" cssClass="read-more" v-if="post.frontmatter.more !== false">Read more</Button>
</Column>
</Columns>
</div>
<p class="subscribe">
<Subscribe />
<a href="/news/" class="all-news">All news</a>
</p>
</div>
</template>
<script>
export default {
computed: {
posts() {
return this.$site.pages
.filter((x) => x.path.startsWith("/news/") && !x.frontmatter.newsIndex)
.sort((a, b) => new Date(b.frontmatter.date) - new Date(a.frontmatter.date))
.slice(0, 3)
},
},
}
</script>
<style lang="stylus" scoped>
.post
display flex
border-bottom 1px solid #eaecef
&:last-child
border-bottom none
a.read-more
float right
margin 28px 0
p.subscribe
margin-top 2em
a.all-news
display block
margin-top 1rem
@media only screen and (min-width: $MQMobileNarrow)
display inline-block
float right
margin-top 0
</style>
================================================
FILE: docs/.vuepress/components/NewsIndex.vue
================================================
<template>
<div>
<div v-for="post in posts">
<h2>{{ post.frontmatter.title }}</h2>
<router-link :to="post.path">
<NewsPostMeta :date="post.frontmatter.date" />
</router-link>
<div v-html="post.excerpt"></div>
<p v-if="post.frontmatter.more !== false">
<router-link :to="post.path">Read more</router-link>
</p>
</div>
</div>
</template>
<script>
export default {
computed: {
posts() {
return this.$site.pages
.filter((x) => x.path.startsWith("/news/") && !x.frontmatter.newsIndex)
.sort((a, b) => new Date(b.frontmatter.date) - new Date(a.frontmatter.date))
},
},
}
</script>
================================================
FILE: docs/.vuepress/components/NewsPost.vue
================================================
<template>
<main class="page">
<slot name="top" />
<div class="theme-default-content" style="padding-bottom: 0px">
<h1>{{ $page.frontmatter.title }}</h1>
<NewsPostMeta :date="$page.frontmatter.date" />
</div>
<Content class="theme-default-content" style="padding-top: 0px" />
<PageEdit />
<slot name="bottom" />
</main>
</template>
<script>
import PageEdit from "@theme/components/PageEdit.vue"
export default {
components: {PageEdit},
}
</script>
<style lang="stylus" scoped>
@require '../theme/styles/wrapper.styl'
.page
padding-bottom 2rem
display block
</style>
================================================
FILE: docs/.vuepress/components/NewsPostMeta.vue
================================================
<template>
<div class="post-meta">
<time class="pub-date" pubdate itemprop="datePublished" :datetime="date">
{{ resolvedDate }}
</time>
</div>
</template>
<script>
import dayjs from "dayjs"
import dayjsPluginUTC from "dayjs/plugin/utc"
dayjs.extend(dayjsPluginUTC)
export default {
props: {
date: {
type: String,
},
},
computed: {
resolvedDate() {
return dayjs.utc(this.date).format("MMMM D, YYYY")
},
},
}
</script>
<style lang="stylus" scoped>
.post-meta > div
display inline-flex
.pub-date
color #808080
</style>
================================================
FILE: docs/.vuepress/components/Projects.vue
================================================
<template>
<div class="projects">
<slot />
</div>
</template>
<style lang="stylus" scoped>
.projects
p
max-width 1100px
padding 0
img
display inline-block
max-width 240px
height 40px
line-height 40px
vertical-align middle
@media only screen and (max-width: $MQMobile)
max-width 160px
height 30px
line-height 30px
a
display inline-block
height 40px
line-height 40px
vertical-align middle
margin 0 36px 30px 0
font-size 28px
font-weight 500
color $textColor
@media only screen and (max-width: $MQMobile)
margin 0 24px 20px 0
height 30px
line-height 30px
font-size 20px
&:hover
text-decoration none
span
display none
</style>
================================================
FILE: docs/.vuepress/components/Sponsors.vue
================================================
<template>
<div class="sponsors" :class="level">
<slot />
</div>
</template>
<script>
export default {
props: {
level: {
type: String,
},
},
}
</script>
<style lang="stylus" scoped>
.sponsors
max-width 800px
margin 0 auto
h2
margin-left 0
text-decoration none
a.header-anchor
width auto
margin-right 0
p
font-size 24px
&.platinum, &.gold, &.bronze
img
width 100%
a
margin-bottom 10px
display inline-block
@media only screen and (min-width: $MQMobileNarrow)
margin-bottom 0
a:last-child
margin-right 0
&.platinum
a
width 100%
display block
@media only screen and (min-width: $MQMobileNarrow)
display inline-block
width 45%
margin-right 8%
&.gold
a
width 45%
margin-right 4%
@media only screen and (min-width: $MQMobileNarrow)
width 31%
margin-right 2%
&.bronze
a
width 45%
margin-right 4%
@media only screen and (min-width: $MQMobileNarrow)
width 22%
margin-right 3%
</style>
================================================
FILE: docs/.vuepress/components/Subscribe.vue
================================================
<template>
<form
action="https://ajv.us1.list-manage.com/subscribe/post?u=4343a2a251fa30892c2360003&id=304f51cbc3"
method="post"
target="_blank"
novalidate
>
<label for="subscription-email">Subscribe to Ajv news</label>
<input id="subscription-email" name="EMAIL" placeholder="Your email" />
<div style="position: absolute; left: -5000px;" aria-hidden="true">
<input type="text" name="b_4343a2a251fa30892c2360003_304f51cbc3" tabindex="-1" value="">
</div>
<button type="submit">Submit</button>
</form>
</template>
<style lang="stylus" scoped>
form
display inline-block
label
display block
margin-bottom 1rem
@media only screen and (min-width: $MQMobile)
display inline-block
margin-bottom 0
input, button
font-family Raleway
font-size 16px
border 0px solid
outline none
input
border 1px solid #cfd4db
height 2rem
width 180px
border-radius 2rem
padding 0 0.5rem
margin 0 0.5rem 0 0
&:focus
border-color: $accentColor
@media only screen and (min-width: $MQMobile)
width 200px
margin 0 1rem
button
width 114px
height 36px
line-height 36px
padding-top 0
background-color $ajvGreenColor
border-radius 6px
color white
text-align center
font-weight 600
display block
margin-top 1em
@media only screen and (min-width: $MQMobileSmall)
display inline-block
margin-top 0
</style>
================================================
FILE: docs/.vuepress/components/Testimonial.vue
================================================
<template>
<div class="testimonial-content" :class="color">
<slot />
</div>
</template>
<script>
export default {
props: {
color: {
type: String,
},
},
}
</script>
<style lang="stylus" scoped>
div.testimonial-content
background-position center
overflow hidden
width 280px
background-repeat no-repeat
&.blue
background-image url(./Testimonial/testimonials-blue.svg)
&.green
background-image url(./Testimonial/testimonials-green.svg)
p
margin 0.9em 0
font-size 15px
@media only screen and (max-width 374px)
&.blue, &.green
background-image none
padding 0 0
p
font-size 15px
@media only screen and (max-width 500px)
width 100%
background-size 350px 156px
padding 0 calc(50% - 100px)
box-sizing border-box
p
font-size 12px
@media only screen and (min-width 500px)
height 212px
padding 0 75px
margin 40px auto 0
@media only screen and (min-width $MQNarrow)
padding 0 calc(25% - 140px)
.header-anchor
display none
</style>
================================================
FILE: docs/.vuepress/components/Testimonials.vue
================================================
<template>
<div class="testimonials">
<slot />
</div>
</template>
<style lang="stylus" scoped>
.testimonials
padding 20px 0
@media only screen and (min-width $MQNarrow)
display flex
</style>
================================================
FILE: docs/.vuepress/config.js
================================================
const {slugify} = require("@vuepress/shared-utils")
const title = "Ajv JSON schema validator"
const description =
"The fastest JSON schema Validator. Supports JSON Schema draft-04/06/07/2019-09/2020-12 and JSON Type Definition (RFC8927)"
module.exports = {
title,
description,
head: [
["link", {rel: "icon", href: `/favicon.ico`}],
["meta", {charset: "utf-8"}],
["meta", {property: "og:title", content: title}],
["meta", {property: "og:description", content: description}],
["meta", {property: "og:image", content: "https://ajv.js.org/img/ajv.png"}],
["meta", {itemprop: "image", content: "https://ajv.js.org/img/ajv.png"}],
["meta", {name: "twitter:card", content: "summary"}],
["meta", {name: "twitter:title", content: title}],
["meta", {name: "twitter:image:src", content: "https://ajv.js.org/img/ajv.png"}],
["meta", {name: "apple-mobile-web-app-capable", content: "yes"}],
["link", {rel: "apple-touch-icon", href: `/img/apple-touch-icon.png`}],
],
markdown: {
slugify: (str) => slugify(str.replace(/<Badge[^>]*\/>/, "")),
toc: {includeLevel: [2, 3, 4]},
},
heroText: "hello there",
themeConfig: {
logo: "/img/ajv.svg",
nav: [
{text: "Home", link: "/"},
{
text: "Guide",
items: [
{link: "/guide/why-ajv", text: "Why use Ajv"},
{link: "/guide/getting-started", text: "Getting started"},
{link: "/guide/typescript", text: "Using with TypeScript"},
{link: "/guide/schema-language", text: "Choosing schema language"},
{link: "/guide/managing-schemas", text: "Managing schemas"},
{link: "/guide/combining-schemas", text: "Combining schemas"},
{link: "/guide/formats", text: "Format validation"},
{link: "/guide/modifying-data", text: "Modifying data"},
{link: "/guide/user-keywords", text: "User-defined keywords"},
{link: "/guide/async-validation", text: "Asynchronous validation"},
{link: "/guide/environments", text: "Execution environments"},
],
},
{
text: "Reference",
items: [
{link: "/api", text: "API Reference"},
{link: "/options", text: "Ajv options"},
{link: "/json-schema", text: "JSON Schema"},
{link: "/json-type-definition", text: "JSON Type Definition"},
{link: "/strict-mode", text: "Strict mode"},
{link: "/standalone", text: "Standalone validation code"},
{link: "/keywords", text: "User defined keywords"},
{link: "/coercion", text: "Type coercion rules"},
],
},
{
text: "Learn more",
items: [
{
text: "Extending Ajv",
items: [
{link: "/packages/", text: "Extending Ajv"},
{link: "/packages/ajv-cli", text: "ajv-cli"},
{link: "/packages/ajv-errors", text: "ajv-errors"},
{link: "/packages/ajv-formats", text: "ajv-formats"},
{link: "/packages/ajv-i18n", text: "ajv-i18n"},
{link: "/packages/ajv-keywords", text: "ajv-keywords"},
],
},
{
text: "Contributors",
items: [
{link: "/contributing", text: "Contributing guide"},
{link: "/codegen", text: "Code generation design"},
{link: "/components", text: "Code components"},
{link: "/code_of_conduct", text: "Code of Conduct"},
],
},
{
text: "Information",
items: [
{link: "/news/", text: "News"},
{link: "/faq", text: "FAQ"},
{link: "/security", text: "Security"},
{link: "/v6-to-v8-migration", text: "Migrate from v6"},
{link: "/testimonials", text: "What users say"},
{link: "/license", text: "License"},
],
},
],
},
],
sidebar: [
{
title: "Guide",
children: [
"/guide/why-ajv",
"/guide/getting-started",
"/guide/typescript",
"/guide/schema-language",
"/guide/managing-schemas",
"/guide/combining-schemas",
"/guide/formats",
"/guide/modifying-data",
"/guide/user-keywords",
"/guide/async-validation",
"/guide/environments",
],
},
{
title: "Reference",
children: [
"/api",
"/options",
"/json-schema",
"/json-type-definition",
"/strict-mode",
"/standalone",
"/keywords",
"/coercion",
],
},
{
title: "Extending Ajv",
children: [
["/packages/", "Extending Ajv"],
["/packages/ajv-formats", "ajv-formats"],
["/packages/ajv-keywords", "ajv-keywords"],
["/packages/ajv-errors", "ajv-errors"],
["/packages/ajv-i18n", "ajv-i18n"],
["/packages/ajv-cli", "ajv-cli"],
],
},
{
title: "Contributors",
children: [
"/contributing",
"/codegen",
"/components",
["/code_of_conduct", "Code of conduct"],
],
},
{
title: "Information",
children: [
"/news/",
"/faq",
"/security",
["/v6-to-v8-migration", "Migrate from v6 to v8"],
"/testimonials",
["/license", "License"],
],
},
],
repo: "ajv-validator/ajv",
docsDir: "docs",
editLinks: true,
activeHeaderLinks: false,
},
}
================================================
FILE: docs/.vuepress/styles/index.styl
================================================
img + span > .icon.outbound {
display: none;
}
body {
font-family: 'Raleway';
font-weight: normal;
}
strong {
font-weight: 550;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'IstokWeb';
font-weight: normal;
}
.custom-block.tip {
border-color: $tipColor;
background-color: $attentionBoxColor;
color: $textColor;
.custom-block-title {
color: $textColor;
}
}
.custom-block.warning {
border-color: $warningColor;
background-color: $attentionBoxColor;
color: $textColor;
.custom-block-title {
color: $textColor;
}
}
.custom-block.danger {
border-color: $dangerColor;
background-color: $attentionBoxColor;
color: $textColor;
.custom-block-title {
color: $textColor;
}
}
.sidebar nav.nav-links div.nav-item {
display: none;
}
span.badge {
font-family: 'Raleway';
font-weight: 500;
}
.theme-code-group .token.string {
color: $accentCode;
}
.theme-code-group button.theme-code-group__nav-tab.theme-code-group__nav-tab-active {
border-color: $accentCode;
}
.navbar span.site-name {
font-family: IstokWeb;
font-weight: 500;
font-size: 1.6em;
}
p.sidebar-heading {
font-weight: 500;
font-size: 1em;
}
a.sidebar-link.active {
font-weight: 500!important;
}
@font-face {
font-family: 'Raleway';
src: url(/fonts/Raleway-VariableFont_wght.ttf);
}
@font-face {
font-family: 'IstokWeb';
src: url(/fonts/IstokWeb-Regular.ttf);
font-weight: normal;
}
================================================
FILE: docs/.vuepress/styles/palette.styl
================================================
$ajvBlueColor = #409cff
$ajvGreenColor = #23c8d2 // #1fdca3
$ajvRedColor = #f5775b
$tipColor = $ajvGreenColor
$warningColor = #f1f440
$dangerColor = $ajvRedColor
$attentionBoxColor = #f7f7f3
$accentColor = #07aab4 // darken($ajvGreenColor, 15%)
$accentCode = #7ec699
$textColor = #292828
$borderColor = #eaecef
$codeBgColor = #282c34
$arrowBgColor = #ccc
$badgeTipColor = $ajvGreenColor
$badgeWarningColor = #e9c400
$badgeErrorColor = $ajvRedColor
$MQMobileNarrow = 480px
$MQMobileSmall = 414px
================================================
FILE: docs/.vuepress/theme/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2018-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: docs/.vuepress/theme/components/AlgoliaSearchBox.vue
================================================
<template>
<form
id="search-form"
class="algolia-search-wrapper search-box"
role="search"
>
<input
id="algolia-search-input"
class="search-query"
:placeholder="placeholder"
>
</form>
</template>
<script>
export default {
name: 'AlgoliaSearchBox',
props: ['options'],
data () {
return {
placeholder: undefined
}
},
watch: {
$lang (newValue) {
this.update(this.options, newValue)
},
options (newValue) {
this.update(newValue, this.$lang)
}
},
mounted () {
this.initialize(this.options, this.$lang)
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
},
methods: {
initialize (userOptions, lang) {
Promise.all([
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.js'),
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css')
]).then(([docsearch]) => {
docsearch = docsearch.default
const { algoliaOptions = {}} = userOptions
docsearch(Object.assign(
{},
userOptions,
{
inputSelector: '#algolia-search-input',
// #697 Make docsearch work well at i18n mode.
algoliaOptions: {
...algoliaOptions,
facetFilters: [`lang:${lang}`].concat(algoliaOptions.facetFilters || [])
},
handleSelected: (input, event, suggestion) => {
const { pathname, hash } = new URL(suggestion.url)
const routepath = pathname.replace(this.$site.base, '/')
const _hash = decodeURIComponent(hash)
this.$router.push(`${routepath}${_hash}`)
}
}
))
})
},
update (options, lang) {
this.$el.innerHTML = '<input id="algolia-search-input" class="search-query">'
this.initialize(options, lang)
}
}
}
</script>
<style lang="stylus">
.algolia-search-wrapper
& > span
vertical-align middle
.algolia-autocomplete
line-height normal
.ds-dropdown-menu
background-color #fff
border 1px solid #999
border-radius 4px
font-size 16px
margin 6px 0 0
padding 4px
text-align left
&:before
border-color #999
[class*=ds-dataset-]
border none
padding 0
.ds-suggestions
margin-top 0
.ds-suggestion
border-bottom 1px solid $borderColor
.algolia-docsearch-suggestion--highlight
color #2c815b
.algolia-docsearch-suggestion
border-color $borderColor
padding 0
.algolia-docsearch-suggestion--category-header
padding 5px 10px
margin-top 0
background $accentColor
color #fff
font-weight 600
.algolia-docsearch-suggestion--highlight
background rgba(255, 255, 255, 0.6)
.algolia-docsearch-suggestion--wrapper
padding 0
.algolia-docsearch-suggestion--title
font-weight 600
margin-bottom 0
color $textColor
.algolia-docsearch-suggestion--subcategory-column
vertical-align top
padding 5px 7px 5px 5px
border-color $borderColor
background #f1f3f5
&:after
display none
.algolia-docsearch-suggestion--subcategory-column-text
color #555
.algolia-docsearch-footer
border-color $borderColor
.ds-cursor .algolia-docsearch-suggestion--content
background-color #e7edf3 !important
color $textColor
@media (min-width: $MQMobile)
.algolia-search-wrapper
.algolia-autocomplete
.algolia-docsearch-suggestion
.algolia-docsearch-suggestion--subcategory-column
float none
width 150px
min-width 150px
display table-cell
.algolia-docsearch-suggestion--content
float none
display table-cell
width 100%
vertical-align top
.ds-dropdown-menu
min-width 515px !important
@media (max-width: $MQMobile)
.algolia-search-wrapper
.ds-dropdown-menu
min-width calc(100vw - 4rem) !important
max-width calc(100vw - 4rem) !important
.algolia-docsearch-suggestion--wrapper
padding 5px 7px 5px 5px !important
.algolia-docsearch-suggestion--subcategory-column
padding 0 !important
background white !important
.algolia-docsearch-suggestion--subcategory-column-text:after
content " > "
font-size 10px
line-height 14.4px
display inline-block
width 5px
margin -3px 3px 0
vertical-align middle
</style>
================================================
FILE: docs/.vuepress/theme/components/DropdownLink.vue
================================================
<template>
<div
class="dropdown-wrapper"
:class="{ open }"
>
<button
class="dropdown-title"
type="button"
:aria-label="dropdownAriaLabel"
@click="handleDropdown"
>
<span class="title">{{ item.text }}</span>
<span
class="arrow down"
/>
</button>
<button
class="mobile-dropdown-title"
type="button"
:aria-label="dropdownAriaLabel"
@click="setOpen(!open)"
>
<span class="title">{{ item.text }}</span>
<span
class="arrow"
:class="open ? 'down' : 'right'"
/>
</button>
<DropdownTransition>
<ul
v-show="open"
class="nav-dropdown"
>
<li
v-for="(subItem, index) in item.items"
:key="subItem.link || index"
class="dropdown-item"
>
<h4 v-if="subItem.type === 'links'">
{{ subItem.text }}
</h4>
<ul
v-if="subItem.type === 'links'"
class="dropdown-subitem-wrapper"
>
<li
v-for="childSubItem in subItem.items"
:key="childSubItem.link"
class="dropdown-subitem"
>
<NavLink
:item="childSubItem"
@focusout="
isLastItemOfArray(childSubItem, subItem.items) &&
isLastItemOfArray(subItem, item.items) &&
setOpen(false)
"
/>
</li>
</ul>
<NavLink
v-else
:item="subItem"
@focusout="isLastItemOfArray(subItem, item.items) && setOpen(false)"
/>
</li>
</ul>
</DropdownTransition>
</div>
</template>
<script>
import NavLink from '@theme/components/NavLink.vue'
import DropdownTransition from '@theme/components/DropdownTransition.vue'
import last from 'lodash/last'
export default {
name: 'DropdownLink',
components: {
NavLink,
DropdownTransition
},
props: {
item: {
required: true
}
},
data () {
return {
open: false
}
},
computed: {
dropdownAriaLabel () {
return this.item.ariaLabel || this.item.text
}
},
watch: {
$route () {
this.open = false
}
},
methods: {
setOpen (value) {
this.open = value
},
isLastItemOfArray (item, array) {
return last(array) === item
},
/**
* Open the dropdown when user tab and click from keyboard.
*
* Use event.detail to detect tab and click from keyboard. Ref: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail
* The Tab + Click is UIEvent > KeyboardEvent, so the detail is 0.
*/
handleDropdown () {
const isTriggerByTab = event.detail === 0
if (isTriggerByTab) this.setOpen(!this.open)
}
}
}
</script>
<style lang="stylus">
.dropdown-wrapper
cursor pointer
.dropdown-title
display block
font-size 0.9rem
font-family inherit
cursor inherit
padding inherit
line-height 1.4rem
background transparent
border none
font-weight 500
color $textColor
&:hover
border-color transparent
.arrow
vertical-align middle
margin-top -1px
margin-left 0.4rem
.mobile-dropdown-title
@extends .dropdown-title
display none
font-weight 600
font-size inherit
&:hover
color $accentColor
.nav-dropdown
.dropdown-item
color inherit
line-height 1.7rem
h4
margin 0.45rem 0 0
border-top 1px solid #eee
padding 1rem 1.5rem 0.45rem 1.25rem
.dropdown-subitem-wrapper
padding 0
list-style none
.dropdown-subitem
font-size 0.9em
a
display block
line-height 1.7rem
position relative
border-bottom none
font-weight 400
margin-bottom 0
padding 0 1.5rem 0 1.25rem
&:hover
color $accentColor
&.router-link-active
color $accentColor
&::after
content ""
width 0
height 0
border-left 5px solid $accentColor
border-top 3px solid transparent
border-bottom 3px solid transparent
position absolute
top calc(50% - 2px)
left 9px
&:first-child h4
margin-top 0
padding-top 0
border-top 0
@media (max-width: $MQMobile)
.dropdown-wrapper
&.open .dropdown-title
margin-bottom 0.5rem
.dropdown-title
display: none
.mobile-dropdown-title
display: block
.nav-dropdown
transition height .1s ease-out
overflow hidden
.dropdown-item
h4
border-top 0
margin-top 0
padding-top 0
h4, & > a
font-size 15px
line-height 2rem
.dropdown-subitem
font-size 14px
padding-left 1rem
@media (min-width: $MQMobile)
.dropdown-wrapper
height 1.8rem
&:hover .nav-dropdown,
&.open .nav-dropdown
// override the inline style.
display block !important
&.open:blur
display none
.nav-dropdown
display none
// Avoid height shaked by clicking
height auto !important
box-sizing border-box;
max-height calc(100vh - 2.7rem)
overflow-y auto
position absolute
top 100%
right 0
background-color #fff
padding 0.6rem 0
border 1px solid #ddd
border-bottom-color #ccc
text-align left
border-radius 0.25rem
white-space nowrap
margin 0
</style>
================================================
FILE: docs/.vuepress/theme/components/DropdownTransition.vue
================================================
<template>
<transition
name="dropdown"
@enter="setHeight"
@after-enter="unsetHeight"
@before-leave="setHeight"
>
<slot />
</transition>
</template>
<script>
export default {
name: 'DropdownTransition',
methods: {
setHeight (items) {
// explicitly set height so that it can be transitioned
items.style.height = items.scrollHeight + 'px'
},
unsetHeight (items) {
items.style.height = ''
}
}
}
</script>
<style lang="stylus">
.dropdown-enter, .dropdown-leave-to
height 0 !important
</style>
================================================
FILE: docs/.vuepress/theme/components/Home.vue
================================================
<template>
<main
class="home"
:aria-labelledby="data.heroText !== null ? 'main-title' : null"
>
<header class="hero">
<img
v-if="data.heroImage"
:src="$withBase(data.heroImage)"
:alt="data.heroAlt || 'hero'"
>
<h1
v-if="data.heroText !== null"
id="main-title"
>
{{ data.heroText || $title || 'Hello' }}
</h1>
<p
v-if="data.tagline !== null"
class="description"
>
{{ data.tagline || $description || 'Welcome to your VuePress site' }}
</p>
<p
v-if="data.actionText && data.actionLink"
class="action"
>
<NavLink
class="action-button"
:item="actionLink"
/>
</p>
</header>
<div
v-if="data.features && data.features.length"
class="features"
>
<div
v-for="(feature, index) in data.features"
:key="index"
class="feature"
>
<h2>{{ feature.title }}</h2>
<p>{{ feature.details }}</p>
</div>
</div>
<Content class="theme-default-content custom" />
<div
v-if="data.footer"
class="footer"
>
{{ data.footer }}
</div>
</main>
</template>
<script>
import NavLink from '@theme/components/NavLink.vue'
export default {
name: 'Home',
components: { NavLink },
computed: {
data () {
return this.$page.frontmatter
},
actionLink () {
return {
link: this.data.actionLink,
text: this.data.actionText
}
}
}
}
</script>
<style lang="stylus">
.home
padding $navbarHeight 2rem 0
max-width $homePageWidth
margin 0px auto
display block
.hero
text-align center
img
max-width: 100%
max-height 280px
display block
margin 3rem auto 1.5rem
h1
font-size 3rem
h1, .description, .action
margin 1.8rem auto
.description
max-width 35rem
font-size 1.6rem
line-height 1.3
color lighten($textColor, 40%)
.action-button
display inline-block
font-size 1.2rem
color #fff
background-color $accentColor
padding 0.8rem 1.6rem
border-radius 4px
transition background-color .1s ease
box-sizing border-box
border-bottom 1px solid darken($accentColor, 10%)
&:hover
background-color lighten($accentColor, 10%)
.features
border-top 1px solid $borderColor
padding 1.2rem 0
margin-top 2.5rem
display flex
flex-wrap wrap
align-items flex-start
align-content stretch
justify-content space-between
.feature
flex-grow 1
flex-basis 30%
max-width 30%
h2
font-size 1.4rem
font-weight 500
border-bottom none
padding-bottom 0
color lighten($textColor, 10%)
p
color lighten($textColor, 25%)
.footer
padding 2.5rem
border-top 1px solid $borderColor
text-align center
color lighten($textColor, 25%)
@media (max-width: $MQMobile)
.home
.features
flex-direction column
.feature
max-width 100%
padding 0 2.5rem
@media (max-width: $MQMobileNarrow)
.home
padding-left 1.5rem
padding-right 1.5rem
.hero
img
max-height 210px
margin 2rem auto 1.2rem
h1
font-size 2rem
h1, .description, .action
margin 1.2rem auto
.description
font-size 1.2rem
.action-button
font-size 1rem
padding 0.6rem 1.2rem
.feature
h2
font-size 1.25rem
</style>
================================================
FILE: docs/.vuepress/theme/components/NavLink.vue
================================================
<template>
<RouterLink
v-if="isInternal"
class="nav-link"
:to="link"
:exact="exact"
@focusout.native="focusoutAction"
>
{{ item.text }}
</RouterLink>
<a
v-else
:href="link"
class="nav-link external"
:target="target"
:rel="rel"
@focusout="focusoutAction"
>
{{ item.text }}
<OutboundLink v-if="isBlankTarget" />
</a>
</template>
<script>
import { isExternal, isMailto, isTel, ensureExt } from '../util'
export default {
name: 'NavLink',
props: {
item: {
required: true
}
},
computed: {
link () {
return ensureExt(this.item.link)
},
exact () {
if (this.$site.locales) {
return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link)
}
return this.link === '/'
},
isNonHttpURI () {
return isMailto(this.link) || isTel(this.link)
},
isBlankTarget () {
return this.target === '_blank'
},
isInternal () {
return !isExternal(this.link) && !this.isBlankTarget
},
target () {
if (this.isNonHttpURI) {
return null
}
if (this.item.target) {
return this.item.target
}
return isExternal(this.link) ? '_blank' : ''
},
rel () {
if (this.isNonHttpURI) {
return null
}
if (this.item.rel === false) {
return null
}
if (this.item.rel) {
return this.item.rel
}
return this.isBlankTarget ? 'noopener noreferrer' : null
}
},
methods: {
focusoutAction () {
this.$emit('focusout')
}
}
}
</script>
================================================
FILE: docs/.vuepress/theme/components/NavLinks.vue
================================================
<template>
<nav
v-if="userLinks.length || repoLink"
class="nav-links"
>
<!-- user links -->
<div
v-for="item in userLinks"
:key="item.link"
class="nav-item"
>
<DropdownLink
v-if="item.type === 'links'"
:item="item"
/>
<NavLink
v-else
:item="item"
/>
</div>
<GitHub/>
</a>
</nav>
</template>
<script>
import DropdownLink from '@theme/components/DropdownLink.vue'
import { resolveNavLinkItem } from '../util'
import NavLink from '@theme/components/NavLink.vue'
export default {
name: 'NavLinks',
components: {
NavLink,
DropdownLink
},
computed: {
userNav () {
return this.$themeLocaleConfig.nav || this.$site.themeConfig.nav || []
},
nav () {
const { locales } = this.$site
if (locales && Object.keys(locales).length > 1) {
const currentLink = this.$page.path
const routes = this.$router.options.routes
const themeLocales = this.$site.themeConfig.locales || {}
const languageDropdown = {
text: this.$themeLocaleConfig.selectText || 'Languages',
ariaLabel: this.$themeLocaleConfig.ariaLabel || 'Select language',
items: Object.keys(locales).map(path => {
const locale = locales[path]
const text = themeLocales[path] && themeLocales[path].label || locale.lang
let link
// Stay on the current page
if (locale.lang === this.$lang) {
link = currentLink
} else {
// Try to stay on the same page
link = currentLink.replace(this.$localeConfig.path, path)
// fallback to homepage
if (!routes.some(route => route.path === link)) {
link = path
}
}
return { text, link }
})
}
return [...this.userNav, languageDropdown]
}
return this.userNav
},
userLinks () {
return (this.nav || []).map(link => {
return Object.assign(resolveNavLinkItem(link), {
items: (link.items || []).map(resolveNavLinkItem)
})
})
},
repoLink () {
const { repo } = this.$site.themeConfig
if (repo) {
return /^https?:/.test(repo)
? repo
: `https://github.com/${repo}`
}
return null
},
repoLabel () {
if (!this.repoLink) return
if (this.$site.themeConfig.repoLabel) {
return this.$site.themeConfig.repoLabel
}
const repoHost = this.repoLink.match(/^https?:\/\/[^/]+/)[0]
const platforms = ['GitHub', 'GitLab', 'Bitbucket']
for (let i = 0; i < platforms.length; i++) {
const platform = platforms[i]
if (new RegExp(platform, 'i').test(repoHost)) {
return platform
}
}
return 'Source'
}
}
}
</script>
<style lang="stylus">
.nav-links
display inline-block
a
line-height 1.4rem
color inherit
&:hover, &.router-link-active
color $accentColor
.nav-item
position relative
display inline-block
margin-left 1.5rem
line-height 2rem
&:first-child
margin-left 0
.repo-link
margin-left 1.5rem
@media (max-width: $MQMobile)
.nav-links
.nav-item, .repo-link
margin-left 0
@media (min-width: $MQMobile)
.nav-links a
&:hover, &.router-link-active
color $textColor
.nav-item > a:not(.external)
&:hover, &.router-link-active
margin-bottom -2px
border-bottom 2px solid lighten($accentColor, 8%)
</style>
================================================
FILE: docs/.vuepress/theme/components/Navbar.vue
================================================
<template>
<header class="navbar">
<SidebarButton @toggle-sidebar="$emit('toggle-sidebar')" />
<RouterLink
:to="$localePath"
class="home-link"
>
<img
v-if="$site.themeConfig.logo"
class="logo"
:src="$withBase($site.themeConfig.logo)"
:alt="$siteTitle"
>
<span
v-if="$siteTitle"
ref="siteName"
class="site-name"
:class="{ 'can-hide': $site.themeConfig.logo }"
>{{ $siteTitle }}</span>
</RouterLink>
<div
class="links"
:style="linksWrapMaxWidth ? {
'max-width': linksWrapMaxWidth + 'px'
} : {}"
>
<AlgoliaSearchBox
v-if="isAlgoliaSearch"
:options="algolia"
/>
<SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false" />
<NavLinks class="can-hide" />
</div>
</header>
</template>
<script>
import AlgoliaSearchBox from '@AlgoliaSearchBox'
import SearchBox from '@SearchBox'
import SidebarButton from '@theme/components/SidebarButton.vue'
import NavLinks from '@theme/components/NavLinks.vue'
export default {
name: 'Navbar',
components: {
SidebarButton,
NavLinks,
SearchBox,
AlgoliaSearchBox
},
data () {
return {
linksWrapMaxWidth: null
}
},
computed: {
algolia () {
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
},
isAlgoliaSearch () {
return this.algolia && this.algolia.apiKey && this.algolia.indexName
}
},
mounted () {
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
const handleLinksWrapWidth = () => {
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
this.linksWrapMaxWidth = null
} else {
this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING
- (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
}
}
handleLinksWrapWidth()
window.addEventListener('resize', handleLinksWrapWidth, false)
}
}
function css (el, property) {
// NOTE: Known bug, will return 'auto' if style value is 'auto'
const win = el.ownerDocument.defaultView
// null means not to return pseudo styles
return win.getComputedStyle(el, null)[property]
}
</script>
<style lang="stylus">
$navbar-vertical-padding = 0.7rem
$navbar-horizontal-padding = 1.5rem
.navbar
padding $navbar-vertical-padding $navbar-horizontal-padding
line-height $navbarHeight - 1.4rem
a, span, img
display inline-block
.logo
height $navbarHeight - 1.4rem
min-width $navbarHeight - 1.4rem
margin-right 0.8rem
vertical-align top
.site-name
font-size 1.3rem
font-weight 600
color $textColor
position relative
.links
padding-left 1.5rem
box-sizing border-box
background-color white
white-space nowrap
font-size 0.9rem
position absolute
right $navbar-horizontal-padding
top $navbar-vertical-padding
display flex
.search-box
flex: 0 0 auto
vertical-align top
@media (max-width: $MQMobile)
.navbar
padding-left 4rem
.can-hide
display none
.links
padding-left 1.5rem
.site-name
width calc(100vw - 9.4rem)
overflow hidden
white-space nowrap
text-overflow ellipsis
</style>
================================================
FILE: docs/.vuepress/theme/components/Page.vue
================================================
<template>
<main class="page">
<slot name="top" />
<Content class="theme-default-content" />
<PageEdit />
<PageNav v-bind="{ sidebarItems }" />
<slot name="bottom" />
</main>
</template>
<script>
import PageEdit from '@theme/components/PageEdit.vue'
import PageNav from '@theme/components/PageNav.vue'
export default {
components: { PageEdit, PageNav },
props: ['sidebarItems']
}
</script>
<style lang="stylus">
@require '../styles/wrapper.styl'
.page
padding-bottom 2rem
display block
</style>
================================================
FILE: docs/.vuepress/theme/components/PageEdit.vue
================================================
<template>
<footer class="page-edit">
<div
v-if="editLink"
class="edit-link"
>
<a
:href="editLink"
target="_blank"
rel="noopener noreferrer"
>{{ editLinkText }}</a>
<OutboundLink />
</div>
<div
v-if="lastUpdated"
class="last-updated"
>
<span class="prefix">{{ lastUpdatedText }}:</span>
<span class="time">{{ lastUpdated }}</span>
</div>
</footer>
</template>
<script>
import isNil from 'lodash/isNil'
import { endingSlashRE, outboundRE } from '../util'
export default {
name: 'PageEdit',
computed: {
lastUpdated () {
return this.$page.lastUpdated
},
lastUpdatedText () {
if (typeof this.$themeLocaleConfig.lastUpdated === 'string') {
return this.$themeLocaleConfig.lastUpdated
}
if (typeof this.$site.themeConfig.lastUpdated === 'string') {
return this.$site.themeConfig.lastUpdated
}
return 'Last Updated'
},
editLink () {
const showEditLink = isNil(this.$page.frontmatter.editLink)
? this.$site.themeConfig.editLinks
: this.$page.frontmatter.editLink
const {
repo,
docsDir = '',
docsBranch = 'master',
docsRepo = repo
} = this.$site.themeConfig
if (typeof showEditLink == "string") return showEditLink
if (showEditLink && docsRepo && this.$page.relativePath) {
return this.createEditLink(
repo,
docsRepo,
docsDir,
docsBranch,
this.$page.relativePath
)
}
return null
},
editLinkText () {
return (
this.$themeLocaleConfig.editLinkText
|| this.$site.themeConfig.editLinkText
|| `Edit this page`
)
}
},
methods: {
createEditLink (repo, docsRepo, docsDir, docsBranch, path) {
const bitbucket = /bitbucket.org/
if (bitbucket.test(docsRepo)) {
const base = docsRepo
return (
base.replace(endingSlashRE, '')
+ `/src`
+ `/${docsBranch}/`
+ (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
+ path
+ `?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
)
}
const gitlab = /gitlab.com/
if (gitlab.test(docsRepo)) {
const base = docsRepo
return (
base.replace(endingSlashRE, '')
+ `/-/edit`
+ `/${docsBranch}/`
+ (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
+ path
)
}
const base = outboundRE.test(docsRepo)
? docsRepo
: `https://github.com/${docsRepo}`
return (
base.replace(endingSlashRE, '')
+ '/edit'
+ `/${docsBranch}/`
+ (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
+ path
)
}
}
}
</script>
<style lang="stylus">
@require '../styles/wrapper.styl'
.page-edit
@extend $wrapper
padding-top 1rem
padding-bottom 1rem
overflow auto
.edit-link
display inline-block
a
color lighten($textColor, 25%)
margin-right 0.25rem
.last-updated
float right
font-size 0.9em
.prefix
font-weight 500
color lighten($textColor, 25%)
.time
font-weight 400
color #767676
@media (max-width: $MQMobile)
.page-edit
.edit-link
margin-bottom 0.5rem
.last-updated
font-size 0.8em
float none
text-align left
</style>
================================================
FILE: docs/.vuepress/theme/components/PageNav.vue
================================================
<template>
<div
v-if="prev || next"
class="page-nav"
>
<p class="inner">
<span
v-if="prev"
class="prev"
>
←
<a
v-if="prev.type === 'external'"
class="prev"
:href="prev.path"
target="_blank"
rel="noopener noreferrer"
>
{{ prev.title || prev.path }}
<OutboundLink />
</a>
<RouterLink
v-else
class="prev"
:to="prev.path"
>
{{ prev.title || prev.path }}
</RouterLink>
</span>
<span
v-if="next"
class="next"
>
<a
v-if="next.type === 'external'"
:href="next.path"
target="_blank"
rel="noopener noreferrer"
>
{{ next.title || next.path }}
<OutboundLink />
</a>
<RouterLink
v-else
:to="next.path"
>
{{ next.title || next.path }}
</RouterLink>
→
</span>
</p>
</div>
</template>
<script>
import { resolvePage } from '../util'
import isString from 'lodash/isString'
import isNil from 'lodash/isNil'
export default {
name: 'PageNav',
props: ['sidebarItems'],
computed: {
prev () {
return resolvePageLink(LINK_TYPES.PREV, this)
},
next () {
return resolvePageLink(LINK_TYPES.NEXT, this)
}
}
}
function resolvePrev (page, items) {
return find(page, items, -1)
}
function resolveNext (page, items) {
return find(page, items, 1)
}
const LINK_TYPES = {
NEXT: {
resolveLink: resolveNext,
getThemeLinkConfig: ({ nextLinks }) => nextLinks,
getPageLinkConfig: ({ frontmatter }) => frontmatter.next
},
PREV: {
resolveLink: resolvePrev,
getThemeLinkConfig: ({ prevLinks }) => prevLinks,
getPageLinkConfig: ({ frontmatter }) => frontmatter.prev
}
}
function resolvePageLink (
linkType,
{ $themeConfig, $page, $route, $site, sidebarItems }
) {
const { resolveLink, getThemeLinkConfig, getPageLinkConfig } = linkType
// Get link config from theme
const themeLinkConfig = getThemeLinkConfig($themeConfig)
// Get link config from current page
const pageLinkConfig = getPageLinkConfig($page)
// Page link config will overwrite global theme link config if defined
const link = isNil(pageLinkConfig) ? themeLinkConfig : pageLinkConfig
if (link === false) {
return
} else if (isString(link)) {
return resolvePage($site.pages, link, $route.path)
} else {
return resolveLink($page, sidebarItems)
}
}
function find (page, items, offset) {
const res = []
flatten(items, res)
for (let i = 0; i < res.length; i++) {
const cur = res[i]
if (cur.type === 'page' && cur.path === decodeURIComponent(page.path)) {
return res[i + offset]
}
}
}
function flatten (items, res) {
for (let i = 0, l = items.length; i < l; i++) {
if (items[i].type === 'group') {
flatten(items[i].children || [], res)
} else {
res.push(items[i])
}
}
}
</script>
<style lang="stylus">
@require '../styles/wrapper.styl'
.page-nav
@extend $wrapper
padding-top 1rem
padding-bottom 0
.inner
min-height 2rem
margin-top 0
border-top 1px solid $borderColor
padding-top 1rem
overflow auto // clear float
.next
float right
</style>
================================================
FILE: docs/.vuepress/theme/components/Sidebar.vue
================================================
<template>
<aside class="sidebar">
<NavLinks />
<slot name="top" />
<SidebarLinks
:depth="0"
:items="items"
/>
<slot name="bottom" />
</aside>
</template>
<script>
import SidebarLinks from '@theme/components/SidebarLinks.vue'
import NavLinks from '@theme/components/NavLinks.vue'
export default {
name: 'Sidebar',
components: { SidebarLinks, NavLinks },
props: ['items']
}
</script>
<style lang="stylus">
.sidebar
ul
padding 0
margin 0
list-style-type none
a
display inline-block
.nav-links
display none
border-bottom 1px solid $borderColor
padding 0.5rem 0 0.75rem 0
a
font-weight 600
.nav-item, .repo-link
display block
line-height 1.25rem
font-size 1.1em
padding 0.5rem 0 0.5rem 1.5rem
& > .sidebar-links
padding 1.5rem 0
& > li > a.sidebar-link
font-size 1.1em
line-height 1.7
font-weight bold
& > li:not(:first-child)
margin-top .75rem
@media (max-width: $MQMobile)
.sidebar
.nav-links
display block
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
top calc(1rem - 2px)
& > .sidebar-links
padding 1rem 0
</style>
================================================
FILE: docs/.vuepress/theme/components/SidebarButton.vue
================================================
<template>
<div
class="sidebar-button"
@click="$emit('toggle-sidebar')"
>
<svg
class="icon"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
role="img"
viewBox="0 0 448 512"
>
<path
fill="currentColor"
d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"
class=""
/>
</svg>
</div>
</template>
<style lang="stylus">
.sidebar-button
cursor pointer
display none
width 1.25rem
height 1.25rem
position absolute
padding 0.6rem
top 0.6rem
left 1rem
.icon
display block
width 1.25rem
height 1.25rem
@media (max-width: $MQMobile)
.sidebar-button
display block
</style>
================================================
FILE: docs/.vuepress/theme/components/SidebarGroup.vue
================================================
<template>
<section
class="sidebar-group"
:class="[
{
collapsable,
'is-sub-group': depth !== 0
},
`depth-${depth}`
]"
>
<RouterLink
v-if="item.path"
class="sidebar-heading clickable"
:class="{
open,
'active': isActive($route, item.path)
}"
:to="item.path"
@click.native="$emit('toggle')"
>
<span>{{ item.title }}</span>
<span
v-if="collapsable"
class="arrow"
:class="open ? 'down' : 'right'"
/>
</RouterLink>
<p
v-else
class="sidebar-heading"
:class="{ open }"
@click="$emit('toggle')"
>
<span>{{ item.title }}</span>
<span
v-if="collapsable"
class="arrow"
:class="open ? 'down' : 'right'"
/>
</p>
<DropdownTransition>
<SidebarLinks
v-if="open || !collapsable"
class="sidebar-group-items"
:items="item.children"
:sidebar-depth="item.sidebarDepth"
:initial-open-group-index="item.initialOpenGroupIndex"
:depth="depth + 1"
/>
</DropdownTransition>
</section>
</template>
<script>
import { isActive } from '../util'
import DropdownTransition from '@theme/components/DropdownTransition.vue'
export default {
name: 'SidebarGroup',
components: {
DropdownTransition
},
props: [
'item',
'open',
'collapsable',
'depth'
],
// ref: https://vuejs.org/v2/guide/components-edge-cases.html#Circular-References-Between-Components
beforeCreate () {
this.$options.components.SidebarLinks = require('@theme/components/SidebarLinks.vue').default
},
methods: { isActive }
}
</script>
<style lang="stylus">
.sidebar-group
.sidebar-group
padding-left 0.5em
&:not(.collapsable)
.sidebar-heading:not(.clickable)
cursor auto
color inherit
// refine styles of nested sidebar groups
&.is-sub-group
padding-left 0
& > .sidebar-heading
font-size 0.95em
line-height 1.4
font-weight normal
padding-left 2rem
&:not(.clickable)
opacity 0.5
& > .sidebar-group-items
padding-left 1rem
& > li > .sidebar-link
font-size: 0.95em;
border-left none
&.depth-2
& > .sidebar-heading
border-left none
.sidebar-heading
color $textColor
transition color .15s ease
cursor pointer
font-size 1.1em
font-weight bold
// text-transform uppercase
padding 0.35rem 1.5rem 0.35rem 1.25rem
width 100%
box-sizing border-box
margin 0
border-left 0.25rem solid transparent
&.open, &:hover
color inherit
.arrow
position relative
top -0.12em
left 0.5em
&.clickable
&.active
font-weight 600
color $accentColor
border-left-color $accentColor
&:hover
color $accentColor
.sidebar-group-items
transition height .1s ease-out
font-size 0.95em
overflow hidden
</style>
================================================
FILE: docs/.vuepress/theme/components/SidebarLink.vue
================================================
<script>
import { isActive, hashRE, groupHeaders } from '../util'
export default {
functional: true,
props: ['item', 'sidebarDepth'],
render (h,
{
parent: {
$page,
$site,
$route,
$themeConfig,
$themeLocaleConfig
},
props: {
item,
sidebarDepth
}
}) {
// use custom active class matching logic
// due to edge case of paths ending with / + hash
const selfActive = isActive($route, item.path)
// for sidebar: auto pages, a hash link should be active if one of its child
// matches
const active = item.type === 'auto'
? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug))
: selfActive
const link = item.type === 'external'
? renderExternal(h, item.path, item.title || item.path)
: renderLink(h, item.path, item.title || item.path, active)
const maxDepth = [
$page.frontmatter.sidebarDepth,
sidebarDepth,
$themeLocaleConfig.sidebarDepth,
$themeConfig.sidebarDepth,
1
].find(depth => depth !== undefined)
const displayAllHeaders = $themeLocaleConfig.displayAllHeaders
|| $themeConfig.displayAllHeaders
if (item.type === 'auto') {
return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
} else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) {
const children = groupHeaders(item.headers)
return [link, renderChildren(h, children, item.path, $route, maxDepth)]
} else {
return link
}
}
}
function renderLink (h, to, text, active, level) {
const component = {
props: {
to,
activeClass: '',
exactActiveClass: ''
},
class: {
active,
'sidebar-link': true
}
}
if (level > 2) {
component.style = {
'padding-left': level + 'rem'
}
}
return h('RouterLink', component, text)
}
function renderChildren (h, children, path, route, maxDepth, depth = 1) {
if (!children || depth > maxDepth) return null
return h('ul', { class: 'sidebar-sub-headers' }, children.map(c => {
const active = isActive(route, path + '#' + c.slug)
return h('li', { class: 'sidebar-sub-header' }, [
renderLink(h, path + '#' + c.slug, c.title, active, c.level - 1),
renderChildren(h, c.children, path, route, maxDepth, depth + 1)
])
}))
}
function renderExternal (h, to, text) {
return h('a', {
attrs: {
href: to,
target: '_blank',
rel: 'noopener noreferrer'
},
class: {
'sidebar-link': true
}
}, [text, h('OutboundLink')])
}
</script>
<style lang="stylus">
.sidebar .sidebar-sub-headers
padding-left 1rem
font-size 0.95em
a.sidebar-link
font-size 1em
font-weight 400
display inline-block
color $textColor
border-left 0.25rem solid transparent
padding 0.35rem 1rem 0.35rem 1.25rem
line-height 1.4
width: 100%
box-sizing: border-box
&:hover
color $accentColor
&.active
font-weight 600
color $accentColor
border-left-color $accentColor
.sidebar-group &
padding-left 2rem
.sidebar-sub-headers &
padding-top 0.25rem
padding-bottom 0.25rem
border-left none
&.active
font-weight 500
</style>
================================================
FILE: docs/.vuepress/theme/components/SidebarLinks.vue
================================================
<template>
<ul
v-if="items.length"
class="sidebar-links"
>
<li
v-for="(item, i) in items"
:key="i"
>
<SidebarGroup
v-if="item.type === 'group'"
:item="item"
:open="i === openGroupIndex"
:collapsable="item.collapsable || item.collapsible"
:depth="depth"
@toggle="toggleGroup(i)"
/>
<SidebarLink
v-else
:sidebar-depth="sidebarDepth"
:item="item"
/>
</li>
</ul>
</template>
<script>
import SidebarGroup from '@theme/components/SidebarGroup.vue'
import SidebarLink from '@theme/components/SidebarLink.vue'
import { isActive } from '../util'
export default {
name: 'SidebarLinks',
components: { SidebarGroup, SidebarLink },
props: [
'items',
'depth', // depth of current sidebar links
'sidebarDepth', // depth of headers to be extracted
'initialOpenGroupIndex'
],
data () {
return {
openGroupIndex: this.initialOpenGroupIndex || 0
}
},
watch: {
'$route' () {
this.refreshIndex()
}
},
created () {
this.refreshIndex()
},
methods: {
refreshIndex () {
const index = resolveOpenGroupIndex(
this.$route,
this.items
)
if (index > -1) {
this.openGroupIndex = index
}
},
toggleGroup (index) {
this.openGroupIndex = index === this.openGroupIndex ? -1 : index
},
isActive (page) {
return isActive(this.$route, page.regularPath)
}
}
}
function resolveOpenGroupIndex (route, items) {
for (let i = 0; i < items.length; i++) {
const item = items[i]
if (descendantIsActive(route, item)) {
return i
}
}
return -1
}
function descendantIsActive (route, item) {
if (item.type === 'group') {
const childIsActive = item.path && isActive(route, item.path)
const grandChildIsActive = item.children.some(child => {
if (child.type === 'group') {
return descendantIsActive(route, child)
} else {
return child.type === 'page' && isActive(route, child.path)
}
})
return childIsActive || grandChildIsActive
}
return false
}
</script>
================================================
FILE: docs/.vuepress/theme/global-components/Badge.vue
================================================
<script>
export default {
functional: true,
props: {
type: {
type: String,
default: 'tip'
},
text: String,
vertical: {
type: String,
default: 'top'
}
},
render (h, { props, slots }) {
return h('span', {
class: ['badge', props.type],
style: {
verticalAlign: props.vertical
}
}, props.text || slots().default)
}
}
</script>
<style lang="stylus" scoped>
.badge
display inline-block
font-size 14px
height 18px
line-height 18px
border-radius 3px
padding 0 6px
color white
background-color #42b983
&.tip, &.green
background-color $badgeTipColor
&.error
background-color $badgeErrorColor
&.warning, &.warn, &.yellow
background-color $badgeWarningColor
& + &
margin-left 5px
</style>
================================================
FILE: docs/.vuepress/theme/global-components/CodeBlock.vue
================================================
<template>
<div
class="theme-code-block"
:class="{ 'theme-code-block__active': active }"
>
<slot />
</div>
</template>
<script>
export default {
name: 'CodeBlock',
props: {
title: {
type: String,
required: true
},
active: {
type: Boolean,
default: false
}
},
mounted () {
if (this.$parent && this.$parent.loadTabs) {
this.$parent.loadTabs()
}
}
}
</script>
<style scoped>
.theme-code-block {
display: none;
}
.theme-code-block__active {
display: block;
}
.theme-code-block > pre {
background-color: orange;
}
</style>
================================================
FILE: docs/.vuepress/theme/global-components/CodeGroup.vue
================================================
<template>
<ClientOnly>
<div class="theme-code-group">
<div class="theme-code-group__nav">
<ul class="theme-code-group__ul">
<li
v-for="(tab, i) in codeTabs"
:key="tab.title"
class="theme-code-group__li"
>
<button
class="theme-code-group__nav-tab"
:class="{
'theme-code-group__nav-tab-active': i === activeCodeTabIndex,
}"
@click="changeCodeTab(i)"
>
{{ tab.title }}
</button>
</li>
</ul>
</div>
<slot />
<pre
v-if="codeTabs.length < 1"
class="pre-blank"
>// Make sure to add code blocks to your code group</pre>
</div>
</ClientOnly>
</template>
<script>
export default {
name: 'CodeGroup',
data () {
return {
codeTabs: [],
activeCodeTabIndex: -1
}
},
watch: {
activeCodeTabIndex (index) {
this.activateCodeTab(index)
}
},
mounted () {
this.loadTabs()
},
methods: {
changeCodeTab (index) {
this.activeCodeTabIndex = index
},
loadTabs () {
this.codeTabs = (this.$slots.default || []).filter(slot => Boolean(slot.componentOptions)).map((slot, index) => {
if (slot.componentOptions.propsData.active === '') {
this.activeCodeTabIndex = index
}
return {
title: slot.componentOptions.propsData.title,
elm: slot.elm
}
})
if (this.activeCodeTabIndex === -1 && this.codeTabs.length > 0) {
this.activeCodeTabIndex = 0
}
this.activateCodeTab(0)
},
activateCodeTab (index) {
this.codeTabs.forEach(tab => {
if (tab.elm) {
tab.elm.classList.remove('theme-code-block__active')
}
})
if (this.codeTabs[index].elm) {
this.codeTabs[index].elm.classList.add('theme-code-block__active')
}
}
}
}
</script>
<style lang="stylus" scoped>
.theme-code-group {}
.theme-code-group__nav {
margin-bottom: -35px;
background-color: $codeBgColor;
padding-bottom: 22px;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
padding-left: 10px;
padding-top: 10px;
}
.theme-code-group__ul {
margin: auto 0;
padding-left: 0;
display: inline-flex;
list-style: none;
}
.theme-code-group__li {}
.theme-code-group__nav-tab {
border: 0;
padding: 5px;
cursor: pointer;
background-color: transparent;
font-size: 0.85em;
line-height: 1.4;
color: rgba(255, 255, 255, 0.9);
font-weight: 600;
}
.theme-code-group__nav-tab-active {
border-bottom: #42b983 1px solid;
}
.pre-blank {
color: #42b983;
}
</style>
================================================
FILE: docs/.vuepress/theme/index.js
================================================
const path = require("path")
// Theme API.
module.exports = (options, ctx) => {
const {themeConfig, siteConfig} = ctx
// resolve algolia
const isAlgoliaSearch =
themeConfig.algolia ||
Object.keys((siteConfig.locales && themeConfig.locales) || {}).some(
(base) => themeConfig.locales[base].algolia
)
const enableSmoothScroll = themeConfig.smoothScroll === true
return {
alias() {
return {
"@AlgoliaSearchBox": isAlgoliaSearch
? path.resolve(__dirname, "components/AlgoliaSearchBox.vue")
: path.resolve(__dirname, "noopModule.js"),
}
},
plugins: [
["@vuepress/active-header-links", options.activeHeaderLinks],
"@vuepress/search",
"@vuepress/plugin-nprogress",
[
"container",
{
type: "tip",
defaultTitle: {
"/": "TIP",
"/zh/": "提示",
},
},
],
[
"container",
{
type: "warning",
defaultTitle: {
"/": "WARNING",
"/zh/": "注意",
},
},
],
[
"container",
{
type: "danger",
defaultTitle: {
"/": "WARNING",
"/zh/": "警告",
},
},
],
[
"container",
{
type: "details",
before: (info) =>
`<details class="custom-block details">${info ? `<summary>${info}</summary>` : ""}\n`,
after: () => "</details>\n",
},
],
["smooth-scroll", enableSmoothScroll],
],
}
}
================================================
FILE: docs/.vuepress/theme/layouts/404.vue
================================================
<template>
<div class="theme-container">
<div class="theme-default-content">
<h1>404</h1>
<blockquote>{{ getMsg() }}</blockquote>
<RouterLink to="/">
Take me home.
</RouterLink>
</div>
</div>
</template>
<script>
const msgs = [
`There's nothing here.`,
`How did we get here?`,
`That's a Four-Oh-Four.`,
`Looks like we've got some broken links.`
]
export default {
methods: {
getMsg () {
return msgs[Math.floor(Math.random() * msgs.length)]
}
}
}
</script>
================================================
FILE: docs/.vuepress/theme/layouts/Layout.vue
================================================
<template>
<div
class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
>
<Navbar
v-if="shouldShowNavbar"
@toggle-sidebar="toggleSidebar"
/>
<div
class="sidebar-mask"
@click="toggleSidebar(false)"
/>
<Sidebar
:items="sidebarItems"
@toggle-sidebar="toggleSidebar"
>
<template #top>
<slot name="sidebar-top" />
</template>
<template #bottom>
<slot name="sidebar-bottom" />
</template>
</Sidebar>
<HomePage
v-if="$page.frontmatter.homepage"
:sidebar-items="sidebarItems"
>
<template #top>
<slot name="page-top" />
</template>
<template #bottom>
<slot name="page-bottom" />
</template>
</HomePage>
<NewsPost
v-else-if="$page.frontmatter.news"
:sidebar-items="sidebarItems"
>
<template #top>
<slot name="page-top" />
</template>
<template #bottom>
<slot name="page-bottom" />
</template>
</NewsPost>
<Page
v-else
:sidebar-items="sidebarItems"
>
<template #top>
<slot name="page-top" />
</template>
<template #bottom>
<slot name="page-bottom" />
</template>
</Page>
</div>
</template>
<script>
import Home from '@theme/components/Home.vue'
import Navbar from '@theme/components/Navbar.vue'
import Page from '@theme/components/Page.vue'
import Sidebar from '@theme/components/Sidebar.vue'
import { resolveSidebarItems } from '../util'
export default {
name: 'Layout',
components: {
Home,
Page,
Sidebar,
Navbar
},
data () {
return {
isSidebarOpen: false
}
},
computed: {
shouldShowNavbar () {
const { themeConfig } = this.$site
const { frontmatter } = this.$page
if (
frontmatter.navbar === false
|| themeConfig.navbar === false) {
return false
}
return (
this.$title
|| themeConfig.logo
|| themeConfig.repo
|| themeConfig.nav
|| this.$themeLocaleConfig.nav
)
},
shouldShowSidebar () {
const { frontmatter } = this.$page
return (
!frontmatter.home
&& frontmatter.sidebar !== false
&& this.sidebarItems.length
)
},
sidebarItems () {
return resolveSidebarItems(
this.$page,
this.$page.regularPath,
this.$site,
this.$localePath
)
},
pageClasses () {
const userPageClass = this.$page.frontmatter.pageClass
return [
{
'no-navbar': !this.shouldShowNavbar,
'sidebar-open': this.isSidebarOpen,
'no-sidebar': !this.shouldShowSidebar
},
userPageClass
]
}
},
mounted () {
this.$router.afterEach(() => {
this.isSidebarOpen = false
})
},
methods: {
toggleSidebar (to) {
this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
this.$emit('toggle-sidebar', this.isSidebarOpen)
},
// side swipe
onTouchStart (e) {
this.touchStart = {
x: e.changedTouches[0].clientX,
y: e.changedTouches[0].clientY
}
},
onTouchEnd (e) {
const dx = e.changedTouches[0].clientX - this.touchStart.x
const dy = e.changedTouches[0].clientY - this.touchStart.y
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
if (dx > 0 && this.touchStart.x <= 80) {
this.toggleSidebar(true)
} else {
this.toggleSidebar(false)
}
}
}
}
}
</script>
================================================
FILE: docs/.vuepress/theme/noopModule.js
================================================
export default {}
================================================
FILE: docs/.vuepress/theme/styles/arrow.styl
================================================
@require './config'
.arrow
display inline-block
width 0
height 0
&.up
border-left 4px solid transparent
border-right 4px solid transparent
border-bottom 6px solid $arrowBgColor
&.down
border-left 4px solid transparent
border-right 4px solid transparent
border-top 6px solid $arrowBgColor
&.right
border-top 4px solid transparent
border-bottom 4px solid transparent
border-left 6px solid $arrowBgColor
&.left
border-top 4px solid transparent
border-bottom 4px solid transparent
border-right 6px solid $arrowBgColor
================================================
FILE: docs/.vuepress/theme/styles/code.styl
================================================
{$contentClass}
code
color lighten($textColor, 20%)
padding 0.25rem 0.5rem
margin 0
font-size 0.85em
background-color rgba(27,31,35,0.05)
border-radius 3px
.token
&.deleted
color #EC5975
&.inserted
color $accentColor
{$contentClass}
pre, pre[class*="language-"]
line-height 1.4
padding 1.25rem 1.5rem
margin 0.85rem 0
background-color $codeBgColor
border-radius 6px
overflow auto
code
color #fff
padding 0
background-color transparent
border-radius 0
div[class*="language-"]
position relative
background-color $codeBgColor
border-radius 6px
.highlight-lines
user-select none
padding-top 1.3rem
position absolute
top 0
left 0
width 100%
line-height 1.4
.highlighted
background-color rgba(0, 0, 0, 66%)
pre, pre[class*="language-"]
background transparent
position relative
z-index 1
&::before
position absolute
z-index 3
top 0.8em
right 1em
font-size 0.75rem
color rgba(255, 255, 255, 0.4)
&:not(.line-numbers-mode)
.line-numbers-wrapper
display none
&.line-numbers-mode
.highlight-lines .highlighted
position relative
&:before
content ' '
position absolute
z-index 3
left 0
top 0
display block
width $lineNumbersWrapperWidth
height 100%
background-color rgba(0, 0, 0, 66%)
pre
padding-left $lineNumbersWrapperWidth + 1 rem
vertical-align middle
.line-numbers-wrapper
position absolute
top 0
width $lineNumbersWrapperWidth
text-align center
color rgba(255, 255, 255, 0.3)
padding 1.25rem 0
line-height 1.4
br
user-select none
.line-number
position relative
z-index 4
user-select none
font-size 0.85em
&::after
content ''
position absolute
z-index 2
top 0
left 0
width $lineNumbersWrapperWidth
height 100%
border-radius 6px 0 0 6px
border-right 1px solid rgba(0, 0, 0, 66%)
background-color $codeBgColor
for lang in $codeLang
div{'[class~="language-' + lang + '"]'}
&:before
content ('' + lang)
div[class~="language-javascript"]
&:before
content "js"
div[class~="language-typescript"]
&:before
content "ts"
div[class~="language-markup"]
&:before
content "html"
div[class~="language-markdown"]
&:before
content "md"
div[class~="language-json"]:before
content "json"
div[class~="language-ruby"]:before
content "rb"
div[class~="language-python"]:before
content "py"
div[class~="language-bash"]:before
content "sh"
div[class~="language-php"]:before
content "php"
@import '~prismjs/themes/prism-tomorrow.css'
================================================
FILE: docs/.vuepress/theme/styles/config.styl
================================================
$contentClass = '.theme-default-content'
================================================
FILE: docs/.vuepress/theme/styles/custom-blocks.styl
================================================
.custom-block
.custom-block-title
font-weight 600
margin-bottom -0.4rem
&.tip, &.warning, &.danger
padding .1rem 1.5rem
border-left-width .5rem
border-left-style solid
margin 1rem 0
&.tip
background-color #f3f5f7
border-color #42b983
&.warning
background-color rgba(255,229,100,.3)
border-color darken(#ffe564, 35%)
color darken(#ffe564, 70%)
.custom-block-title
color darken(#ffe564, 50%)
a
color $textColor
&.danger
background-color #ffe6e6
border-color darken(red, 20%)
color darken(red, 70%)
.custom-block-title
color darken(red, 40%)
a
color $textColor
&.details
display block
position relative
border-radius 2px
margin 1.6em 0
padding 1.6em
background-color #eee
h4
margin-top 0
figure, p
&:last-child
margin-bottom 0
padding-bottom 0
summary
outline none
cursor pointer
================================================
FILE: docs/.vuepress/theme/styles/index.styl
================================================
@require './config'
@require './code'
@require './custom-blocks'
@require './arrow'
@require './wrapper'
@require './toc'
html, body
padding 0
margin 0
background-color #fff
body
font-family -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
font-size 16px
color $textColor
.page
padding-left $sidebarWidth
.navbar
position fixed
z-index 20
top 0
left 0
right 0
height $navbarHeight
background-color #fff
box-sizing border-box
border-bottom 1px solid $borderColor
.sidebar-mask
position fixed
z-index 9
top 0
left 0
width 100vw
height 100vh
display none
.sidebar
font-size 16px
background-color #fff
width $sidebarWidth
position fixed
z-index 10
margin 0
top $navbarHeight
left 0
bottom 0
box-sizing border-box
border-right 1px solid $borderColor
overflow-y auto
{$contentClass}:not(.custom)
@extend $wrapper
> *:first-child
margin-top $navbarHeight
a:hover
text-decoration underline
p.demo
padding 1rem 1.5rem
border 1px solid #ddd
border-radius 4px
img
max-width 100%
{$contentClass}.custom
padding 0
margin 0
img
max-width 100%
a
font-weight 500
color $accentColor
text-decoration none
p a code
font-weight 400
color $accentColor
kbd
background #eee
border solid 0.15rem #ddd
border-bottom solid 0.25rem #ddd
border-radius 0.15rem
padding 0 0.15em
blockquote
font-size 1rem
color #999;
border-left .2rem solid #dfe2e5
margin 1rem 0
padding .25rem 0 .25rem 1rem
& > p
margin 0
ul, ol
padding-left 1.2em
strong
font-weight 600
h1, h2, h3, h4, h5, h6
font-weight 600
line-height 1.25
{$contentClass}:not(.custom) > &
margin-top (0.5rem - $navbarHeight)
padding-top ($navbarHeight + 1rem)
margin-bottom 0
&:first-child
margin-top -1.5rem
margin-bottom 1rem
+ p, + pre, + .custom-block
margin-top 2rem
&:focus .header-anchor,
&:hover .header-anchor
opacity: 1
h1
font-size 2.2rem
h2
font-size 1.65rem
padding-bottom .3rem
border-bottom 1px solid $borderColor
h3
font-size 1.35rem
a.header-anchor
font-size 0.85em
float left
margin-left -0.87em
padding-right 0.23em
margin-top 0.125em
opacity 0
&:focus,
&:hover
text-decoration none
code, kbd, .line-number
font-family source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace
p, ul, ol
line-height 1.7
hr
border 0
border-top 1px solid $borderColor
table
border-collapse collapse
margin 1rem 0
display: block
overflow-x: auto
tr
border-top 1px solid #dfe2e5
&:nth-child(2n)
background-color #f6f8fa
th, td
border 1px solid #dfe2e5
padding .6em 1em
.theme-container
&.sidebar-open
.sidebar-mask
display: block
&.no-navbar
{$contentClass}:not(.custom) > h1, h2, h3, h4, h5, h6
margin-top 1.5rem
padding-top 0
.sidebar
top 0
@media (min-width: ($MQMobile + 1px))
.theme-container.no-sidebar
.sidebar
display none
.page
padding-left 0
@require 'mobile.styl'
================================================
FILE: docs/.vuepress/theme/styles/mobile.styl
================================================
@require './config'
$mobileSidebarWidth = $sidebarWidth * 0.82
// narrow desktop / iPad
@media (max-width: $MQNarrow)
.sidebar
font-size 15px
width $mobileSidebarWidth
.page
padding-left $mobileSidebarWidth
// wide mobile
@media (max-width: $MQMobile)
.sidebar
top 0
padding-top $navbarHeight
transform translateX(-100%)
transition transform .2s ease
.page
padding-left 0
.theme-container
&.sidebar-open
.sidebar
transform translateX(0)
&.no-navbar
.sidebar
padding-top: 0
// narrow mobile
@media (max-width: $MQMobileNarrow)
h1
font-size 1.9rem
{$contentClass}
div[class*="language-"]
margin 0.85rem -1.5rem
border-radius 0
================================================
FILE: docs/.vuepress/theme/styles/toc.styl
================================================
.table-of-contents
.badge
vertical-align middle
================================================
FILE: docs/.vuepress/theme/styles/wrapper.styl
================================================
$wrapper
max-width $contentWidth
margin 0 auto
padding 2rem 2.5rem
@media (max-width: $MQNarrow)
padding 2rem
@media (max-width: $MQMobileNarrow)
padding 1.5rem
================================================
FILE: docs/.vuepress/theme/util/index.js
================================================
export const hashRE = /#.*$/
export const extRE = /\.(md|html)$/
export const endingSlashRE = /\/$/
export const outboundRE = /^[a-z]+:/i
export function normalize(path) {
return decodeURI(path).replace(hashRE, "").replace(extRE, "")
}
export function getHash(path) {
const match = path.match(hashRE)
if (match) {
return match[0]
}
}
export function isExternal(path) {
return outboundRE.test(path)
}
export function isMailto(path) {
return /^mailto:/.test(path)
}
export function isTel(path) {
return /^tel:/.test(path)
}
export function ensureExt(path) {
if (isExternal(path)) {
return path
}
const hashMatch = path.match(hashRE)
const hash = hashMatch ? hashMatch[0] : ""
const normalized = normalize(path)
if (endingSlashRE.test(normalized)) {
return path
}
return normalized + ".html" + hash
}
export function isActive(route, path) {
const routeHash = decodeURIComponent(route.hash)
const linkHash = getHash(path)
if (linkHash && routeHash !== linkHash) {
return false
}
const routePath = normalize(route.path)
const pagePath = normalize(path)
return routePath === pagePath
}
export function resolvePage(pages, rawPath, base) {
if (isExternal(rawPath)) {
return {
type: "external",
path: rawPath,
}
}
if (base) {
rawPath = resolvePath(rawPath, base)
}
const path = normalize(rawPath)
for (let i = 0; i < pages.length; i++) {
if (normalize(pages[i].regularPath) === path) {
return Object.assign({}, pages[i], {
type: "page",
path: ensureExt(pages[i].path),
})
}
}
console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
return {}
}
function resolvePath(relative, base, append) {
const firstChar = relative.charAt(0)
if (firstChar === "/") {
return relative
}
if (firstChar === "?" || firstChar === "#") {
return base + relative
}
const stack = base.split("/")
// remove trailing segment if:
// - not appending
// - appending to trailing slash (last segment is empty)
if (!append || !stack[stack.length - 1]) {
stack.pop()
}
// resolve relative path
const segments = relative.replace(/^\//, "").split("/")
for (let i = 0; i < segments.length; i++) {
const segment = segments[i]
if (segment === "..") {
stack.pop()
} else if (segment !== ".") {
stack.push(segment)
}
}
// ensure leading slash
if (stack[0] !== "") {
stack.unshift("")
}
return stack.join("/")
}
/**
* @param { Page } page
* @param { string } regularPath
* @param { SiteData } site
* @param { string } localePath
* @returns { SidebarGroup }
*/
export function resolveSidebarItems(page, regularPath, site, localePath) {
const {pages, themeConfig} = site
const localeConfig =
localePath && themeConfig.locales ? themeConfig.locales[localePath] || themeConfig : themeConfig
const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
if (pageSidebarConfig === "auto") {
return resolveHeaders(page)
}
const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
if (!sidebarConfig) {
return []
} else {
const {base, config} = resolveMatchingConfig(regularPath, sidebarConfig)
if (config === "auto") {
return resolveHeaders(page)
}
return config ? config.map((item) => resolveItem(item, pages, base)) : []
}
}
/**
* @param { Page } page
* @returns { SidebarGroup }
*/
function resolveHeaders(page) {
const headers = groupHeaders(page.headers || [])
return [
{
type: "group",
collapsable: false,
title: page.title,
path: null,
children: headers.map((h) => ({
type: "auto",
title: h.title,
basePath: page.path,
path: page.path + "#" + h.slug,
children: h.children || [],
})),
},
]
}
export function groupHeaders(headers) {
// group h3s under h2
headers = headers.map((h) => Object.assign({}, h))
let lastH2
headers.forEach((h) => {
if (h.level === 2) {
lastH2 = h
} else if (lastH2) {
;(lastH2.children || (lastH2.children = [])).push(h)
}
})
return headers.filter((h) => h.level === 2)
}
export function resolveNavLinkItem(linkItem) {
return Object.assign(linkItem, {
type: linkItem.items && linkItem.items.length ? "links" : "link",
})
}
/**
* @param { Route } route
* @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config
* @returns { base: string, config: SidebarConfig }
*/
export function resolveMatchingConfig(regularPath, config) {
if (Array.isArray(config)) {
return {
base: "/",
config: config,
}
}
for (const base in config) {
if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
return {
base,
config: config[base],
}
}
}
return {}
}
function ensureEndingSlash(path) {
return /(\.html|\/)$/.test(path) ? path : path + "/"
}
function resolveItem(item, pages, base, groupDepth = 1) {
if (typeof item === "string") {
return resolvePage(pages, item, base)
} else if (Array.isArray(item)) {
return Object.assign(resolvePage(pages, item[0], base), {
title: item[1],
})
} else {
const children = item.children || []
if (children.length === 0 && item.path) {
return Object.assign(resolvePage(pages, item.path, base), {
title: item.title,
})
}
return {
type: "group",
path: item.path,
title: item.title,
sidebarDepth: item.sidebarDepth,
initialOpenGroupIndex: item.initialOpenGroupIndex,
children: children.map((child) => resolveItem(child, pages, base, groupDepth + 1)),
collapsable: item.collapsable !== false,
}
}
}
================================================
FILE: docs/README.md
================================================
---
homepage: true
sidebar: false
---
<HeroSection>
# Ajv JSON schema validator
## Security and reliability for JavaScript applications
<Features>
<Feature type="less-code" link="/guide/why-ajv.html#write-less-code">
### Write less code
Ensure your data is valid once it is received
</Feature>
<Feature type="fast-secure" link="/guide/why-ajv.html#super-fast-secure">
### Super fast & secure
Compiles your schemas to optimized JavaScript code
</Feature>
<Feature type="multi-spec" link="/guide/why-ajv.html#multi-standard">
### Multi-standard
Use JSON Type Definition or JSON Schema
</Feature>
</Features>
<Sponsors level="platinum">
## Ajv sponsors
[](https://www.mozilla.org)
[](https://opencollective.com/ajv)
</Sponsors>
<Sponsors level="gold">
[](https://opensource.microsoft.com)
[](https://opencollective.com/ajv)
[](https://opencollective.com/ajv)
</Sponsors>
<Sponsors level="bronze">
[](https://retool.com/?utm_source=sponsor&utm_campaign=ajv)
[](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=enterprise)
[](https://github.com/simplex-chat/simplex-chat)
[](https://opencollective.com/ajv)
</Sponsors>
</HeroSection>
<HomeSection>
<Columns>
<Column side="left">
Ajv is used by a large number of JavaScript applications and libraries in all JavaScript environments - Node.js, browser, Electron apps, WeChat mini-apps etc.
It allows implementing complex data validation logic via declarative schemas for your JSON data, without writing code.
Out of the box, Ajv supports [JSON Schema](./json-schema.md) (drafts 04, 06, 07, 2019-09 and 2020-12) and [JSON Type Definition](./json-type-definition.md) ([RFC8927](https://datatracker.ietf.org/doc/rfc8927/)).
<br/>
<Button link="/guide/getting-started.html">Learn Ajv</Button>
<br/>
</Column>
<Column side="right">
<code-group>
<code-block title="JSON Schema">
```javascript
const Ajv = require("ajv")
const ajv = new Ajv()
const schema = {
type: "object",
properties: {
foo: {type: "integer"},
bar: {type: "string"}
},
required: ["foo"],
additionalProperties: false
}
const data = {foo: 1, bar: "abc"}
const valid = ajv.validate(schema, data)
if (!valid) console.log(ajv.errors)
```
</code-block>
<code-block title="JSON Type Definition">
```javascript
const Ajv = require("ajv/dist/jtd")
const ajv = new Ajv()
const schema = {
properties: {
foo: {type: "int32"}
},
optionalProperties: {
bar: {type: "string"}
}
}
const data = {foo: 1, bar: "abc"}
const valid = ajv.validate(schema, data)
if (!valid) console.log(ajv.errors)
```
</code-block>
</code-group>
</Column>
</Columns>
</HomeSection>
<HomeSection section="testimonials">
## What users say
<Testimonials>
<Testimonial color="green">
Ajv stands out as the implementation of choice - it provides a rich API which many thousands of people use in production... Ajv is partly responsible for the success of JSON Schema.
[Ben Hutton](https://github.com/relequestual), JSON Schema Specification Lead
</Testimonial>
<Testimonial color="blue">
[ESLint](https://eslint.org/) has used Ajv for validating our complex configurations. Ajv has proven to be reliable over the years we’ve been using it and ESLint is proud to sponsor Ajv’s continued development.
[Nicholas C. Zakas](https://github.com/nzakas), ESLint creator and TSC member
</Testimonial>
</Testimonials>
<span style="float:right;">[All quotes](./testimonials.md)</span>
</HomeSection>
<HomeSection>
## News
<NewsHome/>
</HomeSection>
<HomeSection>
## Who uses Ajv
<Projects>
[](https://eslint.org)
[](https://stoplight.io)
[](https://webpack.js.org)
[table](https://github.com/gajus/table)
[](https://www.fastify.io)
[restbase](https://github.com/wikimedia/restbase)
[objection.js](https://github.com/vincit/objection.js)
[](https://taskcluster.net)
[](https://rxdb.info)
[](https://github.com/rjsf-team/react-jsonschema-form)
[](https://github.com/Azure/autorest)
[](https://github.com/node-red/node-red)
[](https://developer.mozilla.org)
[](https://github.com/quicktype/quicktype)
[](https://github.com/vue-generators/vue-form-generator)
[](https://github.com/teambit/bit)
[React Page](https://react-page.github.io)
[](https://backstage.io)
[](https://github.com/microsoft/rushstack)
[JupyterLab](https://github.com/jupyterlab/jupyterlab)
[](https://github.com/davidmarkclements/0x)
[Plank.js](https://piqnt.com/planck.js/)
[](https://www.fast.design)
[](https://www.netlifycms.org)
[](https://ng-alain.com/en)
[](https://vercel.com)
[](https://github.com/aws-amplify/amplify-cli)
[](https://github.com/facebook/flipper)
[](https://nx.dev)
[](https://www.express-gateway.io)
[](https://www.zigbee2mqtt.io)
[](https://github.com/sverweij/dependency-cruiser)
[](https://theia-ide.org)
[](https://tsdoc.org)
[](https://webhint.io)
[Vega-Lite](https://vega.github.io/vega-lite/)
[](https://middy.js.org)
[JSDoc](https://github.com/jsdoc/jsdoc)
[](https://tsed.io)
</Projects>
</HomeSection>
<HomeSection section="contributors">
## Contributors
Ajv is free to use and open-source that many developers contributed to. Join us!
<Contributors />
</HomeSection>
<HomeSection section="footer">
<FooterColumns>
<FooterColumn type="ajv">

</FooterColumn>
<FooterColumn type="links">
[Learn Ajv](./guide/getting-started.md)
[Reference](./api.md)
[Security](./security.md)
</FooterColumn>
<FooterColumn type="links">
[JSON Schema](./json-schema.md)
[JSON Type Definition](./json-type-definition.md)
[Contributing](./contributing.md)
</FooterColumn>
<FooterColumn type="sponsors">
[](https://www.mozilla.org)
[](https://opencollective.com/ajv)
</FooterColumn>
</FooterColumns>
[© 2015-2021](./license.md) | Ajv JSON schema validator | [ajv.validator@gmail.com](mailto:ajv.validator@gmail.com)
</HomeSection>
================================================
FILE: docs/api.md
================================================
# API Reference
[[toc]]
## Ajv constructor and methods
### new Ajv(options: object)
Create Ajv instance:
```javascript
const ajv = new Ajv()
```
See [Options](./options)
### ajv.compile(schema: object): (data: any) => boolean | Promise < any >
Generate validating function and cache the compiled schema for future use.
Validating function returns a boolean value (or promise for async schemas that must have `$async: true` property - see [Asynchronous validation](./guide/async-validation.md)). This function has properties `errors` and `schema`. Errors encountered during the last validation are assigned to `errors` property (it is assigned `null` if there was no errors). `schema` property contains the reference to the original schema.
The schema passed to this method will be validated against meta-schema unless `validateSchema` option is false. If schema is invalid, an error will be thrown. See [options](#options).
In typescript returned validation function can be a type guard if you pass type parameter:
```typescript
interface Foo {
foo: number
}
const FooSchema: JSONSchemaType<Foo> = {
type: "object",
properties: {foo: {type: "number"}},
required: ["foo"],
additionalProperties: false,
}
const validate = ajv.compile<Foo>(FooSchema) // type of validate extends `(data: any) => data is Foo`
const data: any = {foo: 1}
if (validate(data)) {
// data is Foo here
console.log(data.foo)
} else {
console.log(validate.errors)
}
```
See more advanced example in [the test](https://github.com/ajv-validator/ajv/blob/master/spec/types/json-schema.spec.ts).
<a name="jtd-serialize"></a>
### ajv.compileSerializer(schema: object): (data: any) => string <Badge text="NEW" />
Generate serializing function based on the [JTD schema](./json-type-definition.md) (caches the schema) - only in JTD instance of Ajv (see example below).
Serializers compiled from JTD schemas can be more than 10 times faster than using `JSON.stringify`, because they do not traverse all the data, only the properties that are defined in the schema.
Properties not defined in the schema will not be included in serialized JSON, unless the schema has `additionalProperties: true` flag. It can also be beneficial from the application security point of view, as it prevents leaking accidentally/temporarily added additional properties to the API responses.
If you use JTD with typescript, the type for the schema can be derived from the data type, and generated serializer would only accept correct data type in this case:
```typescript
import Ajv, {JTDSchemaType} from "ajv/dist/jtd"
const ajv = new Ajv()
interface MyData {
foo: number
bar?: string
}
const mySchema: JTDSchemaType<MyData> = {
properties: {
foo: {type: "int32"} // any JTD number type would be accepted here
},
optionalProperties: {
bar: {type: "string"}
}
}
const serializeMyData = ajv.compileSerializer(mySchema)
// serializeMyData has type (x: MyData) => string
// it prevents you from accidentally passing the wrong type
```
::: warning Compiled serializers do NOT validate data!
It is assumed that the data is valid according to the schema.
:::
<a name="jtd-parse"></a>
### ajv.compileParser(schema: object): (json: string) => any <Badge text="NEW" />
Generate parsing function based on the [JTD schema](./json-type-definition.md) (caches the schema) - only in JTD instance of Ajv (see example below).
Parsers compiled from JTD schemas have comparable performance to `JSON.parse`<sup>\*</sup> in case JSON string is valid according to the schema (and they do not just parse JSON - they ensure that parsed JSON is valid according to the schema as they parse), but they can be many times faster in case the string is invalid - for example, if schema expects an object, and JSON string is array the parser would fail on the first character.
Parsing will fail if there are properties not defined in the schema, unless the schema has `additionalProperties: true` flag.
If you use JTD with typescript, the type for the schema can be derived from the data type, and generated parser will return correct data type (see definitions example in the [serialize](#jtd-serialize) section):
```typescript
const parseMyData = ajv.compileParser(mySchema)
// parseMyData has type (s: string) => MyData | undefined
// it returns correct data type in case parsing is successful and undefined if not
const validData = parseMyData('{"foo":1}') // {foo: 1} - success
const invalidData = parseMyData('{"x":1}') // undefined - failure
console.log(parseMyData.position) // 4
console.log(parseMyData.message) // property x not allowed
```
<sup>\*</sup> As long as empty schema `{}` is not used - there is a possibility to improve performance in this case. Also, the performance of parsing `discriminator` schemas depends on the position of discriminator tag in the schema - the best parsing performance will be achieved if the tag is the first property - this is how compiled JTD serializers generate JSON in case of discriminator schemas.
<a name="api-compileAsync"></a>
### ajv.compileAsync(schema: object, meta?: boolean): Promise < Function >
Asynchronous version of `compile` method that loads missing remote schemas using asynchronous function in `options.loadSchema`. This function returns a Promise that resolves to a validation function. An optional callback passed to `compileAsync` will be called with 2 parameters: error (or null) and validating function. The returned promise will reject (and the callback will be called with an error) when:
- missing schema can't be loaded (`loadSchema` returns a Promise that rejects).
- a schema containing a missing reference is loaded, but the reference cannot be resolved.
- schema (or some loaded/referenced schema) is invalid.
The function compiles schema and loads the first missing schema (or meta-schema) until all missing schemas are loaded.
You can asynchronously compile meta-schema by passing `true` as the second parameter.
Similarly to `compile`, it can return type guard in typescript.
See example in [Asynchronous schema loading](./guide/managing-schemas.md#asynchronous-schema-loading).
### ajv.validate(schemaOrRef: object | string, data: any): boolean
Validate data using passed schema (it will be compiled and cached).
Instead of the schema you can use the key that was previously passed to `addSchema`, the schema id if it was present in the schema or any previously resolved reference.
Validation errors will be available in the `errors` property of Ajv instance (`null` if there were no errors).
In typescript this method can act as a type guard (similarly to function returned by `compile` method - see example there).
::: warning Save errors property
Every time this method is called the errors are overwritten so you need to copy them to another variable if you want to use them later.
:::
If the schema is asynchronous (has `$async` keyword on the top level) this method returns a Promise. See [Asynchronous validation](./guide/async-validation.md).
<a id="add-schema"></a>
### ajv.addSchema(schema: object | object[], key?: string): Ajv
Add schema(s) to validator instance. This method does not compile schemas (but it still validates them). Because of that dependencies can be added in any order and circular dependencies are supported. It also prevents unnecessary compilation of schemas that are containers for other schemas but not used as a whole.
Array of schemas can be passed (schemas should have ids), the second parameter will be ignored.
Key can be passed that can be used to reference the schema and will be used as the schema id if there is no id inside the schema. If the key is not passed, the schema id will be used as the key.
Once the schema is added, it (and all the references inside it) can be referenced in other schemas and used to validate data.
Although `addSchema` does not compile schemas, explicit compilation is not required - the schema will be compiled when it is used first time.
By default the schema is validated against meta-schema before it is added, and if the schema does not pass validation the exception is thrown. This behaviour is controlled by `validateSchema` option.
::: tip Method chaining
Ajv returns its instance for chaining from all methods prefixed `add*` and `remove*`:
```javascript
const validate = new Ajv().addSchema(schema).addFormat(name, regex).getSchema(uri)
```
:::
### ajv.addMetaSchema(schema: object | object[], key?: string): Ajv
Adds meta schema(s) that can be used to validate other schemas. That function should be used instead of `addSchema` because there may be instance options that would compile a meta schema incorrectly (at the moment it is `removeAdditional` option).
There is no need to explicitly add draft-07 meta schema (http://json-schema.org/draft-07/schema) - it is added by default, unless option `meta` is set to `false`. You only need to use it if you have a changed meta-schema that you want to use to validate your schemas. See `validateSchema`.
<a name="api-validateschema"></a>
### ajv.validateSchema(schema: object): boolean
Validates schema. This method should be used to validate schemas rather than `validate` due to the inconsistency of `uri` format in JSON Schema standard.
By default this method is called automatically when the schema is added, so you rarely need to use it directly.
If schema doesn't have `$schema` property, it is validated against draft 6 meta-schema (option `meta` should not be false).
If schema has `$schema` property, then the schema with this id (that should be previously added) is used to validate passed schema.
Errors will be available at `ajv.errors`.
### ajv.getSchema(key: string): undefined | ((data: any) => boolean | Promise < any >)
Retrieve compiled schema previously added with `addSchema` by the key passed to `addSchema` or by its full reference (id). The returned validating function has `schema` property with the reference to the original schema.
### ajv.removeSchema(schemaOrRef: object | string | RegExp): Ajv
Remove added/cached schema. Even if schema is referenced by other schemas it can be safely removed as dependent schemas have local references.
Schema can be removed using:
- key passed to `addSchema`
- it's full reference (id)
- RegExp that should match schema id or key (meta-schemas won't be removed)
- actual schema object (that will be optionally serialized) to remove schema from cache
If no parameter is passed all schemas but meta-schemas will be removed and the cache will be cleared.
<a name="api-addformat"></a>
### ajv.addFormat(name: string, format: Format): Ajv
```typescript
type Format =
| true // to ignore this format (and pass validation)
| string // will be converted to RegExp
| RegExp
| (data: string) => boolean
| Object // format definition (see below and in types)
```
Add format to validate strings or numbers.
If object is passed it should have properties `validate`, `compare` and `async`:
```typescript
interface FormatDefinition { // actual type definition is more precise - see types.ts
validate: string | RegExp | (data: number | string) => boolean | Promise<boolean>
compare: (data1: string, data2: string): number // an optional function that accepts two strings
// and compares them according to the format meaning.
// This function is used with keywords `formatMaximum`/`formatMinimum`
// (defined in [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) package).
// It should return `1` if the first value is bigger than the second value,
// `-1` if it is smaller and `0` if it is equal.
async?: true // if `validate` is an asynchronous function
type?: "string" | "number" // "string" is default. If data type is different, the validation will pass.
}
```
Formats can be also added via `formats` option.
<a name="api-addkeyword"></a>
### ajv.addKeyword(definition: string | object): Ajv
Add validation keyword to Ajv instance.
Keyword should be different from all standard JSON Schema keywords and different from previously defined keywords. There is no way to redefine keywords or to remove keyword definition from the instance.
Keyword must start with an ASCII letter, `_` or `$`, and may continue with ASCII letters, numbers, `_`, `$`, `-`, or `:`.
It is recommended to use an application-specific prefix for keywords to avoid current and future name collisions.
Example Keywords:
- `"xyz-example"`: valid, and uses prefix for the xyz project to avoid name collisions.
- `"example"`: valid, but not recommended as it may collide with future versions of JSON Schema etc.
- `"3-example"`: invalid as numbers are not allowed to be the first character in a keyword
Keyword definition is an object with the following properties:
```typescript
interface KeywordDefinition {
// actual type definition is more precise - see types.ts
keyword: string // keyword name
type?: string | string[] // JSON data type(s) the keyword applies to. Default - all types.
schemaType?: string | string[] // the required schema JSON type
code?: Function // function to generate code, used for all pre-defined keywords
validate?: Function // validating function
compile?: Function // compiling function
macro?: Function // macro function
error?: object // error definition object - see types.ts
schema?: false // used with "validate" keyword to not pass schema to function
metaSchema?: object // meta-schema for keyword schema
dependencies?: string[] // properties that must be present in the parent schema -
// it will be checked during schema compilation
implements?: string[] // keyword names to reserve that this keyword implements
modifying?: true // MUST be passed if keyword modifies data
valid?: boolean // to pre-define validation result, validation function result will be ignored -
// this option MUST NOT be used with `macro` keywords.
$data?: true // to support [\$data reference](./guide/combining-schemas.md#data-reference) as the value of keyword.
// The reference will be resolved at validation time. If the keyword has meta-schema,
// it would be extended to allow $data and it will be used to validate the resolved value.
// Supporting $data reference requires that keyword has `code` or `validate` function
// (the latter can be used in addition to `compile` or `macro`).
$dataError?: object // error definition object for invalid \$data schema - see types.ts
async?: true // if the validation function is asynchronous
// (whether it is returned from `compile` or passed in `validate` property).
// It should return a promise that resolves with a value `true` or `false`.
// This option is ignored in case of "macro" and "code" keywords.
errors?: boolean | "full" // whether keyword returns errors.
// If this property is not passed Ajv will determine
// if the errors were set in case of failed validation.
}
```
If only the property `keyword` is provided in the definition object, you can also pass the keyword name as the argument.
`compile`, `macro` and `code` are mutually exclusive, only one should be used at a time. `validate` can be used separately or in addition to `compile` or `macro` to support [\$data reference](./guide/combining-schemas.md#data-reference).
::: tip Keyword is validated only for applicable data types
If the keyword is validating data type that is different from the type(s) in its definition, the validation function will not be called (and expanded macro will not be used), so there is no need to check for data type inside validation function or inside schema returned by macro function (unless you want to enforce a specific type and for some reason do not want to use a separate `type` keyword for that). In the same way as standard keywords work, if the keyword does not apply to the data type being validated, the validation of this keyword will succeed.
:::
See [User defined keywords](./keywords.md) for more details.
### ajv.getKeyword(keyword: string): object | boolean
Returns keyword definition, `false` if the keyword is unknown.
### ajv.removeKeyword(keyword: string): Ajv
Removes added or pre-defined keyword so you can redefine them.
While this method can be used to extend pre-defined keywords, it can also be used to completely change their meaning - it may lead to unexpected results.
::: warning Compiled schemas and removed keywords
The schemas compiled before the keyword is removed will continue to work without changes. To recompile schemas use `removeSchema` method and compile them again.
:::
### ajv.errorsText(errors?: object[], options?: object): string
Returns the text with all errors in a String.
Options can have properties `separator` (string used to separate errors, ", " by default) and `dataVar` (the variable name that instancePath is prefixed with, "data" by default).
## Validation errors
In case of validation failure, Ajv assigns the array of errors to `errors` property of validation function (or to `errors` property of Ajv instance when `validate` or `validateSchema` methods were called). In case of [asynchronous validation](./guide/async-validation.md), the returned promise is rejected with exception `Ajv.ValidationError` that has `errors` property.
### Error objects
Each reported error is an object with the following properties:
```typescript
interface ErrorObject {
keyword: string // validation keyword.
instancePath: string // JSON Pointer to the location in the data instance (e.g., `"/prop/1/subProp"`).
schemaPath: string // JSON Pointer to the location of the failing keyword in the schema
params: object // type is defined by keyword value, see below
// params property is the object with the additional information about error
// it can be used to generate error messages
// (e.g., using [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package).
// See below for parameters set by all keywords.
propertyName?: string // set for errors in `propertyNames` keyword schema.
// `instancePath` still points to the object in this case.
message?: string // the error message (can be excluded with option `messages: false`).
// Options below are added with `verbose` option:
schema?: any // the value of the failing keyword in the schema.
parentSchema?: object // the schema containing the keyword.
data?: any // the data validated by the keyword.
}
```
For [JTD](./json-type-definition.md) schemas `instancePath` and `schemaPath` depend on the nature of the failure - the errors are consistent with [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).
### Error parameters
Properties of `params` object in errors depend on the keyword that failed validation.
In typescript, the ErrorObject is a discriminated union that allows to determine the type of error parameters based on the value of keyword:
```typescript
const ajv = new Ajv()
const validate = ajv.compile<MyData>(schema)
if (validate(data)) {
// data is MyData here
// ...
} else {
// DefinedError is a type for all pre-defined keywords errors,
// validate.errors has type ErrorObject[] - to allow user-defined keywords with any error parameters.
// Users can extend DefinedError to include the keywords errors they defined.
for (const err of validate.errors as DefinedError[]) {
switch (err.keyword) {
case "maximum":
console.log(err.limit)
break
case "pattern":
console.log(err.pattern)
break
// ...
}
}
}
```
Also see an example in [this test](https://github.com/ajv-validator/ajv/blob/master/spec/types/error-parameters.spec.ts)
- `maxItems`, `minItems`, `maxLength`, `minLength`, `maxProperties`, `minProperties`:
```typescript
type ErrorParams = {limit: number} // keyword value
```
- `additionalItems`:
```typescript
// when `items` is an array of schemas and `additionalItems` is false:
type ErrorParams = {limit: number} // the maximum number of allowed items
```
- `additionalProperties`:
```typescript
type ErrorParams = {additionalProperty: string}
// the property not defined in `properties` and `patternProperties` keywords
```
- `dependencies`:
```typescript
type ErrorParams = {
property: string // dependent property,
missingProperty: string // required missing dependency - only the first one is reported
deps: string // required dependencies, comma separated list as a string (TODO change to string[])
depsCount: number // the number of required dependencies
}
```
- `format`:
```typescript
type ErrorParams = {format: string} // keyword value
```
- `maximum`, `minimum`, `exclusiveMaximum`, `exclusiveMinimum`:
```typescript
type ErrorParams = {
limit: number // keyword value
comparison: "<=" | ">=" | "<" | ">" // operation to compare the data to the limit,
// with data on the left and the limit on the right
}
```
- `multipleOf`:
```typescript
type ErrorParams = {multipleOf: number} // keyword value
```
- `pattern`:
```typescript
type ErrorParams = {pattern: string} // keyword value
```
- `required`:
```typescript
type ErrorParams = {missingProperty: string} // required property that is missing
```
- `propertyNames`:
```typescript
type ErrorParams = {propertyName: string} // invalid property name
```
User-defined keywords can define other keyword parameters.
### Errors i18n
You can use [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) package to generate errors in other languages.
### Error logging
A logger instance can be passed via `logger` option to Ajv constructor. The use of other logging packages is supported as long as the package or its associated wrapper exposes the required methods. If any of the required methods are missing an exception will be thrown.
- **Required Methods**: `log`, `warn`, `error`
```javascript
const otherLogger = new OtherLogger()
const ajv = new Ajv({
logger: {
log: console.log.bind(console),
warn: function warn() {
otherLogger.logWarn.apply(otherLogger, arguments)
},
error: function error() {
otherLogger.logError.apply(otherLogger, arguments)
console.error.apply(console, arguments)
},
},
})
```
##### Options
This section is moved to [Initialization options](./options.md) page
================================================
FILE: docs/codegen.md
================================================
# Code generation design
[[toc]]
Starting from v7 Ajv uses [CodeGen module](https://github.com/ajv-validator/ajv/blob/master/lib/compile/codegen/index.ts) that replaced [doT](https://github.com/olado/dot) templates used earlier.
The motivations for this change:
- doT templates were difficult to maintain and to change, particularly for the occasional contributors.
- they discouraged modularity within validation keywords code and also led to implicit dependencies between different parts of code.
- they had risks of remote code execution in case untrusted schemas were used, even though all identified issues were patched.
- ES6 template literals that are now widely supported offer a great alternative to both ASTs and to plain string concatenation - this option was not available when Ajv started.
## Safe code generation
CodeGen module defines two tagged templates that should be passed to all code generation methods and used in other tagged templates:
- `_` - to create instances of private \_Code class that will not be escaped when used in code or other tagged templates.
- `str` - to create code for string expressions.
For example, this code:
```typescript
const x = 0
// Name is a subclass of _Code that can be safely used in code - it only allows valid identifiers
// gen.const creates a unique variable name with the prefix "num".
const num: Name = gen.const("num", 5)
gen.if(
// _`...` returns the instance of _Code with safe interpolation of `num` and `x`.
// if `x` was a string, it would be inserted into code as a quoted string value rather than as a code fragment,
// so if `x` contained some code, it would not be executed.
_`${num} > ${x}`,
() => log("greater"),
() => log("smaller or equal")
)
function log(comparison: string): void {
// msg creates a string expression with concatenation - see generated code below
// type Code = _Code | Name, _Code can only be constructed with template literals
const msg: Code = str`${num} is ${comparison} than ${x}`
// msg is _Code instance, so it will be inserted via another template without quotes
gen.code(_`console.log(${msg})`)
}
```
generates this javascript code:
```javascript
const num0 = 5
if (num0 > 0) {
console.log(num0 + " is greater than 0")
} else {
console.log(num0 + " is smaller or equal than 0")
}
```
`.const`, `.if` and `.code` above are methods of CodeGen class that generate code inside class instance `gen` - see [source code](https://github.com/ajv-validator/ajv/blob/master/lib/compile/codegen/index.ts) for all available methods and [tests](https://github.com/ajv-validator/ajv/blob/master/spec/codegen.spec.ts) for other code generation examples.
These methods only accept instances of private class `_Code`, other values will be rejected by Typescript compiler - the risk to pass unsafe string is mitigated on type level.
If a string variable were used in `_` template literal, its value would be safely wrapped in quotes - in many cases it is quite useful, as it allows to inject values that can be either string or number via the same template. In the worst case, the generated code could be invalid, but it will prevent the risk of code execution that attacker could pass via untrusted schema as a string value that should be inserted in code (e.g., instead of a number). Also see the comment in the example.
## Code optimization
CodeGen class generates code trees and performs several optimizations before the code is rendered:
1. removes empty and unreachable branches (e.g. `else` branch after `if(true)`, etc.).
2. removes unused variable declarations.
3. replaces variables that are used only once and assigned expressions that are explicitly marked as "constant" (i.e. having referential transparency) with the expressions themselves.
::: warning Optimizations assume no side effects
These optimizations assume that the expressions in `if` conditions, `for` statement headers and assigned expressions are free of any side effects - this is the case for all pre-defined validation keywords.
:::
See [these tests](https://github.com/ajv-validator/ajv/blob/master/spec/codegen.spec.ts) for examples.
By default Ajv does 1-pass optimization - based on the test suite it reduces the code size by 10.5% and the number of tree nodes by 16.7% (TODO benchmark the validation time). The second optimization pass changes it by less than 0.1%, so you won't need it unless you have really complex schemas or if you generate standalone code and want it to pass relevant eslint rules.
Optimization mode can be changed with [options](./api.md#options):
- `{code: {optimize: false}}` - to disable (e.g., when schema compilation time is more important),
- `{code: {optimize: 2}}` - 2-pass optimization.
## User-defined keywords
While tagged template literals wrap passed strings based on their run-time values, CodeGen class methods rely on types to ensure safety of passed parameters - there is no run-time checks that the passed value is an instance of \_Code class.
It is strongly recommended to define additional keywords only with Typescript - using plain JavaScript would still allow passing unsafe strings to code generation methods.
::: warning Optimization and side-effects
If your user-defined keywords need to have side-effects that are removed by optimization (see above), you may need to disable it.
:::
================================================
FILE: docs/coercion.md
================================================
# Type coercion rules
To enable type coercion pass option `coerceTypes` to Ajv with `true` or `array` (it is `false` by default). See [example](./guide/modifying-data.md#coercing-data-types).
The coercion rules are different from JavaScript:
- to validate user input as expected
- to have the coercion reversible
- to correctly validate cases where different types are required in subschemas (e.g., in `anyOf`).
Type coercion only happens if there is `type` keyword and if without coercion the validation would have failed. If coercion to the required type succeeds then the validation continues to other keywords, otherwise the validation fails.
If there are multiple types allowed in `type` keyword the coercion will only happen if none of the types match the data and some of the scalar types are present (coercion to/from `object`/`array` is not possible). In this case the validating function will try coercing the data to each type in order until some of them succeeds.
Application of these rules can have some unexpected consequences. Ajv may coerce the same value multiple times (this is why coercion reversibility is required) as needed at different points in the schema. This is particularly evident when using `oneOf`, which must test all of the subschemas. Ajv will coerce the type for each subschema, possibly resulting in unexpected failure if it can coerce to match more than one of the subschemas. Even if it succeeds, Ajv will not backtrack, so you'll get the type of the final coercion even if that's not the one that allowed the data to pass validation. If possible, structure your schema with `anyOf`, which won't validate subsequent subschemas as soon as it encounters one subschema that matches.
Possible type coercions:
| from type →<br>to type ↓ | string | number | boolean | null | array\* |
| ------------------------------------------------------ | :-----------------------------------------------------------------------------: | :-----------------------------------------------: | :--------------------------------------------: | :------------------: | :--------------------------------------------: |
| string | - | `x`→`""+x` | `false`→`"false"`<br>`true`→`"true"` | `null`→`""` | `[x]`→`x` |
| number /<br>integer | Valid number /<br>integer: `x`→`+x`<br> | - | `false`→`0`<br>`true`→`1` | `null`→`0` | `[x]`→`x` |
| boolean | `"false"`→`false`<br>`"true"`→`true`<br>`"abc"`⇸<br>`""`⇸ | `0`→`false`<br>`1`→`true`<br>`x`⇸ | - | `null`→`false` | `[false]`→`false`<br>`[true]`→`true` |
| null | `""`→`null`<br>`"null"`⇸<br>`"abc"`⇸ | `0`→`null`<br>`x`⇸ | `false`→`null`<br>`true`⇸ | - | `[null]`→`null` |
| array\* | `x`→`[x]` | `x`→`[x]` | `false`→`[false]`<br>`true`→`[true]` | `null`→`[null]` | - |
\* Requires option `{coerceTypes: "array"}`
## Coercion from string values
#### To number type
Coercion to `number` is possible if the string is a valid number, `+data` is used.
#### To integer type
Coercion to `integer` is possible if the string is a valid number without fractional part (`data % 1 === 0`).
#### To boolean type
Unlike JavaScript, only these strings can be coerced to `boolean`:
- `"true"` -> `true`
- `"false"` -> `false`
#### To null type
Empty string is coerced to `null`, other strings can't be coerced.
## Coercion from number values
#### To string type
Always possible, `'' + data` is used
#### To boolean type
Unlike JavaScript, only these numbers can be coerced to `boolean`:
- `1` -> `true`
- `0` -> `false`
#### To null type
`0` coerces to `null`, other numbers can't be coerced.
## Coercion from boolean values
#### To string type
- `true` -> `"true"`
- `false` -> `"false"`
#### To number/integer types
- `true` -> `1`
- `false` -> `0`
#### To null type
`false` coerces to `null`, `true` can't be coerced.
## Coercion from null
#### To string type
`null` coerces to the empty string.
#### To number/integer types
`null` coerces to `0`
#### To boolean type
`null` coerces to `false`
## Coercion to and from array
These coercions require that the option `coerceTypes` is `"array"`.
If a scalar data is present and array is required, Ajv wraps scalar data in an array.
If an array with one item is present and a scalar is required, Ajv coerces array into its item.
- `"foo"` -> `[ "foo" ]`
- `[ "foo" ]` -> `"foo"`
================================================
FILE: docs/components.md
================================================
# Code components
[[toc]]
## Ajv classes
[lib/core.ts](https://github.com/ajv-validator/ajv/blob/master/lib/core.ts) - core Ajv class without any keywords. All Ajv methods for managing schemas and extensions are defined in this class.
[lib/ajv.ts](https://github.com/ajv-validator/ajv/blob/master/lib/ajv.ts) - subclass of Ajv core with JSON Schema draft-07 keywords.
[lib/2019.ts](https://github.com/ajv-validator/ajv/blob/master/lib/2019.ts) - subclass of Ajv core with JSON Schema draft-2019-09 keywords.
[lib/jtd.ts](https://github.com/ajv-validator/ajv/blob/master/lib/jtd.ts) - subclass of Ajv core with JSON Type Definition support.
## Schema compilation
[lib/compile](https://github.com/ajv-validator/ajv/blob/master/lib/compile) - code for schema compilation
[lib/compile/index.ts](https://github.com/ajv-validator/ajv/blob/master/lib/compile/index.ts) - the main recursive function code for schema compilation, functions for reference resolution, the interface for schema compilation context (`SchemaCxt`).
[lib/compile/context.ts](https://github.com/ajv-validator/ajv/blob/master/lib/compile/context.ts) - the class for keyword code generation `KeywordCxt`. All pre-defined keywords and user-defined keywords that use `code` function are passed an instance of this class.
[lib/compile/rules.ts](https://github.com/ajv-validator/ajv/blob/master/lib/compile/rules.ts) - data structure to store references to all all keyword definitions that were added to Ajv instance, organised by data type.
[lib/compile/subschema.ts](https://github.com/ajv-validator/ajv/blob/master/lib/compile/subschema.ts) - creates schema context (`SchemaCxt`) to generate code for subschemas - used by all applicator keywords in [lib/vocabularies/applicator](https://github.com/ajv-validator/ajv/blob/master/lib/vocabularies/applicator).
[lib/compile/codegen](https://github.com/ajv-validator/ajv/blob/master/lib/compile/codegen) - the api for [code generation](./codegen.md).
[lib/compile/validate](https://github.com/ajv-validator/ajv/blob/master/lib/compile/validate) - code to iterate the schema to generate code of validation function.
## Other components
[lib/standalone](https://github.com/ajv-validator/ajv/blob/master/lib/standalone) - module to generate [standalone validation code](./standalone.md).
[lib/vocabularies](https://github.com/ajv-validator/ajv/blob/master/lib/vocabularies) - pre-defined validation keywords.
[lib/refs](https://github.com/ajv-validator/ajv/blob/master/lib/refs) - JSON Schema meta-schemas.
================================================
FILE: docs/faq.md
================================================
# Frequently Asked Questions
The purpose of this document is to help find answers quicker. I am happy to continue the discussion about these issues, so please comment on some of the issues mentioned below or create a new issue if it seems more appropriate.
[[toc]]
## Using JSON schema
Ajv implements JSON schema specification. Before submitting the issue about the behaviour of any validation keywords please review them in:
- [JSON Schema specification](https://tools.ietf.org/html/draft-handrews-json-schema-validation-00) (draft-07)
- [JSON Schema reference](./json-schema.md) in Ajv documentation
- [JSON Schema tutorial](https://spacetelescope.github.io/understanding-json-schema/) (for draft-04)
#### Why Ajv validates empty object as valid?
"properties" keyword does not require the presence of any properties, you need to use "required" keyword. It also doesn't require that the data is an object, so any other type of data will also be valid. To require a specific type use "type" keyword. [Strict types mode](./strict-mode.md#strict-types) introduced in v7 requires presence of "type" when "properties" are used, so the mistakes are less likely.
#### Why Ajv validates only the first item of the array?
"items" keyword support [two syntaxes](./json-schema.md#items) - 1) when the schema applies to all items; 2) when there is a different schema for each item in the beginning of the array. This problem means you are using the second syntax.
In v7 with option `strictTuples` (`"log"` by default) this problem is less likely to happen, as Ajv would log warning about missing "minItems" and other keywords that are required to constrain tuple size.
## Ajv API for returning validation errors
See [#65](https://github.com/ajv-validator/ajv/issues/65), [#212](https://github.com/ajv-validator/ajv/issues/212), [#236](https://github.com/ajv-validator/ajv/issues/236), [#242](https://github.com/ajv-validator/ajv/issues/242), [#256](https://github.com/ajv-validator/ajv/issues/256).
#### Why Ajv assigns errors as a property of validation function (or instance) instead of returning an object with validation results and errors?
The reasons are history (other fast validators with the same api) and performance (returning boolean is faster). Although more code is written to process errors than to handle successful results, almost all server-side validations pass. The existing API is more efficient from the performance point of view.
Ajv also supports asynchronous validation (with asynchronous formats and keywords) that returns a promise that either resolves to `true` or rejects with an error.
#### Would errors get overwritten in case of "concurrent" validations?
No. There is no parallel execution in JavaScript, and the cooperative concurrency model of javascript makes this pattern safe. While a validation is run, no other JavaScript code that can access the same memory can be executed. As long as the errors are used in the same execution block, the errors will not be overwritten.
#### Can we change / extend API to add a method that would return errors (rather than assign them to `errors` property)?
No. In many cases there is a module responsible for the validation in the application, usually to load schemas and to process errors. This module is the right place to introduce any user-defined API. Convenience is a subjective thing, changing or extending API purely because of convenience would either break backward compatibility (even if it's done in a new major version it still complicates migration) or bloat API (making it more difficult to maintain).
#### Why don't `"additionalProperties": false` errors display the property name?
Doing this would create a precedent where validated data is used in error messages, creating a vulnerability (e.g., when ajv is used to validate API data/parameters and error messages are logged).
Since the property name is already in the params object, in an application you can modify the messages in any way you need. ajv-errors package allows modifying messages as well.
## Additional properties inside compound keywords anyOf, oneOf, etc.
See [#127](https://github.com/ajv-validator/ajv/issues/127), [#129](https://github.com/ajv-validator/ajv/issues/129), [#134](https://github.com/ajv-validator/ajv/issues/134), [#140](https://github.com/ajv-validator/ajv/issues/140), [#193](https://github.com/ajv-validator/ajv/issues/193), [#205](https://github.com/ajv-validator/ajv/issues/205), [#238](https://github.com/ajv-validator/ajv/issues/238), [#264](https://github.com/ajv-validator/ajv/issues/264).
#### Why the keyword `additionalProperties: false` fails validation when some properties are "declared" inside a subschema in `anyOf`/etc.?
The keyword `additionalProperties` creates the restriction on validated data based on its own value (`false` or schema object) and on the keywords `properties` and `patternProperties` in the SAME schema object. JSON Schema validators must NOT take into account properties used in other schema objects.
While you can expect that the schema below would allow the objects either with properties `foo` and `bar` or with properties `foo` and `baz` and all other properties will be prohibited, this schema will only allow objects with one property `foo` (an empty object and any non-objects will also be valid):
```javascript
{
type: "object",
properties: {foo: {type: "number"}},
additionalProperties: false,
oneOf: [
{properties: {bar: {type: "number"}}},
{properties: {baz: {type: "number"}}}
]
}
```
The reason for that is that `additionalProperties` keyword ignores properties inside `oneOf` keyword subschemas. That's not the limitation of Ajv or any other validator, that's how it must work according to the standard.
There are several ways to implement the described logic that would allow two properties, please see the suggestions in the issues mentioned above.
#### Why the validation fails when I use option `removeAdditional` with the keyword `anyOf`/etc.?
This problem is related to the problem explained above - properties treated as additional in the sense of `additionalProperties` keyword, based on `properties`/`patternProperties` keyword in the same schema object.
See the example in the [Removing Additional Data](https://ajv.js.org/guide/modifying-data.html#removing-additional-properties) section of the docs.
## Generating schemas with resolved references ($ref)
See [#22](https://github.com/ajv-validator/ajv/issues/22), [#125](https://github.com/ajv-validator/ajv/issues/125), [#146](https://github.com/ajv-validator/ajv/issues/146), [#228](https://github.com/ajv-validator/ajv/issues/228), [#336](https://github.com/ajv-validator/ajv/issues/336), [#454](https://github.com/ajv-validator/ajv/issues/454).
#### Why Ajv does not replace references ($ref) with the actual referenced schemas as some validators do?
1. The scope of Ajv is validating data against JSON Schemas; inlining referenced schemas is not necessary for validation. When Ajv generates code for validation it either inlines the code of referenced schema or uses function calls. Doing schema manipulation is more complex and out of scope.
2. When schemas are recursive (or mutually recursive) resolving references would result in self-referencing recursive data-structures that can be difficult to process.
3. There are cases when such inlining would also require adding (or modifying) `id` attribute in the inlined schema fragment to make the resulting schema equivalent.
There were many conversations about the meaning of `$ref` in [JSON Schema GitHub organisation](https://github.com/json-schema-org). The consensus is that while it is possible to treat `$ref` as schema inclusion with two caveats (above), this interpretation is unnecessary complex. A more efficient approach is to treat `$ref` as a delegation, i.e. a special keyword that validates the current data instance against the referenced schema. The analogy with programming languages is that `$ref` is a function call rather than a macro. See [here](https://github.com/json-schema-org/json-schema-spec/issues/279), for example.
#### How can I generate a schema where `$ref` keywords are replaced with referenced schemas?
There are two possible approaches:
1. Traverse schema (e.g. with json-schema-traverse) and replace every `$ref` with the referenced schema.
2. Use a specially constructed JSON Schema with a [user-defined keyword](./keywords.md) to traverse and modify your schema.
================================================
FILE: docs/guide/async-validation.md
================================================
# Asynchronous validation
You can define formats and keywords that perform validation asynchronously by accessing database or some other service. You should add `async: true` in the keyword or format definition (see [addFormat](./api.md#api-addformat), [addKeyword](./api.md#api-addkeyword) and [User-defined keywords](./keywords.md)).
If your schema uses asynchronous formats/keywords or refers to some schema that contains them it should have `"$async": true` keyword so that Ajv can compile it correctly. If asynchronous format/keyword or reference to asynchronous schema is used in the schema without `$async` keyword Ajv will throw an exception during schema compilation.
::: warning Use $async: true in referenced schemas
All asynchronous subschemas that are referenced from the current or other schemas should have `"$async": true` keyword as well, otherwise the schema compilation will fail.
:::
Validation function for an asynchronous format/keyword should return a promise that resolves with `true` or `false` (or
gitextract_hfo2xbb4/ ├── .eslintrc.js ├── .github/ │ ├── CODEOWNERS │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug-or-error-report.md │ │ ├── change.md │ │ ├── compatibility.md │ │ ├── installation.md │ │ └── typescript.md │ ├── ISSUE_TEMPLATE.md │ ├── PULL_REQUEST_TEMPLATE.md │ ├── config.yml │ ├── dependabot.yml │ └── workflows/ │ ├── build.yml │ └── publish.yml ├── .gitignore ├── .gitmodules ├── .npmrc ├── .prettierignore ├── .runkit_example.js ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── benchmark/ │ ├── jtd.js │ └── package.json ├── bower.json ├── docs/ │ ├── .vuepress/ │ │ ├── components/ │ │ │ ├── Button.vue │ │ │ ├── Column.vue │ │ │ ├── Columns.vue │ │ │ ├── Contributors.vue │ │ │ ├── Feature.vue │ │ │ ├── Features.vue │ │ │ ├── FooterColumn.vue │ │ │ ├── FooterColumns.vue │ │ │ ├── GitHub.vue │ │ │ ├── HeroSection.vue │ │ │ ├── HomePage.vue │ │ │ ├── HomeSection.vue │ │ │ ├── NewsHome.vue │ │ │ ├── NewsIndex.vue │ │ │ ├── NewsPost.vue │ │ │ ├── NewsPostMeta.vue │ │ │ ├── Projects.vue │ │ │ ├── Sponsors.vue │ │ │ ├── Subscribe.vue │ │ │ ├── Testimonial.vue │ │ │ └── Testimonials.vue │ │ ├── config.js │ │ ├── styles/ │ │ │ ├── index.styl │ │ │ └── palette.styl │ │ └── theme/ │ │ ├── LICENSE │ │ ├── components/ │ │ │ ├── AlgoliaSearchBox.vue │ │ │ ├── DropdownLink.vue │ │ │ ├── DropdownTransition.vue │ │ │ ├── Home.vue │ │ │ ├── NavLink.vue │ │ │ ├── NavLinks.vue │ │ │ ├── Navbar.vue │ │ │ ├── Page.vue │ │ │ ├── PageEdit.vue │ │ │ ├── PageNav.vue │ │ │ ├── Sidebar.vue │ │ │ ├── SidebarButton.vue │ │ │ ├── SidebarGroup.vue │ │ │ ├── SidebarLink.vue │ │ │ └── SidebarLinks.vue │ │ ├── global-components/ │ │ │ ├── Badge.vue │ │ │ ├── CodeBlock.vue │ │ │ └── CodeGroup.vue │ │ ├── index.js │ │ ├── layouts/ │ │ │ ├── 404.vue │ │ │ └── Layout.vue │ │ ├── noopModule.js │ │ ├── styles/ │ │ │ ├── arrow.styl │ │ │ ├── code.styl │ │ │ ├── config.styl │ │ │ ├── custom-blocks.styl │ │ │ ├── index.styl │ │ │ ├── mobile.styl │ │ │ ├── toc.styl │ │ │ └── wrapper.styl │ │ └── util/ │ │ └── index.js │ ├── README.md │ ├── api.md │ ├── codegen.md │ ├── coercion.md │ ├── components.md │ ├── faq.md │ ├── guide/ │ │ ├── async-validation.md │ │ ├── combining-schemas.md │ │ ├── environments.md │ │ ├── formats.md │ │ ├── getting-started.md │ │ ├── managing-schemas.md │ │ ├── modifying-data.md │ │ ├── schema-language.md │ │ ├── typescript.md │ │ ├── user-keywords.md │ │ └── why-ajv.md │ ├── json-schema.md │ ├── json-type-definition.md │ ├── keywords.md │ ├── news/ │ │ ├── 2020-08-14-mozilla-grant-openjs-foundation.md │ │ ├── 2020-12-15-ajv-version-7-released.md │ │ ├── 2021-03-07-ajv-supports-json-type-definition.md │ │ ├── 2021-03-27-ajv-version-8-released.md │ │ ├── 2021-04-24-ajv-online-event.md │ │ ├── 2021-05-24-ajv-online-event-video.md │ │ ├── 2021-07-22-ajv-microsoft-foss-fund-award.md │ │ └── README.md │ ├── options.md │ ├── packages/ │ │ └── README.md │ ├── security.md │ ├── standalone.md │ ├── strict-mode.md │ ├── testimonials.md │ └── v6-to-v8-migration.md ├── karma.conf.js ├── lib/ │ ├── 2019.ts │ ├── 2020.ts │ ├── ajv.ts │ ├── compile/ │ │ ├── codegen/ │ │ │ ├── code.ts │ │ │ ├── index.ts │ │ │ └── scope.ts │ │ ├── errors.ts │ │ ├── index.ts │ │ ├── jtd/ │ │ │ ├── parse.ts │ │ │ ├── serialize.ts │ │ │ └── types.ts │ │ ├── names.ts │ │ ├── ref_error.ts │ │ ├── resolve.ts │ │ ├── rules.ts │ │ ├── util.ts │ │ └── validate/ │ │ ├── applicability.ts │ │ ├── boolSchema.ts │ │ ├── dataType.ts │ │ ├── defaults.ts │ │ ├── index.ts │ │ ├── keyword.ts │ │ └── subschema.ts │ ├── core.ts │ ├── jtd.ts │ ├── refs/ │ │ ├── data.json │ │ ├── json-schema-2019-09/ │ │ │ ├── index.ts │ │ │ ├── meta/ │ │ │ │ ├── applicator.json │ │ │ │ ├── content.json │ │ │ │ ├── core.json │ │ │ │ ├── format.json │ │ │ │ ├── meta-data.json │ │ │ │ └── validation.json │ │ │ └── schema.json │ │ ├── json-schema-2020-12/ │ │ │ ├── index.ts │ │ │ ├── meta/ │ │ │ │ ├── applicator.json │ │ │ │ ├── content.json │ │ │ │ ├── core.json │ │ │ │ ├── format-annotation.json │ │ │ │ ├── meta-data.json │ │ │ │ ├── unevaluated.json │ │ │ │ └── validation.json │ │ │ └── schema.json │ │ ├── json-schema-draft-06.json │ │ ├── json-schema-draft-07.json │ │ ├── json-schema-secure.json │ │ └── jtd-schema.ts │ ├── runtime/ │ │ ├── equal.ts │ │ ├── parseJson.ts │ │ ├── quote.ts │ │ ├── re2.ts │ │ ├── timestamp.ts │ │ ├── ucs2length.ts │ │ ├── uri.ts │ │ └── validation_error.ts │ ├── standalone/ │ │ ├── index.ts │ │ └── instance.ts │ ├── types/ │ │ ├── index.ts │ │ ├── json-schema.ts │ │ └── jtd-schema.ts │ └── vocabularies/ │ ├── applicator/ │ │ ├── additionalItems.ts │ │ ├── additionalProperties.ts │ │ ├── allOf.ts │ │ ├── anyOf.ts │ │ ├── contains.ts │ │ ├── dependencies.ts │ │ ├── dependentSchemas.ts │ │ ├── if.ts │ │ ├── index.ts │ │ ├── items.ts │ │ ├── items2020.ts │ │ ├── not.ts │ │ ├── oneOf.ts │ │ ├── patternProperties.ts │ │ ├── prefixItems.ts │ │ ├── properties.ts │ │ ├── propertyNames.ts │ │ └── thenElse.ts │ ├── code.ts │ ├── core/ │ │ ├── id.ts │ │ ├── index.ts │ │ └── ref.ts │ ├── discriminator/ │ │ ├── index.ts │ │ └── types.ts │ ├── draft2020.ts │ ├── draft7.ts │ ├── dynamic/ │ │ ├── dynamicAnchor.ts │ │ ├── dynamicRef.ts │ │ ├── index.ts │ │ ├── recursiveAnchor.ts │ │ └── recursiveRef.ts │ ├── errors.ts │ ├── format/ │ │ ├── format.ts │ │ └── index.ts │ ├── jtd/ │ │ ├── discriminator.ts │ │ ├── elements.ts │ │ ├── enum.ts │ │ ├── error.ts │ │ ├── index.ts │ │ ├── metadata.ts │ │ ├── nullable.ts │ │ ├── optionalProperties.ts │ │ ├── properties.ts │ │ ├── ref.ts │ │ ├── type.ts │ │ ├── union.ts │ │ └── values.ts │ ├── metadata.ts │ ├── next.ts │ ├── unevaluated/ │ │ ├── index.ts │ │ ├── unevaluatedItems.ts │ │ └── unevaluatedProperties.ts │ └── validation/ │ ├── const.ts │ ├── dependentRequired.ts │ ├── enum.ts │ ├── index.ts │ ├── limitContains.ts │ ├── limitItems.ts │ ├── limitLength.ts │ ├── limitNumber.ts │ ├── limitProperties.ts │ ├── multipleOf.ts │ ├── pattern.ts │ ├── required.ts │ └── uniqueItems.ts ├── package.json ├── rollup.config.js ├── scripts/ │ ├── .eslintrc.yml │ ├── bundle.js │ ├── get-ajv-packages │ ├── get-contributors.js │ ├── jsontests.js │ ├── prepare-site │ ├── prepare-tests │ ├── publish-bundles │ └── publish-site ├── spec/ │ ├── .eslintrc.yml │ ├── _json/ │ │ └── README.md │ ├── after_test.ts │ ├── ajv.spec.ts │ ├── ajv.ts │ ├── ajv2019.ts │ ├── ajv2020.ts │ ├── ajv_all_instances.ts │ ├── ajv_async_instances.ts │ ├── ajv_instances.ts │ ├── ajv_jtd.ts │ ├── ajv_options.ts │ ├── ajv_standalone.ts │ ├── async/ │ │ ├── boolean.json │ │ ├── compound.json │ │ ├── format.json │ │ ├── items.json │ │ ├── keyword.json │ │ ├── no_async.json │ │ └── properties.json │ ├── async.spec.ts │ ├── async_schemas.spec.ts │ ├── async_validate.spec.ts │ ├── boolean.spec.ts │ ├── chai.ts │ ├── chai_type.ts │ ├── codegen.spec.ts │ ├── coercion.spec.ts │ ├── discriminator.spec.ts │ ├── dynamic-ref.spec.ts │ ├── errors.spec.ts │ ├── extras/ │ │ ├── $data/ │ │ │ ├── absolute_ref.json │ │ │ ├── const.json │ │ │ ├── enum.json │ │ │ ├── exclusiveMaximum.json │ │ │ ├── exclusiveMinimum.json │ │ │ ├── format.json │ │ │ ├── maxItems.json │ │ │ ├── maxLength.json │ │ │ ├── maxProperties.json │ │ │ ├── maximum.json │ │ │ ├── minItems.json │ │ │ ├── minLength.json │ │ │ ├── minProperties.json │ │ │ ├── minimum.json │ │ │ ├── multipleOf.json │ │ │ ├── pattern.json │ │ │ ├── required.json │ │ │ └── uniqueItems.json │ │ ├── const.json │ │ ├── contains.json │ │ ├── exclusiveMaximum.json │ │ └── exclusiveMinimum.json │ ├── extras.spec.ts │ ├── issues/ │ │ ├── 1001_addKeyword_and_schema_without_id.spec.ts │ │ ├── 1344_non_root_recursive_ref_standalone.spec.ts │ │ ├── 1414_base_uri_change.spec.ts │ │ ├── 1501_jtd_many_properties.spec.ts │ │ ├── 1515_evaluated_properties_nested_anyof.spec.ts │ │ ├── 1539_add_keyword_name_to_validation_error.spec.ts │ │ ├── 1625_evaluated_truthy_pattern_properties.spec.ts │ │ ├── 1683_re2_engine.spec.ts │ │ ├── 1819_mincontains.spec.ts │ │ ├── 181_allErrors_custom_keyword_skipped.spec.ts │ │ ├── 182_nan_validation.spec.ts │ │ ├── 1935_integer_narrowing_subschema.spec.ts │ │ ├── 1949_jtd_empty_values.spec.ts │ │ ├── 1971_jtd_discriminator.spec.ts │ │ ├── 2001_jtd_only_optional_properties.spec.ts │ │ ├── 204_options_schemas_data_together.spec.ts │ │ ├── 210_mutual_recur_frags.spec.ts │ │ ├── 240_mutual_recur_frags_common_ref.spec.ts │ │ ├── 259_validate_meta_against_itself.spec.ts │ │ ├── 273_error_schemaPath_refd_schema.spec.ts │ │ ├── 342_uniqueItems_non-json_objects.spec.ts │ │ ├── 485_type_validation_priority.spec.ts │ │ ├── 50_refs_with_definitions.spec.ts │ │ ├── 521_wrong_warning_id_property.spec.ts │ │ ├── 743_removeAdditional_to_remove_proto.spec.ts │ │ ├── 768_passContext_recursive_ref.spec.ts │ │ ├── 815_id_updates_ref_base.spec.ts │ │ ├── 8_shared_refs.spec.ts │ │ ├── 955_removeAdditional_custom_keywords.spec.ts │ │ ├── cve_2025_69873_redos_attack.spec.ts │ │ └── re2.ts │ ├── javacript.spec.js │ ├── json-schema.spec.ts │ ├── json_parse_tests.json │ ├── jtd-schema.spec.ts │ ├── jtd-timestamps.spec.ts │ ├── keyword.spec.ts │ ├── options/ │ │ ├── comment.spec.ts │ │ ├── int32range.spec.ts │ │ ├── meta_validateSchema.spec.ts │ │ ├── nullable.spec.ts │ │ ├── options_add_schemas.spec.ts │ │ ├── options_code.spec.ts │ │ ├── options_refs.spec.ts │ │ ├── options_reporting.spec.ts │ │ ├── options_validation.spec.ts │ │ ├── ownProperties.spec.ts │ │ ├── removeAdditional.spec.ts │ │ ├── schemaId.spec.ts │ │ ├── strict.spec.ts │ │ ├── strictDefaults.spec.ts │ │ ├── strictKeywords.spec.ts │ │ ├── strictNumbers.spec.ts │ │ ├── unicodeRegExp.spec.ts │ │ ├── unknownFormats.spec.ts │ │ └── useDefaults.spec.ts │ ├── remotes/ │ │ ├── bar.json │ │ ├── buu.json │ │ ├── first.json │ │ ├── foo.json │ │ ├── hyper-schema.json │ │ ├── name.json │ │ ├── node.json │ │ ├── scope_change.json │ │ ├── second.json │ │ └── tree.json │ ├── resolve.spec.ts │ ├── schema-tests.spec.ts │ ├── security/ │ │ ├── array.json │ │ ├── object.json │ │ └── string.json │ ├── security.spec.ts │ ├── standalone.spec.ts │ ├── tests/ │ │ ├── issues/ │ │ │ ├── 12_restoring_root_after_resolve.json │ │ │ ├── 13_root_ref_in_ref_in_remote_ref.json │ │ │ ├── 14_ref_in_remote_ref_with_id.json │ │ │ ├── 1668_not_with_other_keywords.json │ │ │ ├── 170_ref_and_id_in_sibling.json │ │ │ ├── 17_escaping_pattern_property.json │ │ │ ├── 19_required_many_properties.json │ │ │ ├── 1_ids_in_refs.json │ │ │ ├── 20_failing_to_parse_schema.json │ │ │ ├── 226_json_with_control_chars.json │ │ │ ├── 27_1_recursive_raml_schema.json │ │ │ ├── 27_recursive_reference.json │ │ │ ├── 28_escaping_pattern_error.json │ │ │ ├── 2_root_ref_in_ref.json │ │ │ ├── 311_quotes_in_refs.json │ │ │ ├── 33_json_schema_latest.json │ │ │ ├── 413_dependencies_with_quote.json │ │ │ ├── 490_integer_validation.json │ │ │ ├── 502_contains_empty_array_with_ref_in_another_property.json │ │ │ ├── 5_adding_dependency_after.json │ │ │ ├── 5_recursive_references.json │ │ │ ├── 62_resolution_scope_change.json │ │ │ ├── 63_id_property_not_in_schema.json │ │ │ ├── 70_1_recursive_hash_ref_in_remote_ref.json │ │ │ ├── 70_swagger_schema.json │ │ │ ├── 861_empty_propertynames.json │ │ │ ├── 87_$_property.json │ │ │ └── 94_dependencies_fail.json │ │ ├── rules/ │ │ │ ├── allOf.json │ │ │ ├── anyOf.json │ │ │ ├── comment.json │ │ │ ├── dependencies.json │ │ │ ├── format.json │ │ │ ├── if.json │ │ │ ├── items.json │ │ │ ├── oneOf.json │ │ │ ├── required.json │ │ │ ├── type.json │ │ │ └── uniqueItems.json │ │ └── schemas/ │ │ ├── advanced.json │ │ ├── basic.json │ │ ├── complex.json │ │ ├── complex2.json │ │ ├── complex3.json │ │ ├── cosmicrealms.json │ │ └── medium.json │ ├── tsconfig.json │ └── types/ │ ├── async-validate.spec.ts │ ├── error-parameters.spec.ts │ ├── json-schema.spec.ts │ └── jtd-schema.spec.ts └── tsconfig.json
SYMBOL INDEX (1013 symbols across 152 files)
FILE: .runkit_example.js
function test (line 19) | function test(data) {
FILE: docs/.vuepress/theme/index.js
method alias (line 17) | alias() {
FILE: docs/.vuepress/theme/util/index.js
function normalize (line 6) | function normalize(path) {
function getHash (line 10) | function getHash(path) {
function isExternal (line 17) | function isExternal(path) {
function isMailto (line 21) | function isMailto(path) {
function isTel (line 25) | function isTel(path) {
function ensureExt (line 29) | function ensureExt(path) {
function isActive (line 43) | function isActive(route, path) {
function resolvePage (line 54) | function resolvePage(pages, rawPath, base) {
function resolvePath (line 77) | function resolvePath(relative, base, append) {
function resolveSidebarItems (line 122) | function resolveSidebarItems(page, regularPath, site, localePath) {
function resolveHeaders (line 149) | function resolveHeaders(page) {
function groupHeaders (line 168) | function groupHeaders(headers) {
function resolveNavLinkItem (line 182) | function resolveNavLinkItem(linkItem) {
function resolveMatchingConfig (line 193) | function resolveMatchingConfig(regularPath, config) {
function ensureEndingSlash (line 211) | function ensureEndingSlash(path) {
function resolveItem (line 215) | function resolveItem(item, pages, base, groupDepth = 1) {
FILE: lib/2019.ts
constant META_SCHEMA_ID (line 11) | const META_SCHEMA_ID = "https://json-schema.org/draft/2019-09/schema"
class Ajv2019 (line 13) | class Ajv2019 extends AjvCore {
method constructor (line 14) | constructor(opts: Options = {}) {
method _addVocabularies (line 23) | _addVocabularies(): void {
method _addDefaultMetaSchema (line 32) | _addDefaultMetaSchema(): void {
method defaultMeta (line 40) | defaultMeta(): string | AnySchemaObject | undefined {
FILE: lib/2020.ts
constant META_SCHEMA_ID (line 8) | const META_SCHEMA_ID = "https://json-schema.org/draft/2020-12/schema"
class Ajv2020 (line 10) | class Ajv2020 extends AjvCore {
method constructor (line 11) | constructor(opts: Options = {}) {
method _addVocabularies (line 20) | _addVocabularies(): void {
method _addDefaultMetaSchema (line 26) | _addDefaultMetaSchema(): void {
method defaultMeta (line 34) | defaultMeta(): string | AnySchemaObject | undefined {
FILE: lib/ajv.ts
constant META_SUPPORT_DATA (line 7) | const META_SUPPORT_DATA = ["/properties"]
constant META_SCHEMA_ID (line 9) | const META_SCHEMA_ID = "http://json-schema.org/draft-07/schema"
class Ajv (line 11) | class Ajv extends AjvCore {
method _addVocabularies (line 12) | _addVocabularies(): void {
method _addDefaultMetaSchema (line 18) | _addDefaultMetaSchema(): void {
method defaultMeta (line 28) | defaultMeta(): string | AnySchemaObject | undefined {
FILE: lib/compile/codegen/code.ts
constant IDENTIFIER (line 9) | const IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i
class Name (line 11) | class Name extends _CodeOrName {
method constructor (line 13) | constructor(s: string) {
method toString (line 19) | toString(): string {
method emptyStr (line 23) | emptyStr(): boolean {
method names (line 27) | get names(): UsedNames {
class _Code (line 32) | class _Code extends _CodeOrName {
method constructor (line 37) | constructor(code: string | readonly CodeItem[]) {
method toString (line 42) | toString(): string {
method emptyStr (line 46) | emptyStr(): boolean {
method str (line 52) | get str(): string {
method names (line 56) | get names(): UsedNames {
type CodeItem (line 64) | type CodeItem = Name | string | number | boolean | null
type UsedNames (line 66) | type UsedNames = Record<string, number | undefined>
type Code (line 68) | type Code = _Code | Name
type SafeExpr (line 70) | type SafeExpr = Code | number | boolean | null
type CodeArg (line 74) | type CodeArg = SafeExpr | string | undefined
function _ (line 76) | function _(strs: TemplateStringsArray, ...args: CodeArg[]): _Code {
function str (line 88) | function str(strs: TemplateStringsArray, ...args: (CodeArg | string[])[]...
function addCodeArg (line 100) | function addCodeArg(code: CodeItem[], arg: CodeArg | string[]): void {
function optimize (line 106) | function optimize(expr: CodeItem[]): void {
function mergeExprItems (line 121) | function mergeExprItems(a: CodeItem, b: CodeItem): CodeItem | undefined {
function strConcat (line 134) | function strConcat(c1: Code, c2: Code): Code {
function interpolate (line 139) | function interpolate(x?: string | string[] | number | boolean | null): S...
function stringify (line 145) | function stringify(x: unknown): Code {
function safeStringify (line 149) | function safeStringify(x: unknown): string {
function getProperty (line 155) | function getProperty(key: Code | string | number): Code {
function getEsmExportName (line 160) | function getEsmExportName(key: Code | string | number): Code {
function regexpCode (line 167) | function regexpCode(rx: RegExp): Code {
FILE: lib/compile/codegen/index.ts
type SafeExpr (line 9) | type SafeExpr = Code | number | boolean | null
type Block (line 12) | type Block = Code | (() => void)
method optimizeNodes (line 30) | optimizeNodes(): this | ChildNode | ChildNode[] | undefined {
method optimizeNames (line 34) | optimizeNames(_names: UsedNames, _constants: Constants): this | undefined {
class Def (line 43) | class Def extends Node {
method constructor (line 44) | constructor(
method render (line 52) | render({es5, _n}: CGOptions): string {
method optimizeNames (line 58) | optimizeNames(names: UsedNames, constants: Constants): this | undefined {
method names (line 64) | get names(): UsedNames {
class Assign (line 69) | class Assign extends Node {
method constructor (line 70) | constructor(
method render (line 78) | render({_n}: CGOptions): string {
method optimizeNames (line 82) | optimizeNames(names: UsedNames, constants: Constants): this | undefined {
method names (line 88) | get names(): UsedNames {
class AssignOp (line 94) | class AssignOp extends Assign {
method constructor (line 95) | constructor(
method render (line 104) | render({_n}: CGOptions): string {
class Label (line 109) | class Label extends Node {
method constructor (line 111) | constructor(readonly label: Name) {
method render (line 115) | render({_n}: CGOptions): string {
class Break (line 120) | class Break extends Node {
method constructor (line 122) | constructor(readonly label?: Code) {
method render (line 126) | render({_n}: CGOptions): string {
class Throw (line 132) | class Throw extends Node {
method constructor (line 133) | constructor(readonly error: Code) {
method render (line 137) | render({_n}: CGOptions): string {
method names (line 141) | get names(): UsedNames {
class AnyCode (line 146) | class AnyCode extends Node {
method constructor (line 147) | constructor(private code: SafeExpr) {
method render (line 151) | render({_n}: CGOptions): string {
method optimizeNodes (line 155) | optimizeNodes(): this | undefined {
method optimizeNames (line 159) | optimizeNames(names: UsedNames, constants: Constants): this {
method names (line 164) | get names(): UsedNames {
method constructor (line 170) | constructor(readonly nodes: ChildNode[] = []) {
method render (line 174) | render(opts: CGOptions): string {
method optimizeNodes (line 178) | optimizeNodes(): this | ChildNode | ChildNode[] | undefined {
method optimizeNames (line 190) | optimizeNames(names: UsedNames, constants: Constants): this | undefined {
method names (line 203) | get names(): UsedNames {
method render (line 213) | render(opts: CGOptions): string {
class Root (line 218) | class Root extends ParentNode {}
class Else (line 220) | class Else extends BlockNode {
class If (line 224) | class If extends BlockNode {
method constructor (line 227) | constructor(
method render (line 234) | render(opts: CGOptions): string {
method optimizeNodes (line 240) | optimizeNodes(): If | ChildNode[] | undefined {
method optimizeNames (line 258) | optimizeNames(names: UsedNames, constants: Constants): this | undefined {
method names (line 265) | get names(): UsedNames {
class ForLoop (line 281) | class ForLoop extends For {
method constructor (line 282) | constructor(private iteration: Code) {
method render (line 286) | render(opts: CGOptions): string {
method optimizeNames (line 290) | optimizeNames(names: UsedNames, constants: Constants): this | undefined {
method names (line 296) | get names(): UsedNames {
class ForRange (line 301) | class ForRange extends For {
method constructor (line 302) | constructor(
method render (line 311) | render(opts: CGOptions): string {
method names (line 317) | get names(): UsedNames {
class ForIter (line 323) | class ForIter extends For {
method constructor (line 324) | constructor(
method render (line 333) | render(opts: CGOptions): string {
method optimizeNames (line 337) | optimizeNames(names: UsedNames, constants: Constants): this | undefined {
method names (line 343) | get names(): UsedNames {
class Func (line 348) | class Func extends BlockNode {
method constructor (line 350) | constructor(
method render (line 358) | render(opts: CGOptions): string {
class Return (line 364) | class Return extends ParentNode {
method render (line 367) | render(opts: CGOptions): string {
class Try (line 372) | class Try extends BlockNode {
method render (line 376) | render(opts: CGOptions): string {
method optimizeNodes (line 383) | optimizeNodes(): this {
method optimizeNames (line 390) | optimizeNames(names: UsedNames, constants: Constants): this {
method names (line 397) | get names(): UsedNames {
class Catch (line 409) | class Catch extends BlockNode {
method constructor (line 411) | constructor(readonly error: Name) {
method render (line 415) | render(opts: CGOptions): string {
class Finally (line 420) | class Finally extends BlockNode {
method render (line 422) | render(opts: CGOptions): string {
type StartBlockNode (line 427) | type StartBlockNode = If | For | Func | Return | Try
type LeafNode (line 429) | type LeafNode = Def | Assign | Label | Break | Throw | AnyCode
type ChildNode (line 431) | type ChildNode = StartBlockNode | LeafNode
type EndBlockNodeType (line 433) | type EndBlockNodeType =
type Constants (line 442) | type Constants = Record<string, SafeExpr | undefined>
type CodeGenOptions (line 444) | interface CodeGenOptions {
type CGOptions (line 450) | interface CGOptions extends CodeGenOptions {
class CodeGen (line 454) | class CodeGen {
method constructor (line 463) | constructor(extScope: ValueScope, opts: CodeGenOptions = {}) {
method toString (line 470) | toString(): string {
method name (line 475) | name(prefix: string): Name {
method scopeName (line 480) | scopeName(prefix: string): ValueScopeName {
method scopeValue (line 485) | scopeValue(prefixOrName: ValueScopeName | string, value: NameValue): N...
method getScopeValue (line 492) | getScopeValue(prefix: string, keyOrRef: unknown): ValueScopeName | und...
method scopeRefs (line 498) | scopeRefs(scopeName: Name): Code {
method scopeCode (line 502) | scopeCode(): Code {
method _def (line 506) | private _def(
method const (line 519) | const(nameOrPrefix: Name | string, rhs: SafeExpr, _constant?: boolean)...
method let (line 524) | let(nameOrPrefix: Name | string, rhs?: SafeExpr, _constant?: boolean):...
method var (line 529) | var(nameOrPrefix: Name | string, rhs?: SafeExpr, _constant?: boolean):...
method assign (line 534) | assign(lhs: Code, rhs: SafeExpr, sideEffects?: boolean): CodeGen {
method add (line 539) | add(lhs: Code, rhs: SafeExpr): CodeGen {
method code (line 544) | code(c: Block | SafeExpr): CodeGen {
method object (line 551) | object(...keyValues: [Name | string, SafeExpr | string][]): _Code {
method if (line 566) | if(condition: Code | boolean, thenBody?: Block, elseBody?: Block): Cod...
method elseIf (line 580) | elseIf(condition: Code | boolean): CodeGen {
method else (line 585) | else(): CodeGen {
method endIf (line 590) | endIf(): CodeGen {
method _for (line 594) | private _for(node: For, forBody?: Block): CodeGen {
method for (line 601) | for(iteration: Code, forBody?: Block): CodeGen {
method forRange (line 606) | forRange(
method forOf (line 618) | forOf(
method forIn (line 637) | forIn(
method endFor (line 651) | endFor(): CodeGen {
method label (line 656) | label(label: Name): CodeGen {
method break (line 661) | break(label?: Code): CodeGen {
method return (line 666) | return(value: Block | SafeExpr): CodeGen {
method try (line 675) | try(tryBody: Block, catchCode?: (e: Name) => void, finallyCode?: Block...
method throw (line 693) | throw(error: Code): CodeGen {
method block (line 698) | block(body?: Block, nodeCount?: number): CodeGen {
method endBlock (line 705) | endBlock(nodeCount?: number): CodeGen {
method func (line 717) | func(name: Name, args: Code = nil, async?: boolean, funcBody?: Block):...
method endFunc (line 724) | endFunc(): CodeGen {
method optimize (line 728) | optimize(n = 1): void {
method _leafNode (line 735) | private _leafNode(node: LeafNode): CodeGen {
method _blockNode (line 740) | private _blockNode(node: StartBlockNode): void {
method _endBlockNode (line 745) | private _endBlockNode(N1: EndBlockNodeType, N2?: EndBlockNodeType): Co...
method _elseNode (line 754) | private _elseNode(node: If | Else): CodeGen {
method _root (line 763) | private get _root(): Root {
method _currNode (line 767) | private get _currNode(): ParentNode {
method _currNode (line 772) | private set _currNode(node: ParentNode) {
function addNames (line 782) | function addNames(names: UsedNames, from: UsedNames): UsedNames {
function addExprNames (line 787) | function addExprNames(names: UsedNames, from: SafeExpr): UsedNames {
function optimizeExpr (line 792) | function optimizeExpr(expr: SafeExpr, names: UsedNames, constants: Const...
function subtractNames (line 821) | function subtractNames(names: UsedNames, from: UsedNames): void {
function not (line 826) | function not(x: Code | SafeExpr): Code | SafeExpr {
function and (line 833) | function and(...args: Code[]): Code {
function or (line 840) | function or(...args: Code[]): Code {
type MAppend (line 844) | type MAppend = (x: Code, y: Code) => Code
function mappend (line 846) | function mappend(op: Code): MAppend {
function par (line 850) | function par(x: Code): Code {
FILE: lib/compile/codegen/scope.ts
type NameGroup (line 3) | interface NameGroup {
type NameValue (line 8) | interface NameValue {
type ValueReference (line 14) | type ValueReference = unknown // possibly make CodeGen parameterized typ...
class ValueError (line 16) | class ValueError extends Error {
method constructor (line 18) | constructor(name: ValueScopeName) {
type ScopeOptions (line 24) | interface ScopeOptions {
type ValueScopeOptions (line 29) | interface ValueScopeOptions extends ScopeOptions {
type ScopeStore (line 35) | type ScopeStore = Record<string, ValueReference[] | undefined>
type ScopeValues (line 37) | type ScopeValues = {
type ScopeValueSets (line 41) | type ScopeValueSets = {
type UsedValueState (line 45) | enum UsedValueState {
type UsedScopeValues (line 50) | type UsedScopeValues = {
class Scope (line 60) | class Scope {
method constructor (line 65) | constructor({prefixes, parent}: ScopeOptions = {}) {
method toName (line 70) | toName(nameOrPrefix: Name | string): Name {
method name (line 74) | name(prefix: string): Name {
method _newName (line 78) | protected _newName(prefix: string): string {
method _nameGroup (line 83) | private _nameGroup(prefix: string): NameGroup {
type ScopePath (line 91) | interface ScopePath {
class ValueScopeName (line 96) | class ValueScopeName extends Name {
method constructor (line 101) | constructor(prefix: string, nameStr: string) {
method setValue (line 106) | setValue(value: NameValue, {property, itemIndex}: ScopePath): void {
type VSOptions (line 112) | interface VSOptions extends ValueScopeOptions {
class ValueScope (line 118) | class ValueScope extends Scope {
method constructor (line 123) | constructor(opts: ValueScopeOptions) {
method get (line 129) | get(): ScopeStore {
method name (line 133) | name(prefix: string): ValueScopeName {
method value (line 137) | value(nameOrPrefix: ValueScopeName | string, value: NameValue): ValueS...
method getValue (line 158) | getValue(prefix: string, keyOrRef: unknown): ValueScopeName | undefined {
method scopeRefs (line 164) | scopeRefs(scopeName: Name, values: ScopeValues | ScopeValueSets = this...
method scopeCode (line 171) | scopeCode(
method _reduceValues (line 187) | private _reduceValues(
FILE: lib/compile/errors.ts
type ErrorPaths (line 19) | interface ErrorPaths {
function reportError (line 25) | function reportError(
function reportExtraError (line 41) | function reportExtraError(
function resetErrorsCount (line 55) | function resetErrorsCount(gen: CodeGen, errsCount: Name): void {
function extendErrors (line 66) | function extendErrors({
function addError (line 90) | function addError(gen: CodeGen, errObj: Code): void {
function returnErrors (line 100) | function returnErrors(it: SchemaCxt, errs: Code): void {
function errorObjectCode (line 120) | function errorObjectCode(
function errorObject (line 130) | function errorObject(
function errorInstancePath (line 144) | function errorInstancePath({errorPath}: SchemaCxt, {instancePath}: Error...
function errorSchemaPath (line 151) | function errorSchemaPath(
function extraErrorProps (line 162) | function extraErrorProps(
FILE: lib/compile/index.ts
type SchemaRefs (line 20) | type SchemaRefs = {
type SchemaCxt (line 24) | interface SchemaCxt {
type SchemaObjCxt (line 61) | interface SchemaObjCxt extends SchemaCxt {
type SchemaEnvArgs (line 64) | interface SchemaEnvArgs {
class SchemaEnv (line 74) | class SchemaEnv implements SchemaEnvArgs {
method constructor (line 92) | constructor(env: SchemaEnvArgs) {
function compileSchema (line 111) | function compileSchema(this: Ajv, sch: SchemaEnv): SchemaEnv {
function resolveRef (line 205) | function resolveRef(
function inlineOrCompile (line 226) | function inlineOrCompile(this: Ajv, sch: SchemaEnv): AnySchema | SchemaE...
function getCompilingSchema (line 232) | function getCompilingSchema(this: Ajv, schEnv: SchemaEnv): SchemaEnv | v...
function sameSchemaEnv (line 238) | function sameSchemaEnv(s1: SchemaEnv, s2: SchemaEnv): boolean {
function resolve (line 244) | function resolve(
function resolveSchema (line 255) | function resolveSchema(
constant PREVENT_SCOPE_CHANGE (line 288) | const PREVENT_SCOPE_CHANGE = new Set([
function getJsonPointer (line 296) | function getJsonPointer(
FILE: lib/compile/jtd/parse.ts
type GenParse (line 15) | type GenParse = (cxt: ParseCxt) => void
type ParseCxt (line 28) | interface ParseCxt {
function compileParser (line 39) | function compileParser(
function parserFunction (line 86) | function parserFunction(cxt: ParseCxt): void {
function parseCode (line 106) | function parseCode(cxt: ParseCxt): void {
function parseNullable (line 120) | function parseNullable(cxt: ParseCxt, parseForm: GenParse): void {
function parseElements (line 126) | function parseElements(cxt: ParseCxt): void {
function parseValues (line 138) | function parseValues(cxt: ParseCxt): void {
function parseItems (line 145) | function parseItems(cxt: ParseCxt, endToken: string, block: () => void):...
function tryParseItems (line 150) | function tryParseItems(cxt: ParseCxt, endToken: string, block: () => voi...
function parseKeyValue (line 162) | function parseKeyValue(cxt: ParseCxt, schema: SchemaObject): void {
function parseDiscriminator (line 170) | function parseDiscriminator(cxt: ParseCxt): void {
function parseProperties (line 204) | function parseProperties(cxt: ParseCxt): void {
function parseSchemaProperties (line 211) | function parseSchemaProperties(cxt: ParseCxt, discriminator?: string): v...
function parseDefinedProperty (line 243) | function parseDefinedProperty(cxt: ParseCxt, key: Name, schemas: SchemaO...
function parsePropertyValue (line 251) | function parsePropertyValue(cxt: ParseCxt, key: Name, schema: SchemaObje...
function parseType (line 255) | function parseType(cxt: ParseCxt): void {
function parseString (line 297) | function parseString(cxt: ParseCxt): void {
function parseEnum (line 302) | function parseEnum(cxt: ParseCxt): void {
function parseNumber (line 319) | function parseNumber(cxt: ParseCxt, maxDigits?: number): void {
function parseBooleanToken (line 329) | function parseBooleanToken(bool: boolean, fail: GenParse): GenParse {
function parseRef (line 341) | function parseRef(cxt: ParseCxt): void {
function getParser (line 352) | function getParser(gen: CodeGen, sch: SchemaEnv): Code {
function parseEmpty (line 358) | function parseEmpty(cxt: ParseCxt): void {
function parseWith (line 362) | function parseWith(cxt: ParseCxt, parseFunc: {code: string}, args?: Safe...
function partialParse (line 366) | function partialParse(cxt: ParseCxt, parseFunc: Name, args?: SafeExpr): ...
function parseToken (line 373) | function parseToken(cxt: ParseCxt, tok: string): void {
function tryParseToken (line 377) | function tryParseToken(cxt: ParseCxt, tok: string, fail: GenParse, succe...
function skipWhitespace (line 391) | function skipWhitespace({gen, char: c}: ParseCxt): void {
function jsonSlice (line 397) | function jsonSlice(len: number | Name): Code {
function jsonSyntaxError (line 403) | function jsonSyntaxError(cxt: ParseCxt): void {
function parsingError (line 407) | function parsingError({gen, parseName}: ParseCxt, msg: Code): void {
FILE: lib/compile/jtd/serialize.ts
type SerializeCxt (line 24) | interface SerializeCxt {
function compileSerializer (line 33) | function compileSerializer(
function serializeCode (line 80) | function serializeCode(cxt: SerializeCxt): void {
function serializeNullable (line 91) | function serializeNullable(cxt: SerializeCxt, serializeForm: (_cxt: Seri...
function serializeElements (line 101) | function serializeElements(cxt: SerializeCxt): void {
function serializeValues (line 112) | function serializeValues(cxt: SerializeCxt): void {
function serializeKeyValue (line 120) | function serializeKeyValue(cxt: SerializeCxt, key: Name, schema: SchemaO...
function serializeDiscriminator (line 129) | function serializeDiscriminator(cxt: SerializeCxt): void {
function serializeProperties (line 145) | function serializeProperties(cxt: SerializeCxt): void {
function serializeSchemaProperties (line 152) | function serializeSchemaProperties(cxt: SerializeCxt, discriminator?: st...
function serializeType (line 206) | function serializeType(cxt: SerializeCxt): void {
function serializeString (line 227) | function serializeString({gen, data}: SerializeCxt): void {
function serializeNumber (line 231) | function serializeNumber({gen, data, self}: SerializeCxt): void {
function serializeRef (line 246) | function serializeRef(cxt: SerializeCxt): void {
function getSerialize (line 257) | function getSerialize(gen: CodeGen, sch: SchemaEnv): Code {
function serializeEmpty (line 263) | function serializeEmpty({gen, data}: SerializeCxt): void {
function addComma (line 267) | function addComma({gen}: SerializeCxt, first?: Name): void {
FILE: lib/compile/jtd/types.ts
type SchemaObjectMap (line 3) | type SchemaObjectMap = {[Ref in string]?: SchemaObject}
type JTDForm (line 16) | type JTDForm = (typeof jtdForms)[number]
FILE: lib/compile/ref_error.ts
class MissingRefError (line 4) | class MissingRefError extends Error {
method constructor (line 8) | constructor(resolver: UriResolver, baseId: string, ref: string, msg?: ...
FILE: lib/compile/resolve.ts
type LocalRefs (line 9) | type LocalRefs = {[Ref in string]?: AnySchemaObject}
constant SIMPLE_INLINED (line 12) | const SIMPLE_INLINED = new Set([
function inlineRef (line 31) | function inlineRef(schema: AnySchema, limit: boolean | number = true): b...
constant REF_KEYWORDS (line 38) | const REF_KEYWORDS = new Set([
function hasRef (line 46) | function hasRef(schema: AnySchemaObject): boolean {
function countKeys (line 56) | function countKeys(schema: AnySchemaObject): number {
function getFullPath (line 70) | function getFullPath(resolver: UriResolver, id = "", normalize?: boolean...
function _getFullPath (line 76) | function _getFullPath(resolver: UriResolver, p: URIComponent): string {
constant TRAILING_SLASH_HASH (line 81) | const TRAILING_SLASH_HASH = /#\/?$/
function normalizeId (line 82) | function normalizeId(id: string | undefined): string {
function resolveUrl (line 86) | function resolveUrl(resolver: UriResolver, baseId: string, id: string): ...
constant ANCHOR (line 91) | const ANCHOR = /^[a-z_][-a-z0-9._]*$/i
function getSchemaRefs (line 93) | function getSchemaRefs(this: Ajv, schema: AnySchema, baseId: string): Lo...
FILE: lib/compile/rules.ts
type JSONType (line 5) | type JSONType = (typeof _jsonTypes)[number]
function isJSONType (line 9) | function isJSONType(x: unknown): x is JSONType {
type ValidationTypes (line 13) | type ValidationTypes = {
type ValidationRules (line 17) | interface ValidationRules {
type RuleGroup (line 25) | interface RuleGroup {
type Rule (line 31) | interface Rule {
function getRules (line 36) | function getRules(): ValidationRules {
FILE: lib/compile/util.ts
function toHash (line 8) | function toHash<T extends string = string>(arr: T[]): {[K in T]?: true} {
function alwaysValidSchema (line 14) | function alwaysValidSchema(it: SchemaCxt, schema: AnySchema): boolean | ...
function checkUnknownRules (line 21) | function checkUnknownRules(it: SchemaCxt, schema: AnySchema = it.schema)...
function schemaHasRules (line 31) | function schemaHasRules(
function schemaHasRulesButRef (line 40) | function schemaHasRulesButRef(schema: AnySchema, RULES: ValidationRules)...
function schemaRefOrVal (line 46) | function schemaRefOrVal(
function unescapeFragment (line 59) | function unescapeFragment(str: string): string {
function escapeFragment (line 63) | function escapeFragment(str: string | number): string {
function escapeJsonPointer (line 67) | function escapeJsonPointer(str: string | number): string {
function unescapeJsonPointer (line 72) | function unescapeJsonPointer(str: string): string {
function eachItem (line 76) | function eachItem<T>(xs: T | T[], f: (x: T) => void): void {
type SomeEvaluated (line 84) | type SomeEvaluated = EvaluatedProperties | EvaluatedItems
type MergeEvaluatedFunc (line 86) | type MergeEvaluatedFunc<T extends SomeEvaluated> = (
type MakeMergeFuncArgs (line 93) | interface MakeMergeFuncArgs<T extends SomeEvaluated> {
function makeMergeEvaluated (line 100) | function makeMergeEvaluated<T extends SomeEvaluated>({
type MergeEvaluated (line 119) | interface MergeEvaluated {
function evaluatedPropsToName (line 160) | function evaluatedPropsToName(gen: CodeGen, ps?: EvaluatedProperties): N...
function setEvaluated (line 167) | function setEvaluated(gen: CodeGen, props: Name, ps: {[K in string]?: tr...
function useFunc (line 173) | function useFunc(gen: CodeGen, f: {code: string}): Name {
type Type (line 180) | enum Type {
function getErrorPath (line 185) | function getErrorPath(
function checkStrictMode (line 204) | function checkStrictMode(
FILE: lib/compile/validate/applicability.ts
function schemaHasRulesForType (line 5) | function schemaHasRulesForType(
function shouldUseGroup (line 13) | function shouldUseGroup(schema: AnySchemaObject, group: RuleGroup): bool...
function shouldUseRule (line 17) | function shouldUseRule(schema: AnySchemaObject, rule: Rule): boolean | u...
FILE: lib/compile/validate/boolSchema.ts
function topBoolOrEmptySchema (line 11) | function topBoolOrEmptySchema(it: SchemaCxt): void {
function boolOrEmptySchema (line 23) | function boolOrEmptySchema(it: SchemaCxt, valid: Name): void {
function falseSchemaError (line 33) | function falseSchemaError(it: SchemaCxt, overrideAllErrors?: boolean): v...
FILE: lib/compile/validate/dataType.ts
type DataType (line 14) | enum DataType {
function getSchemaTypes (line 19) | function getSchemaTypes(schema: AnySchemaObject): JSONType[] {
function getJSONTypes (line 34) | function getJSONTypes(ts: unknown | unknown[]): JSONType[] {
function coerceAndCheckDataType (line 40) | function coerceAndCheckDataType(it: SchemaObjCxt, types: JSONType[]): bo...
constant COERCIBLE (line 56) | const COERCIBLE: Set<JSONType> = new Set(["string", "number", "integer",...
function coerceToTypes (line 57) | function coerceToTypes(types: JSONType[], coerceTypes?: boolean | "array...
function coerceData (line 63) | function coerceData(it: SchemaObjCxt, types: JSONType[], coerceTo: JSONT...
function assignParentData (line 138) | function assignParentData({gen, parentData, parentDataProperty}: SchemaO...
function checkDataType (line 145) | function checkDataType(
function checkDataTypes (line 178) | function checkDataTypes(
type TypeError (line 203) | type TypeError = ErrorObject<"type", {type: string}>
function reportTypeError (line 211) | function reportTypeError(it: SchemaObjCxt): void {
function getTypeErrorContext (line 216) | function getTypeErrorContext(it: SchemaObjCxt): KeywordErrorCxt {
FILE: lib/compile/validate/defaults.ts
function assignDefaults (line 5) | function assignDefaults(it: SchemaObjCxt, ty?: string): void {
function assignDefault (line 16) | function assignDefault(it: SchemaObjCxt, prop: string | number, defaultV...
FILE: lib/compile/validate/index.ts
function validateFunctionCode (line 38) | function validateFunctionCode(it: SchemaCxt): void {
function validateFunction (line 49) | function validateFunction(
function destructureValCxt (line 66) | function destructureValCxt(opts: InstanceOptions): Code {
function destructureValCxtES5 (line 72) | function destructureValCxtES5(gen: CodeGen, opts: InstanceOptions): void {
function topSchemaObjCode (line 92) | function topSchemaObjCode(it: SchemaObjCxt): void {
function resetEvaluated (line 106) | function resetEvaluated(it: SchemaObjCxt): void {
function funcSourceUrl (line 114) | function funcSourceUrl(schema: AnySchema, opts: InstanceOptions): Code {
function subschemaCode (line 120) | function subschemaCode(it: SchemaCxt, valid: Name): void {
function schemaCxtHasRules (line 131) | function schemaCxtHasRules({schema, self}: SchemaCxt): boolean {
function isSchemaObj (line 137) | function isSchemaObj(it: SchemaCxt): it is SchemaObjCxt {
function subSchemaObjCode (line 141) | function subSchemaObjCode(it: SchemaObjCxt, valid: Name): void {
function checkKeywords (line 152) | function checkKeywords(it: SchemaObjCxt): void {
function typeAndKeywords (line 157) | function typeAndKeywords(it: SchemaObjCxt, errsCount?: Name): void {
function checkRefsAndKeywords (line 164) | function checkRefsAndKeywords(it: SchemaObjCxt): void {
function checkNoDefault (line 171) | function checkNoDefault(it: SchemaObjCxt): void {
function updateContext (line 178) | function updateContext(it: SchemaObjCxt): void {
function checkAsyncSchema (line 183) | function checkAsyncSchema(it: SchemaObjCxt): void {
function commentKeyword (line 187) | function commentKeyword({gen, schemaEnv, schema, errSchemaPath, opts}: S...
function returnResults (line 198) | function returnResults(it: SchemaCxt): void {
function assignEvaluated (line 214) | function assignEvaluated({gen, evaluated, props, items}: SchemaCxt): void {
function schemaKeywords (line 219) | function schemaKeywords(
function iterateKeywords (line 255) | function iterateKeywords(it: SchemaObjCxt, group: RuleGroup): void {
function checkStrictTypes (line 271) | function checkStrictTypes(it: SchemaObjCxt, types: JSONType[]): void {
function checkContextTypes (line 278) | function checkContextTypes(it: SchemaObjCxt, types: JSONType[]): void {
function checkMultipleTypes (line 292) | function checkMultipleTypes(it: SchemaObjCxt, ts: JSONType[]): void {
function checkKeywordTypes (line 298) | function checkKeywordTypes(it: SchemaObjCxt, ts: JSONType[]): void {
function hasApplicableType (line 311) | function hasApplicableType(schTs: JSONType[], kwdT: JSONType): boolean {
function includesType (line 315) | function includesType(ts: JSONType[], t: JSONType): boolean {
function narrowSchemaTypes (line 319) | function narrowSchemaTypes(it: SchemaObjCxt, withTypes: JSONType[]): void {
function strictTypesError (line 328) | function strictTypesError(it: SchemaObjCxt, msg: string): void {
class KeywordCxt (line 334) | class KeywordCxt implements KeywordErrorCxt {
method constructor (line 351) | constructor(it: SchemaObjCxt, def: AddedKeywordDefinition, keyword: st...
method result (line 380) | result(condition: Code, successAction?: () => void, failAction?: () =>...
method failResult (line 384) | failResult(condition: Code, successAction?: () => void, failAction?: (...
method pass (line 398) | pass(condition: Code, failAction?: () => void): void {
method fail (line 402) | fail(condition?: Code): void {
method fail$data (line 414) | fail$data(condition: Code): void {
method error (line 420) | error(append?: boolean, errorParams?: KeywordCxtParams, errorPaths?: E...
method _error (line 430) | private _error(append?: boolean, errorPaths?: ErrorPaths): void {
method $dataError (line 434) | $dataError(): void {
method reset (line 438) | reset(): void {
method ok (line 443) | ok(cond: Code | boolean): void {
method setParams (line 447) | setParams(obj: KeywordCxtParams, assign?: true): void {
method block$data (line 452) | block$data(valid: Name, codeBlock: () => void, $dataValid: Code = nil)...
method check$data (line 459) | check$data(valid: Name = nil, $dataValid: Code = nil): void {
method invalid$data (line 472) | invalid$data(): Code {
method subschema (line 495) | subschema(appl: SubschemaArgs, valid: Name): SchemaCxt {
method mergeEvaluated (line 504) | mergeEvaluated(schemaCxt: SchemaCxt, toName?: typeof Name): void {
method mergeValidEvaluated (line 515) | mergeValidEvaluated(schemaCxt: SchemaCxt, valid: Name): boolean | void {
function keywordCode (line 524) | function keywordCode(
constant JSON_POINTER (line 542) | const JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/
constant RELATIVE_JSON_POINTER (line 543) | const RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/
function getData (line 544) | function getData(
FILE: lib/compile/validate/keyword.ts
type KeywordCompilationResult (line 17) | type KeywordCompilationResult = AnySchema | SchemaValidateFunction | Any...
function macroKeywordCode (line 19) | function macroKeywordCode(cxt: KeywordCxt, def: MacroKeywordDefinition):...
function funcKeywordCode (line 39) | function funcKeywordCode(cxt: KeywordCxt, def: FuncKeywordDefinition): v...
function modifyData (line 97) | function modifyData(cxt: KeywordCxt): void {
function addErrs (line 102) | function addErrs(cxt: KeywordCxt, errs: Code): void {
function checkAsyncKeyword (line 116) | function checkAsyncKeyword({schemaEnv}: SchemaObjCxt, def: FuncKeywordDe...
function useKeyword (line 120) | function useKeyword(gen: CodeGen, keyword: string, result?: KeywordCompi...
function validSchemaType (line 128) | function validSchemaType(
function validateKeywordUsage (line 146) | function validateKeywordUsage(
FILE: lib/compile/validate/subschema.ts
type SubschemaContext (line 7) | interface SubschemaContext {
type SubschemaArgs (line 29) | type SubschemaArgs = Partial<{
function getSubschema (line 49) | function getSubschema(
function extendSubschemaData (line 87) | function extendSubschemaData(
function extendSubschemaMode (line 126) | function extendSubschemaMode(
FILE: lib/core.ts
type Plugin (line 24) | interface Plugin<Opts> {
constant META_IGNORE_OPTIONS (line 71) | const META_IGNORE_OPTIONS: (keyof Options)[] = ["removeAdditional", "use...
constant EXT_SCOPE_NAMES (line 72) | const EXT_SCOPE_NAMES = new Set([
type Options (line 88) | type Options = CurrentOptions & DeprecatedOptions
type CurrentOptions (line 90) | interface CurrentOptions {
type CodeOptions (line 145) | interface CodeOptions {
type InstanceCodeOptions (line 156) | interface InstanceCodeOptions extends CodeOptions {
type DeprecatedOptions (line 161) | interface DeprecatedOptions {
type RemovedOptions (line 170) | interface RemovedOptions {
type OptionsInfo (line 188) | type OptionsInfo<T extends RemovedOptions | DeprecatedOptions> = {
type RequiredInstanceOptions (line 216) | type RequiredInstanceOptions = {
type InstanceOptions (line 237) | type InstanceOptions = Options & RequiredInstanceOptions
constant MAX_EXPRESSION (line 239) | const MAX_EXPRESSION = 200
function requiredOptions (line 242) | function requiredOptions(o: Options): RequiredInstanceOptions {
type Logger (line 270) | interface Logger {
class Ajv (line 276) | class Ajv {
method constructor (line 294) | constructor(opts: Options = {}) {
method _addVocabularies (line 317) | _addVocabularies(): void {
method _addDefaultMetaSchema (line 321) | _addDefaultMetaSchema(): void {
method defaultMeta (line 332) | defaultMeta(): string | AnySchemaObject | undefined {
method validate (line 355) | validate<T>(
method compile (line 388) | compile<T = unknown>(schema: AnySchema, _meta?: boolean): AnyValidateF...
method compileAsync (line 410) | compileAsync<T = unknown>(
method addSchema (line 471) | addSchema(
method addMetaSchema (line 497) | addMetaSchema(
method validateSchema (line 507) | validateSchema(schema: AnySchema, throwOrLogError?: boolean): boolean ...
method getSchema (line 531) | getSchema<T = unknown>(keyRef: string): AnyValidateFunction<T> | undef...
method removeSchema (line 548) | removeSchema(schemaKeyRef?: AnySchema | string | RegExp): Ajv {
method addVocabulary (line 584) | addVocabulary(definitions: Vocabulary): Ajv {
method addKeyword (line 589) | addKeyword(
method getKeyword (line 630) | getKeyword(keyword: string): AddedKeywordDefinition | boolean {
method removeKeyword (line 636) | removeKeyword(keyword: string): Ajv {
method addFormat (line 649) | addFormat(name: string, format: Format): Ajv {
method errorsText (line 655) | errorsText(
method $dataMetaSchema (line 665) | $dataMetaSchema(metaSchema: AnySchemaObject, keywordsJsonPointers: str...
method _removeAllSchemas (line 685) | private _removeAllSchemas(schemas: {[Ref in string]?: SchemaEnv | stri...
method _addSchema (line 699) | _addSchema(
method _checkUnique (line 730) | private _checkUnique(id: string): void {
method _compileSchemaEnv (line 736) | private _compileSchemaEnv(sch: SchemaEnv): AnyValidateFunction {
method _compileMetaSchema (line 745) | private _compileMetaSchema(sch: SchemaEnv): void {
type ErrorsTextOptions (line 756) | interface ErrorsTextOptions {
function checkOptions (line 761) | function checkOptions(
function getSchEnv (line 774) | function getSchEnv(this: Ajv, keyRef: string): SchemaEnv | string | unde...
function addInitialSchemas (line 779) | function addInitialSchemas(this: Ajv): void {
function addInitialFormats (line 786) | function addInitialFormats(this: Ajv): void {
function addInitialKeywords (line 793) | function addInitialKeywords(
function getMetaSchemaOptions (line 809) | function getMetaSchemaOptions(this: Ajv): InstanceOptions {
method log (line 815) | log() {}
method warn (line 815) | warn() {}
method error (line 815) | error() {}
function getLogger (line 817) | function getLogger(logger?: Partial<Logger> | false): Logger {
constant KEYWORD_NAME (line 824) | const KEYWORD_NAME = /^[a-z_$][a-z0-9_$:-]*$/i
function checkKeyword (line 826) | function checkKeyword(this: Ajv, keyword: string | string[], def?: Keywo...
function addRule (line 838) | function addRule(
function addBeforeRule (line 869) | function addBeforeRule(this: Ajv, ruleGroup: RuleGroup, rule: Rule, befo...
function keywordMetaschema (line 879) | function keywordMetaschema(this: Ajv, def: KeywordDefinition): void {
function schemaOrData (line 890) | function schemaOrData(schema: AnySchema): AnySchemaObject {
FILE: lib/jtd.ts
constant META_SCHEMA_ID (line 10) | const META_SCHEMA_ID = "JTD-meta-schema"
type JTDOptions (line 12) | type JTDOptions = CurrentOptions & {
class Ajv (line 38) | class Ajv extends AjvCore {
method constructor (line 39) | constructor(opts: JTDOptions = {}) {
method _addVocabularies (line 46) | _addVocabularies(): void {
method _addDefaultMetaSchema (line 51) | _addDefaultMetaSchema(): void {
method defaultMeta (line 57) | defaultMeta(): string | AnySchemaObject | undefined {
method compileSerializer (line 66) | compileSerializer<T = unknown>(schema: SchemaObject): (data: T) => str...
method compileParser (line 75) | compileParser<T = unknown>(schema: SchemaObject): JTDParser<T> {
method _compileSerializer (line 80) | private _compileSerializer<T>(sch: SchemaEnv): (data: T) => string {
method _compileParser (line 87) | private _compileParser(sch: SchemaEnv): JTDParser {
FILE: lib/refs/json-schema-2019-09/index.ts
constant META_SUPPORT_DATA (line 11) | const META_SUPPORT_DATA = ["/properties"]
function addMetaSchema2019 (line 13) | function addMetaSchema2019(this: Ajv, $data?: boolean): Ajv {
FILE: lib/refs/json-schema-2020-12/index.ts
constant META_SUPPORT_DATA (line 12) | const META_SUPPORT_DATA = ["/properties"]
function addMetaSchema2020 (line 14) | function addMetaSchema2020(this: Ajv, $data?: boolean): Ajv {
FILE: lib/refs/jtd-schema.ts
type MetaSchema (line 3) | type MetaSchema = (root: boolean) => SchemaObject
FILE: lib/runtime/equal.ts
type Equal (line 4) | type Equal = typeof equal & {code: string}
FILE: lib/runtime/parseJson.ts
function parseJson (line 3) | function parseJson(s: string, pos: number): unknown {
function parseJsonNumber (line 34) | function parseJsonNumber(s: string, pos: number, maxDigits?: number): nu...
constant CODE_A (line 109) | const CODE_A: number = "a".charCodeAt(0)
constant CODE_0 (line 110) | const CODE_0: number = "0".charCodeAt(0)
function parseJsonString (line 112) | function parseJsonString(s: string, pos: number): string | undefined {
FILE: lib/runtime/quote.ts
function quote (line 15) | function quote(s: string): string {
FILE: lib/runtime/re2.ts
type Re2 (line 3) | type Re2 = typeof re2 & {code: string}
FILE: lib/runtime/timestamp.ts
constant DT_SEPARATOR (line 1) | const DT_SEPARATOR = /t|\s/i
constant DATE (line 2) | const DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/
constant TIME (line 3) | const TIME = /^(\d\d):(\d\d):(\d\d)(?:\.\d+)?(?:z|([+-]\d\d)(?::?(\d\d))...
constant DAYS (line 4) | const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
function validTimestamp (line 6) | function validTimestamp(str: string, allowDate: boolean): boolean {
function validDate (line 15) | function validDate(str: string): boolean {
function validTime (line 31) | function validTime(str: string): boolean {
FILE: lib/runtime/ucs2length.ts
function ucs2length (line 3) | function ucs2length(str: string): number {
FILE: lib/runtime/uri.ts
type URI (line 3) | type URI = typeof uri & {code: string}
FILE: lib/runtime/validation_error.ts
class ValidationError (line 3) | class ValidationError extends Error {
method constructor (line 8) | constructor(errors: Partial<ErrorObject>[]) {
FILE: lib/standalone/index.ts
function standaloneCode (line 7) | function standaloneCode(
FILE: lib/standalone/instance.ts
class AjvPack (line 5) | class AjvPack {
method constructor (line 7) | constructor(readonly ajv: Ajv) {}
method validate (line 9) | validate(schemaKeyRef: AnySchema | string, data: unknown): boolean | P...
method compile (line 13) | compile<T = unknown>(schema: AnySchema, meta?: boolean): AnyValidateFu...
method getSchema (line 17) | getSchema<T = unknown>(keyRef: string): AnyValidateFunction<T> | undef...
method getStandalone (line 23) | private getStandalone<T = unknown>(v: AnyValidateFunction<T>): AnyVali...
method addSchema (line 27) | addSchema(...args: Parameters<typeof Ajv.prototype.addSchema>): AjvPack {
method addKeyword (line 32) | addKeyword(...args: Parameters<typeof Ajv.prototype.addKeyword>): AjvP...
FILE: lib/types/index.ts
type _SchemaObject (line 8) | interface _SchemaObject {
type SchemaObject (line 15) | interface SchemaObject extends _SchemaObject {
type AsyncSchema (line 23) | interface AsyncSchema extends _SchemaObject {
type AnySchemaObject (line 27) | type AnySchemaObject = SchemaObject | AsyncSchema
type Schema (line 29) | type Schema = SchemaObject | boolean
type AnySchema (line 31) | type AnySchema = Schema | AsyncSchema
type SchemaMap (line 33) | type SchemaMap = {[Key in string]?: AnySchema}
type SourceCode (line 35) | interface SourceCode {
type DataValidationCxt (line 42) | interface DataValidationCxt<T extends string | number = string | number> {
type ValidateFunction (line 50) | interface ValidateFunction<T = unknown> {
type JTDParser (line 60) | interface JTDParser<T = unknown> {
type EvaluatedProperties (line 66) | type EvaluatedProperties = {[K in string]?: true} | true
type EvaluatedItems (line 68) | type EvaluatedItems = number | true
type Evaluated (line 70) | interface Evaluated {
type AsyncValidateFunction (line 79) | interface AsyncValidateFunction<T = unknown> extends ValidateFunction<T> {
type AnyValidateFunction (line 84) | type AnyValidateFunction<T = any> = ValidateFunction<T> | AsyncValidateF...
type ErrorObject (line 86) | interface ErrorObject<K extends string = string, P = Record<string, any>...
type ErrorNoParams (line 101) | type ErrorNoParams<K extends string, S = unknown> = ErrorObject<K, Recor...
type _KeywordDef (line 103) | interface _KeywordDef {
type CodeKeywordDefinition (line 119) | interface CodeKeywordDefinition extends _KeywordDef {
type MacroKeywordFunc (line 124) | type MacroKeywordFunc = (
type CompileKeywordFunc (line 130) | type CompileKeywordFunc = (
type DataValidateFunction (line 136) | interface DataValidateFunction {
type SchemaValidateFunction (line 141) | interface SchemaValidateFunction {
type FuncKeywordDefinition (line 151) | interface FuncKeywordDefinition extends _KeywordDef {
type MacroKeywordDefinition (line 162) | interface MacroKeywordDefinition extends FuncKeywordDefinition {
type KeywordDefinition (line 166) | type KeywordDefinition =
type AddedKeywordDefinition (line 171) | type AddedKeywordDefinition = KeywordDefinition & {
type KeywordErrorDefinition (line 176) | interface KeywordErrorDefinition {
type Vocabulary (line 181) | type Vocabulary = (KeywordDefinition | string)[]
type KeywordErrorCxt (line 183) | interface KeywordErrorCxt {
type KeywordCxtParams (line 198) | type KeywordCxtParams = {[P in string]?: Code | string | number}
type FormatValidator (line 200) | type FormatValidator<T extends string | number> = (data: T) => boolean
type FormatCompare (line 202) | type FormatCompare<T extends string | number> = (data1: T, data2: T) => ...
type AsyncFormatValidator (line 204) | type AsyncFormatValidator<T extends string | number> = (data: T) => Prom...
type FormatDefinition (line 206) | interface FormatDefinition<T extends string | number> {
type AsyncFormatDefinition (line 213) | interface AsyncFormatDefinition<T extends string | number> {
type AddedFormat (line 220) | type AddedFormat =
type Format (line 229) | type Format = AddedFormat | string
type RegExpEngine (line 231) | interface RegExpEngine {
type RegExpLike (line 236) | interface RegExpLike {
type UriResolver (line 240) | interface UriResolver {
FILE: lib/types/json-schema.ts
type StrictNullChecksWrapper (line 2) | type StrictNullChecksWrapper<Name extends string, Type> = undefined exte...
type UnionToIntersection (line 6) | type UnionToIntersection<U> = (U extends any ? (_: U) => void : never) e...
type SomeJSONSchema (line 10) | type SomeJSONSchema = UncheckedJSONSchemaType<Known, true>
type UncheckedPartialSchema (line 12) | type UncheckedPartialSchema<T> = Partial<UncheckedJSONSchemaType<T, true>>
type PartialSchema (line 14) | type PartialSchema<T> = StrictNullChecksWrapper<"PartialSchema", Uncheck...
type JSONType (line 16) | type JSONType<T extends string, IsPartial extends boolean> = IsPartial e...
type NumberKeywords (line 20) | interface NumberKeywords {
type StringKeywords (line 29) | interface StringKeywords {
type UncheckedJSONSchemaType (line 36) | type UncheckedJSONSchemaType<T, IsPartial extends boolean> = (
type JSONSchemaType (line 143) | type JSONSchemaType<T> = StrictNullChecksWrapper<
type Known (line 148) | type Known =
type UncheckedPropertiesSchema (line 157) | type UncheckedPropertiesSchema<T> = {
type PropertiesSchema (line 161) | type PropertiesSchema<T> = StrictNullChecksWrapper<
type UncheckedRequiredMembers (line 166) | type UncheckedRequiredMembers<T> = {
type RequiredMembers (line 170) | type RequiredMembers<T> = StrictNullChecksWrapper<
type Nullable (line 175) | type Nullable<T> = undefined extends T
FILE: lib/types/jtd-schema.ts
type NumberType (line 2) | type NumberType = "float32" | "float64" | "int8" | "uint8" | "int16" | "...
type StringType (line 5) | type StringType = "string" | "timestamp"
type SomeJTDSchemaType (line 8) | type SomeJTDSchemaType = (
type RequiredKeys (line 44) | type RequiredKeys<T> = {
type OptionalKeys (line 49) | type OptionalKeys<T> = {
type IsUnion_ (line 54) | type IsUnion_<T, U extends T = T> = false extends (
type IsUnion (line 59) | type IsUnion<T> = IsUnion_<T>
type TypeEquality (line 62) | type TypeEquality<T, E> = [T] extends [E] ? ([E] extends [T] ? true : fa...
type NullTypeEquality (line 65) | type NullTypeEquality<T, E> = TypeEquality<T | null, E | null>
type EnumString (line 68) | type EnumString<T> = [T] extends [never]
type IsEnum (line 77) | type IsEnum<T> = null extends EnumString<T> ? false : true
type IsElements (line 82) | type IsElements<T> = false extends IsUnion<T>
type IsValues (line 91) | type IsValues<T> = false extends IsUnion<T> ? TypeEquality<keyof T, stri...
type IsRecord (line 94) | type IsRecord<T, Union extends boolean> = Union extends IsUnion<T>
type IsEmptyRecord (line 101) | type IsEmptyRecord<T> = [T] extends [Record<string, never>]
type JTDSchemaType (line 108) | type JTDSchemaType<T, D extends Record<string, unknown> = Record<string,...
type JTDDataDef (line 209) | type JTDDataDef<S, D extends Record<string, unknown>> =
type JTDDataType (line 271) | type JTDDataType<S> = S extends {definitions: Record<string, unknown>}
FILE: lib/vocabularies/applicator/additionalItems.ts
type AdditionalItemsError (line 11) | type AdditionalItemsError = ErrorObject<"additionalItems", {limit: numbe...
method code (line 24) | code(cxt: KeywordCxt) {
function validateAdditionalItems (line 35) | function validateAdditionalItems(cxt: KeywordCxt, items: AnySchema[]): v...
FILE: lib/vocabularies/applicator/additionalProperties.ts
type AdditionalPropertiesError (line 14) | type AdditionalPropertiesError = ErrorObject<
method code (line 32) | code(cxt) {
FILE: lib/vocabularies/applicator/allOf.ts
method code (line 8) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/applicator/anyOf.ts
type AnyOfError (line 4) | type AnyOfError = ErrorNoParams<"anyOf", AnySchema[]>
FILE: lib/vocabularies/applicator/contains.ts
type ContainsError (line 11) | type ContainsError = ErrorObject<
method code (line 33) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/applicator/dependencies.ts
type PropertyDependencies (line 13) | type PropertyDependencies = {[K in string]?: string[]}
type DependenciesErrorParams (line 15) | interface DependenciesErrorParams {
type SchemaDependencies (line 22) | type SchemaDependencies = SchemaMap
type DependenciesError (line 24) | type DependenciesError = ErrorObject<
method code (line 47) | code(cxt: KeywordCxt) {
function splitDependencies (line 54) | function splitDependencies({schema}: KeywordCxt): [PropertyDependencies,...
function validatePropertyDeps (line 65) | function validatePropertyDeps(
function validateSchemaDeps (line 95) | function validateSchemaDeps(cxt: KeywordCxt, schemaDeps: SchemaMap = cxt...
FILE: lib/vocabularies/applicator/if.ts
type IfKeywordError (line 12) | type IfKeywordError = ErrorObject<"if", {failingKeyword: string}, AnySch...
method code (line 24) | code(cxt: KeywordCxt) {
function hasSchema (line 75) | function hasSchema(it: SchemaObjCxt, keyword: string): boolean {
FILE: lib/vocabularies/applicator/index.ts
function getApplicator (line 19) | function getApplicator(draft2020 = false): Vocabulary {
type ApplicatorKeywordError (line 42) | type ApplicatorKeywordError =
FILE: lib/vocabularies/applicator/items.ts
method code (line 12) | code(cxt: KeywordCxt) {
function validateTuple (line 21) | function validateTuple(
FILE: lib/vocabularies/applicator/items2020.ts
type ItemsError (line 13) | type ItemsError = ErrorObject<"items", {limit: number}, AnySchema>
method code (line 26) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/applicator/not.ts
type NotKeywordError (line 5) | type NotKeywordError = ErrorNoParams<"not", AnySchema>
method code (line 11) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/applicator/oneOf.ts
type OneOfError (line 12) | type OneOfError = ErrorObject<
method code (line 28) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/applicator/patternProperties.ts
method code (line 13) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/applicator/properties.ts
method code (line 11) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/applicator/propertyNames.ts
type PropertyNamesError (line 11) | type PropertyNamesError = ErrorObject<"propertyNames", {propertyName: st...
method code (line 23) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/applicator/thenElse.ts
method code (line 8) | code({keyword, parentSchema, it}: KeywordCxt) {
FILE: lib/vocabularies/code.ts
function checkReportMissingProp (line 8) | function checkReportMissingProp(cxt: KeywordCxt, prop: string): void {
function checkMissingProp (line 16) | function checkMissingProp(
function reportMissingProp (line 28) | function reportMissingProp(cxt: KeywordCxt, missing: Name): void {
function hasPropFunc (line 33) | function hasPropFunc(gen: CodeGen): Name {
function isOwnProperty (line 41) | function isOwnProperty(gen: CodeGen, data: Name, property: Name | string...
function propertyInData (line 45) | function propertyInData(
function noPropertyInData (line 55) | function noPropertyInData(
function allSchemaProperties (line 65) | function allSchemaProperties(schemaMap?: SchemaMap): string[] {
function schemaProperties (line 69) | function schemaProperties(it: SchemaCxt, schemaMap: SchemaMap): string[] {
function callValidateCode (line 75) | function callValidateCode(
function usePattern (line 95) | function usePattern({gen, it: {opts}}: KeywordCxt, pattern: string): Name {
function validateArray (line 107) | function validateArray(cxt: KeywordCxt): Name {
function validateUnion (line 135) | function validateUnion(cxt: KeywordCxt): void {
FILE: lib/vocabularies/core/id.ts
method code (line 5) | code() {
FILE: lib/vocabularies/core/ref.ts
method code (line 13) | code(cxt: KeywordCxt): void {
function getValidate (line 56) | function getValidate(cxt: KeywordCxt, sch: SchemaEnv): Code {
function callRef (line 63) | function callRef(cxt: KeywordCxt, v: Code, sch?: SchemaEnv, $async?: boo...
FILE: lib/vocabularies/discriminator/index.ts
type DiscriminatorError (line 9) | type DiscriminatorError = DiscrErrorObj<DiscrError.Tag> | DiscrErrorObj<...
method code (line 25) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/discriminator/types.ts
type DiscrError (line 3) | enum DiscrError {
type DiscrErrorObj (line 8) | type DiscrErrorObj<E extends DiscrError> = ErrorObject<
FILE: lib/vocabularies/dynamic/dynamicAnchor.ts
function dynamicAnchor (line 14) | function dynamicAnchor(cxt: KeywordCxt, anchor: string): void {
function _getValidate (line 22) | function _getValidate(cxt: KeywordCxt): Code {
FILE: lib/vocabularies/dynamic/dynamicRef.ts
function dynamicRef (line 13) | function dynamicRef(cxt: KeywordCxt, ref: string): void {
FILE: lib/vocabularies/dynamic/recursiveAnchor.ts
method code (line 8) | code(cxt) {
FILE: lib/vocabularies/errors.ts
type DefinedError (line 10) | type DefinedError =
FILE: lib/vocabularies/format/format.ts
type FormatValidate (line 12) | type FormatValidate =
type FormatError (line 21) | type FormatError = ErrorObject<"format", {format: string}, string | {$da...
method code (line 34) | code(cxt: KeywordCxt, ruleType?: string) {
FILE: lib/vocabularies/jtd/discriminator.ts
type JTDDiscriminatorError (line 9) | type JTDDiscriminatorError =
method code (line 36) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/jtd/elements.ts
type JTDElementsError (line 10) | type JTDElementsError = _JTDTypeError<"elements", "array", SchemaObject>
method code (line 16) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/jtd/enum.ts
type JTDEnumError (line 7) | type JTDEnumError = ErrorObject<"enum", {allowedValues: string[]}, strin...
method code (line 18) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/jtd/error.ts
type _JTDTypeError (line 4) | type _JTDTypeError<K extends string, T extends string, S> = ErrorObject<
function typeError (line 10) | function typeError(t: string): KeywordErrorDefinition {
function typeErrorMessage (line 17) | function typeErrorMessage({parentSchema}: KeywordErrorCxt, t: string): s...
function typeErrorParams (line 21) | function typeErrorParams({parentSchema}: KeywordErrorCxt, t: string): Co...
FILE: lib/vocabularies/jtd/index.ts
type JTDErrorObject (line 31) | type JTDErrorObject =
FILE: lib/vocabularies/jtd/metadata.ts
method code (line 8) | code(cxt: KeywordCxt) {
function checkMetadata (line 18) | function checkMetadata({it, keyword}: KeywordCxt, metadata?: boolean): v...
FILE: lib/vocabularies/jtd/nullable.ts
function checkNullable (line 4) | function checkNullable(
function checkNullableObject (line 18) | function checkNullableObject(cxt: KeywordCxt, cond: Code): [Name, Code] {
FILE: lib/vocabularies/jtd/optionalProperties.ts
method code (line 9) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/jtd/properties.ts
type PropError (line 15) | enum PropError {
type PropKeyword (line 20) | type PropKeyword = "properties" | "optionalProperties"
type PropSchema (line 22) | type PropSchema = {[P in string]?: SchemaObject}
type JTDPropertiesError (line 24) | type JTDPropertiesError =
function validateProperties (line 60) | function validateProperties(cxt: KeywordCxt): void {
FILE: lib/vocabularies/jtd/ref.ts
method code (line 13) | code(cxt: KeywordCxt) {
function hasRef (line 68) | function hasRef(schema: AnySchemaObject): boolean {
FILE: lib/vocabularies/jtd/type.ts
type JTDTypeError (line 9) | type JTDTypeError = _JTDTypeError<"type", JTDType, JTDType>
type IntType (line 11) | type IntType = "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32"
type JTDType (line 22) | type JTDType = "boolean" | "string" | "timestamp" | "float32" | "float64...
function timestampCode (line 29) | function timestampCode(cxt: KeywordCxt): Code {
method code (line 43) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/jtd/values.ts
type JTDValuesError (line 9) | type JTDValuesError = _JTDTypeError<"values", "object", SchemaObject>
method code (line 15) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/unevaluated/unevaluatedItems.ts
type UnevaluatedItemsError (line 11) | type UnevaluatedItemsError = ErrorObject<"unevaluatedItems", {limit: num...
method code (line 23) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/unevaluated/unevaluatedProperties.ts
type UnevaluatedPropertiesError (line 11) | type UnevaluatedPropertiesError = ErrorObject<
method code (line 28) | code(cxt) {
FILE: lib/vocabularies/validation/const.ts
type ConstError (line 7) | type ConstError = ErrorObject<"const", {allowedValue: any}>
method code (line 18) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/dependentRequired.ts
type DependentRequiredError (line 9) | type DependentRequiredError = ErrorObject<
FILE: lib/vocabularies/validation/enum.ts
type EnumError (line 7) | type EnumError = ErrorObject<"enum", {allowedValues: any[]}, any[] | {$d...
method code (line 19) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/index.ts
type LimitError (line 35) | type LimitError = ErrorObject<
type ValidationKeywordError (line 41) | type ValidationKeywordError =
FILE: lib/vocabularies/validation/limitContains.ts
method code (line 9) | code({keyword, parentSchema, it}: KeywordCxt) {
FILE: lib/vocabularies/validation/limitItems.ts
method message (line 6) | message({keyword, schemaCode}) {
method code (line 19) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/limitLength.ts
method message (line 8) | message({keyword, schemaCode}) {
method code (line 21) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/limitNumber.ts
type Kwd (line 7) | type Kwd = "maximum" | "minimum" | "exclusiveMaximum" | "exclusiveMinimum"
type Comparison (line 9) | type Comparison = "<=" | ">=" | "<" | ">"
type LimitNumberError (line 18) | type LimitNumberError = ErrorObject<
method code (line 36) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/limitProperties.ts
method message (line 6) | message({keyword, schemaCode}) {
method code (line 19) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/multipleOf.ts
type MultipleOfError (line 5) | type MultipleOfError = ErrorObject<
method code (line 22) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/pattern.ts
type PatternError (line 7) | type PatternError = ErrorObject<"pattern", {pattern: string}, string | {...
method code (line 20) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/required.ts
type RequiredError (line 13) | type RequiredError = ErrorObject<
method code (line 30) | code(cxt: KeywordCxt) {
FILE: lib/vocabularies/validation/uniqueItems.ts
type UniqueItemsError (line 8) | type UniqueItemsError = ErrorObject<
method code (line 26) | code(cxt: KeywordCxt) {
FILE: rollup.config.js
function createBundleConfig (line 7) | function createBundleConfig(sourceFile, outFile, globalName) {
FILE: scripts/bundle.js
function saveAndMinify (line 18) | async function saveAndMinify(err, buf) {
FILE: scripts/get-contributors.js
constant SIZE (line 12) | const SIZE = 64
function main (line 16) | async function main() {
FILE: spec/after_test.ts
type TestResult (line 6) | interface TestResult {
function afterError (line 16) | function afterError(res: TestResult): void {
function afterEach (line 20) | function afterEach(res: TestResult): void {
FILE: spec/ajv.spec.ts
function badEvenCode (line 66) | function badEvenCode(cxt: KeywordCxt) {
function testFormat (line 446) | function testFormat() {
function passValidationThrowCompile (line 587) | function passValidationThrowCompile(schema: SchemaObject) {
FILE: spec/ajv_all_instances.ts
function getAjvAllInstances (line 7) | function getAjvAllInstances(options: Options, extraOpts: Options = {}): ...
FILE: spec/ajv_async_instances.ts
function getAjvSyncInstances (line 6) | function getAjvSyncInstances(extraOpts?: Options): AjvCore[] {
FILE: spec/ajv_instances.ts
function getAjvInstances (line 4) | function getAjvInstances(
FILE: spec/ajv_standalone.ts
function withStandalone (line 5) | function withStandalone(instances: AjvCore[]): (AjvCore | AjvPack)[] {
function makeStandalone (line 9) | function makeStandalone(ajv: AjvCore): AjvPack {
function getStandalone (line 14) | function getStandalone(_Ajv: typeof AjvCore, opts: Options = {}): AjvPack {
FILE: spec/async.spec.ts
function test (line 204) | function test(schema, expectedLoadCallCount) {
function spec (line 243) | function spec(validate) {
function spec (line 268) | function spec(validate) {
function badLoadSchema (line 331) | function badLoadSchema() {
function badCompile (line 341) | function badCompile(/* schema */) {
function shouldReject (line 346) | function shouldReject(p: Promise<AnyValidateFunction>, rx: RegExp) {
function loadSchema (line 376) | function loadSchema(uri: string): Promise<SchemaObject> {
FILE: spec/async_schemas.spec.ts
function addAsyncFormatsAndKeywords (line 26) | function addAsyncFormatsAndKeywords(ajv: Ajv) {
function checkWordOnServer (line 58) | function checkWordOnServer(str: string): Promise<boolean> {
function checkIdExists (line 66) | function checkIdExists(schema: {table: string}, data: number): Promise<b...
function checkIdExistsWithError (line 81) | function checkIdExistsWithError(schema: {table: string}, data: number): ...
function compileCheckIdExists (line 103) | function compileCheckIdExists(schema: {table: string}): (data: number) =...
FILE: spec/async_validate.spec.ts
function test (line 27) | function test(_ajv) {
function checkIdExists (line 147) | function checkIdExists(schema, data) {
function checkIdExistsWithError (line 162) | function checkIdExistsWithError(schema, data) {
function recursiveTest (line 355) | function recursiveTest(schema, refSchema?) {
function addFormatEnglishWord (line 383) | function addFormatEnglishWord() {
function checkWordOnServer (line 393) | function checkWordOnServer(str) {
function shouldBeValid (line 401) | function shouldBeValid(p, data) {
constant SHOULD_BE_INVALID (line 405) | const SHOULD_BE_INVALID = "test: should be invalid"
function shouldBeInvalid (line 406) | function shouldBeInvalid(p, expectedMessages?: string[]) {
function shouldThrow (line 418) | function shouldThrow(p, exception) {
function checkNotValid (line 422) | function checkNotValid(p) {
function repeat (line 434) | function repeat(func) {
FILE: spec/boolean.spec.ts
function test (line 31) | function test(boolSchema, valid) {
function test (line 52) | function test(boolSchema, valid) {
function test (line 94) | function test(boolSchema, valid) {
function test (line 151) | function test(boolSchema, valid) {
function test (line 193) | function test(boolSchema, valid) {
function test (line 235) | function test(boolSchema, valid) {
function test (line 264) | function test(boolSchema, valid) {
function test (line 298) | function test(boolSchema, valid) {
function test (line 323) | function test(boolSchema, valid) {
function test (line 355) | function test(boolSchema, valid) {
function test (line 387) | function test(boolSchema, valid) {
function test (line 419) | function test(boolSchema, valid) {
function testSchema (line 434) | function testSchema(validate, valid) {
FILE: spec/chai_type.ts
type ChaiStatic (line 2) | type ChaiStatic = Chai.ChaiStatic
FILE: spec/codegen.spec.ts
function log (line 264) | function log(comparison: string): void {
function assertEqual (line 497) | function assertEqual(code: Code | CodeGen, s: string): void {
function getGen (line 501) | function getGen(opts?: CodeGenOptions): CodeGen {
FILE: spec/coercion.spec.ts
function testCoercion (line 238) | function testCoercion(_ajv, _schema, fromData, toData) {
function testCoercion (line 411) | function testCoercion(_schema, fromData, toData) {
function testRules (line 471) | function testRules(rules, cb) {
FILE: spec/discriminator.spec.ts
function getAjvs (line 21) | function getAjvs(AjvClass: typeof AjvCore) {
method loadSchema (line 210) | loadSchema(url) {
function assertValid (line 376) | function assertValid(schemas: SchemaObject[], data: unknown): void {
function assertInvalid (line 382) | function assertInvalid(schemas: SchemaObject[], data: unknown): void {
function invalidSchema (line 388) | function invalidSchema(schema: SchemaObject, error: any): void {
FILE: spec/dynamic-ref.spec.ts
function testTree (line 75) | function testTree(treeSchema: SchemaObject, strictTreeSchema: SchemaObje...
FILE: spec/errors.spec.ts
function createInstances (line 14) | function createInstances() {
function testAdditional (line 59) | function testAdditional() {
function testAdditionalIsSchema (line 126) | function testAdditionalIsSchema() {
function testRequired (line 176) | function testRequired() {
function testRequiredLargeSchema (line 188) | function testRequiredLargeSchema() {
function testRequiredAndProperties (line 251) | function testRequiredAndProperties() {
function testRequiredInAnyOf (line 268) | function testRequiredInAnyOf() {
function test (line 316) | function test(_ajv: Ajv) {
function test (line 356) | function test(_ajv: Ajv): void {
function testDependencies (line 385) | function testDependencies() {
function _testRequired (line 467) | function _testRequired(schema, schemaPathPrefix = "#", extraErrors = 0) {
function requiredMsg (line 511) | function requiredMsg(prop: string) {
function test (line 580) | function test(_ajv) {
function test (line 617) | function test(_ajv: Ajv, numErrors: number) {
function test (line 664) | function test(_ajv) {
function test (line 682) | function test(_ajv) {
function test (line 713) | function test(_ajv) {
function test (line 733) | function test(_ajv, numErrors?: number) {
function test (line 757) | function test(_ajv, numErrors?: number) {
function test (line 781) | function test(_ajv: Ajv, numErrors?: number) {
function testError (line 825) | function testError(keyword, message, params) {
function testError (line 863) | function testError() {
function prepareTest (line 938) | function prepareTest(_ajv: Ajv, schema) {
function testIfError (line 943) | function testIfError(ifClause, multipleOf) {
function testTypeError (line 990) | function testTypeError(i, instancePath) {
function testSchema1 (line 998) | function testSchema1(schema, schemaPathPrefix = "#/properties/foo") {
function _testSchema1 (line 1004) | function _testSchema1(_ajv, schema, schemaPathPrefix) {
function shouldBeValid (line 1021) | function shouldBeValid(validate, data) {
function shouldBeInvalid (line 1026) | function shouldBeInvalid(validate, data, numErrors = 1) {
function shouldBeError (line 1031) | function shouldBeError(
FILE: spec/issues/1501_jtd_many_properties.spec.ts
constant PROP_COUNT (line 5) | const PROP_COUNT = 10
FILE: spec/issues/1539_add_keyword_name_to_validation_error.spec.ts
method macro (line 14) | macro() {
FILE: spec/issues/181_allErrors_custom_keyword_skipped.spec.ts
function testKeywordErrors (line 39) | function testKeywordErrors(def: KeywordDefinition): void {
FILE: spec/issues/182_nan_validation.spec.ts
function testNaN (line 37) | function testNaN(_ajv, schema, NaNisValid) {
FILE: spec/issues/210_mutual_recur_frags.spec.ts
function spec (line 13) | function spec(ajv: AjvCore | AjvPack): () => void {
function spec (line 49) | function spec(ajv: AjvCore | AjvPack): () => void {
FILE: spec/issues/240_mutual_recur_frags_common_ref.spec.ts
function spec (line 49) | function spec(ajv: AjvCore | AjvPack): () => void {
function spec (line 154) | function spec(ajv: AjvCore | AjvPack): () => void {
function testSchema (line 233) | function testSchema(validate) {
FILE: spec/issues/273_error_schemaPath_refd_schema.spec.ts
function test (line 10) | function test(ajv) {
FILE: spec/issues/485_type_validation_priority.spec.ts
function checkErrors (line 23) | function checkErrors(expectedErrs) {
FILE: spec/issues/50_refs_with_definitions.spec.ts
function spec (line 57) | function spec(ajv: AjvCore | AjvPack): void {
FILE: spec/issues/768_passContext_recursive_ref.spec.ts
function getValidate (line 50) | function getValidate(passContext) {
function getValidateFragments (line 69) | function getValidateFragments(passContext) {
function storeContext (line 100) | function storeContext(this: any) {
FILE: spec/issues/8_shared_refs.spec.ts
function spec (line 43) | function spec(ajv: AjvCore | AjvPack): void {
FILE: spec/javacript.spec.js
function test (line 9) | function test(_Ajv) {
FILE: spec/json-schema.spec.ts
constant SKIP_FORMATS (line 26) | const SKIP_FORMATS = ["idn-email", "idn-hostname", "iri", "iri-reference"]
constant SKIP_FORMAT_TESTS (line 27) | const SKIP_FORMAT_TESTS = SKIP_FORMATS.map((f) => `optional/format/${f}`)
constant SKIP_DRAFT7 (line 28) | const SKIP_DRAFT7 = [
type TestSuite (line 203) | interface TestSuite {
type SchemaTest (line 208) | interface SchemaTest {
function runTest (line 216) | function runTest({instances, draft, tests, skip = [], remotes = {}}: Sch...
type SkippedTestCases (line 242) | interface SkippedTestCases {
function skipTestCases (line 248) | function skipTestCases(suites: TestSuite[], skipCases: SkippedTestCases)...
FILE: spec/jtd-schema.spec.ts
type TestCase (line 13) | interface TestCase {
type TestCaseError (line 19) | interface TestCaseError {
type JSONParseTest (line 24) | interface JSONParseTest {
type JSONParseTestSuite (line 33) | interface JSONParseTestSuite {
type JTDError (line 38) | interface JTDError {
constant ONLY (line 55) | const ONLY: RegExp[] = []
function cleanErrors (line 88) | function cleanErrors(errors?: JTDError[] | null): JTDError[] | null | un...
function convertErrors (line 95) | function convertErrors(errors: TestCaseError[]): JTDError[] | null | und...
function sortErrors (line 104) | function sortErrors(errors?: JTDError[] | null): JTDError[] | null | und...
function jsonPointer (line 115) | function jsonPointer(error: string[]): string {
type TestFunc (line 258) | type TestFunc = typeof it | typeof it.only | typeof it.skip
function _it (line 260) | function _it({only, skip}: JSONParseTest): TestFunc {
function shouldParse (line 264) | function shouldParse(parse: JTDParser, str: string, res: unknown): void {
function shouldFail (line 270) | function shouldFail(parse: JTDParser, str: string): void {
function describeOnly (line 276) | function describeOnly(name: string, func: () => void) {
FILE: spec/jtd-timestamps.spec.ts
function testTimestamp (line 33) | function testTimestamp(
FILE: spec/keyword.spec.ts
function validateEven (line 32) | function validateEven(schema, data) {
function validateEven (line 50) | function validateEven(schema, data) {
function validateRange (line 62) | function validateRange(schema, data, parentSchema) {
function validateRange (line 87) | function validateRange(schema, data, parentSchema) {
function _validateRange (line 98) | function _validateRange(schema, data, parentSchema) {
function compileEven (line 156) | function compileEven(schema) {
function isEven (line 163) | function isEven(data) {
function isOdd (line 166) | function isOdd(data) {
function compileEven (line 183) | function compileEven(schema) {
function isEven (line 187) | function isEven(data) {
function isOdd (line 190) | function isOdd(data) {
function compileEven (line 226) | function compileEven(schema) {
function compileConstant (line 233) | function compileConstant(schema) {
function compileRange (line 244) | function compileRange(schema, parentSchema) {
method macro (line 281) | macro(schema, _parentSchema, it) {
function macroDeepProperties (line 411) | function macroDeepProperties(_schema) {
function macroContains (line 522) | function macroContains(_schema) {
function macroInvalid (line 536) | function macroInvalid(/* schema */) {
function macroEven (line 541) | function macroEven(schema) {
function macroConstant (line 547) | function macroConstant(schema /*, parentSchema */) {
function macroRange (line 551) | function macroRange(schema, parentSchema) {
method code (line 566) | code(cxt) {
method code (line 578) | code(cxt) {
method code (line 594) | code(cxt) {
function validateEven (line 641) | function validateEven(schema, data) {
function validateEven (line 658) | function validateEven(schema, data) {
function compileEven (line 663) | function compileEven(schema) {
function isEven (line 671) | function isEven(data) {
function isOdd (line 674) | function isOdd(data) {
function validateEven (line 695) | function validateEven(schema, data) {
function compileEven (line 699) | function compileEven(schema) {
function isEven (line 704) | function isEven(data) {
function isOdd (line 707) | function isOdd(data) {
function validateEven (line 726) | function validateEven(schema, data) {
function macroEven (line 731) | function macroEven(schema) {
function validateEven (line 758) | function validateEven(schema, data) {
function macroEven (line 762) | function macroEven(schema): SchemaObject | void {
method code (line 774) | code(cxt) {
method code (line 787) | code(cxt) {
function validateEven (line 822) | function validateEven(schema, data) {
function testEvenKeyword (line 828) | function testEvenKeyword(evenDefinition, numErrors = 1) {
function testEvenKeyword$data (line 844) | function testEvenKeyword$data(definition, numErrors = 1) {
function testConstantKeyword (line 888) | function testConstantKeyword(definition, numErrors?: number) {
function testMultipleConstantKeyword (line 901) | function testMultipleConstantKeyword(definition, numErrors?: number) {
function testRangeKeyword (line 929) | function testRangeKeyword(definition, createsErrors?: boolean, numErrors...
function testMultipleRangeKeyword (line 981) | function testMultipleRangeKeyword(definition, numErrors?: number) {
function shouldBeRangeError (line 1008) | function shouldBeRangeError(
function validateRangeSchema (line 1031) | function validateRangeSchema(schema, parentSchema) {
function shouldBeValid (line 1048) | function shouldBeValid(validate, data) {
function shouldBeInvalid (line 1053) | function shouldBeInvalid(validate, data, numErrors = 1) {
function shouldBeInvalidSchema (line 1058) | function shouldBeInvalidSchema(
function testThrow (line 1076) | function testThrow(keywords) {
function testThrowDuplicate (line 1084) | function testThrowDuplicate(keywordPrefix) {
function _addKeyword (line 1163) | function _addKeyword(keyword, dataType) {
function testModifying (line 1286) | function testModifying(withOption) {
FILE: spec/options/comment.spec.ts
function log (line 9) | function log(...args: any[]) {
function test (line 36) | function test(data, valid, expectedLogCalls) {
function hook (line 48) | function hook(...args: any[]) {
function test (line 84) | function test(data, valid, expectedHookCalls) {
FILE: spec/options/meta_validateSchema.spec.ts
function testOptionMeta (line 10) | function testOptionMeta(ajv) {
method log (line 51) | log() {}
FILE: spec/options/nullable.spec.ts
function testNullable (line 66) | function testNullable(schema) {
function testNotNullable (line 73) | function testNotNullable(schema) {
FILE: spec/options/options_code.spec.ts
function test (line 12) | function test(ajv) {
function test (line 24) | function test(ajv: Ajv) {
function getValidate (line 76) | function getValidate(passContext) {
function storeContext (line 97) | function storeContext(this: any) {
function compileTestValidate (line 102) | function compileTestValidate() {
function test (line 116) | function test(ajv, schema) {
FILE: spec/options/options_refs.spec.ts
function test (line 28) | function test(opts: Options, shouldExtendRef: boolean) {
function testWarning (line 67) | function testWarning(opts: Options = {}, msgPattern?: RegExp) {
FILE: spec/options/options_reporting.spec.ts
function testVerbose (line 11) | function testVerbose(ajv) {
function test (line 38) | function test(ajv, allErrors) {
function log (line 125) | function log() {
FILE: spec/options/options_validation.spec.ts
constant DATE_FORMAT (line 6) | const DATE_FORMAT = /^\d\d\d\d-[0-1]\d-[0-3]\d$/
function testKeyword (line 80) | function testKeyword(ajv: Ajv) {
function testUnicode (line 99) | function testUnicode(ajv: Ajv) {
function test (line 120) | function test(ajv) {
FILE: spec/options/ownProperties.spec.ts
function test (line 166) | function test(schema, obj, proto, errors = 1, reverse?: boolean) {
FILE: spec/options/schemaId.spec.ts
function test (line 11) | function test(ajv) {
function test (line 27) | function test(ajv: Ajv) {
FILE: spec/options/strict.spec.ts
type MyTuple (line 186) | type MyTuple = [string, number]
function testStrictMode (line 387) | function testStrictMode(schema, logPattern) {
function getLogger (line 428) | function getLogger(output) {
FILE: spec/options/strictDefaults.spec.ts
function test (line 54) | function test(ajv) {
function test (line 68) | function test(ajv) {
function test (line 139) | function test(ajv) {
function test (line 157) | function test(ajv) {
function getLogger (line 178) | function getLogger(output) {
FILE: spec/options/strictKeywords.spec.ts
function test (line 28) | function test(ajv) {
function test (line 61) | function test(ajv) {
function getLogger (line 70) | function getLogger(output) {
FILE: spec/options/strictNumbers.spec.ts
function testStrict (line 10) | function testStrict(ajv) {
function testNotStrict (line 32) | function testNotStrict(_ajv) {
FILE: spec/options/unknownFormats.spec.ts
constant DATE_FORMAT (line 5) | const DATE_FORMAT = /^\d\d\d\d-[0-1]\d-[0-3]\d$/
function test (line 12) | function test(ajv) {
function test (line 22) | function test(ajv) {
function test (line 46) | function test(ajv) {
function test (line 55) | function test(ajv) {
function test (line 77) | function test(ajv) {
function test (line 90) | function test(ajv) {
FILE: spec/options/useDefaults.spec.ts
function test (line 19) | function test(ajv) {
function test (line 64) | function test(ajv) {
function test (line 97) | function test(ajv) {
function test (line 131) | function test(ajv) {
function test (line 196) | function test(ajv) {
FILE: spec/resolve.spec.ts
function testMissingSchemaError (line 266) | function testMissingSchemaError(opts) {
function testSchemas (line 379) | function testSchemas(ajv, expectedInlined) {
function testObjSchema (line 391) | function testObjSchema(validate) {
function testListSchema (line 397) | function testListSchema(validate) {
function testInlined (line 403) | function testInlined(validate: AnyValidateFunction, expectedInlined) {
FILE: spec/schema-tests.spec.ts
function addRemoteRefsAndFormats (line 42) | function addRemoteRefsAndFormats(ajv: AjvCore) {
FILE: spec/standalone.spec.ts
function testExportTypeEsm (line 10) | function testExportTypeEsm(moduleCode: string, singleExport: boolean) {
function testExportTypeCjs (line 19) | function testExportTypeCjs(moduleCode: string, singleExport: boolean) {
function testExports (line 134) | function testExports(m: {[n: string]: AnyValidateFunction<unknown>}) {
function assertNoDuplicateFunctions (line 262) | function assertNoDuplicateFunctions(code: string): void {
function testExports (line 269) | function testExports(validate: {[n: string]: AnyValidateFunction<unknown...
function testExport (line 296) | function testExport(validate: AnyValidateFunction<unknown>) {
function testExport (line 316) | function testExport(validate: AnyValidateFunction<unknown>) {
FILE: spec/types/async-validate.spec.ts
type Foo (line 6) | interface Foo {
FILE: spec/types/json-schema.spec.ts
type MyData (line 7) | interface MyData {
type MyUnionData (line 100) | type MyUnionData = {a: boolean} | string | number
type MyEnumRecord (line 148) | type MyEnumRecord = Record<"a" | "b" | "c" | "d", number | undefined>
FILE: spec/types/jtd-schema.spec.ts
type TypeEquality (line 8) | type TypeEquality<T, E> = [T] extends [E] ? ([E] extends [T] ? true : fa...
type A (line 10) | interface A {
type B (line 15) | interface B {
type C (line 20) | interface C {
type MyData (line 24) | type MyData = A | B
type Missing (line 26) | type Missing = A | C
type LinkedList (line 28) | interface LinkedList {
type Mult (line 267) | type Mult = JTDSchemaType<(A & {typ: "alpha"}) | (B & {typ: "beta"})>
Condensed preview — 433 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,183K chars).
[
{
"path": ".eslintrc.js",
"chars": 947,
"preview": "const jsConfig = require(\"@ajv-validator/config/.eslintrc_js\")\nconst tsConfig = require(\"@ajv-validator/config/.eslintrc"
},
{
"path": ".github/CODEOWNERS",
"chars": 13,
"preview": "@epoberezkin\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 63,
"preview": "github: epoberezkin\ntidelift: \"npm/ajv\"\nopen_collective: \"ajv\"\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug-or-error-report.md",
"chars": 1428,
"preview": "---\nname: Bug or error report\nabout: Please use for issues related to incorrect validation behaviour\ntitle: \"\"\nlabels: \""
},
{
"path": ".github/ISSUE_TEMPLATE/change.md",
"chars": 596,
"preview": "---\nname: Feature or change proposal\nabout: For proposals of new features, options or some other improvements\ntitle: \"\"\n"
},
{
"path": ".github/ISSUE_TEMPLATE/compatibility.md",
"chars": 870,
"preview": "---\nname: Browser and compatibility issue\nabout: For issues that only happen in a specific environment\ntitle: \"\"\nlabels:"
},
{
"path": ".github/ISSUE_TEMPLATE/installation.md",
"chars": 883,
"preview": "---\nname: Installation and dependency issue\nabout: For issues that happen during installation\ntitle: \"\"\nlabels: \"install"
},
{
"path": ".github/ISSUE_TEMPLATE/typescript.md",
"chars": 755,
"preview": "---\nname: Missing or incorrect type definition\nabout: Please use for issues related to typescript types\ntitle: \"\"\nlabels"
},
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 1580,
"preview": "<!--\nFrequently Asked Questions: https://ajv.js.org/faq.html\nPlease provide all info and reduce your schema and data to "
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 535,
"preview": "<!--\nThank you for submitting a pull request to Ajv.\n\nBefore continuing, please read the guidelines:\nhttps://github.com/"
},
{
"path": ".github/config.yml",
"chars": 1283,
"preview": "# Please supply comments to be used for GitHub labels \ngithubLabels:\n bug: >\n Bug confirmed - to be fixed. PR is wel"
},
{
"path": ".github/dependabot.yml",
"chars": 428,
"preview": "version: 2\nupdates:\n- package-ecosystem: npm\n directory: \"/\"\n schedule:\n interval: daily\n open-pull-requests-limit"
},
{
"path": ".github/workflows/build.yml",
"chars": 979,
"preview": "name: build\n\non:\n push:\n branches: [master]\n pull_request:\n branches: [\"*\"]\n\njobs:\n build:\n runs-on: ubuntu-"
},
{
"path": ".github/workflows/publish.yml",
"chars": 997,
"preview": "name: publish\n\non:\n release:\n types: [published]\n\njobs:\n publish-npm:\n runs-on: ubuntu-latest\n steps:\n -"
},
{
"path": ".gitignore",
"chars": 822,
"preview": "# Logs\nlogs\n*.log\n\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nl"
},
{
"path": ".gitmodules",
"chars": 271,
"preview": "[submodule \"spec/JSON-Schema-Test-Suite\"]\n\tpath = spec/JSON-Schema-Test-Suite\n\turl = https://github.com/json-schema/JSON"
},
{
"path": ".npmrc",
"chars": 19,
"preview": "package-lock=false\n"
},
{
"path": ".prettierignore",
"chars": 147,
"preview": "spec/JSON-Schema-Test-Suite\nspec/json-typedef-spec\n.browser\ncoverage\ndist\nbundle\n.nyc_output\nspec/_json\ndocs/.vuepress/c"
},
{
"path": ".runkit_example.js",
"chars": 496,
"preview": "const Ajv = require(\"ajv\")\nconst ajv = new Ajv({allErrors: true})\n\nconst schema = {\n type: \"object\",\n properties: {\n "
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 4406,
"preview": "---\npermalink: /code_of_conduct\n---\n\n# Contributor Covenant Code of Conduct\n\n### Our Pledge\n\nWe commit to creating and m"
},
{
"path": "CONTRIBUTING.md",
"chars": 8851,
"preview": "---\npermalink: /contributing\n---\n\n# Contributing guide\n\nThank you for your help making Ajv better! Every contribution is"
},
{
"path": "LICENSE",
"chars": 1090,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015-2021 Evgeny Poberezkin\n\nPermission is hereby granted, free of charge, to any p"
},
{
"path": "README.md",
"chars": 13781,
"preview": "<img align=\"right\" alt=\"Ajv logo\" width=\"160\" src=\"https://ajv.js.org/img/ajv.svg\">\n\n \n\n# Ajv JSON schema validator"
},
{
"path": "benchmark/jtd.js",
"chars": 2903,
"preview": "/* eslint-disable no-empty */\n/* eslint-disable no-console */\nconst Ajv = require(\"ajv/dist/jtd\")\nconst Benchmark = requ"
},
{
"path": "benchmark/package.json",
"chars": 76,
"preview": "{\n \"private\": true,\n \"devDependencies\": {\n \"benchmark\": \"^2.1.4\"\n }\n}\n"
},
{
"path": "bower.json",
"chars": 360,
"preview": "{\n \"name\": \"ajv\",\n \"description\": \"Another JSON Schema Validator\",\n \"main\": \"bundle/ajv.min.js\",\n \"authors\": [\"Evgen"
},
{
"path": "docs/.vuepress/components/Button.vue",
"chars": 441,
"preview": "<template>\n <a :href=\"link\" :class=\"cssClass\" class=\"button\"><slot /></a>\n</template>\n\n<script>\nexport default {\n prop"
},
{
"path": "docs/.vuepress/components/Column.vue",
"chars": 371,
"preview": "<template>\n <div :class=\"side\" class=\"column\">\n <slot />\n </div>\n</template>\n\n<script>\nexport default {\n props: {\n"
},
{
"path": "docs/.vuepress/components/Columns.vue",
"chars": 182,
"preview": "<template>\n <div class=\"columns\">\n <slot />\n </div>\n</template>\n\n<style lang=\"stylus\" scoped>\n@media only screen an"
},
{
"path": "docs/.vuepress/components/Contributors.vue",
"chars": 878,
"preview": "<template>\n <div>\n <a\n v-for=\"(contributor, i) in contributors\"\n class=\"contributor\"\n :style=\"'backgr"
},
{
"path": "docs/.vuepress/components/Feature.vue",
"chars": 1165,
"preview": "<template>\n <div :class=\"type\">\n <slot />\n <a class=\"read-more\" :href=\"link\">\n <img src=\"./Feature/arrow.svg"
},
{
"path": "docs/.vuepress/components/Features.vue",
"chars": 202,
"preview": "<template>\n <div class=\"features\">\n <slot />\n </div>\n</template>\n\n<style lang=\"stylus\" scoped>\n.features\n padding "
},
{
"path": "docs/.vuepress/components/FooterColumn.vue",
"chars": 888,
"preview": "<template>\n <div :class=\"type\" class=\"column\">\n <slot />\n </div>\n</template>\n\n<script>\nexport default {\n props: {\n"
},
{
"path": "docs/.vuepress/components/FooterColumns.vue",
"chars": 253,
"preview": "<template>\n <div class=\"footer-columns\">\n <slot />\n </div>\n</template>\n\n<style lang=\"stylus\" scoped>\n.footer-column"
},
{
"path": "docs/.vuepress/components/GitHub.vue",
"chars": 705,
"preview": "<template>\n <ClientOnly>\n <span>\n <a\n class=\"github-button\"\n href=\"https://github.com/ajv-validat"
},
{
"path": "docs/.vuepress/components/HeroSection.vue",
"chars": 1656,
"preview": "<template>\n <div class=\"hero-section\">\n <div class=\"section-content\">\n <img src=\"./HeroSection/hero-image.svg\" "
},
{
"path": "docs/.vuepress/components/HomePage.vue",
"chars": 261,
"preview": "<template>\n <main class=\"homepage\">\n <slot name=\"top\" />\n\n <Content />\n\n <slot name=\"bottom\" />\n </main>\n</te"
},
{
"path": "docs/.vuepress/components/HomeSection.vue",
"chars": 1230,
"preview": "<template>\n <div class=\"home-section\" :class=\"section\">\n <div class=\"section-content\">\n <slot />\n </div>\n <"
},
{
"path": "docs/.vuepress/components/NewsHome.vue",
"chars": 1282,
"preview": "<template>\n <div>\n <div v-for=\"(post, i) in posts\" class=\"post\">\n <Columns>\n <Column side=\"left\">\n "
},
{
"path": "docs/.vuepress/components/NewsIndex.vue",
"chars": 677,
"preview": "<template>\n <div>\n <div v-for=\"post in posts\">\n <h2>{{ post.frontmatter.title }}</h2>\n\n <router-link :to=\""
},
{
"path": "docs/.vuepress/components/NewsPost.vue",
"chars": 619,
"preview": "<template>\n <main class=\"page\">\n <slot name=\"top\" />\n\n <div class=\"theme-default-content\" style=\"padding-bottom: "
},
{
"path": "docs/.vuepress/components/NewsPostMeta.vue",
"chars": 579,
"preview": "<template>\n <div class=\"post-meta\">\n <time class=\"pub-date\" pubdate itemprop=\"datePublished\" :datetime=\"date\">\n "
},
{
"path": "docs/.vuepress/components/Projects.vue",
"chars": 772,
"preview": "<template>\n <div class=\"projects\">\n <slot />\n </div>\n</template>\n\n<style lang=\"stylus\" scoped>\n.projects\n p\n ma"
},
{
"path": "docs/.vuepress/components/Sponsors.vue",
"chars": 1126,
"preview": "<template>\n <div class=\"sponsors\" :class=\"level\">\n <slot />\n </div>\n</template>\n\n<script>\nexport default {\n props:"
},
{
"path": "docs/.vuepress/components/Subscribe.vue",
"chars": 1411,
"preview": "<template>\n <form\n action=\"https://ajv.us1.list-manage.com/subscribe/post?u=4343a2a251fa30892c2360003&id=304f51c"
},
{
"path": "docs/.vuepress/components/Testimonial.vue",
"chars": 1062,
"preview": "<template>\n <div class=\"testimonial-content\" :class=\"color\">\n <slot />\n </div>\n</template>\n\n<script>\nexport default"
},
{
"path": "docs/.vuepress/components/Testimonials.vue",
"chars": 208,
"preview": "<template>\n <div class=\"testimonials\">\n <slot />\n </div>\n</template>\n\n<style lang=\"stylus\" scoped>\n.testimonials\n "
},
{
"path": "docs/.vuepress/config.js",
"chars": 5653,
"preview": "const {slugify} = require(\"@vuepress/shared-utils\")\n\nconst title = \"Ajv JSON schema validator\"\nconst description =\n \"Th"
},
{
"path": "docs/.vuepress/styles/index.styl",
"chars": 1428,
"preview": "img + span > .icon.outbound {\n display: none;\n}\n\nbody {\n font-family: 'Raleway';\n font-weight: normal;\n}\n\nstrong {\n "
},
{
"path": "docs/.vuepress/styles/palette.styl",
"chars": 498,
"preview": "$ajvBlueColor = #409cff\n$ajvGreenColor = #23c8d2 // #1fdca3\n$ajvRedColor = #f5775b\n\n$tipColor = $ajvGreenColor\n$warningC"
},
{
"path": "docs/.vuepress/theme/LICENSE",
"chars": 1091,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any"
},
{
"path": "docs/.vuepress/theme/components/AlgoliaSearchBox.vue",
"chars": 4643,
"preview": "<template>\n <form\n id=\"search-form\"\n class=\"algolia-search-wrapper search-box\"\n role=\"search\"\n >\n <input\n "
},
{
"path": "docs/.vuepress/theme/components/DropdownLink.vue",
"chars": 5678,
"preview": "<template>\n <div\n class=\"dropdown-wrapper\"\n :class=\"{ open }\"\n >\n <button\n class=\"dropdown-title\"\n "
},
{
"path": "docs/.vuepress/theme/components/DropdownTransition.vue",
"chars": 561,
"preview": "<template>\n <transition\n name=\"dropdown\"\n @enter=\"setHeight\"\n @after-enter=\"unsetHeight\"\n @before-leave=\"se"
},
{
"path": "docs/.vuepress/theme/components/Home.vue",
"chars": 3573,
"preview": "<template>\n <main\n class=\"home\"\n :aria-labelledby=\"data.heroText !== null ? 'main-title' : null\"\n >\n <header "
},
{
"path": "docs/.vuepress/theme/components/NavLink.vue",
"chars": 1628,
"preview": "<template>\n <RouterLink\n v-if=\"isInternal\"\n class=\"nav-link\"\n :to=\"link\"\n :exact=\"exact\"\n @focusout.nati"
},
{
"path": "docs/.vuepress/theme/components/NavLinks.vue",
"chars": 3614,
"preview": "<template>\n <nav\n v-if=\"userLinks.length || repoLink\"\n class=\"nav-links\"\n >\n <!-- user links -->\n <div\n "
},
{
"path": "docs/.vuepress/theme/components/Navbar.vue",
"chars": 3474,
"preview": "<template>\n <header class=\"navbar\">\n <SidebarButton @toggle-sidebar=\"$emit('toggle-sidebar')\" />\n\n <RouterLink\n "
},
{
"path": "docs/.vuepress/theme/components/Page.vue",
"chars": 535,
"preview": "<template>\n <main class=\"page\">\n <slot name=\"top\" />\n\n <Content class=\"theme-default-content\" />\n <PageEdit />"
},
{
"path": "docs/.vuepress/theme/components/PageEdit.vue",
"chars": 3519,
"preview": "<template>\n <footer class=\"page-edit\">\n <div\n v-if=\"editLink\"\n class=\"edit-link\"\n >\n <a\n :h"
},
{
"path": "docs/.vuepress/theme/components/PageNav.vue",
"chars": 3376,
"preview": "<template>\n <div\n v-if=\"prev || next\"\n class=\"page-nav\"\n >\n <p class=\"inner\">\n <span\n v-if=\"prev\""
},
{
"path": "docs/.vuepress/theme/components/Sidebar.vue",
"chars": 1240,
"preview": "<template>\n <aside class=\"sidebar\">\n <NavLinks />\n\n <slot name=\"top\" />\n\n <SidebarLinks\n :depth=\"0\"\n "
},
{
"path": "docs/.vuepress/theme/components/SidebarButton.vue",
"chars": 990,
"preview": "<template>\n <div\n class=\"sidebar-button\"\n @click=\"$emit('toggle-sidebar')\"\n >\n <svg\n class=\"icon\"\n "
},
{
"path": "docs/.vuepress/theme/components/SidebarGroup.vue",
"chars": 2955,
"preview": "<template>\n <section\n class=\"sidebar-group\"\n :class=\"[\n {\n collapsable,\n 'is-sub-group': depth"
},
{
"path": "docs/.vuepress/theme/components/SidebarLink.vue",
"chars": 3291,
"preview": "<script>\nimport { isActive, hashRE, groupHeaders } from '../util'\n\nexport default {\n functional: true,\n\n props: ['item"
},
{
"path": "docs/.vuepress/theme/components/SidebarLinks.vue",
"chars": 2184,
"preview": "<template>\n <ul\n v-if=\"items.length\"\n class=\"sidebar-links\"\n >\n <li\n v-for=\"(item, i) in items\"\n :k"
},
{
"path": "docs/.vuepress/theme/global-components/Badge.vue",
"chars": 805,
"preview": "<script>\nexport default {\n functional: true,\n props: {\n type: {\n type: String,\n default: 'tip'\n },\n "
},
{
"path": "docs/.vuepress/theme/global-components/CodeBlock.vue",
"chars": 626,
"preview": "<template>\n <div\n class=\"theme-code-block\"\n :class=\"{ 'theme-code-block__active': active }\"\n >\n <slot />\n </"
},
{
"path": "docs/.vuepress/theme/global-components/CodeGroup.vue",
"chars": 2783,
"preview": "<template>\n <ClientOnly>\n <div class=\"theme-code-group\">\n <div class=\"theme-code-group__nav\">\n <ul class"
},
{
"path": "docs/.vuepress/theme/index.js",
"chars": 1599,
"preview": "const path = require(\"path\")\n\n// Theme API.\nmodule.exports = (options, ctx) => {\n const {themeConfig, siteConfig} = ctx"
},
{
"path": "docs/.vuepress/theme/layouts/404.vue",
"chars": 530,
"preview": "<template>\n <div class=\"theme-container\">\n <div class=\"theme-default-content\">\n <h1>404</h1>\n\n <blockquote"
},
{
"path": "docs/.vuepress/theme/layouts/Layout.vue",
"chars": 3672,
"preview": "<template>\n <div\n class=\"theme-container\"\n :class=\"pageClasses\"\n @touchstart=\"onTouchStart\"\n @touchend=\"onT"
},
{
"path": "docs/.vuepress/theme/noopModule.js",
"chars": 18,
"preview": "export default {}\n"
},
{
"path": "docs/.vuepress/theme/styles/arrow.styl",
"chars": 577,
"preview": "@require './config'\n\n.arrow\n display inline-block\n width 0\n height 0\n &.up\n border-left 4px solid transparent\n "
},
{
"path": "docs/.vuepress/theme/styles/code.styl",
"chars": 2861,
"preview": "{$contentClass}\n code\n color lighten($textColor, 20%)\n padding 0.25rem 0.5rem\n margin 0\n font-size 0.85em\n "
},
{
"path": "docs/.vuepress/theme/styles/config.styl",
"chars": 41,
"preview": "$contentClass = '.theme-default-content'\n"
},
{
"path": "docs/.vuepress/theme/styles/custom-blocks.styl",
"chars": 961,
"preview": ".custom-block\n .custom-block-title\n font-weight 600\n margin-bottom -0.4rem\n &.tip, &.warning, &.danger\n paddi"
},
{
"path": "docs/.vuepress/theme/styles/index.styl",
"chars": 3242,
"preview": "@require './config'\n@require './code'\n@require './custom-blocks'\n@require './arrow'\n@require './wrapper'\n@require './toc"
},
{
"path": "docs/.vuepress/theme/styles/mobile.styl",
"chars": 731,
"preview": "@require './config'\n\n$mobileSidebarWidth = $sidebarWidth * 0.82\n\n// narrow desktop / iPad\n@media (max-width: $MQNarrow)\n"
},
{
"path": "docs/.vuepress/theme/styles/toc.styl",
"chars": 54,
"preview": ".table-of-contents\n .badge\n vertical-align middle\n"
},
{
"path": "docs/.vuepress/theme/styles/wrapper.styl",
"chars": 180,
"preview": "$wrapper\n max-width $contentWidth\n margin 0 auto\n padding 2rem 2.5rem\n @media (max-width: $MQNarrow)\n padding 2re"
},
{
"path": "docs/.vuepress/theme/util/index.js",
"chars": 5827,
"preview": "export const hashRE = /#.*$/\nexport const extRE = /\\.(md|html)$/\nexport const endingSlashRE = /\\/$/\nexport const outboun"
},
{
"path": "docs/README.md",
"chars": 7297,
"preview": "---\nhomepage: true\nsidebar: false\n---\n\n<HeroSection>\n\n# Ajv JSON schema validator\n\n## Security and reliability for JavaS"
},
{
"path": "docs/api.md",
"chars": 22328,
"preview": "# API Reference\n\n[[toc]]\n\n## Ajv constructor and methods\n\n### new Ajv(options: object)\n\nCreate Ajv instance:\n\n```javascr"
},
{
"path": "docs/codegen.md",
"chars": 5355,
"preview": "# Code generation design\n\n[[toc]]\n\nStarting from v7 Ajv uses [CodeGen module](https://github.com/ajv-validator/ajv/blob/"
},
{
"path": "docs/coercion.md",
"chars": 5529,
"preview": "# Type coercion rules\n\nTo enable type coercion pass option `coerceTypes` to Ajv with `true` or `array` (it is `false` by"
},
{
"path": "docs/components.md",
"chars": 2531,
"preview": "# Code components\n\n[[toc]]\n\n## Ajv classes\n\n[lib/core.ts](https://github.com/ajv-validator/ajv/blob/master/lib/core.ts) "
},
{
"path": "docs/faq.md",
"chars": 8501,
"preview": "# Frequently Asked Questions\n\nThe purpose of this document is to help find answers quicker. I am happy to continue the d"
},
{
"path": "docs/guide/async-validation.md",
"chars": 2988,
"preview": "# Asynchronous validation\n\nYou can define formats and keywords that perform validation asynchronously by accessing datab"
},
{
"path": "docs/guide/combining-schemas.md",
"chars": 8859,
"preview": "# Combining schemas\n\n[[toc]]\n\n## <a name=\"ref\"></a>Combining schemas with $ref\n\nYou can structure your validation logic "
},
{
"path": "docs/guide/environments.md",
"chars": 5319,
"preview": "# Execution environments\n\n[[toc]]\n\n## Server-side Node.js\n\nThe main consideration for using Ajv server-side is to [manag"
},
{
"path": "docs/guide/formats.md",
"chars": 4447,
"preview": "# Format validation\n\n## String formats\n\nFrom version 7 Ajv does not include formats defined by JSON Schema specification"
},
{
"path": "docs/guide/getting-started.md",
"chars": 5678,
"preview": "# Getting started\n\n[[toc]]\n\n## Install\n\n::: tip Node REPL\nYou can try Ajv without installing it in the Node.js REPL: [ht"
},
{
"path": "docs/guide/managing-schemas.md",
"chars": 9118,
"preview": "# Managing schemas\n\n[[toc]]\n\n## Re-using validation functions\n\nAjv validation model is optimized for server side executi"
},
{
"path": "docs/guide/modifying-data.md",
"chars": 9695,
"preview": "# Modifying data during validation\n\n[[toc]]\n\n## General considerations\n\nAjv has several options that allow to modify dat"
},
{
"path": "docs/guide/schema-language.md",
"chars": 6884,
"preview": "---\ntags:\n - JTD\n---\n\n# Choosing schema language\n\n[[toc]]\n\n## JSON Type Definition\n\nAjv supports the new specification "
},
{
"path": "docs/guide/typescript.md",
"chars": 8373,
"preview": "# Using with TypeScript\n\n[[toc]]\n\n## Additional functionality\n\nAjv takes advantage of TypeScript type system to provide "
},
{
"path": "docs/guide/user-keywords.md",
"chars": 2797,
"preview": "# User-defined keywords\n\nYou can extend keyword available in Ajv by defining your own keywords.\n\nThe advantages of defin"
},
{
"path": "docs/guide/why-ajv.md",
"chars": 2573,
"preview": "# Why use AJV\n\n## Write less code\n\n**Ensure your data is valid as soon as it's received**\n\nInstead of having your data v"
},
{
"path": "docs/json-schema.md",
"chars": 35464,
"preview": "# JSON Schema\n\nIn a simple way, JSON Schema is an object with validation keywords.\n\nThe keywords and their values define"
},
{
"path": "docs/json-type-definition.md",
"chars": 14150,
"preview": "# JSON Type Definition\n\nThis document informally describes JSON Type Definition (JTD) specification to help Ajv users to"
},
{
"path": "docs/keywords.md",
"chars": 10986,
"preview": "# User defined keywords\n\n[[toc]]\n\n## Common attributes of keyword definitions\n\nThe usual interface to define all keyword"
},
{
"path": "docs/news/2020-08-14-mozilla-grant-openjs-foundation.md",
"chars": 1356,
"preview": "---\nnews: true\ntitle: Mozilla MOSS grant and OpenJS Foundation\ndate: 2020-08-14\n---\n\n[<img src=\"/img/mozilla.svg\" width="
},
{
"path": "docs/news/2020-12-15-ajv-version-7-released.md",
"chars": 2066,
"preview": "---\nnews: true\ntitle: Ajv version 7 is released!\ndate: 2020-12-15\n---\n\nAjv version 7 has these new features:\n\n- support "
},
{
"path": "docs/news/2021-03-07-ajv-supports-json-type-definition.md",
"chars": 1084,
"preview": "---\nnews: true\ntitle: Ajv supports JSON Type Definition\ndate: 2021-03-07\n---\n\nJSON Type Definition (JTD) is a new specif"
},
{
"path": "docs/news/2021-03-27-ajv-version-8-released.md",
"chars": 1054,
"preview": "---\nnews: true\ntitle: Ajv version 8 is released!\ndate: 2021-03-27\n---\n\nAjv version 8 has these new features:\n\n- support "
},
{
"path": "docs/news/2021-04-24-ajv-online-event.md",
"chars": 1200,
"preview": "---\nnews: true\ntitle: \"Ajv online event - May 20, 10am PT / 6pm UK\"\ndate: 2021-04-24\nmore: false\n---\n\nWe will talk about"
},
{
"path": "docs/news/2021-05-24-ajv-online-event-video.md",
"chars": 256,
"preview": "---\nnews: true\ntitle: Ajv online event video uploaded\ndate: 2021-05-24\nmore: false\n---\n\nHuge thanks to everybody who joi"
},
{
"path": "docs/news/2021-07-22-ajv-microsoft-foss-fund-award.md",
"chars": 361,
"preview": "---\nnews: true\ntitle: Microsoft FOSS award\ndate: 2021-07-22\nmore: false\n---\n\nAjv was awarded a sponsorship from [Microso"
},
{
"path": "docs/news/README.md",
"chars": 66,
"preview": "---\nnewsIndex: true\neditLink: false\n---\n\n# Ajv News\n\n<NewsIndex/>\n"
},
{
"path": "docs/options.md",
"chars": 18236,
"preview": "# Ajv options\n\n[[toc]]\n\n## Usage\n\nThis page describes properties of the options object that can be passed to Ajv constru"
},
{
"path": "docs/packages/README.md",
"chars": 1658,
"preview": "# Extending Ajv\n\n## Plugins\n\nAjv can be extended with plugins that add [user defined schema keywords](../guide/user-keyw"
},
{
"path": "docs/security.md",
"chars": 7087,
"preview": "# Security considerations\n\nJSON Schema, if properly used, can replace data sanitisation. It doesn't replace other API se"
},
{
"path": "docs/standalone.md",
"chars": 9738,
"preview": "# Standalone validation code\n\n[[toc]]\n\nAjv supports generating standalone validation functions from JSON Schemas at comp"
},
{
"path": "docs/strict-mode.md",
"chars": 11516,
"preview": "# Strict mode\n\nStrict mode intends to prevent any unexpected behaviours or silently ignored mistakes in user schemas. It"
},
{
"path": "docs/testimonials.md",
"chars": 1755,
"preview": "# What users say\n\nIn the past 6 years of working on the JSON Schema Specification itself, Ajv stands out as the implemen"
},
{
"path": "docs/v6-to-v8-migration.md",
"chars": 9131,
"preview": "# Changes from Ajv v6.12.6 to v8.0.0\n\nIf you are migrating from v7 see [v8.0.0 release notes](https://github.com/ajv-val"
},
{
"path": "karma.conf.js",
"chars": 1671,
"preview": "// Karma configuration\n// Generated on Thu Mar 13 2014 14:12:04 GMT-0700 (PDT)\n\nmodule.exports = function (config) {\n c"
},
{
"path": "lib/2019.ts",
"chars": 2502,
"preview": "import type {AnySchemaObject} from \"./types\"\nimport AjvCore, {Options} from \"./core\"\n\nimport draft7Vocabularies from \"./"
},
{
"path": "lib/2020.ts",
"chars": 2217,
"preview": "import type {AnySchemaObject} from \"./types\"\nimport AjvCore, {Options} from \"./core\"\n\nimport draft2020Vocabularies from "
},
{
"path": "lib/ajv.ts",
"chars": 2229,
"preview": "import type {AnySchemaObject} from \"./types\"\nimport AjvCore from \"./core\"\nimport draft7Vocabularies from \"./vocabularies"
},
{
"path": "lib/compile/codegen/code.ts",
"chars": 4474,
"preview": "// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport abstract class _CodeOrName {\n abstract readon"
},
{
"path": "lib/compile/codegen/index.ts",
"chars": 23051,
"preview": "import type {ScopeValueSets, NameValue, ValueScope, ValueScopeName} from \"./scope\"\nimport {_, nil, _Code, Code, Name, Us"
},
{
"path": "lib/compile/codegen/scope.ts",
"chars": 5981,
"preview": "import {_, nil, Code, Name} from \"./code\"\n\ninterface NameGroup {\n prefix: string\n index: number\n}\n\nexport interface Na"
},
{
"path": "lib/compile/errors.ts",
"chars": 5269,
"preview": "import type {KeywordErrorCxt, KeywordErrorDefinition} from \"../types\"\nimport type {SchemaCxt} from \"./index\"\nimport {Cod"
},
{
"path": "lib/compile/index.ts",
"chars": 12299,
"preview": "import type {\n AnySchema,\n AnySchemaObject,\n AnyValidateFunction,\n AsyncValidateFunction,\n EvaluatedProperties,\n E"
},
{
"path": "lib/compile/jtd/parse.ts",
"chars": 12345,
"preview": "import type Ajv from \"../../core\"\nimport type {SchemaObject} from \"../../types\"\nimport {jtdForms, JTDForm, SchemaObjectM"
},
{
"path": "lib/compile/jtd/serialize.ts",
"chars": 8573,
"preview": "import type Ajv from \"../../core\"\nimport type {SchemaObject} from \"../../types\"\nimport {jtdForms, JTDForm, SchemaObjectM"
},
{
"path": "lib/compile/jtd/types.ts",
"chars": 311,
"preview": "import type {SchemaObject} from \"../../types\"\n\nexport type SchemaObjectMap = {[Ref in string]?: SchemaObject}\n\nexport co"
},
{
"path": "lib/compile/names.ts",
"chars": 1116,
"preview": "import {Name} from \"./codegen\"\n\nconst names = {\n // validation function arguments\n data: new Name(\"data\"), // data pas"
},
{
"path": "lib/compile/ref_error.ts",
"chars": 513,
"preview": "import {resolveUrl, normalizeId, getFullPath} from \"./resolve\"\nimport type {UriResolver} from \"../types\"\n\nexport default"
},
{
"path": "lib/compile/resolve.ts",
"chars": 4674,
"preview": "import type {AnySchema, AnySchemaObject, UriResolver} from \"../types\"\nimport type Ajv from \"../ajv\"\nimport type {URIComp"
},
{
"path": "lib/compile/rules.ts",
"chars": 1456,
"preview": "import type {AddedKeywordDefinition} from \"../types\"\n\nconst _jsonTypes = [\"string\", \"number\", \"integer\", \"boolean\", \"nul"
},
{
"path": "lib/compile/util.ts",
"chars": 6639,
"preview": "import type {AnySchema, EvaluatedProperties, EvaluatedItems} from \"../types\"\nimport type {SchemaCxt, SchemaObjCxt} from "
},
{
"path": "lib/compile/validate/applicability.ts",
"chars": 739,
"preview": "import type {AnySchemaObject} from \"../../types\"\nimport type {SchemaObjCxt} from \"..\"\nimport type {JSONType, RuleGroup, "
},
{
"path": "lib/compile/validate/boolSchema.ts",
"chars": 1298,
"preview": "import type {KeywordErrorDefinition, KeywordErrorCxt} from \"../../types\"\nimport type {SchemaCxt} from \"..\"\nimport {repor"
},
{
"path": "lib/compile/validate/dataType.ts",
"chars": 7094,
"preview": "import type {\n KeywordErrorDefinition,\n KeywordErrorCxt,\n ErrorObject,\n AnySchemaObject,\n} from \"../../types\"\nimport"
},
{
"path": "lib/compile/validate/defaults.ts",
"chars": 1215,
"preview": "import type {SchemaObjCxt} from \"..\"\nimport {_, getProperty, stringify} from \"../codegen\"\nimport {checkStrictMode} from "
},
{
"path": "lib/compile/validate/index.ts",
"chars": 19445,
"preview": "import type {\n AddedKeywordDefinition,\n AnySchema,\n AnySchemaObject,\n KeywordErrorCxt,\n KeywordCxtParams,\n} from \"."
},
{
"path": "lib/compile/validate/keyword.ts",
"chars": 5337,
"preview": "import type {KeywordCxt} from \".\"\nimport type {\n AnySchema,\n SchemaValidateFunction,\n AnyValidateFunction,\n AddedKey"
},
{
"path": "lib/compile/validate/subschema.ts",
"chars": 4366,
"preview": "import type {AnySchema} from \"../../types\"\nimport type {SchemaObjCxt} from \"..\"\nimport {_, str, getProperty, Code, Name}"
},
{
"path": "lib/core.ts",
"chars": 30773,
"preview": "export {\n Format,\n FormatDefinition,\n AsyncFormatDefinition,\n KeywordDefinition,\n KeywordErrorDefinition,\n CodeKey"
},
{
"path": "lib/jtd.ts",
"chars": 4172,
"preview": "import type {AnySchemaObject, SchemaObject, JTDParser} from \"./types\"\nimport type {JTDSchemaType, SomeJTDSchemaType, JTD"
},
{
"path": "lib/refs/data.json",
"chars": 409,
"preview": "{\n \"$id\": \"https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#\",\n \"description\": \"Meta-sche"
},
{
"path": "lib/refs/json-schema-2019-09/index.ts",
"chars": 899,
"preview": "import type Ajv from \"../../core\"\nimport type {AnySchemaObject} from \"../../types\"\nimport * as metaSchema from \"./schema"
},
{
"path": "lib/refs/json-schema-2019-09/meta/applicator.json",
"chars": 1566,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\n \"$id\": \"https://json-schema.org/draft/2019-09/meta/appl"
},
{
"path": "lib/refs/json-schema-2019-09/meta/content.json",
"chars": 477,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\n \"$id\": \"https://json-schema.org/draft/2019-09/meta/cont"
},
{
"path": "lib/refs/json-schema-2019-09/meta/core.json",
"chars": 1273,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\n \"$id\": \"https://json-schema.org/draft/2019-09/meta/core"
},
{
"path": "lib/refs/json-schema-2019-09/meta/format.json",
"chars": 375,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\n \"$id\": \"https://json-schema.org/draft/2019-09/meta/form"
},
{
"path": "lib/refs/json-schema-2019-09/meta/meta-data.json",
"chars": 758,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\n \"$id\": \"https://json-schema.org/draft/2019-09/meta/meta"
},
{
"path": "lib/refs/json-schema-2019-09/meta/validation.json",
"chars": 2264,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\n \"$id\": \"https://json-schema.org/draft/2019-09/meta/vali"
},
{
"path": "lib/refs/json-schema-2019-09/schema.json",
"chars": 1579,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\n \"$id\": \"https://json-schema.org/draft/2019-09/schema\",\n"
},
{
"path": "lib/refs/json-schema-2020-12/index.ts",
"chars": 982,
"preview": "import type Ajv from \"../../core\"\nimport type {AnySchemaObject} from \"../../types\"\nimport * as metaSchema from \"./schema"
},
{
"path": "lib/refs/json-schema-2020-12/meta/applicator.json",
"chars": 1441,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://json-schema.org/draft/2020-12/meta/appl"
},
{
"path": "lib/refs/json-schema-2020-12/meta/content.json",
"chars": 479,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://json-schema.org/draft/2020-12/meta/cont"
},
{
"path": "lib/refs/json-schema-2020-12/meta/core.json",
"chars": 1344,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://json-schema.org/draft/2020-12/meta/core"
},
{
"path": "lib/refs/json-schema-2020-12/meta/format-annotation.json",
"chars": 420,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://json-schema.org/draft/2020-12/meta/form"
},
{
"path": "lib/refs/json-schema-2020-12/meta/meta-data.json",
"chars": 758,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://json-schema.org/draft/2020-12/meta/meta"
},
{
"path": "lib/refs/json-schema-2020-12/meta/unevaluated.json",
"chars": 472,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://json-schema.org/draft/2020-12/meta/unev"
},
{
"path": "lib/refs/json-schema-2020-12/meta/validation.json",
"chars": 2264,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://json-schema.org/draft/2020-12/meta/vali"
},
{
"path": "lib/refs/json-schema-2020-12/schema.json",
"chars": 2166,
"preview": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://json-schema.org/draft/2020-12/schema\",\n"
},
{
"path": "lib/refs/json-schema-draft-06.json",
"chars": 3449,
"preview": "{\n \"$schema\": \"http://json-schema.org/draft-06/schema#\",\n \"$id\": \"http://json-schema.org/draft-06/schema#\",\n \"title\":"
},
{
"path": "lib/refs/json-schema-draft-07.json",
"chars": 3811,
"preview": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"http://json-schema.org/draft-07/schema#\",\n \"title\":"
},
{
"path": "lib/refs/json-schema-secure.json",
"chars": 2521,
"preview": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://raw.githubusercontent.com/ajv-validator/ajv/"
},
{
"path": "lib/refs/jtd-schema.ts",
"chars": 2586,
"preview": "import {SchemaObject} from \"../types\"\n\ntype MetaSchema = (root: boolean) => SchemaObject\n\nconst shared: MetaSchema = (ro"
},
{
"path": "lib/runtime/equal.ts",
"chars": 236,
"preview": "// https://github.com/ajv-validator/ajv/issues/889\nimport * as equal from \"fast-deep-equal\"\n\ntype Equal = typeof equal &"
},
{
"path": "lib/runtime/parseJson.ts",
"chars": 4553,
"preview": "const rxParseJson = /position\\s(\\d+)(?: \\(line \\d+ column \\d+\\))?$/\n\nexport function parseJson(s: string, pos: number): "
},
{
"path": "lib/runtime/quote.ts",
"chars": 802,
"preview": "const rxEscapable =\n // eslint-disable-next-line no-control-regex, no-misleading-character-class\n /[\\\\\"\\u0000-\\u001f\\u"
},
{
"path": "lib/runtime/re2.ts",
"chars": 157,
"preview": "import * as re2 from \"re2\"\n\ntype Re2 = typeof re2 & {code: string}\n;(re2 as Re2).code = 'require(\"ajv/dist/runtime/re2\")"
},
{
"path": "lib/runtime/timestamp.ts",
"chars": 1492,
"preview": "const DT_SEPARATOR = /t|\\s/i\nconst DATE = /^(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)$/\nconst TIME = /^(\\d\\d):(\\d\\d):(\\d\\d)(?:\\.\\d+)?(?:z"
},
{
"path": "lib/runtime/ucs2length.ts",
"chars": 629,
"preview": "// https://mathiasbynens.be/notes/javascript-encoding\n// https://github.com/bestiejs/punycode.js - punycode.ucs2.decode\n"
},
{
"path": "lib/runtime/uri.ts",
"chars": 162,
"preview": "import * as uri from \"fast-uri\"\n\ntype URI = typeof uri & {code: string}\n;(uri as URI).code = 'require(\"ajv/dist/runtime/"
},
{
"path": "lib/runtime/validation_error.ts",
"chars": 336,
"preview": "import type {ErrorObject} from \"../types\"\n\nexport default class ValidationError extends Error {\n readonly errors: Parti"
},
{
"path": "lib/standalone/index.ts",
"chars": 4151,
"preview": "import type AjvCore from \"../core\"\nimport type {AnyValidateFunction, SourceCode} from \"../types\"\nimport type {SchemaEnv}"
},
{
"path": "lib/standalone/instance.ts",
"chars": 1272,
"preview": "import Ajv, {AnySchema, AnyValidateFunction, ErrorObject} from \"../core\"\nimport standaloneCode from \".\"\nimport * as requ"
},
{
"path": "lib/types/index.ts",
"chars": 7289,
"preview": "import {URIComponent} from \"fast-uri\"\nimport type {CodeGen, Code, Name, ScopeValueSets, ValueScopeName} from \"../compile"
},
{
"path": "lib/types/json-schema.ts",
"chars": 6380,
"preview": "/* eslint-disable @typescript-eslint/no-empty-interface */\ntype StrictNullChecksWrapper<Name extends string, Type> = und"
},
{
"path": "lib/types/jtd-schema.ts",
"chars": 9321,
"preview": "/** numeric strings */\ntype NumberType = \"float32\" | \"float64\" | \"int8\" | \"uint8\" | \"int16\" | \"uint16\" | \"int32\" | \"uint"
},
{
"path": "lib/vocabularies/applicator/additionalItems.ts",
"chars": 1824,
"preview": "import type {\n CodeKeywordDefinition,\n ErrorObject,\n KeywordErrorDefinition,\n AnySchema,\n} from \"../../types\"\nimport"
},
{
"path": "lib/vocabularies/applicator/additionalProperties.ts",
"chars": 3782,
"preview": "import type {\n CodeKeywordDefinition,\n AddedKeywordDefinition,\n ErrorObject,\n KeywordErrorDefinition,\n AnySchema,\n}"
},
{
"path": "lib/vocabularies/applicator/allOf.ts",
"chars": 717,
"preview": "import type {CodeKeywordDefinition, AnySchema} from \"../../types\"\nimport type {KeywordCxt} from \"../../compile/validate\""
},
{
"path": "lib/vocabularies/applicator/anyOf.ts",
"chars": 380,
"preview": "import type {CodeKeywordDefinition, ErrorNoParams, AnySchema} from \"../../types\"\nimport {validateUnion} from \"../code\"\n\n"
},
{
"path": "lib/vocabularies/applicator/contains.ts",
"chars": 3278,
"preview": "import type {\n CodeKeywordDefinition,\n KeywordErrorDefinition,\n ErrorObject,\n AnySchema,\n} from \"../../types\"\nimport"
},
{
"path": "lib/vocabularies/applicator/dependencies.ts",
"chars": 3391,
"preview": "import type {\n CodeKeywordDefinition,\n ErrorObject,\n KeywordErrorDefinition,\n SchemaMap,\n AnySchema,\n} from \"../../"
},
{
"path": "lib/vocabularies/applicator/dependentSchemas.ts",
"chars": 280,
"preview": "import type {CodeKeywordDefinition} from \"../../types\"\nimport {validateSchemaDeps} from \"./dependencies\"\n\nconst def: Cod"
},
{
"path": "lib/vocabularies/applicator/if.ts",
"chars": 2395,
"preview": "import type {\n CodeKeywordDefinition,\n ErrorObject,\n KeywordErrorDefinition,\n AnySchema,\n} from \"../../types\"\nimport"
},
{
"path": "lib/vocabularies/applicator/index.ts",
"chars": 1592,
"preview": "import type {ErrorNoParams, Vocabulary} from \"../../types\"\nimport additionalItems, {AdditionalItemsError} from \"./additi"
},
{
"path": "lib/vocabularies/applicator/items.ts",
"chars": 1892,
"preview": "import type {CodeKeywordDefinition, AnySchema, AnySchemaObject} from \"../../types\"\nimport type {KeywordCxt} from \"../../"
},
{
"path": "lib/vocabularies/applicator/items2020.ts",
"chars": 1053,
"preview": "import type {\n CodeKeywordDefinition,\n KeywordErrorDefinition,\n ErrorObject,\n AnySchema,\n} from \"../../types\"\nimport"
},
{
"path": "lib/vocabularies/applicator/not.ts",
"chars": 859,
"preview": "import type {CodeKeywordDefinition, ErrorNoParams, AnySchema} from \"../../types\"\nimport type {KeywordCxt} from \"../../co"
},
{
"path": "lib/vocabularies/applicator/oneOf.ts",
"chars": 2197,
"preview": "import type {\n CodeKeywordDefinition,\n ErrorObject,\n KeywordErrorDefinition,\n AnySchema,\n} from \"../../types\"\nimport"
},
{
"path": "lib/vocabularies/applicator/patternProperties.ts",
"chars": 2870,
"preview": "import type {CodeKeywordDefinition} from \"../../types\"\nimport type {KeywordCxt} from \"../../compile/validate\"\nimport {al"
},
{
"path": "lib/vocabularies/applicator/prefixItems.ts",
"chars": 292,
"preview": "import type {CodeKeywordDefinition} from \"../../types\"\nimport {validateTuple} from \"./items\"\n\nconst def: CodeKeywordDefi"
},
{
"path": "lib/vocabularies/applicator/properties.ts",
"chars": 1845,
"preview": "import type {CodeKeywordDefinition} from \"../../types\"\nimport {KeywordCxt} from \"../../compile/validate\"\nimport {propert"
},
{
"path": "lib/vocabularies/applicator/propertyNames.ts",
"chars": 1247,
"preview": "import type {\n CodeKeywordDefinition,\n ErrorObject,\n KeywordErrorDefinition,\n AnySchema,\n} from \"../../types\"\nimport"
},
{
"path": "lib/vocabularies/applicator/thenElse.ts",
"chars": 441,
"preview": "import type {CodeKeywordDefinition} from \"../../types\"\nimport type {KeywordCxt} from \"../../compile/validate\"\nimport {ch"
},
{
"path": "lib/vocabularies/code.ts",
"chars": 5247,
"preview": "import type {AnySchema, SchemaMap} from \"../types\"\nimport type {SchemaCxt} from \"../compile\"\nimport type {KeywordCxt} fr"
},
{
"path": "lib/vocabularies/core/id.ts",
"chars": 224,
"preview": "import type {CodeKeywordDefinition} from \"../../types\"\n\nconst def: CodeKeywordDefinition = {\n keyword: \"id\",\n code() {"
},
{
"path": "lib/vocabularies/core/index.ts",
"chars": 274,
"preview": "import type {Vocabulary} from \"../../types\"\nimport idKeyword from \"./id\"\nimport refKeyword from \"./ref\"\n\nconst core: Voc"
},
{
"path": "lib/vocabularies/core/ref.ts",
"chars": 4384,
"preview": "import type {CodeKeywordDefinition, AnySchema} from \"../../types\"\nimport type {KeywordCxt} from \"../../compile/validate\""
}
]
// ... and 233 more files (download for full content)
About this extraction
This page contains the full source code of the ajv-validator/ajv GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 433 files (1.8 MB), approximately 574.5k tokens, and a symbol index with 1013 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.