@modulify/validator 0.1.0 → 0.2.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +324 -107
  3. package/dist/assert.cjs +66 -0
  4. package/dist/assert.d.ts +16 -0
  5. package/dist/assert.mjs +66 -0
  6. package/dist/assertions.cjs +190 -92
  7. package/dist/assertions.d.ts +58 -2
  8. package/dist/assertions.mjs +191 -93
  9. package/dist/checkers.d.ts +8 -0
  10. package/dist/combinators.cjs +341 -0
  11. package/dist/combinators.d.ts +17 -0
  12. package/dist/combinators.mjs +341 -0
  13. package/dist/constraints.d.ts +4 -0
  14. package/dist/extractors.d.ts +2 -0
  15. package/dist/index.cjs +172 -61
  16. package/dist/index.d.ts +10 -4
  17. package/dist/index.mjs +176 -64
  18. package/dist/json-schema.cjs +514 -0
  19. package/dist/json-schema.d.ts +14 -0
  20. package/dist/json-schema.mjs +514 -0
  21. package/dist/metadata.cjs +8 -0
  22. package/dist/metadata.cjs.js +130 -0
  23. package/dist/metadata.d.ts +8 -0
  24. package/dist/metadata.es.js +131 -0
  25. package/dist/metadata.mjs +8 -0
  26. package/dist/predicates.cjs +40 -5
  27. package/dist/predicates.d.ts +25 -3
  28. package/dist/predicates.mjs +40 -5
  29. package/dist/violations.d.ts +29 -0
  30. package/docs/en/00-index.md +14 -0
  31. package/docs/en/01-shape-api.md +348 -0
  32. package/docs/en/02-metadata-and-introspection.md +276 -0
  33. package/docs/en/03-violations.md +267 -0
  34. package/docs/en/04-json-schema-export.md +264 -0
  35. package/docs/en/05-public-api.md +123 -0
  36. package/docs/en/06-common-recipes.md +273 -0
  37. package/docs/en/07-ai-reference.md +215 -0
  38. package/docs/en/08-violation-code-types.md +241 -0
  39. package/docs/ru/00-index.md +15 -0
  40. package/docs/ru/01-shape-api.md +348 -0
  41. package/docs/ru/02-metadata-and-introspection.md +276 -0
  42. package/docs/ru/03-violations.md +267 -0
  43. package/docs/ru/04-json-schema-export.md +264 -0
  44. package/docs/ru/05-public-api.md +123 -0
  45. package/docs/ru/06-common-recipes.md +273 -0
  46. package/docs/ru/07-ai-reference.md +215 -0
  47. package/docs/ru/08-violation-code-types.md +241 -0
  48. package/docs/ru/README.md +371 -0
  49. package/package.json +51 -33
  50. package/types/index.d.ts +789 -30
  51. package/types/json-schema.d.ts +75 -0
  52. package/dist/assertions/Assert.d.ts +0 -2
  53. package/dist/assertions/HasLength.d.ts +0 -7
  54. package/dist/assertions/check.d.ts +0 -3
  55. package/dist/assertions/index.d.ts +0 -16
  56. package/dist/runners/Each.d.ts +0 -3
  57. package/dist/runners/HasProperties.d.ts +0 -6
  58. package/dist/runners/index.d.ts +0 -2
  59. package/dist/runners.cjs +0 -32
  60. package/dist/runners.d.ts +0 -2
  61. package/dist/runners.mjs +0 -32
@@ -0,0 +1,2 @@
1
+ export declare const length: <T extends unknown[] | string>(value: T) => number;
2
+ export declare const size: <T extends Map<unknown, unknown> | Set<unknown>>(value: T) => number;
package/dist/index.cjs CHANGED
@@ -1,51 +1,119 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const assertions = require("./assertions.cjs");
4
- const runners = require("./runners.cjs");
5
- const check = (assert, value, path = []) => {
6
- if (assert(value)) {
7
- for (const a of assert.also) {
8
- const violation = check(a, value, path);
9
- if (violation) {
10
- return {
11
- ...violation,
12
- violates: assert.fqn
13
- };
14
- }
15
- }
16
- return null;
4
+ const combinators = require("./combinators.cjs");
5
+ const metadata = require("./metadata.cjs.js");
6
+ const assert = require("./assert.cjs");
7
+ const ROOT_PATH = Object.freeze([]);
8
+ const normalizePath = (path) => path ?? ROOT_PATH;
9
+ const isSamePath = (left, right = ROOT_PATH) => {
10
+ const normalizedLeft = normalizePath(left);
11
+ if (normalizedLeft.length !== right.length) {
12
+ return false;
17
13
  }
18
- return {
19
- value,
20
- path,
21
- violates: assert.fqn,
22
- ..."reason" in assert ? { reason: assert.reason } : {},
23
- ..."meta" in assert ? { meta: assert.meta } : {}
24
- };
14
+ return normalizedLeft.every((part, index) => Object.is(part, right[index]));
25
15
  };
26
- const isBatch = (c) => {
27
- return "run" in c;
16
+ const isPathPrefix = (path, prefix) => {
17
+ if (prefix.length > path.length) {
18
+ return false;
19
+ }
20
+ return prefix.every((part, index) => Object.is(part, path[index]));
28
21
  };
29
- const _validate = async (value, constraints, path = []) => {
22
+ const createTreeState = (path) => ({
23
+ path: Object.freeze([...path]),
24
+ self: [],
25
+ subtree: [],
26
+ children: /* @__PURE__ */ new Map()
27
+ });
28
+ class TreeNode {
29
+ constructor(state) {
30
+ this.path = state.path;
31
+ this.self = new ViolationCollection(state.self);
32
+ this.subtree = new ViolationCollection(state.subtree);
33
+ this.children = new Map(
34
+ [...state.children.entries()].map(([key, child]) => [key, new TreeNode(child)])
35
+ );
36
+ }
37
+ at(path) {
38
+ if (!isPathPrefix(path, this.path)) {
39
+ return void 0;
40
+ }
41
+ if (path.length === this.path.length) {
42
+ return this;
43
+ }
44
+ const child = this.children.get(path[this.path.length]);
45
+ return child?.at(path);
46
+ }
47
+ }
48
+ const buildTree = (violations) => {
49
+ const root = createTreeState(ROOT_PATH);
50
+ violations.forEach((violation) => {
51
+ const path = normalizePath(violation.path);
52
+ root.subtree.push(violation);
53
+ if (path.length === 0) {
54
+ root.self.push(violation);
55
+ return;
56
+ }
57
+ let current = root;
58
+ const currentPath = [];
59
+ path.forEach((segment, index) => {
60
+ currentPath.push(segment);
61
+ let child = current.children.get(segment);
62
+ if (!child) {
63
+ child = createTreeState(currentPath);
64
+ current.children.set(segment, child);
65
+ }
66
+ child.subtree.push(violation);
67
+ if (index === path.length - 1) {
68
+ child.self.push(violation);
69
+ }
70
+ current = child;
71
+ });
72
+ });
73
+ return new TreeNode(root);
74
+ };
75
+ class ViolationCollection {
76
+ constructor(violations) {
77
+ this.violations = [...violations];
78
+ this.size = this.violations.length;
79
+ }
80
+ [Symbol.iterator]() {
81
+ return this.violations[Symbol.iterator]();
82
+ }
83
+ forEach(callback) {
84
+ this.violations.forEach((violation, index) => callback(violation, index, this));
85
+ }
86
+ map(callback) {
87
+ return this.violations.map((violation, index) => callback(violation, index, this));
88
+ }
89
+ at(path) {
90
+ return new ViolationCollection(this.violations.filter((violation) => isSamePath(violation.path, path)));
91
+ }
92
+ tree() {
93
+ return buildTree(this.violations);
94
+ }
95
+ }
96
+ const collection = (violations) => new ViolationCollection(violations);
97
+ const collectViolations = async (value, constraints, path = []) => {
30
98
  const validations = [];
31
- for (const c of arraify(constraints)) {
32
- if (isBatch(c)) {
33
- validations.push(...c.run(_validate, value, path).map((v2) => v2 instanceof Promise ? v2 : Promise.resolve(v2)));
99
+ for (const c of metadata.arrayify(constraints)) {
100
+ if (metadata.isValidator(c)) {
101
+ validations.push(...c.run(collectViolations, value, path).map((v2) => v2 instanceof Promise ? v2 : Promise.resolve(v2)));
34
102
  continue;
35
103
  }
36
- const v = "That" in c ? check(c, value, [...path]) : c(value, [...path]);
104
+ const v = c(value);
37
105
  if (v instanceof Promise) {
38
106
  if (c.bail) {
39
107
  const awaited = await v;
40
108
  if (awaited) {
41
- validations.push(Promise.resolve([awaited]));
109
+ validations.push(Promise.resolve([Object.assign(awaited, { path: [...path] })]));
42
110
  break;
43
111
  }
44
112
  } else {
45
- validations.push(v.then((v2) => v2 ? [v2] : []));
113
+ validations.push(v.then((v2) => v2 ? [Object.assign(v2, { path: [...path] })] : []));
46
114
  }
47
115
  } else if (v) {
48
- validations.push(Promise.resolve([v]));
116
+ validations.push(Promise.resolve([Object.assign(v, { path: [...path] })]));
49
117
  if (c.bail) {
50
118
  break;
51
119
  }
@@ -53,30 +121,25 @@ const _validate = async (value, constraints, path = []) => {
53
121
  }
54
122
  return settle(value, path, validations);
55
123
  };
56
- const _sync = (value, constraints, path = []) => {
124
+ const collectViolationsSync = (value, constraints, path = []) => {
57
125
  const violations = [];
58
- for (const c of arraify(constraints)) {
59
- if (isBatch(c)) {
60
- violations.push(...c.run(_sync, value, path));
126
+ for (const c of metadata.arrayify(constraints)) {
127
+ if (metadata.isValidator(c)) {
128
+ violations.push(...c.run(collectViolationsSync, value, path));
61
129
  continue;
62
130
  }
63
- const v = "That" in c ? check(c, value, [...path]) : c(value, [...path]);
131
+ const v = c(value);
64
132
  if (v instanceof Promise) {
65
- throw new Error("Found asynchronous constraint validator " + String(c.fqn));
133
+ throw new Error("Found asynchronous validator " + String(c.name));
66
134
  } else if (v) {
67
- violations.push(v);
68
- if (c.bail) {
69
- break;
70
- }
135
+ violations.push(Object.assign(v, { path: [...path] }));
136
+ if (c.bail) break;
71
137
  }
72
138
  }
73
139
  return flatten(violations);
74
140
  };
75
- const validate = Object.assign(_validate, {
76
- sync: _sync
77
- });
78
- function arraify(value) {
79
- return Array.isArray(value) ? [...value] : [value];
141
+ function toResult(value, violations) {
142
+ return violations.length === 0 ? [true, value, []] : [false, value, violations];
80
143
  }
81
144
  function flatten(recursive) {
82
145
  const flattened = [];
@@ -95,25 +158,73 @@ async function settle(value, path, validations) {
95
158
  violations.push({
96
159
  value,
97
160
  path,
98
- violates: "@modulify/validator",
99
- reason: "reject",
100
- meta: result.reason
161
+ violates: { kind: "runtime", name: "validate", code: "runtime.rejection", args: [result.reason] }
101
162
  });
102
163
  }
103
164
  });
104
165
  return violations;
105
166
  }
106
- exports.Assert = assertions.Assert;
107
- exports.HasLength = assertions.HasLength;
108
- exports.IsBoolean = assertions.IsBoolean;
109
- exports.IsDate = assertions.IsDate;
110
- exports.IsDefined = assertions.IsDefined;
111
- exports.IsEmail = assertions.IsEmail;
112
- exports.IsNull = assertions.IsNull;
113
- exports.IsNumber = assertions.IsNumber;
114
- exports.IsString = assertions.IsString;
115
- exports.IsSymbol = assertions.IsSymbol;
116
- exports.OneOf = assertions.OneOf;
117
- exports.Each = runners.Each;
118
- exports.HasProperties = runners.HasProperties;
167
+ const matches = {
168
+ sync(value, constraints) {
169
+ return collectViolationsSync(value, constraints).length === 0;
170
+ }
171
+ };
172
+ const validate = Object.assign(
173
+ async (value, constraints) => {
174
+ const violations = await collectViolations(value, constraints);
175
+ return toResult(
176
+ value,
177
+ violations
178
+ );
179
+ },
180
+ {
181
+ sync(value, constraints) {
182
+ const violations = collectViolationsSync(value, constraints);
183
+ return toResult(
184
+ value,
185
+ violations
186
+ );
187
+ }
188
+ }
189
+ );
190
+ exports.endsWith = assertions.endsWith;
191
+ exports.hasLength = assertions.hasLength;
192
+ exports.hasPattern = assertions.hasPattern;
193
+ exports.hasSize = assertions.hasSize;
194
+ exports.hasValue = assertions.hasValue;
195
+ exports.isBigInt = assertions.isBigInt;
196
+ exports.isBlob = assertions.isBlob;
197
+ exports.isBoolean = assertions.isBoolean;
198
+ exports.isDate = assertions.isDate;
199
+ exports.isDefined = assertions.isDefined;
200
+ exports.isEmail = assertions.isEmail;
201
+ exports.isFile = assertions.isFile;
202
+ exports.isFunction = assertions.isFunction;
203
+ exports.isMap = assertions.isMap;
204
+ exports.isNaN = assertions.isNaN;
205
+ exports.isNull = assertions.isNull;
206
+ exports.isNumber = assertions.isNumber;
207
+ exports.isSet = assertions.isSet;
208
+ exports.isString = assertions.isString;
209
+ exports.isSymbol = assertions.isSymbol;
210
+ exports.multipleOf = assertions.multipleOf;
211
+ exports.oneOf = assertions.oneOf;
212
+ exports.startsWith = assertions.startsWith;
213
+ exports.discriminatedUnion = combinators.discriminatedUnion;
214
+ exports.each = combinators.each;
215
+ exports.exact = combinators.exact;
216
+ exports.nullable = combinators.nullable;
217
+ exports.nullish = combinators.nullish;
218
+ exports.optional = combinators.optional;
219
+ exports.record = combinators.record;
220
+ exports.shape = combinators.shape;
221
+ exports.tuple = combinators.tuple;
222
+ exports.union = combinators.union;
223
+ exports.custom = metadata.custom;
224
+ exports.describe = metadata.describe;
225
+ exports.meta = metadata.meta;
226
+ exports.assert = assert.assert;
227
+ exports.ViolationCollection = ViolationCollection;
228
+ exports.collection = collection;
229
+ exports.matches = matches;
119
230
  exports.validate = validate;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,12 @@
1
- import { Constraint, MaybeMany, Violation } from '../types';
1
+ import { Constraint, InferConstraints, InferMaybeManyViolations, MaybeMany, ValidationTuple } from '../types';
2
2
  export * from './assertions';
3
- export * from './runners';
4
- export declare const validate: (<T>(value: T, constraints: MaybeMany<Constraint>, path?: PropertyKey[]) => Promise<Violation[]>) & {
5
- sync: <T>(value: T, constraints: MaybeMany<Constraint>, path?: PropertyKey[]) => Violation[];
3
+ export * from './combinators';
4
+ export { collection, ViolationCollection, } from './violations';
5
+ export { custom, describe, meta, } from './metadata';
6
+ export type { AllOfConstraintDescriptor, AssertionDescriptor, AssertionDescriptorConstraint, Constraint, ConstraintDescriptor, ConstraintDescriptorBase, ConstraintMetadata, CustomConstraintDescriptor, DescribeAssertionConstraint, DescribeAssertionConstraintTuple, DescribeConstraint, DescribeConstraintTuple, DescribeMaybeMany, DescribeObjectDescriptor, DescribedValidator, DiscriminatedUnionValidator, EachValidator, FieldsMatchObjectShapeRuleDescriptor, GenericObjectShapeRuleDescriptor, InferConstraint, InferConstraints, InferConstraintViolations, InferMaybeManyViolations, DiscriminatedUnionConstraintDescriptor, EachConstraintDescriptor, NullableValidator, NullishValidator, KnownViolationCode, KnownViolationSubject, ObjectShapeFieldSelector, ObjectShapeRefinement, ObjectShapeRefinementIssue, ObjectShapeRuleDescriptor, ObjectShapeRuleDescriptorBase, OptionalValidator, RecordValidator, RecordConstraintDescriptor, ShapeConstraintDescriptor, TupleValidator, TupleConstraintDescriptor, UnionValidator, ValidationFailure, ValidationSuccess, ViolationArgs, ViolationCode, ViolationCodeEntry, ViolationCodeRegistry, ViolationEntry, ViolationKind, ViolationKindOf, ViolationNameOf, ViolationSubject, ViolationTreeNode, UnionConstraintDescriptor, ValidationTuple, ValidationResult, Validator, ValidatorDescriptor, Violation, WrapperConstraintDescriptor, } from '../types';
7
+ export declare const matches: {
8
+ sync<const C extends MaybeMany<Constraint>>(value: unknown, constraints: C): value is InferConstraints<C>;
9
+ };
10
+ export declare const validate: (<const C extends MaybeMany<Constraint>>(value: unknown, constraints: C) => Promise<ValidationTuple<InferConstraints<C>, InferMaybeManyViolations<C>>>) & {
11
+ sync<const C extends MaybeMany<Constraint>>(value: unknown, constraints: C): ValidationTuple<InferConstraints<C>, InferMaybeManyViolations<C>>;
6
12
  };
package/dist/index.mjs CHANGED
@@ -1,80 +1,144 @@
1
- import { Assert, HasLength, IsBoolean, IsDate, IsDefined, IsEmail, IsNull, IsNumber, IsString, IsSymbol, OneOf } from "./assertions.mjs";
2
- import { Each, HasProperties } from "./runners.mjs";
3
- const check = (assert, value, path = []) => {
4
- if (assert(value)) {
5
- for (const a of assert.also) {
6
- const violation = check(a, value, path);
7
- if (violation) {
8
- return {
9
- ...violation,
10
- violates: assert.fqn
11
- };
12
- }
13
- }
14
- return null;
1
+ import { endsWith, hasLength, hasPattern, hasSize, hasValue, isBigInt, isBlob, isBoolean, isDate, isDefined, isEmail, isFile, isFunction, isMap, isNaN, isNull, isNumber, isSet, isString, isSymbol, multipleOf, oneOf, startsWith } from "./assertions.mjs";
2
+ import { discriminatedUnion, each, exact, nullable, nullish, optional, record, shape, tuple, union } from "./combinators.mjs";
3
+ import { a as arrayify, i as isValidator } from "./metadata.es.js";
4
+ import { c, b, m } from "./metadata.es.js";
5
+ import { assert } from "./assert.mjs";
6
+ const ROOT_PATH = Object.freeze([]);
7
+ const normalizePath = (path) => path ?? ROOT_PATH;
8
+ const isSamePath = (left, right = ROOT_PATH) => {
9
+ const normalizedLeft = normalizePath(left);
10
+ if (normalizedLeft.length !== right.length) {
11
+ return false;
15
12
  }
16
- return {
17
- value,
18
- path,
19
- violates: assert.fqn,
20
- ..."reason" in assert ? { reason: assert.reason } : {},
21
- ..."meta" in assert ? { meta: assert.meta } : {}
22
- };
13
+ return normalizedLeft.every((part, index) => Object.is(part, right[index]));
23
14
  };
24
- const isBatch = (c) => {
25
- return "run" in c;
15
+ const isPathPrefix = (path, prefix) => {
16
+ if (prefix.length > path.length) {
17
+ return false;
18
+ }
19
+ return prefix.every((part, index) => Object.is(part, path[index]));
26
20
  };
27
- const _validate = async (value, constraints, path = []) => {
21
+ const createTreeState = (path) => ({
22
+ path: Object.freeze([...path]),
23
+ self: [],
24
+ subtree: [],
25
+ children: /* @__PURE__ */ new Map()
26
+ });
27
+ class TreeNode {
28
+ constructor(state) {
29
+ this.path = state.path;
30
+ this.self = new ViolationCollection(state.self);
31
+ this.subtree = new ViolationCollection(state.subtree);
32
+ this.children = new Map(
33
+ [...state.children.entries()].map(([key, child]) => [key, new TreeNode(child)])
34
+ );
35
+ }
36
+ at(path) {
37
+ if (!isPathPrefix(path, this.path)) {
38
+ return void 0;
39
+ }
40
+ if (path.length === this.path.length) {
41
+ return this;
42
+ }
43
+ const child = this.children.get(path[this.path.length]);
44
+ return child?.at(path);
45
+ }
46
+ }
47
+ const buildTree = (violations) => {
48
+ const root = createTreeState(ROOT_PATH);
49
+ violations.forEach((violation) => {
50
+ const path = normalizePath(violation.path);
51
+ root.subtree.push(violation);
52
+ if (path.length === 0) {
53
+ root.self.push(violation);
54
+ return;
55
+ }
56
+ let current = root;
57
+ const currentPath = [];
58
+ path.forEach((segment, index) => {
59
+ currentPath.push(segment);
60
+ let child = current.children.get(segment);
61
+ if (!child) {
62
+ child = createTreeState(currentPath);
63
+ current.children.set(segment, child);
64
+ }
65
+ child.subtree.push(violation);
66
+ if (index === path.length - 1) {
67
+ child.self.push(violation);
68
+ }
69
+ current = child;
70
+ });
71
+ });
72
+ return new TreeNode(root);
73
+ };
74
+ class ViolationCollection {
75
+ constructor(violations) {
76
+ this.violations = [...violations];
77
+ this.size = this.violations.length;
78
+ }
79
+ [Symbol.iterator]() {
80
+ return this.violations[Symbol.iterator]();
81
+ }
82
+ forEach(callback) {
83
+ this.violations.forEach((violation, index) => callback(violation, index, this));
84
+ }
85
+ map(callback) {
86
+ return this.violations.map((violation, index) => callback(violation, index, this));
87
+ }
88
+ at(path) {
89
+ return new ViolationCollection(this.violations.filter((violation) => isSamePath(violation.path, path)));
90
+ }
91
+ tree() {
92
+ return buildTree(this.violations);
93
+ }
94
+ }
95
+ const collection = (violations) => new ViolationCollection(violations);
96
+ const collectViolations = async (value, constraints, path = []) => {
28
97
  const validations = [];
29
- for (const c of arraify(constraints)) {
30
- if (isBatch(c)) {
31
- validations.push(...c.run(_validate, value, path).map((v2) => v2 instanceof Promise ? v2 : Promise.resolve(v2)));
98
+ for (const c2 of arrayify(constraints)) {
99
+ if (isValidator(c2)) {
100
+ validations.push(...c2.run(collectViolations, value, path).map((v2) => v2 instanceof Promise ? v2 : Promise.resolve(v2)));
32
101
  continue;
33
102
  }
34
- const v = "That" in c ? check(c, value, [...path]) : c(value, [...path]);
103
+ const v = c2(value);
35
104
  if (v instanceof Promise) {
36
- if (c.bail) {
105
+ if (c2.bail) {
37
106
  const awaited = await v;
38
107
  if (awaited) {
39
- validations.push(Promise.resolve([awaited]));
108
+ validations.push(Promise.resolve([Object.assign(awaited, { path: [...path] })]));
40
109
  break;
41
110
  }
42
111
  } else {
43
- validations.push(v.then((v2) => v2 ? [v2] : []));
112
+ validations.push(v.then((v2) => v2 ? [Object.assign(v2, { path: [...path] })] : []));
44
113
  }
45
114
  } else if (v) {
46
- validations.push(Promise.resolve([v]));
47
- if (c.bail) {
115
+ validations.push(Promise.resolve([Object.assign(v, { path: [...path] })]));
116
+ if (c2.bail) {
48
117
  break;
49
118
  }
50
119
  }
51
120
  }
52
121
  return settle(value, path, validations);
53
122
  };
54
- const _sync = (value, constraints, path = []) => {
123
+ const collectViolationsSync = (value, constraints, path = []) => {
55
124
  const violations = [];
56
- for (const c of arraify(constraints)) {
57
- if (isBatch(c)) {
58
- violations.push(...c.run(_sync, value, path));
125
+ for (const c2 of arrayify(constraints)) {
126
+ if (isValidator(c2)) {
127
+ violations.push(...c2.run(collectViolationsSync, value, path));
59
128
  continue;
60
129
  }
61
- const v = "That" in c ? check(c, value, [...path]) : c(value, [...path]);
130
+ const v = c2(value);
62
131
  if (v instanceof Promise) {
63
- throw new Error("Found asynchronous constraint validator " + String(c.fqn));
132
+ throw new Error("Found asynchronous validator " + String(c2.name));
64
133
  } else if (v) {
65
- violations.push(v);
66
- if (c.bail) {
67
- break;
68
- }
134
+ violations.push(Object.assign(v, { path: [...path] }));
135
+ if (c2.bail) break;
69
136
  }
70
137
  }
71
138
  return flatten(violations);
72
139
  };
73
- const validate = Object.assign(_validate, {
74
- sync: _sync
75
- });
76
- function arraify(value) {
77
- return Array.isArray(value) ? [...value] : [value];
140
+ function toResult(value, violations) {
141
+ return violations.length === 0 ? [true, value, []] : [false, value, violations];
78
142
  }
79
143
  function flatten(recursive) {
80
144
  const flattened = [];
@@ -93,27 +157,75 @@ async function settle(value, path, validations) {
93
157
  violations.push({
94
158
  value,
95
159
  path,
96
- violates: "@modulify/validator",
97
- reason: "reject",
98
- meta: result.reason
160
+ violates: { kind: "runtime", name: "validate", code: "runtime.rejection", args: [result.reason] }
99
161
  });
100
162
  }
101
163
  });
102
164
  return violations;
103
165
  }
166
+ const matches = {
167
+ sync(value, constraints) {
168
+ return collectViolationsSync(value, constraints).length === 0;
169
+ }
170
+ };
171
+ const validate = Object.assign(
172
+ async (value, constraints) => {
173
+ const violations = await collectViolations(value, constraints);
174
+ return toResult(
175
+ value,
176
+ violations
177
+ );
178
+ },
179
+ {
180
+ sync(value, constraints) {
181
+ const violations = collectViolationsSync(value, constraints);
182
+ return toResult(
183
+ value,
184
+ violations
185
+ );
186
+ }
187
+ }
188
+ );
104
189
  export {
105
- Assert,
106
- Each,
107
- HasLength,
108
- HasProperties,
109
- IsBoolean,
110
- IsDate,
111
- IsDefined,
112
- IsEmail,
113
- IsNull,
114
- IsNumber,
115
- IsString,
116
- IsSymbol,
117
- OneOf,
190
+ ViolationCollection,
191
+ assert,
192
+ collection,
193
+ c as custom,
194
+ b as describe,
195
+ discriminatedUnion,
196
+ each,
197
+ endsWith,
198
+ exact,
199
+ hasLength,
200
+ hasPattern,
201
+ hasSize,
202
+ hasValue,
203
+ isBigInt,
204
+ isBlob,
205
+ isBoolean,
206
+ isDate,
207
+ isDefined,
208
+ isEmail,
209
+ isFile,
210
+ isFunction,
211
+ isMap,
212
+ isNaN,
213
+ isNull,
214
+ isNumber,
215
+ isSet,
216
+ isString,
217
+ isSymbol,
218
+ matches,
219
+ m as meta,
220
+ multipleOf,
221
+ nullable,
222
+ nullish,
223
+ oneOf,
224
+ optional,
225
+ record,
226
+ shape,
227
+ startsWith,
228
+ tuple,
229
+ union,
118
230
  validate
119
231
  };