@warlock.js/seal 4.14.0 → 4.16.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 +34 -24
- package/cjs/index.cjs +35 -4
- package/cjs/index.cjs.map +1 -1
- package/esm/index.d.mts +2 -2
- package/esm/index.mjs +2 -2
- package/esm/mutators/index.mjs +1 -1
- package/esm/mutators/string-mutators.d.mts +16 -2
- package/esm/mutators/string-mutators.d.mts.map +1 -1
- package/esm/mutators/string-mutators.mjs +17 -3
- package/esm/mutators/string-mutators.mjs.map +1 -1
- package/esm/validators/string-validator.d.mts +15 -1
- package/esm/validators/string-validator.d.mts.map +1 -1
- package/esm/validators/string-validator.mjs +19 -3
- package/esm/validators/string-validator.mjs.map +1 -1
- package/llms-full.txt +3 -3
- package/package.json +10 -10
- package/skills/pick-seal-primitive/string-methods.md +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,30 +1,40 @@
|
|
|
1
|
-
# Changelog — @warlock.js/seal
|
|
2
|
-
|
|
3
|
-
All notable changes to `@warlock.js/seal` are documented in this file.
|
|
4
|
-
|
|
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
|
-
|
|
1
|
+
# Changelog — @warlock.js/seal
|
|
2
|
+
|
|
3
|
+
All notable changes to `@warlock.js/seal` are documented in this file.
|
|
4
|
+
|
|
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
|
+
|
|
7
|
+
## 4.16.0 - 2026-08-18
|
|
8
|
+
|
|
9
|
+
### Security
|
|
10
|
+
|
|
11
|
+
- **Renamed `safeHtmlMutator`/`.safeHtml()` to `stripTagsMutator`/`.stripTags()`.** The old name implied XSS safety it never provided — the implementation is a naive `<[^>]*>` regex, not an HTML parser, and can be defeated by malformed/nested markup or content re-introduced later in a pipeline. A developer building `v.string().safeHtml()` for user-supplied rich text was liable to treat the output as pre-sanitized and skip further output encoding, opening a stored/reflected XSS path. The new names and doc comments make clear this is tag-stripping only; use a real parser-based sanitizer (DOMPurify / sanitize-html) for untrusted rich text. `safeHtmlMutator` and `.safeHtml()` remain as deprecated aliases (same behavior, `@deprecated` JSDoc pointing at the new names) so existing callers do not break.
|
|
12
|
+
|
|
13
|
+
### Dependencies
|
|
14
|
+
|
|
15
|
+
- Bumped `@mongez/supportive-is` to `^2.1.4` (no breaking changes) and `@mongez/reinforcements` to `^4.0.1`. The reinforcements major makes `Random.string/nanoid/id/token/uuid` CSPRNG-backed (WebCrypto) and removes `Random.seed()` support — audited this package's source and tests for `Random.seed(` and for seeded/reproducible use of `Random.*`; none found, so no code changes were needed.
|
|
16
|
+
|
|
7
17
|
## 4.12.0
|
|
8
18
|
|
|
9
19
|
### Changed
|
|
10
20
|
|
|
11
21
|
- Declares its own test runner and pins it to an exact version (`vitest@4.1.10`). The package is its own repository, so a runner resolved from a workspace root it may not be cloned with is a runner it cannot rely on. The pin is exact rather than a range because the version moved underneath the suite mid-development on an unrelated install — a suite whose runner can change without anyone choosing it proves less than it appears to
|
|
12
22
|
|
|
13
|
-
## 4.9.2
|
|
14
|
-
|
|
15
|
-
### Fixed
|
|
16
|
-
|
|
17
|
-
- `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
|
|
18
|
-
- `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
|
|
19
|
-
- 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`
|
|
20
|
-
- `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
|
|
21
|
-
|
|
22
|
-
## 4.2.11
|
|
23
|
-
|
|
24
|
-
### Changed
|
|
25
|
-
|
|
26
|
-
- Bumped `@mongez/reinforcements` to 3.3.0
|
|
27
|
-
|
|
28
|
-
## 4.1.15
|
|
29
|
-
|
|
30
|
-
- Baseline — per-package changelog tracking starts at this version.
|
|
23
|
+
## 4.9.2
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- `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
|
|
28
|
+
- `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
|
|
29
|
+
- 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`
|
|
30
|
+
- `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
|
|
31
|
+
|
|
32
|
+
## 4.2.11
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- Bumped `@mongez/reinforcements` to 3.3.0
|
|
37
|
+
|
|
38
|
+
## 4.1.15
|
|
39
|
+
|
|
40
|
+
- Baseline — per-package changelog tracking starts at this version.
|
package/cjs/index.cjs
CHANGED
|
@@ -1354,10 +1354,24 @@ const stringifyMutator = async (value) => {
|
|
|
1354
1354
|
const trimMutator = async (value, context) => {
|
|
1355
1355
|
return (0, _mongez_reinforcements.trim)(value?.toString(), context?.options?.needle ?? " ");
|
|
1356
1356
|
};
|
|
1357
|
-
/**
|
|
1358
|
-
|
|
1357
|
+
/**
|
|
1358
|
+
* Strip HTML tags with a naive `<...>` regex.
|
|
1359
|
+
*
|
|
1360
|
+
* This is a **tag stripper, not an XSS sanitizer**: it is not a parser, so
|
|
1361
|
+
* malformed/nested markup, attribute payloads, or content re-introduced
|
|
1362
|
+
* later in a pipeline can defeat it. Do not rely on this alone to make
|
|
1363
|
+
* untrusted rich text safe to render — use a real parser-based sanitizer
|
|
1364
|
+
* (e.g. DOMPurify / sanitize-html) for that.
|
|
1365
|
+
*/
|
|
1366
|
+
const stripTagsMutator = async (value) => {
|
|
1359
1367
|
return value?.toString().replace(/<[^>]*>?/gm, "");
|
|
1360
1368
|
};
|
|
1369
|
+
/**
|
|
1370
|
+
* @deprecated Renamed to {@link stripTagsMutator} — the old name implied
|
|
1371
|
+
* XSS safety this tag-stripping regex does not provide. Kept as an alias
|
|
1372
|
+
* for backward compatibility; switch to `stripTagsMutator`.
|
|
1373
|
+
*/
|
|
1374
|
+
const safeHtmlMutator = stripTagsMutator;
|
|
1361
1375
|
/** HTML escape */
|
|
1362
1376
|
const htmlEscapeMutator = async (value) => {
|
|
1363
1377
|
return value?.toString().replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -7985,9 +7999,25 @@ var StringValidator = class extends PrimitiveValidator {
|
|
|
7985
7999
|
char
|
|
7986
8000
|
});
|
|
7987
8001
|
}
|
|
7988
|
-
/**
|
|
8002
|
+
/**
|
|
8003
|
+
* Strip HTML tags with a naive `<...>` regex.
|
|
8004
|
+
*
|
|
8005
|
+
* This is a **tag stripper, not an XSS sanitizer**: it is not a parser,
|
|
8006
|
+
* so malformed/nested markup or content re-introduced later in a
|
|
8007
|
+
* pipeline can defeat it. Do not rely on this alone to make untrusted
|
|
8008
|
+
* rich text safe to render — use a real parser-based sanitizer (e.g.
|
|
8009
|
+
* DOMPurify / sanitize-html) for that.
|
|
8010
|
+
*/
|
|
8011
|
+
stripTags() {
|
|
8012
|
+
return this.addMutator(stripTagsMutator);
|
|
8013
|
+
}
|
|
8014
|
+
/**
|
|
8015
|
+
* @deprecated Renamed to {@link StringValidator.stripTags} — the old
|
|
8016
|
+
* name implied XSS safety this tag-stripping regex does not provide.
|
|
8017
|
+
* Kept as an alias for backward compatibility; switch to `.stripTags()`.
|
|
8018
|
+
*/
|
|
7989
8019
|
safeHtml() {
|
|
7990
|
-
return this.
|
|
8020
|
+
return this.stripTags();
|
|
7991
8021
|
}
|
|
7992
8022
|
/** HTML escape special characters */
|
|
7993
8023
|
htmlEscape() {
|
|
@@ -8900,6 +8930,7 @@ exports.startsWithRule = startsWithRule;
|
|
|
8900
8930
|
exports.stringMutator = stringMutator;
|
|
8901
8931
|
exports.stringRule = stringRule;
|
|
8902
8932
|
exports.stringifyMutator = stringifyMutator;
|
|
8933
|
+
exports.stripTagsMutator = stripTagsMutator;
|
|
8903
8934
|
exports.stripUnknownMutator = stripUnknownMutator;
|
|
8904
8935
|
exports.strongPasswordRule = strongPasswordRule;
|
|
8905
8936
|
exports.titleCaseMutator = titleCaseMutator;
|