Skip to content
This repository has been archived by the owner on Aug 31, 2022. It is now read-only.

Commit

Permalink
Refactor validator and add ajv-formats
Browse files Browse the repository at this point in the history
  • Loading branch information
juriwiens committed Dec 28, 2020
1 parent e83688b commit f45f159
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"dependencies": {
"@types/pino": "^6.3.4",
"ajv": "^7.0.2",
"ajv-formats": "^1.5.1",
"fastify": "^3.9.2",
"fastify-plugin": "^3.0.0",
"fastify-sensible": "^3.1.0",
Expand Down
1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ export { Logger } from "./logging/logging.types"
export * from "./metrics"
export * from "./http_client"
export { createServiceSkeleton, ServiceSkeletonOptions } from "./skeleton"
export * from "./validator"
export * from "./utils"
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from "./event_emitter_utils"
export * from "./identity"
export * from "./options"
export * from "./type_check"
export * from "./validator"
65 changes: 65 additions & 0 deletions src/utils/validator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Validator, ValidationSchema, ValidationError } from "./validator"

test("validate() validates objects", () => {
const someObjValidator = new Validator<SomeObj>("someObj", someObjSchema)
for (const valid of validSomeObjs) {
expect(someObjValidator.validate(valid)).toBe(true)
}
for (const invalid of invalidSomeObjs) {
expect(someObjValidator.validate(invalid)).toBe(false)
}
})

test("assert() validates objects and throws if the validation fails", () => {
const someObjValidator = new Validator<SomeObj>("someObj", someObjSchema)
for (const valid of validSomeObjs) {
expect(() => Validator.assert(someObjValidator, valid)).not.toThrow()
}
for (const invalid of invalidSomeObjs) {
expect(() => Validator.assert(someObjValidator, invalid)).toThrow(
ValidationError
)
}
})

test("Supports additional ajv-formats like date", () => {
const validator = new Validator("date", {
type: "string",
format: "date",
formatMinimum: "2016-02-06",
formatExclusiveMaximum: "2016-12-27",
})

const validData = ["2016-02-06", "2016-12-26"]
for (const valid of validData) {
expect(validator.validate(valid)).toBe(true)
}

const invalidData = ["2016-02-05", "2016-12-27", "abc"]
for (const invalid of invalidData) {
expect(validator.validate(invalid)).toBe(false)
}
})

interface SomeObj {
n: number
s: string[]
o?: { m: number }
}

const someObjSchema: ValidationSchema = {
type: "object",
properties: {
n: { type: "number" },
s: { type: "array", items: { type: "string" } },
o: { type: "object", properties: { m: { type: "number" } } },
},
required: ["n", "s"],
}

const validSomeObjs: SomeObj[] = [
{ n: 1, s: ["s1"] },
{ n: 1, s: ["s1"], o: { m: 1 } },
]

const invalidSomeObjs = [{}, { n: "1", s: ["s1"] }]
15 changes: 9 additions & 6 deletions src/validator.ts → src/utils/validator.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import Ajv, * as ajv from "ajv"
import addFormats from "ajv-formats"

const staticAjvInstance = new Ajv()
const staticAjvInstance = addFormats(new Ajv())

export class Validator<T> {
readonly validateFunc: ajv.ValidateFunction<T>
readonly schema: Record<string, unknown>
readonly schema: ValidationSchema
readonly schemaName: string

constructor(
schemaName: string,
schema: Record<string, unknown>,
schema: ValidationSchema,
options?: ajv.Options
) {
const ajv = options ? new Ajv(options) : staticAjvInstance
const ajv = options ? addFormats(new Ajv(options)) : staticAjvInstance
this.validateFunc = ajv.compile(schema)
this.schema = schema
this.schemaName = schemaName
Expand Down Expand Up @@ -60,7 +61,7 @@ export class ValidationError extends Error {
constructor(
readonly candidate: unknown,
readonly schemaName: string,
readonly schema: Record<string, unknown>,
readonly schema: ValidationSchema,
readonly validationErrors: ajv.ErrorObject[]
) {
super(
Expand All @@ -76,6 +77,8 @@ export type ValidationResultHandler = (

export interface ValidationContext {
candidate: unknown
schema: Record<string, unknown>
schema: ValidationSchema
schemaName: string
}

export type ValidationSchema = ajv.Schema
9 changes: 8 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,13 @@ acorn@^7.1.1, acorn@^7.4.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==

ajv-formats@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-1.5.1.tgz#0f301b1b3846182f224cc563fc0a032daafb7dab"
integrity sha512-s1RBVF4HZd2UjGkb6t6uWoXjf6o7j7dXPQIL7vprcIT/67bTD6+5ocsU0UKShS2qWxueGDWuGfKHfOxHWrlTQg==
dependencies:
ajv "^7.0.0"

ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
Expand All @@ -848,7 +855,7 @@ ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"

ajv@^7.0.2:
ajv@^7.0.0, ajv@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.2.tgz#04ccc89a93449c64382fe0846d45a7135d986dbc"
integrity sha512-qIaxO9RXjaXyO21tJr0EvwPcZa49m64GcXCU8ZrLjCAlFyMuOcPpI560So4A11M1WsKslJYIXn6jSyG5P0xIeg==
Expand Down

0 comments on commit f45f159

Please sign in to comment.