Initial import of LogDarioSeq baseline

Establishes version control for the personal Logseq DB fork before
starting the server-client architecture migration and domain features
described in docs/agent-guide and the approved implementation plan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 15:32:15 +02:00
commit 40631362b3
2016 changed files with 543898 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
# DB Sync Node.js Adapter Implementation Plan
Goal: Build a Node.js server adapter for DB sync so users can self-host without Cloudflare dependencies.
Architecture: Reuse the existing db-sync core logic and route handlers while introducing a platform abstraction layer that swaps Cloudflare APIs for Node.js equivalents.
Architecture: Provide a new Node.js entrypoint that wires HTTP and WebSocket handling to the shared handlers and pluggable storage and auth backends.
Tech Stack: ClojureScript, shadow-cljs, Node.js LTS, standard Node HTTP and WebSocket libraries, existing db-sync ClojureScript modules.
Related: Builds on the engineering context consolidated in docs/agent-guide/implemented/architecture/2026-08-24-logseq-runtime-and-engineering-guide.md and docs/adr/0001-nodejs-db-sync-server-adapter.md.
## Problem statement
The current DB sync server implementation assumes a Cloudflare Worker runtime and related APIs.
That assumption prevents users from running the sync server on standard Node.js infrastructure.
We need a portable adapter that preserves the DB sync protocol and behavior while replacing Cloudflare-specific primitives.
## Testing Plan
I will add an integration test that spins up the Node.js adapter, runs a health check, and performs a minimal pull and tx/batch round-trip over HTTP to confirm protocol compatibility.
I will add an integration test that opens a WebSocket connection, performs hello and pull, and validates changed notifications on tx/batch.
I will add a unit test that exercises the platform abstraction layer to ensure request and response coercion behave the same for both Node and worker inputs.
I will add a unit test that validates storage and auth adapter selection from configuration, including error handling for missing drivers.
NOTE: I will write all tests before I add any implementation behavior.
## Scope
The Node.js adapter will implement the existing HTTP and WebSocket endpoints summarized in docs/agent-guide/implemented/architecture/2026-08-24-logseq-runtime-and-engineering-guide.md; current route and protocol source remains authoritative.
The adapter will run the same handler logic currently used by the Cloudflare worker.
The adapter will support pluggable storage and auth providers to match the existing worker behavior.
## Non-goals
This plan does not add new DB sync protocol features.
This plan does not migrate existing cloud hosting or change client behavior.
This plan does not redesign storage schemas or transaction ordering.
## Architecture Overview
The adapter will introduce a platform boundary and a Node runtime entrypoint that binds HTTP and WS requests to the existing worker handlers.
The platform boundary will normalize request, response, and WebSocket interfaces so the core logic remains unchanged.
The Node entrypoint will be responsible only for server lifecycle and wiring adapters.
+--------------------+ HTTP/WS +------------------------+ storage/auth +------------------+
| Logseq Client Apps | <--------------> | Node.js DB Sync Adapter | <------------------> | Storage Backends |
+--------------------+ +------------------------+ +------------------+
| Shared db-sync handlers |
+------------------------+
## Implementation Plan
1. Read docs/agent-guide/implemented/architecture/2026-08-24-logseq-runtime-and-engineering-guide.md and list the Cloudflare-specific APIs used by the worker in deps/db-sync/src/logseq/db_sync/worker/.
2. Create a platform abstraction namespace in deps/db-sync/src/logseq/db_sync/platform/core.cljs that defines the minimal request, response, and WebSocket operations used by handlers.
3. Add a Cloudflare platform adapter in deps/db-sync/src/logseq/db_sync/platform/cloudflare.cljs that wraps the current Worker Request, Response, and WebSocket types.
4. Add a Node platform adapter in deps/db-sync/src/logseq/db_sync/platform/node.cljs that wraps Node HTTP requests, responses, and WebSocket connections.
5. Update deps/db-sync/src/logseq/db_sync/worker/dispatch.cljs and deps/db-sync/src/logseq/db_sync/worker/http.cljs to depend on the platform abstraction instead of direct Worker APIs.
6. Add a Node server entrypoint in deps/db-sync/src/logseq/db_sync/node/entry.cljs that sets up HTTP routes, WS upgrade handling, and lifecycle start/stop.
7. Add a Node routing layer in deps/db-sync/src/logseq/db_sync/node/routes.cljs that maps incoming requests to the existing worker route handlers.
8. Introduce configuration parsing in deps/db-sync/src/logseq/db_sync/node/config.cljs to select storage and auth drivers via environment variables.
9. Add Node adapter implementations for storage and assets in deps/db-sync/src/logseq/db_sync/node/storage.cljs and deps/db-sync/src/logseq/db_sync/node/assets.cljs that map to the existing storage interfaces.
10. Add a new shadow-cljs build target in deps/db-sync/shadow-cljs.edn for the Node adapter output.
11. Add build and run scripts to deps/db-sync/package.json for the Node adapter, including a dev watch command.
12. Update the active db-sync documentation with the new local dev and test commands for the Node adapter.
13. Add a new self-hosting section to docs/develop-logseq.md with minimal steps to run the Node adapter.
14. Add integration tests under deps/db-sync/test/logseq/db_sync/node_adapter_test.cljs that launch the Node adapter and exercise HTTP and WS paths.
15. Add unit tests under deps/db-sync/test/logseq/db_sync/platform_test.cljs that cover request normalization and error propagation.
16. Run the tests using the commands listed in the Verification section and confirm they fail before implementation and pass after implementation.
## Configuration Matrix
Use the following environment variables for the Node adapter configuration.
| Variable | Purpose | Example |
| --- | --- | --- |
| DB_SYNC_PORT | HTTP server port | 8080 |
| DB_SYNC_BASE_URL | External base URL for asset links | https://sync.example.com |
| DB_SYNC_STORAGE_DRIVER | Storage backend selection | sqlite |
| DB_SYNC_ASSETS_DRIVER | Asset storage backend selection | filesystem |
| DB_SYNC_LOG_LEVEL | Log verbosity | info |
| COGNITO_ISSUER | Cognito issuer URL | https://cognito-idp.us-east-2.amazonaws.com/us-east-2_kAqZcxIeM |
| COGNITO_CLIENT_ID | Cognito app client id | 1qi1uijg8b6ra70nejvbptis0q |
| COGNITO_JWKS_URL | Cognito JWKS URL | https://cognito-idp.us-east-2.amazonaws.com/us-east-2_kAqZcxIeM/.well-known/jwks.json |
## Verification
Run the server-side test suite.
```bash
bb dev:db-sync-test
```
Expected result is a zero exit code and no failing tests.
Run the Node adapter integration tests.
```bash
cd deps/db-sync
pnpm test:node-adapter
```
Expected result is a zero exit code and logs that the Node adapter started and all tests passed.
## Edge Cases
Unauthorized requests should return the same 401 or 403 responses as the Cloudflare worker.
Invalid request payloads must produce the same error responses as the worker routes.
WebSocket message validation must reject unknown types with the same error shape.
Snapshot upload should preserve content-encoding and reject missing bodies consistently.
Asset uploads must enforce size limits and return the same error codes as the worker.
## Testing Details
I will add integration tests that launch the Node adapter and use HTTP and WebSocket calls to validate real protocol behavior rather than mocking handlers.
I will add unit tests for the platform adapters to ensure coercion and error handling match existing worker semantics.
These tests validate observable behavior and response shapes instead of internal data structures.
## Implementation Details
- Introduce a platform interface to normalize request, response, and WebSocket operations.
- Keep all protocol validation and handler logic inside deps/db-sync/src/logseq/db_sync/worker to avoid divergence.
- Make the Node entrypoint responsible only for wiring and lifecycle.
- Add configuration parsing and driver selection in Node-specific namespaces.
- Add a new shadow-cljs build target for the Node adapter output.
- Add npm scripts for building and testing the Node adapter.
- Update docs to include self-hosting and local dev guidance.
## Question
Where should the AGENTS.workflow.md guidance live for plan documents in this repo.
Do we want to support the same storage backends as Cloudflare on day one or limit to a single local driver for the first release.
Should the Node adapter include optional CORS configuration or match the current worker defaults exactly.
---

View File

@@ -0,0 +1,76 @@
# ADR: Reactions via Properties
## Status
- Proposed
## Context
- Users want lightweight reactions (e.g., 👍 ❤️) on blocks and pages.
- Reactions must be stored in the graph so they sync, can be queried, and work across devices.
- The system already uses properties to attach structured metadata to blocks/pages.
- We need to show who reacted and which emoji they used.
## Decision
- Store reactions as separate entities linked to the reacted block/page.
- Each reaction entity records:
- Emoji id (from Logseq’s supported `emojis-data` set).
- Optional `:logseq.property/created-by-ref` pointing to the reacting user (absent for anonymous graphs).
- Reacted block/page reference.
- `:block/created-at` timestamp for the reaction entity.
- No `:logseq.property/reactions` collection property is required; use the reverse ref
`(:logseq.property.reaction/_target node-entity)` to fetch reactions for a node.
- Keep the property name namespaced in logseq.db.frontend.property/built-in-properties.
### Proposed entity shape
```
{:db/id ...
:logseq.property.reaction/emoji-id "smile"
:logseq.property/created-by-ref <user-db-id> ;; omitted for anonymous graphs
:logseq.property.reaction/target <target-db-id> ;; block/page db id
:block/created-at 1710000000000}
```
### Read/write rules
- Toggling a reaction adds/removes a reaction entity for the current emoji/user.
- If anonymous, only one reaction per emoji per block/page (no user id).
- Reactions are derived via reverse reference lookup; no dedicated collection
property is stored on the node.
### Example queries
```clj
;; Given a block/page entity `node-entity`, fetch all reactions.
(:logseq.property.reaction/_target node-entity)
;; Filter reactions by emoji id.
(filter #(= "smile" (:logseq.property.reaction/emoji-id %))
(:logseq.property.reaction/_target node-entity))
;; Count reactions per emoji id.
(->> (:logseq.property.reaction/_target node-entity)
(map :logseq.property.reaction/emoji-id)
(frequencies))
;; Filter reactions by user id (when present).
(filter #(= user-db-id (:logseq.property/created-by-ref %))
(:logseq.property.reaction/_target node-entity))
```
## Consequences
- Reactions sync naturally as part of DB transactions and are queryable.
- Data model supports “who reacted” and multiple users per emoji without map merging.
- Adds more entities; need efficient queries and indexes.
## Alternatives Considered
- **Dedicated table/attribute per emoji**: complicates schema, increases complexity.
- **Property map (emoji -> users)**: smaller but harder to resolve conflicts and query per user.
- **Inline text markers**: not structured, hard to query and sync.
## Open Questions
- Which user identifier should be stored as `:logseq.property/created-by-ref`?
Each user has a page in the graph
- How to handle anonymous/local graphs (no user identity)?
Record reactions, for anonymous graphs, don't store :logseq.property/created-by-ref
## Notes for Implementation
- Add emoji entity schema to DB validation.
- UI should show a summary (emoji + count) and a hover/popover with user list.
- User can toggle reaction.