@williamthorsen/toolbelt.numbers 7.2.1 → 7.2.3

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.
@@ -1,6 +1,6 @@
1
1
  /** @noformat -- @generated. Do not edit. Compiled by rdy. */
2
2
  /* eslint-disable */
3
- export const __readyupVersion = "0.37.0";
3
+ export const __readyupVersion = "0.40.0";
4
4
 
5
5
 
6
6
  // ../adoption/src/conventions/path-predicates.ts
@@ -301,7 +301,7 @@ var default_default = defineAdoptionKit({
301
301
  description: `Adoption checks for a project consuming ${PACKAGE_NAME}`,
302
302
  detect: listMathIdioms,
303
303
  exportNames: ADOPTED_EXPORTS,
304
- noSourcesReason: "the project holds no JavaScript or TypeScript sources outside the exempt paths",
304
+ noSourcesReason: "the project contains no JavaScript or TypeScript sources outside the exempt paths",
305
305
  packageName: PACKAGE_NAME,
306
306
  // A test computes these values deliberately, and a bootstrap wrapper's hand-rolled arithmetic keeps its
307
307
  // build-first message alive through an incomplete install.
@@ -312,7 +312,7 @@ var default_default = defineAdoptionKit({
312
312
  id: "no-hand-rolled-clamp",
313
313
  kinds: ["clamp-nest"],
314
314
  severity: "recommend",
315
- fix: `Replace each expression named above with clamp from ${PACKAGE_NAME}/candidate, called as clamp(value, { min, max }). It is not a silent substitution: clamp throws a RangeError on a reversed range or a NaN bound, where the nested Math calls return a value for both. Reference: ${README_URL}`
315
+ fix: `Replace each expression named above with clamp from ${PACKAGE_NAME}/candidate, called as clamp(value, { min, max }). It is not a silent substitution: clamp throws a RangeError on a reversed range or a NaN bound, whereas the nested Math calls return a value for both. Reference: ${README_URL}`
316
316
  },
317
317
  {
318
318
  name: "No source rounds to decimal places by hand",
@@ -326,7 +326,7 @@ var default_default = defineAdoptionKit({
326
326
  id: "no-hand-rolled-random-integer",
327
327
  kinds: ["random-integer"],
328
328
  severity: "recommend",
329
- fix: `Replace each expression named above with pickInteger from ${PACKAGE_NAME}/candidate, which also takes a seed. Mind the bound: Math.floor(Math.random() * N) stops at N - 1, where pickInteger's max is inclusive, so the replacement is pickInteger({ max: N - 1 }). A site indexing an array is left to toolbelt.arrays, whose pickItem covers it. Reference: ${README_URL}`
329
+ fix: `Replace each expression named above with pickInteger from ${PACKAGE_NAME}/candidate, which also takes a seed. Mind the bound: Math.floor(Math.random() * N) stops at N - 1, whereas pickInteger's max is inclusive, so the replacement is pickInteger({ max: N - 1 }). A site indexing an array is left to toolbelt.arrays, whose pickItem covers it. Reference: ${README_URL}`
330
330
  }
331
331
  ]
332
332
  });
@@ -9,22 +9,22 @@
9
9
  "esbuildVersion": "0.28.2",
10
10
  "inputs": [
11
11
  {
12
- "hash": "1dc83619",
12
+ "hash": "fcd04dfa",
13
13
  "kind": "module",
14
14
  "path": "../../adoption/src/conventions/path-predicates.ts"
15
15
  },
16
16
  {
17
- "hash": "0237a871",
17
+ "hash": "921ba938",
18
18
  "kind": "module",
19
19
  "path": "../../adoption/src/conventions/site-handoffs.ts"
20
20
  },
21
21
  {
22
- "hash": "8fb83c2d",
22
+ "hash": "e6e87602",
23
23
  "kind": "module",
24
24
  "path": "../../adoption/src/kits/defineAdoptionKit.ts"
25
25
  },
26
26
  {
27
- "hash": "10596562",
27
+ "hash": "09840c67",
28
28
  "kind": "module",
29
29
  "path": "../../adoption/src/mod.ts"
30
30
  },
@@ -34,37 +34,37 @@
34
34
  "path": "../../adoption/src/portable/condenseWhitespace.ts"
35
35
  },
36
36
  {
37
- "hash": "0661f0dd",
37
+ "hash": "3867c304",
38
38
  "kind": "module",
39
39
  "path": "../../adoption/src/portable/listDirectoryAscents.ts"
40
40
  },
41
41
  {
42
- "hash": "07c8358f",
42
+ "hash": "982f3e6d",
43
43
  "kind": "module",
44
44
  "path": "../../adoption/src/portable/listFunctionBodies.ts"
45
45
  },
46
46
  {
47
- "hash": "2d9f1edb",
47
+ "hash": "ce2e063d",
48
48
  "kind": "module",
49
49
  "path": "../../adoption/src/portable/listTemplateLiterals.ts"
50
50
  },
51
51
  {
52
- "hash": "b0751395",
52
+ "hash": "a5dc0993",
53
53
  "kind": "module",
54
54
  "path": "../../adoption/src/portable/readAnchoredWindow.ts"
55
55
  },
56
56
  {
57
- "hash": "0eb1daf1",
57
+ "hash": "9ff7cd2c",
58
58
  "kind": "module",
59
59
  "path": "../../adoption/src/portable/readBalancedGroup.ts"
60
60
  },
61
61
  {
62
- "hash": "e9427d50",
62
+ "hash": "81846f1a",
63
63
  "kind": "module",
64
64
  "path": "../../adoption/src/portable/readLiteral.ts"
65
65
  },
66
66
  {
67
- "hash": "24f6e6db",
67
+ "hash": "eecd2c1e",
68
68
  "kind": "module",
69
69
  "path": "kits/default.ts"
70
70
  },
@@ -74,32 +74,32 @@
74
74
  "path": "../src/readiness/adoptedExports.ts"
75
75
  },
76
76
  {
77
- "hash": "f14085f3",
77
+ "hash": "67b9483f",
78
78
  "kind": "module",
79
79
  "path": "../src/readiness/listClampNestLines.ts"
80
80
  },
81
81
  {
82
- "hash": "eabb769f",
82
+ "hash": "a80a25c8",
83
83
  "kind": "module",
84
84
  "path": "../src/readiness/listMathIdioms.ts"
85
85
  },
86
86
  {
87
- "hash": "827c07b2",
87
+ "hash": "e7ef3938",
88
88
  "kind": "module",
89
89
  "path": "../src/readiness/listRandomIntegerLines.ts"
90
90
  },
91
91
  {
92
- "hash": "bdcac255",
92
+ "hash": "3a93c656",
93
93
  "kind": "module",
94
94
  "path": "../src/readiness/listRoundScaleLines.ts"
95
95
  }
96
96
  ],
97
97
  "name": "default",
98
98
  "path": "kits/default.js",
99
- "readyupVersion": "0.37.0",
99
+ "readyupVersion": "0.40.0",
100
100
  "source": "kits/default.ts",
101
- "sourceHash": "24f6e6db",
102
- "targetHash": "55bc7a45"
101
+ "sourceHash": "eecd2c1e",
102
+ "targetHash": "3296a47b"
103
103
  }
104
104
  ]
105
105
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 7.2.3 — 2026-10-09
6
+
7
+ ### 📚 Documentation
8
+
9
+ - Updates each kit README to show `rdy run --sources` and a `sources: ['npm:…']` config example, and states that this spelling needs readyup 0.40.0 or later. (#371)
10
+
11
+ ## 7.2.2 — 2026-10-02
12
+
13
+ ### 📚 Documentation
14
+
15
+ - Audits the comments in every authored TypeScript, JavaScript, shell, and YAML source and every `tsconfig*.json` against the comment discipline, cutting comments that paraphrase the code or narrate history, rewriting doc descriptions in the third-person indicative, and adding descriptions to the functions, methods, and classes that had none. (#353)
16
+ - Adds `@category` tags to 50 exported tier functions and classes, and `@stage` tags to the 49 of them that lacked one, which puts those 49 under the check in `stage-tag-alignment`. (#353)
17
+ - Revises READMEs, doc comments, and test names across the repository to follow the current `plain-speech` and writing-preference rules. (#354)
18
+ - Rewords the help text and messages printed by `tb-jira`, `tb-node`, and `tb-secret`, and the advice and skip reasons reported by the adoption kits, to follow the same writing conventions. (#354)
19
+
5
20
  ## 7.2.0 — 2026-09-15
6
21
 
7
22
  ### 🎉 Features
@@ -284,6 +299,50 @@ All notable changes to this project will be documented in this file.
284
299
 
285
300
  ### 📦 Dependencies
286
301
 
302
+ - Adapt to dependency upgrades and bump Node engine to >=24 (#8)
303
+
304
+ Upgrades all dependencies to their latest versions, bumps the Node.js engine requirement from >=18.17.0 to >=24.0.0 across all 13 workspace packages, and adapts source code to satisfy new lint rules introduced by the upgraded ESLint plugins. Also upgrades `@williamthorsen/eslint-config-typescript` from 5.12.1 to 5.12.2 to fix ESM import issues in the compiled output.
305
+
306
+ Commit details:
307
+
308
+ - root|deps: Upgrade all deps to latest version
309
+
310
+ - root|refactor: Fix lint
311
+
312
+ - root|deps: Upgrade all deps to latest minor version
313
+
314
+ - root|deps: Allow unpatchable vulns in dev deps
315
+
316
+ - root|refactor: Adapt to dependency upgrades and bump Node engine to >=24
317
+ * Upgrade eslint-config-typescript to 5.12.2 (fixes ESM import issues, removes need for pnpm patch)
318
+ * Bump engines.node from >=18.17.0 to >=24.0.0 across all packages
319
+ * Update CI to Node 24.14.0 and pnpm 10.30.3
320
+ * Replace .sort() with .toSorted() to satisfy unicorn/no-array-sort
321
+ * Fix lint errors: remove useless default assignments, redundant type constituents, deprecated re-exports, and empty array args to Set constructor
322
+ - datetime|tests: Fix locale mismatch in Timestamp test
323
+
324
+ Pass the same 'en-US' locale to both the expected-value computation and
325
+ the method under test. Previously the test used the system default locale
326
+ for the expected value but explicit 'en-US' for the actual call, which
327
+ diverged under Node 24's updated Intl formatting.
328
+
329
+ - root|refactor: Replace toThrow with toThrowError across all tests
330
+
331
+ The vitest/no-alias-methods rule in strict-lint requires the canonical
332
+ toThrowError() name instead of the toThrow() alias.
333
+
334
+ - root|refactor: Fix remaining strict-lint errors
335
+ * Use import() in vi.mock for vitest/prefer-import-in-mock
336
+ * Replace expect(typeof x).toBe() with expectTypeOf for vitest/prefer-expect-type-of
337
+ * Use String.raw for regex escapes for unicorn/prefer-string-raw
338
+ - root|tooling: Use ws runner to fix recursive build command
339
+
340
+ 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.
341
+
342
+ ## 4.3.0 — 2026-03-08
343
+
344
+ ### 📦 Dependencies
345
+
287
346
  - Adapt to dependency upgrades and bump Node engine to >=24 (#8)
288
347
 
289
348
  Upgrades all dependencies to their latest versions, bumps the Node.js engine requirement from >=18.17.0 to >=24.0.0 across all 13 workspace packages, and adapts source code to satisfy new lint rules introduced by the upgraded ESLint plugins. Also upgrades `@williamthorsen/eslint-config-typescript` from 5.12.1 to 5.12.2 to fix ESM import issues in the compiled output.
package/README.md CHANGED
@@ -22,7 +22,7 @@ Requires Node.js 24 or later.
22
22
  clamp(value: number, bounds: { min?: number; max?: number }): number;
23
23
  ```
24
24
 
25
- Returns the value constrained to the inclusive bounds; an omitted bound leaves that side unconstrained. A reversed range or a `NaN` bound throws a `RangeError`, where the `Math.max(min, Math.min(max, value))` idiom that it replaces returns a value for both. A `NaN` value passes through.
25
+ Returns the value constrained to the inclusive bounds; an omitted bound leaves that side unconstrained. `clamp` throws a `RangeError` for a reversed range or a `NaN` bound, whereas the `Math.max(min, Math.min(max, value))` idiom that it replaces returns a value for both. It passes a `NaN` value through.
26
26
 
27
27
  ```ts
28
28
  import { clamp } from '@williamthorsen/toolbelt.numbers/candidate';
@@ -37,7 +37,7 @@ clamp(-5, { min: 0 }); // 0
37
37
  round(value: number, nDecimalPlaces?: number): number;
38
38
  ```
39
39
 
40
- Returns the value rounded to the given number of decimal places, or to a whole number where none is given.
40
+ Returns the value rounded to the given number of decimal places, or to a whole number when none is given.
41
41
 
42
42
  ```ts
43
43
  import { round } from '@williamthorsen/toolbelt.numbers/candidate';
@@ -63,17 +63,17 @@ pickInteger({ min: 1, max: 6 }); // 1 through 6
63
63
 
64
64
  ## Adoption checks
65
65
 
66
- The package ships a ReadyUp kit, so a project that installs it can ask how far its adoption got:
66
+ The package includes a ReadyUp kit. A project that installs it can ask how far its adoption got:
67
67
 
68
68
  ```sh
69
- rdy run --packages
69
+ rdy run --sources
70
70
  ```
71
71
 
72
- The kit reads the project's tracked sources and reports every hand-rolled clamp, decimal rounding, and random integer in them, each counted against the calls that the project already makes into this package. All three report at `recommend`: They are correct code that a published utility expresses better, not defects.
72
+ The kit reads the project's tracked sources and reports every hand-rolled clamp, decimal rounding, and random integer in them, each counted against the calls that the project already makes into this package. The kit reports all three at `recommend`: They are correct code that a published utility expresses better, not defects.
73
73
 
74
74
  A random integer used as an array subscript is left alone. That site belongs to `@williamthorsen/toolbelt.arrays`, whose `pickItem` covers it, and reporting it here would mean seeing one line twice under conflicting advice.
75
75
 
76
- Bootstrap wrappers under `bin/` are exempt: Such a wrapper imports only builtins so its build-first message survives an incomplete install, and importing this package there would replace that message with a module-resolution failure. Tests are exempt too, since they compute these values deliberately. A source declared generated or vendored by the project in its own `.gitattributes`, under `linguist-generated` or `linguist-vendored`, is exempt as well: The sweep drops it before the kit sees it, so committed bundler output yields no advice that anyone could act on. The sweep is readyup's, so this holds on readyup 0.35.0 or later.
76
+ Bootstrap wrappers under `bin/` are exempt: Such a wrapper imports only builtins so that its build-first message survives an incomplete install, and importing this package there would replace that message with a module-resolution failure. Tests are exempt too, since they compute these values deliberately. A source declared generated or vendored by the project in its own `.gitattributes`, under `linguist-generated` or `linguist-vendored`, is exempt as well: The sweep drops it before the kit sees it, so committed bundler output yields no advice that anyone could act on. Because the sweep is readyup's, this holds on readyup 0.35.0 or later.
77
77
 
78
78
  A reviewed site is silenced by an `rdy-ignore` pragma on its own line, or `rdy-ignore-next-line` on the line above. A pragma naming a check's id suppresses that check alone; with no id it covers every check on the line. A failed check prints its id ahead of its fraction, which is the form to write:
79
79
 
@@ -82,10 +82,10 @@ A reviewed site is silenced by an `rdy-ignore` pragma on its own line, or `rdy-i
82
82
  const bounded = Math.max(min, Math.min(max, value));
83
83
  ```
84
84
 
85
- Add the package to `.config/readyup.config.ts` to include it in a routine sweep:
85
+ Add the package to `.config/readyup.config.ts` to include it in a routine sweep, a spelling that readyup 0.40.0 or later reads:
86
86
 
87
87
  ```ts
88
88
  export default defineRdyConfig({
89
- packages: ['@williamthorsen/toolbelt.numbers'],
89
+ sources: ['npm:@williamthorsen/toolbelt.numbers'],
90
90
  });
91
91
  ```
@@ -3,5 +3,9 @@ import { type Seed } from '../internal/evaluateSeed.js';
3
3
  * Returns a number generator whose output, when invoked successively, is a pseudo-random
4
4
  * series of numbers that deterministically depend on the initial seed (or pseudo-random if no seed is given).
5
5
  * This is not intended to be a cryptographically secure random number generator.
6
+ *
7
+ * @category Number
8
+ * @experimental
9
+ * @stage proposed
6
10
  */
7
11
  export declare function makeRng(seed?: Seed): () => number;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Returns the number rounded to the given number of decimal places, or 0 if no nDecimalPlaces is specified.
2
+ * Returns the number rounded to the given number of decimal places.
3
3
  * @param value
4
4
  * @param nDecimalPlaces
5
5
  *
@@ -1,18 +1,24 @@
1
1
  import { type Seed, type SeededGenerator } from '../internal/evaluateSeed.js';
2
2
  /**
3
- * Class that manages a pseudo-random number generator that behaves deterministically when given a seed.
3
+ * A pseudo-random number generator that behaves deterministically when given a seed.
4
+ *
5
+ * @category Number
6
+ * @experimental
7
+ * @stage candidate
4
8
  */
5
9
  export declare class SeededRng implements SeededGenerator {
6
10
  private _seed;
7
11
  private baseSeed;
8
12
  private nIncrements;
9
- /**
10
- * Constructor
11
- */
13
+ /** Creates a generator from the seed, or from a random seed when none is given. */
12
14
  constructor(seed?: Seed);
15
+ /** Returns the upper bound of the seed range, as an accessor because a static property cannot be overridden. */
13
16
  get maxBase(): number;
17
+ /** Returns a function that yields the next value on each call, sharing this instance's state. */
14
18
  get rng(): () => number;
19
+ /** Returns the current seed. */
15
20
  get seed(): number;
21
+ /** Resolves a seed-like value to a number. */
16
22
  static evaluateSeed(seed?: Seed): number | undefined;
17
23
  /**
18
24
  * Creates a child from a seed without mutating the parent seed.
@@ -21,36 +27,59 @@ export declare class SeededRng implements SeededGenerator {
21
27
  static clone<T extends ThisConstructor<typeof SeededRng>>(this: T, seed: Seed, nIncrements?: number): This<T>;
22
28
  static clone<T extends ThisConstructor<typeof SeededRng>>(this: T, seed: Seed | undefined, nIncrements?: number): This<T> | undefined;
23
29
  /**
24
- * Clones the given seed or creates a new one if none is given.
30
+ * Clones the given seed, or creates a randomly seeded generator when none is given.
25
31
  */
26
32
  static cloneOrCreate<T extends ThisConstructor<typeof SeededRng>>(this: T, seed?: Seed, nIncrements?: number): This<T>;
33
+ /** Creates a child from a seed, advancing the seed when it is a generator. */
27
34
  static spawn<T extends ThisConstructor<typeof SeededRng>>(this: T, seed: undefined): undefined;
28
35
  static spawn<T extends ThisConstructor<typeof SeededRng>>(this: T, seed: Seed): This<T>;
29
36
  static spawn<T extends ThisConstructor<typeof SeededRng>>(this: T, seed: Seed | undefined): This<T> | undefined;
30
37
  /**
31
- * Given a seed-accepting function and an optional seed, returns a new function that passes the seed to the function.
38
+ * Wraps a seed-accepting function so that every call passes it one generator spawned from the seed.
32
39
  * The spawned generator is an instance of the class on which the method is called, so subclasses supply their
33
40
  * own sequence.
34
41
  */
35
42
  static withSeed<TOptions extends object, R>(fn: (options?: OptionsWithSeed<TOptions> | OptionsWithSeed<EmptyObject>) => R, seed: Seed | undefined): (options?: TOptions) => R;
43
+ /** Returns a copy of this generator, advanced by the given number of increments. */
36
44
  clone<T extends SeededRng>(this: T, nIncrements?: number): T;
37
45
  /** Safely increments the seed by the given number of increments */
38
46
  increment(nIncrements?: number): this;
47
+ /** Returns the next value in the pseudo-random sequence, then advances the seed `n` times. */
39
48
  next(n?: number): number;
40
49
  /**
41
50
  * Returns the next value in the pseudo-random sequence without incrementing the seed.
42
51
  * For use in testing and debugging.
43
52
  */
44
53
  peek(): number;
54
+ /** Maps a seed from the full integer-seed range onto this generator's range. */
45
55
  scaleDownSeed(seed: number): number;
56
+ /** Maps a seed from this generator's range onto the full integer-seed range. */
46
57
  scaleUpSeed(value: number): number;
58
+ /** Returns the value derived from the current seed. */
47
59
  protected generateValue(): number;
60
+ /** Records the base seed, wrapped into range, and starts the current seed at it. */
48
61
  protected initializeSeeds(baseSeed?: number): void;
49
62
  }
63
+ /**
64
+ * A `SeededRng` that returns integers in the range [1, Number.MAX_SAFE_INTEGER].
65
+ *
66
+ * @category Number
67
+ * @experimental
68
+ * @stage candidate
69
+ */
50
70
  export declare class IntSeededRng extends SeededRng {
71
+ /** Returns an integer derived from the current seed. */
51
72
  protected generateValue(): number;
52
73
  }
74
+ /**
75
+ * A `SeededRng` that returns integers in the range [1, 2 ** 32 - 1].
76
+ *
77
+ * @category Number
78
+ * @experimental
79
+ * @stage candidate
80
+ */
53
81
  export declare class Int32SeededRng extends SeededRng {
82
+ /** Returns an integer derived from the current seed. */
54
83
  protected generateValue(): number;
55
84
  }
56
85
  type EmptyObject = Record<string, never> | Record<number, never>;
@@ -6,6 +6,8 @@
6
6
  export declare const IntegerSeed: {
7
7
  max: number;
8
8
  multiplier: number;
9
+ /** Converts a value to an integer seed, drawing a random value when none is given. */
9
10
  toInt(value?: number): number;
11
+ /** Returns the seed that follows the given one in the Lehmer sequence. */
10
12
  next(seed: number): number;
11
13
  };
@@ -11,7 +11,7 @@ export declare function evaluateSeed(seed: Seed | undefined): number | undefined
11
11
  */
12
12
  export declare function checkIsRngLike(seed: Seed | undefined): seed is SeededGenerator;
13
13
  /**
14
- * Interface describing an object that returns a sequence of numbers.
14
+ * An object that returns a sequence of numbers and exposes its current seed.
15
15
  */
16
16
  export interface SeededGenerator {
17
17
  seed: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/toolbelt.numbers",
3
- "version": "7.2.1",
3
+ "version": "7.2.3",
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.6.1",
50
+ "@williamthorsen/toolbelt.testing": "0.6.3",
51
51
  "esbuild": "0.28.2",
52
- "readyup": "0.37.0"
52
+ "readyup": "0.40.0"
53
53
  },
54
54
  "engines": {
55
55
  "node": ">=24.0.0"