# task--db-worker-nodejs-compatible ## Goal Make `frontend.worker.db-worker` and its dependencies run in both browser and Node.js. Add a Node.js daemon that can be started from the command line and exposes HTTP APIs to the same worker capabilities. ## Scope - Primary target: `src/main/frontend/worker/db_worker.cljs`. - All dependencies used by db-worker: `src/main/frontend/worker/**`, `src/main/frontend/worker_common/**`, and any browser-only utilities used by those namespaces. - Callers: `src/main/frontend/persist_db/browser.cljs`, `src/main/frontend/handler/worker.cljs`, and any callers that assume a WebWorker or Comlink transport. ## Refactor Items (Concrete Work List) 1. Split worker core logic from runtime-specific host APIs. - Create a core module (e.g. `frontend.worker.db-core`) that contains thread-api functions and business logic. - Move all direct uses of `js/self`, `js/location`, `js/navigator`, `importScripts`, `BroadcastChannel`, and `navigator.locks` out of core. 2. Add a platform adapter layer with a consistent interface for browser and Node.js. - Define `frontend.worker.platform` interface: storage, kv-store, broadcast, websocket, crypto, timers, and env flags. - Implement `frontend.worker.platform.browser` using OPFS, IDB, BroadcastChannel, navigator.locks, WebSocket, and `globalThis`. - Implement `frontend.worker.platform.node` using `fs/promises`, `path`, `crypto`, and `ws`. 3. Abstract sqlite storage and VFS specifics. - Browser: keep OPFS SAH pool implementation. - Node: use file-backed sqlite storage via Node built-in `node:sqlite` (no OPFS, no sqlite-wasm). - Route db path resolution through the platform adapter (data dir, per-repo paths). 4. Replace `importScripts` bootstrap with an explicit init entrypoint. - Browser build still uses `:web-worker`, but entrypoint should call `init!` with a browser platform adapter. - Node build should call the same `init!` with a Node adapter. 5. Normalize RPC and transport. - Define a transport-agnostic RPC layer that accepts a method name and args (transit string or direct args). - Keep Comlink for browser worker transport. - Add HTTP transport for Node (see daemon section). 6. Update shared-service for non-browser environments. - Provide a "single-client" fallback for Node; no multi-client coordination is needed. 7. Replace browser-only storage in RTC and crypto modules. - `frontend.worker.rtc.crypt` uses IDB/OPFS and should switch to the platform kv-store and file API. - Any other worker modules using `js/navigator` or OPFS should be routed through the platform adapter. 8. Replace direct `js/WebSocket` usage with a platform websocket factory. - Browser: `js/WebSocket`. - Node: `ws` client with the same interface shape. 9. Update caller-side initialization. - Keep browser `frontend.persist-db.browser` using WebWorker + Comlink. 10. Build config changes. - Add a Node build target in `shadow-cljs.edn` for db-worker (e.g. `:db-worker-node`). - Ensure shared code compiles for `:node-script` or `:node-library` with the correct externs. - Use Node built-in `node:sqlite` and keep Node runtime on `>=22.20.0`. 11. Tests and fixtures. - Add unit tests for platform adapters and storage abstraction. - Add a minimal integration test that starts the Node daemon and exercises a small RPC call. ## Node.js sqlite Implementation (node:sqlite) Node runtime must not use OPFS or sqlite-wasm. Instead, use Node built-in `node:sqlite` as the direct file-backed sqlite engine. ### Concrete Refactor Items (File + Function + Summary) - `src/main/frontend/worker/db_core.cljs` (`init-sqlite-module!`, ` `200 OK` when process is alive. - `GET /readyz` -> `200 OK` only after sqlite init completes. - `POST /v1/invoke` - Request JSON: - `method`: string, e.g. `"thread-api/create-or-open-db"` - `directPass`: boolean - `argsTransit`: string (transit-encoded args) OR `args`: array for direct pass - Response JSON: - `ok`: boolean - `resultTransit`: string (transit-encoded result) when `directPass=false` - `result`: any (when `directPass=true`) - `error`: error object if failed Event delivery options: - `GET /v1/events` using SSE for worker -> client events - Event payload should mirror current `postMessage` payloads in `frontend.handler.worker`. - Each event should be tagged with `type` and `payload`. - Alternatively, provide `WS /v1/events` with the same payload format. ### Security - Bind to localhost by default. ## Notes on Compatibility Gaps - OPFS and IndexedDB do not exist in Node; file-backed storage and a Node KV store are required. - `BroadcastChannel` and `navigator.locks` are browser-only; Node should use a simpler single-client mode. - `Comlink` is browser-optimized; the Node daemon should use HTTP, not Comlink. - sqlite-wasm must remain browser-only; Node uses built-in `node:sqlite` directly. - only db-graph supported in Node db-worker ## Success Criteria - Browser build continues to work with WebWorker + Comlink. - Node daemon can start from CLI, open a repo, and respond to at least: - `list-db` - `create-or-open-db` - `q` - `transact` - A minimal client can call the daemon and receive event notifications.