From c64f528f1514510f8fd98a5df6f857ba16242941 Mon Sep 17 00:00:00 2001 From: Jason Ian Green Date: Sat, 27 Apr 2024 14:10:54 +0100 Subject: [PATCH 1/8] chore: update typescript to 5.3.3 (#2406) * chore: update typescript to 5.3.3 * test: result should always be a Promise --- package.json | 2 +- spec/types/async-validate.spec.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d80c51a46..04dcf1e2e 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "rollup-plugin-terser": "^7.0.2", "ts-node": "^10.9.2", "tsify": "^5.0.4", - "typescript": "^4.9.5" + "typescript": "5.3.3" }, "collective": { "type": "opencollective", diff --git a/spec/types/async-validate.spec.ts b/spec/types/async-validate.spec.ts index 8e3f0588c..83a61417a 100644 --- a/spec/types/async-validate.spec.ts +++ b/spec/types/async-validate.spec.ts @@ -109,10 +109,10 @@ describe("$async validation and type guards", () => { const data: unknown = {foo: 1} let result: boolean | Promise if ((result = validate(data))) { - if (typeof result == "boolean") { - data.foo.should.equal(1) - } else { + if (result instanceof Promise) { await result.then((_data) => _data.foo.should.equal(1)) + } else { + should.fail() } } else { should.fail() From f74ecdb29f401a71e1ed3f2e51224b2ca31ce1ae Mon Sep 17 00:00:00 2001 From: Jason Ian Green Date: Sun, 28 Apr 2024 23:47:11 +0100 Subject: [PATCH 2/8] bump version to 8.13.0 (#2421) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04dcf1e2e..21ac5eed3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ajv", - "version": "8.12.0", + "version": "8.13.0", "description": "Another JSON Schema Validator", "main": "dist/ajv.js", "types": "dist/ajv.d.ts", From 857ecac1e652c833bf6e1249f93b3864f90c13e1 Mon Sep 17 00:00:00 2001 From: Jason Ian Green Date: Tue, 30 Apr 2024 00:28:46 +0100 Subject: [PATCH 3/8] fix: bump node version in publish job (#2423) --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2da03454b..a2ace2179 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 18 registry-url: https://registry.npmjs.org/ - run: npm install - run: git submodule update --init From 2917fb60c16c2aa5c51354af1a8f33d3f75e37ae Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Tue, 30 Apr 2024 00:41:11 +0100 Subject: [PATCH 4/8] readme: build badge (#2424) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c10422e63..d8ee276ce 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ 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) From d9bd01bf3fbe2425d7a74477e2080c229a11adb8 Mon Sep 17 00:00:00 2001 From: Dan Rose Date: Sun, 5 May 2024 04:17:30 -0500 Subject: [PATCH 5/8] Update workflows (#2410) silence warnings about outdated actions e.g. https://github.com/ajv-validator/ajv/actions/runs/8490491525 Co-authored-by: Jason Ian Green --- .github/workflows/build.yml | 6 +++--- .github/workflows/publish.yml | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 415889c83..d374fbd9e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,9 +15,9 @@ jobs: 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 @@ -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 }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a2ace2179..35bf8ed67 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,8 +8,8 @@ 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: 18 registry-url: https://registry.npmjs.org/ @@ -17,12 +17,12 @@ jobs: - 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 }} From a4a85fac1d629f263010c618f9dfec8c1a9b23e6 Mon Sep 17 00:00:00 2001 From: Jason Ian Green Date: Fri, 10 May 2024 22:28:17 +0100 Subject: [PATCH 6/8] docs: add warning to maxLength / minLength (#2428) --- docs/json-schema.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/json-schema.md b/docs/json-schema.md index ac2d82d84..45ef5ef00 100644 --- a/docs/json-schema.md +++ b/docs/json-schema.md @@ -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](https://www.unicode.org/reports/tr29/tr29-17.html#Grapheme_Cluster_Boundaries) will count as multiple characters +Certain charsets have characters that are made up of multiple unicode characters. These "grapheme clusters" are counted as multiple characters. +::: + 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** From be38f349e3c82cd940ba254153290552256256d7 Mon Sep 17 00:00:00 2001 From: Jason Ian Green Date: Sat, 11 May 2024 13:11:19 +0100 Subject: [PATCH 7/8] fix: broken link in docs warning (#2431) --- docs/json-schema.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/json-schema.md b/docs/json-schema.md index 45ef5ef00..c888c636d 100644 --- a/docs/json-schema.md +++ b/docs/json-schema.md @@ -280,8 +280,8 @@ The value of the keyword should be a number. The data to be valid should be a mu ### `maxLength` / `minLength` -::: warning [Grapheme clusters](https://www.unicode.org/reports/tr29/tr29-17.html#Grapheme_Cluster_Boundaries) will count as multiple characters -Certain charsets have characters that are made up of multiple unicode characters. These "grapheme clusters" are counted as multiple characters. +::: 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. From 5f20d5f90adc6ea58e512f5da72638c7a96d93d9 Mon Sep 17 00:00:00 2001 From: Jason Ian Green Date: Fri, 17 May 2024 18:36:54 +0100 Subject: [PATCH 8/8] compileAsync a schema with discriminator and $ref, fixes #2427 (#2433) * fix #2427 compileAsync a schema with discriminator and $ref Make the discriminator code generation throw MissingRefError when the $ref does not synchronously resolve so that compileAsync can loadSchema and retry. * test: fix errors in test --------- Co-authored-by: Yonathan Randolph --- lib/vocabularies/discriminator/index.ts | 5 +- spec/discriminator.spec.ts | 61 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lib/vocabularies/discriminator/index.ts b/lib/vocabularies/discriminator/index.ts index 98f0f8cfb..19ae6049f 100644 --- a/lib/vocabularies/discriminator/index.ts +++ b/lib/vocabularies/discriminator/index.ts @@ -3,6 +3,7 @@ import type {KeywordCxt} from "../../compile/validate" import {_, getProperty, Name} from "../../compile/codegen" import {DiscrError, DiscrErrorObj} from "../discriminator/types" import {resolveRef, SchemaEnv} from "../../compile" +import MissingRefError from "../../compile/ref_error" import {schemaHasRulesButRef} from "../../compile/util" export type DiscriminatorError = DiscrErrorObj | DiscrErrorObj @@ -66,8 +67,10 @@ const def: CodeKeywordDefinition = { for (let i = 0; i < oneOf.length; i++) { let sch = oneOf[i] if (sch?.$ref && !schemaHasRulesButRef(sch, it.self.RULES)) { - sch = resolveRef.call(it.self, it.schemaEnv.root, it.baseId, sch?.$ref) + const ref = sch.$ref + sch = resolveRef.call(it.self, it.schemaEnv.root, it.baseId, ref) if (sch instanceof SchemaEnv) sch = sch.schema + if (sch === undefined) throw new MissingRefError(it.opts.uriResolver, it.baseId, ref) } const propSch = sch?.properties?.[tagName] if (typeof propSch != "object") { diff --git a/spec/discriminator.spec.ts b/spec/discriminator.spec.ts index 28ff12146..74ba33ef0 100644 --- a/spec/discriminator.spec.ts +++ b/spec/discriminator.spec.ts @@ -159,6 +159,67 @@ describe("discriminator keyword", function () { }) }) + describe("schema with external $refs", () => { + const schemas = { + main: { + type: "object", + discriminator: {propertyName: "foo"}, + required: ["foo"], + oneOf: [ + { + $ref: "schema1", + }, + { + $ref: "schema2", + }, + ], + }, + schema1: { + type: "object", + properties: { + foo: {const: "x"}, + }, + }, + schema2: { + type: "object", + properties: { + foo: {enum: ["y", "z"]}, + }, + }, + } + + const data = {foo: "x"} + const badData = {foo: "w"} + + it("compile should resolve each $ref to a schema that was added with addSchema", () => { + const opts = { + discriminator: true, + } + const ajv = new _Ajv(opts) + ajv.addSchema(schemas.main, "https://host/main") + ajv.addSchema(schemas.schema1, "https://host/schema1") + ajv.addSchema(schemas.schema2, "https://host/schema2") + + const validate = ajv.compile({$ref: "https://host/main"}) + assert.strictEqual(validate(data), true) + assert.strictEqual(validate(badData), false) + }) + it("compileAsync should loadSchema each $ref", async () => { + const opts = { + discriminator: true, + loadSchema(url) { + if (!url.startsWith("https://host/")) return undefined + const name = url.substring("https://host/".length) + return schemas[name] + }, + } + const ajv = new _Ajv(opts) + const validate = await ajv.compileAsync({$ref: "https://host/main"}) + assert.strictEqual(validate(data), true) + assert.strictEqual(validate(badData), false) + }) + }) + describe("validation with deeply referenced schemas", () => { const schema = [ {