@vcsuite/check
Advanced tools
Comparing version
{ | ||
"name": "@vcsuite/check", | ||
"version": "1.1.2", | ||
"version": "2.0.0", | ||
"description": "check utilities for input type safety", | ||
"main": "index.js", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"type": "module", | ||
"types": "index.d.ts", | ||
"scripts": { | ||
"test": "mocha \"tests/**/*.spec.js\"", | ||
"test": "tsc -b tests && mocha \".tests/**/*.spec.js\"", | ||
"test:ci": "npm run test -- --reporter mocha-junit-reporter", | ||
"lint": "eslint ." | ||
"lint": "eslint .", | ||
"type-check": "tsc --noEmit && tsc -p tests --noEmit", | ||
"build": "tsc", | ||
"prepack": "npm run build" | ||
}, | ||
"files": [ | ||
"index.js", | ||
"index.d.ts" | ||
"dist" | ||
], | ||
@@ -20,16 +22,20 @@ "author": "Ben Kuster <bkuster@vc.systems>", | ||
"devDependencies": { | ||
"@types/chai": "^4.3.4", | ||
"@types/mocha": "^10.0.1", | ||
"@types/node": "^16.18.11", | ||
"@typescript-eslint/eslint-plugin": "^5.48.2", | ||
"@typescript-eslint/parser": "^5.48.2", | ||
"@vcsuite/eslint-config": "^2.1.1", | ||
"chai": "^4.3.4", | ||
"eslint": "^8.1.0", | ||
"@vcsuite/eslint-config": "^2.0.3", | ||
"eslint": "^8.32.0", | ||
"eslint-import-resolver-typescript": "^2.7.1", | ||
"mocha": "^9.1.3", | ||
"mocha-junit-reporter": "^2.0.2" | ||
"mocha-junit-reporter": "^2.0.2", | ||
"typescript": "^4.9.4" | ||
}, | ||
"eslintConfig": { | ||
"extends": [ | ||
"@vcsuite/eslint-config/vue" | ||
] | ||
}, | ||
"eslintIgnore": [ | ||
"index.d.ts" | ||
"index.d.ts", | ||
"dist", | ||
".tests" | ||
] | ||
} |
170
README.md
# @vcs/check | ||
A small library to check input variables with. | ||
A small library to check input variables. The main goal is to sanitize user input and | ||
create humanly readable error messages from argument errors. Performance is not | ||
a main target. If checking large amounts of data, use `where` callbacks or create a custom input | ||
validation function. | ||
## Installation | ||
```bash | ||
@@ -8,44 +12,150 @@ npm i @vcs/check | ||
## Example Usage | ||
```javascript | ||
import { check, checkMaybe } from '@vcs/check'; | ||
## Usage | ||
The general idea, is to validate user input: | ||
```typescript | ||
import { check, Integer, NonEmptyString } from '@vcs/check'; | ||
/** | ||
* checking of input parameters | ||
* @param {number} bar | ||
* @param {Array<string>} baz | ||
* @param {{ bar: number, baz: Array<boolean>}} foobar | ||
*/ | ||
function foo(bar, baz, foobar) { | ||
function foo(bar: number, baz: string[], foobar: object): void { | ||
check(bar, Number); // bar must be a number | ||
check(bar, 5); // bar must be 5 | ||
check(bar, Integer); // bar must be an integer value | ||
check(baz, [String]); // baz must be an array of strings | ||
check(baz, [NonEmptyString]); // baz must be an array of strings and the values may not be '' | ||
check(foobar, { bar: Number, baz: [Boolean] }); // foobar must be an object where property bar is a number and property baz an array of booleans | ||
} | ||
``` | ||
/** | ||
* checking of input parameters with multiple types | ||
* @param {number|string} bar | ||
* @param {Array<number>|string} baz | ||
* @param {{ bar: number, baz: (boolean|string)}|boolean} foobar | ||
*/ | ||
function foo2(bar, baz, foobar) { | ||
check(bar, [Number, String]); // bar must be a number or a string | ||
check(bar, [5, '5']); // bar must 5 or '5' | ||
check(baz, [[Number], String]); // baz must be an array of numbers or a string | ||
check(foobar, [{ bar: Number, baz: [Boolean, String] }, Boolean]); // foobar must be an object where bar is a number and baz is either a boolean or a string or a boolean | ||
You can also check overloaded inputs using `oneOf`: | ||
```typescript | ||
import { check, oneOf } from '@vcs/check'; | ||
function foo(bar: number | string, baz: number[] | string[], foobar: object | boolean): void { | ||
check(bar, oneOf(Number, String)); // bar must be a number or a string | ||
check(bar, oneOf(5, '5')); // bar must 5 or '5' | ||
check(baz, oneOf([Number], [String])); // baz must be an array of numbers or a string | ||
check(foobar, oneOf({ bar: Number, baz: oneOf(Boolean, String) }, Boolean)); // foobar must be an object where bar is a number and baz is either a boolean or a string or a boolean | ||
} | ||
``` | ||
/** | ||
* checking for nested or optional parameters | ||
* @param {Array<{ bar: number }>>} bar | ||
* @param {HTMLElement=} baz | ||
* @param {{ bar: number }=} foobar | ||
*/ | ||
function foo3(bar, baz, foobar) { | ||
check(bar, [{ bar: Number }]); // bar must be an array of object where the property bar is a number | ||
check(bar.length, 4) // bar must have a length of 4 | ||
checkMaybe(baz, HTMLElement); // baz must be an instance of HTMLElement, null or undefined | ||
checkMaybe(foobar, { bar: Number }, true); // foobar must be an object whos only property is numeric bar or undefined or null | ||
Instead of using `oneOf<T>(undefined, T)` to define optional or possible inputs, you can | ||
use the `maybe` or `optional` helpers: | ||
```typescript | ||
import { check, maybe, optional } from '@vcs/check'; | ||
function foo(bar?: number, baz?: number): void { | ||
check(bar, maybe(Number)); // bar must be an number or null or undefined | ||
check(baz, optional(Number)); // baz must be a number or undefined | ||
} | ||
``` | ||
If you check for object patterns using `Record<string, Pattern>`, you will ensure, the | ||
keys on your object have the given types. Additional keys are simply ignored. Sometimes, | ||
you would like to ensure an object has certain keys, and only certain keys. You | ||
can use the `strict` helper for this. The strict helper only checks keys on the level | ||
of record it is defined, you would have to use it multiple times to ensure strict keys on nested | ||
objects. | ||
```typescript | ||
import { check, optional, strict } from '@vcs/check'; | ||
type StrictOne = { one: number }; | ||
const strictOneMatcher = strict({ one: number }) | ||
function foo(bar: StrictOne): void { | ||
check(bar, strictOneMatcher); // bar must have key one and only key one of type number | ||
} | ||
function foobar(bar: { foo: StrictOne, bar?: number }): void { | ||
check(bar, { foo: strictOneMatcher, bar: optional(number) }); | ||
} | ||
function baz(bar: { foo: { one: number | string } }): void { | ||
check(bar, { foo: strict({ one: oneOf(Number, String) }) }); // bar must have key one and only key one of type number or string | ||
} | ||
function deepFoo(bar: { foo: { bar: StrictOne } }): void { | ||
check(bar, strict({ foo: strict({ bar: strictOneMatcher }) })); // bar must have key foo and only key foo which must have key bar and only key bar which must have key one and only key one of type number | ||
} | ||
``` | ||
You can create custom matchers with `where`. This can provide better type safety or | ||
better performance. For instance, you can use `is` as a type guard to transform unknown to a custom | ||
type using `where`: | ||
```typescript | ||
import { is, where } from '@vcs/check'; | ||
type Coordinate = [number, number, number]; | ||
function offset(coordinate: Coordinate, offset: number): Coordinate { | ||
return [ | ||
coordinate[0] + offset, | ||
coordinate[1] + offset, | ||
coordinate[2] + offset, | ||
]; | ||
} | ||
function isCoordinate(coordinate: unknown): coordinate is Coordinate { | ||
if (Array.isArray(coordinate) && coordinate.length === 3 && coordinate.every(Number.isFinite)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function foo(coordinate: unknown): void { | ||
if (is(coordinate, where<Coordinate>(isCoordinate))) { | ||
offset(coordinate, 10); | ||
} | ||
} | ||
``` | ||
Sometimes you have arbitrary records and you wish to ensure all values have the same type | ||
but the keys are user defined (for instance a record of Tags). You can use the `recordOf` helper to ensure | ||
a Record has a certain type: | ||
```typescript | ||
import { check, recordOf } from '@vcs/check'; | ||
function foo(bar: Record<string, string>): void { | ||
check(bar, recordOf(String)); // bar must be an object with string keys and all values must be strings | ||
} | ||
``` | ||
If you use enumeration in your TS code, checking oneOf doesn't give you the required typeof | ||
you're looking for. To use `check` as a type guard for enumerations, you can use | ||
the `ofEnum` helper as follows. The way TS transpiles enums, makes this only work with | ||
string enumerations. | ||
```typescript | ||
import { check, ofEnum } from '@vcs/check'; | ||
enum Baz { | ||
ONE = 'one', | ||
TWO = 'two', | ||
THREE = 'three', | ||
} | ||
function foo(bar: unknown): void { | ||
check(bar, ofEnum(Baz)); // bar is assignable to Baz enum; | ||
const baz: Baz = bar; // safe | ||
console.log(baz); | ||
} | ||
``` | ||
Furthermore, there are some numeric range & value helpers to ensure numbers | ||
are in a certain validity range, such as `inRange` & `gte` | ||
```typescript | ||
import { check, gte, inRange, Integer } from '@vcsuite/check'; | ||
function foo(bar: number, baz: number): void { | ||
check(bar, inRange(0, 2)); // bar must be a number greater equal 0 and less then equal 1; | ||
check(bar, inRange(0, 2, Integer)); // bar must be an integer number greater equal 0 and less then equal 2 | ||
check(baz, gte(0)); // bar must be a number greater equal 0 | ||
check(baz, gte(0, Integer)); // bar must be an integer number greater equal 0 | ||
} | ||
``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
21041
55.73%388
7.18%161
215.69%12
140%1
Infinity%