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
@@ -4,13 +4,31 @@ import { createWebPersistence, isOpfsAvailable } from "./persistence.js";
4
4
  import { BroadcastChannelExternalChangeSignal, SqlJsExternalChangeApplier, createDefaultSyncChannelName } from "./external-change.js";
5
5
  import { SqlJsDriver } from "./sqljs.js";
6
6
  import { SyncoreWebWorkerClient, attachWebWorkerRuntime, createManagedWebWorkerClient, createSyncoreWebWorkerClient, createWebWorkerClient } from "./worker.js";
7
- import { SyncoreRuntime, createDevtoolsCommandHandler, createDevtoolsSubscriptionHost } from "../core/index.mjs";
7
+ import { SyncoreRuntime, createDevtoolsCommandHandler, createDevtoolsSubscriptionHost, generateId } from "../core/index.mjs";
8
+ import { SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_PROTOCOL_VERSION } from "../devtools-protocol/index.js";
8
9
  //#region src/index.ts
10
+ const DEVTOOLS_META_NAMESPACE = "__syncore_devtools_meta__";
11
+ const STORAGE_SCOPE_ID_PREFIX = "storage-scope";
12
+ const DATA_SOURCE_ALIAS_PREFIX = "data-source-alias";
9
13
  /**
10
- * Create a full Syncore runtime directly in the browser.
14
+ * Create a full Syncore runtime directly in the browser (main thread or
15
+ * shared worker).
11
16
  *
12
- * Most React apps should use a worker runtime instead so queries and SQLite work
13
- * stay off the main thread.
17
+ * This function sets up SQL.js, the OPFS/IndexedDB persistence layer, blob
18
+ * storage, cross-tab change synchronisation via `BroadcastChannel`, and
19
+ * auto-connects to the devtools server in development.
20
+ *
21
+ * @remarks
22
+ * Most React/Svelte apps should run the runtime inside a `Worker` using
23
+ * `createWebWorkerSyncoreRuntime()` instead, so that SQLite queries don’t
24
+ * block the main thread. Use `createWebSyncoreRuntime` only when a worker is
25
+ * not practical (e.g. in Electron renderer processes or certain test setups).
26
+ *
27
+ * ```ts
28
+ * const runtime = await createWebSyncoreRuntime({ schema, functions });
29
+ * await runtime.start();
30
+ * const client = runtime.createClient();
31
+ * ```
14
32
  */
15
33
  async function createWebSyncoreRuntime(options) {
16
34
  const persistence = options.persistence ?? await createWebPersistence({
@@ -18,10 +36,11 @@ async function createWebSyncoreRuntime(options) {
18
36
  ...options.persistenceDatabaseName ? { indexedDbDatabaseName: options.persistenceDatabaseName } : {},
19
37
  opfsRootDirectoryName: options.opfsRootDirectoryName ?? options.databaseName ?? "syncore"
20
38
  });
39
+ const wasmUrl = options.wasmUrl ?? (options.locateFile || !isBrowserLikeRuntime() ? void 0 : await resolveDefaultWebWasmUrl());
21
40
  const driver = options.driver ?? await SqlJsDriver.create({
22
41
  databaseName: options.databaseName ?? "syncore",
23
42
  persistence,
24
- ...options.wasmUrl ? { wasmUrl: options.wasmUrl } : {},
43
+ ...wasmUrl ? { wasmUrl } : {},
25
44
  ...options.locateFile ? { locateFile: options.locateFile } : {}
26
45
  });
27
46
  const storage = options.storage ?? new BrowserFileStorageAdapter(persistence, options.storageNamespace ?? options.databaseName ?? "syncore");
@@ -30,22 +49,27 @@ async function createWebSyncoreRuntime(options) {
30
49
  persistence,
31
50
  driver
32
51
  });
33
- const appName = resolveWebAppName();
52
+ const appName = options.appName ?? resolveWebAppName();
34
53
  const origin = resolveWebOrigin();
35
54
  const sessionLabel = resolveWebSessionLabel();
36
55
  const databaseLabel = options.databaseName ?? "syncore";
56
+ const storageScopeId = await resolvePersistedStorageScopeId(persistence, databaseLabel);
57
+ const dataSourceAlias = await resolvePersistedDataSourceAlias(persistence, databaseLabel);
37
58
  const storageIdentity = [
38
59
  origin ?? "unknown-origin",
39
60
  persistence.storageProtocol,
40
- databaseLabel
61
+ databaseLabel,
62
+ storageScopeId
41
63
  ].join("::");
42
64
  const autoDevtools = options.devtools === void 0 && shouldAutoConnectDevtools() ? (() => {
43
65
  const sinkOptions = {
44
- url: resolveDefaultDevtoolsUrl(),
66
+ url: options.devtoolsUrl ?? resolveDefaultDevtoolsUrl(),
45
67
  targetKind: "client",
46
68
  storageProtocol: persistence.storageProtocol,
47
69
  databaseLabel,
48
- storageIdentity
70
+ dataSourceAlias,
71
+ storageIdentity,
72
+ capabilities: createBrowserDevtoolsCapabilities()
49
73
  };
50
74
  if (appName) sinkOptions.appName = appName;
51
75
  if (origin) sinkOptions.origin = origin;
@@ -58,11 +82,12 @@ async function createWebSyncoreRuntime(options) {
58
82
  sessionLabel,
59
83
  appName,
60
84
  origin,
61
- devtoolsUrl: options.devtools && typeof options.devtools === "object" ? void 0 : resolveDefaultDevtoolsUrl()
85
+ devtoolsUrl: options.devtools && typeof options.devtools === "object" ? void 0 : options.devtoolsUrl ?? resolveDefaultDevtoolsUrl()
62
86
  });
63
87
  const runtime = new SyncoreRuntime({
64
88
  schema: options.schema,
65
89
  functions: options.functions,
90
+ ...options.components ? { components: options.components } : {},
66
91
  driver,
67
92
  storage,
68
93
  externalChangeSignal: externalChangeSupport.signal,
@@ -70,26 +95,40 @@ async function createWebSyncoreRuntime(options) {
70
95
  platform: options.platform ?? "browser",
71
96
  ...options.capabilities ? { capabilities: options.capabilities } : {},
72
97
  ...resolvedDevtools ? { devtools: resolvedDevtools } : {},
73
- ...options.experimentalPlugins ? { experimentalPlugins: options.experimentalPlugins } : {},
74
98
  ...options.scheduler ? { scheduler: options.scheduler } : {}
75
99
  });
76
- if (autoDevtools) {
77
- autoDevtools.attachRuntime(runtime);
78
- autoDevtools.attachCommandHandler(createDevtoolsCommandHandler({
100
+ if (isAttachableBrowserDevtoolsSink(resolvedDevtools)) {
101
+ resolvedDevtools.attachRuntime(runtime);
102
+ resolvedDevtools.attachCommandHandler(createDevtoolsCommandHandler({
79
103
  driver,
80
104
  schema: options.schema,
81
105
  functions: options.functions,
82
- runtime
106
+ admin: runtime.getAdmin()
83
107
  }));
84
- autoDevtools.attachSubscriptionHost(createDevtoolsSubscriptionHost({
108
+ resolvedDevtools.attachSubscriptionHost(createDevtoolsSubscriptionHost({
85
109
  driver,
86
110
  schema: options.schema,
87
111
  functions: options.functions,
88
- runtime
112
+ admin: runtime.getAdmin()
89
113
  }));
90
114
  }
91
115
  return runtime;
92
116
  }
117
+ function isAttachableBrowserDevtoolsSink(sink) {
118
+ return !!sink && typeof sink.attachRuntime === "function" && typeof sink.attachCommandHandler === "function" && typeof sink.attachSubscriptionHost === "function";
119
+ }
120
+ /**
121
+ * Build a {@link WebExternalChangeSupport} bundle for a given database and
122
+ * persistence layer.
123
+ *
124
+ * Creates a `BroadcastChannel`-based signal so that all tabs sharing the same
125
+ * `databaseName` are notified when a mutation commits. When `driver` is a
126
+ * `SqlJsDriver` (i.e. an in-memory database), an `applier` is also created so
127
+ * the local database can be updated from the latest on-disk snapshot.
128
+ *
129
+ * Called automatically by `createWebSyncoreRuntime`. Exposed for advanced use
130
+ * cases such as the Expo web adapter.
131
+ */
93
132
  function createWebExternalChangeSupport(options) {
94
133
  const signal = new BroadcastChannelExternalChangeSignal({ channelName: createDefaultSyncChannelName(options.databaseName) });
95
134
  const sqlDriver = options.driver instanceof SqlJsDriver ? options.driver : void 0;
@@ -106,16 +145,28 @@ function createWebExternalChangeSupport(options) {
106
145
  })
107
146
  };
108
147
  }
148
+ /**
149
+ * Build a {@link WebExternalChangeSupport} bundle for an Expo app running on
150
+ * the web platform.
151
+ *
152
+ * Behaves identically to {@link createWebExternalChangeSupport} but accepts
153
+ * the same options shape used by `createExpoSyncoreRuntime`, making it easy
154
+ * to share config when bootstrapping an Expo web runtime.\
155
+ *
156
+ * Called internally by the Expo platform adapter. Use directly only when
157
+ * constructing the runtime outside of `createExpoSyncoreRuntime`.
158
+ */
109
159
  async function createExpoWebExternalChangeSupport(options) {
110
160
  const persistence = await createWebPersistence({
111
161
  ...options.persistenceMode ? { mode: options.persistenceMode } : {},
112
162
  ...options.persistenceDatabaseName ? { indexedDbDatabaseName: options.persistenceDatabaseName } : {},
113
163
  opfsRootDirectoryName: options.opfsRootDirectoryName ?? options.databaseName
114
164
  });
165
+ const wasmUrl = options.wasmUrl ?? (options.locateFile || !isBrowserLikeRuntime() ? void 0 : await resolveDefaultWebWasmUrl());
115
166
  const driver = await SqlJsDriver.create({
116
167
  databaseName: options.databaseName,
117
168
  persistence,
118
- ...options.wasmUrl ? { wasmUrl: options.wasmUrl } : {},
169
+ ...wasmUrl ? { wasmUrl } : {},
119
170
  ...options.locateFile ? { locateFile: options.locateFile } : {}
120
171
  });
121
172
  return createWebExternalChangeSupport({
@@ -125,38 +176,107 @@ async function createExpoWebExternalChangeSupport(options) {
125
176
  });
126
177
  }
127
178
  /**
128
- * Attach a Syncore runtime to a browser Worker endpoint.
179
+ * Start a Syncore runtime inside a browser `Worker` and wire it to the
180
+ * worker’s own message endpoint.
181
+ *
182
+ * This is the function you call **inside your worker file** (`syncore.worker.ts`).
183
+ * It creates the full runtime (SQL.js + OPFS + BroadcastChannel) in the worker
184
+ * context and begins listening for messages from the main-thread client.
185
+ *
186
+ * ```ts
187
+ * // syncore.worker.ts
188
+ * import { createWebWorkerRuntime } from "syncorejs/browser";
189
+ * import schema from "./syncore/schema";
190
+ * import { functions } from "./syncore/_generated/functions";
191
+ *
192
+ * void createWebWorkerRuntime({
193
+ * schema,
194
+ * functions,
195
+ * endpoint: self as unknown as SyncoreWorkerMessageEndpoint,
196
+ * });
197
+ * ```
198
+ *
199
+ * On the main thread, connect with `createManagedWebWorkerClient()` or
200
+ * `SyncoreNextProvider` (Next.js).
129
201
  */
130
202
  function createWebWorkerRuntime(options) {
131
203
  return attachWebWorkerRuntime({
132
204
  endpoint: options.endpoint,
133
- createRuntime: () => createWebSyncoreRuntime(options)
205
+ createRuntime: () => createWebSyncoreRuntime({
206
+ ...options,
207
+ platform: options.platform ?? "browser-worker"
208
+ })
134
209
  });
135
210
  }
136
211
  /**
137
- * Attach a Syncore runtime to a browser Worker endpoint.
212
+ * Alias of {@link createWebWorkerRuntime} for the `syncorejs/browser` surface.
213
+ * @see createWebWorkerRuntime
138
214
  */
139
215
  function createBrowserWorkerRuntime(options) {
140
216
  return createWebWorkerRuntime(options);
141
217
  }
142
218
  /**
143
- * Create a client directly from a browser Syncore runtime.
219
+ * Create a same-process Syncore client from a started browser runtime.
220
+ *
221
+ * Use this when the runtime lives in the same context as the client (e.g.
222
+ * main-thread runtime in an Electron renderer or a test harness). For
223
+ * worker-based setups use `createManagedWebWorkerClient()` instead, which
224
+ * communicates with the worker over `postMessage`.
225
+ *
226
+ * ```ts
227
+ * const runtime = await createWebSyncoreRuntime({ schema, functions });
228
+ * await runtime.start();
229
+ * const client = createWebSyncoreClient(runtime);
230
+ * ```
144
231
  */
145
232
  function createWebSyncoreClient(runtime) {
146
233
  return runtime.createClient();
147
234
  }
148
235
  /**
149
- * Create a full Syncore runtime directly in the browser.
236
+ * Alias of {@link createWebSyncoreRuntime} for the `syncorejs/browser` surface.
237
+ * @see createWebSyncoreRuntime
150
238
  */
151
239
  function createBrowserSyncoreRuntime(options) {
152
240
  return createWebSyncoreRuntime(options);
153
241
  }
154
242
  /**
155
- * Create a client directly from a browser Syncore runtime.
243
+ * Alias of {@link createWebSyncoreClient} for the `syncorejs/browser` surface.
244
+ * @see createWebSyncoreClient
156
245
  */
157
246
  function createBrowserSyncoreClient(runtime) {
158
247
  return createWebSyncoreClient(runtime);
159
248
  }
249
+ async function resolveDefaultWebWasmUrl() {
250
+ try {
251
+ return (await import("./web-sqljs-wasm.js")).resolveDefaultWebSqlJsWasmUrl();
252
+ } catch (error) {
253
+ if (!isBrowserLikeRuntime()) return;
254
+ throw new Error("Syncore could not resolve the default sql.js WebAssembly asset. Pass wasmUrl or locateFile to createWebSyncoreRuntime/createBrowserWorkerRuntime for this bundler.", { cause: error });
255
+ }
256
+ }
257
+ function isBrowserLikeRuntime() {
258
+ return typeof window !== "undefined" || globalThis.WorkerGlobalScope !== void 0;
259
+ }
260
+ /**
261
+ * Create a WebSocket-based devtools sink that connects to the Syncore devtools
262
+ * server and forwards runtime events in real time.
263
+ *
264
+ * The sink auto-reconnects if the connection drops (e.g. while the devtools
265
+ * dashboard is restarting) and buffers events that arrive before the socket is
266
+ * open.
267
+ *
268
+ * In most cases you do not need to call this directly — `createWebSyncoreRuntime`
269
+ * creates and attaches the sink automatically when `devtools` is omitted and the
270
+ * page is served from a local/private hostname.
271
+ *
272
+ * ```ts
273
+ * const sink = createBrowserWebSocketDevtoolsSink({
274
+ * url: "ws://127.0.0.1:4311",
275
+ * appName: "My App",
276
+ * });
277
+ * const runtime = await createWebSyncoreRuntime({ schema, functions, devtools: sink });
278
+ * ```
279
+ */
160
280
  function createBrowserWebSocketDevtoolsSink(options) {
161
281
  let socket;
162
282
  let disposed = false;
@@ -172,6 +292,9 @@ function createBrowserWebSocketDevtoolsSink(options) {
172
292
  socket.onopen = () => {
173
293
  if (latestHello) sendNow({
174
294
  type: "hello",
295
+ protocolVersion: SYNCORE_DEVTOOLS_PROTOCOL_VERSION,
296
+ minSupportedProtocolVersion: SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION,
297
+ maxSupportedProtocolVersion: SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION,
175
298
  runtimeId: latestHello.runtimeId,
176
299
  platform: latestHello.platform,
177
300
  ...options.appName ? { appName: options.appName } : {},
@@ -180,7 +303,9 @@ function createBrowserWebSocketDevtoolsSink(options) {
180
303
  ...options.targetKind ? { targetKind: options.targetKind } : {},
181
304
  ...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
182
305
  ...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
183
- ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {}
306
+ ...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
307
+ ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
308
+ capabilities: options.capabilities ?? createBrowserDevtoolsCapabilities()
184
309
  });
185
310
  flushPendingMessages();
186
311
  };
@@ -260,6 +385,9 @@ function createBrowserWebSocketDevtoolsSink(options) {
260
385
  };
261
386
  send({
262
387
  type: "hello",
388
+ protocolVersion: SYNCORE_DEVTOOLS_PROTOCOL_VERSION,
389
+ minSupportedProtocolVersion: SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION,
390
+ maxSupportedProtocolVersion: SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION,
263
391
  runtimeId: event.runtimeId,
264
392
  platform: event.platform,
265
393
  ...options.appName ? { appName: options.appName } : {},
@@ -268,7 +396,9 @@ function createBrowserWebSocketDevtoolsSink(options) {
268
396
  ...options.targetKind ? { targetKind: options.targetKind } : {},
269
397
  ...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
270
398
  ...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
271
- ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {}
399
+ ...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
400
+ ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
401
+ capabilities: options.capabilities ?? createBrowserDevtoolsCapabilities()
272
402
  });
273
403
  }
274
404
  send({
@@ -277,7 +407,7 @@ function createBrowserWebSocketDevtoolsSink(options) {
277
407
  });
278
408
  },
279
409
  attachRuntime(runtime) {
280
- getSummary = () => withRuntimeSummaryMeta(runtime.getRuntimeSummary(), options);
410
+ getSummary = () => withRuntimeSummaryMeta(runtime.getAdmin().getRuntimeSummary(), options);
281
411
  },
282
412
  attachCommandHandler(handler) {
283
413
  onCommand = handler;
@@ -302,7 +432,28 @@ function withRuntimeSummaryMeta(summary, options) {
302
432
  ...options.targetKind ? { targetKind: options.targetKind } : {},
303
433
  ...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
304
434
  ...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
305
- ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {}
435
+ ...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
436
+ ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
437
+ capabilities: options.capabilities ?? createBrowserDevtoolsCapabilities()
438
+ };
439
+ }
440
+ function createBrowserDevtoolsCapabilities() {
441
+ return {
442
+ sql: {
443
+ read: false,
444
+ write: false,
445
+ live: false,
446
+ reason: "SQL Console is not available for browser runtimes."
447
+ },
448
+ data: {
449
+ browse: true,
450
+ mutate: true,
451
+ importExport: true
452
+ },
453
+ scheduler: {
454
+ read: true,
455
+ edit: true
456
+ }
306
457
  };
307
458
  }
308
459
  function shouldAutoConnectDevtools() {
@@ -388,12 +539,49 @@ function resolveWebSessionLabel() {
388
539
  globalThis.localStorage?.setItem(STORAGE_KEY, uniqueName);
389
540
  } catch {}
390
541
  }
391
- const browser = navigator.userAgent.includes("Firefox") ? "Firefox" : navigator.userAgent.includes("Chrome") ? "Chrome" : navigator.userAgent.includes("Safari") ? "Safari" : "Browser";
542
+ const browser = resolveBrowserName(navigator);
392
543
  return `${uniqueName} (${browser})`;
393
544
  } catch {
394
545
  return;
395
546
  }
396
547
  }
548
+ function resolveBrowserName(nav) {
549
+ const brands = nav.userAgentData?.brands?.map((entry) => entry.brand) ?? [];
550
+ if (brands.some((brand) => /microsoft edge/i.test(brand))) return "Edge";
551
+ if (brands.some((brand) => /firefox/i.test(brand))) return "Firefox";
552
+ if (brands.some((brand) => /opera/i.test(brand))) return "Opera";
553
+ if (brands.some((brand) => /chrome|chromium/i.test(brand))) return "Chrome";
554
+ if (brands.some((brand) => /safari/i.test(brand))) return "Safari";
555
+ const userAgent = nav.userAgent;
556
+ if (/Firefox\//i.test(userAgent)) return "Firefox";
557
+ if (/Edg\//i.test(userAgent)) return "Edge";
558
+ if (/OPR\/|Opera/i.test(userAgent)) return "Opera";
559
+ if (/Chrome\/|CriOS\//i.test(userAgent)) return "Chrome";
560
+ if (/Safari\//i.test(userAgent)) return "Safari";
561
+ return "Browser";
562
+ }
563
+ async function resolvePersistedStorageScopeId(persistence, databaseLabel) {
564
+ const id = `${STORAGE_SCOPE_ID_PREFIX}:${databaseLabel}`;
565
+ const existing = await persistence.getFile(DEVTOOLS_META_NAMESPACE, id);
566
+ if (existing) {
567
+ const value = new TextDecoder().decode(existing.bytes).trim();
568
+ if (value.length > 0) return value;
569
+ }
570
+ const nextValue = generateId();
571
+ await persistence.putFile(DEVTOOLS_META_NAMESPACE, id, new TextEncoder().encode(nextValue), "text/plain");
572
+ return nextValue;
573
+ }
574
+ async function resolvePersistedDataSourceAlias(persistence, databaseLabel) {
575
+ const id = `${DATA_SOURCE_ALIAS_PREFIX}:${databaseLabel}`;
576
+ const existing = await persistence.getFile(DEVTOOLS_META_NAMESPACE, id);
577
+ if (existing) {
578
+ const value = new TextDecoder().decode(existing.bytes).trim();
579
+ if (value.length > 0) return value;
580
+ }
581
+ const nextValue = generateUniqueSessionName();
582
+ await persistence.putFile(DEVTOOLS_META_NAMESPACE, id, new TextEncoder().encode(nextValue), "text/plain");
583
+ return nextValue;
584
+ }
397
585
  function announceBrowserSession(options) {
398
586
  if (!options.enabled || !options.sessionLabel) return;
399
587
  const announcedSessions = getAnnouncedBrowserSessions();
@@ -522,9 +710,24 @@ function generateUniqueSessionName() {
522
710
  return `${SESSION_ADJECTIVES[Math.floor(Math.random() * SESSION_ADJECTIVES.length)]} ${SESSION_NOUNS[Math.floor(Math.random() * SESSION_NOUNS.length)]}`;
523
711
  }
524
712
  /**
525
- * Browser file/blob storage built on top of Syncore web persistence.
713
+ * Browser file/blob storage adapter backed by `SyncoreWebPersistence`.
714
+ *
715
+ * Stores binary blobs (images, documents, etc.) in the same OPFS or
716
+ * IndexedDB store as the SQLite database. Pass an instance to
717
+ * `CreateWebRuntimeOptions.storage` to enable Syncore's Storage API
718
+ * (`ctx.storage.put`, `ctx.storage.get`, etc.) in browser functions.
719
+ *
720
+ * ```ts
721
+ * const runtime = await createWebSyncoreRuntime({
722
+ * schema,
723
+ * functions,
724
+ * storage: (persistence) => new BrowserFileStorageAdapter(persistence, "files"),
725
+ * });
726
+ * ```
526
727
  */
527
728
  var BrowserFileStorageAdapter = class {
729
+ persistence;
730
+ namespace;
528
731
  constructor(persistence, namespace) {
529
732
  this.persistence = persistence;
530
733
  this.namespace = namespace;