@williamthorsen/toolbelt.numbers 7.1.0 → 7.2.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/.readyup/kits/default.js +44 -14
- package/.readyup/manifest.json +19 -9
- package/CHANGELOG.md +91 -76
- package/README.md +34 -7
- package/dist/esm/3-candidate/generateRandom.d.ts +4 -0
- package/dist/esm/3-candidate/pickInteger.d.ts +6 -0
- package/dist/esm/3-candidate/pickInteger.js +0 -3
- package/dist/esm/3-candidate/round.d.ts +4 -0
- package/dist/esm/3-candidate/scale.d.ts +12 -0
- package/dist/esm/internal/computeFakeMathRandom.js +1 -1
- package/package.json +3 -3
package/.readyup/kits/default.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @noformat -- @generated. Do not edit. Compiled by rdy. */
|
|
2
2
|
/* eslint-disable */
|
|
3
|
-
export const __readyupVersion = "0.
|
|
3
|
+
export const __readyupVersion = "0.36.0";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// ../adoption/src/conventions/path-predicates.ts
|
|
@@ -56,6 +56,11 @@ function defineAdoptionKit(spec) {
|
|
|
56
56
|
assertCheckIdsAreUnique();
|
|
57
57
|
const cache = {};
|
|
58
58
|
const adoptedPackage = { exportNames: spec.exportNames, packageName: spec.packageName };
|
|
59
|
+
const kitScope = { noSourcesReason: spec.noSourcesReason, pathFilter: spec.pathFilter };
|
|
60
|
+
const pathFiltersByKind = mapPathFiltersByKind();
|
|
61
|
+
const sweptPathFilters = [
|
|
62
|
+
.../* @__PURE__ */ new Set([spec.pathFilter, ...spec.checks.map((check) => resolveScope(check).pathFilter)])
|
|
63
|
+
];
|
|
59
64
|
return defineRdyKit({
|
|
60
65
|
description: spec.description,
|
|
61
66
|
defaultSeverity: "warn",
|
|
@@ -66,7 +71,7 @@ function defineAdoptionKit(spec) {
|
|
|
66
71
|
name: check.name,
|
|
67
72
|
id: check.id,
|
|
68
73
|
...check.severity !== void 0 && { severity: check.severity },
|
|
69
|
-
skip: skipUnlessProjectHoldsSources,
|
|
74
|
+
skip: () => skipUnlessProjectHoldsSources(resolveScope(check)),
|
|
70
75
|
check: () => reportKinds(check.kinds),
|
|
71
76
|
fix: check.fix
|
|
72
77
|
}))
|
|
@@ -85,16 +90,38 @@ function defineAdoptionKit(spec) {
|
|
|
85
90
|
throw new Error(`${spec.packageName}'s kit gives one id to more than one check: ${ids}`);
|
|
86
91
|
}
|
|
87
92
|
}
|
|
93
|
+
function isSweptPath(path) {
|
|
94
|
+
return sweptPathFilters.some((pathFilter) => pathFilter(path));
|
|
95
|
+
}
|
|
88
96
|
function loadSummary() {
|
|
89
97
|
cache.summary ??= readProject();
|
|
90
98
|
return cache.summary;
|
|
91
99
|
}
|
|
100
|
+
function mapPathFiltersByKind() {
|
|
101
|
+
const pathFilters = /* @__PURE__ */ new Map();
|
|
102
|
+
const conflicted = /* @__PURE__ */ new Set();
|
|
103
|
+
for (const check of spec.checks) {
|
|
104
|
+
const { pathFilter } = resolveScope(check);
|
|
105
|
+
for (const kind of check.kinds) {
|
|
106
|
+
const assigned = pathFilters.get(kind);
|
|
107
|
+
if (assigned !== void 0 && assigned !== pathFilter) conflicted.add(kind);
|
|
108
|
+
pathFilters.set(kind, pathFilter);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (conflicted.size > 0) {
|
|
112
|
+
const kinds = [...conflicted].toSorted().join(", ");
|
|
113
|
+
throw new Error(`${spec.packageName}'s kit reads one kind through more than one path filter: ${kinds}`);
|
|
114
|
+
}
|
|
115
|
+
return pathFilters;
|
|
116
|
+
}
|
|
92
117
|
async function readProject() {
|
|
93
|
-
const sources = await readTrackedSources(
|
|
118
|
+
const sources = await readTrackedSources(isSweptPath);
|
|
94
119
|
if (sources === void 0) return void 0;
|
|
95
120
|
return {
|
|
96
121
|
adoptedCount: countPackageUsage(sources, adoptedPackage),
|
|
97
|
-
findings: sources.flatMap(
|
|
122
|
+
findings: sources.flatMap(
|
|
123
|
+
(source) => spec.detect(source.text).filter((site) => (pathFiltersByKind.get(site.kind) ?? spec.pathFilter)(source.path)).map((site) => ({ ...site, path: source.path }))
|
|
124
|
+
),
|
|
98
125
|
sources
|
|
99
126
|
};
|
|
100
127
|
}
|
|
@@ -108,10 +135,13 @@ function defineAdoptionKit(spec) {
|
|
|
108
135
|
shouldReport: (finding) => kinds.includes(finding.kind)
|
|
109
136
|
});
|
|
110
137
|
}
|
|
111
|
-
|
|
138
|
+
function resolveScope(check) {
|
|
139
|
+
return check.pathFilter === void 0 ? kitScope : { noSourcesReason: check.noSourcesReason, pathFilter: check.pathFilter };
|
|
140
|
+
}
|
|
141
|
+
async function skipUnlessProjectHoldsSources(scope) {
|
|
112
142
|
const summary = await loadSummary();
|
|
113
143
|
if (summary === void 0) return NOT_A_REPO;
|
|
114
|
-
return summary.sources.
|
|
144
|
+
return summary.sources.some((source) => scope.pathFilter(source.path)) ? false : scope.noSourcesReason;
|
|
115
145
|
}
|
|
116
146
|
}
|
|
117
147
|
|
|
@@ -120,6 +150,14 @@ function condenseWhitespace(text) {
|
|
|
120
150
|
return text.replaceAll(/\s+/g, " ");
|
|
121
151
|
}
|
|
122
152
|
|
|
153
|
+
// ../adoption/src/portable/readAnchoredWindow.ts
|
|
154
|
+
function readAnchoredWindow(source, offset, lengths) {
|
|
155
|
+
return {
|
|
156
|
+
after: condenseWhitespace(source.slice(offset, offset + lengths.lookahead)),
|
|
157
|
+
before: condenseWhitespace(source.slice(Math.max(0, offset - lengths.lookbehind), offset))
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
123
161
|
// ../adoption/src/portable/readBalancedGroup.ts
|
|
124
162
|
var PARENTHESES = { close: ")", open: "(" };
|
|
125
163
|
function readBalancedGroup(source, from, delimiters) {
|
|
@@ -136,14 +174,6 @@ function readBalancedGroup(source, from, delimiters) {
|
|
|
136
174
|
return void 0;
|
|
137
175
|
}
|
|
138
176
|
|
|
139
|
-
// ../adoption/src/portable/readAnchoredWindow.ts
|
|
140
|
-
function readAnchoredWindow(source, offset, lengths) {
|
|
141
|
-
return {
|
|
142
|
-
after: condenseWhitespace(source.slice(offset, offset + lengths.lookahead)),
|
|
143
|
-
before: condenseWhitespace(source.slice(Math.max(0, offset - lengths.lookbehind), offset))
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
177
|
// ../adoption/src/mod.ts
|
|
148
178
|
import { blankNonCode, getLineAtOffset } from "readyup/check-utils";
|
|
149
179
|
|
package/.readyup/manifest.json
CHANGED
|
@@ -9,22 +9,22 @@
|
|
|
9
9
|
"esbuildVersion": "0.28.2",
|
|
10
10
|
"inputs": [
|
|
11
11
|
{
|
|
12
|
-
"hash": "
|
|
12
|
+
"hash": "1dc83619",
|
|
13
13
|
"kind": "module",
|
|
14
14
|
"path": "../../adoption/src/conventions/path-predicates.ts"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
|
-
"hash": "
|
|
17
|
+
"hash": "0237a871",
|
|
18
18
|
"kind": "module",
|
|
19
19
|
"path": "../../adoption/src/conventions/site-handoffs.ts"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
|
-
"hash": "
|
|
22
|
+
"hash": "8fb83c2d",
|
|
23
23
|
"kind": "module",
|
|
24
24
|
"path": "../../adoption/src/kits/defineAdoptionKit.ts"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
"hash": "
|
|
27
|
+
"hash": "10596562",
|
|
28
28
|
"kind": "module",
|
|
29
29
|
"path": "../../adoption/src/mod.ts"
|
|
30
30
|
},
|
|
@@ -34,17 +34,27 @@
|
|
|
34
34
|
"path": "../../adoption/src/portable/condenseWhitespace.ts"
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
|
-
"hash": "
|
|
37
|
+
"hash": "0661f0dd",
|
|
38
|
+
"kind": "module",
|
|
39
|
+
"path": "../../adoption/src/portable/listDirectoryAscents.ts"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"hash": "07c8358f",
|
|
38
43
|
"kind": "module",
|
|
39
44
|
"path": "../../adoption/src/portable/listFunctionBodies.ts"
|
|
40
45
|
},
|
|
41
46
|
{
|
|
42
|
-
"hash": "
|
|
47
|
+
"hash": "2d9f1edb",
|
|
48
|
+
"kind": "module",
|
|
49
|
+
"path": "../../adoption/src/portable/listTemplateLiterals.ts"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"hash": "b0751395",
|
|
43
53
|
"kind": "module",
|
|
44
54
|
"path": "../../adoption/src/portable/readAnchoredWindow.ts"
|
|
45
55
|
},
|
|
46
56
|
{
|
|
47
|
-
"hash": "
|
|
57
|
+
"hash": "0eb1daf1",
|
|
48
58
|
"kind": "module",
|
|
49
59
|
"path": "../../adoption/src/portable/readBalancedGroup.ts"
|
|
50
60
|
},
|
|
@@ -86,10 +96,10 @@
|
|
|
86
96
|
],
|
|
87
97
|
"name": "default",
|
|
88
98
|
"path": "kits/default.js",
|
|
89
|
-
"readyupVersion": "0.
|
|
99
|
+
"readyupVersion": "0.36.0",
|
|
90
100
|
"source": "kits/default.ts",
|
|
91
101
|
"sourceHash": "24f6e6db",
|
|
92
|
-
"targetHash": "
|
|
102
|
+
"targetHash": "b1603ae6"
|
|
93
103
|
}
|
|
94
104
|
]
|
|
95
105
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,77 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 7.2.0 — 2026-09-15
|
|
6
|
+
|
|
7
|
+
### 🎉 Features
|
|
8
|
+
|
|
9
|
+
- Add a ReadyUp adoption kit reporting hand-rolled guards (#311)
|
|
10
|
+
|
|
11
|
+
- Adds a ReadyUp adoption kit to `@williamthorsen/toolbelt.guards` that reports every function whose entire body re-implements a guard published by the package.
|
|
12
|
+
|
|
13
|
+
- Add a ReadyUp adoption kit to toolbelt.filesystem (#316)
|
|
14
|
+
|
|
15
|
+
- Adds a ReadyUp adoption kit to `@williamthorsen/toolbelt.filesystem` that recommends `writeAtomic` where a project writes a file to a temporary path and renames it into place, and `listDirectoryChain`, `findDirectoryChainMatch`, or `listDirectoryChainMatches` where a loop ascends to the filesystem root by `path.dirname`.
|
|
16
|
+
- Promotes `writeAtomic` to the candidate tier.
|
|
17
|
+
|
|
18
|
+
Migration: Change any import of `writeAtomic` from `@williamthorsen/toolbelt.filesystem/proposed` to `@williamthorsen/toolbelt.filesystem/candidate`.
|
|
19
|
+
|
|
20
|
+
- Read a directory walk's probed name through a binding or constant (#324)
|
|
21
|
+
|
|
22
|
+
- Extends the ReadyUp adoption kit in `@williamthorsen/toolbelt.packaging` to recommend `findPackageRoot` or `resolveSelfVersion` for a hand-rolled `package.json` search that checks for the file through a variable declared once inside its loop and never reassigned there, or through a string constant declared once in the same file.
|
|
23
|
+
- Stops the kit in `@williamthorsen/toolbelt.filesystem` from reporting such a search, which it previously treated as a generic directory walk.
|
|
24
|
+
|
|
25
|
+
- Report hand-rolled dedents in the strings adoption kit (#330)
|
|
26
|
+
|
|
27
|
+
- Adds `no-joined-line-array`, which reports an array of string or template literals that spans several lines and is joined with a newline.
|
|
28
|
+
- Adds `no-layout-breaking-template`, which reports an untagged template literal whose later lines drop below the indentation of the line on which it opens.
|
|
29
|
+
|
|
30
|
+
### 🐛 Bug fixes
|
|
31
|
+
|
|
32
|
+
- Stop reading each segment of a probe's path as a separately probed name (#320)
|
|
33
|
+
|
|
34
|
+
- Fixes an issue in which `toolbelt.filesystem`'s ReadyUp adoption kit treated a loop over parent directories as a search for each directory's own `package.json` when the path checked at each level contained a `'package.json'` literal, as in `path.join(dir, 'node_modules', name, 'package.json')`, and so did not report the loop under `no-hand-rolled-directory-walk`.
|
|
35
|
+
|
|
36
|
+
- Make pickInteger draw once per call and keep seeded draws below 1 (#329)
|
|
37
|
+
|
|
38
|
+
- Fixes seeded draws that could return exactly 1, outside the documented range of [0, 1): With seed `1_000_000_856_026_238`, `pickInteger({ min: 0, max: 9, seed })` returned 10 and `pickItem` from `toolbelt.arrays` threw a `RangeError`.
|
|
39
|
+
- Changes only the draw that returned 1, which no `SeededRng` and no integer seed below 2³¹ could produce.
|
|
40
|
+
- Stops `pickInteger` from skipping its draw when `min` and `max` truncate to the same integer, which changes no return value but shifts the later values drawn from a `SeededRng` or seed function passed with such bounds.
|
|
41
|
+
|
|
42
|
+
### ♻️ Refactoring
|
|
43
|
+
|
|
44
|
+
- Move directory-walk recognition from filesystem into packages/adoption (#318)
|
|
45
|
+
|
|
46
|
+
- Adds `listDirectoryAscents` to `packages/adoption`, which reports each directory ascent once with the names probed by its innermost loop, and reduces `filesystem`'s `listChainWalkSites` to a partition of that output, so a `toolbelt.packaging` kit can partition the same ascents without its own copy of the recognition.
|
|
47
|
+
- Renames the hand-off rule `isProjectRootSearch` to `isManifestSearch` and rewrites the text in `packages/adoption` and `filesystem` that credited `findProjectRoot` alone with a `package.json` walk.
|
|
48
|
+
- Stops `filesystem`'s kit from reporting a loop that ascends one binding around an inner loop ascending another binding and probing for `package.json`, which is the only finding changed by the move.
|
|
49
|
+
|
|
50
|
+
### 🧪 Tests
|
|
51
|
+
|
|
52
|
+
- Move the rdy run report reader into the adoption test utilities (#323)
|
|
53
|
+
|
|
54
|
+
- Replaces the `rdy run --json` report reader copied into each of the twelve `pragma-suppression.tool.test.ts` suites with `listKitCheckReports`, a helper added to `@williamthorsen/toolbelt.adoption/test-utils` that runs a package's compiled kit over a fixture repo and returns its check reports, so a change to the shape of readyup's report needs one edit rather than twelve.
|
|
55
|
+
- Fixes the error thrown for a kit that does not load: Each copy discarded the load error recorded by `rdy` on the kit's entry and threw "the run reported no adoption checks", and the helper throws with `rdy`'s own message instead.
|
|
56
|
+
|
|
57
|
+
### ⚙️ Tooling
|
|
58
|
+
|
|
59
|
+
- Remove the stale repo-local cliff.toml and normalize changelog titles (#327)
|
|
60
|
+
|
|
61
|
+
- Stops `release-kit prepare` from printing a "skipped due to grouping error(s)" warning for each releasable workspace by letting it resolve the git-cliff template bundled with release-kit, previously overridden by the root `cliff.toml`.
|
|
62
|
+
- Excludes commits without a ticket prefix from future changelog entries.
|
|
63
|
+
- Renames the section titles in every `packages/*/.meta/changelog.json`, except `Dependency updates`, to the headings of release-kit's work-type taxonomy, such as "🎉 Features" and "🏗️ Internal features", and regenerates each `CHANGELOG.md` so that release-kit orders existing and new sections by the same rule.
|
|
64
|
+
- Causes the next `release-kit prepare` to plan patch releases of `dstructs`, `hof`, and `sets`, which had no other commits since their last release, because the changelog commit touches every workspace.
|
|
65
|
+
|
|
66
|
+
### 📚 Documentation
|
|
67
|
+
|
|
68
|
+
- Align prose with plain-speech doctrine and writing conventions (#306)
|
|
69
|
+
|
|
70
|
+
- Copy-edits prose across the repo: comments, test names, package READMEs, and `AGENTS.md`.
|
|
71
|
+
- Rewrites a few user-facing strings as well, among them `configure-project`'s help text and the errors from `parseProjectSpec`, `securityCommands`, and `hashString`.
|
|
72
|
+
|
|
5
73
|
## 7.1.0 — 2026-09-06
|
|
6
74
|
|
|
7
|
-
### Features
|
|
75
|
+
### 🎉 Features
|
|
8
76
|
|
|
9
77
|
- Add a ReadyUp adoption kit (#253)
|
|
10
78
|
|
|
@@ -14,12 +82,7 @@ All notable changes to this project will be documented in this file.
|
|
|
14
82
|
|
|
15
83
|
- Adds a ReadyUp adoption kit to `@williamthorsen/toolbelt.async` that recommends the use of `delay` to replace a hand-rolled sleep.
|
|
16
84
|
|
|
17
|
-
###
|
|
18
|
-
|
|
19
|
-
- Upgrade all deps to latest version
|
|
20
|
-
- Upgrade all deps to latest version
|
|
21
|
-
|
|
22
|
-
### Documentation
|
|
85
|
+
### 📚 Documentation
|
|
23
86
|
|
|
24
87
|
- Document the generated-source exemption in the adoption kits (#251)
|
|
25
88
|
|
|
@@ -47,7 +110,7 @@ All notable changes to this project will be documented in this file.
|
|
|
47
110
|
|
|
48
111
|
## 7.0.3 — 2026-08-30
|
|
49
112
|
|
|
50
|
-
### Bug fixes
|
|
113
|
+
### 🐛 Bug fixes
|
|
51
114
|
|
|
52
115
|
- Reject a check declaring a kind its detector never produces (#246)
|
|
53
116
|
|
|
@@ -55,21 +118,15 @@ All notable changes to this project will be documented in this file.
|
|
|
55
118
|
|
|
56
119
|
## 7.0.2 — 2026-08-28
|
|
57
120
|
|
|
58
|
-
### Refactoring
|
|
121
|
+
### ♻️ Refactoring
|
|
59
122
|
|
|
60
123
|
- Upgrade eslint-config-typescript to v12.0.1 and satisfy its new rules (#236)
|
|
61
124
|
|
|
62
125
|
Upgrades `@williamthorsen/eslint-config-typescript` to v12 and fixes violations surfaced by the new rules banning unpublished barrels and floating disposables.
|
|
63
126
|
|
|
64
|
-
### Dependencies
|
|
65
|
-
|
|
66
|
-
- Upgrade all deps to latest version
|
|
67
|
-
- Upgrade deps to latest version
|
|
68
|
-
- Upgrade all deps to latest version
|
|
69
|
-
|
|
70
127
|
## 7.0.1 — 2026-08-24
|
|
71
128
|
|
|
72
|
-
### Bug fixes
|
|
129
|
+
### 🐛 Bug fixes
|
|
73
130
|
|
|
74
131
|
- Stop the adoption kits from blanking code after `++`, `!`, and keyword-named members (#208)
|
|
75
132
|
|
|
@@ -77,7 +134,7 @@ All notable changes to this project will be documented in this file.
|
|
|
77
134
|
|
|
78
135
|
`@williamthorsen/toolbelt.adoption` now takes `blankNonCode` and `getLineAtOffset` from `readyup/check-utils` in place of the copies it held, which had fallen behind readyup's on those three cases.
|
|
79
136
|
|
|
80
|
-
### Internal
|
|
137
|
+
### 🏗️ Internal features
|
|
81
138
|
|
|
82
139
|
- Migrate the adoption kits onto FindingOutcome and add check ids (#217)
|
|
83
140
|
|
|
@@ -93,7 +150,7 @@ All notable changes to this project will be documented in this file.
|
|
|
93
150
|
|
|
94
151
|
## 7.0.0 — 2026-08-21
|
|
95
152
|
|
|
96
|
-
### Features
|
|
153
|
+
### 🎉 Features
|
|
97
154
|
|
|
98
155
|
- 🚨 **Breaking:** Promote clamp to the candidate tier with a stricter bounds contract (#185)
|
|
99
156
|
|
|
@@ -105,25 +162,21 @@ All notable changes to this project will be documented in this file.
|
|
|
105
162
|
|
|
106
163
|
Adds a ReadyUp adoption kit to `@williamthorsen/toolbelt.numbers`. When run against a project, the kit identifies hand-rolled code that can be replaced by the package's `clamp`, `round`, or `pickInteger` functions.
|
|
107
164
|
|
|
108
|
-
### Bug fixes
|
|
165
|
+
### 🐛 Bug fixes
|
|
109
166
|
|
|
110
167
|
- Blank comments and literals before a detector reads a source (#191)
|
|
111
168
|
|
|
112
169
|
Fixes the issue that the `errors`, `numbers`, and `vitest` adoption kits' detectors did not distinguish code from comments and literals, and so flagged a pattern written in a comment or a string as a candidate replacement site. Each detector now blanks every comment, string, template literal, and regular expression before its anchor scan, leaving interpolated expressions intact.
|
|
113
170
|
|
|
114
|
-
### Refactoring
|
|
171
|
+
### ♻️ Refactoring
|
|
115
172
|
|
|
116
173
|
- Break the workspace dependency cycle by making `adoption` a leaf (#195)
|
|
117
174
|
|
|
118
175
|
Fixes a cyclic dependency among packages in the repo. `packages/adoption` is now a workspace leaf: It declares no workspace dependency, and its test scaffolding is held to node builtins. A new root test fails on any cycle in the workspace dependency graph.
|
|
119
176
|
|
|
120
|
-
### Dependencies
|
|
121
|
-
|
|
122
|
-
- Upgrade all deps to latest version
|
|
123
|
-
|
|
124
177
|
## 6.0.1 — 2026-08-13
|
|
125
178
|
|
|
126
|
-
### Tooling
|
|
179
|
+
### ⚙️ Tooling
|
|
127
180
|
|
|
128
181
|
- Remove redundant .gitignore files
|
|
129
182
|
- Populate manifest metadata and adopt a pnpm catalog (#140)
|
|
@@ -132,13 +185,13 @@ All notable changes to this project will be documented in this file.
|
|
|
132
185
|
|
|
133
186
|
## 6.0.0 — 2026-08-12
|
|
134
187
|
|
|
135
|
-
### Features
|
|
188
|
+
### 🎉 Features
|
|
136
189
|
|
|
137
190
|
- 🚨 **Breaking:** Rename get* functions by return kind and verb specificity (#119)
|
|
138
191
|
|
|
139
192
|
Renames thirteen functions across various packages to align with a consistent naming pattern.
|
|
140
193
|
|
|
141
|
-
### Refactoring
|
|
194
|
+
### ♻️ Refactoring
|
|
142
195
|
|
|
143
196
|
- Stop shipping test-only and dead support modules (#117)
|
|
144
197
|
|
|
@@ -150,17 +203,13 @@ All notable changes to this project will be documented in this file.
|
|
|
150
203
|
|
|
151
204
|
## 5.0.0 — 2026-08-08
|
|
152
205
|
|
|
153
|
-
### Features
|
|
206
|
+
### 🎉 Features
|
|
154
207
|
|
|
155
208
|
- 🚨 **Breaking:** Spawn seeded number generator of same subclass (#84)
|
|
156
209
|
|
|
157
210
|
A seeded generator spawned from a subclass now matches that subclass, so `IntSeededRng.withSeed` supplies the wrapped function integers where it previously supplied floats. Callers relying on values derived through that path must re-baseline. A detached reference such as `const { withSeed } = SeededRng` now throws.
|
|
158
211
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
Changes the `unicorn/numeric-separators-style` rule config so that separators are consistently used in base 10 numbers, instead of exempting numbers of 5 digits or less.
|
|
162
|
-
|
|
163
|
-
### Refactoring
|
|
212
|
+
### ♻️ Refactoring
|
|
164
213
|
|
|
165
214
|
- Fixes violations surfaced by newly active lint rules (#84)
|
|
166
215
|
- Fix slug punctuation and require safe integers (#86)
|
|
@@ -169,9 +218,7 @@ All notable changes to this project will be documented in this file.
|
|
|
169
218
|
- Time-unit conversions, scaling range bounds, normal-distribution interval counts, and array indices in object paths now reject values too large to represent exactly instead of silently losing precision.
|
|
170
219
|
- Seeded number generators now produce distinct sequences for seeds at or beyond 2^53, where adjacent seeds previously collapsed onto nearly identical output. A seed of that size saved before this release no longer reproduces the same output.
|
|
171
220
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
### Tooling
|
|
221
|
+
### ⚙️ Tooling
|
|
175
222
|
|
|
176
223
|
- Migrate Vitest configs to the nmr projects model (#73)
|
|
177
224
|
|
|
@@ -189,35 +236,31 @@ All notable changes to this project will be documented in this file.
|
|
|
189
236
|
|
|
190
237
|
All packages now have identical compiler settings, using the settings from the `@williamthorsen/tsconfig` base config without modification.
|
|
191
238
|
|
|
192
|
-
### Dependencies
|
|
193
|
-
|
|
194
|
-
- Upgrade all deps to latest version
|
|
195
|
-
|
|
196
239
|
## 4.3.8 — 2026-07-27
|
|
197
240
|
|
|
198
|
-
### Tooling
|
|
241
|
+
### ⚙️ Tooling
|
|
199
242
|
|
|
200
243
|
- Normalize Vitest, and lint configs
|
|
201
244
|
|
|
202
|
-
### Documentation
|
|
245
|
+
### 📚 Documentation
|
|
203
246
|
|
|
204
247
|
- Change license to ISC
|
|
205
248
|
|
|
206
249
|
## 4.3.7 — 2026-07-24
|
|
207
250
|
|
|
208
|
-
### Tooling
|
|
251
|
+
### ⚙️ Tooling
|
|
209
252
|
|
|
210
253
|
- Configure release-kit & repo labels
|
|
211
254
|
|
|
212
255
|
## 4.3.6 — 2026-07-20
|
|
213
256
|
|
|
214
|
-
### Bug fixes
|
|
257
|
+
### 🐛 Bug fixes
|
|
215
258
|
|
|
216
259
|
- Add repository field to package manifests for npm provenance (#65)
|
|
217
260
|
|
|
218
261
|
Fixes an issue that prevented every package from publishing to npm. Each package now links to its source repository from its npm page.
|
|
219
262
|
|
|
220
|
-
### Dependencies
|
|
263
|
+
### 📦 Dependencies
|
|
221
264
|
|
|
222
265
|
- Upgrade ESLint packages and migrate to TypeScript 6 (#67)
|
|
223
266
|
|
|
@@ -225,7 +268,7 @@ All notable changes to this project will be documented in this file.
|
|
|
225
268
|
|
|
226
269
|
## 4.3.5 — 2026-07-20
|
|
227
270
|
|
|
228
|
-
### Tooling
|
|
271
|
+
### ⚙️ Tooling
|
|
229
272
|
|
|
230
273
|
- Migrate to the nmr toolchain and resolve dependency vulnerabilities (#45)
|
|
231
274
|
|
|
@@ -233,37 +276,13 @@ All notable changes to this project will be documented in this file.
|
|
|
233
276
|
|
|
234
277
|
## 4.3.4 — 2026-03-19
|
|
235
278
|
|
|
236
|
-
### Formatting
|
|
279
|
+
### 🎨 Formatting
|
|
237
280
|
|
|
238
281
|
- Format changelogs
|
|
239
282
|
|
|
240
283
|
## 4.3.1 — 2026-03-10
|
|
241
284
|
|
|
242
|
-
###
|
|
243
|
-
|
|
244
|
-
- Add string functions
|
|
245
|
-
- Add number functions
|
|
246
|
-
- Add integer string functions
|
|
247
|
-
- Caller can specify fallback value for safeParseInteger
|
|
248
|
-
- Allow error as safeParseInteger fallback
|
|
249
|
-
- Add safeParseNumber
|
|
250
|
-
|
|
251
|
-
### Refactoring
|
|
252
|
-
|
|
253
|
-
- Rename functions
|
|
254
|
-
|
|
255
|
-
### Tests
|
|
256
|
-
|
|
257
|
-
- Adapt Deno tests to Vitest
|
|
258
|
-
|
|
259
|
-
### Tooling
|
|
260
|
-
|
|
261
|
-
- Scaffold the numbers workspace
|
|
262
|
-
- Enable incremental type generation
|
|
263
|
-
- Rename publish script to avoid recursion
|
|
264
|
-
- Change package registry from github to npmjs
|
|
265
|
-
|
|
266
|
-
### Dependencies
|
|
285
|
+
### 📦 Dependencies
|
|
267
286
|
|
|
268
287
|
- Adapt to dependency upgrades and bump Node engine to >=24 (#8)
|
|
269
288
|
|
|
@@ -305,8 +324,4 @@ All notable changes to this project will be documented in this file.
|
|
|
305
324
|
|
|
306
325
|
The build script used `pnpm --recursive run build` but no workspace package defines a `build` script — they all use `ws build` through the workspace script runner. Aligns with all other recursive commands.
|
|
307
326
|
|
|
308
|
-
### Documentation
|
|
309
|
-
|
|
310
|
-
- Fix lint
|
|
311
|
-
|
|
312
327
|
<!-- Generated by release-kit. Do not edit this file. Use .meta/changelog-overrides.json to override entries. -->
|
package/README.md
CHANGED
|
@@ -1,19 +1,46 @@
|
|
|
1
|
+
<!-- readme-type: library -->
|
|
2
|
+
|
|
1
3
|
# @williamthorsen/toolbelt.numbers
|
|
2
4
|
|
|
3
5
|
Utility functions for working with numbers.
|
|
4
6
|
|
|
5
7
|
<!-- section:release-notes -->
|
|
6
|
-
## Release notes — v7.
|
|
8
|
+
## Release notes — v7.2.0 (2026-09-15)
|
|
9
|
+
|
|
10
|
+
### 🎉 Features
|
|
11
|
+
|
|
12
|
+
- Add a ReadyUp adoption kit reporting hand-rolled guards (#311)
|
|
13
|
+
|
|
14
|
+
- Adds a ReadyUp adoption kit to `@williamthorsen/toolbelt.guards` that reports every function whose entire body re-implements a guard published by the package.
|
|
15
|
+
|
|
16
|
+
- Add a ReadyUp adoption kit to toolbelt.filesystem (#316)
|
|
17
|
+
|
|
18
|
+
- Adds a ReadyUp adoption kit to `@williamthorsen/toolbelt.filesystem` that recommends `writeAtomic` where a project writes a file to a temporary path and renames it into place, and `listDirectoryChain`, `findDirectoryChainMatch`, or `listDirectoryChainMatches` where a loop ascends to the filesystem root by `path.dirname`.
|
|
19
|
+
- Promotes `writeAtomic` to the candidate tier.
|
|
20
|
+
|
|
21
|
+
Migration: Change any import of `writeAtomic` from `@williamthorsen/toolbelt.filesystem/proposed` to `@williamthorsen/toolbelt.filesystem/candidate`.
|
|
22
|
+
|
|
23
|
+
- Read a directory walk's probed name through a binding or constant (#324)
|
|
24
|
+
|
|
25
|
+
- Extends the ReadyUp adoption kit in `@williamthorsen/toolbelt.packaging` to recommend `findPackageRoot` or `resolveSelfVersion` for a hand-rolled `package.json` search that checks for the file through a variable declared once inside its loop and never reassigned there, or through a string constant declared once in the same file.
|
|
26
|
+
- Stops the kit in `@williamthorsen/toolbelt.filesystem` from reporting such a search, which it previously treated as a generic directory walk.
|
|
27
|
+
|
|
28
|
+
- Report hand-rolled dedents in the strings adoption kit (#330)
|
|
29
|
+
|
|
30
|
+
- Adds `no-joined-line-array`, which reports an array of string or template literals that spans several lines and is joined with a newline.
|
|
31
|
+
- Adds `no-layout-breaking-template`, which reports an untagged template literal whose later lines drop below the indentation of the line on which it opens.
|
|
7
32
|
|
|
8
|
-
###
|
|
33
|
+
### 🐛 Bug fixes
|
|
9
34
|
|
|
10
|
-
-
|
|
35
|
+
- Stop reading each segment of a probe's path as a separately probed name (#320)
|
|
11
36
|
|
|
12
|
-
|
|
37
|
+
- Fixes an issue in which `toolbelt.filesystem`'s ReadyUp adoption kit treated a loop over parent directories as a search for each directory's own `package.json` when the path checked at each level contained a `'package.json'` literal, as in `path.join(dir, 'node_modules', name, 'package.json')`, and so did not report the loop under `no-hand-rolled-directory-walk`.
|
|
13
38
|
|
|
14
|
-
-
|
|
39
|
+
- Make pickInteger draw once per call and keep seeded draws below 1 (#329)
|
|
15
40
|
|
|
16
|
-
-
|
|
41
|
+
- Fixes seeded draws that could return exactly 1, outside the documented range of [0, 1): With seed `1_000_000_856_026_238`, `pickInteger({ min: 0, max: 9, seed })` returned 10 and `pickItem` from `toolbelt.arrays` threw a `RangeError`.
|
|
42
|
+
- Changes only the draw that returned 1, which no `SeededRng` and no integer seed below 2³¹ could produce.
|
|
43
|
+
- Stops `pickInteger` from skipping its draw when `min` and `max` truncate to the same integer, which changes no return value but shifts the later values drawn from a `SeededRng` or seed function passed with such bounds.
|
|
17
44
|
<!-- /section:release-notes -->
|
|
18
45
|
|
|
19
46
|
## Installation
|
|
@@ -61,7 +88,7 @@ round(3.14159, 2); // 3.14
|
|
|
61
88
|
pickInteger(params?: { min?: number; max?: number; seed?: Seed }): number;
|
|
62
89
|
```
|
|
63
90
|
|
|
64
|
-
Returns a random integer between the bounds, **inclusive** of both, and truncates a non-integer bound. Passing a seed makes the draw deterministic, which a test wants.
|
|
91
|
+
Returns a random integer between the bounds, **inclusive** of both, and truncates a non-integer bound. Passing a seed makes the draw deterministic, which a test wants. Each call draws exactly once, even when the bounds admit a single value.
|
|
65
92
|
|
|
66
93
|
Mind the bound when replacing `Math.floor(Math.random() * n)`: That idiom stops at `n - 1`, so the equivalent is `pickInteger({ max: n - 1 })`.
|
|
67
94
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { type Seed } from '../internal/evaluateSeed.js';
|
|
2
2
|
/**
|
|
3
3
|
* Returns a scaled random number in the range [min, max).
|
|
4
|
+
*
|
|
5
|
+
* @category Number
|
|
6
|
+
* @experimental
|
|
7
|
+
* @stage candidate
|
|
4
8
|
*/
|
|
5
9
|
export declare function generateRandom(options?: Options): number;
|
|
6
10
|
interface Options {
|
|
@@ -2,6 +2,12 @@ import type { Seed } from '../internal/evaluateSeed.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Returns a random integer between the bounds inclusive.
|
|
4
4
|
* If the bounds are not integers, they are truncated to integers.
|
|
5
|
+
* Draws exactly once per call, even when the bounds admit a single value, so that a shared seed advances the same way
|
|
6
|
+
* whatever the bounds.
|
|
7
|
+
*
|
|
8
|
+
* @category Number
|
|
9
|
+
* @experimental
|
|
10
|
+
* @stage candidate
|
|
5
11
|
*/
|
|
6
12
|
export declare function pickInteger(params?: Params): number;
|
|
7
13
|
interface Params {
|
|
@@ -9,9 +9,6 @@ export function pickInteger(params = {}) {
|
|
|
9
9
|
}
|
|
10
10
|
const start = Math.trunc(Math.min(min, max));
|
|
11
11
|
const end = Math.trunc(Math.max(min, max));
|
|
12
|
-
if (start === end) {
|
|
13
|
-
return start;
|
|
14
|
-
}
|
|
15
12
|
const range = end - start + 1;
|
|
16
13
|
return start + Math.floor(generateRandom({ seed }) * range);
|
|
17
14
|
}
|
|
@@ -2,5 +2,9 @@
|
|
|
2
2
|
* Returns the number rounded to the given number of decimal places, or 0 if no nDecimalPlaces is specified.
|
|
3
3
|
* @param value
|
|
4
4
|
* @param nDecimalPlaces
|
|
5
|
+
*
|
|
6
|
+
* @category Number
|
|
7
|
+
* @experimental
|
|
8
|
+
* @stage candidate
|
|
5
9
|
*/
|
|
6
10
|
export declare function round(value: number, nDecimalPlaces?: number): number;
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scales a number from one range to another.
|
|
3
|
+
*
|
|
4
|
+
* @category Number
|
|
5
|
+
* @experimental
|
|
6
|
+
* @stage candidate
|
|
3
7
|
*/
|
|
4
8
|
export declare function scale(value: number, toRange: Range, fromRange?: Partial<Range>): number;
|
|
9
|
+
/**
|
|
10
|
+
* Scales a number from one range to another and rounds it to the nearest integer.
|
|
11
|
+
* Throws a RangeError unless the target bounds are safe integers.
|
|
12
|
+
*
|
|
13
|
+
* @category Number
|
|
14
|
+
* @experimental
|
|
15
|
+
* @stage candidate
|
|
16
|
+
*/
|
|
5
17
|
export declare function scaleInt(value: number, toRange: Range, fromRange?: Partial<IntegerRange>): number;
|
|
6
18
|
interface Range {
|
|
7
19
|
min: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@williamthorsen/toolbelt.numbers",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.0",
|
|
4
4
|
"description": "Utility functions for working with numbers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"esm",
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
],
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@williamthorsen/toolbelt.adoption": "0.1.0",
|
|
50
|
-
"@williamthorsen/toolbelt.testing": "0.
|
|
50
|
+
"@williamthorsen/toolbelt.testing": "0.6.0",
|
|
51
51
|
"esbuild": "0.28.2",
|
|
52
|
-
"readyup": "0.
|
|
52
|
+
"readyup": "0.36.0"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
55
|
"node": ">=24.0.0"
|