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.
Files changed (169) hide show
  1. package/README.md +2 -1
  2. package/dist/_vendor/cli/app.d.mts.map +1 -1
  3. package/dist/_vendor/cli/app.mjs +330 -46
  4. package/dist/_vendor/cli/app.mjs.map +1 -1
  5. package/dist/_vendor/cli/context.mjs +27 -9
  6. package/dist/_vendor/cli/context.mjs.map +1 -1
  7. package/dist/_vendor/cli/dev-session.mjs.map +1 -1
  8. package/dist/_vendor/cli/doctor.mjs +513 -46
  9. package/dist/_vendor/cli/doctor.mjs.map +1 -1
  10. package/dist/_vendor/cli/errors.mjs.map +1 -1
  11. package/dist/_vendor/cli/help.mjs.map +1 -1
  12. package/dist/_vendor/cli/index.mjs +9 -2
  13. package/dist/_vendor/cli/index.mjs.map +1 -1
  14. package/dist/_vendor/cli/messages.mjs +5 -4
  15. package/dist/_vendor/cli/messages.mjs.map +1 -1
  16. package/dist/_vendor/cli/preflight.mjs.map +1 -1
  17. package/dist/_vendor/cli/project.mjs +125 -27
  18. package/dist/_vendor/cli/project.mjs.map +1 -1
  19. package/dist/_vendor/cli/render.mjs +57 -9
  20. package/dist/_vendor/cli/render.mjs.map +1 -1
  21. package/dist/_vendor/cli/targets.mjs +4 -3
  22. package/dist/_vendor/cli/targets.mjs.map +1 -1
  23. package/dist/_vendor/core/cli.d.mts +20 -4
  24. package/dist/_vendor/core/cli.d.mts.map +1 -1
  25. package/dist/_vendor/core/cli.mjs +458 -133
  26. package/dist/_vendor/core/cli.mjs.map +1 -1
  27. package/dist/_vendor/core/devtools-auth.mjs +60 -0
  28. package/dist/_vendor/core/devtools-auth.mjs.map +1 -0
  29. package/dist/_vendor/core/index.d.mts +5 -3
  30. package/dist/_vendor/core/index.mjs +22 -2
  31. package/dist/_vendor/core/index.mjs.map +1 -1
  32. package/dist/_vendor/core/runtime/components.d.mts +111 -0
  33. package/dist/_vendor/core/runtime/components.d.mts.map +1 -0
  34. package/dist/_vendor/core/runtime/components.mjs +186 -0
  35. package/dist/_vendor/core/runtime/components.mjs.map +1 -0
  36. package/dist/_vendor/core/runtime/devtools.d.mts +4 -4
  37. package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
  38. package/dist/_vendor/core/runtime/devtools.mjs +178 -60
  39. package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
  40. package/dist/_vendor/core/runtime/functions.d.mts +398 -16
  41. package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
  42. package/dist/_vendor/core/runtime/functions.mjs +74 -3
  43. package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
  44. package/dist/_vendor/core/runtime/id.d.mts.map +1 -1
  45. package/dist/_vendor/core/runtime/id.mjs.map +1 -1
  46. package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +83 -0
  47. package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -0
  48. package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +720 -0
  49. package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -0
  50. package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +234 -0
  51. package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -0
  52. package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +255 -0
  53. package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -0
  54. package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +200 -0
  55. package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -0
  56. package/dist/_vendor/core/runtime/internal/engines/shared.mjs +252 -0
  57. package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -0
  58. package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +145 -0
  59. package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -0
  60. package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +221 -0
  61. package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -0
  62. package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs +32 -0
  63. package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -0
  64. package/dist/_vendor/core/runtime/internal/systemMeta.mjs +61 -0
  65. package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -0
  66. package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +41 -0
  67. package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -0
  68. package/dist/_vendor/core/runtime/runtime.d.mts +1187 -202
  69. package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
  70. package/dist/_vendor/core/runtime/runtime.mjs +73 -1365
  71. package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
  72. package/dist/_vendor/core/transport.d.mts +113 -0
  73. package/dist/_vendor/core/transport.d.mts.map +1 -0
  74. package/dist/_vendor/core/transport.mjs +428 -0
  75. package/dist/_vendor/core/transport.mjs.map +1 -0
  76. package/dist/_vendor/devtools-protocol/index.d.ts +187 -4
  77. package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
  78. package/dist/_vendor/devtools-protocol/index.js +25 -9
  79. package/dist/_vendor/devtools-protocol/index.js.map +1 -1
  80. package/dist/_vendor/next/config.d.ts +3 -4
  81. package/dist/_vendor/next/config.d.ts.map +1 -1
  82. package/dist/_vendor/next/config.js +37 -19
  83. package/dist/_vendor/next/config.js.map +1 -1
  84. package/dist/_vendor/next/index.d.ts +109 -29
  85. package/dist/_vendor/next/index.d.ts.map +1 -1
  86. package/dist/_vendor/next/index.js +104 -26
  87. package/dist/_vendor/next/index.js.map +1 -1
  88. package/dist/_vendor/platform-expo/index.d.ts +156 -37
  89. package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
  90. package/dist/_vendor/platform-expo/index.js +80 -12
  91. package/dist/_vendor/platform-expo/index.js.map +1 -1
  92. package/dist/_vendor/platform-expo/react.d.ts.map +1 -1
  93. package/dist/_vendor/platform-expo/react.js +11 -10
  94. package/dist/_vendor/platform-expo/react.js.map +1 -1
  95. package/dist/_vendor/platform-expo/web-sqljs-wasm.js +16 -0
  96. package/dist/_vendor/platform-expo/web-sqljs-wasm.js.map +1 -0
  97. package/dist/_vendor/platform-node/index.d.mts +192 -24
  98. package/dist/_vendor/platform-node/index.d.mts.map +1 -1
  99. package/dist/_vendor/platform-node/index.mjs +236 -97
  100. package/dist/_vendor/platform-node/index.mjs.map +1 -1
  101. package/dist/_vendor/platform-node/ipc-react.d.mts.map +1 -1
  102. package/dist/_vendor/platform-node/ipc-react.mjs +15 -2
  103. package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
  104. package/dist/_vendor/platform-node/ipc.d.mts +11 -35
  105. package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
  106. package/dist/_vendor/platform-node/ipc.mjs +3 -273
  107. package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
  108. package/dist/_vendor/platform-web/external-change.d.ts +43 -1
  109. package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
  110. package/dist/_vendor/platform-web/external-change.js +32 -1
  111. package/dist/_vendor/platform-web/external-change.js.map +1 -1
  112. package/dist/_vendor/platform-web/index.d.ts +323 -51
  113. package/dist/_vendor/platform-web/index.d.ts.map +1 -1
  114. package/dist/_vendor/platform-web/index.js +233 -30
  115. package/dist/_vendor/platform-web/index.js.map +1 -1
  116. package/dist/_vendor/platform-web/indexeddb.d.ts +12 -0
  117. package/dist/_vendor/platform-web/indexeddb.d.ts.map +1 -1
  118. package/dist/_vendor/platform-web/indexeddb.js +10 -0
  119. package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
  120. package/dist/_vendor/platform-web/opfs.d.ts +13 -0
  121. package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
  122. package/dist/_vendor/platform-web/opfs.js +12 -0
  123. package/dist/_vendor/platform-web/opfs.js.map +1 -1
  124. package/dist/_vendor/platform-web/persistence.d.ts +54 -0
  125. package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
  126. package/dist/_vendor/platform-web/persistence.js +15 -0
  127. package/dist/_vendor/platform-web/persistence.js.map +1 -1
  128. package/dist/_vendor/platform-web/react.d.ts +1 -2
  129. package/dist/_vendor/platform-web/react.d.ts.map +1 -1
  130. package/dist/_vendor/platform-web/react.js +27 -13
  131. package/dist/_vendor/platform-web/react.js.map +1 -1
  132. package/dist/_vendor/platform-web/sqljs.js +10 -1
  133. package/dist/_vendor/platform-web/sqljs.js.map +1 -1
  134. package/dist/_vendor/platform-web/web-sqljs-wasm.js +8 -0
  135. package/dist/_vendor/platform-web/web-sqljs-wasm.js.map +1 -0
  136. package/dist/_vendor/platform-web/worker.d.ts +71 -44
  137. package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
  138. package/dist/_vendor/platform-web/worker.js +40 -271
  139. package/dist/_vendor/platform-web/worker.js.map +1 -1
  140. package/dist/_vendor/react/index.d.ts +222 -23
  141. package/dist/_vendor/react/index.d.ts.map +1 -1
  142. package/dist/_vendor/react/index.js +476 -63
  143. package/dist/_vendor/react/index.js.map +1 -1
  144. package/dist/_vendor/schema/definition.d.ts +151 -37
  145. package/dist/_vendor/schema/definition.d.ts.map +1 -1
  146. package/dist/_vendor/schema/definition.js +102 -20
  147. package/dist/_vendor/schema/definition.js.map +1 -1
  148. package/dist/_vendor/schema/index.d.ts +4 -4
  149. package/dist/_vendor/schema/index.js +2 -2
  150. package/dist/_vendor/schema/planner.d.ts +19 -2
  151. package/dist/_vendor/schema/planner.d.ts.map +1 -1
  152. package/dist/_vendor/schema/planner.js +79 -3
  153. package/dist/_vendor/schema/planner.js.map +1 -1
  154. package/dist/_vendor/schema/validators.d.ts +279 -83
  155. package/dist/_vendor/schema/validators.d.ts.map +1 -1
  156. package/dist/_vendor/schema/validators.js +330 -38
  157. package/dist/_vendor/schema/validators.js.map +1 -1
  158. package/dist/_vendor/svelte/index.d.ts +245 -19
  159. package/dist/_vendor/svelte/index.d.ts.map +1 -1
  160. package/dist/_vendor/svelte/index.js +443 -20
  161. package/dist/_vendor/svelte/index.js.map +1 -1
  162. package/dist/browser.d.ts.map +1 -1
  163. package/dist/cli.js +3 -1
  164. package/dist/cli.js.map +1 -1
  165. package/dist/components.d.ts +2 -0
  166. package/dist/components.js +2 -0
  167. package/dist/index.d.ts +3 -2
  168. package/dist/index.js +2 -1
  169. package/package.json +29 -21
@@ -1,145 +1,30 @@
1
- import { generateId } from "../core/index.mjs";
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
- * Create a web worker Syncore client from a low-level message endpoint.
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 and manage both a browser Worker and the Syncore client that talks to it.
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 worker-backed Syncore client using the standard Worker constructor.
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
- * Attach a Syncore runtime implementation to a worker message endpoint.
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
- const subscriptions = /* @__PURE__ */ new Map();
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"}