@evolu/common 8.10.0 → 8.11.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/Config.d.ts +22 -22
- package/dist/src/Config.d.ts.map +1 -1
- package/dist/src/Console.d.ts +62 -7
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +20 -4
- package/dist/src/Crypto.d.ts +76 -4
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +55 -4
- package/dist/src/Error.d.ts +45 -0
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +69 -0
- package/dist/src/Fs.d.ts +92 -18
- package/dist/src/Fs.d.ts.map +1 -1
- package/dist/src/Fs.js +2 -0
- package/dist/src/Identicon.d.ts +2 -2
- package/dist/src/Identicon.js +2 -2
- package/dist/src/LeakDetector.d.ts +22 -3
- package/dist/src/LeakDetector.d.ts.map +1 -1
- package/dist/src/LeakDetector.js +12 -2
- package/dist/src/LockManager.d.ts +8 -0
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +6 -0
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +5 -0
- package/dist/src/Platform.d.ts +47 -7
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +24 -5
- package/dist/src/Random.d.ts +25 -2
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +14 -2
- package/dist/src/Resource.d.ts +156 -1
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +201 -72
- package/dist/src/Schedule.d.ts +11 -10
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +1 -1
- package/dist/src/Sqlite.d.ts +132 -16
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +63 -9
- package/dist/src/Task.d.ts +15 -4
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +41 -15
- package/dist/src/Test.d.ts +9 -0
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +4 -0
- package/dist/src/Time.d.ts +106 -9
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +55 -4
- package/dist/src/Type.d.ts +1455 -1310
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +1274 -517
- package/dist/src/WebSocket.d.ts +164 -13
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +133 -24
- package/dist/src/Worker.d.ts +90 -8
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +28 -2
- package/dist/src/index.d.ts +6 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -3
- package/dist/src/local-first/Db.d.ts +52 -3
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +412 -137
- package/dist/src/local-first/Evolu.d.ts +336 -211
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +102 -15
- package/dist/src/local-first/Owner.d.ts +13 -30
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +13 -30
- package/dist/src/local-first/Protocol.d.ts +94 -16
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +118 -38
- package/dist/src/local-first/Query.d.ts +8 -15
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +335 -21
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +214 -17
- package/dist/src/local-first/Shared.d.ts +537 -22
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +1437 -234
- package/dist/src/local-first/Storage.d.ts +192 -14
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +81 -20
- package/dist/src/local-first/Timestamp.d.ts +392 -41
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +403 -81
- package/dist/src/local-first/index.d.ts +0 -1
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +0 -1
- package/package.json +1 -1
- package/src/Assert.test.ts +2 -5
- package/src/Config.test.ts +2 -6
- package/src/Config.ts +133 -133
- package/src/Console.ts +62 -7
- package/src/Crypto.ts +76 -4
- package/src/Eq.test.ts +2 -3
- package/src/Error.test.ts +76 -3
- package/src/Error.ts +71 -0
- package/src/Fs.ts +92 -18
- package/src/Identicon.ts +2 -2
- package/src/LeakDetector.ts +22 -3
- package/src/LockManager.ts +8 -0
- package/src/Object.test.ts +27 -12
- package/src/Object.ts +5 -0
- package/src/Platform.ts +50 -8
- package/src/Random.ts +25 -2
- package/src/Resource.test.ts +837 -0
- package/src/Resource.ts +235 -15
- package/src/Schedule.test.ts +50 -12
- package/src/Schedule.ts +24 -14
- package/src/Sqlite.ts +137 -17
- package/src/Task.test.ts +189 -8
- package/src/Task.ts +56 -17
- package/src/Test.ts +9 -0
- package/src/Time.ts +106 -9
- package/src/Type.test.ts +946 -1028
- package/src/Type.ts +4195 -3136
- package/src/Types.test.ts +4 -14
- package/src/WebSocket.ts +313 -40
- package/src/Worker.ts +90 -8
- package/src/index.ts +15 -6
- package/src/local-first/Db.ts +644 -339
- package/src/local-first/Evolu.test.ts +686 -21
- package/src/local-first/Evolu.ts +450 -228
- package/src/local-first/Owner.ts +13 -30
- package/src/local-first/Protocol.test.ts +617 -10
- package/src/local-first/Protocol.ts +196 -72
- package/src/local-first/Query.ts +8 -15
- package/src/local-first/Schema.test.ts +143 -0
- package/src/local-first/Schema.ts +363 -24
- package/src/local-first/Shared.test.ts +7731 -559
- package/src/local-first/Shared.ts +2036 -267
- package/src/local-first/Storage.ts +218 -32
- package/src/local-first/Timestamp.test.ts +344 -70
- package/src/local-first/Timestamp.ts +434 -118
- package/src/local-first/index.ts +0 -1
- package/dist/src/local-first/Error.d.ts +0 -12
- package/dist/src/local-first/Error.d.ts.map +0 -1
- package/dist/src/local-first/Error.js +0 -6
- package/dist/src/local-first/LocalAuth.d.ts +0 -150
- package/dist/src/local-first/LocalAuth.d.ts.map +0 -1
- package/dist/src/local-first/LocalAuth.js +0 -179
- package/src/local-first/Error.ts +0 -17
- package/src/local-first/LocalAuth.ts +0 -457
package/src/Task.ts
CHANGED
|
@@ -686,6 +686,7 @@ import {
|
|
|
686
686
|
type RandomBytesDep,
|
|
687
687
|
} from "./Crypto.ts";
|
|
688
688
|
import { eqArraySameValue } from "./Eq.ts";
|
|
689
|
+
import type { defectToError } from "./Error.ts";
|
|
689
690
|
import { constTrue, constVoid, identity } from "./Function.ts";
|
|
690
691
|
import type { fetch, NativeFetch, NativeFetchDep } from "./Http.ts";
|
|
691
692
|
import {
|
|
@@ -1462,10 +1463,20 @@ export interface Run<D = unknown> {
|
|
|
1462
1463
|
callback: (abortError: AbortError) => void,
|
|
1463
1464
|
) => Disposable | null;
|
|
1464
1465
|
|
|
1465
|
-
/**
|
|
1466
|
+
/**
|
|
1467
|
+
* Returns the current {@link RunState} of this {@link Run}.
|
|
1468
|
+
*
|
|
1469
|
+
* Abort requests are recorded before propagating to descendants. Observed
|
|
1470
|
+
* aborts are recorded before this Run's abort callbacks execute.
|
|
1471
|
+
*/
|
|
1466
1472
|
readonly getState: () => RunState;
|
|
1467
1473
|
|
|
1468
|
-
/**
|
|
1474
|
+
/**
|
|
1475
|
+
* Creates a memoized recursive {@link RunSnapshot} of the current Run tree.
|
|
1476
|
+
*
|
|
1477
|
+
* Reflects abort requests and observations with the same timing as
|
|
1478
|
+
* {@link Run.getState}.
|
|
1479
|
+
*/
|
|
1469
1480
|
readonly snapshot: () => RunSnapshot;
|
|
1470
1481
|
|
|
1471
1482
|
/**
|
|
@@ -2085,8 +2096,9 @@ export interface ReportDefectDep {
|
|
|
2085
2096
|
* platforms without native global error reporting. Browser adapters use the
|
|
2086
2097
|
* native
|
|
2087
2098
|
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/reportError | reportError}
|
|
2088
|
-
* API
|
|
2089
|
-
*
|
|
2099
|
+
* API, and other platform adapters can use platform-specific reporting.
|
|
2100
|
+
* Adapters report an `Error` from {@link defectToError}, which such reporting
|
|
2101
|
+
* shows readably.
|
|
2090
2102
|
*
|
|
2091
2103
|
* @group Run
|
|
2092
2104
|
*/
|
|
@@ -2481,6 +2493,7 @@ const createRunInternal = <D extends object>(
|
|
|
2481
2493
|
: abortBehavior.abortMask;
|
|
2482
2494
|
|
|
2483
2495
|
let state: RunState = runningRunState;
|
|
2496
|
+
let publishedState: RunState = state;
|
|
2484
2497
|
let exit: RunExit | undefined;
|
|
2485
2498
|
let snapshot: RunSnapshot | undefined;
|
|
2486
2499
|
|
|
@@ -2533,6 +2546,13 @@ const createRunInternal = <D extends object>(
|
|
|
2533
2546
|
}
|
|
2534
2547
|
};
|
|
2535
2548
|
|
|
2549
|
+
const publishState = (): void => {
|
|
2550
|
+
// A nested disposal may have published this state before the outer abort.
|
|
2551
|
+
if (publishedState === state) return;
|
|
2552
|
+
publishedState = state;
|
|
2553
|
+
emitEvent({ type: "StateChanged", state });
|
|
2554
|
+
};
|
|
2555
|
+
|
|
2536
2556
|
// Reads abort reasons from the Run-owned controllers, which are only
|
|
2537
2557
|
// aborted with AbortError.
|
|
2538
2558
|
const currentAbort = (): RunAbortState["abort"] => ({
|
|
@@ -2542,17 +2562,10 @@ const createRunInternal = <D extends object>(
|
|
|
2542
2562
|
: null,
|
|
2543
2563
|
});
|
|
2544
2564
|
|
|
2545
|
-
const commitState = (nextState: RunState): void => {
|
|
2546
|
-
state = nextState;
|
|
2547
|
-
emitEvent({ type: "StateChanged", state });
|
|
2548
|
-
};
|
|
2549
|
-
|
|
2550
2565
|
const requestAbort = (reason: AbortReason = explicitAbortReason): void => {
|
|
2551
2566
|
if (requestController.signal.aborted) return;
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
if (abortMask === abortableMask) signalController.abort(abortError);
|
|
2555
|
-
commitState({ type: "Aborted", abort: currentAbort() });
|
|
2567
|
+
abortControllers(createAbortError(reason), abortMask === abortableMask);
|
|
2568
|
+
publishState();
|
|
2556
2569
|
};
|
|
2557
2570
|
|
|
2558
2571
|
// The first provided exit claims the Run exit; later exits are ignored. A
|
|
@@ -2569,7 +2582,8 @@ const createRunInternal = <D extends object>(
|
|
|
2569
2582
|
|
|
2570
2583
|
const settle = (): RunExit => {
|
|
2571
2584
|
exit ??= ok(ok());
|
|
2572
|
-
|
|
2585
|
+
state = { type: "Settled", abort: currentAbort(), exit };
|
|
2586
|
+
publishState();
|
|
2573
2587
|
return exit;
|
|
2574
2588
|
};
|
|
2575
2589
|
|
|
@@ -2590,14 +2604,39 @@ const createRunInternal = <D extends object>(
|
|
|
2590
2604
|
|
|
2591
2605
|
const abortError = exit?.ok === false ? exit.error : runDisposedAbortError;
|
|
2592
2606
|
|
|
2607
|
+
// If called from a local abort callback, let its abort operation finish
|
|
2608
|
+
// dispatching callbacks before publishing the state.
|
|
2593
2609
|
const { aborted } = signalController.signal;
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
if (!aborted) commitState({ type: "Aborted", abort: currentAbort() });
|
|
2610
|
+
abortControllers(abortError, true);
|
|
2611
|
+
if (!aborted) publishState();
|
|
2597
2612
|
|
|
2598
2613
|
return disposePromise;
|
|
2599
2614
|
};
|
|
2600
2615
|
|
|
2616
|
+
const abortControllers = (abortError: AbortError, observe: boolean): void => {
|
|
2617
|
+
// Record the request before propagation invokes descendant callbacks.
|
|
2618
|
+
if (!requestController.signal.aborted) {
|
|
2619
|
+
state = {
|
|
2620
|
+
type: "Aborted",
|
|
2621
|
+
abort: { request: abortError.reason, observed: null },
|
|
2622
|
+
};
|
|
2623
|
+
requestController.abort(abortError);
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
// A descendant callback may have disposed this Run reentrantly. Preserve
|
|
2627
|
+
// the first observed reason; otherwise record it before local callbacks.
|
|
2628
|
+
if (observe && !signalController.signal.aborted) {
|
|
2629
|
+
state = {
|
|
2630
|
+
type: "Aborted",
|
|
2631
|
+
abort: {
|
|
2632
|
+
request: (requestController.signal.reason as AbortError).reason,
|
|
2633
|
+
observed: abortError.reason,
|
|
2634
|
+
},
|
|
2635
|
+
};
|
|
2636
|
+
signalController.abort(abortError);
|
|
2637
|
+
}
|
|
2638
|
+
};
|
|
2639
|
+
|
|
2601
2640
|
// Custom deps replace parent custom deps, so defaults must be picked from
|
|
2602
2641
|
// the merged deps by key. `satisfies RunDefaultDeps` fails to compile when
|
|
2603
2642
|
// a newly added required default dep is missing here; optional ones like
|
package/src/Test.ts
CHANGED
|
@@ -38,6 +38,8 @@ import { createId, type Id } from "./Type.ts";
|
|
|
38
38
|
* }
|
|
39
39
|
* assertFalse(Reflect.has(globalThis, key));
|
|
40
40
|
* ```
|
|
41
|
+
*
|
|
42
|
+
* @group Testing
|
|
41
43
|
*/
|
|
42
44
|
export const testStubGlobal = (
|
|
43
45
|
key: PropertyKey,
|
|
@@ -58,6 +60,11 @@ export const testStubGlobal = (
|
|
|
58
60
|
return disposer;
|
|
59
61
|
};
|
|
60
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Deterministic id factory returned by {@link testCreateId}.
|
|
65
|
+
*
|
|
66
|
+
* @group Testing
|
|
67
|
+
*/
|
|
61
68
|
export type TestCreateId = <B extends string = never>() => [B] extends [never]
|
|
62
69
|
? Id
|
|
63
70
|
: Id & Brand<B>;
|
|
@@ -96,6 +103,8 @@ export type TestCreateId = <B extends string = never>() => [B] extends [never]
|
|
|
96
103
|
* assertEqual(replayCreateId(), callbackId);
|
|
97
104
|
* assertType<typeof todoId, Id & Brand<"Todo">>();
|
|
98
105
|
* ```
|
|
106
|
+
*
|
|
107
|
+
* @group Testing
|
|
99
108
|
*/
|
|
100
109
|
export const testCreateId = (): TestCreateId => {
|
|
101
110
|
const randomBytes = testCreateRandomBytes({
|
package/src/Time.ts
CHANGED
|
@@ -42,7 +42,11 @@ import {
|
|
|
42
42
|
union,
|
|
43
43
|
} from "./Type.ts";
|
|
44
44
|
|
|
45
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Time and timer operations.
|
|
47
|
+
*
|
|
48
|
+
* @group Core
|
|
49
|
+
*/
|
|
46
50
|
export interface Time {
|
|
47
51
|
readonly now: {
|
|
48
52
|
/** Returns current time as Unix epoch milliseconds. */
|
|
@@ -80,6 +84,11 @@ export interface Time {
|
|
|
80
84
|
readonly clearTimeout: (id: TimeoutId) => void;
|
|
81
85
|
}
|
|
82
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Dependency wrapper for {@link Time}.
|
|
89
|
+
*
|
|
90
|
+
* @group Core
|
|
91
|
+
*/
|
|
83
92
|
export interface TimeDep {
|
|
84
93
|
readonly time: Time;
|
|
85
94
|
}
|
|
@@ -88,6 +97,8 @@ export interface TimeDep {
|
|
|
88
97
|
* Opaque type for timeout handles.
|
|
89
98
|
*
|
|
90
99
|
* Use with {@link Time.clearTimeout} to cancel a pending timeout.
|
|
100
|
+
*
|
|
101
|
+
* @group Core
|
|
91
102
|
*/
|
|
92
103
|
export type TimeoutId = Brand<"TimeoutId">;
|
|
93
104
|
|
|
@@ -107,6 +118,8 @@ interface TimeoutIdInternal {
|
|
|
107
118
|
*
|
|
108
119
|
* Throws if the system clock returns an out-of-range value. This is intentional
|
|
109
120
|
* — there's no reasonable fallback for a misconfigured clock.
|
|
121
|
+
*
|
|
122
|
+
* @group Core
|
|
110
123
|
*/
|
|
111
124
|
export const createTime = (): Time => {
|
|
112
125
|
const timeoutOwner = Symbol("Time");
|
|
@@ -204,6 +217,8 @@ const clearTimeoutId = (owner: symbol, id: TimeoutId): void => {
|
|
|
204
217
|
* Test {@link Time} with controllable timers.
|
|
205
218
|
*
|
|
206
219
|
* Call `advance(ms)` to move time forward and trigger any pending timeouts.
|
|
220
|
+
*
|
|
221
|
+
* @group Testing
|
|
207
222
|
*/
|
|
208
223
|
export interface TestTime extends Time {
|
|
209
224
|
/**
|
|
@@ -215,6 +230,11 @@ export interface TestTime extends Time {
|
|
|
215
230
|
readonly advance: (duration: Duration) => void;
|
|
216
231
|
}
|
|
217
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Dependency wrapper for {@link TestTime}.
|
|
235
|
+
*
|
|
236
|
+
* @group Testing
|
|
237
|
+
*/
|
|
218
238
|
export interface TestTimeDep {
|
|
219
239
|
readonly time: TestTime;
|
|
220
240
|
}
|
|
@@ -230,6 +250,8 @@ export interface TestTimeDep {
|
|
|
230
250
|
* wall-clock or performance `now()` call. `"microtask"` increments after the
|
|
231
251
|
* current turn, while `"sync"` increments immediately after each read. Omit it
|
|
232
252
|
* to keep time fixed until `advance()` is called.
|
|
253
|
+
*
|
|
254
|
+
* @group Testing
|
|
233
255
|
*/
|
|
234
256
|
export const testCreateTime = (options?: {
|
|
235
257
|
readonly startAt?: Millis;
|
|
@@ -341,6 +363,8 @@ const maxMillisWithInfinity = 281474976710655;
|
|
|
341
363
|
*
|
|
342
364
|
* If a system clock exceeds this range, operations will throw. This is
|
|
343
365
|
* intentional — there's no reasonable fallback for a misconfigured clock.
|
|
366
|
+
*
|
|
367
|
+
* @group Millis
|
|
344
368
|
*/
|
|
345
369
|
export const Millis = /*#__PURE__*/ brand(
|
|
346
370
|
"Millis",
|
|
@@ -348,19 +372,33 @@ export const Millis = /*#__PURE__*/ brand(
|
|
|
348
372
|
);
|
|
349
373
|
export type Millis = typeof Millis.Output;
|
|
350
374
|
|
|
351
|
-
/**
|
|
375
|
+
/**
|
|
376
|
+
* Positive {@link Millis} value.
|
|
377
|
+
*
|
|
378
|
+
* @group Millis
|
|
379
|
+
*/
|
|
352
380
|
export const PositiveMillis = /*#__PURE__*/ positive(Millis);
|
|
353
381
|
export type PositiveMillis = typeof PositiveMillis.Output;
|
|
354
382
|
|
|
355
|
-
/**
|
|
383
|
+
/**
|
|
384
|
+
* Minimum {@link Millis} value.
|
|
385
|
+
*
|
|
386
|
+
* @group Millis
|
|
387
|
+
*/
|
|
356
388
|
export const minMillis = 0 as Millis;
|
|
357
389
|
|
|
358
|
-
/**
|
|
390
|
+
/**
|
|
391
|
+
* Maximum {@link Millis} value.
|
|
392
|
+
*
|
|
393
|
+
* @group Millis
|
|
394
|
+
*/
|
|
359
395
|
export const maxMillis = (maxMillisWithInfinity - 1) as Millis;
|
|
360
396
|
|
|
361
397
|
/**
|
|
362
398
|
* Converts a number to {@link Millis}, rounding to the nearest millisecond and
|
|
363
399
|
* saturating overflow at {@link maxMillis}.
|
|
400
|
+
*
|
|
401
|
+
* @group Millis
|
|
364
402
|
*/
|
|
365
403
|
export const saturateMillis = (value: NonNaNNumber): Millis =>
|
|
366
404
|
Millis.orNull(Math.max(0, Math.round(value))) ?? maxMillis;
|
|
@@ -370,23 +408,39 @@ export const saturateMillis = (value: NonNaNNumber): Millis =>
|
|
|
370
408
|
*
|
|
371
409
|
* This is a safe cast because {@link Millis} guarantees a valid timestamp range
|
|
372
410
|
* that always produces a valid ISO string.
|
|
411
|
+
*
|
|
412
|
+
* @group Millis
|
|
373
413
|
*/
|
|
374
414
|
export const millisToDateIso = (value: Millis): DateIso =>
|
|
375
415
|
new Date(value).toISOString() as DateIso;
|
|
376
416
|
|
|
377
|
-
/**
|
|
417
|
+
/**
|
|
418
|
+
* Unix epoch milliseconds used as the origin for {@link PerformanceTime}.
|
|
419
|
+
*
|
|
420
|
+
* @group Performance
|
|
421
|
+
*/
|
|
378
422
|
export type PerformanceTimeOrigin = number & Brand<"PerformanceTimeOrigin">;
|
|
379
423
|
|
|
380
|
-
/**
|
|
424
|
+
/**
|
|
425
|
+
* High-resolution milliseconds elapsed since {@link PerformanceTimeOrigin}.
|
|
426
|
+
*
|
|
427
|
+
* @group Performance
|
|
428
|
+
*/
|
|
381
429
|
export type PerformanceTime = number & Brand<"PerformanceTime">;
|
|
382
430
|
|
|
383
|
-
/**
|
|
431
|
+
/**
|
|
432
|
+
* Elapsed fractional milliseconds measured using {@link PerformanceTime}.
|
|
433
|
+
*
|
|
434
|
+
* @group Performance
|
|
435
|
+
*/
|
|
384
436
|
export type PerformanceDuration = number & Brand<"PerformanceDuration">;
|
|
385
437
|
|
|
386
438
|
/**
|
|
387
439
|
* Returns the elapsed fractional milliseconds between two performance times.
|
|
388
440
|
*
|
|
389
441
|
* Throws if `end` precedes `start`.
|
|
442
|
+
*
|
|
443
|
+
* @group Performance
|
|
390
444
|
*/
|
|
391
445
|
export const performanceDurationBetween = (
|
|
392
446
|
start: PerformanceTime,
|
|
@@ -412,6 +466,8 @@ export const performanceDurationBetween = (
|
|
|
412
466
|
*
|
|
413
467
|
* assertType<typeof readableSchedule, typeof validatedSchedule>();
|
|
414
468
|
* ```
|
|
469
|
+
*
|
|
470
|
+
* @group Durations
|
|
415
471
|
*/
|
|
416
472
|
export type Duration = DurationLiteral | Millis;
|
|
417
473
|
|
|
@@ -431,12 +487,18 @@ export type Duration = DurationLiteral | Millis;
|
|
|
431
487
|
*
|
|
432
488
|
* assertType<typeof readableSleep, typeof validatedSleep>();
|
|
433
489
|
* ```
|
|
490
|
+
*
|
|
491
|
+
* @group Durations
|
|
434
492
|
*/
|
|
435
493
|
export type PositiveDuration = DurationLiteral | PositiveMillis;
|
|
436
494
|
|
|
437
495
|
// Keep these annotations concrete. Generic unit wrappers add thousands of
|
|
438
496
|
// compiler instantiations to pnpm bench:type.
|
|
439
|
-
/**
|
|
497
|
+
/**
|
|
498
|
+
* Milliseconds duration: `"1ms"` to `"999ms"`. See {@link DurationLiteral}.
|
|
499
|
+
*
|
|
500
|
+
* @group Durations
|
|
501
|
+
*/
|
|
440
502
|
export const DurationLiteralMilliseconds: UnionType<
|
|
441
503
|
readonly [
|
|
442
504
|
TemplateLiteralType<readonly [typeof Digit1To9, "ms"]>,
|
|
@@ -456,6 +518,8 @@ export type DurationLiteralMilliseconds =
|
|
|
456
518
|
/**
|
|
457
519
|
* Seconds duration: `"1s"` to `"59s"` or `"1.1s"` to `"59.9s"`. See
|
|
458
520
|
* {@link DurationLiteral}.
|
|
521
|
+
*
|
|
522
|
+
* @group Durations
|
|
459
523
|
*/
|
|
460
524
|
export const DurationLiteralSeconds: UnionType<
|
|
461
525
|
readonly [
|
|
@@ -473,6 +537,8 @@ export type DurationLiteralSeconds = typeof DurationLiteralSeconds.Output;
|
|
|
473
537
|
/**
|
|
474
538
|
* Minutes duration: `"1m"` to `"59m"` or `"1.1m"` to `"59.9m"`. See
|
|
475
539
|
* {@link DurationLiteral}.
|
|
540
|
+
*
|
|
541
|
+
* @group Durations
|
|
476
542
|
*/
|
|
477
543
|
export const DurationLiteralMinutes: UnionType<
|
|
478
544
|
readonly [
|
|
@@ -490,6 +556,8 @@ export type DurationLiteralMinutes = typeof DurationLiteralMinutes.Output;
|
|
|
490
556
|
/**
|
|
491
557
|
* Hours duration: `"1h"` to `"23h"` or `"1.1h"` to `"23.9h"`. See
|
|
492
558
|
* {@link DurationLiteral}.
|
|
559
|
+
*
|
|
560
|
+
* @group Durations
|
|
493
561
|
*/
|
|
494
562
|
export const DurationLiteralHours: UnionType<
|
|
495
563
|
readonly [
|
|
@@ -507,6 +575,8 @@ export type DurationLiteralHours = typeof DurationLiteralHours.Output;
|
|
|
507
575
|
/**
|
|
508
576
|
* Days duration: `"1d"` to `"6d"` or `"1.1d"` to `"6.9d"`. See
|
|
509
577
|
* {@link DurationLiteral}.
|
|
578
|
+
*
|
|
579
|
+
* @group Durations
|
|
510
580
|
*/
|
|
511
581
|
export const DurationLiteralDays: UnionType<
|
|
512
582
|
readonly [
|
|
@@ -524,6 +594,8 @@ export type DurationLiteralDays = typeof DurationLiteralDays.Output;
|
|
|
524
594
|
/**
|
|
525
595
|
* Weeks duration: `"1w"` to `"51w"` or `"1.1w"` to `"51.9w"`. See
|
|
526
596
|
* {@link DurationLiteral}.
|
|
597
|
+
*
|
|
598
|
+
* @group Durations
|
|
527
599
|
*/
|
|
528
600
|
export const DurationLiteralWeeks: UnionType<
|
|
529
601
|
readonly [
|
|
@@ -541,6 +613,8 @@ export type DurationLiteralWeeks = typeof DurationLiteralWeeks.Output;
|
|
|
541
613
|
/**
|
|
542
614
|
* Years duration: `"1y"` to `"99y"` or `"1.1y"` to `"99.9y"`. See
|
|
543
615
|
* {@link DurationLiteral}.
|
|
616
|
+
*
|
|
617
|
+
* @group Durations
|
|
544
618
|
*/
|
|
545
619
|
export const DurationLiteralYears: UnionType<
|
|
546
620
|
readonly [
|
|
@@ -555,6 +629,12 @@ export const DurationLiteralYears: UnionType<
|
|
|
555
629
|
);
|
|
556
630
|
export type DurationLiteralYears = typeof DurationLiteralYears.Output;
|
|
557
631
|
|
|
632
|
+
/**
|
|
633
|
+
* Duration literal string, from {@link DurationLiteralMilliseconds} to
|
|
634
|
+
* {@link DurationLiteralYears}.
|
|
635
|
+
*
|
|
636
|
+
* @group Durations
|
|
637
|
+
*/
|
|
558
638
|
export type DurationLiteral =
|
|
559
639
|
| DurationLiteralMilliseconds
|
|
560
640
|
| DurationLiteralSeconds
|
|
@@ -622,6 +702,8 @@ const durationLiteralSyntax = /*#__PURE__*/ union(
|
|
|
622
702
|
* assertOk(DurationLiteral.fromUnknown(literal), "1.5s");
|
|
623
703
|
* assertFalse(DurationLiteral.is("1000ms"));
|
|
624
704
|
* ```
|
|
705
|
+
*
|
|
706
|
+
* @group Durations
|
|
625
707
|
*/
|
|
626
708
|
export const DurationLiteral: Type<
|
|
627
709
|
"DurationLiteral",
|
|
@@ -640,7 +722,11 @@ export const DurationLiteral: Type<
|
|
|
640
722
|
`The value ${safelyStringifyUnknownValue(error.value)} is not a duration literal. Use a value such as "500ms" or "1.5s".`,
|
|
641
723
|
);
|
|
642
724
|
|
|
643
|
-
/**
|
|
725
|
+
/**
|
|
726
|
+
* Error returned when {@link DurationLiteral} rejects a value.
|
|
727
|
+
*
|
|
728
|
+
* @group Durations
|
|
729
|
+
*/
|
|
644
730
|
export interface DurationLiteralError extends TypeError<"DurationLiteral"> {
|
|
645
731
|
readonly value: unknown;
|
|
646
732
|
/**
|
|
@@ -668,6 +754,8 @@ export interface DurationLiteralError extends TypeError<"DurationLiteral"> {
|
|
|
668
754
|
* assertEqual(durationToMillis("1w"), 604800000);
|
|
669
755
|
* assertEqual(durationToMillis(Millis.orThrow(5000)), 5000);
|
|
670
756
|
* ```
|
|
757
|
+
*
|
|
758
|
+
* @group Durations
|
|
671
759
|
*/
|
|
672
760
|
export function durationToMillis(
|
|
673
761
|
duration: DurationLiteral | PositiveMillis,
|
|
@@ -704,6 +792,8 @@ const durationUnits = {
|
|
|
704
792
|
* Frame budget at 60fps (16ms).
|
|
705
793
|
*
|
|
706
794
|
* Work exceeding this blocks a frame, causing visible jank in animations.
|
|
795
|
+
*
|
|
796
|
+
* @group Millis
|
|
707
797
|
*/
|
|
708
798
|
export const ms60fps = 16 as Millis;
|
|
709
799
|
|
|
@@ -711,6 +801,8 @@ export const ms60fps = 16 as Millis;
|
|
|
711
801
|
* Frame budget at 120fps (8ms).
|
|
712
802
|
*
|
|
713
803
|
* For high refresh rate displays. Work exceeding this blocks a frame.
|
|
804
|
+
*
|
|
805
|
+
* @group Millis
|
|
714
806
|
*/
|
|
715
807
|
export const ms120fps = 8 as Millis;
|
|
716
808
|
|
|
@@ -720,6 +812,7 @@ export const ms120fps = 8 as Millis;
|
|
|
720
812
|
* Tasks exceeding this are "long tasks" per web standards. Use with
|
|
721
813
|
* {@link yieldNow} to yield periodically and keep UI responsive.
|
|
722
814
|
*
|
|
815
|
+
* @group Millis
|
|
723
816
|
* @see https://web.dev/articles/optimize-long-tasks
|
|
724
817
|
*/
|
|
725
818
|
export const msLongTask = 50 as Millis;
|
|
@@ -752,6 +845,8 @@ export const msLongTask = 50 as Millis;
|
|
|
752
845
|
* "1d1h1m1.000s",
|
|
753
846
|
* );
|
|
754
847
|
* ```
|
|
848
|
+
*
|
|
849
|
+
* @group Millis
|
|
755
850
|
*/
|
|
756
851
|
export const formatMillisAsDuration = (millis: Millis): string => {
|
|
757
852
|
const seconds = ((millis % durationUnits.m) / durationUnits.s).toFixed(3);
|
|
@@ -796,6 +891,8 @@ export const formatMillisAsDuration = (millis: Millis): string => {
|
|
|
796
891
|
* "14:32:15.234",
|
|
797
892
|
* );
|
|
798
893
|
* ```
|
|
894
|
+
*
|
|
895
|
+
* @group Millis
|
|
799
896
|
*/
|
|
800
897
|
export const formatMillisAsClockTime = (millis: Millis): string => {
|
|
801
898
|
const date = new Date(millis);
|