@thi.ng/validate 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/package.json +2 -2
- package/validators.d.ts +62 -10
- package/validators.js +50 -13
package/README.md
CHANGED
|
@@ -90,13 +90,17 @@ try {
|
|
|
90
90
|
- [`isPositive()`](https://docs.thi.ng/umbrella/validate/functions/isPositive.html)
|
|
91
91
|
- [`isRegExp()`](https://docs.thi.ng/umbrella/validate/functions/isRegExp.html)
|
|
92
92
|
- [`isString()`](https://docs.thi.ng/umbrella/validate/functions/isString.html)
|
|
93
|
+
- [`isTypedArray()`](https://docs.thi.ng/umbrella/validate/functions/isTypedArray.html)
|
|
94
|
+
- [`isU8Array()`](https://docs.thi.ng/umbrella/validate/functions/isU8Array.html)
|
|
93
95
|
- [`isUndefined()`](https://docs.thi.ng/umbrella/validate/functions/isUndefined.html)
|
|
94
96
|
- [`matchesRegexp()`](https://docs.thi.ng/umbrella/validate/functions/matchesRegexp.html)
|
|
95
97
|
|
|
96
98
|
### Combinators
|
|
97
99
|
|
|
98
|
-
- [`
|
|
100
|
+
- [`every()`](https://docs.thi.ng/umbrella/validate/functions/every.html)
|
|
101
|
+
- [`not()`](https://docs.thi.ng/umbrella/validate/functions/not.html)
|
|
99
102
|
- [`optional()`](https://docs.thi.ng/umbrella/validate/functions/optional.html)
|
|
103
|
+
- [`some()`](https://docs.thi.ng/umbrella/validate/functions/some.html)
|
|
100
104
|
|
|
101
105
|
## Status
|
|
102
106
|
|
|
@@ -130,7 +134,7 @@ For Node.js REPL:
|
|
|
130
134
|
const val = await import("@thi.ng/validate");
|
|
131
135
|
```
|
|
132
136
|
|
|
133
|
-
Package sizes (brotli'd, pre-treeshake): ESM:
|
|
137
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 1.19 KB
|
|
134
138
|
|
|
135
139
|
## Dependencies
|
|
136
140
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/validate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Functional, composable, fully extensible, predicate-based value validation with customizable error messages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"status": "alpha",
|
|
86
86
|
"year": 2026
|
|
87
87
|
},
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "c0d6e8f2517c5edc745774266f3cbca586b03d5e"
|
|
89
89
|
}
|
package/validators.d.ts
CHANGED
|
@@ -56,20 +56,46 @@ export declare const ValidationError: {
|
|
|
56
56
|
*/
|
|
57
57
|
export declare const validator: (...validators: Validator[]) => (x: any) => boolean;
|
|
58
58
|
/**
|
|
59
|
-
* Higher order validator. Takes
|
|
60
|
-
* version which also allows
|
|
59
|
+
* Higher order validator. Takes existing validator(s) and returns an augmented
|
|
60
|
+
* version which also allows values to be nullish. If more than one validator is
|
|
61
|
+
* given, they're first combined via {@link every}.
|
|
62
|
+
*
|
|
63
|
+
* @param first
|
|
64
|
+
* @param rest
|
|
65
|
+
*/
|
|
66
|
+
export declare const optional: (first: Validator, ...rest: Validator[]) => Validator;
|
|
67
|
+
/**
|
|
68
|
+
* Higher order validator. Takes existing validator and optional error message.
|
|
69
|
+
* Returns an augmented validator which applies logical negation of the original
|
|
70
|
+
* validator.
|
|
61
71
|
*
|
|
62
72
|
* @param validator
|
|
73
|
+
* @param msg
|
|
63
74
|
*/
|
|
64
|
-
export declare const
|
|
75
|
+
export declare const not: ({ coerce, valid, msg: $msg }: Validator, msg?: Validator["msg"]) => Validator;
|
|
65
76
|
/**
|
|
66
|
-
* Higher order validator. Takes
|
|
67
|
-
* which will apply the validators in given order,
|
|
68
|
-
*
|
|
77
|
+
* Higher order validator. Takes one or more validators and returns a new one
|
|
78
|
+
* which will apply the validators in given order, and return successfully with
|
|
79
|
+
* the first one passed and only fails if **none** of the validators passed.
|
|
69
80
|
*
|
|
70
|
-
* @param
|
|
81
|
+
* @param first
|
|
82
|
+
* @param rest
|
|
71
83
|
*/
|
|
72
|
-
export declare const
|
|
84
|
+
export declare const some: (first: Validator | Validator[], ...rest: (Validator | Validator[])[]) => Validator;
|
|
85
|
+
/**
|
|
86
|
+
* Higher order validator. Takes a number of validators and returns a new one
|
|
87
|
+
* which will apply the validators in given order, and only returns success if
|
|
88
|
+
* **all** of the validators passed.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* Essentially the same as {@link validator}, but returns a {@link Validator}
|
|
92
|
+
* object (presumably for further composition) instead of a predicate function
|
|
93
|
+
* to apply directly.
|
|
94
|
+
*
|
|
95
|
+
* @param first
|
|
96
|
+
* @param rest
|
|
97
|
+
*/
|
|
98
|
+
export declare const every: (first: Validator, ...rest: Validator[]) => Validator;
|
|
73
99
|
/**
|
|
74
100
|
* Returns validator to check if value is undefined.
|
|
75
101
|
*
|
|
@@ -98,8 +124,34 @@ export declare const isObject: (msg?: Validator["msg"]) => Validator;
|
|
|
98
124
|
export declare const isObjectOf: (validators: Validator | Validator[], msg?: Validator["msg"]) => Validator;
|
|
99
125
|
export declare const isArray: (msg?: Validator["msg"]) => Validator;
|
|
100
126
|
export declare const isArrayOf: (validators: Validator | Validator[], msg?: Validator["msg"]) => Validator;
|
|
101
|
-
export declare const
|
|
102
|
-
|
|
127
|
+
export declare const isTypedArray: (msg?: Validator["msg"]) => Validator;
|
|
128
|
+
/**
|
|
129
|
+
* Returns validator to check if value is a `Uint8Array`.
|
|
130
|
+
*
|
|
131
|
+
* @param msg
|
|
132
|
+
*/
|
|
133
|
+
export declare const isU8Array: (msg?: Validator["msg"]) => Validator;
|
|
134
|
+
/**
|
|
135
|
+
* Returns validator to ensure given `keys` are present in an object, optionally
|
|
136
|
+
* also checks their values are `nonNullish` (default: false). If `onlyKeys` is
|
|
137
|
+
* true (default: false), the validator also checks that no other keys are
|
|
138
|
+
* defined in the object.
|
|
139
|
+
*
|
|
140
|
+
* @param keys
|
|
141
|
+
* @param nonNullish
|
|
142
|
+
* @param onlyKeys
|
|
143
|
+
* @param msg
|
|
144
|
+
*/
|
|
145
|
+
export declare const hasRequiredKeys: (keys: string[], nonNullish?: boolean, onlyKeys?: boolean, msg?: Validator["msg"]) => Validator;
|
|
146
|
+
/**
|
|
147
|
+
* Takes object of validators to check values of different keys in an object.
|
|
148
|
+
* Returns validator which applies all checks, optionally also ensures no other
|
|
149
|
+
* keys are defined (if `onlyKeys` is true, default: false).
|
|
150
|
+
*
|
|
151
|
+
* @param validators
|
|
152
|
+
* @param onlyKeys
|
|
153
|
+
*/
|
|
154
|
+
export declare const hasKeysOf: (validators: Record<PropertyKey, Validator | Validator[]>, onlyKeys?: boolean) => Validator;
|
|
103
155
|
/**
|
|
104
156
|
* Returns validator to check if value is one of the given options.
|
|
105
157
|
*
|
package/validators.js
CHANGED
|
@@ -8,6 +8,7 @@ import { isObjectOf as $isObjectOf } from "@thi.ng/checks/is-object-of";
|
|
|
8
8
|
import { isPlainObject } from "@thi.ng/checks/is-plain-object";
|
|
9
9
|
import { isRegExp as $isRegExp } from "@thi.ng/checks/is-regexp";
|
|
10
10
|
import { isString as $isString } from "@thi.ng/checks/is-string";
|
|
11
|
+
import { isTypedArray as $isTypedArray } from "@thi.ng/checks/is-typedarray";
|
|
11
12
|
import { defError } from "@thi.ng/errors/deferror";
|
|
12
13
|
const ValidationError = defError(() => `validation error`);
|
|
13
14
|
const validator = (...validators) => (x) => {
|
|
@@ -20,20 +21,34 @@ const validator = (...validators) => (x) => {
|
|
|
20
21
|
}
|
|
21
22
|
return true;
|
|
22
23
|
};
|
|
23
|
-
const
|
|
24
|
+
const __asArray = (v) => $isArray(v) ? v : [v];
|
|
25
|
+
const optional = (first, ...rest) => {
|
|
26
|
+
const { coerce, valid, msg } = rest.length ? every(first, ...rest) : first;
|
|
27
|
+
return {
|
|
28
|
+
coerce,
|
|
29
|
+
valid: (x) => x == null || valid(x),
|
|
30
|
+
msg
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const not = ({ coerce, valid, msg: $msg }, msg) => ({
|
|
24
34
|
coerce,
|
|
25
|
-
valid: (x) =>
|
|
26
|
-
|
|
35
|
+
valid: (x) => {
|
|
36
|
+
try {
|
|
37
|
+
return !valid(x);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
msg: msg ?? $msg
|
|
27
43
|
});
|
|
28
|
-
const
|
|
29
|
-
const oneOf = (validators) => {
|
|
44
|
+
const some = (first, ...rest) => {
|
|
30
45
|
let lastMsg;
|
|
31
46
|
return {
|
|
32
47
|
valid: (x) => {
|
|
33
48
|
lastMsg = void 0;
|
|
34
|
-
for (let v of
|
|
49
|
+
for (let $v of [first, ...rest]) {
|
|
35
50
|
try {
|
|
36
|
-
return validator(...__asArray(v))(x);
|
|
51
|
+
return validator(...__asArray($v))(x);
|
|
37
52
|
} catch (e) {
|
|
38
53
|
lastMsg = e.origMessage ?? e.message;
|
|
39
54
|
}
|
|
@@ -43,6 +58,9 @@ const oneOf = (validators) => {
|
|
|
43
58
|
msg: () => lastMsg ?? "invalid value"
|
|
44
59
|
};
|
|
45
60
|
};
|
|
61
|
+
const every = (first, ...rest) => ({
|
|
62
|
+
valid: (x) => validator(first, ...rest)(x)
|
|
63
|
+
});
|
|
46
64
|
const isUndefined = (msg) => ({
|
|
47
65
|
valid: (x) => x === void 0,
|
|
48
66
|
msg: msg ?? `expected undefined value`
|
|
@@ -87,16 +105,25 @@ const isArrayOf = (validators, msg) => ({
|
|
|
87
105
|
valid: $isArrayOf(validator(...__asArray(validators))),
|
|
88
106
|
msg: msg ?? `required array value`
|
|
89
107
|
});
|
|
90
|
-
const
|
|
108
|
+
const isTypedArray = (msg) => ({
|
|
109
|
+
valid: $isTypedArray,
|
|
110
|
+
msg: msg ?? `required typed array value`
|
|
111
|
+
});
|
|
112
|
+
const isU8Array = (msg) => ({
|
|
113
|
+
valid: (x) => x instanceof Uint8Array,
|
|
114
|
+
msg: msg ?? `required byte array value`
|
|
115
|
+
});
|
|
116
|
+
const hasRequiredKeys = (keys, nonNullish = false, onlyKeys = false, msg) => ({
|
|
91
117
|
valid: (x) => {
|
|
92
|
-
|
|
93
|
-
return keys.every((k) =>
|
|
118
|
+
if (onlyKeys) __onlyKeys(keys, x);
|
|
119
|
+
return keys.every((k) => k in x && (nonNullish ? x[k] != null : true));
|
|
94
120
|
},
|
|
95
|
-
msg: msg ?? `required keys: ${keys.join(", ")}`
|
|
121
|
+
msg: msg ?? `required keys: ${keys.join(", ")}${nonNullish ? " (must be non-nullish)" : ""}`
|
|
96
122
|
});
|
|
97
|
-
const hasKeysOf = (validators) => ({
|
|
123
|
+
const hasKeysOf = (validators, onlyKeys = false) => ({
|
|
98
124
|
valid: (x) => {
|
|
99
125
|
if (x == null) return false;
|
|
126
|
+
if (onlyKeys) __onlyKeys(Object.keys(validators), x);
|
|
100
127
|
for (let [key, v] of Object.entries(validators)) {
|
|
101
128
|
try {
|
|
102
129
|
validator(...__asArray(v))(x[key]);
|
|
@@ -109,6 +136,12 @@ const hasKeysOf = (validators) => ({
|
|
|
109
136
|
return true;
|
|
110
137
|
}
|
|
111
138
|
});
|
|
139
|
+
const __onlyKeys = (keys, x) => {
|
|
140
|
+
for (let k in x) {
|
|
141
|
+
if (!keys.includes(k))
|
|
142
|
+
throw new ValidationError(`key: ${k} not allowed`);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
112
145
|
const isEnum = (opts, msg) => ({
|
|
113
146
|
valid: (x) => opts.includes(x),
|
|
114
147
|
msg: msg ?? `required value to be one of: ${opts.join(", ")}`
|
|
@@ -155,6 +188,7 @@ const matchesRegexp = (re, msg) => ({
|
|
|
155
188
|
});
|
|
156
189
|
export {
|
|
157
190
|
ValidationError,
|
|
191
|
+
every,
|
|
158
192
|
hasKeysOf,
|
|
159
193
|
hasRequiredKeys,
|
|
160
194
|
isArray,
|
|
@@ -177,9 +211,12 @@ export {
|
|
|
177
211
|
isPositive,
|
|
178
212
|
isRegExp,
|
|
179
213
|
isString,
|
|
214
|
+
isTypedArray,
|
|
215
|
+
isU8Array,
|
|
180
216
|
isUndefined,
|
|
181
217
|
matchesRegexp,
|
|
182
|
-
|
|
218
|
+
not,
|
|
183
219
|
optional,
|
|
220
|
+
some,
|
|
184
221
|
validator
|
|
185
222
|
};
|