@evolu/common 8.0.0-next.4 → 8.0.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.
- package/dist/src/Array.d.ts +279 -173
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +105 -101
- package/dist/src/Assert.d.ts +44 -44
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +44 -32
- package/dist/src/BigInt.d.ts +6 -3
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -2
- package/dist/src/Brand.d.ts +27 -40
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Buffer.d.ts +27 -11
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Cache.d.ts +9 -4
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +8 -3
- package/dist/src/Callbacks.d.ts +30 -19
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Console.d.ts +145 -66
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +91 -43
- package/dist/src/Crypto.d.ts +85 -42
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +44 -20
- package/dist/src/Eq.d.ts +87 -21
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +67 -19
- package/dist/src/Error.d.ts +5 -3
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +16 -0
- package/dist/src/Function.d.ts +119 -58
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +86 -43
- package/dist/src/Http.d.ts +394 -0
- package/dist/src/Http.d.ts.map +1 -0
- package/dist/src/Http.js +102 -0
- package/dist/src/Identicon.d.ts +16 -7
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +14 -5
- package/dist/src/LeakDetector.d.ts +88 -0
- package/dist/src/LeakDetector.d.ts.map +1 -0
- package/dist/src/LeakDetector.js +86 -0
- package/dist/src/LockManager.d.ts +18 -9
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +7 -8
- package/dist/src/Lookup.d.ts +43 -13
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +28 -8
- package/dist/src/Microtask.d.ts +1 -1
- package/dist/src/Microtask.d.ts.map +1 -1
- package/dist/src/Microtask.js +3 -7
- package/dist/src/Number.d.ts +49 -13
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +34 -5
- package/dist/src/Object.d.ts +160 -40
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +92 -46
- package/dist/src/Option.d.ts +10 -7
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +9 -6
- package/dist/src/Order.d.ts +21 -21
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +18 -21
- package/dist/src/Platform.d.ts +31 -0
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +98 -0
- package/dist/src/Random.d.ts +32 -17
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +12 -8
- package/dist/src/Redacted.d.ts +43 -29
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +14 -3
- package/dist/src/Ref.d.ts +11 -3
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +2 -2
- package/dist/src/RefCount.d.ts +2 -6
- package/dist/src/RefCount.d.ts.map +1 -1
- package/dist/src/RefCount.js +33 -90
- package/dist/src/Relation.d.ts +70 -5
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +77 -2
- package/dist/src/Resource.d.ts +590 -155
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +592 -343
- package/dist/src/Result.d.ts +838 -191
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +163 -102
- package/dist/src/Schedule.d.ts +684 -231
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +766 -295
- package/dist/src/Set.d.ts +89 -40
- package/dist/src/Set.d.ts.map +1 -1
- package/dist/src/Set.js +50 -29
- package/dist/src/Sqlite.d.ts +29 -72
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +41 -46
- package/dist/src/StackTrace.d.ts +40 -0
- package/dist/src/StackTrace.d.ts.map +1 -0
- package/dist/src/StackTrace.js +140 -0
- package/dist/src/Store.d.ts +5 -4
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +5 -4
- package/dist/src/String.d.ts +7 -1
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +20 -7
- package/dist/src/Task.d.ts +3572 -1770
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1879 -1274
- package/dist/src/Test.d.ts +17 -125
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +17 -68
- package/dist/src/Time.d.ts +108 -49
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +172 -73
- package/dist/src/Type.d.ts +3542 -1926
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +3070 -1784
- package/dist/src/Types.d.ts +200 -108
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +39 -8
- package/dist/src/WebSocket.d.ts +48 -23
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +15 -6
- package/dist/src/Worker.d.ts +94 -36
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +58 -24
- package/dist/src/index.d.ts +55 -52
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/intl/cs.d.ts +94 -0
- package/dist/src/intl/cs.d.ts.map +1 -0
- package/dist/src/intl/cs.js +220 -0
- package/dist/src/intl/index.d.ts +7 -0
- package/dist/src/intl/index.d.ts.map +1 -0
- package/dist/src/intl/index.js +6 -0
- package/dist/src/local-first/Db.d.ts +12 -8
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +109 -132
- package/dist/src/local-first/Error.d.ts +4 -4
- package/dist/src/local-first/Evolu.d.ts +338 -92
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +47 -55
- package/dist/src/local-first/LocalAuth.d.ts +4 -4
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/Owner.d.ts +61 -24
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +45 -8
- package/dist/src/local-first/Protocol.d.ts +44 -31
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +36 -13
- package/dist/src/local-first/Query.d.ts +147 -62
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +112 -58
- package/dist/src/local-first/Relay.d.ts +44 -14
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +92 -41
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +25 -8
- package/dist/src/local-first/Shared.d.ts +23 -21
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +100 -57
- package/dist/src/local-first/Storage.d.ts +53 -32
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +194 -234
- package/dist/src/local-first/Timestamp.d.ts +21 -21
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +2 -2
- package/dist/src/local-first/index.d.ts +11 -11
- package/package.json +14 -13
- package/src/Array.ts +306 -205
- package/src/Assert.ts +54 -69
- package/src/BigInt.ts +6 -3
- package/src/Brand.ts +27 -40
- package/src/Buffer.ts +28 -12
- package/src/Cache.ts +9 -4
- package/src/Callbacks.ts +30 -19
- package/src/Console.ts +156 -84
- package/src/Crypto.ts +83 -41
- package/src/Eq.ts +95 -22
- package/src/Error.ts +8 -4
- package/src/Function.ts +167 -59
- package/src/Http.ts +549 -0
- package/src/Identicon.ts +16 -7
- package/src/LeakDetector.ts +182 -0
- package/src/LockManager.ts +43 -39
- package/src/Lookup.ts +62 -28
- package/src/Microtask.ts +19 -23
- package/src/Number.ts +64 -12
- package/src/Object.ts +173 -49
- package/src/Option.ts +10 -7
- package/src/Order.ts +23 -21
- package/src/Platform.ts +136 -0
- package/src/Polyfills.ts +6 -12
- package/src/Random.ts +32 -19
- package/src/Redacted.ts +44 -30
- package/src/Ref.ts +14 -6
- package/src/RefCount.ts +38 -80
- package/src/Relation.ts +202 -10
- package/src/Resource.ts +1199 -591
- package/src/Result.ts +930 -271
- package/src/Schedule.ts +859 -343
- package/src/Set.ts +89 -40
- package/src/Sqlite.ts +144 -138
- package/src/StackTrace.ts +230 -0
- package/src/Store.ts +8 -7
- package/src/String.ts +22 -5
- package/src/Task.ts +5101 -2832
- package/src/Test.ts +20 -168
- package/src/Time.ts +293 -90
- package/src/Type.ts +10034 -4117
- package/src/Types.ts +227 -110
- package/src/WebSocket.ts +64 -36
- package/src/Worker.ts +180 -72
- package/src/index.ts +55 -52
- package/src/intl/cs.ts +388 -0
- package/src/intl/index.ts +7 -0
- package/src/local-first/Db.ts +152 -179
- package/src/local-first/Error.ts +4 -4
- package/src/local-first/Evolu.ts +495 -250
- package/src/local-first/LocalAuth.ts +6 -12
- package/src/local-first/Owner.ts +58 -21
- package/src/local-first/Protocol.ts +49 -31
- package/src/local-first/Query.ts +146 -61
- package/src/local-first/Relay.ts +51 -21
- package/src/local-first/Schema.ts +109 -51
- package/src/local-first/Shared.ts +266 -226
- package/src/local-first/Storage.ts +266 -264
- package/src/local-first/Timestamp.ts +25 -18
- package/src/local-first/index.ts +11 -11
- package/dist/src/Skiplist.d.ts +0 -28
- package/dist/src/Skiplist.d.ts.map +0 -1
- package/dist/src/Skiplist.js +0 -64
- package/dist/src/Tracer.d.ts +0 -48
- package/dist/src/Tracer.d.ts.map +0 -1
- package/dist/src/Tracer.js +0 -6
- package/src/Skiplist.ts +0 -108
- package/src/Tracer.ts +0 -54
package/dist/src/Time.js
CHANGED
|
@@ -4,24 +4,86 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
import { assert } from "./Assert.js";
|
|
7
|
-
import { brand, lessThan, NonNegativeInt } from "./Type.js";
|
|
7
|
+
import { brand, lessThan, NonNegativeInt, positive, } from "./Type.js";
|
|
8
8
|
/**
|
|
9
|
-
* Creates a {@link Time} using `Date.now()` and
|
|
9
|
+
* Creates a {@link Time} using `Date.now()`, `performance`, and
|
|
10
|
+
* `globalThis.setTimeout`.
|
|
11
|
+
*
|
|
12
|
+
* Long timeouts are split into native timer chunks and tracked against an
|
|
13
|
+
* absolute wall-clock deadline so late callback execution and system suspension
|
|
14
|
+
* do not extend the requested delay. System clock adjustments can therefore
|
|
15
|
+
* shorten or lengthen long timeouts.
|
|
10
16
|
*
|
|
11
17
|
* Throws if the system clock returns an out-of-range value. This is intentional
|
|
12
18
|
* — there's no reasonable fallback for a misconfigured clock.
|
|
13
19
|
*/
|
|
14
20
|
export const createTime = () => {
|
|
15
|
-
const
|
|
21
|
+
const timeoutOwner = Symbol("Time");
|
|
22
|
+
function now(type) {
|
|
23
|
+
const millis = getSystemNowMillis();
|
|
24
|
+
return type === "DateIso" ? millisToDateIso(millis) : millis;
|
|
25
|
+
}
|
|
16
26
|
return {
|
|
17
|
-
now
|
|
18
|
-
|
|
19
|
-
|
|
27
|
+
now,
|
|
28
|
+
performance: {
|
|
29
|
+
timeOrigin: globalThis.performance.timeOrigin,
|
|
30
|
+
now: () => globalThis.performance.now(),
|
|
31
|
+
},
|
|
32
|
+
setTimeout: (callback, duration) => scheduleNativeTimeout(timeoutOwner, callback, duration),
|
|
20
33
|
clearTimeout: (id) => {
|
|
21
|
-
|
|
34
|
+
clearTimeoutId(timeoutOwner, id);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const scheduleNativeTimeout = (owner, callback, duration) => {
|
|
39
|
+
const delay = durationToMillis(duration);
|
|
40
|
+
let cancelled = false;
|
|
41
|
+
let nativeId;
|
|
42
|
+
if (delay <= maxNativeTimeoutMillis) {
|
|
43
|
+
nativeId = globalThis.setTimeout(() => {
|
|
44
|
+
if (cancelled)
|
|
45
|
+
return;
|
|
46
|
+
cancelled = true;
|
|
47
|
+
callback();
|
|
48
|
+
}, delay);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Recompute each chunk from one absolute deadline so time elapsed while the
|
|
52
|
+
// event loop is suspended, for example during system sleep, is not added again.
|
|
53
|
+
const deadline = getSystemNowMillis() + delay;
|
|
54
|
+
const onTimeout = () => {
|
|
55
|
+
if (cancelled)
|
|
56
|
+
return;
|
|
57
|
+
const remaining = deadline - getSystemNowMillis();
|
|
58
|
+
if (remaining > 0) {
|
|
59
|
+
nativeId = globalThis.setTimeout(onTimeout, Math.min(remaining, maxNativeTimeoutMillis));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
cancelled = true;
|
|
63
|
+
callback();
|
|
64
|
+
};
|
|
65
|
+
nativeId = globalThis.setTimeout(onTimeout, maxNativeTimeoutMillis);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
owner,
|
|
69
|
+
clear: () => {
|
|
70
|
+
cancelled = true;
|
|
71
|
+
globalThis.clearTimeout(nativeId);
|
|
22
72
|
},
|
|
23
73
|
};
|
|
24
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* Maximum delay supported reliably by native timers: the largest positive
|
|
77
|
+
* signed 32-bit integer, approximately 24.9 days in milliseconds. Longer
|
|
78
|
+
* logical delays are scheduled in chunks to avoid native timer overflow.
|
|
79
|
+
*/
|
|
80
|
+
const maxNativeTimeoutMillis = 2 ** 31 - 1;
|
|
81
|
+
const getSystemNowMillis = () => Millis.orThrow(globalThis.Date.now());
|
|
82
|
+
const clearTimeoutId = (owner, id) => {
|
|
83
|
+
const internal = id;
|
|
84
|
+
assert(internal.owner === owner, "TimeoutId was created by another Time instance");
|
|
85
|
+
internal.clear();
|
|
86
|
+
};
|
|
25
87
|
/**
|
|
26
88
|
* Creates a {@link TestTime} with controllable timers for testing.
|
|
27
89
|
*
|
|
@@ -29,15 +91,18 @@ export const createTime = () => {
|
|
|
29
91
|
* called. Timeouts scheduled via `setTimeout` fire when time is advanced past
|
|
30
92
|
* their deadline.
|
|
31
93
|
*
|
|
32
|
-
* Set `autoIncrement` to automatically increment time by 1ms after each
|
|
33
|
-
* call. `"microtask"` increments after the
|
|
34
|
-
* increments immediately after each read. Omit it
|
|
35
|
-
* `advance()` is called.
|
|
94
|
+
* Set `autoIncrement` to automatically increment time by 1ms after each
|
|
95
|
+
* wall-clock or performance `now()` call. `"microtask"` increments after the
|
|
96
|
+
* current turn, while `"sync"` increments immediately after each read. Omit it
|
|
97
|
+
* to keep time fixed until `advance()` is called.
|
|
36
98
|
*/
|
|
37
99
|
export const testCreateTime = (options) => {
|
|
38
|
-
|
|
100
|
+
const startAt = options?.startAt ?? minMillis;
|
|
39
101
|
const autoIncrement = options?.autoIncrement;
|
|
102
|
+
const timeoutOwner = Symbol("TestTime");
|
|
103
|
+
let now = startAt;
|
|
40
104
|
let nextId = 1;
|
|
105
|
+
let advancing = false;
|
|
41
106
|
const pending = new Map();
|
|
42
107
|
const incrementNow = () => {
|
|
43
108
|
now = Millis.orThrow(now + 1);
|
|
@@ -54,24 +119,55 @@ export const testCreateTime = (options) => {
|
|
|
54
119
|
}
|
|
55
120
|
return result;
|
|
56
121
|
};
|
|
122
|
+
function getNow(type) {
|
|
123
|
+
const millis = getNowMillis();
|
|
124
|
+
return type === "DateIso" ? millisToDateIso(millis) : millis;
|
|
125
|
+
}
|
|
57
126
|
return {
|
|
58
|
-
now:
|
|
59
|
-
|
|
127
|
+
now: getNow,
|
|
128
|
+
performance: {
|
|
129
|
+
timeOrigin: Number(startAt),
|
|
130
|
+
now: () => (getNowMillis() - startAt),
|
|
131
|
+
},
|
|
60
132
|
setTimeout: (callback, delay) => {
|
|
133
|
+
const runAt = Millis.orThrow(now + durationToMillis(delay));
|
|
61
134
|
const id = nextId++;
|
|
62
|
-
pending.set(id, { callback, runAt
|
|
63
|
-
return
|
|
135
|
+
pending.set(id, { callback, runAt });
|
|
136
|
+
return {
|
|
137
|
+
owner: timeoutOwner,
|
|
138
|
+
clear: () => {
|
|
139
|
+
pending.delete(id);
|
|
140
|
+
},
|
|
141
|
+
};
|
|
64
142
|
},
|
|
65
143
|
clearTimeout: (id) => {
|
|
66
|
-
|
|
144
|
+
clearTimeoutId(timeoutOwner, id);
|
|
67
145
|
},
|
|
68
146
|
advance: (duration) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
147
|
+
assert(!advancing, "TestTime.advance cannot be called while advancing");
|
|
148
|
+
const target = Millis.orThrow(now + durationToMillis(duration));
|
|
149
|
+
advancing = true;
|
|
150
|
+
try {
|
|
151
|
+
while (pending.size > 0) {
|
|
152
|
+
let earliestId = null;
|
|
153
|
+
let nextRunAt = Number.POSITIVE_INFINITY;
|
|
154
|
+
for (const [id, timeout] of pending) {
|
|
155
|
+
if (timeout.runAt <= target && timeout.runAt < nextRunAt) {
|
|
156
|
+
earliestId = id;
|
|
157
|
+
nextRunAt = timeout.runAt;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (earliestId === null)
|
|
161
|
+
break;
|
|
162
|
+
const timeout = pending.get(earliestId);
|
|
163
|
+
pending.delete(earliestId);
|
|
164
|
+
now = Millis.orThrow(Math.max(now, nextRunAt));
|
|
73
165
|
timeout.callback();
|
|
74
166
|
}
|
|
167
|
+
now = Millis.orThrow(Math.max(now, target));
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
advancing = false;
|
|
75
171
|
}
|
|
76
172
|
},
|
|
77
173
|
};
|
|
@@ -79,7 +175,7 @@ export const testCreateTime = (options) => {
|
|
|
79
175
|
// Literal (not expression like 1 + 2) to preserve type for Brand<"LessThan...">
|
|
80
176
|
const maxMillisWithInfinity = 281474976710655;
|
|
81
177
|
/**
|
|
82
|
-
*
|
|
178
|
+
* Non-negative integer milliseconds used for timestamps and durations.
|
|
83
179
|
*
|
|
84
180
|
* The maximum value is 281474976710654 (281474976710655 - 1, reserved for
|
|
85
181
|
* infinity). This enables efficient binary serialization, saving 2 bytes
|
|
@@ -92,6 +188,8 @@ const maxMillisWithInfinity = 281474976710655;
|
|
|
92
188
|
*/
|
|
93
189
|
export const Millis = /*#__PURE__*/ brand("Millis",
|
|
94
190
|
/*#__PURE__*/ lessThan(maxMillisWithInfinity)(NonNegativeInt));
|
|
191
|
+
/** Positive {@link Millis} value. */
|
|
192
|
+
export const PositiveMillis = /*#__PURE__*/ positive(Millis);
|
|
95
193
|
/** Minimum {@link Millis} value. */
|
|
96
194
|
export const minMillis = 0;
|
|
97
195
|
/** Maximum {@link Millis} value. */
|
|
@@ -109,46 +207,22 @@ export const saturateMillis = (value) => Millis.orNull(Math.max(0, Math.round(va
|
|
|
109
207
|
*/
|
|
110
208
|
export const millisToDateIso = (value) => new globalThis.Date(value).toISOString();
|
|
111
209
|
/**
|
|
112
|
-
*
|
|
210
|
+
* Returns the elapsed fractional milliseconds between two performance times.
|
|
113
211
|
*
|
|
114
|
-
*
|
|
115
|
-
* {@link Millis}.
|
|
116
|
-
*
|
|
117
|
-
* ### Example
|
|
118
|
-
*
|
|
119
|
-
* ```ts
|
|
120
|
-
* durationToMillis("1ms"); // 1
|
|
121
|
-
* durationToMillis("500ms"); // 500
|
|
122
|
-
* durationToMillis("1.5s"); // 1500
|
|
123
|
-
* durationToMillis("30s"); // 30000
|
|
124
|
-
* durationToMillis("5m"); // 300000
|
|
125
|
-
* durationToMillis("12h"); // 43200000
|
|
126
|
-
* durationToMillis("7d"); // 604800000
|
|
127
|
-
* durationToMillis(Millis.orThrow(5000)); // 5000 (already Millis)
|
|
128
|
-
* ```
|
|
212
|
+
* Throws if `end` precedes `start`.
|
|
129
213
|
*/
|
|
130
|
-
export const
|
|
214
|
+
export const performanceDurationBetween = (start, end) => {
|
|
215
|
+
assert(end >= start, "Performance end time must not precede start time");
|
|
216
|
+
return (end - start);
|
|
217
|
+
};
|
|
218
|
+
export function durationToMillis(duration) {
|
|
131
219
|
if (typeof duration === "number")
|
|
132
220
|
return duration;
|
|
133
221
|
const num = parseFloat(duration);
|
|
134
222
|
const unit = duration.endsWith("ms") ? "ms" : duration.at(-1);
|
|
135
223
|
assert(unit in durationUnits, `Unknown duration unit: ${unit}`);
|
|
136
224
|
return Millis.orThrow(Math.round(num * durationUnits[unit]));
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Returns a Promise that resolves after the specified duration.
|
|
140
|
-
*
|
|
141
|
-
* Uses {@link Duration} parsing and `globalThis.setTimeout`.
|
|
142
|
-
*
|
|
143
|
-
* ### Example
|
|
144
|
-
*
|
|
145
|
-
* ```ts
|
|
146
|
-
* await setTimeout("1ms");
|
|
147
|
-
* ```
|
|
148
|
-
*/
|
|
149
|
-
export const setTimeout = (duration) => new Promise((resolve) => {
|
|
150
|
-
globalThis.setTimeout(resolve, durationToMillis(duration));
|
|
151
|
-
});
|
|
225
|
+
}
|
|
152
226
|
const durationUnits = {
|
|
153
227
|
ms: 1,
|
|
154
228
|
s: 1000,
|
|
@@ -184,40 +258,65 @@ export const msLongTask = 50;
|
|
|
184
258
|
*
|
|
185
259
|
* - Under 1 minute: `1.234s`
|
|
186
260
|
* - Under 1 hour: `1m30.000s`
|
|
187
|
-
* - 1
|
|
261
|
+
* - Under 1 day: `1h30m45.000s`
|
|
262
|
+
* - Under 1 week: `1d2h30m45.000s`
|
|
263
|
+
* - Under 1 year: `1w2d3h30m45.000s`
|
|
264
|
+
* - 1 year or more: `1y2w3d4h30m45.000s`
|
|
265
|
+
*
|
|
266
|
+
* Weeks are 7 days and years are 365 days.
|
|
188
267
|
*
|
|
189
268
|
* ### Example
|
|
190
269
|
*
|
|
191
270
|
* ```ts
|
|
192
|
-
* formatMillisAsDuration
|
|
193
|
-
*
|
|
194
|
-
* formatMillisAsDuration(
|
|
271
|
+
* import { formatMillisAsDuration, Millis } from "@evolu/common";
|
|
272
|
+
*
|
|
273
|
+
* expect(formatMillisAsDuration(Millis.orThrow(1234))).toBe("1.234s");
|
|
274
|
+
* expect(formatMillisAsDuration(Millis.orThrow(90000))).toBe("1m30.000s");
|
|
275
|
+
* expect(formatMillisAsDuration(Millis.orThrow(90061000))).toBe(
|
|
276
|
+
* "1d1h1m1.000s",
|
|
277
|
+
* );
|
|
195
278
|
* ```
|
|
196
279
|
*/
|
|
197
280
|
export const formatMillisAsDuration = (millis) => {
|
|
198
|
-
const
|
|
199
|
-
if (
|
|
200
|
-
return `${
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const minutes = Math.floor(elapsed / 60);
|
|
204
|
-
const seconds = (elapsed % 60).toFixed(3);
|
|
281
|
+
const seconds = ((millis % durationUnits.m) / durationUnits.s).toFixed(3);
|
|
282
|
+
if (millis < durationUnits.m)
|
|
283
|
+
return `${seconds}s`;
|
|
284
|
+
const minutes = Math.floor(millis / durationUnits.m) % 60;
|
|
285
|
+
if (millis < durationUnits.h)
|
|
205
286
|
return `${minutes}m${seconds}s`;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const hours = Math.floor(elapsed / 3600);
|
|
209
|
-
const minutes = Math.floor((elapsed % 3600) / 60);
|
|
210
|
-
const seconds = ((elapsed % 3600) % 60).toFixed(3);
|
|
287
|
+
const hours = Math.floor(millis / durationUnits.h) % 24;
|
|
288
|
+
if (millis < durationUnits.d)
|
|
211
289
|
return `${hours}h${minutes}m${seconds}s`;
|
|
212
|
-
|
|
290
|
+
const daysAfterYears = Math.floor((millis % durationUnits.y) / durationUnits.d);
|
|
291
|
+
const days = daysAfterYears % 7;
|
|
292
|
+
if (millis < durationUnits.w)
|
|
293
|
+
return `${days}d${hours}h${minutes}m${seconds}s`;
|
|
294
|
+
const weeks = Math.floor(daysAfterYears / 7);
|
|
295
|
+
if (millis < durationUnits.y)
|
|
296
|
+
return `${weeks}w${days}d${hours}h${minutes}m${seconds}s`;
|
|
297
|
+
const years = Math.floor(millis / durationUnits.y);
|
|
298
|
+
return `${years}y${weeks}w${days}d${hours}h${minutes}m${seconds}s`;
|
|
213
299
|
};
|
|
214
300
|
/**
|
|
215
|
-
* Formats {@link Millis} as `HH:MM:SS.mmm
|
|
301
|
+
* Formats {@link Millis} as local time in `HH:MM:SS.mmm` format.
|
|
216
302
|
*
|
|
217
303
|
* ### Example
|
|
218
304
|
*
|
|
219
305
|
* ```ts
|
|
220
|
-
* formatMillisAsClockTime
|
|
306
|
+
* import { formatMillisAsClockTime, Millis } from "@evolu/common";
|
|
307
|
+
*
|
|
308
|
+
* const timestamp = new globalThis.Date(
|
|
309
|
+
* 2026,
|
|
310
|
+
* 0,
|
|
311
|
+
* 28,
|
|
312
|
+
* 14,
|
|
313
|
+
* 32,
|
|
314
|
+
* 15,
|
|
315
|
+
* 234,
|
|
316
|
+
* ).getTime();
|
|
317
|
+
* expect(formatMillisAsClockTime(Millis.orThrow(timestamp))).toBe(
|
|
318
|
+
* "14:32:15.234",
|
|
319
|
+
* );
|
|
221
320
|
* ```
|
|
222
321
|
*/
|
|
223
322
|
export const formatMillisAsClockTime = (millis) => {
|