@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 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
- - [`oneOf()`](https://docs.thi.ng/umbrella/validate/functions/oneOf.html)
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: 1021 bytes
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.1.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": "92be63f24030506f09d6d156804da2798c381dc4"
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 an existing validator and returns an augmented
60
- * version which also allows value to be nullish.
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 optional: ({ coerce, valid, msg }: Validator) => Validator;
75
+ export declare const not: ({ coerce, valid, msg: $msg }: Validator, msg?: Validator["msg"]) => Validator;
65
76
  /**
66
- * Higher order validator. Takes a numer of validators and returns a new one
67
- * which will apply the validators in given order, but return when the first one
68
- * succeeds and only fails if all of the validators failed.
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 validators
81
+ * @param first
82
+ * @param rest
71
83
  */
72
- export declare const oneOf: (validators: (Validator | Validator[])[]) => Validator;
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 hasRequiredKeys: (keys: string[], msg?: Validator["msg"]) => Validator;
102
- export declare const hasKeysOf: (validators: Record<PropertyKey, Validator | Validator[]>) => Validator;
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 optional = ({ coerce, valid, msg }) => ({
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) => x == null || valid(x),
26
- msg
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 __asArray = (v) => $isArray(v) ? v : [v];
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 validators) {
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 hasRequiredKeys = (keys, msg) => ({
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
- const $keys = new Set(Object.keys(x));
93
- return keys.every((k) => $keys.has(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
- oneOf,
218
+ not,
183
219
  optional,
220
+ some,
184
221
  validator
185
222
  };