@warlock.js/seal 5.8.0 → 5.10.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/esm/index.d.mts CHANGED
@@ -87,6 +87,7 @@ import { getFieldValue } from "./helpers/get-field-value.mjs";
87
87
  import { setKeyPath } from "./helpers/path-helpers.mjs";
88
88
  import { VALID_RULE, invalidRule, resolveTranslation } from "./helpers/validation-helpers.mjs";
89
89
  import { flipArrayMutator, removeEmptyArrayElementsMutator, reverseArrayMutator, sortArrayMutator, uniqueArrayMutator } from "./mutators/array-mutators.mjs";
90
+ import { booleanCoerceMutator } from "./mutators/boolean-mutators.mjs";
90
91
  import { addDaysMutator, addHoursMutator, addMonthsMutator, addYearsMutator, dateMutator, toDateOnlyMutator, toEndOfDayMutator, toEndOfMonthMutator, toEndOfYearMutator, toFormatMutator, toISOStringMutator, toStartOfDayMutator, toStartOfMonthMutator, toStartOfYearMutator, toTimeOnlyMutator, toTimestampMutator, toUTCMutator } from "./mutators/date-mutators.mjs";
91
92
  import { absMutator, booleanMutator, ceilMutator, floorMutator, numberMutator, numericMutator, roundMutator, roundNumberMutator, toFixedMutator } from "./mutators/number-mutators.mjs";
92
93
  import { jsonMutator, objectTrimMutator, stripUnknownMutator } from "./mutators/object-mutators.mjs";
@@ -97,7 +98,7 @@ import { ValidateOptions, ValidatorV, v } from "./factory/validators.mjs";
97
98
  import { validate } from "./factory/validate.mjs";
98
99
  import { PluginContext, SealPlugin, getInstalledPlugins, hasPlugin, registerPlugin, unregisterPlugin } from "./plugins/plugin-system.mjs";
99
100
  import { mapToStandardResult } from "./standard-schema/map-result.mjs";
100
- export { AnyValidator, ArrayValidator, AttributeTranslation, BaseValidator, BooleanValidator, ComputedCallback, ComputedValidator, ContextualSchemaRule, ContextualizedMutator, ContextualizedTransformer, DateValidator, DiscriminatedUnionValidator, FileSizeOption, FloatValidator, Infer, InferInput, InferInputObjectShape, InferObjectShape, InferOutput, InferOutputObjectShape, InstanceOfValidator, IntValidator, IsInputOptionalKey, IsOptionalKey, IsOutputOptionalKey, JsonSchemaResult, JsonSchemaTarget, LazyValidator, LiteralValidator, ManagedCallback, ManagedValidator, Month, Mutator, MutatorContext, NumberValidator, NumericValidator, ObjectValidator, PluginContext, PrimitiveValidator, RecordValidator, RuleResult, RuleTranslation, ScalarValidator, Schema, SchemaContext, SchemaRule, SchemaRuleOptions, SealConfig, SealPlugin, SimpleTransformerCallback, StandardJSONSchemaV1, StandardSchemaV1, StringValidator, TransformerCallback, TranslateAttributeCallback, TranslateRuleCallback, TupleValidator, UUIDVersion, UnionValidator, VALID_RULE, ValidateOptions, ValidationAttributesList, ValidationResult, ValidatorV, WEEK_DAYS, WeekDay, WhenRuleOptions, absMutator, addDaysMutator, addHoursMutator, addMonthsMutator, addYearsMutator, afterFieldRule, afterTodayRule, ageRule, allowedValuesRule, alphaNumericRule, alphaOnlyMutator, alphaRule, alphanumericOnlyMutator, appendMutator, applyNullable, arrayRule, base64DecodeMutator, base64EncodeMutator, beforeFieldRule, beforeHourRule, beforeMinuteRule, beforeTodayRule, betweenAgeRule, betweenDatesRule, betweenDaysRule, betweenHoursRule, betweenLengthRule, betweenMinutesRule, betweenMonthsRule, betweenNumbersRule, betweenTimesRule, betweenYearsRule, birthdayRule, booleanMutator, booleanRule, businessDayRule, camelCaseMutator, capitalizeMutator, ceilMutator, colorRule, configureSeal, containsRule, cuidRule, darkColorRule, dateMutator, dateRule, emailRule, endsWithRule, enumRule, equalRule, equalityConditionalMethodsApplied, equalsFieldRule, evenRule, flipArrayMutator, floatRule, floorMutator, forbiddenIfEmptyRule, forbiddenIfInRule, forbiddenIfNotEmptyRule, forbiddenIfNotInRule, forbiddenIfNotRule, forbiddenIfRule, forbiddenMethodsApplied, forbiddenRule, fromHourRule, fromMinuteRule, fromTodayRule, futureRule, getFieldValue, getInstalledPlugins, getRuleOptions, getSealConfig, greaterThanRule, hasPlugin, hexColorRule, hslColorRule, htmlEscapeMutator, humanizeSize, inRule, instanceofRule, intRule, invalidRule, ip4Rule, ip6Rule, ipRule, isCreditCardRule, isDateValue, isIP, isIPv4, isIPv6, isNumericRule, jsonMutator, kebabCaseMutator, leapYearRule, lengthRule, lessThanRule, lightColorRule, literalRule, lowercaseMutator, ltrimMutator, mapToStandardResult, maskMutator, matchesRule, maxAgeRule, maxDateRule, maxDayRule, maxFileSizeRule, maxHeightRule, maxLengthRule, maxMonthRule, maxRule, maxWidthRule, maxWordsRule, maxYearRule, minAgeRule, minDateRule, minDayRule, minFileSizeRule, minHeightRule, minLengthRule, minMonthRule, minRule, minWidthRule, minWordsRule, minYearRule, moduloRule, monthRule, nanoidRule, negativeRule, notAllowedValuesRule, notContainsRule, notEqualsFieldRule, numberMutator, numberRule, numericMutator, objectRule, objectTrimMutator, oddRule, padEndMutator, padStartMutator, pascalCaseMutator, pastRule, patternRule, plainObjectRule, positiveRule, prependMutator, presentIfEmptyRule, presentIfInRule, presentIfNotEmptyRule, presentIfNotInRule, presentIfRule, presentMethodsApplied, presentRule, presentUnlessRule, presentWithAllRule, presentWithAnyRule, presentWithRule, presentWithoutAllRule, presentWithoutAnyRule, presentWithoutRule, quarterRule, registerPlugin, removeEmptyArrayElementsMutator, removeNumbersMutator, removeSpecialCharactersMutator, repeatMutator, replaceAllMutator, replaceMutator, requiredIfAllEmptyRule, requiredIfAllNotEmptyRule, requiredIfAnyEmptyRule, requiredIfAnyNotEmptyRule, requiredIfEmptyRule, requiredIfInRule, requiredIfNotEmptyRule, requiredIfNotInRule, requiredIfRule, requiredMethodsApplied, requiredRule, requiredUnlessRule, requiredWhenRule, requiredWithAllRule, requiredWithAnyRule, requiredWithRule, requiredWithoutAllRule, requiredWithoutAnyRule, requiredWithoutRule, resetSealConfig, resolveFileSize, resolveTranslation, reverseArrayMutator, reverseMutator, rgbColorRule, rgbaColorRule, roundMutator, roundNumberMutator, rtrimMutator, safeHtmlMutator, sameAsFieldDateRule, scalarRule, setKeyPath, slugMutator, snakeCaseMutator, sortArrayMutator, sortedArrayRule, startsWithRule, stringMutator, stringRule, stringifyMutator, stripTagsMutator, stripUnknownMutator, strongPasswordRule, titleCaseMutator, toDateOnlyMutator, toEndOfDayMutator, toEndOfMonthMutator, toEndOfYearMutator, toFixedMutator, toFormatMutator, toISOStringMutator, toStartOfDayMutator, toStartOfMonthMutator, toStartOfYearMutator, toTimeOnlyMutator, toTimestampMutator, toUTCMutator, todayRule, trimMultipleWhitespaceMutator, trimMutator, truncateMutator, ulidRule, unescapeHtmlMutator, unionRule, uniqueArrayMutator, uniqueArrayRule, unknownKeyRule, unregisterPlugin, uppercaseMutator, urlDecodeMutator, urlEncodeMutator, urlRule, uuidRule, v, validate, weekDayRule, weekdayRule, weekdaysRule, weekendRule, whenRule, withinDaysRule, withinFutureDaysRule, withinPastDaysRule, withoutWhitespaceRule, wordsRule, wrapNullableStrict, yearRule };
101
+ export { AnyValidator, ArrayValidator, AttributeTranslation, BaseValidator, BooleanValidator, ComputedCallback, ComputedValidator, ContextualSchemaRule, ContextualizedMutator, ContextualizedTransformer, DateValidator, DiscriminatedUnionValidator, FileSizeOption, FloatValidator, Infer, InferInput, InferInputObjectShape, InferObjectShape, InferOutput, InferOutputObjectShape, InstanceOfValidator, IntValidator, IsInputOptionalKey, IsOptionalKey, IsOutputOptionalKey, JsonSchemaResult, JsonSchemaTarget, LazyValidator, LiteralValidator, ManagedCallback, ManagedValidator, Month, Mutator, MutatorContext, NumberValidator, NumericValidator, ObjectValidator, PluginContext, PrimitiveValidator, RecordValidator, RuleResult, RuleTranslation, ScalarValidator, Schema, SchemaContext, SchemaRule, SchemaRuleOptions, SealConfig, SealPlugin, SimpleTransformerCallback, StandardJSONSchemaV1, StandardSchemaV1, StringValidator, TransformerCallback, TranslateAttributeCallback, TranslateRuleCallback, TupleValidator, UUIDVersion, UnionValidator, VALID_RULE, ValidateOptions, ValidationAttributesList, ValidationResult, ValidatorV, WEEK_DAYS, WeekDay, WhenRuleOptions, absMutator, addDaysMutator, addHoursMutator, addMonthsMutator, addYearsMutator, afterFieldRule, afterTodayRule, ageRule, allowedValuesRule, alphaNumericRule, alphaOnlyMutator, alphaRule, alphanumericOnlyMutator, appendMutator, applyNullable, arrayRule, base64DecodeMutator, base64EncodeMutator, beforeFieldRule, beforeHourRule, beforeMinuteRule, beforeTodayRule, betweenAgeRule, betweenDatesRule, betweenDaysRule, betweenHoursRule, betweenLengthRule, betweenMinutesRule, betweenMonthsRule, betweenNumbersRule, betweenTimesRule, betweenYearsRule, birthdayRule, booleanCoerceMutator, booleanMutator, booleanRule, businessDayRule, camelCaseMutator, capitalizeMutator, ceilMutator, colorRule, configureSeal, containsRule, cuidRule, darkColorRule, dateMutator, dateRule, emailRule, endsWithRule, enumRule, equalRule, equalityConditionalMethodsApplied, equalsFieldRule, evenRule, flipArrayMutator, floatRule, floorMutator, forbiddenIfEmptyRule, forbiddenIfInRule, forbiddenIfNotEmptyRule, forbiddenIfNotInRule, forbiddenIfNotRule, forbiddenIfRule, forbiddenMethodsApplied, forbiddenRule, fromHourRule, fromMinuteRule, fromTodayRule, futureRule, getFieldValue, getInstalledPlugins, getRuleOptions, getSealConfig, greaterThanRule, hasPlugin, hexColorRule, hslColorRule, htmlEscapeMutator, humanizeSize, inRule, instanceofRule, intRule, invalidRule, ip4Rule, ip6Rule, ipRule, isCreditCardRule, isDateValue, isIP, isIPv4, isIPv6, isNumericRule, jsonMutator, kebabCaseMutator, leapYearRule, lengthRule, lessThanRule, lightColorRule, literalRule, lowercaseMutator, ltrimMutator, mapToStandardResult, maskMutator, matchesRule, maxAgeRule, maxDateRule, maxDayRule, maxFileSizeRule, maxHeightRule, maxLengthRule, maxMonthRule, maxRule, maxWidthRule, maxWordsRule, maxYearRule, minAgeRule, minDateRule, minDayRule, minFileSizeRule, minHeightRule, minLengthRule, minMonthRule, minRule, minWidthRule, minWordsRule, minYearRule, moduloRule, monthRule, nanoidRule, negativeRule, notAllowedValuesRule, notContainsRule, notEqualsFieldRule, numberMutator, numberRule, numericMutator, objectRule, objectTrimMutator, oddRule, padEndMutator, padStartMutator, pascalCaseMutator, pastRule, patternRule, plainObjectRule, positiveRule, prependMutator, presentIfEmptyRule, presentIfInRule, presentIfNotEmptyRule, presentIfNotInRule, presentIfRule, presentMethodsApplied, presentRule, presentUnlessRule, presentWithAllRule, presentWithAnyRule, presentWithRule, presentWithoutAllRule, presentWithoutAnyRule, presentWithoutRule, quarterRule, registerPlugin, removeEmptyArrayElementsMutator, removeNumbersMutator, removeSpecialCharactersMutator, repeatMutator, replaceAllMutator, replaceMutator, requiredIfAllEmptyRule, requiredIfAllNotEmptyRule, requiredIfAnyEmptyRule, requiredIfAnyNotEmptyRule, requiredIfEmptyRule, requiredIfInRule, requiredIfNotEmptyRule, requiredIfNotInRule, requiredIfRule, requiredMethodsApplied, requiredRule, requiredUnlessRule, requiredWhenRule, requiredWithAllRule, requiredWithAnyRule, requiredWithRule, requiredWithoutAllRule, requiredWithoutAnyRule, requiredWithoutRule, resetSealConfig, resolveFileSize, resolveTranslation, reverseArrayMutator, reverseMutator, rgbColorRule, rgbaColorRule, roundMutator, roundNumberMutator, rtrimMutator, safeHtmlMutator, sameAsFieldDateRule, scalarRule, setKeyPath, slugMutator, snakeCaseMutator, sortArrayMutator, sortedArrayRule, startsWithRule, stringMutator, stringRule, stringifyMutator, stripTagsMutator, stripUnknownMutator, strongPasswordRule, titleCaseMutator, toDateOnlyMutator, toEndOfDayMutator, toEndOfMonthMutator, toEndOfYearMutator, toFixedMutator, toFormatMutator, toISOStringMutator, toStartOfDayMutator, toStartOfMonthMutator, toStartOfYearMutator, toTimeOnlyMutator, toTimestampMutator, toUTCMutator, todayRule, trimMultipleWhitespaceMutator, trimMutator, truncateMutator, ulidRule, unescapeHtmlMutator, unionRule, uniqueArrayMutator, uniqueArrayRule, unknownKeyRule, unregisterPlugin, uppercaseMutator, urlDecodeMutator, urlEncodeMutator, urlRule, uuidRule, v, validate, weekDayRule, weekdayRule, weekdaysRule, weekendRule, whenRule, withinDaysRule, withinFutureDaysRule, withinPastDaysRule, withoutWhitespaceRule, wordsRule, wrapNullableStrict, yearRule };
101
102
  import "./validators/methods/equality-conditional-methods.mjs";
102
103
  import "./validators/methods/forbidden-methods.mjs";
103
104
  import "./validators/methods/present-methods.mjs";
package/esm/index.mjs CHANGED
@@ -12,6 +12,7 @@ import { mapToStandardResult } from "./standard-schema/map-result.mjs";
12
12
  import { BaseValidator } from "./validators/base-validator.mjs";
13
13
  import { AnyValidator } from "./validators/any-validator.mjs";
14
14
  import { flipArrayMutator, removeEmptyArrayElementsMutator, reverseArrayMutator, sortArrayMutator, uniqueArrayMutator } from "./mutators/array-mutators.mjs";
15
+ import { booleanCoerceMutator } from "./mutators/boolean-mutators.mjs";
15
16
  import { addDaysMutator, addHoursMutator, addMonthsMutator, addYearsMutator, dateMutator, toDateOnlyMutator, toEndOfDayMutator, toEndOfMonthMutator, toEndOfYearMutator, toFormatMutator, toISOStringMutator, toStartOfDayMutator, toStartOfMonthMutator, toStartOfYearMutator, toTimeOnlyMutator, toTimestampMutator, toUTCMutator } from "./mutators/date-mutators.mjs";
16
17
  import { absMutator, booleanMutator, ceilMutator, floorMutator, numberMutator, numericMutator, roundMutator, roundNumberMutator, toFixedMutator } from "./mutators/number-mutators.mjs";
17
18
  import { jsonMutator, objectTrimMutator, stripUnknownMutator } from "./mutators/object-mutators.mjs";
@@ -93,4 +94,4 @@ import { v } from "./factory/validators.mjs";
93
94
  import "./factory/index.mjs";
94
95
  import { getInstalledPlugins, hasPlugin, registerPlugin, unregisterPlugin } from "./plugins/plugin-system.mjs";
95
96
 
96
- export { AnyValidator, ArrayValidator, BaseValidator, BooleanValidator, ComputedValidator, DateValidator, DiscriminatedUnionValidator, FloatValidator, InstanceOfValidator, IntValidator, LazyValidator, LiteralValidator, ManagedValidator, NumberValidator, NumericValidator, ObjectValidator, PrimitiveValidator, RecordValidator, ScalarValidator, StringValidator, TupleValidator, UnionValidator, VALID_RULE, WEEK_DAYS, absMutator, addDaysMutator, addHoursMutator, addMonthsMutator, addYearsMutator, afterFieldRule, afterTodayRule, ageRule, allowedValuesRule, alphaNumericRule, alphaOnlyMutator, alphaRule, alphanumericOnlyMutator, appendMutator, applyNullable, arrayRule, base64DecodeMutator, base64EncodeMutator, beforeFieldRule, beforeHourRule, beforeMinuteRule, beforeTodayRule, betweenAgeRule, betweenDatesRule, betweenDaysRule, betweenHoursRule, betweenLengthRule, betweenMinutesRule, betweenMonthsRule, betweenNumbersRule, betweenTimesRule, betweenYearsRule, birthdayRule, booleanMutator, booleanRule, businessDayRule, camelCaseMutator, capitalizeMutator, ceilMutator, colorRule, configureSeal, containsRule, cuidRule, darkColorRule, dateMutator, dateRule, emailRule, endsWithRule, enumRule, equalRule, equalityConditionalMethodsApplied, equalsFieldRule, evenRule, flipArrayMutator, floatRule, floorMutator, forbiddenIfEmptyRule, forbiddenIfInRule, forbiddenIfNotEmptyRule, forbiddenIfNotInRule, forbiddenIfNotRule, forbiddenIfRule, forbiddenMethodsApplied, forbiddenRule, fromHourRule, fromMinuteRule, fromTodayRule, futureRule, getFieldValue, getInstalledPlugins, getRuleOptions, getSealConfig, greaterThanRule, hasPlugin, hexColorRule, hslColorRule, htmlEscapeMutator, humanizeSize, inRule, instanceofRule, intRule, invalidRule, ip4Rule, ip6Rule, ipRule, isCreditCardRule, isDateValue, isIP, isIPv4, isIPv6, isNumericRule, jsonMutator, kebabCaseMutator, leapYearRule, lengthRule, lessThanRule, lightColorRule, literalRule, lowercaseMutator, ltrimMutator, mapToStandardResult, maskMutator, matchesRule, maxAgeRule, maxDateRule, maxDayRule, maxFileSizeRule, maxHeightRule, maxLengthRule, maxMonthRule, maxRule, maxWidthRule, maxWordsRule, maxYearRule, minAgeRule, minDateRule, minDayRule, minFileSizeRule, minHeightRule, minLengthRule, minMonthRule, minRule, minWidthRule, minWordsRule, minYearRule, moduloRule, monthRule, nanoidRule, negativeRule, notAllowedValuesRule, notContainsRule, notEqualsFieldRule, numberMutator, numberRule, numericMutator, objectRule, objectTrimMutator, oddRule, padEndMutator, padStartMutator, pascalCaseMutator, pastRule, patternRule, plainObjectRule, positiveRule, prependMutator, presentIfEmptyRule, presentIfInRule, presentIfNotEmptyRule, presentIfNotInRule, presentIfRule, presentMethodsApplied, presentRule, presentUnlessRule, presentWithAllRule, presentWithAnyRule, presentWithRule, presentWithoutAllRule, presentWithoutAnyRule, presentWithoutRule, quarterRule, registerPlugin, removeEmptyArrayElementsMutator, removeNumbersMutator, removeSpecialCharactersMutator, repeatMutator, replaceAllMutator, replaceMutator, requiredIfAllEmptyRule, requiredIfAllNotEmptyRule, requiredIfAnyEmptyRule, requiredIfAnyNotEmptyRule, requiredIfEmptyRule, requiredIfInRule, requiredIfNotEmptyRule, requiredIfNotInRule, requiredIfRule, requiredMethodsApplied, requiredRule, requiredUnlessRule, requiredWhenRule, requiredWithAllRule, requiredWithAnyRule, requiredWithRule, requiredWithoutAllRule, requiredWithoutAnyRule, requiredWithoutRule, resetSealConfig, resolveFileSize, resolveTranslation, reverseArrayMutator, reverseMutator, rgbColorRule, rgbaColorRule, roundMutator, roundNumberMutator, rtrimMutator, safeHtmlMutator, sameAsFieldDateRule, scalarRule, setKeyPath, slugMutator, snakeCaseMutator, sortArrayMutator, sortedArrayRule, startsWithRule, stringMutator, stringRule, stringifyMutator, stripTagsMutator, stripUnknownMutator, strongPasswordRule, titleCaseMutator, toDateOnlyMutator, toEndOfDayMutator, toEndOfMonthMutator, toEndOfYearMutator, toFixedMutator, toFormatMutator, toISOStringMutator, toStartOfDayMutator, toStartOfMonthMutator, toStartOfYearMutator, toTimeOnlyMutator, toTimestampMutator, toUTCMutator, todayRule, trimMultipleWhitespaceMutator, trimMutator, truncateMutator, ulidRule, unescapeHtmlMutator, unionRule, uniqueArrayMutator, uniqueArrayRule, unknownKeyRule, unregisterPlugin, uppercaseMutator, urlDecodeMutator, urlEncodeMutator, urlRule, uuidRule, v, validate, weekDayRule, weekdayRule, weekdaysRule, weekendRule, whenRule, withinDaysRule, withinFutureDaysRule, withinPastDaysRule, withoutWhitespaceRule, wordsRule, wrapNullableStrict, yearRule };
97
+ export { AnyValidator, ArrayValidator, BaseValidator, BooleanValidator, ComputedValidator, DateValidator, DiscriminatedUnionValidator, FloatValidator, InstanceOfValidator, IntValidator, LazyValidator, LiteralValidator, ManagedValidator, NumberValidator, NumericValidator, ObjectValidator, PrimitiveValidator, RecordValidator, ScalarValidator, StringValidator, TupleValidator, UnionValidator, VALID_RULE, WEEK_DAYS, absMutator, addDaysMutator, addHoursMutator, addMonthsMutator, addYearsMutator, afterFieldRule, afterTodayRule, ageRule, allowedValuesRule, alphaNumericRule, alphaOnlyMutator, alphaRule, alphanumericOnlyMutator, appendMutator, applyNullable, arrayRule, base64DecodeMutator, base64EncodeMutator, beforeFieldRule, beforeHourRule, beforeMinuteRule, beforeTodayRule, betweenAgeRule, betweenDatesRule, betweenDaysRule, betweenHoursRule, betweenLengthRule, betweenMinutesRule, betweenMonthsRule, betweenNumbersRule, betweenTimesRule, betweenYearsRule, birthdayRule, booleanCoerceMutator, booleanMutator, booleanRule, businessDayRule, camelCaseMutator, capitalizeMutator, ceilMutator, colorRule, configureSeal, containsRule, cuidRule, darkColorRule, dateMutator, dateRule, emailRule, endsWithRule, enumRule, equalRule, equalityConditionalMethodsApplied, equalsFieldRule, evenRule, flipArrayMutator, floatRule, floorMutator, forbiddenIfEmptyRule, forbiddenIfInRule, forbiddenIfNotEmptyRule, forbiddenIfNotInRule, forbiddenIfNotRule, forbiddenIfRule, forbiddenMethodsApplied, forbiddenRule, fromHourRule, fromMinuteRule, fromTodayRule, futureRule, getFieldValue, getInstalledPlugins, getRuleOptions, getSealConfig, greaterThanRule, hasPlugin, hexColorRule, hslColorRule, htmlEscapeMutator, humanizeSize, inRule, instanceofRule, intRule, invalidRule, ip4Rule, ip6Rule, ipRule, isCreditCardRule, isDateValue, isIP, isIPv4, isIPv6, isNumericRule, jsonMutator, kebabCaseMutator, leapYearRule, lengthRule, lessThanRule, lightColorRule, literalRule, lowercaseMutator, ltrimMutator, mapToStandardResult, maskMutator, matchesRule, maxAgeRule, maxDateRule, maxDayRule, maxFileSizeRule, maxHeightRule, maxLengthRule, maxMonthRule, maxRule, maxWidthRule, maxWordsRule, maxYearRule, minAgeRule, minDateRule, minDayRule, minFileSizeRule, minHeightRule, minLengthRule, minMonthRule, minRule, minWidthRule, minWordsRule, minYearRule, moduloRule, monthRule, nanoidRule, negativeRule, notAllowedValuesRule, notContainsRule, notEqualsFieldRule, numberMutator, numberRule, numericMutator, objectRule, objectTrimMutator, oddRule, padEndMutator, padStartMutator, pascalCaseMutator, pastRule, patternRule, plainObjectRule, positiveRule, prependMutator, presentIfEmptyRule, presentIfInRule, presentIfNotEmptyRule, presentIfNotInRule, presentIfRule, presentMethodsApplied, presentRule, presentUnlessRule, presentWithAllRule, presentWithAnyRule, presentWithRule, presentWithoutAllRule, presentWithoutAnyRule, presentWithoutRule, quarterRule, registerPlugin, removeEmptyArrayElementsMutator, removeNumbersMutator, removeSpecialCharactersMutator, repeatMutator, replaceAllMutator, replaceMutator, requiredIfAllEmptyRule, requiredIfAllNotEmptyRule, requiredIfAnyEmptyRule, requiredIfAnyNotEmptyRule, requiredIfEmptyRule, requiredIfInRule, requiredIfNotEmptyRule, requiredIfNotInRule, requiredIfRule, requiredMethodsApplied, requiredRule, requiredUnlessRule, requiredWhenRule, requiredWithAllRule, requiredWithAnyRule, requiredWithRule, requiredWithoutAllRule, requiredWithoutAnyRule, requiredWithoutRule, resetSealConfig, resolveFileSize, resolveTranslation, reverseArrayMutator, reverseMutator, rgbColorRule, rgbaColorRule, roundMutator, roundNumberMutator, rtrimMutator, safeHtmlMutator, sameAsFieldDateRule, scalarRule, setKeyPath, slugMutator, snakeCaseMutator, sortArrayMutator, sortedArrayRule, startsWithRule, stringMutator, stringRule, stringifyMutator, stripTagsMutator, stripUnknownMutator, strongPasswordRule, titleCaseMutator, toDateOnlyMutator, toEndOfDayMutator, toEndOfMonthMutator, toEndOfYearMutator, toFixedMutator, toFormatMutator, toISOStringMutator, toStartOfDayMutator, toStartOfMonthMutator, toStartOfYearMutator, toTimeOnlyMutator, toTimestampMutator, toUTCMutator, todayRule, trimMultipleWhitespaceMutator, trimMutator, truncateMutator, ulidRule, unescapeHtmlMutator, unionRule, uniqueArrayMutator, uniqueArrayRule, unknownKeyRule, unregisterPlugin, uppercaseMutator, urlDecodeMutator, urlEncodeMutator, urlRule, uuidRule, v, validate, weekDayRule, weekdayRule, weekdaysRule, weekendRule, whenRule, withinDaysRule, withinFutureDaysRule, withinPastDaysRule, withoutWhitespaceRule, wordsRule, wrapNullableStrict, yearRule };
@@ -0,0 +1,14 @@
1
+ import { Mutator } from "../types/mutator-types.mjs";
2
+
3
+ //#region ../seal/src/mutators/boolean-mutators.d.ts
4
+ /**
5
+ * Coerce a query-string-shaped boolean into a real boolean.
6
+ *
7
+ * Converts exactly: `"true"` / `"1"` / `1` → `true`, `"false"` / `"0"` / `0` → `false`.
8
+ * Case-sensitive, no trimming. Any other value (`"yes"`, `"on"`, `"TRUE"`, `""`,
9
+ * `2`, `null`, etc.) passes through unchanged so the boolean type rule rejects it.
10
+ */
11
+ declare const booleanCoerceMutator: Mutator;
12
+ //#endregion
13
+ export { booleanCoerceMutator };
14
+ //# sourceMappingURL=boolean-mutators.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boolean-mutators.d.mts","names":[],"sources":["../../../../../../../seal/src/mutators/boolean-mutators.ts"],"mappings":";;;;;AASA;;;;AAUC;cAVY,oBAAA,EAAsB,OAUlC"}
@@ -0,0 +1,17 @@
1
+ //#region ../seal/src/mutators/boolean-mutators.ts
2
+ /**
3
+ * Coerce a query-string-shaped boolean into a real boolean.
4
+ *
5
+ * Converts exactly: `"true"` / `"1"` / `1` → `true`, `"false"` / `"0"` / `0` → `false`.
6
+ * Case-sensitive, no trimming. Any other value (`"yes"`, `"on"`, `"TRUE"`, `""`,
7
+ * `2`, `null`, etc.) passes through unchanged so the boolean type rule rejects it.
8
+ */
9
+ const booleanCoerceMutator = async (value) => {
10
+ if (value === "true" || value === "1" || value === 1) return true;
11
+ if (value === "false" || value === "0" || value === 0) return false;
12
+ return value;
13
+ };
14
+
15
+ //#endregion
16
+ export { booleanCoerceMutator };
17
+ //# sourceMappingURL=boolean-mutators.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boolean-mutators.mjs","names":[],"sources":["../../../../../../../seal/src/mutators/boolean-mutators.ts"],"sourcesContent":["import type { Mutator } from \"../types\";\n\n/**\n * Coerce a query-string-shaped boolean into a real boolean.\n *\n * Converts exactly: `\"true\"` / `\"1\"` / `1` → `true`, `\"false\"` / `\"0\"` / `0` → `false`.\n * Case-sensitive, no trimming. Any other value (`\"yes\"`, `\"on\"`, `\"TRUE\"`, `\"\"`,\n * `2`, `null`, etc.) passes through unchanged so the boolean type rule rejects it.\n */\nexport const booleanCoerceMutator: Mutator = async (value) => {\n if (value === \"true\" || value === \"1\" || value === 1) {\n return true;\n }\n\n if (value === \"false\" || value === \"0\" || value === 0) {\n return false;\n }\n\n return value;\n};\n"],"mappings":";;;;;;;;AASA,MAAa,uBAAgC,OAAO,UAAU;CAC5D,IAAI,UAAU,UAAU,UAAU,OAAO,UAAU,GACjD,OAAO;CAGT,IAAI,UAAU,WAAW,UAAU,OAAO,UAAU,GAClD,OAAO;CAGT,OAAO;AACT"}
@@ -1,4 +1,5 @@
1
1
  import { flipArrayMutator, removeEmptyArrayElementsMutator, reverseArrayMutator, sortArrayMutator, uniqueArrayMutator } from "./array-mutators.mjs";
2
+ import { booleanCoerceMutator } from "./boolean-mutators.mjs";
2
3
  import { addDaysMutator, addHoursMutator, addMonthsMutator, addYearsMutator, dateMutator, toDateOnlyMutator, toEndOfDayMutator, toEndOfMonthMutator, toEndOfYearMutator, toFormatMutator, toISOStringMutator, toStartOfDayMutator, toStartOfMonthMutator, toStartOfYearMutator, toTimeOnlyMutator, toTimestampMutator, toUTCMutator } from "./date-mutators.mjs";
3
4
  import { absMutator, booleanMutator, ceilMutator, floorMutator, numberMutator, numericMutator, roundMutator, roundNumberMutator, toFixedMutator } from "./number-mutators.mjs";
4
5
  import { jsonMutator, objectTrimMutator, stripUnknownMutator } from "./object-mutators.mjs";
@@ -39,6 +39,27 @@ declare class BooleanValidator extends PrimitiveValidator {
39
39
  declinedIfPresent(field: string, errorMessage?: string): this;
40
40
  /** Value must be declined if another field is missing */
41
41
  declinedWithout(field: string, errorMessage?: string): this;
42
+ /**
43
+ * Opt in to coercion: an exact query-string-shaped boolean is converted to a
44
+ * real boolean **before** the type rules run; any other value passes through
45
+ * unchanged so bad input still fails the type rule.
46
+ *
47
+ * Converts exactly `"true"` / `"1"` / `1` → `true` and `"false"` / `"0"` / `0`
48
+ * → `false`. Case-sensitive, no trimming — `"TRUE"`, `"yes"`, `"on"`, `""`, and
49
+ * `2` all pass through unchanged and fail the type rule. `v.boolean()` does
50
+ * **not** coerce by default; this only takes effect when explicitly chained.
51
+ * For form-style truthy strings like `"yes"` / `"on"`, use `.accepted()` /
52
+ * `.declined()` instead — those are separate pass/fail rules, not coercion.
53
+ *
54
+ * The output type is unchanged (`Infer<>` keys off the validator class), so
55
+ * `v.boolean().coerce()` still infers `boolean`.
56
+ *
57
+ * @example
58
+ * v.boolean().coerce() // "true" → true; "1" → true; "0" → false; "yes" → invalid
59
+ */
60
+ coerce(): this & {
61
+ isCoerced: true;
62
+ };
42
63
  /**
43
64
  * Value must be strictly true (not "yes", "on", 1, etc.)
44
65
  * @alias accepted - strict version
@@ -1 +1 @@
1
- {"version":3,"file":"boolean-validator.d.mts","names":[],"sources":["../../../../../../../seal/src/validators/boolean-validator.ts"],"mappings":";;;;;;AA0BA;;;;;cAAa,gBAAA,SAAyB,kBAAA;cACjB,YAAA;EADmC;;;EAS/C,WAAA,CAAY,KAAA;EAAZ;EAOA,QAAA,CAAS,YAAA;EAAT;EAKA,UAAA,CAAW,KAAA,UAAe,KAAA,OAAY,YAAA;EAAtC;EAKA,cAAA,CAAe,KAAA,UAAe,KAAA,OAAY,YAAA;EALhB;EAU1B,kBAAA,CAAmB,KAAA,UAAe,YAAA;EALlC;EAUA,iBAAA,CAAkB,KAAA,UAAe,YAAA;EAVH;EAe9B,eAAA,CAAgB,KAAA,UAAe,YAAA;EAV/B;EAiBA,QAAA,CAAS,YAAA;EAjByB;EAsBlC,UAAA,CAAW,KAAA,UAAe,KAAA,OAAY,YAAA;EAjBpB;EAsBlB,cAAA,CAAe,KAAA,UAAe,KAAA,OAAY,YAAA;EAjB1C;EAsBA,kBAAA,CAAmB,KAAA,UAAe,YAAA;EAtBH;EA2B/B,iBAAA,CAAkB,KAAA,UAAe,YAAA;EApBxB;EAyBT,eAAA,CAAgB,KAAA,UAAe,YAAA;EApBpB;;;;EA8BX,UAAA,CAAW,YAAA;EAzBmB;;;;EAiC9B,WAAA,CAAY,YAAA;EAvBZ;;;;;;;;;;;;;;;EA0CS,YAAA,CAAa,MAAA,GAAQ,gBAAA,GAAqC,gBAAA;AAAA"}
1
+ {"version":3,"file":"boolean-validator.d.mts","names":[],"sources":["../../../../../../../seal/src/validators/boolean-validator.ts"],"mappings":";;;;;;AA2BA;;;;;cAAa,gBAAA,SAAyB,kBAAA;cACjB,YAAA;EADmC;;;EAS/C,WAAA,CAAY,KAAA;EAAZ;EAOA,QAAA,CAAS,YAAA;EAAT;EAKA,UAAA,CAAW,KAAA,UAAe,KAAA,OAAY,YAAA;EAAtC;EAKA,cAAA,CAAe,KAAA,UAAe,KAAA,OAAY,YAAA;EALhB;EAU1B,kBAAA,CAAmB,KAAA,UAAe,YAAA;EALlC;EAUA,iBAAA,CAAkB,KAAA,UAAe,YAAA;EAVH;EAe9B,eAAA,CAAgB,KAAA,UAAe,YAAA;EAV/B;EAiBA,QAAA,CAAS,YAAA;EAjByB;EAsBlC,UAAA,CAAW,KAAA,UAAe,KAAA,OAAY,YAAA;EAjBpB;EAsBlB,cAAA,CAAe,KAAA,UAAe,KAAA,OAAY,YAAA;EAjB1C;EAsBA,kBAAA,CAAmB,KAAA,UAAe,YAAA;EAtBH;EA2B/B,iBAAA,CAAkB,KAAA,UAAe,YAAA;EApBxB;EAyBT,eAAA,CAAgB,KAAA,UAAe,YAAA;EApBpB;;;;;;;;;;;;;;;;;;EA4CX,MAAA;IACoD,SAAA;EAAA;EAiBxC;;;;EARZ,UAAA,CAAW,YAAA;EA2BwE;AAAA;;;EAnBnF,WAAA,CAAY,YAAA;;;;;;;;;;;;;;;;EAmBH,YAAA,CAAa,MAAA,GAAQ,gBAAA,GAAqC,gBAAA;AAAA"}
@@ -1,4 +1,5 @@
1
1
  import { applyNullable } from "../standard-schema/json-schema.mjs";
2
+ import { booleanCoerceMutator } from "../mutators/boolean-mutators.mjs";
2
3
  import { booleanRule } from "../rules/common/type-rules.mjs";
3
4
  import "../rules/index.mjs";
4
5
  import { PrimitiveValidator } from "./primitive-validator.mjs";
@@ -86,6 +87,27 @@ var BooleanValidator = class extends PrimitiveValidator {
86
87
  return this.addRule(declinedWithoutRule, errorMessage, { field });
87
88
  }
88
89
  /**
90
+ * Opt in to coercion: an exact query-string-shaped boolean is converted to a
91
+ * real boolean **before** the type rules run; any other value passes through
92
+ * unchanged so bad input still fails the type rule.
93
+ *
94
+ * Converts exactly `"true"` / `"1"` / `1` → `true` and `"false"` / `"0"` / `0`
95
+ * → `false`. Case-sensitive, no trimming — `"TRUE"`, `"yes"`, `"on"`, `""`, and
96
+ * `2` all pass through unchanged and fail the type rule. `v.boolean()` does
97
+ * **not** coerce by default; this only takes effect when explicitly chained.
98
+ * For form-style truthy strings like `"yes"` / `"on"`, use `.accepted()` /
99
+ * `.declined()` instead — those are separate pass/fail rules, not coercion.
100
+ *
101
+ * The output type is unchanged (`Infer<>` keys off the validator class), so
102
+ * `v.boolean().coerce()` still infers `boolean`.
103
+ *
104
+ * @example
105
+ * v.boolean().coerce() // "true" → true; "1" → true; "0" → false; "yes" → invalid
106
+ */
107
+ coerce() {
108
+ return this.addMutator(booleanCoerceMutator);
109
+ }
110
+ /**
89
111
  * Value must be strictly true (not "yes", "on", 1, etc.)
90
112
  * @alias accepted - strict version
91
113
  */
@@ -1 +1 @@
1
- {"version":3,"file":"boolean-validator.mjs","names":[],"sources":["../../../../../../../seal/src/validators/boolean-validator.ts"],"sourcesContent":["import {\n acceptedIfPresentRule,\n acceptedIfRequiredRule,\n acceptedIfRule,\n acceptedRule,\n acceptedUnlessRule,\n acceptedWithoutRule,\n declinedIfPresentRule,\n declinedIfRequiredRule,\n declinedIfRule,\n declinedRule,\n declinedUnlessRule,\n declinedWithoutRule,\n} from \"../rules/scalar\";\nimport { booleanRule } from \"../rules\";\nimport { PrimitiveValidator } from \"./primitive-validator\";\nimport { applyNullable } from \"../standard-schema/json-schema\";\nimport type { JsonSchemaResult, JsonSchemaTarget } from \"../standard-schema/json-schema\";\n\n/**\n * Boolean validator class\n *\n * Extends PrimitiveValidator — inherits enum/in/oneOf/allowsOnly/forbids/notIn.\n * Defines accepted/declined directly as real methods (not ScalarValidator field copies)\n * so they survive cloning correctly.\n */\nexport class BooleanValidator extends PrimitiveValidator {\n public constructor(errorMessage?: string) {\n super();\n this.addMutableRule(booleanRule, errorMessage);\n }\n\n /**\n * Check if value is a boolean type\n */\n public matchesType(value: any): boolean {\n return typeof value === \"boolean\";\n }\n\n // ==================== Accepted ====================\n\n /** Value must be accepted (true, \"yes\", 1, \"on\", etc.) */\n public accepted(errorMessage?: string) {\n return this.addRule(acceptedRule, errorMessage);\n }\n\n /** Value must be accepted if another field equals a value */\n public acceptedIf(field: string, value: any, errorMessage?: string) {\n return this.addRule(acceptedIfRule, errorMessage, { field, value });\n }\n\n /** Value must be accepted unless another field equals a value */\n public acceptedUnless(field: string, value: any, errorMessage?: string) {\n return this.addRule(acceptedUnlessRule, errorMessage, { field, value });\n }\n\n /** Value must be accepted if another field is required */\n public acceptedIfRequired(field: string, errorMessage?: string) {\n return this.addRule(acceptedIfRequiredRule, errorMessage, { field });\n }\n\n /** Value must be accepted if another field is present */\n public acceptedIfPresent(field: string, errorMessage?: string) {\n return this.addRule(acceptedIfPresentRule, errorMessage, { field });\n }\n\n /** Value must be accepted if another field is missing */\n public acceptedWithout(field: string, errorMessage?: string) {\n return this.addRule(acceptedWithoutRule, errorMessage, { field });\n }\n\n // ==================== Declined ====================\n\n /** Value must be declined (false, \"no\", 0, \"off\", etc.) */\n public declined(errorMessage?: string) {\n return this.addRule(declinedRule, errorMessage);\n }\n\n /** Value must be declined if another field equals a value */\n public declinedIf(field: string, value: any, errorMessage?: string) {\n return this.addRule(declinedIfRule, errorMessage, { field, value });\n }\n\n /** Value must be declined unless another field equals a value */\n public declinedUnless(field: string, value: any, errorMessage?: string) {\n return this.addRule(declinedUnlessRule, errorMessage, { field, value });\n }\n\n /** Value must be declined if another field is required */\n public declinedIfRequired(field: string, errorMessage?: string) {\n return this.addRule(declinedIfRequiredRule, errorMessage, { field });\n }\n\n /** Value must be declined if another field is present */\n public declinedIfPresent(field: string, errorMessage?: string) {\n return this.addRule(declinedIfPresentRule, errorMessage, { field });\n }\n\n /** Value must be declined if another field is missing */\n public declinedWithout(field: string, errorMessage?: string) {\n return this.addRule(declinedWithoutRule, errorMessage, { field });\n }\n\n // ==================== Strict boolean checks ====================\n\n /**\n * Value must be strictly true (not \"yes\", \"on\", 1, etc.)\n * @alias accepted - strict version\n */\n public mustBeTrue(errorMessage?: string) {\n return this.equal(true, errorMessage);\n }\n\n /**\n * Value must be strictly false (not \"no\", \"off\", 0, etc.)\n * @alias declined - strict version\n */\n public mustBeFalse(errorMessage?: string) {\n return this.equal(false, errorMessage);\n }\n\n /**\n * @inheritdoc\n *\n * @note accepted/declined rules and all cross-field boolean rules\n * are not representable in JSON Schema and are silently omitted.\n *\n * @example\n * ```ts\n * v.boolean().toJsonSchema(\"draft-2020-12\")\n * // → { type: \"boolean\" }\n *\n * v.boolean().nullable().toJsonSchema(\"openapi-3.0\")\n * // → { type: \"boolean\", nullable: true }\n * ```\n */\n public override toJsonSchema(target: JsonSchemaTarget = \"draft-2020-12\"): JsonSchemaResult {\n const schema: JsonSchemaResult = { type: \"boolean\" };\n if (this.isNullable) applyNullable(schema, target);\n return schema;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA0BA,IAAa,mBAAb,cAAsC,mBAAmB;CACvD,AAAO,YAAY,cAAuB;EACxC,MAAM;EACN,KAAK,eAAe,aAAa,YAAY;CAC/C;;;;CAKA,AAAO,YAAY,OAAqB;EACtC,OAAO,OAAO,UAAU;CAC1B;;CAKA,AAAO,SAAS,cAAuB;EACrC,OAAO,KAAK,QAAQ,cAAc,YAAY;CAChD;;CAGA,AAAO,WAAW,OAAe,OAAY,cAAuB;EAClE,OAAO,KAAK,QAAQ,gBAAgB,cAAc;GAAE;GAAO;EAAM,CAAC;CACpE;;CAGA,AAAO,eAAe,OAAe,OAAY,cAAuB;EACtE,OAAO,KAAK,QAAQ,oBAAoB,cAAc;GAAE;GAAO;EAAM,CAAC;CACxE;;CAGA,AAAO,mBAAmB,OAAe,cAAuB;EAC9D,OAAO,KAAK,QAAQ,wBAAwB,cAAc,EAAE,MAAM,CAAC;CACrE;;CAGA,AAAO,kBAAkB,OAAe,cAAuB;EAC7D,OAAO,KAAK,QAAQ,uBAAuB,cAAc,EAAE,MAAM,CAAC;CACpE;;CAGA,AAAO,gBAAgB,OAAe,cAAuB;EAC3D,OAAO,KAAK,QAAQ,qBAAqB,cAAc,EAAE,MAAM,CAAC;CAClE;;CAKA,AAAO,SAAS,cAAuB;EACrC,OAAO,KAAK,QAAQ,cAAc,YAAY;CAChD;;CAGA,AAAO,WAAW,OAAe,OAAY,cAAuB;EAClE,OAAO,KAAK,QAAQ,gBAAgB,cAAc;GAAE;GAAO;EAAM,CAAC;CACpE;;CAGA,AAAO,eAAe,OAAe,OAAY,cAAuB;EACtE,OAAO,KAAK,QAAQ,oBAAoB,cAAc;GAAE;GAAO;EAAM,CAAC;CACxE;;CAGA,AAAO,mBAAmB,OAAe,cAAuB;EAC9D,OAAO,KAAK,QAAQ,wBAAwB,cAAc,EAAE,MAAM,CAAC;CACrE;;CAGA,AAAO,kBAAkB,OAAe,cAAuB;EAC7D,OAAO,KAAK,QAAQ,uBAAuB,cAAc,EAAE,MAAM,CAAC;CACpE;;CAGA,AAAO,gBAAgB,OAAe,cAAuB;EAC3D,OAAO,KAAK,QAAQ,qBAAqB,cAAc,EAAE,MAAM,CAAC;CAClE;;;;;CAQA,AAAO,WAAW,cAAuB;EACvC,OAAO,KAAK,MAAM,MAAM,YAAY;CACtC;;;;;CAMA,AAAO,YAAY,cAAuB;EACxC,OAAO,KAAK,MAAM,OAAO,YAAY;CACvC;;;;;;;;;;;;;;;;CAiBA,AAAgB,aAAa,SAA2B,iBAAmC;EACzF,MAAM,SAA2B,EAAE,MAAM,UAAU;EACnD,IAAI,KAAK,YAAY,cAAc,QAAQ,MAAM;EACjD,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"boolean-validator.mjs","names":[],"sources":["../../../../../../../seal/src/validators/boolean-validator.ts"],"sourcesContent":["import { booleanCoerceMutator } from \"../mutators/boolean-mutators\";\nimport {\n acceptedIfPresentRule,\n acceptedIfRequiredRule,\n acceptedIfRule,\n acceptedRule,\n acceptedUnlessRule,\n acceptedWithoutRule,\n declinedIfPresentRule,\n declinedIfRequiredRule,\n declinedIfRule,\n declinedRule,\n declinedUnlessRule,\n declinedWithoutRule,\n} from \"../rules/scalar\";\nimport { booleanRule } from \"../rules\";\nimport { PrimitiveValidator } from \"./primitive-validator\";\nimport { applyNullable } from \"../standard-schema/json-schema\";\nimport type { JsonSchemaResult, JsonSchemaTarget } from \"../standard-schema/json-schema\";\n\n/**\n * Boolean validator class\n *\n * Extends PrimitiveValidator — inherits enum/in/oneOf/allowsOnly/forbids/notIn.\n * Defines accepted/declined directly as real methods (not ScalarValidator field copies)\n * so they survive cloning correctly.\n */\nexport class BooleanValidator extends PrimitiveValidator {\n public constructor(errorMessage?: string) {\n super();\n this.addMutableRule(booleanRule, errorMessage);\n }\n\n /**\n * Check if value is a boolean type\n */\n public matchesType(value: any): boolean {\n return typeof value === \"boolean\";\n }\n\n // ==================== Accepted ====================\n\n /** Value must be accepted (true, \"yes\", 1, \"on\", etc.) */\n public accepted(errorMessage?: string) {\n return this.addRule(acceptedRule, errorMessage);\n }\n\n /** Value must be accepted if another field equals a value */\n public acceptedIf(field: string, value: any, errorMessage?: string) {\n return this.addRule(acceptedIfRule, errorMessage, { field, value });\n }\n\n /** Value must be accepted unless another field equals a value */\n public acceptedUnless(field: string, value: any, errorMessage?: string) {\n return this.addRule(acceptedUnlessRule, errorMessage, { field, value });\n }\n\n /** Value must be accepted if another field is required */\n public acceptedIfRequired(field: string, errorMessage?: string) {\n return this.addRule(acceptedIfRequiredRule, errorMessage, { field });\n }\n\n /** Value must be accepted if another field is present */\n public acceptedIfPresent(field: string, errorMessage?: string) {\n return this.addRule(acceptedIfPresentRule, errorMessage, { field });\n }\n\n /** Value must be accepted if another field is missing */\n public acceptedWithout(field: string, errorMessage?: string) {\n return this.addRule(acceptedWithoutRule, errorMessage, { field });\n }\n\n // ==================== Declined ====================\n\n /** Value must be declined (false, \"no\", 0, \"off\", etc.) */\n public declined(errorMessage?: string) {\n return this.addRule(declinedRule, errorMessage);\n }\n\n /** Value must be declined if another field equals a value */\n public declinedIf(field: string, value: any, errorMessage?: string) {\n return this.addRule(declinedIfRule, errorMessage, { field, value });\n }\n\n /** Value must be declined unless another field equals a value */\n public declinedUnless(field: string, value: any, errorMessage?: string) {\n return this.addRule(declinedUnlessRule, errorMessage, { field, value });\n }\n\n /** Value must be declined if another field is required */\n public declinedIfRequired(field: string, errorMessage?: string) {\n return this.addRule(declinedIfRequiredRule, errorMessage, { field });\n }\n\n /** Value must be declined if another field is present */\n public declinedIfPresent(field: string, errorMessage?: string) {\n return this.addRule(declinedIfPresentRule, errorMessage, { field });\n }\n\n /** Value must be declined if another field is missing */\n public declinedWithout(field: string, errorMessage?: string) {\n return this.addRule(declinedWithoutRule, errorMessage, { field });\n }\n\n // ==================== Coercion ====================\n\n /**\n * Opt in to coercion: an exact query-string-shaped boolean is converted to a\n * real boolean **before** the type rules run; any other value passes through\n * unchanged so bad input still fails the type rule.\n *\n * Converts exactly `\"true\"` / `\"1\"` / `1` → `true` and `\"false\"` / `\"0\"` / `0`\n * → `false`. Case-sensitive, no trimming — `\"TRUE\"`, `\"yes\"`, `\"on\"`, `\"\"`, and\n * `2` all pass through unchanged and fail the type rule. `v.boolean()` does\n * **not** coerce by default; this only takes effect when explicitly chained.\n * For form-style truthy strings like `\"yes\"` / `\"on\"`, use `.accepted()` /\n * `.declined()` instead — those are separate pass/fail rules, not coercion.\n *\n * The output type is unchanged (`Infer<>` keys off the validator class), so\n * `v.boolean().coerce()` still infers `boolean`.\n *\n * @example\n * v.boolean().coerce() // \"true\" → true; \"1\" → true; \"0\" → false; \"yes\" → invalid\n */\n public coerce() {\n return this.addMutator(booleanCoerceMutator) as this & { isCoerced: true };\n }\n\n // ==================== Strict boolean checks ====================\n\n /**\n * Value must be strictly true (not \"yes\", \"on\", 1, etc.)\n * @alias accepted - strict version\n */\n public mustBeTrue(errorMessage?: string) {\n return this.equal(true, errorMessage);\n }\n\n /**\n * Value must be strictly false (not \"no\", \"off\", 0, etc.)\n * @alias declined - strict version\n */\n public mustBeFalse(errorMessage?: string) {\n return this.equal(false, errorMessage);\n }\n\n /**\n * @inheritdoc\n *\n * @note accepted/declined rules and all cross-field boolean rules\n * are not representable in JSON Schema and are silently omitted.\n *\n * @example\n * ```ts\n * v.boolean().toJsonSchema(\"draft-2020-12\")\n * // → { type: \"boolean\" }\n *\n * v.boolean().nullable().toJsonSchema(\"openapi-3.0\")\n * // → { type: \"boolean\", nullable: true }\n * ```\n */\n public override toJsonSchema(target: JsonSchemaTarget = \"draft-2020-12\"): JsonSchemaResult {\n const schema: JsonSchemaResult = { type: \"boolean\" };\n if (this.isNullable) applyNullable(schema, target);\n return schema;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA2BA,IAAa,mBAAb,cAAsC,mBAAmB;CACvD,AAAO,YAAY,cAAuB;EACxC,MAAM;EACN,KAAK,eAAe,aAAa,YAAY;CAC/C;;;;CAKA,AAAO,YAAY,OAAqB;EACtC,OAAO,OAAO,UAAU;CAC1B;;CAKA,AAAO,SAAS,cAAuB;EACrC,OAAO,KAAK,QAAQ,cAAc,YAAY;CAChD;;CAGA,AAAO,WAAW,OAAe,OAAY,cAAuB;EAClE,OAAO,KAAK,QAAQ,gBAAgB,cAAc;GAAE;GAAO;EAAM,CAAC;CACpE;;CAGA,AAAO,eAAe,OAAe,OAAY,cAAuB;EACtE,OAAO,KAAK,QAAQ,oBAAoB,cAAc;GAAE;GAAO;EAAM,CAAC;CACxE;;CAGA,AAAO,mBAAmB,OAAe,cAAuB;EAC9D,OAAO,KAAK,QAAQ,wBAAwB,cAAc,EAAE,MAAM,CAAC;CACrE;;CAGA,AAAO,kBAAkB,OAAe,cAAuB;EAC7D,OAAO,KAAK,QAAQ,uBAAuB,cAAc,EAAE,MAAM,CAAC;CACpE;;CAGA,AAAO,gBAAgB,OAAe,cAAuB;EAC3D,OAAO,KAAK,QAAQ,qBAAqB,cAAc,EAAE,MAAM,CAAC;CAClE;;CAKA,AAAO,SAAS,cAAuB;EACrC,OAAO,KAAK,QAAQ,cAAc,YAAY;CAChD;;CAGA,AAAO,WAAW,OAAe,OAAY,cAAuB;EAClE,OAAO,KAAK,QAAQ,gBAAgB,cAAc;GAAE;GAAO;EAAM,CAAC;CACpE;;CAGA,AAAO,eAAe,OAAe,OAAY,cAAuB;EACtE,OAAO,KAAK,QAAQ,oBAAoB,cAAc;GAAE;GAAO;EAAM,CAAC;CACxE;;CAGA,AAAO,mBAAmB,OAAe,cAAuB;EAC9D,OAAO,KAAK,QAAQ,wBAAwB,cAAc,EAAE,MAAM,CAAC;CACrE;;CAGA,AAAO,kBAAkB,OAAe,cAAuB;EAC7D,OAAO,KAAK,QAAQ,uBAAuB,cAAc,EAAE,MAAM,CAAC;CACpE;;CAGA,AAAO,gBAAgB,OAAe,cAAuB;EAC3D,OAAO,KAAK,QAAQ,qBAAqB,cAAc,EAAE,MAAM,CAAC;CAClE;;;;;;;;;;;;;;;;;;;CAsBA,AAAO,SAAS;EACd,OAAO,KAAK,WAAW,oBAAoB;CAC7C;;;;;CAQA,AAAO,WAAW,cAAuB;EACvC,OAAO,KAAK,MAAM,MAAM,YAAY;CACtC;;;;;CAMA,AAAO,YAAY,cAAuB;EACxC,OAAO,KAAK,MAAM,OAAO,YAAY;CACvC;;;;;;;;;;;;;;;;CAiBA,AAAgB,aAAa,SAA2B,iBAAmC;EACzF,MAAM,SAA2B,EAAE,MAAM,UAAU;EACnD,IAAI,KAAK,YAAY,cAAc,QAAQ,MAAM;EACjD,OAAO;CACT;AACF"}
@@ -149,6 +149,26 @@ declare class NumberValidator extends PrimitiveValidator {
149
149
  * v.number().toFixed(2) // 3.14159 → 3.14
150
150
  */
151
151
  toFixed(decimals?: number): this;
152
+ /**
153
+ * Opt in to coercion: a numeric-shaped string is converted to a number
154
+ * **before** the type rules run; any other value passes through unchanged
155
+ * so bad input still fails the type rule.
156
+ *
157
+ * Strictness is preserved — coercion only fixes the string *representation*,
158
+ * not the value's shape. `v.int().coerce()` turns `"5"` into `5` (valid) but
159
+ * `"5.5"` into `5.5`, which still fails the integer rule. Number validators
160
+ * do **not** coerce by default; this only takes effect when explicitly chained.
161
+ *
162
+ * The output type is unchanged (`Infer<>` keys off the validator class), so
163
+ * `v.int().coerce()` still infers `number`.
164
+ *
165
+ * @example
166
+ * v.int().coerce() // "5" → 5 (valid); "5.5" → 5.5 (invalid); "abc" → invalid
167
+ * v.number().coerce() // "5.5" → 5.5 (valid)
168
+ */
169
+ coerce(): this & {
170
+ isCoerced: true;
171
+ };
152
172
  /**
153
173
  * @inheritdoc
154
174
  *
@@ -1 +1 @@
1
- {"version":3,"file":"number-validator.d.mts","names":[],"sources":["../../../../../../../seal/src/validators/number-validator.ts"],"mappings":";;;;;;AAwBA;cAAa,eAAA,SAAwB,kBAAA;cAChB,YAAA;EAuRkB;;;EA/Q9B,WAAA,CAAY,KAAA;EATgB;;;;;;EAmB5B,GAAA,CAAI,GAAA,mBAAsB,YAAA;EAVd;;;;;;EAoBZ,GAAA,CAAI,GAAA,mBAAsB,YAAA;EAQ1B;;;;EAAA,UAAA,CAAW,KAAA,UAAe,YAAA;EAQA;;;;EAA1B,UAAA,CAAW,KAAA,UAAe,YAAA;EAuBjB;;;;;;EAbT,WAAA,CAAY,KAAA,mBAAwB,YAAA;EAgCT;;;;;;EAnB3B,QAAA,CAAS,KAAA,mBAAwB,YAAA;EA8CjC;;;;EAnCA,EAAA,CAAG,KAAA,mBAAwB,YAAA;EA8CF;;;;EAtCzB,EAAA,CAAG,KAAA,mBAAwB,YAAA;EAkDf;;;;EA1CZ,kBAAA,CAAmB,KAAA,UAAe,YAAA;EAwDlC;;;;EA7CA,SAAA,CAAU,KAAA,UAAe,YAAA;EAuDzB;;;;EA/CA,eAAA,CAAgB,KAAA,UAAe,YAAA;EAyD1B;;;;EA9CL,SAAA,CAAU,KAAA,UAAe,YAAA;EAoEzB;EA/DA,MAAA,CAAO,KAAA,UAAe,YAAA;EA+DW;;;EAxDjC,WAAA,CAAY,KAAA,UAAe,YAAA;EAsEJ;;;EA/DvB,UAAA,CAAW,KAAA,UAAe,YAAA;EAyE1B;;;EAlEA,SAAA,CAAU,KAAA,UAAe,YAAA;EAkFzB;EA7EA,QAAA,CAAS,YAAA;EA2FT;EAtFA,QAAA,CAAS,YAAA;EAoGT;EA/FA,GAAA,CAAI,YAAA;EAkHK;EA7GT,IAAA,CAAK,YAAA;EA6GiB;;;;;;EAnGtB,OAAA,CAAQ,GAAA,mBAAsB,GAAA,mBAAsB,YAAA;EA+GxC;AAAA;;;EAnGZ,cAAA,CAAe,QAAA,UAAkB,QAAA,UAAkB,YAAA;;;;;EAcnD,MAAA,CAAO,MAAA,UAAgB,YAAA;;EAKvB,SAAA,CAAU,MAAA,UAAgB,YAAA;;EAK1B,SAAA,CAAU,MAAA,UAAgB,YAAA;;;;EAS1B,GAAA;;;;EAOA,IAAA;;;;EAOA,KAAA;;;;EAOA,KAAA,CAAM,QAAA;;;;;;;;;;;EAcN,OAAA,CAAQ,QAAA;;;;;;;;;;;;;;;;EAmBC,YAAA,CAAa,MAAA,GAAQ,gBAAA,GAAqC,gBAAA;;;;;;YAShE,qBAAA,CACR,IAAA,wBACA,MAAA,EAAQ,gBAAA,GACP,gBAAA;AAAA"}
1
+ {"version":3,"file":"number-validator.d.mts","names":[],"sources":["../../../../../../../seal/src/validators/number-validator.ts"],"mappings":";;;;;;AA+BA;cAAa,eAAA,SAAwB,kBAAA;cAChB,YAAA;EA4SkB;;;EApS9B,WAAA,CAAY,KAAA;EATgB;;;;;;EAmB5B,GAAA,CAAI,GAAA,mBAAsB,YAAA;EAVd;;;;;;EAoBZ,GAAA,CAAI,GAAA,mBAAsB,YAAA;EAQ1B;;;;EAAA,UAAA,CAAW,KAAA,UAAe,YAAA;EAQA;;;;EAA1B,UAAA,CAAW,KAAA,UAAe,YAAA;EAuBjB;;;;;;EAbT,WAAA,CAAY,KAAA,mBAAwB,YAAA;EAgCT;;;;;;EAnB3B,QAAA,CAAS,KAAA,mBAAwB,YAAA;EA8CjC;;;;EAnCA,EAAA,CAAG,KAAA,mBAAwB,YAAA;EA8CF;;;;EAtCzB,EAAA,CAAG,KAAA,mBAAwB,YAAA;EAkDf;;;;EA1CZ,kBAAA,CAAmB,KAAA,UAAe,YAAA;EAwDlC;;;;EA7CA,SAAA,CAAU,KAAA,UAAe,YAAA;EAuDzB;;;;EA/CA,eAAA,CAAgB,KAAA,UAAe,YAAA;EAyD1B;;;;EA9CL,SAAA,CAAU,KAAA,UAAe,YAAA;EAoEzB;EA/DA,MAAA,CAAO,KAAA,UAAe,YAAA;EA+DW;;;EAxDjC,WAAA,CAAY,KAAA,UAAe,YAAA;EAsEJ;;;EA/DvB,UAAA,CAAW,KAAA,UAAe,YAAA;EAyE1B;;;EAlEA,SAAA,CAAU,KAAA,UAAe,YAAA;EAkFzB;EA7EA,QAAA,CAAS,YAAA;EA2FT;EAtFA,QAAA,CAAS,YAAA;EAoGT;EA/FA,GAAA,CAAI,YAAA;EAoHJ;EA/GA,IAAA,CAAK,YAAA;EAkII;;;;;;EAxHT,OAAA,CAAQ,GAAA,mBAAsB,GAAA,mBAAsB,YAAA;EAmIzD;;;AACiB;EAxHZ,cAAA,CAAe,QAAA,UAAkB,QAAA,UAAkB,YAAA;;;;;EAcnD,MAAA,CAAO,MAAA,UAAgB,YAAA;;EAKvB,SAAA,CAAU,MAAA,UAAgB,YAAA;;EAK1B,SAAA,CAAU,MAAA,UAAgB,YAAA;;;;EAS1B,GAAA;;;;EAOA,IAAA;;;;EAOA,KAAA;;;;EAOA,KAAA,CAAM,QAAA;;;;;;;;;;;EAcN,OAAA,CAAQ,QAAA;;;;;;;;;;;;;;;;;;EAqBR,MAAA;IAC8C,SAAA;EAAA;;;;;;;;;;;;;;;;EAkBrC,YAAA,CAAa,MAAA,GAAQ,gBAAA,GAAqC,gBAAA;;;;;;YAShE,qBAAA,CACR,IAAA,wBACA,MAAA,EAAQ,gBAAA,GACP,gBAAA;AAAA"}
@@ -1,5 +1,5 @@
1
1
  import { applyNullable, getRuleOptions } from "../standard-schema/json-schema.mjs";
2
- import { absMutator, ceilMutator, floorMutator, roundMutator, toFixedMutator } from "../mutators/number-mutators.mjs";
2
+ import { absMutator, ceilMutator, floorMutator, numericMutator, roundMutator, toFixedMutator } from "../mutators/number-mutators.mjs";
3
3
  import "../mutators/index.mjs";
4
4
  import { betweenNumbersRule, evenRule, greaterThanRule, lessThanRule, maxRule, minRule, moduloRule, negativeRule, oddRule, positiveRule } from "../rules/number/number-rules.mjs";
5
5
  import { lengthRule, maxLengthRule, minLengthRule } from "../rules/length/length-rules.mjs";
@@ -253,6 +253,26 @@ var NumberValidator = class extends PrimitiveValidator {
253
253
  return this.addMutator(toFixedMutator, { decimals });
254
254
  }
255
255
  /**
256
+ * Opt in to coercion: a numeric-shaped string is converted to a number
257
+ * **before** the type rules run; any other value passes through unchanged
258
+ * so bad input still fails the type rule.
259
+ *
260
+ * Strictness is preserved — coercion only fixes the string *representation*,
261
+ * not the value's shape. `v.int().coerce()` turns `"5"` into `5` (valid) but
262
+ * `"5.5"` into `5.5`, which still fails the integer rule. Number validators
263
+ * do **not** coerce by default; this only takes effect when explicitly chained.
264
+ *
265
+ * The output type is unchanged (`Infer<>` keys off the validator class), so
266
+ * `v.int().coerce()` still infers `number`.
267
+ *
268
+ * @example
269
+ * v.int().coerce() // "5" → 5 (valid); "5.5" → 5.5 (invalid); "abc" → invalid
270
+ * v.number().coerce() // "5.5" → 5.5 (valid)
271
+ */
272
+ coerce() {
273
+ return this.addMutator(numericMutator);
274
+ }
275
+ /**
256
276
  * @inheritdoc
257
277
  *
258
278
  * Returns `{ type: "number" }` with numeric constraint keywords.
@@ -1 +1 @@
1
- {"version":3,"file":"number-validator.mjs","names":[],"sources":["../../../../../../../seal/src/validators/number-validator.ts"],"sourcesContent":["import { absMutator, ceilMutator, floorMutator, roundMutator, toFixedMutator } from \"../mutators\";\r\nimport {\r\n betweenNumbersRule,\r\n evenRule,\r\n greaterThanRule,\r\n lengthRule,\r\n lessThanRule,\r\n maxLengthRule,\r\n maxRule,\r\n minLengthRule,\r\n minRule,\r\n moduloRule,\r\n negativeRule,\r\n numberRule,\r\n oddRule,\r\n positiveRule,\r\n} from \"../rules\";\r\nimport { PrimitiveValidator } from \"./primitive-validator\";\r\nimport { applyNullable, getRuleOptions } from \"../standard-schema/json-schema\";\r\nimport type { JsonSchemaResult, JsonSchemaTarget } from \"../standard-schema/json-schema\";\r\n\r\n/**\r\n * Number validator class - base for Int and Float validators\r\n */\r\nexport class NumberValidator extends PrimitiveValidator {\r\n public constructor(errorMessage?: string) {\r\n super();\r\n this.addMutableRule(numberRule, errorMessage);\r\n }\r\n\r\n /**\r\n * Check if value is a number type\r\n */\r\n public matchesType(value: any): boolean {\r\n return typeof value === \"number\" && !isNaN(value);\r\n }\r\n\r\n /**\r\n * Value must be equal or higher than the given number or field\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public min(min: number | string, errorMessage?: string) {\r\n return this.addRule(minRule, errorMessage, { min, scope: \"global\" });\r\n }\r\n\r\n /**\r\n * Value must be equal or less than the given number or field\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public max(max: number | string, errorMessage?: string) {\r\n return this.addRule(maxRule, errorMessage, { max, scope: \"global\" });\r\n }\r\n\r\n /**\r\n * Value must be >= sibling field value\r\n * @category Validation Rule\r\n */\r\n public minSibling(field: string, errorMessage?: string) {\r\n return this.addRule(minRule, errorMessage, { min: field, scope: \"sibling\" });\r\n }\r\n\r\n /**\r\n * Value must be <= sibling field value\r\n * @category Validation Rule\r\n */\r\n public maxSibling(field: string, errorMessage?: string) {\r\n return this.addRule(maxRule, errorMessage, { max: field, scope: \"sibling\" });\r\n }\r\n\r\n /**\r\n * Value must be strictly greater than the given number or field (>)\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public greaterThan(value: number | string, errorMessage?: string) {\r\n return this.addRule(greaterThanRule, errorMessage, {\r\n value,\r\n scope: \"global\",\r\n });\r\n }\r\n\r\n /**\r\n * Value must be strictly less than the given number or field (<)\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public lessThan(value: number | string, errorMessage?: string) {\r\n return this.addRule(lessThanRule, errorMessage, {\r\n value,\r\n scope: \"global\",\r\n });\r\n }\r\n\r\n /**\r\n * Alias for greaterThan() - shorter syntax\r\n * @category Validation Rule\r\n */\r\n public gt(value: number | string, errorMessage?: string) {\r\n return this.greaterThan(value, errorMessage);\r\n }\r\n\r\n /**\r\n * Alias for lessThan() - shorter syntax\r\n * @category Validation Rule\r\n */\r\n public lt(value: number | string, errorMessage?: string) {\r\n return this.lessThan(value, errorMessage);\r\n }\r\n\r\n /**\r\n * Value must be > sibling field value\r\n * @category Validation Rule\r\n */\r\n public greaterThanSibling(field: string, errorMessage?: string) {\r\n return this.addRule(greaterThanRule, errorMessage, {\r\n value: field,\r\n scope: \"sibling\",\r\n });\r\n }\r\n\r\n /**\r\n * Alias for greaterThanSibling() - shorter syntax\r\n * @category Validation Rule\r\n */\r\n public gtSibling(field: string, errorMessage?: string) {\r\n return this.greaterThanSibling(field, errorMessage);\r\n }\r\n\r\n /**\r\n * Value must be < sibling field value\r\n * @category Validation Rule\r\n */\r\n public lessThanSibling(field: string, errorMessage?: string) {\r\n return this.addRule(lessThanRule, errorMessage, {\r\n value: field,\r\n scope: \"sibling\",\r\n });\r\n }\r\n\r\n /**\r\n * Alias for lessThanSibling() - shorter syntax\r\n * @category Validation Rule\r\n */\r\n public ltSibling(field: string, errorMessage?: string) {\r\n return this.lessThanSibling(field, errorMessage);\r\n }\r\n\r\n /** Value must be a modulo of the given number */\r\n public modulo(value: number, errorMessage?: string) {\r\n return this.addRule(moduloRule, errorMessage, { value });\r\n }\r\n\r\n /**\r\n * Alias for modulo() - Value must be divisible by the given number\r\n */\r\n public divisibleBy(value: number, errorMessage?: string) {\r\n return this.modulo(value, errorMessage);\r\n }\r\n\r\n /**\r\n * Alias for modulo() - Value must be a multiple of the given number\r\n */\r\n public multipleOf(value: number, errorMessage?: string) {\r\n return this.modulo(value, errorMessage);\r\n }\r\n\r\n /**\r\n * Alias for modulo() - Value must be a multiple of the given number\r\n */\r\n public modulusOf(value: number, errorMessage?: string) {\r\n return this.modulo(value, errorMessage);\r\n }\r\n\r\n /** Accept only numbers higher than 0 */\r\n public positive(errorMessage?: string) {\r\n return this.addRule(positiveRule, errorMessage);\r\n }\r\n\r\n /** Accept only negative numbers */\r\n public negative(errorMessage?: string) {\r\n return this.addRule(negativeRule, errorMessage);\r\n }\r\n\r\n /** Accept only odd numbers */\r\n public odd(errorMessage?: string) {\r\n return this.addRule(oddRule, errorMessage);\r\n }\r\n\r\n /** Accept only even numbers */\r\n public even(errorMessage?: string) {\r\n return this.addRule(evenRule, errorMessage);\r\n }\r\n\r\n /**\r\n * Accept only numbers between the given two numbers or fields (Inclusive)\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public between(min: number | string, max: number | string, errorMessage?: string) {\r\n return this.addRule(betweenNumbersRule, errorMessage, {\r\n min,\r\n max,\r\n scope: \"global\",\r\n });\r\n }\r\n\r\n /**\r\n * Value must be between sibling field values\r\n * @category Validation Rule\r\n */\r\n public betweenSibling(minField: string, maxField: string, errorMessage?: string) {\r\n return this.addRule(betweenNumbersRule, errorMessage, {\r\n min: minField,\r\n max: maxField,\r\n scope: \"sibling\",\r\n });\r\n }\r\n\r\n // Enum and value membership methods are inherited from PrimitiveValidator.\r\n\r\n /**\r\n * Value (as a string) must be exactly this many characters.\r\n * Useful for fixed-format numeric codes (e.g. 4-digit PIN).\r\n */\r\n public length(length: number, errorMessage?: string) {\r\n return this.addRule(lengthRule, errorMessage, { length });\r\n }\r\n\r\n /** Value (as string representation) length must be ≥ min */\r\n public minLength(length: number, errorMessage?: string) {\r\n return this.addRule(minLengthRule, errorMessage, { minLength: length });\r\n }\r\n\r\n /** Value (as string representation) length must be ≤ max */\r\n public maxLength(length: number, errorMessage?: string) {\r\n return this.addRule(maxLengthRule, errorMessage, { maxLength: length });\r\n }\r\n\r\n // Mutators\r\n\r\n /**\r\n * Convert value to its absolute value\r\n */\r\n public abs() {\r\n return this.addMutator(absMutator);\r\n }\r\n\r\n /**\r\n * Round value up to the nearest integer\r\n */\r\n public ceil() {\r\n return this.addMutator(ceilMutator);\r\n }\r\n\r\n /**\r\n * Round value down to the nearest integer\r\n */\r\n public floor() {\r\n return this.addMutator(floorMutator);\r\n }\r\n\r\n /**\r\n * Round value to the nearest integer or specified decimals\r\n */\r\n public round(decimals = 0) {\r\n return this.addMutator(roundMutator, { decimals });\r\n }\r\n\r\n /**\r\n * Round to a fixed number of decimal places, keeping the value a **number**.\r\n *\r\n * `v.number().toFixed(2)` on `3.14159` yields `3.14`, not `\"3.14\"` — a number\r\n * schema has to output a number, or its own type rule rejects the result.\r\n * Format to a fixed-point *string* at the presentation edge instead.\r\n *\r\n * @example\r\n * v.number().toFixed(2) // 3.14159 → 3.14\r\n */\r\n public toFixed(decimals = 2) {\r\n return this.addMutator(toFixedMutator, { decimals });\r\n }\r\n\r\n /**\r\n * @inheritdoc\r\n *\r\n * Returns `{ type: \"number\" }` with numeric constraint keywords.\r\n * IntValidator overrides `type` to `\"integer\"`.\r\n *\r\n * @note Sibling-scoped rules (minSibling, maxSibling, etc.) are not representable\r\n * in JSON Schema and are silently omitted.\r\n *\r\n * @example\r\n * ```ts\r\n * v.number().min(0).max(100).toJsonSchema(\"draft-2020-12\")\r\n * // → { type: \"number\", minimum: 0, maximum: 100 }\r\n * ```\r\n */\r\n public override toJsonSchema(target: JsonSchemaTarget = \"draft-2020-12\"): JsonSchemaResult {\r\n return this.buildNumberJsonSchema(\"number\", target);\r\n }\r\n\r\n /**\r\n * Shared logic for number/integer JSON Schema generation.\r\n * Called by NumberValidator.toJsonSchema() (→ type: \"number\")\r\n * and IntValidator.toJsonSchema() (→ type: \"integer\").\r\n */\r\n protected buildNumberJsonSchema(\r\n type: \"number\" | \"integer\",\r\n target: JsonSchemaTarget,\r\n ): JsonSchemaResult {\r\n const schema: JsonSchemaResult = { type };\r\n\r\n // minimum (inclusive)\r\n const minOpts = getRuleOptions(this.rules, \"min\");\r\n if (minOpts?.min !== undefined && typeof minOpts.min === \"number\") {\r\n schema.minimum = minOpts.min;\r\n }\r\n\r\n // maximum (inclusive)\r\n const maxOpts = getRuleOptions(this.rules, \"max\");\r\n if (maxOpts?.max !== undefined && typeof maxOpts.max === \"number\") {\r\n schema.maximum = maxOpts.max;\r\n }\r\n\r\n // between (inclusive range)\r\n const betweenOpts = getRuleOptions(this.rules, \"betweenNumbers\");\r\n if (betweenOpts) {\r\n if (typeof betweenOpts.min === \"number\") schema.minimum = betweenOpts.min;\r\n if (typeof betweenOpts.max === \"number\") schema.maximum = betweenOpts.max;\r\n }\r\n\r\n // greaterThan (>) → exclusiveMinimum\r\n const gtOpts = getRuleOptions(this.rules, \"greaterThan\");\r\n if (gtOpts?.value !== undefined && typeof gtOpts.value === \"number\") {\r\n if (target === \"draft-07\") {\r\n schema.minimum = gtOpts.value;\r\n schema.exclusiveMinimum = true;\r\n } else {\r\n schema.exclusiveMinimum = gtOpts.value;\r\n }\r\n }\r\n\r\n // lessThan (<) → exclusiveMaximum\r\n const ltOpts = getRuleOptions(this.rules, \"lessThan\");\r\n if (ltOpts?.value !== undefined && typeof ltOpts.value === \"number\") {\r\n if (target === \"draft-07\") {\r\n schema.maximum = ltOpts.value;\r\n schema.exclusiveMaximum = true;\r\n } else {\r\n schema.exclusiveMaximum = ltOpts.value;\r\n }\r\n }\r\n\r\n // multipleOf / modulo\r\n const moduloOpts = getRuleOptions(this.rules, \"modulo\");\r\n if (moduloOpts?.value !== undefined && typeof moduloOpts.value === \"number\") {\r\n schema.multipleOf = moduloOpts.value;\r\n }\r\n\r\n // enum (from PrimitiveValidator.in / .enum)\r\n const inOpts = getRuleOptions(this.rules, \"in\");\r\n if (inOpts?.values && Array.isArray(inOpts.values)) {\r\n schema.enum = inOpts.values;\r\n }\r\n\r\n if (this.isNullable) applyNullable(schema, target);\r\n\r\n return schema;\r\n }\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"number-validator.mjs","names":[],"sources":["../../../../../../../seal/src/validators/number-validator.ts"],"sourcesContent":["import {\r\n absMutator,\r\n ceilMutator,\r\n floorMutator,\r\n numericMutator,\r\n roundMutator,\r\n toFixedMutator,\r\n} from \"../mutators\";\r\nimport {\r\n betweenNumbersRule,\r\n evenRule,\r\n greaterThanRule,\r\n lengthRule,\r\n lessThanRule,\r\n maxLengthRule,\r\n maxRule,\r\n minLengthRule,\r\n minRule,\r\n moduloRule,\r\n negativeRule,\r\n numberRule,\r\n oddRule,\r\n positiveRule,\r\n} from \"../rules\";\r\nimport { PrimitiveValidator } from \"./primitive-validator\";\r\nimport { applyNullable, getRuleOptions } from \"../standard-schema/json-schema\";\r\nimport type { JsonSchemaResult, JsonSchemaTarget } from \"../standard-schema/json-schema\";\r\n\r\n/**\r\n * Number validator class - base for Int and Float validators\r\n */\r\nexport class NumberValidator extends PrimitiveValidator {\r\n public constructor(errorMessage?: string) {\r\n super();\r\n this.addMutableRule(numberRule, errorMessage);\r\n }\r\n\r\n /**\r\n * Check if value is a number type\r\n */\r\n public matchesType(value: any): boolean {\r\n return typeof value === \"number\" && !isNaN(value);\r\n }\r\n\r\n /**\r\n * Value must be equal or higher than the given number or field\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public min(min: number | string, errorMessage?: string) {\r\n return this.addRule(minRule, errorMessage, { min, scope: \"global\" });\r\n }\r\n\r\n /**\r\n * Value must be equal or less than the given number or field\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public max(max: number | string, errorMessage?: string) {\r\n return this.addRule(maxRule, errorMessage, { max, scope: \"global\" });\r\n }\r\n\r\n /**\r\n * Value must be >= sibling field value\r\n * @category Validation Rule\r\n */\r\n public minSibling(field: string, errorMessage?: string) {\r\n return this.addRule(minRule, errorMessage, { min: field, scope: \"sibling\" });\r\n }\r\n\r\n /**\r\n * Value must be <= sibling field value\r\n * @category Validation Rule\r\n */\r\n public maxSibling(field: string, errorMessage?: string) {\r\n return this.addRule(maxRule, errorMessage, { max: field, scope: \"sibling\" });\r\n }\r\n\r\n /**\r\n * Value must be strictly greater than the given number or field (>)\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public greaterThan(value: number | string, errorMessage?: string) {\r\n return this.addRule(greaterThanRule, errorMessage, {\r\n value,\r\n scope: \"global\",\r\n });\r\n }\r\n\r\n /**\r\n * Value must be strictly less than the given number or field (<)\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public lessThan(value: number | string, errorMessage?: string) {\r\n return this.addRule(lessThanRule, errorMessage, {\r\n value,\r\n scope: \"global\",\r\n });\r\n }\r\n\r\n /**\r\n * Alias for greaterThan() - shorter syntax\r\n * @category Validation Rule\r\n */\r\n public gt(value: number | string, errorMessage?: string) {\r\n return this.greaterThan(value, errorMessage);\r\n }\r\n\r\n /**\r\n * Alias for lessThan() - shorter syntax\r\n * @category Validation Rule\r\n */\r\n public lt(value: number | string, errorMessage?: string) {\r\n return this.lessThan(value, errorMessage);\r\n }\r\n\r\n /**\r\n * Value must be > sibling field value\r\n * @category Validation Rule\r\n */\r\n public greaterThanSibling(field: string, errorMessage?: string) {\r\n return this.addRule(greaterThanRule, errorMessage, {\r\n value: field,\r\n scope: \"sibling\",\r\n });\r\n }\r\n\r\n /**\r\n * Alias for greaterThanSibling() - shorter syntax\r\n * @category Validation Rule\r\n */\r\n public gtSibling(field: string, errorMessage?: string) {\r\n return this.greaterThanSibling(field, errorMessage);\r\n }\r\n\r\n /**\r\n * Value must be < sibling field value\r\n * @category Validation Rule\r\n */\r\n public lessThanSibling(field: string, errorMessage?: string) {\r\n return this.addRule(lessThanRule, errorMessage, {\r\n value: field,\r\n scope: \"sibling\",\r\n });\r\n }\r\n\r\n /**\r\n * Alias for lessThanSibling() - shorter syntax\r\n * @category Validation Rule\r\n */\r\n public ltSibling(field: string, errorMessage?: string) {\r\n return this.lessThanSibling(field, errorMessage);\r\n }\r\n\r\n /** Value must be a modulo of the given number */\r\n public modulo(value: number, errorMessage?: string) {\r\n return this.addRule(moduloRule, errorMessage, { value });\r\n }\r\n\r\n /**\r\n * Alias for modulo() - Value must be divisible by the given number\r\n */\r\n public divisibleBy(value: number, errorMessage?: string) {\r\n return this.modulo(value, errorMessage);\r\n }\r\n\r\n /**\r\n * Alias for modulo() - Value must be a multiple of the given number\r\n */\r\n public multipleOf(value: number, errorMessage?: string) {\r\n return this.modulo(value, errorMessage);\r\n }\r\n\r\n /**\r\n * Alias for modulo() - Value must be a multiple of the given number\r\n */\r\n public modulusOf(value: number, errorMessage?: string) {\r\n return this.modulo(value, errorMessage);\r\n }\r\n\r\n /** Accept only numbers higher than 0 */\r\n public positive(errorMessage?: string) {\r\n return this.addRule(positiveRule, errorMessage);\r\n }\r\n\r\n /** Accept only negative numbers */\r\n public negative(errorMessage?: string) {\r\n return this.addRule(negativeRule, errorMessage);\r\n }\r\n\r\n /** Accept only odd numbers */\r\n public odd(errorMessage?: string) {\r\n return this.addRule(oddRule, errorMessage);\r\n }\r\n\r\n /** Accept only even numbers */\r\n public even(errorMessage?: string) {\r\n return this.addRule(evenRule, errorMessage);\r\n }\r\n\r\n /**\r\n * Accept only numbers between the given two numbers or fields (Inclusive)\r\n * Smart detection: number or field name\r\n *\r\n * @category Validation Rule\r\n */\r\n public between(min: number | string, max: number | string, errorMessage?: string) {\r\n return this.addRule(betweenNumbersRule, errorMessage, {\r\n min,\r\n max,\r\n scope: \"global\",\r\n });\r\n }\r\n\r\n /**\r\n * Value must be between sibling field values\r\n * @category Validation Rule\r\n */\r\n public betweenSibling(minField: string, maxField: string, errorMessage?: string) {\r\n return this.addRule(betweenNumbersRule, errorMessage, {\r\n min: minField,\r\n max: maxField,\r\n scope: \"sibling\",\r\n });\r\n }\r\n\r\n // Enum and value membership methods are inherited from PrimitiveValidator.\r\n\r\n /**\r\n * Value (as a string) must be exactly this many characters.\r\n * Useful for fixed-format numeric codes (e.g. 4-digit PIN).\r\n */\r\n public length(length: number, errorMessage?: string) {\r\n return this.addRule(lengthRule, errorMessage, { length });\r\n }\r\n\r\n /** Value (as string representation) length must be ≥ min */\r\n public minLength(length: number, errorMessage?: string) {\r\n return this.addRule(minLengthRule, errorMessage, { minLength: length });\r\n }\r\n\r\n /** Value (as string representation) length must be ≤ max */\r\n public maxLength(length: number, errorMessage?: string) {\r\n return this.addRule(maxLengthRule, errorMessage, { maxLength: length });\r\n }\r\n\r\n // Mutators\r\n\r\n /**\r\n * Convert value to its absolute value\r\n */\r\n public abs() {\r\n return this.addMutator(absMutator);\r\n }\r\n\r\n /**\r\n * Round value up to the nearest integer\r\n */\r\n public ceil() {\r\n return this.addMutator(ceilMutator);\r\n }\r\n\r\n /**\r\n * Round value down to the nearest integer\r\n */\r\n public floor() {\r\n return this.addMutator(floorMutator);\r\n }\r\n\r\n /**\r\n * Round value to the nearest integer or specified decimals\r\n */\r\n public round(decimals = 0) {\r\n return this.addMutator(roundMutator, { decimals });\r\n }\r\n\r\n /**\r\n * Round to a fixed number of decimal places, keeping the value a **number**.\r\n *\r\n * `v.number().toFixed(2)` on `3.14159` yields `3.14`, not `\"3.14\"` — a number\r\n * schema has to output a number, or its own type rule rejects the result.\r\n * Format to a fixed-point *string* at the presentation edge instead.\r\n *\r\n * @example\r\n * v.number().toFixed(2) // 3.14159 → 3.14\r\n */\r\n public toFixed(decimals = 2) {\r\n return this.addMutator(toFixedMutator, { decimals });\r\n }\r\n\r\n /**\r\n * Opt in to coercion: a numeric-shaped string is converted to a number\r\n * **before** the type rules run; any other value passes through unchanged\r\n * so bad input still fails the type rule.\r\n *\r\n * Strictness is preserved — coercion only fixes the string *representation*,\r\n * not the value's shape. `v.int().coerce()` turns `\"5\"` into `5` (valid) but\r\n * `\"5.5\"` into `5.5`, which still fails the integer rule. Number validators\r\n * do **not** coerce by default; this only takes effect when explicitly chained.\r\n *\r\n * The output type is unchanged (`Infer<>` keys off the validator class), so\r\n * `v.int().coerce()` still infers `number`.\r\n *\r\n * @example\r\n * v.int().coerce() // \"5\" → 5 (valid); \"5.5\" → 5.5 (invalid); \"abc\" → invalid\r\n * v.number().coerce() // \"5.5\" → 5.5 (valid)\r\n */\r\n public coerce() {\r\n return this.addMutator(numericMutator) as this & { isCoerced: true };\r\n }\r\n\r\n /**\r\n * @inheritdoc\r\n *\r\n * Returns `{ type: \"number\" }` with numeric constraint keywords.\r\n * IntValidator overrides `type` to `\"integer\"`.\r\n *\r\n * @note Sibling-scoped rules (minSibling, maxSibling, etc.) are not representable\r\n * in JSON Schema and are silently omitted.\r\n *\r\n * @example\r\n * ```ts\r\n * v.number().min(0).max(100).toJsonSchema(\"draft-2020-12\")\r\n * // → { type: \"number\", minimum: 0, maximum: 100 }\r\n * ```\r\n */\r\n public override toJsonSchema(target: JsonSchemaTarget = \"draft-2020-12\"): JsonSchemaResult {\r\n return this.buildNumberJsonSchema(\"number\", target);\r\n }\r\n\r\n /**\r\n * Shared logic for number/integer JSON Schema generation.\r\n * Called by NumberValidator.toJsonSchema() (→ type: \"number\")\r\n * and IntValidator.toJsonSchema() (→ type: \"integer\").\r\n */\r\n protected buildNumberJsonSchema(\r\n type: \"number\" | \"integer\",\r\n target: JsonSchemaTarget,\r\n ): JsonSchemaResult {\r\n const schema: JsonSchemaResult = { type };\r\n\r\n // minimum (inclusive)\r\n const minOpts = getRuleOptions(this.rules, \"min\");\r\n if (minOpts?.min !== undefined && typeof minOpts.min === \"number\") {\r\n schema.minimum = minOpts.min;\r\n }\r\n\r\n // maximum (inclusive)\r\n const maxOpts = getRuleOptions(this.rules, \"max\");\r\n if (maxOpts?.max !== undefined && typeof maxOpts.max === \"number\") {\r\n schema.maximum = maxOpts.max;\r\n }\r\n\r\n // between (inclusive range)\r\n const betweenOpts = getRuleOptions(this.rules, \"betweenNumbers\");\r\n if (betweenOpts) {\r\n if (typeof betweenOpts.min === \"number\") schema.minimum = betweenOpts.min;\r\n if (typeof betweenOpts.max === \"number\") schema.maximum = betweenOpts.max;\r\n }\r\n\r\n // greaterThan (>) → exclusiveMinimum\r\n const gtOpts = getRuleOptions(this.rules, \"greaterThan\");\r\n if (gtOpts?.value !== undefined && typeof gtOpts.value === \"number\") {\r\n if (target === \"draft-07\") {\r\n schema.minimum = gtOpts.value;\r\n schema.exclusiveMinimum = true;\r\n } else {\r\n schema.exclusiveMinimum = gtOpts.value;\r\n }\r\n }\r\n\r\n // lessThan (<) → exclusiveMaximum\r\n const ltOpts = getRuleOptions(this.rules, \"lessThan\");\r\n if (ltOpts?.value !== undefined && typeof ltOpts.value === \"number\") {\r\n if (target === \"draft-07\") {\r\n schema.maximum = ltOpts.value;\r\n schema.exclusiveMaximum = true;\r\n } else {\r\n schema.exclusiveMaximum = ltOpts.value;\r\n }\r\n }\r\n\r\n // multipleOf / modulo\r\n const moduloOpts = getRuleOptions(this.rules, \"modulo\");\r\n if (moduloOpts?.value !== undefined && typeof moduloOpts.value === \"number\") {\r\n schema.multipleOf = moduloOpts.value;\r\n }\r\n\r\n // enum (from PrimitiveValidator.in / .enum)\r\n const inOpts = getRuleOptions(this.rules, \"in\");\r\n if (inOpts?.values && Array.isArray(inOpts.values)) {\r\n schema.enum = inOpts.values;\r\n }\r\n\r\n if (this.isNullable) applyNullable(schema, target);\r\n\r\n return schema;\r\n }\r\n}\r\n"],"mappings":"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"}
package/llms-full.txt CHANGED
@@ -1569,6 +1569,24 @@ The "accepted" rules treat `true`, `"yes"`, `"on"`, `1`, `"1"`, `"true"` as acce
1569
1569
  | `.accepted(msg?)` | value must be accepted |
1570
1570
  | `.declined(msg?)` | value must be declined |
1571
1571
 
1572
+ ## Query-string coercion — `.coerce()`
1573
+
1574
+ `.coerce()` (5.10+) is the opt-in for query-string flags: `?active=true` arrives as the
1575
+ string `"true"`, and bare `v.boolean()` is strict by default — it rejects that string. Add
1576
+ `.coerce()` when a schema validates `request.query`:
1577
+
1578
+ ```ts
1579
+ v.object({ active: v.boolean().coerce() }) // "true" → true, passes
1580
+ ```
1581
+
1582
+ It converts *exactly* `"true"` / `"1"` / `1` → `true` and `"false"` / `"0"` / `0` → `false`.
1583
+ Case-sensitive, no trimming — anything else (`"yes"`, `"on"`, `"TRUE"`, `""`, `2`) passes
1584
+ through unchanged and still fails the type rule. That's the line between this and
1585
+ `accepted()`/`declined()` below: `.coerce()` is for the narrow, exact query-string
1586
+ serialization; `accepted()`/`declined()` are for broader form-style truthy strings like
1587
+ `"yes"`/`"on"`. `v.boolean()` does not coerce by default; the output type is unaffected
1588
+ (`v.boolean().coerce()` still infers `boolean`).
1589
+
1572
1590
  ## Conditional variants — accepted
1573
1591
 
1574
1592
  | Method | Args | Effect |
@@ -1596,6 +1614,7 @@ All conditional variants only run inside `v.object` — sibling resolution silen
1596
1614
  - `v.boolean()` → `{ type: "boolean" }`
1597
1615
  - `.mustBeTrue()` / `.mustBeFalse()` — not currently emitted (could add `const: true/false` in the future)
1598
1616
  - `.accepted()` / `.declined()` and their conditional variants — runtime coercion concerns, not representable
1617
+ - `.coerce()` — a pre-validation mutator, not representable; the schema still emits `{ type: "boolean" }`
1599
1618
 
1600
1619
  ## Common chains
1601
1620
 
@@ -1617,6 +1636,11 @@ v.object({
1617
1636
  region: v.string(),
1618
1637
  marketingOptIn: v.boolean().declinedUnless("region", "US"),
1619
1638
  })
1639
+
1640
+ // Query-string flag — ?active=true
1641
+ v.object({
1642
+ active: v.boolean().coerce(),
1643
+ })
1620
1644
  ```
1621
1645
 
1622
1646
 
@@ -1883,9 +1907,18 @@ For most numeric-shaped IDs you'd use `v.string().length(n).numeric()` instead
1883
1907
  | `.floor()` | — | round down to integer |
1884
1908
  | `.round(decimals?)` | default 0 | round to N decimals |
1885
1909
  | `.toFixed(decimals?)` | default 2 | round to N decimals — returns a **number** |
1910
+ | `.coerce()` | — | a **numeric-shaped string** → `Number`; any other value passes through unchanged |
1886
1911
 
1887
1912
  These run *before* validation rules. If you mutate `1.6` with `.ceil()`, `v.int()` sees `2` and passes. Use mutators when the input arrives in a slightly wrong form and you want to coerce, not reject.
1888
1913
 
1914
+ `.coerce()` (5.9+) is the opt-in for the most common case: **query-string params arrive as strings.** `v.int()` is strict by default — `?limit=2` is the string `"2"` and is rejected — so add `.coerce()` when a schema validates `request.query`:
1915
+
1916
+ ```ts
1917
+ v.object({ limit: v.int().coerce().min(1).max(100) }) // "2" → 2, passes
1918
+ ```
1919
+
1920
+ It only fixes the string *representation* — the type rule still runs, so `v.int().coerce()` on `"5.5"` coerces to `5.5` and correctly **fails** (still not an integer), and `"abc"` passes through and fails. Strictness is unchanged unless you chain `.coerce()`; the output type is unaffected (`v.int().coerce()` still infers `number`). Prefer this over hand-rolling `.addMutator(...)` in app schemas.
1921
+
1889
1922
  That ordering is exactly why `.toFixed()` yields a number rather than a fixed-point string: the mutated value is what the validator's own type rule sees, and a `number` schema that emitted `"3.14"` would reject its own output. Format to a string at the presentation edge instead.
1890
1923
 
1891
1924
  :::note[Fixed in 4.9.2]
package/package.json CHANGED
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "author": "hassanzohdy",
24
24
  "license": "MIT",
25
- "version": "5.8.0",
25
+ "version": "5.10.0",
26
26
  "main": "./cjs/index.cjs",
27
27
  "module": "./esm/index.mjs",
28
28
  "types": "./esm/index.d.mts",
@@ -4,10 +4,10 @@ Picking guide is in [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.j
4
4
 
5
5
  ## Strict equality
6
6
 
7
- | Method | Effect |
8
- |---|---|
9
- | `.mustBeTrue(msg?)` | strictly `=== true` (rejects `"yes"`, `1`, `"on"`) |
10
- | `.mustBeFalse(msg?)` | strictly `=== false` |
7
+ | Method | Effect |
8
+ | -------------------- | -------------------------------------------------- |
9
+ | `.mustBeTrue(msg?)` | strictly `=== true` (rejects `"yes"`, `1`, `"on"`) |
10
+ | `.mustBeFalse(msg?)` | strictly `=== false` |
11
11
 
12
12
  Use these when the field is a real boolean checkbox value — e.g. "agree to terms" must be exactly `true`, not a truthy string.
13
13
 
@@ -15,30 +15,48 @@ Use these when the field is a real boolean checkbox value — e.g. "agree to ter
15
15
 
16
16
  The "accepted" rules treat `true`, `"yes"`, `"on"`, `1`, `"1"`, `"true"` as accepted. "Declined" treats their counterparts (`false`, `"no"`, `"off"`, `0`, etc.) as declined. Designed for form inputs where a checkbox/radio arrives as a string.
17
17
 
18
- | Method | Effect |
19
- |---|---|
18
+ | Method | Effect |
19
+ | ----------------- | ---------------------- |
20
20
  | `.accepted(msg?)` | value must be accepted |
21
21
  | `.declined(msg?)` | value must be declined |
22
22
 
23
+ ## Query-string coercion — `.coerce()`
24
+
25
+ `.coerce()` (5.10+) is the opt-in for query-string flags: `?active=true` arrives as the
26
+ string `"true"`, and bare `v.boolean()` is strict by default — it rejects that string. Add
27
+ `.coerce()` when a schema validates `request.query`:
28
+
29
+ ```ts
30
+ v.object({ active: v.boolean().coerce() }); // "true" → true, passes
31
+ ```
32
+
33
+ It converts _exactly_ `"true"` / `"1"` / `1` → `true` and `"false"` / `"0"` / `0` → `false`.
34
+ Case-sensitive, no trimming — anything else (`"yes"`, `"on"`, `"TRUE"`, `""`, `2`) passes
35
+ through unchanged and still fails the type rule. That's the line between this and
36
+ `accepted()`/`declined()` below: `.coerce()` is for the narrow, exact query-string
37
+ serialization; `accepted()`/`declined()` are for broader form-style truthy strings like
38
+ `"yes"`/`"on"`. `v.boolean()` does not coerce by default; the output type is unaffected
39
+ (`v.boolean().coerce()` still infers `boolean`).
40
+
23
41
  ## Conditional variants — accepted
24
42
 
25
- | Method | Args | Effect |
26
- |---|---|---|
27
- | `.acceptedIf(field, value, msg?)` | sibling field equals value | must be accepted in that case |
43
+ | Method | Args | Effect |
44
+ | ------------------------------------- | -------------------------- | ----------------------------------- |
45
+ | `.acceptedIf(field, value, msg?)` | sibling field equals value | must be accepted in that case |
28
46
  | `.acceptedUnless(field, value, msg?)` | sibling field equals value | must be accepted unless that's true |
29
- | `.acceptedIfRequired(field, msg?)` | sibling field is required | — |
30
- | `.acceptedIfPresent(field, msg?)` | sibling field is present | — |
31
- | `.acceptedWithout(field, msg?)` | sibling field is absent | — |
47
+ | `.acceptedIfRequired(field, msg?)` | sibling field is required | — |
48
+ | `.acceptedIfPresent(field, msg?)` | sibling field is present | — |
49
+ | `.acceptedWithout(field, msg?)` | sibling field is absent | — |
32
50
 
33
51
  ## Conditional variants — declined
34
52
 
35
- | Method | Args | Effect |
36
- |---|---|---|
37
- | `.declinedIf(field, value, msg?)` | sibling field equals value | must be declined in that case |
53
+ | Method | Args | Effect |
54
+ | ------------------------------------- | -------------------------- | ----------------------------------- |
55
+ | `.declinedIf(field, value, msg?)` | sibling field equals value | must be declined in that case |
38
56
  | `.declinedUnless(field, value, msg?)` | sibling field equals value | must be declined unless that's true |
39
- | `.declinedIfRequired(field, msg?)` | — | — |
40
- | `.declinedIfPresent(field, msg?)` | — | — |
41
- | `.declinedWithout(field, msg?)` | — | — |
57
+ | `.declinedIfRequired(field, msg?)` | — | — |
58
+ | `.declinedIfPresent(field, msg?)` | — | — |
59
+ | `.declinedWithout(field, msg?)` | — | — |
42
60
 
43
61
  All conditional variants only run inside `v.object` — sibling resolution silently passes otherwise.
44
62
 
@@ -47,25 +65,31 @@ All conditional variants only run inside `v.object` — sibling resolution silen
47
65
  - `v.boolean()` → `{ type: "boolean" }`
48
66
  - `.mustBeTrue()` / `.mustBeFalse()` — not currently emitted (could add `const: true/false` in the future)
49
67
  - `.accepted()` / `.declined()` and their conditional variants — runtime coercion concerns, not representable
68
+ - `.coerce()` — a pre-validation mutator, not representable; the schema still emits `{ type: "boolean" }`
50
69
 
51
70
  ## Common chains
52
71
 
53
72
  ```ts
54
73
  // Strict consent checkbox
55
- v.boolean().mustBeTrue("You must accept the terms")
74
+ v.boolean().mustBeTrue("You must accept the terms");
56
75
 
57
76
  // Form-style "remember me" — accepts "on" / true / 1
58
- v.boolean().accepted().optional()
77
+ v.boolean().accepted().optional();
59
78
 
60
79
  // Cross-field — newsletter must be accepted if subscriptionType = "premium"
61
80
  v.object({
62
81
  subscriptionType: v.string().oneOf(["free", "premium"]),
63
82
  newsletter: v.boolean().acceptedIf("subscriptionType", "premium"),
64
- })
83
+ });
65
84
 
66
85
  // Marketing opt-in — declined unless region is GDPR-exempt
67
86
  v.object({
68
87
  region: v.string(),
69
88
  marketingOptIn: v.boolean().declinedUnless("region", "US"),
70
- })
89
+ });
90
+
91
+ // Query-string flag — ?active=true
92
+ v.object({
93
+ active: v.boolean().coerce(),
94
+ });
71
95
  ```
@@ -80,9 +80,18 @@ For most numeric-shaped IDs you'd use `v.string().length(n).numeric()` instead
80
80
  | `.floor()` | — | round down to integer |
81
81
  | `.round(decimals?)` | default 0 | round to N decimals |
82
82
  | `.toFixed(decimals?)` | default 2 | round to N decimals — returns a **number** |
83
+ | `.coerce()` | — | a **numeric-shaped string** → `Number`; any other value passes through unchanged |
83
84
 
84
85
  These run *before* validation rules. If you mutate `1.6` with `.ceil()`, `v.int()` sees `2` and passes. Use mutators when the input arrives in a slightly wrong form and you want to coerce, not reject.
85
86
 
87
+ `.coerce()` (5.9+) is the opt-in for the most common case: **query-string params arrive as strings.** `v.int()` is strict by default — `?limit=2` is the string `"2"` and is rejected — so add `.coerce()` when a schema validates `request.query`:
88
+
89
+ ```ts
90
+ v.object({ limit: v.int().coerce().min(1).max(100) }) // "2" → 2, passes
91
+ ```
92
+
93
+ It only fixes the string *representation* — the type rule still runs, so `v.int().coerce()` on `"5.5"` coerces to `5.5` and correctly **fails** (still not an integer), and `"abc"` passes through and fails. Strictness is unchanged unless you chain `.coerce()`; the output type is unaffected (`v.int().coerce()` still infers `number`). Prefer this over hand-rolling `.addMutator(...)` in app schemas.
94
+
86
95
  That ordering is exactly why `.toFixed()` yields a number rather than a fixed-point string: the mutated value is what the validator's own type rule sees, and a `number` schema that emitted `"3.14"` would reject its own output. Format to a string at the presentation edge instead.
87
96
 
88
97
  :::note[Fixed in 4.9.2]