@evolu/react-native 15.0.0-next.0 → 15.0.0-next.2

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.
@@ -1,37 +1,119 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
1
53
  import { bytesToHex, createPreparedStatementsCache, lazyVoid, ok, } from "@evolu/common";
2
54
  import { open } from "@op-engineering/op-sqlite";
3
55
  export const createOpSqliteDriver = (name, options) => () => {
4
- // https://op-engineering.github.io/op-sqlite/docs/configuration#in-memory
5
- const stack = new globalThis.DisposableStack();
6
- const db = stack.adopt(open(options?.mode === "memory"
7
- ? { name: `inMemoryDb`, location: ":memory:" }
8
- : {
9
- name: `evolu1-${name}.db`,
10
- ...(options?.mode === "encrypted" && {
11
- encryptionKey: `x'${bytesToHex(options.encryptionKey)}'`,
12
- }),
13
- }), (db) => {
14
- db.close();
15
- });
16
- const cache = stack.use(createPreparedStatementsCache((sql) => db.prepareStatement(sql),
17
- // op-sqlite doesn't have API for that
18
- lazyVoid));
19
- return ok({
20
- exec: (query) => {
21
- const prepared = cache.get(query);
22
- if (prepared) {
23
- prepared.bindSync(query.parameters);
24
- }
25
- const { rows, rowsAffected } = db.executeSync(query.sql, query.parameters);
26
- return { rows: rows, changes: rowsAffected };
27
- },
28
- // FIXME: op-sqlite does not expose binary, but a path to the database file
29
- // another react native dependency would be needed to implement this
30
- export: () => {
31
- throw new Error("TODO: Not implemented yet");
32
- },
33
- [Symbol.dispose]: () => {
34
- stack.dispose();
35
- },
36
- });
56
+ const env_1 = { stack: [], error: void 0, hasError: false };
57
+ try {
58
+ // https://op-engineering.github.io/op-sqlite/docs/configuration#in-memory
59
+ const disposer = __addDisposableResource(env_1, new DisposableStack(), false);
60
+ const db = disposer.adopt(open(options?.mode === "memory"
61
+ ? { name: `inMemoryDb`, location: ":memory:" }
62
+ : {
63
+ name: `evolu1-${name}.db`,
64
+ ...(options?.mode === "encrypted" && {
65
+ encryptionKey: `x'${bytesToHex(options.encryptionKey)}'`,
66
+ }),
67
+ }), (db) => {
68
+ db.close();
69
+ });
70
+ const cache = disposer.use(createPreparedStatementsCache((sql) => db.prepareStatement(sql),
71
+ // op-sqlite doesn't have API for that
72
+ lazyVoid));
73
+ const disposables = disposer.move();
74
+ return ok({
75
+ exec: (query) => {
76
+ const prepared = cache.get(query);
77
+ if (prepared) {
78
+ prepared.bindSync(query.parameters);
79
+ }
80
+ const { rows, rowsAffected } = db.executeSync(query.sql, query.parameters);
81
+ return { rows: rows, changes: rowsAffected };
82
+ },
83
+ // FIXME: op-sqlite does not expose binary, but a path to the database file
84
+ // another react native dependency would be needed to implement this
85
+ export: () => {
86
+ throw new Error("TODO: Not implemented yet");
87
+ },
88
+ deleteDatabase: () => {
89
+ const env_2 = { stack: [], error: void 0, hasError: false };
90
+ try {
91
+ const deleteDisposer = __addDisposableResource(env_2, new DisposableStack(), false);
92
+ if (options?.mode !== "memory") {
93
+ deleteDisposer.defer(() => {
94
+ db.delete();
95
+ });
96
+ }
97
+ deleteDisposer.use(disposables);
98
+ }
99
+ catch (e_2) {
100
+ env_2.error = e_2;
101
+ env_2.hasError = true;
102
+ }
103
+ finally {
104
+ __disposeResources(env_2);
105
+ }
106
+ },
107
+ [Symbol.dispose]: () => {
108
+ disposables.dispose();
109
+ },
110
+ });
111
+ }
112
+ catch (e_1) {
113
+ env_1.error = e_1;
114
+ env_1.hasError = true;
115
+ }
116
+ finally {
117
+ __disposeResources(env_1);
118
+ }
37
119
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolu/react-native",
3
- "version": "15.0.0-next.0",
3
+ "version": "15.0.0-next.2",
4
4
  "description": "Evolu for React Native and Expo",
5
5
  "keywords": [
6
6
  "evolu",
@@ -12,7 +12,10 @@
12
12
  ],
13
13
  "author": "Daniel Steigerwald <daniel@steigerwald.cz>",
14
14
  "license": "MIT",
15
- "repository": "evoluhq/evolu",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/evoluhq/evolu.git"
18
+ },
16
19
  "bugs": {
17
20
  "url": "https://github.com/evoluhq/evolu/issues"
18
21
  },
@@ -72,11 +75,6 @@
72
75
  "src/**",
73
76
  "README.md"
74
77
  ],
75
- "scripts": {
76
- "build": "tsc --build tsconfig.build.json",
77
- "prepack": "npm run build",
78
- "format": "prettier --write \"src/*.{ts,tsx,md}\""
79
- },
80
78
  "dependencies": {
81
79
  "array-from-async": "^3.0.0",
82
80
  "array.prototype.tosorted": "^1.1.4",
@@ -91,20 +89,20 @@
91
89
  "set.prototype.union": "^1.1.3"
92
90
  },
93
91
  "devDependencies": {
94
- "@evolu/common": "8.0.0-next.0",
95
- "@evolu/react": "11.0.0-next.0",
96
- "@evolu/typescript-config": "*",
97
92
  "@op-engineering/op-sqlite": "^15.2.2",
98
93
  "@types/react": "^19.2.14",
99
94
  "expo": "^55.0.4",
100
95
  "expo-secure-store": "~55.0.8",
101
96
  "expo-sqlite": "~55.0.10",
102
97
  "react": "^19.2.4",
103
- "react-native": "0.83.2",
98
+ "react-native": "0.83.6",
104
99
  "react-native-nitro-modules": "0.34.1",
105
100
  "react-native-sensitive-info": "6.0.0-rc.11",
106
101
  "react-native-svg": "15.15.3",
107
- "typescript": "^5.9.3"
102
+ "typescript": "^6",
103
+ "@evolu/common": "8.0.0-next.5",
104
+ "@evolu/react": "11.0.0-next.0",
105
+ "@evolu/typescript-config": "0.0.2"
108
106
  },
109
107
  "peerDependencies": {
110
108
  "@evolu/common": "^8.0.0-next.0",
@@ -148,5 +146,9 @@
148
146
  "engines": {
149
147
  "node": ">=24.0.0"
150
148
  },
151
- "sideEffects": false
152
- }
149
+ "sideEffects": false,
150
+ "scripts": {
151
+ "build": "tsc --build tsconfig.build.json",
152
+ "format": "prettier --write \"src/*.{ts,tsx,md}\""
153
+ }
154
+ }
@@ -0,0 +1,325 @@
1
+ /**
2
+ * React Native implementation of {@link LockManager}.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ /**
8
+ * React Native `LockManager` ponyfill.
9
+ *
10
+ * This is a temporary in-memory ponyfill until React Native ships native
11
+ * `LockManager` support.
12
+ *
13
+ * The ponyfill follows Web Locks request and query semantics within the current
14
+ * JavaScript process.
15
+ *
16
+ * ### Example
17
+ *
18
+ * ```ts
19
+ * await lockManager.request("db", async () => {
20
+ * // critical section
21
+ * });
22
+ * ```
23
+ */
24
+ const createLockManagerPonyfill = ({
25
+ clientId = "in-memory-main-thread",
26
+ }: {
27
+ readonly clientId?: string;
28
+ } = {}): LockManager => {
29
+ const heldLocksByName = new Map<string, Array<HeldLock>>();
30
+ const pendingRequestsByName = new Map<string, Array<PendingRequest<any>>>();
31
+
32
+ const processPendingRequests = (name: string): void => {
33
+ const pendingRequests = pendingRequestsByName.get(name);
34
+ if (pendingRequests == null || pendingRequests.length === 0) return;
35
+
36
+ const heldLocks = heldLocksByName.get(name) ?? [];
37
+ const hasExclusiveLock = heldLocks.some(
38
+ (lock) => lock.mode === "exclusive",
39
+ );
40
+ if (hasExclusiveLock) return;
41
+
42
+ if (heldLocks.length === 0) {
43
+ const nextRequest = pendingRequests[0];
44
+ if (nextRequest.mode === "exclusive") {
45
+ grantPendingRequest(name, pendingRequests.shift()!);
46
+ } else {
47
+ while (pendingRequests[0]?.mode === "shared") {
48
+ grantPendingRequest(name, pendingRequests.shift()!);
49
+ }
50
+ }
51
+ } else {
52
+ while (pendingRequests[0]?.mode === "shared") {
53
+ grantPendingRequest(name, pendingRequests.shift()!);
54
+ }
55
+ }
56
+
57
+ cleanupNameState(name);
58
+ };
59
+
60
+ const grantPendingRequest = <T>(
61
+ name: string,
62
+ pendingRequest: PendingRequest<T>,
63
+ ): void => {
64
+ const heldLocks = heldLocksByName.get(name) ?? [];
65
+ const heldLock = {
66
+ clientId,
67
+ mode: pendingRequest.mode,
68
+ name,
69
+ reject: pendingRequest.reject,
70
+ } satisfies HeldLock;
71
+
72
+ heldLocks.push(heldLock);
73
+ heldLocksByName.set(name, heldLocks);
74
+ pendingRequest.phase = "granted";
75
+
76
+ void Promise.resolve()
77
+ .then(() => {
78
+ if (pendingRequest.signal?.aborted) {
79
+ pendingRequest.phase = "settled";
80
+ pendingRequest.signal.removeEventListener(
81
+ "abort",
82
+ pendingRequest.abort,
83
+ );
84
+ releaseHeldLock(name, heldLock);
85
+ return;
86
+ }
87
+
88
+ pendingRequest.signal?.removeEventListener(
89
+ "abort",
90
+ pendingRequest.abort,
91
+ );
92
+ pendingRequest.phase = "running";
93
+
94
+ return Promise.resolve(
95
+ pendingRequest.callback({ mode: pendingRequest.mode, name }),
96
+ );
97
+ })
98
+ .then(
99
+ (value) => {
100
+ if (pendingRequest.phase === "settled") return;
101
+
102
+ pendingRequest.phase = "settled";
103
+ releaseHeldLock(name, heldLock);
104
+ pendingRequest.resolve(value!);
105
+ },
106
+ (error: unknown) => {
107
+ pendingRequest.phase = "settled";
108
+ releaseHeldLock(name, heldLock);
109
+ pendingRequest.reject(error);
110
+ },
111
+ );
112
+ };
113
+
114
+ const releaseHeldLock = (name: string, heldLock: HeldLock): void => {
115
+ const currentHeldLocks = heldLocksByName.get(name) ?? [];
116
+ heldLocksByName.set(
117
+ name,
118
+ currentHeldLocks.filter((lock) => lock !== heldLock),
119
+ );
120
+
121
+ cleanupNameState(name);
122
+ processPendingRequests(name);
123
+ };
124
+
125
+ const stealLocks = (name: string): void => {
126
+ const heldLocks = heldLocksByName.get(name) ?? [];
127
+ if (heldLocks.length === 0) return;
128
+
129
+ heldLocksByName.delete(name);
130
+
131
+ for (const heldLock of heldLocks) {
132
+ heldLock.reject(createAbortError());
133
+ }
134
+ };
135
+
136
+ const cleanupNameState = (name: string): void => {
137
+ if (heldLocksByName.get(name)?.length === 0) {
138
+ heldLocksByName.delete(name);
139
+ }
140
+
141
+ if (pendingRequestsByName.get(name)?.length === 0) {
142
+ pendingRequestsByName.delete(name);
143
+ }
144
+ };
145
+
146
+ const removePendingRequest = <T>(
147
+ name: string,
148
+ pendingRequest: PendingRequest<T>,
149
+ ): void => {
150
+ const pendingRequests = pendingRequestsByName.get(name)!;
151
+ pendingRequestsByName.set(
152
+ name,
153
+ pendingRequests.filter((request) => request !== pendingRequest),
154
+ );
155
+
156
+ cleanupNameState(name);
157
+ processPendingRequests(name);
158
+ };
159
+
160
+ const canGrantImmediately = (name: string, mode: LockMode): boolean => {
161
+ const pendingRequests = pendingRequestsByName.get(name);
162
+ if (pendingRequests != null && pendingRequests.length > 0) {
163
+ return false;
164
+ }
165
+
166
+ const heldLocks = heldLocksByName.get(name) ?? [];
167
+
168
+ if (mode === "exclusive") {
169
+ return heldLocks.length === 0;
170
+ }
171
+
172
+ return heldLocks.every((lock) => lock.mode === "shared");
173
+ };
174
+
175
+ return {
176
+ request: <T>(
177
+ name: string,
178
+ optionsOrCallback: RequestOptions | LockGrantedCallback<T>,
179
+ maybeCallback?: LockGrantedCallback<T>,
180
+ ): Promise<Awaited<T>> => {
181
+ const [options, callback] = normalizeRequestArguments(
182
+ optionsOrCallback,
183
+ maybeCallback,
184
+ );
185
+ const mode = options.mode ?? "exclusive";
186
+
187
+ if (name.startsWith("-")) {
188
+ return Promise.reject(createNotSupportedError());
189
+ }
190
+
191
+ if (options.ifAvailable && options.steal) {
192
+ return Promise.reject(createNotSupportedError());
193
+ }
194
+
195
+ if (options.steal && mode !== "exclusive") {
196
+ return Promise.reject(createNotSupportedError());
197
+ }
198
+
199
+ if (options.signal != null && (options.ifAvailable || options.steal)) {
200
+ return Promise.reject(createNotSupportedError());
201
+ }
202
+
203
+ if (options.signal?.aborted) {
204
+ return Promise.reject(options.signal.reason as Error);
205
+ }
206
+
207
+ if (options.ifAvailable && !canGrantImmediately(name, mode)) {
208
+ return Promise.resolve().then(() => Promise.resolve(callback(null)));
209
+ }
210
+
211
+ return new Promise<Awaited<T>>((resolve, reject) => {
212
+ const pendingRequest: PendingRequest<T> = {
213
+ abort: () => {
214
+ if (pendingRequest.phase === "queued") {
215
+ pendingRequest.phase = "settled";
216
+ removePendingRequest(name, pendingRequest);
217
+ reject(options.signal!.reason as Error);
218
+ return;
219
+ }
220
+
221
+ pendingRequest.phase = "settled";
222
+ reject(options.signal!.reason as Error);
223
+ },
224
+ callback,
225
+ mode,
226
+ name,
227
+ phase: "queued",
228
+ reject,
229
+ resolve,
230
+ ...(options.signal == null ? {} : { signal: options.signal }),
231
+ };
232
+
233
+ if (options.signal != null) {
234
+ options.signal.addEventListener("abort", pendingRequest.abort, {
235
+ once: true,
236
+ });
237
+ }
238
+
239
+ const pendingRequests = pendingRequestsByName.get(name) ?? [];
240
+
241
+ if (options.steal) {
242
+ stealLocks(name);
243
+ pendingRequests.unshift(pendingRequest);
244
+ } else {
245
+ pendingRequests.push(pendingRequest);
246
+ }
247
+
248
+ pendingRequestsByName.set(name, pendingRequests);
249
+ processPendingRequests(name);
250
+ });
251
+ },
252
+
253
+ query: () => {
254
+ const held = Array.from(heldLocksByName.values())
255
+ .flat()
256
+ .map(({ clientId, mode, name }) => ({ clientId, mode, name }));
257
+ const pending = Array.from(pendingRequestsByName.values())
258
+ .flat()
259
+ .map(({ mode, name }) => ({
260
+ clientId,
261
+ mode,
262
+ name,
263
+ }));
264
+
265
+ return Promise.resolve({ held, pending });
266
+ },
267
+ };
268
+ };
269
+
270
+ /**
271
+ * React Native {@link LockManager}.
272
+ *
273
+ * Uses an in-memory lock manager scoped to the main JavaScript thread while
274
+ * following Web Locks request and query semantics.
275
+ */
276
+ export const lockManager: LockManager = /*#__PURE__*/ createLockManagerPonyfill(
277
+ {
278
+ clientId: "react-native-main-thread",
279
+ },
280
+ );
281
+
282
+ const normalizeRequestArguments = <T>(
283
+ optionsOrCallback: RequestOptions | LockGrantedCallback<T>,
284
+ maybeCallback?: LockGrantedCallback<T>,
285
+ ): [RequestOptions, LockGrantedCallback<T>] =>
286
+ typeof optionsOrCallback === "function"
287
+ ? [{}, optionsOrCallback]
288
+ : [optionsOrCallback, maybeCallback!];
289
+
290
+ const createAbortError = (): Error =>
291
+ createNamedError("AbortError", "The request was aborted.");
292
+
293
+ const createNotSupportedError = (): Error =>
294
+ createNamedError("NotSupportedError", "The operation is not supported.");
295
+
296
+ const createNamedError = (name: string, message: string): Error => {
297
+ const error = new Error(message) as Error & { name: string };
298
+ error.name = name;
299
+ return error;
300
+ };
301
+
302
+ interface HeldLock extends LockInfo {
303
+ readonly clientId: string;
304
+ readonly mode: LockMode;
305
+ readonly name: string;
306
+ readonly reject: (reason?: unknown) => void;
307
+ }
308
+
309
+ interface RequestOptions {
310
+ readonly ifAvailable?: boolean;
311
+ readonly mode?: LockMode;
312
+ readonly signal?: AbortSignal;
313
+ readonly steal?: boolean;
314
+ }
315
+
316
+ interface PendingRequest<T> {
317
+ readonly abort: () => void;
318
+ readonly callback: LockGrantedCallback<T>;
319
+ readonly mode: LockMode;
320
+ readonly name: string;
321
+ phase: "queued" | "granted" | "running" | "settled";
322
+ readonly reject: (reason?: unknown) => void;
323
+ readonly resolve: (value: Awaited<T> | PromiseLike<Awaited<T>>) => void;
324
+ readonly signal?: AbortSignal;
325
+ }
package/src/Polyfills.ts CHANGED
@@ -76,10 +76,6 @@ interface AbortControllerPrototype extends AbortController {
76
76
  readonly __evoluAbortReasonPatched?: true;
77
77
  }
78
78
 
79
- interface AbortSignalWithReason extends AbortSignal {
80
- readonly reason: unknown;
81
- }
82
-
83
79
  interface AnyControllersRegistry {
84
80
  readonly add: (controller: AbortController) => void;
85
81
  readonly remove: (controller: AbortController) => void;
@@ -99,12 +95,12 @@ const anyControllersBySignal = new WeakMap<
99
95
 
100
96
  const installAbortControllerPolyfills = (): void => {
101
97
  installAbortReasonPolyfill(
102
- globalThis.AbortController as AbortControllerConstructor,
103
- globalThis.AbortSignal as AbortSignalConstructor,
98
+ globalThis.AbortController,
99
+ globalThis.AbortSignal,
104
100
  );
105
101
  installAbortSignalStaticMethods(
106
- globalThis.AbortController as AbortControllerConstructor,
107
- globalThis.AbortSignal as AbortSignalConstructor,
102
+ globalThis.AbortController,
103
+ globalThis.AbortSignal,
108
104
  );
109
105
  };
110
106
 
@@ -279,7 +275,7 @@ const createAnyControllersRegistry = (
279
275
 
280
276
  const readSignalReason = (signal: AbortSignal): unknown => {
281
277
  if ("reason" in signal) {
282
- return (signal as AbortSignalWithReason).reason;
278
+ return signal.reason;
283
279
  }
284
280
  return createAbortError();
285
281
  };
package/src/Task.ts CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  createUnknownError,
10
10
  type CreateRun,
11
11
  type Run,
12
- type RunDeps,
12
+ type RunDefaultDeps,
13
13
  } from "@evolu/common";
14
14
 
15
15
  /**
@@ -28,16 +28,16 @@ import {
28
28
  * });
29
29
  *
30
30
  * await using run = createRun({ console });
31
- * await using stack = new AsyncDisposableStack();
31
+ * await using disposer = new AsyncDisposableStack();
32
32
  *
33
- * stack.use(await run.orThrow(startApp()));
33
+ * disposer.use(await run.orThrow(startApp()));
34
34
  * ```
35
35
  *
36
36
  * @group React Native Run
37
37
  */
38
- export const createRun: CreateRun<RunDeps> = <D>(
38
+ export const createRun: CreateRun<RunDefaultDeps> = <D>(
39
39
  deps?: D,
40
- ): Run<RunDeps & D> => {
40
+ ): Run<RunDefaultDeps & D> => {
41
41
  const run = createCommonRun(deps);
42
42
 
43
43
  const console = run.deps.console.child("global");
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from "./components/EvoluIdenticon.js";
2
+ export * from "./LockManager.js";
2
3
  export * from "./Task.js";
3
- export * from "./Worker.js";
package/src/shared.ts CHANGED
@@ -1,10 +1,14 @@
1
1
  import {
2
2
  createConsole,
3
3
  createConsoleStoreOutput,
4
- createInMemoryLeaderLock,
4
+ createBroadcastChannel,
5
+ createMessageChannel,
6
+ createMessagePort,
5
7
  createRandomBytes,
6
8
  createRun,
9
+ createSharedWorker,
7
10
  createWebSocket,
11
+ createWorker,
8
12
  type ConsoleDep,
9
13
  type CreateSqliteDriverDep,
10
14
  type ReloadAppDep,
@@ -15,20 +19,14 @@ import type {
15
19
  DbWorkerInit,
16
20
  EvoluDeps,
17
21
  SharedWorkerInput,
22
+ SharedWorkerOutput,
18
23
  } from "@evolu/common/local-first";
19
24
  import {
20
25
  createEvoluDeps as createCommonEvoluDeps,
21
- startDbWorker,
22
26
  initSharedWorker,
27
+ startDbWorker,
23
28
  } from "@evolu/common/local-first";
24
- import {
25
- createMessageChannel,
26
- createMessagePort,
27
- createSharedWorker,
28
- createWorker,
29
- } from "./Worker.js";
30
-
31
- const leaderLock = createInMemoryLeaderLock();
29
+ import { lockManager } from "./LockManager.js";
32
30
 
33
31
  /** Creates Evolu dependencies for React Native. */
34
32
  export const createEvoluDeps = (
@@ -46,10 +44,12 @@ export const createEvoluDeps = (
46
44
  return createRun({
47
45
  console: workerConsole,
48
46
  consoleStoreOutputEntry: consoleStoreOutput.entry,
47
+ createBroadcastChannel,
48
+ createMessageChannel,
49
49
  createMessagePort,
50
50
  createWebSocket,
51
51
  createSqliteDriver: deps.createSqliteDriver,
52
- leaderLock,
52
+ lockManager,
53
53
  randomBytes: createRandomBytes(),
54
54
  });
55
55
  };
@@ -60,7 +60,10 @@ export const createEvoluDeps = (
60
60
  dbWorkerRun(startDbWorker(self));
61
61
  });
62
62
 
63
- const sharedWorker = createSharedWorker<SharedWorkerInput, never>((self) => {
63
+ const sharedWorker = createSharedWorker<
64
+ SharedWorkerInput,
65
+ SharedWorkerOutput
66
+ >((self) => {
64
67
  const sharedWorkerRun = createWorkerRun();
65
68
  sharedWorkerRun(initSharedWorker(self));
66
69
  });
@@ -68,7 +71,9 @@ export const createEvoluDeps = (
68
71
  return createCommonEvoluDeps({
69
72
  ...deps,
70
73
  createDbWorker,
74
+ createBroadcastChannel,
71
75
  createMessageChannel,
76
+ lockManager,
72
77
  reloadApp: deps.reloadApp,
73
78
  sharedWorker,
74
79
  });