@fuzdev/fuz_util 0.42.0 → 0.43.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.
Files changed (46) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +19 -12
  3. package/dist/async.d.ts +2 -2
  4. package/dist/async.d.ts.map +1 -1
  5. package/dist/async.js +2 -2
  6. package/dist/benchmark.d.ts +179 -0
  7. package/dist/benchmark.d.ts.map +1 -0
  8. package/dist/benchmark.js +400 -0
  9. package/dist/benchmark_baseline.d.ts +195 -0
  10. package/dist/benchmark_baseline.d.ts.map +1 -0
  11. package/dist/benchmark_baseline.js +415 -0
  12. package/dist/benchmark_format.d.ts +92 -0
  13. package/dist/benchmark_format.d.ts.map +1 -0
  14. package/dist/benchmark_format.js +327 -0
  15. package/dist/benchmark_stats.d.ts +112 -0
  16. package/dist/benchmark_stats.d.ts.map +1 -0
  17. package/dist/benchmark_stats.js +336 -0
  18. package/dist/benchmark_types.d.ts +174 -0
  19. package/dist/benchmark_types.d.ts.map +1 -0
  20. package/dist/benchmark_types.js +1 -0
  21. package/dist/library_json.d.ts +3 -3
  22. package/dist/library_json.d.ts.map +1 -1
  23. package/dist/library_json.js +1 -1
  24. package/dist/object.js +1 -1
  25. package/dist/stats.d.ts +126 -0
  26. package/dist/stats.d.ts.map +1 -0
  27. package/dist/stats.js +262 -0
  28. package/dist/time.d.ts +161 -0
  29. package/dist/time.d.ts.map +1 -0
  30. package/dist/time.js +260 -0
  31. package/dist/timings.d.ts +1 -7
  32. package/dist/timings.d.ts.map +1 -1
  33. package/dist/timings.js +16 -16
  34. package/package.json +21 -19
  35. package/src/lib/async.ts +3 -3
  36. package/src/lib/benchmark.ts +498 -0
  37. package/src/lib/benchmark_baseline.ts +573 -0
  38. package/src/lib/benchmark_format.ts +379 -0
  39. package/src/lib/benchmark_stats.ts +448 -0
  40. package/src/lib/benchmark_types.ts +197 -0
  41. package/src/lib/library_json.ts +3 -3
  42. package/src/lib/object.ts +1 -1
  43. package/src/lib/stats.ts +353 -0
  44. package/src/lib/time.ts +314 -0
  45. package/src/lib/timings.ts +17 -17
  46. package/src/lib/types.ts +2 -2
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) Ryan Atkinson <mail@ryanatkn.com> <https://ryanatkn.com/>
3
+ Copyright (c) fuz.dev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # @ryanatkn/belt
1
+ # @fuzdev/fuz_util
2
2
 
3
- [<img src="static/logo.svg" alt="a green sauropod wearing a brown utility belt" align="right" width="256" height="256">](https://belt.ryanatkn.com/)
3
+ [<img src="static/logo.svg" alt="a green sauropod wearing a brown utility belt" align="right" width="256" height="256">](https://util.fuz.dev/)
4
4
 
5
5
  > utility belt for JS 🦕 ancient not extinct
6
6
 
7
- **[belt.ryanatkn.com](https://belt.ryanatkn.com)**
7
+ **[util.fuz.dev](https://util.fuz.dev)**
8
8
 
9
9
  design:
10
10
 
@@ -15,32 +15,39 @@ design:
15
15
  - mix of JS module environments - browser-only, Node-only, universal
16
16
  - mostly small pure functions
17
17
  - all TypeScript, for styles and Svelte and SvelteKit
18
- see <a href="https://github.com/fuz-dev/fuz">@ryanatkn/fuz</a>
18
+ see <a href="https://github.com/fuz-dev/fuz">@fuzdev/fuz_ui</a>
19
19
  - complements the modern web platform, drops legacy quickly
20
20
  - kinda minimal in many ways but also not, treeshakes well
21
+ - includes a benchmarking library with rich statistical analysis
21
22
 
22
23
  ## usage
23
24
 
24
- Install from [npm](https://www.npmjs.com/package/@ryanatkn/belt):
25
+ Install from [npm](https://www.npmjs.com/package/@fuzdev/fuz_util):
25
26
 
26
27
  ```bash
27
- npm i -D @ryanatkn/belt
28
+ npm i -D @fuzdev/fuz_util
28
29
  ```
29
30
 
30
31
  Import modules at their full paths:
31
32
 
32
33
  ```ts
33
- import {type Result, unwrap} from '@ryanatkn/belt/result.js';
34
- import {random_int} from '@ryanatkn/belt/random.js';
34
+ import {type Result, unwrap} from '@fuzdev/fuz_util/result.js';
35
+ import {random_int} from '@fuzdev/fuz_util/random.js';
35
36
  ```
36
37
 
37
38
  `.ts` imports also work:
38
39
 
39
40
  ```ts
40
- import {deep_equal} from '@ryanatkn/belt/deep_equal.ts';
41
+ import {deep_equal} from '@fuzdev/fuz_util/deep_equal.ts';
41
42
  ```
42
43
 
43
- Docs at [belt.ryanatkn.com/docs](https://belt.ryanatkn.com/docs).
44
+ Docs at [util.fuz.dev/docs](https://util.fuz.dev/docs).
45
+
46
+ ## features
47
+
48
+ ### Benchmarking
49
+
50
+ See [`docs/benchmark.md`](docs/benchmark.md).
44
51
 
45
52
  ## build
46
53
 
@@ -52,13 +59,13 @@ gro build
52
59
 
53
60
  ## test
54
61
 
55
- For more see [`uvu`](https://github.com/lukeed/uvu)
62
+ For more see [Vitest](https://github.com/vitest-dev/vitest)
56
63
  and [Gro's test docs](https://github.com/feltjs/gro/blob/main/src/docs/test.md).
57
64
 
58
65
  ```bash
59
66
  gro test
60
67
  gro test filepattern1 filepatternB
61
- gro test -- uvu --forwarded_args 'to uvu'
68
+ gro test -- --forwarded-args 'to vitest'
62
69
  ```
63
70
 
64
71
  ## deploy
package/dist/async.d.ts CHANGED
@@ -4,9 +4,9 @@ export type AsyncStatus = 'initial' | 'pending' | 'success' | 'failure';
4
4
  */
5
5
  export declare const wait: (duration?: number) => Promise<void>;
6
6
  /**
7
- * Checks if `value` is a `Promise`.
7
+ * Checks if `value` is a `Promise` (or thenable).
8
8
  */
9
- export declare const is_promise: (value: any) => value is Promise<any>;
9
+ export declare const is_promise: (value: unknown) => value is Promise<unknown>;
10
10
  /**
11
11
  * Creates a deferred object with a promise and its resolve/reject handlers.
12
12
  */
@@ -1 +1 @@
1
- {"version":3,"file":"async.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/async.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,iBAAY,KAAG,OAAO,CAAC,IAAI,CACQ,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,GAAG,KAAG,KAAK,IAAI,OAAO,CAAC,GAAG,CAClB,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAC9B;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,OAAK,QAAQ,CAAC,CAAC,CAQ/C,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,GAAU,CAAC,EAAE,CAAC,EACxC,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,aAAa,MAAM,KACjB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAoDlB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,sBAAsB,GAAU,CAAC,EAAE,CAAC,EAChD,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,aAAa,MAAM,KACjB,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CA6CxC,CAAC"}
1
+ {"version":3,"file":"async.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/async.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,iBAAY,KAAG,OAAO,CAAC,IAAI,CACQ,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,OAAO,CAAC,OAAO,CACI,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAC9B;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,OAAK,QAAQ,CAAC,CAAC,CAQ/C,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,GAAU,CAAC,EAAE,CAAC,EACxC,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,aAAa,MAAM,KACjB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAoDlB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,sBAAsB,GAAU,CAAC,EAAE,CAAC,EAChD,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,aAAa,MAAM,KACjB,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CA6CxC,CAAC"}
package/dist/async.js CHANGED
@@ -3,9 +3,9 @@
3
3
  */
4
4
  export const wait = (duration = 0) => new Promise((resolve) => setTimeout(resolve, duration));
5
5
  /**
6
- * Checks if `value` is a `Promise`.
6
+ * Checks if `value` is a `Promise` (or thenable).
7
7
  */
8
- export const is_promise = (value) => value && typeof value.then === 'function';
8
+ export const is_promise = (value) => value != null && typeof value.then === 'function';
9
9
  /**
10
10
  * Creates a object with a `promise` and its `resolve`/`reject` handlers.
11
11
  */
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Benchmarking library.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import {Benchmark} from './benchmark.js';
7
+ *
8
+ * const bench = new Benchmark({
9
+ * duration_ms: 5000,
10
+ * warmup_iterations: 5,
11
+ * });
12
+ *
13
+ * bench
14
+ * .add('slugify', () => slugify(title))
15
+ * .add('slugify_slower', () => slugify_slower(title));
16
+ *
17
+ * const results = await bench.run();
18
+ * console.log(bench.table());
19
+ * ```
20
+ */
21
+ import { type BenchmarkFormatJsonOptions } from './benchmark_format.js';
22
+ import type { BenchmarkConfig, BenchmarkTask, BenchmarkResult, BenchmarkFormatTableOptions } from './benchmark_types.js';
23
+ /**
24
+ * Warmup function by running it multiple times.
25
+ * Detects whether the function is async based on return value.
26
+ *
27
+ * @param fn - Function to warmup (sync or async)
28
+ * @param iterations - Number of warmup iterations
29
+ * @param async_hint - If provided, use this instead of detecting
30
+ * @returns Whether the function is async
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * const is_async = await benchmark_warmup(() => expensive_operation(), 10);
35
+ * ```
36
+ */
37
+ export declare const benchmark_warmup: (fn: () => unknown, iterations: number, async_hint?: boolean) => Promise<boolean>;
38
+ /**
39
+ * Benchmark class for measuring and comparing function performance.
40
+ */
41
+ export declare class Benchmark {
42
+ #private;
43
+ constructor(config?: BenchmarkConfig);
44
+ /**
45
+ * Add a benchmark task.
46
+ * @param name - Task name or full task object
47
+ * @param fn - Function to benchmark (if name is string). Return values are ignored.
48
+ * @returns This Benchmark instance for chaining
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * bench.add('simple', () => fn());
53
+ *
54
+ * // Or with setup/teardown:
55
+ * bench.add({
56
+ * name: 'with setup',
57
+ * fn: () => process(data),
58
+ * setup: () => { data = load() },
59
+ * teardown: () => { cleanup() },
60
+ * });
61
+ * ```
62
+ */
63
+ add(name: string, fn: () => unknown): this;
64
+ add(task: BenchmarkTask): this;
65
+ /**
66
+ * Remove a benchmark task by name.
67
+ * @param name - Name of the task to remove
68
+ * @returns This Benchmark instance for chaining
69
+ * @throws Error if task with given name doesn't exist
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * bench.add('task1', () => fn1());
74
+ * bench.add('task2', () => fn2());
75
+ * bench.remove('task1');
76
+ * // Only task2 remains
77
+ * ```
78
+ */
79
+ remove(name: string): this;
80
+ /**
81
+ * Mark a task to be skipped during benchmark runs.
82
+ * @param name - Name of the task to skip
83
+ * @returns This Benchmark instance for chaining
84
+ * @throws Error if task with given name doesn't exist
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * bench.add('task1', () => fn1());
89
+ * bench.add('task2', () => fn2());
90
+ * bench.skip('task1');
91
+ * // Only task2 will run
92
+ * ```
93
+ */
94
+ skip(name: string): this;
95
+ /**
96
+ * Mark a task to run exclusively (along with other `only` tasks).
97
+ * @param name - Name of the task to run exclusively
98
+ * @returns This Benchmark instance for chaining
99
+ * @throws Error if task with given name doesn't exist
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * bench.add('task1', () => fn1());
104
+ * bench.add('task2', () => fn2());
105
+ * bench.add('task3', () => fn3());
106
+ * bench.only('task2');
107
+ * // Only task2 will run
108
+ * ```
109
+ */
110
+ only(name: string): this;
111
+ /**
112
+ * Run all benchmark tasks.
113
+ * @returns Array of benchmark results
114
+ */
115
+ run(): Promise<Array<BenchmarkResult>>;
116
+ /**
117
+ * Format results as an ASCII table with percentiles, min/max, and relative performance.
118
+ * @param options - Formatting options
119
+ * @returns Formatted table string
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * // Standard table
124
+ * console.log(bench.table());
125
+ *
126
+ * // Grouped by category
127
+ * console.log(bench.table({
128
+ * groups: [
129
+ * { name: 'FAST PATHS', filter: (r) => r.name.includes('fast') },
130
+ * { name: 'SLOW PATHS', filter: (r) => r.name.includes('slow') },
131
+ * ]
132
+ * }));
133
+ * ```
134
+ */
135
+ table(options?: BenchmarkFormatTableOptions): string;
136
+ /**
137
+ * Format results as a Markdown table.
138
+ * @returns Formatted markdown string
139
+ */
140
+ markdown(): string;
141
+ /**
142
+ * Format results as JSON.
143
+ * @param options - Formatting options (pretty, include_timings)
144
+ * @returns JSON string
145
+ */
146
+ json(options?: BenchmarkFormatJsonOptions): string;
147
+ /**
148
+ * Get the benchmark results.
149
+ * Returns a shallow copy to prevent external mutation.
150
+ * @returns Array of benchmark results
151
+ */
152
+ results(): Array<BenchmarkResult>;
153
+ /**
154
+ * Reset the benchmark results.
155
+ * Keeps tasks intact so benchmarks can be rerun.
156
+ * @returns This Benchmark instance for chaining
157
+ */
158
+ reset(): this;
159
+ /**
160
+ * Clear everything (results and tasks).
161
+ * Use this to start fresh with a new set of benchmarks.
162
+ * @returns This Benchmark instance for chaining
163
+ */
164
+ clear(): this;
165
+ /**
166
+ * Get a quick text summary of the fastest task.
167
+ * @returns Human-readable summary string
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * console.log(bench.summary());
172
+ * // "Fastest: slugify_v2 (1,285,515.00 ops/sec, 786.52ns per op)"
173
+ * // "Slowest: slugify (252,955.00 ops/sec, 3.95μs per op)"
174
+ * // "Speed difference: 5.08x"
175
+ * ```
176
+ */
177
+ summary(): string;
178
+ }
179
+ //# sourceMappingURL=benchmark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmark.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/benchmark.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,EAMN,KAAK,0BAA0B,EAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACX,eAAe,EACf,aAAa,EACb,eAAe,EACf,2BAA2B,EAC3B,MAAM,sBAAsB,CAAC;AAgD9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,GAC5B,IAAI,MAAM,OAAO,EACjB,YAAY,MAAM,EAClB,aAAa,OAAO,KAClB,OAAO,CAAC,OAAO,CAyBjB,CAAC;AAEF;;GAEG;AACH,qBAAa,SAAS;;gBAMT,MAAM,GAAE,eAAoB;IAcxC;;;;;;;;;;;;;;;;;;OAkBG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,GAAG,IAAI;IAC1C,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAkB9B;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAS1B;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IASxB;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IASxB;;;OAGG;IACG,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAqH5C;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,2BAA2B,GAAG,MAAM;IAMpD;;;OAGG;IACH,QAAQ,IAAI,MAAM;IAIlB;;;;OAIG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,MAAM;IAIlD;;;;OAIG;IACH,OAAO,IAAI,KAAK,CAAC,eAAe,CAAC;IAIjC;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAKb;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAMb;;;;;;;;;;;OAWG;IACH,OAAO,IAAI,MAAM;CA+BjB"}