Skip to content

Commit

Permalink
feat: added API to disable and enable validation (#180)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait authored Jun 14, 2023
1 parent 3a39ad5 commit d6b9c9e
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 6 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,36 @@ class Plugin {
export default Plugin;
```

### Allow to disable and enable validation (the `validate` function do nothing)

This can be useful when you don't want to do validation for `production` builds.

```js
import { disableValidation, enableValidation, validate } from "schema-utils";

// Disable validation
disableValidation();
// Do nothing
validate(schema, options);

// Enable validation
enableValidation();
// Will throw an error if schema is not valid
validate(schema, options);

// Allow to undestand do you need validation or not
const need = needValidate();

console.log(need);
```

Also you can enable/disable validation using the `process.env.SKIP_VALIDATION` env variable.

Supported values (case insensitive):

- `yes`/`y`/`true`/`1`/`on`
- `no`/`n`/`false`/`0`/`off`

## Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.
Expand Down
11 changes: 10 additions & 1 deletion declarations/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import { validate } from "./validate";
import { ValidationError } from "./validate";
export { validate, ValidationError };
import { enableValidation } from "./validate";
import { disableValidation } from "./validate";
import { needValidate } from "./validate";
export {
validate,
ValidationError,
enableValidation,
disableValidation,
needValidate,
};
3 changes: 3 additions & 0 deletions declarations/validate.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,8 @@ export function validate(
options: Array<object> | object,
configuration?: ValidationErrorConfiguration | undefined
): void;
export function enableValidation(): void;
export function disableValidation(): void;
export function needValidate(): boolean;
import ValidationError from "./ValidationError";
export { ValidationError };
16 changes: 14 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
const { validate, ValidationError } = require("./validate");
const {
validate,
ValidationError,
enableValidation,
disableValidation,
needValidate,
} = require("./validate");

module.exports = { validate, ValidationError };
module.exports = {
validate,
ValidationError,
enableValidation,
disableValidation,
needValidate,
};
59 changes: 57 additions & 2 deletions src/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const getAjv = memoize(() => {

/** @typedef {(JSONSchema4 | JSONSchema6 | JSONSchema7) & Extend} Schema */

/** @typedef {ErrorObject & { children?: Array<ErrorObject>}} SchemaUtilErrorObject */
/** @typedef {ErrorObject & { children?: Array<ErrorObject> }} SchemaUtilErrorObject */

/**
* @callback PostFormatter
Expand Down Expand Up @@ -87,13 +87,62 @@ function applyPrefix(error, idx) {
return error;
}

let skipValidation = false;

// We use `process.env.SKIP_VALIDATION` because you can have multiple `schema-utils` with different version,
// so we want to disable it globally, `process.env` doesn't supported by browsers, so we have the local `skipValidation` variables

// Enable validation
function enableValidation() {
skipValidation = false;

// Disable validation for any versions
if (process && process.env) {
process.env.SKIP_VALIDATION = "n";
}
}

// Disable validation
function disableValidation() {
skipValidation = true;

if (process && process.env) {
process.env.SKIP_VALIDATION = "y";
}
}

// Check if we need to confirm
function needValidate() {
if (skipValidation) {
return false;
}

if (process && process.env && process.env.SKIP_VALIDATION) {
const value = process.env.SKIP_VALIDATION.trim();

if (/^(?:y|yes|true|1|on)$/i.test(value)) {
return false;
}

if (/^(?:n|no|false|0|off)$/i.test(value)) {
return true;
}
}

return true;
}

/**
* @param {Schema} schema
* @param {Array<object> | object} options
* @param {ValidationErrorConfiguration=} configuration
* @returns {void}
*/
function validate(schema, options, configuration) {
if (!needValidate()) {
return;
}

let errors = [];

if (Array.isArray(options)) {
Expand Down Expand Up @@ -165,4 +214,10 @@ function filterErrors(errors) {
return newErrors;
}

export { validate, ValidationError };
export {
validate,
enableValidation,
disableValidation,
needValidate,
ValidationError,
};
18 changes: 18 additions & 0 deletions test/__snapshots__/api.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`api should allow to enable validation using "process.env.SKIP_VALIDATION" #2 1`] = `
"Invalid options object. NAME has been initialized using an options object that does not match the API schema.
- options has an unknown property 'foo'. These properties are valid:
object { name? }"
`;
exports[`api should allow to enable validation using "process.env.SKIP_VALIDATION" 1`] = `
"Invalid options object. NAME has been initialized using an options object that does not match the API schema.
- options has an unknown property 'foo'. These properties are valid:
object { name? }"
`;
exports[`api should allow to enable validation using API 1`] = `
"Invalid options object. NAME has been initialized using an options object that does not match the API schema.
- options has an unknown property 'foo'. These properties are valid:
object { name? }"
`;
exports[`api should get configuration from schema 1`] = `
"Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'foo'. These properties are valid:
Expand Down
137 changes: 136 additions & 1 deletion test/api.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { validate, ValidationError } from "../src/index";
import {
validate,
ValidationError,
enableValidation,
disableValidation,
needValidate,
} from "../src/index";

import schema from "./fixtures/schema.json";
import schemaTitle from "./fixtures/schema-title.json";
Expand Down Expand Up @@ -196,4 +202,133 @@ describe("api", () => {
expect(error.message).toMatchSnapshot();
}
});

it('should allow to disable validation using "process.env.SKIP_VALIDATION"', () => {
const oldValue = process.env.SKIP_VALIDATION;

let errored;

process.env.SKIP_VALIDATION = "y";

try {
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
} catch (error) {
errored = error;
}

expect(errored).toBeUndefined();

process.env.SKIP_VALIDATION = oldValue;
});

it('should allow to disable validation using "process.env.SKIP_VALIDATION" #2', () => {
const oldValue = process.env.SKIP_VALIDATION;

let errored;

process.env.SKIP_VALIDATION = "YeS";

try {
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
} catch (error) {
errored = error;
}

expect(errored).toBeUndefined();

process.env.SKIP_VALIDATION = oldValue;
});

it('should allow to enable validation using "process.env.SKIP_VALIDATION"', () => {
const oldValue = process.env.SKIP_VALIDATION;

process.env.SKIP_VALIDATION = "n";

try {
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
} catch (error) {
if (error.name !== "ValidationError") {
throw error;
}

expect(error.message).toMatchSnapshot();
}

process.env.SKIP_VALIDATION = oldValue;
});

it('should allow to enable validation using "process.env.SKIP_VALIDATION" #2', () => {
const oldValue = process.env.SKIP_VALIDATION;

process.env.SKIP_VALIDATION = " FaLse ";

try {
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
} catch (error) {
if (error.name !== "ValidationError") {
throw error;
}

expect(error.message).toMatchSnapshot();
}

process.env.SKIP_VALIDATION = oldValue;
});

it("should allow to disable validation using API", () => {
let errored;

disableValidation();

try {
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
} catch (error) {
errored = error;
}

expect(errored).toBeUndefined();

enableValidation();
});

it("should allow to enable validation using API", () => {
disableValidation();
enableValidation();

try {
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
} catch (error) {
if (error.name !== "ValidationError") {
throw error;
}

expect(error.message).toMatchSnapshot();
}
});

it("should allow to enable and disable validation using API", () => {
enableValidation();
expect(needValidate()).toBe(true);

disableValidation();
expect(needValidate()).toBe(false);
enableValidation();

enableValidation();
enableValidation();
expect(needValidate()).toBe(true);

enableValidation();
disableValidation();
expect(needValidate()).toBe(false);
enableValidation();

enableValidation();
expect(process.env.SKIP_VALIDATION).toBe("n");

disableValidation();
expect(process.env.SKIP_VALIDATION).toBe("y");
enableValidation();
expect(process.env.SKIP_VALIDATION).toBe("n");
});
});

0 comments on commit d6b9c9e

Please sign in to comment.