@evolu/web 3.0.0-next.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,5 @@
1
- import type { ReloadApp } from "@evolu/common";
1
+ import { PositiveInt, type ReloadApp } from "@evolu/common";
2
+ /** Returns the amount of logical processors available to the browser. */
3
+ export declare const availableParallelism: () => PositiveInt;
2
4
  export declare const reloadApp: ReloadApp;
3
5
  //# sourceMappingURL=Platform.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"Platform.d.ts","sourceRoot":"","sources":["../../src/Platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAE5D,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,QAAO,WACuB,CAAC;AAEhE,eAAO,MAAM,SAAS,EAAE,SAMvB,CAAC"}
@@ -1,3 +1,6 @@
1
+ import { PositiveInt } from "@evolu/common";
2
+ /** Returns the amount of logical processors available to the browser. */
3
+ export const availableParallelism = () => PositiveInt.orThrow(globalThis.navigator.hardwareConcurrency);
1
4
  export const reloadApp = (url) => {
2
5
  if (typeof document === "undefined") {
3
6
  return;
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Web platform-specific Task utilities.
2
+ * Web-specific Task utilities.
3
3
  *
4
4
  * @module
5
5
  */
6
- import { type CreateRun, type RunDefaultDeps } from "@evolu/common";
6
+ import { type DisposableRun, type RunCustomDeps } from "@evolu/common";
7
7
  /**
8
- * Creates {@link Run} for the browser with global error handling.
8
+ * Creates a root {@link Run} for the browser.
9
9
  *
10
- * Registers `error` and `unhandledrejection` handlers that log errors to the
11
- * console. Handlers are removed when the Run is disposed.
10
+ * Defects are reported with the browser's global `reportError`. A custom
11
+ * `reportDefect` dependency overrides the browser default.
12
12
  *
13
13
  * ### Example
14
14
  *
@@ -19,11 +19,10 @@ import { type CreateRun, type RunDefaultDeps } from "@evolu/common";
19
19
  * }),
20
20
  * });
21
21
  *
22
- * await using run = createRun({ console });
23
- * await using disposer = new AsyncDisposableStack();
24
- *
25
- * disposer.use(await run.orThrow(startApp()));
22
+ * const run = createRun({ console });
23
+ * const appPromise = run.ok(startApp());
26
24
  * ```
27
25
  */
28
- export declare const createRun: CreateRun<RunDefaultDeps>;
26
+ export declare function createRun(): DisposableRun;
27
+ export declare function createRun<D extends object>(deps: RunCustomDeps<D>): DisposableRun<D>;
29
28
  //# sourceMappingURL=Task.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"Task.d.ts","sourceRoot":"","sources":["../../src/Task.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,IAAI,aAAa,CAAC;AAC3C,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EACxC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,GACrB,aAAa,CAAC,CAAC,CAAC,CAAC"}
package/dist/src/Task.js CHANGED
@@ -1,38 +1,14 @@
1
1
  /**
2
- * Web platform-specific Task utilities.
2
+ * Web-specific Task utilities.
3
3
  *
4
4
  * @module
5
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
- };
6
+ import { createRun as createCommonRun, } from "@evolu/common";
7
+ export function createRun(deps) {
8
+ const reportDefect = (reported) => {
9
+ globalThis.reportError(reported);
10
+ };
11
+ return deps === undefined
12
+ ? createCommonRun({ reportDefect })
13
+ : createCommonRun({ reportDefect, ...deps });
14
+ }
@@ -1 +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"}
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,gBAC1B,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,sBAClC,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,sBAsCpC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,EAAE,MAAM,GAAG,KAAK,cACxC,UAAU,CAAC,0BAA0B,KAChD,UAAU,CAAC,KAAK,EAAE,MAAM,CAAoC,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GAAI,KAAK,EAAE,MAAM,GAAG,KAAK,cAC9C,UAAU,CAAC,uBAAuB,KAC7C,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAkBhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,GAAI,KAAK,EAAE,MAAM,GAAG,KAAK,cAC5D,UAAU,CAAC,0BAA0B,KAChD,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAyEhC,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,QAAO,UAAU,GAC5C,yBAAyB,GACzB,uBAWD,CAAC"}
@@ -50,7 +50,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
50
50
  var e = new Error(message);
51
51
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
52
  });
53
- import { assert, assertNotDisposed, createConsole, createConsoleStoreOutput, } from "@evolu/common";
53
+ import { assert, createConsole, createConsoleStoreOutput, disposable, } from "@evolu/common";
54
54
  /** Creates a {@link Worker} from a Web Worker. */
55
55
  export const createWorker = (nativeWorker) => wrap(nativeWorker);
56
56
  /**
@@ -131,22 +131,22 @@ export const createBroadcastChannel = (name) => {
131
131
  try {
132
132
  const nativeBroadcastChannel = new globalThis.BroadcastChannel(name);
133
133
  const disposer = __addDisposableResource(env_2, new DisposableStack(), false);
134
+ let disposed = false;
134
135
  disposer.defer(() => {
136
+ disposed = true;
135
137
  nativeBroadcastChannel.onmessage = null;
136
138
  nativeBroadcastChannel.close();
137
139
  });
138
- const disposables = disposer.move();
139
140
  let onMessageHandler = null;
140
- return {
141
+ return disposable({
141
142
  postMessage: (message) => {
142
- assertNotDisposed(disposables);
143
143
  nativeBroadcastChannel.postMessage(message);
144
144
  },
145
145
  get onMessage() {
146
- return disposables.disposed ? null : onMessageHandler;
146
+ return disposed ? null : onMessageHandler;
147
147
  },
148
148
  set onMessage(fn) {
149
- if (disposables.disposed)
149
+ if (disposed)
150
150
  return;
151
151
  onMessageHandler = fn;
152
152
  nativeBroadcastChannel.onmessage = fn
@@ -155,8 +155,7 @@ export const createBroadcastChannel = (name) => {
155
155
  }
156
156
  : null;
157
157
  },
158
- [Symbol.dispose]: () => disposables.dispose(),
159
- };
158
+ }, disposer);
160
159
  }
161
160
  catch (e_2) {
162
161
  env_2.error = e_2;
@@ -1,5 +1,6 @@
1
- export * from "./local-first/index.js";
2
- export * from "./Sqlite.js";
3
- export * from "./Task.js";
4
- export * from "./Worker.js";
1
+ export * from "./local-first/index.ts";
2
+ export { availableParallelism } from "./Platform.ts";
3
+ export * from "./Sqlite.ts";
4
+ export * from "./Task.ts";
5
+ export * from "./Worker.ts";
5
6
  //# 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,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
package/dist/src/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./local-first/index.js";
2
+ export { availableParallelism } from "./Platform.js";
2
3
  export * from "./Sqlite.js";
3
4
  export * from "./Task.js";
4
5
  export * from "./Worker.js";
@@ -6,11 +6,10 @@ import { startDbWorker } from "@evolu/common/local-first";
6
6
  import { createWasmSqliteDriver } from "../Sqlite.js";
7
7
  import { createRun } from "../Task.js";
8
8
  import { createWorkerDeps, createWorkerSelf } from "../Worker.js";
9
- // TODO: Disposal.
10
9
  const run = createRun({
11
10
  ...createWorkerDeps(),
12
11
  createSqliteDriver: createWasmSqliteDriver,
13
12
  lockManager: globalThis.navigator.locks,
14
13
  randomBytes: createRandomBytes(),
15
14
  });
16
- run(startDbWorker(createWorkerSelf(self)));
15
+ void run(startDbWorker(createWorkerSelf(self)));
@@ -1 +1 @@
1
- {"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/local-first/Evolu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAIV,SAAS,EAGV,MAAM,2BAA2B,CAAC;AAkBnC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;CAC1C;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,IAAI,CAAC;CAChD;AAED,uDAAuD;AACvD,eAAO,MAAM,eAAe,GAC1B,OAAM,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,0BAA0B,CAAM,KACnE,SAkEF,CAAC"}
1
+ {"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/local-first/Evolu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAIV,SAAS,EAGV,MAAM,2BAA2B,CAAC;AAkBnC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;CAC1C;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,IAAI,CAAC;CAChD;AAED,uDAAuD;AACvD,eAAO,MAAM,eAAe,UACpB,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,0BAA0B,CAAC,KAC9D,SAkEF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"LocalAuth.d.ts","sourceRoot":"","sources":["../../../src/local-first/LocalAuth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,cAAc,EACd,aAAa,EAEd,MAAM,eAAe,CAAC;AAiBvB,eAAO,MAAM,mBAAmB,GAAI,MAAM,cAAc,KAAG,aA4GzD,CAAC"}
1
+ {"version":3,"file":"LocalAuth.d.ts","sourceRoot":"","sources":["../../../src/local-first/LocalAuth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,cAAc,EACd,aAAa,EAEd,MAAM,eAAe,CAAC;AAiBvB,eAAO,MAAM,mBAAmB,SAAU,cAAc,KAAG,aA4GzD,CAAC"}
@@ -53,11 +53,10 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
53
53
  /// <reference lib="webworker" />
54
54
  import { installPolyfills } from "@evolu/common/polyfills";
55
55
  installPolyfills();
56
- import { createWebSocket, ok } from "@evolu/common";
56
+ import { createWebSocket, ok, waitForAbort } from "@evolu/common";
57
57
  import { initSharedWorker } from "@evolu/common/local-first";
58
58
  import { createRun } from "../Task.js";
59
59
  import { createOneTabSharedWorkerSelfPolyfill, createSharedWorkerSelf, createWorkerDeps, } from "../Worker.js";
60
- // No disposal (`await using`) is needed — a SharedWorker lives forever.
61
60
  const run = createRun({
62
61
  ...createWorkerDeps(),
63
62
  createWebSocket,
@@ -67,25 +66,49 @@ void run(async (run) => {
67
66
  const env_1 = { stack: [], error: void 0, hasError: false };
68
67
  try {
69
68
  if ("onconnect" in self) {
70
- void run(initSharedWorker(createSharedWorkerSelf(self)));
71
- return ok();
69
+ const env_2 = { stack: [], error: void 0, hasError: false };
70
+ try {
71
+ const _ = __addDisposableResource(env_2, await run.ok(initSharedWorker(createSharedWorkerSelf(self))), true);
72
+ return await run(waitForAbort);
73
+ }
74
+ catch (e_1) {
75
+ env_2.error = e_1;
76
+ env_2.hasError = true;
77
+ }
78
+ finally {
79
+ const result_1 = __disposeResources(env_2);
80
+ if (result_1)
81
+ await result_1;
82
+ }
72
83
  }
73
84
  const workerSelf = __addDisposableResource(env_1, createOneTabSharedWorkerSelfPolyfill(self), false);
74
85
  await globalThis.navigator.locks.request("evolu-one-tab-sharedworker-polyfill", { ifAvailable: true, mode: "exclusive" }, async (lock) => {
75
- if (!lock) {
76
- const message = {
77
- type: "SharedWorkerUnsupported",
78
- };
79
- self.postMessage(message);
80
- return;
86
+ const env_3 = { stack: [], error: void 0, hasError: false };
87
+ try {
88
+ if (!lock) {
89
+ const message = {
90
+ type: "SharedWorkerUnsupported",
91
+ };
92
+ self.postMessage(message);
93
+ return;
94
+ }
95
+ const _ = __addDisposableResource(env_3, await run.ok(initSharedWorker(workerSelf)), true);
96
+ await run(waitForAbort);
97
+ }
98
+ catch (e_3) {
99
+ env_3.error = e_3;
100
+ env_3.hasError = true;
101
+ }
102
+ finally {
103
+ const result_2 = __disposeResources(env_3);
104
+ if (result_2)
105
+ await result_2;
81
106
  }
82
- void run(initSharedWorker(workerSelf));
83
- await Promise.withResolvers().promise;
84
107
  });
85
108
  return ok();
86
109
  }
87
- catch (e_1) {
88
- env_1.error = e_1;
110
+ catch (e_2) {
111
+ env_1.error = e_2;
89
112
  env_1.hasError = true;
90
113
  }
91
114
  finally {
@@ -1,2 +1,2 @@
1
- export * from "./Evolu.js";
1
+ export * from "./Evolu.ts";
2
2
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolu/web",
3
- "version": "3.0.0-next.1",
3
+ "version": "3.0.0",
4
4
  "description": "Evolu for web",
5
5
  "keywords": [
6
6
  "evolu",
@@ -36,11 +36,11 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^24.10.9",
39
- "@types/sharedworker": "^0.0.221",
39
+ "@types/sharedworker": "^0.0.229",
40
40
  "@types/web-locks-api": "^0.0.5",
41
- "typescript": "^6",
41
+ "@typescript/native": "npm:typescript@^7.0.2",
42
42
  "user-agent-data-types": "^0.4.2",
43
- "@evolu/common": "8.0.0-next.5",
43
+ "@evolu/common": "8.0.0",
44
44
  "@evolu/typescript-config": "0.0.2"
45
45
  },
46
46
  "peerDependencies": {
package/src/Platform.ts CHANGED
@@ -1,4 +1,8 @@
1
- import type { ReloadApp } from "@evolu/common";
1
+ import { PositiveInt, type ReloadApp } from "@evolu/common";
2
+
3
+ /** Returns the amount of logical processors available to the browser. */
4
+ export const availableParallelism = (): PositiveInt =>
5
+ PositiveInt.orThrow(globalThis.navigator.hardwareConcurrency);
2
6
 
3
7
  export const reloadApp: ReloadApp = (url) => {
4
8
  if (typeof document === "undefined") {
package/src/Task.ts CHANGED
@@ -1,22 +1,21 @@
1
1
  /**
2
- * Web platform-specific Task utilities.
2
+ * Web-specific Task utilities.
3
3
  *
4
4
  * @module
5
5
  */
6
6
 
7
7
  import {
8
8
  createRun as createCommonRun,
9
- createUnknownError,
10
- type CreateRun,
9
+ type DisposableRun,
11
10
  type Run,
12
- type RunDefaultDeps,
11
+ type RunCustomDeps,
13
12
  } from "@evolu/common";
14
13
 
15
14
  /**
16
- * Creates {@link Run} for the browser with global error handling.
15
+ * Creates a root {@link Run} for the browser.
17
16
  *
18
- * Registers `error` and `unhandledrejection` handlers that log errors to the
19
- * console. Handlers are removed when the Run is disposed.
17
+ * Defects are reported with the browser's global `reportError`. A custom
18
+ * `reportDefect` dependency overrides the browser default.
20
19
  *
21
20
  * ### Example
22
21
  *
@@ -27,33 +26,22 @@ import {
27
26
  * }),
28
27
  * });
29
28
  *
30
- * await using run = createRun({ console });
31
- * await using disposer = new AsyncDisposableStack();
32
- *
33
- * disposer.use(await run.orThrow(startApp()));
29
+ * const run = createRun({ console });
30
+ * const appPromise = run.ok(startApp());
34
31
  * ```
35
32
  */
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
- );
33
+ export function createRun(): DisposableRun;
34
+ export function createRun<D extends object>(
35
+ deps: RunCustomDeps<D>,
36
+ ): DisposableRun<D>;
37
+ export function createRun<D extends object>(
38
+ deps?: RunCustomDeps<D>,
39
+ ): DisposableRun | DisposableRun<D> {
40
+ const reportDefect = (reported: unknown): void => {
41
+ globalThis.reportError(reported);
42
+ };
57
43
 
58
- return run;
59
- };
44
+ return deps === undefined
45
+ ? createCommonRun({ reportDefect })
46
+ : createCommonRun<D>({ reportDefect, ...deps });
47
+ }
package/src/Worker.ts CHANGED
@@ -16,9 +16,9 @@ import type {
16
16
  } from "@evolu/common";
17
17
  import {
18
18
  assert,
19
- assertNotDisposed,
20
19
  createConsole,
21
20
  createConsoleStoreOutput,
21
+ disposable,
22
22
  } from "@evolu/common";
23
23
 
24
24
  /** Creates a {@link Worker} from a Web Worker. */
@@ -113,34 +113,36 @@ export const createBroadcastChannel: CreateBroadcastChannel = <
113
113
  ): BroadcastChannel<Input, Output> => {
114
114
  const nativeBroadcastChannel = new globalThis.BroadcastChannel(name);
115
115
  using disposer = new DisposableStack();
116
+ let disposed = false;
116
117
 
117
118
  disposer.defer(() => {
119
+ disposed = true;
118
120
  nativeBroadcastChannel.onmessage = null;
119
121
  nativeBroadcastChannel.close();
120
122
  });
121
123
 
122
- const disposables = disposer.move();
123
124
  let onMessageHandler: ((message: Output) => void) | null = null;
124
125
 
125
- return {
126
- postMessage: (message) => {
127
- assertNotDisposed(disposables);
128
- nativeBroadcastChannel.postMessage(message);
129
- },
130
- get onMessage() {
131
- return disposables.disposed ? null : onMessageHandler;
126
+ return disposable<BroadcastChannel<Input, Output>>(
127
+ {
128
+ postMessage: (message) => {
129
+ nativeBroadcastChannel.postMessage(message);
130
+ },
131
+ get onMessage() {
132
+ return disposed ? null : onMessageHandler;
133
+ },
134
+ set onMessage(fn) {
135
+ if (disposed) return;
136
+ onMessageHandler = fn;
137
+ nativeBroadcastChannel.onmessage = fn
138
+ ? (event: MessageEvent<Output>) => {
139
+ fn(event.data);
140
+ }
141
+ : null;
142
+ },
132
143
  },
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
+ disposer,
145
+ );
144
146
  };
145
147
 
146
148
  /**
@@ -281,9 +283,7 @@ export const createWorkerDeps = (): WorkerDeps &
281
283
 
282
284
  const wrap = <Input, Output>(
283
285
  native:
284
- | DedicatedWorkerGlobalScope
285
- | globalThis.MessagePort
286
- | globalThis.Worker,
286
+ DedicatedWorkerGlobalScope | globalThis.MessagePort | globalThis.Worker,
287
287
  ): MessagePort<Input, Output> => {
288
288
  let onMessageHandler: ((message: Output) => void) | null = null;
289
289
 
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * from "./local-first/index.js";
2
- export * from "./Sqlite.js";
3
- export * from "./Task.js";
4
- export * from "./Worker.js";
1
+ export * from "./local-first/index.ts";
2
+ export { availableParallelism } from "./Platform.ts";
3
+ export * from "./Sqlite.ts";
4
+ export * from "./Task.ts";
5
+ export * from "./Worker.ts";
@@ -6,11 +6,10 @@ installPolyfills();
6
6
 
7
7
  import { createRandomBytes } from "@evolu/common";
8
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";
9
+ import { createWasmSqliteDriver } from "../Sqlite.ts";
10
+ import { createRun } from "../Task.ts";
11
+ import { createWorkerDeps, createWorkerSelf } from "../Worker.ts";
12
12
 
13
- // TODO: Disposal.
14
13
  const run = createRun({
15
14
  ...createWorkerDeps(),
16
15
  createSqliteDriver: createWasmSqliteDriver,
@@ -18,4 +17,4 @@ const run = createRun({
18
17
  randomBytes: createRandomBytes(),
19
18
  });
20
19
 
21
- run(startDbWorker(createWorkerSelf(self)));
20
+ void run(startDbWorker(createWorkerSelf(self)));
@@ -8,14 +8,14 @@ import type {
8
8
  SharedWorkerOutput,
9
9
  } from "@evolu/common/local-first";
10
10
  import { createEvoluDeps as createCommonEvoluDeps } from "@evolu/common/local-first";
11
- import { reloadApp } from "../Platform.js";
11
+ import { reloadApp } from "../Platform.ts";
12
12
  import {
13
13
  createBroadcastChannel,
14
14
  createMessageChannel,
15
15
  createSharedWorker,
16
16
  createWorker,
17
17
  installOneTabSharedWorkerPolyfill,
18
- } from "../Worker.js";
18
+ } from "../Worker.ts";
19
19
 
20
20
  // // TODO: Redesign.
21
21
  // // eslint-disable-next-line evolu/require-pure-annotation
@@ -4,21 +4,20 @@ declare const self: DedicatedWorkerGlobalScope | SharedWorkerGlobalScope;
4
4
  import { installPolyfills } from "@evolu/common/polyfills";
5
5
  installPolyfills();
6
6
 
7
- import { createWebSocket, ok } from "@evolu/common";
7
+ import { createWebSocket, ok, waitForAbort } from "@evolu/common";
8
8
  import type {
9
9
  SharedWorkerInput,
10
10
  SharedWorkerOutput,
11
11
  } from "@evolu/common/local-first";
12
12
  import { initSharedWorker } from "@evolu/common/local-first";
13
- import type { SharedWorkerUnsupported } from "./Evolu.js";
14
- import { createRun } from "../Task.js";
13
+ import type { SharedWorkerUnsupported } from "./Evolu.ts";
14
+ import { createRun } from "../Task.ts";
15
15
  import {
16
16
  createOneTabSharedWorkerSelfPolyfill,
17
17
  createSharedWorkerSelf,
18
18
  createWorkerDeps,
19
- } from "../Worker.js";
19
+ } from "../Worker.ts";
20
20
 
21
- // No disposal (`await using`) is needed — a SharedWorker lives forever.
22
21
  const run = createRun({
23
22
  ...createWorkerDeps(),
24
23
  createWebSocket,
@@ -27,8 +26,10 @@ const run = createRun({
27
26
 
28
27
  void run(async (run) => {
29
28
  if ("onconnect" in self) {
30
- void run(initSharedWorker(createSharedWorkerSelf(self)));
31
- return ok();
29
+ await using _ = await run.ok(
30
+ initSharedWorker(createSharedWorkerSelf(self)),
31
+ );
32
+ return await run(waitForAbort);
32
33
  }
33
34
 
34
35
  using workerSelf = createOneTabSharedWorkerSelfPolyfill<
@@ -48,9 +49,8 @@ void run(async (run) => {
48
49
  return;
49
50
  }
50
51
 
51
- void run(initSharedWorker(workerSelf));
52
-
53
- await Promise.withResolvers<never>().promise;
52
+ await using _ = await run.ok(initSharedWorker(workerSelf));
53
+ await run(waitForAbort);
54
54
  },
55
55
  );
56
56
 
@@ -1 +1 @@
1
- export * from "./Evolu.js";
1
+ export * from "./Evolu.ts";