@evolu/common 8.0.0-next.3 → 8.0.0-next.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 (73) hide show
  1. package/dist/src/Assert.d.ts +5 -5
  2. package/dist/src/Assert.d.ts.map +1 -1
  3. package/dist/src/Assert.js +4 -4
  4. package/dist/src/Identicon.js +4 -4
  5. package/dist/src/LockManager.d.ts +74 -0
  6. package/dist/src/LockManager.d.ts.map +1 -0
  7. package/dist/src/LockManager.js +103 -0
  8. package/dist/src/Microtask.d.ts.map +1 -1
  9. package/dist/src/Microtask.js +90 -26
  10. package/dist/src/Object.d.ts.map +1 -1
  11. package/dist/src/RefCount.d.ts.map +1 -1
  12. package/dist/src/RefCount.js +153 -68
  13. package/dist/src/Resource.d.ts +6 -6
  14. package/dist/src/Resource.d.ts.map +1 -1
  15. package/dist/src/Resource.js +211 -162
  16. package/dist/src/Schedule.d.ts +5 -5
  17. package/dist/src/Schedule.d.ts.map +1 -1
  18. package/dist/src/Schedule.js +53 -44
  19. package/dist/src/Sqlite.d.ts +2 -0
  20. package/dist/src/Sqlite.d.ts.map +1 -1
  21. package/dist/src/Sqlite.js +64 -40
  22. package/dist/src/Task.d.ts +6 -33
  23. package/dist/src/Task.d.ts.map +1 -1
  24. package/dist/src/Task.js +213 -204
  25. package/dist/src/Test.d.ts +4 -4
  26. package/dist/src/Time.d.ts +5 -0
  27. package/dist/src/Time.d.ts.map +1 -1
  28. package/dist/src/Time.js +5 -0
  29. package/dist/src/Type.d.ts +7 -0
  30. package/dist/src/Type.d.ts.map +1 -1
  31. package/dist/src/Type.js +7 -0
  32. package/dist/src/WebSocket.d.ts.map +1 -1
  33. package/dist/src/WebSocket.js +7 -6
  34. package/dist/src/Worker.d.ts +42 -8
  35. package/dist/src/Worker.d.ts.map +1 -1
  36. package/dist/src/Worker.js +292 -112
  37. package/dist/src/index.d.ts +1 -0
  38. package/dist/src/index.d.ts.map +1 -1
  39. package/dist/src/index.js +1 -0
  40. package/dist/src/local-first/Db.d.ts +5 -4
  41. package/dist/src/local-first/Db.d.ts.map +1 -1
  42. package/dist/src/local-first/Db.js +44 -38
  43. package/dist/src/local-first/Evolu.d.ts +3 -2
  44. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  45. package/dist/src/local-first/Evolu.js +90 -80
  46. package/dist/src/local-first/Owner.d.ts.map +1 -1
  47. package/dist/src/local-first/Shared.d.ts +65 -54
  48. package/dist/src/local-first/Shared.d.ts.map +1 -1
  49. package/dist/src/local-first/Shared.js +387 -373
  50. package/package.json +1 -1
  51. package/src/Array.ts +8 -8
  52. package/src/Assert.ts +5 -5
  53. package/src/Identicon.ts +4 -4
  54. package/src/LockManager.ts +181 -0
  55. package/src/Microtask.ts +17 -11
  56. package/src/Object.ts +3 -3
  57. package/src/RefCount.ts +25 -21
  58. package/src/Resource.ts +63 -56
  59. package/src/Schedule.ts +70 -48
  60. package/src/Set.ts +4 -4
  61. package/src/Sqlite.ts +41 -30
  62. package/src/Task.ts +77 -120
  63. package/src/Test.ts +4 -4
  64. package/src/Time.ts +7 -0
  65. package/src/Type.ts +9 -0
  66. package/src/WebSocket.ts +7 -6
  67. package/src/Worker.ts +195 -53
  68. package/src/index.ts +1 -0
  69. package/src/local-first/Db.ts +69 -46
  70. package/src/local-first/Evolu.ts +74 -68
  71. package/src/local-first/Owner.ts +1 -1
  72. package/src/local-first/Query.ts +1 -1
  73. package/src/local-first/Shared.ts +472 -464
package/dist/src/Task.js CHANGED
@@ -56,7 +56,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
56
56
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
57
57
  });
58
58
  import { arrayFrom, emptyArray, isNonEmptyArray, mapArray, } from "./Array.js";
59
- import { assert } from "./Assert.js";
59
+ import { assert, assertNotDisposed } from "./Assert.js";
60
60
  import { createConsole } from "./Console.js";
61
61
  import { createRandomBytes } from "./Crypto.js";
62
62
  import { eqArrayStrict } from "./Eq.js";
@@ -998,37 +998,51 @@ export const deferredDisposedError = {
998
998
  * @group Concurrency primitives
999
999
  */
1000
1000
  export const createGate = () => {
1001
- let isOpen = false;
1002
- let disposed = false;
1003
- let deferred = createDeferred();
1004
- return {
1005
- wait: (run) => {
1006
- if (disposed)
1007
- return err(deferredDisposedError);
1008
- if (isOpen)
1009
- return ok();
1010
- return run(deferred.task);
1011
- },
1012
- open: () => {
1013
- if (disposed || isOpen)
1014
- return;
1015
- isOpen = true;
1016
- deferred.resolve(ok());
1017
- },
1018
- close: () => {
1019
- if (disposed || !isOpen)
1020
- return;
1021
- isOpen = false;
1022
- deferred = createDeferred();
1023
- },
1024
- isOpen: () => isOpen,
1025
- [Symbol.dispose]: () => {
1026
- if (disposed)
1027
- return;
1028
- disposed = true;
1001
+ const env_1 = { stack: [], error: void 0, hasError: false };
1002
+ try {
1003
+ const disposer = __addDisposableResource(env_1, new DisposableStack(), false);
1004
+ let isOpen = false;
1005
+ let deferred = createDeferred();
1006
+ disposer.defer(() => {
1029
1007
  deferred[Symbol.dispose]();
1030
- },
1031
- };
1008
+ });
1009
+ const disposables = disposer.move();
1010
+ return {
1011
+ wait: (run) => {
1012
+ if (disposables.disposed)
1013
+ return err(deferredDisposedError);
1014
+ if (isOpen)
1015
+ return ok();
1016
+ return run(deferred.task);
1017
+ },
1018
+ open: () => {
1019
+ assertNotDisposed(disposables);
1020
+ if (isOpen)
1021
+ return;
1022
+ isOpen = true;
1023
+ deferred.resolve(ok());
1024
+ },
1025
+ close: () => {
1026
+ assertNotDisposed(disposables);
1027
+ if (!isOpen)
1028
+ return;
1029
+ isOpen = false;
1030
+ deferred = createDeferred();
1031
+ },
1032
+ isOpen: () => {
1033
+ assertNotDisposed(disposables);
1034
+ return isOpen;
1035
+ },
1036
+ [Symbol.dispose]: () => disposables.dispose(),
1037
+ };
1038
+ }
1039
+ catch (e_1) {
1040
+ env_1.error = e_1;
1041
+ env_1.hasError = true;
1042
+ }
1043
+ finally {
1044
+ __disposeResources(env_1);
1045
+ }
1032
1046
  };
1033
1047
  /**
1034
1048
  * Creates a {@link Semaphore} that limits concurrent {@link Task}s.
@@ -1071,85 +1085,18 @@ export const createGate = () => {
1071
1085
  * @group Concurrency primitives
1072
1086
  */
1073
1087
  export const createSemaphore = (permits) => {
1074
- const fibers = new Set();
1075
- const waiters = [];
1076
- let taken = zeroNonNegativeInt;
1077
- let disposed = false;
1078
- const withPermits = (requestedPermits) => (task) => async (run) => {
1079
- const env_1 = { stack: [], error: void 0, hasError: false };
1080
- try {
1081
- const requested = PositiveInt.orThrow(requestedPermits);
1082
- assert(requested <= permits, "Requested permits must not exceed semaphore capacity.");
1083
- if (disposed)
1084
- return err(semaphoreDisposedAbortError);
1085
- if (waiters.length > 0 || taken + requested > permits) {
1086
- const waiter = Promise.withResolvers();
1087
- const waiting = {
1088
- permits: requested,
1089
- resolve: waiter.resolve,
1090
- };
1091
- waiters.push(waiting);
1092
- run.onAbort((reason) => {
1093
- const i = waiters.indexOf(waiting);
1094
- if (i >= 0)
1095
- waiters.splice(i, 1);
1096
- waiter.resolve(err(createAbortError(reason)));
1097
- });
1098
- const permit = await waiter.promise;
1099
- if (!permit.ok)
1100
- return permit;
1101
- }
1102
- else {
1103
- taken = NonNegativeInt.orThrow(taken + requested);
1104
- }
1105
- let fiber = null;
1106
- const _ = __addDisposableResource(env_1, {
1107
- [Symbol.dispose]: () => {
1108
- if (fiber)
1109
- fibers.delete(fiber);
1110
- taken = NonNegativeInt.orThrow(taken - requested);
1111
- while (waiters.length > 0) {
1112
- const waiter = waiters[0];
1113
- if (taken + waiter.permits > permits)
1114
- break;
1115
- waiters.shift();
1116
- taken = NonNegativeInt.orThrow(taken + waiter.permits);
1117
- waiter.resolve(ok());
1118
- }
1119
- },
1120
- }, false);
1121
- fiber = run(task);
1122
- fibers.add(fiber);
1123
- return await fiber;
1124
- }
1125
- catch (e_1) {
1126
- env_1.error = e_1;
1127
- env_1.hasError = true;
1128
- }
1129
- finally {
1130
- __disposeResources(env_1);
1131
- }
1132
- };
1133
- return {
1134
- withPermits,
1135
- withPermit: (task) => withPermits(1)(task),
1136
- snapshot: () => ({
1137
- permits,
1138
- taken,
1139
- waiting: NonNegativeInt.orThrow(waiters.length),
1140
- available: NonNegativeInt.orThrow(permits - taken),
1141
- isIdle: taken === 0 && waiters.length === 0,
1142
- disposed,
1143
- }),
1144
- [Symbol.dispose]: () => {
1145
- const env_2 = { stack: [], error: void 0, hasError: false };
1088
+ const env_2 = { stack: [], error: void 0, hasError: false };
1089
+ try {
1090
+ const disposer = __addDisposableResource(env_2, new DisposableStack(), false);
1091
+ const fibers = new Set();
1092
+ const waiters = [];
1093
+ let taken = zeroNonNegativeInt;
1094
+ disposer.defer(() => {
1095
+ const env_3 = { stack: [], error: void 0, hasError: false };
1146
1096
  try {
1147
- if (disposed)
1148
- return;
1149
- disposed = true;
1150
- const stack = __addDisposableResource(env_2, new DisposableStack(), false);
1097
+ const disposer = __addDisposableResource(env_3, new DisposableStack(), false);
1151
1098
  for (const fiber of fibers) {
1152
- stack.adopt(fiber, (fiber) => {
1099
+ disposer.adopt(fiber, (fiber) => {
1153
1100
  fiber.abort(semaphoreDisposedError);
1154
1101
  });
1155
1102
  }
@@ -1158,15 +1105,94 @@ export const createSemaphore = (permits) => {
1158
1105
  }
1159
1106
  waiters.length = 0;
1160
1107
  }
1161
- catch (e_2) {
1162
- env_2.error = e_2;
1163
- env_2.hasError = true;
1108
+ catch (e_3) {
1109
+ env_3.error = e_3;
1110
+ env_3.hasError = true;
1164
1111
  }
1165
1112
  finally {
1166
- __disposeResources(env_2);
1113
+ __disposeResources(env_3);
1167
1114
  }
1168
- },
1169
- };
1115
+ });
1116
+ const disposables = disposer.move();
1117
+ const withPermits = (requestedPermits) => (task) => async (run) => {
1118
+ const env_4 = { stack: [], error: void 0, hasError: false };
1119
+ try {
1120
+ const requested = PositiveInt.orThrow(requestedPermits);
1121
+ assert(requested <= permits, "Requested permits must not exceed semaphore capacity.");
1122
+ if (disposables.disposed)
1123
+ return err(semaphoreDisposedAbortError);
1124
+ if (waiters.length > 0 || taken + requested > permits) {
1125
+ const waiter = Promise.withResolvers();
1126
+ const waiting = {
1127
+ permits: requested,
1128
+ resolve: waiter.resolve,
1129
+ };
1130
+ waiters.push(waiting);
1131
+ run.onAbort((reason) => {
1132
+ const i = waiters.indexOf(waiting);
1133
+ if (i >= 0)
1134
+ waiters.splice(i, 1);
1135
+ waiter.resolve(err(createAbortError(reason)));
1136
+ });
1137
+ const permit = await waiter.promise;
1138
+ if (!permit.ok)
1139
+ return permit;
1140
+ }
1141
+ else {
1142
+ taken = NonNegativeInt.orThrow(taken + requested);
1143
+ }
1144
+ let fiber = null;
1145
+ const _ = __addDisposableResource(env_4, {
1146
+ [Symbol.dispose]: () => {
1147
+ if (fiber)
1148
+ fibers.delete(fiber);
1149
+ taken = NonNegativeInt.orThrow(taken - requested);
1150
+ while (waiters.length > 0) {
1151
+ const waiter = waiters[0];
1152
+ if (taken + waiter.permits > permits)
1153
+ break;
1154
+ waiters.shift();
1155
+ taken = NonNegativeInt.orThrow(taken + waiter.permits);
1156
+ waiter.resolve(ok());
1157
+ }
1158
+ },
1159
+ }, false);
1160
+ fiber = run(task);
1161
+ fibers.add(fiber);
1162
+ return await fiber;
1163
+ }
1164
+ catch (e_4) {
1165
+ env_4.error = e_4;
1166
+ env_4.hasError = true;
1167
+ }
1168
+ finally {
1169
+ __disposeResources(env_4);
1170
+ }
1171
+ };
1172
+ return {
1173
+ withPermits,
1174
+ withPermit: (task) => withPermits(1)(task),
1175
+ snapshot: () => {
1176
+ assertNotDisposed(disposables);
1177
+ return {
1178
+ permits,
1179
+ taken,
1180
+ waiting: NonNegativeInt.orThrow(waiters.length),
1181
+ available: NonNegativeInt.orThrow(permits - taken),
1182
+ isIdle: taken === 0 && waiters.length === 0,
1183
+ disposed: disposables.disposed,
1184
+ };
1185
+ },
1186
+ [Symbol.dispose]: () => disposables.dispose(),
1187
+ };
1188
+ }
1189
+ catch (e_2) {
1190
+ env_2.error = e_2;
1191
+ env_2.hasError = true;
1192
+ }
1193
+ finally {
1194
+ __disposeResources(env_2);
1195
+ }
1170
1196
  };
1171
1197
  /**
1172
1198
  * Abort reason used when a {@link Semaphore} is disposed.
@@ -1184,64 +1210,80 @@ export const semaphoreDisposedError = {
1184
1210
  };
1185
1211
  const semaphoreDisposedAbortError = createAbortError(semaphoreDisposedError);
1186
1212
  export function createSemaphoreByKey(permits, { lookup = identity } = {}) {
1187
- const semaphoresByKey = createLookupMap({
1188
- lookup,
1189
- });
1190
- let disposed = false;
1191
- const withPermits = (key, requestedPermits) => (task) => async (run) => {
1192
- const env_3 = { stack: [], error: void 0, hasError: false };
1193
- try {
1194
- if (disposed)
1195
- return err(semaphoreDisposedAbortError);
1196
- let semaphore = semaphoresByKey.get(key);
1197
- if (!semaphore) {
1198
- semaphore = createSemaphore(permits);
1199
- semaphoresByKey.set(key, semaphore);
1200
- }
1201
- const _ = __addDisposableResource(env_3, {
1202
- [Symbol.dispose]: () => {
1203
- const snapshot = semaphore.snapshot();
1204
- if (snapshot.isIdle) {
1205
- semaphoresByKey.delete(key);
1206
- semaphore[Symbol.dispose]();
1207
- }
1208
- },
1209
- }, false);
1210
- return await run(semaphore.withPermits(requestedPermits)(task));
1211
- }
1212
- catch (e_3) {
1213
- env_3.error = e_3;
1214
- env_3.hasError = true;
1215
- }
1216
- finally {
1217
- __disposeResources(env_3);
1218
- }
1219
- };
1220
- return {
1221
- withPermit: (key, task) => withPermits(key, 1)(task),
1222
- withPermits,
1223
- snapshot: (key) => semaphoresByKey.get(key)?.snapshot() ?? null,
1224
- [Symbol.dispose]: () => {
1225
- const env_4 = { stack: [], error: void 0, hasError: false };
1213
+ const env_5 = { stack: [], error: void 0, hasError: false };
1214
+ try {
1215
+ const disposer = __addDisposableResource(env_5, new DisposableStack(), false);
1216
+ const semaphoresByKey = createLookupMap({
1217
+ lookup,
1218
+ });
1219
+ disposer.defer(() => {
1220
+ const env_6 = { stack: [], error: void 0, hasError: false };
1226
1221
  try {
1227
- if (disposed)
1228
- return;
1229
- disposed = true;
1230
- const stack = __addDisposableResource(env_4, new DisposableStack(), false);
1222
+ const disposer = __addDisposableResource(env_6, new DisposableStack(), false);
1223
+ disposer.defer(() => {
1224
+ semaphoresByKey.clear();
1225
+ });
1231
1226
  for (const semaphore of semaphoresByKey.values()) {
1232
- stack.use(semaphore);
1227
+ disposer.use(semaphore);
1233
1228
  }
1234
- semaphoresByKey.clear();
1235
1229
  }
1236
- catch (e_4) {
1237
- env_4.error = e_4;
1238
- env_4.hasError = true;
1230
+ catch (e_6) {
1231
+ env_6.error = e_6;
1232
+ env_6.hasError = true;
1239
1233
  }
1240
1234
  finally {
1241
- __disposeResources(env_4);
1235
+ __disposeResources(env_6);
1242
1236
  }
1243
- },
1244
- };
1237
+ });
1238
+ const disposables = disposer.move();
1239
+ const withPermits = (key, requestedPermits) => (task) => async (run) => {
1240
+ const env_7 = { stack: [], error: void 0, hasError: false };
1241
+ try {
1242
+ if (disposables.disposed)
1243
+ return err(semaphoreDisposedAbortError);
1244
+ let semaphore = semaphoresByKey.get(key);
1245
+ if (!semaphore) {
1246
+ semaphore = createSemaphore(permits);
1247
+ semaphoresByKey.set(key, semaphore);
1248
+ }
1249
+ const _ = __addDisposableResource(env_7, {
1250
+ [Symbol.dispose]: () => {
1251
+ if (semaphoresByKey.get(key) !== semaphore)
1252
+ return;
1253
+ const snapshot = semaphore.snapshot();
1254
+ if (snapshot.isIdle) {
1255
+ semaphoresByKey.delete(key);
1256
+ semaphore[Symbol.dispose]();
1257
+ }
1258
+ },
1259
+ }, false);
1260
+ return await run(semaphore.withPermits(requestedPermits)(task));
1261
+ }
1262
+ catch (e_7) {
1263
+ env_7.error = e_7;
1264
+ env_7.hasError = true;
1265
+ }
1266
+ finally {
1267
+ __disposeResources(env_7);
1268
+ }
1269
+ };
1270
+ return {
1271
+ withPermit: (key, task) => withPermits(key, 1)(task),
1272
+ withPermits,
1273
+ snapshot: (key) => {
1274
+ assertNotDisposed(disposables);
1275
+ return semaphoresByKey.get(key)?.snapshot() ?? null;
1276
+ },
1277
+ [Symbol.dispose]: () => disposables.dispose(),
1278
+ };
1279
+ }
1280
+ catch (e_5) {
1281
+ env_5.error = e_5;
1282
+ env_5.hasError = true;
1283
+ }
1284
+ finally {
1285
+ __disposeResources(env_5);
1286
+ }
1245
1287
  }
1246
1288
  /**
1247
1289
  * Creates a {@link Mutex}.
@@ -1316,39 +1358,6 @@ export const createMutexRef = (initialValue) => {
1316
1358
  [Symbol.dispose]: mutex[Symbol.dispose],
1317
1359
  };
1318
1360
  };
1319
- /**
1320
- * Creates an in-process {@link LeaderLock}.
1321
- *
1322
- * Uses one {@link Mutex} per {@link Name}. Suitable for runtimes without a
1323
- * cross-process lock manager (for example in-memory worker tests or React
1324
- * Native).
1325
- *
1326
- * @group Concurrency primitives
1327
- */
1328
- export const createInMemoryLeaderLock = () => {
1329
- const mutexByName = createMutexByKey();
1330
- return {
1331
- lock: (name) => async (run) => {
1332
- const leaseRun = run.create();
1333
- const released = createDeferred();
1334
- const acquired = createDeferred();
1335
- void leaseRun(mutexByName.withLock(name, async (run) => {
1336
- acquired.resolve(ok());
1337
- await run(released.task);
1338
- return ok();
1339
- }));
1340
- const acquiredResult = await run(acquired.task);
1341
- if (!acquiredResult.ok) {
1342
- assert(AbortError.is(acquiredResult.error), "Leader lock acquisition deferred must not be disposed.");
1343
- void leaseRun[Symbol.asyncDispose]();
1344
- return err(acquiredResult.error);
1345
- }
1346
- return ok({
1347
- [Symbol.asyncDispose]: leaseRun[Symbol.asyncDispose],
1348
- });
1349
- },
1350
- };
1351
- };
1352
1361
  export function all(input, options) {
1353
1362
  return collect("all", input, options);
1354
1363
  }
@@ -1470,7 +1479,7 @@ function pool(tasksIterable, { stopOn = null, collect, abortReason, allFailed, }
1470
1479
  if (length === 0)
1471
1480
  return () => ok(emptyArray);
1472
1481
  return async (run) => {
1473
- const env_5 = { stack: [], error: void 0, hasError: false };
1482
+ const env_8 = { stack: [], error: void 0, hasError: false };
1474
1483
  try {
1475
1484
  const results = collect ? new Array(length) : null;
1476
1485
  const aborted = Promise.withResolvers();
@@ -1520,7 +1529,7 @@ function pool(tasksIterable, { stopOn = null, collect, abortReason, allFailed, }
1520
1529
  };
1521
1530
  const workerCount = Math.min(run.concurrency, length);
1522
1531
  const workers = arrayFrom(workerCount, () => run.daemon(worker));
1523
- const _ = __addDisposableResource(env_5, new DisposableStack(), false);
1532
+ const _ = __addDisposableResource(env_8, new DisposableStack(), false);
1524
1533
  _.defer(() => {
1525
1534
  abortWorkers(abortReason);
1526
1535
  });
@@ -1546,12 +1555,12 @@ function pool(tasksIterable, { stopOn = null, collect, abortReason, allFailed, }
1546
1555
  return ok();
1547
1556
  return allFailed === "completion" ? lastResult : lastIndexResult;
1548
1557
  }
1549
- catch (e_5) {
1550
- env_5.error = e_5;
1551
- env_5.hasError = true;
1558
+ catch (e_8) {
1559
+ env_8.error = e_8;
1560
+ env_8.hasError = true;
1552
1561
  }
1553
1562
  finally {
1554
- __disposeResources(env_5);
1563
+ __disposeResources(env_8);
1555
1564
  }
1556
1565
  };
1557
1566
  }
@@ -84,10 +84,10 @@ export declare const testCreateDeps: (options?: {
84
84
  * // If multiple tests need the same setup, create a disposable helper.
85
85
  * // Then `await using setup` disposes everything the helper owns.
86
86
  * const setupFoo = async () => {
87
- * await using stack = new AsyncDisposableStack();
88
- * const run = stack.use(testCreateRun());
89
- * const foo = stack.use(await run.orThrow(createFoo()));
90
- * const moved = stack.move();
87
+ * await using disposer = new AsyncDisposableStack();
88
+ * const run = disposer.use(testCreateRun());
89
+ * const foo = disposer.use(await run.orThrow(createFoo()));
90
+ * const disposables = disposer.move();
91
91
  *
92
92
  * // Return whatever the tests need: a Run with the dependency,
93
93
  * // the dependency itself, or both.
@@ -79,6 +79,11 @@ export type Millis = typeof Millis.Type;
79
79
  export declare const minMillis: Millis;
80
80
  /** Maximum {@link Millis} value. */
81
81
  export declare const maxMillis: Millis;
82
+ /**
83
+ * Converts a number to {@link Millis}, rounding to the nearest millisecond and
84
+ * saturating overflow at {@link maxMillis}.
85
+ */
86
+ export declare const saturateMillis: (value: number) => Millis;
82
87
  /**
83
88
  * Converts {@link Millis} to {@link DateIso}.
84
89
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Time.d.ts","sourceRoot":"","sources":["../../src/Time.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Time.d.ts","sourceRoot":"","sources":["../../src/Time.ts"],"names":[],"mappings":"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"}
package/dist/src/Time.js CHANGED
@@ -96,6 +96,11 @@ export const Millis = /*#__PURE__*/ brand("Millis",
96
96
  export const minMillis = 0;
97
97
  /** Maximum {@link Millis} value. */
98
98
  export const maxMillis = (maxMillisWithInfinity - 1);
99
+ /**
100
+ * Converts a number to {@link Millis}, rounding to the nearest millisecond and
101
+ * saturating overflow at {@link maxMillis}.
102
+ */
103
+ export const saturateMillis = (value) => Millis.orNull(Math.max(0, Math.round(value))) ?? maxMillis;
99
104
  /**
100
105
  * Converts {@link Millis} to {@link DateIso}.
101
106
  *
@@ -1509,6 +1509,13 @@ export declare const formatFiniteError: TypeErrorFormatter<FiniteError>;
1509
1509
  */
1510
1510
  export declare const FiniteNumber: BrandType<Type<"Number", number, number, NumberError, number, NumberError>, "Finite", FiniteError, NumberError>;
1511
1511
  export type FiniteNumber = typeof FiniteNumber.Type;
1512
+ /**
1513
+ * Non-negative finite number.
1514
+ *
1515
+ * @group Number
1516
+ */
1517
+ export declare const NonNegativeFiniteNumber: BrandType<Type<"Brand", number & Brand<"Finite">, number, FiniteError, number, NumberError>, "NonNegative", NonNegativeError, FiniteError | NumberError>;
1518
+ export type NonNegativeFiniteNumber = typeof NonNegativeFiniteNumber.Type;
1512
1519
  /**
1513
1520
  * Number that is a multiple of a divisor.
1514
1521
  *