@evolu/common 8.7.0 → 8.8.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 (300) hide show
  1. package/dist/src/Array.d.ts +21 -21
  2. package/dist/src/Array.js +5 -5
  3. package/dist/src/Assert.d.ts +478 -141
  4. package/dist/src/Assert.d.ts.map +1 -1
  5. package/dist/src/Assert.js +644 -99
  6. package/dist/src/{Buffer.d.ts → Binary.d.ts} +85 -12
  7. package/dist/src/Binary.d.ts.map +1 -0
  8. package/dist/src/{Buffer.js → Binary.js} +206 -24
  9. package/dist/src/Console.d.ts +2 -10
  10. package/dist/src/Console.d.ts.map +1 -1
  11. package/dist/src/Console.js +6 -12
  12. package/dist/src/Crypto.d.ts +5 -5
  13. package/dist/src/Crypto.js +1 -1
  14. package/dist/src/Eq.d.ts +35 -40
  15. package/dist/src/Eq.d.ts.map +1 -1
  16. package/dist/src/Eq.js +51 -87
  17. package/dist/src/Function.d.ts +9 -14
  18. package/dist/src/Function.d.ts.map +1 -1
  19. package/dist/src/Function.js +7 -9
  20. package/dist/src/Http.d.ts +6 -7
  21. package/dist/src/Http.d.ts.map +1 -1
  22. package/dist/src/LeakDetector.d.ts.map +1 -1
  23. package/dist/src/LeakDetector.js +1 -0
  24. package/dist/src/LockManager.d.ts +1 -1
  25. package/dist/src/LockManager.js +1 -1
  26. package/dist/src/Lookup.d.ts +3 -2
  27. package/dist/src/Lookup.d.ts.map +1 -1
  28. package/dist/src/Lookup.js +4 -3
  29. package/dist/src/Number.d.ts +1 -1
  30. package/dist/src/Number.d.ts.map +1 -1
  31. package/dist/src/Number.js +1 -1
  32. package/dist/src/Object.d.ts +4 -4
  33. package/dist/src/Object.d.ts.map +1 -1
  34. package/dist/src/Object.js +5 -4
  35. package/dist/src/Option.d.ts +1 -2
  36. package/dist/src/Option.d.ts.map +1 -1
  37. package/dist/src/Option.js +1 -2
  38. package/dist/src/Platform.js +2 -0
  39. package/dist/src/Polyfills.js +4 -1
  40. package/dist/src/Random.d.ts +1 -1
  41. package/dist/src/Result.d.ts +49 -54
  42. package/dist/src/Result.d.ts.map +1 -1
  43. package/dist/src/Result.js +17 -22
  44. package/dist/src/Set.d.ts +6 -6
  45. package/dist/src/Set.js +2 -2
  46. package/dist/src/Sqlite.js +1 -1
  47. package/dist/src/String.js +3 -2
  48. package/dist/src/Task.d.ts +32 -32
  49. package/dist/src/Task.d.ts.map +1 -1
  50. package/dist/src/Task.js +20 -22
  51. package/dist/src/Test.d.ts +31 -3
  52. package/dist/src/Test.d.ts.map +1 -1
  53. package/dist/src/Test.js +46 -3
  54. package/dist/src/Time.d.ts +3 -11
  55. package/dist/src/Time.d.ts.map +1 -1
  56. package/dist/src/Time.js +10 -18
  57. package/dist/src/Type.d.ts +87 -85
  58. package/dist/src/Type.d.ts.map +1 -1
  59. package/dist/src/Type.js +70 -63
  60. package/dist/src/Types.d.ts +12 -12
  61. package/dist/src/Types.js +1 -1
  62. package/dist/src/WebSocket.d.ts +4 -7
  63. package/dist/src/WebSocket.d.ts.map +1 -1
  64. package/dist/src/Worker.d.ts +1 -1
  65. package/dist/src/Worker.js +7 -7
  66. package/dist/src/index.d.ts +1 -1
  67. package/dist/src/index.js +1 -1
  68. package/dist/src/intl/_en.d.ts.map +1 -1
  69. package/dist/src/intl/_en.js +1 -1
  70. package/dist/src/intl/ar.d.ts.map +1 -1
  71. package/dist/src/intl/ar.js +1 -1
  72. package/dist/src/intl/bn.d.ts.map +1 -1
  73. package/dist/src/intl/bn.js +1 -1
  74. package/dist/src/intl/ca.d.ts.map +1 -1
  75. package/dist/src/intl/ca.js +1 -1
  76. package/dist/src/intl/cs.d.ts.map +1 -1
  77. package/dist/src/intl/cs.js +1 -1
  78. package/dist/src/intl/da.d.ts.map +1 -1
  79. package/dist/src/intl/da.js +1 -1
  80. package/dist/src/intl/de.d.ts.map +1 -1
  81. package/dist/src/intl/de.js +1 -1
  82. package/dist/src/intl/el.d.ts.map +1 -1
  83. package/dist/src/intl/el.js +1 -1
  84. package/dist/src/intl/es.d.ts.map +1 -1
  85. package/dist/src/intl/es.js +1 -1
  86. package/dist/src/intl/fa.d.ts.map +1 -1
  87. package/dist/src/intl/fa.js +1 -1
  88. package/dist/src/intl/fi.d.ts.map +1 -1
  89. package/dist/src/intl/fi.js +1 -1
  90. package/dist/src/intl/fil.d.ts.map +1 -1
  91. package/dist/src/intl/fil.js +1 -1
  92. package/dist/src/intl/fr.d.ts.map +1 -1
  93. package/dist/src/intl/fr.js +1 -1
  94. package/dist/src/intl/he.d.ts.map +1 -1
  95. package/dist/src/intl/he.js +1 -1
  96. package/dist/src/intl/hi.d.ts.map +1 -1
  97. package/dist/src/intl/hi.js +1 -1
  98. package/dist/src/intl/hr.d.ts.map +1 -1
  99. package/dist/src/intl/hr.js +1 -1
  100. package/dist/src/intl/hu.d.ts.map +1 -1
  101. package/dist/src/intl/hu.js +1 -1
  102. package/dist/src/intl/id.d.ts.map +1 -1
  103. package/dist/src/intl/id.js +1 -1
  104. package/dist/src/intl/it.d.ts.map +1 -1
  105. package/dist/src/intl/it.js +1 -1
  106. package/dist/src/intl/ja.d.ts.map +1 -1
  107. package/dist/src/intl/ja.js +1 -1
  108. package/dist/src/intl/ko.d.ts.map +1 -1
  109. package/dist/src/intl/ko.js +1 -1
  110. package/dist/src/intl/ml.d.ts.map +1 -1
  111. package/dist/src/intl/ml.js +1 -1
  112. package/dist/src/intl/mr.d.ts.map +1 -1
  113. package/dist/src/intl/mr.js +1 -1
  114. package/dist/src/intl/ms.d.ts.map +1 -1
  115. package/dist/src/intl/ms.js +1 -1
  116. package/dist/src/intl/nb.d.ts.map +1 -1
  117. package/dist/src/intl/nb.js +1 -1
  118. package/dist/src/intl/nl.d.ts.map +1 -1
  119. package/dist/src/intl/nl.js +1 -1
  120. package/dist/src/intl/pa.d.ts.map +1 -1
  121. package/dist/src/intl/pa.js +1 -1
  122. package/dist/src/intl/pl.d.ts.map +1 -1
  123. package/dist/src/intl/pl.js +1 -1
  124. package/dist/src/intl/pt-BR.d.ts.map +1 -1
  125. package/dist/src/intl/pt-BR.js +1 -1
  126. package/dist/src/intl/pt.d.ts.map +1 -1
  127. package/dist/src/intl/pt.js +1 -1
  128. package/dist/src/intl/ro.d.ts.map +1 -1
  129. package/dist/src/intl/ro.js +1 -1
  130. package/dist/src/intl/sk.d.ts.map +1 -1
  131. package/dist/src/intl/sk.js +1 -1
  132. package/dist/src/intl/sl.d.ts.map +1 -1
  133. package/dist/src/intl/sl.js +1 -1
  134. package/dist/src/intl/sv.d.ts.map +1 -1
  135. package/dist/src/intl/sv.js +1 -1
  136. package/dist/src/intl/sw.d.ts.map +1 -1
  137. package/dist/src/intl/sw.js +1 -1
  138. package/dist/src/intl/ta.d.ts.map +1 -1
  139. package/dist/src/intl/ta.js +1 -1
  140. package/dist/src/intl/te.d.ts.map +1 -1
  141. package/dist/src/intl/te.js +1 -1
  142. package/dist/src/intl/th.d.ts.map +1 -1
  143. package/dist/src/intl/th.js +1 -1
  144. package/dist/src/intl/tr.d.ts.map +1 -1
  145. package/dist/src/intl/tr.js +1 -1
  146. package/dist/src/intl/uk.d.ts.map +1 -1
  147. package/dist/src/intl/uk.js +1 -1
  148. package/dist/src/intl/ur.d.ts.map +1 -1
  149. package/dist/src/intl/ur.js +1 -1
  150. package/dist/src/intl/vi.d.ts.map +1 -1
  151. package/dist/src/intl/vi.js +1 -1
  152. package/dist/src/intl/zh-CN.d.ts.map +1 -1
  153. package/dist/src/intl/zh-CN.js +1 -1
  154. package/dist/src/intl/zh-TW.d.ts.map +1 -1
  155. package/dist/src/intl/zh-TW.js +1 -1
  156. package/dist/src/local-first/Evolu.d.ts +12 -12
  157. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  158. package/dist/src/local-first/Evolu.js +2 -2
  159. package/dist/src/local-first/Protocol.d.ts +14 -76
  160. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  161. package/dist/src/local-first/Protocol.js +29 -206
  162. package/dist/src/local-first/Query.d.ts +11 -11
  163. package/dist/src/local-first/Query.js +6 -6
  164. package/dist/src/local-first/Relay.d.ts +2 -2
  165. package/dist/src/local-first/Schema.d.ts +3 -5
  166. package/dist/src/local-first/Schema.d.ts.map +1 -1
  167. package/dist/src/local-first/Schema.js +2 -4
  168. package/dist/src/local-first/Shared.d.ts.map +1 -1
  169. package/dist/src/local-first/Shared.js +5 -5
  170. package/dist/src/local-first/Storage.js +4 -4
  171. package/dist/src/local-first/Timestamp.d.ts +9 -0
  172. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  173. package/dist/src/local-first/Timestamp.js +13 -10
  174. package/package.json +7 -4
  175. package/src/Array.test.ts +809 -0
  176. package/src/Array.ts +21 -21
  177. package/src/Assert.test.ts +1181 -0
  178. package/src/Assert.ts +971 -227
  179. package/src/BigInt.test.ts +28 -0
  180. package/src/Binary.test.ts +1128 -0
  181. package/src/{Buffer.ts → Binary.ts} +273 -46
  182. package/src/Brand.test.ts +90 -0
  183. package/src/Cache.test.ts +183 -0
  184. package/src/Callbacks.test.ts +66 -0
  185. package/src/Console.test.ts +809 -0
  186. package/src/Console.ts +9 -17
  187. package/src/Crypto.test.ts +138 -0
  188. package/src/Crypto.ts +5 -5
  189. package/src/Eq.test.ts +333 -0
  190. package/src/Eq.ts +110 -176
  191. package/src/Error.test.ts +118 -0
  192. package/src/Function.test.ts +204 -0
  193. package/src/Function.ts +10 -15
  194. package/src/Http.test.ts +816 -0
  195. package/src/Http.ts +6 -7
  196. package/src/LeakDetector.test.ts +210 -0
  197. package/src/LeakDetector.ts +1 -0
  198. package/src/LockManager.ts +2 -2
  199. package/src/Lookup.test.ts +418 -0
  200. package/src/Lookup.ts +4 -3
  201. package/src/Microtask.test.ts +140 -0
  202. package/src/Number.test.ts +218 -0
  203. package/src/Number.ts +2 -2
  204. package/src/Object.test.ts +293 -0
  205. package/src/Object.ts +5 -4
  206. package/src/Option.test.ts +104 -0
  207. package/src/Option.ts +1 -2
  208. package/src/Order.test.ts +56 -0
  209. package/src/Platform.ts +2 -0
  210. package/src/Polyfills.ts +3 -4
  211. package/src/Random.test.ts +89 -0
  212. package/src/Random.ts +1 -1
  213. package/src/Ref.test.ts +139 -0
  214. package/src/RefCount.test.ts +184 -0
  215. package/src/Relation.test.ts +505 -0
  216. package/src/Resource.test.ts +4623 -0
  217. package/src/Result.test.ts +1829 -0
  218. package/src/Result.ts +49 -54
  219. package/src/Schedule.test.ts +1554 -0
  220. package/src/Set.test.ts +279 -0
  221. package/src/Set.ts +6 -6
  222. package/src/Sqlite.ts +1 -1
  223. package/src/Store.test.ts +288 -0
  224. package/src/String.test.ts +54 -0
  225. package/src/String.ts +3 -3
  226. package/src/Task.test.ts +10820 -0
  227. package/src/Task.ts +38 -43
  228. package/src/Test.test.ts +88 -0
  229. package/src/Test.ts +49 -3
  230. package/src/Time.test.ts +926 -0
  231. package/src/Time.ts +13 -21
  232. package/src/Type.base64.test.ts +88 -0
  233. package/src/Type.test.ts +20465 -0
  234. package/src/Type.ts +114 -111
  235. package/src/Types.test.ts +324 -0
  236. package/src/Types.ts +13 -13
  237. package/src/WebSocket.ts +4 -7
  238. package/src/Worker.test.ts +755 -0
  239. package/src/Worker.ts +13 -18
  240. package/src/index.ts +1 -1
  241. package/src/intl/_en.ts +1 -1
  242. package/src/intl/ar.ts +1 -1
  243. package/src/intl/bn.ts +1 -1
  244. package/src/intl/ca.ts +1 -1
  245. package/src/intl/cs.ts +1 -1
  246. package/src/intl/da.ts +1 -1
  247. package/src/intl/de.ts +1 -1
  248. package/src/intl/el.ts +1 -1
  249. package/src/intl/es.ts +1 -1
  250. package/src/intl/fa.ts +1 -1
  251. package/src/intl/fi.ts +1 -1
  252. package/src/intl/fil.ts +1 -1
  253. package/src/intl/fr.ts +1 -1
  254. package/src/intl/he.ts +1 -1
  255. package/src/intl/hi.ts +1 -1
  256. package/src/intl/hr.ts +1 -1
  257. package/src/intl/hu.ts +1 -1
  258. package/src/intl/id.ts +1 -1
  259. package/src/intl/intl.test.ts +3106 -0
  260. package/src/intl/it.ts +1 -1
  261. package/src/intl/ja.ts +1 -1
  262. package/src/intl/ko.ts +1 -1
  263. package/src/intl/ml.ts +1 -1
  264. package/src/intl/mr.ts +1 -1
  265. package/src/intl/ms.ts +1 -1
  266. package/src/intl/nb.ts +1 -1
  267. package/src/intl/nl.ts +1 -1
  268. package/src/intl/pa.ts +1 -1
  269. package/src/intl/pl.ts +1 -1
  270. package/src/intl/pt-BR.ts +1 -1
  271. package/src/intl/pt.ts +1 -1
  272. package/src/intl/ro.ts +1 -1
  273. package/src/intl/sk.ts +1 -1
  274. package/src/intl/sl.ts +1 -1
  275. package/src/intl/sv.ts +1 -1
  276. package/src/intl/sw.ts +1 -1
  277. package/src/intl/ta.ts +1 -1
  278. package/src/intl/te.ts +1 -1
  279. package/src/intl/th.ts +1 -1
  280. package/src/intl/tr.ts +1 -1
  281. package/src/intl/uk.ts +1 -1
  282. package/src/intl/ur.ts +1 -1
  283. package/src/intl/vi.ts +1 -1
  284. package/src/intl/zh-CN.ts +1 -1
  285. package/src/intl/zh-TW.ts +1 -1
  286. package/src/local-first/Evolu.test.ts +1921 -0
  287. package/src/local-first/Evolu.ts +18 -14
  288. package/src/local-first/Owner.test.ts +83 -0
  289. package/src/local-first/Protocol.test.ts +1037 -0
  290. package/src/local-first/Protocol.ts +58 -261
  291. package/src/local-first/Query.test.ts +349 -0
  292. package/src/local-first/Query.ts +11 -11
  293. package/src/local-first/Relay.ts +2 -2
  294. package/src/local-first/Schema.ts +3 -5
  295. package/src/local-first/Shared.test.ts +1828 -0
  296. package/src/local-first/Shared.ts +9 -8
  297. package/src/local-first/Storage.ts +4 -4
  298. package/src/local-first/Timestamp.test.ts +374 -0
  299. package/src/local-first/Timestamp.ts +22 -10
  300. package/dist/src/Buffer.d.ts.map +0 -1
package/src/Time.ts CHANGED
@@ -105,8 +105,8 @@ export const createTime = (): Time => {
105
105
  now,
106
106
 
107
107
  performance: {
108
- timeOrigin: globalThis.performance.timeOrigin as PerformanceTimeOrigin,
109
- now: () => globalThis.performance.now() as PerformanceTime,
108
+ timeOrigin: performance.timeOrigin as PerformanceTimeOrigin,
109
+ now: () => performance.now() as PerformanceTime,
110
110
  },
111
111
 
112
112
  setTimeout: (callback, duration) =>
@@ -125,10 +125,10 @@ const scheduleNativeTimeout = (
125
125
  ): TimeoutId => {
126
126
  const delay = durationToMillis(duration);
127
127
  let cancelled = false;
128
- let nativeId: ReturnType<typeof globalThis.setTimeout>;
128
+ let nativeId: ReturnType<typeof setTimeout>;
129
129
 
130
130
  if (delay <= maxNativeTimeoutMillis) {
131
- nativeId = globalThis.setTimeout(() => {
131
+ nativeId = setTimeout(() => {
132
132
  if (cancelled) return;
133
133
  cancelled = true;
134
134
  callback();
@@ -143,7 +143,7 @@ const scheduleNativeTimeout = (
143
143
 
144
144
  const remaining = deadline - getSystemNowMillis();
145
145
  if (remaining > 0) {
146
- nativeId = globalThis.setTimeout(
146
+ nativeId = setTimeout(
147
147
  onTimeout,
148
148
  Math.min(remaining, maxNativeTimeoutMillis),
149
149
  );
@@ -154,14 +154,14 @@ const scheduleNativeTimeout = (
154
154
  callback();
155
155
  };
156
156
 
157
- nativeId = globalThis.setTimeout(onTimeout, maxNativeTimeoutMillis);
157
+ nativeId = setTimeout(onTimeout, maxNativeTimeoutMillis);
158
158
  }
159
159
 
160
160
  return {
161
161
  owner,
162
162
  clear: () => {
163
163
  cancelled = true;
164
- globalThis.clearTimeout(nativeId);
164
+ clearTimeout(nativeId);
165
165
  },
166
166
  } as unknown as TimeoutId;
167
167
  };
@@ -173,7 +173,7 @@ const scheduleNativeTimeout = (
173
173
  */
174
174
  const maxNativeTimeoutMillis = 2 ** 31 - 1;
175
175
 
176
- const getSystemNowMillis = (): Millis => Millis.orThrow(globalThis.Date.now());
176
+ const getSystemNowMillis = (): Millis => Millis.orThrow(Date.now());
177
177
 
178
178
  const clearTimeoutId = (owner: symbol, id: TimeoutId): void => {
179
179
  const internal = id as unknown as TimeoutIdInternal;
@@ -356,7 +356,7 @@ export const saturateMillis = (value: NonNaNNumber): Millis =>
356
356
  * that always produces a valid ISO string.
357
357
  */
358
358
  export const millisToDateIso = (value: Millis): DateIso =>
359
- new globalThis.Date(value).toISOString() as DateIso;
359
+ new Date(value).toISOString() as DateIso;
360
360
 
361
361
  /** Unix epoch milliseconds used as the origin for {@link PerformanceTime}. */
362
362
  export type PerformanceTimeOrigin = number & Brand<"PerformanceTimeOrigin">;
@@ -394,7 +394,7 @@ export const performanceDurationBetween = (
394
394
  * const readableSchedule = spaced("1s");
395
395
  * const validatedSchedule = spaced(Millis.orThrow(1000));
396
396
  *
397
- * assertType<typeof validatedSchedule, typeof readableSchedule>();
397
+ * assertType<typeof readableSchedule, typeof validatedSchedule>();
398
398
  * ```
399
399
  */
400
400
  export type Duration = DurationLiteral | Millis;
@@ -413,7 +413,7 @@ export type Duration = DurationLiteral | Millis;
413
413
  * const readableSleep = sleep("1s");
414
414
  * const validatedSleep = sleep(PositiveMillis.orThrow(1000));
415
415
  *
416
- * assertType<typeof validatedSleep, typeof readableSleep>();
416
+ * assertType<typeof readableSleep, typeof validatedSleep>();
417
417
  * ```
418
418
  */
419
419
  export type PositiveDuration = DurationLiteral | PositiveMillis;
@@ -665,15 +665,7 @@ export const formatMillisAsDuration = (millis: Millis): string => {
665
665
  * Millis,
666
666
  * } from "@evolu/common";
667
667
  *
668
- * const timestamp = new globalThis.Date(
669
- * 2026,
670
- * 0,
671
- * 28,
672
- * 14,
673
- * 32,
674
- * 15,
675
- * 234,
676
- * ).getTime();
668
+ * const timestamp = new Date(2026, 0, 28, 14, 32, 15, 234).getTime();
677
669
  * assertEqual(
678
670
  * formatMillisAsClockTime(Millis.orThrow(timestamp)),
679
671
  * "14:32:15.234",
@@ -681,7 +673,7 @@ export const formatMillisAsDuration = (millis: Millis): string => {
681
673
  * ```
682
674
  */
683
675
  export const formatMillisAsClockTime = (millis: Millis): string => {
684
- const date = new globalThis.Date(millis);
676
+ const date = new Date(millis);
685
677
  const hours = date.getHours().toString().padStart(2, "0");
686
678
  const minutes = date.getMinutes().toString().padStart(2, "0");
687
679
  const seconds = date.getSeconds().toString().padStart(2, "0");
@@ -0,0 +1,88 @@
1
+ import { afterEach, beforeEach, describe, it, mock } from "node:test";
2
+ import { assertEqualBytes, assertEqual, assertTrue } from "./Assert.ts";
3
+
4
+ // Keep this coverage in a separate test file. Per-file process isolation gives
5
+ // it a fresh module cache and globals, so Type.ts is first loaded after
6
+ // Platform.ts is mocked and temporary Uint8Array mutations cannot affect
7
+ // Type.test.ts.
8
+ const toBase64Descriptor = Object.getOwnPropertyDescriptor(
9
+ Uint8Array.prototype,
10
+ "toBase64",
11
+ );
12
+ const fromBase64Descriptor = Object.getOwnPropertyDescriptor(
13
+ Uint8Array,
14
+ "fromBase64",
15
+ );
16
+
17
+ mock.module("./Platform.ts", {
18
+ // @ts-expect-error -- Node.js 24.20 replaces the deprecated namedExports option with exports, which @types/node 24.13 does not declare yet.
19
+ exports: { hasNodeBuffer: false },
20
+ });
21
+
22
+ const { base64UrlToUint8Array, uint8ArrayToBase64Url } =
23
+ await import("./Type.ts");
24
+
25
+ const restoreBase64Methods = (): void => {
26
+ if (toBase64Descriptor === undefined) {
27
+ Reflect.deleteProperty(Uint8Array.prototype, "toBase64");
28
+ } else {
29
+ // oxlint-disable-next-line eslint/no-extend-native -- The test restores the native method it temporarily replaces.
30
+ Object.defineProperty(Uint8Array.prototype, "toBase64", toBase64Descriptor);
31
+ }
32
+
33
+ if (fromBase64Descriptor === undefined) {
34
+ Reflect.deleteProperty(Uint8Array, "fromBase64");
35
+ } else {
36
+ Object.defineProperty(Uint8Array, "fromBase64", fromBase64Descriptor);
37
+ }
38
+ };
39
+
40
+ describe("Base64Url browser implementations", () => {
41
+ beforeEach(() => {
42
+ assertTrue(Reflect.deleteProperty(Uint8Array.prototype, "toBase64"));
43
+ assertTrue(Reflect.deleteProperty(Uint8Array, "fromBase64"));
44
+ });
45
+
46
+ afterEach(() => {
47
+ restoreBase64Methods();
48
+ });
49
+
50
+ it("uses Uint8Array Base64 methods when available", () => {
51
+ // oxlint-disable-next-line eslint/no-extend-native -- The test installs the native API to exercise its code path.
52
+ Object.defineProperty(Uint8Array.prototype, "toBase64", {
53
+ configurable: true,
54
+ value(this: Uint8Array, options: unknown): string {
55
+ assertEqual(options, { alphabet: "base64url", omitPadding: true });
56
+ return Buffer.from(this).toString("base64url");
57
+ },
58
+ });
59
+ Object.defineProperty(Uint8Array, "fromBase64", {
60
+ configurable: true,
61
+ value(value: string, options: unknown): Uint8Array {
62
+ assertEqual(options, { alphabet: "base64url", omitPadding: true });
63
+ return new Uint8Array(Buffer.from(value, "base64url"));
64
+ },
65
+ });
66
+
67
+ const bytes = new Uint8Array([251, 255]);
68
+ const encoded = uint8ArrayToBase64Url(bytes);
69
+
70
+ assertEqual(encoded, "-_8");
71
+ assertEqualBytes(base64UrlToUint8Array(encoded), bytes);
72
+ });
73
+
74
+ it("uses btoa and atob when Uint8Array Base64 methods are unavailable", () => {
75
+ for (const bytes of [
76
+ new Uint8Array(),
77
+ new Uint8Array([0]),
78
+ new Uint8Array([0, 1]),
79
+ new Uint8Array([0, 1, 2]),
80
+ new Uint8Array([251, 255]),
81
+ ]) {
82
+ const encoded = uint8ArrayToBase64Url(bytes);
83
+ assertEqualBytes(base64UrlToUint8Array(encoded), bytes);
84
+ }
85
+
86
+ assertEqual(uint8ArrayToBase64Url(new Uint8Array([251, 255])), "-_8");
87
+ });
88
+ });