Skip to content

Commit

Permalink
Merge branch 'master' into fix-ajv-doc-link
Browse files Browse the repository at this point in the history
  • Loading branch information
Nevon authored Nov 4, 2021
2 parents 5c72311 + 1da0ea6 commit 518321b
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 9 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@typescript-eslint/eslint-plugin": "^2.1.0",
"@typescript-eslint/parser": "^2.1.0",
"@typescript-eslint/typescript-estree": "^2.1.0",
"ajv8": "npm:ajv@^8.6.3",
"dockest": "^2.1.0",
"eslint": "^6.3.0",
"eslint-config-prettier": "^6.1.0",
Expand Down
7 changes: 6 additions & 1 deletion src/@types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Resolver, ForSchemaOptions } from 'avsc'
import { ValidateFunction } from './JsonSchema'
import Ajv from 'ajv'

export enum SchemaType {
Expand All @@ -14,7 +15,11 @@ export interface SchemaHelper {
}

export type AvroOptions = Partial<ForSchemaOptions>
export type JsonOptions = ConstructorParameters<typeof Ajv>[0] & { ajvInstance?: Ajv }
export type JsonOptions = ConstructorParameters<typeof Ajv>[0] & {
ajvInstance?: {
compile: (schema: any) => ValidateFunction
}
}
export type ProtoOptions = { messageName: string }

export interface LegacyOptions {
Expand Down
30 changes: 27 additions & 3 deletions src/JsonSchema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import { Schema, JsonOptions, ConfluentSchema } from './@types'
import Ajv, { DefinedError, ValidateFunction } from 'ajv'
import Ajv from 'ajv'
import { ConfluentSchemaRegistryValidationError } from './errors'

interface BaseAjvValidationError {
data?: unknown
schema?: unknown
}

interface OldAjvValidationError extends BaseAjvValidationError {
dataPath: string
instancePath?: string
}
interface NewAjvValidationError extends BaseAjvValidationError {
instancePath: string
}

type AjvValidationError = OldAjvValidationError | NewAjvValidationError

export interface ValidateFunction {
(this: any, data: any): boolean
errors?: null | AjvValidationError[]
}
export default class JsonSchema implements Schema {
private validate: ValidateFunction

Expand Down Expand Up @@ -39,12 +58,17 @@ export default class JsonSchema implements Schema {
): boolean {
if (!this.validate(payload)) {
if (opts?.errorHook) {
for (const err of this.validate.errors as DefinedError[]) {
opts.errorHook([err.dataPath], err.data, err.schema)
for (const err of this.validate.errors as AjvValidationError[]) {
const path = this.isOldAjvValidationError(err) ? err.dataPath : err.instancePath
opts.errorHook([path], err.data, err.schema)
}
}
return false
}
return true
}

private isOldAjvValidationError(error: AjvValidationError): error is OldAjvValidationError {
return (error as OldAjvValidationError).dataPath != null
}
}
37 changes: 37 additions & 0 deletions src/SchemaRegistry.newApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import encodedAnotherPersonV2Json from '../fixtures/json/encodedAnotherPersonV2'
import encodedAnotherPersonV2Proto from '../fixtures/proto/encodedAnotherPersonV2'
import encodedNestedV2Proto from '../fixtures/proto/encodedNestedV2'
import wrongMagicByte from '../fixtures/wrongMagicByte'
import Ajv2020 from 'ajv8/dist/2020'
import Ajv from 'ajv'
import { ConfluentSchemaRegistryValidationError } from './errors'

const REGISTRY_HOST = 'http://localhost:8982'
const schemaRegistryAPIClientArgs = { host: REGISTRY_HOST }
Expand Down Expand Up @@ -561,4 +564,38 @@ describe('SchemaRegistry - new Api', () => {
})
})
})

describe('JSON Schema tests', () => {
describe('passing an Ajv instance in the constructor', () => {
test.each([
['Ajv 7', new Ajv()],
['Ajv2020', new Ajv2020()],
])(
'Errors are thrown with their path in %s when the validation fails',
async (_, ajvInstance) => {
expect.assertions(3)
const registry = new SchemaRegistry(schemaRegistryArgs, {
[SchemaType.JSON]: { ajvInstance },
})
const subject: ConfluentSubject = {
name: [SchemaType.JSON, 'com.org.domain.fixtures', 'AnotherPerson'].join('.'),
}
const schema: ConfluentSchema = {
type: SchemaType.JSON,
schema: schemaStringsByType[SchemaType.JSON].v1,
}

const { id: schemaId } = await registry.register(schema, { subject: subject.name })

try {
await schemaRegistry.encode(schemaId, { fullName: true })
} catch (error) {
expect(error).toBeInstanceOf(ConfluentSchemaRegistryValidationError)
expect(error.message).toEqual('invalid payload')
expect(error.paths).toEqual([['/fullName']])
}
},
)
})
})
})
62 changes: 57 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,16 @@ acorn@^7.1.0, acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf"
integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==

"ajv8@npm:ajv@^8.6.3":
version "8.6.3"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764"
integrity sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
require-from-string "^2.0.2"
uri-js "^4.2.2"

ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5:
version "6.12.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7"
Expand Down Expand Up @@ -1308,13 +1318,18 @@ diff@^4.0.1:
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==

dockest@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/dockest/-/dockest-1.0.4.tgz#0da0fb44aeba1d9923aa72a6f43fe6aea1174296"
integrity sha512-fHAU1z9CkMDHeoJo0oxg0sK1BYc3tANmGKAm7tPY/OpVV3DUVCSDwnpqtq7H3/I7tKvII5xF44hE1iSC+qNvnA==
dockest@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/dockest/-/dockest-2.1.0.tgz#efbeaca7bb6078b9bb0a431a050cdefc5b50f07e"
integrity sha512-cEudMXrP9Sl1obedYDEyXoKSePGsmbT8750W2D1/W19szr+EbSlEpaRp3tIl5q8oeZ6UxFnfZjXzD+4nDrVhZw==
dependencies:
execa "^2.0.4"
chalk "^3.0.0"
execa "^4.0.0"
fp-ts "^2.8.3"
io-ts "^2.2.10"
is-docker "^2.0.0"
js-yaml "^3.13.1"
rxjs "^6.5.4"

doctrine@^3.0.0:
version "3.0.0"
Expand Down Expand Up @@ -1568,6 +1583,21 @@ execa@^3.2.0:
signal-exit "^3.0.2"
strip-final-newline "^2.0.0"

execa@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
dependencies:
cross-spawn "^7.0.0"
get-stream "^5.0.0"
human-signals "^1.1.1"
is-stream "^2.0.0"
merge-stream "^2.0.0"
npm-run-path "^4.0.0"
onetime "^5.1.0"
signal-exit "^3.0.2"
strip-final-newline "^2.0.0"

exit@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
Expand Down Expand Up @@ -1750,6 +1780,11 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"

fp-ts@^2.8.3:
version "2.11.5"
resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.11.5.tgz#97cceb26655b1452d7088d6fb0864f84cceffbe4"
integrity sha512-OqlwJq1BdpB83BZXTqI+dNcA6uYk6qk4u9Cgnt64Y+XS7dwdbp/mobx8S2KXf2AXH+scNmA/UVK3SEFHR3vHZA==

fragment-cache@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
Expand Down Expand Up @@ -2008,6 +2043,11 @@ inquirer@^7.0.0:
strip-ansi "^6.0.0"
through "^2.3.6"

io-ts@^2.2.10:
version "2.2.16"
resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.16.tgz#597dffa03db1913fc318c9c6df6931cb4ed808b2"
integrity sha512-y5TTSa6VP6le0hhmIyN0dqEXkrZeJLeC5KApJq6VLci3UEKF80lZ+KuoUs02RhBxNWlrqSNxzfI7otLX1Euv8Q==

ip-regex@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
Expand Down Expand Up @@ -2071,6 +2111,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"

is-docker@^2.0.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==

is-extendable@^0.1.0, is-extendable@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
Expand Down Expand Up @@ -3406,6 +3451,13 @@ rxjs@^6.5.3:
dependencies:
tslib "^1.9.0"

rxjs@^6.5.4:
version "6.6.7"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
dependencies:
tslib "^1.9.0"

safe-buffer@^5.0.1, safe-buffer@^5.1.2:
version "5.2.0"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
Expand Down

0 comments on commit 518321b

Please sign in to comment.