@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/CHANGELOG.md +14 -1
- package/cjs/index.cjs +57 -0
- package/cjs/index.cjs.map +1 -1
- package/esm/index.d.mts +2 -1
- package/esm/index.mjs +2 -1
- package/esm/mutators/boolean-mutators.d.mts +14 -0
- package/esm/mutators/boolean-mutators.d.mts.map +1 -0
- package/esm/mutators/boolean-mutators.mjs +17 -0
- package/esm/mutators/boolean-mutators.mjs.map +1 -0
- package/esm/mutators/index.mjs +1 -0
- package/esm/validators/boolean-validator.d.mts +21 -0
- package/esm/validators/boolean-validator.d.mts.map +1 -1
- package/esm/validators/boolean-validator.mjs +22 -0
- package/esm/validators/boolean-validator.mjs.map +1 -1
- package/esm/validators/number-validator.d.mts +20 -0
- package/esm/validators/number-validator.d.mts.map +1 -1
- package/esm/validators/number-validator.mjs +21 -1
- package/esm/validators/number-validator.mjs.map +1 -1
- package/llms-full.txt +33 -0
- package/package.json +1 -1
- package/skills/pick-seal-primitive/boolean-methods.md +46 -22
- package/skills/pick-seal-primitive/number-methods.md +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ 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.10.0 - 2026-09-14
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `.coerce()` on `v.boolean()` — opt-in query-string coercion (`"true"`/`"1"` → `true`, `"false"`/`"0"` → `false`).
|
|
12
|
+
|
|
13
|
+
## 5.9.0 - 2026-09-13
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `.coerce()` modifier on the number validators (`int` / `number` / `float` / `numeric`): opt into parsing a numeric-shaped string (e.g. a query-string param) into a number while the type rule stays strict. `v.int()` is unchanged by default; chain `.coerce()` to accept `"2"` as `2`. The inferred output type is unaffected.
|
|
18
|
+
|
|
7
19
|
## 5.7.0 - 2026-09-11
|
|
8
20
|
|
|
9
21
|
### Changed
|
|
@@ -11,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
11
23
|
- Internal type-safety hardening; no behaviour change.
|
|
12
24
|
|
|
13
25
|
## 5.6.0 - 2026-09-08
|
|
26
|
+
|
|
14
27
|
### Fixed
|
|
15
28
|
|
|
16
29
|
- **`warlock build` and `warlock start` died inside Seal before any application code ran**, with a `ReferenceError` from `array-validator.ts` extending `BaseValidator` before `base-validator.ts` had finished evaluating. The cause was one inline `type` import: under `verbatimModuleSyntax`, `import { type ValidateOptions } from "./validators"` is emitted as a real side-effect import, which closed an import cycle that a type-only import would never have created. Written as `import type { ... }`, the module is not pulled into evaluation at all. Nothing about the validators changed — only which modules load, and when.
|
|
@@ -86,7 +99,7 @@ changelogs.
|
|
|
86
99
|
- `v.literal("")` could never pass. Every validator is required by default and `required` rejects anything the empty-value check calls empty — which includes `""` — so a schema demanding an exact empty string reported "is required" for a field that was present. A literal set containing an empty value now uses `present` (the key must exist) instead of `required`, leaving the literal set to judge the value. Only the empty string was affected; `v.literal(0)` and `v.literal(false)` always worked
|
|
87
100
|
- `v.literal("").optional()` silently disabled the literal check rather than fixing it, accepting `""`, `null` **and** a missing key alike. The literal rule now runs on empty values (`requiresValue: false`) while treating absence as the required/present rule's question, so `.optional()` means optional again and a present value must still match
|
|
88
101
|
- a **failed** validation no longer returns the input it rejected. `object` returned the raw input — including the unknown keys it had just complained about — while `discriminatedUnion` returned `undefined`; the same call shape had two contracts. Validating an outbound DTO to keep internal fields out of a response, then reading `data` without branching on `isValid`, shipped every field the schema existed to exclude. `data` is now `undefined` whenever `isValid` is `false`
|
|
89
|
-
- `v.number().toFixed(n)` could never produce a valid result — the mutator returned `Number(value).toFixed(n)`, a
|
|
102
|
+
- `v.number().toFixed(n)` could never produce a valid result — the mutator returned `Number(value).toFixed(n)`, a _string_, which the validator's own `number` type rule then rejected. It now yields a number (`3.14159` → `3.14`), so the method works where it lives. No working code can have depended on the old output, since every such validation failed; for a fixed-point _string_, format at the presentation edge rather than asking a number schema to emit one
|
|
90
103
|
|
|
91
104
|
## 4.2.11
|
|
92
105
|
|
package/cjs/index.cjs
CHANGED
|
@@ -1127,6 +1127,21 @@ const removeEmptyArrayElementsMutator = async (value) => {
|
|
|
1127
1127
|
return value.filter((item) => !isEmptyValue(item));
|
|
1128
1128
|
};
|
|
1129
1129
|
|
|
1130
|
+
//#endregion
|
|
1131
|
+
//#region ../seal/src/mutators/boolean-mutators.ts
|
|
1132
|
+
/**
|
|
1133
|
+
* Coerce a query-string-shaped boolean into a real boolean.
|
|
1134
|
+
*
|
|
1135
|
+
* Converts exactly: `"true"` / `"1"` / `1` → `true`, `"false"` / `"0"` / `0` → `false`.
|
|
1136
|
+
* Case-sensitive, no trimming. Any other value (`"yes"`, `"on"`, `"TRUE"`, `""`,
|
|
1137
|
+
* `2`, `null`, etc.) passes through unchanged so the boolean type rule rejects it.
|
|
1138
|
+
*/
|
|
1139
|
+
const booleanCoerceMutator = async (value) => {
|
|
1140
|
+
if (value === "true" || value === "1" || value === 1) return true;
|
|
1141
|
+
if (value === "false" || value === "0" || value === 0) return false;
|
|
1142
|
+
return value;
|
|
1143
|
+
};
|
|
1144
|
+
|
|
1130
1145
|
//#endregion
|
|
1131
1146
|
//#region ../seal/src/mutators/date-mutators.ts
|
|
1132
1147
|
/**
|
|
@@ -5783,6 +5798,27 @@ var BooleanValidator = class extends PrimitiveValidator {
|
|
|
5783
5798
|
return this.addRule(declinedWithoutRule, errorMessage, { field });
|
|
5784
5799
|
}
|
|
5785
5800
|
/**
|
|
5801
|
+
* Opt in to coercion: an exact query-string-shaped boolean is converted to a
|
|
5802
|
+
* real boolean **before** the type rules run; any other value passes through
|
|
5803
|
+
* unchanged so bad input still fails the type rule.
|
|
5804
|
+
*
|
|
5805
|
+
* Converts exactly `"true"` / `"1"` / `1` → `true` and `"false"` / `"0"` / `0`
|
|
5806
|
+
* → `false`. Case-sensitive, no trimming — `"TRUE"`, `"yes"`, `"on"`, `""`, and
|
|
5807
|
+
* `2` all pass through unchanged and fail the type rule. `v.boolean()` does
|
|
5808
|
+
* **not** coerce by default; this only takes effect when explicitly chained.
|
|
5809
|
+
* For form-style truthy strings like `"yes"` / `"on"`, use `.accepted()` /
|
|
5810
|
+
* `.declined()` instead — those are separate pass/fail rules, not coercion.
|
|
5811
|
+
*
|
|
5812
|
+
* The output type is unchanged (`Infer<>` keys off the validator class), so
|
|
5813
|
+
* `v.boolean().coerce()` still infers `boolean`.
|
|
5814
|
+
*
|
|
5815
|
+
* @example
|
|
5816
|
+
* v.boolean().coerce() // "true" → true; "1" → true; "0" → false; "yes" → invalid
|
|
5817
|
+
*/
|
|
5818
|
+
coerce() {
|
|
5819
|
+
return this.addMutator(booleanCoerceMutator);
|
|
5820
|
+
}
|
|
5821
|
+
/**
|
|
5786
5822
|
* Value must be strictly true (not "yes", "on", 1, etc.)
|
|
5787
5823
|
* @alias accepted - strict version
|
|
5788
5824
|
*/
|
|
@@ -6977,6 +7013,26 @@ var NumberValidator = class extends PrimitiveValidator {
|
|
|
6977
7013
|
return this.addMutator(toFixedMutator, { decimals });
|
|
6978
7014
|
}
|
|
6979
7015
|
/**
|
|
7016
|
+
* Opt in to coercion: a numeric-shaped string is converted to a number
|
|
7017
|
+
* **before** the type rules run; any other value passes through unchanged
|
|
7018
|
+
* so bad input still fails the type rule.
|
|
7019
|
+
*
|
|
7020
|
+
* Strictness is preserved — coercion only fixes the string *representation*,
|
|
7021
|
+
* not the value's shape. `v.int().coerce()` turns `"5"` into `5` (valid) but
|
|
7022
|
+
* `"5.5"` into `5.5`, which still fails the integer rule. Number validators
|
|
7023
|
+
* do **not** coerce by default; this only takes effect when explicitly chained.
|
|
7024
|
+
*
|
|
7025
|
+
* The output type is unchanged (`Infer<>` keys off the validator class), so
|
|
7026
|
+
* `v.int().coerce()` still infers `number`.
|
|
7027
|
+
*
|
|
7028
|
+
* @example
|
|
7029
|
+
* v.int().coerce() // "5" → 5 (valid); "5.5" → 5.5 (invalid); "abc" → invalid
|
|
7030
|
+
* v.number().coerce() // "5.5" → 5.5 (valid)
|
|
7031
|
+
*/
|
|
7032
|
+
coerce() {
|
|
7033
|
+
return this.addMutator(numericMutator);
|
|
7034
|
+
}
|
|
7035
|
+
/**
|
|
6980
7036
|
* @inheritdoc
|
|
6981
7037
|
*
|
|
6982
7038
|
* Returns `{ type: "number" }` with numeric constraint keywords.
|
|
@@ -8788,6 +8844,7 @@ exports.betweenNumbersRule = betweenNumbersRule;
|
|
|
8788
8844
|
exports.betweenTimesRule = betweenTimesRule;
|
|
8789
8845
|
exports.betweenYearsRule = betweenYearsRule;
|
|
8790
8846
|
exports.birthdayRule = birthdayRule;
|
|
8847
|
+
exports.booleanCoerceMutator = booleanCoerceMutator;
|
|
8791
8848
|
exports.booleanMutator = booleanMutator;
|
|
8792
8849
|
exports.booleanRule = booleanRule;
|
|
8793
8850
|
exports.businessDayRule = businessDayRule;
|