@evolu/common 6.0.1-preview.20 → 6.0.1-preview.21
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/Evolu/Db.d.ts +23 -1
- package/dist/src/Evolu/Db.d.ts.map +1 -1
- package/dist/src/Evolu/Owner.d.ts +60 -0
- package/dist/src/Evolu/Owner.d.ts.map +1 -1
- package/dist/src/Evolu/Owner.js +33 -0
- package/dist/src/Evolu/Protocol.d.ts +91 -30
- package/dist/src/Evolu/Protocol.d.ts.map +1 -1
- package/dist/src/Evolu/Protocol.js +80 -25
- package/dist/src/Evolu/Relay.d.ts +70 -3
- package/dist/src/Evolu/Relay.d.ts.map +1 -1
- package/dist/src/Evolu/Relay.js +74 -1
- package/dist/src/Evolu/Sync.d.ts +2 -11
- package/dist/src/Evolu/Sync.d.ts.map +1 -1
- package/dist/src/Evolu/Sync.js +7 -46
- package/dist/src/Result.d.ts +45 -16
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +23 -0
- package/dist/src/Task.js +1 -1
- package/dist/src/Type.d.ts +12 -0
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +12 -0
- package/package.json +1 -1
- package/src/Evolu/Db.ts +24 -1
- package/src/Evolu/Owner.ts +70 -1
- package/src/Evolu/Protocol.ts +117 -36
- package/src/Evolu/Relay.ts +180 -6
- package/src/Evolu/Sync.ts +7 -57
- package/src/Result.ts +47 -16
- package/src/Task.ts +3 -3
- package/src/Type.ts +12 -0
package/src/Result.ts
CHANGED
|
@@ -228,23 +228,26 @@
|
|
|
228
228
|
*
|
|
229
229
|
* ### FAQ
|
|
230
230
|
*
|
|
231
|
-
* ####
|
|
231
|
+
* #### When should a function return a plain value instead of `Result<T, E>`?
|
|
232
232
|
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
233
|
+
* Use `Result<T, E>` only when a function can fail with **known, expected
|
|
234
|
+
* errors** that callers need to handle. If a function cannot fail with a known
|
|
235
|
+
* error, return the value directly.
|
|
236
|
+
*
|
|
237
|
+
* - ✅ Return `Result<User, UserNotFoundError>` - can fail with a known error
|
|
238
|
+
* - ✅ Return `User` - cannot fail with a known error
|
|
239
|
+
* - ❌ Don't return `Result<User, never>` - unnecessary wrapper
|
|
237
240
|
*
|
|
238
|
-
*
|
|
241
|
+
* This keeps the codebase clean and makes error handling intentional. The type
|
|
242
|
+
* system communicates which operations can fail and which cannot.
|
|
239
243
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
* without error handling.
|
|
244
|
+
* Unsafe code from external libraries (not under our control) should be wrapped
|
|
245
|
+
* with `trySync` or `tryAsync` at the boundaries. Once wrapped, if the error is
|
|
246
|
+
* not important to callers, functions can safely return plain values. If the
|
|
247
|
+
* error matters, use `Result` with a typed error.
|
|
245
248
|
*
|
|
246
249
|
* ```ts
|
|
247
|
-
* // ✅ Safe to return void -
|
|
250
|
+
* // ✅ Safe to return void - unsafe code is wrapped and error is handled
|
|
248
251
|
* const processData = (data: string): void => {
|
|
249
252
|
* const parseResult = trySync(
|
|
250
253
|
* () => JSON.parse(data),
|
|
@@ -252,7 +255,7 @@
|
|
|
252
255
|
* );
|
|
253
256
|
*
|
|
254
257
|
* if (!parseResult.ok) {
|
|
255
|
-
* logError(parseResult.error);
|
|
258
|
+
* logError(parseResult.error);
|
|
256
259
|
* return;
|
|
257
260
|
* }
|
|
258
261
|
*
|
|
@@ -263,9 +266,12 @@
|
|
|
263
266
|
* processData(jsonString);
|
|
264
267
|
* ```
|
|
265
268
|
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
+
* #### What if my function doesn't return a value on success?
|
|
270
|
+
*
|
|
271
|
+
* If your function performs an operation but doesn't need to return a value on
|
|
272
|
+
* success, you can use `Result<void, E>`. Using `Result<void, E>` is clearer
|
|
273
|
+
* than using `Result<true, E>` or `Result<null, E>` because it communicates
|
|
274
|
+
* that the function doesn't produce a value but can produce errors.
|
|
269
275
|
*
|
|
270
276
|
* #### How do I short-circuit processing of an array on the first error?
|
|
271
277
|
*
|
|
@@ -460,6 +466,31 @@ export const getOrThrow = <T, E>(result: Result<T, E>): T => {
|
|
|
460
466
|
}
|
|
461
467
|
};
|
|
462
468
|
|
|
469
|
+
/**
|
|
470
|
+
* Extracts the value from a {@link Result} if it is an `Ok`, or returns `null`
|
|
471
|
+
* if it is an `Err`.
|
|
472
|
+
*
|
|
473
|
+
* **Intended usage:**
|
|
474
|
+
*
|
|
475
|
+
* - When you need to convert a `Result` to a nullable value for APIs that expect
|
|
476
|
+
* `T | null`.
|
|
477
|
+
* - When the error is not important and you just want the value or nothing.
|
|
478
|
+
*
|
|
479
|
+
* ### Example
|
|
480
|
+
*
|
|
481
|
+
* ```ts
|
|
482
|
+
* const parseResult = parseJson('{"key": "value"}');
|
|
483
|
+
* const value = getOrNull(parseResult);
|
|
484
|
+
* // value is unknown | null
|
|
485
|
+
*
|
|
486
|
+
* if (value != null) {
|
|
487
|
+
* console.log("Parsed value:", value);
|
|
488
|
+
* }
|
|
489
|
+
* ```
|
|
490
|
+
*/
|
|
491
|
+
export const getOrNull = <T, E>(result: Result<T, E>): T | null =>
|
|
492
|
+
result.ok ? result.value : null;
|
|
493
|
+
|
|
463
494
|
/**
|
|
464
495
|
* Wraps synchronous functions that may throw exceptions, returning a
|
|
465
496
|
* {@link Result}.
|
package/src/Task.ts
CHANGED
|
@@ -484,10 +484,10 @@ export interface RetryError<E> {
|
|
|
484
484
|
export const retry = <T, E>(
|
|
485
485
|
{
|
|
486
486
|
retries,
|
|
487
|
-
initialDelay = "
|
|
488
|
-
maxDelay = "
|
|
487
|
+
initialDelay = "1s",
|
|
488
|
+
maxDelay = "30s",
|
|
489
489
|
factor = 2,
|
|
490
|
-
jitter = 0.
|
|
490
|
+
jitter = 0.5,
|
|
491
491
|
retryable = (error: E | AbortError) => !isAbortError(error),
|
|
492
492
|
onRetry,
|
|
493
493
|
}: RetryOptions<E>,
|
package/src/Type.ts
CHANGED
|
@@ -1503,6 +1503,18 @@ export const formatSimplePasswordError = (
|
|
|
1503
1503
|
* characters), standard and native string serialization (Base64Url), and no
|
|
1504
1504
|
* privacy leaks.
|
|
1505
1505
|
*
|
|
1506
|
+
* ### Future Consideration
|
|
1507
|
+
*
|
|
1508
|
+
* For database-heavy workloads where insert performance is critical, a hybrid
|
|
1509
|
+
* approach could be considered: `timestamp ^ H(cluster_id, timestamp >> N)`
|
|
1510
|
+
* where H is a keyed hash function and N is a configurable parameter. This
|
|
1511
|
+
* would maintain spatial locality for database caches (improving insert
|
|
1512
|
+
* performance by an order of magnitude) while adding entropy to prevent
|
|
1513
|
+
* timestamp leakage and correlation across systems. The parameter N would allow
|
|
1514
|
+
* trading off cache locality (larger N = better locality) versus entropy
|
|
1515
|
+
* distribution. See https://brooker.co.za/blog/2025/10/22/uuidv7.html for
|
|
1516
|
+
* details on this approach.
|
|
1517
|
+
*
|
|
1506
1518
|
* @category String
|
|
1507
1519
|
*/
|
|
1508
1520
|
export const Id = brand("Id", String, (value) =>
|