syncorejs 0.2.1 → 0.2.3
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 +2 -1
- package/dist/_vendor/cli/app.d.mts.map +1 -1
- package/dist/_vendor/cli/app.mjs +330 -46
- package/dist/_vendor/cli/app.mjs.map +1 -1
- package/dist/_vendor/cli/context.mjs +27 -9
- package/dist/_vendor/cli/context.mjs.map +1 -1
- package/dist/_vendor/cli/dev-session.mjs.map +1 -1
- package/dist/_vendor/cli/doctor.mjs +513 -46
- package/dist/_vendor/cli/doctor.mjs.map +1 -1
- package/dist/_vendor/cli/errors.mjs.map +1 -1
- package/dist/_vendor/cli/help.mjs.map +1 -1
- package/dist/_vendor/cli/index.mjs +9 -2
- package/dist/_vendor/cli/index.mjs.map +1 -1
- package/dist/_vendor/cli/messages.mjs +5 -4
- package/dist/_vendor/cli/messages.mjs.map +1 -1
- package/dist/_vendor/cli/preflight.mjs.map +1 -1
- package/dist/_vendor/cli/project.mjs +125 -27
- package/dist/_vendor/cli/project.mjs.map +1 -1
- package/dist/_vendor/cli/render.mjs +57 -9
- package/dist/_vendor/cli/render.mjs.map +1 -1
- package/dist/_vendor/cli/targets.mjs +4 -3
- package/dist/_vendor/cli/targets.mjs.map +1 -1
- package/dist/_vendor/core/cli.d.mts +20 -4
- package/dist/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +458 -133
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/devtools-auth.mjs +60 -0
- package/dist/_vendor/core/devtools-auth.mjs.map +1 -0
- package/dist/_vendor/core/index.d.mts +5 -3
- package/dist/_vendor/core/index.mjs +22 -2
- package/dist/_vendor/core/index.mjs.map +1 -1
- package/dist/_vendor/core/runtime/components.d.mts +111 -0
- package/dist/_vendor/core/runtime/components.d.mts.map +1 -0
- package/dist/_vendor/core/runtime/components.mjs +186 -0
- package/dist/_vendor/core/runtime/components.mjs.map +1 -0
- package/dist/_vendor/core/runtime/devtools.d.mts +4 -4
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +178 -60
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.d.mts +398 -16
- package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/functions.mjs +74 -3
- package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
- package/dist/_vendor/core/runtime/id.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/id.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +83 -0
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +720 -0
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +234 -0
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +255 -0
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +200 -0
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs +252 -0
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +145 -0
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +221 -0
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs +32 -0
- package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/systemMeta.mjs +61 -0
- package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +41 -0
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -0
- package/dist/_vendor/core/runtime/runtime.d.mts +1187 -202
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs +73 -1365
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/core/transport.d.mts +113 -0
- package/dist/_vendor/core/transport.d.mts.map +1 -0
- package/dist/_vendor/core/transport.mjs +428 -0
- package/dist/_vendor/core/transport.mjs.map +1 -0
- package/dist/_vendor/devtools-protocol/index.d.ts +187 -4
- package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
- package/dist/_vendor/devtools-protocol/index.js +25 -9
- package/dist/_vendor/devtools-protocol/index.js.map +1 -1
- package/dist/_vendor/next/config.d.ts +3 -4
- package/dist/_vendor/next/config.d.ts.map +1 -1
- package/dist/_vendor/next/config.js +37 -19
- package/dist/_vendor/next/config.js.map +1 -1
- package/dist/_vendor/next/index.d.ts +109 -29
- package/dist/_vendor/next/index.d.ts.map +1 -1
- package/dist/_vendor/next/index.js +104 -26
- package/dist/_vendor/next/index.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +156 -37
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +80 -12
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- package/dist/_vendor/platform-expo/react.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/react.js +11 -10
- package/dist/_vendor/platform-expo/react.js.map +1 -1
- package/dist/_vendor/platform-expo/web-sqljs-wasm.js +16 -0
- package/dist/_vendor/platform-expo/web-sqljs-wasm.js.map +1 -0
- package/dist/_vendor/platform-node/index.d.mts +192 -24
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +236 -97
- package/dist/_vendor/platform-node/index.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.d.mts.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.mjs +15 -2
- package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc.d.mts +11 -35
- package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
- package/dist/_vendor/platform-node/ipc.mjs +3 -273
- package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +43 -1
- package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
- package/dist/_vendor/platform-web/external-change.js +32 -1
- package/dist/_vendor/platform-web/external-change.js.map +1 -1
- package/dist/_vendor/platform-web/index.d.ts +323 -51
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +233 -30
- package/dist/_vendor/platform-web/index.js.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.d.ts +12 -0
- package/dist/_vendor/platform-web/indexeddb.d.ts.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.js +10 -0
- package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
- package/dist/_vendor/platform-web/opfs.d.ts +13 -0
- package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
- package/dist/_vendor/platform-web/opfs.js +12 -0
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.d.ts +54 -0
- package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
- package/dist/_vendor/platform-web/persistence.js +15 -0
- package/dist/_vendor/platform-web/persistence.js.map +1 -1
- package/dist/_vendor/platform-web/react.d.ts +1 -2
- package/dist/_vendor/platform-web/react.d.ts.map +1 -1
- package/dist/_vendor/platform-web/react.js +27 -13
- package/dist/_vendor/platform-web/react.js.map +1 -1
- package/dist/_vendor/platform-web/sqljs.js +10 -1
- package/dist/_vendor/platform-web/sqljs.js.map +1 -1
- package/dist/_vendor/platform-web/web-sqljs-wasm.js +8 -0
- package/dist/_vendor/platform-web/web-sqljs-wasm.js.map +1 -0
- package/dist/_vendor/platform-web/worker.d.ts +71 -44
- package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
- package/dist/_vendor/platform-web/worker.js +40 -271
- package/dist/_vendor/platform-web/worker.js.map +1 -1
- package/dist/_vendor/react/index.d.ts +222 -23
- package/dist/_vendor/react/index.d.ts.map +1 -1
- package/dist/_vendor/react/index.js +476 -63
- package/dist/_vendor/react/index.js.map +1 -1
- package/dist/_vendor/schema/definition.d.ts +151 -37
- package/dist/_vendor/schema/definition.d.ts.map +1 -1
- package/dist/_vendor/schema/definition.js +102 -20
- package/dist/_vendor/schema/definition.js.map +1 -1
- package/dist/_vendor/schema/index.d.ts +4 -4
- package/dist/_vendor/schema/index.js +2 -2
- package/dist/_vendor/schema/planner.d.ts +19 -2
- package/dist/_vendor/schema/planner.d.ts.map +1 -1
- package/dist/_vendor/schema/planner.js +79 -3
- package/dist/_vendor/schema/planner.js.map +1 -1
- package/dist/_vendor/schema/validators.d.ts +279 -83
- package/dist/_vendor/schema/validators.d.ts.map +1 -1
- package/dist/_vendor/schema/validators.js +330 -38
- package/dist/_vendor/schema/validators.js.map +1 -1
- package/dist/_vendor/svelte/index.d.ts +245 -19
- package/dist/_vendor/svelte/index.d.ts.map +1 -1
- package/dist/_vendor/svelte/index.js +443 -20
- package/dist/_vendor/svelte/index.js.map +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/components.d.ts +2 -0
- package/dist/components.js +2 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/package.json +29 -21
|
@@ -1,145 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SyncoreBridgeClient, attachRuntimeBridge } from "../core/index.mjs";
|
|
2
2
|
//#region src/worker.ts
|
|
3
|
-
var SyncoreWebWorkerClient = class {
|
|
4
|
-
pendingRequests = /* @__PURE__ */ new Map();
|
|
5
|
-
watchRecordsByKey = /* @__PURE__ */ new Map();
|
|
6
|
-
watchKeyBySubscriptionId = /* @__PURE__ */ new Map();
|
|
7
|
-
disposed = false;
|
|
8
|
-
handleMessage = (event) => {
|
|
9
|
-
const message = event.data;
|
|
10
|
-
if (!message || typeof message !== "object" || !("type" in message)) return;
|
|
11
|
-
switch (message.type) {
|
|
12
|
-
case "runtime.ready": return;
|
|
13
|
-
case "runtime.error":
|
|
14
|
-
this.rejectAllPending(new Error(message.error));
|
|
15
|
-
return;
|
|
16
|
-
case "invoke.result": {
|
|
17
|
-
const pending = this.pendingRequests.get(message.requestId);
|
|
18
|
-
if (!pending) return;
|
|
19
|
-
this.pendingRequests.delete(message.requestId);
|
|
20
|
-
if (message.success) pending.resolve(message.value);
|
|
21
|
-
else pending.reject(new Error(message.error));
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
case "watch.update": {
|
|
25
|
-
const watchKey = this.watchKeyBySubscriptionId.get(message.subscriptionId);
|
|
26
|
-
if (!watchKey) return;
|
|
27
|
-
const watchRecord = this.watchRecordsByKey.get(watchKey);
|
|
28
|
-
if (!watchRecord) return;
|
|
29
|
-
if (message.success) {
|
|
30
|
-
watchRecord.result = message.value;
|
|
31
|
-
watchRecord.error = void 0;
|
|
32
|
-
} else watchRecord.error = new Error(message.error);
|
|
33
|
-
for (const listener of watchRecord.listeners) listener();
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
constructor(endpoint) {
|
|
38
|
-
this.endpoint = endpoint;
|
|
39
|
-
this.endpoint.addEventListener("message", this.handleMessage);
|
|
40
|
-
}
|
|
41
|
-
query(reference, ...args) {
|
|
42
|
-
return this.invoke("query", reference, normalizeOptionalArgs(args));
|
|
43
|
-
}
|
|
44
|
-
mutation(reference, ...args) {
|
|
45
|
-
return this.invoke("mutation", reference, normalizeOptionalArgs(args));
|
|
46
|
-
}
|
|
47
|
-
action(reference, ...args) {
|
|
48
|
-
return this.invoke("action", reference, normalizeOptionalArgs(args));
|
|
49
|
-
}
|
|
50
|
-
watchQuery(reference, ...args) {
|
|
51
|
-
this.ensureNotDisposed();
|
|
52
|
-
const normalizedArgs = normalizeOptionalArgs(args);
|
|
53
|
-
const watchKey = createWatchKey(reference, normalizedArgs);
|
|
54
|
-
let watchRecord = this.watchRecordsByKey.get(watchKey);
|
|
55
|
-
if (!watchRecord) {
|
|
56
|
-
watchRecord = {
|
|
57
|
-
subscriptionId: generateId(),
|
|
58
|
-
listeners: /* @__PURE__ */ new Set(),
|
|
59
|
-
consumers: 0,
|
|
60
|
-
result: void 0,
|
|
61
|
-
error: void 0
|
|
62
|
-
};
|
|
63
|
-
this.watchRecordsByKey.set(watchKey, watchRecord);
|
|
64
|
-
this.watchKeyBySubscriptionId.set(watchRecord.subscriptionId, watchKey);
|
|
65
|
-
this.endpoint.postMessage({
|
|
66
|
-
type: "watch.subscribe",
|
|
67
|
-
subscriptionId: watchRecord.subscriptionId,
|
|
68
|
-
reference,
|
|
69
|
-
args: normalizedArgs
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
watchRecord.consumers += 1;
|
|
73
|
-
let disposed = false;
|
|
74
|
-
const ownedListeners = /* @__PURE__ */ new Set();
|
|
75
|
-
return {
|
|
76
|
-
onUpdate: (callback) => {
|
|
77
|
-
watchRecord.listeners.add(callback);
|
|
78
|
-
ownedListeners.add(callback);
|
|
79
|
-
queueMicrotask(callback);
|
|
80
|
-
return () => {
|
|
81
|
-
watchRecord.listeners.delete(callback);
|
|
82
|
-
ownedListeners.delete(callback);
|
|
83
|
-
};
|
|
84
|
-
},
|
|
85
|
-
localQueryResult: () => watchRecord.result,
|
|
86
|
-
localQueryError: () => watchRecord.error,
|
|
87
|
-
dispose: () => {
|
|
88
|
-
if (disposed) return;
|
|
89
|
-
disposed = true;
|
|
90
|
-
for (const callback of ownedListeners) watchRecord.listeners.delete(callback);
|
|
91
|
-
ownedListeners.clear();
|
|
92
|
-
watchRecord.consumers = Math.max(0, watchRecord.consumers - 1);
|
|
93
|
-
if (watchRecord.consumers > 0) return;
|
|
94
|
-
this.endpoint.postMessage({
|
|
95
|
-
type: "watch.unsubscribe",
|
|
96
|
-
subscriptionId: watchRecord.subscriptionId
|
|
97
|
-
});
|
|
98
|
-
this.watchKeyBySubscriptionId.delete(watchRecord.subscriptionId);
|
|
99
|
-
this.watchRecordsByKey.delete(watchKey);
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
dispose() {
|
|
104
|
-
if (this.disposed) return;
|
|
105
|
-
this.disposed = true;
|
|
106
|
-
this.endpoint.removeEventListener("message", this.handleMessage);
|
|
107
|
-
for (const watchRecord of this.watchRecordsByKey.values()) this.endpoint.postMessage({
|
|
108
|
-
type: "watch.unsubscribe",
|
|
109
|
-
subscriptionId: watchRecord.subscriptionId
|
|
110
|
-
});
|
|
111
|
-
this.watchKeyBySubscriptionId.clear();
|
|
112
|
-
this.watchRecordsByKey.clear();
|
|
113
|
-
this.rejectAllPending(/* @__PURE__ */ new Error("Syncore worker client was disposed."));
|
|
114
|
-
}
|
|
115
|
-
invoke(kind, reference, args) {
|
|
116
|
-
this.ensureNotDisposed();
|
|
117
|
-
const requestId = generateId();
|
|
118
|
-
const promise = new Promise((resolve, reject) => {
|
|
119
|
-
this.pendingRequests.set(requestId, {
|
|
120
|
-
resolve,
|
|
121
|
-
reject
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
this.endpoint.postMessage(createInvokeRequest(requestId, kind, reference, args));
|
|
125
|
-
return promise;
|
|
126
|
-
}
|
|
127
|
-
rejectAllPending(error) {
|
|
128
|
-
for (const pending of this.pendingRequests.values()) pending.reject(error);
|
|
129
|
-
this.pendingRequests.clear();
|
|
130
|
-
}
|
|
131
|
-
ensureNotDisposed() {
|
|
132
|
-
if (this.disposed) throw new Error("Syncore worker client was disposed.");
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
3
|
/**
|
|
136
|
-
*
|
|
4
|
+
* Syncore client that communicates with a runtime running in a browser Worker
|
|
5
|
+
* over the `postMessage` bridge.
|
|
6
|
+
*
|
|
7
|
+
* Use `createSyncoreWebWorkerClient()` or `createManagedWebWorkerClient()` to
|
|
8
|
+
* create instances. Prefer the React hooks (`useQuery`, `useMutation`, etc.)
|
|
9
|
+
* over calling this directly in React apps.
|
|
10
|
+
*/
|
|
11
|
+
var SyncoreWebWorkerClient = class extends SyncoreBridgeClient {};
|
|
12
|
+
/**
|
|
13
|
+
* Create a {@link SyncoreWebWorkerClient} from a low-level message endpoint.
|
|
14
|
+
*
|
|
15
|
+
* Use this when you already have a `Worker` or `MessagePort` reference and
|
|
16
|
+
* want to wrap it manually. For the common case of spawning a new Worker from
|
|
17
|
+
* a URL, use `createSyncoreWebWorkerClient` instead.
|
|
137
18
|
*/
|
|
138
19
|
function createWebWorkerClient(endpoint) {
|
|
139
20
|
return new SyncoreWebWorkerClient(endpoint);
|
|
140
21
|
}
|
|
141
22
|
/**
|
|
142
|
-
* Create
|
|
23
|
+
* Create a {@link ManagedWebWorkerClient} using a provided Worker factory.
|
|
24
|
+
*
|
|
25
|
+
* Useful when you need control over how the Worker is constructed (e.g. to
|
|
26
|
+
* pass constructor options not exposed by `CreateWebWorkerClientProviderOptions`).
|
|
27
|
+
* For the common URL-based case, use `createSyncoreWebWorkerClient`.
|
|
143
28
|
*/
|
|
144
29
|
function createManagedWebWorkerClient(options) {
|
|
145
30
|
const worker = options.createWorker();
|
|
@@ -154,7 +39,21 @@ function createManagedWebWorkerClient(options) {
|
|
|
154
39
|
};
|
|
155
40
|
}
|
|
156
41
|
/**
|
|
157
|
-
* Create a
|
|
42
|
+
* Create a {@link ManagedWebWorkerClient} by spawning a new Worker from a URL.
|
|
43
|
+
*
|
|
44
|
+
* This is the standard way to create a main-thread client in a browser app.
|
|
45
|
+
* Pass the URL of your `syncore.worker.ts` file (which calls
|
|
46
|
+
* `createWebWorkerRuntime`) and connect the returned `client` to your React
|
|
47
|
+
* `SyncoreProvider` or Svelte context.
|
|
48
|
+
*
|
|
49
|
+
* ```ts
|
|
50
|
+
* // main.ts (or React root)
|
|
51
|
+
* import { createSyncoreWebWorkerClient } from "syncorejs/browser";
|
|
52
|
+
*
|
|
53
|
+
* const { client, dispose } = createSyncoreWebWorkerClient({
|
|
54
|
+
* workerUrl: new URL("./syncore.worker.ts", import.meta.url),
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
158
57
|
*/
|
|
159
58
|
function createSyncoreWebWorkerClient(options) {
|
|
160
59
|
return createManagedWebWorkerClient({ createWorker: () => new Worker(options.workerUrl, {
|
|
@@ -163,143 +62,13 @@ function createSyncoreWebWorkerClient(options) {
|
|
|
163
62
|
}) });
|
|
164
63
|
}
|
|
165
64
|
/**
|
|
166
|
-
*
|
|
65
|
+
* Wire a Syncore runtime factory to a worker message endpoint.
|
|
66
|
+
*
|
|
67
|
+
* Called internally by `createWebWorkerRuntime`. Exposed for cases where you
|
|
68
|
+
* need to attach a runtime to a custom bridge endpoint (e.g. a `MessagePort`).
|
|
167
69
|
*/
|
|
168
70
|
function attachWebWorkerRuntime(options) {
|
|
169
|
-
|
|
170
|
-
const runtimePromise = Promise.resolve(options.createRuntime()).then(async (runtime) => {
|
|
171
|
-
await runtime.start();
|
|
172
|
-
return runtime;
|
|
173
|
-
});
|
|
174
|
-
const clientPromise = runtimePromise.then((runtime) => runtime.createClient());
|
|
175
|
-
const ready = clientPromise.then(() => {
|
|
176
|
-
options.endpoint.postMessage({ type: "runtime.ready" });
|
|
177
|
-
}).catch((error) => {
|
|
178
|
-
options.endpoint.postMessage({
|
|
179
|
-
type: "runtime.error",
|
|
180
|
-
error: error instanceof Error ? error.message : String(error)
|
|
181
|
-
});
|
|
182
|
-
throw error;
|
|
183
|
-
});
|
|
184
|
-
const handleMessage = (event) => {
|
|
185
|
-
(async () => {
|
|
186
|
-
const message = event.data;
|
|
187
|
-
if (!message || typeof message !== "object" || !("type" in message)) return;
|
|
188
|
-
try {
|
|
189
|
-
const client = await clientPromise;
|
|
190
|
-
switch (message.type) {
|
|
191
|
-
case "invoke": {
|
|
192
|
-
const value = message.kind === "query" ? await client.query(message.reference, message.args) : message.kind === "mutation" ? await client.mutation(message.reference, message.args) : await client.action(message.reference, message.args);
|
|
193
|
-
options.endpoint.postMessage({
|
|
194
|
-
type: "invoke.result",
|
|
195
|
-
requestId: message.requestId,
|
|
196
|
-
success: true,
|
|
197
|
-
value
|
|
198
|
-
});
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
case "watch.subscribe": {
|
|
202
|
-
if (subscriptions.has(message.subscriptionId)) return;
|
|
203
|
-
const watch = client.watchQuery(message.reference, message.args);
|
|
204
|
-
const sendCurrentState = () => {
|
|
205
|
-
const error = watch.localQueryError();
|
|
206
|
-
if (error) {
|
|
207
|
-
options.endpoint.postMessage({
|
|
208
|
-
type: "watch.update",
|
|
209
|
-
subscriptionId: message.subscriptionId,
|
|
210
|
-
success: false,
|
|
211
|
-
error: error.message
|
|
212
|
-
});
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
options.endpoint.postMessage({
|
|
216
|
-
type: "watch.update",
|
|
217
|
-
subscriptionId: message.subscriptionId,
|
|
218
|
-
success: true,
|
|
219
|
-
value: watch.localQueryResult()
|
|
220
|
-
});
|
|
221
|
-
};
|
|
222
|
-
const unsubscribe = watch.onUpdate(sendCurrentState);
|
|
223
|
-
subscriptions.set(message.subscriptionId, {
|
|
224
|
-
watch,
|
|
225
|
-
unsubscribe
|
|
226
|
-
});
|
|
227
|
-
sendCurrentState();
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
case "watch.unsubscribe": {
|
|
231
|
-
const subscription = subscriptions.get(message.subscriptionId);
|
|
232
|
-
if (!subscription) return;
|
|
233
|
-
subscription.unsubscribe();
|
|
234
|
-
subscriptions.delete(message.subscriptionId);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
} catch (error) {
|
|
238
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
239
|
-
if (message.type === "invoke") options.endpoint.postMessage({
|
|
240
|
-
type: "invoke.result",
|
|
241
|
-
requestId: message.requestId,
|
|
242
|
-
success: false,
|
|
243
|
-
error: errorMessage
|
|
244
|
-
});
|
|
245
|
-
if (message.type === "watch.subscribe") options.endpoint.postMessage({
|
|
246
|
-
type: "watch.update",
|
|
247
|
-
subscriptionId: message.subscriptionId,
|
|
248
|
-
success: false,
|
|
249
|
-
error: errorMessage
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
})();
|
|
253
|
-
};
|
|
254
|
-
options.endpoint.addEventListener("message", handleMessage);
|
|
255
|
-
return {
|
|
256
|
-
ready,
|
|
257
|
-
async dispose() {
|
|
258
|
-
options.endpoint.removeEventListener("message", handleMessage);
|
|
259
|
-
for (const subscription of subscriptions.values()) subscription.unsubscribe();
|
|
260
|
-
subscriptions.clear();
|
|
261
|
-
await (await runtimePromise).stop();
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
function createWatchKey(reference, args) {
|
|
266
|
-
return `${reference.name}:${stableStringify(args)}`;
|
|
267
|
-
}
|
|
268
|
-
function createInvokeRequest(requestId, kind, reference, args) {
|
|
269
|
-
switch (kind) {
|
|
270
|
-
case "query": return {
|
|
271
|
-
type: "invoke",
|
|
272
|
-
requestId,
|
|
273
|
-
kind,
|
|
274
|
-
reference,
|
|
275
|
-
args
|
|
276
|
-
};
|
|
277
|
-
case "mutation": return {
|
|
278
|
-
type: "invoke",
|
|
279
|
-
requestId,
|
|
280
|
-
kind,
|
|
281
|
-
reference,
|
|
282
|
-
args
|
|
283
|
-
};
|
|
284
|
-
case "action": return {
|
|
285
|
-
type: "invoke",
|
|
286
|
-
requestId,
|
|
287
|
-
kind,
|
|
288
|
-
reference,
|
|
289
|
-
args
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
function stableStringify(value) {
|
|
294
|
-
return JSON.stringify(sortValue(value));
|
|
295
|
-
}
|
|
296
|
-
function sortValue(value) {
|
|
297
|
-
if (Array.isArray(value)) return value.map(sortValue);
|
|
298
|
-
if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortValue(nested)]));
|
|
299
|
-
return value;
|
|
300
|
-
}
|
|
301
|
-
function normalizeOptionalArgs(args) {
|
|
302
|
-
return args[0] ?? {};
|
|
71
|
+
return attachRuntimeBridge(options);
|
|
303
72
|
}
|
|
304
73
|
//#endregion
|
|
305
74
|
export { SyncoreWebWorkerClient, attachWebWorkerRuntime, createManagedWebWorkerClient, createSyncoreWebWorkerClient, createWebWorkerClient };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","names":[],"sources":["../src/worker.ts"],"sourcesContent":["import {\n generateId,\n type AnySyncoreSchema,\n type FunctionReference,\n type JsonObject,\n type SyncoreClient,\n type SyncoreRuntime,\n type SyncoreWatch\n} from \"@syncore/core\";\nexport type WebWorkerSyncoreSchema = AnySyncoreSchema;\n\nexport interface SyncoreWorkerMessageEndpoint {\n postMessage(message: unknown): void;\n addEventListener(\n type: \"message\",\n listener: (event: MessageEvent<unknown>) => void\n ): void;\n removeEventListener(\n type: \"message\",\n listener: (event: MessageEvent<unknown>) => void\n ): void;\n}\n\ntype SyncoreWorkerRequest =\n | {\n type: \"invoke\";\n requestId: string;\n kind: \"query\";\n reference: FunctionReference<\"query\", unknown, unknown>;\n args: JsonObject;\n }\n | {\n type: \"invoke\";\n requestId: string;\n kind: \"mutation\";\n reference: FunctionReference<\"mutation\", unknown, unknown>;\n args: JsonObject;\n }\n | {\n type: \"invoke\";\n requestId: string;\n kind: \"action\";\n reference: FunctionReference<\"action\", unknown, unknown>;\n args: JsonObject;\n }\n | {\n type: \"watch.subscribe\";\n subscriptionId: string;\n reference: FunctionReference<\"query\", unknown, unknown>;\n args: JsonObject;\n }\n | {\n type: \"watch.unsubscribe\";\n subscriptionId: string;\n };\n\ntype SyncoreWorkerResponse =\n | {\n type: \"runtime.ready\";\n }\n | {\n type: \"runtime.error\";\n error: string;\n }\n | {\n type: \"invoke.result\";\n requestId: string;\n success: true;\n value: unknown;\n }\n | {\n type: \"invoke.result\";\n requestId: string;\n success: false;\n error: string;\n }\n | {\n type: \"watch.update\";\n subscriptionId: string;\n success: true;\n value: unknown;\n }\n | {\n type: \"watch.update\";\n subscriptionId: string;\n success: false;\n error: string;\n };\n\ninterface PendingRequest {\n resolve(value: unknown): void;\n reject(error: Error): void;\n}\n\ninterface WatchRecord {\n subscriptionId: string;\n listeners: Set<() => void>;\n consumers: number;\n result: unknown;\n error: Error | undefined;\n}\n\nexport type WorkerQueryWatch<TValue> = SyncoreWatch<TValue> & {\n dispose(): void;\n};\n\ntype OptionalArgsTuple<TArgs> =\n Record<never, never> extends TArgs ? [args?: TArgs] : [args: TArgs];\n\nexport class SyncoreWebWorkerClient implements SyncoreClient {\n private readonly pendingRequests = new Map<string, PendingRequest>();\n private readonly watchRecordsByKey = new Map<string, WatchRecord>();\n private readonly watchKeyBySubscriptionId = new Map<string, string>();\n private disposed = false;\n\n private readonly handleMessage = (event: MessageEvent<unknown>) => {\n const message = event.data as SyncoreWorkerResponse;\n if (!message || typeof message !== \"object\" || !(\"type\" in message)) {\n return;\n }\n\n switch (message.type) {\n case \"runtime.ready\":\n return;\n case \"runtime.error\":\n this.rejectAllPending(new Error(message.error));\n return;\n case \"invoke.result\": {\n const pending = this.pendingRequests.get(message.requestId);\n if (!pending) {\n return;\n }\n this.pendingRequests.delete(message.requestId);\n if (message.success) {\n pending.resolve(message.value);\n } else {\n pending.reject(new Error(message.error));\n }\n return;\n }\n case \"watch.update\": {\n const watchKey = this.watchKeyBySubscriptionId.get(\n message.subscriptionId\n );\n if (!watchKey) {\n return;\n }\n const watchRecord = this.watchRecordsByKey.get(watchKey);\n if (!watchRecord) {\n return;\n }\n if (message.success) {\n watchRecord.result = message.value;\n watchRecord.error = undefined;\n } else {\n watchRecord.error = new Error(message.error);\n }\n for (const listener of watchRecord.listeners) {\n listener();\n }\n }\n }\n };\n\n constructor(private readonly endpoint: SyncoreWorkerMessageEndpoint) {\n this.endpoint.addEventListener(\"message\", this.handleMessage);\n }\n\n query<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs>\n ): Promise<TResult> {\n return this.invoke(\n \"query\",\n reference,\n normalizeOptionalArgs(args) as JsonObject\n );\n }\n\n mutation<TArgs, TResult>(\n reference: FunctionReference<\"mutation\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs>\n ): Promise<TResult> {\n return this.invoke(\n \"mutation\",\n reference,\n normalizeOptionalArgs(args) as JsonObject\n );\n }\n\n action<TArgs, TResult>(\n reference: FunctionReference<\"action\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs>\n ): Promise<TResult> {\n return this.invoke(\n \"action\",\n reference,\n normalizeOptionalArgs(args) as JsonObject\n );\n }\n\n watchQuery<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs>\n ): WorkerQueryWatch<TResult> {\n this.ensureNotDisposed();\n const normalizedArgs = normalizeOptionalArgs(args) as JsonObject;\n const watchKey = createWatchKey(reference, normalizedArgs);\n let watchRecord = this.watchRecordsByKey.get(watchKey);\n if (!watchRecord) {\n watchRecord = {\n subscriptionId: generateId(),\n listeners: new Set<() => void>(),\n consumers: 0,\n result: undefined,\n error: undefined\n };\n this.watchRecordsByKey.set(watchKey, watchRecord);\n this.watchKeyBySubscriptionId.set(watchRecord.subscriptionId, watchKey);\n this.endpoint.postMessage({\n type: \"watch.subscribe\",\n subscriptionId: watchRecord.subscriptionId,\n reference,\n args: normalizedArgs\n } satisfies SyncoreWorkerRequest);\n }\n\n watchRecord.consumers += 1;\n let disposed = false;\n const ownedListeners = new Set<() => void>();\n\n return {\n onUpdate: (callback) => {\n watchRecord.listeners.add(callback);\n ownedListeners.add(callback);\n queueMicrotask(callback);\n return () => {\n watchRecord.listeners.delete(callback);\n ownedListeners.delete(callback);\n };\n },\n localQueryResult: () => watchRecord.result as TResult | undefined,\n localQueryError: () => watchRecord.error,\n dispose: () => {\n if (disposed) {\n return;\n }\n disposed = true;\n for (const callback of ownedListeners) {\n watchRecord.listeners.delete(callback);\n }\n ownedListeners.clear();\n watchRecord.consumers = Math.max(0, watchRecord.consumers - 1);\n if (watchRecord.consumers > 0) {\n return;\n }\n this.endpoint.postMessage({\n type: \"watch.unsubscribe\",\n subscriptionId: watchRecord.subscriptionId\n } satisfies SyncoreWorkerRequest);\n this.watchKeyBySubscriptionId.delete(watchRecord.subscriptionId);\n this.watchRecordsByKey.delete(watchKey);\n }\n };\n }\n\n dispose(): void {\n if (this.disposed) {\n return;\n }\n this.disposed = true;\n this.endpoint.removeEventListener(\"message\", this.handleMessage);\n for (const watchRecord of this.watchRecordsByKey.values()) {\n this.endpoint.postMessage({\n type: \"watch.unsubscribe\",\n subscriptionId: watchRecord.subscriptionId\n } satisfies SyncoreWorkerRequest);\n }\n this.watchKeyBySubscriptionId.clear();\n this.watchRecordsByKey.clear();\n this.rejectAllPending(new Error(\"Syncore worker client was disposed.\"));\n }\n\n private invoke<TArgs, TResult>(\n kind: \"query\",\n reference: FunctionReference<\"query\", TArgs, TResult>,\n args: JsonObject\n ): Promise<TResult>;\n private invoke<TArgs, TResult>(\n kind: \"mutation\",\n reference: FunctionReference<\"mutation\", TArgs, TResult>,\n args: JsonObject\n ): Promise<TResult>;\n private invoke<TArgs, TResult>(\n kind: \"action\",\n reference: FunctionReference<\"action\", TArgs, TResult>,\n args: JsonObject\n ): Promise<TResult>;\n private invoke<TArgs, TResult>(\n kind: \"query\" | \"mutation\" | \"action\",\n reference: FunctionReference<\n \"query\" | \"mutation\" | \"action\",\n TArgs,\n TResult\n >,\n args: JsonObject\n ): Promise<TResult> {\n this.ensureNotDisposed();\n const requestId = generateId();\n const promise = new Promise<TResult>((resolve, reject) => {\n this.pendingRequests.set(requestId, { resolve, reject });\n });\n\n this.endpoint.postMessage(\n createInvokeRequest(requestId, kind, reference, args)\n );\n\n return promise;\n }\n\n private rejectAllPending(error: Error): void {\n for (const pending of this.pendingRequests.values()) {\n pending.reject(error);\n }\n this.pendingRequests.clear();\n }\n\n private ensureNotDisposed(): void {\n if (this.disposed) {\n throw new Error(\"Syncore worker client was disposed.\");\n }\n }\n}\n\nexport interface AttachWebWorkerRuntimeOptions {\n endpoint: SyncoreWorkerMessageEndpoint;\n createRuntime:\n | (() => Promise<SyncoreRuntime<WebWorkerSyncoreSchema>>)\n | (() => SyncoreRuntime<WebWorkerSyncoreSchema>);\n}\n\nexport interface AttachedWebWorkerRuntime {\n ready: Promise<void>;\n dispose(): Promise<void>;\n}\n\n/**\n * A worker-backed browser client plus the Worker instance it owns.\n */\nexport interface ManagedWebWorkerClient {\n client: SyncoreWebWorkerClient;\n worker: Worker;\n dispose(): void;\n}\n\n/**\n * Options for creating a worker-backed Syncore client in the browser.\n */\nexport interface CreateWebWorkerClientProviderOptions {\n /** The worker module URL passed to `new Worker(...)`. */\n workerUrl: URL | string;\n\n /** Optional worker type, defaults to `module`. */\n workerType?: WorkerOptions[\"type\"];\n\n /** Optional name shown in browser devtools. */\n workerName?: string;\n}\n\n/**\n * Create a web worker Syncore client from a low-level message endpoint.\n */\nexport function createWebWorkerClient(\n endpoint: SyncoreWorkerMessageEndpoint\n): SyncoreWebWorkerClient {\n return new SyncoreWebWorkerClient(endpoint);\n}\n\n/**\n * Create and manage both a browser Worker and the Syncore client that talks to it.\n */\nexport function createManagedWebWorkerClient(options: {\n createWorker: () => Worker;\n}): ManagedWebWorkerClient {\n const worker = options.createWorker();\n const client = createWebWorkerClient(worker);\n return {\n client,\n worker,\n dispose() {\n client.dispose();\n worker.terminate();\n }\n };\n}\n\n/**\n * Create a worker-backed Syncore client using the standard Worker constructor.\n */\nexport function createSyncoreWebWorkerClient(\n options: CreateWebWorkerClientProviderOptions\n): ManagedWebWorkerClient {\n return createManagedWebWorkerClient({\n createWorker: () =>\n new Worker(options.workerUrl, {\n type: options.workerType ?? \"module\",\n ...(options.workerName ? { name: options.workerName } : {})\n })\n });\n}\n\n/**\n * Attach a Syncore runtime implementation to a worker message endpoint.\n */\nexport function attachWebWorkerRuntime(\n options: AttachWebWorkerRuntimeOptions\n): AttachedWebWorkerRuntime {\n const subscriptions = new Map<\n string,\n {\n watch: SyncoreWatch<unknown>;\n unsubscribe: () => void;\n }\n >();\n\n const runtimePromise = Promise.resolve(options.createRuntime()).then(\n async (runtime) => {\n await runtime.start();\n return runtime;\n }\n );\n\n const clientPromise = runtimePromise.then((runtime) =>\n runtime.createClient()\n );\n\n const ready = clientPromise\n .then(() => {\n options.endpoint.postMessage({\n type: \"runtime.ready\"\n } satisfies SyncoreWorkerResponse);\n })\n .catch((error) => {\n options.endpoint.postMessage({\n type: \"runtime.error\",\n error: error instanceof Error ? error.message : String(error)\n } satisfies SyncoreWorkerResponse);\n throw error;\n });\n\n const handleMessage = (event: MessageEvent<unknown>) => {\n void (async () => {\n const message = event.data as SyncoreWorkerRequest;\n if (!message || typeof message !== \"object\" || !(\"type\" in message)) {\n return;\n }\n\n try {\n const client = await clientPromise;\n switch (message.type) {\n case \"invoke\": {\n const value =\n message.kind === \"query\"\n ? await client.query(message.reference, message.args)\n : message.kind === \"mutation\"\n ? await client.mutation(message.reference, message.args)\n : await client.action(message.reference, message.args);\n options.endpoint.postMessage({\n type: \"invoke.result\",\n requestId: message.requestId,\n success: true,\n value\n } satisfies SyncoreWorkerResponse);\n return;\n }\n case \"watch.subscribe\": {\n if (subscriptions.has(message.subscriptionId)) {\n return;\n }\n const watch = client.watchQuery(message.reference, message.args);\n const sendCurrentState = () => {\n const error = watch.localQueryError();\n if (error) {\n options.endpoint.postMessage({\n type: \"watch.update\",\n subscriptionId: message.subscriptionId,\n success: false,\n error: error.message\n } satisfies SyncoreWorkerResponse);\n return;\n }\n options.endpoint.postMessage({\n type: \"watch.update\",\n subscriptionId: message.subscriptionId,\n success: true,\n value: watch.localQueryResult()\n } satisfies SyncoreWorkerResponse);\n };\n const unsubscribe = watch.onUpdate(sendCurrentState);\n subscriptions.set(message.subscriptionId, { watch, unsubscribe });\n sendCurrentState();\n return;\n }\n case \"watch.unsubscribe\": {\n const subscription = subscriptions.get(message.subscriptionId);\n if (!subscription) {\n return;\n }\n subscription.unsubscribe();\n subscriptions.delete(message.subscriptionId);\n }\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n if (message.type === \"invoke\") {\n options.endpoint.postMessage({\n type: \"invoke.result\",\n requestId: message.requestId,\n success: false,\n error: errorMessage\n } satisfies SyncoreWorkerResponse);\n }\n if (message.type === \"watch.subscribe\") {\n options.endpoint.postMessage({\n type: \"watch.update\",\n subscriptionId: message.subscriptionId,\n success: false,\n error: errorMessage\n } satisfies SyncoreWorkerResponse);\n }\n }\n })();\n };\n\n options.endpoint.addEventListener(\"message\", handleMessage);\n\n return {\n ready,\n async dispose() {\n options.endpoint.removeEventListener(\"message\", handleMessage);\n for (const subscription of subscriptions.values()) {\n subscription.unsubscribe();\n }\n subscriptions.clear();\n const runtime = await runtimePromise;\n await runtime.stop();\n }\n };\n}\n\nfunction createWatchKey(\n reference: FunctionReference<\"query\", unknown, unknown>,\n args: JsonObject\n): string {\n return `${reference.name}:${stableStringify(args)}`;\n}\n\nfunction createInvokeRequest(\n requestId: string,\n kind: \"query\" | \"mutation\" | \"action\",\n reference:\n | FunctionReference<\"query\", unknown, unknown>\n | FunctionReference<\"mutation\", unknown, unknown>\n | FunctionReference<\"action\", unknown, unknown>,\n args: JsonObject\n): SyncoreWorkerRequest {\n switch (kind) {\n case \"query\":\n return {\n type: \"invoke\",\n requestId,\n kind,\n reference: reference as FunctionReference<\"query\">,\n args\n };\n case \"mutation\":\n return {\n type: \"invoke\",\n requestId,\n kind,\n reference: reference as FunctionReference<\"mutation\">,\n args\n };\n case \"action\":\n return {\n type: \"invoke\",\n requestId,\n kind,\n reference: reference as FunctionReference<\"action\">,\n args\n };\n }\n}\n\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortValue(value));\n}\n\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortValue);\n }\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, sortValue(nested)])\n );\n }\n return value;\n}\n\nfunction normalizeOptionalArgs<TArgs>(\n args: [] | [TArgs] | readonly unknown[]\n): TArgs {\n return (args[0] ?? {}) as TArgs;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"worker.js","names":[],"sources":["../src/worker.ts"],"sourcesContent":["import {\n attachRuntimeBridge,\n type AttachRuntimeBridgeOptions,\n type AttachedRuntimeBridge,\n type BridgeQueryWatch,\n SyncoreBridgeClient,\n type SyncoreDataModel,\n type SyncoreBridgeMessageEndpoint,\n} from \"@syncore/core\";\n\n/**\n * Schema type constraint for worker-side Syncore runtimes.\n *\n * Pass any schema produced by `defineSchema()` where this type is expected.\n * Defaults to the unconstrained `SyncoreDataModel` when omitted.\n */\nexport type WebWorkerSyncoreSchema<\n TSchema extends SyncoreDataModel = SyncoreDataModel\n> = TSchema;\n/** Message endpoint shape required by the browser worker bridge (alias of `SyncoreBridgeMessageEndpoint`). */\nexport type SyncoreWorkerMessageEndpoint = SyncoreBridgeMessageEndpoint;\n/** Live-query subscription handle returned by `SyncoreWebWorkerClient.watchQuery`. */\nexport type WorkerQueryWatch<TValue> = BridgeQueryWatch<TValue>;\n\n/**\n * Syncore client that communicates with a runtime running in a browser Worker\n * over the `postMessage` bridge.\n *\n * Use `createSyncoreWebWorkerClient()` or `createManagedWebWorkerClient()` to\n * create instances. Prefer the React hooks (`useQuery`, `useMutation`, etc.)\n * over calling this directly in React apps.\n */\nexport class SyncoreWebWorkerClient extends SyncoreBridgeClient {\n declare query: SyncoreBridgeClient[\"query\"];\n declare mutation: SyncoreBridgeClient[\"mutation\"];\n declare action: SyncoreBridgeClient[\"action\"];\n declare watchQuery: SyncoreBridgeClient[\"watchQuery\"];\n}\n\n/** Options for attaching a runtime to a worker bridge endpoint. Alias of `AttachRuntimeBridgeOptions`. */\nexport type AttachWebWorkerRuntimeOptions<\n TSchema extends WebWorkerSyncoreSchema = WebWorkerSyncoreSchema\n> = AttachRuntimeBridgeOptions<TSchema>;\n/** Handle returned by `attachWebWorkerRuntime` for controlling the attached bridge. */\nexport type AttachedWebWorkerRuntime = AttachedRuntimeBridge;\n\n/**\n * A browser Worker and its associated Syncore client, bundled for easy\n * lifecycle management.\n *\n * Returned by `createSyncoreWebWorkerClient` and `createManagedWebWorkerClient`.\n * Call `dispose()` to terminate the worker and release its resources.\n */\nexport interface ManagedWebWorkerClient {\n /** The Syncore client connected to the worker. */\n client: SyncoreWebWorkerClient;\n /** The underlying `Worker` instance. Useful for low-level control. */\n worker: Worker;\n /** Terminate the worker and dispose the client. Call on app unmount or navigation. */\n dispose(): void;\n}\n\n/**\n * Options for creating a managed worker Syncore client via\n * `createSyncoreWebWorkerClient`.\n */\nexport interface CreateWebWorkerClientProviderOptions {\n /** The worker module URL passed to `new Worker(...)`. Typically an `import.meta.url`-relative `URL`. */\n workerUrl: URL | string;\n /** Worker module type. Defaults to `\"module\"` (ESM worker). */\n workerType?: WorkerOptions[\"type\"];\n /** Optional label shown in browser devtools’ Sources panel. */\n workerName?: string;\n}\n\n/**\n * Create a {@link SyncoreWebWorkerClient} from a low-level message endpoint.\n *\n * Use this when you already have a `Worker` or `MessagePort` reference and\n * want to wrap it manually. For the common case of spawning a new Worker from\n * a URL, use `createSyncoreWebWorkerClient` instead.\n */\nexport function createWebWorkerClient(\n endpoint: SyncoreWorkerMessageEndpoint\n): SyncoreWebWorkerClient {\n return new SyncoreWebWorkerClient(endpoint);\n}\n\n/**\n * Create a {@link ManagedWebWorkerClient} using a provided Worker factory.\n *\n * Useful when you need control over how the Worker is constructed (e.g. to\n * pass constructor options not exposed by `CreateWebWorkerClientProviderOptions`).\n * For the common URL-based case, use `createSyncoreWebWorkerClient`.\n */\nexport function createManagedWebWorkerClient(options: {\n createWorker: () => Worker;\n}): ManagedWebWorkerClient {\n const worker = options.createWorker();\n const client = createWebWorkerClient(worker);\n return {\n client,\n worker,\n dispose() {\n client.dispose();\n worker.terminate();\n }\n };\n}\n\n/**\n * Create a {@link ManagedWebWorkerClient} by spawning a new Worker from a URL.\n *\n * This is the standard way to create a main-thread client in a browser app.\n * Pass the URL of your `syncore.worker.ts` file (which calls\n * `createWebWorkerRuntime`) and connect the returned `client` to your React\n * `SyncoreProvider` or Svelte context.\n *\n * ```ts\n * // main.ts (or React root)\n * import { createSyncoreWebWorkerClient } from \"syncorejs/browser\";\n *\n * const { client, dispose } = createSyncoreWebWorkerClient({\n * workerUrl: new URL(\"./syncore.worker.ts\", import.meta.url),\n * });\n * ```\n */\nexport function createSyncoreWebWorkerClient(\n options: CreateWebWorkerClientProviderOptions\n): ManagedWebWorkerClient {\n return createManagedWebWorkerClient({\n createWorker: () =>\n new Worker(options.workerUrl, {\n type: options.workerType ?? \"module\",\n ...(options.workerName ? { name: options.workerName } : {})\n })\n });\n}\n\n/**\n * Wire a Syncore runtime factory to a worker message endpoint.\n *\n * Called internally by `createWebWorkerRuntime`. Exposed for cases where you\n * need to attach a runtime to a custom bridge endpoint (e.g. a `MessagePort`).\n */\nexport function attachWebWorkerRuntime(\n options: AttachWebWorkerRuntimeOptions\n): AttachedWebWorkerRuntime {\n return attachRuntimeBridge(options);\n}\n"],"mappings":";;;;;;;;;;AAgCA,IAAa,yBAAb,cAA4C,oBAAoB,CAKhE;;;;;;;;AA6CA,SAAgB,sBACd,UACwB;CACxB,OAAO,IAAI,uBAAuB,QAAQ;AAC5C;;;;;;;;AASA,SAAgB,6BAA6B,SAElB;CACzB,MAAM,SAAS,QAAQ,aAAa;CACpC,MAAM,SAAS,sBAAsB,MAAM;CAC3C,OAAO;EACL;EACA;EACA,UAAU;GACR,OAAO,QAAQ;GACf,OAAO,UAAU;EACnB;CACF;AACF;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,6BACd,SACwB;CACxB,OAAO,6BAA6B,EAClC,oBACE,IAAI,OAAO,QAAQ,WAAW;EAC5B,MAAM,QAAQ,cAAc;EAC5B,GAAI,QAAQ,aAAa,EAAE,MAAM,QAAQ,WAAW,IAAI,CAAC;CAC3D,CAAC,EACL,CAAC;AACH;;;;;;;AAQA,SAAgB,uBACd,SAC0B;CAC1B,OAAO,oBAAoB,OAAO;AACpC"}
|