@thi.ng/validate 0.2.0 → 0.3.2
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 +1 -1
- package/api.d.ts +1 -1
- package/package.json +5 -5
- package/validators.d.ts +20 -3
- package/validators.js +66 -18
package/README.md
CHANGED
package/api.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/validate",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Functional, composable, fully extensible, predicate-based value validation with customizable error messages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@thi.ng/api": "^8.12.
|
|
44
|
-
"@thi.ng/checks": "^3.9.
|
|
45
|
-
"@thi.ng/errors": "^2.6.
|
|
43
|
+
"@thi.ng/api": "^8.12.21",
|
|
44
|
+
"@thi.ng/checks": "^3.9.1",
|
|
45
|
+
"@thi.ng/errors": "^2.6.10"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"esbuild": "^0.28.0",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"status": "alpha",
|
|
86
86
|
"year": 2026
|
|
87
87
|
},
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "dcaa4e2beb427e434a68cba1259a9bf9983a569a"
|
|
89
89
|
}
|
package/validators.d.ts
CHANGED
|
@@ -55,6 +55,14 @@ export declare const ValidationError: {
|
|
|
55
55
|
* @param validators
|
|
56
56
|
*/
|
|
57
57
|
export declare const validator: (...validators: Validator[]) => (x: any) => boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Utility validator which always passes.
|
|
60
|
+
*/
|
|
61
|
+
export declare const ALWAYS: Validator;
|
|
62
|
+
/**
|
|
63
|
+
* Utility validator which always fails.
|
|
64
|
+
*/
|
|
65
|
+
export declare const NEVER: Validator;
|
|
58
66
|
/**
|
|
59
67
|
* Higher order validator. Takes existing validator(s) and returns an augmented
|
|
60
68
|
* version which also allows values to be nullish. If more than one validator is
|
|
@@ -108,11 +116,19 @@ export declare const isUndefined: (msg?: Validator["msg"]) => Validator;
|
|
|
108
116
|
* @param msg
|
|
109
117
|
*/
|
|
110
118
|
export declare const isNullish: (msg?: Validator["msg"]) => Validator;
|
|
119
|
+
export declare const isArray: (msg?: Validator["msg"]) => Validator;
|
|
120
|
+
export declare const isArrayOf: (validators: Validator | Validator[], msg?: Validator["msg"]) => Validator;
|
|
111
121
|
export declare const isBoolean: (msg?: Validator["msg"]) => Validator;
|
|
112
122
|
export declare const isNumber: (msg?: Validator["msg"]) => Validator;
|
|
113
123
|
export declare const isString: (msg?: Validator["msg"]) => Validator;
|
|
114
124
|
export declare const isDate: (msg?: Validator["msg"]) => Validator;
|
|
125
|
+
export declare const isFunction: (msg?: Validator["msg"]) => Validator;
|
|
115
126
|
export declare const isRegExp: (msg?: Validator["msg"]) => Validator;
|
|
127
|
+
/**
|
|
128
|
+
* Returns validator which checks that given value is a plain object (not class).
|
|
129
|
+
*
|
|
130
|
+
* @param msg
|
|
131
|
+
*/
|
|
116
132
|
export declare const isObject: (msg?: Validator["msg"]) => Validator;
|
|
117
133
|
/**
|
|
118
134
|
* Returns validator to check if value is a plain object and the values of all
|
|
@@ -122,8 +138,6 @@ export declare const isObject: (msg?: Validator["msg"]) => Validator;
|
|
|
122
138
|
* @param msg
|
|
123
139
|
*/
|
|
124
140
|
export declare const isObjectOf: (validators: Validator | Validator[], msg?: Validator["msg"]) => Validator;
|
|
125
|
-
export declare const isArray: (msg?: Validator["msg"]) => Validator;
|
|
126
|
-
export declare const isArrayOf: (validators: Validator | Validator[], msg?: Validator["msg"]) => Validator;
|
|
127
141
|
export declare const isTypedArray: (msg?: Validator["msg"]) => Validator;
|
|
128
142
|
/**
|
|
129
143
|
* Returns validator to check if value is a `Uint8Array`.
|
|
@@ -152,8 +166,11 @@ export declare const hasRequiredKeys: (keys: string[], nonNullish?: boolean, onl
|
|
|
152
166
|
* @param onlyKeys
|
|
153
167
|
*/
|
|
154
168
|
export declare const hasKeysOf: (validators: Record<PropertyKey, Validator | Validator[]>, onlyKeys?: boolean) => Validator;
|
|
169
|
+
export declare const hasRequiredPatternKeys: (pattern: RegExp, nonNullish?: boolean, onlyKeys?: boolean, msg?: Validator["msg"]) => Validator;
|
|
170
|
+
export declare const hasPatternKeysOf: (pattern: RegExp, validators: Validator | Validator[], onlyKeys?: boolean) => Validator;
|
|
155
171
|
/**
|
|
156
|
-
* Returns validator to check if value is one of the given options.
|
|
172
|
+
* Returns validator to check if value is one of the given options. Values are
|
|
173
|
+
* checked via `opts.includes(x)`.
|
|
157
174
|
*
|
|
158
175
|
* @param opts
|
|
159
176
|
* @param msg
|
package/validators.js
CHANGED
|
@@ -2,7 +2,7 @@ import { isArray as $isArray } from "@thi.ng/checks/is-array";
|
|
|
2
2
|
import { isArrayOf as $isArrayOf } from "@thi.ng/checks/is-array-of";
|
|
3
3
|
import { isBoolean as $isBoolean } from "@thi.ng/checks/is-boolean";
|
|
4
4
|
import { isDate as $isDate } from "@thi.ng/checks/is-date";
|
|
5
|
-
import { isFunction } from "@thi.ng/checks/is-function";
|
|
5
|
+
import { isFunction as $isFunction } from "@thi.ng/checks/is-function";
|
|
6
6
|
import { isNumber as $isNumber } from "@thi.ng/checks/is-number";
|
|
7
7
|
import { isObjectOf as $isObjectOf } from "@thi.ng/checks/is-object-of";
|
|
8
8
|
import { isPlainObject } from "@thi.ng/checks/is-plain-object";
|
|
@@ -15,13 +15,15 @@ const validator = (...validators) => (x) => {
|
|
|
15
15
|
for (let { coerce, valid, msg } of validators) {
|
|
16
16
|
if (coerce) x = coerce(x);
|
|
17
17
|
if (!valid(x)) {
|
|
18
|
-
if (isFunction(msg)) msg = msg(x);
|
|
18
|
+
if ($isFunction(msg)) msg = msg(x);
|
|
19
19
|
throw new ValidationError(msg ?? "failed validation");
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
return true;
|
|
23
23
|
};
|
|
24
24
|
const __asArray = (v) => $isArray(v) ? v : [v];
|
|
25
|
+
const ALWAYS = { valid: () => true };
|
|
26
|
+
const NEVER = { valid: () => false };
|
|
25
27
|
const optional = (first, ...rest) => {
|
|
26
28
|
const { coerce, valid, msg } = rest.length ? every(first, ...rest) : first;
|
|
27
29
|
return {
|
|
@@ -69,6 +71,14 @@ const isNullish = (msg) => ({
|
|
|
69
71
|
valid: (x) => x === null,
|
|
70
72
|
msg: msg ?? `expected nullish value`
|
|
71
73
|
});
|
|
74
|
+
const isArray = (msg) => ({
|
|
75
|
+
valid: $isArray,
|
|
76
|
+
msg: msg ?? `required array value`
|
|
77
|
+
});
|
|
78
|
+
const isArrayOf = (validators, msg) => ({
|
|
79
|
+
valid: $isArrayOf(validator(...__asArray(validators))),
|
|
80
|
+
msg: msg ?? `required array value`
|
|
81
|
+
});
|
|
72
82
|
const isBoolean = (msg) => ({
|
|
73
83
|
valid: $isBoolean,
|
|
74
84
|
msg: msg ?? `required boolean value`
|
|
@@ -85,26 +95,22 @@ const isDate = (msg) => ({
|
|
|
85
95
|
valid: $isDate,
|
|
86
96
|
msg: msg ?? `required date value`
|
|
87
97
|
});
|
|
98
|
+
const isFunction = (msg) => ({
|
|
99
|
+
valid: $isFunction,
|
|
100
|
+
msg: msg ?? `required function value`
|
|
101
|
+
});
|
|
88
102
|
const isRegExp = (msg) => ({
|
|
89
103
|
valid: $isRegExp,
|
|
90
104
|
msg: msg ?? `required regexp value`
|
|
91
105
|
});
|
|
92
106
|
const isObject = (msg) => ({
|
|
93
107
|
valid: isPlainObject,
|
|
94
|
-
msg: msg ?? `required object value`
|
|
108
|
+
msg: msg ?? `required plain object value`
|
|
95
109
|
});
|
|
96
110
|
const isObjectOf = (validators, msg) => ({
|
|
97
111
|
valid: $isObjectOf(validator(...__asArray(validators))),
|
|
98
112
|
msg: msg ?? `required object value`
|
|
99
113
|
});
|
|
100
|
-
const isArray = (msg) => ({
|
|
101
|
-
valid: $isArray,
|
|
102
|
-
msg: msg ?? `required array value`
|
|
103
|
-
});
|
|
104
|
-
const isArrayOf = (validators, msg) => ({
|
|
105
|
-
valid: $isArrayOf(validator(...__asArray(validators))),
|
|
106
|
-
msg: msg ?? `required array value`
|
|
107
|
-
});
|
|
108
114
|
const isTypedArray = (msg) => ({
|
|
109
115
|
valid: $isTypedArray,
|
|
110
116
|
msg: msg ?? `required typed array value`
|
|
@@ -118,30 +124,67 @@ const hasRequiredKeys = (keys, nonNullish = false, onlyKeys = false, msg) => ({
|
|
|
118
124
|
if (onlyKeys) __onlyKeys(keys, x);
|
|
119
125
|
return keys.every((k) => k in x && (nonNullish ? x[k] != null : true));
|
|
120
126
|
},
|
|
121
|
-
msg: msg ?? `required keys: ${keys.join(", ")}${nonNullish ? " (must be non-nullish)" : ""}`
|
|
127
|
+
msg: msg ?? `required keys: ${keys.join(", ")}${nonNullish ? " (values must be non-nullish)" : ""}`
|
|
122
128
|
});
|
|
123
129
|
const hasKeysOf = (validators, onlyKeys = false) => ({
|
|
124
130
|
valid: (x) => {
|
|
125
|
-
if (x == null) return false;
|
|
126
131
|
if (onlyKeys) __onlyKeys(Object.keys(validators), x);
|
|
127
|
-
for (let
|
|
132
|
+
for (let k in validators) {
|
|
128
133
|
try {
|
|
129
|
-
validator(...__asArray(
|
|
134
|
+
validator(...__asArray(validators[k]))(x[k]);
|
|
130
135
|
} catch (e) {
|
|
131
136
|
throw new ValidationError(
|
|
132
|
-
(e.origMessage ?? e.message) + ` (key: ${
|
|
137
|
+
(e.origMessage ?? e.message) + ` (key: ${k})`
|
|
133
138
|
);
|
|
134
139
|
}
|
|
135
140
|
}
|
|
136
141
|
return true;
|
|
137
142
|
}
|
|
138
143
|
});
|
|
144
|
+
const hasRequiredPatternKeys = (pattern, nonNullish = false, onlyKeys = false, msg) => ({
|
|
145
|
+
valid: (x) => {
|
|
146
|
+
let found = false;
|
|
147
|
+
for (let k in x) {
|
|
148
|
+
if (pattern.test(k)) {
|
|
149
|
+
if (nonNullish && x[k] == null) return false;
|
|
150
|
+
found = true;
|
|
151
|
+
} else if (onlyKeys) {
|
|
152
|
+
__disallowedKey(k);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return found;
|
|
156
|
+
},
|
|
157
|
+
msg: msg ?? `required pattern keys: ${pattern}${nonNullish ? " (values must be non-nullish)" : ""}`
|
|
158
|
+
});
|
|
159
|
+
const hasPatternKeysOf = (pattern, validators, onlyKeys = false) => {
|
|
160
|
+
const fn = validator(...__asArray(validators));
|
|
161
|
+
return {
|
|
162
|
+
valid: (x) => {
|
|
163
|
+
for (let k in x) {
|
|
164
|
+
if (pattern.test(k)) {
|
|
165
|
+
try {
|
|
166
|
+
fn(x[k]);
|
|
167
|
+
} catch (e) {
|
|
168
|
+
throw new ValidationError(
|
|
169
|
+
(e.origMessage ?? e.message) + ` (key: ${k})`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
} else if (onlyKeys) {
|
|
173
|
+
__disallowedKey(k);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
};
|
|
139
180
|
const __onlyKeys = (keys, x) => {
|
|
140
181
|
for (let k in x) {
|
|
141
|
-
if (!keys.includes(k))
|
|
142
|
-
throw new ValidationError(`key: ${k} not allowed`);
|
|
182
|
+
if (!keys.includes(k)) __disallowedKey(k);
|
|
143
183
|
}
|
|
144
184
|
};
|
|
185
|
+
const __disallowedKey = (key) => {
|
|
186
|
+
throw new ValidationError(`key: ${key} not allowed`);
|
|
187
|
+
};
|
|
145
188
|
const isEnum = (opts, msg) => ({
|
|
146
189
|
valid: (x) => opts.includes(x),
|
|
147
190
|
msg: msg ?? `required value to be one of: ${opts.join(", ")}`
|
|
@@ -187,15 +230,20 @@ const matchesRegexp = (re, msg) => ({
|
|
|
187
230
|
msg: msg ?? `doesn't match pattern`
|
|
188
231
|
});
|
|
189
232
|
export {
|
|
233
|
+
ALWAYS,
|
|
234
|
+
NEVER,
|
|
190
235
|
ValidationError,
|
|
191
236
|
every,
|
|
192
237
|
hasKeysOf,
|
|
238
|
+
hasPatternKeysOf,
|
|
193
239
|
hasRequiredKeys,
|
|
240
|
+
hasRequiredPatternKeys,
|
|
194
241
|
isArray,
|
|
195
242
|
isArrayOf,
|
|
196
243
|
isBoolean,
|
|
197
244
|
isDate,
|
|
198
245
|
isEnum,
|
|
246
|
+
isFunction,
|
|
199
247
|
isInRange,
|
|
200
248
|
isLength,
|
|
201
249
|
isMaxLength,
|