@thi.ng/validate 0.3.6 → 0.4.1

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 CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  > [!NOTE]
10
10
 
11
- > This is one of 215 standalone projects. LLM-free, human-made and
11
+ > This is one of 216 standalone projects. LLM-free, human-made and
12
12
  > cared for software, maintained as part of the
13
13
  > [@thi.ng/umbrella](https://codeberg.org/thi.ng/umbrella/) ecosystem and
14
14
  > anti-framework.
@@ -21,6 +21,7 @@
21
21
  - [Built-in validators](#built-in-validators)
22
22
  - [Combinators](#combinators)
23
23
  - [Status](#status)
24
+ - [Support packages](#support-packages)
24
25
  - [Installation](#installation)
25
26
  - [Dependencies](#dependencies)
26
27
  - [API](#api)
@@ -77,11 +78,15 @@ try {
77
78
  - [`isBoolean()`](https://docs.thi.ng/umbrella/validate/functions/isBoolean.html)
78
79
  - [`isDate()`](https://docs.thi.ng/umbrella/validate/functions/isDate.html)
79
80
  - [`isEnum()`](https://docs.thi.ng/umbrella/validate/functions/isEnum.html)
80
- - [`isInRange()`](https://docs.thi.ng/umbrella/validate/functions/isInRange.html)
81
+ - [`isEqual()`](https://docs.thi.ng/umbrella/validate/functions/isEqual.html)
82
+ - [`isInClosedInterval()`](https://docs.thi.ng/umbrella/validate/functions/isInClosedInterval.html)
83
+ - [`isInOpenInterval()`](https://docs.thi.ng/umbrella/validate/functions/isInOpenInterval.html)
84
+ - [`isInteger()`](https://docs.thi.ng/umbrella/validate/functions/isInteger.html)
81
85
  - [`isLength()`](https://docs.thi.ng/umbrella/validate/functions/isLength.html)
82
86
  - [`isMaxLength()`](https://docs.thi.ng/umbrella/validate/functions/isMaxLength.html)
83
87
  - [`isMinLength()`](https://docs.thi.ng/umbrella/validate/functions/isMinLength.html)
84
88
  - [`isMinMaxLength()`](https://docs.thi.ng/umbrella/validate/functions/isMinMaxLength.html)
89
+ - [`isMultipleOf()`](https://docs.thi.ng/umbrella/validate/functions/isMultipleOf.html)
85
90
  - [`isNegative()`](https://docs.thi.ng/umbrella/validate/functions/isNegative.html)
86
91
  - [`isNonNegative()`](https://docs.thi.ng/umbrella/validate/functions/isNonNegative.html)
87
92
  - [`isNonPositive()`](https://docs.thi.ng/umbrella/validate/functions/isNonPositive.html)
@@ -110,6 +115,10 @@ try {
110
115
 
111
116
  [Search or submit any issues for this package](https://codeberg.org/thi.ng/umbrella/issues?q=%5Bvalidate%5D)
112
117
 
118
+ ## Support packages
119
+
120
+ - [@thi.ng/validate-schema](https://codeberg.org/thi.ng/umbrella/src/branch/develop/packages/validate-schema) - JSON schema validation layer for [@thi.ng/validate](https://codeberg.org/thi.ng/umbrella/src/branch/develop/packages/validate)
121
+
113
122
  ## Installation
114
123
 
115
124
  ```bash
@@ -136,12 +145,13 @@ For Node.js REPL:
136
145
  const val = await import("@thi.ng/validate");
137
146
  ```
138
147
 
139
- Package sizes (brotli'd, pre-treeshake): ESM: 1.34 KB
148
+ Package sizes (brotli'd, pre-treeshake): ESM: 1.53 KB
140
149
 
141
150
  ## Dependencies
142
151
 
143
152
  - [@thi.ng/api](https://codeberg.org/thi.ng/umbrella/src/branch/develop/packages/api)
144
153
  - [@thi.ng/checks](https://codeberg.org/thi.ng/umbrella/src/branch/develop/packages/checks)
154
+ - [@thi.ng/equiv](https://codeberg.org/thi.ng/umbrella/src/branch/develop/packages/equiv)
145
155
  - [@thi.ng/errors](https://codeberg.org/thi.ng/umbrella/src/branch/develop/packages/errors)
146
156
 
147
157
  Note: @thi.ng/api is in _most_ cases a type-only import (not used at runtime)
package/api.d.ts CHANGED
@@ -12,6 +12,7 @@ export interface Validator {
12
12
  /**
13
13
  * Optional error message (or function to produce such).
14
14
  */
15
- msg?: string | Fn<any, string>;
15
+ msg?: ValidatorMsg;
16
16
  }
17
+ export type ValidatorMsg = string | Fn<any, string>;
17
18
  //# sourceMappingURL=api.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/validate",
3
- "version": "0.3.6",
3
+ "version": "0.4.1",
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,10 @@
40
40
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@thi.ng/api": "^8.12.25",
44
- "@thi.ng/checks": "^3.9.5",
45
- "@thi.ng/errors": "^2.6.14"
43
+ "@thi.ng/api": "^8.12.26",
44
+ "@thi.ng/checks": "^3.10.0",
45
+ "@thi.ng/equiv": "^2.1.115",
46
+ "@thi.ng/errors": "^2.6.15"
46
47
  },
47
48
  "devDependencies": {
48
49
  "esbuild": "^0.28.0",
@@ -85,5 +86,5 @@
85
86
  "status": "alpha",
86
87
  "year": 2026
87
88
  },
88
- "gitHead": "65b041e97110e16c01cf968949b72a0873f14445"
89
+ "gitHead": "c87ef48d7000abc4e38ecf04ab8685f3901b2952"
89
90
  }
package/validators.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Validator } from "./api.js";
1
+ import type { Validator, ValidatorMsg } from "./api.js";
2
2
  /**
3
3
  * Error type thrown by validation functions.
4
4
  */
@@ -80,7 +80,7 @@ export declare const optional: (first: Validator, ...rest: Validator[]) => Valid
80
80
  * @param validator
81
81
  * @param msg
82
82
  */
83
- export declare const not: ({ coerce, valid, msg: $msg }: Validator, msg?: Validator["msg"]) => Validator;
83
+ export declare const not: ({ coerce, valid, msg: $msg }: Validator, msg?: ValidatorMsg) => Validator;
84
84
  /**
85
85
  * Higher order validator. Takes one or more validators and returns a new one
86
86
  * which will apply the validators in given order, and return successfully with
@@ -109,27 +109,42 @@ export declare const every: (first: Validator, ...rest: Validator[]) => Validato
109
109
  *
110
110
  * @param msg
111
111
  */
112
- export declare const isUndefined: (msg?: Validator["msg"]) => Validator;
112
+ export declare const isUndefined: (msg?: ValidatorMsg) => Validator;
113
113
  /**
114
114
  * Returns validator to check if value is nullish.
115
115
  *
116
116
  * @param msg
117
117
  */
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;
121
- export declare const isBoolean: (msg?: Validator["msg"]) => Validator;
122
- export declare const isNumber: (msg?: Validator["msg"]) => Validator;
123
- export declare const isString: (msg?: Validator["msg"]) => Validator;
124
- export declare const isDate: (msg?: Validator["msg"]) => Validator;
125
- export declare const isFunction: (msg?: Validator["msg"]) => Validator;
126
- export declare const isRegExp: (msg?: Validator["msg"]) => Validator;
118
+ export declare const isNullish: (msg?: ValidatorMsg) => Validator;
119
+ /**
120
+ * Returns validator to check if value equals `expected` value (uses
121
+ * [`equiv()`](https://thi.ng/equiv) for equality checking).
122
+ *
123
+ * @param expected
124
+ * @param msg
125
+ */
126
+ export declare const isEqual: (expected: any, msg?: ValidatorMsg) => Validator;
127
+ export declare const isArray: (msg?: ValidatorMsg) => Validator;
128
+ export declare const isArrayOf: (validators: Validator | Validator[], msg?: ValidatorMsg) => Validator;
129
+ export declare const isBoolean: (msg?: ValidatorMsg) => Validator;
130
+ export declare const isNumber: (msg?: ValidatorMsg) => Validator;
131
+ /**
132
+ * Return validator to check if value is an integer (not necessarily in the
133
+ * 32bit range, but merely if the value has no fractional part).
134
+ *
135
+ * @param msg
136
+ */
137
+ export declare const isInteger: (msg?: ValidatorMsg) => Validator;
138
+ export declare const isString: (msg?: ValidatorMsg) => Validator;
139
+ export declare const isDate: (msg?: ValidatorMsg) => Validator;
140
+ export declare const isFunction: (msg?: ValidatorMsg) => Validator;
141
+ export declare const isRegExp: (msg?: ValidatorMsg) => Validator;
127
142
  /**
128
143
  * Returns validator which checks that given value is a plain object (not class).
129
144
  *
130
145
  * @param msg
131
146
  */
132
- export declare const isObject: (msg?: Validator["msg"]) => Validator;
147
+ export declare const isObject: (msg?: ValidatorMsg) => Validator;
133
148
  /**
134
149
  * Returns validator to check if value is a plain object and the values of all
135
150
  * its keys are matching given validators.
@@ -137,14 +152,23 @@ export declare const isObject: (msg?: Validator["msg"]) => Validator;
137
152
  * @param validators
138
153
  * @param msg
139
154
  */
140
- export declare const isObjectOf: (validators: Validator | Validator[], msg?: Validator["msg"]) => Validator;
141
- export declare const isTypedArray: (msg?: Validator["msg"]) => Validator;
155
+ export declare const isObjectOf: (validators: Validator | Validator[], msg?: ValidatorMsg) => Validator;
156
+ export declare const isTypedArray: (msg?: ValidatorMsg) => Validator;
142
157
  /**
143
158
  * Returns validator to check if value is a `Uint8Array`.
144
159
  *
145
160
  * @param msg
146
161
  */
147
- export declare const isU8Array: (msg?: Validator["msg"]) => Validator;
162
+ export declare const isU8Array: (msg?: ValidatorMsg) => Validator;
163
+ /**
164
+ * Returns validator to check if value is a number and a multiple of given
165
+ * `base` (using `eps` tolerance, default: 1e-6).
166
+ *
167
+ * @param base
168
+ * @param eps
169
+ * @param msg
170
+ */
171
+ export declare const isMultipleOf: (base: number, eps?: number, msg?: ValidatorMsg) => Validator;
148
172
  /**
149
173
  * Returns validator to ensure given `keys` are present in an object, optionally
150
174
  * also checks their values are `nonNullish` (default: false). If `onlyKeys` is
@@ -156,7 +180,7 @@ export declare const isU8Array: (msg?: Validator["msg"]) => Validator;
156
180
  * @param onlyKeys
157
181
  * @param msg
158
182
  */
159
- export declare const hasRequiredKeys: (keys: string[], nonNullish?: boolean, onlyKeys?: boolean, msg?: Validator["msg"]) => Validator;
183
+ export declare const hasRequiredKeys: (keys: string[], nonNullish?: boolean, onlyKeys?: boolean, msg?: ValidatorMsg) => Validator;
160
184
  /**
161
185
  * Takes object of validators to check values of different keys in an object.
162
186
  * Returns validator which applies all checks, optionally also ensures no other
@@ -166,7 +190,7 @@ export declare const hasRequiredKeys: (keys: string[], nonNullish?: boolean, onl
166
190
  * @param onlyKeys
167
191
  */
168
192
  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;
193
+ export declare const hasRequiredPatternKeys: (pattern: RegExp, nonNullish?: boolean, onlyKeys?: boolean, msg?: ValidatorMsg) => Validator;
170
194
  export declare const hasPatternKeysOf: (pattern: RegExp, validators: Validator | Validator[], onlyKeys?: boolean) => Validator;
171
195
  /**
172
196
  * Returns validator to check if value is one of the given options. Values are
@@ -175,7 +199,7 @@ export declare const hasPatternKeysOf: (pattern: RegExp, validators: Validator |
175
199
  * @param opts
176
200
  * @param msg
177
201
  */
178
- export declare const isEnum: <T>(opts: T[], msg?: Validator["msg"]) => Validator;
202
+ export declare const isEnum: <T>(opts: T[], msg?: ValidatorMsg) => Validator;
179
203
  /**
180
204
  * Returns validator to check if value is in given closed [min,max] interval.
181
205
  *
@@ -183,20 +207,23 @@ export declare const isEnum: <T>(opts: T[], msg?: Validator["msg"]) => Validator
183
207
  * @param max
184
208
  * @param msg
185
209
  */
186
- export declare const isInRange: <T extends number | string>(min: T, max: T, msg?: Validator["msg"]) => Validator;
187
- export declare const isPositive: (msg?: Validator["msg"]) => Validator;
188
- export declare const isNegative: (msg?: Validator["msg"]) => Validator;
189
- export declare const isNonPositive: (msg?: Validator["msg"]) => Validator;
190
- export declare const isNonNegative: (msg?: Validator["msg"]) => Validator;
191
- export declare const isLength: (n: number, msg?: Validator["msg"]) => Validator;
192
- export declare const isMinLength: (n: number, msg?: Validator["msg"]) => Validator;
193
- export declare const isMaxLength: (n: number, msg?: Validator["msg"]) => Validator;
194
- export declare const isMinMaxLength: (min: number, max: number, msg?: Validator["msg"]) => Validator;
210
+ export declare const isInClosedInterval: (min: number, max: number, msg?: ValidatorMsg) => Validator;
211
+ /** @deprecated renamed to {@link isInClosedInterval} */
212
+ export declare const isInRange: (min: number, max: number, msg?: ValidatorMsg) => Validator;
213
+ export declare const isInOpenInterval: (min: number, max: number, msg?: ValidatorMsg) => Validator;
214
+ export declare const isPositive: (msg?: ValidatorMsg) => Validator;
215
+ export declare const isNegative: (msg?: ValidatorMsg) => Validator;
216
+ export declare const isNonPositive: (msg?: ValidatorMsg) => Validator;
217
+ export declare const isNonNegative: (msg?: ValidatorMsg) => Validator;
218
+ export declare const isLength: (n: number, msg?: ValidatorMsg) => Validator;
219
+ export declare const isMinLength: (n: number, msg?: ValidatorMsg) => Validator;
220
+ export declare const isMaxLength: (n: number, msg?: ValidatorMsg) => Validator;
221
+ export declare const isMinMaxLength: (min: number, max: number, msg?: ValidatorMsg) => Validator;
195
222
  /**
196
223
  * Returns validator to check if value is a string and matches given regexp.
197
224
  *
198
225
  * @param re
199
226
  * @param msg
200
227
  */
201
- export declare const matchesRegexp: (re: RegExp, msg?: Validator["msg"]) => Validator;
228
+ export declare const matchesRegexp: (re: RegExp, msg?: ValidatorMsg) => Validator;
202
229
  //# sourceMappingURL=validators.d.ts.map
package/validators.js CHANGED
@@ -3,12 +3,14 @@ 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
5
  import { isFunction as $isFunction } from "@thi.ng/checks/is-function";
6
+ import { isMultipleOf as $isMultipleOf } from "@thi.ng/checks/is-multiple-of";
6
7
  import { isNumber as $isNumber } from "@thi.ng/checks/is-number";
7
8
  import { isObjectOf as $isObjectOf } from "@thi.ng/checks/is-object-of";
8
9
  import { isPlainObject } from "@thi.ng/checks/is-plain-object";
9
10
  import { isRegExp as $isRegExp } from "@thi.ng/checks/is-regexp";
10
11
  import { isString as $isString } from "@thi.ng/checks/is-string";
11
12
  import { isTypedArray as $isTypedArray } from "@thi.ng/checks/is-typedarray";
13
+ import { equiv } from "@thi.ng/equiv";
12
14
  import { defError } from "@thi.ng/errors/deferror";
13
15
  const ValidationError = defError(() => `validation error`);
14
16
  const validator = (...validators) => (x) => {
@@ -65,66 +67,80 @@ const every = (first, ...rest) => ({
65
67
  });
66
68
  const isUndefined = (msg) => ({
67
69
  valid: (x) => x === void 0,
68
- msg: msg ?? `expected undefined value`
70
+ msg: msg ?? __expectedVal("undefined")
69
71
  });
70
72
  const isNullish = (msg) => ({
71
73
  valid: (x) => x === null,
72
- msg: msg ?? `expected nullish value`
74
+ msg: msg ?? __expectedVal("nullish")
75
+ });
76
+ const isEqual = (expected, msg) => ({
77
+ valid: (x) => equiv(x, expected),
78
+ msg: msg ?? __expected(`value to be: ${JSON.stringify(expected) ?? "null"}`)
73
79
  });
74
80
  const isArray = (msg) => ({
75
81
  valid: $isArray,
76
- msg: msg ?? `required array value`
82
+ msg: msg ?? __expectedVal("array")
77
83
  });
78
84
  const isArrayOf = (validators, msg) => ({
79
85
  valid: $isArrayOf(validator(...__asArray(validators))),
80
- msg: msg ?? `required array value`
86
+ msg: msg ?? __expectedVal("array")
81
87
  });
82
88
  const isBoolean = (msg) => ({
83
89
  valid: $isBoolean,
84
- msg: msg ?? `required boolean value`
90
+ msg: msg ?? __expectedVal("boolean")
85
91
  });
86
92
  const isNumber = (msg) => ({
87
93
  valid: $isNumber,
88
- msg: msg ?? `required number value`
94
+ msg: msg ?? __expectedVal("number")
95
+ });
96
+ const isInteger = (msg) => ({
97
+ valid: (x) => $isNumber(x) && Math.trunc(x) === x,
98
+ msg: msg ?? __expectedVal("integer")
89
99
  });
90
100
  const isString = (msg) => ({
91
101
  valid: $isString,
92
- msg: msg ?? `required string value`
102
+ msg: msg ?? __expectedVal("string")
93
103
  });
94
104
  const isDate = (msg) => ({
95
105
  valid: $isDate,
96
- msg: msg ?? `required date value`
106
+ msg: msg ?? __expectedVal("date")
97
107
  });
98
108
  const isFunction = (msg) => ({
99
109
  valid: $isFunction,
100
- msg: msg ?? `required function value`
110
+ msg: msg ?? __expectedVal("function")
101
111
  });
102
112
  const isRegExp = (msg) => ({
103
113
  valid: $isRegExp,
104
- msg: msg ?? `required regexp value`
114
+ msg: msg ?? __expectedVal("regexp")
105
115
  });
106
116
  const isObject = (msg) => ({
107
117
  valid: isPlainObject,
108
- msg: msg ?? `required plain object value`
118
+ msg: msg ?? __expectedVal("object")
109
119
  });
110
120
  const isObjectOf = (validators, msg) => ({
111
121
  valid: $isObjectOf(validator(...__asArray(validators))),
112
- msg: msg ?? `required object value`
122
+ msg: msg ?? __expectedVal("object")
113
123
  });
114
124
  const isTypedArray = (msg) => ({
115
125
  valid: $isTypedArray,
116
- msg: msg ?? `required typed array value`
126
+ msg: msg ?? __expectedVal(`typed array`)
117
127
  });
118
128
  const isU8Array = (msg) => ({
119
129
  valid: (x) => x instanceof Uint8Array,
120
- msg: msg ?? `required byte array value`
130
+ msg: msg ?? __expectedVal(`byte array`)
131
+ });
132
+ const isMultipleOf = (base, eps, msg) => ({
133
+ valid: (x) => $isMultipleOf(base, x, eps),
134
+ msg: msg ?? __expected(`number value, a multiple of ${base}`)
121
135
  });
122
136
  const hasRequiredKeys = (keys, nonNullish = false, onlyKeys = false, msg) => ({
123
137
  valid: (x) => {
124
138
  if (onlyKeys) __onlyKeys(keys, x);
125
139
  return keys.every((k) => k in x && (nonNullish ? x[k] != null : true));
126
140
  },
127
- msg: msg ?? `required keys: ${keys.join(", ")}${nonNullish ? " (values must be non-nullish)" : ""}`
141
+ msg: msg ?? __expected(
142
+ `keys: ${keys.join(", ")}${nonNullish ? " (values must be non-nullish)" : ""}`
143
+ )
128
144
  });
129
145
  const hasKeysOf = (validators, onlyKeys = false) => ({
130
146
  valid: (x) => {
@@ -154,7 +170,9 @@ const hasRequiredPatternKeys = (pattern, nonNullish = false, onlyKeys = false, m
154
170
  }
155
171
  return found;
156
172
  },
157
- msg: msg ?? `required pattern keys: ${pattern}${nonNullish ? " (values must be non-nullish)" : ""}`
173
+ msg: msg ?? __expected(
174
+ `pattern keys: ${pattern}${nonNullish ? " (values must be non-nullish)" : ""}`
175
+ )
158
176
  });
159
177
  const hasPatternKeysOf = (pattern, validators, onlyKeys = false) => {
160
178
  const fn = validator(...__asArray(validators));
@@ -187,48 +205,55 @@ const __disallowedKey = (key) => {
187
205
  };
188
206
  const isEnum = (opts, msg) => ({
189
207
  valid: (x) => opts.includes(x),
190
- msg: msg ?? `required value to be one of: ${opts.join(", ")}`
208
+ msg: msg ?? __expected(`value to be one of: ${opts.join(", ")}`)
191
209
  });
192
- const isInRange = (min, max, msg) => ({
210
+ const isInClosedInterval = (min, max, msg) => ({
193
211
  valid: (x) => x >= min && x <= max,
194
- msg: msg ?? ((x) => `value ${x} not in range [${min},${max}]`)
212
+ msg: msg ?? (min > -Infinity ? max < Infinity ? __expected(`value in closed interval [${min},${max}]`) : __expected(`value >= ${min}`) : max < Infinity ? __expected(`value <= ${max}`) : "")
213
+ });
214
+ const isInRange = isInClosedInterval;
215
+ const isInOpenInterval = (min, max, msg) => ({
216
+ valid: (x) => x > min && x < max,
217
+ msg: msg ?? (min > -Infinity ? max < Infinity ? __expected(`value in open interval (${min},${max})`) : __expected(`value > ${min}`) : max < Infinity ? __expected(`value < ${max}`) : "")
195
218
  });
196
219
  const isPositive = (msg) => ({
197
220
  valid: (x) => x > 0,
198
- msg: msg ?? `required positive value`
221
+ msg: msg ?? __expectedVal("positive")
199
222
  });
200
223
  const isNegative = (msg) => ({
201
224
  valid: (x) => x < 0,
202
- msg: msg ?? `required negative number`
225
+ msg: msg ?? __expectedVal("negative")
203
226
  });
204
227
  const isNonPositive = (msg) => ({
205
228
  valid: (x) => x <= 0,
206
- msg: msg ?? `required non-positive value`
229
+ msg: msg ?? __expectedVal("non-positive")
207
230
  });
208
231
  const isNonNegative = (msg) => ({
209
232
  valid: (x) => x >= 0,
210
- msg: msg ?? `required non-negative value`
233
+ msg: msg ?? __expectedVal("non-negative")
211
234
  });
212
235
  const isLength = (n, msg) => ({
213
236
  valid: (x) => x?.length === n,
214
- msg: msg ?? `required length (${n})`
237
+ msg: msg ?? __expected(`length of ${n}`)
215
238
  });
216
239
  const isMinLength = (n, msg) => ({
217
240
  valid: (x) => x?.length >= n,
218
- msg: msg ?? `required min. length (${n})`
241
+ msg: msg ?? __expected(`min. length ${n}`)
219
242
  });
220
243
  const isMaxLength = (n, msg) => ({
221
244
  valid: (x) => x?.length <= n,
222
- msg: msg ?? `required max. length (${n})`
245
+ msg: msg ?? __expected(`max. length ${n}`)
223
246
  });
224
- const isMinMaxLength = (min, max, msg) => ({
247
+ const isMinMaxLength = (min, max, msg) => min > 0 ? max < Infinity ? min !== max ? {
225
248
  valid: (x) => x?.length >= min && x?.length <= max,
226
- msg: msg ?? `length not in [${min},${max}] range`
227
- });
249
+ msg: msg ?? __expected(`length in [${min},${max}] range`)
250
+ } : isLength(min) : isMinLength(min) : max < Infinity ? isMaxLength(max) : ALWAYS;
228
251
  const matchesRegexp = (re, msg) => ({
229
252
  valid: (x) => $isString(x) && re.test(x),
230
- msg: msg ?? `doesn't match pattern`
253
+ msg: msg ?? __expected(`pattern: ${re.source}`)
231
254
  });
255
+ const __expected = (x) => `expected ${x}`;
256
+ const __expectedVal = (x) => `expected ${x} value`;
232
257
  export {
233
258
  ALWAYS,
234
259
  NEVER,
@@ -243,12 +268,17 @@ export {
243
268
  isBoolean,
244
269
  isDate,
245
270
  isEnum,
271
+ isEqual,
246
272
  isFunction,
273
+ isInClosedInterval,
274
+ isInOpenInterval,
247
275
  isInRange,
276
+ isInteger,
248
277
  isLength,
249
278
  isMaxLength,
250
279
  isMinLength,
251
280
  isMinMaxLength,
281
+ isMultipleOf,
252
282
  isNegative,
253
283
  isNonNegative,
254
284
  isNonPositive,