@provex/utils 1.0.16 → 1.2.4

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 (149) hide show
  1. package/dist/chain.d.ts +446 -0
  2. package/dist/chain.js +98 -0
  3. package/dist/chain.test.js +112 -0
  4. package/dist/contracts.d.ts +206 -0
  5. package/dist/contracts.js +292 -0
  6. package/dist/contracts.test.js +243 -0
  7. package/dist/conversionRates.d.ts +215 -0
  8. package/dist/{src/conversionRates.js → conversionRates.js} +74 -4
  9. package/dist/conversionRates.test.js +473 -0
  10. package/dist/currencies.d.ts +248 -0
  11. package/dist/{src/currencies.js → currencies.js} +119 -38
  12. package/dist/currencies.test.js +343 -0
  13. package/dist/data/countries.json +1099 -0
  14. package/dist/deposit.d.ts +69 -0
  15. package/dist/deposit.js +52 -0
  16. package/dist/depositKeys.d.ts +154 -0
  17. package/dist/depositKeys.js +104 -0
  18. package/dist/depositKeys.test.d.ts +1 -0
  19. package/dist/depositKeys.test.js +231 -0
  20. package/dist/events.d.ts +41 -0
  21. package/dist/events.js +92 -0
  22. package/dist/events.test.d.ts +1 -0
  23. package/dist/events.test.js +111 -0
  24. package/dist/fees.d.ts +136 -0
  25. package/dist/fees.js +178 -0
  26. package/dist/fees.test.d.ts +1 -0
  27. package/dist/fees.test.js +165 -0
  28. package/dist/ids.d.ts +175 -0
  29. package/dist/ids.js +231 -0
  30. package/dist/ids.test.d.ts +1 -0
  31. package/dist/ids.test.js +607 -0
  32. package/dist/index.d.ts +45 -0
  33. package/dist/index.js +45 -0
  34. package/dist/input.d.ts +26 -0
  35. package/dist/{src/input.js → input.js} +23 -4
  36. package/dist/intent.d.ts +50 -0
  37. package/dist/intent.js +28 -0
  38. package/dist/intent.test.d.ts +1 -0
  39. package/dist/intent.test.js +119 -0
  40. package/dist/json.d.ts +55 -0
  41. package/dist/json.js +80 -0
  42. package/dist/participants.d.ts +22 -0
  43. package/dist/participants.js +28 -0
  44. package/dist/payment.d.ts +481 -0
  45. package/dist/payment.js +1149 -0
  46. package/dist/payment.test.d.ts +1 -0
  47. package/dist/payment.test.js +272 -0
  48. package/dist/peer-types.d.ts +327 -0
  49. package/dist/peer-types.js +169 -0
  50. package/dist/profit.d.ts +49 -0
  51. package/dist/profit.js +57 -0
  52. package/dist/profit.test.d.ts +1 -0
  53. package/dist/profit.test.js +315 -0
  54. package/dist/reputation.d.ts +125 -0
  55. package/dist/reputation.js +188 -0
  56. package/dist/reputation.test.d.ts +1 -0
  57. package/dist/reputation.test.js +156 -0
  58. package/dist/sort.d.ts +75 -0
  59. package/dist/sort.js +70 -0
  60. package/dist/sort.test.d.ts +1 -0
  61. package/dist/sort.test.js +216 -0
  62. package/dist/stateKey.d.ts +35 -0
  63. package/dist/stateKey.js +36 -0
  64. package/dist/stats.d.ts +61 -0
  65. package/dist/stats.js +53 -0
  66. package/dist/stats.test.d.ts +1 -0
  67. package/dist/stats.test.js +104 -0
  68. package/dist/time.d.ts +104 -0
  69. package/dist/time.js +162 -0
  70. package/dist/time.test.d.ts +1 -0
  71. package/dist/time.test.js +231 -0
  72. package/dist/tokens.d.ts +15502 -0
  73. package/dist/{src/tokens.js → tokens.js} +98 -17
  74. package/dist/tokens.test.d.ts +1 -0
  75. package/dist/tokens.test.js +193 -0
  76. package/dist/units.d.ts +200 -0
  77. package/dist/units.js +279 -0
  78. package/dist/units.test.d.ts +1 -0
  79. package/dist/units.test.js +327 -0
  80. package/package.json +119 -29
  81. package/dist/scripts/convert-svg.js +0 -17
  82. package/dist/src/chain.d.ts +0 -14
  83. package/dist/src/chain.js +0 -18
  84. package/dist/src/contracts.d.ts +0 -30
  85. package/dist/src/contracts.js +0 -64
  86. package/dist/src/conversionRates.d.ts +0 -124
  87. package/dist/src/currencies.d.ts +0 -144
  88. package/dist/src/data/countries.json +0 -1099
  89. package/dist/src/deposit.d.ts +0 -1
  90. package/dist/src/events.d.ts +0 -3
  91. package/dist/src/events.js +0 -16
  92. package/dist/src/ids.d.ts +0 -72
  93. package/dist/src/ids.js +0 -81
  94. package/dist/src/index.d.ts +0 -16
  95. package/dist/src/index.js +0 -16
  96. package/dist/src/input.d.ts +0 -7
  97. package/dist/src/intent.d.ts +0 -14
  98. package/dist/src/json.d.ts +0 -18
  99. package/dist/src/json.js +0 -44
  100. package/dist/src/participants.d.ts +0 -7
  101. package/dist/src/participants.js +0 -13
  102. package/dist/src/payment.d.ts +0 -164
  103. package/dist/src/payment.js +0 -439
  104. package/dist/src/profit.d.ts +0 -28
  105. package/dist/src/profit.js +0 -34
  106. package/dist/src/sort.d.ts +0 -36
  107. package/dist/src/sort.js +0 -39
  108. package/dist/src/stats.d.ts +0 -7
  109. package/dist/src/stats.js +0 -8
  110. package/dist/src/time.d.ts +0 -54
  111. package/dist/src/time.js +0 -106
  112. package/dist/src/tokens.d.ts +0 -3675
  113. package/dist/src/units.d.ts +0 -17
  114. package/dist/src/units.js +0 -79
  115. package/dist/src/zkp2p-types.d.ts +0 -48
  116. package/dist/tsconfig.tsbuildinfo +0 -1
  117. package/scripts/convert-svg.ts +0 -22
  118. package/src/chain.ts +0 -27
  119. package/src/contracts.ts +0 -89
  120. package/src/conversionRates.ts +0 -356
  121. package/src/currencies.ts +0 -286
  122. package/src/data/countries.json +0 -1099
  123. package/src/deposit.ts +0 -2
  124. package/src/events.ts +0 -21
  125. package/src/flags/eur.svg +0 -4
  126. package/src/flags/usd.svg +0 -25
  127. package/src/flags.ts +0 -4
  128. package/src/global.d.ts +0 -9
  129. package/src/ids.ts +0 -137
  130. package/src/index.ts +0 -16
  131. package/src/input.ts +0 -35
  132. package/src/intent.ts +0 -15
  133. package/src/json.ts +0 -42
  134. package/src/participants.ts +0 -14
  135. package/src/payment.ts +0 -573
  136. package/src/profit.ts +0 -55
  137. package/src/sort.ts +0 -49
  138. package/src/stats.ts +0 -10
  139. package/src/time.ts +0 -123
  140. package/src/tokens.ts +0 -159
  141. package/src/units.ts +0 -120
  142. package/src/zkp2p-types.ts +0 -55
  143. package/tsconfig.json +0 -18
  144. /package/dist/{scripts/convert-svg.d.ts → chain.test.d.ts} +0 -0
  145. /package/dist/{src/deposit.js → contracts.test.d.ts} +0 -0
  146. /package/dist/{src/intent.js → conversionRates.test.d.ts} +0 -0
  147. /package/dist/{src/zkp2p-types.js → currencies.test.d.ts} +0 -0
  148. /package/dist/{src/flags.d.ts → flags.d.ts} +0 -0
  149. /package/dist/{src/flags.js → flags.js} +0 -0
package/dist/time.js ADDED
@@ -0,0 +1,162 @@
1
+ /**
2
+ * @fileoverview Time and date utilities for formatting and calculations.
3
+ *
4
+ * Provides:
5
+ * - Interval constants in milliseconds for time calculations
6
+ * - Human-readable relative time formatting ("5m ago", "2d 3h ago")
7
+ * - Duration formatting for time ranges
8
+ * - Absolute timestamp formatting
9
+ *
10
+ * @see {@link units} for blockchain timestamp conversion
11
+ */
12
+ /**
13
+ * Time unit relationships for manual calculations.
14
+ * Use these when building complex time expressions.
15
+ */
16
+ export const intervalIn = {
17
+ yearInDays: 365,
18
+ quarterInMonths: 3,
19
+ monthInDays: 30,
20
+ hourInDays: 24,
21
+ daysInWeek: 7,
22
+ minuteInHours: 60,
23
+ secondInMinutes: 60,
24
+ millisecondInSecond: 1000,
25
+ };
26
+ const second = intervalIn.millisecondInSecond;
27
+ const minute = intervalIn.secondInMinutes * second;
28
+ const hour = intervalIn.minuteInHours * minute;
29
+ const day = intervalIn.hourInDays * hour;
30
+ const month = intervalIn.monthInDays * day;
31
+ const year = intervalIn.yearInDays * month;
32
+ /**
33
+ * Common time intervals in milliseconds.
34
+ * Use for timeout calculations, polling intervals, and date math.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * // Set a 5 minute timeout
39
+ * setTimeout(callback, 5 * interval.minute)
40
+ *
41
+ * // Calculate time 1 day ago
42
+ * const yesterday = Date.now() - interval.day
43
+ * ```
44
+ */
45
+ export const interval = {
46
+ second,
47
+ minute,
48
+ hour,
49
+ day,
50
+ month,
51
+ year,
52
+ };
53
+ /**
54
+ * Default number of time units to display in statistics/charts.
55
+ * Used for "show last N hours/days/months" UI controls.
56
+ */
57
+ export const defaultDisplayInterval = {
58
+ hour: 7 * 24,
59
+ day: 6 * 30,
60
+ month: 60,
61
+ };
62
+ /**
63
+ * Format a timestamp as a human-readable relative time string.
64
+ * Produces compact strings like "5m ago", "2h 30m ago", "3d ago".
65
+ *
66
+ * @param timestamp - The timestamp to format (Date, number in ms, or date string)
67
+ * @param options - Optional configuration
68
+ * @param options.anchor - Reference date for "ago" calculation (default: now)
69
+ * @param options.showSeconds - Whether to show seconds for very recent times
70
+ * @returns Human-readable relative time string
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * formatTimestamp(Date.now() - 5 * 60 * 1000) // "5m ago"
75
+ * formatTimestamp(Date.now() - 2.5 * 60 * 60 * 1000) // "2h 30m ago"
76
+ * formatTimestamp(Date.now() - 3 * 24 * 60 * 60 * 1000) // "3d 0h ago"
77
+ * ```
78
+ */
79
+ export const formatTimestamp = (timestamp, options) => {
80
+ const anchor = options?.anchor ?? new Date(), showSeconds = options?.showSeconds ?? false, date = new Date(timestamp);
81
+ const diffMs = anchor.getTime() - date.getTime(), diffMins = Math.floor(diffMs / interval.minute), diffHours = Math.floor(diffMs / interval.hour);
82
+ const diffDays = Math.floor(diffMs / interval.day), diffMonths = Math.floor(diffDays / intervalIn.monthInDays);
83
+ if (diffMonths > 0) {
84
+ if (diffMonths < intervalIn.quarterInMonths) {
85
+ return `${diffMonths}mo ${diffDays % intervalIn.monthInDays}d ago`;
86
+ }
87
+ return `${diffMonths}mo ago`;
88
+ }
89
+ if (diffMins < 1) {
90
+ if (showSeconds) {
91
+ if (diffMs < 10 * interval.second) {
92
+ return 'Just now';
93
+ }
94
+ return `${Math.floor(diffMs / interval.second)}s ago`;
95
+ }
96
+ return 'Just now';
97
+ }
98
+ if (diffMins < intervalIn.secondInMinutes) {
99
+ return `${diffMins}m ago`;
100
+ }
101
+ else if (diffHours < intervalIn.hourInDays) {
102
+ if (diffHours < 6) {
103
+ return `${diffHours}h ${diffMins % intervalIn.minuteInHours}m ago`;
104
+ }
105
+ return `${diffHours}h ago`;
106
+ }
107
+ else {
108
+ if (diffDays < intervalIn.daysInWeek) {
109
+ return `${diffDays}d ${diffHours % intervalIn.hourInDays}h ago`;
110
+ }
111
+ return `${diffDays}d ago`;
112
+ }
113
+ };
114
+ /**
115
+ * Format a duration
116
+ * @param param0.start - The start date
117
+ * @param param0.until - The end date
118
+ * @returns The formatted duration
119
+ */
120
+ export const formatDuration = ({ start = new Date(), until = new Date(), } = {}) => {
121
+ const diffMs = until.getTime() - start.getTime();
122
+ const diffMins = Math.floor(diffMs / interval.minute);
123
+ const diffHours = Math.floor(diffMs / interval.hour);
124
+ const diffDays = Math.floor(diffMs / interval.day);
125
+ const diffMonths = Math.floor(diffDays / intervalIn.monthInDays);
126
+ if (diffMonths > 0) {
127
+ return `${diffMonths}mo ${diffDays % intervalIn.monthInDays}d`;
128
+ }
129
+ if (diffDays > 0) {
130
+ return `${diffDays}d ${diffHours % intervalIn.hourInDays}h`;
131
+ }
132
+ if (diffHours > 0) {
133
+ return `${diffHours}h ${diffMins % intervalIn.minuteInHours}m`;
134
+ }
135
+ return `${diffMins % intervalIn.minuteInHours}m`;
136
+ };
137
+ /**
138
+ * Format an absolute timestamp to a human-readable string
139
+ * @param timestamp - Unix timestamp in seconds or milliseconds (auto-detected)
140
+ * @param options - Intl.DateTimeFormatOptions for formatting
141
+ * @returns Formatted absolute timestamp string
142
+ */
143
+ export const formatAbsoluteTimestamp = (timestamp, options) => {
144
+ // Auto-detect if timestamp is in seconds or milliseconds
145
+ // Timestamps > 10 billion are assumed to be in milliseconds (year 2286+ if seconds)
146
+ const timestampMs = Number(timestamp) > 10000000000 ? Number(timestamp) : Number(timestamp) * 1000;
147
+ const date = new Date(timestampMs);
148
+ return date.toLocaleString(undefined, options ?? {
149
+ year: 'numeric',
150
+ month: 'short',
151
+ day: 'numeric',
152
+ hour: '2-digit',
153
+ minute: '2-digit',
154
+ second: '2-digit'
155
+ });
156
+ };
157
+ /**
158
+ * Sleep for a given number of milliseconds
159
+ * @param ms - The number of milliseconds to sleep
160
+ * @returns A promise that resolves after the given number of milliseconds
161
+ */
162
+ export const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,231 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { interval, intervalIn, formatTimestamp, formatDuration, formatAbsoluteTimestamp, sleep, defaultDisplayInterval, } from './time.js';
4
+ describe('time', () => {
5
+ describe('formatTimestamp', () => {
6
+ const anchor = new Date('2025-01-05T12:00:00Z');
7
+ it('should return "Just now" for very recent timestamps', () => {
8
+ const recent = new Date(anchor.getTime() - 5 * 1000); // 5 seconds ago
9
+ assert.equal(formatTimestamp(recent, { anchor }), 'Just now');
10
+ });
11
+ it('should show seconds when enabled', () => {
12
+ const recent = new Date(anchor.getTime() - 30 * 1000); // 30 seconds ago
13
+ assert.equal(formatTimestamp(recent, { anchor, showSeconds: true }), '30s ago');
14
+ });
15
+ it('should format minutes correctly', () => {
16
+ const mins = new Date(anchor.getTime() - 15 * 60 * 1000); // 15 minutes ago
17
+ assert.equal(formatTimestamp(mins, { anchor }), '15m ago');
18
+ });
19
+ it('should format hours with minutes for recent hours', () => {
20
+ const hours = new Date(anchor.getTime() - 3 * 60 * 60 * 1000 - 30 * 60 * 1000); // 3h 30m ago
21
+ assert.equal(formatTimestamp(hours, { anchor }), '3h 30m ago');
22
+ });
23
+ it('should format hours only for older hours', () => {
24
+ const hours = new Date(anchor.getTime() - 8 * 60 * 60 * 1000); // 8 hours ago
25
+ assert.equal(formatTimestamp(hours, { anchor }), '8h ago');
26
+ });
27
+ it('should format days with hours for recent days', () => {
28
+ const days = new Date(anchor.getTime() - 2 * 24 * 60 * 60 * 1000 - 5 * 60 * 60 * 1000); // 2d 5h ago
29
+ assert.equal(formatTimestamp(days, { anchor }), '2d 5h ago');
30
+ });
31
+ it('should format days only for older days', () => {
32
+ const days = new Date(anchor.getTime() - 10 * 24 * 60 * 60 * 1000); // 10 days ago
33
+ assert.equal(formatTimestamp(days, { anchor }), '10d ago');
34
+ });
35
+ it('should format months with days for recent months', () => {
36
+ const twoMonthsAgo = new Date(anchor.getTime() - 60 * 24 * 60 * 60 * 1000); // 60 days = 2 months
37
+ const result = formatTimestamp(twoMonthsAgo, { anchor });
38
+ // 2 months is less than a quarter, so shows "2mo 0d ago"
39
+ assert.equal(result, '2mo 0d ago');
40
+ });
41
+ it('should format months only for older months', () => {
42
+ const fourMonthsAgo = new Date(anchor.getTime() - 120 * 24 * 60 * 60 * 1000); // 120 days = 4 months
43
+ const result = formatTimestamp(fourMonthsAgo, { anchor });
44
+ // 4 months is >= a quarter (3 months), so shows just "4mo ago"
45
+ assert.equal(result, '4mo ago');
46
+ });
47
+ it('should handle Date objects', () => {
48
+ const date = new Date(anchor.getTime() - 5 * 60 * 1000);
49
+ assert.equal(formatTimestamp(date, { anchor }), '5m ago');
50
+ });
51
+ it('should handle timestamp numbers', () => {
52
+ const timestamp = anchor.getTime() - 5 * 60 * 1000;
53
+ assert.equal(formatTimestamp(timestamp, { anchor }), '5m ago');
54
+ });
55
+ it('should handle ISO strings', () => {
56
+ const isoString = new Date(anchor.getTime() - 5 * 60 * 1000).toISOString();
57
+ assert.equal(formatTimestamp(isoString, { anchor }), '5m ago');
58
+ });
59
+ });
60
+ describe('formatDuration', () => {
61
+ it('should format minute durations', () => {
62
+ const start = new Date('2025-01-05T12:00:00Z');
63
+ const until = new Date('2025-01-05T12:15:00Z');
64
+ assert.equal(formatDuration({ start, until }), '15m');
65
+ });
66
+ it('should format hour durations with minutes', () => {
67
+ const start = new Date('2025-01-05T12:00:00Z');
68
+ const until = new Date('2025-01-05T15:30:00Z');
69
+ assert.equal(formatDuration({ start, until }), '3h 30m');
70
+ });
71
+ it('should format day durations with hours', () => {
72
+ const start = new Date('2025-01-05T12:00:00Z');
73
+ const until = new Date('2025-01-07T18:00:00Z');
74
+ assert.equal(formatDuration({ start, until }), '2d 6h');
75
+ });
76
+ it('should format month durations with days', () => {
77
+ const start = new Date('2025-01-05T12:00:00Z');
78
+ const until = new Date('2025-02-20T12:00:00Z');
79
+ const result = formatDuration({ start, until });
80
+ assert.ok(result.includes('mo'));
81
+ assert.ok(result.includes('d'));
82
+ });
83
+ it('should handle zero duration', () => {
84
+ const date = new Date('2025-01-05T12:00:00Z');
85
+ assert.equal(formatDuration({ start: date, until: date }), '0m');
86
+ });
87
+ it('should default to current time if no dates provided', () => {
88
+ const result = formatDuration();
89
+ assert.equal(result, '0m');
90
+ });
91
+ it('should handle only start date', () => {
92
+ const start = new Date(Date.now() - 5 * 60 * 1000);
93
+ const result = formatDuration({ start });
94
+ assert.ok(result.includes('m'));
95
+ });
96
+ it('should handle only until date', () => {
97
+ const until = new Date(Date.now() + 5 * 60 * 1000);
98
+ const result = formatDuration({ until });
99
+ assert.ok(result.includes('m'));
100
+ });
101
+ });
102
+ describe('sleep', () => {
103
+ it('should resolve after specified milliseconds', async () => {
104
+ const start = Date.now();
105
+ await sleep(100);
106
+ const elapsed = Date.now() - start;
107
+ assert.ok(elapsed >= 100, `Expected at least 100ms, got ${elapsed}ms`);
108
+ // Allow generous upper bound for CI environments with high load
109
+ assert.ok(elapsed < 1000, `Expected less than 1000ms, got ${elapsed}ms`);
110
+ });
111
+ it('should return a promise', () => {
112
+ const result = sleep(1);
113
+ assert.ok(result instanceof Promise);
114
+ });
115
+ it('should resolve immediately for 0ms', async () => {
116
+ const start = Date.now();
117
+ await sleep(0);
118
+ const elapsed = Date.now() - start;
119
+ assert.ok(elapsed < 10, `Expected less than 10ms, got ${elapsed}ms`);
120
+ });
121
+ });
122
+ describe('formatAbsoluteTimestamp', () => {
123
+ it('should format timestamp in seconds', () => {
124
+ // Unix timestamp for 2024-01-01 00:00:00 UTC
125
+ const timestamp = 1704067200;
126
+ const result = formatAbsoluteTimestamp(timestamp);
127
+ // Result format varies by timezone, just check it's a valid date string
128
+ assert.ok(result.length > 0);
129
+ assert.ok(typeof result === 'string');
130
+ });
131
+ it('should format timestamp in milliseconds', () => {
132
+ // Unix timestamp in ms for 2024-01-01 00:00:00 UTC
133
+ const timestamp = 1704067200000;
134
+ const result = formatAbsoluteTimestamp(timestamp);
135
+ assert.ok(result.length > 0);
136
+ assert.ok(typeof result === 'string');
137
+ });
138
+ it('should handle bigint timestamps', () => {
139
+ const timestamp = 1704067200n;
140
+ const result = formatAbsoluteTimestamp(timestamp);
141
+ assert.ok(result.length > 0);
142
+ });
143
+ it('should accept custom format options', () => {
144
+ const timestamp = 1704067200;
145
+ const result = formatAbsoluteTimestamp(timestamp, {
146
+ year: 'numeric',
147
+ month: 'numeric',
148
+ day: 'numeric',
149
+ timeZone: 'UTC', // Use UTC to get consistent results
150
+ });
151
+ assert.ok(result.includes('2024') || result.includes('1/1')); // Different locales format differently
152
+ });
153
+ it('should auto-detect milliseconds for large numbers', () => {
154
+ // Timestamp > 10 billion should be treated as milliseconds
155
+ const timestampMs = 1704067200000;
156
+ const timestampSec = 1704067200;
157
+ const resultMs = formatAbsoluteTimestamp(timestampMs);
158
+ const resultSec = formatAbsoluteTimestamp(timestampSec);
159
+ // Both should produce the same date
160
+ assert.equal(resultMs, resultSec);
161
+ });
162
+ });
163
+ describe('interval constants', () => {
164
+ it('should have correct second value', () => {
165
+ assert.equal(interval.second, 1000);
166
+ });
167
+ it('should have correct minute value', () => {
168
+ assert.equal(interval.minute, 60 * 1000);
169
+ });
170
+ it('should have correct hour value', () => {
171
+ assert.equal(interval.hour, 60 * 60 * 1000);
172
+ });
173
+ it('should have correct day value', () => {
174
+ assert.equal(interval.day, 24 * 60 * 60 * 1000);
175
+ });
176
+ });
177
+ describe('intervalIn constants', () => {
178
+ it('should have correct values', () => {
179
+ assert.equal(intervalIn.yearInDays, 365);
180
+ assert.equal(intervalIn.quarterInMonths, 3);
181
+ assert.equal(intervalIn.monthInDays, 30);
182
+ assert.equal(intervalIn.hourInDays, 24);
183
+ assert.equal(intervalIn.daysInWeek, 7);
184
+ assert.equal(intervalIn.minuteInHours, 60);
185
+ assert.equal(intervalIn.secondInMinutes, 60);
186
+ assert.equal(intervalIn.millisecondInSecond, 1000);
187
+ });
188
+ });
189
+ describe('defaultDisplayInterval', () => {
190
+ it('should have correct default values', () => {
191
+ assert.equal(defaultDisplayInterval.hour, 7 * 24);
192
+ assert.equal(defaultDisplayInterval.day, 6 * 30);
193
+ assert.equal(defaultDisplayInterval.month, 60);
194
+ });
195
+ });
196
+ describe('formatTimestamp edge cases', () => {
197
+ const anchor = new Date('2025-01-05T12:00:00Z');
198
+ it('should show "Just now" for showSeconds with very recent timestamp', () => {
199
+ const recent = new Date(anchor.getTime() - 5 * 1000); // 5 seconds ago
200
+ assert.equal(formatTimestamp(recent, { anchor, showSeconds: true }), 'Just now');
201
+ });
202
+ it('should show seconds for 10-59 seconds ago', () => {
203
+ const recent = new Date(anchor.getTime() - 15 * 1000); // 15 seconds ago
204
+ const result = formatTimestamp(recent, { anchor, showSeconds: true });
205
+ assert.equal(result, '15s ago');
206
+ });
207
+ it('should use default anchor and showSeconds when no options provided', () => {
208
+ // Test calling with no options object to cover default parameter initialization
209
+ const recent = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes ago
210
+ const result = formatTimestamp(recent);
211
+ assert.ok(result.includes('m ago'));
212
+ });
213
+ it('should use defaults when empty options object provided', () => {
214
+ // Test calling with empty options to cover default parameter values
215
+ const recent = new Date(Date.now() - 10 * 60 * 1000); // 10 minutes ago
216
+ const result = formatTimestamp(recent, {});
217
+ assert.ok(result.includes('m ago'));
218
+ });
219
+ it('should use default anchor when only showSeconds provided', () => {
220
+ const recent = new Date(Date.now() - 30 * 1000); // 30 seconds ago
221
+ const result = formatTimestamp(recent, { showSeconds: true });
222
+ assert.ok(result.includes('s ago'));
223
+ });
224
+ it('should use default showSeconds when only anchor provided', () => {
225
+ const anchor = new Date('2025-01-05T12:00:00Z');
226
+ const recent = new Date(anchor.getTime() - 5 * 1000); // 5 seconds ago
227
+ const result = formatTimestamp(recent, { anchor });
228
+ assert.equal(result, 'Just now'); // showSeconds defaults to false
229
+ });
230
+ });
231
+ });