New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

checkeasy

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

checkeasy - npm Package Compare versions

Comparing version 1.0.4 to 1.1.0

4

dist/index.d.ts
export declare type Validator<T> = (v: any, path: string) => T;
export declare class ValidationError extends Error {
name: string;
constructor(message: string);
}
export declare const optional: <T>(handler: Validator<T>) => Validator<T | undefined>;

@@ -3,0 +7,0 @@ export declare const defaultValue: <T>(def: T, handler: Validator<T>) => Validator<T>;

87

dist/index.js
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
exports.exact = exports.oneOf = exports.transform = exports.email = exports.UUID = exports.arrayOf = exports.alternatives = exports.strToFloat = exports.float = exports.strToInt = exports.int = exports.string = exports.strToBoolean = exports.boolean = exports.object = exports.nullable = exports.defaultValue = exports.optional = void 0;
exports.exact = exports.oneOf = exports.transform = exports.email = exports.UUID = exports.arrayOf = exports.alternatives = exports.strToFloat = exports.float = exports.strToInt = exports.int = exports.string = exports.strToBoolean = exports.boolean = exports.object = exports.nullable = exports.defaultValue = exports.optional = exports.ValidationError = void 0;
var ValidationError = (function (_super) {
__extends(ValidationError, _super);
function ValidationError(message) {
var _this = _super.call(this, message) || this;
_this.name = 'ValidationError';
Object.setPrototypeOf(_this, ValidationError.prototype);
return _this;
}
return ValidationError;
}(Error));
exports.ValidationError = ValidationError;
function assertValueInRange(actual, min, max, path) {
if (min !== undefined && actual < min) {
throw new ValidationError("[" + path + "] is smaller than the allowed minimum (" + min + ")");
}
if (max !== undefined && actual > max) {
throw new ValidationError("[" + path + "] is larger than the allowed maximum (" + max + ")");
}
}
var optional = function (handler) { return function (v, path) {

@@ -29,3 +63,3 @@ if (v === undefined) {

if (typeof v !== 'object' || !v || Array.isArray(v)) {
throw new Error("[" + path + "] should be an object");
throw new ValidationError("[" + path + "] should be an object");
}

@@ -36,5 +70,3 @@ var res = {};

}
if ((min !== undefined && Object.keys(v).length < min) || (max !== undefined && Object.keys(v).length > max)) {
throw new Error("[" + path + "] size isn't in allowed range");
}
assertValueInRange(Object.keys(v).length, min, max, "size(" + path + ")");
for (var key in v) {

@@ -46,3 +78,3 @@ if (!desc[key]) {

else {
throw new Error("Property [" + path + "." + key + "] is unknown");
throw new ValidationError("Property [" + path + "." + key + "] is unknown");
}

@@ -57,3 +89,3 @@ }

if (typeof v !== 'boolean') {
throw new Error("[" + path + "] should be a boolean");
throw new ValidationError("[" + path + "] should be a boolean");
}

@@ -74,10 +106,8 @@ return v;

if (typeof v !== 'string') {
throw new Error("[" + path + "] should be a string");
throw new ValidationError("[" + path + "] should be a string");
}
if (pattern && !pattern.test(v)) {
throw new Error("[" + path + "] doesn't match the pattern");
throw new ValidationError("[" + path + "] doesn't match the pattern");
}
if ((min && v.length < min) || (max && v.length > max)) {
throw new Error("[" + path + "] length isn't in allowed range");
}
assertValueInRange(v.length, min, max, "length(" + path + ")");
return v;

@@ -91,7 +121,5 @@ };

if (!Number.isInteger(v)) {
throw new Error("[" + path + "] should be an integer");
throw new ValidationError("[" + path + "] should be an integer");
}
if ((min !== undefined && v < min) || (max !== undefined && v > max)) {
throw new Error("[" + path + "] isn't in allowed range");
}
assertValueInRange(v, min, max, path);
return v;

@@ -113,7 +141,5 @@ };

if (!Number.isFinite(n)) {
throw new Error("[" + path + "] should be a float");
throw new ValidationError("[" + path + "] should be a float");
}
if ((min !== undefined && n < min) || (max !== undefined && n > max)) {
throw new Error("[" + path + "] isn't in allowed range");
}
assertValueInRange(v, min, max, path);
return n;

@@ -134,9 +160,14 @@ };

try {
return alts[i](v, path + ".@alternative(" + i + ")");
return alts[i](v, "*");
}
catch (err) {
errs.push(err.message);
if (err instanceof ValidationError) {
errs.push("\n " + i + ": " + err.message.replace(/\n/g, '\n '));
}
else {
throw err;
}
}
}
throw new Error("All alternatives failed for [" + path + "]:\n\t" + errs.join('\n\t'));
throw new ValidationError("[" + path + "] doesn't match any of allowed alternatives:" + errs.join(''));
}; };

@@ -148,7 +179,5 @@ exports.alternatives = alternatives;

if (!Array.isArray(v)) {
throw new Error("[" + path + "] should be an array");
throw new ValidationError("[" + path + "] should be an array");
}
if ((min !== undefined && v.length < min) || (max !== undefined && v.length > max)) {
throw new Error("[" + path + "] length isn't in allowed range");
}
assertValueInRange(v.length, min, max, "length(" + path + ")");
return v.map(function (item, index) { return itemValidator(item, path + "[" + index + "]"); });

@@ -172,3 +201,3 @@ };

if (values.indexOf(v) === -1) {
throw new Error("[" + path + "] isn't equal to any of predefined values");
throw new ValidationError("[" + path + "] isn't equal to any of the expected values");
}

@@ -180,3 +209,3 @@ return v;

if (value !== v) {
throw new Error("[" + path + "] isn't equal to predefined value");
throw new ValidationError("[" + path + "] isn't equal to the expected value");
}

@@ -183,0 +212,0 @@ return v;

{
"name": "checkeasy",
"version": "1.0.4",
"version": "1.1.0",
"description": "Light, expressive and type-safe data validation in typescript",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -1,4 +0,4 @@

checkeasy
----------
# checkeasy
Light, expressive and type-safe data validation in typescript.

@@ -11,4 +11,3 @@

Why I need one more type validator?
-----------------------------------
# Why I need one more type validator?

@@ -35,4 +34,3 @@ Because I wanted to have type validation which:

Documentation
-------------
# Documentation

@@ -61,5 +59,5 @@ - [Validators](#validators)

Validators
----------
# Validators
Although, it's really easy to create your own validators, library exports few ready to go ones.

@@ -80,7 +78,7 @@

const validator2 = int({min: 1}) // returns: 5
validator2(5, 'myValue'); // returns: 5
const validator2 = int() // returns: 5
validator2('5', 'myValue'); // throws: [myValue] should be an integer
const validator3 = int({min: 0, max: 4});
validator3(5, 'myValue'); // throws: [myValue] isn't in allowed range
validator3(5, 'myValue'); // throws: [myValue] is larger than the allowed maximum (4)
```

@@ -106,7 +104,7 @@

const validator2 = float({min: 1});
validator2(5.2, 'myValue'); // returns: 5
const validator2 = float();
validator2('5.2', 'myValue'); // throws: [myValue] should be a float
const validator3 = float({min: 0, max: 4});
validator3(5.2, 'myValue'); // throws: [myValue] isn't in allowed range
validator3(5.2, 'myValue'); // throws: [myValue] is larger than the allowed maximum (4)
```

@@ -138,3 +136,3 @@

const validator3 = string({max: 3});
validator3('aaaa', 'myValue'); // throws: [myValue] length isn't in allowed range
validator3('aaaa', 'myValue'); // throws: [length(myValue)] is larger than the allowed maximum (4)

@@ -223,3 +221,3 @@ const validator4 = string({patten: /^[a-z]{3}$/i});

const validator4 = arrayOf(int(), {max: 2});
validator4([1, 2, 3, 'abc'], 'myValue'); // throws: [myValue] length isn't in allowed range
validator4([1, 2, 3, 'abc'], 'myValue'); // throws: [length(myValue)] is larger than the allowed maximum (2)

@@ -244,7 +242,7 @@ const validator5 = arrayOf(

const validator2 = exact(1)
validator2('1', 'myValue'); // throws: [myValue] isn't equal to predefined value
validator2('1', 'myValue'); // throws: [myValue] isn't equal to the expected value
const validator3 = exact({a: 1});
validator3({a: 1}, 'myValue'); // throws: [myValue] isn't equal to predefined value
// it's because it doesn't make deepEqual
validator3({a: 1}, 'myValue'); // throws: [myValue] isn't equal to the expected value
// it's because it doesn't call deepEqual, but uses with strict equality
```

@@ -261,7 +259,7 @@

const validator2 = oneOf([1, 2, '3'] as const)
validator2(3, 'myValue'); // throws: [myValue] isn't equal to any of predefined values
validator2(3, 'myValue'); // throws: [myValue] isn't equal to any of the expected values
const validator3 = oneOf([1, 2, {a: 1}] as const);
validator3({a: 1}, 'myValue'); // throws: [myValue] isn't equal to any of predefined values
// it's because it doesn't make deepEqual
validator3({a: 1}, 'myValue'); // throws: [myValue] isn't equal to any of the expected values
// it's because it doesn't call deepEqual, but uses with strict equality
```

@@ -281,3 +279,2 @@

// as typescript recognizes type of your values array as Array<string | number> in this case
// (pls let me know, if you have a solution to avoid "as const" here)
```

@@ -287,3 +284,3 @@

Checks value with the help of each passed validator one by one. Returns value from first validator, which doesn't fail.
Checks a value with the help of every of passed validators, one by one. Returns value from first validator, which doesn't fail.

@@ -302,5 +299,5 @@ If all validators failed, throws an error.

validator({a: 5}, 'myValue');
// throws: All alternatives failed for [myValue]:
// [myValue.@alternative(0)] should be a string
// [myValue.@alternative(1).a] should be a string
// throws: [myValue] doesn't match any of allowed alternatives:
// 0: [*] should be a string
// 1: [*.a] should be a string
```

@@ -351,7 +348,7 @@

Checks if value is uuid.
Checks if value is a valid uuid string.
## email
Checks if value is email.
Checks if value is a valid email string.

@@ -392,15 +389,43 @@ ## any

validator({type: 'user'}, 'myValue');
// throws: All alternatives failed for [myValue]:
// [myValue.@alternative(0)] should be a string
// [myValue.@alternative(1).id] should be a string
// throws: [myValue] doesn't match any of allowed alternatives:
// 0: [*] should be a string
// 1: [*.id] should be a string
validator('asd', 'myValue');
// throws: All alternatives failed for [myValue]:
// [myValue.@alternative(0)] doesn't match the pattern
// [myValue.@alternative(1)] should be an object
// throws: [myValue] doesn't match any of allowed alternatives:
// 0: [*] doesn't match the pattern
// 1: [*] should be an object
```
Custom validators
-----------------
Error handling
--------------
In the case of validation failed, validator throws instance of ValidationError. So, it's easy to catch it.
```ts
import {ValidationError, int} from './index';
const validator = int();
try {
validator('a', 'myValue');
} catch (err) {
if (err instanceof ValidationError) {
//...
}
// OR
if (err.name === 'ValidationError') {
//...
}
}
```
# Custom validators
The idea here is simple. To check any type of value you should to create a validator.

@@ -414,6 +439,9 @@

In case of validation error, validator should throw an error, using _path_ to point at a place of shape, where validation
failed. In case of success validator should return a value. Validator can return the same value which was received, or
modify it if needed.
In case of validation error, validator should throw a ValidationError,
using _path_ to point at a place of shape, where validation failed.
In case of success validator should return a value.
Validator can return the same value which was received.
Or some another value, if it should be modified on the fly.
You can make inline validators. E.g.:

@@ -426,3 +454,3 @@

if (typeof v !== 'string' || !v.startsWith('TYPE__')) {
throw new Error(`[${path}] is not correct type`);
throw new ValidationError(`[${path}] is not correct type`);
}

@@ -435,3 +463,3 @@ return v;

If you want to crate reusable validator, the convention is to wrap it into one more function, which can additionally
receive options as parameters. E.g. _int_ validator looks like:
receive options as parameters. E.g. _int_ validator can look like:

@@ -441,6 +469,6 @@ ```ts

if (!Number.isInteger(v)) {
throw new Error(`[${path}] should be an integer`);
throw new ValidationError(`[${path}] should be an integer`);
}
if ((min !== undefined && v < min) || (max !== undefined && v > max)) {
throw new Error(`[${path}] isn\'t in allowed range`);
throw new ValidationError(`[${path}] isn\'t in allowed range`);
}

@@ -462,3 +490,3 @@ return v;

We can use itself:
We can use it itself:

@@ -484,5 +512,14 @@ ```ts

License
-------
# Changelog
## [1.1.0] - 2022-05-20
- Added ValidationError, improved error messages.
- Changed some error messages
- Changes in README
Thank you [joshuafcole](https://github.com/joshuafcole) for some changes here
# License
ISC

@@ -489,0 +526,0 @@

@@ -5,2 +5,20 @@ // common

export class ValidationError extends Error {
public name = 'ValidationError';
constructor(message: string) {
super(message);
// fix custom error prototype in case of using with ES5
Object.setPrototypeOf(this, ValidationError.prototype);
}
}
function assertValueInRange(actual: number, min: number | undefined, max: number | undefined, path: string) {
if (min !== undefined && actual < min) {
throw new ValidationError(`[${path}] is smaller than the allowed minimum (${min})`);
}
if (max !== undefined && actual > max) {
throw new ValidationError(`[${path}] is larger than the allowed maximum (${max})`);
}
}
export const optional = <T>(handler: Validator<T>): Validator<T | undefined> => (v, path) => {

@@ -38,3 +56,3 @@ if (v === undefined) {

if(typeof v !== 'object' || !v || Array.isArray(v)) {
throw new Error(`[${path}] should be an object`);
throw new ValidationError(`[${path}] should be an object`);
}

@@ -45,5 +63,3 @@ const res: any = {};

}
if ((min !== undefined && Object.keys(v).length < min) || (max !== undefined && Object.keys(v).length > max)) {
throw new Error(`[${path}] size isn\'t in allowed range`);
}
assertValueInRange(Object.keys(v).length, min, max, `size(${path})`);
for (const key in v) {

@@ -54,3 +70,3 @@ if (!desc[key]) {

} else {
throw new Error(`Property [${path}.${key}] is unknown`);
throw new ValidationError(`Property [${path}.${key}] is unknown`);
}

@@ -64,3 +80,3 @@ }

if (typeof v !== 'boolean') {
throw new Error(`[${path}] should be a boolean`);
throw new ValidationError(`[${path}] should be a boolean`);
}

@@ -83,10 +99,8 @@ return v;

if(typeof v !== 'string') {
throw new Error(`[${path}] should be a string`);
throw new ValidationError(`[${path}] should be a string`);
}
if (pattern && !pattern.test(v)) {
throw new Error(`[${path}] doesn't match the pattern`);
throw new ValidationError(`[${path}] doesn't match the pattern`);
}
if ((min && v.length < min) || (max && v.length > max)) {
throw new Error(`[${path}] length isn\'t in allowed range`);
}
assertValueInRange(v.length, min, max, `length(${path})`);
return v;

@@ -97,7 +111,5 @@ }

if (!Number.isInteger(v)) {
throw new Error(`[${path}] should be an integer`);
throw new ValidationError(`[${path}] should be an integer`);
}
if ((min !== undefined && v < min) || (max !== undefined && v > max)) {
throw new Error(`[${path}] isn\'t in allowed range`);
}
assertValueInRange(v, min, max, path);
return v;

@@ -116,7 +128,5 @@ };

if (!Number.isFinite(n)) {
throw new Error(`[${path}] should be a float`);
throw new ValidationError(`[${path}] should be a float`);
}
if ((min !== undefined && n < min) || (max !== undefined && n > max)) {
throw new Error(`[${path}] isn\'t in allowed range`);
}
assertValueInRange(v, min, max, path);
return n;

@@ -138,8 +148,12 @@ };

try {
return alts[i](v, `${path}.@alternative(${i})`);
return alts[i](v, `*`);
} catch (err: any) {
errs.push(err.message);
if (err instanceof ValidationError) {
errs.push(`\n ${i}: ${err.message.replace(/\n/g, '\n ')}`);
} else {
throw err;
}
}
}
throw new Error(`All alternatives failed for [${path}]:\n\t${errs.join('\n\t')}`);
throw new ValidationError(`[${path}] doesn't match any of allowed alternatives:${errs.join('')}`);
};

@@ -152,7 +166,5 @@

if (!Array.isArray(v)) {
throw new Error(`[${path}] should be an array`);
throw new ValidationError(`[${path}] should be an array`);
}
if ((min !== undefined && v.length < min) || (max !== undefined && v.length > max)) {
throw new Error(`[${path}] length isn\'t in allowed range`);
}
assertValueInRange(v.length, min, max, `length(${path})`);
return v.map((item, index) => itemValidator(item, `${path}[${index}]`));

@@ -177,3 +189,3 @@ };

if (values.indexOf(v) === -1) {
throw new Error(`[${path}] isn't equal to any of predefined values`);
throw new ValidationError(`[${path}] isn't equal to any of the expected values`);
}

@@ -187,5 +199,5 @@ return v;

if (value !== v) {
throw new Error(`[${path}] isn't equal to predefined value`);
throw new ValidationError(`[${path}] isn't equal to the expected value`);
}
return v;
};

@@ -13,2 +13,3 @@ import {

strToInt, transform,
ValidationError,
} from '../src';

@@ -38,7 +39,7 @@

int({min: 5})(4, 'test');
}).toThrow('[test] isn\'t in allowed range');
}).toThrow('[test] is smaller than the allowed minimum (5)');
expect(() => {
int({max: 10})(12, 'test');
}).toThrow('[test] isn\'t in allowed range');
}).toThrow('[test] is larger than the allowed maximum (10)');

@@ -85,7 +86,7 @@ expect(() => {

float({min: 5})(4, 'test');
}).toThrow('[test] isn\'t in allowed range');
}).toThrow('[test] is smaller than the allowed minimum (5)');
expect(() => {
float({max: 10})(12, 'test');
}).toThrow('[test] isn\'t in allowed range');
}).toThrow('[test] is larger than the allowed maximum (10)');

@@ -132,7 +133,7 @@ expect(float()(0.5, 'test')).toEqual(0.5);

string({min: 2, max: 4})('value', 'test');
}).toThrow('[test] length isn\'t in allowed range');
}).toThrow('[length(test)] is larger than the allowed maximum (4)');
expect(() => {
string({min: 2, max: 4})('', 'test');
}).toThrow('[test] length isn\'t in allowed range');
}).toThrow('[length(test)] is smaller than the allowed minimum (2)');

@@ -181,3 +182,3 @@ expect(() => {

})({a: 5}, 'test');
}).toThrow('[test] size isn\'t in allowed range');
}).toThrow('[size(test)] is smaller than the allowed minimum (2)');

@@ -190,3 +191,3 @@ expect(() => {

})({a: 5, b: 5, c: 5, d: 5}, 'test');
}).toThrow('[test] size isn\'t in allowed range');
}).toThrow('[size(test)] is larger than the allowed maximum (3)');

@@ -227,3 +228,3 @@ expect(object({}, {

arrayOf(int(), {max: 2})([1, 2, 3, 'abc'], 'test');
}).toThrow('[test] length isn\'t in allowed range');
}).toThrow('[length(test)] is larger than the allowed maximum (2)');

@@ -243,3 +244,3 @@ expect(arrayOf(optional(string()))(['1', '2', '3'], 'test')).toEqual(['1', '2', '3']);

exact(1)(2, 'test');
}).toThrow('[test] isn\'t equal to predefined value');
}).toThrow('[test] isn\'t equal to the expected value');
});

@@ -252,11 +253,11 @@

oneOf([1, 2, '3'])(3, 'test');
}).toThrow('[test] isn\'t equal to any of predefined values');
}).toThrow('[test] isn\'t equal to any of the expected values');
expect(() => {
oneOf([1, 2, '3'])(undefined, 'test');
}).toThrow('[test] isn\'t equal to any of predefined values');
}).toThrow('[test] isn\'t equal to any of the expected values');
expect(() => {
oneOf([1, 2, {a: 1}])({a: 1}, 'test');
}).toThrow('[test] isn\'t equal to any of predefined values');
}).toThrow('[test] isn\'t equal to any of the expected values');
});

@@ -269,3 +270,3 @@

alternatives([string(), int()])(undefined, 'test');
}).toThrow('All alternatives failed for [test]:\n\t[test.@alternative(0)] should be a string\n\t[test.@alternative(1)] should be an integer');
}).toThrow('[test] doesn\'t match any of allowed alternatives:\n 0: [*] should be a string\n 1: [*] should be an integer');

@@ -276,3 +277,19 @@ expect(alternatives([string(), object({a: string()})])({a: '5'}, 'test')).toEqual({a: '5'});

alternatives([string(), object({a: string()})])({a: 5}, 'test');
}).toThrow('All alternatives failed for [test]:\n\t[test.@alternative(0)] should be a string\n\t[test.@alternative(1).a] should be a string');
}).toThrow('[test] doesn\'t match any of allowed alternatives:\n 0: [*] should be a string\n 1: [*.a] should be a string');
expect(() => {
alternatives([
string(),
int(),
object({id: alternatives([
string(),
int(),
])}),
])({a: 5}, 'test');
}).toThrow('[test] doesn\'t match any of allowed alternatives:\n' +
' 0: [*] should be a string\n' +
' 1: [*] should be an integer\n' +
' 2: [*.id] doesn\'t match any of allowed alternatives:\n' +
' 0: [*] should be a string\n' +
' 1: [*] should be an integer');
});

@@ -359,7 +376,16 @@

validator({type: 'user'}, 'myValue');
}).toThrow('All alternatives failed for [myValue]:\n\t[myValue.@alternative(0)] should be a string\n\t[myValue.@alternative(1).id] should be a string');
}).toThrow('[myValue] doesn\'t match any of allowed alternatives:\n 0: [*] should be a string\n 1: [*.id] should be a string');
expect(() => {
validator('asd', 'myValue');
}).toThrow('All alternatives failed for [myValue]:\n\t[myValue.@alternative(0)] doesn\'t match the pattern\n\t[myValue.@alternative(1)] should be an object');
}).toThrow('[myValue] doesn\'t match any of allowed alternatives:\n 0: [*] doesn\'t match the pattern\n 1: [*] should be an object');
});
});
it('should throw with ValidateError', () => {
try {
int()("a", 'test');
} catch (err) {
expect(err).toBeInstanceOf(ValidationError);
expect(err.name).toEqual('ValidationError');
}
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc