Skip to content

Commit

Permalink
support migration from draft-04 to draft-2020-12
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Mar 28, 2021
1 parent 9c12226 commit 647d3bd
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = {
files: ["*.ts"],
rules: {
...tsConfig.rules,
complexity: ["error", 35],
complexity: ["error", 15],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unnecessary-condition": "warn",
"@typescript-eslint/no-unsafe-assignment": "off",
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# json-schema-migrate

Migrate JSON-Schema from draft-04 to draft-07 or draft-2019-09
Migrate JSON-Schema from draft-04 to draft-07, draft-2019-09 or draft-2020-12

[![build](https://github.com/ajv-validator/json-schema-migrate/workflows/build/badge.svg)](https://github.com/ajv-validator/json-schema-migrate/actions?query=workflow%3Abuild)
[![npm](https://img.shields.io/npm/v/json-schema-migrate)](https://www.npmjs.com/package/json-schema-migrate)
Expand All @@ -23,6 +23,7 @@ const schema = {
}
migrate.draft7(schema)
// or migrate.draft2019(schema)
// or migrate.draft2020(schema)

console.log(schema)
// {
Expand All @@ -40,7 +41,7 @@ console.log(migrate.getAjv().errorsText(errors))
## Changes in schemas after migration

- `id` is replaced with `$id`
- `$schema` value becomes draft-07 or draft-2019-09 meta-schema
- `$schema` value becomes draft-07, draft-2019-09 or draft-2020-12 meta-schema
- draft-04 boolean form of `exclusiveMaximum/Minimum` is replaced with the current number form
- `enum` with a single allowed value is replaced with `const`
- Non-standard `constant` is replaced with `const`
Expand All @@ -51,6 +52,7 @@ console.log(migrate.getAjv().errorsText(errors))
- `dependencies` with `dependentRequired` and `dependentSchemas`
- `"id": "#foo"` with `"$anchor": "foo"`
- `"id": "schema#foo"` with `"$id": "schema", "$anchor": "foo"`
- `draft2020` function additionally replaces array form of `items` with `prefixItems` (and `additionalItems` with `items`)

## License

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"homepage": "https://github.com/epoberezkin/json-schema-migrate#readme",
"dependencies": {
"ajv": "^7.0.0-beta.9"
"ajv": "^8.0.0"
},
"devDependencies": {
"@ajv-validator/config": "^0.3.0",
Expand Down
13 changes: 12 additions & 1 deletion spec/fixtures/expected-schema-from-draft-04-to-07.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,18 @@
"alwaysValid": true,
"alsoAlwaysValid": true,
"alwaysInvalid": false,
"alsoAlwaysInvalid": false
"alsoAlwaysInvalid": false,
"array": {
"items": {"type": "number"}
},
"tuple": {
"items": [{"type": "number"}, {"type": "string"}],
"additionalItems": false
},
"tupleExtras": {
"items": [{"type": "number"}, {"type": "string"}],
"additionalItems": {"type": "boolean"}
}
},
"dependencies": {
"foo": ["bar"],
Expand Down
13 changes: 12 additions & 1 deletion spec/fixtures/expected-schema-from-draft-04-to-2019.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,18 @@
"alwaysValid": true,
"alsoAlwaysValid": true,
"alwaysInvalid": false,
"alsoAlwaysInvalid": false
"alsoAlwaysInvalid": false,
"array": {
"items": {"type": "number"}
},
"tuple": {
"items": [{"type": "number"}, {"type": "string"}],
"additionalItems": false
},
"tupleExtras": {
"items": [{"type": "number"}, {"type": "string"}],
"additionalItems": {"type": "boolean"}
}
},
"dependentRequired": {
"foo": ["bar"]
Expand Down
54 changes: 54 additions & 0 deletions spec/fixtures/expected-schema-from-draft-04-to-2020.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"$id": "my-schema",
"$schema": "https://json-schema.org/draft/2019-09/schema",
"definitions": {
"str": {
"$anchor": "str",
"type": "string"
},
"num": {
"$id": "another-schema",
"$anchor": "num",
"type": "string"
}
},
"properties": {
"exclusiveLimits": {
"exclusiveMinimum": 1,
"exclusiveMaximum": 3
},
"nonExclusiveLimits": {
"minimum": 1,
"maximum": 3
},
"singleValue": {"const": "foo"},
"singleValueConstant": {"const": "foo"},
"multipleValues": {"enum": ["foo", "bar"]},
"alwaysValid": true,
"alsoAlwaysValid": true,
"alwaysInvalid": false,
"alsoAlwaysInvalid": false,
"array": {
"items": {"type": "number"}
},
"tuple": {
"prefixItems": [{"type": "number"}, {"type": "string"}],
"items": false
},
"tupleExtras": {
"prefixItems": [{"type": "number"}, {"type": "string"}],
"items": {"type": "boolean"}
}
},
"dependentRequired": {
"foo": ["bar"]
},
"dependentSchemas": {
"bar": {
"required": ["baz"],
"properties": {
"baz": {"type": "string"}
}
}
}
}
13 changes: 12 additions & 1 deletion spec/fixtures/schema-draft-04.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,18 @@
"alwaysValid": {},
"alsoAlwaysValid": {"not": {"not": {}}},
"alwaysInvalid": {"not": {}},
"alsoAlwaysInvalid": {"not": {"not": {"not": {}}}}
"alsoAlwaysInvalid": {"not": {"not": {"not": {}}}},
"array": {
"items": {"type": "number"}
},
"tuple": {
"items": [{"type": "number"}, {"type": "string"}],
"additionalItems": false
},
"tupleExtras": {
"items": [{"type": "number"}, {"type": "string"}],
"additionalItems": {"type": "boolean"}
}
},
"dependencies": {
"foo": ["bar"],
Expand Down
9 changes: 8 additions & 1 deletion spec/migrate.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import assert = require("assert")
import {draft7, draft2019, getAjv} from ".."
import {draft7, draft2019, draft2020, getAjv} from ".."
import schemaDraft4 = require("./fixtures/schema-draft-04.json")
import expectedSchemaDraft7 = require("./fixtures/expected-schema-from-draft-04-to-07.json")
import expectedSchemaDraft2019 = require("./fixtures/expected-schema-from-draft-04-to-2019.json")
import expectedSchemaDraft2020 = require("./fixtures/expected-schema-from-draft-04-to-2020.json")
import Ajv, {AnySchemaObject} from "ajv/dist/core"

function clone(schema: AnySchemaObject): AnySchemaObject {
Expand All @@ -25,6 +26,12 @@ describe("migrate to draft-07 schema", () => {
assert.deepStrictEqual(schema, expectedSchemaDraft2019)
})

it("should migrate from draft-04 schema to draft-2020-12 schema", () => {
const schema = clone(schemaDraft4)
draft2020(schema)
assert.deepStrictEqual(schema, expectedSchemaDraft2020)
})

describe("invalid schemas", () => {
it("should throw if id is not a string", () => {
assert.throws(() => draft7({id: 1}))
Expand Down
23 changes: 20 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import Ajv, {SchemaObject, AnySchemaObject, AnySchema} from "ajv/dist/2019"
import type {DataValidationCxt, ValidateFunction} from "ajv/dist/types"

type SchemaVersion = "draft7" | "draft2019"
type SchemaVersion = "draft7" | "draft2019" | "draft2020"

export const draft7 = getMigrate("draft7")
export const draft2019 = getMigrate("draft2019")
export const draft2020 = getMigrate("draft2020")

function getMigrateSchema(version: SchemaVersion): SchemaObject {
return {
Expand Down Expand Up @@ -41,7 +42,8 @@ export function getAjv(): Ajv {
keyword: "migrateSchema",
schemaType: "string",
modifying: true,
metaSchema: {enum: ["draft7", "draft2019"]},
metaSchema: {enum: ["draft7", "draft2019", "draft2020"]},
// eslint-disable-next-line complexity
validate(
version: SchemaVersion,
dataSchema: AnySchema,
Expand All @@ -66,7 +68,7 @@ export function getAjv(): Ajv {
if (typeof id !== "string") {
throw new Error(`json-schema-migrate: schema id must be string`)
}
if (version === "draft2019" && id.includes("#")) {
if ((version === "draft2019" || version === "draft2020") && id.includes("#")) {
const [$id, $anchor, ...rest] = id.split("#")
if (rest.length > 0) {
throw new Error(`json-schema-migrate: invalid schema id ${id}`)
Expand Down Expand Up @@ -127,6 +129,21 @@ export function getAjv(): Ajv {
}
break
}
case "items":
if (version === "draft2020" && Array.isArray(dsCopy.items)) {
dataSchema.prefixItems = dsCopy.items
if (dsCopy.additionalItems !== undefined) {
dataSchema.items = dsCopy.additionalItems
}
} else {
dataSchema.items = dsCopy.items
}
break
case "additionalItems":
if (version !== "draft2020") {
dataSchema.additionalItems = dsCopy.additionalItems
}
break
default:
dataSchema[key] = dsCopy[key]
}
Expand Down

0 comments on commit 647d3bd

Please sign in to comment.