@warlock.js/seal 5.9.0 → 5.11.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 +330 -232
- 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 +30 -0
- package/esm/mutators/boolean-mutators.d.mts.map +1 -0
- package/esm/mutators/boolean-mutators.mjs +40 -0
- package/esm/mutators/boolean-mutators.mjs.map +1 -0
- package/esm/mutators/index.mjs +1 -0
- package/esm/rules/scalar/accepted-rule.mjs +20 -13
- package/esm/rules/scalar/accepted-rule.mjs.map +1 -1
- package/esm/rules/scalar/declined-rule.mjs +20 -13
- package/esm/rules/scalar/declined-rule.mjs.map +1 -1
- package/esm/rules/scalar/index.mjs +2 -2
- package/esm/validators/boolean-validator.d.mts +44 -2
- package/esm/validators/boolean-validator.d.mts.map +1 -1
- package/esm/validators/boolean-validator.mjs +64 -16
- package/esm/validators/boolean-validator.mjs.map +1 -1
- package/esm/validators/scalar-validator.mjs +2 -2
- package/llms-full.txt +57 -24
- package/package.json +1 -1
- package/skills/pick-seal-primitive/boolean-methods.md +57 -24
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { getRuleOptions } from "../standard-schema/json-schema.mjs";
|
|
2
2
|
import { VALID_RULE, invalidRule } from "../helpers/validation-helpers.mjs";
|
|
3
3
|
import "../helpers/index.mjs";
|
|
4
|
+
import { acceptedIfPresentRule, acceptedIfRequiredRule, acceptedIfRule, acceptedRule, acceptedUnlessRule, acceptedWithoutRule } from "../rules/scalar/accepted-rule.mjs";
|
|
5
|
+
import { declinedIfPresentRule, declinedIfRequiredRule, declinedIfRule, declinedRule, declinedUnlessRule, declinedWithoutRule } from "../rules/scalar/declined-rule.mjs";
|
|
4
6
|
import { numberMutator } from "../mutators/number-mutators.mjs";
|
|
5
7
|
import { stringMutator } from "../mutators/scalar-mutators.mjs";
|
|
6
8
|
import "../mutators/index.mjs";
|
|
7
9
|
import { PrimitiveValidator } from "./primitive-validator.mjs";
|
|
8
|
-
import { acceptedIfPresentRule, acceptedIfRequiredRule, acceptedIfRule, acceptedRule, acceptedUnlessRule, acceptedWithoutRule } from "../rules/scalar/accepted-rule.mjs";
|
|
9
|
-
import { declinedIfPresentRule, declinedIfRequiredRule, declinedIfRule, declinedRule, declinedUnlessRule, declinedWithoutRule } from "../rules/scalar/declined-rule.mjs";
|
|
10
10
|
import "../rules/scalar/index.mjs";
|
|
11
11
|
|
|
12
12
|
//#region ../seal/src/validators/scalar-validator.ts
|
package/llms-full.txt
CHANGED
|
@@ -1553,41 +1553,68 @@ Picking guide is in [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.j
|
|
|
1553
1553
|
|
|
1554
1554
|
## Strict equality
|
|
1555
1555
|
|
|
1556
|
-
| Method
|
|
1557
|
-
|
|
1558
|
-
| `.mustBeTrue(msg?)`
|
|
1559
|
-
| `.mustBeFalse(msg?)` | strictly `=== false`
|
|
1556
|
+
| Method | Effect |
|
|
1557
|
+
| -------------------- | -------------------------------------------------- |
|
|
1558
|
+
| `.mustBeTrue(msg?)` | strictly `=== true` (rejects `"yes"`, `1`, `"on"`) |
|
|
1559
|
+
| `.mustBeFalse(msg?)` | strictly `=== false` |
|
|
1560
1560
|
|
|
1561
1561
|
Use these when the field is a real boolean checkbox value — e.g. "agree to terms" must be exactly `true`, not a truthy string.
|
|
1562
1562
|
|
|
1563
1563
|
## Form-style coercion — `accepted` / `declined`
|
|
1564
1564
|
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1565
|
+
Calling `.accepted()`/`.declined()` (or any conditional variant) opts `v.boolean()` into
|
|
1566
|
+
form-boolean parsing: a mutator runs before the type rule and converts the accepted set
|
|
1567
|
+
(`1`, `"1"`, `true`, `"true"`, `"yes"`, `"y"`, `"on"`, `"Yes"`, `"Y"`, `"On"`) to `true` and
|
|
1568
|
+
the declined set (`0`, `"0"`, `false`, `"false"`, `"no"`, `"n"`, `"off"`, `"No"`, `"N"`,
|
|
1569
|
+
`"Off"`) to `false`; any other value passes through unchanged and still fails the type rule.
|
|
1570
|
+
So `v.boolean().accepted()` given `"yes"` is valid **and its output is the real boolean
|
|
1571
|
+
`true`** — not the original string. Designed for form inputs where a checkbox/radio arrives
|
|
1572
|
+
as a string. `v.scalar().accepted()` runs the same accepted/declined rule but keeps the raw
|
|
1573
|
+
value untouched (no boolean type rule, no parsing mutator) — use it when you want the
|
|
1574
|
+
pass/fail check without normalizing the output.
|
|
1575
|
+
|
|
1576
|
+
| Method | Effect |
|
|
1577
|
+
| ----------------- | ---------------------- |
|
|
1569
1578
|
| `.accepted(msg?)` | value must be accepted |
|
|
1570
1579
|
| `.declined(msg?)` | value must be declined |
|
|
1571
1580
|
|
|
1581
|
+
## Query-string coercion — `.coerce()`
|
|
1582
|
+
|
|
1583
|
+
`.coerce()` (5.10+) is the opt-in for query-string flags: `?active=true` arrives as the
|
|
1584
|
+
string `"true"`, and bare `v.boolean()` is strict by default — it rejects that string. Add
|
|
1585
|
+
`.coerce()` when a schema validates `request.query`:
|
|
1586
|
+
|
|
1587
|
+
```ts
|
|
1588
|
+
v.object({ active: v.boolean().coerce() }); // "true" → true, passes
|
|
1589
|
+
```
|
|
1590
|
+
|
|
1591
|
+
It converts _exactly_ `"true"` / `"1"` / `1` → `true` and `"false"` / `"0"` / `0` → `false`.
|
|
1592
|
+
Case-sensitive, no trimming — anything else (`"yes"`, `"on"`, `"TRUE"`, `""`, `2`) passes
|
|
1593
|
+
through unchanged and still fails the type rule. That's the line between this and
|
|
1594
|
+
`accepted()`/`declined()` below: `.coerce()` is for the narrow, exact query-string
|
|
1595
|
+
serialization; `accepted()`/`declined()` are for broader form-style truthy strings like
|
|
1596
|
+
`"yes"`/`"on"`. `v.boolean()` does not coerce by default; the output type is unaffected
|
|
1597
|
+
(`v.boolean().coerce()` still infers `boolean`).
|
|
1598
|
+
|
|
1572
1599
|
## Conditional variants — accepted
|
|
1573
1600
|
|
|
1574
|
-
| Method
|
|
1575
|
-
|
|
1576
|
-
| `.acceptedIf(field, value, msg?)`
|
|
1601
|
+
| Method | Args | Effect |
|
|
1602
|
+
| ------------------------------------- | -------------------------- | ----------------------------------- |
|
|
1603
|
+
| `.acceptedIf(field, value, msg?)` | sibling field equals value | must be accepted in that case |
|
|
1577
1604
|
| `.acceptedUnless(field, value, msg?)` | sibling field equals value | must be accepted unless that's true |
|
|
1578
|
-
| `.acceptedIfRequired(field, msg?)`
|
|
1579
|
-
| `.acceptedIfPresent(field, msg?)`
|
|
1580
|
-
| `.acceptedWithout(field, msg?)`
|
|
1605
|
+
| `.acceptedIfRequired(field, msg?)` | sibling field is required | — |
|
|
1606
|
+
| `.acceptedIfPresent(field, msg?)` | sibling field is present | — |
|
|
1607
|
+
| `.acceptedWithout(field, msg?)` | sibling field is absent | — |
|
|
1581
1608
|
|
|
1582
1609
|
## Conditional variants — declined
|
|
1583
1610
|
|
|
1584
|
-
| Method
|
|
1585
|
-
|
|
1586
|
-
| `.declinedIf(field, value, msg?)`
|
|
1611
|
+
| Method | Args | Effect |
|
|
1612
|
+
| ------------------------------------- | -------------------------- | ----------------------------------- |
|
|
1613
|
+
| `.declinedIf(field, value, msg?)` | sibling field equals value | must be declined in that case |
|
|
1587
1614
|
| `.declinedUnless(field, value, msg?)` | sibling field equals value | must be declined unless that's true |
|
|
1588
|
-
| `.declinedIfRequired(field, msg?)`
|
|
1589
|
-
| `.declinedIfPresent(field, msg?)`
|
|
1590
|
-
| `.declinedWithout(field, msg?)`
|
|
1615
|
+
| `.declinedIfRequired(field, msg?)` | — | — |
|
|
1616
|
+
| `.declinedIfPresent(field, msg?)` | — | — |
|
|
1617
|
+
| `.declinedWithout(field, msg?)` | — | — |
|
|
1591
1618
|
|
|
1592
1619
|
All conditional variants only run inside `v.object` — sibling resolution silently passes otherwise.
|
|
1593
1620
|
|
|
@@ -1596,27 +1623,33 @@ All conditional variants only run inside `v.object` — sibling resolution silen
|
|
|
1596
1623
|
- `v.boolean()` → `{ type: "boolean" }`
|
|
1597
1624
|
- `.mustBeTrue()` / `.mustBeFalse()` — not currently emitted (could add `const: true/false` in the future)
|
|
1598
1625
|
- `.accepted()` / `.declined()` and their conditional variants — runtime coercion concerns, not representable
|
|
1626
|
+
- `.coerce()` — a pre-validation mutator, not representable; the schema still emits `{ type: "boolean" }`
|
|
1599
1627
|
|
|
1600
1628
|
## Common chains
|
|
1601
1629
|
|
|
1602
1630
|
```ts
|
|
1603
1631
|
// Strict consent checkbox
|
|
1604
|
-
v.boolean().mustBeTrue("You must accept the terms")
|
|
1632
|
+
v.boolean().mustBeTrue("You must accept the terms");
|
|
1605
1633
|
|
|
1606
1634
|
// Form-style "remember me" — accepts "on" / true / 1
|
|
1607
|
-
v.boolean().accepted().optional()
|
|
1635
|
+
v.boolean().accepted().optional();
|
|
1608
1636
|
|
|
1609
1637
|
// Cross-field — newsletter must be accepted if subscriptionType = "premium"
|
|
1610
1638
|
v.object({
|
|
1611
1639
|
subscriptionType: v.string().oneOf(["free", "premium"]),
|
|
1612
1640
|
newsletter: v.boolean().acceptedIf("subscriptionType", "premium"),
|
|
1613
|
-
})
|
|
1641
|
+
});
|
|
1614
1642
|
|
|
1615
1643
|
// Marketing opt-in — declined unless region is GDPR-exempt
|
|
1616
1644
|
v.object({
|
|
1617
1645
|
region: v.string(),
|
|
1618
1646
|
marketingOptIn: v.boolean().declinedUnless("region", "US"),
|
|
1619
|
-
})
|
|
1647
|
+
});
|
|
1648
|
+
|
|
1649
|
+
// Query-string flag — ?active=true
|
|
1650
|
+
v.object({
|
|
1651
|
+
active: v.boolean().coerce(),
|
|
1652
|
+
});
|
|
1620
1653
|
```
|
|
1621
1654
|
|
|
1622
1655
|
|
package/package.json
CHANGED
|
@@ -4,41 +4,68 @@ Picking guide is in [`@warlock.js/seal/pick-seal-primitive/SKILL.md`](@warlock.j
|
|
|
4
4
|
|
|
5
5
|
## Strict equality
|
|
6
6
|
|
|
7
|
-
| Method
|
|
8
|
-
|
|
9
|
-
| `.mustBeTrue(msg?)`
|
|
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
|
|
|
14
14
|
## Form-style coercion — `accepted` / `declined`
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
Calling `.accepted()`/`.declined()` (or any conditional variant) opts `v.boolean()` into
|
|
17
|
+
form-boolean parsing: a mutator runs before the type rule and converts the accepted set
|
|
18
|
+
(`1`, `"1"`, `true`, `"true"`, `"yes"`, `"y"`, `"on"`, `"Yes"`, `"Y"`, `"On"`) to `true` and
|
|
19
|
+
the declined set (`0`, `"0"`, `false`, `"false"`, `"no"`, `"n"`, `"off"`, `"No"`, `"N"`,
|
|
20
|
+
`"Off"`) to `false`; any other value passes through unchanged and still fails the type rule.
|
|
21
|
+
So `v.boolean().accepted()` given `"yes"` is valid **and its output is the real boolean
|
|
22
|
+
`true`** — not the original string. Designed for form inputs where a checkbox/radio arrives
|
|
23
|
+
as a string. `v.scalar().accepted()` runs the same accepted/declined rule but keeps the raw
|
|
24
|
+
value untouched (no boolean type rule, no parsing mutator) — use it when you want the
|
|
25
|
+
pass/fail check without normalizing the output.
|
|
26
|
+
|
|
27
|
+
| Method | Effect |
|
|
28
|
+
| ----------------- | ---------------------- |
|
|
20
29
|
| `.accepted(msg?)` | value must be accepted |
|
|
21
30
|
| `.declined(msg?)` | value must be declined |
|
|
22
31
|
|
|
32
|
+
## Query-string coercion — `.coerce()`
|
|
33
|
+
|
|
34
|
+
`.coerce()` (5.10+) is the opt-in for query-string flags: `?active=true` arrives as the
|
|
35
|
+
string `"true"`, and bare `v.boolean()` is strict by default — it rejects that string. Add
|
|
36
|
+
`.coerce()` when a schema validates `request.query`:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
v.object({ active: v.boolean().coerce() }); // "true" → true, passes
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
It converts _exactly_ `"true"` / `"1"` / `1` → `true` and `"false"` / `"0"` / `0` → `false`.
|
|
43
|
+
Case-sensitive, no trimming — anything else (`"yes"`, `"on"`, `"TRUE"`, `""`, `2`) passes
|
|
44
|
+
through unchanged and still fails the type rule. That's the line between this and
|
|
45
|
+
`accepted()`/`declined()` below: `.coerce()` is for the narrow, exact query-string
|
|
46
|
+
serialization; `accepted()`/`declined()` are for broader form-style truthy strings like
|
|
47
|
+
`"yes"`/`"on"`. `v.boolean()` does not coerce by default; the output type is unaffected
|
|
48
|
+
(`v.boolean().coerce()` still infers `boolean`).
|
|
49
|
+
|
|
23
50
|
## Conditional variants — accepted
|
|
24
51
|
|
|
25
|
-
| Method
|
|
26
|
-
|
|
27
|
-
| `.acceptedIf(field, value, msg?)`
|
|
52
|
+
| Method | Args | Effect |
|
|
53
|
+
| ------------------------------------- | -------------------------- | ----------------------------------- |
|
|
54
|
+
| `.acceptedIf(field, value, msg?)` | sibling field equals value | must be accepted in that case |
|
|
28
55
|
| `.acceptedUnless(field, value, msg?)` | sibling field equals value | must be accepted unless that's true |
|
|
29
|
-
| `.acceptedIfRequired(field, msg?)`
|
|
30
|
-
| `.acceptedIfPresent(field, msg?)`
|
|
31
|
-
| `.acceptedWithout(field, msg?)`
|
|
56
|
+
| `.acceptedIfRequired(field, msg?)` | sibling field is required | — |
|
|
57
|
+
| `.acceptedIfPresent(field, msg?)` | sibling field is present | — |
|
|
58
|
+
| `.acceptedWithout(field, msg?)` | sibling field is absent | — |
|
|
32
59
|
|
|
33
60
|
## Conditional variants — declined
|
|
34
61
|
|
|
35
|
-
| Method
|
|
36
|
-
|
|
37
|
-
| `.declinedIf(field, value, msg?)`
|
|
62
|
+
| Method | Args | Effect |
|
|
63
|
+
| ------------------------------------- | -------------------------- | ----------------------------------- |
|
|
64
|
+
| `.declinedIf(field, value, msg?)` | sibling field equals value | must be declined in that case |
|
|
38
65
|
| `.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?)`
|
|
66
|
+
| `.declinedIfRequired(field, msg?)` | — | — |
|
|
67
|
+
| `.declinedIfPresent(field, msg?)` | — | — |
|
|
68
|
+
| `.declinedWithout(field, msg?)` | — | — |
|
|
42
69
|
|
|
43
70
|
All conditional variants only run inside `v.object` — sibling resolution silently passes otherwise.
|
|
44
71
|
|
|
@@ -47,25 +74,31 @@ All conditional variants only run inside `v.object` — sibling resolution silen
|
|
|
47
74
|
- `v.boolean()` → `{ type: "boolean" }`
|
|
48
75
|
- `.mustBeTrue()` / `.mustBeFalse()` — not currently emitted (could add `const: true/false` in the future)
|
|
49
76
|
- `.accepted()` / `.declined()` and their conditional variants — runtime coercion concerns, not representable
|
|
77
|
+
- `.coerce()` — a pre-validation mutator, not representable; the schema still emits `{ type: "boolean" }`
|
|
50
78
|
|
|
51
79
|
## Common chains
|
|
52
80
|
|
|
53
81
|
```ts
|
|
54
82
|
// Strict consent checkbox
|
|
55
|
-
v.boolean().mustBeTrue("You must accept the terms")
|
|
83
|
+
v.boolean().mustBeTrue("You must accept the terms");
|
|
56
84
|
|
|
57
85
|
// Form-style "remember me" — accepts "on" / true / 1
|
|
58
|
-
v.boolean().accepted().optional()
|
|
86
|
+
v.boolean().accepted().optional();
|
|
59
87
|
|
|
60
88
|
// Cross-field — newsletter must be accepted if subscriptionType = "premium"
|
|
61
89
|
v.object({
|
|
62
90
|
subscriptionType: v.string().oneOf(["free", "premium"]),
|
|
63
91
|
newsletter: v.boolean().acceptedIf("subscriptionType", "premium"),
|
|
64
|
-
})
|
|
92
|
+
});
|
|
65
93
|
|
|
66
94
|
// Marketing opt-in — declined unless region is GDPR-exempt
|
|
67
95
|
v.object({
|
|
68
96
|
region: v.string(),
|
|
69
97
|
marketingOptIn: v.boolean().declinedUnless("region", "US"),
|
|
70
|
-
})
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Query-string flag — ?active=true
|
|
101
|
+
v.object({
|
|
102
|
+
active: v.boolean().coerce(),
|
|
103
|
+
});
|
|
71
104
|
```
|