@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.
Files changed (58) hide show
  1. package/README.md +3 -1
  2. package/dist/src/Platform.d.ts +3 -0
  3. package/dist/src/Platform.d.ts.map +1 -0
  4. package/dist/src/{local-first/Platform.js → Platform.js} +1 -1
  5. package/dist/src/Sqlite.d.ts +3 -0
  6. package/dist/src/Sqlite.d.ts.map +1 -0
  7. package/dist/src/Sqlite.js +162 -0
  8. package/dist/src/Task.d.ts +29 -0
  9. package/dist/src/Task.d.ts.map +1 -0
  10. package/dist/src/Task.js +38 -0
  11. package/dist/src/Worker.d.ts +60 -0
  12. package/dist/src/Worker.d.ts.map +1 -0
  13. package/dist/src/Worker.js +328 -0
  14. package/dist/src/index.d.ts +3 -3
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/index.js +3 -3
  17. package/dist/src/local-first/Db.worker.js +13 -10
  18. package/dist/src/local-first/Evolu.d.ts +11 -0
  19. package/dist/src/local-first/Evolu.d.ts.map +1 -0
  20. package/dist/src/local-first/Evolu.js +57 -0
  21. package/dist/src/local-first/LocalAuth.d.ts +2 -3
  22. package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
  23. package/dist/src/local-first/LocalAuth.js +60 -71
  24. package/dist/src/local-first/Shared.worker.d.ts +2 -0
  25. package/dist/src/local-first/Shared.worker.d.ts.map +1 -0
  26. package/dist/src/local-first/Shared.worker.js +94 -0
  27. package/dist/src/local-first/index.d.ts +1 -3
  28. package/dist/src/local-first/index.d.ts.map +1 -1
  29. package/dist/src/local-first/index.js +1 -20
  30. package/package.json +16 -16
  31. package/src/Platform.ts +9 -0
  32. package/src/Sqlite.ts +138 -0
  33. package/src/Task.ts +59 -0
  34. package/src/Worker.ts +319 -0
  35. package/src/index.ts +3 -3
  36. package/src/local-first/Db.worker.ts +16 -16
  37. package/src/local-first/Evolu.ts +104 -0
  38. package/src/local-first/LocalAuth.ts +93 -105
  39. package/src/local-first/Shared.worker.ts +58 -0
  40. package/src/local-first/index.ts +1 -41
  41. package/dist/src/SharedWebWorker.d.ts +0 -30
  42. package/dist/src/SharedWebWorker.d.ts.map +0 -1
  43. package/dist/src/SharedWebWorker.js +0 -104
  44. package/dist/src/WasmSqliteDriver.d.ts +0 -3
  45. package/dist/src/WasmSqliteDriver.d.ts.map +0 -1
  46. package/dist/src/WasmSqliteDriver.js +0 -85
  47. package/dist/src/WebWorker.d.ts +0 -17
  48. package/dist/src/WebWorker.d.ts.map +0 -1
  49. package/dist/src/WebWorker.js +0 -42
  50. package/dist/src/local-first/Platform.d.ts +0 -3
  51. package/dist/src/local-first/Platform.d.ts.map +0 -1
  52. package/dist/test/SharedWebWorker.test.d.ts +0 -2
  53. package/dist/test/SharedWebWorker.test.d.ts.map +0 -1
  54. package/dist/test/SharedWebWorker.test.js +0 -248
  55. package/src/SharedWebWorker.ts +0 -149
  56. package/src/WasmSqliteDriver.ts +0 -118
  57. package/src/WebWorker.ts +0 -54
  58. package/src/local-first/Platform.ts +0 -9
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Evolu for Web
2
2
 
3
+ This package provides Evolu for the web platform (browsers). We use "web" rather than "browser" because "web platform" is the standard W3C terminology for browser APIs and aligns with ecosystem conventions.
4
+
3
5
  ## Documentation
4
6
 
5
7
  For detailed information and usage examples, please visit [evolu.dev](https://www.evolu.dev).
@@ -10,4 +12,4 @@ The Evolu community is on [GitHub Discussions](https://github.com/evoluhq/evolu/
10
12
 
11
13
  To chat with other community members, you can join the [Evolu Discord](https://discord.gg/2J8yyyyxtZ).
12
14
 
13
- [![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,3 @@
1
+ import type { ReloadApp } from "@evolu/common";
2
+ export declare const reloadApp: ReloadApp;
3
+ //# sourceMappingURL=Platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Platform.d.ts","sourceRoot":"","sources":["../../src/Platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,eAAO,MAAM,SAAS,EAAE,SAMvB,CAAC"}
@@ -2,5 +2,5 @@ export const reloadApp = (url) => {
2
2
  if (typeof document === "undefined") {
3
3
  return;
4
4
  }
5
- location.replace(url);
5
+ location.replace(url ?? "/");
6
6
  };
@@ -0,0 +1,3 @@
1
+ import type { CreateSqliteDriver } from "@evolu/common";
2
+ export declare const createWasmSqliteDriver: CreateSqliteDriver;
3
+ //# sourceMappingURL=Sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../src/Sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAa,MAAM,eAAe,CAAC;AA4BnE,eAAO,MAAM,sBAAsB,EAAE,kBA6GlC,CAAC"}
@@ -0,0 +1,162 @@
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
+ });
53
+ import { bytesToHex, createPreparedStatementsCache, ok } from "@evolu/common";
54
+ import sqlite3InitModule, {} from "@evolu/sqlite-wasm";
55
+ // @ts-expect-error Missing types.
56
+ globalThis.sqlite3ApiConfig = {
57
+ warn: (arg) => {
58
+ // Ignore irrelevant warning.
59
+ // https://github.com/sqlite/sqlite-wasm/issues/62
60
+ if (typeof arg === "string" &&
61
+ arg.startsWith("Ignoring inability to install OPFS sqlite3_vfs"))
62
+ return;
63
+ // eslint-disable-next-line no-console
64
+ console.warn(arg);
65
+ },
66
+ };
67
+ // Init ASAP.
68
+ const sqlite3Promise = sqlite3InitModule();
69
+ const fileName = "evolu1.db";
70
+ export const createWasmSqliteDriver = (name, options) => async () => {
71
+ const env_1 = { stack: [], error: void 0, hasError: false };
72
+ try {
73
+ const sqlite3 = await sqlite3Promise;
74
+ const disposer = __addDisposableResource(env_1, new DisposableStack(), false);
75
+ const useDatabase = (database) => disposer.adopt(database, (database) => {
76
+ database.close();
77
+ });
78
+ let deleteDatabaseFile = false;
79
+ const createOpfsSAHPoolVfs = async (options) => {
80
+ const pool = await sqlite3.installOpfsSAHPoolVfs(options);
81
+ if (pool.isPaused())
82
+ await pool.unpauseVfs();
83
+ disposer.defer(() => {
84
+ if (deleteDatabaseFile)
85
+ pool.unlink(`/${fileName}`);
86
+ pool.pauseVfs();
87
+ });
88
+ return pool;
89
+ };
90
+ let db;
91
+ switch (options?.mode) {
92
+ case "memory":
93
+ db = useDatabase(new sqlite3.oo1.DB(":memory:"));
94
+ break;
95
+ case "encrypted": {
96
+ // MultipleCiphers encryption requires its VFS wrapper for OPFS SAH-pool.
97
+ // @ts-expect-error Missing types (update @evolu/sqlite-wasm types)
98
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
99
+ sqlite3.capi.sqlite3mc_vfs_create("opfs", 1);
100
+ const pool = await createOpfsSAHPoolVfs({
101
+ directory: `.${name}`,
102
+ });
103
+ db = useDatabase(new pool.OpfsSAHPoolDb(
104
+ // SQLite normalizes this URI filename to SAH-pool path "/evolu1.db".
105
+ `file:${fileName}?vfs=multipleciphers-opfs-sahpool`));
106
+ db.exec(`
107
+ PRAGMA cipher = 'sqlcipher';
108
+ PRAGMA key = "x'${bytesToHex(options.encryptionKey)}'";
109
+ `);
110
+ break;
111
+ }
112
+ default: {
113
+ const pool = await createOpfsSAHPoolVfs({ name });
114
+ db = useDatabase(new pool.OpfsSAHPoolDb(`file:${fileName}`));
115
+ }
116
+ }
117
+ const cache = disposer.use(createPreparedStatementsCache((sql) => db.prepare(sql), (statement) => {
118
+ statement.finalize();
119
+ }));
120
+ const disposables = disposer.move();
121
+ return ok({
122
+ exec: (query) => {
123
+ const prepared = cache.get(query);
124
+ if (prepared) {
125
+ if (query.parameters.length > 0)
126
+ prepared.bind(query.parameters);
127
+ const rows = [];
128
+ while (prepared.step()) {
129
+ rows.push(prepared.get({}));
130
+ }
131
+ prepared.reset();
132
+ return {
133
+ rows: rows,
134
+ changes: db.changes(),
135
+ };
136
+ }
137
+ const rows = db.exec(query.sql, {
138
+ returnValue: "resultRows",
139
+ rowMode: "object",
140
+ bind: query.parameters,
141
+ });
142
+ const changes = db.changes();
143
+ return { rows, changes };
144
+ },
145
+ export: () => sqlite3.capi.sqlite3_js_db_export(db),
146
+ deleteDatabase: () => {
147
+ deleteDatabaseFile = true;
148
+ disposables.dispose();
149
+ },
150
+ [Symbol.dispose]: () => {
151
+ disposables.dispose();
152
+ },
153
+ });
154
+ }
155
+ catch (e_1) {
156
+ env_1.error = e_1;
157
+ env_1.hasError = true;
158
+ }
159
+ finally {
160
+ __disposeResources(env_1);
161
+ }
162
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Web platform-specific Task utilities.
3
+ *
4
+ * @module
5
+ */
6
+ import { type CreateRun, type RunDefaultDeps } from "@evolu/common";
7
+ /**
8
+ * Creates {@link Run} for the browser with global error handling.
9
+ *
10
+ * Registers `error` and `unhandledrejection` handlers that log errors to the
11
+ * console. Handlers are removed 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
+ export declare const createRun: CreateRun<RunDefaultDeps>;
29
+ //# 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,cAAc,EACpB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,cAAc,CAuB/C,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Web platform-specific Task utilities.
3
+ *
4
+ * @module
5
+ */
6
+ import { createRun as createCommonRun, createUnknownError, } from "@evolu/common";
7
+ /**
8
+ * Creates {@link Run} for the browser with global error handling.
9
+ *
10
+ * Registers `error` and `unhandledrejection` handlers that log errors to the
11
+ * console. Handlers are removed 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
+ export const createRun = (deps) => {
29
+ const run = createCommonRun(deps);
30
+ const console = run.deps.console.child("global");
31
+ globalThis.addEventListener("error", (event) => {
32
+ console.error("error", createUnknownError(event.error));
33
+ }, { signal: run.signal });
34
+ globalThis.addEventListener("unhandledrejection", (event) => {
35
+ console.error("unhandledrejection", createUnknownError(event.reason));
36
+ }, { signal: run.signal });
37
+ return run;
38
+ };
@@ -0,0 +1,60 @@
1
+ import type { CreateBroadcastChannel, CreateBroadcastChannelDep, CreateMessageChannelDep, CreateMessagePort, MessageChannel, SharedWorker, SharedWorkerSelf, Worker, WorkerDeps, WorkerSelf } from "@evolu/common";
2
+ /** Creates a {@link Worker} from a Web Worker. */
3
+ export declare const createWorker: <Input, Output>(nativeWorker: globalThis.Worker) => Worker<Input, Output>;
4
+ /**
5
+ * Installs a one-tab SharedWorker polyfill backed by a Web Worker.
6
+ *
7
+ * Use it before constructing a SharedWorker in browsers without native
8
+ * SharedWorker support.
9
+ */
10
+ export declare const installOneTabSharedWorkerPolyfill: () => void;
11
+ /**
12
+ * Creates a {@link SharedWorker} from a Web SharedWorker.
13
+ *
14
+ * Call {@link installOneTabSharedWorkerPolyfill} first to support browsers
15
+ * without native SharedWorker support.
16
+ */
17
+ export declare const createSharedWorker: <Input, Output = never>(nativeSharedWorker: globalThis.SharedWorker) => SharedWorker<Input, Output>;
18
+ /**
19
+ * Creates a {@link MessageChannel} from a Web MessageChannel.
20
+ *
21
+ * ### Example
22
+ *
23
+ * ```ts
24
+ * const channel = createMessageChannel<Request, Response>();
25
+ * channel.port1.onMessage = (response) => console.log(response);
26
+ * channel.port1.postMessage({ type: "ping" });
27
+ * ```
28
+ */
29
+ export declare const createMessageChannel: <Input, Output = never>() => MessageChannel<Input, Output>;
30
+ /**
31
+ * Creates an Evolu {@link MessagePort} from a Web MessagePort.
32
+ *
33
+ * Use this for ports received via postMessage transfer.
34
+ */
35
+ export declare const createMessagePort: CreateMessagePort;
36
+ /** Creates an Evolu {@link BroadcastChannel} from a Web BroadcastChannel. */
37
+ export declare const createBroadcastChannel: CreateBroadcastChannel;
38
+ /**
39
+ * Creates an Evolu {@link WorkerSelf} from a Web `DedicatedWorkerGlobalScope`
40
+ * (`self` inside a dedicated worker).
41
+ */
42
+ export declare const createWorkerSelf: <Input, Output = never>(nativeSelf: globalThis.DedicatedWorkerGlobalScope) => WorkerSelf<Input, Output>;
43
+ /**
44
+ * Creates an Evolu {@link SharedWorkerSelf} from a Web `SharedWorkerGlobalScope`
45
+ * (`self` inside a shared worker).
46
+ *
47
+ * Disposing closes the shared worker scope for all connected clients.
48
+ */
49
+ export declare const createSharedWorkerSelf: <Input, Output = never>(nativeSelf: globalThis.SharedWorkerGlobalScope) => SharedWorkerSelf<Input, Output>;
50
+ /**
51
+ * Creates a one-tab {@link SharedWorkerSelf} polyfill for browsers without
52
+ * native SharedWorker support.
53
+ *
54
+ * Delivers one synthetic `onConnect` port, queues startup messages until
55
+ * `onMessage` is set, and does not share state across tabs.
56
+ */
57
+ export declare const createOneTabSharedWorkerSelfPolyfill: <Input, Output = never>(nativeSelf: globalThis.DedicatedWorkerGlobalScope) => SharedWorkerSelf<Input, Output>;
58
+ /** Creates deps shared by web worker entry points. */
59
+ export declare const createWorkerDeps: () => WorkerDeps & CreateBroadcastChannelDep & CreateMessageChannelDep;
60
+ //# sourceMappingURL=Worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Worker.d.ts","sourceRoot":"","sources":["../../src/Worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,sBAAsB,EACtB,yBAAyB,EACzB,uBAAuB,EACvB,iBAAiB,EACjB,cAAc,EAGd,YAAY,EACZ,gBAAgB,EAEhB,MAAM,EACN,UAAU,EACV,UAAU,EACX,MAAM,eAAe,CAAC;AAQvB,kDAAkD;AAClD,eAAO,MAAM,YAAY,GAAI,KAAK,EAAE,MAAM,EACxC,cAAc,UAAU,CAAC,MAAM,KAC9B,MAAM,CAAC,KAAK,EAAE,MAAM,CAAuB,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,QAAO,IAiBpD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,KAAK,EAAE,MAAM,GAAG,KAAK,EACtD,oBAAoB,UAAU,CAAC,YAAY,KAC1C,YAAY,CAAC,KAAK,EAAE,MAAM,CAM5B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,EAAE,MAAM,GAAG,KAAK,OAAK,cAAc,CAC3E,KAAK,EACL,MAAM,CAcP,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,iBACuB,CAAC;AAExD,6EAA6E;AAC7E,eAAO,MAAM,sBAAsB,EAAE,sBAoCpC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,EAAE,MAAM,GAAG,KAAK,EACpD,YAAY,UAAU,CAAC,0BAA0B,KAChD,UAAU,CAAC,KAAK,EAAE,MAAM,CAAoC,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GAAI,KAAK,EAAE,MAAM,GAAG,KAAK,EAC1D,YAAY,UAAU,CAAC,uBAAuB,KAC7C,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAkBhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,GAAI,KAAK,EAAE,MAAM,GAAG,KAAK,EACxE,YAAY,UAAU,CAAC,0BAA0B,KAChD,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAyEhC,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,QAAO,UAAU,GAC5C,yBAAyB,GACzB,uBAWD,CAAC"}
@@ -0,0 +1,328 @@
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
+ });
53
+ import { assert, assertNotDisposed, createConsole, createConsoleStoreOutput, } from "@evolu/common";
54
+ /** Creates a {@link Worker} from a Web Worker. */
55
+ export const createWorker = (nativeWorker) => wrap(nativeWorker);
56
+ /**
57
+ * Installs a one-tab SharedWorker polyfill backed by a Web Worker.
58
+ *
59
+ * Use it before constructing a SharedWorker in browsers without native
60
+ * SharedWorker support.
61
+ */
62
+ export const installOneTabSharedWorkerPolyfill = () => {
63
+ if (typeof globalThis.SharedWorker === "function")
64
+ return;
65
+ Object.defineProperty(globalThis, "SharedWorker", {
66
+ configurable: true,
67
+ writable: true,
68
+ value: class {
69
+ port;
70
+ constructor(scriptURL, options) {
71
+ this.port = new globalThis.Worker(scriptURL, options);
72
+ }
73
+ },
74
+ });
75
+ };
76
+ /**
77
+ * Creates a {@link SharedWorker} from a Web SharedWorker.
78
+ *
79
+ * Call {@link installOneTabSharedWorkerPolyfill} first to support browsers
80
+ * without native SharedWorker support.
81
+ */
82
+ export const createSharedWorker = (nativeSharedWorker) => {
83
+ const port = wrap(nativeSharedWorker.port);
84
+ return {
85
+ port,
86
+ [Symbol.dispose]: port[Symbol.dispose],
87
+ };
88
+ };
89
+ /**
90
+ * Creates a {@link MessageChannel} from a Web MessageChannel.
91
+ *
92
+ * ### Example
93
+ *
94
+ * ```ts
95
+ * const channel = createMessageChannel<Request, Response>();
96
+ * channel.port1.onMessage = (response) => console.log(response);
97
+ * channel.port1.postMessage({ type: "ping" });
98
+ * ```
99
+ */
100
+ export const createMessageChannel = () => {
101
+ const env_1 = { stack: [], error: void 0, hasError: false };
102
+ try {
103
+ const channel = new globalThis.MessageChannel();
104
+ const disposer = __addDisposableResource(env_1, new DisposableStack(), false);
105
+ const port1 = disposer.use(wrap(channel.port1));
106
+ const port2 = disposer.use(wrap(channel.port2));
107
+ const disposables = disposer.move();
108
+ return {
109
+ port1,
110
+ port2,
111
+ [Symbol.dispose]: () => disposables.dispose(),
112
+ };
113
+ }
114
+ catch (e_1) {
115
+ env_1.error = e_1;
116
+ env_1.hasError = true;
117
+ }
118
+ finally {
119
+ __disposeResources(env_1);
120
+ }
121
+ };
122
+ /**
123
+ * Creates an Evolu {@link MessagePort} from a Web MessagePort.
124
+ *
125
+ * Use this for ports received via postMessage transfer.
126
+ */
127
+ export const createMessagePort = (nativePort) => wrap(nativePort);
128
+ /** Creates an Evolu {@link BroadcastChannel} from a Web BroadcastChannel. */
129
+ export const createBroadcastChannel = (name) => {
130
+ const env_2 = { stack: [], error: void 0, hasError: false };
131
+ try {
132
+ const nativeBroadcastChannel = new globalThis.BroadcastChannel(name);
133
+ const disposer = __addDisposableResource(env_2, new DisposableStack(), false);
134
+ disposer.defer(() => {
135
+ nativeBroadcastChannel.onmessage = null;
136
+ nativeBroadcastChannel.close();
137
+ });
138
+ const disposables = disposer.move();
139
+ let onMessageHandler = null;
140
+ return {
141
+ postMessage: (message) => {
142
+ assertNotDisposed(disposables);
143
+ nativeBroadcastChannel.postMessage(message);
144
+ },
145
+ get onMessage() {
146
+ return disposables.disposed ? null : onMessageHandler;
147
+ },
148
+ set onMessage(fn) {
149
+ if (disposables.disposed)
150
+ return;
151
+ onMessageHandler = fn;
152
+ nativeBroadcastChannel.onmessage = fn
153
+ ? (event) => {
154
+ fn(event.data);
155
+ }
156
+ : null;
157
+ },
158
+ [Symbol.dispose]: () => disposables.dispose(),
159
+ };
160
+ }
161
+ catch (e_2) {
162
+ env_2.error = e_2;
163
+ env_2.hasError = true;
164
+ }
165
+ finally {
166
+ __disposeResources(env_2);
167
+ }
168
+ };
169
+ /**
170
+ * Creates an Evolu {@link WorkerSelf} from a Web `DedicatedWorkerGlobalScope`
171
+ * (`self` inside a dedicated worker).
172
+ */
173
+ export const createWorkerSelf = (nativeSelf) => wrap(nativeSelf);
174
+ /**
175
+ * Creates an Evolu {@link SharedWorkerSelf} from a Web `SharedWorkerGlobalScope`
176
+ * (`self` inside a shared worker).
177
+ *
178
+ * Disposing closes the shared worker scope for all connected clients.
179
+ */
180
+ export const createSharedWorkerSelf = (nativeSelf) => {
181
+ const self = {
182
+ onConnect: null,
183
+ [Symbol.dispose]: () => {
184
+ nativeSelf.onconnect = null;
185
+ nativeSelf.close();
186
+ },
187
+ };
188
+ nativeSelf.onconnect = (e) => {
189
+ assert(self.onConnect != null, "onConnect must be set before receiving connections");
190
+ self.onConnect(wrap(e.ports[0]));
191
+ };
192
+ return self;
193
+ };
194
+ /**
195
+ * Creates a one-tab {@link SharedWorkerSelf} polyfill for browsers without
196
+ * native SharedWorker support.
197
+ *
198
+ * Delivers one synthetic `onConnect` port, queues startup messages until
199
+ * `onMessage` is set, and does not share state across tabs.
200
+ */
201
+ export const createOneTabSharedWorkerSelfPolyfill = (nativeSelf) => {
202
+ const env_3 = { stack: [], error: void 0, hasError: false };
203
+ try {
204
+ const disposer = __addDisposableResource(env_3, new DisposableStack(), false);
205
+ let onConnectHandler = null;
206
+ let onMessageHandler = null;
207
+ const messages = [];
208
+ let connected = false;
209
+ disposer.defer(() => {
210
+ messages.length = 0;
211
+ onConnectHandler = null;
212
+ onMessageHandler = null;
213
+ nativeSelf.onmessage = null;
214
+ nativeSelf.close();
215
+ });
216
+ const disposables = disposer.move();
217
+ nativeSelf.onmessage = (event) => {
218
+ if (disposables.disposed)
219
+ return;
220
+ const handler = onMessageHandler;
221
+ if (handler)
222
+ handler(event.data);
223
+ else
224
+ messages.push(event.data);
225
+ };
226
+ const flushMessages = () => {
227
+ for (const message of messages.splice(0)) {
228
+ const handler = onMessageHandler;
229
+ if (!handler)
230
+ return;
231
+ handler(message);
232
+ }
233
+ };
234
+ const port = {
235
+ postMessage: (message, transfer) => {
236
+ if (disposables.disposed)
237
+ return;
238
+ if (transfer == null)
239
+ nativeSelf.postMessage(message);
240
+ else
241
+ nativeSelf.postMessage(message, [...transfer]);
242
+ },
243
+ get onMessage() {
244
+ return disposables.disposed ? null : onMessageHandler;
245
+ },
246
+ set onMessage(fn) {
247
+ if (disposables.disposed)
248
+ return;
249
+ onMessageHandler = fn;
250
+ if (fn)
251
+ flushMessages();
252
+ },
253
+ native: nativeSelf,
254
+ [Symbol.dispose]: () => disposables.dispose(),
255
+ };
256
+ const connect = () => {
257
+ if (connected || !onConnectHandler)
258
+ return;
259
+ connected = true;
260
+ onConnectHandler(port);
261
+ };
262
+ return {
263
+ get onConnect() {
264
+ return onConnectHandler;
265
+ },
266
+ set onConnect(fn) {
267
+ if (disposables.disposed)
268
+ return;
269
+ onConnectHandler = fn;
270
+ connect();
271
+ },
272
+ [Symbol.dispose]: () => disposables.dispose(),
273
+ };
274
+ }
275
+ catch (e_3) {
276
+ env_3.error = e_3;
277
+ env_3.hasError = true;
278
+ }
279
+ finally {
280
+ __disposeResources(env_3);
281
+ }
282
+ };
283
+ /** Creates deps shared by web worker entry points. */
284
+ export const createWorkerDeps = () => {
285
+ const consoleStoreOutput = createConsoleStoreOutput();
286
+ const console = createConsole({ output: consoleStoreOutput });
287
+ return {
288
+ console,
289
+ consoleStoreOutputEntry: consoleStoreOutput.entry,
290
+ createBroadcastChannel,
291
+ createMessageChannel,
292
+ createMessagePort,
293
+ };
294
+ };
295
+ const wrap = (native) => {
296
+ let onMessageHandler = null;
297
+ return {
298
+ postMessage: (message, transfer) => {
299
+ if (transfer == null)
300
+ native.postMessage(message);
301
+ else
302
+ native.postMessage(message, [...transfer]);
303
+ },
304
+ get onMessage() {
305
+ return onMessageHandler;
306
+ },
307
+ set onMessage(fn) {
308
+ onMessageHandler = fn;
309
+ if (fn) {
310
+ // Messages are queued until onMessage is assigned.
311
+ native.onmessage = (event) => {
312
+ fn(event.data);
313
+ };
314
+ }
315
+ else {
316
+ native.onmessage = null;
317
+ }
318
+ },
319
+ native: native,
320
+ [Symbol.dispose]: () => {
321
+ native.onmessage = null;
322
+ if ("terminate" in native)
323
+ native.terminate();
324
+ else
325
+ native.close();
326
+ },
327
+ };
328
+ };
@@ -1,5 +1,5 @@
1
1
  export * from "./local-first/index.js";
2
- export * from "./SharedWebWorker.js";
3
- export * from "./WasmSqliteDriver.js";
4
- export * from "./WebWorker.js";
2
+ export * from "./Sqlite.js";
3
+ export * from "./Task.js";
4
+ export * from "./Worker.js";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}