@evolu/common 8.0.0-next.4 → 8.0.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 (237) hide show
  1. package/dist/src/Array.d.ts +279 -173
  2. package/dist/src/Array.d.ts.map +1 -1
  3. package/dist/src/Array.js +105 -101
  4. package/dist/src/Assert.d.ts +44 -44
  5. package/dist/src/Assert.d.ts.map +1 -1
  6. package/dist/src/Assert.js +44 -32
  7. package/dist/src/BigInt.d.ts +6 -3
  8. package/dist/src/BigInt.d.ts.map +1 -1
  9. package/dist/src/BigInt.js +5 -2
  10. package/dist/src/Brand.d.ts +27 -40
  11. package/dist/src/Brand.d.ts.map +1 -1
  12. package/dist/src/Buffer.d.ts +27 -11
  13. package/dist/src/Buffer.d.ts.map +1 -1
  14. package/dist/src/Cache.d.ts +9 -4
  15. package/dist/src/Cache.d.ts.map +1 -1
  16. package/dist/src/Cache.js +8 -3
  17. package/dist/src/Callbacks.d.ts +30 -19
  18. package/dist/src/Callbacks.d.ts.map +1 -1
  19. package/dist/src/Console.d.ts +145 -66
  20. package/dist/src/Console.d.ts.map +1 -1
  21. package/dist/src/Console.js +91 -43
  22. package/dist/src/Crypto.d.ts +85 -42
  23. package/dist/src/Crypto.d.ts.map +1 -1
  24. package/dist/src/Crypto.js +44 -20
  25. package/dist/src/Eq.d.ts +87 -21
  26. package/dist/src/Eq.d.ts.map +1 -1
  27. package/dist/src/Eq.js +67 -19
  28. package/dist/src/Error.d.ts +5 -3
  29. package/dist/src/Error.d.ts.map +1 -1
  30. package/dist/src/Error.js +16 -0
  31. package/dist/src/Function.d.ts +119 -58
  32. package/dist/src/Function.d.ts.map +1 -1
  33. package/dist/src/Function.js +86 -43
  34. package/dist/src/Http.d.ts +394 -0
  35. package/dist/src/Http.d.ts.map +1 -0
  36. package/dist/src/Http.js +102 -0
  37. package/dist/src/Identicon.d.ts +16 -7
  38. package/dist/src/Identicon.d.ts.map +1 -1
  39. package/dist/src/Identicon.js +14 -5
  40. package/dist/src/LeakDetector.d.ts +88 -0
  41. package/dist/src/LeakDetector.d.ts.map +1 -0
  42. package/dist/src/LeakDetector.js +86 -0
  43. package/dist/src/LockManager.d.ts +18 -9
  44. package/dist/src/LockManager.d.ts.map +1 -1
  45. package/dist/src/LockManager.js +7 -8
  46. package/dist/src/Lookup.d.ts +43 -13
  47. package/dist/src/Lookup.d.ts.map +1 -1
  48. package/dist/src/Lookup.js +28 -8
  49. package/dist/src/Microtask.d.ts +1 -1
  50. package/dist/src/Microtask.d.ts.map +1 -1
  51. package/dist/src/Microtask.js +3 -7
  52. package/dist/src/Number.d.ts +49 -13
  53. package/dist/src/Number.d.ts.map +1 -1
  54. package/dist/src/Number.js +34 -5
  55. package/dist/src/Object.d.ts +160 -40
  56. package/dist/src/Object.d.ts.map +1 -1
  57. package/dist/src/Object.js +92 -46
  58. package/dist/src/Option.d.ts +10 -7
  59. package/dist/src/Option.d.ts.map +1 -1
  60. package/dist/src/Option.js +9 -6
  61. package/dist/src/Order.d.ts +21 -21
  62. package/dist/src/Order.d.ts.map +1 -1
  63. package/dist/src/Order.js +18 -21
  64. package/dist/src/Platform.d.ts +31 -0
  65. package/dist/src/Platform.d.ts.map +1 -1
  66. package/dist/src/Platform.js +98 -0
  67. package/dist/src/Random.d.ts +32 -17
  68. package/dist/src/Random.d.ts.map +1 -1
  69. package/dist/src/Random.js +12 -8
  70. package/dist/src/Redacted.d.ts +43 -29
  71. package/dist/src/Redacted.d.ts.map +1 -1
  72. package/dist/src/Redacted.js +14 -3
  73. package/dist/src/Ref.d.ts +11 -3
  74. package/dist/src/Ref.d.ts.map +1 -1
  75. package/dist/src/Ref.js +2 -2
  76. package/dist/src/RefCount.d.ts +2 -6
  77. package/dist/src/RefCount.d.ts.map +1 -1
  78. package/dist/src/RefCount.js +33 -90
  79. package/dist/src/Relation.d.ts +70 -5
  80. package/dist/src/Relation.d.ts.map +1 -1
  81. package/dist/src/Relation.js +77 -2
  82. package/dist/src/Resource.d.ts +590 -155
  83. package/dist/src/Resource.d.ts.map +1 -1
  84. package/dist/src/Resource.js +592 -343
  85. package/dist/src/Result.d.ts +838 -191
  86. package/dist/src/Result.d.ts.map +1 -1
  87. package/dist/src/Result.js +163 -102
  88. package/dist/src/Schedule.d.ts +684 -231
  89. package/dist/src/Schedule.d.ts.map +1 -1
  90. package/dist/src/Schedule.js +766 -295
  91. package/dist/src/Set.d.ts +89 -40
  92. package/dist/src/Set.d.ts.map +1 -1
  93. package/dist/src/Set.js +50 -29
  94. package/dist/src/Sqlite.d.ts +29 -72
  95. package/dist/src/Sqlite.d.ts.map +1 -1
  96. package/dist/src/Sqlite.js +41 -46
  97. package/dist/src/StackTrace.d.ts +40 -0
  98. package/dist/src/StackTrace.d.ts.map +1 -0
  99. package/dist/src/StackTrace.js +140 -0
  100. package/dist/src/Store.d.ts +5 -4
  101. package/dist/src/Store.d.ts.map +1 -1
  102. package/dist/src/Store.js +5 -4
  103. package/dist/src/String.d.ts +7 -1
  104. package/dist/src/String.d.ts.map +1 -1
  105. package/dist/src/String.js +20 -7
  106. package/dist/src/Task.d.ts +3572 -1770
  107. package/dist/src/Task.d.ts.map +1 -1
  108. package/dist/src/Task.js +1879 -1274
  109. package/dist/src/Test.d.ts +17 -125
  110. package/dist/src/Test.d.ts.map +1 -1
  111. package/dist/src/Test.js +17 -68
  112. package/dist/src/Time.d.ts +108 -49
  113. package/dist/src/Time.d.ts.map +1 -1
  114. package/dist/src/Time.js +172 -73
  115. package/dist/src/Type.d.ts +3542 -1926
  116. package/dist/src/Type.d.ts.map +1 -1
  117. package/dist/src/Type.js +3070 -1784
  118. package/dist/src/Types.d.ts +200 -108
  119. package/dist/src/Types.d.ts.map +1 -1
  120. package/dist/src/Types.js +39 -8
  121. package/dist/src/WebSocket.d.ts +48 -23
  122. package/dist/src/WebSocket.d.ts.map +1 -1
  123. package/dist/src/WebSocket.js +15 -6
  124. package/dist/src/Worker.d.ts +94 -36
  125. package/dist/src/Worker.d.ts.map +1 -1
  126. package/dist/src/Worker.js +58 -24
  127. package/dist/src/index.d.ts +55 -52
  128. package/dist/src/index.d.ts.map +1 -1
  129. package/dist/src/index.js +3 -1
  130. package/dist/src/intl/cs.d.ts +94 -0
  131. package/dist/src/intl/cs.d.ts.map +1 -0
  132. package/dist/src/intl/cs.js +220 -0
  133. package/dist/src/intl/index.d.ts +7 -0
  134. package/dist/src/intl/index.d.ts.map +1 -0
  135. package/dist/src/intl/index.js +6 -0
  136. package/dist/src/local-first/Db.d.ts +12 -8
  137. package/dist/src/local-first/Db.d.ts.map +1 -1
  138. package/dist/src/local-first/Db.js +109 -132
  139. package/dist/src/local-first/Error.d.ts +4 -4
  140. package/dist/src/local-first/Evolu.d.ts +338 -92
  141. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  142. package/dist/src/local-first/Evolu.js +47 -55
  143. package/dist/src/local-first/LocalAuth.d.ts +4 -4
  144. package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
  145. package/dist/src/local-first/Owner.d.ts +61 -24
  146. package/dist/src/local-first/Owner.d.ts.map +1 -1
  147. package/dist/src/local-first/Owner.js +45 -8
  148. package/dist/src/local-first/Protocol.d.ts +44 -31
  149. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  150. package/dist/src/local-first/Protocol.js +36 -13
  151. package/dist/src/local-first/Query.d.ts +147 -62
  152. package/dist/src/local-first/Query.d.ts.map +1 -1
  153. package/dist/src/local-first/Query.js +112 -58
  154. package/dist/src/local-first/Relay.d.ts +44 -14
  155. package/dist/src/local-first/Relay.d.ts.map +1 -1
  156. package/dist/src/local-first/Schema.d.ts +92 -41
  157. package/dist/src/local-first/Schema.d.ts.map +1 -1
  158. package/dist/src/local-first/Schema.js +25 -8
  159. package/dist/src/local-first/Shared.d.ts +23 -21
  160. package/dist/src/local-first/Shared.d.ts.map +1 -1
  161. package/dist/src/local-first/Shared.js +100 -57
  162. package/dist/src/local-first/Storage.d.ts +53 -32
  163. package/dist/src/local-first/Storage.d.ts.map +1 -1
  164. package/dist/src/local-first/Storage.js +194 -234
  165. package/dist/src/local-first/Timestamp.d.ts +21 -21
  166. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  167. package/dist/src/local-first/Timestamp.js +2 -2
  168. package/dist/src/local-first/index.d.ts +11 -11
  169. package/package.json +14 -13
  170. package/src/Array.ts +306 -205
  171. package/src/Assert.ts +54 -69
  172. package/src/BigInt.ts +6 -3
  173. package/src/Brand.ts +27 -40
  174. package/src/Buffer.ts +28 -12
  175. package/src/Cache.ts +9 -4
  176. package/src/Callbacks.ts +30 -19
  177. package/src/Console.ts +156 -84
  178. package/src/Crypto.ts +83 -41
  179. package/src/Eq.ts +95 -22
  180. package/src/Error.ts +8 -4
  181. package/src/Function.ts +167 -59
  182. package/src/Http.ts +549 -0
  183. package/src/Identicon.ts +16 -7
  184. package/src/LeakDetector.ts +182 -0
  185. package/src/LockManager.ts +43 -39
  186. package/src/Lookup.ts +62 -28
  187. package/src/Microtask.ts +19 -23
  188. package/src/Number.ts +64 -12
  189. package/src/Object.ts +173 -49
  190. package/src/Option.ts +10 -7
  191. package/src/Order.ts +23 -21
  192. package/src/Platform.ts +136 -0
  193. package/src/Polyfills.ts +6 -12
  194. package/src/Random.ts +32 -19
  195. package/src/Redacted.ts +44 -30
  196. package/src/Ref.ts +14 -6
  197. package/src/RefCount.ts +38 -80
  198. package/src/Relation.ts +202 -10
  199. package/src/Resource.ts +1199 -591
  200. package/src/Result.ts +930 -271
  201. package/src/Schedule.ts +859 -343
  202. package/src/Set.ts +89 -40
  203. package/src/Sqlite.ts +144 -138
  204. package/src/StackTrace.ts +230 -0
  205. package/src/Store.ts +8 -7
  206. package/src/String.ts +22 -5
  207. package/src/Task.ts +5101 -2832
  208. package/src/Test.ts +20 -168
  209. package/src/Time.ts +293 -90
  210. package/src/Type.ts +10034 -4117
  211. package/src/Types.ts +227 -110
  212. package/src/WebSocket.ts +64 -36
  213. package/src/Worker.ts +180 -72
  214. package/src/index.ts +55 -52
  215. package/src/intl/cs.ts +388 -0
  216. package/src/intl/index.ts +7 -0
  217. package/src/local-first/Db.ts +152 -179
  218. package/src/local-first/Error.ts +4 -4
  219. package/src/local-first/Evolu.ts +495 -250
  220. package/src/local-first/LocalAuth.ts +6 -12
  221. package/src/local-first/Owner.ts +58 -21
  222. package/src/local-first/Protocol.ts +49 -31
  223. package/src/local-first/Query.ts +146 -61
  224. package/src/local-first/Relay.ts +51 -21
  225. package/src/local-first/Schema.ts +109 -51
  226. package/src/local-first/Shared.ts +266 -226
  227. package/src/local-first/Storage.ts +266 -264
  228. package/src/local-first/Timestamp.ts +25 -18
  229. package/src/local-first/index.ts +11 -11
  230. package/dist/src/Skiplist.d.ts +0 -28
  231. package/dist/src/Skiplist.d.ts.map +0 -1
  232. package/dist/src/Skiplist.js +0 -64
  233. package/dist/src/Tracer.d.ts +0 -48
  234. package/dist/src/Tracer.d.ts.map +0 -1
  235. package/dist/src/Tracer.js +0 -6
  236. package/src/Skiplist.ts +0 -108
  237. package/src/Tracer.ts +0 -54
@@ -20,8 +20,9 @@
20
20
  *
21
21
  * const scores = [3, 1, 2];
22
22
  * const leaderboard = sortScores(scores);
23
- * leaderboard; // [1, 2, 3]
24
- * scores; // [1, 2, 3] — original order lost!
23
+ * expect(leaderboard).toEqual([1, 2, 3]);
24
+ * expect(scores).toEqual([1, 2, 3]);
25
+ * expect(leaderboard).toBe(scores);
25
26
  * ```
26
27
  *
27
28
  * Imagine every method doing that.
@@ -30,71 +31,50 @@
30
31
  * instead:
31
32
  *
32
33
  * ```ts
34
+ * import { sortArray } from "@evolu/common";
35
+ *
33
36
  * const sortScores = (arr: ReadonlyArray<number>) =>
34
37
  * sortArray(arr, (a, b) => a - b);
35
38
  *
36
39
  * const scores: ReadonlyArray<number> = [3, 1, 2];
37
40
  * const leaderboard = sortScores(scores);
38
- * leaderboard; // [1, 2, 3]
39
- * scores; // [3, 1, 2] — safe!
41
+ * expect(leaderboard).toEqual([1, 2, 3]);
42
+ * expect(scores).toEqual([3, 1, 2]);
43
+ * expect(leaderboard).not.toBe(scores);
40
44
  * ```
41
45
  *
42
46
  * Even better, require a {@link NonEmptyReadonlyArray} — there's nothing to sort
43
47
  * if the array is empty anyway:
44
48
  *
45
49
  * ```ts
50
+ * import { sortArray, type NonEmptyReadonlyArray } from "@evolu/common";
51
+ *
46
52
  * const sortScores = (arr: NonEmptyReadonlyArray<number>) =>
47
53
  * sortArray(arr, (a, b) => a - b);
54
+ *
55
+ * const leaderboard = sortScores([3, 1, 2]);
56
+ * expect(leaderboard).toEqual([1, 2, 3]);
57
+ * expectTypeOf(leaderboard).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
48
58
  * ```
49
59
  *
50
60
  * Sorting an empty array isn't expensive, but functions can have side effects
51
61
  * like database queries or network requests. Using non-empty arrays whenever
52
62
  * possible is a good convention.
53
63
  *
54
- * For performance-critical cases where mutation is needed, Evolu provides
55
- * {@link shiftFromArray} and {@link popFromArray} — but only because they improve
56
- * type safety by returning a guaranteed `T` rather than an optional value.
57
- *
58
64
  * ### When to use native methods
59
65
  *
60
66
  * These helpers only exist where they add type-level value. Native methods like
61
67
  * `find`, `some`, `every`, `includes`, `indexOf`, and `findIndex` work well on
62
68
  * readonly arrays without mutation — use them directly.
63
69
  *
64
- * ## Examples
65
- *
66
70
  * ```ts
67
- * // Types - compile-time guarantee of at least one element
68
- * const _valid: NonEmptyReadonlyArray<number> = [1, 2, 3];
69
- * // ts-expect-error - empty array is not a valid NonEmptyReadonlyArray
70
- * const _invalid: NonEmptyReadonlyArray<number> = [];
71
- *
72
- * // Type guards
73
- * const arr: ReadonlyArray<number> = [1, 2, 3];
74
- * if (isNonEmptyArray(arr)) {
75
- * firstInArray(arr);
76
- * }
77
- *
78
- * // Transformations
79
- * const appended = appendToArray([1, 2, 3], 4); // [1, 2, 3, 4]
80
- * const prepended = prependToArray([2, 3], 1); // [1, 2, 3]
81
- * const readonly: ReadonlyArray<number> = [1, 2, 3];
82
- * const mapped = mapArray(readonly, (x) => x * 2); // [2, 4, 6]
83
- * const filtered = filterArray(readonly, (x) => x > 1); // [2, 3]
84
- * const deduped = dedupeArray([1, 2, 1, 3, 2]); // [1, 2, 3]
85
- * const [evens, odds] = partitionArray(
86
- * [1, 2, 3, 4, 5],
87
- * (x) => x % 2 === 0,
88
- * );
71
+ * import { type NonEmptyReadonlyArray } from "@evolu/common";
89
72
  *
90
- * // Accessors
91
- * const first = firstInArray(["a", "b", "c"]); // "a"
92
- * const last = lastInArray(["a", "b", "c"]); // "c"
73
+ * const valid: NonEmptyReadonlyArray<number> = [1, 2, 3];
74
+ * // @ts-expect-error An empty array is not non-empty.
75
+ * const invalid: NonEmptyReadonlyArray<number> = [];
93
76
  *
94
- * // Mutations
95
- * const mutable: NonEmptyArray<number> = [1, 2, 3];
96
- * shiftFromArray(mutable); // 1 (guaranteed to exist)
97
- * mutable; // [2, 3]
77
+ * expect(valid.find((value) => value === 2)).toBe(2);
98
78
  * ```
99
79
  *
100
80
  * ## Composition
@@ -103,16 +83,51 @@
103
83
  * because it's natural for single operations:
104
84
  *
105
85
  * ```ts
86
+ * import { mapArray } from "@evolu/common";
87
+ *
88
+ * interface Message {
89
+ * readonly timestamp: number;
90
+ * }
91
+ *
92
+ * const messages: ReadonlyArray<Message> = [
93
+ * { timestamp: 10 },
94
+ * { timestamp: 20 },
95
+ * ];
106
96
  * const timestamps = mapArray(messages, (m) => m.timestamp);
97
+ * expect(timestamps).toEqual([10, 20]);
107
98
  * ```
108
99
  *
109
100
  * Data-first style also reads well for a few operations, often fitting on a
110
101
  * line:
111
102
  *
112
103
  * ```ts
113
- * const cheapest = firstInArray(sortArray(prices, orderNumber));
104
+ * import {
105
+ * dedupeArray,
106
+ * filterArray,
107
+ * firstInArray,
108
+ * isNonEmptyArray,
109
+ * lastInArray,
110
+ * mapArray,
111
+ * orderNumber,
112
+ * sortArray,
113
+ * } from "@evolu/common";
114
+ *
115
+ * const cheapest = firstInArray(sortArray([30, 10, 20], orderNumber));
116
+ * expect(cheapest).toBe(10);
117
+ *
118
+ * const users = [{ name: "Ada" }, { name: "Linus" }, { name: "Ada" }];
114
119
  * const uniqueNames = dedupeArray(mapArray(users, (u) => u.name));
115
- * const latestDone = lastInArray(filterArray(jobs, isCompletedJob));
120
+ * expect(uniqueNames).toEqual(["Ada", "Linus"]);
121
+ *
122
+ * const jobs = [
123
+ * { id: 1, done: false },
124
+ * { id: 2, done: true },
125
+ * ];
126
+ * const completedJobs = filterArray(jobs, (job) => job.done);
127
+ * if (!isNonEmptyArray(completedJobs)) throw new Error("Expected a job");
128
+ * const latestDone = lastInArray(completedJobs);
129
+ *
130
+ * expect(latestDone).toEqual({ id: 2, done: true });
116
131
  * ```
117
132
  *
118
133
  * For more operations, create a function like `getOldestActiveUser` or a
@@ -127,7 +142,6 @@
127
142
  *
128
143
  * @module
129
144
  */
130
- import type { PredicateWithIndex, RefinementWithIndex } from "./Types.js";
131
145
  /**
132
146
  * An array with at least one element.
133
147
  *
@@ -140,6 +154,12 @@ export type NonEmptyArray<T> = [T, ...Array<T>];
140
154
  * @group Types
141
155
  */
142
156
  export type NonEmptyReadonlyArray<T> = readonly [T, ...ReadonlyArray<T>];
157
+ /**
158
+ * A readonly array with at least two elements.
159
+ *
160
+ * @group Types
161
+ */
162
+ export type AtLeastTwoReadonlyArray<T> = readonly [T, T, ...ReadonlyArray<T>];
143
163
  /**
144
164
  * An empty readonly array.
145
165
  *
@@ -154,14 +174,21 @@ export declare const emptyArray: ReadonlyArray<never>;
154
174
  * - Returns readonly arrays
155
175
  * - Accepts length directly: `arrayFrom(3, fn)` instead of `Array.from({ length:
156
176
  * 3 }, fn)`
157
- * - Skips copying if iterable is already an array (safe because readonly)
177
+ * - Returns existing arrays unchanged
158
178
  *
159
- * ### Example
179
+ * ### Creating from iterables and lengths
160
180
  *
161
181
  * ```ts
162
- * arrayFrom(new Set([1, 2, 3])); // ReadonlyArray<number>
163
- * arrayFrom(3, (i) => i * 10); // [0, 10, 20]
164
- * arrayFrom(iterableMaybeArray); // no unnecessary copy
182
+ * import { arrayFrom } from "@evolu/common";
183
+ *
184
+ * const fromSet = arrayFrom(new Set([1, 2, 3]));
185
+ * expect(fromSet).toEqual([1, 2, 3]);
186
+ * expectTypeOf(fromSet).toEqualTypeOf<ReadonlyArray<number>>();
187
+ *
188
+ * expect(arrayFrom(3, (i) => i * 10)).toEqual([0, 10, 20]);
189
+ *
190
+ * const existing: ReadonlyArray<number> = [1, 2, 3];
191
+ * expect(arrayFrom(existing)).toBe(existing);
165
192
  * ```
166
193
  *
167
194
  * Unlike `Array.from`, there's no map parameter for iterables — use
@@ -180,16 +207,22 @@ export declare function arrayFrom<T>(length: number, map: (index: number) => T):
180
207
  * Returns a readonly array and awaits promised items from sync or async
181
208
  * iterables.
182
209
  *
183
- * ### Example
210
+ * ### Awaiting sync and async iterables
184
211
  *
185
212
  * ```ts
186
- * await arrayFromAsync(new Set([1, 2, 3])); // ReadonlyArray<number>
187
- * await arrayFromAsync(
213
+ * import { arrayFromAsync } from "@evolu/common";
214
+ *
215
+ * const fromIterable = await arrayFromAsync(new Set([1, 2, 3]));
216
+ * expect(fromIterable).toEqual([1, 2, 3]);
217
+ *
218
+ * const fromAsyncIterable = await arrayFromAsync(
188
219
  * (async function* () {
189
220
  * yield Promise.resolve(1);
190
221
  * yield Promise.resolve(2);
191
222
  * })(),
192
- * ); // [1, 2]
223
+ * );
224
+ * expect(fromAsyncIterable).toEqual([1, 2]);
225
+ * expectTypeOf(fromAsyncIterable).toEqualTypeOf<ReadonlyArray<number>>();
193
226
  * ```
194
227
  *
195
228
  * Unlike `Array.fromAsync`, there's no map parameter — map the result with
@@ -208,20 +241,25 @@ export declare const arrayFromAsync: <T>(iterable: AsyncIterable<T> | Iterable<T
208
241
  * negated guard is better than `.length === 0` for early returns because
209
242
  * TypeScript narrows the type after the check.
210
243
  *
211
- * ### Example
244
+ * ### Narrowing mutable and readonly arrays
212
245
  *
213
246
  * ```ts
214
- * // Mutable array narrows to NonEmptyArray
215
- * const arr: Array<number> = [1, 2, 3];
216
- * if (isNonEmptyArray(arr)) {
217
- * shiftFromArray(arr); // arr is NonEmptyArray<number>
218
- * }
219
- *
220
- * // Readonly array narrows to NonEmptyReadonlyArray
247
+ * import {
248
+ * firstInArray,
249
+ * isNonEmptyArray,
250
+ * type NonEmptyArray,
251
+ * type NonEmptyReadonlyArray,
252
+ * } from "@evolu/common";
253
+ *
254
+ * const mutable: Array<number> = [1, 2, 3];
221
255
  * const readonly: ReadonlyArray<number> = [1, 2, 3];
222
- * if (isNonEmptyArray(readonly)) {
223
- * firstInArray(readonly); // readonly is NonEmptyReadonlyArray<number>
256
+ * if (!isNonEmptyArray(mutable) || !isNonEmptyArray(readonly)) {
257
+ * throw new Error("Expected values");
224
258
  * }
259
+ *
260
+ * expectTypeOf(mutable).toEqualTypeOf<NonEmptyArray<number>>();
261
+ * expectTypeOf(readonly).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
262
+ * expect(firstInArray(readonly)).toBe(1);
225
263
  * ```
226
264
  *
227
265
  * @group Types
@@ -232,10 +270,17 @@ export declare function isNonEmptyArray<T>(array: ReadonlyArray<T>): array is No
232
270
  /**
233
271
  * Appends an item to an array, returning a new non-empty readonly array.
234
272
  *
235
- * ### Example
273
+ * ### Appending a value
236
274
  *
237
275
  * ```ts
238
- * appendToArray([1, 2, 3], 4); // [1, 2, 3, 4]
276
+ * import {
277
+ * appendToArray,
278
+ * type NonEmptyReadonlyArray,
279
+ * } from "@evolu/common";
280
+ *
281
+ * const values = appendToArray([1, 2, 3], 4);
282
+ * expect(values).toEqual([1, 2, 3, 4]);
283
+ * expectTypeOf(values).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
239
284
  * ```
240
285
  *
241
286
  * @group Transformations
@@ -244,10 +289,17 @@ export declare const appendToArray: <T>(array: ReadonlyArray<T>, item: T) => Non
244
289
  /**
245
290
  * Prepends an item to an array, returning a new non-empty readonly array.
246
291
  *
247
- * ### Example
292
+ * ### Prepending a value
248
293
  *
249
294
  * ```ts
250
- * prependToArray([2, 3], 1); // [1, 2, 3]
295
+ * import {
296
+ * prependToArray,
297
+ * type NonEmptyReadonlyArray,
298
+ * } from "@evolu/common";
299
+ *
300
+ * const values = prependToArray([2, 3], 1);
301
+ * expect(values).toEqual([1, 2, 3]);
302
+ * expectTypeOf(values).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
251
303
  * ```
252
304
  *
253
305
  * @group Transformations
@@ -258,17 +310,29 @@ export declare const prependToArray: <T>(array: ReadonlyArray<T>, item: T) => No
258
310
  *
259
311
  * Preserves non-empty type.
260
312
  *
261
- * ### Example
313
+ * ### Mapping with indexes while preserving non-emptiness
262
314
  *
263
315
  * ```ts
264
- * mapArray([1, 2, 3], (x) => x * 2); // [2, 4, 6]
316
+ * import { mapArray, type NonEmptyReadonlyArray } from "@evolu/common";
317
+ *
318
+ * const values: ReadonlyArray<number> = [1, 2, 3];
319
+ * const indexed = mapArray(values, (value, index) => value + index);
320
+ * expect(indexed).toEqual([1, 3, 5]);
321
+ * expectTypeOf(indexed).toEqualTypeOf<ReadonlyArray<number>>();
322
+ *
323
+ * const nonEmpty: NonEmptyReadonlyArray<number> = [1, 2, 3];
324
+ * expectTypeOf(mapArray(nonEmpty, (x) => x * 2)).toEqualTypeOf<
325
+ * NonEmptyReadonlyArray<number>
326
+ * >();
265
327
  * ```
266
328
  *
329
+ * The mapper receives `(item, index, array)`, matching native `Array.map`.
330
+ *
267
331
  * @group Transformations
268
332
  */
269
- export declare function mapArray<T, U>(array: NonEmptyReadonlyArray<T> | NonEmptyArray<T>, mapper: (item: T, index: number) => U): NonEmptyReadonlyArray<U>;
333
+ export declare function mapArray<T, U>(array: NonEmptyReadonlyArray<T>, mapper: (item: T, index: number, array: ReadonlyArray<T>) => U): NonEmptyReadonlyArray<U>;
270
334
  /** Possibly empty array. */
271
- export declare function mapArray<T, U>(array: ReadonlyArray<T> | Array<T>, mapper: (item: T, index: number) => U): ReadonlyArray<U>;
335
+ export declare function mapArray<T, U>(array: ReadonlyArray<T>, mapper: (item: T, index: number, array: ReadonlyArray<T>) => U): ReadonlyArray<U>;
272
336
  /**
273
337
  * Maps each element to an array and flattens the result.
274
338
  *
@@ -276,15 +340,23 @@ export declare function mapArray<T, U>(array: ReadonlyArray<T> | Array<T>, mappe
276
340
  * non-empty arrays. When called without a mapper, flattens nested arrays using
277
341
  * {@link identity}.
278
342
  *
279
- * ### Example
343
+ * ### Flattening and expanding values
280
344
  *
281
345
  * ```ts
282
- * flatMapArray([
346
+ * import { flatMapArray, type NonEmptyReadonlyArray } from "@evolu/common";
347
+ *
348
+ * const flattened = flatMapArray([
283
349
  * [1, 2],
284
350
  * [3, 4],
285
- * ]); // [1, 2, 3, 4]
286
- *
287
- * flatMapArray([1, 2, 3], (x) => [x, x * 10]); // [1, 10, 2, 20, 3, 30]
351
+ * ]);
352
+ * const values: NonEmptyReadonlyArray<number> = [1, 2, 3];
353
+ * const expanded = flatMapArray(
354
+ * values,
355
+ * (value, index): NonEmptyReadonlyArray<number> => [value, index],
356
+ * );
357
+ * expect(flattened).toEqual([1, 2, 3, 4]);
358
+ * expectTypeOf(expanded).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
359
+ * expect(expanded).toEqual([1, 0, 2, 1, 3, 2]);
288
360
  * ```
289
361
  *
290
362
  * ### Filter and map in one pass
@@ -292,41 +364,56 @@ export declare function mapArray<T, U>(array: ReadonlyArray<T> | Array<T>, mappe
292
364
  * Return `[]` to filter out, `[value]` to keep:
293
365
  *
294
366
  * ```ts
367
+ * import { err, flatMapArray, ok } from "@evolu/common";
368
+ *
369
+ * const validate = (value: number) =>
370
+ * value > 0 ? ok(value) : err(`${value} is not positive`);
371
+ * const fields = [1, -2, 3, -4];
295
372
  * const errors = flatMapArray(fields, (f) => {
296
373
  * const result = validate(f);
297
374
  * return result.ok ? [] : [result.error];
298
375
  * });
376
+ * expect(errors).toEqual(["-2 is not positive", "-4 is not positive"]);
299
377
  * ```
300
378
  *
379
+ * The mapper receives `(item, index, array)`, matching native `Array.flatMap`.
380
+ *
301
381
  * @group Transformations
302
382
  */
303
- export declare function flatMapArray<T>(array: NonEmptyReadonlyArray<NonEmptyReadonlyArray<T> | NonEmptyArray<T>> | NonEmptyArray<NonEmptyReadonlyArray<T> | NonEmptyArray<T>>): NonEmptyReadonlyArray<T>;
383
+ export declare function flatMapArray<T>(array: NonEmptyReadonlyArray<NonEmptyReadonlyArray<T>>): NonEmptyReadonlyArray<T>;
304
384
  /** Possibly empty nested arrays. */
305
- export declare function flatMapArray<T>(array: ReadonlyArray<ReadonlyArray<T> | Array<T>> | Array<ReadonlyArray<T> | Array<T>>): ReadonlyArray<T>;
385
+ export declare function flatMapArray<T>(array: ReadonlyArray<ReadonlyArray<T>>): ReadonlyArray<T>;
306
386
  /** Non-empty with mapper returning non-empty. */
307
- export declare function flatMapArray<T, U>(array: NonEmptyReadonlyArray<T> | NonEmptyArray<T>, mapper: (item: T, index: number) => NonEmptyReadonlyArray<U> | NonEmptyArray<U>): NonEmptyReadonlyArray<U>;
387
+ export declare function flatMapArray<T, U>(array: NonEmptyReadonlyArray<T>, mapper: (item: T, index: number, array: ReadonlyArray<T>) => NonEmptyReadonlyArray<U>): NonEmptyReadonlyArray<U>;
308
388
  /** With mapper function. */
309
- export declare function flatMapArray<T, U>(array: ReadonlyArray<T> | Array<T>, mapper: (item: T, index: number) => ReadonlyArray<U> | Array<U>): ReadonlyArray<U>;
389
+ export declare function flatMapArray<T, U>(array: ReadonlyArray<T>, mapper: (item: T, index: number, array: ReadonlyArray<T>) => ReadonlyArray<U>): ReadonlyArray<U>;
310
390
  /**
311
391
  * Concatenates two arrays, returning a new readonly array.
312
392
  *
313
393
  * Returns a non-empty array when at least one input is non-empty.
314
394
  *
315
- * ### Example
395
+ * ### Concatenating non-empty inputs
316
396
  *
317
397
  * ```ts
318
- * concatArrays([1, 2], [3, 4]); // [1, 2, 3, 4]
319
- * concatArrays([], [1]); // [1] (non-empty)
320
- * concatArrays([1], []); // [1] (non-empty)
398
+ * import { concatArrays, type NonEmptyReadonlyArray } from "@evolu/common";
399
+ *
400
+ * const nonEmpty: NonEmptyReadonlyArray<number> = [1];
401
+ * const joined = concatArrays([1, 2], [3, 4]);
402
+ * const fromLeft = concatArrays(nonEmpty, []);
403
+ * const fromRight = concatArrays([], nonEmpty);
404
+ *
405
+ * expect(joined).toEqual([1, 2, 3, 4]);
406
+ * expectTypeOf(fromLeft).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
407
+ * expectTypeOf(fromRight).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
321
408
  * ```
322
409
  *
323
410
  * @group Transformations
324
411
  */
325
- export declare function concatArrays<T>(first: NonEmptyReadonlyArray<T> | NonEmptyArray<T>, second: ReadonlyArray<T> | Array<T>): NonEmptyReadonlyArray<T>;
412
+ export declare function concatArrays<T>(first: NonEmptyReadonlyArray<T>, second: ReadonlyArray<T>): NonEmptyReadonlyArray<T>;
326
413
  /** Second non-empty. */
327
- export declare function concatArrays<T>(first: ReadonlyArray<T> | Array<T>, second: NonEmptyReadonlyArray<T> | NonEmptyArray<T>): NonEmptyReadonlyArray<T>;
414
+ export declare function concatArrays<T>(first: ReadonlyArray<T>, second: NonEmptyReadonlyArray<T>): NonEmptyReadonlyArray<T>;
328
415
  /** Both possibly empty. */
329
- export declare function concatArrays<T>(first: ReadonlyArray<T> | Array<T>, second: ReadonlyArray<T> | Array<T>): ReadonlyArray<T>;
416
+ export declare function concatArrays<T>(first: ReadonlyArray<T>, second: ReadonlyArray<T>): ReadonlyArray<T>;
330
417
  /**
331
418
  * Filters an array using a predicate or refinement function, returning a new
332
419
  * readonly array.
@@ -335,60 +422,75 @@ export declare function concatArrays<T>(first: ReadonlyArray<T> | Array<T>, seco
335
422
  * TypeScript will narrow the result type to the narrowed type, making it useful
336
423
  * for filtering with Evolu Types like `PositiveInt.is`.
337
424
  *
338
- * ### Example
339
- *
340
425
  * ### With predicate
341
426
  *
342
427
  * ```ts
343
- * filterArray([1, 2, 3, 4, 5], (x) => x % 2 === 0); // [2, 4]
428
+ * import { filterArray } from "@evolu/common";
429
+ *
430
+ * const evens = filterArray([1, 2, 3, 4, 5], (x) => x % 2 === 0);
431
+ * expect(evens).toEqual([2, 4]);
344
432
  * ```
345
433
  *
346
434
  * ### With refinement
347
435
  *
348
436
  * ```ts
349
- * const mixed: ReadonlyArray<NonEmptyString | PositiveInt> = [
350
- * NonEmptyString.orThrow("hello"),
437
+ * import {
438
+ * filterArray,
439
+ * NonEmptyTrimmedString,
440
+ * PositiveInt,
441
+ * } from "@evolu/common";
442
+ *
443
+ * const mixed: ReadonlyArray<NonEmptyTrimmedString | PositiveInt> = [
444
+ * NonEmptyTrimmedString.orThrow("hello"),
351
445
  * PositiveInt.orThrow(42),
352
446
  * ];
353
447
  * const positiveInts = filterArray(mixed, PositiveInt.is);
354
- * // positiveInts: ReadonlyArray<PositiveInt> (narrowed type)
448
+ * expect(positiveInts).toEqual([42]);
449
+ * expectTypeOf(positiveInts).toEqualTypeOf<ReadonlyArray<PositiveInt>>();
355
450
  * ```
356
451
  *
452
+ * The predicate receives `(item, index, array)`, matching native
453
+ * `Array.filter`.
454
+ *
357
455
  * @group Transformations
358
456
  */
359
- export declare function filterArray<T, S extends T>(array: ReadonlyArray<T>, refinement: RefinementWithIndex<T, S>): ReadonlyArray<S>;
457
+ export declare function filterArray<T, S extends T>(array: ReadonlyArray<T>, refinement: (item: T, index: number, array: ReadonlyArray<T>) => item is S): ReadonlyArray<S>;
360
458
  /** With predicate. */
361
- export declare function filterArray<T>(array: ReadonlyArray<T>, predicate: PredicateWithIndex<T>): ReadonlyArray<T>;
459
+ export declare function filterArray<T>(array: ReadonlyArray<T>, predicate: (item: T, index: number, array: ReadonlyArray<T>) => boolean): ReadonlyArray<T>;
362
460
  /**
363
- * Returns a new readonly array with duplicate items removed. If `by` is
364
- * provided, it will be used to derive the key for uniqueness; otherwise values
365
- * are used directly. Dedupes by reference equality of values (or extracted keys
366
- * when `by` is used).
461
+ * Returns a new readonly array with duplicate items removed. Items are compared
462
+ * using `Set` equality (SameValueZero): primitives by value, and objects and
463
+ * arrays by reference. If `by` is provided, it derives the comparison key.
367
464
  *
368
465
  * Preserves non-empty type.
369
466
  *
370
- * ### Example
467
+ * ### Deduplicating by value or key
371
468
  *
372
469
  * ```ts
373
- * // Dedupe primitives by value
374
- * dedupeArray([1, 2, 1, 3, 2]); // [1, 2, 3]
470
+ * import { dedupeArray, type NonEmptyReadonlyArray } from "@evolu/common";
375
471
  *
376
- * // Dedupe objects by property
377
- * dedupeArray(
472
+ * const numbers = dedupeArray([1, 2, 1, 3, 2]);
473
+ * const people = dedupeArray(
378
474
  * [
379
475
  * { id: 1, name: "Alice" },
380
476
  * { id: 2, name: "Bob" },
381
477
  * { id: 1, name: "Alice 2" },
382
478
  * ],
383
479
  * (item) => item.id,
384
- * ); // [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }]
480
+ * );
481
+ * expectTypeOf(numbers).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
482
+ * expect(numbers).toEqual([1, 2, 3]);
483
+ * expect(people).toEqual([
484
+ * { id: 1, name: "Alice" },
485
+ * { id: 2, name: "Bob" },
486
+ * ]);
385
487
  * ```
386
488
  *
387
489
  * @group Transformations
388
490
  */
389
- export declare function dedupeArray<T>(array: NonEmptyReadonlyArray<T> | NonEmptyArray<T>, by?: (item: T) => unknown): NonEmptyReadonlyArray<T>;
491
+ export declare function dedupeArray<T>(array: NonEmptyReadonlyArray<T>, by?: (item: T) => unknown): NonEmptyReadonlyArray<T>;
390
492
  /** Possibly empty array. */
391
- export declare function dedupeArray<T>(array: ReadonlyArray<T> | Array<T>, by?: (item: T) => unknown): ReadonlyArray<T>;
493
+ export declare function dedupeArray<T>(array: ReadonlyArray<T>, by?: (item: T) => unknown): ReadonlyArray<T>;
392
494
  /**
393
495
  * Partitions an array into two readonly arrays based on a predicate or
394
496
  * refinement function.
@@ -400,45 +502,61 @@ export declare function dedupeArray<T>(array: ReadonlyArray<T> | Array<T>, by?:
400
502
  * TypeScript will narrow the first array to the narrowed type, making it useful
401
503
  * for filtering with Evolu Types like `PositiveInt.is`.
402
504
  *
403
- * ### Example
404
- *
405
505
  * ### With predicate
406
506
  *
407
507
  * ```ts
508
+ * import { partitionArray } from "@evolu/common";
509
+ *
408
510
  * const [evens, odds] = partitionArray(
409
511
  * [1, 2, 3, 4, 5],
410
512
  * (x) => x % 2 === 0,
411
513
  * );
412
- * evens; // [2, 4]
413
- * odds; // [1, 3, 5]
514
+ * expect(evens).toEqual([2, 4]);
515
+ * expect(odds).toEqual([1, 3, 5]);
414
516
  * ```
415
517
  *
416
518
  * ### With refinement
417
519
  *
418
520
  * ```ts
419
- * const mixed: ReadonlyArray<NonEmptyString | PositiveInt> = [
420
- * NonEmptyString.orThrow("hello"),
521
+ * import {
522
+ * NonEmptyTrimmedString,
523
+ * partitionArray,
524
+ * PositiveInt,
525
+ * } from "@evolu/common";
526
+ *
527
+ * const mixed: ReadonlyArray<NonEmptyTrimmedString | PositiveInt> = [
528
+ * NonEmptyTrimmedString.orThrow("hello"),
421
529
  * PositiveInt.orThrow(42),
422
530
  * ];
423
531
  * const [positiveInts, strings] = partitionArray(mixed, PositiveInt.is);
424
- * // positiveInts: ReadonlyArray<PositiveInt> (narrowed type)
425
- * // strings: ReadonlyArray<NonEmptyString> (Exclude<T, PositiveInt>)
532
+ * expect(positiveInts).toEqual([42]);
533
+ * expectTypeOf(positiveInts).toEqualTypeOf<ReadonlyArray<PositiveInt>>();
534
+ * expectTypeOf(strings).toEqualTypeOf<
535
+ * ReadonlyArray<NonEmptyTrimmedString>
536
+ * >();
426
537
  * ```
427
538
  *
539
+ * The predicate receives `(item, index, array)`.
540
+ *
428
541
  * @group Transformations
429
542
  */
430
- export declare function partitionArray<T, S extends T>(array: ReadonlyArray<T>, refinement: RefinementWithIndex<T, S>): readonly [ReadonlyArray<S>, ReadonlyArray<Exclude<T, S>>];
543
+ export declare function partitionArray<T, S extends T>(array: ReadonlyArray<T>, refinement: (item: T, index: number, array: ReadonlyArray<T>) => item is S): readonly [ReadonlyArray<S>, ReadonlyArray<Exclude<T, S>>];
431
544
  /** With predicate. */
432
- export declare function partitionArray<T>(array: ReadonlyArray<T>, predicate: PredicateWithIndex<T>): readonly [ReadonlyArray<T>, ReadonlyArray<T>];
545
+ export declare function partitionArray<T>(array: ReadonlyArray<T>, predicate: (item: T, index: number, array: ReadonlyArray<T>) => boolean): readonly [ReadonlyArray<T>, ReadonlyArray<T>];
433
546
  /**
434
547
  * Returns a new sorted readonly array.
435
548
  *
436
549
  * Wraps native `toSorted`. Preserves non-empty type.
437
550
  *
438
- * ### Example
551
+ * ### Sorting without mutation
439
552
  *
440
553
  * ```ts
441
- * sortArray([3, 1, 2], (a, b) => a - b); // [1, 2, 3]
554
+ * import { sortArray, type NonEmptyReadonlyArray } from "@evolu/common";
555
+ *
556
+ * const values: NonEmptyReadonlyArray<number> = [3, 1, 2];
557
+ * const sorted = sortArray(values, (a, b) => a - b);
558
+ * expect(sorted).toEqual([1, 2, 3]);
559
+ * expectTypeOf(sorted).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
442
560
  * ```
443
561
  *
444
562
  * @group Transformations
@@ -451,10 +569,15 @@ export declare function sortArray<T>(array: ReadonlyArray<T>, compareFn?: (a: T,
451
569
  *
452
570
  * Wraps native `toReversed`. Preserves non-empty type.
453
571
  *
454
- * ### Example
572
+ * ### Reversing without mutation
455
573
  *
456
574
  * ```ts
457
- * reverseArray([1, 2, 3]); // [3, 2, 1]
575
+ * import { reverseArray, type NonEmptyReadonlyArray } from "@evolu/common";
576
+ *
577
+ * const values: NonEmptyReadonlyArray<number> = [1, 2, 3];
578
+ * const reversed = reverseArray(values);
579
+ * expect(reversed).toEqual([3, 2, 1]);
580
+ * expectTypeOf(reversed).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
458
581
  * ```
459
582
  *
460
583
  * @group Transformations
@@ -467,11 +590,15 @@ export declare function reverseArray<T>(array: ReadonlyArray<T>): ReadonlyArray<
467
590
  *
468
591
  * Wraps native `toSpliced`.
469
592
  *
470
- * ### Example
593
+ * ### Removing and replacing values
471
594
  *
472
595
  * ```ts
473
- * spliceArray([1, 2, 3, 4], 1, 2); // [1, 4]
474
- * spliceArray([1, 2, 3], 1, 1, 10, 11); // [1, 10, 11, 3]
596
+ * import { spliceArray } from "@evolu/common";
597
+ *
598
+ * const values: ReadonlyArray<number> = [1, 2, 3, 4];
599
+ * expect(spliceArray(values, 1, 2)).toEqual([1, 4]);
600
+ * expect(spliceArray([1, 2, 3], 1, 1, 10, 11)).toEqual([1, 10, 11, 3]);
601
+ * expect(values).toEqual([1, 2, 3, 4]);
475
602
  * ```
476
603
  *
477
604
  * @group Transformations
@@ -493,35 +620,49 @@ export type ZipArrayResult<T extends ReadonlyArray<ReadonlyArray<unknown>>> = {
493
620
  * {@link https://github.com/tc39/proposal-array-zip | TC39 Array.zip proposal}
494
621
  * for the pattern this follows.
495
622
  *
496
- * ### Example
623
+ * ### Zipping to the shortest input
497
624
  *
498
625
  * ```ts
499
- * zipArray([
626
+ * import { zipArray, type NonEmptyReadonlyArray } from "@evolu/common";
627
+ *
628
+ * const pairs = zipArray([
500
629
  * [1, 2, 3],
501
630
  * ["a", "b", "c"],
502
631
  * ]);
503
- * // [[1, "a"], [2, "b"], [3, "c"]]
504
- *
505
- * zipArray([
506
- * [1, 2],
507
- * ["a", "b", "c"],
508
- * [true, false],
632
+ * expect(pairs).toEqual([
633
+ * [1, "a"],
634
+ * [2, "b"],
635
+ * [3, "c"],
509
636
  * ]);
510
- * // [[1, "a", true], [2, "b", false]]
637
+ * expect(
638
+ * zipArray([
639
+ * [1, 2],
640
+ * ["a", "b", "c"],
641
+ * [true, false],
642
+ * ]),
643
+ * ).toEqual([
644
+ * [1, "a", true],
645
+ * [2, "b", false],
646
+ * ]);
647
+ * expectTypeOf(pairs).toEqualTypeOf<
648
+ * NonEmptyReadonlyArray<Readonly<[number, string]>>
649
+ * >();
511
650
  * ```
512
651
  *
513
652
  * @group Transformations
514
653
  */
515
654
  export declare function zipArray<T extends NonEmptyReadonlyArray<NonEmptyReadonlyArray<unknown>>>(arrays: T): NonEmptyReadonlyArray<Readonly<ZipArrayResult<T>>>;
516
655
  /** Possibly empty arrays. */
517
- export declare function zipArray<T extends ReadonlyArray<ReadonlyArray<unknown>>>(arrays: T): ReadonlyArray<Readonly<ZipArrayResult<T>>>;
656
+ export declare function zipArray<const T extends ReadonlyArray<ReadonlyArray<unknown>>>(arrays: T): ReadonlyArray<Readonly<ZipArrayResult<T>>>;
518
657
  /**
519
658
  * Returns the first element of a non-empty array.
520
659
  *
521
- * ### Example
660
+ * ### Reading the first value
522
661
  *
523
662
  * ```ts
524
- * firstInArray(["a", "b", "c"]); // "a"
663
+ * import { firstInArray } from "@evolu/common";
664
+ *
665
+ * expect(firstInArray(["a", "b", "c"])).toBe("a");
525
666
  * ```
526
667
  *
527
668
  * @group Accessors
@@ -530,50 +671,15 @@ export declare const firstInArray: <T>(array: NonEmptyReadonlyArray<T>) => T;
530
671
  /**
531
672
  * Returns the last element of a non-empty array.
532
673
  *
533
- * ### Example
674
+ * ### Reading the last value
534
675
  *
535
676
  * ```ts
536
- * lastInArray(["a", "b", "c"]); // "c"
677
+ * import { lastInArray } from "@evolu/common";
678
+ *
679
+ * expect(lastInArray(["a", "b", "c"])).toBe("c");
537
680
  * ```
538
681
  *
539
682
  * @group Accessors
540
683
  */
541
684
  export declare const lastInArray: <T>(array: NonEmptyReadonlyArray<T>) => T;
542
- /**
543
- * Shifts (removes and returns) the first element from a non-empty mutable
544
- * array.
545
- *
546
- * **Mutates** the original array.
547
- *
548
- * ### Example
549
- *
550
- * ```ts
551
- * // Process a queue of callbacks
552
- * const waitingQueue: Array<() => void> = [callback1, callback2];
553
- * if (isNonEmptyArray(waitingQueue)) {
554
- * shiftFromArray(waitingQueue)(); // Remove and immediately invoke
555
- * }
556
- * ```
557
- *
558
- * @group Mutations
559
- */
560
- export declare const shiftFromArray: <T>(array: NonEmptyArray<T>) => T;
561
- /**
562
- * Pops (removes and returns) the last element from a non-empty mutable array.
563
- *
564
- * **Mutates** the original array.
565
- *
566
- * ### Example
567
- *
568
- * ```ts
569
- * // Process a stack of callbacks (LIFO)
570
- * const callbackStack: Array<() => void> = [callback1, callback2];
571
- * if (isNonEmptyArray(callbackStack)) {
572
- * popFromArray(callbackStack)(); // Remove and immediately invoke
573
- * }
574
- * ```
575
- *
576
- * @group Mutations
577
- */
578
- export declare const popFromArray: <T>(array: NonEmptyArray<T>) => T;
579
685
  //# sourceMappingURL=Array.d.ts.map