From 01abaa00ce2efe2287a3381ee184396ebb7c92da Mon Sep 17 00:00:00 2001 From: Rehan Date: Tue, 28 Dec 2021 11:58:28 +0200 Subject: [PATCH 1/8] docs: updated standalone documentation and added new examples #1831 --- docs/standalone.md | 291 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 243 insertions(+), 48 deletions(-) diff --git a/docs/standalone.md b/docs/standalone.md index 70373fd18..aab344e8e 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -2,97 +2,292 @@ [[toc]] -Ajv supports generating standalone modules with exported validation function(s), with one default export or multiple named exports, that are pre-compiled and can be used without Ajv. It is useful for several reasons: +Ajv supports generating standalone validation functions from the JSON Schema into functions at compile/build +time. These functions can then just be consumed during runtime to do validation checks against JSON. +It is useful for several reasons: -- to reduce the browser bundle size - Ajv is not included in the bundle (although if you have a large number of schemas the bundle can become bigger - when the total size of generated validation code is bigger than Ajv code). -- to reduce the start-up time - the validation and compilation of schemas will happen during build time. -- to avoid dynamic code evaluation with Function constructor (used for schema compilation) - when it is prohibited by the browser page [Content Security Policy](./security.md#content-security-policy). +- To reduce the browser bundle size - Ajv is not included in the bundle (although if you have a large number +of schemas the bundle can become bigger - when the total size of generated validation code is bigger than Ajv code). +- To reduce the start-up time - the validation and compilation of schemas will happen during build time. +- To avoid dynamic code evaluation with the function constructor (used for schema compilation) - when it is prohibited +by the browser page [Content Security Policy](./security.md#content-security-policy). -This functionality in Ajv v7 supersedes deprecated package ajv-pack that can be used with Ajv v6. All schemas, including those with recursive references, formats and user-defined keywords are supported, with few [limitations](#configuration-and-limitations). +This functionality in Ajv v7 supersedes the deprecated package ajv-pack that can be used with Ajv v6. All schemas, +including those with recursive references, formats and user-defined keywords are supported, with few +[limitations](#configuration-and-limitations). -## Usage with CLI +## Two-step process -In most cases you would use this functionality via [ajv-cli](https://github.com/ajv-validator/ajv-cli) (>= 4.0.0) to generate module that exports validation function. +The **first step** is to **generate** the standalone validation function code. This is done at compile/build time +of your project and the output is a generated JS file. The **second step** is to **consume** the generated +JS validation function. +There are two methods to generate the code, using either the Ajv CLI or the Ajv JS library. There are also a few +different options that can be passed when generating code. Below is just a highlight of a few options: + +- Set the `code.source` (JS) value to true or use the `compile` (CLI) command to generate standalone code. +- The standalone code can be generated in either ES5 or ES6, it defaults to ES5. Set the `code.es5` (JS) value to true or + pass the `--code-es5` (CLI) flag to true if you want ES5 code. +- The standalone code can be generated in either CJS (module.export & require) or ESM (exports & import), it defaults +to CJS. Set the `code.esm` (JS) value to true or pass the `--code-esm` (CLI) flag if you want ESM exported code. + +Note that the way the function is exported, differs if you are exporting a single or multiple schemas. Examples below. + +### Generating function(s) using CLI + +In most cases you would use this functionality via [ajv-cli](https://github.com/ajv-validator/ajv-cli) (>= 4.0.0) +to generate the standalone code that exports the validation function. +See [ajv-cli](https://github.com/ajv-validator/ajv-cli#compile-schemas) docs and the +[cli options](https://github.com/ajv-validator/ajv-cli#ajv-options) for additional information. + +#### Using the defaults - ES6 and CJS exports ```sh npm install -g ajv-cli ajv compile -s schema.json -o validate_schema.js ``` -`validate_schema.js` will contain the module exporting validation function that can be bundled into your application. - -See [ajv-cli](https://github.com/ajv-validator/ajv-cli) docs for additional information. - -## Usage from code +### Generating using the JS library +Install the package, version >= v7.0.0: ```sh npm install ajv ``` +#### Generating functions(s) for a single schema using the JS library - ES6 and CJS exports + ```javascript -const Ajv = require("ajv") // version >= v7.0.0 -const ajv = new Ajv({code: {source: true}}) // this option is required to generate standalone code +const fs = require("fs") +const path = require("path") +const Ajv = require("ajv") const standaloneCode = require("ajv/dist/standalone").default const schema = { - $id: "https://example.com/object.json", + $id: "https://example.com/bar.json", + $schema: "http://json-schema.org/draft-07/schema#", type: "object", properties: { - foo: { - type: "string", - pattern: "^[a-z]+$", + bar: { + type: "string" }, }, + "required": [ + "bar", + ] } -// 1. generate module with a single default export (CommonJS and ESM compatible): +// The generated code will have a default export: +// `module.exports = ;module.exports.default = ;` +const ajv = new Ajv({code: {source: true}}) const validate = ajv.compile(schema) let moduleCode = standaloneCode(ajv, validate) -// 2. pass map of schema IDs to generate multiple exports, -// it avoids code duplication if schemas are mutually recursive or have some share elements: -let moduleCode = standaloneCode(ajv, { - validateObject: "https://example.com/object.json", -}) +// Now you can write the module code to file +fs.writeFileSync(path.join(__dirname, "../consume/validate-cjs.js"), moduleCode) +``` + +#### Generating functions(s) for multiple schemas using the JS library - ES6 and CJS exports + +```javascript +const fs = require("fs") +const path = require("path") +const Ajv = require("ajv") +const standaloneCode = require("ajv/dist/standalone").default + +const schemaFoo = { + $id: "#/definitions/Foo", + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + foo: { + "$ref": "#/definitions/Bar" + } + } +} +const schemaBar = { + $id: "#/definitions/Bar", + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + bar: { + type: "string" + }, + }, + "required": [ + "bar", + ] +} -// 3. or generate module with all schemas added to the instance (excluding meta-schemas), -// export names would use schema IDs (or keys passed to addSchema method): +// For CJS, it generates an exports array, will generate +// `exports["#/definitions/Foo"] = ...;exports["#/definitions/Bar"] = ... ;` +const ajv = new Ajv({schemas: [schemaFoo, schemaBar], code: {source: true}}) let moduleCode = standaloneCode(ajv) -// now you can -// write module code to file +// Now you can write the module code to file +fs.writeFileSync(path.join(__dirname, "../consume/validate-cjs.js"), moduleCode) +``` + +#### Generating functions(s) for multiple schemas using the JS library - ES6 and ESM exports + +```javascript const fs = require("fs") const path = require("path") -fs.writeFileSync(path.join(__dirname, "/validate.js"), moduleCode) +const Ajv = require("ajv") +const standaloneCode = require("ajv/dist/standalone").default + +const schemaFoo = { + $id: "#/definitions/Foo", + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + foo: { + "$ref": "#/definitions/Bar" + } + } +} +const schemaBar = { + $id: "#/definitions/Bar", + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + bar: { + type: "string" + }, + }, + "required": [ + "bar", + ] +} + +// For ESM, the export name needs to be a valid export name, it can not be `export const #/definitions/Foo = ...;` so we +// need to provide a mapping between a valid name and the $id field. Below will generate +// `export const Foo = ...;export const Bar = ...;` +// This mapping would not have been needed if the `$ids` was just `Bar` and `Foo` instead of `#/definitions/Foo` +// and `#/definitions/Bar` respectfully +const ajv = new Ajv({schemas: [schemaFoo, schemaBar], code: {source: true, esm: true}}) +let moduleCode = standaloneCode(ajv, { + "Foo": "#/definitions/Foo", + "Bar": "#/definitions/Bar" +}) + +// Now you can write the module code to file +fs.writeFileSync(path.join(__dirname, "../consume/validate-esm.mjs"), moduleCode) +``` + +::: warning ESM name mapping +The ESM version only requires the mapping if the ids are not valid export names. If the $ids were just the +`Foo` and `Bar` instead of `#/definitions/Foo` and `#/definitions/Bar` then the mapping would not be needed. +::: + + +## Using the validation function(s) + +### Validating a single schemas using the JS library - ES6 and CJS + +```javascript +const Bar = require('./validate-cjs') + +const barPass = { + bar: "something" +} + +const barFail = { + // bar: "something" // <= empty/omitted property that is required +} + +let validateBar = Bar +if (!validateBar(barPass)) + console.log("ERRORS 1:", validateBar.errors) //Never reaches this because valid + +if (!validateBar(barFail)) + console.log("ERRORS 2:", validateBar.errors) //Errors array gets logged +``` + +### Validating multiple schemas using the JS library - ES6 and CJS + +```javascript +const validations = require('./validate-cjs') -// ... or require module from string -const requireFromString = require("require-from-string") -const standaloneValidate = requireFromString(moduleCode) // for a single default export +const fooPass = { + foo: { + bar: "something" + } +} + +const fooFail = { + foo: { + // bar: "something" // <= empty/omitted property that is required + } +} + +let validateFoo = validations["#/definitions/Foo"]; +if (!validateFoo(fooPass)) + console.log("ERRORS 1:", validateFoo.errors); //Never reaches this because valid + +if (!validateFoo(fooFail)) + console.log("ERRORS 2:", validateFoo.errors); //Errors array gets logged + +``` + +### Validating multiple schemas using the JS library - ES6 and ESM +```javascript +import {Foo, Bar} from './validate-multiple-esm.mjs'; + +const fooPass = { + foo: { + bar: "something" + } +} + +const fooFail = { + foo: { + // bar: "something" // bar: "something" <= empty properties + } +} + +let validateFoo = Foo; +if (!validateFoo(fooPass)) + console.log("ERRORS 1:", validateFoo.errors); //Never reaches here because valid + +if (!validateFoo(fooFail)) + console.log("ERRORS 2:", validateFoo.errors); //Errors array gets logged ``` + ### Requirement at runtime -To run the standalone generated functions, the Ajv package should still be a run-time dependency for most schemas, but generated modules can only depend on code in [runtime](https://github.com/ajv-validator/ajv/tree/master/lib/runtime) folder, so the whole Ajv will not be included in the bundle (or executed) if you require the modules with standalone validation code from your application code. +One of the main reason for using the standalone mode is to compile the JSON schema into functions at build +time and then just consume them during runtime. This prevents the initial compilation at runtime which saves time at runtime. + +It is important to understand that the standalone generated functions still has a dependency on the Ajv. Specifically +on the code in the [runtime](https://github.com/ajv-validator/ajv/tree/master/lib/runtime) folder of the package. + +Completely isolated validation functions can be generated if desired (won't be for most use cases). Run the generated code +through a bundler like ES Build to create completely isolated validation functions that can be imported/required +without any dependency on Ajv. This is also not needed if your project is already using a bundler. ## Configuration and limitations To support standalone code generation: -- Ajv option `source.code` must be set to `true` -- only `code` and `macro` user-defined keywords are supported (see [User defined keywords](./keywords.md)). -- when `code` keywords define variables in shared scope using `gen.scopeValue`, they must provide `code` property with the code snippet. See source code of pre-defined keywords for examples in [vocabularies folder](https://github.com/ajv-validator/ajv/blob/master/lib/vocabularies). -- if formats are used in standalone code, ajv option `code.formats` should contain the code snippet that will evaluate to an object with all used format definitions - it can be a call to `require("...")` with the correct path (relative to the location of saved module): +- Ajv option `code.source` must be set to `true` +- Only `code` and `macro` user-defined keywords are supported (see [User defined keywords](./keywords.md)). +- When `code` keywords define variables in shared scope using `gen.scopeValue`, they must provide `code` property with +the code snippet. See source code of pre-defined keywords for examples in +[vocabularies folder](https://github.com/ajv-validator/ajv/blob/master/lib/vocabularies). +- If formats are used in standalone code, ajv option `code.formats` should contain the code snippet that will evaluate +to an object with all used format definitions - it can be a call to `require("...")` with the correct path +(relative to the location of saved module): -```javascript -import myFormats from "./my-formats" -import Ajv, {_} from "ajv" -const ajv = new Ajv({ - formats: myFormats, - code: { - source: true, - formats: _`require("./my-formats")`, - }, -}) -``` + ```javascript + import myFormats from "./my-formats" + import Ajv, {_} from "ajv" + const ajv = new Ajv({ + formats: myFormats, + code: { + source: true, + formats: _`require("./my-formats")`, + }, + }) + ``` If you only use formats from [ajv-formats](https://github.com/ajv-validator/ajv-formats) this option will be set by this package automatically. From e490152974a53daeb0f6d2978f1f10d9b2c4a106 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 15 Jan 2022 09:10:33 +0000 Subject: [PATCH 2/8] remove unnecessary line breaks --- docs/standalone.md | 59 +++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 37 deletions(-) diff --git a/docs/standalone.md b/docs/standalone.md index aab344e8e..eba447bb7 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -2,28 +2,19 @@ [[toc]] -Ajv supports generating standalone validation functions from the JSON Schema into functions at compile/build -time. These functions can then just be consumed during runtime to do validation checks against JSON. -It is useful for several reasons: +Ajv supports generating standalone validation functions from the JSON Schema into functions at compile/build time. These functions can then just be consumed during runtime to do validation checks against JSON. It is useful for several reasons: -- To reduce the browser bundle size - Ajv is not included in the bundle (although if you have a large number -of schemas the bundle can become bigger - when the total size of generated validation code is bigger than Ajv code). +- To reduce the browser bundle size - Ajv is not included in the bundle (although if you have a large number of schemas the bundle can become bigger - when the total size of generated validation code is bigger than Ajv code). - To reduce the start-up time - the validation and compilation of schemas will happen during build time. -- To avoid dynamic code evaluation with the function constructor (used for schema compilation) - when it is prohibited -by the browser page [Content Security Policy](./security.md#content-security-policy). +- To avoid dynamic code evaluation with the function constructor (used for schema compilation) - when it is prohibited by the browser page [Content Security Policy](./security.md#content-security-policy). -This functionality in Ajv v7 supersedes the deprecated package ajv-pack that can be used with Ajv v6. All schemas, -including those with recursive references, formats and user-defined keywords are supported, with few -[limitations](#configuration-and-limitations). +This functionality in Ajv v7 supersedes the deprecated package ajv-pack that can be used with Ajv v6. All schemas, including those with recursive references, formats and user-defined keywords are supported, with few [limitations](#configuration-and-limitations). ## Two-step process -The **first step** is to **generate** the standalone validation function code. This is done at compile/build time -of your project and the output is a generated JS file. The **second step** is to **consume** the generated -JS validation function. +The **first step** is to **generate** the standalone validation function code. This is done at compile/build time of your project and the output is a generated JS file. The **second step** is to **consume** the generated JS validation function. -There are two methods to generate the code, using either the Ajv CLI or the Ajv JS library. There are also a few -different options that can be passed when generating code. Below is just a highlight of a few options: +There are two methods to generate the code, using either the Ajv CLI or the Ajv JS library. There are also a few different options that can be passed when generating code. Below is just a highlight of a few options: - Set the `code.source` (JS) value to true or use the `compile` (CLI) command to generate standalone code. - The standalone code can be generated in either ES5 or ES6, it defaults to ES5. Set the `code.es5` (JS) value to true or @@ -229,6 +220,7 @@ if (!validateFoo(fooFail)) ``` ### Validating multiple schemas using the JS library - ES6 and ESM + ```javascript import {Foo, Bar} from './validate-multiple-esm.mjs'; @@ -255,11 +247,9 @@ if (!validateFoo(fooFail)) ### Requirement at runtime -One of the main reason for using the standalone mode is to compile the JSON schema into functions at build -time and then just consume them during runtime. This prevents the initial compilation at runtime which saves time at runtime. +One of the main reason for using the standalone mode is to compile the JSON schema into functions at build time and then just consume them during runtime. This prevents the initial compilation at runtime which saves time at runtime. -It is important to understand that the standalone generated functions still has a dependency on the Ajv. Specifically -on the code in the [runtime](https://github.com/ajv-validator/ajv/tree/master/lib/runtime) folder of the package. +It is important to understand that the standalone generated functions still has a dependency on the Ajv. Specifically on the code in the [runtime](https://github.com/ajv-validator/ajv/tree/master/lib/runtime) folder of the package. Completely isolated validation functions can be generated if desired (won't be for most use cases). Run the generated code through a bundler like ES Build to create completely isolated validation functions that can be imported/required @@ -271,23 +261,18 @@ To support standalone code generation: - Ajv option `code.source` must be set to `true` - Only `code` and `macro` user-defined keywords are supported (see [User defined keywords](./keywords.md)). -- When `code` keywords define variables in shared scope using `gen.scopeValue`, they must provide `code` property with -the code snippet. See source code of pre-defined keywords for examples in -[vocabularies folder](https://github.com/ajv-validator/ajv/blob/master/lib/vocabularies). -- If formats are used in standalone code, ajv option `code.formats` should contain the code snippet that will evaluate -to an object with all used format definitions - it can be a call to `require("...")` with the correct path -(relative to the location of saved module): - - ```javascript - import myFormats from "./my-formats" - import Ajv, {_} from "ajv" - const ajv = new Ajv({ - formats: myFormats, - code: { - source: true, - formats: _`require("./my-formats")`, - }, - }) - ``` +- When `code` keywords define variables in shared scope using `gen.scopeValue`, they must provide `code` property with the code snippet. See source code of pre-defined keywords for examples in [vocabularies folder](https://github.com/ajv-validator/ajv/blob/master/lib/vocabularies). +- If formats are used in standalone code, ajv option `code.formats` should contain the code snippet that will evaluate to an object with all used format definitions - it can be a call to `require("...")` with the correct path (relative to the location of saved module): + +```javascript +import myFormats from "./my-formats" +import Ajv, {_} from "ajv" +const ajv = new Ajv({ + formats: myFormats, + code: { + source: true, + formats: _`require("./my-formats")`, + }, +}) If you only use formats from [ajv-formats](https://github.com/ajv-validator/ajv-formats) this option will be set by this package automatically. From 47c7fd8416ce568c7a6c4aabac2a1184b0cea115 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 15 Jan 2022 09:12:00 +0000 Subject: [PATCH 3/8] remove style changes --- docs/standalone.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/standalone.md b/docs/standalone.md index eba447bb7..095772564 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -4,9 +4,9 @@ Ajv supports generating standalone validation functions from the JSON Schema into functions at compile/build time. These functions can then just be consumed during runtime to do validation checks against JSON. It is useful for several reasons: -- To reduce the browser bundle size - Ajv is not included in the bundle (although if you have a large number of schemas the bundle can become bigger - when the total size of generated validation code is bigger than Ajv code). -- To reduce the start-up time - the validation and compilation of schemas will happen during build time. -- To avoid dynamic code evaluation with the function constructor (used for schema compilation) - when it is prohibited by the browser page [Content Security Policy](./security.md#content-security-policy). +- to reduce the browser bundle size - Ajv is not included in the bundle (although if you have a large number of schemas the bundle can become bigger - when the total size of generated validation code is bigger than Ajv code). +- to reduce the start-up time - the validation and compilation of schemas will happen during build time. +- to avoid dynamic code evaluation with Function constructor (used for schema compilation) - when it is prohibited by the browser page [Content Security Policy](./security.md#content-security-policy). This functionality in Ajv v7 supersedes the deprecated package ajv-pack that can be used with Ajv v6. All schemas, including those with recursive references, formats and user-defined keywords are supported, with few [limitations](#configuration-and-limitations). From a1bb3a8278437e70a2ccc86091f94f68182db6b7 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 15 Jan 2022 09:17:54 +0000 Subject: [PATCH 4/8] minor corrections --- docs/standalone.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/docs/standalone.md b/docs/standalone.md index 095772564..32a62240a 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -2,7 +2,7 @@ [[toc]] -Ajv supports generating standalone validation functions from the JSON Schema into functions at compile/build time. These functions can then just be consumed during runtime to do validation checks against JSON. It is useful for several reasons: +Ajv supports generating standalone validation functions from JSON Schemas at compile/build time. These functions can then be used during runtime to do validation without initialising Ajv. It is useful for several reasons: - to reduce the browser bundle size - Ajv is not included in the bundle (although if you have a large number of schemas the bundle can become bigger - when the total size of generated validation code is bigger than Ajv code). - to reduce the start-up time - the validation and compilation of schemas will happen during build time. @@ -12,7 +12,7 @@ This functionality in Ajv v7 supersedes the deprecated package ajv-pack that can ## Two-step process -The **first step** is to **generate** the standalone validation function code. This is done at compile/build time of your project and the output is a generated JS file. The **second step** is to **consume** the generated JS validation function. +The **first step** is to **generate** the standalone validation function code. This is done at compile/build time of your project and the output is a generated JS file. The **second step** is to **use** the generated JS validation function. There are two methods to generate the code, using either the Ajv CLI or the Ajv JS library. There are also a few different options that can be passed when generating code. Below is just a highlight of a few options: @@ -22,14 +22,11 @@ There are two methods to generate the code, using either the Ajv CLI or the Ajv - The standalone code can be generated in either CJS (module.export & require) or ESM (exports & import), it defaults to CJS. Set the `code.esm` (JS) value to true or pass the `--code-esm` (CLI) flag if you want ESM exported code. -Note that the way the function is exported, differs if you are exporting a single or multiple schemas. Examples below. +Note that the way the function is exported, differs if you are exporting a single or multiple schemas. See examples below. ### Generating function(s) using CLI -In most cases you would use this functionality via [ajv-cli](https://github.com/ajv-validator/ajv-cli) (>= 4.0.0) -to generate the standalone code that exports the validation function. -See [ajv-cli](https://github.com/ajv-validator/ajv-cli#compile-schemas) docs and the -[cli options](https://github.com/ajv-validator/ajv-cli#ajv-options) for additional information. +In most cases you would use this functionality via [ajv-cli](https://github.com/ajv-validator/ajv-cli) (>= 4.0.0) to generate the standalone code that exports the validation function. See [ajv-cli](https://github.com/ajv-validator/ajv-cli#compile-schemas) docs and the [cli options](https://github.com/ajv-validator/ajv-cli#ajv-options) for additional information. #### Using the defaults - ES6 and CJS exports ```sh @@ -57,13 +54,9 @@ const schema = { $schema: "http://json-schema.org/draft-07/schema#", type: "object", properties: { - bar: { - type: "string" - }, + bar: {type: "string"}, }, - "required": [ - "bar", - ] + "required": ["bar"] } // The generated code will have a default export: From 8be8f1a103ba034cab850b13f5d0060177599133 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 15 Jan 2022 09:22:32 +0000 Subject: [PATCH 5/8] minor corrections --- docs/standalone.md | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/docs/standalone.md b/docs/standalone.md index 32a62240a..c151fce56 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -82,9 +82,7 @@ const schemaFoo = { $schema: "http://json-schema.org/draft-07/schema#", type: "object", properties: { - foo: { - "$ref": "#/definitions/Bar" - } + foo: {"$ref": "#/definitions/Bar"} } } const schemaBar = { @@ -92,13 +90,9 @@ const schemaBar = { $schema: "http://json-schema.org/draft-07/schema#", type: "object", properties: { - bar: { - type: "string" - }, + bar: {type: "string"}, }, - "required": [ - "bar", - ] + "required": ["bar"] } // For CJS, it generates an exports array, will generate @@ -123,9 +117,7 @@ const schemaFoo = { $schema: "http://json-schema.org/draft-07/schema#", type: "object", properties: { - foo: { - "$ref": "#/definitions/Bar" - } + foo: {"$ref": "#/definitions/Bar"} } } const schemaBar = { @@ -133,13 +125,9 @@ const schemaBar = { $schema: "http://json-schema.org/draft-07/schema#", type: "object", properties: { - bar: { - type: "string" - }, + bar: {type: "string"}, }, - "required": [ - "bar", - ] + "required": ["bar"] } // For ESM, the export name needs to be a valid export name, it can not be `export const #/definitions/Foo = ...;` so we @@ -240,9 +228,9 @@ if (!validateFoo(fooFail)) ### Requirement at runtime -One of the main reason for using the standalone mode is to compile the JSON schema into functions at build time and then just consume them during runtime. This prevents the initial compilation at runtime which saves time at runtime. +One of the main reason for using the standalone mode is to start applications faster to avoid runtime schema compilation. -It is important to understand that the standalone generated functions still has a dependency on the Ajv. Specifically on the code in the [runtime](https://github.com/ajv-validator/ajv/tree/master/lib/runtime) folder of the package. +The standalone generated functions still has a dependency on the Ajv. Specifically on the code in the [runtime](https://github.com/ajv-validator/ajv/tree/master/lib/runtime) folder of the package. Completely isolated validation functions can be generated if desired (won't be for most use cases). Run the generated code through a bundler like ES Build to create completely isolated validation functions that can be imported/required @@ -253,9 +241,9 @@ without any dependency on Ajv. This is also not needed if your project is alread To support standalone code generation: - Ajv option `code.source` must be set to `true` -- Only `code` and `macro` user-defined keywords are supported (see [User defined keywords](./keywords.md)). -- When `code` keywords define variables in shared scope using `gen.scopeValue`, they must provide `code` property with the code snippet. See source code of pre-defined keywords for examples in [vocabularies folder](https://github.com/ajv-validator/ajv/blob/master/lib/vocabularies). -- If formats are used in standalone code, ajv option `code.formats` should contain the code snippet that will evaluate to an object with all used format definitions - it can be a call to `require("...")` with the correct path (relative to the location of saved module): +- only `code` and `macro` user-defined keywords are supported (see [User defined keywords](./keywords.md)). +- when `code` keywords define variables in shared scope using `gen.scopeValue`, they must provide `code` property with the code snippet. See source code of pre-defined keywords for examples in [vocabularies folder](https://github.com/ajv-validator/ajv/blob/master/lib/vocabularies). +- if formats are used in standalone code, ajv option `code.formats` should contain the code snippet that will evaluate to an object with all used format definitions - it can be a call to `require("...")` with the correct path (relative to the location of saved module): ```javascript import myFormats from "./my-formats" From cd874d18ea1771dcd1cc7346ca91c7c2cf096dac Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 15 Jan 2022 09:23:08 +0000 Subject: [PATCH 6/8] Update docs/standalone.md --- docs/standalone.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/standalone.md b/docs/standalone.md index c151fce56..919c68bd3 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -232,9 +232,7 @@ One of the main reason for using the standalone mode is to start applications fa The standalone generated functions still has a dependency on the Ajv. Specifically on the code in the [runtime](https://github.com/ajv-validator/ajv/tree/master/lib/runtime) folder of the package. -Completely isolated validation functions can be generated if desired (won't be for most use cases). Run the generated code -through a bundler like ES Build to create completely isolated validation functions that can be imported/required -without any dependency on Ajv. This is also not needed if your project is already using a bundler. +Completely isolated validation functions can be generated if desired (won't be for most use cases). Run the generated code through a bundler like ES Build to create completely isolated validation functions that can be imported/required without any dependency on Ajv. This is also not needed if your project is already using a bundler. ## Configuration and limitations From c763565dab673acef867cf1c2ccee926662db09b Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 15 Jan 2022 09:23:24 +0000 Subject: [PATCH 7/8] Update docs/standalone.md --- docs/standalone.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/standalone.md b/docs/standalone.md index 919c68bd3..68aab1db9 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -19,8 +19,7 @@ There are two methods to generate the code, using either the Ajv CLI or the Ajv - Set the `code.source` (JS) value to true or use the `compile` (CLI) command to generate standalone code. - The standalone code can be generated in either ES5 or ES6, it defaults to ES5. Set the `code.es5` (JS) value to true or pass the `--code-es5` (CLI) flag to true if you want ES5 code. -- The standalone code can be generated in either CJS (module.export & require) or ESM (exports & import), it defaults -to CJS. Set the `code.esm` (JS) value to true or pass the `--code-esm` (CLI) flag if you want ESM exported code. +- The standalone code can be generated in either CJS (module.export & require) or ESM (exports & import), it defaults to CJS. Set the `code.esm` (JS) value to true or pass the `--code-esm` (CLI) flag if you want ESM exported code. Note that the way the function is exported, differs if you are exporting a single or multiple schemas. See examples below. From 13d7ac2a457dacf5a43719e210ad79efc899a689 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 15 Jan 2022 09:23:33 +0000 Subject: [PATCH 8/8] Update docs/standalone.md --- docs/standalone.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/standalone.md b/docs/standalone.md index 68aab1db9..5b32b73e7 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -17,8 +17,7 @@ The **first step** is to **generate** the standalone validation function code. T There are two methods to generate the code, using either the Ajv CLI or the Ajv JS library. There are also a few different options that can be passed when generating code. Below is just a highlight of a few options: - Set the `code.source` (JS) value to true or use the `compile` (CLI) command to generate standalone code. -- The standalone code can be generated in either ES5 or ES6, it defaults to ES5. Set the `code.es5` (JS) value to true or - pass the `--code-es5` (CLI) flag to true if you want ES5 code. +- The standalone code can be generated in either ES5 or ES6, it defaults to ES6. Set the `code.es5` (JS) value to true or pass the `--code-es5` (CLI) flag to true if you want ES5 code. - The standalone code can be generated in either CJS (module.export & require) or ESM (exports & import), it defaults to CJS. Set the `code.esm` (JS) value to true or pass the `--code-esm` (CLI) flag if you want ESM exported code. Note that the way the function is exported, differs if you are exporting a single or multiple schemas. See examples below.