@evolu/web 2.4.0 → 3.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.
- package/README.md +3 -1
- package/dist/src/Platform.d.ts +3 -0
- package/dist/src/Platform.d.ts.map +1 -0
- package/dist/src/{local-first/Platform.js → Platform.js} +1 -1
- package/dist/src/Sqlite.d.ts +3 -0
- package/dist/src/Sqlite.d.ts.map +1 -0
- package/dist/src/Sqlite.js +162 -0
- package/dist/src/Task.d.ts +29 -0
- package/dist/src/Task.d.ts.map +1 -0
- package/dist/src/Task.js +38 -0
- package/dist/src/Worker.d.ts +60 -0
- package/dist/src/Worker.d.ts.map +1 -0
- package/dist/src/Worker.js +328 -0
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/local-first/Db.worker.js +13 -10
- package/dist/src/local-first/Evolu.d.ts +11 -0
- package/dist/src/local-first/Evolu.d.ts.map +1 -0
- package/dist/src/local-first/Evolu.js +57 -0
- package/dist/src/local-first/LocalAuth.d.ts +2 -3
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/LocalAuth.js +60 -71
- package/dist/src/local-first/Shared.worker.d.ts +2 -0
- package/dist/src/local-first/Shared.worker.d.ts.map +1 -0
- package/dist/src/local-first/Shared.worker.js +94 -0
- package/dist/src/local-first/index.d.ts +1 -3
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +1 -20
- package/package.json +16 -16
- package/src/Platform.ts +9 -0
- package/src/Sqlite.ts +138 -0
- package/src/Task.ts +59 -0
- package/src/Worker.ts +319 -0
- package/src/index.ts +3 -3
- package/src/local-first/Db.worker.ts +16 -16
- package/src/local-first/Evolu.ts +104 -0
- package/src/local-first/LocalAuth.ts +93 -105
- package/src/local-first/Shared.worker.ts +58 -0
- package/src/local-first/index.ts +1 -41
- package/dist/src/SharedWebWorker.d.ts +0 -30
- package/dist/src/SharedWebWorker.d.ts.map +0 -1
- package/dist/src/SharedWebWorker.js +0 -104
- package/dist/src/WasmSqliteDriver.d.ts +0 -3
- package/dist/src/WasmSqliteDriver.d.ts.map +0 -1
- package/dist/src/WasmSqliteDriver.js +0 -85
- package/dist/src/WebWorker.d.ts +0 -17
- package/dist/src/WebWorker.d.ts.map +0 -1
- package/dist/src/WebWorker.js +0 -42
- package/dist/src/local-first/Platform.d.ts +0 -3
- package/dist/src/local-first/Platform.d.ts.map +0 -1
- package/dist/test/SharedWebWorker.test.d.ts +0 -2
- package/dist/test/SharedWebWorker.test.d.ts.map +0 -1
- package/dist/test/SharedWebWorker.test.js +0 -248
- package/src/SharedWebWorker.ts +0 -149
- package/src/WasmSqliteDriver.ts +0 -118
- package/src/WebWorker.ts +0 -54
- package/src/local-first/Platform.ts +0 -9
package/src/Task.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web platform-specific Task utilities.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
createRun as createCommonRun,
|
|
9
|
+
createUnknownError,
|
|
10
|
+
type CreateRun,
|
|
11
|
+
type Run,
|
|
12
|
+
type RunDefaultDeps,
|
|
13
|
+
} from "@evolu/common";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates {@link Run} for the browser with global error handling.
|
|
17
|
+
*
|
|
18
|
+
* Registers `error` and `unhandledrejection` handlers that log errors to the
|
|
19
|
+
* console. Handlers are removed when the Run is disposed.
|
|
20
|
+
*
|
|
21
|
+
* ### Example
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* const console = createConsole({
|
|
25
|
+
* formatter: createConsoleFormatter()({
|
|
26
|
+
* timestampFormat: "relative",
|
|
27
|
+
* }),
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* await using run = createRun({ console });
|
|
31
|
+
* await using disposer = new AsyncDisposableStack();
|
|
32
|
+
*
|
|
33
|
+
* disposer.use(await run.orThrow(startApp()));
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const createRun: CreateRun<RunDefaultDeps> = <D>(
|
|
37
|
+
deps?: D,
|
|
38
|
+
): Run<RunDefaultDeps & D> => {
|
|
39
|
+
const run = createCommonRun(deps);
|
|
40
|
+
const console = run.deps.console.child("global");
|
|
41
|
+
|
|
42
|
+
globalThis.addEventListener(
|
|
43
|
+
"error",
|
|
44
|
+
(event) => {
|
|
45
|
+
console.error("error", createUnknownError(event.error));
|
|
46
|
+
},
|
|
47
|
+
{ signal: run.signal },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
globalThis.addEventListener(
|
|
51
|
+
"unhandledrejection",
|
|
52
|
+
(event) => {
|
|
53
|
+
console.error("unhandledrejection", createUnknownError(event.reason));
|
|
54
|
+
},
|
|
55
|
+
{ signal: run.signal },
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return run;
|
|
59
|
+
};
|
package/src/Worker.ts
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BroadcastChannel,
|
|
3
|
+
CreateBroadcastChannel,
|
|
4
|
+
CreateBroadcastChannelDep,
|
|
5
|
+
CreateMessageChannelDep,
|
|
6
|
+
CreateMessagePort,
|
|
7
|
+
MessageChannel,
|
|
8
|
+
MessagePort,
|
|
9
|
+
NativeMessagePort,
|
|
10
|
+
SharedWorker,
|
|
11
|
+
SharedWorkerSelf,
|
|
12
|
+
Transferable,
|
|
13
|
+
Worker,
|
|
14
|
+
WorkerDeps,
|
|
15
|
+
WorkerSelf,
|
|
16
|
+
} from "@evolu/common";
|
|
17
|
+
import {
|
|
18
|
+
assert,
|
|
19
|
+
assertNotDisposed,
|
|
20
|
+
createConsole,
|
|
21
|
+
createConsoleStoreOutput,
|
|
22
|
+
} from "@evolu/common";
|
|
23
|
+
|
|
24
|
+
/** Creates a {@link Worker} from a Web Worker. */
|
|
25
|
+
export const createWorker = <Input, Output>(
|
|
26
|
+
nativeWorker: globalThis.Worker,
|
|
27
|
+
): Worker<Input, Output> => wrap(nativeWorker);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Installs a one-tab SharedWorker polyfill backed by a Web Worker.
|
|
31
|
+
*
|
|
32
|
+
* Use it before constructing a SharedWorker in browsers without native
|
|
33
|
+
* SharedWorker support.
|
|
34
|
+
*/
|
|
35
|
+
export const installOneTabSharedWorkerPolyfill = (): void => {
|
|
36
|
+
if (typeof globalThis.SharedWorker === "function") return;
|
|
37
|
+
|
|
38
|
+
Object.defineProperty(globalThis, "SharedWorker", {
|
|
39
|
+
configurable: true,
|
|
40
|
+
writable: true,
|
|
41
|
+
value: class {
|
|
42
|
+
readonly port: globalThis.MessagePort;
|
|
43
|
+
|
|
44
|
+
constructor(scriptURL: string | URL, options?: WorkerOptions) {
|
|
45
|
+
this.port = new globalThis.Worker(
|
|
46
|
+
scriptURL,
|
|
47
|
+
options,
|
|
48
|
+
) as unknown as globalThis.MessagePort;
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Creates a {@link SharedWorker} from a Web SharedWorker.
|
|
56
|
+
*
|
|
57
|
+
* Call {@link installOneTabSharedWorkerPolyfill} first to support browsers
|
|
58
|
+
* without native SharedWorker support.
|
|
59
|
+
*/
|
|
60
|
+
export const createSharedWorker = <Input, Output = never>(
|
|
61
|
+
nativeSharedWorker: globalThis.SharedWorker,
|
|
62
|
+
): SharedWorker<Input, Output> => {
|
|
63
|
+
const port = wrap<Input, Output>(nativeSharedWorker.port);
|
|
64
|
+
return {
|
|
65
|
+
port,
|
|
66
|
+
[Symbol.dispose]: port[Symbol.dispose],
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Creates a {@link MessageChannel} from a Web MessageChannel.
|
|
72
|
+
*
|
|
73
|
+
* ### Example
|
|
74
|
+
*
|
|
75
|
+
* ```ts
|
|
76
|
+
* const channel = createMessageChannel<Request, Response>();
|
|
77
|
+
* channel.port1.onMessage = (response) => console.log(response);
|
|
78
|
+
* channel.port1.postMessage({ type: "ping" });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export const createMessageChannel = <Input, Output = never>(): MessageChannel<
|
|
82
|
+
Input,
|
|
83
|
+
Output
|
|
84
|
+
> => {
|
|
85
|
+
const channel = new globalThis.MessageChannel();
|
|
86
|
+
using disposer = new DisposableStack();
|
|
87
|
+
|
|
88
|
+
const port1 = disposer.use(wrap<Input, Output>(channel.port1));
|
|
89
|
+
const port2 = disposer.use(wrap<Output, Input>(channel.port2));
|
|
90
|
+
const disposables = disposer.move();
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
port1,
|
|
94
|
+
port2,
|
|
95
|
+
[Symbol.dispose]: () => disposables.dispose(),
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Creates an Evolu {@link MessagePort} from a Web MessagePort.
|
|
101
|
+
*
|
|
102
|
+
* Use this for ports received via postMessage transfer.
|
|
103
|
+
*/
|
|
104
|
+
export const createMessagePort: CreateMessagePort = (nativePort) =>
|
|
105
|
+
wrap(nativePort as unknown as globalThis.MessagePort);
|
|
106
|
+
|
|
107
|
+
/** Creates an Evolu {@link BroadcastChannel} from a Web BroadcastChannel. */
|
|
108
|
+
export const createBroadcastChannel: CreateBroadcastChannel = <
|
|
109
|
+
Input,
|
|
110
|
+
Output = Input,
|
|
111
|
+
>(
|
|
112
|
+
name: string,
|
|
113
|
+
): BroadcastChannel<Input, Output> => {
|
|
114
|
+
const nativeBroadcastChannel = new globalThis.BroadcastChannel(name);
|
|
115
|
+
using disposer = new DisposableStack();
|
|
116
|
+
|
|
117
|
+
disposer.defer(() => {
|
|
118
|
+
nativeBroadcastChannel.onmessage = null;
|
|
119
|
+
nativeBroadcastChannel.close();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const disposables = disposer.move();
|
|
123
|
+
let onMessageHandler: ((message: Output) => void) | null = null;
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
postMessage: (message) => {
|
|
127
|
+
assertNotDisposed(disposables);
|
|
128
|
+
nativeBroadcastChannel.postMessage(message);
|
|
129
|
+
},
|
|
130
|
+
get onMessage() {
|
|
131
|
+
return disposables.disposed ? null : onMessageHandler;
|
|
132
|
+
},
|
|
133
|
+
set onMessage(fn) {
|
|
134
|
+
if (disposables.disposed) return;
|
|
135
|
+
onMessageHandler = fn;
|
|
136
|
+
nativeBroadcastChannel.onmessage = fn
|
|
137
|
+
? (event: MessageEvent<Output>) => {
|
|
138
|
+
fn(event.data);
|
|
139
|
+
}
|
|
140
|
+
: null;
|
|
141
|
+
},
|
|
142
|
+
[Symbol.dispose]: () => disposables.dispose(),
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Creates an Evolu {@link WorkerSelf} from a Web `DedicatedWorkerGlobalScope`
|
|
148
|
+
* (`self` inside a dedicated worker).
|
|
149
|
+
*/
|
|
150
|
+
export const createWorkerSelf = <Input, Output = never>(
|
|
151
|
+
nativeSelf: globalThis.DedicatedWorkerGlobalScope,
|
|
152
|
+
): WorkerSelf<Input, Output> => wrap<Output, Input>(nativeSelf);
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Creates an Evolu {@link SharedWorkerSelf} from a Web `SharedWorkerGlobalScope`
|
|
156
|
+
* (`self` inside a shared worker).
|
|
157
|
+
*
|
|
158
|
+
* Disposing closes the shared worker scope for all connected clients.
|
|
159
|
+
*/
|
|
160
|
+
export const createSharedWorkerSelf = <Input, Output = never>(
|
|
161
|
+
nativeSelf: globalThis.SharedWorkerGlobalScope,
|
|
162
|
+
): SharedWorkerSelf<Input, Output> => {
|
|
163
|
+
const self: SharedWorkerSelf<Input, Output> = {
|
|
164
|
+
onConnect: null,
|
|
165
|
+
[Symbol.dispose]: () => {
|
|
166
|
+
nativeSelf.onconnect = null;
|
|
167
|
+
nativeSelf.close();
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
nativeSelf.onconnect = (e) => {
|
|
172
|
+
assert(
|
|
173
|
+
self.onConnect != null,
|
|
174
|
+
"onConnect must be set before receiving connections",
|
|
175
|
+
);
|
|
176
|
+
self.onConnect(wrap<Output, Input>(e.ports[0]));
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
return self;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Creates a one-tab {@link SharedWorkerSelf} polyfill for browsers without
|
|
184
|
+
* native SharedWorker support.
|
|
185
|
+
*
|
|
186
|
+
* Delivers one synthetic `onConnect` port, queues startup messages until
|
|
187
|
+
* `onMessage` is set, and does not share state across tabs.
|
|
188
|
+
*/
|
|
189
|
+
export const createOneTabSharedWorkerSelfPolyfill = <Input, Output = never>(
|
|
190
|
+
nativeSelf: globalThis.DedicatedWorkerGlobalScope,
|
|
191
|
+
): SharedWorkerSelf<Input, Output> => {
|
|
192
|
+
using disposer = new DisposableStack();
|
|
193
|
+
|
|
194
|
+
let onConnectHandler: ((port: MessagePort<Output, Input>) => void) | null =
|
|
195
|
+
null;
|
|
196
|
+
let onMessageHandler: ((message: Input) => void) | null = null;
|
|
197
|
+
const messages: Array<Input> = [];
|
|
198
|
+
let connected = false;
|
|
199
|
+
|
|
200
|
+
disposer.defer(() => {
|
|
201
|
+
messages.length = 0;
|
|
202
|
+
onConnectHandler = null;
|
|
203
|
+
onMessageHandler = null;
|
|
204
|
+
nativeSelf.onmessage = null;
|
|
205
|
+
nativeSelf.close();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const disposables = disposer.move();
|
|
209
|
+
|
|
210
|
+
nativeSelf.onmessage = (event: MessageEvent<Input>) => {
|
|
211
|
+
if (disposables.disposed) return;
|
|
212
|
+
|
|
213
|
+
const handler = onMessageHandler;
|
|
214
|
+
if (handler) handler(event.data);
|
|
215
|
+
else messages.push(event.data);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const flushMessages = (): void => {
|
|
219
|
+
for (const message of messages.splice(0)) {
|
|
220
|
+
const handler = onMessageHandler;
|
|
221
|
+
if (!handler) return;
|
|
222
|
+
handler(message);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const port: MessagePort<Output, Input> = {
|
|
227
|
+
postMessage: (message, transfer) => {
|
|
228
|
+
if (disposables.disposed) return;
|
|
229
|
+
if (transfer == null) nativeSelf.postMessage(message);
|
|
230
|
+
else nativeSelf.postMessage(message, [...transfer]);
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
get onMessage() {
|
|
234
|
+
return disposables.disposed ? null : onMessageHandler;
|
|
235
|
+
},
|
|
236
|
+
set onMessage(fn) {
|
|
237
|
+
if (disposables.disposed) return;
|
|
238
|
+
onMessageHandler = fn;
|
|
239
|
+
if (fn) flushMessages();
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
native: nativeSelf as unknown as NativeMessagePort<Output, Input>,
|
|
243
|
+
|
|
244
|
+
[Symbol.dispose]: () => disposables.dispose(),
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const connect = (): void => {
|
|
248
|
+
if (connected || !onConnectHandler) return;
|
|
249
|
+
connected = true;
|
|
250
|
+
onConnectHandler(port);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
get onConnect() {
|
|
255
|
+
return onConnectHandler;
|
|
256
|
+
},
|
|
257
|
+
set onConnect(fn) {
|
|
258
|
+
if (disposables.disposed) return;
|
|
259
|
+
onConnectHandler = fn;
|
|
260
|
+
connect();
|
|
261
|
+
},
|
|
262
|
+
[Symbol.dispose]: () => disposables.dispose(),
|
|
263
|
+
};
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/** Creates deps shared by web worker entry points. */
|
|
267
|
+
export const createWorkerDeps = (): WorkerDeps &
|
|
268
|
+
CreateBroadcastChannelDep &
|
|
269
|
+
CreateMessageChannelDep => {
|
|
270
|
+
const consoleStoreOutput = createConsoleStoreOutput();
|
|
271
|
+
const console = createConsole({ output: consoleStoreOutput });
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
console,
|
|
275
|
+
consoleStoreOutputEntry: consoleStoreOutput.entry,
|
|
276
|
+
createBroadcastChannel,
|
|
277
|
+
createMessageChannel,
|
|
278
|
+
createMessagePort,
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const wrap = <Input, Output>(
|
|
283
|
+
native:
|
|
284
|
+
| DedicatedWorkerGlobalScope
|
|
285
|
+
| globalThis.MessagePort
|
|
286
|
+
| globalThis.Worker,
|
|
287
|
+
): MessagePort<Input, Output> => {
|
|
288
|
+
let onMessageHandler: ((message: Output) => void) | null = null;
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
postMessage: (message: Input, transfer?: ReadonlyArray<Transferable>) => {
|
|
292
|
+
if (transfer == null) native.postMessage(message);
|
|
293
|
+
else native.postMessage(message, [...transfer]);
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
get onMessage() {
|
|
297
|
+
return onMessageHandler;
|
|
298
|
+
},
|
|
299
|
+
set onMessage(fn) {
|
|
300
|
+
onMessageHandler = fn;
|
|
301
|
+
if (fn) {
|
|
302
|
+
// Messages are queued until onMessage is assigned.
|
|
303
|
+
native.onmessage = (event: MessageEvent<Output>) => {
|
|
304
|
+
fn(event.data);
|
|
305
|
+
};
|
|
306
|
+
} else {
|
|
307
|
+
native.onmessage = null;
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
native: native as unknown as NativeMessagePort<Input, Output>,
|
|
312
|
+
|
|
313
|
+
[Symbol.dispose]: () => {
|
|
314
|
+
native.onmessage = null;
|
|
315
|
+
if ("terminate" in native) native.terminate();
|
|
316
|
+
else native.close();
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from "./local-first/index.js";
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
2
|
+
export * from "./Sqlite.js";
|
|
3
|
+
export * from "./Task.js";
|
|
4
|
+
export * from "./Worker.js";
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
createRandom,
|
|
4
|
-
createRandomBytes,
|
|
5
|
-
createTime,
|
|
6
|
-
createWebSocket,
|
|
7
|
-
} from "@evolu/common";
|
|
8
|
-
import { createDbWorkerForPlatform } from "@evolu/common/local-first";
|
|
9
|
-
import { createWasmSqliteDriver } from "../WasmSqliteDriver.js";
|
|
10
|
-
import { wrapWebWorkerSelf } from "../WebWorker.js";
|
|
1
|
+
/// <reference lib="webworker" />
|
|
2
|
+
declare const self: DedicatedWorkerGlobalScope;
|
|
11
3
|
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
import { installPolyfills } from "@evolu/common/polyfills";
|
|
5
|
+
installPolyfills();
|
|
6
|
+
|
|
7
|
+
import { createRandomBytes } from "@evolu/common";
|
|
8
|
+
import { startDbWorker } from "@evolu/common/local-first";
|
|
9
|
+
import { createWasmSqliteDriver } from "../Sqlite.js";
|
|
10
|
+
import { createRun } from "../Task.js";
|
|
11
|
+
import { createWorkerDeps, createWorkerSelf } from "../Worker.js";
|
|
12
|
+
|
|
13
|
+
// TODO: Disposal.
|
|
14
|
+
const run = createRun({
|
|
15
|
+
...createWorkerDeps(),
|
|
14
16
|
createSqliteDriver: createWasmSqliteDriver,
|
|
15
|
-
|
|
16
|
-
random: createRandom(),
|
|
17
|
+
lockManager: globalThis.navigator.locks,
|
|
17
18
|
randomBytes: createRandomBytes(),
|
|
18
|
-
time: createTime(),
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
run(startDbWorker(createWorkerSelf(self)));
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { exhaustiveCheck, type ConsoleDep } from "@evolu/common";
|
|
2
|
+
import type {
|
|
3
|
+
SharedWorker as CommonSharedWorker,
|
|
4
|
+
CreateDbWorker,
|
|
5
|
+
DbWorkerInit,
|
|
6
|
+
EvoluDeps,
|
|
7
|
+
SharedWorkerInput,
|
|
8
|
+
SharedWorkerOutput,
|
|
9
|
+
} from "@evolu/common/local-first";
|
|
10
|
+
import { createEvoluDeps as createCommonEvoluDeps } from "@evolu/common/local-first";
|
|
11
|
+
import { reloadApp } from "../Platform.js";
|
|
12
|
+
import {
|
|
13
|
+
createBroadcastChannel,
|
|
14
|
+
createMessageChannel,
|
|
15
|
+
createSharedWorker,
|
|
16
|
+
createWorker,
|
|
17
|
+
installOneTabSharedWorkerPolyfill,
|
|
18
|
+
} from "../Worker.js";
|
|
19
|
+
|
|
20
|
+
// // TODO: Redesign.
|
|
21
|
+
// // eslint-disable-next-line evolu/require-pure-annotation
|
|
22
|
+
// export const localAuth = createLocalAuth({
|
|
23
|
+
// randomBytes: createRandomBytes(),
|
|
24
|
+
// secureStorage: createWebAuthnStore({ randomBytes: createRandomBytes() }),
|
|
25
|
+
// });
|
|
26
|
+
|
|
27
|
+
export interface SharedWorkerUnsupported {
|
|
28
|
+
readonly type: "SharedWorkerUnsupported";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SharedWorkerUnsupportedDep {
|
|
32
|
+
readonly onSharedWorkerUnsupported: () => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Creates Evolu dependencies for the web platform. */
|
|
36
|
+
export const createEvoluDeps = (
|
|
37
|
+
deps: Partial<ConsoleDep> & Partial<SharedWorkerUnsupportedDep> = {},
|
|
38
|
+
): EvoluDeps => {
|
|
39
|
+
installOneTabSharedWorkerPolyfill();
|
|
40
|
+
|
|
41
|
+
const createDbWorker: CreateDbWorker = () =>
|
|
42
|
+
createWorker<DbWorkerInit, never>(
|
|
43
|
+
new Worker(new URL("Db.worker.js", import.meta.url), {
|
|
44
|
+
type: "module",
|
|
45
|
+
}),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const webSharedWorker = createSharedWorker<
|
|
49
|
+
SharedWorkerInput,
|
|
50
|
+
SharedWorkerOutput
|
|
51
|
+
>(
|
|
52
|
+
new SharedWorker(new URL("Shared.worker.js", import.meta.url), {
|
|
53
|
+
type: "module",
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
let onSharedWorkerMessage: ((message: SharedWorkerOutput) => void) | null =
|
|
57
|
+
null;
|
|
58
|
+
const sharedWorker: CommonSharedWorker = {
|
|
59
|
+
...webSharedWorker,
|
|
60
|
+
port: {
|
|
61
|
+
...webSharedWorker.port,
|
|
62
|
+
get onMessage() {
|
|
63
|
+
return onSharedWorkerMessage;
|
|
64
|
+
},
|
|
65
|
+
set onMessage(fn) {
|
|
66
|
+
onSharedWorkerMessage = fn;
|
|
67
|
+
webSharedWorker.port.onMessage = fn
|
|
68
|
+
? (message: SharedWorkerOutput | SharedWorkerUnsupported) => {
|
|
69
|
+
switch (message.type) {
|
|
70
|
+
case "DbWorkerInit": {
|
|
71
|
+
fn(message);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
case "SharedWorkerUnsupported": {
|
|
76
|
+
if (deps.onSharedWorkerUnsupported) {
|
|
77
|
+
deps.onSharedWorkerUnsupported();
|
|
78
|
+
} else {
|
|
79
|
+
globalThis.alert(
|
|
80
|
+
"This browser supports Evolu in one tab only. Close this tab and use the already open tab.",
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
default:
|
|
87
|
+
exhaustiveCheck(message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
: null;
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return createCommonEvoluDeps({
|
|
96
|
+
...deps,
|
|
97
|
+
createDbWorker,
|
|
98
|
+
createBroadcastChannel,
|
|
99
|
+
createMessageChannel,
|
|
100
|
+
lockManager: globalThis.navigator.locks,
|
|
101
|
+
reloadApp,
|
|
102
|
+
sharedWorker,
|
|
103
|
+
});
|
|
104
|
+
};
|