syncorejs 0.2.2 → 0.2.4
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/dist/_vendor/cli/app.d.mts.map +1 -1
- package/dist/_vendor/cli/app.mjs +8 -5
- package/dist/_vendor/cli/app.mjs.map +1 -1
- 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.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.map +1 -1
- package/dist/_vendor/cli/preflight.mjs.map +1 -1
- package/dist/_vendor/cli/project.mjs +20 -20
- package/dist/_vendor/cli/project.mjs.map +1 -1
- package/dist/_vendor/cli/render.mjs.map +1 -1
- package/dist/_vendor/cli/targets.mjs.map +1 -1
- package/dist/_vendor/core/cli.d.mts +8 -2
- package/dist/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +510 -71
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/devtools-auth.mjs.map +1 -1
- package/dist/_vendor/core/index.d.mts +3 -3
- package/dist/_vendor/core/runtime/components.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/components.mjs.map +1 -1
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +261 -23
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.d.mts +388 -6
- package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/functions.mjs +72 -1
- 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 +12 -6
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +123 -20
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +56 -8
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +49 -14
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +4 -7
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs +81 -2
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +100 -13
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +42 -7
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +4 -0
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -1
- package/dist/_vendor/core/runtime/runtime.d.mts +1100 -12
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs +63 -0
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/core/transport.d.mts +2 -0
- package/dist/_vendor/core/transport.d.mts.map +1 -1
- package/dist/_vendor/core/transport.mjs +61 -27
- package/dist/_vendor/core/transport.mjs.map +1 -1
- package/dist/_vendor/devtools-protocol/index.d.ts +223 -4
- package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
- 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 +86 -18
- package/dist/_vendor/next/index.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +146 -27
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +81 -10
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- 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 +174 -9
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +251 -95
- package/dist/_vendor/platform-node/index.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.mjs +4 -0
- package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
- package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +41 -0
- package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
- package/dist/_vendor/platform-web/external-change.js +30 -0
- package/dist/_vendor/platform-web/external-change.js.map +1 -1
- package/dist/_vendor/platform-web/index.d.ts +312 -37
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +247 -25
- 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 +16 -1
- package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
- package/dist/_vendor/platform-web/opfs.js +41 -3
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.d.ts +85 -1
- 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 +11 -5
- 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 +60 -9
- package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
- package/dist/_vendor/platform-web/worker.js +37 -4
- package/dist/_vendor/platform-web/worker.js.map +1 -1
- package/dist/_vendor/react/index.d.ts +197 -13
- package/dist/_vendor/react/index.d.ts.map +1 -1
- package/dist/_vendor/react/index.js +209 -17
- package/dist/_vendor/react/index.js.map +1 -1
- package/dist/_vendor/schema/definition.d.ts +129 -0
- package/dist/_vendor/schema/definition.d.ts.map +1 -1
- package/dist/_vendor/schema/definition.js +99 -0
- package/dist/_vendor/schema/definition.js.map +1 -1
- package/dist/_vendor/schema/planner.d.ts.map +1 -1
- package/dist/_vendor/schema/planner.js.map +1 -1
- package/dist/_vendor/schema/validators.d.ts +180 -4
- package/dist/_vendor/schema/validators.d.ts.map +1 -1
- package/dist/_vendor/schema/validators.js +35 -1
- package/dist/_vendor/schema/validators.js.map +1 -1
- package/dist/_vendor/svelte/index.d.ts +207 -7
- package/dist/_vendor/svelte/index.d.ts.map +1 -1
- package/dist/_vendor/svelte/index.js +201 -6
- 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/index.d.ts +1 -1
- package/package.json +24 -21
|
@@ -9,11 +9,26 @@ import { SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_MIN_S
|
|
|
9
9
|
//#region src/index.ts
|
|
10
10
|
const DEVTOOLS_META_NAMESPACE = "__syncore_devtools_meta__";
|
|
11
11
|
const STORAGE_SCOPE_ID_PREFIX = "storage-scope";
|
|
12
|
+
const DATA_SOURCE_ALIAS_PREFIX = "data-source-alias";
|
|
12
13
|
/**
|
|
13
|
-
* 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).
|
|
14
16
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
+
* This function sets up SQL.js, the OPFS/IndexedDB persistence layer,
|
|
18
|
+
* OPFS-backed blob storage when available, 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
|
+
* ```
|
|
17
32
|
*/
|
|
18
33
|
async function createWebSyncoreRuntime(options) {
|
|
19
34
|
const persistence = options.persistence ?? await createWebPersistence({
|
|
@@ -21,23 +36,27 @@ async function createWebSyncoreRuntime(options) {
|
|
|
21
36
|
...options.persistenceDatabaseName ? { indexedDbDatabaseName: options.persistenceDatabaseName } : {},
|
|
22
37
|
opfsRootDirectoryName: options.opfsRootDirectoryName ?? options.databaseName ?? "syncore"
|
|
23
38
|
});
|
|
39
|
+
const wasmUrl = options.wasmUrl ?? (options.locateFile || !isBrowserLikeRuntime() ? void 0 : await resolveDefaultWebWasmUrl());
|
|
24
40
|
const driver = options.driver ?? await SqlJsDriver.create({
|
|
25
41
|
databaseName: options.databaseName ?? "syncore",
|
|
26
42
|
persistence,
|
|
27
|
-
...
|
|
43
|
+
...wasmUrl ? { wasmUrl } : {},
|
|
28
44
|
...options.locateFile ? { locateFile: options.locateFile } : {}
|
|
29
45
|
});
|
|
30
|
-
const
|
|
46
|
+
const storageNamespace = options.storageNamespace ?? options.databaseName ?? "syncore";
|
|
47
|
+
const storage = options.storage ?? (persistence.storageProtocol === "opfs" ? new BrowserFileStorageAdapter(persistence, storageNamespace) : new UnavailableBrowserStorageAdapter(BROWSER_STORAGE_UNAVAILABLE_REASON));
|
|
48
|
+
const runtimeCapabilities = createBrowserRuntimeCapabilities(persistence, storage, Boolean(options.storage));
|
|
31
49
|
const externalChangeSupport = createWebExternalChangeSupport({
|
|
32
50
|
databaseName: options.databaseName ?? "syncore",
|
|
33
51
|
persistence,
|
|
34
52
|
driver
|
|
35
53
|
});
|
|
36
|
-
const appName = resolveWebAppName();
|
|
54
|
+
const appName = options.appName ?? resolveWebAppName();
|
|
37
55
|
const origin = resolveWebOrigin();
|
|
38
56
|
const sessionLabel = resolveWebSessionLabel();
|
|
39
57
|
const databaseLabel = options.databaseName ?? "syncore";
|
|
40
58
|
const storageScopeId = await resolvePersistedStorageScopeId(persistence, databaseLabel);
|
|
59
|
+
const dataSourceAlias = await resolvePersistedDataSourceAlias(persistence, databaseLabel);
|
|
41
60
|
const storageIdentity = [
|
|
42
61
|
origin ?? "unknown-origin",
|
|
43
62
|
persistence.storageProtocol,
|
|
@@ -46,11 +65,13 @@ async function createWebSyncoreRuntime(options) {
|
|
|
46
65
|
].join("::");
|
|
47
66
|
const autoDevtools = options.devtools === void 0 && shouldAutoConnectDevtools() ? (() => {
|
|
48
67
|
const sinkOptions = {
|
|
49
|
-
url: resolveDefaultDevtoolsUrl(),
|
|
68
|
+
url: options.devtoolsUrl ?? resolveDefaultDevtoolsUrl(),
|
|
50
69
|
targetKind: "client",
|
|
51
70
|
storageProtocol: persistence.storageProtocol,
|
|
52
71
|
databaseLabel,
|
|
53
|
-
|
|
72
|
+
dataSourceAlias,
|
|
73
|
+
storageIdentity,
|
|
74
|
+
capabilities: createBrowserDevtoolsCapabilities(runtimeCapabilities)
|
|
54
75
|
};
|
|
55
76
|
if (appName) sinkOptions.appName = appName;
|
|
56
77
|
if (origin) sinkOptions.origin = origin;
|
|
@@ -63,7 +84,7 @@ async function createWebSyncoreRuntime(options) {
|
|
|
63
84
|
sessionLabel,
|
|
64
85
|
appName,
|
|
65
86
|
origin,
|
|
66
|
-
devtoolsUrl: options.devtools && typeof options.devtools === "object" ? void 0 : resolveDefaultDevtoolsUrl()
|
|
87
|
+
devtoolsUrl: options.devtools && typeof options.devtools === "object" ? void 0 : options.devtoolsUrl ?? resolveDefaultDevtoolsUrl()
|
|
67
88
|
});
|
|
68
89
|
const runtime = new SyncoreRuntime({
|
|
69
90
|
schema: options.schema,
|
|
@@ -75,18 +96,19 @@ async function createWebSyncoreRuntime(options) {
|
|
|
75
96
|
...externalChangeSupport.applier ? { externalChangeApplier: externalChangeSupport.applier } : {},
|
|
76
97
|
platform: options.platform ?? "browser",
|
|
77
98
|
...options.capabilities ? { capabilities: options.capabilities } : {},
|
|
99
|
+
runtimeCapabilities,
|
|
78
100
|
...resolvedDevtools ? { devtools: resolvedDevtools } : {},
|
|
79
101
|
...options.scheduler ? { scheduler: options.scheduler } : {}
|
|
80
102
|
});
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
|
|
103
|
+
if (isAttachableBrowserDevtoolsSink(resolvedDevtools)) {
|
|
104
|
+
resolvedDevtools.attachRuntime(runtime);
|
|
105
|
+
resolvedDevtools.attachCommandHandler(createDevtoolsCommandHandler({
|
|
84
106
|
driver,
|
|
85
107
|
schema: options.schema,
|
|
86
108
|
functions: options.functions,
|
|
87
109
|
admin: runtime.getAdmin()
|
|
88
110
|
}));
|
|
89
|
-
|
|
111
|
+
resolvedDevtools.attachSubscriptionHost(createDevtoolsSubscriptionHost({
|
|
90
112
|
driver,
|
|
91
113
|
schema: options.schema,
|
|
92
114
|
functions: options.functions,
|
|
@@ -95,6 +117,21 @@ async function createWebSyncoreRuntime(options) {
|
|
|
95
117
|
}
|
|
96
118
|
return runtime;
|
|
97
119
|
}
|
|
120
|
+
function isAttachableBrowserDevtoolsSink(sink) {
|
|
121
|
+
return !!sink && typeof sink.attachRuntime === "function" && typeof sink.attachCommandHandler === "function" && typeof sink.attachSubscriptionHost === "function";
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Build a {@link WebExternalChangeSupport} bundle for a given database and
|
|
125
|
+
* persistence layer.
|
|
126
|
+
*
|
|
127
|
+
* Creates a `BroadcastChannel`-based signal so that all tabs sharing the same
|
|
128
|
+
* `databaseName` are notified when a mutation commits. When `driver` is a
|
|
129
|
+
* `SqlJsDriver` (i.e. an in-memory database), an `applier` is also created so
|
|
130
|
+
* the local database can be updated from the latest on-disk snapshot.
|
|
131
|
+
*
|
|
132
|
+
* Called automatically by `createWebSyncoreRuntime`. Exposed for advanced use
|
|
133
|
+
* cases such as the Expo web adapter.
|
|
134
|
+
*/
|
|
98
135
|
function createWebExternalChangeSupport(options) {
|
|
99
136
|
const signal = new BroadcastChannelExternalChangeSignal({ channelName: createDefaultSyncChannelName(options.databaseName) });
|
|
100
137
|
const sqlDriver = options.driver instanceof SqlJsDriver ? options.driver : void 0;
|
|
@@ -111,16 +148,28 @@ function createWebExternalChangeSupport(options) {
|
|
|
111
148
|
})
|
|
112
149
|
};
|
|
113
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Build a {@link WebExternalChangeSupport} bundle for an Expo app running on
|
|
153
|
+
* the web platform.
|
|
154
|
+
*
|
|
155
|
+
* Behaves identically to {@link createWebExternalChangeSupport} but accepts
|
|
156
|
+
* the same options shape used by `createExpoSyncoreRuntime`, making it easy
|
|
157
|
+
* to share config when bootstrapping an Expo web runtime.
|
|
158
|
+
*
|
|
159
|
+
* Called internally by the Expo platform adapter. Use directly only when
|
|
160
|
+
* constructing the runtime outside of `createExpoSyncoreRuntime`.
|
|
161
|
+
*/
|
|
114
162
|
async function createExpoWebExternalChangeSupport(options) {
|
|
115
163
|
const persistence = await createWebPersistence({
|
|
116
164
|
...options.persistenceMode ? { mode: options.persistenceMode } : {},
|
|
117
165
|
...options.persistenceDatabaseName ? { indexedDbDatabaseName: options.persistenceDatabaseName } : {},
|
|
118
166
|
opfsRootDirectoryName: options.opfsRootDirectoryName ?? options.databaseName
|
|
119
167
|
});
|
|
168
|
+
const wasmUrl = options.wasmUrl ?? (options.locateFile || !isBrowserLikeRuntime() ? void 0 : await resolveDefaultWebWasmUrl());
|
|
120
169
|
const driver = await SqlJsDriver.create({
|
|
121
170
|
databaseName: options.databaseName,
|
|
122
171
|
persistence,
|
|
123
|
-
...
|
|
172
|
+
...wasmUrl ? { wasmUrl } : {},
|
|
124
173
|
...options.locateFile ? { locateFile: options.locateFile } : {}
|
|
125
174
|
});
|
|
126
175
|
return createWebExternalChangeSupport({
|
|
@@ -130,38 +179,107 @@ async function createExpoWebExternalChangeSupport(options) {
|
|
|
130
179
|
});
|
|
131
180
|
}
|
|
132
181
|
/**
|
|
133
|
-
*
|
|
182
|
+
* Start a Syncore runtime inside a browser `Worker` and wire it to the
|
|
183
|
+
* worker’s own message endpoint.
|
|
184
|
+
*
|
|
185
|
+
* This is the function you call **inside your worker file** (`syncore.worker.ts`).
|
|
186
|
+
* It creates the full runtime (SQL.js + OPFS + BroadcastChannel) in the worker
|
|
187
|
+
* context and begins listening for messages from the main-thread client.
|
|
188
|
+
*
|
|
189
|
+
* ```ts
|
|
190
|
+
* // syncore.worker.ts
|
|
191
|
+
* import { createWebWorkerRuntime } from "syncorejs/browser";
|
|
192
|
+
* import schema from "./syncore/schema";
|
|
193
|
+
* import { functions } from "./syncore/_generated/functions";
|
|
194
|
+
*
|
|
195
|
+
* void createWebWorkerRuntime({
|
|
196
|
+
* schema,
|
|
197
|
+
* functions,
|
|
198
|
+
* endpoint: self as unknown as SyncoreWorkerMessageEndpoint,
|
|
199
|
+
* });
|
|
200
|
+
* ```
|
|
201
|
+
*
|
|
202
|
+
* On the main thread, connect with `createManagedWebWorkerClient()` or
|
|
203
|
+
* `SyncoreNextProvider` (Next.js).
|
|
134
204
|
*/
|
|
135
205
|
function createWebWorkerRuntime(options) {
|
|
136
206
|
return attachWebWorkerRuntime({
|
|
137
207
|
endpoint: options.endpoint,
|
|
138
|
-
createRuntime: () => createWebSyncoreRuntime(
|
|
208
|
+
createRuntime: () => createWebSyncoreRuntime({
|
|
209
|
+
...options,
|
|
210
|
+
platform: options.platform ?? "browser-worker"
|
|
211
|
+
})
|
|
139
212
|
});
|
|
140
213
|
}
|
|
141
214
|
/**
|
|
142
|
-
*
|
|
215
|
+
* Alias of {@link createWebWorkerRuntime} for the `syncorejs/browser` surface.
|
|
216
|
+
* @see createWebWorkerRuntime
|
|
143
217
|
*/
|
|
144
218
|
function createBrowserWorkerRuntime(options) {
|
|
145
219
|
return createWebWorkerRuntime(options);
|
|
146
220
|
}
|
|
147
221
|
/**
|
|
148
|
-
* Create a client
|
|
222
|
+
* Create a same-process Syncore client from a started browser runtime.
|
|
223
|
+
*
|
|
224
|
+
* Use this when the runtime lives in the same context as the client (e.g.
|
|
225
|
+
* main-thread runtime in an Electron renderer or a test harness). For
|
|
226
|
+
* worker-based setups use `createManagedWebWorkerClient()` instead, which
|
|
227
|
+
* communicates with the worker over `postMessage`.
|
|
228
|
+
*
|
|
229
|
+
* ```ts
|
|
230
|
+
* const runtime = await createWebSyncoreRuntime({ schema, functions });
|
|
231
|
+
* await runtime.start();
|
|
232
|
+
* const client = createWebSyncoreClient(runtime);
|
|
233
|
+
* ```
|
|
149
234
|
*/
|
|
150
235
|
function createWebSyncoreClient(runtime) {
|
|
151
236
|
return runtime.createClient();
|
|
152
237
|
}
|
|
153
238
|
/**
|
|
154
|
-
*
|
|
239
|
+
* Alias of {@link createWebSyncoreRuntime} for the `syncorejs/browser` surface.
|
|
240
|
+
* @see createWebSyncoreRuntime
|
|
155
241
|
*/
|
|
156
242
|
function createBrowserSyncoreRuntime(options) {
|
|
157
243
|
return createWebSyncoreRuntime(options);
|
|
158
244
|
}
|
|
159
245
|
/**
|
|
160
|
-
*
|
|
246
|
+
* Alias of {@link createWebSyncoreClient} for the `syncorejs/browser` surface.
|
|
247
|
+
* @see createWebSyncoreClient
|
|
161
248
|
*/
|
|
162
249
|
function createBrowserSyncoreClient(runtime) {
|
|
163
250
|
return createWebSyncoreClient(runtime);
|
|
164
251
|
}
|
|
252
|
+
async function resolveDefaultWebWasmUrl() {
|
|
253
|
+
try {
|
|
254
|
+
return (await import("./web-sqljs-wasm.js")).resolveDefaultWebSqlJsWasmUrl();
|
|
255
|
+
} catch (error) {
|
|
256
|
+
if (!isBrowserLikeRuntime()) return;
|
|
257
|
+
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 });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function isBrowserLikeRuntime() {
|
|
261
|
+
return typeof window !== "undefined" || globalThis.WorkerGlobalScope !== void 0;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Create a WebSocket-based devtools sink that connects to the Syncore devtools
|
|
265
|
+
* server and forwards runtime events in real time.
|
|
266
|
+
*
|
|
267
|
+
* The sink auto-reconnects if the connection drops (e.g. while the devtools
|
|
268
|
+
* dashboard is restarting) and buffers events that arrive before the socket is
|
|
269
|
+
* open.
|
|
270
|
+
*
|
|
271
|
+
* In most cases you do not need to call this directly — `createWebSyncoreRuntime`
|
|
272
|
+
* creates and attaches the sink automatically when `devtools` is omitted and the
|
|
273
|
+
* page is served from a local/private hostname.
|
|
274
|
+
*
|
|
275
|
+
* ```ts
|
|
276
|
+
* const sink = createBrowserWebSocketDevtoolsSink({
|
|
277
|
+
* url: "ws://127.0.0.1:4311",
|
|
278
|
+
* appName: "My App",
|
|
279
|
+
* });
|
|
280
|
+
* const runtime = await createWebSyncoreRuntime({ schema, functions, devtools: sink });
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
165
283
|
function createBrowserWebSocketDevtoolsSink(options) {
|
|
166
284
|
let socket;
|
|
167
285
|
let disposed = false;
|
|
@@ -188,7 +306,9 @@ function createBrowserWebSocketDevtoolsSink(options) {
|
|
|
188
306
|
...options.targetKind ? { targetKind: options.targetKind } : {},
|
|
189
307
|
...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
|
|
190
308
|
...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
|
|
191
|
-
...options.
|
|
309
|
+
...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
|
|
310
|
+
...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
|
|
311
|
+
capabilities: options.capabilities ?? createBrowserDevtoolsCapabilities()
|
|
192
312
|
});
|
|
193
313
|
flushPendingMessages();
|
|
194
314
|
};
|
|
@@ -279,7 +399,9 @@ function createBrowserWebSocketDevtoolsSink(options) {
|
|
|
279
399
|
...options.targetKind ? { targetKind: options.targetKind } : {},
|
|
280
400
|
...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
|
|
281
401
|
...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
|
|
282
|
-
...options.
|
|
402
|
+
...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
|
|
403
|
+
...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
|
|
404
|
+
capabilities: options.capabilities ?? createBrowserDevtoolsCapabilities()
|
|
283
405
|
});
|
|
284
406
|
}
|
|
285
407
|
send({
|
|
@@ -313,7 +435,51 @@ function withRuntimeSummaryMeta(summary, options) {
|
|
|
313
435
|
...options.targetKind ? { targetKind: options.targetKind } : {},
|
|
314
436
|
...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
|
|
315
437
|
...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
|
|
316
|
-
...options.
|
|
438
|
+
...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
|
|
439
|
+
...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
|
|
440
|
+
capabilities: options.capabilities ?? createBrowserDevtoolsCapabilities()
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function createBrowserRuntimeCapabilities(persistence, storage, hasExplicitStorage) {
|
|
444
|
+
if (!hasExplicitStorage && persistence.storageProtocol !== "opfs") return { storage: {
|
|
445
|
+
available: false,
|
|
446
|
+
reason: BROWSER_STORAGE_UNAVAILABLE_REASON,
|
|
447
|
+
protocol: persistence.storageProtocol,
|
|
448
|
+
supportsRange: false
|
|
449
|
+
} };
|
|
450
|
+
return { storage: {
|
|
451
|
+
available: true,
|
|
452
|
+
protocol: hasExplicitStorage ? "custom" : persistence.storageProtocol,
|
|
453
|
+
...storage.supportsRange ? { supportsRange: storage.supportsRange() !== false } : {}
|
|
454
|
+
} };
|
|
455
|
+
}
|
|
456
|
+
function createBrowserDevtoolsCapabilities(runtimeCapabilities) {
|
|
457
|
+
const storageCapability = runtimeCapabilities?.storage;
|
|
458
|
+
const storageAvailable = storageCapability?.available !== false;
|
|
459
|
+
return {
|
|
460
|
+
sql: {
|
|
461
|
+
read: false,
|
|
462
|
+
write: false,
|
|
463
|
+
live: false,
|
|
464
|
+
reason: "SQL Console is not available for browser runtimes."
|
|
465
|
+
},
|
|
466
|
+
data: {
|
|
467
|
+
browse: true,
|
|
468
|
+
mutate: true,
|
|
469
|
+
importExport: true
|
|
470
|
+
},
|
|
471
|
+
storage: {
|
|
472
|
+
browse: storageAvailable,
|
|
473
|
+
download: storageAvailable,
|
|
474
|
+
readRange: storageCapability?.supportsRange === true,
|
|
475
|
+
delete: storageAvailable,
|
|
476
|
+
maxPreviewBytes: 8e4,
|
|
477
|
+
...!storageAvailable && storageCapability?.reason ? { reason: storageCapability.reason } : {}
|
|
478
|
+
},
|
|
479
|
+
scheduler: {
|
|
480
|
+
read: true,
|
|
481
|
+
edit: true
|
|
482
|
+
}
|
|
317
483
|
};
|
|
318
484
|
}
|
|
319
485
|
function shouldAutoConnectDevtools() {
|
|
@@ -431,6 +597,17 @@ async function resolvePersistedStorageScopeId(persistence, databaseLabel) {
|
|
|
431
597
|
await persistence.putFile(DEVTOOLS_META_NAMESPACE, id, new TextEncoder().encode(nextValue), "text/plain");
|
|
432
598
|
return nextValue;
|
|
433
599
|
}
|
|
600
|
+
async function resolvePersistedDataSourceAlias(persistence, databaseLabel) {
|
|
601
|
+
const id = `${DATA_SOURCE_ALIAS_PREFIX}:${databaseLabel}`;
|
|
602
|
+
const existing = await persistence.getFile(DEVTOOLS_META_NAMESPACE, id);
|
|
603
|
+
if (existing) {
|
|
604
|
+
const value = new TextDecoder().decode(existing.bytes).trim();
|
|
605
|
+
if (value.length > 0) return value;
|
|
606
|
+
}
|
|
607
|
+
const nextValue = generateUniqueSessionName();
|
|
608
|
+
await persistence.putFile(DEVTOOLS_META_NAMESPACE, id, new TextEncoder().encode(nextValue), "text/plain");
|
|
609
|
+
return nextValue;
|
|
610
|
+
}
|
|
434
611
|
function announceBrowserSession(options) {
|
|
435
612
|
if (!options.enabled || !options.sessionLabel) return;
|
|
436
613
|
const announcedSessions = getAnnouncedBrowserSessions();
|
|
@@ -555,16 +732,33 @@ const SESSION_NOUNS = [
|
|
|
555
732
|
"Thunder",
|
|
556
733
|
"Drift"
|
|
557
734
|
];
|
|
735
|
+
const BROWSER_STORAGE_UNAVAILABLE_REASON = "Browser file storage requires OPFS. IndexedDB is used for data only.";
|
|
558
736
|
function generateUniqueSessionName() {
|
|
559
737
|
return `${SESSION_ADJECTIVES[Math.floor(Math.random() * SESSION_ADJECTIVES.length)]} ${SESSION_NOUNS[Math.floor(Math.random() * SESSION_NOUNS.length)]}`;
|
|
560
738
|
}
|
|
561
739
|
/**
|
|
562
|
-
* Browser file/blob storage
|
|
740
|
+
* Browser file/blob storage adapter backed by `SyncoreWebPersistence`.
|
|
741
|
+
*
|
|
742
|
+
* Stores binary blobs (images, documents, etc.) in OPFS alongside the SQLite
|
|
743
|
+
* database. Pass an instance to
|
|
744
|
+
* `CreateWebRuntimeOptions.storage` to enable Syncore's Storage API
|
|
745
|
+
* (`ctx.storage.put`, `ctx.storage.get`, etc.) in browser functions.
|
|
746
|
+
*
|
|
747
|
+
* ```ts
|
|
748
|
+
* const runtime = await createWebSyncoreRuntime({
|
|
749
|
+
* schema,
|
|
750
|
+
* functions,
|
|
751
|
+
* storage: new BrowserFileStorageAdapter(persistence, "files"),
|
|
752
|
+
* });
|
|
753
|
+
* ```
|
|
563
754
|
*/
|
|
564
755
|
var BrowserFileStorageAdapter = class {
|
|
756
|
+
persistence;
|
|
757
|
+
namespace;
|
|
565
758
|
constructor(persistence, namespace) {
|
|
566
759
|
this.persistence = persistence;
|
|
567
760
|
this.namespace = namespace;
|
|
761
|
+
if (persistence.storageProtocol !== "opfs") throw new Error(BROWSER_STORAGE_UNAVAILABLE_REASON);
|
|
568
762
|
}
|
|
569
763
|
async put(id, input) {
|
|
570
764
|
const bytes = normalizeBinary(input.data);
|
|
@@ -589,11 +783,18 @@ var BrowserFileStorageAdapter = class {
|
|
|
589
783
|
async read(id) {
|
|
590
784
|
return (await this.persistence.getFile(this.namespace, id))?.bytes ?? null;
|
|
591
785
|
}
|
|
786
|
+
supportsRange() {
|
|
787
|
+
return Boolean(this.persistence.getFileRange);
|
|
788
|
+
}
|
|
789
|
+
async readRange(id, offset, length) {
|
|
790
|
+
if (!this.persistence.getFileRange) return null;
|
|
791
|
+
return (await this.persistence.getFileRange(this.namespace, id, offset, length))?.bytes ?? null;
|
|
792
|
+
}
|
|
592
793
|
async delete(id) {
|
|
593
794
|
await this.persistence.deleteFile(this.namespace, id);
|
|
594
795
|
}
|
|
595
796
|
async list() {
|
|
596
|
-
return (await this.persistence.listFiles(this.namespace)).map((file) => ({
|
|
797
|
+
return (this.persistence.listFileMetadata ? await this.persistence.listFileMetadata(this.namespace) : await this.persistence.listFiles(this.namespace)).map((file) => ({
|
|
597
798
|
id: file.id,
|
|
598
799
|
path: `${this.persistence.storageProtocol}://${this.namespace}/${file.id}`,
|
|
599
800
|
size: file.size,
|
|
@@ -601,6 +802,27 @@ var BrowserFileStorageAdapter = class {
|
|
|
601
802
|
}));
|
|
602
803
|
}
|
|
603
804
|
};
|
|
805
|
+
var UnavailableBrowserStorageAdapter = class {
|
|
806
|
+
reason;
|
|
807
|
+
constructor(reason) {
|
|
808
|
+
this.reason = reason;
|
|
809
|
+
}
|
|
810
|
+
async put() {
|
|
811
|
+
throw new Error(this.reason);
|
|
812
|
+
}
|
|
813
|
+
async get() {
|
|
814
|
+
throw new Error(this.reason);
|
|
815
|
+
}
|
|
816
|
+
async read() {
|
|
817
|
+
throw new Error(this.reason);
|
|
818
|
+
}
|
|
819
|
+
supportsRange() {
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
822
|
+
async delete() {
|
|
823
|
+
throw new Error(this.reason);
|
|
824
|
+
}
|
|
825
|
+
};
|
|
604
826
|
function normalizeBinary(data) {
|
|
605
827
|
if (typeof data === "string") return new TextEncoder().encode(data);
|
|
606
828
|
if (data instanceof Uint8Array) return data;
|