@evolu/react-native 14.3.0 → 15.0.0-next.1

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 (81) hide show
  1. package/README.md +3 -3
  2. package/dist/src/LockManager.d.ts +13 -0
  3. package/dist/src/LockManager.d.ts.map +1 -0
  4. package/dist/src/LockManager.js +219 -0
  5. package/dist/src/Polyfills.d.ts +3 -0
  6. package/dist/src/Polyfills.d.ts.map +1 -0
  7. package/dist/src/Polyfills.js +209 -0
  8. package/dist/src/Task.d.ts +31 -0
  9. package/dist/src/Task.d.ts.map +1 -0
  10. package/dist/src/Task.js +46 -0
  11. package/dist/src/components/EvoluIdenticon.d.ts +9 -0
  12. package/dist/src/components/EvoluIdenticon.d.ts.map +1 -0
  13. package/dist/{components → src/components}/EvoluIdenticon.js +1 -1
  14. package/dist/src/createExpoDeps.d.ts +1 -0
  15. package/dist/src/createExpoDeps.d.ts.map +1 -0
  16. package/dist/src/createExpoDeps.js +163 -0
  17. package/dist/src/exports/bare-op-sqlite.d.ts +1 -0
  18. package/dist/src/exports/bare-op-sqlite.d.ts.map +1 -0
  19. package/dist/src/exports/bare-op-sqlite.js +31 -0
  20. package/dist/src/exports/expo-op-sqlite.d.ts +1 -0
  21. package/dist/src/exports/expo-op-sqlite.d.ts.map +1 -0
  22. package/dist/src/exports/expo-op-sqlite.js +16 -0
  23. package/dist/src/exports/expo-sqlite.d.ts +11 -0
  24. package/dist/src/exports/expo-sqlite.d.ts.map +1 -0
  25. package/dist/src/exports/expo-sqlite.js +24 -0
  26. package/dist/src/index.d.ts +4 -0
  27. package/dist/src/index.d.ts.map +1 -0
  28. package/dist/src/index.js +3 -0
  29. package/dist/src/shared.d.ts +5 -0
  30. package/dist/src/shared.d.ts.map +1 -0
  31. package/dist/src/shared.js +90 -0
  32. package/dist/src/sqlite-drivers/createExpoSqliteDriver.d.ts +3 -0
  33. package/dist/src/sqlite-drivers/createExpoSqliteDriver.d.ts.map +1 -0
  34. package/dist/src/sqlite-drivers/createExpoSqliteDriver.js +134 -0
  35. package/dist/src/sqlite-drivers/createOpSqliteDriver.d.ts +3 -0
  36. package/dist/src/sqlite-drivers/createOpSqliteDriver.d.ts.map +1 -0
  37. package/dist/src/sqlite-drivers/createOpSqliteDriver.js +119 -0
  38. package/dist/src/web.d.ts.map +1 -0
  39. package/package.json +72 -48
  40. package/src/ErrorUtils.d.ts +19 -0
  41. package/src/LockManager.ts +325 -0
  42. package/src/Polyfills.ts +301 -0
  43. package/src/Task.ts +66 -0
  44. package/src/components/EvoluIdenticon.tsx +2 -2
  45. package/src/createExpoDeps.ts +162 -160
  46. package/src/exports/bare-op-sqlite.ts +30 -28
  47. package/src/exports/expo-op-sqlite.ts +15 -14
  48. package/src/exports/expo-sqlite.ts +21 -4
  49. package/src/index.ts +2 -0
  50. package/src/shared.ts +115 -49
  51. package/src/sqlite-drivers/createExpoSqliteDriver.ts +74 -51
  52. package/src/sqlite-drivers/createOpSqliteDriver.ts +62 -60
  53. package/dist/components/EvoluIdenticon.d.ts +0 -9
  54. package/dist/components/EvoluIdenticon.d.ts.map +0 -1
  55. package/dist/createExpoDeps.d.ts +0 -7
  56. package/dist/createExpoDeps.d.ts.map +0 -1
  57. package/dist/createExpoDeps.js +0 -123
  58. package/dist/exports/bare-op-sqlite.d.ts +0 -10
  59. package/dist/exports/bare-op-sqlite.d.ts.map +0 -1
  60. package/dist/exports/bare-op-sqlite.js +0 -24
  61. package/dist/exports/expo-op-sqlite.d.ts +0 -9
  62. package/dist/exports/expo-op-sqlite.d.ts.map +0 -1
  63. package/dist/exports/expo-op-sqlite.js +0 -12
  64. package/dist/exports/expo-sqlite.d.ts +0 -8
  65. package/dist/exports/expo-sqlite.d.ts.map +0 -1
  66. package/dist/exports/expo-sqlite.js +0 -11
  67. package/dist/index.d.ts +0 -2
  68. package/dist/index.d.ts.map +0 -1
  69. package/dist/index.js +0 -1
  70. package/dist/shared.d.ts +0 -5
  71. package/dist/shared.d.ts.map +0 -1
  72. package/dist/shared.js +0 -39
  73. package/dist/sqlite-drivers/createExpoSqliteDriver.d.ts +0 -3
  74. package/dist/sqlite-drivers/createExpoSqliteDriver.d.ts.map +0 -1
  75. package/dist/sqlite-drivers/createExpoSqliteDriver.js +0 -46
  76. package/dist/sqlite-drivers/createOpSqliteDriver.d.ts +0 -3
  77. package/dist/sqlite-drivers/createOpSqliteDriver.d.ts.map +0 -1
  78. package/dist/sqlite-drivers/createOpSqliteDriver.js +0 -54
  79. package/dist/web.d.ts.map +0 -1
  80. /package/dist/{web.d.ts → src/web.d.ts} +0 -0
  81. /package/dist/{web.js → src/web.js} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Evolu for React Native and Expo
1
+ # Evolu for React Native
2
2
 
3
- [Evolu](https://github.com/evoluhq/evolu) for [React Native](https://reactnative.dev/) and [Expo](https://expo.dev/).
3
+ This package provides Evolu for [React Native](https://reactnative.dev) and [Expo](https://expo.dev).
4
4
 
5
5
  ## Documentation
6
6
 
@@ -12,4 +12,4 @@ The Evolu community is on [GitHub Discussions](https://github.com/evoluhq/evolu/
12
12
 
13
13
  To chat with other community members, you can join the [Evolu Discord](https://discord.gg/2J8yyyyxtZ).
14
14
 
15
- [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/evoluhq.svg?style=social&label=Follow%20%40evoluhq)](https://twitter.com/evoluhq)
15
+ [![X](https://img.shields.io/twitter/url/https/x.com/evoluhq.svg?style=social&label=Follow%20%40evoluhq)](https://x.com/evoluhq)
@@ -0,0 +1,13 @@
1
+ /**
2
+ * React Native implementation of {@link LockManager}.
3
+ *
4
+ * @module
5
+ */
6
+ /**
7
+ * React Native {@link LockManager}.
8
+ *
9
+ * Uses an in-memory lock manager scoped to the main JavaScript thread while
10
+ * following Web Locks request and query semantics.
11
+ */
12
+ export declare const lockManager: LockManager;
13
+ //# sourceMappingURL=LockManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LockManager.d.ts","sourceRoot":"","sources":["../../src/LockManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyQH;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,WAIzB,CAAC"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * React Native implementation of {@link LockManager}.
3
+ *
4
+ * @module
5
+ */
6
+ /**
7
+ * React Native `LockManager` ponyfill.
8
+ *
9
+ * This is a temporary in-memory ponyfill until React Native ships native
10
+ * `LockManager` support.
11
+ *
12
+ * The ponyfill follows Web Locks request and query semantics within the current
13
+ * JavaScript process.
14
+ *
15
+ * ### Example
16
+ *
17
+ * ```ts
18
+ * await lockManager.request("db", async () => {
19
+ * // critical section
20
+ * });
21
+ * ```
22
+ */
23
+ const createLockManagerPonyfill = ({ clientId = "in-memory-main-thread", } = {}) => {
24
+ const heldLocksByName = new Map();
25
+ const pendingRequestsByName = new Map();
26
+ const processPendingRequests = (name) => {
27
+ const pendingRequests = pendingRequestsByName.get(name);
28
+ if (pendingRequests == null || pendingRequests.length === 0)
29
+ return;
30
+ const heldLocks = heldLocksByName.get(name) ?? [];
31
+ const hasExclusiveLock = heldLocks.some((lock) => lock.mode === "exclusive");
32
+ if (hasExclusiveLock)
33
+ return;
34
+ if (heldLocks.length === 0) {
35
+ const nextRequest = pendingRequests[0];
36
+ if (nextRequest.mode === "exclusive") {
37
+ grantPendingRequest(name, pendingRequests.shift());
38
+ }
39
+ else {
40
+ while (pendingRequests[0]?.mode === "shared") {
41
+ grantPendingRequest(name, pendingRequests.shift());
42
+ }
43
+ }
44
+ }
45
+ else {
46
+ while (pendingRequests[0]?.mode === "shared") {
47
+ grantPendingRequest(name, pendingRequests.shift());
48
+ }
49
+ }
50
+ cleanupNameState(name);
51
+ };
52
+ const grantPendingRequest = (name, pendingRequest) => {
53
+ const heldLocks = heldLocksByName.get(name) ?? [];
54
+ const heldLock = {
55
+ clientId,
56
+ mode: pendingRequest.mode,
57
+ name,
58
+ reject: pendingRequest.reject,
59
+ };
60
+ heldLocks.push(heldLock);
61
+ heldLocksByName.set(name, heldLocks);
62
+ pendingRequest.phase = "granted";
63
+ void Promise.resolve()
64
+ .then(() => {
65
+ if (pendingRequest.signal?.aborted) {
66
+ pendingRequest.phase = "settled";
67
+ pendingRequest.signal.removeEventListener("abort", pendingRequest.abort);
68
+ releaseHeldLock(name, heldLock);
69
+ return;
70
+ }
71
+ pendingRequest.signal?.removeEventListener("abort", pendingRequest.abort);
72
+ pendingRequest.phase = "running";
73
+ return Promise.resolve(pendingRequest.callback({ mode: pendingRequest.mode, name }));
74
+ })
75
+ .then((value) => {
76
+ if (pendingRequest.phase === "settled")
77
+ return;
78
+ pendingRequest.phase = "settled";
79
+ releaseHeldLock(name, heldLock);
80
+ pendingRequest.resolve(value);
81
+ }, (error) => {
82
+ pendingRequest.phase = "settled";
83
+ releaseHeldLock(name, heldLock);
84
+ pendingRequest.reject(error);
85
+ });
86
+ };
87
+ const releaseHeldLock = (name, heldLock) => {
88
+ const currentHeldLocks = heldLocksByName.get(name) ?? [];
89
+ heldLocksByName.set(name, currentHeldLocks.filter((lock) => lock !== heldLock));
90
+ cleanupNameState(name);
91
+ processPendingRequests(name);
92
+ };
93
+ const stealLocks = (name) => {
94
+ const heldLocks = heldLocksByName.get(name) ?? [];
95
+ if (heldLocks.length === 0)
96
+ return;
97
+ heldLocksByName.delete(name);
98
+ for (const heldLock of heldLocks) {
99
+ heldLock.reject(createAbortError());
100
+ }
101
+ };
102
+ const cleanupNameState = (name) => {
103
+ if (heldLocksByName.get(name)?.length === 0) {
104
+ heldLocksByName.delete(name);
105
+ }
106
+ if (pendingRequestsByName.get(name)?.length === 0) {
107
+ pendingRequestsByName.delete(name);
108
+ }
109
+ };
110
+ const removePendingRequest = (name, pendingRequest) => {
111
+ const pendingRequests = pendingRequestsByName.get(name);
112
+ pendingRequestsByName.set(name, pendingRequests.filter((request) => request !== pendingRequest));
113
+ cleanupNameState(name);
114
+ processPendingRequests(name);
115
+ };
116
+ const canGrantImmediately = (name, mode) => {
117
+ const pendingRequests = pendingRequestsByName.get(name);
118
+ if (pendingRequests != null && pendingRequests.length > 0) {
119
+ return false;
120
+ }
121
+ const heldLocks = heldLocksByName.get(name) ?? [];
122
+ if (mode === "exclusive") {
123
+ return heldLocks.length === 0;
124
+ }
125
+ return heldLocks.every((lock) => lock.mode === "shared");
126
+ };
127
+ return {
128
+ request: (name, optionsOrCallback, maybeCallback) => {
129
+ const [options, callback] = normalizeRequestArguments(optionsOrCallback, maybeCallback);
130
+ const mode = options.mode ?? "exclusive";
131
+ if (name.startsWith("-")) {
132
+ return Promise.reject(createNotSupportedError());
133
+ }
134
+ if (options.ifAvailable && options.steal) {
135
+ return Promise.reject(createNotSupportedError());
136
+ }
137
+ if (options.steal && mode !== "exclusive") {
138
+ return Promise.reject(createNotSupportedError());
139
+ }
140
+ if (options.signal != null && (options.ifAvailable || options.steal)) {
141
+ return Promise.reject(createNotSupportedError());
142
+ }
143
+ if (options.signal?.aborted) {
144
+ return Promise.reject(options.signal.reason);
145
+ }
146
+ if (options.ifAvailable && !canGrantImmediately(name, mode)) {
147
+ return Promise.resolve().then(() => Promise.resolve(callback(null)));
148
+ }
149
+ return new Promise((resolve, reject) => {
150
+ const pendingRequest = {
151
+ abort: () => {
152
+ if (pendingRequest.phase === "queued") {
153
+ pendingRequest.phase = "settled";
154
+ removePendingRequest(name, pendingRequest);
155
+ reject(options.signal.reason);
156
+ return;
157
+ }
158
+ pendingRequest.phase = "settled";
159
+ reject(options.signal.reason);
160
+ },
161
+ callback,
162
+ mode,
163
+ name,
164
+ phase: "queued",
165
+ reject,
166
+ resolve,
167
+ ...(options.signal == null ? {} : { signal: options.signal }),
168
+ };
169
+ if (options.signal != null) {
170
+ options.signal.addEventListener("abort", pendingRequest.abort, {
171
+ once: true,
172
+ });
173
+ }
174
+ const pendingRequests = pendingRequestsByName.get(name) ?? [];
175
+ if (options.steal) {
176
+ stealLocks(name);
177
+ pendingRequests.unshift(pendingRequest);
178
+ }
179
+ else {
180
+ pendingRequests.push(pendingRequest);
181
+ }
182
+ pendingRequestsByName.set(name, pendingRequests);
183
+ processPendingRequests(name);
184
+ });
185
+ },
186
+ query: () => {
187
+ const held = Array.from(heldLocksByName.values())
188
+ .flat()
189
+ .map(({ clientId, mode, name }) => ({ clientId, mode, name }));
190
+ const pending = Array.from(pendingRequestsByName.values())
191
+ .flat()
192
+ .map(({ mode, name }) => ({
193
+ clientId,
194
+ mode,
195
+ name,
196
+ }));
197
+ return Promise.resolve({ held, pending });
198
+ },
199
+ };
200
+ };
201
+ /**
202
+ * React Native {@link LockManager}.
203
+ *
204
+ * Uses an in-memory lock manager scoped to the main JavaScript thread while
205
+ * following Web Locks request and query semantics.
206
+ */
207
+ export const lockManager = /*#__PURE__*/ createLockManagerPonyfill({
208
+ clientId: "react-native-main-thread",
209
+ });
210
+ const normalizeRequestArguments = (optionsOrCallback, maybeCallback) => typeof optionsOrCallback === "function"
211
+ ? [{}, optionsOrCallback]
212
+ : [optionsOrCallback, maybeCallback];
213
+ const createAbortError = () => createNamedError("AbortError", "The request was aborted.");
214
+ const createNotSupportedError = () => createNamedError("NotSupportedError", "The operation is not supported.");
215
+ const createNamedError = (name, message) => {
216
+ const error = new Error(message);
217
+ error.name = name;
218
+ return error;
219
+ };
@@ -0,0 +1,3 @@
1
+ /** Installs polyfills required by Evolu in React Native runtimes. */
2
+ export declare const installPolyfills: () => void;
3
+ //# sourceMappingURL=Polyfills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Polyfills.d.ts","sourceRoot":"","sources":["../../src/Polyfills.ts"],"names":[],"mappings":"AAmCA,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,QAAO,IAKnC,CAAC"}
@@ -0,0 +1,209 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-call */
3
+ import { installPolyfills as installCommonPolyfills } from "@evolu/common/polyfills";
4
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
5
+ import fromAsync from "array-from-async";
6
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
7
+ import withResolvers from "promise.withresolvers";
8
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
9
+ import promiseTry from "promise.try";
10
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
11
+ import toSorted from "array.prototype.tosorted";
12
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
13
+ import difference from "set.prototype.difference";
14
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
15
+ import intersection from "set.prototype.intersection";
16
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
17
+ import isDisjointFrom from "set.prototype.isdisjointfrom";
18
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
19
+ import isSubsetOf from "set.prototype.issubsetof";
20
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
21
+ import isSupersetOf from "set.prototype.issupersetof";
22
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
23
+ import symmetricDifference from "set.prototype.symmetricdifference";
24
+ // @ts-expect-error Runtime polyfill package has no TypeScript declarations.
25
+ import union from "set.prototype.union";
26
+ difference.shim();
27
+ intersection.shim();
28
+ isDisjointFrom.shim();
29
+ isSubsetOf.shim();
30
+ isSupersetOf.shim();
31
+ symmetricDifference.shim();
32
+ union.shim();
33
+ /** Installs polyfills required by Evolu in React Native runtimes. */
34
+ export const installPolyfills = () => {
35
+ installCommonPolyfills();
36
+ installArrayPolyfills();
37
+ installPromisePolyfills();
38
+ installAbortControllerPolyfills();
39
+ };
40
+ const installArrayPolyfills = () => {
41
+ if (typeof Array.fromAsync !== "function") {
42
+ Object.defineProperty(Array, "fromAsync", {
43
+ configurable: true,
44
+ enumerable: false,
45
+ writable: true,
46
+ value: fromAsync,
47
+ });
48
+ }
49
+ toSorted.shim();
50
+ };
51
+ const installPromisePolyfills = () => {
52
+ withResolvers.shim();
53
+ promiseTry.shim();
54
+ };
55
+ const abortReasonBySignal = new WeakMap();
56
+ const anyControllersBySignal = new WeakMap();
57
+ const installAbortControllerPolyfills = () => {
58
+ installAbortReasonPolyfill(globalThis.AbortController, globalThis.AbortSignal);
59
+ installAbortSignalStaticMethods(globalThis.AbortController, globalThis.AbortSignal);
60
+ };
61
+ const installAbortReasonPolyfill = (abortController, abortSignal) => {
62
+ if (!("reason" in abortSignal.prototype)) {
63
+ Object.defineProperty(abortSignal.prototype, "reason", {
64
+ configurable: true,
65
+ enumerable: false,
66
+ get() {
67
+ return abortReasonBySignal.get(this);
68
+ },
69
+ });
70
+ }
71
+ const prototype = abortController.prototype;
72
+ if (prototype.__evoluAbortReasonPatched)
73
+ return;
74
+ const nativeAbort = prototype.abort;
75
+ prototype.abort = function (reason) {
76
+ const normalizedReason = reason === undefined ? createAbortError() : reason;
77
+ abortReasonBySignal.set(this.signal, normalizedReason);
78
+ nativeAbort.call(this, normalizedReason);
79
+ };
80
+ Object.defineProperty(prototype, "__evoluAbortReasonPatched", {
81
+ value: true,
82
+ configurable: true,
83
+ enumerable: false,
84
+ writable: false,
85
+ });
86
+ };
87
+ const installAbortSignalStaticMethods = (abortController, abortSignal) => {
88
+ if (typeof abortSignal.abort !== "function") {
89
+ Object.defineProperty(abortSignal, "abort", {
90
+ configurable: true,
91
+ enumerable: false,
92
+ writable: true,
93
+ value: (reason) => {
94
+ const controller = new abortController();
95
+ controller.abort(reason);
96
+ return controller.signal;
97
+ },
98
+ });
99
+ }
100
+ if (typeof abortSignal.timeout !== "function") {
101
+ Object.defineProperty(abortSignal, "timeout", {
102
+ configurable: true,
103
+ enumerable: false,
104
+ writable: true,
105
+ value: (milliseconds) => {
106
+ const controller = new abortController();
107
+ const timeoutId = globalThis.setTimeout(() => {
108
+ controller.abort(createTimeoutError(milliseconds));
109
+ }, milliseconds);
110
+ controller.signal.addEventListener("abort", () => {
111
+ globalThis.clearTimeout(timeoutId);
112
+ }, { once: true });
113
+ return controller.signal;
114
+ },
115
+ });
116
+ }
117
+ if (typeof abortSignal.any !== "function") {
118
+ Object.defineProperty(abortSignal, "any", {
119
+ configurable: true,
120
+ enumerable: false,
121
+ writable: true,
122
+ value: (signals) => createAbortSignalAny(abortController, signals),
123
+ });
124
+ }
125
+ };
126
+ const createAbortSignalAny = (abortController, signals) => {
127
+ const controller = new abortController();
128
+ if (signals.length === 0)
129
+ return controller.signal;
130
+ for (const signal of signals) {
131
+ if (signal.aborted) {
132
+ controller.abort(readSignalReason(signal));
133
+ return controller.signal;
134
+ }
135
+ }
136
+ const sources = Array.from(new Set(signals));
137
+ for (const signal of sources) {
138
+ const registry = anyControllersBySignal.get(signal) ??
139
+ createAnyControllersRegistry(signal);
140
+ anyControllersBySignal.set(signal, registry);
141
+ registry.add(controller);
142
+ }
143
+ controller.signal.addEventListener("abort", () => {
144
+ for (const signal of sources) {
145
+ anyControllersBySignal.get(signal)?.remove(controller);
146
+ }
147
+ }, { once: true });
148
+ return controller.signal;
149
+ };
150
+ const createAnyControllersRegistry = (sourceSignal) => {
151
+ let refs = [];
152
+ const cleanup = () => {
153
+ refs = refs.filter((ref) => {
154
+ const controller = ref.deref();
155
+ return controller != null && !controller.signal.aborted;
156
+ });
157
+ if (refs.length === 0) {
158
+ sourceSignal.removeEventListener("abort", onAbort);
159
+ anyControllersBySignal.delete(sourceSignal);
160
+ }
161
+ };
162
+ const onAbort = () => {
163
+ const reason = readSignalReason(sourceSignal);
164
+ for (const ref of refs) {
165
+ const controller = ref.deref();
166
+ if (!controller || controller.signal.aborted)
167
+ continue;
168
+ controller.abort(reason);
169
+ }
170
+ refs = [];
171
+ sourceSignal.removeEventListener("abort", onAbort);
172
+ anyControllersBySignal.delete(sourceSignal);
173
+ };
174
+ sourceSignal.addEventListener("abort", onAbort, { once: true });
175
+ return {
176
+ add: (controller) => {
177
+ refs.push(new globalThis.WeakRef(controller));
178
+ cleanup();
179
+ },
180
+ remove: (controller) => {
181
+ refs = refs.filter((ref) => {
182
+ const candidate = ref.deref();
183
+ return candidate != null && candidate !== controller;
184
+ });
185
+ cleanup();
186
+ },
187
+ };
188
+ };
189
+ const readSignalReason = (signal) => {
190
+ if ("reason" in signal) {
191
+ return signal.reason;
192
+ }
193
+ return createAbortError();
194
+ };
195
+ const createTimeoutError = (milliseconds) => createNamedError("TimeoutError", `signal timed out after ${milliseconds} ms`);
196
+ const createAbortError = () => createNamedError("AbortError", "This operation was aborted");
197
+ const createNamedError = (name, message) => {
198
+ if (typeof globalThis.DOMException === "function") {
199
+ try {
200
+ return new globalThis.DOMException(message, name);
201
+ }
202
+ catch {
203
+ // Some runtimes expose DOMException but cannot construct it reliably.
204
+ }
205
+ }
206
+ const error = new Error(message);
207
+ error.name = name;
208
+ return error;
209
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * React Native-specific Task utilities.
3
+ *
4
+ * @module
5
+ */
6
+ import { type CreateRun, type RunDeps } from "@evolu/common";
7
+ /**
8
+ * Creates {@link Run} for React Native with global error handling.
9
+ *
10
+ * Registers `ErrorUtils.setGlobalHandler` for uncaught JavaScript errors. The
11
+ * handler is restored to the previous one when the Run is disposed.
12
+ *
13
+ * ### Example
14
+ *
15
+ * ```ts
16
+ * const console = createConsole({
17
+ * formatter: createConsoleFormatter()({
18
+ * timestampFormat: "relative",
19
+ * }),
20
+ * });
21
+ *
22
+ * await using run = createRun({ console });
23
+ * await using disposer = new AsyncDisposableStack();
24
+ *
25
+ * disposer.use(await run.orThrow(startApp()));
26
+ * ```
27
+ *
28
+ * @group React Native Run
29
+ */
30
+ export declare const createRun: CreateRun<RunDeps>;
31
+ //# sourceMappingURL=Task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Task.d.ts","sourceRoot":"","sources":["../../src/Task.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGL,KAAK,SAAS,EAEd,KAAK,OAAO,EACb,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,OAAO,CA4BxC,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * React Native-specific Task utilities.
3
+ *
4
+ * @module
5
+ */
6
+ import { createRun as createCommonRun, createUnknownError, } from "@evolu/common";
7
+ /**
8
+ * Creates {@link Run} for React Native with global error handling.
9
+ *
10
+ * Registers `ErrorUtils.setGlobalHandler` for uncaught JavaScript errors. The
11
+ * handler is restored to the previous one when the Run is disposed.
12
+ *
13
+ * ### Example
14
+ *
15
+ * ```ts
16
+ * const console = createConsole({
17
+ * formatter: createConsoleFormatter()({
18
+ * timestampFormat: "relative",
19
+ * }),
20
+ * });
21
+ *
22
+ * await using run = createRun({ console });
23
+ * await using disposer = new AsyncDisposableStack();
24
+ *
25
+ * disposer.use(await run.orThrow(startApp()));
26
+ * ```
27
+ *
28
+ * @group React Native Run
29
+ */
30
+ export const createRun = (deps) => {
31
+ const run = createCommonRun(deps);
32
+ const console = run.deps.console.child("global");
33
+ const previousHandler = globalThis.ErrorUtils?.getGlobalHandler();
34
+ const handleError = (error, isFatal) => {
35
+ console.error(isFatal ? "fatalError" : "uncaughtError", createUnknownError(error));
36
+ // Call the previous handler if it exists
37
+ previousHandler?.(error, isFatal);
38
+ };
39
+ globalThis.ErrorUtils?.setGlobalHandler(handleError);
40
+ run.onAbort(() => {
41
+ if (previousHandler) {
42
+ globalThis.ErrorUtils?.setGlobalHandler(previousHandler);
43
+ }
44
+ });
45
+ return run;
46
+ };
@@ -0,0 +1,9 @@
1
+ import { type IdenticonStyle, OwnerId } from "@evolu/common";
2
+ import { type FC } from "react";
3
+ export declare const EvoluIdenticon: FC<{
4
+ id: OwnerId;
5
+ size?: number;
6
+ borderRadius?: number;
7
+ style?: IdenticonStyle;
8
+ }>;
9
+ //# sourceMappingURL=EvoluIdenticon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EvoluIdenticon.d.ts","sourceRoot":"","sources":["../../../src/components/EvoluIdenticon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,KAAK,EAAE,EAAW,MAAM,OAAO,CAAC;AAIzC,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB,CAcA,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createIdenticon } from "@evolu/common";
2
+ import { createIdenticon, OwnerId } from "@evolu/common";
3
3
  import { useMemo } from "react";
4
4
  import { View } from "react-native";
5
5
  import { SvgXml } from "react-native-svg";
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=createExpoDeps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createExpoDeps.d.ts","sourceRoot":"","sources":["../../src/createExpoDeps.ts"],"names":[],"mappings":""}