Run the desktop's model layer in the browser

The browser host now stores data through yaak-models compiled to wasm — the
same queries, migrations, cascade rules, duplicate naming and first-run
bootstrap the desktop and CLI use — instead of a TypeScript port of them.

- crates/yaak-web: the wasm crate. boot() registers an IndexedDB-backed VFS
  and calls init_standalone; rpc(cmd, payload, label) answers the models_*
  commands via ClientDb and returns the model_writes it caused; blob get/put
  through blob_manager. Built like yaak-templates (pkg/ committed); the
  build script keeps pkg/ and says so when no wasm-capable clang is present,
  so a desktop bootstrap never depends on one.
- models_ops moves from crates/yaak into yaak-models so the wasm crate can
  use it without the send engine.
- The database lives in a SharedWorker (packages/platform/src/web/worker.ts):
  one process holds the data and pushes writes to every tab, as on the
  desktop. Where SharedWorker is missing or its script cannot be fetched, a
  dedicated worker guarded by a Web Lock takes over and a second tab is told
  so. The worker imports the wasm lazily so a tab's connect is answered
  instantly; the tab reconnects if it isn't.
- packages/platform/src/web loses models.ts, schema.ts, db.ts and the
  BroadcastChannel; commands.ts forwards model commands to the worker and
  keeps the fixed answers and refusals.

Verified in Chrome, dev and production builds: bootstrap, CRUD across every
model type, serde defaults, engine-format ids, Rust copy naming, folder
cascade with per-descendant events, single-event workspace delete, reload
persistence, two tabs coherent, Send declined with a toast, 8/8 reloads
rendering in ~100 ms.
This commit is contained in:
Gregory Schier
2026-08-15 15:48:49 -07:00
parent 32e92d484b
commit 0a7a9f7a2b
35 changed files with 3270 additions and 24 deletions
+23 -1
View File
@@ -59,6 +59,7 @@
"crates-tauri/yaak-fonts",
"crates-tauri/yaak-license",
"crates-tauri/yaak-mac-window",
"crates/common/yaak-rpc-schema",
"crates/yaak-crypto",
"crates/yaak-git",
"crates/yaak-models",
@@ -66,6 +67,7 @@
"crates/yaak-sse",
"crates/yaak-sync",
"crates/yaak-templates",
"crates/yaak-web",
"crates/yaak-ws",
"crates-proxy/yaak-proxy-lib",
"apps/yaak-client",
@@ -290,6 +292,10 @@
"name": "@yaakapp-internal/mac-window",
"version": "1.0.0"
},
"crates/common/yaak-rpc-schema": {
"name": "@yaakapp-internal/rpc-schema",
"version": "1.0.0"
},
"crates/yaak-crypto": {
"name": "@yaakapp-internal/crypto",
"version": "1.0.0"
@@ -324,6 +330,13 @@
"rimraf": "^6.1.2"
}
},
"crates/yaak-web": {
"name": "@yaakapp-internal/web",
"version": "1.0.0",
"devDependencies": {
"rimraf": "^6.1.2"
}
},
"crates/yaak-ws": {
"name": "@yaakapp-internal/ws",
"version": "1.0.0"
@@ -5753,6 +5766,10 @@
"resolved": "crates-proxy/yaak-proxy-lib",
"link": true
},
"node_modules/@yaakapp-internal/rpc-schema": {
"resolved": "crates/common/yaak-rpc-schema",
"link": true
},
"node_modules/@yaakapp-internal/sse": {
"resolved": "crates/yaak-sse",
"link": true
@@ -5785,6 +5802,10 @@
"resolved": "packages/ui",
"link": true
},
"node_modules/@yaakapp-internal/web": {
"resolved": "crates/yaak-web",
"link": true
},
"node_modules/@yaakapp-internal/ws": {
"resolved": "crates/yaak-ws",
"link": true
@@ -17189,7 +17210,8 @@
"@tauri-apps/plugin-dialog": "^2.7.1",
"@tauri-apps/plugin-fs": "^2.5.1",
"@tauri-apps/plugin-opener": "^2.5.4",
"@tauri-apps/plugin-os": "^2.3.2"
"@tauri-apps/plugin-os": "^2.3.2",
"@yaakapp-internal/rpc-schema": "^1.0.0"
}
},
"packages/plugin-runtime": {