@modulify/validator 0.2.1 → 0.3.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 (88) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +12 -2
  3. package/dist/assert.cjs +99 -63
  4. package/dist/assert.d.cts +37 -0
  5. package/dist/assert.d.mts +37 -0
  6. package/dist/assert.d.ts +24 -3
  7. package/dist/assert.mjs +94 -64
  8. package/dist/assertions.cjs +283 -178
  9. package/dist/assertions.d.cts +56 -0
  10. package/dist/assertions.d.mts +56 -0
  11. package/dist/assertions.d.ts +43 -45
  12. package/dist/assertions.mjs +274 -201
  13. package/dist/checkers.cjs +23 -0
  14. package/dist/checkers.d.cts +8 -0
  15. package/dist/checkers.d.mts +8 -0
  16. package/dist/checkers.d.ts +1 -1
  17. package/dist/checkers.mjs +16 -0
  18. package/dist/combinators.cjs +305 -304
  19. package/dist/combinators.d.cts +16 -0
  20. package/dist/combinators.d.mts +16 -0
  21. package/dist/combinators.d.ts +15 -16
  22. package/dist/combinators.mjs +305 -314
  23. package/dist/constraints.cjs +23 -0
  24. package/dist/constraints.d.cts +4 -0
  25. package/dist/constraints.d.mts +4 -0
  26. package/dist/constraints.d.ts +2 -2
  27. package/dist/constraints.mjs +21 -0
  28. package/dist/extractors.cjs +6 -0
  29. package/dist/extractors.d.cts +2 -0
  30. package/dist/extractors.d.mts +2 -0
  31. package/dist/extractors.mjs +5 -0
  32. package/dist/index.cjs +140 -219
  33. package/dist/index.d.cts +12 -0
  34. package/dist/index.d.mts +12 -0
  35. package/dist/index.d.ts +9 -9
  36. package/dist/index.mjs +93 -222
  37. package/dist/json-schema.cjs +364 -489
  38. package/dist/json-schema.d.cts +14 -0
  39. package/dist/json-schema.d.mts +14 -0
  40. package/dist/json-schema.d.ts +3 -3
  41. package/dist/json-schema.mjs +365 -492
  42. package/dist/metadata.cjs +98 -7
  43. package/dist/metadata.d.cts +8 -0
  44. package/dist/metadata.d.mts +8 -0
  45. package/dist/metadata.d.ts +2 -2
  46. package/dist/metadata.mjs +93 -7
  47. package/dist/predicates.cjs +98 -41
  48. package/dist/predicates.d.cts +77 -0
  49. package/dist/predicates.d.mts +77 -0
  50. package/dist/predicates.d.ts +25 -4
  51. package/dist/predicates.mjs +92 -66
  52. package/dist/types/index.d.cts +984 -0
  53. package/dist/types/index.d.mts +984 -0
  54. package/dist/types/index.d.ts +984 -0
  55. package/dist/types/json-schema.d.cts +75 -0
  56. package/dist/types/json-schema.d.mts +75 -0
  57. package/dist/types/json-schema.d.ts +75 -0
  58. package/dist/violations.cjs +81 -0
  59. package/dist/violations.d.cts +29 -0
  60. package/dist/violations.d.mts +29 -0
  61. package/dist/violations.d.ts +1 -1
  62. package/dist/violations.mjs +80 -0
  63. package/docs/RELEASING.md +66 -0
  64. package/docs/en/00-index.md +2 -0
  65. package/docs/en/01-shape-api.md +35 -10
  66. package/docs/en/02-metadata-and-introspection.md +2 -1
  67. package/docs/en/03-violations.md +1 -1
  68. package/docs/en/04-json-schema-export.md +5 -0
  69. package/docs/en/05-public-api.md +35 -3
  70. package/docs/en/06-common-recipes.md +2 -1
  71. package/docs/en/07-ai-reference.md +5 -2
  72. package/docs/en/08-violation-code-types.md +28 -2
  73. package/docs/en/09-migration.md +75 -0
  74. package/docs/ru/00-index.md +2 -0
  75. package/docs/ru/01-shape-api.md +35 -10
  76. package/docs/ru/02-metadata-and-introspection.md +2 -1
  77. package/docs/ru/03-violations.md +1 -1
  78. package/docs/ru/04-json-schema-export.md +5 -0
  79. package/docs/ru/05-public-api.md +35 -3
  80. package/docs/ru/06-common-recipes.md +2 -1
  81. package/docs/ru/07-ai-reference.md +5 -2
  82. package/docs/ru/08-violation-code-types.md +28 -2
  83. package/docs/ru/09-migration.md +76 -0
  84. package/docs/ru/README.md +10 -2
  85. package/package.json +63 -37
  86. package/types/index.d.ts +275 -115
  87. package/dist/metadata.cjs.js +0 -130
  88. package/dist/metadata.es.js +0 -131
package/CHANGELOG.md CHANGED
@@ -1,6 +1,33 @@
1
1
  # Changelog
2
2
 
3
- All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
3
+ ## 0.3.1
4
+
5
+ ## 0.3.0
6
+
7
+ ### ⚠ BREAKING CHANGE* **types:** Public type names were simplified
8
+ * **types:** Exported public type names were renamed without compatibility aliases.
9
+ * Object shape refinements were made async-first
10
+ * shape.refine(...) was changed to the async-first object-level API. Use shape.refine.sync(...) for explicitly sync-safe object rules.
11
+ * ObjectShapeRefinement now describes the async-first refinement contract. Use ObjectShapeRefinementSync for the explicit sync-only type name.
12
+ * validate.sync(...), matches.sync(...), and shape.check(...) now throw when they encounter async object-level shape refinements.
13
+
14
+
15
+ ### Features
16
+
17
+ * Object shape refinements were made async-first ([8877b93](https://github.com/modulify/validator/commit/8877b93fa4a8b7c29c918d5d9df08e90ae816379))
18
+ * Built-in value guards were expanded ([1846c17](https://github.com/modulify/validator/commit/1846c176188182b76074b46a60c12d3a2af790a0))
19
+
20
+ ### Bug Fixes
21
+
22
+ * **predicates:** Shape field validation and inference were corrected ([b2c0e44](https://github.com/modulify/validator/commit/b2c0e441ecf923c0ed3e3a8cbe432a052fed42ce))
23
+ * **types:** Strict assertion contracts were aligned ([2bdd390](https://github.com/modulify/validator/commit/2bdd39019caff5522821ab3b07d832efdd4ca1ab))
24
+ * **build:** Packed ESM and CommonJS consumers were supported ([6fd0c3b](https://github.com/modulify/validator/commit/6fd0c3b2ad7adca314b321283245f831deb2e160))
25
+
26
+ ### Performance Improvements
27
+
28
+ * **build:** Tree-shaking hints were added ([29bbc70](https://github.com/modulify/validator/commit/29bbc7017b58ef50927ccda745a7be76a8b73ba4))
29
+
30
+ All notable changes to this project will be documented in this file. Release notes are generated by [@modulify/conventional-release](https://github.com/modulify/conventional/tree/main/packages/conventional-release) from Conventional Commits.
4
31
 
5
32
  ### [0.2.1](https://github.com/modulify/validator/compare/v0.2.0...v0.2.1) (2026-03-09)
6
33
 
@@ -73,3 +100,4 @@ All notable changes to this project will be documented in this file. See [standa
73
100
  * Added meta to OneOf violation ([8dd59fc](https://github.com/modulify/validator/commit/8dd59fc2663df1e791ad95449ba774374b6e0bf8))
74
101
  * Added possibility to override initial valitators set ([0192f44](https://github.com/modulify/validator/commit/0192f44e4e9e487cbc1230cd588ea62d926e7143))
75
102
  * Asynchronous validation ([1505f41](https://github.com/modulify/validator/commit/1505f417bd869ba762f6a91d1d30a360d2505ad4))
103
+
package/README.md CHANGED
@@ -204,7 +204,7 @@ if (ok) {
204
204
 
205
205
  ## Shape API
206
206
 
207
- `shape(...)` is the reusable object-shape API. It validates nested record-like objects and exposes small immutable helpers such as `strict()`, `pick()`, `omit()`, `partial()`, `extend()`, `merge()`, `refine()`, and `fieldsMatch(...)`.
207
+ `shape(...)` is the reusable object-shape API. It validates nested record-like objects and exposes small immutable helpers such as `strict()`, `pick()`, `omit()`, `partial()`, `extend()`, `merge()`, async-first `refine()`, explicit `refine.sync()`, and `fieldsMatch(...)`.
208
208
 
209
209
  ```typescript
210
210
  import {
@@ -270,11 +270,17 @@ A practical way to think about the library is:
270
270
 
271
271
  In the current API this usually looks like:
272
272
 
273
- - leaf checks with assertions such as `isString`, `isDefined`, `hasLength`, `oneOf`;
273
+ - guard assertions such as `isString`, `isNumber`, `isDefined`, `oneOf(...)` establish the base domain for a value;
274
+ - refinement assertions such as `hasLength(...)`, `hasPattern(...)`, `startsWith(...)`, `hasValue(...)`, `multipleOf(...)` validate properties inside that domain;
274
275
  - schema composition with combinators such as `exact`, `optional`, `nullable`, `nullish`, `shape(...)`, `each(...)`;
275
276
  - typed validation through `validate(...)` or `validate.sync(...)`;
276
277
  - narrowing of the original sync variable through `matches.sync(...)`.
277
278
 
279
+ Sequential assertion arrays are stage-aware. A tuple like `[isString, hasLength({ min: 3 })]` is valid, while incompatible combinations like `[isNumber, hasLength({ min: 3 })]` are rejected by TypeScript.
280
+ Refinement assertions are not meant to be passed to `validate(...)` or `matches.sync(...)` on their own.
281
+
282
+ `validate(...)` is the default async-first validation entrypoint. `validate.sync(...)` and `matches.sync(...)` are specialized sync APIs and will throw if they encounter async validators or async object-level `shape(...).refine(...)` rules.
283
+
278
284
  ## Violations
279
285
 
280
286
  `validate(...)` returns machine-readable `Violation[]`, and `collection(...)` can wrap that list into a small helper API for exact path lookups and tree traversal.
@@ -354,6 +360,8 @@ Two additional guides are useful when you want faster practical navigation inste
354
360
  - [Common Recipes](./docs/en/06-common-recipes.md) - task-oriented examples for payload validation, wrapper choice, reusable shapes, form error mapping, and JSON Schema export.
355
361
  - [AI Reference](./docs/en/07-ai-reference.md) - compact contract summary for agents, tooling, and quick semantic lookup.
356
362
 
363
+ - [Migration From 0.2.1](./docs/en/09-migration.md)
364
+
357
365
  ## Notes
358
366
 
359
367
  - Assertions return structured metadata instead of messages.
@@ -366,3 +374,5 @@ Two additional guides are useful when you want faster practical navigation inste
366
374
  ## Translations
367
375
 
368
376
  - [Russian](./docs/ru/README.md)
377
+
378
+ Release workflow and npm OIDC setup: [Releasing](docs/RELEASING.md).
package/dist/assert.cjs CHANGED
@@ -1,66 +1,102 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const metadata = require("./metadata.cjs.js");
4
- const assert = (predicate, meta, constraints = []) => {
5
- const assertionCode = meta.code ?? meta.name;
6
- const assertionArgs = meta.args ?? [];
7
- const violationSubject = {
8
- kind: "assertion",
9
- name: meta.name,
10
- code: assertionCode,
11
- args: assertionArgs
12
- };
13
- const assertion = ((value) => {
14
- if (!predicate(value)) {
15
- return {
16
- value,
17
- violates: violationSubject
18
- };
19
- }
20
- for (const [extract, check, code, ...args] of constraints) {
21
- if (!check(extract(value), ...args)) {
22
- const constraintSubject = {
23
- kind: "assertion",
24
- name: meta.name,
25
- code,
26
- args
27
- };
28
- return {
29
- value,
30
- violates: constraintSubject
31
- };
32
- }
33
- }
34
- return null;
35
- });
36
- Object.defineProperties(assertion, {
37
- name: {
38
- configurable: true,
39
- value: meta.name
40
- },
41
- bail: {
42
- enumerable: true,
43
- value: meta.bail
44
- },
45
- constraints: {
46
- enumerable: true,
47
- value: constraints
48
- },
49
- check: {
50
- enumerable: true,
51
- value: (value) => predicate(value) && (!constraints.length || constraints.every(([extract, check, , ...args]) => check(extract(value), ...args)))
52
- }
53
- });
54
- return metadata.attachConstraintDescriptor(assertion, () => ({
55
- kind: "assertion",
56
- name: meta.name,
57
- bail: meta.bail,
58
- code: assertionCode,
59
- args: assertionArgs,
60
- constraints: constraints.map(([, , code, ...args]) => ({
61
- code,
62
- args
63
- }))
64
- }));
2
+ const require_metadata = require("./metadata.cjs");
3
+ //#region src/assert.ts
4
+ var assertionStageSymbol = Symbol("modulify.validator.assertion.stage");
5
+ var runRefinementSymbol = Symbol("modulify.validator.assertion.runRefinement");
6
+ var checkRefinementSymbol = Symbol("modulify.validator.assertion.checkRefinement");
7
+ var createAssertion = (stage, predicate, meta, constraints = []) => {
8
+ const assertionCode = meta.code ?? meta.name;
9
+ const assertionArgs = meta.args ?? [];
10
+ const violationSubject = {
11
+ kind: "assertion",
12
+ name: meta.name,
13
+ code: assertionCode,
14
+ args: assertionArgs
15
+ };
16
+ const runConstraints = (value) => {
17
+ for (const [extract, check, code, ...args] of constraints) if (!check(extract(value), ...args)) return {
18
+ value,
19
+ violates: {
20
+ kind: "assertion",
21
+ name: meta.name,
22
+ code,
23
+ args
24
+ }
25
+ };
26
+ return null;
27
+ };
28
+ const checkConstraints = (value) => !constraints.length || constraints.every(([extract, check, , ...args]) => check(extract(value), ...args));
29
+ const assertion = ((value) => {
30
+ if (!predicate(value)) return {
31
+ value,
32
+ violates: violationSubject
33
+ };
34
+ return runConstraints(value);
35
+ });
36
+ Object.defineProperties(assertion, {
37
+ name: {
38
+ configurable: true,
39
+ value: meta.name
40
+ },
41
+ bail: {
42
+ enumerable: true,
43
+ value: meta.bail
44
+ },
45
+ constraints: {
46
+ enumerable: true,
47
+ value: constraints
48
+ },
49
+ check: {
50
+ enumerable: true,
51
+ value: (value) => predicate(value) && checkConstraints(value)
52
+ },
53
+ [assertionStageSymbol]: {
54
+ enumerable: false,
55
+ value: stage
56
+ },
57
+ [runRefinementSymbol]: {
58
+ enumerable: false,
59
+ value: (value) => runConstraints(value)
60
+ },
61
+ [checkRefinementSymbol]: {
62
+ enumerable: false,
63
+ value: (value) => checkConstraints(value)
64
+ }
65
+ });
66
+ return /* @__PURE__ */ require_metadata.attachConstraintDescriptor(assertion, () => ({
67
+ kind: "assertion",
68
+ name: meta.name,
69
+ bail: meta.bail,
70
+ code: assertionCode,
71
+ args: assertionArgs,
72
+ constraints: constraints.map(([, , code, ...args]) => ({
73
+ code,
74
+ args
75
+ }))
76
+ }));
65
77
  };
78
+ var assert = (predicate, meta, constraints = []) => {
79
+ return createAssertion("guard", predicate, meta, constraints);
80
+ };
81
+ var isRefinementAssertion = (constraint) => {
82
+ return typeof constraint === "function" && constraint[assertionStageSymbol] === "refinement";
83
+ };
84
+ var runRefinementAssertion = (constraint, value) => {
85
+ const runRefinement = constraint[runRefinementSymbol];
86
+ return runRefinement ? runRefinement(value) : constraint(value);
87
+ };
88
+ var checkRefinementAssertion = (constraint, value) => {
89
+ const checkRefinement = constraint[checkRefinementSymbol];
90
+ return checkRefinement ? checkRefinement(value) : constraint.check(value);
91
+ };
92
+ var createRefinement = (meta, constraints = []) => {
93
+ return createAssertion("refinement", ((value) => true), meta, constraints);
94
+ };
95
+ var refine = createRefinement;
96
+ //#endregion
66
97
  exports.assert = assert;
98
+ exports.checkRefinementAssertion = checkRefinementAssertion;
99
+ exports.createRefinement = createRefinement;
100
+ exports.isRefinementAssertion = isRefinementAssertion;
101
+ exports.refine = refine;
102
+ exports.runRefinementAssertion = runRefinementAssertion;
@@ -0,0 +1,37 @@
1
+ import { Assertion, Constraint, AssertionConstraint, Guard, Predicate, Refinement } from './types/index.cjs';
2
+ type AssertMeta = {
3
+ name: string;
4
+ bail: boolean;
5
+ code?: string;
6
+ args?: readonly unknown[];
7
+ };
8
+ type ResolveAssertionCode<Name extends string, Code extends string | undefined> = Code extends string ? Code : Name;
9
+ type ResolveAssertionArgs<Args extends readonly unknown[] | undefined> = Args extends readonly unknown[] ? Args : [];
10
+ type ConstraintInputFunction<C extends AssertionConstraint> = C extends unknown ? (value: Parameters<C[0]>[0]) => void : never;
11
+ type ConstraintInput<C extends readonly AssertionConstraint[]> = C extends readonly [] ? unknown : ConstraintInputFunction<C[number]> extends (value: infer Input) => void ? Input : never;
12
+ type ConstraintArgs<C extends AssertionConstraint> = C extends readonly [unknown, unknown, string, ...infer Args] ? Args : never;
13
+ type CompatibleAssertionConstraints<Input, C extends readonly AssertionConstraint[]> = {
14
+ [K in keyof C]: AssertionConstraint<Input, ReturnType<C[K][0]>, ConstraintArgs<C[K]>, C[K][2]>;
15
+ };
16
+ export declare const assert: <T, const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint<T, any, any[], string>[] = []>(predicate: Predicate<T>, meta: AssertMeta & {
17
+ name: Name;
18
+ bail: Bail;
19
+ code?: Code;
20
+ args?: Args;
21
+ }, constraints?: C & CompatibleAssertionConstraints<T, C>) => Guard<T, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
22
+ export declare const isRefinementAssertion: (constraint: Constraint) => constraint is Assertion;
23
+ export declare const runRefinementAssertion: (constraint: Assertion, value: unknown) => ReturnType<Assertion>;
24
+ export declare const checkRefinementAssertion: (constraint: Assertion, value: unknown) => boolean;
25
+ export declare const createRefinement: <const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint[] = []>(meta: AssertMeta & {
26
+ name: Name;
27
+ bail: Bail;
28
+ code?: Code;
29
+ args?: Args;
30
+ }, constraints?: C) => Refinement<ConstraintInput<C>, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
31
+ export declare const refine: <const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint[] = []>(meta: AssertMeta & {
32
+ name: Name;
33
+ bail: Bail;
34
+ code?: Code;
35
+ args?: Args;
36
+ }, constraints?: C & CompatibleAssertionConstraints<ConstraintInput<C>, C>) => Refinement<ConstraintInput<C>, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
37
+ export {};
@@ -0,0 +1,37 @@
1
+ import { Assertion, Constraint, AssertionConstraint, Guard, Predicate, Refinement } from './types/index.mjs';
2
+ type AssertMeta = {
3
+ name: string;
4
+ bail: boolean;
5
+ code?: string;
6
+ args?: readonly unknown[];
7
+ };
8
+ type ResolveAssertionCode<Name extends string, Code extends string | undefined> = Code extends string ? Code : Name;
9
+ type ResolveAssertionArgs<Args extends readonly unknown[] | undefined> = Args extends readonly unknown[] ? Args : [];
10
+ type ConstraintInputFunction<C extends AssertionConstraint> = C extends unknown ? (value: Parameters<C[0]>[0]) => void : never;
11
+ type ConstraintInput<C extends readonly AssertionConstraint[]> = C extends readonly [] ? unknown : ConstraintInputFunction<C[number]> extends (value: infer Input) => void ? Input : never;
12
+ type ConstraintArgs<C extends AssertionConstraint> = C extends readonly [unknown, unknown, string, ...infer Args] ? Args : never;
13
+ type CompatibleAssertionConstraints<Input, C extends readonly AssertionConstraint[]> = {
14
+ [K in keyof C]: AssertionConstraint<Input, ReturnType<C[K][0]>, ConstraintArgs<C[K]>, C[K][2]>;
15
+ };
16
+ export declare const assert: <T, const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint<T, any, any[], string>[] = []>(predicate: Predicate<T>, meta: AssertMeta & {
17
+ name: Name;
18
+ bail: Bail;
19
+ code?: Code;
20
+ args?: Args;
21
+ }, constraints?: C & CompatibleAssertionConstraints<T, C>) => Guard<T, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
22
+ export declare const isRefinementAssertion: (constraint: Constraint) => constraint is Assertion;
23
+ export declare const runRefinementAssertion: (constraint: Assertion, value: unknown) => ReturnType<Assertion>;
24
+ export declare const checkRefinementAssertion: (constraint: Assertion, value: unknown) => boolean;
25
+ export declare const createRefinement: <const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint[] = []>(meta: AssertMeta & {
26
+ name: Name;
27
+ bail: Bail;
28
+ code?: Code;
29
+ args?: Args;
30
+ }, constraints?: C) => Refinement<ConstraintInput<C>, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
31
+ export declare const refine: <const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint[] = []>(meta: AssertMeta & {
32
+ name: Name;
33
+ bail: Bail;
34
+ code?: Code;
35
+ args?: Args;
36
+ }, constraints?: C & CompatibleAssertionConstraints<ConstraintInput<C>, C>) => Refinement<ConstraintInput<C>, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
37
+ export {};
package/dist/assert.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Assertion, AssertionConstraint, Predicate } from '../types';
1
+ import { Assertion, Constraint, AssertionConstraint, Guard, Predicate, Refinement } from './types/index.js';
2
2
  type AssertMeta = {
3
3
  name: string;
4
4
  bail: boolean;
@@ -7,10 +7,31 @@ type AssertMeta = {
7
7
  };
8
8
  type ResolveAssertionCode<Name extends string, Code extends string | undefined> = Code extends string ? Code : Name;
9
9
  type ResolveAssertionArgs<Args extends readonly unknown[] | undefined> = Args extends readonly unknown[] ? Args : [];
10
- export declare const assert: <T, const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint[] = []>(predicate: Predicate<T>, meta: AssertMeta & {
10
+ type ConstraintInputFunction<C extends AssertionConstraint> = C extends unknown ? (value: Parameters<C[0]>[0]) => void : never;
11
+ type ConstraintInput<C extends readonly AssertionConstraint[]> = C extends readonly [] ? unknown : ConstraintInputFunction<C[number]> extends (value: infer Input) => void ? Input : never;
12
+ type ConstraintArgs<C extends AssertionConstraint> = C extends readonly [unknown, unknown, string, ...infer Args] ? Args : never;
13
+ type CompatibleAssertionConstraints<Input, C extends readonly AssertionConstraint[]> = {
14
+ [K in keyof C]: AssertionConstraint<Input, ReturnType<C[K][0]>, ConstraintArgs<C[K]>, C[K][2]>;
15
+ };
16
+ export declare const assert: <T, const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint<T, any, any[], string>[] = []>(predicate: Predicate<T>, meta: AssertMeta & {
17
+ name: Name;
18
+ bail: Bail;
19
+ code?: Code;
20
+ args?: Args;
21
+ }, constraints?: C & CompatibleAssertionConstraints<T, C>) => Guard<T, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
22
+ export declare const isRefinementAssertion: (constraint: Constraint) => constraint is Assertion;
23
+ export declare const runRefinementAssertion: (constraint: Assertion, value: unknown) => ReturnType<Assertion>;
24
+ export declare const checkRefinementAssertion: (constraint: Assertion, value: unknown) => boolean;
25
+ export declare const createRefinement: <const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint[] = []>(meta: AssertMeta & {
26
+ name: Name;
27
+ bail: Bail;
28
+ code?: Code;
29
+ args?: Args;
30
+ }, constraints?: C) => Refinement<ConstraintInput<C>, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
31
+ export declare const refine: <const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, const C extends readonly AssertionConstraint[] = []>(meta: AssertMeta & {
11
32
  name: Name;
12
33
  bail: Bail;
13
34
  code?: Code;
14
35
  args?: Args;
15
- }, constraints?: C) => Assertion<T, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
36
+ }, constraints?: C & CompatibleAssertionConstraints<ConstraintInput<C>, C>) => Refinement<ConstraintInput<C>, C, ResolveAssertionCode<Name, Code>, ResolveAssertionArgs<Args>, Name>;
16
37
  export {};
package/dist/assert.mjs CHANGED
@@ -1,66 +1,96 @@
1
- import { e as attachConstraintDescriptor } from "./metadata.es.js";
2
- const assert = (predicate, meta, constraints = []) => {
3
- const assertionCode = meta.code ?? meta.name;
4
- const assertionArgs = meta.args ?? [];
5
- const violationSubject = {
6
- kind: "assertion",
7
- name: meta.name,
8
- code: assertionCode,
9
- args: assertionArgs
10
- };
11
- const assertion = ((value) => {
12
- if (!predicate(value)) {
13
- return {
14
- value,
15
- violates: violationSubject
16
- };
17
- }
18
- for (const [extract, check, code, ...args] of constraints) {
19
- if (!check(extract(value), ...args)) {
20
- const constraintSubject = {
21
- kind: "assertion",
22
- name: meta.name,
23
- code,
24
- args
25
- };
26
- return {
27
- value,
28
- violates: constraintSubject
29
- };
30
- }
31
- }
32
- return null;
33
- });
34
- Object.defineProperties(assertion, {
35
- name: {
36
- configurable: true,
37
- value: meta.name
38
- },
39
- bail: {
40
- enumerable: true,
41
- value: meta.bail
42
- },
43
- constraints: {
44
- enumerable: true,
45
- value: constraints
46
- },
47
- check: {
48
- enumerable: true,
49
- value: (value) => predicate(value) && (!constraints.length || constraints.every(([extract, check, , ...args]) => check(extract(value), ...args)))
50
- }
51
- });
52
- return attachConstraintDescriptor(assertion, () => ({
53
- kind: "assertion",
54
- name: meta.name,
55
- bail: meta.bail,
56
- code: assertionCode,
57
- args: assertionArgs,
58
- constraints: constraints.map(([, , code, ...args]) => ({
59
- code,
60
- args
61
- }))
62
- }));
1
+ import { attachConstraintDescriptor } from "./metadata.mjs";
2
+ //#region src/assert.ts
3
+ var assertionStageSymbol = Symbol("modulify.validator.assertion.stage");
4
+ var runRefinementSymbol = Symbol("modulify.validator.assertion.runRefinement");
5
+ var checkRefinementSymbol = Symbol("modulify.validator.assertion.checkRefinement");
6
+ var createAssertion = (stage, predicate, meta, constraints = []) => {
7
+ const assertionCode = meta.code ?? meta.name;
8
+ const assertionArgs = meta.args ?? [];
9
+ const violationSubject = {
10
+ kind: "assertion",
11
+ name: meta.name,
12
+ code: assertionCode,
13
+ args: assertionArgs
14
+ };
15
+ const runConstraints = (value) => {
16
+ for (const [extract, check, code, ...args] of constraints) if (!check(extract(value), ...args)) return {
17
+ value,
18
+ violates: {
19
+ kind: "assertion",
20
+ name: meta.name,
21
+ code,
22
+ args
23
+ }
24
+ };
25
+ return null;
26
+ };
27
+ const checkConstraints = (value) => !constraints.length || constraints.every(([extract, check, , ...args]) => check(extract(value), ...args));
28
+ const assertion = ((value) => {
29
+ if (!predicate(value)) return {
30
+ value,
31
+ violates: violationSubject
32
+ };
33
+ return runConstraints(value);
34
+ });
35
+ Object.defineProperties(assertion, {
36
+ name: {
37
+ configurable: true,
38
+ value: meta.name
39
+ },
40
+ bail: {
41
+ enumerable: true,
42
+ value: meta.bail
43
+ },
44
+ constraints: {
45
+ enumerable: true,
46
+ value: constraints
47
+ },
48
+ check: {
49
+ enumerable: true,
50
+ value: (value) => predicate(value) && checkConstraints(value)
51
+ },
52
+ [assertionStageSymbol]: {
53
+ enumerable: false,
54
+ value: stage
55
+ },
56
+ [runRefinementSymbol]: {
57
+ enumerable: false,
58
+ value: (value) => runConstraints(value)
59
+ },
60
+ [checkRefinementSymbol]: {
61
+ enumerable: false,
62
+ value: (value) => checkConstraints(value)
63
+ }
64
+ });
65
+ return /* @__PURE__ */ attachConstraintDescriptor(assertion, () => ({
66
+ kind: "assertion",
67
+ name: meta.name,
68
+ bail: meta.bail,
69
+ code: assertionCode,
70
+ args: assertionArgs,
71
+ constraints: constraints.map(([, , code, ...args]) => ({
72
+ code,
73
+ args
74
+ }))
75
+ }));
63
76
  };
64
- export {
65
- assert
77
+ var assert = (predicate, meta, constraints = []) => {
78
+ return createAssertion("guard", predicate, meta, constraints);
66
79
  };
80
+ var isRefinementAssertion = (constraint) => {
81
+ return typeof constraint === "function" && constraint[assertionStageSymbol] === "refinement";
82
+ };
83
+ var runRefinementAssertion = (constraint, value) => {
84
+ const runRefinement = constraint[runRefinementSymbol];
85
+ return runRefinement ? runRefinement(value) : constraint(value);
86
+ };
87
+ var checkRefinementAssertion = (constraint, value) => {
88
+ const checkRefinement = constraint[checkRefinementSymbol];
89
+ return checkRefinement ? checkRefinement(value) : constraint.check(value);
90
+ };
91
+ var createRefinement = (meta, constraints = []) => {
92
+ return createAssertion("refinement", ((value) => true), meta, constraints);
93
+ };
94
+ var refine = createRefinement;
95
+ //#endregion
96
+ export { assert, checkRefinementAssertion, createRefinement, isRefinementAssertion, refine, runRefinementAssertion };