@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
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Benchmark-specific statistical analysis.
3
+ * Uses the general stats utilities from stats.ts for timing/performance analysis.
4
+ * All timing values are in nanoseconds.
5
+ */
6
+ import { TIME_NS_PER_SEC, time_format_adaptive } from './time.js';
7
+ import { stats_mean, stats_median, stats_std_dev, stats_percentile, stats_cv, stats_min_max, stats_confidence_interval, stats_outliers_mad, } from './stats.js';
8
+ /**
9
+ * Complete statistical analysis of timing measurements.
10
+ * Includes outlier detection, descriptive statistics, and performance metrics.
11
+ * All timing values are in nanoseconds.
12
+ */
13
+ export class BenchmarkStats {
14
+ /** Mean (average) time in nanoseconds */
15
+ mean_ns;
16
+ /** Median time in nanoseconds */
17
+ median_ns;
18
+ /** Standard deviation in nanoseconds */
19
+ std_dev_ns;
20
+ /** Minimum time in nanoseconds */
21
+ min_ns;
22
+ /** Maximum time in nanoseconds */
23
+ max_ns;
24
+ /** 75th percentile in nanoseconds */
25
+ p75_ns;
26
+ /** 90th percentile in nanoseconds */
27
+ p90_ns;
28
+ /** 95th percentile in nanoseconds */
29
+ p95_ns;
30
+ /** 99th percentile in nanoseconds */
31
+ p99_ns;
32
+ /** Coefficient of variation (std_dev / mean) */
33
+ cv;
34
+ /** 95% confidence interval for the mean in nanoseconds */
35
+ confidence_interval_ns;
36
+ /** Array of detected outlier values in nanoseconds */
37
+ outliers_ns;
38
+ /** Ratio of outliers to total samples */
39
+ outlier_ratio;
40
+ /** Number of samples after outlier removal */
41
+ sample_size;
42
+ /** Original number of samples (before outlier removal) */
43
+ raw_sample_size;
44
+ /** Operations per second (NS_PER_SEC / mean_ns) */
45
+ ops_per_second;
46
+ /** Number of failed iterations (NaN, Infinity, or negative values) */
47
+ failed_iterations;
48
+ constructor(timings_ns) {
49
+ // Filter out invalid values (NaN, Infinity, negative)
50
+ const valid_timings = [];
51
+ let failed_count = 0;
52
+ for (const t of timings_ns) {
53
+ if (!isNaN(t) && isFinite(t) && t > 0) {
54
+ valid_timings.push(t);
55
+ }
56
+ else {
57
+ failed_count++;
58
+ }
59
+ }
60
+ this.failed_iterations = failed_count;
61
+ this.raw_sample_size = timings_ns.length;
62
+ // If no valid timings, return empty stats
63
+ if (valid_timings.length === 0) {
64
+ this.mean_ns = NaN;
65
+ this.median_ns = NaN;
66
+ this.std_dev_ns = NaN;
67
+ this.min_ns = NaN;
68
+ this.max_ns = NaN;
69
+ this.p75_ns = NaN;
70
+ this.p90_ns = NaN;
71
+ this.p95_ns = NaN;
72
+ this.p99_ns = NaN;
73
+ this.cv = NaN;
74
+ this.confidence_interval_ns = [NaN, NaN];
75
+ this.outliers_ns = [];
76
+ this.outlier_ratio = 0;
77
+ this.sample_size = 0;
78
+ this.ops_per_second = 0;
79
+ return;
80
+ }
81
+ // Detect and remove outliers
82
+ const { cleaned, outliers } = stats_outliers_mad(valid_timings);
83
+ const sorted_cleaned = [...cleaned].sort((a, b) => a - b);
84
+ this.outliers_ns = outliers;
85
+ this.outlier_ratio = outliers.length / valid_timings.length;
86
+ this.sample_size = cleaned.length;
87
+ // Calculate statistics on cleaned data
88
+ this.mean_ns = stats_mean(cleaned);
89
+ this.median_ns = stats_median(sorted_cleaned);
90
+ this.std_dev_ns = stats_std_dev(cleaned, this.mean_ns);
91
+ const { min, max } = stats_min_max(sorted_cleaned);
92
+ this.min_ns = min;
93
+ this.max_ns = max;
94
+ this.p75_ns = stats_percentile(sorted_cleaned, 0.75);
95
+ this.p90_ns = stats_percentile(sorted_cleaned, 0.9);
96
+ this.p95_ns = stats_percentile(sorted_cleaned, 0.95);
97
+ this.p99_ns = stats_percentile(sorted_cleaned, 0.99);
98
+ this.cv = stats_cv(this.mean_ns, this.std_dev_ns);
99
+ this.confidence_interval_ns = stats_confidence_interval(cleaned);
100
+ // Calculate throughput (operations per second)
101
+ this.ops_per_second = this.mean_ns > 0 ? TIME_NS_PER_SEC / this.mean_ns : 0;
102
+ }
103
+ /**
104
+ * Format stats as a human-readable string.
105
+ */
106
+ toString() {
107
+ return `BenchmarkStats(mean=${time_format_adaptive(this.mean_ns)}, ops/sec=${this.ops_per_second.toFixed(2)}, cv=${(this.cv * 100).toFixed(1)}%, samples=${this.sample_size})`;
108
+ }
109
+ }
110
+ /**
111
+ * Compare two benchmark results for statistical significance.
112
+ * Uses Welch's t-test (handles unequal variances) and Cohen's d effect size.
113
+ *
114
+ * @param a - First benchmark stats (or any object with required properties)
115
+ * @param b - Second benchmark stats (or any object with required properties)
116
+ * @param options - Comparison options
117
+ * @returns Comparison result with significance, effect size, and recommendation
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * const comparison = benchmark_stats_compare(result_a.stats, result_b.stats);
122
+ * if (comparison.significant) {
123
+ * console.log(`${comparison.faster} is ${comparison.speedup_ratio.toFixed(2)}x faster`);
124
+ * }
125
+ * ```
126
+ */
127
+ export const benchmark_stats_compare = (a, b, options) => {
128
+ const alpha = options?.alpha ?? 0.05;
129
+ // Handle edge cases
130
+ if (a.sample_size === 0 || b.sample_size === 0) {
131
+ return {
132
+ faster: 'equal',
133
+ speedup_ratio: 1,
134
+ significant: false,
135
+ p_value: 1,
136
+ effect_size: 0,
137
+ effect_magnitude: 'negligible',
138
+ ci_overlap: true,
139
+ recommendation: 'Insufficient data for comparison',
140
+ };
141
+ }
142
+ // Calculate speedup ratio (lower time = faster, so compare by time not ops/sec)
143
+ const speedup_ratio = a.mean_ns < b.mean_ns ? b.mean_ns / a.mean_ns : a.mean_ns / b.mean_ns;
144
+ const faster = a.mean_ns < b.mean_ns ? 'a' : a.mean_ns > b.mean_ns ? 'b' : 'equal';
145
+ // Welch's t-test (handles unequal variances)
146
+ // Special case: if both have zero variance, t-test is undefined
147
+ let p_value;
148
+ if (a.std_dev_ns === 0 && b.std_dev_ns === 0) {
149
+ // When there's no variance, any difference is 100% reliable (p=0) or identical (p=1)
150
+ p_value = a.mean_ns === b.mean_ns ? 1 : 0;
151
+ }
152
+ else {
153
+ const { t_statistic, degrees_of_freedom } = welch_t_test(a.mean_ns, a.std_dev_ns, a.sample_size, b.mean_ns, b.std_dev_ns, b.sample_size);
154
+ // Calculate two-tailed p-value using t-distribution approximation
155
+ p_value = t_distribution_p_value(Math.abs(t_statistic), degrees_of_freedom);
156
+ }
157
+ // Cohen's d effect size
158
+ const pooled_std_dev = Math.sqrt(((a.sample_size - 1) * a.std_dev_ns ** 2 + (b.sample_size - 1) * b.std_dev_ns ** 2) /
159
+ (a.sample_size + b.sample_size - 2));
160
+ // When pooled_std_dev is 0 but means differ, effect is maximal (infinite)
161
+ // When means are equal, effect is 0
162
+ let effect_size;
163
+ let effect_magnitude;
164
+ if (pooled_std_dev === 0) {
165
+ // Zero variance case - if means differ, it's a definitive difference
166
+ if (a.mean_ns === b.mean_ns) {
167
+ effect_size = 0;
168
+ effect_magnitude = 'negligible';
169
+ }
170
+ else {
171
+ // Any difference is 100% reliable when there's no variance
172
+ effect_size = Infinity;
173
+ effect_magnitude = 'large';
174
+ }
175
+ }
176
+ else {
177
+ effect_size = Math.abs(a.mean_ns - b.mean_ns) / pooled_std_dev;
178
+ // Interpret effect size (Cohen's conventions)
179
+ effect_magnitude =
180
+ effect_size < 0.2
181
+ ? 'negligible'
182
+ : effect_size < 0.5
183
+ ? 'small'
184
+ : effect_size < 0.8
185
+ ? 'medium'
186
+ : 'large';
187
+ }
188
+ // Check confidence interval overlap
189
+ const ci_overlap = a.confidence_interval_ns[0] <= b.confidence_interval_ns[1] &&
190
+ b.confidence_interval_ns[0] <= a.confidence_interval_ns[1];
191
+ // Determine significance
192
+ const significant = p_value < alpha;
193
+ // Generate recommendation
194
+ let recommendation;
195
+ if (!significant) {
196
+ recommendation =
197
+ effect_magnitude === 'negligible'
198
+ ? 'No meaningful difference detected'
199
+ : `Difference not statistically significant (p=${p_value.toFixed(3)}), but effect size suggests ${effect_magnitude} practical difference`;
200
+ }
201
+ else if (effect_magnitude === 'negligible') {
202
+ recommendation = `Statistically significant but negligible practical difference (${speedup_ratio.toFixed(2)}x)`;
203
+ }
204
+ else {
205
+ recommendation = `${faster === 'a' ? 'First' : 'Second'} is ${speedup_ratio.toFixed(2)}x faster with ${effect_magnitude} effect size (p=${p_value.toFixed(3)})`;
206
+ }
207
+ // Adjust 'faster' to 'equal' if effect is negligible
208
+ const adjusted_faster = effect_magnitude === 'negligible' ? 'equal' : faster;
209
+ return {
210
+ faster: adjusted_faster,
211
+ speedup_ratio,
212
+ significant,
213
+ p_value,
214
+ effect_size,
215
+ effect_magnitude,
216
+ ci_overlap,
217
+ recommendation,
218
+ };
219
+ };
220
+ /**
221
+ * Calculate Welch's t-test statistic and degrees of freedom.
222
+ * Welch's t-test is more robust than Student's t-test when variances are unequal.
223
+ */
224
+ const welch_t_test = (mean1, std1, n1, mean2, std2, n2) => {
225
+ const var1 = std1 ** 2;
226
+ const var2 = std2 ** 2;
227
+ const se1 = var1 / n1;
228
+ const se2 = var2 / n2;
229
+ const t_statistic = (mean1 - mean2) / Math.sqrt(se1 + se2);
230
+ // Welch-Satterthwaite degrees of freedom
231
+ const numerator = (se1 + se2) ** 2;
232
+ const denominator = se1 ** 2 / (n1 - 1) + se2 ** 2 / (n2 - 1);
233
+ const degrees_of_freedom = numerator / denominator;
234
+ return { t_statistic, degrees_of_freedom };
235
+ };
236
+ /**
237
+ * Approximate p-value from t-distribution using the approximation formula.
238
+ * This avoids requiring a full t-distribution table or library.
239
+ * For large df (>30), this approximation is very accurate.
240
+ */
241
+ const t_distribution_p_value = (t, df) => {
242
+ // Use normal approximation for large df
243
+ if (df > 100) {
244
+ // Standard normal CDF approximation
245
+ return 2 * (1 - normal_cdf(t));
246
+ }
247
+ // For smaller df, use a more accurate approximation
248
+ // Based on the incomplete beta function relationship
249
+ const x = df / (df + t * t);
250
+ const a = df / 2;
251
+ const b = 0.5;
252
+ // Approximation of regularized incomplete beta function
253
+ // This is accurate to about 4 decimal places for typical use cases
254
+ const beta_approx = incomplete_beta_approx(x, a, b);
255
+ return beta_approx;
256
+ };
257
+ /**
258
+ * Standard normal CDF approximation (Abramowitz and Stegun formula 7.1.26).
259
+ */
260
+ const normal_cdf = (x) => {
261
+ const t = 1 / (1 + 0.2316419 * Math.abs(x));
262
+ const d = 0.3989423 * Math.exp((-x * x) / 2);
263
+ const p = d * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));
264
+ return x > 0 ? 1 - p : p;
265
+ };
266
+ /**
267
+ * Approximate regularized incomplete beta function for p-value calculation.
268
+ * Uses continued fraction expansion for reasonable accuracy.
269
+ */
270
+ const incomplete_beta_approx = (x, a, b) => {
271
+ // Simple approximation using the relationship between beta and normal distributions
272
+ // For our use case (t-distribution p-values), this provides sufficient accuracy
273
+ if (x <= 0)
274
+ return 0;
275
+ if (x >= 1)
276
+ return 1;
277
+ // Use symmetry if needed
278
+ if (x > (a + 1) / (a + b + 2)) {
279
+ return 1 - incomplete_beta_approx(1 - x, b, a);
280
+ }
281
+ // Continued fraction approximation (first few terms)
282
+ const lnBeta = ln_gamma(a) + ln_gamma(b) - ln_gamma(a + b);
283
+ const front = Math.exp(Math.log(x) * a + Math.log(1 - x) * b - lnBeta) / a;
284
+ // Simple continued fraction (limited iterations for speed)
285
+ let f = 1;
286
+ let c = 1;
287
+ let d = 0;
288
+ for (let m = 1; m <= 100; m++) {
289
+ const m2 = 2 * m;
290
+ // Even step
291
+ let aa = (m * (b - m) * x) / ((a + m2 - 1) * (a + m2));
292
+ d = 1 + aa * d;
293
+ if (Math.abs(d) < 1e-30)
294
+ d = 1e-30;
295
+ c = 1 + aa / c;
296
+ if (Math.abs(c) < 1e-30)
297
+ c = 1e-30;
298
+ d = 1 / d;
299
+ f *= d * c;
300
+ // Odd step
301
+ aa = (-(a + m) * (a + b + m) * x) / ((a + m2) * (a + m2 + 1));
302
+ d = 1 + aa * d;
303
+ if (Math.abs(d) < 1e-30)
304
+ d = 1e-30;
305
+ c = 1 + aa / c;
306
+ if (Math.abs(c) < 1e-30)
307
+ c = 1e-30;
308
+ d = 1 / d;
309
+ const delta = d * c;
310
+ f *= delta;
311
+ if (Math.abs(delta - 1) < 1e-8)
312
+ break;
313
+ }
314
+ return front * f;
315
+ };
316
+ /**
317
+ * Log gamma function approximation (Lanczos approximation).
318
+ */
319
+ const ln_gamma = (z) => {
320
+ const g = 7;
321
+ const c = [
322
+ 0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313,
323
+ -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6,
324
+ 1.5056327351493116e-7,
325
+ ];
326
+ if (z < 0.5) {
327
+ return Math.log(Math.PI / Math.sin(Math.PI * z)) - ln_gamma(1 - z);
328
+ }
329
+ const z_adj = z - 1;
330
+ let x = c[0];
331
+ for (let i = 1; i < g + 2; i++) {
332
+ x += c[i] / (z_adj + i);
333
+ }
334
+ const t = z_adj + g + 0.5;
335
+ return 0.5 * Math.log(2 * Math.PI) + (z_adj + 0.5) * Math.log(t) - t + Math.log(x);
336
+ };
@@ -0,0 +1,174 @@
1
+ import type { BenchmarkStats } from './benchmark_stats.js';
2
+ import type { Timer } from './time.js';
3
+ /**
4
+ * Configuration options for a benchmark suite.
5
+ */
6
+ export interface BenchmarkConfig {
7
+ /**
8
+ * Target duration to run each benchmark task in milliseconds.
9
+ * The benchmark will run until this duration is reached or max_iterations is hit.
10
+ * Default: 1000ms
11
+ */
12
+ duration_ms?: number;
13
+ /**
14
+ * Number of warmup iterations before actual measurements.
15
+ * Warmup helps stabilize JIT compilation and caches.
16
+ * Default: 5
17
+ */
18
+ warmup_iterations?: number;
19
+ /**
20
+ * Cooldown time between tasks in milliseconds.
21
+ * Helps prevent interference between benchmarks.
22
+ * Default: 100ms
23
+ */
24
+ cooldown_ms?: number;
25
+ /**
26
+ * Minimum number of iterations to run.
27
+ * Default: 10
28
+ */
29
+ min_iterations?: number;
30
+ /**
31
+ * Maximum number of iterations to run.
32
+ * Prevents infinite loops if function is extremely fast.
33
+ * Default: 100000
34
+ */
35
+ max_iterations?: number;
36
+ /**
37
+ * Custom timer to use for measurements.
38
+ * Default: timer_default (auto-detects environment)
39
+ */
40
+ timer?: Timer;
41
+ /**
42
+ * Callback invoked after each iteration completes.
43
+ * Useful for triggering garbage collection, logging progress, early termination,
44
+ * or custom instrumentation.
45
+ *
46
+ * **Note**: The callback time is NOT included in iteration measurements - it runs
47
+ * after the timing capture. However, frequent GC calls will slow overall benchmark
48
+ * execution time.
49
+ *
50
+ * @param task_name - Name of the current task being benchmarked
51
+ * @param iteration - Current iteration number (1-indexed)
52
+ * @param abort - Call to stop the benchmark early for this task
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * // Trigger GC between iterations (run node with --expose-gc)
57
+ * new Benchmark({
58
+ * on_iteration: () => {
59
+ * if (globalThis.gc) globalThis.gc();
60
+ * }
61
+ * })
62
+ *
63
+ * // Log progress for long-running benchmarks
64
+ * new Benchmark({
65
+ * on_iteration: (name, iteration) => {
66
+ * if (iteration % 1000 === 0) {
67
+ * console.log(`${name}: ${iteration} iterations`);
68
+ * }
69
+ * }
70
+ * })
71
+ *
72
+ * // Stop early when converged
73
+ * new Benchmark({
74
+ * on_iteration: (name, iteration, abort) => {
75
+ * if (iteration > 1000 && has_stabilized()) abort();
76
+ * }
77
+ * })
78
+ * ```
79
+ */
80
+ on_iteration?: (task_name: string, iteration: number, abort: () => void) => void;
81
+ /**
82
+ * Callback invoked after each task completes.
83
+ * Useful for logging progress during long benchmark runs.
84
+ *
85
+ * @param result - The completed benchmark result
86
+ * @param index - Zero-based index of the completed task
87
+ * @param total - Total number of tasks to run
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * new Benchmark({
92
+ * on_task_complete: (result, index, total) => {
93
+ * console.log(`[${index + 1}/${total}] ${result.name}: ${result.stats.ops_per_second.toFixed(0)} ops/sec`);
94
+ * }
95
+ * })
96
+ * ```
97
+ */
98
+ on_task_complete?: (result: BenchmarkResult, index: number, total: number) => void;
99
+ }
100
+ /**
101
+ * A benchmark task to execute.
102
+ */
103
+ export interface BenchmarkTask {
104
+ /** Name of the task (for display) */
105
+ name: string;
106
+ /** Function to benchmark (sync or async). Return values are ignored. */
107
+ fn: () => unknown;
108
+ /**
109
+ * Optional setup function run before benchmarking this task.
110
+ * Not included in timing measurements.
111
+ */
112
+ setup?: () => void | Promise<void>;
113
+ /**
114
+ * Optional teardown function run after benchmarking this task.
115
+ * Not included in timing measurements.
116
+ */
117
+ teardown?: () => void | Promise<void>;
118
+ /**
119
+ * If true, skip this task during benchmark runs.
120
+ * Useful for temporarily disabling tasks during development.
121
+ */
122
+ skip?: boolean;
123
+ /**
124
+ * If true, run only this task (and other tasks marked `only`).
125
+ * Useful for focusing on specific tasks during development.
126
+ */
127
+ only?: boolean;
128
+ /**
129
+ * Hint for whether the function is sync or async.
130
+ * If not provided, automatically detected during warmup.
131
+ * Setting this explicitly skips per-iteration promise checking for sync functions.
132
+ */
133
+ async?: boolean;
134
+ }
135
+ /**
136
+ * Result from running a single benchmark task.
137
+ */
138
+ export interface BenchmarkResult {
139
+ /** Task name */
140
+ name: string;
141
+ /** Statistical analysis of the benchmark */
142
+ stats: BenchmarkStats;
143
+ /** Number of iterations executed */
144
+ iterations: number;
145
+ /** Total time spent benchmarking (including warmup) in milliseconds */
146
+ total_time_ms: number;
147
+ /**
148
+ * Raw timing data for each iteration in nanoseconds.
149
+ * Useful for custom statistical analysis, histogram generation,
150
+ * or exporting to external tools.
151
+ */
152
+ timings_ns: Array<number>;
153
+ }
154
+ /**
155
+ * Options for table formatting.
156
+ */
157
+ export interface BenchmarkFormatTableOptions {
158
+ /**
159
+ * Group results by category using filter functions.
160
+ */
161
+ groups?: Array<BenchmarkGroup>;
162
+ }
163
+ /**
164
+ * A group definition for organizing benchmark results.
165
+ */
166
+ export interface BenchmarkGroup {
167
+ /** Display name for the group */
168
+ name: string;
169
+ /** Optional description shown below the group name */
170
+ description?: string;
171
+ /** Filter function to determine which results belong to this group */
172
+ filter: (result: BenchmarkResult) => boolean;
173
+ }
174
+ //# sourceMappingURL=benchmark_types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmark_types.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/benchmark_types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,WAAW,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;IACH,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAEjF;;;;;;;;;;;;;;;;OAgBG;IACH,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnF;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IAEb,wEAAwE;IACxE,EAAE,EAAE,MAAM,OAAO,CAAC;IAElB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IAEb,4CAA4C;IAC5C,KAAK,EAAE,cAAc,CAAC;IAEtB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IAEnB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC3C;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IAEb,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,sEAAsE;IACtE,MAAM,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC;CAC7C"}
@@ -0,0 +1 @@
1
+ export {};
@@ -10,11 +10,11 @@ import type { Url } from './url.js';
10
10
  export interface LibraryJson {
11
11
  package_json: PackageJson;
12
12
  source_json: SourceJson;
13
- /** Package name, e.g. `@ryanatkn/fuz`. */
13
+ /** Package name, e.g. `@fuzdev/fuz_ui`. */
14
14
  name: string;
15
15
  /** Name without scope, e.g. `fuz`. */
16
16
  repo_name: string;
17
- /** GitHub repo URL, e.g. `https://github.com/ryanatkn/fuz`. */
17
+ /** GitHub repo URL, e.g. `https://github.com/fuzdev/fuz_ui`. */
18
18
  repo_url: Url;
19
19
  /** GitHub user/org, e.g. `ryanatkn`. */
20
20
  owner_name: string | null;
@@ -32,7 +32,7 @@ export interface LibraryJson {
32
32
  */
33
33
  export declare const library_json_parse: (package_json: PackageJson, source_json: SourceJson) => LibraryJson;
34
34
  /**
35
- * Extracts repo name from a package name, e.g. `@ryanatkn/fuz` → `fuz`.
35
+ * Extracts repo name from a package name, e.g. `@fuzdev/fuz_ui` → `fuz`.
36
36
  */
37
37
  export declare const library_repo_name_parse: (name: string) => string;
38
38
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"library_json.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library_json.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,UAAU,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,YAAY,EAAE,WAAW,CAAC;IAC1B,WAAW,EAAE,UAAU,CAAC;IACxB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,EAAE,GAAG,CAAC;IACd,wCAAwC;IACxC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,GAAG,GAAG,IAAI,CAAC;IACzB,6CAA6C;IAC7C,QAAQ,EAAE,GAAG,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;IACpB,aAAa,EAAE,GAAG,GAAG,IAAI,CAAC;IAC1B,sDAAsD;IACtD,SAAS,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC9B,cAAc,WAAW,EACzB,aAAa,UAAU,KACrB,WAuDF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,MAStD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS,WAAW,KAAG,MAAM,GAAG,IAQrE,CAAC"}
1
+ {"version":3,"file":"library_json.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library_json.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,UAAU,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,YAAY,EAAE,WAAW,CAAC;IAC1B,WAAW,EAAE,UAAU,CAAC;IACxB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,QAAQ,EAAE,GAAG,CAAC;IACd,wCAAwC;IACxC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,GAAG,GAAG,IAAI,CAAC;IACzB,6CAA6C;IAC7C,QAAQ,EAAE,GAAG,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;IACpB,aAAa,EAAE,GAAG,GAAG,IAAI,CAAC;IAC1B,sDAAsD;IACtD,SAAS,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC9B,cAAc,WAAW,EACzB,aAAa,UAAU,KACrB,WAuDF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,MAStD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS,WAAW,KAAG,MAAM,GAAG,IAQrE,CAAC"}
@@ -49,7 +49,7 @@ export const library_json_parse = (package_json, source_json) => {
49
49
  };
50
50
  };
51
51
  /**
52
- * Extracts repo name from a package name, e.g. `@ryanatkn/fuz` → `fuz`.
52
+ * Extracts repo name from a package name, e.g. `@fuzdev/fuz_ui` → `fuz`.
53
53
  */
54
54
  export const library_repo_name_parse = (name) => {
55
55
  if (name[0] === '@') {
package/dist/object.js CHANGED
@@ -65,7 +65,7 @@ export const reorder = (obj, keys) => {
65
65
  /**
66
66
  * Frozen empty object with no properties, good for options default values.
67
67
  */
68
- export const EMPTY_OBJECT = Object.freeze({}); // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
68
+ export const EMPTY_OBJECT = Object.freeze({});
69
69
  /**
70
70
  * Performs a depth-first traversal of an object's enumerable properties,
71
71
  * calling `cb` for every key and value with the current `obj` context.