Skip to content

Commit

Permalink
Merge branch 'master' into feature/2003-Support_OpenAPI_3.0_discrimin…
Browse files Browse the repository at this point in the history
…ator.mapping
  • Loading branch information
jasoniangreen authored Jun 19, 2024
2 parents 0980a57 + 650c7f6 commit 0a8f691
Show file tree
Hide file tree
Showing 27 changed files with 203 additions and 100 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x, 18.x, 19.x]
node-version: [16.x, 18.x, 20.x, 21.x]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
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 == '14.x' }}
if: ${{ github.event_name == 'push' && matrix.node-version == '16.x' }}
run: ./scripts/publish-site
env:
GH_TOKEN_PUBLIC: ${{ secrets.GH_TOKEN_PUBLIC }}
Expand All @@ -32,6 +32,6 @@ jobs:
- run: npm run build
- run: npm run test-ci
- name: coveralls
uses: coverallsapp/github-action@master
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
10 changes: 5 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ jobs:
publish-npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 14
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"
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"
if: ${{ !github.event.release.prerelease }}
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ 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/).

[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)
[![build](https://github.com/ajv-validator/ajv/actions/workflows/build.yml/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)
[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)
[![npm downloads](https://img.shields.io/npm/dm/ajv.svg)](https://www.npmjs.com/package/ajv)
[![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv?branch=master)
[![SimpleX](https://img.shields.io/badge/chat-on%20SimpleX-%2307b4b9)](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FV-6t4hoy_SsvKMi9KekdGX-VKQOhDeAe%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAm98gjwvrAEiiz_YgBoaQB9dtKTl5Om1pborUyevQwzg%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22wYrTFafovkymjUtc2vUjCQ%3D%3D%22%7D)
[![SimpleX](https://img.shields.io/badge/chat-on%20SimpleX-70F0F9)](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)
[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)
[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/managing-schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ In the example above, the key passed to the `addSchema` method was used to retri

### Pre-adding all schemas vs adding on demand

In the example above all schemas were added in advance. It is also possible, to add schemas as they are used - it can be helpful if there is many schemas. In this case, you need to check first whether the schema is already added by calling `getSchema` method - it would return `undefined` if not:
In the example above all schemas were added in advance. It is also possible, to add schemas as they are used - it can be helpful if there are many schemas. In this case, you need to check first whether the schema is already added by calling `getSchema` method - it would return `undefined` if not:

```javascript
const schema_user = require("./schema_user.json")
Expand Down
10 changes: 7 additions & 3 deletions docs/json-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ The value of the keyword should be a number. The data to be valid should be a mu

### `maxLength` / `minLength`

::: warning Grapheme clusters will count as multiple characters
Certain charsets have characters that are made up of multiple Unicode code points. These [grapheme clusters](https://www.unicode.org/reports/tr29/tr29-17.html#Grapheme_Cluster_Boundaries) are counted as multiple in length calculations.
:::

The value of the keywords should be a number. The data to be valid should have length satisfying this rule. Unicode pairs are counted as a single character.

**Examples**
Expand Down Expand Up @@ -474,11 +478,11 @@ To create and equivalent schema in draft-2020-12 use keywords [prefixItems](#pre

The value of the keyword should be a boolean or an object.

If `items` keyword is not present or it is an object, `additionalItems` keyword should be ignored regardless of its value. By default Ajv will throw exception in this case - see [Strict mode](./strict-mode.md)
`additionalItems` keyword is ignored if `items` keyword is not present or is an object. By default Ajv will throw exception in this case - see [Strict mode](./strict-mode.md)

If `items` keyword is an array and data array has not more items than the length of `items` keyword value, `additionalItems` keyword is also ignored.
`additionalItems` keyword is ignored if `items` keyword has more elements than data array.

If the length of data array is bigger than the length of "items" keyword value than the result of the validation depends on the value of `additionalItems` keyword:
If the data array has more elements than the `items` keyword value then the result of the validation depends on the value of `additionalItems` keyword:

- `false`: data is invalid
- `true`: data is valid
Expand Down
4 changes: 2 additions & 2 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ An array or object of schemas that will be added to the instance. In case you pa

### logger

Sets the logging method. Default is the global `console` object that should have methods `log`, `warn` and `error`. See [Error logging](#error-logging).
Sets the logging method. Default is the global `console` object that should have methods `log`, `warn` and `error`. See [Error logging](./api.md#error-logging).

Option values:

Expand Down Expand Up @@ -349,7 +349,7 @@ Include human-readable messages in errors. `true` by default. `false` can be pas

### uriResolver

By default `uriResolver` is undefined and relies on the embedded uriResolver [uri-js](https://github.com/garycourt/uri-js). Pass an object that satisfies the interface [UriResolver](https://github.com/ajv-validator/ajv/blob/master/lib/types/index.ts) to be used in replacement. One alternative is [fast-uri](https://github.com/fastify/fast-uri).
By default `uriResolver` is undefined and relies on the embedded uriResolver [fast-uri](https://github.com/fastify/fast-uri). Pass an object that satisfies the interface [UriResolver](https://github.com/ajv-validator/ajv/blob/master/lib/types/index.ts) to be used in replacement. One alternative is [uri-js](https://github.com/garycourt/uri-js).

### code <Badge text="v7" />

Expand Down
10 changes: 5 additions & 5 deletions docs/packages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ If you have published a useful plugin please submit a PR to add it to the next s

## Related packages

- [ajv-formats](./ajv-formats.md) - formats defined in JSON Schema specification
- [ajv-keywords](./ajv-keywords) - additional validation keywords (select, typeof, etc.)
- [ajv-errors](./ajv-errors.md) - defining error messages in the schema
- [ajv-i18n](./ajv-i18n) - internationalised error messages
- [ajv-cli](./ajv-cli.md) - command line interface
- [ajv-formats](https://github.com/ajv-validator/ajv-formats) - formats defined in JSON Schema specification
- [ajv-keywords](https://github.com/ajv-validator/ajv-keywords) - additional validation keywords (select, typeof, etc.)
- [ajv-errors](https://github.com/ajv-validator/ajv-errors) - defining error messages in the schema
- [ajv-i18n](https://github.com/ajv-validator/ajv-i18n) - internationalised error messages
- [ajv-cli](https://github.com/ajv-validator/ajv-cli) - command line interface
- [ajv-bsontype](https://github.com/BoLaMN/ajv-bsontype) - MongoDB's bsonType formats
- [ajv-formats-draft2019](https://github.com/luzlab/ajv-formats-draft2019) - formats for draft-2019-09 that are not included in [ajv-formats](./ajv-formats.md) (`idn-hostname`, `idn-email`, `iri` and `iri-reference`)
- [ajv-merge-patch](https://github.com/ajv-validator/ajv-merge-patch) - keywords $merge and $patch
2 changes: 1 addition & 1 deletion docs/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ If you use Ajv to validate data from untrusted sources **it is strongly recommen

- making assessment of "format" implementations in [ajv-formats](https://github.com/ajv-validator/ajv-formats).
- passing `"fast"` option to ajv-formats plugin (see its docs) that simplifies some of the regular expressions (although it does not guarantee that they are safe).
- replacing format implementations provided by ajv-formats with your own implementations of "format" keyword that either use different regular expressions or another approach to format validation. Please see [addFormat](#api-addformat) method.
- replacing format implementations provided by ajv-formats with your own implementations of "format" keyword that either use different regular expressions or another approach to format validation. Please see [addFormat](https://github.com/ajv-validator/ajv/blob/master/docs/api.md#api-addformat) method.
- disabling format validation by ignoring "format" keyword with option `format: false`

Whatever mitigation you choose, please assume all formats provided by ajv-formats as potentially unsafe and make your own assessment of their suitability for your validation scenarios.
Expand Down
4 changes: 2 additions & 2 deletions docs/strict-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ By default Ajv fails schema compilation when unknown keywords are used. Users ca
ajv.addKeyword("allowedKeyword")
```

or
or use the convenience method `addVocabulary` for multiple keywords

```javascript
ajv.addVocabulary(["allowed1", "allowed2"])
ajv.addVocabulary(["allowed1", "allowed2"]) // simply calls addKeyword multiple times
```

#### Ignored "additionalItems" keyword
Expand Down
3 changes: 2 additions & 1 deletion lib/2019.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import addMetaSchema2019 from "./refs/json-schema-2019-09"

const META_SCHEMA_ID = "https://json-schema.org/draft/2019-09/schema"

class Ajv2019 extends AjvCore {
export class Ajv2019 extends AjvCore {
constructor(opts: Options = {}) {
super({
...opts,
Expand Down Expand Up @@ -44,6 +44,7 @@ class Ajv2019 extends AjvCore {
}

module.exports = exports = Ajv2019
module.exports.Ajv2019 = Ajv2019
Object.defineProperty(exports, "__esModule", {value: true})

export default Ajv2019
Expand Down
3 changes: 2 additions & 1 deletion lib/2020.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import addMetaSchema2020 from "./refs/json-schema-2020-12"

const META_SCHEMA_ID = "https://json-schema.org/draft/2020-12/schema"

class Ajv2020 extends AjvCore {
export class Ajv2020 extends AjvCore {
constructor(opts: Options = {}) {
super({
...opts,
Expand Down Expand Up @@ -38,6 +38,7 @@ class Ajv2020 extends AjvCore {
}

module.exports = exports = Ajv2020
module.exports.Ajv2020 = Ajv2020
Object.defineProperty(exports, "__esModule", {value: true})

export default Ajv2020
Expand Down
3 changes: 2 additions & 1 deletion lib/ajv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const META_SUPPORT_DATA = ["/properties"]

const META_SCHEMA_ID = "http://json-schema.org/draft-07/schema"

class Ajv extends AjvCore {
export class Ajv extends AjvCore {
_addVocabularies(): void {
super._addVocabularies()
draft7Vocabularies.forEach((v) => this.addVocabulary(v))
Expand All @@ -32,6 +32,7 @@ class Ajv extends AjvCore {
}

module.exports = exports = Ajv
module.exports.Ajv = Ajv
Object.defineProperty(exports, "__esModule", {value: true})

export default Ajv
Expand Down
1 change: 1 addition & 0 deletions lib/compile/codegen/code.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export abstract class _CodeOrName {
abstract readonly str: string
abstract readonly names: UsedNames
Expand Down
30 changes: 25 additions & 5 deletions lib/compile/codegen/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ abstract class Node {
}

class Def extends Node {
constructor(private readonly varKind: Name, private readonly name: Name, private rhs?: SafeExpr) {
constructor(
private readonly varKind: Name,
private readonly name: Name,
private rhs?: SafeExpr
) {
super()
}

Expand All @@ -63,7 +67,11 @@ class Def extends Node {
}

class Assign extends Node {
constructor(readonly lhs: Code, public rhs: SafeExpr, private readonly sideEffects?: boolean) {
constructor(
readonly lhs: Code,
public rhs: SafeExpr,
private readonly sideEffects?: boolean
) {
super()
}

Expand All @@ -84,7 +92,12 @@ class Assign extends Node {
}

class AssignOp extends Assign {
constructor(lhs: Code, private readonly op: Code, rhs: SafeExpr, sideEffects?: boolean) {
constructor(
lhs: Code,
private readonly op: Code,
rhs: SafeExpr,
sideEffects?: boolean
) {
super(lhs, rhs, sideEffects)
}

Expand Down Expand Up @@ -211,7 +224,10 @@ class Else extends BlockNode {
class If extends BlockNode {
static readonly kind = "if"
else?: If | Else
constructor(private condition: Code | boolean, nodes?: ChildNode[]) {
constructor(
private condition: Code | boolean,
nodes?: ChildNode[]
) {
super(nodes)
}

Expand Down Expand Up @@ -331,7 +347,11 @@ class ForIter extends For {

class Func extends BlockNode {
static readonly kind = "func"
constructor(public name: Name, public args: Code, public async?: boolean) {
constructor(
public name: Name,
public args: Code,
public async?: boolean
) {
super()
}

Expand Down
4 changes: 2 additions & 2 deletions lib/compile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import N from "./names"
import {LocalRefs, getFullPath, _getFullPath, inlineRef, normalizeId, resolveUrl} from "./resolve"
import {schemaHasRulesButRef, unescapeFragment} from "./util"
import {validateFunctionCode} from "./validate"
import * as URI from "uri-js"
import {URIComponent} from "fast-uri"
import {JSONType} from "./rules"

export type SchemaRefs = {
Expand Down Expand Up @@ -295,7 +295,7 @@ const PREVENT_SCOPE_CHANGE = new Set([

function getJsonPointer(
this: Ajv,
parsedRef: URI.URIComponents,
parsedRef: URIComponent,
{baseId, schema, root}: SchemaEnv
): SchemaEnv | undefined {
if (parsedRef.fragment?.[0] !== "/") return
Expand Down
12 changes: 6 additions & 6 deletions lib/compile/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {AnySchema, AnySchemaObject, UriResolver} from "../types"
import type Ajv from "../ajv"
import type {URIComponents} from "uri-js"
import type {URIComponent} from "fast-uri"
import {eachItem} from "./util"
import * as equal from "fast-deep-equal"
import * as traverse from "json-schema-traverse"
Expand Down Expand Up @@ -73,7 +73,7 @@ export function getFullPath(resolver: UriResolver, id = "", normalize?: boolean)
return _getFullPath(resolver, p)
}

export function _getFullPath(resolver: UriResolver, p: URIComponents): string {
export function _getFullPath(resolver: UriResolver, p: URIComponent): string {
const serialized = resolver.serialize(p)
return serialized.split("#")[0] + "#"
}
Expand Down Expand Up @@ -102,16 +102,16 @@ export function getSchemaRefs(this: Ajv, schema: AnySchema, baseId: string): Loc
traverse(schema, {allKeys: true}, (sch, jsonPtr, _, parentJsonPtr) => {
if (parentJsonPtr === undefined) return
const fullPath = pathPrefix + jsonPtr
let baseId = baseIds[parentJsonPtr]
if (typeof sch[schemaId] == "string") baseId = addRef.call(this, sch[schemaId])
let innerBaseId = baseIds[parentJsonPtr]
if (typeof sch[schemaId] == "string") innerBaseId = addRef.call(this, sch[schemaId])
addAnchor.call(this, sch.$anchor)
addAnchor.call(this, sch.$dynamicAnchor)
baseIds[jsonPtr] = baseId
baseIds[jsonPtr] = innerBaseId

function addRef(this: Ajv, ref: string): string {
// eslint-disable-next-line @typescript-eslint/unbound-method
const _resolve = this.opts.uriResolver.resolve
ref = normalizeId(baseId ? _resolve(baseId, ref) : ref)
ref = normalizeId(innerBaseId ? _resolve(innerBaseId, ref) : ref)
if (schemaRefs.has(ref)) throw ambiguos(ref)
schemaRefs.add(ref)
let schOrRef = this.refs[ref]
Expand Down
1 change: 1 addition & 0 deletions lib/compile/validate/dataType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export function getSchemaTypes(schema: AnySchemaObject): JSONType[] {
return types
}

// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
export function getJSONTypes(ts: unknown | unknown[]): JSONType[] {
const types: unknown[] = Array.isArray(ts) ? ts : ts ? [ts] : []
if (types.every(isJSONType)) return types
Expand Down
4 changes: 4 additions & 0 deletions lib/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,14 +343,17 @@ export default class Ajv {
validate<T>(schema: JTDSchemaType<T>, data: unknown): data is T
// This overload is only intended for typescript inference, the first
// argument prevents manual type annotation from matching this overload
// eslint-disable-next-line @typescript-eslint/no-unused-vars
validate<N extends never, T extends SomeJTDSchemaType>(
schema: T,
data: unknown
): data is JTDDataType<T>
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
validate<T>(schema: AsyncSchema, data: unknown | T): Promise<T>
validate<T>(schemaKeyRef: AnySchema | string, data: unknown): data is T | Promise<T>
validate<T>(
schemaKeyRef: AnySchema | string, // key, ref or schema object
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
data: unknown | T // to be validated
): boolean | Promise<T> {
let v: AnyValidateFunction | undefined
Expand All @@ -374,6 +377,7 @@ export default class Ajv {
compile<T = unknown>(schema: JTDSchemaType<T>, _meta?: boolean): ValidateFunction<T>
// This overload is only intended for typescript inference, the first
// argument prevents manual type annotation from matching this overload
// eslint-disable-next-line @typescript-eslint/no-unused-vars
compile<N extends never, T extends SomeJTDSchemaType>(
schema: T,
_meta?: boolean
Expand Down
3 changes: 2 additions & 1 deletion lib/jtd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type JTDOptions = CurrentOptions & {
multipleOfPrecision?: never
}

class Ajv extends AjvCore {
export class Ajv extends AjvCore {
constructor(opts: JTDOptions = {}) {
super({
...opts,
Expand Down Expand Up @@ -93,6 +93,7 @@ class Ajv extends AjvCore {
}

module.exports = exports = Ajv
module.exports.Ajv = Ajv
Object.defineProperty(exports, "__esModule", {value: true})

export default Ajv
Expand Down
Loading

0 comments on commit 0a8f691

Please sign in to comment.