@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.
- package/dist/src/Array.d.ts +279 -173
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +105 -101
- package/dist/src/Assert.d.ts +44 -44
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +44 -32
- package/dist/src/BigInt.d.ts +6 -3
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -2
- package/dist/src/Brand.d.ts +27 -40
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Buffer.d.ts +27 -11
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Cache.d.ts +9 -4
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +8 -3
- package/dist/src/Callbacks.d.ts +30 -19
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Console.d.ts +145 -66
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +91 -43
- package/dist/src/Crypto.d.ts +85 -42
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +44 -20
- package/dist/src/Eq.d.ts +87 -21
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +67 -19
- package/dist/src/Error.d.ts +5 -3
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +16 -0
- package/dist/src/Function.d.ts +119 -58
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +86 -43
- package/dist/src/Http.d.ts +394 -0
- package/dist/src/Http.d.ts.map +1 -0
- package/dist/src/Http.js +102 -0
- package/dist/src/Identicon.d.ts +16 -7
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +14 -5
- package/dist/src/LeakDetector.d.ts +88 -0
- package/dist/src/LeakDetector.d.ts.map +1 -0
- package/dist/src/LeakDetector.js +86 -0
- package/dist/src/LockManager.d.ts +18 -9
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +7 -8
- package/dist/src/Lookup.d.ts +43 -13
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +28 -8
- package/dist/src/Microtask.d.ts +1 -1
- package/dist/src/Microtask.d.ts.map +1 -1
- package/dist/src/Microtask.js +3 -7
- package/dist/src/Number.d.ts +49 -13
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +34 -5
- package/dist/src/Object.d.ts +160 -40
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +92 -46
- package/dist/src/Option.d.ts +10 -7
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +9 -6
- package/dist/src/Order.d.ts +21 -21
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +18 -21
- package/dist/src/Platform.d.ts +31 -0
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +98 -0
- package/dist/src/Random.d.ts +32 -17
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +12 -8
- package/dist/src/Redacted.d.ts +43 -29
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +14 -3
- package/dist/src/Ref.d.ts +11 -3
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +2 -2
- package/dist/src/RefCount.d.ts +2 -6
- package/dist/src/RefCount.d.ts.map +1 -1
- package/dist/src/RefCount.js +33 -90
- package/dist/src/Relation.d.ts +70 -5
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +77 -2
- package/dist/src/Resource.d.ts +590 -155
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +592 -343
- package/dist/src/Result.d.ts +838 -191
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +163 -102
- package/dist/src/Schedule.d.ts +684 -231
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +766 -295
- package/dist/src/Set.d.ts +89 -40
- package/dist/src/Set.d.ts.map +1 -1
- package/dist/src/Set.js +50 -29
- package/dist/src/Sqlite.d.ts +29 -72
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +41 -46
- package/dist/src/StackTrace.d.ts +40 -0
- package/dist/src/StackTrace.d.ts.map +1 -0
- package/dist/src/StackTrace.js +140 -0
- package/dist/src/Store.d.ts +5 -4
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +5 -4
- package/dist/src/String.d.ts +7 -1
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +20 -7
- package/dist/src/Task.d.ts +3572 -1770
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1879 -1274
- package/dist/src/Test.d.ts +17 -125
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +17 -68
- package/dist/src/Time.d.ts +108 -49
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +172 -73
- package/dist/src/Type.d.ts +3542 -1926
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +3070 -1784
- package/dist/src/Types.d.ts +200 -108
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +39 -8
- package/dist/src/WebSocket.d.ts +48 -23
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +15 -6
- package/dist/src/Worker.d.ts +94 -36
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +58 -24
- package/dist/src/index.d.ts +55 -52
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/intl/cs.d.ts +94 -0
- package/dist/src/intl/cs.d.ts.map +1 -0
- package/dist/src/intl/cs.js +220 -0
- package/dist/src/intl/index.d.ts +7 -0
- package/dist/src/intl/index.d.ts.map +1 -0
- package/dist/src/intl/index.js +6 -0
- package/dist/src/local-first/Db.d.ts +12 -8
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +109 -132
- package/dist/src/local-first/Error.d.ts +4 -4
- package/dist/src/local-first/Evolu.d.ts +338 -92
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +47 -55
- package/dist/src/local-first/LocalAuth.d.ts +4 -4
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/Owner.d.ts +61 -24
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +45 -8
- package/dist/src/local-first/Protocol.d.ts +44 -31
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +36 -13
- package/dist/src/local-first/Query.d.ts +147 -62
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +112 -58
- package/dist/src/local-first/Relay.d.ts +44 -14
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +92 -41
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +25 -8
- package/dist/src/local-first/Shared.d.ts +23 -21
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +100 -57
- package/dist/src/local-first/Storage.d.ts +53 -32
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +194 -234
- package/dist/src/local-first/Timestamp.d.ts +21 -21
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +2 -2
- package/dist/src/local-first/index.d.ts +11 -11
- package/package.json +14 -13
- package/src/Array.ts +306 -205
- package/src/Assert.ts +54 -69
- package/src/BigInt.ts +6 -3
- package/src/Brand.ts +27 -40
- package/src/Buffer.ts +28 -12
- package/src/Cache.ts +9 -4
- package/src/Callbacks.ts +30 -19
- package/src/Console.ts +156 -84
- package/src/Crypto.ts +83 -41
- package/src/Eq.ts +95 -22
- package/src/Error.ts +8 -4
- package/src/Function.ts +167 -59
- package/src/Http.ts +549 -0
- package/src/Identicon.ts +16 -7
- package/src/LeakDetector.ts +182 -0
- package/src/LockManager.ts +43 -39
- package/src/Lookup.ts +62 -28
- package/src/Microtask.ts +19 -23
- package/src/Number.ts +64 -12
- package/src/Object.ts +173 -49
- package/src/Option.ts +10 -7
- package/src/Order.ts +23 -21
- package/src/Platform.ts +136 -0
- package/src/Polyfills.ts +6 -12
- package/src/Random.ts +32 -19
- package/src/Redacted.ts +44 -30
- package/src/Ref.ts +14 -6
- package/src/RefCount.ts +38 -80
- package/src/Relation.ts +202 -10
- package/src/Resource.ts +1199 -591
- package/src/Result.ts +930 -271
- package/src/Schedule.ts +859 -343
- package/src/Set.ts +89 -40
- package/src/Sqlite.ts +144 -138
- package/src/StackTrace.ts +230 -0
- package/src/Store.ts +8 -7
- package/src/String.ts +22 -5
- package/src/Task.ts +5101 -2832
- package/src/Test.ts +20 -168
- package/src/Time.ts +293 -90
- package/src/Type.ts +10034 -4117
- package/src/Types.ts +227 -110
- package/src/WebSocket.ts +64 -36
- package/src/Worker.ts +180 -72
- package/src/index.ts +55 -52
- package/src/intl/cs.ts +388 -0
- package/src/intl/index.ts +7 -0
- package/src/local-first/Db.ts +152 -179
- package/src/local-first/Error.ts +4 -4
- package/src/local-first/Evolu.ts +495 -250
- package/src/local-first/LocalAuth.ts +6 -12
- package/src/local-first/Owner.ts +58 -21
- package/src/local-first/Protocol.ts +49 -31
- package/src/local-first/Query.ts +146 -61
- package/src/local-first/Relay.ts +51 -21
- package/src/local-first/Schema.ts +109 -51
- package/src/local-first/Shared.ts +266 -226
- package/src/local-first/Storage.ts +266 -264
- package/src/local-first/Timestamp.ts +25 -18
- package/src/local-first/index.ts +11 -11
- package/dist/src/Skiplist.d.ts +0 -28
- package/dist/src/Skiplist.d.ts.map +0 -1
- package/dist/src/Skiplist.js +0 -64
- package/dist/src/Tracer.d.ts +0 -48
- package/dist/src/Tracer.d.ts.map +0 -1
- package/dist/src/Tracer.js +0 -6
- package/src/Skiplist.ts +0 -108
- package/src/Tracer.ts +0 -54
package/dist/src/Array.d.ts
CHANGED
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
*
|
|
21
21
|
* const scores = [3, 1, 2];
|
|
22
22
|
* const leaderboard = sortScores(scores);
|
|
23
|
-
* leaderboard
|
|
24
|
-
* scores
|
|
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
|
|
39
|
-
* scores
|
|
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
|
-
*
|
|
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
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* const
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* -
|
|
177
|
+
* - Returns existing arrays unchanged
|
|
158
178
|
*
|
|
159
|
-
* ###
|
|
179
|
+
* ### Creating from iterables and lengths
|
|
160
180
|
*
|
|
161
181
|
* ```ts
|
|
162
|
-
* arrayFrom
|
|
163
|
-
*
|
|
164
|
-
* arrayFrom(
|
|
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
|
-
* ###
|
|
210
|
+
* ### Awaiting sync and async iterables
|
|
184
211
|
*
|
|
185
212
|
* ```ts
|
|
186
|
-
*
|
|
187
|
-
*
|
|
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
|
-
* );
|
|
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
|
-
* ###
|
|
244
|
+
* ### Narrowing mutable and readonly arrays
|
|
212
245
|
*
|
|
213
246
|
* ```ts
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* ###
|
|
273
|
+
* ### Appending a value
|
|
236
274
|
*
|
|
237
275
|
* ```ts
|
|
238
|
-
*
|
|
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
|
-
* ###
|
|
292
|
+
* ### Prepending a value
|
|
248
293
|
*
|
|
249
294
|
* ```ts
|
|
250
|
-
*
|
|
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
|
-
* ###
|
|
313
|
+
* ### Mapping with indexes while preserving non-emptiness
|
|
262
314
|
*
|
|
263
315
|
* ```ts
|
|
264
|
-
*
|
|
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
|
|
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
|
|
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
|
-
* ###
|
|
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
|
-
* ]);
|
|
286
|
-
*
|
|
287
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
* ###
|
|
395
|
+
* ### Concatenating non-empty inputs
|
|
316
396
|
*
|
|
317
397
|
* ```ts
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
350
|
-
*
|
|
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
|
-
*
|
|
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:
|
|
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:
|
|
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.
|
|
364
|
-
*
|
|
365
|
-
*
|
|
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
|
-
* ###
|
|
467
|
+
* ### Deduplicating by value or key
|
|
371
468
|
*
|
|
372
469
|
* ```ts
|
|
373
|
-
*
|
|
374
|
-
* dedupeArray([1, 2, 1, 3, 2]); // [1, 2, 3]
|
|
470
|
+
* import { dedupeArray, type NonEmptyReadonlyArray } from "@evolu/common";
|
|
375
471
|
*
|
|
376
|
-
*
|
|
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
|
-
* );
|
|
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
|
|
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
|
|
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
|
|
413
|
-
* odds
|
|
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
|
-
*
|
|
420
|
-
*
|
|
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
|
-
*
|
|
425
|
-
*
|
|
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:
|
|
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:
|
|
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
|
-
* ###
|
|
551
|
+
* ### Sorting without mutation
|
|
439
552
|
*
|
|
440
553
|
* ```ts
|
|
441
|
-
*
|
|
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
|
-
* ###
|
|
572
|
+
* ### Reversing without mutation
|
|
455
573
|
*
|
|
456
574
|
* ```ts
|
|
457
|
-
* reverseArray
|
|
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
|
-
* ###
|
|
593
|
+
* ### Removing and replacing values
|
|
471
594
|
*
|
|
472
595
|
* ```ts
|
|
473
|
-
*
|
|
474
|
-
*
|
|
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
|
-
* ###
|
|
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
|
-
*
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
* [
|
|
507
|
-
* ["a", "b", "c"],
|
|
508
|
-
* [true, false],
|
|
632
|
+
* expect(pairs).toEqual([
|
|
633
|
+
* [1, "a"],
|
|
634
|
+
* [2, "b"],
|
|
635
|
+
* [3, "c"],
|
|
509
636
|
* ]);
|
|
510
|
-
*
|
|
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
|
-
* ###
|
|
660
|
+
* ### Reading the first value
|
|
522
661
|
*
|
|
523
662
|
* ```ts
|
|
524
|
-
* firstInArray
|
|
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
|
-
* ###
|
|
674
|
+
* ### Reading the last value
|
|
534
675
|
*
|
|
535
676
|
* ```ts
|
|
536
|
-
* lastInArray
|
|
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
|