@evolu/common 6.0.1-preview.9 → 7.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 (184) hide show
  1. package/README.md +2 -2
  2. package/dist/src/Array.d.ts +256 -12
  3. package/dist/src/Array.d.ts.map +1 -1
  4. package/dist/src/Array.js +215 -9
  5. package/dist/src/Assert.d.ts +0 -13
  6. package/dist/src/Assert.d.ts.map +1 -1
  7. package/dist/src/Assert.js +0 -15
  8. package/dist/src/Brand.d.ts +75 -0
  9. package/dist/src/Brand.d.ts.map +1 -0
  10. package/dist/src/Brand.js +1 -0
  11. package/dist/src/Buffer.d.ts +1 -1
  12. package/dist/src/Buffer.d.ts.map +1 -1
  13. package/dist/src/Buffer.js +8 -7
  14. package/dist/src/Cache.d.ts +44 -0
  15. package/dist/src/Cache.d.ts.map +1 -0
  16. package/dist/src/Cache.js +52 -0
  17. package/dist/src/Callbacks.d.ts +45 -12
  18. package/dist/src/Callbacks.d.ts.map +1 -1
  19. package/dist/src/Callbacks.js +14 -7
  20. package/dist/src/Console.d.ts +31 -6
  21. package/dist/src/Console.d.ts.map +1 -1
  22. package/dist/src/Console.js +72 -9
  23. package/dist/src/Crypto.d.ts +56 -42
  24. package/dist/src/Crypto.d.ts.map +1 -1
  25. package/dist/src/Crypto.js +40 -53
  26. package/dist/src/Evolu/Db.d.ts +162 -74
  27. package/dist/src/Evolu/Db.d.ts.map +1 -1
  28. package/dist/src/Evolu/Db.js +284 -702
  29. package/dist/src/Evolu/Diff.d.ts +3 -3
  30. package/dist/src/Evolu/Diff.d.ts.map +1 -1
  31. package/dist/src/Evolu/Diff.js +7 -5
  32. package/dist/src/Evolu/Evolu.d.ts +213 -133
  33. package/dist/src/Evolu/Evolu.d.ts.map +1 -1
  34. package/dist/src/Evolu/Evolu.js +189 -180
  35. package/dist/src/Evolu/Internal.d.ts +0 -2
  36. package/dist/src/Evolu/Internal.d.ts.map +1 -1
  37. package/dist/src/Evolu/Internal.js +0 -2
  38. package/dist/src/Evolu/LocalAuth.d.ts +150 -0
  39. package/dist/src/Evolu/LocalAuth.d.ts.map +1 -0
  40. package/dist/src/Evolu/LocalAuth.js +174 -0
  41. package/dist/src/Evolu/Owner.d.ts +273 -120
  42. package/dist/src/Evolu/Owner.d.ts.map +1 -1
  43. package/dist/src/Evolu/Owner.js +130 -104
  44. package/dist/src/Evolu/Platform.d.ts +9 -7
  45. package/dist/src/Evolu/Platform.d.ts.map +1 -1
  46. package/dist/src/Evolu/Protocol.d.ts +268 -240
  47. package/dist/src/Evolu/Protocol.d.ts.map +1 -1
  48. package/dist/src/Evolu/Protocol.js +595 -447
  49. package/dist/src/Evolu/Public.d.ts +6 -8
  50. package/dist/src/Evolu/Public.d.ts.map +1 -1
  51. package/dist/src/Evolu/Public.js +2 -3
  52. package/dist/src/Evolu/PublicKysely.d.ts.map +1 -1
  53. package/dist/src/Evolu/PublicKysely.js +3 -4
  54. package/dist/src/Evolu/Query.d.ts +2 -1
  55. package/dist/src/Evolu/Query.d.ts.map +1 -1
  56. package/dist/src/Evolu/Query.js +1 -1
  57. package/dist/src/Evolu/Relay.d.ts +91 -8
  58. package/dist/src/Evolu/Relay.d.ts.map +1 -1
  59. package/dist/src/Evolu/Relay.js +214 -88
  60. package/dist/src/Evolu/Schema.d.ts +125 -47
  61. package/dist/src/Evolu/Schema.d.ts.map +1 -1
  62. package/dist/src/Evolu/Schema.js +175 -31
  63. package/dist/src/Evolu/Storage.d.ts +249 -27
  64. package/dist/src/Evolu/Storage.d.ts.map +1 -1
  65. package/dist/src/Evolu/Storage.js +198 -92
  66. package/dist/src/Evolu/Sync.d.ts +68 -13
  67. package/dist/src/Evolu/Sync.d.ts.map +1 -1
  68. package/dist/src/Evolu/Sync.js +469 -20
  69. package/dist/src/Evolu/Timestamp.d.ts +83 -30
  70. package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
  71. package/dist/src/Evolu/Timestamp.js +79 -34
  72. package/dist/src/Identicon.d.ts +35 -0
  73. package/dist/src/Identicon.d.ts.map +1 -0
  74. package/dist/src/Identicon.js +143 -0
  75. package/dist/src/Instances.d.ts +34 -0
  76. package/dist/src/Instances.d.ts.map +1 -0
  77. package/dist/src/Instances.js +44 -0
  78. package/dist/src/Number.d.ts +4 -3
  79. package/dist/src/Number.d.ts.map +1 -1
  80. package/dist/src/Number.js +5 -4
  81. package/dist/src/Object.d.ts +10 -4
  82. package/dist/src/Object.d.ts.map +1 -1
  83. package/dist/src/Object.js +9 -3
  84. package/dist/src/Platform.d.ts +20 -0
  85. package/dist/src/Platform.d.ts.map +1 -0
  86. package/dist/src/Platform.js +22 -0
  87. package/dist/src/Random.d.ts +3 -2
  88. package/dist/src/Random.d.ts.map +1 -1
  89. package/dist/src/Relation.d.ts +79 -0
  90. package/dist/src/Relation.d.ts.map +1 -0
  91. package/dist/src/Relation.js +127 -0
  92. package/dist/src/Resources.d.ts +118 -0
  93. package/dist/src/Resources.d.ts.map +1 -0
  94. package/dist/src/Resources.js +197 -0
  95. package/dist/src/Result.d.ts +184 -52
  96. package/dist/src/Result.d.ts.map +1 -1
  97. package/dist/src/Result.js +30 -241
  98. package/dist/src/Skiplist.js +2 -1
  99. package/dist/src/Sqlite.d.ts +89 -5
  100. package/dist/src/Sqlite.d.ts.map +1 -1
  101. package/dist/src/Sqlite.js +136 -9
  102. package/dist/src/Task.d.ts +586 -0
  103. package/dist/src/Task.d.ts.map +1 -0
  104. package/dist/src/Task.js +469 -0
  105. package/dist/src/Time.d.ts +66 -1
  106. package/dist/src/Time.d.ts.map +1 -1
  107. package/dist/src/Time.js +99 -5
  108. package/dist/src/Type.d.ts +676 -343
  109. package/dist/src/Type.d.ts.map +1 -1
  110. package/dist/src/Type.js +718 -467
  111. package/dist/src/Types.d.ts +1 -75
  112. package/dist/src/Types.d.ts.map +1 -1
  113. package/dist/src/WebSocket.d.ts +5 -2
  114. package/dist/src/WebSocket.d.ts.map +1 -1
  115. package/dist/src/WebSocket.js +12 -18
  116. package/dist/src/Worker.d.ts +39 -11
  117. package/dist/src/Worker.d.ts.map +1 -1
  118. package/dist/src/Worker.js +22 -4
  119. package/dist/src/index.d.ts +8 -3
  120. package/dist/src/index.d.ts.map +1 -1
  121. package/dist/src/index.js +8 -3
  122. package/package.json +14 -13
  123. package/src/Array.ts +301 -19
  124. package/src/Assert.ts +0 -21
  125. package/src/Brand.ts +75 -0
  126. package/src/Buffer.ts +7 -7
  127. package/src/Cache.ts +85 -0
  128. package/src/Callbacks.ts +62 -22
  129. package/src/Console.ts +91 -11
  130. package/src/Crypto.ts +94 -90
  131. package/src/Evolu/Db.ts +519 -1026
  132. package/src/Evolu/Diff.ts +7 -5
  133. package/src/Evolu/Evolu.ts +476 -360
  134. package/src/Evolu/Internal.ts +0 -2
  135. package/src/Evolu/LocalAuth.ts +463 -0
  136. package/src/Evolu/Owner.ts +355 -228
  137. package/src/Evolu/Platform.ts +9 -9
  138. package/src/Evolu/Protocol.ts +846 -742
  139. package/src/Evolu/Public.ts +7 -14
  140. package/src/Evolu/PublicKysely.ts +4 -5
  141. package/src/Evolu/Query.ts +3 -2
  142. package/src/Evolu/Relay.ts +406 -103
  143. package/src/Evolu/Schema.ts +323 -91
  144. package/src/Evolu/Storage.ts +559 -137
  145. package/src/Evolu/Sync.ts +819 -36
  146. package/src/Evolu/Timestamp.ts +90 -58
  147. package/src/Identicon.ts +197 -0
  148. package/src/Instances.ts +90 -0
  149. package/src/Number.ts +6 -10
  150. package/src/Object.ts +13 -5
  151. package/src/Platform.ts +26 -0
  152. package/src/Random.ts +3 -2
  153. package/src/Relation.ts +234 -0
  154. package/src/Resources.ts +367 -0
  155. package/src/Result.ts +191 -54
  156. package/src/Skiplist.ts +1 -1
  157. package/src/Sqlite.ts +152 -17
  158. package/src/Task.ts +901 -0
  159. package/src/Time.ts +180 -5
  160. package/src/Type.ts +1135 -730
  161. package/src/Types.ts +1 -77
  162. package/src/WebSocket.ts +27 -25
  163. package/src/Worker.ts +72 -23
  164. package/src/index.ts +8 -3
  165. package/dist/src/Evolu/Config.d.ts +0 -69
  166. package/dist/src/Evolu/Config.d.ts.map +0 -1
  167. package/dist/src/Evolu/Config.js +0 -9
  168. package/dist/src/Evolu/Kysely.d.ts +0 -6
  169. package/dist/src/Evolu/Kysely.d.ts.map +0 -1
  170. package/dist/src/Evolu/Kysely.js +0 -21
  171. package/dist/src/ManyToManyMap.d.ts +0 -26
  172. package/dist/src/ManyToManyMap.d.ts.map +0 -1
  173. package/dist/src/ManyToManyMap.js +0 -92
  174. package/dist/src/NanoId.d.ts +0 -27
  175. package/dist/src/NanoId.d.ts.map +0 -1
  176. package/dist/src/NanoId.js +0 -6
  177. package/dist/src/Promise.d.ts +0 -180
  178. package/dist/src/Promise.d.ts.map +0 -1
  179. package/dist/src/Promise.js +0 -176
  180. package/src/Evolu/Config.ts +0 -83
  181. package/src/Evolu/Kysely.ts +0 -38
  182. package/src/ManyToManyMap.ts +0 -140
  183. package/src/NanoId.ts +0 -39
  184. package/src/Promise.ts +0 -295
@@ -1,180 +0,0 @@
1
- import { Result } from "./Result.js";
2
- import { Predicate } from "./Types.js";
3
- /**
4
- * Helper function to delay execution for a specified number of milliseconds.
5
- *
6
- * ### Example
7
- *
8
- * ```ts
9
- * await wait(10);
10
- * ```
11
- */
12
- export declare const wait: (ms: number) => Promise<Result<void, never>>;
13
- /** Options for configuring retry behavior. */
14
- export interface RetryOptions<E> {
15
- /**
16
- * Maximum number of retry attempts after the initial attempt (default: 3).
17
- * For example, with maxRetries = 3, the function will be called up to 4 times
18
- * (1 initial attempt + 3 retries).
19
- */
20
- maxRetries?: number;
21
- /**
22
- * Initial delay between retry attempts in milliseconds (default: 100). This
23
- * is the delay after the first failed attempt. Subsequent delays increase
24
- * exponentially according to the factor option.
25
- */
26
- initialDelay?: number;
27
- /**
28
- * Maximum delay between retry attempts in milliseconds (default: 10000). This
29
- * caps the exponential backoff to prevent extremely long delays after many
30
- * retries.
31
- */
32
- maxDelay?: number;
33
- /**
34
- * Multiplier that determines how quickly the delay increases (default: 2).
35
- * With the default value, each successive delay is twice as long as the
36
- * previous one (e.g., 100ms, 200ms, 400ms, 800ms, etc).
37
- */
38
- factor?: number;
39
- /**
40
- * Random jitter factor between 0 and 1 (default: 0.1). Adds randomness to
41
- * delay times to prevent retry storms in distributed systems.
42
- */
43
- jitter?: number;
44
- /**
45
- * Optional AbortSignal to cancel retries. If the signal is aborted, the retry
46
- * operation stops and returns a RetryAbortError.
47
- */
48
- signal?: AbortSignal;
49
- /**
50
- * Optional predicate to determine if an error should be retried. Returns true
51
- * if the error is retryable, false otherwise. This allows selectively
52
- * retrying only certain types of errors. By default, all errors are
53
- * considered retryable.
54
- */
55
- retryable?: Predicate<E>;
56
- /**
57
- * Optional callback called before each retry attempt. Receives the error that
58
- * caused the retry, the current attempt number (starting at 1), and the delay
59
- * in milliseconds before the next attempt.
60
- */
61
- onRetry?: (error: E, attempt: number, delay: number) => void;
62
- }
63
- /** Error representing a retry operation that failed after multiple attempts. */
64
- export interface RetryError<E> {
65
- readonly type: "RetryError";
66
- /** The original error that caused the retry to fail */
67
- readonly cause: E;
68
- /** Number of retry attempts made */
69
- readonly attempts: number;
70
- }
71
- /** Error representing a retry operation that was aborted. */
72
- export interface RetryAbortError {
73
- readonly type: "RetryAbortError";
74
- readonly abortedBeforeExecution: boolean;
75
- }
76
- /**
77
- * Executes a function with retry logic using exponential backoff and jitter.
78
- *
79
- * ### Example with Result-based API
80
- *
81
- * ```ts
82
- * interface ApiError {
83
- * type: "ApiError";
84
- * statusCode: number;
85
- * }
86
- *
87
- * const fetchData = async (
88
- * url: string,
89
- * ): Promise<Result<Data, ApiError>> => {
90
- * // Implementation that returns Result
91
- * };
92
- *
93
- * const result = await retry(
94
- * async () => fetchData("https://api.example.com/data"),
95
- * {
96
- * maxRetries: 5,
97
- * initialDelay: 200,
98
- * // Only retry on specific status codes
99
- * retryable: (error) =>
100
- * error.type === "ApiError" && [429, 503].includes(error.statusCode),
101
- * },
102
- * );
103
- *
104
- * if (!result.ok) {
105
- * if (result.error.type === "RetryAbortError") {
106
- * console.log("Operation was aborted");
107
- * } else {
108
- * console.log(`Failed after ${result.error.attempts} attempts`);
109
- * }
110
- * return;
111
- * }
112
- *
113
- * // Use result.value
114
- * ```
115
- *
116
- * ### Example with tryAsync for exception-based API
117
- *
118
- * ```ts
119
- * interface FetchError {
120
- * type: "FetchError";
121
- * message: string;
122
- * }
123
- *
124
- * const controller = new AbortController();
125
- *
126
- * const result = await retry(
127
- * async () =>
128
- * tryAsync(
129
- * async () => {
130
- * const response = await fetch("https://api.example.com/data", {
131
- * signal: controller.signal,
132
- * });
133
- *
134
- * if (!response.ok) {
135
- * throw new Error(`HTTP error ${response.status}`);
136
- * }
137
- *
138
- * return await response.json();
139
- * },
140
- * (error): FetchError => ({
141
- * type: "FetchError",
142
- * message: String(error),
143
- * }),
144
- * ),
145
- * {
146
- * maxRetries: 3,
147
- * signal: controller.signal,
148
- * },
149
- * );
150
- * ```
151
- *
152
- * ## HTTP Request Recommendations
153
- *
154
- * For HTTP requests, configure the `retryable` option to only retry on
155
- * appropriate errors:
156
- *
157
- * - **DO retry**: 429 (Too Many Requests), 503 (Service Unavailable), network
158
- * errors
159
- * - **DON'T retry**: 4xx client errors (except 429), most 5xx server errors
160
- */
161
- export declare const retry: <T, E>(fn: () => Promise<Result<T, E>>, options?: RetryOptions<E>) => Promise<Result<T, RetryError<E> | RetryAbortError>>;
162
- export interface TimeoutError {
163
- readonly type: "TimeoutError";
164
- readonly timeoutMs: number;
165
- }
166
- /**
167
- * Wraps an async function with a timeout, returning {@link Result} that fails
168
- * with {@link TimeoutError} if the timeout is exceeded. The provided function
169
- * must accept an AbortSignal and return a Result.
170
- *
171
- * ### Example
172
- *
173
- * ```ts
174
- * const fetchWithTimeout = () =>
175
- * withTimeout((signal) => fetch("url", signal), 5000);
176
- * const result = await retry(fetchWithTimeout, { maxRetries: 3 });
177
- * ```
178
- */
179
- export declare const withTimeout: <T, E>(fn: (signal: AbortSignal) => Promise<Result<T, E>>, timeoutMs: number) => Promise<Result<T, E | TimeoutError>>;
180
- //# sourceMappingURL=Promise.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Promise.d.ts","sourceRoot":"","sources":["../../src/Promise.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAW,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI,GAAI,IAAI,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAK1D,CAAC;AAEJ,8CAA8C;AAC9C,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAEzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9D;AAED,gFAAgF;AAChF,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,eAAO,MAAM,KAAK,GAAU,CAAC,EAAE,CAAC,EAC9B,IAAI,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAC/B,UAAS,YAAY,CAAC,CAAC,CAAM,KAC5B,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CA2EpD,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,CAAC,EAAE,CAAC,EACpC,IAAI,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAClD,WAAW,MAAM,KAChB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,CAerC,CAAC"}
@@ -1,176 +0,0 @@
1
- import { constTrue } from "./Function.js";
2
- import { err, ok } from "./Result.js";
3
- /**
4
- * Helper function to delay execution for a specified number of milliseconds.
5
- *
6
- * ### Example
7
- *
8
- * ```ts
9
- * await wait(10);
10
- * ```
11
- */
12
- export const wait = (ms) => new Promise((resolve) => setTimeout(() => {
13
- resolve(ok());
14
- }, ms));
15
- /**
16
- * Executes a function with retry logic using exponential backoff and jitter.
17
- *
18
- * ### Example with Result-based API
19
- *
20
- * ```ts
21
- * interface ApiError {
22
- * type: "ApiError";
23
- * statusCode: number;
24
- * }
25
- *
26
- * const fetchData = async (
27
- * url: string,
28
- * ): Promise<Result<Data, ApiError>> => {
29
- * // Implementation that returns Result
30
- * };
31
- *
32
- * const result = await retry(
33
- * async () => fetchData("https://api.example.com/data"),
34
- * {
35
- * maxRetries: 5,
36
- * initialDelay: 200,
37
- * // Only retry on specific status codes
38
- * retryable: (error) =>
39
- * error.type === "ApiError" && [429, 503].includes(error.statusCode),
40
- * },
41
- * );
42
- *
43
- * if (!result.ok) {
44
- * if (result.error.type === "RetryAbortError") {
45
- * console.log("Operation was aborted");
46
- * } else {
47
- * console.log(`Failed after ${result.error.attempts} attempts`);
48
- * }
49
- * return;
50
- * }
51
- *
52
- * // Use result.value
53
- * ```
54
- *
55
- * ### Example with tryAsync for exception-based API
56
- *
57
- * ```ts
58
- * interface FetchError {
59
- * type: "FetchError";
60
- * message: string;
61
- * }
62
- *
63
- * const controller = new AbortController();
64
- *
65
- * const result = await retry(
66
- * async () =>
67
- * tryAsync(
68
- * async () => {
69
- * const response = await fetch("https://api.example.com/data", {
70
- * signal: controller.signal,
71
- * });
72
- *
73
- * if (!response.ok) {
74
- * throw new Error(`HTTP error ${response.status}`);
75
- * }
76
- *
77
- * return await response.json();
78
- * },
79
- * (error): FetchError => ({
80
- * type: "FetchError",
81
- * message: String(error),
82
- * }),
83
- * ),
84
- * {
85
- * maxRetries: 3,
86
- * signal: controller.signal,
87
- * },
88
- * );
89
- * ```
90
- *
91
- * ## HTTP Request Recommendations
92
- *
93
- * For HTTP requests, configure the `retryable` option to only retry on
94
- * appropriate errors:
95
- *
96
- * - **DO retry**: 429 (Too Many Requests), 503 (Service Unavailable), network
97
- * errors
98
- * - **DON'T retry**: 4xx client errors (except 429), most 5xx server errors
99
- */
100
- export const retry = async (fn, options = {}) => {
101
- const { maxRetries = 3, initialDelay = 100, maxDelay = 10000, factor = 2, jitter = 0.1, signal, retryable = constTrue, onRetry, } = options;
102
- let attempt = 0;
103
- if (signal?.aborted) {
104
- return err({ type: "RetryAbortError", abortedBeforeExecution: true });
105
- }
106
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
107
- while (true) {
108
- const result = await fn();
109
- if (result.ok) {
110
- return result;
111
- }
112
- attempt += 1;
113
- if (attempt > maxRetries || !retryable(result.error)) {
114
- return err({
115
- type: "RetryError",
116
- cause: result.error,
117
- attempts: attempt,
118
- });
119
- }
120
- // Calculate delay with exponential backoff
121
- const exponentialDelay = initialDelay * Math.pow(factor, attempt);
122
- const cappedDelay = Math.min(exponentialDelay, maxDelay);
123
- // Apply jitter to prevent thundering herd problem
124
- const randomFactor = 1 - jitter + Math.random() * jitter * 2;
125
- const delay = Math.floor(cappedDelay * randomFactor);
126
- if (onRetry) {
127
- onRetry(result.error, attempt, delay);
128
- }
129
- if (signal?.aborted) {
130
- return err({ type: "RetryAbortError", abortedBeforeExecution: false });
131
- }
132
- // Wait with abort support
133
- if (signal) {
134
- const abortPromise = new Promise((resolve) => {
135
- const onAbort = () => {
136
- resolve(err({ type: "RetryAbortError", abortedBeforeExecution: false }));
137
- };
138
- signal.addEventListener("abort", onAbort, { once: true });
139
- });
140
- const delayPromise = wait(delay);
141
- const raceResult = await Promise.race([abortPromise, delayPromise]);
142
- if (!raceResult.ok) {
143
- return raceResult;
144
- }
145
- }
146
- else {
147
- await wait(delay);
148
- }
149
- }
150
- };
151
- /**
152
- * Wraps an async function with a timeout, returning {@link Result} that fails
153
- * with {@link TimeoutError} if the timeout is exceeded. The provided function
154
- * must accept an AbortSignal and return a Result.
155
- *
156
- * ### Example
157
- *
158
- * ```ts
159
- * const fetchWithTimeout = () =>
160
- * withTimeout((signal) => fetch("url", signal), 5000);
161
- * const result = await retry(fetchWithTimeout, { maxRetries: 3 });
162
- * ```
163
- */
164
- export const withTimeout = async (fn, timeoutMs) => {
165
- const controller = new AbortController();
166
- const signal = controller.signal;
167
- const timeoutId = setTimeout(() => {
168
- controller.abort();
169
- }, timeoutMs);
170
- const result = await fn(signal);
171
- clearTimeout(timeoutId);
172
- if (signal.aborted) {
173
- return err({ type: "TimeoutError", timeoutMs });
174
- }
175
- return result;
176
- };
@@ -1,83 +0,0 @@
1
- import { ConsoleConfig } from "../Console.js";
2
- import { getOrThrow } from "../Result.js";
3
- import { Mnemonic, SimpleName } from "../Type.js";
4
- import type { DbIndexesBuilder } from "./Kysely.js";
5
-
6
- export interface Config extends ConsoleConfig {
7
- /**
8
- * The name of Evolu instances. Evolu is multitenant - it can run more
9
- * instances concurrently. Every Evolu instance has to have its own unique
10
- * name. Database files are separated and invisible to each other.
11
- *
12
- * The default value is: `Evolu`.
13
- *
14
- * ### Example
15
- *
16
- * ```ts
17
- * // name: getOrThrow(SimpleName.from("MyApp"))
18
- * ```
19
- */
20
- readonly name: SimpleName;
21
-
22
- /**
23
- * URL for Evolu sync and backup server.
24
- *
25
- * The default value is `https://free.evoluhq.com`.
26
- */
27
- readonly syncUrl: string;
28
-
29
- /**
30
- * URL to reload browser tabs after reset or restore.
31
- *
32
- * The default value is `/`.
33
- */
34
- readonly reloadUrl: string;
35
-
36
- /**
37
- * Maximum physical clock drift allowed in ms.
38
- *
39
- * The default value is 5 * 60 * 1000 (5 minutes).
40
- */
41
- readonly maxDrift: number;
42
-
43
- /**
44
- * Use the `indexes` option to define SQLite indexes.
45
- *
46
- * Table and column names are not typed because Kysely doesn't support it.
47
- *
48
- * https://medium.com/@JasonWyatt/squeezing-performance-from-sqlite-indexes-indexes-c4e175f3c346
49
- *
50
- * ### Example
51
- *
52
- * ```ts
53
- * const evolu = createEvolu(evoluReactDeps)(Schema, {
54
- * indexes: (create) => [
55
- * create("todoCreatedAt").on("todo").column("createdAt"),
56
- * create("todoCategoryCreatedAt")
57
- * .on("todoCategory")
58
- * .column("createdAt"),
59
- * ],
60
- * });
61
- * ```
62
- */
63
- readonly indexes?: DbIndexesBuilder;
64
-
65
- /**
66
- * Use this option to create Evolu with the specified mnemonic. If omitted,
67
- * the mnemonic will be autogenerated. That should be the default behavior
68
- * until special UX requirements are needed (e.g., multitenancy).
69
- */
70
- readonly mnemonic?: Mnemonic;
71
- }
72
-
73
- export interface ConfigDep {
74
- readonly config: Config;
75
- }
76
-
77
- export const defaultConfig: Config = {
78
- name: getOrThrow(SimpleName.fromParent("Evolu")),
79
- syncUrl: "wss://free.evoluhq.com",
80
- reloadUrl: "/",
81
- maxDrift: 5 * 60 * 1000,
82
- enableLogging: false,
83
- };
@@ -1,38 +0,0 @@
1
- import {
2
- CreateIndexBuilder,
3
- DummyDriver,
4
- Kysely,
5
- SqliteAdapter,
6
- SqliteQueryCompiler,
7
- } from "kysely";
8
- import { DbIndex } from "./Db.js";
9
-
10
- // https://kysely.dev/docs/recipes/splitting-query-building-and-execution
11
- export const kysely = new Kysely({
12
- dialect: {
13
- createAdapter: () => new SqliteAdapter(),
14
- createDriver: () => new DummyDriver(),
15
- createIntrospector() {
16
- throw new Error("Not implemeneted");
17
- },
18
- createQueryCompiler: () => new SqliteQueryCompiler(),
19
- },
20
- });
21
-
22
- export type DbIndexesBuilder = (
23
- create: (indexName: string) => CreateIndexBuilder,
24
- ) => ReadonlyArray<CreateIndexBuilder<any>>;
25
-
26
- const createIndex = kysely.schema.createIndex.bind(kysely.schema);
27
-
28
- export const createIndexes = (
29
- indexes?: DbIndexesBuilder,
30
- ): ReadonlyArray<DbIndex> => {
31
- if (!indexes) return [];
32
- return indexes(createIndex).map(
33
- (index): DbIndex => ({
34
- name: index.toOperationNode().name.name,
35
- sql: index.compile().sql,
36
- }),
37
- );
38
- };
@@ -1,140 +0,0 @@
1
- /** Represents a many-to-many mapping between keys and values. */
2
- export interface ManyToManyMap<K, V> {
3
- /** Adds a key-value association to the map. */
4
- add: (key: K, value: V) => ManyToManyMap<K, V>;
5
-
6
- /** Removes a specific key-value association. */
7
- remove: (key: K, value: V) => boolean;
8
-
9
- /** Gets all values associated with a key. */
10
- getValues: (key: K) => Set<V> | undefined;
11
-
12
- /** Gets all keys associated with a value. */
13
- getKeys: (value: V) => Set<K> | undefined;
14
-
15
- /** Checks if a specific key-value pair exists. */
16
- hasPair: (key: K, value: V) => boolean;
17
-
18
- /** Checks if a key exists in the map. */
19
- hasKey(key: K): boolean;
20
-
21
- /** Checks if a value exists in the map. */
22
- hasValue: (value: V) => boolean;
23
-
24
- /** Deletes all associations for a key. */
25
- deleteKey: (key: K) => boolean;
26
-
27
- /** Deletes all associations for a value. */
28
- deleteValue: (value: V) => boolean;
29
-
30
- /** Clears all associations in the map. */
31
- clear(): void;
32
- }
33
-
34
- /** Creates a {@link ManyToManyMap}. */
35
- export const createManyToManyMap = <K, V>(): ManyToManyMap<K, V> => {
36
- const forwardMap = new Map<K, Set<V>>();
37
- const reverseMap = new Map<V, Set<K>>();
38
-
39
- const map: ManyToManyMap<K, V> = {
40
- add(key: K, value: V) {
41
- let values = forwardMap.get(key);
42
- if (!values) {
43
- values = new Set<V>();
44
- forwardMap.set(key, values);
45
- }
46
- values.add(value);
47
-
48
- let keys = reverseMap.get(value);
49
- if (!keys) {
50
- keys = new Set<K>();
51
- reverseMap.set(value, keys);
52
- }
53
- keys.add(key);
54
-
55
- return map;
56
- },
57
-
58
- remove(key: K, value: V) {
59
- const values = forwardMap.get(key);
60
- if (!values?.has(value)) return false;
61
-
62
- values.delete(value);
63
- if (values.size === 0) {
64
- forwardMap.delete(key);
65
- }
66
-
67
- const keys = reverseMap.get(value);
68
- if (keys?.size) {
69
- keys.delete(key);
70
- if (keys.size === 0) {
71
- reverseMap.delete(value);
72
- }
73
- }
74
-
75
- return true;
76
- },
77
-
78
- getValues(key: K) {
79
- return forwardMap.get(key);
80
- },
81
-
82
- getKeys(value: V) {
83
- return reverseMap.get(value);
84
- },
85
-
86
- hasPair(key: K, value: V) {
87
- const values = forwardMap.get(key);
88
- return values?.has(value) ?? false;
89
- },
90
-
91
- hasKey(key: K) {
92
- return forwardMap.has(key);
93
- },
94
-
95
- hasValue(value: V) {
96
- return reverseMap.has(value);
97
- },
98
-
99
- deleteKey(key: K) {
100
- const values = forwardMap.get(key);
101
- if (!values) return false;
102
-
103
- for (const value of values) {
104
- const keys = reverseMap.get(value);
105
- if (keys) {
106
- keys.delete(key);
107
- if (keys.size === 0) {
108
- reverseMap.delete(value);
109
- }
110
- }
111
- }
112
- forwardMap.delete(key);
113
- return true;
114
- },
115
-
116
- deleteValue(value: V) {
117
- const keys = reverseMap.get(value);
118
- if (!keys) return false;
119
-
120
- for (const key of keys) {
121
- const values = forwardMap.get(key);
122
- if (values) {
123
- values.delete(value);
124
- if (values.size === 0) {
125
- forwardMap.delete(key);
126
- }
127
- }
128
- }
129
- reverseMap.delete(value);
130
- return true;
131
- },
132
-
133
- clear() {
134
- forwardMap.clear();
135
- reverseMap.clear();
136
- },
137
- };
138
-
139
- return map;
140
- };
package/src/NanoId.ts DELETED
@@ -1,39 +0,0 @@
1
- import { customAlphabet, nanoid, urlAlphabet } from "nanoid";
2
-
3
- /**
4
- * Interface representing a NanoId library.
5
- *
6
- * It's useful for testing by allowing ID generation to be mocked, ensuring
7
- * consistent results.
8
- *
9
- * @see https://github.com/ai/nanoid
10
- *
11
- * ### Example
12
- *
13
- * ```ts
14
- * const foo = createFoo({
15
- * ...createNanoIdLib(),
16
- * ...createTime(),
17
- * });
18
- * ```
19
- */
20
- export interface NanoIdLib {
21
- readonly urlAlphabet: string;
22
-
23
- readonly customAlphabet: (
24
- alphabet: string,
25
- defaultSize?: number,
26
- ) => (size?: number) => string;
27
-
28
- readonly nanoid: (size?: number) => string;
29
- }
30
-
31
- export interface NanoIdLibDep {
32
- readonly nanoIdLib: NanoIdLib;
33
- }
34
-
35
- export const createNanoIdLib = (): NanoIdLib => ({
36
- urlAlphabet,
37
- customAlphabet,
38
- nanoid,
39
- });