@evolu/common 8.8.0 → 8.10.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 (242) hide show
  1. package/dist/src/Assert.d.ts +21 -1
  2. package/dist/src/Assert.d.ts.map +1 -1
  3. package/dist/src/Assert.js +31 -27
  4. package/dist/src/Bytes.d.ts +647 -0
  5. package/dist/src/Bytes.d.ts.map +1 -0
  6. package/dist/src/{Binary.js → Bytes.js} +266 -16
  7. package/dist/src/Config.d.ts +142 -0
  8. package/dist/src/Config.d.ts.map +1 -0
  9. package/dist/src/Config.js +181 -0
  10. package/dist/src/Fs.d.ts +302 -0
  11. package/dist/src/Fs.d.ts.map +1 -0
  12. package/dist/src/Fs.js +111 -0
  13. package/dist/src/Number.d.ts +50 -7
  14. package/dist/src/Number.d.ts.map +1 -1
  15. package/dist/src/Number.js +47 -8
  16. package/dist/src/Object.d.ts +32 -0
  17. package/dist/src/Object.d.ts.map +1 -1
  18. package/dist/src/Object.js +41 -0
  19. package/dist/src/Polyfills.d.ts +6 -0
  20. package/dist/src/Polyfills.d.ts.map +1 -1
  21. package/dist/src/Polyfills.js +6 -0
  22. package/dist/src/Sqlite.js +1 -1
  23. package/dist/src/Time.d.ts +74 -12
  24. package/dist/src/Time.d.ts.map +1 -1
  25. package/dist/src/Time.js +40 -2
  26. package/dist/src/Type.d.ts +1451 -79
  27. package/dist/src/Type.d.ts.map +1 -1
  28. package/dist/src/Type.js +1303 -96
  29. package/dist/src/index.d.ts +3 -1
  30. package/dist/src/index.d.ts.map +1 -1
  31. package/dist/src/index.js +3 -1
  32. package/dist/src/intl/_en.d.ts +24 -1
  33. package/dist/src/intl/_en.d.ts.map +1 -1
  34. package/dist/src/intl/_en.js +20 -0
  35. package/dist/src/intl/ar.d.ts +24 -1
  36. package/dist/src/intl/ar.d.ts.map +1 -1
  37. package/dist/src/intl/ar.js +20 -0
  38. package/dist/src/intl/bn.d.ts +24 -1
  39. package/dist/src/intl/bn.d.ts.map +1 -1
  40. package/dist/src/intl/bn.js +20 -0
  41. package/dist/src/intl/ca.d.ts +24 -1
  42. package/dist/src/intl/ca.d.ts.map +1 -1
  43. package/dist/src/intl/ca.js +20 -0
  44. package/dist/src/intl/cs.d.ts +24 -1
  45. package/dist/src/intl/cs.d.ts.map +1 -1
  46. package/dist/src/intl/cs.js +20 -0
  47. package/dist/src/intl/da.d.ts +24 -1
  48. package/dist/src/intl/da.d.ts.map +1 -1
  49. package/dist/src/intl/da.js +20 -0
  50. package/dist/src/intl/de.d.ts +24 -1
  51. package/dist/src/intl/de.d.ts.map +1 -1
  52. package/dist/src/intl/de.js +20 -0
  53. package/dist/src/intl/el.d.ts +24 -1
  54. package/dist/src/intl/el.d.ts.map +1 -1
  55. package/dist/src/intl/el.js +20 -0
  56. package/dist/src/intl/es.d.ts +24 -1
  57. package/dist/src/intl/es.d.ts.map +1 -1
  58. package/dist/src/intl/es.js +20 -0
  59. package/dist/src/intl/fa.d.ts +24 -1
  60. package/dist/src/intl/fa.d.ts.map +1 -1
  61. package/dist/src/intl/fa.js +20 -0
  62. package/dist/src/intl/fi.d.ts +24 -1
  63. package/dist/src/intl/fi.d.ts.map +1 -1
  64. package/dist/src/intl/fi.js +20 -0
  65. package/dist/src/intl/fil.d.ts +24 -1
  66. package/dist/src/intl/fil.d.ts.map +1 -1
  67. package/dist/src/intl/fil.js +20 -0
  68. package/dist/src/intl/fr.d.ts +24 -1
  69. package/dist/src/intl/fr.d.ts.map +1 -1
  70. package/dist/src/intl/fr.js +20 -0
  71. package/dist/src/intl/he.d.ts +24 -1
  72. package/dist/src/intl/he.d.ts.map +1 -1
  73. package/dist/src/intl/he.js +20 -0
  74. package/dist/src/intl/hi.d.ts +24 -1
  75. package/dist/src/intl/hi.d.ts.map +1 -1
  76. package/dist/src/intl/hi.js +20 -0
  77. package/dist/src/intl/hr.d.ts +24 -1
  78. package/dist/src/intl/hr.d.ts.map +1 -1
  79. package/dist/src/intl/hr.js +20 -0
  80. package/dist/src/intl/hu.d.ts +22 -1
  81. package/dist/src/intl/hu.d.ts.map +1 -1
  82. package/dist/src/intl/hu.js +18 -0
  83. package/dist/src/intl/id.d.ts +24 -1
  84. package/dist/src/intl/id.d.ts.map +1 -1
  85. package/dist/src/intl/id.js +20 -0
  86. package/dist/src/intl/it.d.ts +24 -1
  87. package/dist/src/intl/it.d.ts.map +1 -1
  88. package/dist/src/intl/it.js +20 -0
  89. package/dist/src/intl/ja.d.ts +24 -1
  90. package/dist/src/intl/ja.d.ts.map +1 -1
  91. package/dist/src/intl/ja.js +20 -0
  92. package/dist/src/intl/ko.d.ts +24 -1
  93. package/dist/src/intl/ko.d.ts.map +1 -1
  94. package/dist/src/intl/ko.js +20 -0
  95. package/dist/src/intl/ml.d.ts +24 -1
  96. package/dist/src/intl/ml.d.ts.map +1 -1
  97. package/dist/src/intl/ml.js +20 -0
  98. package/dist/src/intl/mr.d.ts +24 -1
  99. package/dist/src/intl/mr.d.ts.map +1 -1
  100. package/dist/src/intl/mr.js +20 -0
  101. package/dist/src/intl/ms.d.ts +24 -1
  102. package/dist/src/intl/ms.d.ts.map +1 -1
  103. package/dist/src/intl/ms.js +20 -0
  104. package/dist/src/intl/nb.d.ts +22 -1
  105. package/dist/src/intl/nb.d.ts.map +1 -1
  106. package/dist/src/intl/nb.js +18 -0
  107. package/dist/src/intl/nl.d.ts +24 -1
  108. package/dist/src/intl/nl.d.ts.map +1 -1
  109. package/dist/src/intl/nl.js +20 -0
  110. package/dist/src/intl/pa.d.ts +24 -1
  111. package/dist/src/intl/pa.d.ts.map +1 -1
  112. package/dist/src/intl/pa.js +20 -0
  113. package/dist/src/intl/pl.d.ts +23 -0
  114. package/dist/src/intl/pl.d.ts.map +1 -1
  115. package/dist/src/intl/pl.js +20 -0
  116. package/dist/src/intl/pt-BR.d.ts +24 -1
  117. package/dist/src/intl/pt-BR.d.ts.map +1 -1
  118. package/dist/src/intl/pt-BR.js +20 -0
  119. package/dist/src/intl/pt.d.ts +24 -1
  120. package/dist/src/intl/pt.d.ts.map +1 -1
  121. package/dist/src/intl/pt.js +20 -0
  122. package/dist/src/intl/ro.d.ts +24 -1
  123. package/dist/src/intl/ro.d.ts.map +1 -1
  124. package/dist/src/intl/ro.js +20 -0
  125. package/dist/src/intl/sk.d.ts +24 -1
  126. package/dist/src/intl/sk.d.ts.map +1 -1
  127. package/dist/src/intl/sk.js +20 -0
  128. package/dist/src/intl/sl.d.ts +24 -1
  129. package/dist/src/intl/sl.d.ts.map +1 -1
  130. package/dist/src/intl/sl.js +20 -0
  131. package/dist/src/intl/sv.d.ts +24 -1
  132. package/dist/src/intl/sv.d.ts.map +1 -1
  133. package/dist/src/intl/sv.js +20 -0
  134. package/dist/src/intl/sw.d.ts +21 -0
  135. package/dist/src/intl/sw.d.ts.map +1 -1
  136. package/dist/src/intl/sw.js +18 -0
  137. package/dist/src/intl/ta.d.ts +24 -1
  138. package/dist/src/intl/ta.d.ts.map +1 -1
  139. package/dist/src/intl/ta.js +20 -0
  140. package/dist/src/intl/te.d.ts +24 -1
  141. package/dist/src/intl/te.d.ts.map +1 -1
  142. package/dist/src/intl/te.js +20 -0
  143. package/dist/src/intl/th.d.ts +24 -1
  144. package/dist/src/intl/th.d.ts.map +1 -1
  145. package/dist/src/intl/th.js +20 -0
  146. package/dist/src/intl/tr.d.ts +24 -1
  147. package/dist/src/intl/tr.d.ts.map +1 -1
  148. package/dist/src/intl/tr.js +20 -0
  149. package/dist/src/intl/uk.d.ts +80 -57
  150. package/dist/src/intl/uk.d.ts.map +1 -1
  151. package/dist/src/intl/uk.js +174 -149
  152. package/dist/src/intl/ur.d.ts +24 -1
  153. package/dist/src/intl/ur.d.ts.map +1 -1
  154. package/dist/src/intl/ur.js +20 -0
  155. package/dist/src/intl/vi.d.ts +24 -1
  156. package/dist/src/intl/vi.d.ts.map +1 -1
  157. package/dist/src/intl/vi.js +20 -0
  158. package/dist/src/intl/zh-CN.d.ts +24 -1
  159. package/dist/src/intl/zh-CN.d.ts.map +1 -1
  160. package/dist/src/intl/zh-CN.js +20 -0
  161. package/dist/src/intl/zh-TW.d.ts +24 -1
  162. package/dist/src/intl/zh-TW.d.ts.map +1 -1
  163. package/dist/src/intl/zh-TW.js +20 -0
  164. package/dist/src/local-first/Protocol.d.ts +1 -1
  165. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  166. package/dist/src/local-first/Protocol.js +1 -1
  167. package/dist/src/local-first/Schema.d.ts +10 -0
  168. package/dist/src/local-first/Schema.d.ts.map +1 -1
  169. package/dist/src/local-first/Storage.js +1 -1
  170. package/dist/src/local-first/Timestamp.js +1 -1
  171. package/package.json +1 -1
  172. package/src/Assert.test.ts +51 -0
  173. package/src/Assert.ts +56 -4
  174. package/src/{Binary.test.ts → Bytes.test.ts} +286 -1
  175. package/src/{Binary.ts → Bytes.ts} +652 -21
  176. package/src/Config.test.ts +672 -0
  177. package/src/Config.ts +410 -0
  178. package/src/Fs.test.ts +105 -0
  179. package/src/Fs.ts +414 -0
  180. package/src/Number.test.ts +82 -18
  181. package/src/Number.ts +76 -8
  182. package/src/Object.test.ts +115 -1
  183. package/src/Object.ts +44 -0
  184. package/src/Polyfills.ts +6 -0
  185. package/src/Sqlite.ts +1 -1
  186. package/src/Time.test.ts +82 -11
  187. package/src/Time.ts +141 -16
  188. package/src/Type.test.ts +3114 -157
  189. package/src/Type.ts +2553 -196
  190. package/src/index.ts +3 -1
  191. package/src/intl/_en.ts +70 -0
  192. package/src/intl/ar.ts +71 -0
  193. package/src/intl/bn.ts +70 -0
  194. package/src/intl/ca.ts +70 -0
  195. package/src/intl/cs.ts +70 -0
  196. package/src/intl/da.ts +70 -0
  197. package/src/intl/de.ts +70 -0
  198. package/src/intl/el.ts +70 -0
  199. package/src/intl/es.ts +70 -0
  200. package/src/intl/fa.ts +70 -0
  201. package/src/intl/fi.ts +70 -0
  202. package/src/intl/fil.ts +70 -0
  203. package/src/intl/fr.ts +70 -0
  204. package/src/intl/he.ts +70 -0
  205. package/src/intl/hi.ts +70 -0
  206. package/src/intl/hr.ts +70 -0
  207. package/src/intl/hu.ts +69 -0
  208. package/src/intl/id.ts +70 -0
  209. package/src/intl/intl.test.ts +819 -1
  210. package/src/intl/it.ts +70 -0
  211. package/src/intl/ja.ts +70 -0
  212. package/src/intl/ko.ts +68 -0
  213. package/src/intl/ml.ts +70 -0
  214. package/src/intl/mr.ts +70 -0
  215. package/src/intl/ms.ts +71 -0
  216. package/src/intl/nb.ts +69 -0
  217. package/src/intl/nl.ts +70 -0
  218. package/src/intl/pa.ts +70 -0
  219. package/src/intl/pl.ts +63 -0
  220. package/src/intl/pt-BR.ts +70 -0
  221. package/src/intl/pt.ts +71 -0
  222. package/src/intl/ro.ts +70 -0
  223. package/src/intl/sk.ts +71 -0
  224. package/src/intl/sl.ts +70 -0
  225. package/src/intl/sv.ts +70 -0
  226. package/src/intl/sw.ts +62 -0
  227. package/src/intl/ta.ts +70 -0
  228. package/src/intl/te.ts +70 -0
  229. package/src/intl/th.ts +68 -0
  230. package/src/intl/tr.ts +70 -0
  231. package/src/intl/uk.ts +228 -155
  232. package/src/intl/ur.ts +70 -0
  233. package/src/intl/vi.ts +70 -0
  234. package/src/intl/zh-CN.ts +68 -0
  235. package/src/intl/zh-TW.ts +68 -0
  236. package/src/local-first/Protocol.test.ts +1 -1
  237. package/src/local-first/Protocol.ts +1 -1
  238. package/src/local-first/Schema.ts +11 -0
  239. package/src/local-first/Storage.ts +1 -1
  240. package/src/local-first/Timestamp.ts +1 -1
  241. package/dist/src/Binary.d.ts +0 -254
  242. package/dist/src/Binary.d.ts.map +0 -1
@@ -1,23 +1,48 @@
1
1
  /**
2
- * Binary data handling and byte array utilities.
2
+ * Bytes: `Uint8Array` helpers, the {@link Buffer} codec, and byte sizes.
3
3
  *
4
- * Buffer-based decoding functions intentionally throw errors instead of
5
- * returning {@link Result}. This is a deliberate micro-optimization for Evolu
6
- * Protocol's hot paths: Result is inexpensive, but returning decoded values
7
- * directly avoids its success-case allocation, and using `Error` objects
8
- * preserves stack traces. In the future, we will try returning `Error` objects
9
- * in `Result` values to measure the real-world performance impact.
4
+ * Sizes follow the same pattern as durations in Time.ts:
5
+ *
6
+ * - {@link ByteLength} is the canonical unit, a validated number of bytes.
7
+ * - {@link ByteSizeLiteral} is the human-readable form, such as `"10MiB"`,
8
+ * validated at compile time and runtime.
9
+ * - {@link ByteSize} is what APIs accept: `ByteSizeLiteral | ByteLength`.
10
+ * - {@link byteSizeToByteLength} normalizes a `ByteSize` to a `ByteLength`.
11
+ * - {@link ByteLengthFromString} parses either form from text.
12
+ *
13
+ * Buffer-based decoding functions throw instead of returning {@link Result}.
14
+ * Result is not slow, but every successful decode would allocate one, and a
15
+ * protocol message decodes many values. Throwing is the safe bet for that hot
16
+ * path until benchmarks cover the alternatives. Callers convert a thrown error
17
+ * into a Result once, at the boundary, as `parseProtocolHeader` in Protocol.ts
18
+ * does.
10
19
  *
11
20
  * @module
12
21
  */
13
22
 
14
23
  import { bytesToUtf8, utf8ToBytes } from "@noble/ciphers/utils.js";
15
- import type { Result } from "./Result.ts";
16
- import type {
17
- FiniteNumber,
18
- JsonValue,
24
+ import { assert } from "./Assert.ts";
25
+ import { err, ok, type Result } from "./Result.ts";
26
+ import { safelyStringifyUnknownValue } from "./String.ts";
27
+ import {
28
+ brand,
29
+ createTypeWithError,
30
+ Digit,
31
+ Digit1To9,
32
+ type FiniteNumber,
33
+ type JsonValue,
19
34
  NonNegativeInt,
20
- PositiveInt,
35
+ type PositiveInt,
36
+ String,
37
+ templateLiteral,
38
+ type TemplateLiteralType,
39
+ type LiteralType,
40
+ type UnionType,
41
+ transform,
42
+ type Type,
43
+ type TypeError,
44
+ union,
45
+ type UnionError,
21
46
  } from "./Type.ts";
22
47
  export { bytesToHex, concatBytes, hexToBytes } from "@noble/ciphers/utils.js";
23
48
  export { bytesToUtf8, utf8ToBytes };
@@ -143,7 +168,7 @@ export const createBuffer = (
143
168
  arrayLike?: Uint8Array | ArrayLike<number>,
144
169
  ): Buffer => {
145
170
  const initialLength = arrayLike?.length ?? 0;
146
- assertNonNegativeInt(initialLength, "arrayLike.length");
171
+ assertBufferNonNegativeInt(initialLength, "arrayLike.length");
147
172
 
148
173
  let value = arrayLike ? new Uint8Array(arrayLike) : new Uint8Array(512);
149
174
  let length = initialLength;
@@ -155,10 +180,10 @@ export const createBuffer = (
155
180
 
156
181
  extend: (arg) => {
157
182
  const argLength = arg.length;
158
- assertNonNegativeInt(argLength, "arg.length");
183
+ assertBufferNonNegativeInt(argLength, "arg.length");
159
184
 
160
185
  const targetSize = length + argLength;
161
- assertNonNegativeInt(targetSize, "Buffer length");
186
+ assertBufferNonNegativeInt(targetSize, "Buffer length");
162
187
 
163
188
  if (value.length < targetSize) {
164
189
  const oldValue = value;
@@ -341,7 +366,7 @@ export const decodeNonNegativeInt = (buffer: Buffer): NonNegativeInt => {
341
366
  }
342
367
 
343
368
  const value = Number(result);
344
- assertNonNegativeInt(value, "Decoded integer");
369
+ assertBufferNonNegativeInt(value, "Decoded integer");
345
370
  return value;
346
371
  };
347
372
 
@@ -350,7 +375,7 @@ export const encodeLength = (
350
375
  buffer: Buffer,
351
376
  value: ArrayLike<unknown>,
352
377
  ): void => {
353
- assertNonNegativeInt(value.length, "Array-like length");
378
+ assertBufferNonNegativeInt(value.length, "Array-like length");
354
379
  encodeNonNegativeInt(buffer, value.length);
355
380
  };
356
381
 
@@ -489,7 +514,7 @@ let jsonDecoderSource: Uint8Array = emptyJsonDecoderSource;
489
514
  let jsonDecoderView: DataView = emptyJsonDecoderView;
490
515
  let jsonDecoderPosition = 0;
491
516
  let jsonDecoderDepth = 0;
492
- const jsonStringFromCharCode = String.fromCharCode;
517
+ const jsonStringFromCharCode = globalThis.String.fromCharCode;
493
518
  // Cache only short keys and use a fixed table to bound retained memory.
494
519
  const jsonKeyCache: Array<JsonKeyCacheEntry | undefined> = Array.from(
495
520
  { length: jsonKeyCacheSize },
@@ -816,12 +841,12 @@ const writeJsonEncoderByte = (value: number): void => {
816
841
 
817
842
  const ensureJsonEncoderCapacity = (additionalLength: number): void => {
818
843
  const requiredLength = jsonEncoderPosition + additionalLength;
819
- assertNonNegativeInt(requiredLength, "Encoded JSON value length");
844
+ assertBufferNonNegativeInt(requiredLength, "Encoded JSON value length");
820
845
 
821
846
  if (requiredLength <= jsonEncoderTarget.length) return;
822
847
 
823
848
  const newCapacity = Math.max(jsonEncoderTarget.length * 2, requiredLength);
824
- assertNonNegativeInt(newCapacity, "JSON encoder capacity");
849
+ assertBufferNonNegativeInt(newCapacity, "JSON encoder capacity");
825
850
 
826
851
  const oldTarget = jsonEncoderTarget;
827
852
  jsonEncoderTarget = new Uint8Array(newCapacity);
@@ -1358,7 +1383,7 @@ const assertJsonDecoderHasRemainingBytes = (requiredBytes: number): void => {
1358
1383
  }
1359
1384
  };
1360
1385
 
1361
- const assertNonNegativeInt: (
1386
+ const assertBufferNonNegativeInt: (
1362
1387
  value: number,
1363
1388
  name: string,
1364
1389
  ) => asserts value is NonNegativeInt = (value, name) => {
@@ -1375,3 +1400,609 @@ const assertBufferHasRemainingBytes = (
1375
1400
  throw new BufferError("Buffer parse ended prematurely");
1376
1401
  }
1377
1402
  };
1403
+
1404
+ /**
1405
+ * Non-negative safe integer number of bytes.
1406
+ *
1407
+ * The canonical unit for sizes, as milliseconds are for time. APIs accept
1408
+ * {@link ByteSize} and normalize it with {@link byteSizeToByteLength}. Parse text
1409
+ * such as an environment variable with {@link ByteLengthFromString}. Negative
1410
+ * zero is rejected so zero has one canonical representation.
1411
+ *
1412
+ * ### Example
1413
+ *
1414
+ * ```ts
1415
+ * import { assertErr, assertOk, ByteLength } from "@evolu/common";
1416
+ *
1417
+ * assertOk(ByteLength.fromUnknown(0), 0);
1418
+ * assertOk(ByteLength.fromUnknown(1024), 1024);
1419
+ * assertErr(ByteLength.fromUnknown(-0));
1420
+ * assertErr(ByteLength.fromUnknown(-1));
1421
+ * assertErr(ByteLength.fromUnknown(1.5));
1422
+ * ```
1423
+ */
1424
+ export const ByteLength = /*#__PURE__*/ brand(
1425
+ "ByteLength",
1426
+ NonNegativeInt,
1427
+ (value) =>
1428
+ Object.is(value, -0)
1429
+ ? err<ByteLengthError>({ type: "ByteLength", value })
1430
+ : ok(),
1431
+ () => "The value -0 is not a byte length. Use 0 instead.",
1432
+ );
1433
+ export type ByteLength = typeof ByteLength.Output;
1434
+
1435
+ /** Error returned when {@link ByteLength} rejects negative zero. */
1436
+ export interface ByteLengthError extends TypeError<"ByteLength"> {
1437
+ readonly value: number;
1438
+ }
1439
+
1440
+ const Digit0To1 = /*#__PURE__*/ union("0", "1");
1441
+ const Digit0To3 = /*#__PURE__*/ union("0", "1", "2", "3");
1442
+
1443
+ // Keep these annotations concrete. Generic unit wrappers add thousands of
1444
+ // compiler instantiations to pnpm bench:type.
1445
+ /** Bytes: `"0B"` to `"1023B"`. See {@link ByteSizeLiteral}. */
1446
+ export const ByteSizeLiteralBytes: UnionType<
1447
+ readonly [
1448
+ TemplateLiteralType<readonly [typeof Digit, "B"]>,
1449
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, "B"]>,
1450
+ TemplateLiteralType<
1451
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, "B"]
1452
+ >,
1453
+ TemplateLiteralType<
1454
+ readonly [
1455
+ "10",
1456
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1457
+ typeof Digit,
1458
+ "B",
1459
+ ]
1460
+ >,
1461
+ TemplateLiteralType<
1462
+ readonly [
1463
+ "102",
1464
+ UnionType<
1465
+ readonly [
1466
+ LiteralType<"0">,
1467
+ LiteralType<"1">,
1468
+ LiteralType<"2">,
1469
+ LiteralType<"3">,
1470
+ ]
1471
+ >,
1472
+ "B",
1473
+ ]
1474
+ >,
1475
+ ]
1476
+ > = /*#__PURE__*/ union(
1477
+ /*#__PURE__*/ templateLiteral(Digit, "B"),
1478
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, "B"),
1479
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, "B"),
1480
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, "B"),
1481
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, "B"),
1482
+ );
1483
+ export type ByteSizeLiteralBytes = typeof ByteSizeLiteralBytes.Output;
1484
+
1485
+ /**
1486
+ * KiB: `"1KiB"` to `"1023KiB"` or `"1.5KiB"` to `"1023.5KiB"`. See
1487
+ * {@link ByteSizeLiteral}.
1488
+ */
1489
+ export const ByteSizeLiteralKiB: UnionType<
1490
+ readonly [
1491
+ TemplateLiteralType<readonly [typeof Digit1To9, "KiB"]>,
1492
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, "KiB"]>,
1493
+ TemplateLiteralType<
1494
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, "KiB"]
1495
+ >,
1496
+ TemplateLiteralType<
1497
+ readonly [
1498
+ "10",
1499
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1500
+ typeof Digit,
1501
+ "KiB",
1502
+ ]
1503
+ >,
1504
+ TemplateLiteralType<
1505
+ readonly [
1506
+ "102",
1507
+ UnionType<
1508
+ readonly [
1509
+ LiteralType<"0">,
1510
+ LiteralType<"1">,
1511
+ LiteralType<"2">,
1512
+ LiteralType<"3">,
1513
+ ]
1514
+ >,
1515
+ "KiB",
1516
+ ]
1517
+ >,
1518
+ TemplateLiteralType<readonly [typeof Digit1To9, ".5KiB"]>,
1519
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, ".5KiB"]>,
1520
+ TemplateLiteralType<
1521
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, ".5KiB"]
1522
+ >,
1523
+ TemplateLiteralType<
1524
+ readonly [
1525
+ "10",
1526
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1527
+ typeof Digit,
1528
+ ".5KiB",
1529
+ ]
1530
+ >,
1531
+ TemplateLiteralType<
1532
+ readonly [
1533
+ "102",
1534
+ UnionType<
1535
+ readonly [
1536
+ LiteralType<"0">,
1537
+ LiteralType<"1">,
1538
+ LiteralType<"2">,
1539
+ LiteralType<"3">,
1540
+ ]
1541
+ >,
1542
+ ".5KiB",
1543
+ ]
1544
+ >,
1545
+ ]
1546
+ > = /*#__PURE__*/ union(
1547
+ /*#__PURE__*/ templateLiteral(Digit1To9, "KiB"),
1548
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, "KiB"),
1549
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, "KiB"),
1550
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, "KiB"),
1551
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, "KiB"),
1552
+ /*#__PURE__*/ templateLiteral(Digit1To9, ".5KiB"),
1553
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, ".5KiB"),
1554
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, ".5KiB"),
1555
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, ".5KiB"),
1556
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, ".5KiB"),
1557
+ );
1558
+ export type ByteSizeLiteralKiB = typeof ByteSizeLiteralKiB.Output;
1559
+
1560
+ /**
1561
+ * MiB: `"1MiB"` to `"1023MiB"` or `"1.5MiB"` to `"1023.5MiB"`. See
1562
+ * {@link ByteSizeLiteral}.
1563
+ */
1564
+ export const ByteSizeLiteralMiB: UnionType<
1565
+ readonly [
1566
+ TemplateLiteralType<readonly [typeof Digit1To9, "MiB"]>,
1567
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, "MiB"]>,
1568
+ TemplateLiteralType<
1569
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, "MiB"]
1570
+ >,
1571
+ TemplateLiteralType<
1572
+ readonly [
1573
+ "10",
1574
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1575
+ typeof Digit,
1576
+ "MiB",
1577
+ ]
1578
+ >,
1579
+ TemplateLiteralType<
1580
+ readonly [
1581
+ "102",
1582
+ UnionType<
1583
+ readonly [
1584
+ LiteralType<"0">,
1585
+ LiteralType<"1">,
1586
+ LiteralType<"2">,
1587
+ LiteralType<"3">,
1588
+ ]
1589
+ >,
1590
+ "MiB",
1591
+ ]
1592
+ >,
1593
+ TemplateLiteralType<readonly [typeof Digit1To9, ".5MiB"]>,
1594
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, ".5MiB"]>,
1595
+ TemplateLiteralType<
1596
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, ".5MiB"]
1597
+ >,
1598
+ TemplateLiteralType<
1599
+ readonly [
1600
+ "10",
1601
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1602
+ typeof Digit,
1603
+ ".5MiB",
1604
+ ]
1605
+ >,
1606
+ TemplateLiteralType<
1607
+ readonly [
1608
+ "102",
1609
+ UnionType<
1610
+ readonly [
1611
+ LiteralType<"0">,
1612
+ LiteralType<"1">,
1613
+ LiteralType<"2">,
1614
+ LiteralType<"3">,
1615
+ ]
1616
+ >,
1617
+ ".5MiB",
1618
+ ]
1619
+ >,
1620
+ ]
1621
+ > = /*#__PURE__*/ union(
1622
+ /*#__PURE__*/ templateLiteral(Digit1To9, "MiB"),
1623
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, "MiB"),
1624
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, "MiB"),
1625
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, "MiB"),
1626
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, "MiB"),
1627
+ /*#__PURE__*/ templateLiteral(Digit1To9, ".5MiB"),
1628
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, ".5MiB"),
1629
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, ".5MiB"),
1630
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, ".5MiB"),
1631
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, ".5MiB"),
1632
+ );
1633
+ export type ByteSizeLiteralMiB = typeof ByteSizeLiteralMiB.Output;
1634
+
1635
+ /**
1636
+ * GiB: `"1GiB"` to `"1023GiB"` or `"1.5GiB"` to `"1023.5GiB"`. See
1637
+ * {@link ByteSizeLiteral}.
1638
+ */
1639
+ export const ByteSizeLiteralGiB: UnionType<
1640
+ readonly [
1641
+ TemplateLiteralType<readonly [typeof Digit1To9, "GiB"]>,
1642
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, "GiB"]>,
1643
+ TemplateLiteralType<
1644
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, "GiB"]
1645
+ >,
1646
+ TemplateLiteralType<
1647
+ readonly [
1648
+ "10",
1649
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1650
+ typeof Digit,
1651
+ "GiB",
1652
+ ]
1653
+ >,
1654
+ TemplateLiteralType<
1655
+ readonly [
1656
+ "102",
1657
+ UnionType<
1658
+ readonly [
1659
+ LiteralType<"0">,
1660
+ LiteralType<"1">,
1661
+ LiteralType<"2">,
1662
+ LiteralType<"3">,
1663
+ ]
1664
+ >,
1665
+ "GiB",
1666
+ ]
1667
+ >,
1668
+ TemplateLiteralType<readonly [typeof Digit1To9, ".5GiB"]>,
1669
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, ".5GiB"]>,
1670
+ TemplateLiteralType<
1671
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, ".5GiB"]
1672
+ >,
1673
+ TemplateLiteralType<
1674
+ readonly [
1675
+ "10",
1676
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1677
+ typeof Digit,
1678
+ ".5GiB",
1679
+ ]
1680
+ >,
1681
+ TemplateLiteralType<
1682
+ readonly [
1683
+ "102",
1684
+ UnionType<
1685
+ readonly [
1686
+ LiteralType<"0">,
1687
+ LiteralType<"1">,
1688
+ LiteralType<"2">,
1689
+ LiteralType<"3">,
1690
+ ]
1691
+ >,
1692
+ ".5GiB",
1693
+ ]
1694
+ >,
1695
+ ]
1696
+ > = /*#__PURE__*/ union(
1697
+ /*#__PURE__*/ templateLiteral(Digit1To9, "GiB"),
1698
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, "GiB"),
1699
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, "GiB"),
1700
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, "GiB"),
1701
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, "GiB"),
1702
+ /*#__PURE__*/ templateLiteral(Digit1To9, ".5GiB"),
1703
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, ".5GiB"),
1704
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, ".5GiB"),
1705
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, ".5GiB"),
1706
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, ".5GiB"),
1707
+ );
1708
+ export type ByteSizeLiteralGiB = typeof ByteSizeLiteralGiB.Output;
1709
+
1710
+ /**
1711
+ * TiB: `"1TiB"` to `"1023TiB"` or `"1.5TiB"` to `"1023.5TiB"`. See
1712
+ * {@link ByteSizeLiteral}.
1713
+ */
1714
+ export const ByteSizeLiteralTiB: UnionType<
1715
+ readonly [
1716
+ TemplateLiteralType<readonly [typeof Digit1To9, "TiB"]>,
1717
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, "TiB"]>,
1718
+ TemplateLiteralType<
1719
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, "TiB"]
1720
+ >,
1721
+ TemplateLiteralType<
1722
+ readonly [
1723
+ "10",
1724
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1725
+ typeof Digit,
1726
+ "TiB",
1727
+ ]
1728
+ >,
1729
+ TemplateLiteralType<
1730
+ readonly [
1731
+ "102",
1732
+ UnionType<
1733
+ readonly [
1734
+ LiteralType<"0">,
1735
+ LiteralType<"1">,
1736
+ LiteralType<"2">,
1737
+ LiteralType<"3">,
1738
+ ]
1739
+ >,
1740
+ "TiB",
1741
+ ]
1742
+ >,
1743
+ TemplateLiteralType<readonly [typeof Digit1To9, ".5TiB"]>,
1744
+ TemplateLiteralType<readonly [typeof Digit1To9, typeof Digit, ".5TiB"]>,
1745
+ TemplateLiteralType<
1746
+ readonly [typeof Digit1To9, typeof Digit, typeof Digit, ".5TiB"]
1747
+ >,
1748
+ TemplateLiteralType<
1749
+ readonly [
1750
+ "10",
1751
+ UnionType<readonly [LiteralType<"0">, LiteralType<"1">]>,
1752
+ typeof Digit,
1753
+ ".5TiB",
1754
+ ]
1755
+ >,
1756
+ TemplateLiteralType<
1757
+ readonly [
1758
+ "102",
1759
+ UnionType<
1760
+ readonly [
1761
+ LiteralType<"0">,
1762
+ LiteralType<"1">,
1763
+ LiteralType<"2">,
1764
+ LiteralType<"3">,
1765
+ ]
1766
+ >,
1767
+ ".5TiB",
1768
+ ]
1769
+ >,
1770
+ ]
1771
+ > = /*#__PURE__*/ union(
1772
+ /*#__PURE__*/ templateLiteral(Digit1To9, "TiB"),
1773
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, "TiB"),
1774
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, "TiB"),
1775
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, "TiB"),
1776
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, "TiB"),
1777
+ /*#__PURE__*/ templateLiteral(Digit1To9, ".5TiB"),
1778
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, ".5TiB"),
1779
+ /*#__PURE__*/ templateLiteral(Digit1To9, Digit, Digit, ".5TiB"),
1780
+ /*#__PURE__*/ templateLiteral("10", Digit0To1, Digit, ".5TiB"),
1781
+ /*#__PURE__*/ templateLiteral("102", Digit0To3, ".5TiB"),
1782
+ );
1783
+ export type ByteSizeLiteralTiB = typeof ByteSizeLiteralTiB.Output;
1784
+
1785
+ export type ByteSizeLiteral =
1786
+ | ByteSizeLiteralBytes
1787
+ | ByteSizeLiteralKiB
1788
+ | ByteSizeLiteralMiB
1789
+ | ByteSizeLiteralGiB
1790
+ | ByteSizeLiteralTiB;
1791
+
1792
+ const byteSizeLiteralSyntax = /*#__PURE__*/ union(
1793
+ ByteSizeLiteralBytes,
1794
+ ByteSizeLiteralKiB,
1795
+ ByteSizeLiteralMiB,
1796
+ ByteSizeLiteralGiB,
1797
+ ByteSizeLiteralTiB,
1798
+ );
1799
+
1800
+ /**
1801
+ * Byte length literal Type with compile-time and runtime validation.
1802
+ *
1803
+ * Supported formats:
1804
+ *
1805
+ * - Bytes: `0B` to `1023B`
1806
+ * - KiB: `1KiB` to `1023KiB` or `1.5KiB` to `1023.5KiB`
1807
+ * - MiB: `1MiB` to `1023MiB` or `1.5MiB` to `1023.5MiB`
1808
+ * - GiB: `1GiB` to `1023GiB` or `1.5GiB` to `1023.5GiB`
1809
+ * - TiB: `1TiB` to `1023TiB` or `1.5TiB` to `1023.5TiB`
1810
+ *
1811
+ * Units are the binary ones defined by IEC, named kibibyte (`KiB`, 1024 bytes),
1812
+ * mebibyte (`MiB`), gibibyte (`GiB`), and tebibyte (`TiB`), each 1024 times the
1813
+ * previous. Memory, storage quotas, and caches are measured in them. The
1814
+ * familiar `MB` is ambiguous: SI defines it as a million bytes, storage vendors
1815
+ * use that meaning, and most software uses 1048576 instead, which is why a "1
1816
+ * TB" drive shows as 931 "GB". `MiB` has only one meaning, so a literal never
1817
+ * depends on a convention.
1818
+ *
1819
+ * Each unit is bounded below 1024, so equivalent representations are avoided:
1820
+ * `1024KiB` must be written as `"1MiB"`. A half is the only decimal allowed,
1821
+ * because it is the only single decimal digit that is exact in every binary
1822
+ * unit; `1.1KiB` would be 1126.4 bytes. For other exact values, use
1823
+ * {@link ByteLength} directly.
1824
+ *
1825
+ * See {@link ByteSize} for a type that also accepts {@link ByteLength}. Use
1826
+ * {@link byteSizeToByteLength} to convert.
1827
+ *
1828
+ * Invalid values produce a {@link ByteSizeLiteralError}.
1829
+ *
1830
+ * ### Example
1831
+ *
1832
+ * ```ts
1833
+ * import {
1834
+ * assertEqual,
1835
+ * assertErr,
1836
+ * assertFalse,
1837
+ * assertOk,
1838
+ * assertType,
1839
+ * ByteSizeLiteral,
1840
+ * } from "@evolu/common";
1841
+ *
1842
+ * // The TypeScript type accepts valid spellings and rejects the rest.
1843
+ * const literal: ByteSizeLiteral = "1023MiB";
1844
+ * assertType<
1845
+ * Extract<ByteSizeLiteral, "1024KiB" | "1.1KiB" | "1MB">,
1846
+ * never
1847
+ * >();
1848
+ *
1849
+ * // The runtime Type validates the same grammar.
1850
+ * assertOk(ByteSizeLiteral.fromUnknown(literal), "1023MiB");
1851
+ * assertFalse(ByteSizeLiteral.is("1024KiB"));
1852
+ *
1853
+ * const invalid = ByteSizeLiteral.fromUnknown("1MB");
1854
+ * assertErr(invalid);
1855
+ * assertEqual(invalid.error.type, "ByteSizeLiteral");
1856
+ * assertEqual(
1857
+ * ByteSizeLiteral.formatError(invalid.error),
1858
+ * 'The value "1MB" is not a byte-size literal. Use a value such as "512KiB" or "1MiB".',
1859
+ * );
1860
+ * ```
1861
+ */
1862
+ export const ByteSizeLiteral: Type<
1863
+ "ByteSizeLiteral",
1864
+ ByteSizeLiteral,
1865
+ ByteSizeLiteral,
1866
+ ByteSizeLiteralError
1867
+ > = /*#__PURE__*/ createTypeWithError(
1868
+ "ByteSizeLiteral",
1869
+ byteSizeLiteralSyntax,
1870
+ (cause, value): ByteSizeLiteralError => ({
1871
+ type: "ByteSizeLiteral",
1872
+ value,
1873
+ cause,
1874
+ }),
1875
+ (error) =>
1876
+ `The value ${safelyStringifyUnknownValue(error.value)} is not a byte-size literal. Use a value such as "512KiB" or "1MiB".`,
1877
+ );
1878
+
1879
+ /** Error returned when {@link ByteSizeLiteral} rejects a value. */
1880
+ export interface ByteSizeLiteralError extends TypeError<"ByteSizeLiteral"> {
1881
+ readonly value: unknown;
1882
+ /**
1883
+ * The underlying union failure, retained for diagnostics.
1884
+ *
1885
+ * With `{ errors: "all" }`, includes every failed alternative.
1886
+ */
1887
+ readonly cause: UnionError;
1888
+ }
1889
+
1890
+ /**
1891
+ * {@link ByteSizeLiteral} or {@link ByteLength}.
1892
+ *
1893
+ * Convenience input accepting a human-readable {@link ByteSizeLiteral} or a
1894
+ * validated {@link ByteLength} for values that no literal expresses. APIs
1895
+ * normalize it with {@link byteSizeToByteLength}.
1896
+ *
1897
+ * ### Example
1898
+ *
1899
+ * ```ts
1900
+ * import {
1901
+ * assertEqual,
1902
+ * ByteLength,
1903
+ * byteSizeToByteLength,
1904
+ * type ByteSize,
1905
+ * } from "@evolu/common";
1906
+ *
1907
+ * const literal: ByteSize = "1MiB";
1908
+ * const validated: ByteSize = ByteLength.orThrow(1000000);
1909
+ *
1910
+ * assertEqual(byteSizeToByteLength(literal), 1048576);
1911
+ * assertEqual(byteSizeToByteLength(validated), 1000000);
1912
+ * ```
1913
+ */
1914
+ export type ByteSize = ByteSizeLiteral | ByteLength;
1915
+
1916
+ const bytesByByteLengthUnit = {
1917
+ B: 1,
1918
+ KiB: 1024,
1919
+ MiB: 1024 ** 2,
1920
+ GiB: 1024 ** 3,
1921
+ TiB: 1024 ** 4,
1922
+ };
1923
+
1924
+ /**
1925
+ * Converts a {@link ByteSize} to a {@link ByteLength}. A {@link ByteLength} is
1926
+ * returned unchanged.
1927
+ *
1928
+ * ### Example
1929
+ *
1930
+ * ```ts
1931
+ * import { assertEqual, byteSizeToByteLength } from "@evolu/common";
1932
+ *
1933
+ * assertEqual(byteSizeToByteLength("0B"), 0);
1934
+ * assertEqual(byteSizeToByteLength("2KiB"), 2048);
1935
+ * assertEqual(byteSizeToByteLength("1GiB"), 1073741824);
1936
+ * ```
1937
+ */
1938
+ export const byteSizeToByteLength = (value: ByteSize): ByteLength => {
1939
+ if (typeof value === "number") return value;
1940
+
1941
+ const unit = value.endsWith("iB") ? value.slice(-3) : "B";
1942
+ assert(unit in bytesByByteLengthUnit, `Unknown byte length unit: ${unit}`);
1943
+
1944
+ return ByteLength.orThrow(
1945
+ Number.parseFloat(value) *
1946
+ bytesByByteLengthUnit[unit as keyof typeof bytesByByteLengthUnit],
1947
+ );
1948
+ };
1949
+
1950
+ /**
1951
+ * Error returned when a string is neither a number of bytes nor a
1952
+ * {@link ByteSizeLiteral}.
1953
+ */
1954
+ export interface ByteLengthFromStringError extends TypeError<"ByteLengthFromString"> {
1955
+ readonly value: string;
1956
+ }
1957
+
1958
+ /**
1959
+ * Transforms a number of bytes or a {@link ByteSizeLiteral} in text into a
1960
+ * {@link ByteLength}.
1961
+ *
1962
+ * This is useful for inputs that carry sizes as text, such as environment
1963
+ * variables and configuration files, where `"10MiB"` reads better than
1964
+ * `"10485760"`. Encoding produces the number of bytes.
1965
+ *
1966
+ * ### Example
1967
+ *
1968
+ * ```ts
1969
+ * import {
1970
+ * assertEqual,
1971
+ * assertErr,
1972
+ * assertOk,
1973
+ * ByteLengthFromString,
1974
+ * } from "@evolu/common";
1975
+ *
1976
+ * assertOk(ByteLengthFromString.fromUnknown("10MiB"), 10485760);
1977
+ * assertOk(ByteLengthFromString.fromUnknown("1048576"), 1048576);
1978
+ * assertEqual(
1979
+ * ByteLengthFromString.to(ByteLengthFromString.orThrow("1KiB")),
1980
+ * "1024",
1981
+ * );
1982
+ *
1983
+ * const invalid = ByteLengthFromString.fromUnknown("10MB");
1984
+ * assertErr(invalid, { type: "ByteLengthFromString", value: "10MB" });
1985
+ * assertEqual(
1986
+ * ByteLengthFromString.formatError(invalid.error),
1987
+ * 'The value "10MB" is not a byte length. Use a number of bytes or a literal such as 10MiB.',
1988
+ * );
1989
+ * ```
1990
+ */
1991
+ export const ByteLengthFromString = /*#__PURE__*/ transform(
1992
+ "ByteLengthFromString",
1993
+ String,
1994
+ ByteLength,
1995
+ {
1996
+ from: (value): Result<number, ByteLengthFromStringError> => {
1997
+ if (ByteSizeLiteral.is(value)) return ok(byteSizeToByteLength(value));
1998
+ if (/^\d+$/u.test(value)) {
1999
+ const number = Number(value);
2000
+ if (Number.isSafeInteger(number)) return ok(number);
2001
+ }
2002
+ return err({ type: "ByteLengthFromString", value });
2003
+ },
2004
+ to: (value) => globalThis.String(value),
2005
+ },
2006
+ (error) =>
2007
+ `The value ${safelyStringifyUnknownValue(error.value)} is not a byte length. Use a number of bytes or a literal such as 10MiB.`,
2008
+ );