@evolu/common 7.4.0 → 8.0.0-next.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.
Files changed (251) hide show
  1. package/README.md +4 -61
  2. package/dist/src/Array.d.ts +343 -102
  3. package/dist/src/Array.d.ts.map +1 -1
  4. package/dist/src/Array.js +181 -85
  5. package/dist/src/Assert.d.ts +57 -11
  6. package/dist/src/Assert.d.ts.map +1 -1
  7. package/dist/src/Assert.js +47 -11
  8. package/dist/src/BigInt.d.ts +6 -1
  9. package/dist/src/BigInt.d.ts.map +1 -1
  10. package/dist/src/BigInt.js +5 -0
  11. package/dist/src/Brand.d.ts +40 -12
  12. package/dist/src/Brand.d.ts.map +1 -1
  13. package/dist/src/Brand.js +5 -0
  14. package/dist/src/Buffer.d.ts +6 -1
  15. package/dist/src/Buffer.d.ts.map +1 -1
  16. package/dist/src/Buffer.js +7 -2
  17. package/dist/src/Cache.d.ts +10 -2
  18. package/dist/src/Cache.d.ts.map +1 -1
  19. package/dist/src/Cache.js +6 -0
  20. package/dist/src/Callbacks.d.ts +10 -7
  21. package/dist/src/Callbacks.d.ts.map +1 -1
  22. package/dist/src/Callbacks.js +23 -13
  23. package/dist/src/Console.d.ts +361 -69
  24. package/dist/src/Console.d.ts.map +1 -1
  25. package/dist/src/Console.js +217 -117
  26. package/dist/src/Crypto.d.ts +70 -21
  27. package/dist/src/Crypto.d.ts.map +1 -1
  28. package/dist/src/Crypto.js +72 -27
  29. package/dist/src/Eq.d.ts +22 -2
  30. package/dist/src/Eq.d.ts.map +1 -1
  31. package/dist/src/Eq.js +21 -1
  32. package/dist/src/Error.d.ts +23 -12
  33. package/dist/src/Error.d.ts.map +1 -1
  34. package/dist/src/Error.js +27 -11
  35. package/dist/src/Function.d.ts +128 -56
  36. package/dist/src/Function.d.ts.map +1 -1
  37. package/dist/src/Function.js +118 -14
  38. package/dist/src/Identicon.d.ts +5 -0
  39. package/dist/src/Identicon.d.ts.map +1 -1
  40. package/dist/src/Identicon.js +6 -1
  41. package/dist/src/Lookup.d.ts +160 -0
  42. package/dist/src/Lookup.d.ts.map +1 -0
  43. package/dist/src/Lookup.js +192 -0
  44. package/dist/src/Microtask.d.ts +21 -0
  45. package/dist/src/Microtask.d.ts.map +1 -0
  46. package/dist/src/Microtask.js +37 -0
  47. package/dist/src/Number.d.ts +18 -4
  48. package/dist/src/Number.d.ts.map +1 -1
  49. package/dist/src/Number.js +23 -1
  50. package/dist/src/Object.d.ts +110 -5
  51. package/dist/src/Object.d.ts.map +1 -1
  52. package/dist/src/Object.js +108 -5
  53. package/dist/src/Option.d.ts +58 -0
  54. package/dist/src/Option.d.ts.map +1 -0
  55. package/dist/src/Option.js +43 -0
  56. package/dist/src/Order.d.ts +5 -0
  57. package/dist/src/Order.d.ts.map +1 -1
  58. package/dist/src/Order.js +8 -3
  59. package/dist/src/Platform.d.ts +36 -2
  60. package/dist/src/Platform.d.ts.map +1 -1
  61. package/dist/src/Platform.js +10 -6
  62. package/dist/src/Polyfills.d.ts +27 -0
  63. package/dist/src/Polyfills.d.ts.map +1 -0
  64. package/dist/src/Polyfills.js +299 -0
  65. package/dist/src/Random.d.ts +18 -7
  66. package/dist/src/Random.d.ts.map +1 -1
  67. package/dist/src/Random.js +9 -7
  68. package/dist/src/Redacted.d.ts +7 -4
  69. package/dist/src/Redacted.d.ts.map +1 -1
  70. package/dist/src/Redacted.js +5 -0
  71. package/dist/src/Ref.d.ts +31 -16
  72. package/dist/src/Ref.d.ts.map +1 -1
  73. package/dist/src/Ref.js +35 -7
  74. package/dist/src/RefCount.d.ts +62 -0
  75. package/dist/src/RefCount.d.ts.map +1 -0
  76. package/dist/src/RefCount.js +83 -0
  77. package/dist/src/Relation.d.ts +84 -29
  78. package/dist/src/Relation.d.ts.map +1 -1
  79. package/dist/src/Relation.js +83 -105
  80. package/dist/src/Resource.d.ts +263 -0
  81. package/dist/src/Resource.d.ts.map +1 -0
  82. package/dist/src/Resource.js +389 -0
  83. package/dist/src/Result.d.ts +390 -374
  84. package/dist/src/Result.d.ts.map +1 -1
  85. package/dist/src/Result.js +142 -70
  86. package/dist/src/Schedule.d.ts +953 -0
  87. package/dist/src/Schedule.d.ts.map +1 -0
  88. package/dist/src/Schedule.js +1199 -0
  89. package/dist/src/Set.d.ts +181 -0
  90. package/dist/src/Set.d.ts.map +1 -0
  91. package/dist/src/Set.js +137 -0
  92. package/dist/src/Skiplist.d.ts +6 -1
  93. package/dist/src/Skiplist.d.ts.map +1 -1
  94. package/dist/src/Skiplist.js +5 -0
  95. package/dist/src/Sqlite.d.ts +160 -60
  96. package/dist/src/Sqlite.d.ts.map +1 -1
  97. package/dist/src/Sqlite.js +290 -190
  98. package/dist/src/Store.d.ts +36 -28
  99. package/dist/src/Store.d.ts.map +1 -1
  100. package/dist/src/Store.js +55 -15
  101. package/dist/src/String.d.ts +5 -0
  102. package/dist/src/String.d.ts.map +1 -1
  103. package/dist/src/String.js +5 -0
  104. package/dist/src/Task.d.ts +2263 -423
  105. package/dist/src/Task.d.ts.map +1 -1
  106. package/dist/src/Task.js +1488 -348
  107. package/dist/src/Test.d.ts +122 -0
  108. package/dist/src/Test.d.ts.map +1 -0
  109. package/dist/src/Test.js +66 -0
  110. package/dist/src/Time.d.ts +201 -48
  111. package/dist/src/Time.d.ts.map +1 -1
  112. package/dist/src/Time.js +190 -86
  113. package/dist/src/Tracer.d.ts +48 -0
  114. package/dist/src/Tracer.d.ts.map +1 -0
  115. package/dist/src/Tracer.js +6 -0
  116. package/dist/src/Type.d.ts +582 -209
  117. package/dist/src/Type.d.ts.map +1 -1
  118. package/dist/src/Type.js +362 -240
  119. package/dist/src/Types.d.ts +160 -6
  120. package/dist/src/Types.d.ts.map +1 -1
  121. package/dist/src/Types.js +22 -2
  122. package/dist/src/WebSocket.d.ts +113 -58
  123. package/dist/src/WebSocket.d.ts.map +1 -1
  124. package/dist/src/WebSocket.js +210 -118
  125. package/dist/src/Worker.d.ts +245 -60
  126. package/dist/src/Worker.d.ts.map +1 -1
  127. package/dist/src/Worker.js +220 -64
  128. package/dist/src/index.d.ts +25 -3
  129. package/dist/src/index.d.ts.map +1 -1
  130. package/dist/src/index.js +19 -3
  131. package/dist/src/local-first/Db.d.ts +24 -213
  132. package/dist/src/local-first/Db.d.ts.map +1 -1
  133. package/dist/src/local-first/Db.js +622 -293
  134. package/dist/src/local-first/Error.d.ts +12 -0
  135. package/dist/src/local-first/Error.d.ts.map +1 -0
  136. package/dist/src/local-first/Error.js +6 -0
  137. package/dist/src/local-first/Evolu.d.ts +330 -285
  138. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  139. package/dist/src/local-first/Evolu.js +472 -402
  140. package/dist/src/local-first/LocalAuth.d.ts +10 -10
  141. package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
  142. package/dist/src/local-first/LocalAuth.js +6 -1
  143. package/dist/src/local-first/Owner.d.ts +70 -27
  144. package/dist/src/local-first/Owner.d.ts.map +1 -1
  145. package/dist/src/local-first/Owner.js +27 -14
  146. package/dist/src/local-first/Protocol.d.ts +58 -50
  147. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  148. package/dist/src/local-first/Protocol.js +253 -155
  149. package/dist/src/local-first/Query.d.ts +133 -43
  150. package/dist/src/local-first/Query.d.ts.map +1 -1
  151. package/dist/src/local-first/Query.js +139 -90
  152. package/dist/src/local-first/Relay.d.ts +18 -38
  153. package/dist/src/local-first/Relay.d.ts.map +1 -1
  154. package/dist/src/local-first/Relay.js +59 -171
  155. package/dist/src/local-first/Schema.d.ts +139 -144
  156. package/dist/src/local-first/Schema.d.ts.map +1 -1
  157. package/dist/src/local-first/Schema.js +78 -163
  158. package/dist/src/local-first/Shared.d.ts +125 -0
  159. package/dist/src/local-first/Shared.d.ts.map +1 -0
  160. package/dist/src/local-first/Shared.js +569 -0
  161. package/dist/src/local-first/Storage.d.ts +50 -53
  162. package/dist/src/local-first/Storage.d.ts.map +1 -1
  163. package/dist/src/local-first/Storage.js +121 -173
  164. package/dist/src/local-first/Timestamp.d.ts +28 -35
  165. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  166. package/dist/src/local-first/Timestamp.js +24 -25
  167. package/dist/src/local-first/index.d.ts +2 -15
  168. package/dist/src/local-first/index.d.ts.map +1 -1
  169. package/dist/src/local-first/index.js +2 -15
  170. package/package.json +36 -26
  171. package/src/Array.ts +467 -106
  172. package/src/Assert.ts +87 -12
  173. package/src/BigInt.ts +7 -1
  174. package/src/Brand.ts +41 -12
  175. package/src/Buffer.ts +10 -4
  176. package/src/Cache.ts +11 -2
  177. package/src/Callbacks.ts +33 -23
  178. package/src/Console.ts +567 -178
  179. package/src/Crypto.ts +111 -62
  180. package/src/Eq.ts +30 -3
  181. package/src/Error.ts +50 -34
  182. package/src/Function.ts +140 -68
  183. package/src/Identicon.ts +7 -1
  184. package/src/Lookup.ts +415 -0
  185. package/src/Microtask.ts +58 -0
  186. package/src/Number.ts +40 -7
  187. package/src/Object.ts +155 -16
  188. package/src/Option.ts +74 -0
  189. package/src/Order.ts +11 -3
  190. package/src/Platform.ts +43 -7
  191. package/src/Polyfills.ts +465 -0
  192. package/src/Random.ts +25 -11
  193. package/src/Redacted.ts +8 -4
  194. package/src/Ref.ts +72 -21
  195. package/src/RefCount.ts +170 -0
  196. package/src/Relation.ts +188 -136
  197. package/src/Resource.ts +864 -0
  198. package/src/Result.ts +548 -381
  199. package/src/Schedule.ts +1471 -0
  200. package/src/Set.ts +247 -0
  201. package/src/Skiplist.ts +7 -1
  202. package/src/Sqlite.ts +409 -304
  203. package/src/Store.ts +94 -48
  204. package/src/String.ts +6 -0
  205. package/src/Task.ts +3685 -740
  206. package/src/Test.ts +162 -0
  207. package/src/Time.ts +348 -145
  208. package/src/Tracer.ts +54 -0
  209. package/src/Type.ts +1064 -630
  210. package/src/Types.ts +202 -7
  211. package/src/WebSocket.ts +311 -178
  212. package/src/Worker.ts +527 -147
  213. package/src/index.ts +74 -3
  214. package/src/local-first/Db.ts +871 -597
  215. package/src/local-first/Error.ts +17 -0
  216. package/src/local-first/Evolu.ts +884 -823
  217. package/src/local-first/LocalAuth.ts +10 -10
  218. package/src/local-first/Owner.ts +94 -42
  219. package/src/local-first/Protocol.ts +440 -303
  220. package/src/local-first/Query.ts +243 -194
  221. package/src/local-first/Relay.ts +91 -252
  222. package/src/local-first/Schema.ts +284 -394
  223. package/src/local-first/Shared.ts +932 -0
  224. package/src/local-first/Storage.ts +209 -282
  225. package/src/local-first/Timestamp.ts +38 -45
  226. package/src/local-first/index.ts +2 -16
  227. package/LICENSE +0 -21
  228. package/dist/src/Instances.d.ts +0 -34
  229. package/dist/src/Instances.d.ts.map +0 -1
  230. package/dist/src/Instances.js +0 -44
  231. package/dist/src/Resources.d.ts +0 -118
  232. package/dist/src/Resources.d.ts.map +0 -1
  233. package/dist/src/Resources.js +0 -197
  234. package/dist/src/local-first/Platform.d.ts +0 -25
  235. package/dist/src/local-first/Platform.d.ts.map +0 -1
  236. package/dist/src/local-first/Platform.js +0 -1
  237. package/dist/src/local-first/Public.d.ts +0 -22
  238. package/dist/src/local-first/Public.d.ts.map +0 -1
  239. package/dist/src/local-first/Public.js +0 -15
  240. package/dist/src/local-first/PublicKysely.d.ts +0 -148
  241. package/dist/src/local-first/PublicKysely.d.ts.map +0 -1
  242. package/dist/src/local-first/PublicKysely.js +0 -184
  243. package/dist/src/local-first/Sync.d.ts +0 -112
  244. package/dist/src/local-first/Sync.d.ts.map +0 -1
  245. package/dist/src/local-first/Sync.js +0 -529
  246. package/src/Instances.ts +0 -90
  247. package/src/Resources.ts +0 -367
  248. package/src/local-first/Platform.ts +0 -27
  249. package/src/local-first/Public.ts +0 -42
  250. package/src/local-first/PublicKysely.ts +0 -239
  251. package/src/local-first/Sync.ts +0 -960
package/dist/src/Type.js CHANGED
@@ -1,9 +1,14 @@
1
+ /**
2
+ * Runtime type validation, parsing, and branded types.
3
+ *
4
+ * @module
5
+ */
1
6
  import { utf8ToBytes } from "@noble/ciphers/utils.js";
2
7
  import { sha256 } from "@noble/hashes/sha2.js";
3
8
  import * as bip39 from "@scure/bip39";
4
9
  import { wordlist } from "@scure/bip39/wordlists/english.js";
5
- import { pack } from "msgpackr";
6
- import { isPlainObject } from "./Object.js";
10
+ import { exhaustiveCheck } from "./Function.js";
11
+ import { isFunction, isPlainObject } from "./Object.js";
7
12
  import { hasNodeBuffer } from "./Platform.js";
8
13
  import { err, getOrNull, getOrThrow, ok, trySync } from "./Result.js";
9
14
  import { safelyStringifyUnknownValue } from "./String.js";
@@ -11,7 +16,7 @@ const EvoluTypeSymbol = Symbol("evolu.Type");
11
16
  /**
12
17
  * Checks if the given value is an {@link Type}.
13
18
  *
14
- * @category Utilities
19
+ * @group Utilities
15
20
  */
16
21
  export const isType = (value) => typeof value === "object" && value !== null && EvoluTypeSymbol in value;
17
22
  const createType = (name, definition) => ({
@@ -36,9 +41,8 @@ const createType = (name, definition) => ({
36
41
  if (result.ok) {
37
42
  return { value: result.value };
38
43
  }
39
- cachedStandardSchemaFormatTypeError ??= createFormatTypeError();
40
44
  return {
41
- issues: typeErrorToStandardSchemaIssues(result.error, cachedStandardSchemaFormatTypeError),
45
+ issues: typeErrorToStandardSchemaIssues(result.error),
42
46
  };
43
47
  },
44
48
  types: {
@@ -61,7 +65,7 @@ const createType = (name, definition) => ({
61
65
  * );
62
66
  * ```
63
67
  *
64
- * @category Utilities
68
+ * @group Utilities
65
69
  */
66
70
  export const createTypeErrorFormatter = (format) => (error) => format({ ...error, value: safelyStringifyUnknownValue(error.value) });
67
71
  /**
@@ -85,7 +89,7 @@ export const createTypeErrorFormatter = (format) => (error) => format({ ...error
85
89
  * );
86
90
  * ```
87
91
  *
88
- * @category Base Factories
92
+ * @group Base factories
89
93
  */
90
94
  export const base = (name, fromUnknown) => createType(name, {
91
95
  fromUnknown,
@@ -104,52 +108,60 @@ export const base = (name, fromUnknown) => createType(name, {
104
108
  * createBaseTypeErrorFormatter<StringError>();
105
109
  * ```
106
110
  *
107
- * @category Utilities
111
+ * @group Utilities
108
112
  */
109
113
  export const createBaseTypeErrorFormatter = () => createTypeErrorFormatter((error) => `A value ${error.value} is not a ${error.type.toLowerCase()}.`);
110
- /** @category Base Types */
111
- export const Unknown = base("Unknown", ok);
114
+ /** @group Base Types */
115
+ export const Unknown = /*#__PURE__*/ base("Unknown", ok);
112
116
  /**
113
- * @category Base Types
114
- * @category String
117
+ * @group Base Types
118
+ * @group String
115
119
  */
116
- export const String = base("String", (value) => typeof value === "string"
120
+ export const String = /*#__PURE__*/ base("String", (value) => typeof value === "string"
117
121
  ? ok(value)
118
122
  : err({ type: "String", value }));
119
- export const formatStringError = createBaseTypeErrorFormatter();
120
- /** @category Base Types */
121
- export const Number = base("Number", (value) => typeof value === "number"
123
+ export const formatStringError =
124
+ /*#__PURE__*/ createBaseTypeErrorFormatter();
125
+ /** @group Base Types */
126
+ export const Number = /*#__PURE__*/ base("Number", (value) => typeof value === "number"
122
127
  ? ok(value)
123
128
  : err({ type: "Number", value }));
124
- export const formatNumberError = createBaseTypeErrorFormatter();
125
- /** @category Base Types */
126
- export const BigInt = base("BigInt", (value) => typeof value === "bigint"
129
+ export const formatNumberError =
130
+ /*#__PURE__*/ createBaseTypeErrorFormatter();
131
+ /** @group Base Types */
132
+ export const BigInt = /*#__PURE__*/ base("BigInt", (value) => typeof value === "bigint"
127
133
  ? ok(value)
128
134
  : err({ type: "BigInt", value }));
129
- export const formatBigIntError = createBaseTypeErrorFormatter();
130
- /** @category Base Types */
131
- export const Boolean = base("Boolean", (value) => typeof value === "boolean"
135
+ export const formatBigIntError =
136
+ /*#__PURE__*/ createBaseTypeErrorFormatter();
137
+ /** @group Base Types */
138
+ export const Boolean = /*#__PURE__*/ base("Boolean", (value) => typeof value === "boolean"
132
139
  ? ok(value)
133
140
  : err({ type: "Boolean", value }));
134
- export const formatBooleanError = createBaseTypeErrorFormatter();
135
- /** @category Base Types */
136
- export const Undefined = base("Undefined", (value) => value === undefined
141
+ export const formatBooleanError =
142
+ /*#__PURE__*/ createBaseTypeErrorFormatter();
143
+ /** @group Base Types */
144
+ export const Undefined = /*#__PURE__*/ base("Undefined", (value) => value === undefined
137
145
  ? ok(value)
138
146
  : err({ type: "Undefined", value }));
139
- export const formatUndefinedError = createBaseTypeErrorFormatter();
140
- /** @category Base Types */
141
- export const Null = base("Null", (value) => value === null ? ok(value) : err({ type: "Null", value }));
142
- export const formatNullError = createBaseTypeErrorFormatter();
143
- /** @category Base Types */
144
- export const Function = base("Function", (value) => typeof value === "function"
147
+ export const formatUndefinedError =
148
+ /*#__PURE__*/ createBaseTypeErrorFormatter();
149
+ /** @group Base Types */
150
+ export const Null = /*#__PURE__*/ base("Null", (value) => value === null ? ok(value) : err({ type: "Null", value }));
151
+ export const formatNullError =
152
+ /*#__PURE__*/ createBaseTypeErrorFormatter();
153
+ /** @group Base Types */
154
+ export const Function = /*#__PURE__*/ base("Function", (value) => isFunction(value)
145
155
  ? ok(value)
146
156
  : err({ type: "Function", value }));
147
- export const formatFunctionError = createBaseTypeErrorFormatter();
148
- /** @category Base Types */
149
- export const Uint8Array = base("Uint8Array", (value) => value instanceof globalThis.Uint8Array
157
+ export const formatFunctionError =
158
+ /*#__PURE__*/ createBaseTypeErrorFormatter();
159
+ /** @group Base Types */
160
+ export const Uint8Array = /*#__PURE__*/ base("Uint8Array", (value) => Object.prototype.toString.call(value) === "[object Uint8Array]"
150
161
  ? ok(value)
151
162
  : err({ type: "Uint8Array", value }));
152
- export const formatUint8ArrayError = createBaseTypeErrorFormatter();
163
+ export const formatUint8ArrayError =
164
+ /*#__PURE__*/ createBaseTypeErrorFormatter();
153
165
  /**
154
166
  * `instanceof` {@link Type}.
155
167
  *
@@ -168,7 +180,7 @@ export const formatUint8ArrayError = createBaseTypeErrorFormatter();
168
180
  * const error = UserInstance.from({}); // err
169
181
  * ```
170
182
  *
171
- * @category Base Factories
183
+ * @group Base factories
172
184
  */
173
185
  export const instanceOf = (ctor) => ({
174
186
  ...base("InstanceOf", (value) => value instanceof ctor
@@ -176,13 +188,14 @@ export const instanceOf = (ctor) => ({
176
188
  : err({ type: "InstanceOf", value, ctor: ctor.name })),
177
189
  ctor,
178
190
  });
179
- export const formatInstanceOfError = createTypeErrorFormatter((error) => `The value ${error.value} is not an instance of ${error.ctor}.`);
191
+ export const formatInstanceOfError =
192
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not an instance of ${error.ctor}.`);
180
193
  /**
181
194
  * JavaScript Date.
182
195
  *
183
- * @category Base Types
196
+ * @group Base Types
184
197
  */
185
- export const Date = instanceOf(globalThis.Date);
198
+ export const Date = /*#__PURE__*/ instanceOf(globalThis.Date);
186
199
  /**
187
200
  * Validates that an unknown value is an Evolu {@link Type} (i.e., satisfies
188
201
  * `AnyType`).
@@ -195,13 +208,14 @@ export const Date = instanceOf(globalThis.Date);
195
208
  * ```
196
209
  */
197
210
  // TODO: Rename to TypeInstance or something like that.
198
- export const EvoluType = base("EvoluType", (value) => isType(value)
211
+ export const EvoluType = /*#__PURE__*/ base("EvoluType", (value) => isType(value)
199
212
  ? ok(value)
200
213
  : err({
201
214
  type: "EvoluType",
202
215
  value,
203
216
  }));
204
- export const formatIsTypeError = createTypeErrorFormatter((error) => `Value ${error.value} is not a valid Evolu Type.`);
217
+ export const formatIsTypeError =
218
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `Value ${error.value} is not a valid Evolu Type.`);
205
219
  export function brand(name, parent, refine) {
206
220
  const fromUnknown = refine
207
221
  ? (value) => {
@@ -232,12 +246,13 @@ export function brand(name, parent, refine) {
232
246
  /**
233
247
  * A three-letter ISO 4217 currency code (e.g., USD, EUR).
234
248
  *
235
- * @category String
249
+ * @group String
236
250
  */
237
- export const CurrencyCode = brand("CurrencyCode", String, (value) => /^[A-Z]{3}$/.test(value)
251
+ export const CurrencyCode = /*#__PURE__*/ brand("CurrencyCode", String, (value) => /^[A-Z]{3}$/.test(value)
238
252
  ? ok(value)
239
253
  : err({ type: "CurrencyCode", value }));
240
- export const formatCurrencyCodeError = createTypeErrorFormatter((error) => `Invalid currency code: ${error.value}.`);
254
+ export const formatCurrencyCodeError =
255
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `Invalid currency code: ${error.value}.`);
241
256
  /**
242
257
  * ISO 8601 date-time string.
243
258
  *
@@ -257,9 +272,9 @@ export const formatCurrencyCodeError = createTypeErrorFormatter((error) => `Inva
257
272
  * const error = DateIso.from("10000-01-01T00:00:00.000Z"); // err
258
273
  * ```
259
274
  *
260
- * @category String
275
+ * @group String
261
276
  */
262
- export const DateIso = brand("DateIso", String, (value) => {
277
+ export const DateIso = /*#__PURE__*/ brand("DateIso", String, (value) => {
263
278
  if (value.length !== 24) {
264
279
  return err({ type: "DateIso", value });
265
280
  }
@@ -274,7 +289,8 @@ export const DateIso = brand("DateIso", String, (value) => {
274
289
  }
275
290
  return ok(value);
276
291
  });
277
- export const formatDateIsoError = createTypeErrorFormatter((error) => `The value ${error.value} is not a valid ISO 8601 date string.`);
292
+ export const formatDateIsoError =
293
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid ISO 8601 date string.`);
278
294
  export const dateToDateIso = (value) => DateIso.fromParent(value.toISOString());
279
295
  export const dateIsoToDate = (value) => new globalThis.Date(value);
280
296
  /**
@@ -291,25 +307,28 @@ export const dateIsoToDate = (value) => new globalThis.Date(value);
291
307
  * type TrimmedNonEmptyString = typeof TrimmedNonEmptyString.Type;
292
308
  * ```
293
309
  *
294
- * @category String
310
+ * @group String
295
311
  */
296
312
  export const trimmed = (parent) => brand("Trimmed", parent, (value) => value.trim().length === value.length
297
313
  ? ok(value)
298
314
  : err({ type: "Trimmed", value }));
299
- export const formatTrimmedError = createTypeErrorFormatter((error) => `The value ${error.value} must be trimmed.`);
315
+ export const formatTrimmedError =
316
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be trimmed.`);
300
317
  /**
301
318
  * Trimmed string
302
319
  *
303
320
  * - Use `TrimmedString.is` to check if an unknown value is trimmed.
304
321
  * - Use `TrimmedString.from` to check if a string is trimmed.
305
322
  *
306
- * @category String
323
+ * @group String
307
324
  */
308
- export const TrimmedString = trimmed(String);
325
+ export const TrimmedString = /*#__PURE__*/ trimmed(String);
309
326
  export const trim = (value) => value.trim();
310
327
  /**
311
328
  * Minimum length.
312
329
  *
330
+ * Use numeric literal, not expression. See {@link BrandFactory}.
331
+ *
313
332
  * ### Example
314
333
  *
315
334
  * ```ts
@@ -317,14 +336,17 @@ export const trim = (value) => value.trim();
317
336
  * const NonEmptyString = minLength(1)(String);
318
337
  * ```
319
338
  *
320
- * @category String
321
- * @category Array
339
+ * @group String
340
+ * @group Array
322
341
  */
323
342
  export const minLength = (min) => (parent) => brand(`MinLength${min}`, parent, (value) => value.length >= min ? ok(value) : err({ type: "MinLength", value, min }));
324
- export const formatMinLengthError = createTypeErrorFormatter((error) => `The value ${error.value} does not meet the minimum length of ${error.min}.`);
343
+ export const formatMinLengthError =
344
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} does not meet the minimum length of ${error.min}.`);
325
345
  /**
326
346
  * Maximum length.
327
347
  *
348
+ * Use numeric literal, not expression. See {@link BrandFactory}.
349
+ *
328
350
  * ### Example
329
351
  *
330
352
  * ```ts
@@ -332,14 +354,17 @@ export const formatMinLengthError = createTypeErrorFormatter((error) => `The val
332
354
  * const String100 = maxLength(100)(String);
333
355
  * ```
334
356
  *
335
- * @category String
336
- * @category Array
357
+ * @group String
358
+ * @group Array
337
359
  */
338
360
  export const maxLength = (max) => (parent) => brand(`MaxLength${max}`, parent, (value) => value.length <= max ? ok(value) : err({ type: "MaxLength", value, max }));
339
- export const formatMaxLengthError = createTypeErrorFormatter((error) => `The value ${error.value} exceeds the maximum length of ${error.max}.`);
361
+ export const formatMaxLengthError =
362
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} exceeds the maximum length of ${error.max}.`);
340
363
  /**
341
364
  * Exact length.
342
365
  *
366
+ * Use numeric literal, not expression. See {@link BrandFactory}.
367
+ *
343
368
  * ### Example
344
369
  *
345
370
  * ```ts
@@ -347,33 +372,36 @@ export const formatMaxLengthError = createTypeErrorFormatter((error) => `The val
347
372
  * const Length1String = length(1)(String);
348
373
  * ```
349
374
  *
350
- * @category String
351
- * @category Array
375
+ * @group String
376
+ * @group Array
352
377
  */
353
378
  export const length = (exact) => (parent) => brand(`Length${exact}`, parent, (value) => value.length === exact
354
379
  ? ok(value)
355
380
  : err({ type: "Length", value, exact }));
356
- export const formatLengthError = createTypeErrorFormatter((error) => `The value ${error.value} does not have the required length of ${error.exact}.`);
357
- /** @category String */
358
- export const NonEmptyString = minLength(1)(String);
359
- /** @category String */
360
- export const String100 = maxLength(100)(String);
361
- /** @category String */
362
- export const String1000 = maxLength(1000)(String);
363
- /** @category String */
364
- export const NonEmptyString100 = minLength(1)(String100);
365
- /** @category String */
366
- export const NonEmptyString1000 = minLength(1)(String1000);
367
- /** @category String */
368
- export const NonEmptyTrimmedString = minLength(1)(TrimmedString);
369
- /** @category String */
370
- export const TrimmedString100 = maxLength(100)(TrimmedString);
371
- /** @category String */
372
- export const TrimmedString1000 = maxLength(1000)(TrimmedString);
373
- /** @category String */
374
- export const NonEmptyTrimmedString100 = minLength(1)(TrimmedString100);
375
- /** @category String */
376
- export const NonEmptyTrimmedString1000 = minLength(1)(TrimmedString1000);
381
+ export const formatLengthError =
382
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} does not have the required length of ${error.exact}.`);
383
+ /** @group String */
384
+ export const NonEmptyString = /*#__PURE__*/ minLength(1)(String);
385
+ /** @group String */
386
+ export const String100 = /*#__PURE__*/ maxLength(100)(String);
387
+ /** @group String */
388
+ export const String1000 = /*#__PURE__*/ maxLength(1000)(String);
389
+ /** @group String */
390
+ export const NonEmptyString100 = /*#__PURE__*/ minLength(1)(String100);
391
+ /** @group String */
392
+ export const NonEmptyString1000 = /*#__PURE__*/ minLength(1)(String1000);
393
+ /** @group String */
394
+ export const NonEmptyTrimmedString = /*#__PURE__*/ minLength(1)(TrimmedString);
395
+ /** @group String */
396
+ export const TrimmedString100 = /*#__PURE__*/ maxLength(100)(TrimmedString);
397
+ /** @group String */
398
+ export const TrimmedString1000 = /*#__PURE__*/ maxLength(1000)(TrimmedString);
399
+ /** @group String */
400
+ export const NonEmptyTrimmedString100 =
401
+ /*#__PURE__*/ minLength(1)(TrimmedString100);
402
+ /** @group String */
403
+ export const NonEmptyTrimmedString1000 =
404
+ /*#__PURE__*/ minLength(1)(TrimmedString1000);
377
405
  /**
378
406
  * The mnemonic, also known as a "seed phrase," is a set of 12 words in a
379
407
  * specific order chosen from a predefined list (BIP39). It provides a
@@ -381,12 +409,13 @@ export const NonEmptyTrimmedString1000 = minLength(1)(TrimmedString1000);
381
409
  * safely on the user's device using cryptographically secure random number
382
410
  * generation, ensuring it remains private and unique.
383
411
  *
384
- * @category String
412
+ * @group String
385
413
  */
386
- export const Mnemonic = brand("Mnemonic", NonEmptyTrimmedString, (value) => bip39.validateMnemonic(value, wordlist)
414
+ export const Mnemonic = /*#__PURE__*/ brand("Mnemonic", NonEmptyTrimmedString, (value) => bip39.validateMnemonic(value, wordlist)
387
415
  ? ok(value)
388
416
  : err({ type: "Mnemonic", value }));
389
- export const formatMnemonicError = createTypeErrorFormatter((error) => `Invalid BIP39 mnemonic: ${error.value}.`);
417
+ export const formatMnemonicError =
418
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `Invalid BIP39 mnemonic: ${error.value}.`);
390
419
  /**
391
420
  * String matching a regular expression.
392
421
  *
@@ -396,7 +425,7 @@ export const formatMnemonicError = createTypeErrorFormatter((error) => `Invalid
396
425
  * const Alphanumeric = regex("Alphanumeric", /^[a-z0-9]+$/i)(String);
397
426
  * ```
398
427
  *
399
- * @category String
428
+ * @group String
400
429
  */
401
430
  export const regex = (name, pattern) => {
402
431
  // Clone the regex to avoid shared state.
@@ -410,7 +439,8 @@ export const regex = (name, pattern) => {
410
439
  : err({ type: "Regex", name, value, pattern });
411
440
  });
412
441
  };
413
- export const formatRegexError = createTypeErrorFormatter((error) => `The value ${error.value} does not match the pattern for ${error.name}: ${error.pattern}.`);
442
+ export const formatRegexError =
443
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} does not match the pattern for ${error.name}: ${error.pattern}.`);
414
444
  /**
415
445
  * URL-safe string.
416
446
  *
@@ -436,18 +466,18 @@ export const formatRegexError = createTypeErrorFormatter((error) => `The value $
436
466
  * }
437
467
  * ```
438
468
  *
439
- * @category String
469
+ * @group String
440
470
  */
441
- export const UrlSafeString = regex("UrlSafeString", /^[A-Za-z0-9_-]+$/)(String);
471
+ export const UrlSafeString = /*#__PURE__*/ regex("UrlSafeString", /^[A-Za-z0-9_-]+$/)(String);
442
472
  /**
443
473
  * Base64Url without padding.
444
474
  *
445
475
  * Encode with {@link uint8ArrayToBase64Url}, decode with
446
476
  * {@link base64UrlToUint8Array}.
447
477
  *
448
- * @category String
478
+ * @group String
449
479
  */
450
- export const Base64Url = brand("Base64Url", String, (value) => {
480
+ export const Base64Url = /*#__PURE__*/ brand("Base64Url", String, (value) => {
451
481
  // Round-trip validation ensures consistency across different base64url
452
482
  // implementations (Node.js Buffer, native browser API, manual fallback).
453
483
  // Only strings that decode and encode identically are accepted.
@@ -462,7 +492,8 @@ export const Base64Url = brand("Base64Url", String, (value) => {
462
492
  ? ok(value)
463
493
  : err({ type: "Base64Url", value });
464
494
  });
465
- export const formatBase64UrlError = createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Base64Url string.`);
495
+ export const formatBase64UrlError =
496
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Base64Url string.`);
466
497
  const base64UrlOptions = { alphabet: "base64url", omitPadding: true };
467
498
  /** Encodes a Uint8Array to a {@link Base64Url} string. */
468
499
  export const uint8ArrayToBase64Url = hasNodeBuffer
@@ -500,29 +531,30 @@ export const base64UrlToUint8Array = hasNodeBuffer
500
531
  return globalThis.Uint8Array.from(binaryString, (c) => c.charCodeAt(0));
501
532
  };
502
533
  /**
503
- * Simple alphanumeric string for naming in file systems, URLs, and identifiers.
534
+ * Alphanumeric string for naming in file systems, URLs, and identifiers.
504
535
  *
505
536
  * Uses the same safe alphabet as {@link UrlSafeString} (letters, digits, `-`,
506
- * `_`). See `UrlSafeString` for details.
537
+ * `_`).
507
538
  *
508
539
  * The string must be between 1 and 64 characters.
509
540
  *
510
541
  * ### Example
511
542
  *
512
543
  * ```ts
513
- * const result = SimpleName.from("data-report-123");
544
+ * const result = Name.from("data-report-123");
514
545
  * if (result.ok) {
515
- * console.log("Valid SimpleName string:", result.value);
546
+ * console.log("Valid Name string:", result.value);
516
547
  * } else {
517
- * console.error("Invalid SimpleName string:", result.error);
548
+ * console.error("Invalid Name string:", result.error);
518
549
  * }
519
550
  * ```
520
551
  *
521
- * @category String
552
+ * @group String
522
553
  */
523
- export const SimpleName = brand("SimpleName", UrlSafeString, (value) => value.length >= 1 && value.length <= 64
554
+ export const Name = /*#__PURE__*/ brand("Name", UrlSafeString, (value) => value.length >= 1 && value.length <= 64
524
555
  ? ok(value)
525
- : err({ type: "SimpleName", value }));
556
+ : err({ type: "Name", value }));
557
+ export const testName = /*#__PURE__*/ Name.orThrow("Name");
526
558
  /**
527
559
  * Trimmed string between 8 and 64 characters, branded as `SimplePassword`.
528
560
  *
@@ -545,9 +577,10 @@ export const SimpleName = brand("SimpleName", UrlSafeString, (value) => value.le
545
577
  * // |> brand("SimplePassword", %)
546
578
  * ```
547
579
  *
548
- * @category String
580
+ * @group String
549
581
  */
550
- export const SimplePassword = brand("SimplePassword", minLength(8)(maxLength(64)(TrimmedString)));
582
+ export const SimplePassword = /*#__PURE__*/ brand("SimplePassword",
583
+ /*#__PURE__*/ minLength(8)(/*#__PURE__*/ maxLength(64)(TrimmedString)));
551
584
  export const formatSimplePasswordError = (formatTypeError) => createTypeErrorFormatter((error) => `Invalid password: ${formatTypeError(error.parentError)}`);
552
585
  /**
553
586
  * Evolu Id: 16 bytes encoded as a 22‑character Base64Url string.
@@ -565,19 +598,19 @@ export const formatSimplePasswordError = (formatTypeError) => createTypeErrorFor
565
598
  * copied (logs, URLs, exports); only use it when you explicitly want insertion
566
599
  * locality for very large write‑heavy tables and accept timestamp exposure.
567
600
  *
568
- * ### Future
601
+ * ## Future
569
602
  *
570
603
  * A possible hybrid masked‑time approach (`timestamp ^ H(cluster_id, timestamp
571
604
  *
572
605
  * > > N)`) could provide locality without exposing raw creation time. See
573
606
  * > > https://brooker.co.za/blog/2025/10/22/uuidv7.html
574
607
  *
575
- * @category String
608
+ * @group String
576
609
  */
577
- export const Id = brand("Id", String, (value) => value.length === 22 && Base64Url.fromParent(value).ok
610
+ export const Id = /*#__PURE__*/ brand("Id", String, (value) => value.length === 22 && Base64Url.fromParent(value).ok
578
611
  ? ok(value)
579
612
  : err({ type: "Id", value }));
580
- export const formatIdError = createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Id.`);
613
+ export const formatIdError = /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Id.`);
581
614
  /**
582
615
  * Creates a random {@link Id}. This is the recommended default.
583
616
  *
@@ -626,7 +659,7 @@ export const createId = (deps) => {
626
659
  * external string from the generated {@link Id}. If you need to preserve the
627
660
  * original external ID, store it in a separate column.
628
661
  *
629
- * @category String
662
+ * @group String
630
663
  */
631
664
  export const createIdFromString = (value) => {
632
665
  const hash = sha256(utf8ToBytes(value));
@@ -661,7 +694,7 @@ export const createIdAsUuidv7 = (deps) => {
661
694
  id[5] = globalThis.Number(timestamp & 0xffn);
662
695
  id[6] = (id[6] & 0x0f) | 0x70;
663
696
  id[8] = (id[8] & 0x3f) | 0x80;
664
- return id;
697
+ return uint8ArrayToBase64Url(id);
665
698
  };
666
699
  /**
667
700
  * Creates a branded {@link Id} Type for a table's primary key.
@@ -676,7 +709,7 @@ export const createIdAsUuidv7 = (deps) => {
676
709
  * type TodoId = typeof TodoId.Type;
677
710
  * ```
678
711
  *
679
- * @category String
712
+ * @group String
680
713
  */
681
714
  export const id = (table) => {
682
715
  const fromUnknown = (value) => {
@@ -697,9 +730,11 @@ export const id = (table) => {
697
730
  table,
698
731
  };
699
732
  };
700
- export const formatTableIdError = createTypeErrorFormatter((error) => `Invalid Id for table ${error.table}: ${error.value}.`);
733
+ export const formatTableIdError =
734
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `Invalid Id for table ${error.table}: ${error.value}.`);
701
735
  /** Binary representation of an {@link Id}. */
702
- export const IdBytes = brand("IdBytes", length(16)(Uint8Array));
736
+ export const IdBytes = /*#__PURE__*/ brand("IdBytes",
737
+ /*#__PURE__*/ length(16)(Uint8Array));
703
738
  export const idBytesTypeValueLength = 16;
704
739
  export const idToIdBytes = (id) =>
705
740
  // Id is Base64Url (validated by Id.from), cast is safe
@@ -719,10 +754,11 @@ uint8ArrayToBase64Url(idBytes);
719
754
  * const errorResult = PositiveNumber.from(-5); // err
720
755
  * ```
721
756
  *
722
- * @category Number
757
+ * @group Number
723
758
  */
724
759
  export const positive = (parent) => brand("Positive", parent, (value) => value > 0 ? ok(value) : err({ type: "Positive", value }));
725
- export const formatPositiveError = createTypeErrorFormatter((error) => `The value ${error.value} must be positive (> 0).`);
760
+ export const formatPositiveError =
761
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be positive (> 0).`);
726
762
  /**
727
763
  * Negative number (< 0).
728
764
  *
@@ -732,10 +768,11 @@ export const formatPositiveError = createTypeErrorFormatter((error) => `The valu
732
768
  * const NegativeNumber = negative(Number);
733
769
  * ```
734
770
  *
735
- * @category Number
771
+ * @group Number
736
772
  */
737
773
  export const negative = (parent) => brand("Negative", parent, (value) => value < 0 ? ok(value) : err({ type: "Negative", value }));
738
- export const formatNegativeError = createTypeErrorFormatter((error) => `The value ${error.value} must be negative (< 0).`);
774
+ export const formatNegativeError =
775
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be negative (< 0).`);
739
776
  /**
740
777
  * Non-positive number (≤ 0).
741
778
  *
@@ -745,12 +782,13 @@ export const formatNegativeError = createTypeErrorFormatter((error) => `The valu
745
782
  * const NonPositiveNumber = nonPositive(Number);
746
783
  * ```
747
784
  *
748
- * @category Number
785
+ * @group Number
749
786
  */
750
787
  export const nonPositive = (parent) => brand("NonPositive", parent, (value) => value <= 0
751
788
  ? ok(value)
752
789
  : err({ type: "NonPositive", value }));
753
- export const formatNonPositiveError = createTypeErrorFormatter((error) => `The value ${error.value} must be non-positive (≤ 0).`);
790
+ export const formatNonPositiveError =
791
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be non-positive (≤ 0).`);
754
792
  /**
755
793
  * Non-negative number (≥ 0).
756
794
  *
@@ -760,133 +798,156 @@ export const formatNonPositiveError = createTypeErrorFormatter((error) => `The v
760
798
  * const NonNegativeNumber = nonNegative(Number);
761
799
  * ```
762
800
  *
763
- * @category Number
801
+ * @group Number
764
802
  */
765
803
  export const nonNegative = (parent) => brand("NonNegative", parent, (value) => value >= 0
766
804
  ? ok(value)
767
805
  : err({ type: "NonNegative", value }));
768
- export const formatNonNegativeError = createTypeErrorFormatter((error) => `The value ${error.value} must be non-negative (≥ 0).`);
806
+ export const formatNonNegativeError =
807
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be non-negative (≥ 0).`);
769
808
  /**
770
809
  * Non-negative number (≥ 0).
771
810
  *
772
- * @category Number
811
+ * @group Number
773
812
  */
774
- export const NonNegativeNumber = nonNegative(Number);
813
+ export const NonNegativeNumber = /*#__PURE__*/ nonNegative(Number);
775
814
  /**
776
815
  * Positive number (> 0).
777
816
  *
778
- * @category Number
817
+ * @group Number
779
818
  */
780
- export const PositiveNumber = positive(NonNegativeNumber);
819
+ export const PositiveNumber = /*#__PURE__*/ positive(NonNegativeNumber);
781
820
  /**
782
821
  * Non-positive number (≤ 0).
783
822
  *
784
- * @category Number
823
+ * @group Number
785
824
  */
786
- export const NonPositiveNumber = nonPositive(Number);
825
+ export const NonPositiveNumber = /*#__PURE__*/ nonPositive(Number);
787
826
  /**
788
827
  * Negative number (< 0).
789
828
  *
790
- * @category Number
829
+ * @group Number
791
830
  */
792
- export const NegativeNumber = negative(NonPositiveNumber);
831
+ export const NegativeNumber = /*#__PURE__*/ negative(NonPositiveNumber);
793
832
  /**
794
833
  * Integer within the safe range of JavaScript numbers.
795
834
  *
796
835
  * ### Example
797
836
  *
798
837
  * ```ts
799
- * const Int = int(Number);
838
+ * const Int = safeInt(Number);
800
839
  * ```
801
840
  *
802
- * @category Number
841
+ * Note: This helper was previously named `int`. A Next.js regression produced
842
+ * runtime `int is not defined`, so we keep the implementation under the
843
+ * `safeInt` alias.
844
+ *
845
+ * @group Number
803
846
  */
804
- export const int = (parent) => brand("Int", parent, (value) => globalThis.Number.isSafeInteger(value)
847
+ const safeInt = (parent) => brand("Int", parent, (value) => globalThis.Number.isSafeInteger(value)
805
848
  ? ok(value)
806
849
  : err({ type: "Int", value }));
807
- export const formatIntError = createTypeErrorFormatter((error) => `The value ${error.value} must be an integer.`);
850
+ export const formatIntError = /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be an integer.`);
808
851
  /**
809
852
  * Integer within the safe range of JavaScript numbers.
810
853
  *
811
- * @category Number
854
+ * @group Number
812
855
  */
813
- export const Int = int(Number);
856
+ export const Int = /*#__PURE__*/ safeInt(Number);
814
857
  /**
815
858
  * Non-negative integer (≥ 0).
816
859
  *
817
- * @category Number
860
+ * @group Number
818
861
  */
819
- export const NonNegativeInt = nonNegative(Int);
862
+ export const NonNegativeInt = /*#__PURE__*/ nonNegative(Int);
863
+ /** Minimum {@link NonNegativeInt} value (0). */
864
+ export const zeroNonNegativeInt = /*#__PURE__*/ NonNegativeInt.orThrow(0);
820
865
  /**
821
866
  * Positive integer (> 0).
822
867
  *
823
- * @category Number
868
+ * @group Number
824
869
  */
825
- export const PositiveInt = positive(NonNegativeInt);
826
- /** Maximum safe positive integer value for practically infinite operations. */
827
- export const maxPositiveInt = PositiveInt.orThrow(globalThis.Number.MAX_SAFE_INTEGER);
870
+ export const PositiveInt = /*#__PURE__*/ positive(NonNegativeInt);
871
+ /** {@link PositiveInt} value 1. */
872
+ export const onePositiveInt = /*#__PURE__*/ PositiveInt.orThrow(1);
873
+ /** Maximum {@link PositiveInt} value (MAX_SAFE_INTEGER). */
874
+ export const maxPositiveInt = /*#__PURE__*/ PositiveInt.orThrow(globalThis.Number.MAX_SAFE_INTEGER);
828
875
  /**
829
876
  * Non-positive integer (≤ 0).
830
877
  *
831
- * @category Number
878
+ * @group Number
832
879
  */
833
- export const NonPositiveInt = nonPositive(Int);
880
+ export const NonPositiveInt = /*#__PURE__*/ nonPositive(Int);
834
881
  /**
835
882
  * Negative integer (< 0).
836
883
  *
837
- * @category Number
884
+ * @group Number
838
885
  */
839
- export const NegativeInt = negative(NonPositiveInt);
886
+ export const NegativeInt = /*#__PURE__*/ negative(NonPositiveInt);
840
887
  /**
841
888
  * Number greater than a specified value.
842
889
  *
843
- * @category Number
890
+ * Use numeric literal, not expression. See {@link BrandFactory}.
891
+ *
892
+ * @group Number
844
893
  */
845
894
  export const greaterThan = (min) => (parent) => brand(`GreaterThan${min}`, parent, (value) => value > min ? ok(value) : err({ type: "GreaterThan", value, min }));
846
- export const formatGreaterThanError = createTypeErrorFormatter((error) => `The value ${error.value} is not > ${error.min}.`);
895
+ export const formatGreaterThanError =
896
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not > ${error.min}.`);
847
897
  /**
848
898
  * Number less than a specified value.
849
899
  *
850
- * @category Number
900
+ * Use numeric literal, not expression. See {@link BrandFactory}.
901
+ *
902
+ * @group Number
851
903
  */
852
904
  export const lessThan = (max) => (parent) => brand(`LessThan${max}`, parent, (value) => value < max ? ok(value) : err({ type: "LessThan", value, max }));
853
- export const formatLessThanError = createTypeErrorFormatter((error) => `The value ${error.value} is not < ${error.max}.`);
905
+ export const formatLessThanError =
906
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not < ${error.max}.`);
854
907
  /**
855
908
  * Number ≥ a specified value.
856
909
  *
857
- * @category Number
910
+ * Use numeric literal, not expression. See {@link BrandFactory}.
911
+ *
912
+ * @group Number
858
913
  */
859
914
  export const greaterThanOrEqualTo = (min) => (parent) => brand(`GreaterThanOrEqualTo${min}`, parent, (value) => value >= min
860
915
  ? ok(value)
861
916
  : err({ type: "GreaterThanOrEqualTo", value, min }));
862
- export const formatGreaterThanOrEqualToError = createTypeErrorFormatter((error) => `The value ${error.value} is not >= ${error.min}.`);
917
+ export const formatGreaterThanOrEqualToError =
918
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not >= ${error.min}.`);
863
919
  /**
864
920
  * Number ≤ a specified value.
865
921
  *
866
- * @category Number
922
+ * Use numeric literal, not expression. See {@link BrandFactory}.
923
+ *
924
+ * @group Number
867
925
  */
868
926
  export const lessThanOrEqualTo = (max) => (parent) => brand(`LessThanOrEqualTo${max}`, parent, (value) => value <= max ? ok(value) : err({ type: "LessThanOrEqualTo", value, max }));
869
- export const formatLessThanOrEqualToError = createTypeErrorFormatter((error) => `The value ${error.value} is not <= ${error.max}.`);
927
+ export const formatLessThanOrEqualToError =
928
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not <= ${error.max}.`);
870
929
  /**
871
930
  * Number that is not NaN.
872
931
  *
873
- * @category Number
932
+ * @group Number
874
933
  */
875
934
  export const nonNaN = (parent) => brand("NonNaN", parent, (value) => !globalThis.Number.isNaN(value)
876
935
  ? ok(value)
877
936
  : err({ type: "NonNaN", value }));
878
- export const formatNonNaNError = createTypeErrorFormatter(() => `The value must not be NaN.`);
879
- /** @category Number */
880
- export const NonNaNNumber = nonNaN(Number);
937
+ export const formatNonNaNError =
938
+ /*#__PURE__*/ createTypeErrorFormatter(() => `The value must not be NaN.`);
939
+ /** @group Number */
940
+ export const NonNaNNumber = /*#__PURE__*/ nonNaN(Number);
881
941
  /**
882
942
  * Finite number.
883
943
  *
884
- * @category Number
944
+ * @group Number
885
945
  */
886
946
  export const finite = (parent) => brand("Finite", parent, (value) => globalThis.Number.isFinite(value)
887
947
  ? ok(value)
888
948
  : err({ type: "Finite", value }));
889
- export const formatFiniteError = createTypeErrorFormatter((error) => `The value ${error.value} must be finite.`);
949
+ export const formatFiniteError =
950
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be finite.`);
890
951
  /**
891
952
  * Finite number.
892
953
  *
@@ -898,21 +959,26 @@ export const formatFiniteError = createTypeErrorFormatter((error) => `The value
898
959
  * finite (e.g., `Infinity`, `-Infinity`, or `NaN`). Using `FiniteNumber` helps
899
960
  * prevent these unexpected behaviors when working with JSON serialization.
900
961
  *
901
- * @category Number
962
+ * @group Number
902
963
  */
903
- export const FiniteNumber = finite(Number);
964
+ export const FiniteNumber = /*#__PURE__*/ finite(Number);
904
965
  /**
905
966
  * Number that is a multiple of a divisor.
906
967
  *
907
- * @category Number
968
+ * Use numeric literal, not expression. See {@link BrandFactory}.
969
+ *
970
+ * @group Number
908
971
  */
909
972
  export const multipleOf = (divisor) => (parent) => brand(`MultipleOf${divisor}`, parent, (value) => value % divisor === 0
910
973
  ? ok(value)
911
974
  : err({ type: "MultipleOf", value, divisor }));
912
- export const formatMultipleOfError = createTypeErrorFormatter((error) => `The value ${error.value} is not a multiple of ${error.divisor}.`);
975
+ export const formatMultipleOfError =
976
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a multiple of ${error.divisor}.`);
913
977
  /**
914
978
  * Number within a range, inclusive.
915
979
  *
980
+ * Use numeric literal, not expression. See {@link BrandFactory}.
981
+ *
916
982
  * ### Example
917
983
  *
918
984
  * ```ts
@@ -921,12 +987,13 @@ export const formatMultipleOfError = createTypeErrorFormatter((error) => `The va
921
987
  * const errorResult = Between1And10.from(11); // err
922
988
  * ```
923
989
  *
924
- * @category Number
990
+ * @group Number
925
991
  */
926
992
  export const between = (min, max) => (parent) => brand(`Between${min}-${max}`, parent, (value) => value >= min && value <= max
927
993
  ? ok(value)
928
994
  : err({ type: "Between", value, min, max }));
929
- export const formatBetweenError = createTypeErrorFormatter((error) => `The value ${error.value} is not between ${error.min} and ${error.max}, inclusive.`);
995
+ export const formatBetweenError =
996
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not between ${error.min} and ${error.max}, inclusive.`);
930
997
  /**
931
998
  * Literal {@link Type}.
932
999
  *
@@ -942,7 +1009,7 @@ export const formatBetweenError = createTypeErrorFormatter((error) => `The value
942
1009
  *
943
1010
  * TODO: Add JsonValue
944
1011
  *
945
- * @category Base Factories
1012
+ * @group Base factories
946
1013
  */
947
1014
  export const literal = (expected) => {
948
1015
  const fromUnknown = (value) => value === expected
@@ -956,11 +1023,12 @@ export const literal = (expected) => {
956
1023
  expected,
957
1024
  };
958
1025
  };
959
- export const formatLiteralError = createTypeErrorFormatter((error) => `The value ${error.value} is not strictly equal to the expected literal: ${globalThis.String(error.expected)}.`);
1026
+ export const formatLiteralError =
1027
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not strictly equal to the expected literal: ${globalThis.String(error.expected)}.`);
960
1028
  /**
961
1029
  * Array of a specific {@link Type}.
962
1030
  *
963
- * Usage:
1031
+ * ### Example
964
1032
  *
965
1033
  * ```ts
966
1034
  * const NumberArray = array(Number);
@@ -969,8 +1037,8 @@ export const formatLiteralError = createTypeErrorFormatter((error) => `The value
969
1037
  * const result2 = NumberArray.from(["a", "b"]); // err(...)
970
1038
  * ```
971
1039
  *
972
- * @category Base Factories
973
- * @category Array
1040
+ * @group Base factories
1041
+ * @group Array
974
1042
  */
975
1043
  export const array = (element) => {
976
1044
  const fromUnknown = (value) => {
@@ -1043,7 +1111,7 @@ export const formatArrayError = (formatTypeError) => createTypeErrorFormatter((e
1043
1111
  * const result2 = NumberSet.from(new Set(["a", "b"])); // err(...)
1044
1112
  * ```
1045
1113
  *
1046
- * @category Base Factories
1114
+ * @group Base factories
1047
1115
  */
1048
1116
  export const set = (element) => {
1049
1117
  const fromUnknown = (value) => {
@@ -1128,8 +1196,8 @@ export const formatSetError = (formatTypeError) => createTypeErrorFormatter((err
1128
1196
  * StringToNumberRecord.from({ a: "x", b: 2 });
1129
1197
  * ```
1130
1198
  *
1131
- * @category Base Factories
1132
- * @category Object
1199
+ * @group Base factories
1200
+ * @group Object
1133
1201
  */
1134
1202
  export const record = (keyType, valueType) => {
1135
1203
  const fromUnknown = (value) => {
@@ -1375,6 +1443,9 @@ export const formatObjectWithRecordError = (formatTypeError) => createTypeErrorF
1375
1443
  return `Invalid value at index key ${error.reason.key}: ${formatTypeError(error.reason.error)}`;
1376
1444
  }
1377
1445
  });
1446
+ export function typed(tag, props) {
1447
+ return object({ type: literal(tag), ...props });
1448
+ }
1378
1449
  export function union(...args) {
1379
1450
  /**
1380
1451
  * Good First Issue:
@@ -1420,6 +1491,75 @@ export const formatUnionError = (formatTypeError) => createTypeErrorFormatter((e
1420
1491
  return `Value ${error.value} does not match any member of the union.\nErrors:\n${formattedErrors}`;
1421
1492
  });
1422
1493
  export const isUnionType = (t) => t.name === "Union" && Array.isArray(t.members);
1494
+ /**
1495
+ * Creates a {@link Type} for {@link Result} values.
1496
+ *
1497
+ * Use for validating serialized Results from storage, APIs, or message passing.
1498
+ *
1499
+ * ### Example
1500
+ *
1501
+ * ```ts
1502
+ * const SyncResponse = result(
1503
+ * object({ timestamp: NonNegativeInt }),
1504
+ * typed("SyncError", { message: String }),
1505
+ * );
1506
+ *
1507
+ * // Validate response from worker or API
1508
+ * const validated = SyncResponse.from(JSON.parse(message));
1509
+ * if (!validated.ok) return validated; // validation error
1510
+ * // validated.value is Result<{ timestamp }, SyncError>
1511
+ * ```
1512
+ *
1513
+ * @group Composite factories
1514
+ */
1515
+ export const result = (okType, errType) => union(object({ ok: literal(true), value: okType }), object({ ok: literal(false), error: errType }));
1516
+ /**
1517
+ * A {@link result} type for `Result<unknown, unknown>`.
1518
+ *
1519
+ * Useful for serializing Results where the value and error types are unknown.
1520
+ *
1521
+ * @group Composite factories
1522
+ */
1523
+ export const UnknownResult = /*#__PURE__*/ result(Unknown, Unknown);
1524
+ /**
1525
+ * Creates a {@link Type} for {@link NextResult} with three outcomes.
1526
+ *
1527
+ * Validates results where the producer responds with:
1528
+ *
1529
+ * - `Ok<A>` — produced a value
1530
+ * - `Err<Done<D>>` — completed normally with a done value
1531
+ * - `Err<E>` — failed with an error
1532
+ *
1533
+ * ### Example
1534
+ *
1535
+ * ```ts
1536
+ * const MyNextResult = nextResult(Item, MyError, Summary);
1537
+ *
1538
+ * const validated = MyNextResult.fromUnknown(data);
1539
+ * if (!validated.ok) return validated;
1540
+ *
1541
+ * const result = validated.value;
1542
+ * if (result.ok) {
1543
+ * console.log(result.value);
1544
+ * } else if (result.error.type === "Done") {
1545
+ * console.log("Done:", result.error.done);
1546
+ * } else {
1547
+ * console.error(result.error);
1548
+ * }
1549
+ * ```
1550
+ *
1551
+ * @group Composite factories
1552
+ */
1553
+ export const nextResult = (valueType, errorType, doneType) => result(valueType, union(errorType, typed("Done", { done: doneType })));
1554
+ /**
1555
+ * A {@link nextResult} type for `NextResult<unknown, unknown, unknown>`.
1556
+ *
1557
+ * Useful for checking if a value is a {@link NextResult} via
1558
+ * `UnknownNextResult.is(value)`.
1559
+ *
1560
+ * @group Composite factories
1561
+ */
1562
+ export const UnknownNextResult = /*#__PURE__*/ nextResult(Unknown, Unknown, Unknown);
1423
1563
  /**
1424
1564
  * Recursive {@link Type}.
1425
1565
  *
@@ -1453,7 +1593,7 @@ export const isUnionType = (t) => t.name === "Union" && Array.isArray(t.members)
1453
1593
  * );
1454
1594
  * ```
1455
1595
  *
1456
- * @category Base Factories
1596
+ * @group Base factories
1457
1597
  */
1458
1598
  export const recursive = (create) => {
1459
1599
  let type;
@@ -1494,7 +1634,7 @@ export const recursive = (create) => {
1494
1634
  * NullOrString.from(42); // err(...)
1495
1635
  * ```
1496
1636
  *
1497
- * @category Base Factories
1637
+ * @group Base factories
1498
1638
  */
1499
1639
  export const nullOr = (type) => union(Null, type);
1500
1640
  /**
@@ -1509,7 +1649,7 @@ export const nullOr = (type) => union(Null, type);
1509
1649
  * UndefinedOrString.from(42); // err(...)
1510
1650
  * ```
1511
1651
  *
1512
- * @category Base Factories
1652
+ * @group Base factories
1513
1653
  */
1514
1654
  export const undefinedOr = (type) => union(Undefined, type);
1515
1655
  /**
@@ -1528,7 +1668,7 @@ export const undefinedOr = (type) => union(Undefined, type);
1528
1668
  * NullishOrString.from(42); // err(...)
1529
1669
  * ```
1530
1670
  *
1531
- * @category Base Factories
1671
+ * @group Base factories
1532
1672
  */
1533
1673
  export const nullishOr = (type) => union(Undefined, Null, type);
1534
1674
  /**
@@ -1545,7 +1685,7 @@ export const nullishOr = (type) => union(Undefined, Null, type);
1545
1685
  * const error = NameAndAge.from(["Alice", -10]); // err
1546
1686
  * ```
1547
1687
  *
1548
- * @category Base Factories
1688
+ * @group Base factories
1549
1689
  */
1550
1690
  export const tuple = (...elements) => {
1551
1691
  const fromUnknown = (value) => {
@@ -1631,42 +1771,44 @@ export const formatTupleError = (formatTypeError) => createTypeErrorFormatter((e
1631
1771
  *
1632
1772
  * https://www.sqlite.org/c3ref/int64.html
1633
1773
  *
1634
- * @category Number
1774
+ * @group Number
1635
1775
  */
1636
- export const Int64 = brand("Int64", BigInt, (value) => value >= -9223372036854775808n && value <= 9223372036854775807n
1776
+ export const Int64 = /*#__PURE__*/ brand("Int64", BigInt, (value) => value >= -9223372036854775808n && value <= 9223372036854775807n
1637
1777
  ? ok(value)
1638
1778
  : err({ type: "Int64", value }));
1639
- export const formatInt64Error = createTypeErrorFormatter((error) => `The value ${error.value} is not a valid 64-bit signed integer (Int64).`);
1779
+ export const formatInt64Error =
1780
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid 64-bit signed integer (Int64).`);
1640
1781
  /**
1641
1782
  * Stringified {@link Int64}.
1642
1783
  *
1643
- * @category String
1784
+ * @group String
1644
1785
  */
1645
- export const Int64String = brand("Int64", NonEmptyTrimmedString, (value) => trySync(() => {
1786
+ export const Int64String = /*#__PURE__*/ brand("Int64", NonEmptyTrimmedString, (value) => trySync(() => {
1646
1787
  const maybeInt = globalThis.BigInt(value);
1647
1788
  Int64.orThrow(maybeInt);
1648
1789
  return value;
1649
1790
  }, () => ({ type: "Int64String", value })));
1650
- export const formatInt64StringError = createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Int64 string.`);
1791
+ export const formatInt64StringError =
1792
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Int64 string.`);
1651
1793
  /**
1652
1794
  * JSON-compatible value: string, {@link FiniteNumber}, boolean, null,
1653
1795
  * {@link JsonArray}, or {@link JsonObject}.
1654
1796
  *
1655
- * @category Base Types
1797
+ * @group Base Types
1656
1798
  */
1657
- export const JsonValue = recursive(() => union(String, FiniteNumber, Boolean, Null, JsonArray, JsonObject));
1799
+ export const JsonValue = /*#__PURE__*/ recursive(() => union(String, FiniteNumber, Boolean, Null, JsonArray, JsonObject));
1658
1800
  /**
1659
1801
  * JSON-compatible array of {@link JsonValue} elements.
1660
1802
  *
1661
- * @category Array
1803
+ * @group Array
1662
1804
  */
1663
- export const JsonArray = array(JsonValue);
1805
+ export const JsonArray = /*#__PURE__*/ array(JsonValue);
1664
1806
  /**
1665
1807
  * JSON-compatible object with string keys and {@link JsonValue} values.
1666
1808
  *
1667
- * @category Object
1809
+ * @group Object
1668
1810
  */
1669
- export const JsonObject = record(String, JsonValue);
1811
+ export const JsonObject = /*#__PURE__*/ record(String, JsonValue);
1670
1812
  export const parseJson = (value) => trySync(() => JSON.parse(value), (error) => ({
1671
1813
  type: `Json`,
1672
1814
  value,
@@ -1682,15 +1824,16 @@ export const parseJson = (value) => trySync(() => JSON.parse(value), (error) =>
1682
1824
  * const error = Json.from("invalid json"); // err
1683
1825
  * ```
1684
1826
  *
1685
- * @category String
1827
+ * @group String
1686
1828
  */
1687
- export const Json = brand("Json", String, (value) => {
1829
+ export const Json = /*#__PURE__*/ brand("Json", String, (value) => {
1688
1830
  const result = parseJson(value);
1689
1831
  if (!result.ok)
1690
1832
  return result;
1691
1833
  return ok(value);
1692
1834
  });
1693
- export const formatJsonError = createTypeErrorFormatter((error) => `Invalid JSON: ${error.value}. Error: ${error.message}`);
1835
+ export const formatJsonError =
1836
+ /*#__PURE__*/ createTypeErrorFormatter((error) => `Invalid JSON: ${error.value}. Error: ${error.message}`);
1694
1837
  export const jsonValueToJson = (value) => JSON.stringify(value);
1695
1838
  export const jsonToJsonValue = (value) => JSON.parse(value);
1696
1839
  /**
@@ -1713,7 +1856,7 @@ export const jsonToJsonValue = (value) => JSON.parse(value);
1713
1856
  * name: NonEmptyString100,
1714
1857
  * age: FiniteNumber,
1715
1858
  * });
1716
- * type Person = typeof Person.Type;
1859
+ * interface Person extends InferType<typeof Person> {}
1717
1860
  *
1718
1861
  * const [PersonJson, personToPersonJson, personJsonToPerson] = json(
1719
1862
  * Person,
@@ -1738,11 +1881,7 @@ export const json = (type, name) => {
1738
1881
  return validationResult;
1739
1882
  return ok(value);
1740
1883
  });
1741
- return [
1742
- BrandedJsonType,
1743
- jsonValueToJson,
1744
- jsonToJsonValue,
1745
- ];
1884
+ return [BrandedJsonType, jsonValueToJson, jsonToJsonValue];
1746
1885
  };
1747
1886
  /**
1748
1887
  * Optional {@link Type}.
@@ -1799,7 +1938,7 @@ export const isOptionalType = (x) => typeof x === "object" && x != null && "name
1799
1938
  * PartialUser.from({ age: -5 });
1800
1939
  * ```
1801
1940
  *
1802
- * @category Object
1941
+ * @group Object
1803
1942
  */
1804
1943
  export const partial = (props) => {
1805
1944
  const optionalProps = {};
@@ -1816,7 +1955,7 @@ export const partial = (props) => {
1816
1955
  * entirely, or set it to `null`, or set it to the non-null member of the
1817
1956
  * union.
1818
1957
  *
1819
- * @category Object
1958
+ * @group Object
1820
1959
  */
1821
1960
  export const nullableToOptional = (props) => {
1822
1961
  const transformedProps = {};
@@ -1836,9 +1975,9 @@ export const nullableToOptional = (props) => {
1836
1975
  /**
1837
1976
  * Create a new `object` {@link Type} by omitting some keys.
1838
1977
  *
1839
- * @category Object
1978
+ * @group Object
1840
1979
  */
1841
- export function omit(objectType, ...keys) {
1980
+ export const omit = (objectType, ...keys) => {
1842
1981
  const newProps = {};
1843
1982
  for (const key in objectType.props) {
1844
1983
  if (!keys.includes(key)) {
@@ -1847,18 +1986,7 @@ export function omit(objectType, ...keys) {
1847
1986
  }
1848
1987
  }
1849
1988
  return object(newProps);
1850
- }
1851
- export const maxMutationSize = 655360;
1852
- /**
1853
- * Evolu has to limit the maximum mutation size. Otherwise, sync couldn't use
1854
- * the `maxProtocolMessageRangesSize`. The max size is 640KB in bytes, measured
1855
- * via MessagePack. Evolu Protocol DbChange will be smaller thanks to various
1856
- * optimizations.
1857
- */
1858
- export const validMutationSize = (type) => brand("ValidMutationSize", type, (value) => pack(value).byteLength <= maxMutationSize
1859
- ? ok(value)
1860
- : err({ type: "ValidMutationSize", value }));
1861
- export const formatValidMutationSizeError = createTypeErrorFormatter((error) => `The mutation size exceeds the maximum limit of ${maxMutationSize} bytes. The provided mutation has a size of ${pack(error.value).byteLength} bytes.`);
1989
+ };
1862
1990
  /**
1863
1991
  * Formats Evolu Type errors into user-friendly messages.
1864
1992
  *
@@ -1937,7 +2065,7 @@ export const formatValidMutationSizeError = createTypeErrorFormatter((error) =>
1937
2065
  * };
1938
2066
  * ```
1939
2067
  *
1940
- * @category Utilities
2068
+ * @group Utilities
1941
2069
  */
1942
2070
  export const createFormatTypeError = (extraFormatter) => {
1943
2071
  const formatTypeError = (error) => {
@@ -2020,8 +2148,6 @@ export const createFormatTypeError = (extraFormatter) => {
2020
2148
  return formatInt64StringError(error);
2021
2149
  case "Json":
2022
2150
  return formatJsonError(error);
2023
- case "ValidMutationSize":
2024
- return formatValidMutationSizeError(error);
2025
2151
  // Composite Types
2026
2152
  case "SimplePassword":
2027
2153
  return formatSimplePasswordError(formatTypeError)(error);
@@ -2052,82 +2178,78 @@ export const createFormatTypeError = (extraFormatter) => {
2052
2178
  * Converts an Evolu {@link TypeError} to Standard Schema V1 issues format.
2053
2179
  *
2054
2180
  * This function recursively converts Evolu's typed errors into the Standard
2055
- * Schema issue format with proper path tracking for nested structures.
2181
+ * Schema issue format with proper path tracking for nested structures. The
2182
+ * `message` field contains the JSON-serialized typed error, which users can
2183
+ * deserialize and format using appropriate {@link TypeErrorFormatter}s.
2056
2184
  *
2057
- * @category Utilities
2185
+ * @group Utilities
2058
2186
  */
2059
- export const typeErrorToStandardSchemaIssues = (error, formatTypeError, path = []) => {
2187
+ export const typeErrorToStandardSchemaIssues = (error, path = []) => {
2060
2188
  if (error.type === "Array") {
2061
2189
  const arrayError = error;
2062
2190
  if (arrayError.reason.kind === "NotArray") {
2063
- return [{ message: formatTypeError(error), path }];
2191
+ return [{ message: JSON.stringify(error), path }];
2064
2192
  }
2065
- return typeErrorToStandardSchemaIssues(arrayError.reason.error, formatTypeError, [...path, arrayError.reason.index]);
2193
+ return typeErrorToStandardSchemaIssues(arrayError.reason.error, [...path, arrayError.reason.index]);
2066
2194
  }
2067
2195
  if (error.type === "Set") {
2068
2196
  const setError = error;
2069
2197
  if (setError.reason.kind === "NotSet") {
2070
- return [{ message: formatTypeError(error), path }];
2198
+ return [{ message: JSON.stringify(error), path }];
2071
2199
  }
2072
- return typeErrorToStandardSchemaIssues(setError.reason.error, formatTypeError, [...path, setError.reason.index]);
2200
+ return typeErrorToStandardSchemaIssues(setError.reason.error, [...path, setError.reason.index]);
2073
2201
  }
2074
2202
  if (error.type === "Object") {
2075
2203
  const objectError = error;
2076
2204
  if (objectError.reason.kind === "NotObject" ||
2077
2205
  objectError.reason.kind === "ExtraKeys") {
2078
- return [{ message: formatTypeError(error), path }];
2206
+ return [{ message: JSON.stringify(error), path }];
2079
2207
  }
2080
2208
  const issues = [];
2081
2209
  for (const [key, propError] of Object.entries(objectError.reason.errors)) {
2082
- issues.push(...typeErrorToStandardSchemaIssues(propError, formatTypeError, [...path, key]));
2210
+ issues.push(...typeErrorToStandardSchemaIssues(propError, [...path, key]));
2083
2211
  }
2084
2212
  return issues;
2085
2213
  }
2086
2214
  if (error.type === "ObjectWithRecord") {
2087
2215
  const objectWithRecordError = error;
2088
2216
  if (objectWithRecordError.reason.kind === "NotObject") {
2089
- return [{ message: formatTypeError(error), path }];
2217
+ return [{ message: JSON.stringify(error), path }];
2090
2218
  }
2091
2219
  if (objectWithRecordError.reason.kind === "IndexKey" ||
2092
2220
  objectWithRecordError.reason.kind === "IndexValue") {
2093
- return typeErrorToStandardSchemaIssues(objectWithRecordError.reason.error, formatTypeError, [...path, objectWithRecordError.reason.key]);
2221
+ return typeErrorToStandardSchemaIssues(objectWithRecordError.reason.error, [...path, objectWithRecordError.reason.key]);
2094
2222
  }
2095
2223
  const issues = [];
2096
2224
  for (const [key, propError] of Object.entries(objectWithRecordError.reason.errors)) {
2097
- issues.push(...typeErrorToStandardSchemaIssues(propError, formatTypeError, [...path, key]));
2225
+ issues.push(...typeErrorToStandardSchemaIssues(propError, [...path, key]));
2098
2226
  }
2099
2227
  return issues;
2100
2228
  }
2101
2229
  if (error.type === "Record") {
2102
2230
  const recordError = error;
2103
2231
  if (recordError.reason.kind === "NotRecord") {
2104
- return [{ message: formatTypeError(error), path }];
2232
+ return [{ message: JSON.stringify(error), path }];
2105
2233
  }
2106
- return typeErrorToStandardSchemaIssues(recordError.reason.error, formatTypeError, [...path, recordError.reason.key]);
2234
+ return typeErrorToStandardSchemaIssues(recordError.reason.error, [...path, recordError.reason.key]);
2107
2235
  }
2108
2236
  if (error.type === "Tuple") {
2109
2237
  const tupleError = error;
2110
2238
  if (tupleError.reason.kind === "InvalidLength") {
2111
- return [{ message: formatTypeError(error), path }];
2239
+ return [{ message: JSON.stringify(error), path }];
2112
2240
  }
2113
- return typeErrorToStandardSchemaIssues(tupleError.reason.error, formatTypeError, [...path, tupleError.reason.index]);
2241
+ return typeErrorToStandardSchemaIssues(tupleError.reason.error, [...path, tupleError.reason.index]);
2114
2242
  }
2115
2243
  if (error.type === "Union") {
2116
2244
  const unionError = error;
2117
- return unionError.errors.flatMap((err) => typeErrorToStandardSchemaIssues(err, formatTypeError, path));
2245
+ return unionError.errors.flatMap((err) => typeErrorToStandardSchemaIssues(err, path));
2118
2246
  }
2119
2247
  if (error.type === "Brand") {
2120
2248
  const brandError = error;
2121
2249
  if ("parentError" in brandError) {
2122
- return typeErrorToStandardSchemaIssues(brandError.parentError, formatTypeError, path);
2250
+ return typeErrorToStandardSchemaIssues(brandError.parentError, path);
2123
2251
  }
2124
- return [{ message: formatTypeError(error), path }];
2252
+ return [{ message: JSON.stringify(error), path }];
2125
2253
  }
2126
- return [{ message: formatTypeError(error), path }];
2254
+ return [{ message: JSON.stringify(error), path }];
2127
2255
  };
2128
- /**
2129
- * Shared formatter cache for Standard Schema integration - avoids circular
2130
- * dependency by lazily creating the formatter on first use rather than during
2131
- * module initialization.
2132
- */
2133
- let cachedStandardSchemaFormatTypeError;