@getdashfy/utils 0.1.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.
@@ -0,0 +1,594 @@
1
+ import * as dateFns from 'date-fns';
2
+ export { dateFns };
3
+
4
+ /**
5
+ * Type guard and utility functions for safe error message extraction.
6
+ *
7
+ * TypeScript's catch blocks receive `unknown` types, not `Error` types.
8
+ * These utilities provide type-safe ways to extract error messages from any thrown value.
9
+ *
10
+ * @link https://kentcdodds.com/blog/get-a-catch-block-error-message-with-typescript
11
+ */
12
+ /**
13
+ * Safely extracts an error message from any thrown value.
14
+ *
15
+ * Use this in catch blocks to get a string message regardless of what was thrown.
16
+ *
17
+ * @param error - The caught error (of type unknown)
18
+ * @returns A string error message
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * try {
23
+ * // some code that might throw
24
+ * } catch (error) {
25
+ * const message = getErrorMessage(error)
26
+ * console.error(message)
27
+ * }
28
+ * ```
29
+ */
30
+ declare function getErrorMessage(error: unknown): string;
31
+
32
+ /**
33
+ * Base options shared across all format functions.
34
+ */
35
+ interface BaseFormatOptions {
36
+ /** BCP 47 locale(s) for formatting (e.g. 'en-US', 'pt-BR') */
37
+ locale?: string | string[];
38
+ /** Custom output when value is 0 */
39
+ zeroFormat?: string;
40
+ /** Custom output when value is null or undefined */
41
+ nullFormat?: string;
42
+ }
43
+ /**
44
+ * Options for number formatting.
45
+ */
46
+ interface NumberFormatOptions extends BaseFormatOptions {
47
+ /** Minimum number of decimal places */
48
+ minimumFractionDigits?: number;
49
+ /** Maximum number of decimal places */
50
+ maximumFractionDigits?: number;
51
+ /** Use compact notation (1K, 1.2M) */
52
+ notation?: 'standard' | 'scientific' | 'engineering' | 'compact';
53
+ /** Compact display: 'short' (1K) or 'long' (1 thousand) */
54
+ compactDisplay?: 'short' | 'long';
55
+ }
56
+ /**
57
+ * Options for currency formatting.
58
+ */
59
+ interface CurrencyFormatOptions extends BaseFormatOptions {
60
+ /** ISO 4217 currency code (e.g. 'USD', 'EUR') */
61
+ currency?: string;
62
+ minimumFractionDigits?: number;
63
+ maximumFractionDigits?: number;
64
+ }
65
+ /**
66
+ * Options for bytes formatting.
67
+ */
68
+ interface BytesFormatOptions extends BaseFormatOptions {
69
+ /** Use binary units (KiB, MiB) instead of decimal (KB, MB) */
70
+ binary?: boolean;
71
+ /** Format as bits instead of bytes */
72
+ bits?: boolean;
73
+ /** Include +/- for positive/negative */
74
+ signed?: boolean;
75
+ minimumFractionDigits?: number;
76
+ maximumFractionDigits?: number;
77
+ }
78
+ /**
79
+ * Options for percentage formatting.
80
+ */
81
+ interface PercentFormatOptions extends BaseFormatOptions {
82
+ /** Scale value by 100 (0.5 → 50%). Default: true */
83
+ scaleBy100?: boolean;
84
+ minimumFractionDigits?: number;
85
+ maximumFractionDigits?: number;
86
+ }
87
+ /**
88
+ * Options for time/duration formatting.
89
+ */
90
+ interface TimeFormatOptions extends BaseFormatOptions {
91
+ /** Include seconds in output */
92
+ includeSeconds?: boolean;
93
+ /** Format style: 'short' (2h 30m) or 'long' (2 hours 30 minutes) */
94
+ style?: 'short' | 'long';
95
+ }
96
+ /**
97
+ * Options for temperature formatting.
98
+ */
99
+ interface TemperatureFormatOptions extends BaseFormatOptions {
100
+ /** Temperature unit */
101
+ unit?: 'celsius' | 'fahrenheit' | 'kelvin';
102
+ minimumFractionDigits?: number;
103
+ maximumFractionDigits?: number;
104
+ }
105
+ /**
106
+ * Options for date formatting.
107
+ */
108
+ interface DateFormatOptions extends BaseFormatOptions {
109
+ /** Date format pattern (date-fns tokens) */
110
+ format?: string;
111
+ /** For relative time: add "ago" / "in" suffix */
112
+ addSuffix?: boolean;
113
+ }
114
+ /**
115
+ * Options for list formatting.
116
+ */
117
+ interface ListFormatOptions extends BaseFormatOptions {
118
+ /** Conjunction style: 'conjunction' (A, B, and C) or 'disjunction' (A, B, or C) */
119
+ type?: 'conjunction' | 'disjunction' | 'unit';
120
+ /** Style: 'long', 'short', or 'narrow' */
121
+ style?: 'long' | 'short' | 'narrow';
122
+ }
123
+ /**
124
+ * Options for ordinal formatting.
125
+ */
126
+ interface OrdinalFormatOptions extends BaseFormatOptions {
127
+ minimumFractionDigits?: number;
128
+ maximumFractionDigits?: number;
129
+ }
130
+ /**
131
+ * Options for exponential/scientific formatting.
132
+ */
133
+ interface ExponentialFormatOptions extends BaseFormatOptions {
134
+ minimumFractionDigits?: number;
135
+ maximumFractionDigits?: number;
136
+ }
137
+
138
+ /**
139
+ * Format a byte count into a human-readable string.
140
+ *
141
+ * @param value - The byte count to format
142
+ * @param options - Optional formatting options
143
+ * @returns A human-readable string representing the byte count
144
+ *
145
+ * @example
146
+ * ```ts
147
+ * formatBytes(1024) // '1.02 kB'
148
+ * formatBytes(1024, { binary: true }) // '1 KiB'
149
+ * formatBytes(8192, { bits: true }) // '8.19 kbit'
150
+ * formatBytes(1024, { locale: 'de-DE' }) // '1,02 kB'
151
+ * ```
152
+ */
153
+ declare function formatBytes(value: number | bigint, options?: BytesFormatOptions): string;
154
+ /**
155
+ * Format a byte-rate value into a human-readable per-second string.
156
+ *
157
+ * @param value - The throughput in bytes per second
158
+ * @param options - Optional formatting options (same as {@link formatBytes})
159
+ * @returns A human-readable string representing the throughput
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * formatBytesPerSecond(1024) // '1.02 kB/s'
164
+ * formatBytesPerSecond(1024, { binary: true }) // '1 KiB/s'
165
+ * formatBytesPerSecond(0) // '0 B/s'
166
+ * ```
167
+ */
168
+ declare function formatBytesPerSecond(value: number | bigint, options?: BytesFormatOptions): string;
169
+
170
+ /**
171
+ * Core utilities shared across format modules.
172
+ */
173
+ /**
174
+ * Set the default locale for all format functions.
175
+ *
176
+ * When a format is called without `locale` in its options, it uses this value.
177
+ * Call at app startup or in tests for consistent output (e.g. `setDefaultLocale('en-US')`).
178
+ *
179
+ * @param locale - BCP 47 locale (e.g. 'en-US'), an array of fallbacks, or `undefined` to use runtime default
180
+ */
181
+ declare function setDefaultLocale(locale: string | string[] | undefined): void;
182
+ /**
183
+ * Get the current default locale.
184
+ *
185
+ * @returns The default locale, or `undefined` if none is set
186
+ */
187
+ declare function getDefaultLocale(): string | string[] | undefined;
188
+
189
+ /**
190
+ * Format a number as currency with the correct symbol and locale-specific formatting.
191
+ *
192
+ * @param value - The numeric value to format
193
+ * @param options - Optional formatting options
194
+ * @returns Formatted string representing the currency value
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * formatCurrency(1234.56) // '$1,234.56'
199
+ * formatCurrency(99.99, { currency: 'EUR' }) // '€99.99'
200
+ * formatCurrency(0, { zeroFormat: 'Free' }) // 'Free'
201
+ * formatCurrency(1234.56, { locale: 'de-DE' }) // '1.234,56 €'
202
+ * ```
203
+ */
204
+ declare function formatCurrency(value: number, options?: CurrencyFormatOptions): string;
205
+
206
+ /**
207
+ * Format a date (Date, string, or Unix timestamp in seconds).
208
+ *
209
+ * @param value - Date instance, ISO string, or Unix seconds
210
+ * @param options - Optional formatting options
211
+ * @returns Formatted string per the pattern
212
+ *
213
+ * @example
214
+ * ```ts
215
+ * formatDate(new Date('2025-03-13')) // 'Mar 13, 2025'
216
+ * formatDate('2025-03-13', { format: 'yyyy-MM-dd' }) // '2025-03-13'
217
+ * ```
218
+ */
219
+ declare function formatDate(value: Date | string | number, options?: DateFormatOptions): string;
220
+ /**
221
+ * Format a date as human-readable relative time.
222
+ *
223
+ * @param value - Date instance, ISO string, or Unix seconds
224
+ * @param options - Optional formatting options
225
+ * @returns Relative string such as "about 2 hours ago" or "in 3 days"
226
+ *
227
+ * @example
228
+ * ```ts
229
+ * formatRelativeTime(Date.now() / 1000 - 3600) // 'about 1 hour ago'
230
+ * formatRelativeTime(new Date(), { addSuffix: false }) // 'less than a minute'
231
+ * ```
232
+ */
233
+ declare function formatRelativeTime(value: Date | string | number, options?: DateFormatOptions): string;
234
+
235
+ /**
236
+ * Format a number in exponential/scientific notation.
237
+ *
238
+ * @param value - The number to format
239
+ * @param options - Optional formatting options
240
+ * @returns Formatted string representing the exponential value
241
+ *
242
+ * @example
243
+ * ```ts
244
+ * formatExponential(1234.56) // '1.23E3'
245
+ * formatExponential(1234.56, { maximumFractionDigits: 0 }) // '1E3'
246
+ * formatExponential(0.00123) // '1.23E-3'
247
+ * formatExponential(1234.56, { locale: 'de-DE' }) // '1,23E3'
248
+ * formatExponential(0, { zeroFormat: '0' }) // '0'
249
+ * ```
250
+ */
251
+ declare function formatExponential(value: number, options?: ExponentialFormatOptions): string;
252
+
253
+ /**
254
+ * Main format function - parses format strings and delegates to the appropriate formatter.
255
+ *
256
+ * @param value - The value to format
257
+ * @param formatString - The format string
258
+ * @param options - Optional formatting options
259
+ * @returns The formatted value
260
+ *
261
+ * @example
262
+ * ```ts
263
+ * format(1000, '0,0')
264
+ * // => '1,000'
265
+ *
266
+ * format(1500000, '0.0a')
267
+ * // => '1.5M'
268
+ *
269
+ * format(new Date(), 'relative')
270
+ * // => 'less than a minute ago'
271
+ * ```
272
+ */
273
+ declare function format(value: number | bigint | Date | string | string[] | null | undefined, formatString: string, options?: BaseFormatOptions): string;
274
+
275
+ /**
276
+ * Format a list of strings.
277
+ *
278
+ * @param items - The list of strings to format
279
+ * @param options - Optional formatting options
280
+ * @returns The formatted list
281
+ *
282
+ * @example
283
+ * ```ts
284
+ * formatList(['A', 'B', 'C'])
285
+ * // => 'A, B, and C'
286
+ *
287
+ * formatList(['A', 'B', 'C'], { type: 'disjunction' })
288
+ * // => 'A, B, or C'
289
+ *
290
+ * formatList(['A', 'B', 'C'], { style: 'short' })
291
+ * // => 'A, B, & C'
292
+ *
293
+ * formatList(['A', 'B', 'C'], { style: 'narrow' })
294
+ * // => 'A, B, C'
295
+ * ```
296
+ */
297
+ declare function formatList(items: string[], options?: ListFormatOptions): string;
298
+
299
+ /**
300
+ * Format a number with locale-aware thousands separators and optional decimals.
301
+ *
302
+ * @param value - The number to format
303
+ * @param options - Optional formatting options
304
+ * @returns Formatted string representing the number
305
+ *
306
+ * @example
307
+ * ```ts
308
+ * formatNumber(1234.56)
309
+ * // => '1,234.56'
310
+ *
311
+ * formatNumber(1234.56, { maximumFractionDigits: 2 })
312
+ * // => '1,234.56'
313
+ *
314
+ * formatNumber(1234.56, { notation: 'compact' })
315
+ * // => '1.2K'
316
+ *
317
+ * formatNumber(1234.56, { notation: 'compact', compactDisplay: 'long' })
318
+ * // => '1.2 thousand'
319
+ * ```
320
+ */
321
+ declare function formatNumber(value: number, options?: NumberFormatOptions): string;
322
+
323
+ /**
324
+ * Format a number with ordinal suffix.
325
+ *
326
+ * @param value - The number to format
327
+ * @param options - Optional formatting options
328
+ * @returns Formatted string representing the ordinal value
329
+ *
330
+ * @example
331
+ * ```ts
332
+ * formatOrdinal(1) // '1st'
333
+ * formatOrdinal(2) // '2nd'
334
+ * formatOrdinal(3) // '3rd'
335
+ * ```
336
+ */
337
+ declare function formatOrdinal(value: number, options?: OrdinalFormatOptions): string;
338
+
339
+ /**
340
+ * Format a number as a percentage.
341
+ *
342
+ * @param value - The number to format
343
+ * @param options - Optional formatting options
344
+ * @returns Formatted string representing the percentage value
345
+ *
346
+ * @example
347
+ * ```ts
348
+ * formatPercent(0.5)
349
+ * // => '50%'
350
+ *
351
+ * formatPercent(0.5, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
352
+ * // => '50.00%'
353
+ *
354
+ * formatPercent(50, { scaleBy100: false })
355
+ * // => '50%' (value already 0–100)
356
+ * ```
357
+ */
358
+ declare function formatPercent(value: number, options?: PercentFormatOptions): string;
359
+
360
+ /**
361
+ * Format a temperature value.
362
+ *
363
+ * @param value - The temperature value to format
364
+ * @param options - Optional formatting options
365
+ * @returns Formatted string representing the temperature value
366
+ *
367
+ * @example
368
+ * ```ts
369
+ * formatTemperature(25) // '25°C'
370
+ * formatTemperature(77, { unit: 'fahrenheit' }) // '77°F'
371
+ * formatTemperature(273.15, { unit: 'kelvin' }) // '273.15 K'
372
+ * ```
373
+ */
374
+ declare function formatTemperature(value: number, options?: TemperatureFormatOptions): string;
375
+
376
+ /**
377
+ * Format a duration in seconds to HH:MM:SS or human-readable string.
378
+ *
379
+ * @param seconds - The duration in seconds to format
380
+ * @param options - Optional formatting options
381
+ * @returns Formatted string representing the time value
382
+ *
383
+ * @example
384
+ * ```ts
385
+ * formatTime(3661, { style: 'short' })
386
+ * // => '01:01:01'
387
+ *
388
+ * formatTime(65, { style: 'long' })
389
+ * // => '1 minute 5 seconds'
390
+ *
391
+ * formatTime(3661, { style: 'long', includeSeconds: false })
392
+ * // => '1 hour 1 minute'
393
+ * ```
394
+ */
395
+ declare function formatTime(seconds: number, options?: TimeFormatOptions): string;
396
+ /**
397
+ * Format a duration in seconds into a compact, multi-day-aware string.
398
+ *
399
+ * Drops zero units and joins the remainder with spaces. Useful for uptime
400
+ * fields where space is tight and the long-form `formatTime` is too verbose.
401
+ *
402
+ * @param seconds - The duration in seconds to format
403
+ * @param options - Optional formatting options
404
+ * @returns Formatted string representing the duration
405
+ *
406
+ * @example
407
+ * ```ts
408
+ * formatTimeCompact(3 * 86400 + 5 * 3600 + 12 * 60)
409
+ * // => '3d 5h 12m'
410
+ *
411
+ * formatTimeCompact(45 * 60)
412
+ * // => '45m'
413
+ *
414
+ * formatTimeCompact(0)
415
+ * // => '0m'
416
+ * ```
417
+ */
418
+ declare function formatTimeCompact(seconds: number, options?: TimeFormatOptions): string;
419
+
420
+ /**
421
+ * Creates a debounced function that delays invoking `func` until after `wait` milliseconds.
422
+ *
423
+ * @template T - The type of the function to debounce
424
+ * @param func - The function to debounce
425
+ * @param wait - The number of milliseconds to delay execution
426
+ * @returns A new debounced version of the provided function
427
+ *
428
+ * @example
429
+ * ```ts
430
+ * // Debounce a search function
431
+ * const debouncedSearch = debounce((query: string) => {
432
+ * fetchSearchResults(query)
433
+ * }, 300)
434
+ *
435
+ * // User types "hello"
436
+ * debouncedSearch('h') // Waits...
437
+ * debouncedSearch('he') // Cancels previous, waits...
438
+ * debouncedSearch('hel') // Cancels previous, waits...
439
+ * // After 300ms of no calls, executes with 'hel'
440
+ * ```
441
+ *
442
+ * @example
443
+ * ```ts
444
+ * // Debounce window resize handler
445
+ * const debouncedResize = debounce(() => {
446
+ * recalculateLayout()
447
+ * }, 150)
448
+ *
449
+ * window.addEventListener('resize', debouncedResize)
450
+ * ```
451
+ */
452
+ declare function debounce<T extends (...args: unknown[]) => unknown>(func: T, wait: number): (...args: Parameters<T>) => void;
453
+
454
+ /**
455
+ * Safely retrieves a nested property value from an object using a dot-notation path.
456
+ *
457
+ * This function provides a safe way to access deeply nested properties without
458
+ * worrying about undefined intermediate values. Similar to lodash's `_.get()`.
459
+ * Returns `undefined` if any part of the path doesn't exist.
460
+ *
461
+ * @param obj - The object to query
462
+ * @param path - The dot-notation path to the property (e.g., 'user.address.city')
463
+ * @returns The value at the path, or `undefined` if not found
464
+ *
465
+ * @example
466
+ * ```ts
467
+ * const user = { name: 'John', address: { city: 'NYC', zip: '10001' } }
468
+ *
469
+ * get(user, 'name')
470
+ * // => 'John'
471
+ * ```
472
+ *
473
+ * @example
474
+ * ```ts
475
+ * get(user, 'address.city')
476
+ * // => 'NYC'
477
+ * ```
478
+ *
479
+ * @example
480
+ * ```ts
481
+ * // Safe access - returns undefined instead of throwing
482
+ * get(user, 'address.country')
483
+ * // => undefined
484
+ * ```
485
+ */
486
+ declare function get(obj: Record<string, unknown>, path: string): unknown;
487
+
488
+ /** Check if the code is running in development mode. */
489
+ declare const isDevelopment: boolean;
490
+ /** Check if the code is running in production mode. */
491
+ declare const isProduction: boolean;
492
+ /** Check if the code is running in test mode. */
493
+ declare const isTest: boolean;
494
+
495
+ /**
496
+ * Check if the current platform is macOS.
497
+ */
498
+ declare const isMac: boolean;
499
+ /**
500
+ * Get the modifier key symbol based on the current platform.
501
+ *
502
+ * @returns '⌘' for macOS, 'Ctrl' for other platforms
503
+ *
504
+ * @example
505
+ * ```ts
506
+ * // On macOS
507
+ * `Press ${modKey}+S to save` // => 'Press ⌘+S to save'
508
+ *
509
+ * // On Windows/Linux
510
+ * `Press ${modKey}+S to save` // => 'Press Ctrl+S to save'
511
+ * ```
512
+ */
513
+ declare const modKey: string;
514
+
515
+ /** Check if the code is running on the client. */
516
+ declare const isClient: boolean;
517
+ /** Check if the code is running on the server. */
518
+ declare const isServer: boolean;
519
+
520
+ /**
521
+ * Converts any value to a string representation (primitives as-is, objects as JSON).
522
+ *
523
+ * @param value - The value to convert to a string
524
+ * @returns A string representation of the value
525
+ *
526
+ * @example
527
+ * ```ts
528
+ * stringifyValue(null)
529
+ * // => ''
530
+ *
531
+ * stringifyValue(undefined)
532
+ * // => ''
533
+ *
534
+ * stringifyValue('hello')
535
+ * // => 'hello'
536
+ *
537
+ * stringifyValue(42)
538
+ * // => '42'
539
+ *
540
+ * stringifyValue(true)
541
+ * // => 'true'
542
+ *
543
+ * stringifyValue({ name: 'John', age: 30 })
544
+ * // => '{"name":"John","age":30}'
545
+ *
546
+ * stringifyValue([1, 2, 3])
547
+ * // => '[1,2,3]'
548
+ * ```
549
+ */
550
+ declare function stringifyValue(value: unknown): string;
551
+
552
+ /**
553
+ * Truncates a string to a specified length and adds an ellipsis if needed.
554
+ *
555
+ * @param str - The string to truncate
556
+ * @param length - The maximum length before truncation (excluding ellipsis)
557
+ * @returns The truncated string with '...' appended, or the original if short enough
558
+ *
559
+ * @example
560
+ * ```ts
561
+ * truncate('Hello, World!', 5)
562
+ * // => 'Hello...'
563
+ *
564
+ * truncate('Short', 10)
565
+ * // => 'Short'
566
+ *
567
+ * // Perfect for long descriptions in UI
568
+ * const description = 'This is a very long description that needs truncation'
569
+ * truncate(description, 20)
570
+ * // => 'This is a very long ...'
571
+ * ```
572
+ */
573
+ declare function truncate(str: string, length: number): string;
574
+
575
+ /**
576
+ * Formats a value into a human-readable display string.
577
+ *
578
+ * @param value - The value to format
579
+ * @returns Formatted string representation for display
580
+ *
581
+ * @example
582
+ * ```ts
583
+ * valueToDisplayString(null) // 'null'
584
+ * valueToDisplayString(undefined) // 'undefined'
585
+ * valueToDisplayString(true) // 'true'
586
+ * valueToDisplayString('hello') // 'hello'
587
+ * valueToDisplayString(42) // '42'
588
+ * valueToDisplayString([1, 2, 3]) // 'Array(3)'
589
+ * valueToDisplayString({ a: 1, b: 2 }) // 'Object(2)'
590
+ * ```
591
+ */
592
+ declare function valueToDisplayString(value: unknown): string;
593
+
594
+ export { type BaseFormatOptions, debounce, format, formatBytes, formatBytesPerSecond, formatCurrency, formatDate, formatExponential, formatList, formatNumber, formatOrdinal, formatPercent, formatRelativeTime, formatTemperature, formatTime, formatTimeCompact, get, getDefaultLocale, getErrorMessage, isClient, isDevelopment, isMac, isProduction, isServer, isTest, modKey, setDefaultLocale, stringifyValue, truncate, valueToDisplayString };