@evolu/common 6.0.1-preview.24 → 6.0.1-preview.26

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 (66) hide show
  1. package/dist/src/Assert.d.ts +0 -13
  2. package/dist/src/Assert.d.ts.map +1 -1
  3. package/dist/src/Assert.js +0 -15
  4. package/dist/src/Cache.d.ts +44 -0
  5. package/dist/src/Cache.d.ts.map +1 -0
  6. package/dist/src/Cache.js +52 -0
  7. package/dist/src/Evolu/Db.d.ts +6 -6
  8. package/dist/src/Evolu/Db.d.ts.map +1 -1
  9. package/dist/src/Evolu/Db.js +4 -0
  10. package/dist/src/Evolu/LocalAuth.d.ts +2 -2
  11. package/dist/src/Evolu/LocalAuth.d.ts.map +1 -1
  12. package/dist/src/Evolu/Owner.d.ts +116 -86
  13. package/dist/src/Evolu/Owner.d.ts.map +1 -1
  14. package/dist/src/Evolu/Owner.js +48 -45
  15. package/dist/src/Evolu/Relay.d.ts +6 -5
  16. package/dist/src/Evolu/Relay.d.ts.map +1 -1
  17. package/dist/src/Evolu/Relay.js +40 -39
  18. package/dist/src/Evolu/Storage.d.ts +6 -11
  19. package/dist/src/Evolu/Storage.d.ts.map +1 -1
  20. package/dist/src/Evolu/Storage.js +30 -9
  21. package/dist/src/Evolu/Sync.d.ts +5 -5
  22. package/dist/src/Evolu/Sync.d.ts.map +1 -1
  23. package/dist/src/Evolu/Sync.js +3 -5
  24. package/dist/src/Evolu/Timestamp.d.ts +24 -0
  25. package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
  26. package/dist/src/Evolu/Timestamp.js +24 -0
  27. package/dist/src/Identicon.d.ts +35 -0
  28. package/dist/src/Identicon.d.ts.map +1 -0
  29. package/dist/src/Identicon.js +143 -0
  30. package/dist/src/ManyToManyMap.d.ts +0 -3
  31. package/dist/src/ManyToManyMap.d.ts.map +1 -1
  32. package/dist/src/Result.d.ts +13 -6
  33. package/dist/src/Result.d.ts.map +1 -1
  34. package/dist/src/Sqlite.d.ts +36 -1
  35. package/dist/src/Sqlite.d.ts.map +1 -1
  36. package/dist/src/Sqlite.js +56 -3
  37. package/dist/src/Task.d.ts.map +1 -1
  38. package/dist/src/Task.js +36 -0
  39. package/dist/src/Type.d.ts +73 -9
  40. package/dist/src/Type.d.ts.map +1 -1
  41. package/dist/src/Type.js +124 -22
  42. package/dist/src/Types.d.ts +1 -1
  43. package/dist/src/WebSocket.d.ts.map +1 -1
  44. package/dist/src/WebSocket.js +2 -7
  45. package/dist/src/index.d.ts +2 -0
  46. package/dist/src/index.d.ts.map +1 -1
  47. package/dist/src/index.js +2 -0
  48. package/package.json +1 -1
  49. package/src/Assert.ts +0 -19
  50. package/src/Cache.ts +85 -0
  51. package/src/Evolu/Db.ts +11 -7
  52. package/src/Evolu/LocalAuth.ts +19 -7
  53. package/src/Evolu/Owner.ts +140 -103
  54. package/src/Evolu/Relay.ts +52 -48
  55. package/src/Evolu/Storage.ts +47 -23
  56. package/src/Evolu/Sync.ts +11 -12
  57. package/src/Evolu/Timestamp.ts +24 -0
  58. package/src/Identicon.ts +197 -0
  59. package/src/ManyToManyMap.ts +0 -3
  60. package/src/Result.ts +13 -6
  61. package/src/Sqlite.ts +68 -5
  62. package/src/Task.ts +41 -0
  63. package/src/Type.ts +262 -27
  64. package/src/Types.ts +1 -1
  65. package/src/WebSocket.ts +6 -10
  66. package/src/index.ts +2 -0
package/src/Type.ts CHANGED
@@ -5,6 +5,9 @@
5
5
  * {@link Result}) instead of throwing. We either get a safely typed value or a
6
6
  * precise, composable error value telling us exactly why validation failed.
7
7
  *
8
+ * Evolu Type supports [Standard Schema](https://standardschema.dev/) for
9
+ * interoperability with 40+ validation-compatible tools and frameworks.
10
+ *
8
11
  * Why another validation library?
9
12
  *
10
13
  * - **Result-based error handling** – no exceptions for normal control flow.
@@ -196,7 +199,7 @@ export interface Type<
196
199
  Parent = T,
197
200
  /** The parent's error. */
198
201
  ParentError extends TypeError = Error,
199
- > {
202
+ > extends StandardSchemaV1<Input, T> {
200
203
  readonly name: Name;
201
204
 
202
205
  /**
@@ -250,7 +253,6 @@ export interface Type<
250
253
  *
251
254
  * - When you need to convert a validation result to a nullable value
252
255
  * - When the error is not important and you just want the value or nothing
253
- * - APIs that expect `T | null`
254
256
  *
255
257
  * ### Example
256
258
  *
@@ -367,8 +369,6 @@ export interface Type<
367
369
  readonly ParentError: ParentError;
368
370
 
369
371
  /**
370
- * Error | ParentError
371
- *
372
372
  * ### Example
373
373
  *
374
374
  * ```ts
@@ -458,7 +458,7 @@ export type InferParentError<A extends AnyType> =
458
458
  : never;
459
459
 
460
460
  /**
461
- * Extracts all error types (Error | ParentError) from a {@link Type}.
461
+ * Extracts all error types from a {@link Type}.
462
462
  *
463
463
  * @category Utilities
464
464
  */
@@ -500,6 +500,7 @@ const createType = <
500
500
  | "Parent"
501
501
  | "ParentError"
502
502
  | "Errors"
503
+ | "~standard"
503
504
  >,
504
505
  ): Type<Name, T, Input, Error, Parent, ParentError> => ({
505
506
  ...definition,
@@ -515,6 +516,27 @@ const createType = <
515
516
  Parent: undefined as unknown as Parent,
516
517
  ParentError: undefined as unknown as ParentError,
517
518
  Errors: undefined as unknown as Error | ParentError,
519
+ "~standard": {
520
+ version: 1,
521
+ vendor: "evolu",
522
+ validate: (value: unknown): StandardSchemaV1.Result<T> => {
523
+ const result = definition.fromUnknown(value);
524
+ if (result.ok) {
525
+ return { value: result.value };
526
+ }
527
+ cachedStandardSchemaFormatTypeError ??= createFormatTypeError();
528
+ return {
529
+ issues: typeErrorToStandardSchemaIssues(
530
+ result.error as TypeErrors<Error>,
531
+ cachedStandardSchemaFormatTypeError,
532
+ ),
533
+ };
534
+ },
535
+ types: {
536
+ input: undefined as unknown as Input,
537
+ output: undefined as unknown as T,
538
+ },
539
+ },
518
540
  });
519
541
 
520
542
  /**
@@ -741,7 +763,7 @@ export interface InstanceOfType<T extends abstract new (...args: any) => any>
741
763
  }
742
764
 
743
765
  export const formatInstanceOfError = createTypeErrorFormatter<InstanceOfError>(
744
- (error) => `Value ${error.value} is not an instance of ${error.ctor}`,
766
+ (error) => `The value ${error.value} is not an instance of ${error.ctor}.`,
745
767
  );
746
768
 
747
769
  /**
@@ -1005,7 +1027,7 @@ export interface CurrencyCodeError extends TypeError<"CurrencyCode"> {}
1005
1027
 
1006
1028
  export const formatCurrencyCodeError =
1007
1029
  createTypeErrorFormatter<CurrencyCodeError>(
1008
- (error) => `Invalid currency code: ${error.value}`,
1030
+ (error) => `Invalid currency code: ${error.value}.`,
1009
1031
  );
1010
1032
 
1011
1033
  /**
@@ -1125,7 +1147,7 @@ export const trimmed: BrandFactory<"Trimmed", string, TrimmedError> = (
1125
1147
  export interface TrimmedError extends TypeError<"Trimmed"> {}
1126
1148
 
1127
1149
  export const formatTrimmedError = createTypeErrorFormatter<TrimmedError>(
1128
- (error) => `A value ${error.value} is not trimmed`,
1150
+ (error) => `The value ${error.value} must be trimmed.`,
1129
1151
  );
1130
1152
 
1131
1153
  /**
@@ -1170,7 +1192,7 @@ export interface MinLengthError<Min extends number = number>
1170
1192
 
1171
1193
  export const formatMinLengthError = createTypeErrorFormatter<MinLengthError>(
1172
1194
  (error) =>
1173
- `Value ${error.value} does not meet the minimum length of ${error.min}.`,
1195
+ `The value ${error.value} does not meet the minimum length of ${error.min}.`,
1174
1196
  );
1175
1197
 
1176
1198
  /**
@@ -1200,7 +1222,8 @@ export interface MaxLengthError<Max extends number = number>
1200
1222
  }
1201
1223
 
1202
1224
  export const formatMaxLengthError = createTypeErrorFormatter<MaxLengthError>(
1203
- (error) => `Value ${error.value} exceeds the maximum length of ${error.max}.`,
1225
+ (error) =>
1226
+ `The value ${error.value} exceeds the maximum length of ${error.max}.`,
1204
1227
  );
1205
1228
 
1206
1229
  /**
@@ -1233,7 +1256,7 @@ export interface LengthError<Exact extends number = number>
1233
1256
 
1234
1257
  export const formatLengthError = createTypeErrorFormatter<LengthError>(
1235
1258
  (error) =>
1236
- `Value ${error.value} does not have the required length of ${error.exact}.`,
1259
+ `The value ${error.value} does not have the required length of ${error.exact}.`,
1237
1260
  );
1238
1261
 
1239
1262
  /** @category String */
@@ -1295,7 +1318,7 @@ export type Mnemonic = typeof Mnemonic.Type;
1295
1318
  export interface MnemonicError extends TypeError<"Mnemonic"> {}
1296
1319
 
1297
1320
  export const formatMnemonicError = createTypeErrorFormatter<MnemonicError>(
1298
- (error) => `Invalid BIP39 mnemonic: ${error.value}`,
1321
+ (error) => `Invalid BIP39 mnemonic: ${error.value}.`,
1299
1322
  );
1300
1323
 
1301
1324
  /**
@@ -1334,7 +1357,7 @@ export interface RegexError<Name extends TypeName = TypeName>
1334
1357
 
1335
1358
  export const formatRegexError = createTypeErrorFormatter<RegexError>(
1336
1359
  (error) =>
1337
- `Value ${error.value} does not match the pattern for ${error.name}: ${error.pattern}`,
1360
+ `The value ${error.value} does not match the pattern for ${error.name}: ${error.pattern}.`,
1338
1361
  );
1339
1362
 
1340
1363
  /**
@@ -1400,7 +1423,7 @@ export type Base64Url = typeof Base64Url.Type;
1400
1423
  export interface Base64UrlError extends TypeError<"Base64Url"> {}
1401
1424
 
1402
1425
  export const formatBase64UrlError = createTypeErrorFormatter<Base64UrlError>(
1403
- (error) => `Value ${error.value} is not a valid Base64Url string.`,
1426
+ (error) => `The value ${error.value} is not a valid Base64Url string.`,
1404
1427
  );
1405
1428
 
1406
1429
  const hasNodeBuffer = typeof globalThis.Buffer !== "undefined";
@@ -1553,7 +1576,7 @@ export type Id = typeof Id.Type;
1553
1576
  export interface IdError extends TypeError<"Id"> {}
1554
1577
 
1555
1578
  export const formatIdError = createTypeErrorFormatter<IdError>(
1556
- (error) => `Value ${error.value} is not a valid Id.`,
1579
+ (error) => `The value ${error.value} is not a valid Id.`,
1557
1580
  );
1558
1581
 
1559
1582
  /**
@@ -1673,7 +1696,7 @@ export interface TableIdError<Table extends TypeName = TypeName>
1673
1696
  }
1674
1697
 
1675
1698
  export const formatTableIdError = createTypeErrorFormatter<TableIdError>(
1676
- (error) => `Invalid ${error.type} table Id: ${error.value}`,
1699
+ (error) => `Invalid Id for table ${error.table}: ${error.value}.`,
1677
1700
  );
1678
1701
 
1679
1702
  /** Binary representation of an {@link Id}. */
@@ -1691,7 +1714,7 @@ export const idBytesToId = (idBytes: IdBytes): Id =>
1691
1714
  uint8ArrayToBase64Url(idBytes) as unknown as Id;
1692
1715
 
1693
1716
  /**
1694
- * Positive number.
1717
+ * Positive number (> 0).
1695
1718
  *
1696
1719
  * ### Example
1697
1720
  *
@@ -1714,11 +1737,11 @@ export const positive: BrandFactory<"Positive", number, PositiveError> = (
1714
1737
  export interface PositiveError extends TypeError<"Positive"> {}
1715
1738
 
1716
1739
  export const formatPositiveError = createTypeErrorFormatter<PositiveError>(
1717
- (error) => `The value ${error.value} is not positive.`,
1740
+ (error) => `The value ${error.value} must be positive (> 0).`,
1718
1741
  );
1719
1742
 
1720
1743
  /**
1721
- * Negative number.
1744
+ * Negative number (< 0).
1722
1745
  *
1723
1746
  * ### Example
1724
1747
  *
@@ -1738,11 +1761,11 @@ export const negative: BrandFactory<"Negative", number, NegativeError> = (
1738
1761
  export interface NegativeError extends TypeError<"Negative"> {}
1739
1762
 
1740
1763
  export const formatNegativeError = createTypeErrorFormatter<NegativeError>(
1741
- (error) => `The value ${error.value} is not negative.`,
1764
+ (error) => `The value ${error.value} must be negative (< 0).`,
1742
1765
  );
1743
1766
 
1744
1767
  /**
1745
- * Non-positive number.
1768
+ * Non-positive number (≤ 0).
1746
1769
  *
1747
1770
  * ### Example
1748
1771
  *
@@ -1767,11 +1790,11 @@ export interface NonPositiveError extends TypeError<"NonPositive"> {}
1767
1790
 
1768
1791
  export const formatNonPositiveError =
1769
1792
  createTypeErrorFormatter<NonPositiveError>(
1770
- (error) => `The value ${error.value} is not non-positive.`,
1793
+ (error) => `The value ${error.value} must be non-positive (≤ 0).`,
1771
1794
  );
1772
1795
 
1773
1796
  /**
1774
- * Non-negative number.
1797
+ * Non-negative number (≥ 0).
1775
1798
  *
1776
1799
  * ### Example
1777
1800
  *
@@ -1796,7 +1819,7 @@ export interface NonNegativeError extends TypeError<"NonNegative"> {}
1796
1819
 
1797
1820
  export const formatNonNegativeError =
1798
1821
  createTypeErrorFormatter<NonNegativeError>(
1799
- (error) => `The value ${error.value} is not non-negative.`,
1822
+ (error) => `The value ${error.value} must be non-negative (≥ 0).`,
1800
1823
  );
1801
1824
 
1802
1825
  /** @category Number */
@@ -1836,7 +1859,7 @@ export const int: BrandFactory<"Int", number, IntError> = (parent) =>
1836
1859
  export interface IntError extends TypeError<"Int"> {}
1837
1860
 
1838
1861
  export const formatIntError = createTypeErrorFormatter<IntError>(
1839
- (error) => `The value ${error.value} is not an integer.`,
1862
+ (error) => `The value ${error.value} must be an integer.`,
1840
1863
  );
1841
1864
 
1842
1865
  /**
@@ -1982,7 +2005,7 @@ export const nonNaN: BrandFactory<"NonNaN", number, NonNaNError> = (parent) =>
1982
2005
  export interface NonNaNError extends TypeError<"NonNaN"> {}
1983
2006
 
1984
2007
  export const formatNonNaNError = createTypeErrorFormatter<NonNaNError>(
1985
- (error) => `The value ${error.value} is NaN (not a number).`,
2008
+ () => `The value must not be NaN.`,
1986
2009
  );
1987
2010
 
1988
2011
  /** @category Number */
@@ -2004,7 +2027,7 @@ export const finite: BrandFactory<"Finite", number, FiniteError> = (parent) =>
2004
2027
  export interface FiniteError extends TypeError<"Finite"> {}
2005
2028
 
2006
2029
  export const formatFiniteError = createTypeErrorFormatter<FiniteError>(
2007
- (error) => `The value ${error.value} is not finite.`,
2030
+ (error) => `The value ${error.value} must be finite.`,
2008
2031
  );
2009
2032
 
2010
2033
  /**
@@ -4045,8 +4068,220 @@ export const createFormatTypeError = <ExtraErrors extends TypeError = never>(
4045
4068
  return formatUnionError(formatTypeError)(error);
4046
4069
  case "Tuple":
4047
4070
  return formatTupleError(formatTypeError)(error);
4071
+ default: {
4072
+ // Fallback for unknown error types
4073
+ const unknownError = error as TypeError;
4074
+ return `A value ${safelyStringifyUnknownValue(unknownError.value)} is not valid for type ${unknownError.type}.`;
4075
+ }
4048
4076
  }
4049
4077
  };
4050
4078
 
4051
4079
  return formatTypeError;
4052
4080
  };
4081
+
4082
+ /**
4083
+ * Converts an Evolu {@link TypeError} to Standard Schema V1 issues format.
4084
+ *
4085
+ * This function recursively converts Evolu's typed errors into the Standard
4086
+ * Schema issue format with proper path tracking for nested structures.
4087
+ *
4088
+ * @category Utilities
4089
+ */
4090
+ export const typeErrorToStandardSchemaIssues = <
4091
+ ExtraErrors extends TypeError = never,
4092
+ >(
4093
+ error: TypeErrors<ExtraErrors>,
4094
+ formatTypeError: TypeErrorFormatter<TypeErrors<ExtraErrors>>,
4095
+ path: ReadonlyArray<PropertyKey> = [],
4096
+ ): ReadonlyArray<StandardSchemaV1.Issue> => {
4097
+ if (error.type === "Array") {
4098
+ const arrayError = error as ArrayError;
4099
+ if (arrayError.reason.kind === "NotArray") {
4100
+ return [{ message: formatTypeError(error), path }];
4101
+ }
4102
+ return typeErrorToStandardSchemaIssues(
4103
+ arrayError.reason.error as TypeErrors<ExtraErrors>,
4104
+ formatTypeError,
4105
+ [...path, arrayError.reason.index],
4106
+ );
4107
+ }
4108
+
4109
+ if (error.type === "Object") {
4110
+ const objectError = error as ObjectError;
4111
+ if (
4112
+ objectError.reason.kind === "NotObject" ||
4113
+ objectError.reason.kind === "ExtraKeys"
4114
+ ) {
4115
+ return [{ message: formatTypeError(error), path }];
4116
+ }
4117
+ const issues: Array<StandardSchemaV1.Issue> = [];
4118
+ for (const [key, propError] of Object.entries(objectError.reason.errors)) {
4119
+ issues.push(
4120
+ ...typeErrorToStandardSchemaIssues(
4121
+ propError as TypeErrors<ExtraErrors>,
4122
+ formatTypeError,
4123
+ [...path, key],
4124
+ ),
4125
+ );
4126
+ }
4127
+ return issues;
4128
+ }
4129
+
4130
+ if (error.type === "ObjectWithRecord") {
4131
+ const objectWithRecordError = error as ObjectWithRecordError;
4132
+ if (objectWithRecordError.reason.kind === "NotObject") {
4133
+ return [{ message: formatTypeError(error), path }];
4134
+ }
4135
+ if (
4136
+ objectWithRecordError.reason.kind === "IndexKey" ||
4137
+ objectWithRecordError.reason.kind === "IndexValue"
4138
+ ) {
4139
+ return typeErrorToStandardSchemaIssues(
4140
+ objectWithRecordError.reason.error as TypeErrors<ExtraErrors>,
4141
+ formatTypeError,
4142
+ [...path, objectWithRecordError.reason.key as PropertyKey],
4143
+ );
4144
+ }
4145
+ const issues: Array<StandardSchemaV1.Issue> = [];
4146
+ for (const [key, propError] of Object.entries(
4147
+ objectWithRecordError.reason.errors,
4148
+ )) {
4149
+ issues.push(
4150
+ ...typeErrorToStandardSchemaIssues(
4151
+ propError as TypeErrors<ExtraErrors>,
4152
+ formatTypeError,
4153
+ [...path, key],
4154
+ ),
4155
+ );
4156
+ }
4157
+ return issues;
4158
+ }
4159
+
4160
+ if (error.type === "Record") {
4161
+ const recordError = error as RecordError;
4162
+ if (recordError.reason.kind === "NotRecord") {
4163
+ return [{ message: formatTypeError(error), path }];
4164
+ }
4165
+ return typeErrorToStandardSchemaIssues(
4166
+ recordError.reason.error as TypeErrors<ExtraErrors>,
4167
+ formatTypeError,
4168
+ [...path, recordError.reason.key as PropertyKey],
4169
+ );
4170
+ }
4171
+
4172
+ if (error.type === "Tuple") {
4173
+ const tupleError = error as TupleError;
4174
+ if (tupleError.reason.kind === "InvalidLength") {
4175
+ return [{ message: formatTypeError(error), path }];
4176
+ }
4177
+ return typeErrorToStandardSchemaIssues(
4178
+ tupleError.reason.error as TypeErrors<ExtraErrors>,
4179
+ formatTypeError,
4180
+ [...path, tupleError.reason.index],
4181
+ );
4182
+ }
4183
+
4184
+ if (error.type === "Union") {
4185
+ const unionError = error as UnionError;
4186
+ return unionError.errors.flatMap((err) =>
4187
+ typeErrorToStandardSchemaIssues(
4188
+ err as TypeErrors<ExtraErrors>,
4189
+ formatTypeError,
4190
+ path,
4191
+ ),
4192
+ );
4193
+ }
4194
+
4195
+ if (error.type === "Brand") {
4196
+ const brandError = error as BrandWithoutRefineError<TypeName, TypeError>;
4197
+ if ("parentError" in brandError) {
4198
+ return typeErrorToStandardSchemaIssues(
4199
+ brandError.parentError as TypeErrors<ExtraErrors>,
4200
+ formatTypeError,
4201
+ path,
4202
+ );
4203
+ }
4204
+ return [{ message: formatTypeError(error), path }];
4205
+ }
4206
+
4207
+ return [{ message: formatTypeError(error), path }];
4208
+ };
4209
+
4210
+ /** The Standard Schema interface. */
4211
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
4212
+ /** The Standard Schema properties. */
4213
+ readonly "~standard": StandardSchemaV1.Props<Input, Output>;
4214
+ }
4215
+
4216
+ // eslint-disable-next-line @typescript-eslint/no-namespace
4217
+ export declare namespace StandardSchemaV1 {
4218
+ /** The Standard Schema properties interface. */
4219
+ export interface Props<Input = unknown, Output = Input> {
4220
+ /** The version number of the standard. */
4221
+ readonly version: 1;
4222
+ /** The vendor name of the schema library. */
4223
+ readonly vendor: string;
4224
+ /** Validates unknown input values. */
4225
+ readonly validate: (
4226
+ value: unknown,
4227
+ ) => Result<Output> | Promise<Result<Output>>;
4228
+ /** Inferred types associated with the schema. */
4229
+ readonly types?: Types<Input, Output> | undefined;
4230
+ }
4231
+
4232
+ /** The result interface of the validate function. */
4233
+ export type Result<Output> = SuccessResult<Output> | FailureResult;
4234
+
4235
+ /** The result interface if validation succeeds. */
4236
+ export interface SuccessResult<Output> {
4237
+ /** The typed output value. */
4238
+ readonly value: Output;
4239
+ /** The non-existent issues. */
4240
+ readonly issues?: undefined;
4241
+ }
4242
+
4243
+ /** The result interface if validation fails. */
4244
+ export interface FailureResult {
4245
+ /** The issues of failed validation. */
4246
+ readonly issues: ReadonlyArray<Issue>;
4247
+ }
4248
+
4249
+ /** The issue interface of the failure output. */
4250
+ export interface Issue {
4251
+ /** The error message of the issue. */
4252
+ readonly message: string;
4253
+ /** The path of the issue, if any. */
4254
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
4255
+ }
4256
+
4257
+ /** The path segment interface of the issue. */
4258
+ export interface PathSegment {
4259
+ /** The key representing a path segment. */
4260
+ readonly key: PropertyKey;
4261
+ }
4262
+
4263
+ /** The Standard Schema types interface. */
4264
+ export interface Types<Input = unknown, Output = Input> {
4265
+ /** The input type of the schema. */
4266
+ readonly input: Input;
4267
+ /** The output type of the schema. */
4268
+ readonly output: Output;
4269
+ }
4270
+
4271
+ /** Infers the input type of a Standard Schema. */
4272
+ export type InferInput<Schema extends StandardSchemaV1> = NonNullable<
4273
+ Schema["~standard"]["types"]
4274
+ >["input"];
4275
+
4276
+ /** Infers the output type of a Standard Schema. */
4277
+ export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<
4278
+ Schema["~standard"]["types"]
4279
+ >["output"];
4280
+ }
4281
+
4282
+ /**
4283
+ * Shared formatter cache for Standard Schema integration - avoids circular
4284
+ * dependency by lazily creating the formatter on first use rather than during
4285
+ * module initialization.
4286
+ */
4287
+ let cachedStandardSchemaFormatTypeError: TypeErrorFormatter<any> | undefined;
package/src/Types.ts CHANGED
@@ -79,7 +79,7 @@ export type NullablePartial<
79
79
  export type IntentionalNever = never;
80
80
 
81
81
  /**
82
- * String | number | bigint | boolean | undefined | null
82
+ * String, number, bigint, boolean, undefined, null
83
83
  *
84
84
  * https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types
85
85
  */
package/src/WebSocket.ts CHANGED
@@ -4,7 +4,6 @@
4
4
  * @module
5
5
  */
6
6
 
7
- import { assertNoErrorInCatch } from "./Assert.js";
8
7
  import { constVoid } from "./Function.js";
9
8
  import { err, ok, Result } from "./Result.js";
10
9
  import { retry, RetryError, RetryOptions } from "./Task.js";
@@ -192,7 +191,7 @@ export const createWebSocket: CreateWebSocket = (
192
191
  * - Is rejected when a connection is closed.
193
192
  * - Is resolved when WebSocket is disposed().
194
193
  */
195
- retry(
194
+ void retry(
196
195
  {
197
196
  ...defaultRetryOptions,
198
197
  ...retryOptions,
@@ -222,6 +221,7 @@ export const createWebSocket: CreateWebSocket = (
222
221
  ? { type: "WebSocketConnectionError", event }
223
222
  : { type: "WebSocketConnectError", event };
224
223
  onError?.(error);
224
+
225
225
  // Trigger reconnect only on WebSocketConnectError.
226
226
  if (error.type === "WebSocketConnectError") {
227
227
  resolve(err(error));
@@ -237,14 +237,10 @@ export const createWebSocket: CreateWebSocket = (
237
237
  onMessage?.(event.data as string | ArrayBuffer | Blob);
238
238
  };
239
239
  }),
240
- )(reconnectController)
241
- .then((result) => {
242
- if (result.ok || result.error.type === "AbortError") return;
243
- onError?.(result.error as WebSocketError);
244
- })
245
- .catch((error: unknown) => {
246
- assertNoErrorInCatch("WebSocket retry", error);
247
- });
240
+ )(reconnectController).then((result) => {
241
+ if (result.ok || result.error.type === "AbortError") return;
242
+ onError?.(result.error as WebSocketError);
243
+ });
248
244
 
249
245
  return {
250
246
  send: (data) => {
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./Assert.js";
3
3
  export * from "./BigInt.js";
4
4
  export * from "./Brand.js";
5
5
  export * from "./Buffer.js";
6
+ export * from "./Cache.js";
6
7
  export * from "./CallbackRegistry.js";
7
8
  export * from "./Console.js";
8
9
  export * from "./Crypto.js";
@@ -10,6 +11,7 @@ export * from "./Eq.js";
10
11
  export * from "./Error.js";
11
12
  export * from "./Evolu/Public.js";
12
13
  export * from "./Function.js";
14
+ export * from "./Identicon.js";
13
15
  export * from "./ManyToManyMap.js";
14
16
  export * from "./Number.js";
15
17
  export * from "./Object.js";