@warlock.js/seal 5.30.0 → 5.32.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/CHANGELOG.md +46 -7
- package/README.md +57 -9
- package/cjs/index.cjs +41 -29
- package/cjs/index.cjs.map +1 -1
- package/cjs/{object--LXRt5RF.cjs → object-BoVGJ68E.cjs} +43 -24
- package/cjs/object-BoVGJ68E.cjs.map +1 -0
- package/cjs/object.cjs +2 -2
- package/cjs/{required-methods-DYsRO9aZ.cjs → required-methods-BJlnLnwa.cjs} +343 -258
- package/cjs/required-methods-BJlnLnwa.cjs.map +1 -0
- package/cjs/{string-DsqnKoSB.cjs → string-CM8x0u2w.cjs} +46 -44
- package/cjs/string-CM8x0u2w.cjs.map +1 -0
- package/cjs/string.cjs +2 -2
- package/esm/config.d.mts +7 -8
- package/esm/config.d.mts.map +1 -1
- package/esm/config.mjs.map +1 -1
- package/esm/factory/index.d.mts +2 -1
- package/esm/factory/index.mjs +1 -1
- package/esm/factory/validate.d.mts +3 -6
- package/esm/factory/validate.d.mts.map +1 -1
- package/esm/factory/validators.d.mts +16 -13
- package/esm/factory/validators.d.mts.map +1 -1
- package/esm/factory/validators.mjs +7 -1
- package/esm/factory/validators.mjs.map +1 -1
- package/esm/helpers/date-helpers.d.mts +1 -2
- package/esm/helpers/date-helpers.d.mts.map +1 -1
- package/esm/helpers/file.utils.d.mts +2 -4
- package/esm/helpers/file.utils.d.mts.map +1 -1
- package/esm/helpers/get-field-value.d.mts +2 -3
- package/esm/helpers/get-field-value.d.mts.map +1 -1
- package/esm/helpers/get-field-value.mjs +2 -1
- package/esm/helpers/get-field-value.mjs.map +1 -1
- package/esm/helpers/index.d.mts +6 -0
- package/esm/helpers/index.mjs +1 -1
- package/esm/helpers/path-helpers.d.mts +1 -2
- package/esm/helpers/path-helpers.d.mts.map +1 -1
- package/esm/helpers/validation-helpers.d.mts +4 -10
- package/esm/helpers/validation-helpers.d.mts.map +1 -1
- package/esm/index.d.mts +7 -0
- package/esm/mutators/array-mutators.d.mts +6 -7
- package/esm/mutators/array-mutators.d.mts.map +1 -1
- package/esm/mutators/boolean-mutators.d.mts +3 -4
- package/esm/mutators/boolean-mutators.d.mts.map +1 -1
- package/esm/mutators/date-mutators.d.mts +18 -19
- package/esm/mutators/date-mutators.d.mts.map +1 -1
- package/esm/mutators/index.d.mts +8 -0
- package/esm/mutators/index.mjs +1 -1
- package/esm/mutators/number-mutators.d.mts +10 -11
- package/esm/mutators/number-mutators.d.mts.map +1 -1
- package/esm/mutators/object-mutators.d.mts +4 -5
- package/esm/mutators/object-mutators.d.mts.map +1 -1
- package/esm/mutators/object-mutators.mjs +5 -4
- package/esm/mutators/object-mutators.mjs.map +1 -1
- package/esm/mutators/scalar-mutators.d.mts +2 -3
- package/esm/mutators/scalar-mutators.d.mts.map +1 -1
- package/esm/mutators/string-mutators.d.mts +37 -38
- package/esm/mutators/string-mutators.d.mts.map +1 -1
- package/esm/mutators/string-mutators.mjs +5 -3
- package/esm/mutators/string-mutators.mjs.map +1 -1
- package/esm/object.d.mts +3 -5
- package/esm/object.d.mts.map +1 -1
- package/esm/object.mjs.map +1 -1
- package/esm/plugins/plugin-system.d.mts +11 -9
- package/esm/plugins/plugin-system.d.mts.map +1 -1
- package/esm/rules/array/array-rules.d.mts +3 -4
- package/esm/rules/array/array-rules.d.mts.map +1 -1
- package/esm/rules/array/index.d.mts +2 -0
- package/esm/rules/array/index.mjs +1 -1
- package/esm/rules/color/color-rules.d.mts +8 -9
- package/esm/rules/color/color-rules.d.mts.map +1 -1
- package/esm/rules/color/index.d.mts +2 -0
- package/esm/rules/color/index.mjs +1 -1
- package/esm/rules/common/enum.d.mts +5 -6
- package/esm/rules/common/enum.d.mts.map +1 -1
- package/esm/rules/common/equals-field-rules.d.mts +3 -4
- package/esm/rules/common/equals-field-rules.d.mts.map +1 -1
- package/esm/rules/common/index.d.mts +7 -0
- package/esm/rules/common/index.mjs +1 -1
- package/esm/rules/common/instanceof.d.mts +2 -3
- package/esm/rules/common/instanceof.d.mts.map +1 -1
- package/esm/rules/common/literal.d.mts +2 -3
- package/esm/rules/common/literal.d.mts.map +1 -1
- package/esm/rules/common/literal.mjs.map +1 -1
- package/esm/rules/common/type-rules.d.mts +10 -11
- package/esm/rules/common/type-rules.d.mts.map +1 -1
- package/esm/rules/common/unknown-key.d.mts +2 -3
- package/esm/rules/common/unknown-key.d.mts.map +1 -1
- package/esm/rules/conditional/forbidden-if-rules.d.mts +7 -8
- package/esm/rules/conditional/forbidden-if-rules.d.mts.map +1 -1
- package/esm/rules/conditional/index.d.mts +11 -0
- package/esm/rules/conditional/index.mjs +1 -1
- package/esm/rules/conditional/present-if-rules.d.mts +6 -7
- package/esm/rules/conditional/present-if-rules.d.mts.map +1 -1
- package/esm/rules/conditional/present-unless-rules.d.mts +2 -3
- package/esm/rules/conditional/present-unless-rules.d.mts.map +1 -1
- package/esm/rules/conditional/present-with-rules.d.mts +4 -5
- package/esm/rules/conditional/present-with-rules.d.mts.map +1 -1
- package/esm/rules/conditional/present-without-rules.d.mts +4 -5
- package/esm/rules/conditional/present-without-rules.d.mts.map +1 -1
- package/esm/rules/conditional/required-if-rules.d.mts +10 -11
- package/esm/rules/conditional/required-if-rules.d.mts.map +1 -1
- package/esm/rules/conditional/required-unless-rules.d.mts +2 -3
- package/esm/rules/conditional/required-unless-rules.d.mts.map +1 -1
- package/esm/rules/conditional/required-when-rule.d.mts +2 -3
- package/esm/rules/conditional/required-when-rule.d.mts.map +1 -1
- package/esm/rules/conditional/required-with-rules.d.mts +4 -5
- package/esm/rules/conditional/required-with-rules.d.mts.map +1 -1
- package/esm/rules/conditional/required-without-rules.d.mts +4 -5
- package/esm/rules/conditional/required-without-rules.d.mts.map +1 -1
- package/esm/rules/core/equal.d.mts +2 -3
- package/esm/rules/core/equal.d.mts.map +1 -1
- package/esm/rules/core/forbidden.d.mts +2 -3
- package/esm/rules/core/forbidden.d.mts.map +1 -1
- package/esm/rules/core/index.d.mts +6 -0
- package/esm/rules/core/index.mjs +1 -1
- package/esm/rules/core/required.d.mts +3 -4
- package/esm/rules/core/required.d.mts.map +1 -1
- package/esm/rules/core/union.d.mts +10 -4
- package/esm/rules/core/union.d.mts.map +1 -1
- package/esm/rules/core/union.mjs +56 -10
- package/esm/rules/core/union.mjs.map +1 -1
- package/esm/rules/core/when.d.mts +2 -3
- package/esm/rules/core/when.d.mts.map +1 -1
- package/esm/rules/core/when.mjs.map +1 -1
- package/esm/rules/date/date-comparison-rules.d.mts +6 -7
- package/esm/rules/date/date-comparison-rules.d.mts.map +1 -1
- package/esm/rules/date/date-day-rules.d.mts +5 -6
- package/esm/rules/date/date-day-rules.d.mts.map +1 -1
- package/esm/rules/date/date-field-comparison-rules.d.mts +4 -5
- package/esm/rules/date/date-field-comparison-rules.d.mts.map +1 -1
- package/esm/rules/date/date-field-comparison-rules.mjs +6 -3
- package/esm/rules/date/date-field-comparison-rules.mjs.map +1 -1
- package/esm/rules/date/date-period-rules.d.mts +16 -16
- package/esm/rules/date/date-period-rules.d.mts.map +1 -1
- package/esm/rules/date/date-period-rules.mjs +24 -12
- package/esm/rules/date/date-period-rules.mjs.map +1 -1
- package/esm/rules/date/date-relative-rules.d.mts +4 -5
- package/esm/rules/date/date-relative-rules.d.mts.map +1 -1
- package/esm/rules/date/date-relative-rules.mjs +3 -3
- package/esm/rules/date/date-relative-rules.mjs.map +1 -1
- package/esm/rules/date/date-special-rules.d.mts +4 -5
- package/esm/rules/date/date-special-rules.d.mts.map +1 -1
- package/esm/rules/date/date.d.mts +16 -17
- package/esm/rules/date/date.d.mts.map +1 -1
- package/esm/rules/date/date.mjs +4 -2
- package/esm/rules/date/date.mjs.map +1 -1
- package/esm/rules/date/index.d.mts +8 -0
- package/esm/rules/date/index.mjs +1 -1
- package/esm/rules/file/dimensions.d.mts +5 -6
- package/esm/rules/file/dimensions.d.mts.map +1 -1
- package/esm/rules/file/file-size.d.mts +3 -4
- package/esm/rules/file/file-size.d.mts.map +1 -1
- package/esm/rules/file/index.d.mts +3 -0
- package/esm/rules/file/index.mjs +1 -1
- package/esm/rules/index.d.mts +56 -0
- package/esm/rules/index.mjs +1 -1
- package/esm/rules/length/index.d.mts +2 -0
- package/esm/rules/length/index.mjs +1 -1
- package/esm/rules/length/length-rules.d.mts +8 -9
- package/esm/rules/length/length-rules.d.mts.map +1 -1
- package/esm/rules/number/index.d.mts +2 -0
- package/esm/rules/number/index.mjs +1 -1
- package/esm/rules/number/number-rules.d.mts +11 -12
- package/esm/rules/number/number-rules.d.mts.map +1 -1
- package/esm/rules/number/number-rules.mjs +12 -6
- package/esm/rules/number/number-rules.mjs.map +1 -1
- package/esm/rules/scalar/index.mjs +1 -1
- package/esm/rules/string/alpha.d.mts +4 -5
- package/esm/rules/string/alpha.d.mts.map +1 -1
- package/esm/rules/string/credit-card.d.mts +2 -3
- package/esm/rules/string/credit-card.d.mts.map +1 -1
- package/esm/rules/string/email.d.mts +2 -3
- package/esm/rules/string/email.d.mts.map +1 -1
- package/esm/rules/string/id-formats.d.mts +6 -7
- package/esm/rules/string/id-formats.d.mts.map +1 -1
- package/esm/rules/string/index.d.mts +12 -0
- package/esm/rules/string/index.mjs +1 -1
- package/esm/rules/string/ip.d.mts +7 -8
- package/esm/rules/string/ip.d.mts.map +1 -1
- package/esm/rules/string/matches.d.mts +2 -3
- package/esm/rules/string/matches.d.mts.map +1 -1
- package/esm/rules/string/pattern.d.mts +2 -3
- package/esm/rules/string/pattern.d.mts.map +1 -1
- package/esm/rules/string/string-comparison.d.mts +5 -6
- package/esm/rules/string/string-comparison.d.mts.map +1 -1
- package/esm/rules/string/strong-password-rule.d.mts +2 -3
- package/esm/rules/string/strong-password-rule.d.mts.map +1 -1
- package/esm/rules/string/url.d.mts +2 -3
- package/esm/rules/string/url.d.mts.map +1 -1
- package/esm/rules/string/without-whitespace.d.mts +2 -3
- package/esm/rules/string/without-whitespace.d.mts.map +1 -1
- package/esm/standard-schema/index.d.mts +4 -0
- package/esm/standard-schema/json-schema.d.mts +5 -7
- package/esm/standard-schema/json-schema.d.mts.map +1 -1
- package/esm/standard-schema/json-schema.mjs.map +1 -1
- package/esm/standard-schema/map-result.d.mts +2 -3
- package/esm/standard-schema/map-result.d.mts.map +1 -1
- package/esm/standard-schema/map-result.mjs.map +1 -1
- package/esm/standard-schema/types.d.mts +4 -5
- package/esm/standard-schema/types.d.mts.map +1 -1
- package/esm/string.d.mts +2 -3
- package/esm/string.d.mts.map +1 -1
- package/esm/types/conditional-types.d.mts +8 -6
- package/esm/types/conditional-types.d.mts.map +1 -1
- package/esm/types/context-types.d.mts +24 -15
- package/esm/types/context-types.d.mts.map +1 -1
- package/esm/types/data-transformer-types.d.mts +3 -5
- package/esm/types/data-transformer-types.d.mts.map +1 -1
- package/esm/types/date-types.d.mts +2 -3
- package/esm/types/date-types.d.mts.map +1 -1
- package/esm/types/file.types.d.mts +1 -2
- package/esm/types/file.types.d.mts.map +1 -1
- package/esm/types/index.d.mts +11 -0
- package/esm/types/inference-types.d.mts +15 -14
- package/esm/types/inference-types.d.mts.map +1 -1
- package/esm/types/mutator-types.d.mts +9 -7
- package/esm/types/mutator-types.d.mts.map +1 -1
- package/esm/types/result-types.d.mts +12 -7
- package/esm/types/result-types.d.mts.map +1 -1
- package/esm/types/rule-types.d.mts +33 -15
- package/esm/types/rule-types.d.mts.map +1 -1
- package/esm/types/schema-types.d.mts +1 -3
- package/esm/types/schema-types.d.mts.map +1 -1
- package/esm/validators/any-validator.d.mts +1 -3
- package/esm/validators/any-validator.d.mts.map +1 -1
- package/esm/validators/array-validator.d.mts +2 -3
- package/esm/validators/array-validator.d.mts.map +1 -1
- package/esm/validators/array-validator.mjs +3 -3
- package/esm/validators/array-validator.mjs.map +1 -1
- package/esm/validators/base-validator.d.mts +10 -11
- package/esm/validators/base-validator.d.mts.map +1 -1
- package/esm/validators/base-validator.mjs +52 -21
- package/esm/validators/base-validator.mjs.map +1 -1
- package/esm/validators/boolean-validator.d.mts +1 -3
- package/esm/validators/boolean-validator.d.mts.map +1 -1
- package/esm/validators/computed-validator.d.mts +3 -4
- package/esm/validators/computed-validator.d.mts.map +1 -1
- package/esm/validators/computed-validator.mjs +4 -4
- package/esm/validators/computed-validator.mjs.map +1 -1
- package/esm/validators/date-validator.d.mts +2 -3
- package/esm/validators/date-validator.d.mts.map +1 -1
- package/esm/validators/discriminated-union-validator.d.mts +3 -3
- package/esm/validators/discriminated-union-validator.d.mts.map +1 -1
- package/esm/validators/discriminated-union-validator.mjs +1 -1
- package/esm/validators/discriminated-union-validator.mjs.map +1 -1
- package/esm/validators/float-validator.d.mts +1 -3
- package/esm/validators/float-validator.d.mts.map +1 -1
- package/esm/validators/index.d.mts +2 -1
- package/esm/validators/index.mjs +1 -1
- package/esm/validators/instanceof-validator.d.mts +1 -3
- package/esm/validators/instanceof-validator.d.mts.map +1 -1
- package/esm/validators/int-validator.d.mts +1 -3
- package/esm/validators/int-validator.d.mts.map +1 -1
- package/esm/validators/lazy-validator.d.mts +2 -3
- package/esm/validators/lazy-validator.d.mts.map +1 -1
- package/esm/validators/lazy-validator.mjs +1 -1
- package/esm/validators/lazy-validator.mjs.map +1 -1
- package/esm/validators/literal-validator.d.mts +1 -3
- package/esm/validators/literal-validator.d.mts.map +1 -1
- package/esm/validators/managed-validator.d.mts +3 -4
- package/esm/validators/managed-validator.d.mts.map +1 -1
- package/esm/validators/methods/equality-conditional-methods.d.mts +3 -4
- package/esm/validators/methods/equality-conditional-methods.d.mts.map +1 -1
- package/esm/validators/methods/forbidden-methods.d.mts +2 -3
- package/esm/validators/methods/forbidden-methods.d.mts.map +1 -1
- package/esm/validators/methods/present-methods.d.mts +2 -3
- package/esm/validators/methods/present-methods.d.mts.map +1 -1
- package/esm/validators/methods/required-methods.d.mts +3 -4
- package/esm/validators/methods/required-methods.d.mts.map +1 -1
- package/esm/validators/number-validator.d.mts +1 -3
- package/esm/validators/number-validator.d.mts.map +1 -1
- package/esm/validators/number-validator.mjs +12 -8
- package/esm/validators/number-validator.mjs.map +1 -1
- package/esm/validators/numeric-validator.d.mts +1 -3
- package/esm/validators/numeric-validator.d.mts.map +1 -1
- package/esm/validators/object-validator.d.mts +2 -3
- package/esm/validators/object-validator.d.mts.map +1 -1
- package/esm/validators/object-validator.mjs +9 -7
- package/esm/validators/object-validator.mjs.map +1 -1
- package/esm/validators/primitive-validator.d.mts +1 -3
- package/esm/validators/primitive-validator.d.mts.map +1 -1
- package/esm/validators/record-validator.d.mts +2 -3
- package/esm/validators/record-validator.d.mts.map +1 -1
- package/esm/validators/record-validator.mjs +3 -3
- package/esm/validators/record-validator.mjs.map +1 -1
- package/esm/validators/scalar-validator.d.mts +1 -3
- package/esm/validators/scalar-validator.d.mts.map +1 -1
- package/esm/validators/scalar-validator.mjs.map +1 -1
- package/esm/validators/string-validator.d.mts +1 -3
- package/esm/validators/string-validator.d.mts.map +1 -1
- package/esm/validators/tuple-validator.d.mts +2 -3
- package/esm/validators/tuple-validator.d.mts.map +1 -1
- package/esm/validators/tuple-validator.mjs +3 -3
- package/esm/validators/tuple-validator.mjs.map +1 -1
- package/esm/validators/union-validator.d.mts +4 -4
- package/esm/validators/union-validator.d.mts.map +1 -1
- package/esm/validators/union-validator.mjs +3 -1
- package/esm/validators/union-validator.mjs.map +1 -1
- package/llms-full.txt +656 -527
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/skills/bridge-standard-schema/SKILL.md +60 -36
- package/skills/compose-seal-modifiers/SKILL.md +89 -53
- package/skills/define-structural-shape/SKILL.md +41 -27
- package/skills/define-structural-shape/array-methods.md +27 -27
- package/skills/define-structural-shape/object-methods.md +38 -30
- package/skills/extend-seal-with-plugins/SKILL.md +39 -5
- package/skills/generate-json-schema/SKILL.md +13 -13
- package/skills/handle-seal-errors/SKILL.md +23 -23
- package/skills/index.md +4 -1
- package/skills/overview/SKILL.md +10 -2
- package/skills/pick-seal-primitive/SKILL.md +45 -45
- package/skills/pick-seal-primitive/date-methods.md +96 -96
- package/skills/pick-seal-primitive/number-methods.md +55 -55
- package/skills/pick-seal-primitive/string-methods.md +107 -102
- package/skills/seal-basics/SKILL.md +14 -14
- package/cjs/object--LXRt5RF.cjs.map +0 -1
- package/cjs/required-methods-DYsRO9aZ.cjs.map +0 -1
- package/cjs/string-DsqnKoSB.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,33 +4,71 @@ All notable changes to `@warlock.js/seal` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.32.0 - 2026-10-18
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Replace the unused classic TypeScript import-organizer development dependency with `@ianvs/prettier-plugin-sort-imports`, compatible with TypeScript 7.
|
|
12
|
+
- Pin the package development compiler to TypeScript 7.0.2 and use explicit Node types and source roots with supported module resolution.
|
|
13
|
+
- Rebaseline the type benchmark on TS7 with `--checkers 1` so type/instantiation counts remain deterministic; resolve the compiler through its exported package manifest.
|
|
14
|
+
|
|
15
|
+
## 5.31.0 - 2026-10-18
|
|
16
|
+
|
|
17
|
+
### Upgrading
|
|
18
|
+
|
|
19
|
+
- **BREAKING:** a failed `v.union(...)` reports the closest member's errors at their own paths (`actor.id` instead of `actor`), still typed `union`; with `firstErrorOnly: false` it reports each of that member's errors separately instead of one `;`-joined message from every member. A custom union message, or a value no member can hold by type, still gives one error at the union's path. Update code that reads union errors by path or splits the joined message.
|
|
20
|
+
- **BREAKING:** `.refine()` now runs against successful output after child validation and transformers, and skips absent/null or invalid values. Callbacks are typed from the validator's output instead of `any`. Move checks that need input before child validation to `.addRule()`. `warlock upgrade --from 5.30 --to 5.31.0` lists every `.refine()` to review (codemod `seal-refine-output`).
|
|
21
|
+
- **BREAKING:** `.catch()` is a no-op on container validators, including failures in the container's own rules. Inputs previously accepted by an array/object catch after a length or unknown-key error now fail. Apply catches to child validators or handle a failed container result explicitly. `warlock upgrade --from 5.30 --to 5.31.0` lists `.catch()` calls on containers (codemod `seal-container-catch`).
|
|
22
|
+
- **BREAKING:** `v.union()` now returns its matched branch's validated output. Trimming and date parsing change values; object defaults/computed fields are retained, stripped unknown keys disappear, and an explicit `undefined` output drops the containing object field. Persisted, compared or serialized output can differ. Read and keep the raw input before validation when you need it. `warlock upgrade --from 5.30 --to 5.31.0` lists every `v.union()` to review (codemod `seal-union-output`).
|
|
23
|
+
- Refinements now also check successful empty defaults such as `.default("")`; callbacks that reject those defaults now reject validation.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Object factories return their already typed class directly, avoiding a duplicate Standard Schema intersection and reducing compiler work for composed schemas. CI now checks the Seal inference benchmark against its updated baseline.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- `v.union(...)` tries every member whose type matches before failing, so a union of several object schemas accepts a value that matches a later member; `firstErrorOnly` limits the errors reported, not the members tried. A failing union reports its closest member: fewest mismatched literals, then fewest errors, then the deepest error path, then declaration order.
|
|
32
|
+
- A failing union no longer stores its last member error on the shared rule, so a later validation with no type-matching member reports the default message instead of a stale one.
|
|
33
|
+
- The custom-error locale example is strict JSON, with its filename outside the code fence.
|
|
34
|
+
- Standalone string replacement mutators accept an omitted context or options and preserve the stringified input instead of throwing.
|
|
35
|
+
- Object `.merge()` retains refinements from both schemas, in their original order; cloning, extending and selecting fields preserve the original schema's refinements.
|
|
36
|
+
- Union and record Standard Schema types now distinguish child input from validated output; `Infer.Output` reads the Standard Schema output parameter. Defaults and catches remain guaranteed in output.
|
|
37
|
+
- Object, array, tuple and lazy Standard Schema output declarations preserve child defaults and catches independently of their input types.
|
|
38
|
+
- `v.tuple([...])` infers one type per position: `v.tuple([v.string(), v.int()])` is typed `[string, number]` for input and output instead of `(string | number)[]`, so a value with swapped positions no longer type-checks. A `BaseValidator[]` variable is still accepted.
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- A failed rule result may carry `errors: [{ error, path }]` to report several errors, each at its own path, under the rule's type.
|
|
43
|
+
- Successful custom rules may return a `data` property to replace the current validated value, including explicit `undefined`; omitting the property preserves the value.
|
|
44
|
+
|
|
7
45
|
## 5.30.0 - 2026-10-16
|
|
8
46
|
|
|
9
47
|
### Upgrading
|
|
10
48
|
|
|
11
|
-
- **BREAKING (types only):** `validate()` now returns a result narrowed on `isValid`. On success `data` is `Infer.Output<typeof schema>`, on failure it is `undefined`. Code that read `result.data` without checking `isValid`, or assigned it to an unrelated type, may need a check or a cast. A schema typed as bare `BaseValidator`/`ObjectValidator` keeps `data: any`.
|
|
49
|
+
- **BREAKING (types only):** `validate()` now returns a result narrowed on `isValid`. On success `data` is `Infer.Output<typeof schema>`, on failure it is `undefined`. Code that read `result.data` without checking `isValid`, or assigned it to an unrelated type, may need a check or a cast. A schema typed as bare `BaseValidator`/`ObjectValidator` keeps `data: any`. `warlock upgrade --from 5.29 --to 5.31.0` lists `validate()` results read without an `isValid` check (codemod `seal-validate-result`).
|
|
12
50
|
|
|
13
51
|
### Added
|
|
14
52
|
|
|
15
53
|
- `TypedValidationResult<T>` and `ValidatedOutput<T>` types.
|
|
16
|
-
- `pnpm bench:types` measures inference compile cost on a generated composed-schema project (16 entities, 8 services) and fails when instantiations or types grow more than 5% over `bench/types-baseline.json
|
|
54
|
+
- `pnpm bench:types` measures inference compile cost on a generated composed-schema project (16 entities, 8 services) and fails when instantiations or types grow more than 5% over `bench/types-baseline.json`. It also fails when it cannot read a metric or is given a malformed option, warns when the TypeScript version differs from the baseline's (`--strict` makes that a failure), and removes its temporary project on Ctrl+C.
|
|
17
55
|
|
|
18
56
|
### Changed
|
|
19
57
|
|
|
20
58
|
- `validate()` takes `data: unknown` instead of `any`.
|
|
21
59
|
- `Infer.Input`/`Infer.Output` of an object is one flat object type instead of an intersection of its optional and required halves; the shape is unchanged and compile cost moves by 0.1%.
|
|
22
60
|
- `pnpm typecheck` now also checks the `expectTypeOf` assertions in `tests/unit/types/` (`tsconfig.typecheck.json`); they were never enforced before.
|
|
23
|
-
- `.refine()` callbacks stay `value: any` on purpose: custom rules run before an object or array validates its children, so the value is not the schema output
|
|
61
|
+
- `.refine()` callbacks stay `value: any` on purpose: custom rules run before an object or array validates its children, so the value is not the schema output.
|
|
24
62
|
- **Behaviour change:** `v.union([...])` now checks a present empty value (`""`) against its members instead of accepting it unchecked; a missing key is still the required/`.optional()` question. `v.union([v.literal("x"), v.int()]).present()` now rejects `""`.
|
|
25
63
|
- `validate()` keeps the typed output of `v.record(...)` (`Record<string, …>`); only an index signature over `any`/`unknown` (the wide `Schema`) stays `any`.
|
|
26
64
|
|
|
27
65
|
### Fixed
|
|
28
66
|
|
|
29
|
-
- `v.literal("")` accepts a present `""` again (regressed in 5.25): its default (implicit) required state and `.present()` keep it, `.optional()` and `.nullable()` no longer drop it. An explicit `.required()` or `requiredIf(...)` still rejects `""`. A literal set without a blank value still reads `""` as missing
|
|
30
|
-
- A field with an empty default (`v.string().max(n).default("")`) no longer fails "is required" when the input omits it, sends `null`, or sends a blank string (an untouched HTML input); the output is the default
|
|
67
|
+
- `v.literal("")` accepts a present `""` again (regressed in 5.25): its default (implicit) required state and `.present()` keep it, `.optional()` and `.nullable()` no longer drop it. An explicit `.required()` or `requiredIf(...)` still rejects `""`. A literal set without a blank value still reads `""` as missing.
|
|
68
|
+
- A field with an empty default (`v.string().max(n).default("")`) no longer fails "is required" when the input omits it, sends `null`, or sends a blank string (an untouched HTML input); the output is the default.
|
|
31
69
|
- A `null` default no longer satisfies "required" on a field that is not `.nullable()`, and an empty default of the wrong type (`v.int().default("")`) now fails the type rule instead of being returned unchecked.
|
|
32
|
-
- `v.discriminatedUnion(...).optional()` accepts an absent, `undefined` or `null` field, as every other validator does; `.default(...)` replaces `null` too and is validated through its branch. A required union reports a missing or `null` field with the `required` error; `.nullable()` keeps `null
|
|
33
|
-
- `schema["~standard"].validate(...)` on a discriminated union resolves to the branch output union instead of `unknown
|
|
70
|
+
- `v.discriminatedUnion(...).optional()` accepts an absent, `undefined` or `null` field, as every other validator does; `.default(...)` replaces `null` too and is validated through its branch. A required union reports a missing or `null` field with the `required` error; `.nullable()` keeps `null`.
|
|
71
|
+
- `schema["~standard"].validate(...)` on a discriminated union resolves to the branch output union instead of `unknown`.
|
|
34
72
|
|
|
35
73
|
## 5.29.0 - 2026-10-01
|
|
36
74
|
|
|
@@ -112,6 +150,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
112
150
|
### Changed
|
|
113
151
|
|
|
114
152
|
- Lockstep release maintenance and dependency refresh.
|
|
153
|
+
|
|
115
154
|
## 5.20.0 - 2026-09-24
|
|
116
155
|
|
|
117
156
|
### Changed
|
package/README.md
CHANGED
|
@@ -181,18 +181,56 @@ const schema = v.object({
|
|
|
181
181
|
});
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
+
### Union and record output types
|
|
185
|
+
|
|
186
|
+
`v.union(...)` and `v.record(...)` expose separate Standard Schema input and output
|
|
187
|
+
types. `Infer.Output` and `~standard.validate()` describe validated child output:
|
|
188
|
+
defaults and catches guarantee fields even when callers may omit them. A union
|
|
189
|
+
returns its matching branch's validated data, including computed fields and child
|
|
190
|
+
transformers, before running its own transformers and refinements.
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
const entry = v.object({ count: v.int().optional().default(1) });
|
|
194
|
+
const union = v.union([entry, v.string()]);
|
|
195
|
+
const record = v.record(entry);
|
|
196
|
+
// Infer.Input<typeof union>: { count?: number } | string
|
|
197
|
+
// Infer.Output<typeof union>: { count: number } | string
|
|
198
|
+
// Infer.Output<typeof record>: Record<string, { count: number }>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Upgrading:** union output now includes member trimming, date parsing, defaults,
|
|
202
|
+
computed fields and unknown-key stripping. A member that outputs `undefined`
|
|
203
|
+
causes the containing object field to be omitted. This can change stored,
|
|
204
|
+
compared or serialized values. Keep any raw input you need before validation.
|
|
205
|
+
|
|
184
206
|
### ✅ Custom Validation
|
|
185
207
|
|
|
186
208
|
Add your own validation logic:
|
|
187
209
|
|
|
188
210
|
```typescript
|
|
189
|
-
v.string().refine(async value => {
|
|
211
|
+
v.string().refine(async (value) => {
|
|
190
212
|
const exists = await checkUsername(value);
|
|
191
213
|
if (exists) return "Username already taken";
|
|
192
214
|
});
|
|
193
215
|
```
|
|
194
216
|
|
|
195
|
-
The callback's `value` is typed
|
|
217
|
+
The callback's `value` is typed from the validator's output. Refinements run after value rules, child validation (including defaults and computed fields), and output transformers succeed. They skip absent/null values and failed validation, even with `firstErrorOnly: false`. Multiple refinements run in declaration order and respect `firstErrorOnly`. Use `.addRule()` for checks that need the input before child validation.
|
|
218
|
+
|
|
219
|
+
Refinements also run on successful empty defaults such as `.default("")`. Object
|
|
220
|
+
`.merge()` appends refinements from the merged schema; `.extend()` imports only
|
|
221
|
+
its fields and retains the receiver's refinements. Other clone/field-selection
|
|
222
|
+
operations keep the receiver's refinements, so callbacks must tolerate any fields
|
|
223
|
+
you remove from the shape.
|
|
224
|
+
|
|
225
|
+
Output transformer types are not fully tracked yet: for example,
|
|
226
|
+
`v.date().toISOString()` returns a string at runtime while its declared output
|
|
227
|
+
remains `Date`. Use a Date input rule or convert the Date after validation when
|
|
228
|
+
a refinement needs Date methods. Chaining `.refine()` before `.toISOString()`
|
|
229
|
+
does not change execution order.
|
|
230
|
+
|
|
231
|
+
A successful `.addRule()` callback may return `{ isValid: true, data: replacement }`
|
|
232
|
+
to replace the value for later rules, transformers and refinements. Omitting `data`
|
|
233
|
+
keeps the current value; including `data: undefined` explicitly clears it.
|
|
196
234
|
|
|
197
235
|
### ✅ Mutators & Transformers
|
|
198
236
|
|
|
@@ -304,19 +342,14 @@ const bookingSchema = v.object({
|
|
|
304
342
|
### Array Validation
|
|
305
343
|
|
|
306
344
|
```typescript
|
|
307
|
-
const tagsSchema = v
|
|
308
|
-
.array(v.string())
|
|
309
|
-
.required()
|
|
310
|
-
.minLength(1)
|
|
311
|
-
.maxLength(10)
|
|
312
|
-
.unique();
|
|
345
|
+
const tagsSchema = v.array(v.string()).required().minLength(1).maxLength(10).unique();
|
|
313
346
|
|
|
314
347
|
const usersSchema = v
|
|
315
348
|
.array(
|
|
316
349
|
v.object({
|
|
317
350
|
name: v.string().required(),
|
|
318
351
|
email: v.string().email(),
|
|
319
|
-
})
|
|
352
|
+
}),
|
|
320
353
|
)
|
|
321
354
|
.minLength(1);
|
|
322
355
|
```
|
|
@@ -382,6 +415,21 @@ The documentation includes:
|
|
|
382
415
|
|
|
383
416
|
---
|
|
384
417
|
|
|
418
|
+
## Type inference compiler budget
|
|
419
|
+
|
|
420
|
+
From `packages/seal`, run `pnpm bench:types --check` to compile a deterministic
|
|
421
|
+
fixture of 16 composed entities and 8 services. CI runs the same check when Seal
|
|
422
|
+
is selected. It rejects compiler errors and growth above 5% in instantiations or
|
|
423
|
+
types; memory and elapsed time are recorded for context. Object factories use the
|
|
424
|
+
class's existing input/output generics directly, avoiding a duplicate Standard
|
|
425
|
+
Schema intersection on every nested object.
|
|
426
|
+
|
|
427
|
+
After reviewing a deliberate change, refresh the baseline with
|
|
428
|
+
`node scripts/bench-types.mjs --update`. Keep fixture sizes and TypeScript versions
|
|
429
|
+
the same when comparing counts.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
385
433
|
## 📄 License
|
|
386
434
|
|
|
387
435
|
MIT
|
package/cjs/index.cjs
CHANGED
|
@@ -20,15 +20,15 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
20
|
}
|
|
21
21
|
return to;
|
|
22
22
|
};
|
|
23
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
24
24
|
value: mod,
|
|
25
25
|
enumerable: true
|
|
26
26
|
}) : target, mod));
|
|
27
27
|
|
|
28
28
|
//#endregion
|
|
29
|
-
const require_required_methods = require(
|
|
30
|
-
const require_object = require(
|
|
31
|
-
const require_string = require(
|
|
29
|
+
const require_required_methods = require("./required-methods-BJlnLnwa.cjs");
|
|
30
|
+
const require_object = require("./object-BoVGJ68E.cjs");
|
|
31
|
+
const require_string = require("./string-CM8x0u2w.cjs");
|
|
32
32
|
let _mongez_reinforcements = require("@mongez/reinforcements");
|
|
33
33
|
let _mongez_supportive_is = require("@mongez/supportive-is");
|
|
34
34
|
let dayjs = require("dayjs");
|
|
@@ -650,7 +650,7 @@ var ArrayValidator = class extends require_required_methods.BaseValidator {
|
|
|
650
650
|
async validate(data, context) {
|
|
651
651
|
const valueForRules = data ?? this.getDefaultValue();
|
|
652
652
|
const mutatedData = await this.mutate(valueForRules, context);
|
|
653
|
-
const result = await
|
|
653
|
+
const result = await this.validateRules(data, context);
|
|
654
654
|
if (result.isValid === false) return result;
|
|
655
655
|
if (mutatedData === void 0 || mutatedData === null) return result;
|
|
656
656
|
if (!Array.isArray(mutatedData)) return result;
|
|
@@ -661,18 +661,18 @@ var ArrayValidator = class extends require_required_methods.BaseValidator {
|
|
|
661
661
|
parent: mutatedData,
|
|
662
662
|
value,
|
|
663
663
|
key: index.toString(),
|
|
664
|
-
path:
|
|
664
|
+
path: require_object.setKeyPath(context.path, index.toString())
|
|
665
665
|
};
|
|
666
666
|
const childResult = await this.validator.validate(value, childContext);
|
|
667
667
|
mutatedData[index] = childResult.data;
|
|
668
668
|
if (childResult.isValid === false) errors.push(...childResult.errors);
|
|
669
669
|
});
|
|
670
670
|
await Promise.all(validationPromises);
|
|
671
|
-
return {
|
|
671
|
+
return this.refineResult({
|
|
672
672
|
isValid: errors.length === 0,
|
|
673
673
|
errors,
|
|
674
674
|
data: await this.startTransformationPipeline(mutatedData, context)
|
|
675
|
-
};
|
|
675
|
+
}, context);
|
|
676
676
|
}
|
|
677
677
|
/**
|
|
678
678
|
* @inheritdoc
|
|
@@ -1657,7 +1657,7 @@ var DiscriminatedUnionValidator = class DiscriminatedUnionValidator extends requ
|
|
|
1657
1657
|
data: void 0
|
|
1658
1658
|
};
|
|
1659
1659
|
}
|
|
1660
|
-
return branch.validate(data, context);
|
|
1660
|
+
return this.refineResult(await branch.validate(data, context), context);
|
|
1661
1661
|
}
|
|
1662
1662
|
clone() {
|
|
1663
1663
|
const cloned = super.clone();
|
|
@@ -1987,15 +1987,19 @@ var NumberValidator = class extends require_string.PrimitiveValidator {
|
|
|
1987
1987
|
if (typeof betweenOpts.max === "number") schema.maximum = betweenOpts.max;
|
|
1988
1988
|
}
|
|
1989
1989
|
const gtOpts = require_required_methods.getRuleOptions(this.rules, "greaterThan");
|
|
1990
|
-
if (gtOpts?.value !== void 0 && typeof gtOpts.value === "number")
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1990
|
+
if (gtOpts?.value !== void 0 && typeof gtOpts.value === "number") {
|
|
1991
|
+
if (target === "draft-07") {
|
|
1992
|
+
schema.minimum = gtOpts.value;
|
|
1993
|
+
schema.exclusiveMinimum = true;
|
|
1994
|
+
} else schema.exclusiveMinimum = gtOpts.value;
|
|
1995
|
+
}
|
|
1994
1996
|
const ltOpts = require_required_methods.getRuleOptions(this.rules, "lessThan");
|
|
1995
|
-
if (ltOpts?.value !== void 0 && typeof ltOpts.value === "number")
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1997
|
+
if (ltOpts?.value !== void 0 && typeof ltOpts.value === "number") {
|
|
1998
|
+
if (target === "draft-07") {
|
|
1999
|
+
schema.maximum = ltOpts.value;
|
|
2000
|
+
schema.exclusiveMaximum = true;
|
|
2001
|
+
} else schema.exclusiveMaximum = ltOpts.value;
|
|
2002
|
+
}
|
|
1999
2003
|
const moduloOpts = require_required_methods.getRuleOptions(this.rules, "modulo");
|
|
2000
2004
|
if (moduloOpts?.value !== void 0 && typeof moduloOpts.value === "number") schema.multipleOf = moduloOpts.value;
|
|
2001
2005
|
const inOpts = require_required_methods.getRuleOptions(this.rules, "in");
|
|
@@ -2157,7 +2161,7 @@ var LazyValidator = class extends require_required_methods.BaseValidator {
|
|
|
2157
2161
|
return this.resolvedValidator;
|
|
2158
2162
|
}
|
|
2159
2163
|
async validate(data, context) {
|
|
2160
|
-
return this.resolve().validate(data, context);
|
|
2164
|
+
return this.refineResult(await this.resolve().validate(data, context), context);
|
|
2161
2165
|
}
|
|
2162
2166
|
matchesType(value) {
|
|
2163
2167
|
return this.resolve().matchesType(value);
|
|
@@ -2288,7 +2292,7 @@ var RecordValidator = class extends require_required_methods.BaseValidator {
|
|
|
2288
2292
|
async validate(data, context) {
|
|
2289
2293
|
const valueForRules = data ?? this.getDefaultValue();
|
|
2290
2294
|
const mutatedData = await this.mutate(valueForRules, context);
|
|
2291
|
-
const result = await
|
|
2295
|
+
const result = await this.validateRules(data, context);
|
|
2292
2296
|
if (result.isValid === false) return result;
|
|
2293
2297
|
if (mutatedData === void 0 || mutatedData === null) return result;
|
|
2294
2298
|
if (!(0, _mongez_supportive_is.isPlainObject)(mutatedData)) return result;
|
|
@@ -2299,18 +2303,18 @@ var RecordValidator = class extends require_required_methods.BaseValidator {
|
|
|
2299
2303
|
parent: mutatedData,
|
|
2300
2304
|
value: mutatedData[key],
|
|
2301
2305
|
key,
|
|
2302
|
-
path:
|
|
2306
|
+
path: require_object.setKeyPath(context.path, key)
|
|
2303
2307
|
};
|
|
2304
2308
|
const childResult = await this.valueValidator.validate(mutatedData[key], childContext);
|
|
2305
2309
|
mutatedData[key] = childResult.data;
|
|
2306
2310
|
if (childResult.isValid === false) errors.push(...childResult.errors);
|
|
2307
2311
|
});
|
|
2308
2312
|
await Promise.all(validationPromises);
|
|
2309
|
-
return {
|
|
2313
|
+
return this.refineResult({
|
|
2310
2314
|
isValid: errors.length === 0,
|
|
2311
2315
|
errors,
|
|
2312
2316
|
data: await this.startTransformationPipeline(mutatedData, context)
|
|
2313
|
-
};
|
|
2317
|
+
}, context);
|
|
2314
2318
|
}
|
|
2315
2319
|
/**
|
|
2316
2320
|
* @inheritdoc
|
|
@@ -2545,7 +2549,7 @@ var TupleValidator = class extends require_required_methods.BaseValidator {
|
|
|
2545
2549
|
async validate(data, context) {
|
|
2546
2550
|
const valueForRules = data ?? this.getDefaultValue();
|
|
2547
2551
|
const mutatedData = await this.mutate(valueForRules, context);
|
|
2548
|
-
const result = await
|
|
2552
|
+
const result = await this.validateRules(data, context);
|
|
2549
2553
|
if (result.isValid === false) return result;
|
|
2550
2554
|
if (mutatedData === void 0 || mutatedData === null) return result;
|
|
2551
2555
|
if (!Array.isArray(mutatedData)) return result;
|
|
@@ -2568,18 +2572,18 @@ var TupleValidator = class extends require_required_methods.BaseValidator {
|
|
|
2568
2572
|
parent: mutatedData,
|
|
2569
2573
|
value: mutatedData[index],
|
|
2570
2574
|
key: index.toString(),
|
|
2571
|
-
path:
|
|
2575
|
+
path: require_object.setKeyPath(context.path, index.toString())
|
|
2572
2576
|
};
|
|
2573
2577
|
const childResult = await validator.validate(mutatedData[index], childContext);
|
|
2574
2578
|
mutatedData[index] = childResult.data;
|
|
2575
2579
|
if (childResult.isValid === false) errors.push(...childResult.errors);
|
|
2576
2580
|
});
|
|
2577
2581
|
await Promise.all(validationPromises);
|
|
2578
|
-
return {
|
|
2582
|
+
return this.refineResult({
|
|
2579
2583
|
isValid: errors.length === 0,
|
|
2580
2584
|
errors,
|
|
2581
2585
|
data: await this.startTransformationPipeline(mutatedData, context)
|
|
2582
|
-
};
|
|
2586
|
+
}, context);
|
|
2583
2587
|
}
|
|
2584
2588
|
/**
|
|
2585
2589
|
* @inheritdoc
|
|
@@ -2628,7 +2632,9 @@ var TupleValidator = class extends require_required_methods.BaseValidator {
|
|
|
2628
2632
|
*
|
|
2629
2633
|
* Tries each validator in order until one passes. If a validator's matchesType()
|
|
2630
2634
|
* returns false, it's skipped for optimization. First validator that both matches
|
|
2631
|
-
* the type and passes validation wins
|
|
2635
|
+
* the type and passes validation wins; every type-matching validator is tried,
|
|
2636
|
+
* whatever `firstErrorOnly` says. When none passes, the closest one's errors are
|
|
2637
|
+
* reported (fewest mismatched literals, then fewest errors, then deepest path).
|
|
2632
2638
|
*
|
|
2633
2639
|
* @example
|
|
2634
2640
|
* ```ts
|
|
@@ -2696,7 +2702,13 @@ const v = {
|
|
|
2696
2702
|
array: (validator, errorMessage) => new ArrayValidator(validator, errorMessage),
|
|
2697
2703
|
/** Create a record validator - object with dynamic keys and consistent value types */
|
|
2698
2704
|
record: (validator, errorMessage) => new RecordValidator(validator || v.any(), errorMessage),
|
|
2699
|
-
/**
|
|
2705
|
+
/**
|
|
2706
|
+
* Create a tuple validator - fixed-length array with position-specific types.
|
|
2707
|
+
*
|
|
2708
|
+
* The `| []` in the constraint makes TypeScript infer a literal list as a tuple, so
|
|
2709
|
+
* `v.tuple([v.string(), v.int()])` is typed `[string, number]` rather than
|
|
2710
|
+
* `(string | number)[]`; a `BaseValidator[]` variable is still accepted.
|
|
2711
|
+
*/
|
|
2700
2712
|
tuple: (validators, errorMessage) => new TupleValidator(validators, errorMessage),
|
|
2701
2713
|
/** Create a date validator */
|
|
2702
2714
|
date: (errorMessage) => new DateValidator(errorMessage),
|
|
@@ -3073,7 +3085,7 @@ exports.rtrimMutator = require_string.rtrimMutator;
|
|
|
3073
3085
|
exports.safeHtmlMutator = require_string.safeHtmlMutator;
|
|
3074
3086
|
exports.sameAsFieldDateRule = require_required_methods.sameAsFieldDateRule;
|
|
3075
3087
|
exports.scalarRule = require_required_methods.scalarRule;
|
|
3076
|
-
exports.setKeyPath =
|
|
3088
|
+
exports.setKeyPath = require_object.setKeyPath;
|
|
3077
3089
|
exports.slugMutator = require_string.slugMutator;
|
|
3078
3090
|
exports.snakeCaseMutator = require_string.snakeCaseMutator;
|
|
3079
3091
|
exports.sortArrayMutator = sortArrayMutator;
|