Skip to content

Commit d6b9c9e

Browse files
feat: added API to disable and enable validation (#180)
1 parent 3a39ad5 commit d6b9c9e

File tree

7 files changed

+268
-6
lines changed

7 files changed

+268
-6
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,36 @@ class Plugin {
263263
export default Plugin;
264264
```
265265

266+
### Allow to disable and enable validation (the `validate` function do nothing)
267+
268+
This can be useful when you don't want to do validation for `production` builds.
269+
270+
```js
271+
import { disableValidation, enableValidation, validate } from "schema-utils";
272+
273+
// Disable validation
274+
disableValidation();
275+
// Do nothing
276+
validate(schema, options);
277+
278+
// Enable validation
279+
enableValidation();
280+
// Will throw an error if schema is not valid
281+
validate(schema, options);
282+
283+
// Allow to undestand do you need validation or not
284+
const need = needValidate();
285+
286+
console.log(need);
287+
```
288+
289+
Also you can enable/disable validation using the `process.env.SKIP_VALIDATION` env variable.
290+
291+
Supported values (case insensitive):
292+
293+
- `yes`/`y`/`true`/`1`/`on`
294+
- `no`/`n`/`false`/`0`/`off`
295+
266296
## Contributing
267297

268298
Please take a moment to read our contributing guidelines if you haven't yet done so.

declarations/index.d.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
import { validate } from "./validate";
22
import { ValidationError } from "./validate";
3-
export { validate, ValidationError };
3+
import { enableValidation } from "./validate";
4+
import { disableValidation } from "./validate";
5+
import { needValidate } from "./validate";
6+
export {
7+
validate,
8+
ValidationError,
9+
enableValidation,
10+
disableValidation,
11+
needValidate,
12+
};

declarations/validate.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,8 @@ export function validate(
3434
options: Array<object> | object,
3535
configuration?: ValidationErrorConfiguration | undefined
3636
): void;
37+
export function enableValidation(): void;
38+
export function disableValidation(): void;
39+
export function needValidate(): boolean;
3740
import ValidationError from "./ValidationError";
3841
export { ValidationError };

src/index.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1-
const { validate, ValidationError } = require("./validate");
1+
const {
2+
validate,
3+
ValidationError,
4+
enableValidation,
5+
disableValidation,
6+
needValidate,
7+
} = require("./validate");
28

3-
module.exports = { validate, ValidationError };
9+
module.exports = {
10+
validate,
11+
ValidationError,
12+
enableValidation,
13+
disableValidation,
14+
needValidate,
15+
};

src/validate.js

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const getAjv = memoize(() => {
5555

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

58-
/** @typedef {ErrorObject & { children?: Array<ErrorObject>}} SchemaUtilErrorObject */
58+
/** @typedef {ErrorObject & { children?: Array<ErrorObject> }} SchemaUtilErrorObject */
5959

6060
/**
6161
* @callback PostFormatter
@@ -87,13 +87,62 @@ function applyPrefix(error, idx) {
8787
return error;
8888
}
8989

90+
let skipValidation = false;
91+
92+
// We use `process.env.SKIP_VALIDATION` because you can have multiple `schema-utils` with different version,
93+
// so we want to disable it globally, `process.env` doesn't supported by browsers, so we have the local `skipValidation` variables
94+
95+
// Enable validation
96+
function enableValidation() {
97+
skipValidation = false;
98+
99+
// Disable validation for any versions
100+
if (process && process.env) {
101+
process.env.SKIP_VALIDATION = "n";
102+
}
103+
}
104+
105+
// Disable validation
106+
function disableValidation() {
107+
skipValidation = true;
108+
109+
if (process && process.env) {
110+
process.env.SKIP_VALIDATION = "y";
111+
}
112+
}
113+
114+
// Check if we need to confirm
115+
function needValidate() {
116+
if (skipValidation) {
117+
return false;
118+
}
119+
120+
if (process && process.env && process.env.SKIP_VALIDATION) {
121+
const value = process.env.SKIP_VALIDATION.trim();
122+
123+
if (/^(?:y|yes|true|1|on)$/i.test(value)) {
124+
return false;
125+
}
126+
127+
if (/^(?:n|no|false|0|off)$/i.test(value)) {
128+
return true;
129+
}
130+
}
131+
132+
return true;
133+
}
134+
90135
/**
91136
* @param {Schema} schema
92137
* @param {Array<object> | object} options
93138
* @param {ValidationErrorConfiguration=} configuration
94139
* @returns {void}
95140
*/
96141
function validate(schema, options, configuration) {
142+
if (!needValidate()) {
143+
return;
144+
}
145+
97146
let errors = [];
98147

99148
if (Array.isArray(options)) {
@@ -165,4 +214,10 @@ function filterErrors(errors) {
165214
return newErrors;
166215
}
167216

168-
export { validate, ValidationError };
217+
export {
218+
validate,
219+
enableValidation,
220+
disableValidation,
221+
needValidate,
222+
ValidationError,
223+
};

test/__snapshots__/api.test.js.snap

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`api should allow to enable validation using "process.env.SKIP_VALIDATION" #2 1`] = `
4+
"Invalid options object. NAME has been initialized using an options object that does not match the API schema.
5+
- options has an unknown property 'foo'. These properties are valid:
6+
object { name? }"
7+
`;
8+
9+
exports[`api should allow to enable validation using "process.env.SKIP_VALIDATION" 1`] = `
10+
"Invalid options object. NAME has been initialized using an options object that does not match the API schema.
11+
- options has an unknown property 'foo'. These properties are valid:
12+
object { name? }"
13+
`;
14+
15+
exports[`api should allow to enable validation using API 1`] = `
16+
"Invalid options object. NAME has been initialized using an options object that does not match the API schema.
17+
- options has an unknown property 'foo'. These properties are valid:
18+
object { name? }"
19+
`;
20+
321
exports[`api should get configuration from schema 1`] = `
422
"Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
523
- options has an unknown property 'foo'. These properties are valid:

test/api.test.js

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { validate, ValidationError } from "../src/index";
1+
import {
2+
validate,
3+
ValidationError,
4+
enableValidation,
5+
disableValidation,
6+
needValidate,
7+
} from "../src/index";
28

39
import schema from "./fixtures/schema.json";
410
import schemaTitle from "./fixtures/schema-title.json";
@@ -196,4 +202,133 @@ describe("api", () => {
196202
expect(error.message).toMatchSnapshot();
197203
}
198204
});
205+
206+
it('should allow to disable validation using "process.env.SKIP_VALIDATION"', () => {
207+
const oldValue = process.env.SKIP_VALIDATION;
208+
209+
let errored;
210+
211+
process.env.SKIP_VALIDATION = "y";
212+
213+
try {
214+
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
215+
} catch (error) {
216+
errored = error;
217+
}
218+
219+
expect(errored).toBeUndefined();
220+
221+
process.env.SKIP_VALIDATION = oldValue;
222+
});
223+
224+
it('should allow to disable validation using "process.env.SKIP_VALIDATION" #2', () => {
225+
const oldValue = process.env.SKIP_VALIDATION;
226+
227+
let errored;
228+
229+
process.env.SKIP_VALIDATION = "YeS";
230+
231+
try {
232+
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
233+
} catch (error) {
234+
errored = error;
235+
}
236+
237+
expect(errored).toBeUndefined();
238+
239+
process.env.SKIP_VALIDATION = oldValue;
240+
});
241+
242+
it('should allow to enable validation using "process.env.SKIP_VALIDATION"', () => {
243+
const oldValue = process.env.SKIP_VALIDATION;
244+
245+
process.env.SKIP_VALIDATION = "n";
246+
247+
try {
248+
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
249+
} catch (error) {
250+
if (error.name !== "ValidationError") {
251+
throw error;
252+
}
253+
254+
expect(error.message).toMatchSnapshot();
255+
}
256+
257+
process.env.SKIP_VALIDATION = oldValue;
258+
});
259+
260+
it('should allow to enable validation using "process.env.SKIP_VALIDATION" #2', () => {
261+
const oldValue = process.env.SKIP_VALIDATION;
262+
263+
process.env.SKIP_VALIDATION = " FaLse ";
264+
265+
try {
266+
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
267+
} catch (error) {
268+
if (error.name !== "ValidationError") {
269+
throw error;
270+
}
271+
272+
expect(error.message).toMatchSnapshot();
273+
}
274+
275+
process.env.SKIP_VALIDATION = oldValue;
276+
});
277+
278+
it("should allow to disable validation using API", () => {
279+
let errored;
280+
281+
disableValidation();
282+
283+
try {
284+
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
285+
} catch (error) {
286+
errored = error;
287+
}
288+
289+
expect(errored).toBeUndefined();
290+
291+
enableValidation();
292+
});
293+
294+
it("should allow to enable validation using API", () => {
295+
disableValidation();
296+
enableValidation();
297+
298+
try {
299+
validate(schemaTitle, { foo: "bar" }, { name: "NAME" });
300+
} catch (error) {
301+
if (error.name !== "ValidationError") {
302+
throw error;
303+
}
304+
305+
expect(error.message).toMatchSnapshot();
306+
}
307+
});
308+
309+
it("should allow to enable and disable validation using API", () => {
310+
enableValidation();
311+
expect(needValidate()).toBe(true);
312+
313+
disableValidation();
314+
expect(needValidate()).toBe(false);
315+
enableValidation();
316+
317+
enableValidation();
318+
enableValidation();
319+
expect(needValidate()).toBe(true);
320+
321+
enableValidation();
322+
disableValidation();
323+
expect(needValidate()).toBe(false);
324+
enableValidation();
325+
326+
enableValidation();
327+
expect(process.env.SKIP_VALIDATION).toBe("n");
328+
329+
disableValidation();
330+
expect(process.env.SKIP_VALIDATION).toBe("y");
331+
enableValidation();
332+
expect(process.env.SKIP_VALIDATION).toBe("n");
333+
});
199334
});

0 commit comments

Comments
 (0)