mirror of
https://github.com/logseq/logseq.git
synced 2026-05-18 01:42:19 +00:00
040-hide-db-prefix-in-user-visible-graph-names.md
This commit is contained in:
4
deps/cli/src/logseq/cli/commands/graph.cljs
vendored
4
deps/cli/src/logseq/cli/commands/graph.cljs
vendored
@@ -38,6 +38,6 @@
|
||||
(defn list-graphs
|
||||
[]
|
||||
(let [db-graphs (->> (cli-common-graph/get-db-based-graphs)
|
||||
(map #(string/replace-first % common-config/db-version-prefix ""))
|
||||
(map common-config/strip-leading-db-version-prefix)
|
||||
sort)]
|
||||
(println (string/join "\n" db-graphs))))
|
||||
(println (string/join "\n" db-graphs))))
|
||||
|
||||
6
deps/cli/src/logseq/cli/common/graph.cljs
vendored
6
deps/cli/src/logseq/cli/common/graph.cljs
vendored
@@ -27,5 +27,7 @@
|
||||
(remove (fn [s] (= s common-config/unlinked-graphs-dir)))
|
||||
(map graph-name->path)
|
||||
(keep (fn [s]
|
||||
(when-not (string/starts-with? s common-config/file-version-prefix)
|
||||
(str common-config/db-version-prefix s)))))))
|
||||
(when (and (string? s)
|
||||
(not (string/starts-with? s common-config/file-version-prefix)))
|
||||
(common-config/canonicalize-db-version-repo s))))
|
||||
distinct)))
|
||||
|
||||
19
deps/common/src/logseq/common/config.cljs
vendored
19
deps/common/src/logseq/common/config.cljs
vendored
@@ -33,6 +33,25 @@
|
||||
(defonce db-version-prefix "logseq_db_")
|
||||
(defonce file-version-prefix "logseq_local_")
|
||||
|
||||
(defn strip-leading-db-version-prefix
|
||||
"Strip exactly one leading db prefix for user-facing display values."
|
||||
[s]
|
||||
(if (and (string? s)
|
||||
(string/starts-with? s db-version-prefix))
|
||||
(subs s (count db-version-prefix))
|
||||
s))
|
||||
|
||||
(defn canonicalize-db-version-repo
|
||||
"Normalize any repo/graph name to exactly one leading db prefix."
|
||||
[s]
|
||||
(when (seq s)
|
||||
(let [s (str s)
|
||||
stripped (loop [name s]
|
||||
(if (string/starts-with? name db-version-prefix)
|
||||
(recur (subs name (count db-version-prefix)))
|
||||
name))]
|
||||
(str db-version-prefix stripped))))
|
||||
|
||||
(defonce local-assets-dir "assets")
|
||||
(defonce unlinked-graphs-dir "Unlinked graphs")
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
# Hide Db Prefix In User Visible Graph Names Implementation Plan
|
||||
|
||||
Goal: Ensure user-visible graph names strip exactly one leading `logseq_db_` prefix while preventing new multi-prefix repos from being created.
|
||||
|
||||
Architecture: Keep display normalization as single-pass prefix stripping for web, Electron, and CLI user-facing fields.
|
||||
|
||||
Architecture: Add shared canonicalization at ingestion and graph-discovery boundaries so internal repo identifiers are normalized to exactly one leading prefix before persistence and routing.
|
||||
|
||||
Architecture: Follow `@test-driven-development` with failing tests first across frontend, Electron boundary code, RTC ingestion, and CLI paths.
|
||||
|
||||
Tech Stack: ClojureScript, Rum, Electron IPC, db-worker-node runtime, Logseq CLI formatting pipeline, Babashka tests.
|
||||
|
||||
Related: Relates to `docs/agent-guide/033-desktop-db-worker-node-backend.md`.
|
||||
|
||||
Related: Builds on `docs/agent-guide/038-electron-db-worker-switch-graph.md`.
|
||||
|
||||
## Problem statement
|
||||
|
||||
Graph names shown in the web graph list can expose `logseq_db_` when the stored repo value has multiple leading prefixes.
|
||||
|
||||
Current rendering logic intentionally strips only one leading prefix, so malformed values like `logseq_db_logseq_db_demo` still render as `logseq_db_demo`.
|
||||
|
||||
The product decision is to keep one-layer stripping behavior and fix the upstream causes that create multi-prefix repo identifiers.
|
||||
|
||||
Multi-prefix data can enter through legacy disk graph discovery, Electron graph mapping, RTC remote metadata ingestion, and CLI graph-name conversion paths.
|
||||
|
||||
The required outcome is stable single-prefix internal repo identifiers plus single-pass display normalization, so normal graphs render as `demo` and malformed legacy doubles render as `logseq_db_demo`.
|
||||
|
||||
## Current and target normalization path
|
||||
|
||||
```text
|
||||
Current path with multi-prefix source data.
|
||||
input repo: logseq_db_logseq_db_demo
|
||||
-> display helper strips once
|
||||
-> output: logseq_db_demo
|
||||
-> user-visible prefix leak occurs.
|
||||
|
||||
Target path with source canonicalization + single-pass display stripping.
|
||||
ingress repo: logseq_db_logseq_db_demo
|
||||
-> canonicalize to one internal prefix: logseq_db_demo
|
||||
-> display helper strips once
|
||||
-> output: demo
|
||||
|
||||
Legacy persisted double-prefix fallback path (no migration).
|
||||
input repo from old state: logseq_db_logseq_db_demo
|
||||
-> display helper strips once
|
||||
-> output: logseq_db_demo
|
||||
```
|
||||
|
||||
## Testing Plan
|
||||
|
||||
I will follow `@test-driven-development` and write all failing tests before implementation.
|
||||
|
||||
I will add frontend unit tests in `/Users/rcmerci/gh-repos/logseq/src/test/frontend/util/text_test.cljs` to assert single-pass prefix stripping behavior.
|
||||
|
||||
I will add frontend persist tests in `/Users/rcmerci/gh-repos/logseq/src/test/frontend/db/persist_test.cljs` to assert merged graph sources are canonicalized to one internal prefix before UI state usage.
|
||||
|
||||
I will add RTC tests in `/Users/rcmerci/gh-repos/logseq/src/test/frontend/handler/db_based/rtc_test.cljs` to assert remote graph payload ingestion cannot create local double-prefix repos.
|
||||
|
||||
I will extend CLI formatter tests in `/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/format_test.cljs` to assert user-facing fields strip exactly one prefix and never introduce additional prefixes.
|
||||
|
||||
I will extend CLI command tests in `/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs` for `graph list` and server output paths with unprefixed and prefix-like graph names, and assert prefix-like `--repo` values are treated as graph-name content instead of invalid input.
|
||||
|
||||
I will add legacy graph discovery tests in `/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/common/graph_test.cljs` to verify old directory names do not produce multi-prefix repo ids.
|
||||
|
||||
I will run focused tests after RED and GREEN phases, then run `bb dev:lint-and-test` before completion.
|
||||
|
||||
I will review changes against `@prompts/review.md` before merge.
|
||||
|
||||
NOTE: I will write all tests before I add any implementation behavior.
|
||||
|
||||
## Implementation plan
|
||||
|
||||
### Phase 1: Add failing tests for one-layer display stripping and multi-prefix prevention.
|
||||
|
||||
1. Add failing unit tests in `/Users/rcmerci/gh-repos/logseq/src/test/frontend/util/text_test.cljs` for `logseq_db_demo -> demo`, `logseq_db_logseq_db_demo -> logseq_db_demo`, and middle-substring preservation.
|
||||
2. Add failing tests in `/Users/rcmerci/gh-repos/logseq/src/test/frontend/db/persist_test.cljs` to verify worker and Electron graph sources are canonicalized to one internal prefix.
|
||||
3. Add failing tests in `/Users/rcmerci/gh-repos/logseq/src/test/frontend/handler/db_based/rtc_test.cljs` for remote graph mapping and download paths with prefixed and double-prefixed payload names.
|
||||
4. Extend `/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/format_test.cljs` with failing cases where `:repo` or `:graph` includes one or two prefixes and output uses one-layer stripping only.
|
||||
5. Extend `/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs` with failing cases for graph list and server output using unprefixed and prefix-like `--repo` values, and assert prefix-like values are not rejected by argument validation.
|
||||
6. Add failing tests in `/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/common/graph_test.cljs` for legacy directory names that already contain `logseq_db_`.
|
||||
7. Run focused tests and confirm failures reflect behavior gaps rather than setup errors.
|
||||
|
||||
### Phase 2: Implement shared helpers for display normalization and repo canonicalization.
|
||||
|
||||
8. Add shared helpers in `/Users/rcmerci/gh-repos/logseq/deps/common/src/logseq/common/config.cljs` for single-pass display stripping and exact-one-prefix canonicalization.
|
||||
9. Keep display helper semantics strict to remove only one leading prefix and preserve all middle substrings.
|
||||
10. Keep canonicalization helper semantics strict to collapse any number of leading prefixes to exactly one.
|
||||
11. Use function names that clearly separate display behavior from internal repo id normalization.
|
||||
12. Keep helpers pure and dependency-light so they can be reused in frontend, Electron, and CLI namespaces.
|
||||
|
||||
### Phase 3: Apply web app fixes with one-layer display semantics.
|
||||
|
||||
13. Update `/Users/rcmerci/gh-repos/logseq/src/main/frontend/util/text.cljs` so `get-graph-name-from-path` calls the shared single-pass display helper.
|
||||
14. Update `/Users/rcmerci/gh-repos/logseq/src/main/frontend/config.cljs` so `db-graph-name` remains one-layer stripping and does not over-strip.
|
||||
15. Update `/Users/rcmerci/gh-repos/logseq/src/main/frontend/db/conn.cljs` so `get-short-repo-name` uses shared one-layer display normalization.
|
||||
16. Update `/Users/rcmerci/gh-repos/logseq/src/main/frontend/components/repo.cljs` rendering paths only if needed to ensure all user-visible labels share one-layer stripping behavior.
|
||||
17. Update `/Users/rcmerci/gh-repos/logseq/src/main/frontend/db/persist.cljs` so merged graph sources are canonicalized to one internal prefix before entering repo state.
|
||||
18. Keep `data-testid` and internal routing keys unchanged unless canonicalization is required to prevent multi-prefix key creation.
|
||||
|
||||
### Phase 4: Fix Electron and graph discovery paths that can create multi-prefix repos.
|
||||
|
||||
19. Update `/Users/rcmerci/gh-repos/logseq/deps/cli/src/logseq/cli/common/graph.cljs` so `get-db-based-graphs` canonicalizes discovered graph repo names to one prefix.
|
||||
20. Update `/Users/rcmerci/gh-repos/logseq/src/electron/electron/handler.cljs` and `/Users/rcmerci/gh-repos/logseq/src/electron/electron/utils.cljs` to canonicalize repo identifiers at IPC mapping boundaries.
|
||||
21. Verify Electron IPC `getGraphs` keeps stable internal repo identifiers and no path emits new double-prefixed repos.
|
||||
|
||||
### Phase 5: Fix RTC ingestion paths that can reintroduce multi-prefix repos.
|
||||
|
||||
22. Update `/Users/rcmerci/gh-repos/logseq/src/main/frontend/handler/db_based/rtc.cljs` so remote graph payload mapping canonicalizes incoming graph names before repo/url construction.
|
||||
23. Update `/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/rtc/full_upload_download_graph.cljs` so download naming canonicalizes to one internal prefix before local repo creation.
|
||||
24. Ensure existing graphs with prefixed remote names remain accessible after normalization.
|
||||
25. Ensure new uploads and downloads cannot create `logseq_db_logseq_db_*` local repo ids.
|
||||
|
||||
### Phase 6: Apply CLI fixes for one-layer display and one-prefix internal ids.
|
||||
|
||||
26. Update `/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/core.cljs` so `repo->graph` strips exactly one leading prefix for user-visible output.
|
||||
27. Verify `/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/format.cljs` uses one-layer display normalization consistently for human, JSON, and EDN user-facing graph fields.
|
||||
28. Update `/Users/rcmerci/gh-repos/logseq/deps/cli/src/logseq/cli/commands/graph.cljs` to canonicalize internal repo identifiers before list rendering and server-target resolution.
|
||||
29. Ensure CLI parsing and command execution treat `--repo` as a graph-name string, so leading `logseq_db_` is interpreted as part of graph name when present and is not rejected by input validation.
|
||||
|
||||
### Phase 7: Verification and release gate.
|
||||
|
||||
30. Run `bb dev:test -v 'frontend.util.text-test'` and confirm one-layer strip behavior and canonicalization tests pass.
|
||||
31. Run `bb dev:test -v 'frontend.db.persist-test'` and confirm merged-source canonicalization behavior is stable.
|
||||
32. Run `bb dev:test -v 'frontend.handler.db-based.rtc-test'` and confirm remote ingestion cannot produce multi-prefix repos.
|
||||
33. Run `bb dev:test -v 'logseq.cli.format-test'` and confirm CLI display fields apply one-layer strip behavior.
|
||||
34. Run `bb dev:test -v 'logseq.cli.commands-test'` and confirm graph command behavior remains stable with unprefixed and prefix-like `--repo` input.
|
||||
35. Run `bb dev:test -v 'logseq.cli.common.graph-test'` and confirm legacy graph discovery does not emit double-prefixed repo names.
|
||||
36. Run `bb dev:lint-and-test` and confirm `0 failures, 0 errors`.
|
||||
37. Perform a manual graph-list smoke check on web and Electron to confirm normal graphs display without prefix and legacy doubles display with one remaining prefix.
|
||||
38. Perform a manual CLI smoke check with `logseq graph list`, `logseq server status --repo demo`, and `logseq server status --repo logseq_db_demo` to confirm both inputs are accepted as graph names.
|
||||
|
||||
## Edge cases
|
||||
|
||||
| Scenario | Expected behavior |
|
||||
|---|---|
|
||||
| Internal repo is `logseq_db_demo`. | User-visible name is `demo`. |
|
||||
| Internal repo is `logseq_db_logseq_db_demo`. | User-visible name is `logseq_db_demo`. |
|
||||
| Graph name contains middle substring like `my_logseq_db_notes`. | Middle substring is preserved and only one leading prefix is removed when present. |
|
||||
| Legacy disk directory is named `logseq_db_demo`. | Discovery canonicalization keeps exactly one prefix and does not create `logseq_db_logseq_db_demo`. |
|
||||
| Legacy disk directory is named `logseq_db_logseq_db_demo`. | Discovery canonicalization collapses to internal repo `logseq_db_demo`. |
|
||||
| Remote graph payload returns `graph-name` as `logseq_db_demo`. | RTC mapping keeps internal repo `logseq_db_demo` and user-visible name `demo`. |
|
||||
| Remote graph payload returns `graph-name` as `logseq_db_logseq_db_demo`. | RTC mapping canonicalizes to internal repo `logseq_db_demo`, and user-visible name is `demo` after one-layer display strip. |
|
||||
| CLI receives `--repo demo`. | Command works and output graph name is `demo`. |
|
||||
| CLI receives `--repo logseq_db_demo`. | Command treats `logseq_db_` as part of graph name and does not fail argument validation. |
|
||||
| CLI receives `--repo logseq_db_logseq_db_demo`. | Command treats the full value as graph name content and does not fail argument validation. |
|
||||
| Non-user-visible fields like `data-testid` include repo id. | Existing selectors remain unchanged unless canonicalization is required to prevent duplicate graph entries. |
|
||||
|
||||
## Verification commands and expected outputs
|
||||
|
||||
```bash
|
||||
bb dev:test -v 'frontend.util.text-test'
|
||||
bb dev:test -v 'frontend.db.persist-test'
|
||||
bb dev:test -v 'frontend.handler.db-based.rtc-test'
|
||||
bb dev:test -v 'logseq.cli.format-test'
|
||||
bb dev:test -v 'logseq.cli.commands-test'
|
||||
bb dev:test -v 'logseq.cli.common.graph-test'
|
||||
bb dev:lint-and-test
|
||||
```
|
||||
|
||||
Each command should finish with `0 failures, 0 errors`.
|
||||
|
||||
Web and Electron manual checks should show no new multi-prefix repo entries.
|
||||
|
||||
Web and Electron display should strip one prefix only at render time.
|
||||
|
||||
CLI human output should match one-layer strip semantics, and CLI `--repo` should treat prefix-like values as normal graph names.
|
||||
|
||||
## Testing Details
|
||||
|
||||
The tests verify user-visible behavior and repo-id canonicalization at ingress and discovery boundaries.
|
||||
|
||||
Frontend tests assert display output and merged-state behavior rather than helper internals alone.
|
||||
|
||||
RTC and Electron tests assert that incoming prefixed names cannot generate additional prefixes in local repo ids.
|
||||
|
||||
CLI tests assert command behavior and output formatting remain stable for unprefixed and prefix-like graph-name input.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
- Keep display normalization as single-pass prefix stripping.
|
||||
- Add one shared helper for exact-one-prefix repo canonicalization.
|
||||
- Canonicalize ingress and discovery data before it reaches persistent repo state.
|
||||
- Reuse shared helpers across frontend, Electron, and CLI.
|
||||
- Preserve `data-testid` compatibility unless canonicalization makes key updates unavoidable.
|
||||
- Avoid one-time metadata migration for existing persisted graphs.
|
||||
- Treat CLI `--repo` input as raw graph name where `logseq_db_` may be part of the name.
|
||||
- Keep internal thread-api contracts based on prefixed repo ids.
|
||||
- Follow `@test-driven-development` for RED, GREEN, and REFACTOR order.
|
||||
- Validate final patch with `@prompts/review.md` checklist.
|
||||
|
||||
## Question
|
||||
|
||||
Decision: Display normalization removes only one leading prefix, so `logseq_db_logseq_db_xxxx` displays as `logseq_db_xxxx` in app surfaces that read legacy uncanonicalized values.
|
||||
|
||||
Decision: The implementation focus is to identify and fix all paths that can create multi-prefix repo identifiers, so newly produced data stays canonical.
|
||||
|
||||
Decision: This change does not include a one-time metadata migration for existing persisted legacy values.
|
||||
|
||||
Decision: CLI `--repo` option treats leading `logseq_db_` as graph-name content, not as forbidden prefix.
|
||||
|
||||
Decision: Treat `data-testid` stability as a strict compatibility requirement for `clj-e2e`.
|
||||
|
||||
---
|
||||
@@ -29,6 +29,7 @@
|
||||
[electron.window :as win]
|
||||
[electron.graph-switch-flow :as graph-switch-flow]
|
||||
[logseq.cli.common.graph :as cli-common-graph]
|
||||
[logseq.common.config :as common-config]
|
||||
[logseq.common.graph :as common-graph]
|
||||
[logseq.db.sqlite.util :as sqlite-util]
|
||||
[promesa.core :as p]))
|
||||
@@ -200,24 +201,30 @@
|
||||
[]
|
||||
(distinct (cli-common-graph/get-db-based-graphs)))
|
||||
|
||||
(defn- canonical-repo
|
||||
[graph]
|
||||
(common-config/canonicalize-db-version-repo graph))
|
||||
|
||||
;; TODO support alias mechanism
|
||||
(defn get-graph-name
|
||||
"Given a graph's name of string, returns the graph's fullname. For example, given
|
||||
`cat`, returns `logseq_db_cat`. Returns `nil` if no such graph exists."
|
||||
[graph-identifier]
|
||||
(->> (get-graphs)
|
||||
(some #(when (or
|
||||
(= (utils/normalize-lc %) (utils/normalize-lc (str sqlite-util/db-version-prefix graph-identifier)))
|
||||
(string/ends-with? (utils/normalize-lc %)
|
||||
(str "/" (utils/normalize-lc graph-identifier))))
|
||||
%))))
|
||||
(when-let [repo (canonical-repo graph-identifier)]
|
||||
(let [graph-name (common-config/strip-leading-db-version-prefix repo)]
|
||||
(->> (get-graphs)
|
||||
(some #(when (or
|
||||
(= (utils/normalize-lc %) (utils/normalize-lc repo))
|
||||
(string/ends-with? (utils/normalize-lc %)
|
||||
(str "/" (utils/normalize-lc graph-name))))
|
||||
%))))))
|
||||
|
||||
(defmethod handle :getGraphs [_window [_]]
|
||||
(get-graphs))
|
||||
|
||||
(defmethod handle :deleteGraph [_window [_ graph]]
|
||||
(when graph
|
||||
(db/unlink-graph! graph)))
|
||||
(when-let [repo (canonical-repo graph)]
|
||||
(db/unlink-graph! repo)))
|
||||
|
||||
;; DB related IPCs start
|
||||
|
||||
@@ -228,20 +235,22 @@
|
||||
(defmethod handle :db-worker-runtime [^js window [_ repo]]
|
||||
(if (string/blank? repo)
|
||||
(p/rejected (ex-info "repo is required" {:code :missing-repo}))
|
||||
(db-worker/ensure-runtime! repo (.-id window))))
|
||||
(db-worker/ensure-runtime! (canonical-repo repo) (.-id window))))
|
||||
|
||||
(defmethod handle :db-export [_window [_ repo data]]
|
||||
(logger/warn ::db-export-compat
|
||||
{:repo repo
|
||||
:message "legacy db-export IPC path invoked; desktop should use db-worker runtime"})
|
||||
(db/ensure-graph-dir! repo)
|
||||
(db/save-db! repo data))
|
||||
(when-let [repo (canonical-repo repo)]
|
||||
(logger/warn ::db-export-compat
|
||||
{:repo repo
|
||||
:message "legacy db-export IPC path invoked; desktop should use db-worker runtime"})
|
||||
(db/ensure-graph-dir! repo)
|
||||
(db/save-db! repo data)))
|
||||
|
||||
(defmethod handle :db-get [_window [_ repo]]
|
||||
(logger/warn ::db-get-compat
|
||||
{:repo repo
|
||||
:message "legacy db-get IPC path invoked; desktop should use db-worker runtime"})
|
||||
(db/get-db repo))
|
||||
(when-let [repo (canonical-repo repo)]
|
||||
(logger/warn ::db-get-compat
|
||||
{:repo repo
|
||||
:message "legacy db-get IPC path invoked; desktop should use db-worker runtime"})
|
||||
(db/get-db repo)))
|
||||
|
||||
;; DB related IPCs End
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
[electron.configs :as cfgs]
|
||||
[electron.logger :as logger]
|
||||
[logseq.cli.common.graph :as cli-common-graph]
|
||||
[logseq.db.sqlite.util :as sqlite-util]
|
||||
[logseq.common.config :as common-config]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defonce *win (atom nil)) ;; The main window
|
||||
@@ -240,14 +240,17 @@
|
||||
(defn get-graph-dir
|
||||
"required by all internal state in the electron section"
|
||||
[graph-name]
|
||||
(when (string/starts-with? graph-name sqlite-util/db-version-prefix)
|
||||
(node-path/join (cli-common-graph/get-db-graphs-dir) (string/replace-first graph-name sqlite-util/db-version-prefix ""))))
|
||||
(when (and (string? graph-name)
|
||||
(string/starts-with? graph-name common-config/db-version-prefix))
|
||||
(let [repo (common-config/canonicalize-db-version-repo graph-name)]
|
||||
(node-path/join (cli-common-graph/get-db-graphs-dir)
|
||||
(common-config/strip-leading-db-version-prefix repo)))))
|
||||
|
||||
(comment
|
||||
(defn get-graph-name
|
||||
"Reverse `get-graph-dir`"
|
||||
[graph-dir]
|
||||
(str sqlite-util/db-version-prefix (node-path/basename graph-dir))))
|
||||
(str common-config/db-version-prefix (node-path/basename graph-dir))))
|
||||
|
||||
(defn decode-protected-assets-schema-path
|
||||
[schema-path]
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
|
||||
(defn db-graph-name
|
||||
[repo-with-prefix]
|
||||
(string/replace-first repo-with-prefix db-version-prefix ""))
|
||||
(common-config/strip-leading-db-version-prefix repo-with-prefix))
|
||||
|
||||
(defn db-based-graph?
|
||||
([]
|
||||
@@ -257,7 +257,7 @@
|
||||
(path/path-join (get-in @state/state [:system/info :home-dir])
|
||||
"logseq"
|
||||
"graphs"
|
||||
(string/replace repo db-version-prefix "")))
|
||||
(db-graph-name repo)))
|
||||
|
||||
(defn get-electron-backup-dir
|
||||
[repo]
|
||||
@@ -269,7 +269,7 @@
|
||||
(if (util/electron?)
|
||||
(get-local-dir repo-url)
|
||||
(str "memory:///"
|
||||
(string/replace-first repo-url db-version-prefix "")))))
|
||||
(db-graph-name repo-url)))))
|
||||
|
||||
(defn get-repo-config-path
|
||||
[]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns frontend.db.conn
|
||||
"Contains db connections."
|
||||
(:require [clojure.string :as string]
|
||||
[datascript.core :as d]
|
||||
(:require [datascript.core :as d]
|
||||
[frontend.config :as config]
|
||||
[frontend.db.conn-state :as db-conn-state]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
@@ -52,7 +51,7 @@
|
||||
:else
|
||||
repo-name)]
|
||||
(if (config/db-based-graph? repo-name')
|
||||
(string/replace-first repo-name' config/db-version-prefix "")
|
||||
(config/db-graph-name repo-name')
|
||||
repo-name')))
|
||||
|
||||
(defn remove-conn!
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[clojure.string :as string]
|
||||
[electron.ipc :as ipc]
|
||||
[frontend.config :as config]
|
||||
[frontend.persist-db :as persist-db]
|
||||
[frontend.util :as util]
|
||||
[logseq.common.config :as common-config]
|
||||
@@ -23,12 +22,13 @@
|
||||
(map
|
||||
(fn [{:keys [name] :as repo}]
|
||||
(assoc repo :name
|
||||
(str config/db-version-prefix name)))))
|
||||
(common-config/canonicalize-db-version-repo name)))))
|
||||
electron-disk-graphs (when (util/electron?) (ipc/ipc "getGraphs"))]
|
||||
(distinct
|
||||
(concat
|
||||
repos'
|
||||
(map (fn [repo-name] {:name repo-name})
|
||||
(map (fn [repo-name]
|
||||
{:name (common-config/canonicalize-db-version-repo repo-name)})
|
||||
(some-> electron-disk-graphs bean/->clj))))))
|
||||
|
||||
(defn delete-graph!
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[frontend.state :as state]
|
||||
[frontend.util :as util]
|
||||
[lambdaisland.glogi :as log]
|
||||
[logseq.common.config :as common-config]
|
||||
[logseq.db :as ldb]
|
||||
[logseq.db-sync.malli-schema :as db-sync-schema]
|
||||
[logseq.db.sqlite.util :as sqlite-util]
|
||||
@@ -286,7 +287,7 @@
|
||||
(if base
|
||||
(p/let [_ (js/Promise. user-handler/task--ensure-id&access-token)
|
||||
body (coerce-http-request :graphs/create
|
||||
{:graph-name (string/replace repo config/db-version-prefix "")
|
||||
{:graph-name (common-config/strip-leading-db-version-prefix repo)
|
||||
:schema-version schema-version
|
||||
:graph-e2ee? graph-e2ee?})
|
||||
result (if (nil? body)
|
||||
@@ -334,15 +335,15 @@
|
||||
([graph-name graph-uuid graph-e2ee?]
|
||||
(state/set-state! :rtc/downloading-graph-uuid graph-uuid)
|
||||
(state/pub-event!
|
||||
[:rtc/log {:type :rtc.log/download
|
||||
[:rtc/log {:type :rtc.log/download
|
||||
:sub-type :download-progress
|
||||
:graph-uuid graph-uuid
|
||||
:message "Preparing graph snapshot download"}])
|
||||
(let [graph-e2ee? (normalize-graph-e2ee? graph-e2ee?)
|
||||
graph (common-config/canonicalize-db-version-repo graph-name)
|
||||
base (http-base)]
|
||||
(-> (if (and graph-uuid base)
|
||||
(-> (p/let [_ (js/Promise. user-handler/task--ensure-id&access-token)
|
||||
graph (str config/db-version-prefix graph-name)
|
||||
pull-resp (fetch-json (str base "/sync/" graph-uuid "/pull")
|
||||
{:method "GET"}
|
||||
{:response-schema :sync/pull})
|
||||
@@ -398,12 +399,14 @@
|
||||
{:response-schema :graphs/list})
|
||||
graphs (:graphs resp)
|
||||
result (mapv (fn [graph]
|
||||
(let [graph-e2ee? (if (contains? graph :graph-e2ee?)
|
||||
(let [repo (common-config/canonicalize-db-version-repo (:graph-name graph))
|
||||
graph-name (common-config/strip-leading-db-version-prefix repo)
|
||||
graph-e2ee? (if (contains? graph :graph-e2ee?)
|
||||
(normalize-graph-e2ee? (:graph-e2ee? graph))
|
||||
true)]
|
||||
(merge
|
||||
{:url (str config/db-version-prefix (:graph-name graph))
|
||||
:GraphName (:graph-name graph)
|
||||
{:url repo
|
||||
:GraphName graph-name
|
||||
:GraphSchemaVersion (:schema-version graph)
|
||||
:GraphUUID (:graph-id graph)
|
||||
:rtc-graph? true
|
||||
|
||||
@@ -101,4 +101,4 @@
|
||||
On iOS, repo-url might be nil"
|
||||
[repo-url]
|
||||
(when (not-empty repo-url)
|
||||
(string/replace-first repo-url config/db-version-prefix "")))
|
||||
(config/db-graph-name repo-url)))
|
||||
|
||||
@@ -210,15 +210,14 @@
|
||||
|
||||
(defn graph->repo
|
||||
[graph]
|
||||
(when (seq graph)
|
||||
(if (string/starts-with? graph common-config/db-version-prefix)
|
||||
graph
|
||||
(str common-config/db-version-prefix graph))))
|
||||
(some-> graph
|
||||
string/trim
|
||||
common-config/canonicalize-db-version-repo))
|
||||
|
||||
(defn repo->graph
|
||||
[repo]
|
||||
(when (seq repo)
|
||||
(string/replace-first repo common-config/db-version-prefix "")))
|
||||
(common-config/strip-leading-db-version-prefix repo)))
|
||||
|
||||
(defn resolve-repo
|
||||
[graph]
|
||||
|
||||
31
src/test/frontend/db/persist_test.cljs
Normal file
31
src/test/frontend/db/persist_test.cljs
Normal file
@@ -0,0 +1,31 @@
|
||||
(ns frontend.db.persist-test
|
||||
(:require [cljs.test :refer [async deftest is]]
|
||||
[electron.ipc :as ipc]
|
||||
[frontend.db.persist :as db-persist]
|
||||
[frontend.persist-db :as persist-db]
|
||||
[frontend.util :as util]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(deftest get-all-graphs-canonicalizes-db-prefixes-from-all-sources
|
||||
(async done
|
||||
(-> (p/with-redefs [persist-db/<list-db (fn []
|
||||
(p/resolved [{:name "demo"}
|
||||
{:name "logseq_db_prefixed"}
|
||||
{:name "logseq_db_logseq_db_legacy"}
|
||||
{:name "logseq_local_local-only"}]))
|
||||
util/electron? (constantly true)
|
||||
ipc/ipc (fn [_channel]
|
||||
(p/resolved #js ["logseq_db_remote"
|
||||
"logseq_db_logseq_db_remote-legacy"]))]
|
||||
(p/let [graphs (db-persist/get-all-graphs)
|
||||
names (mapv :name graphs)]
|
||||
(is (= #{"logseq_db_demo"
|
||||
"logseq_db_prefixed"
|
||||
"logseq_db_legacy"
|
||||
"logseq_db_remote"
|
||||
"logseq_db_remote-legacy"}
|
||||
(set names)))
|
||||
(is (not-any? #(re-find #"^logseq_db_logseq_db_" %) names))))
|
||||
(p/catch (fn [error]
|
||||
(is false (str error))))
|
||||
(p/finally done))))
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require [cljs.test :refer [deftest is async]]
|
||||
[clojure.string :as string]
|
||||
[frontend.db :as db]
|
||||
[frontend.handler.repo :as repo-handler]
|
||||
[frontend.handler.db-based.sync :as db-sync]
|
||||
[frontend.handler.user :as user-handler]
|
||||
[frontend.state :as state]
|
||||
@@ -152,6 +153,37 @@
|
||||
(is false (str e))
|
||||
(done)))))))
|
||||
|
||||
(deftest get-remote-graphs-canonicalizes-prefixed-graph-names
|
||||
(async done
|
||||
(let [set-state-calls (atom [])]
|
||||
(-> (p/with-redefs [db-sync/http-base (constantly "http://base")
|
||||
user-handler/task--ensure-id&access-token (fn [resolve _reject]
|
||||
(resolve true))
|
||||
db-sync/fetch-json (fn [url _opts _schema]
|
||||
(if (string/ends-with? url "/graphs")
|
||||
(p/resolved {:graphs [{:graph-name "logseq_db_demo"
|
||||
:graph-id "graph-1"
|
||||
:schema-version 1}
|
||||
{:graph-name "logseq_db_logseq_db_legacy"
|
||||
:graph-id "graph-2"
|
||||
:schema-version 1}]})
|
||||
(p/rejected (ex-info "unexpected fetch-json URL"
|
||||
{:url url}))))
|
||||
state/set-state! (fn [k v]
|
||||
(swap! set-state-calls conj [k v]))
|
||||
repo-handler/refresh-repos! (fn [] nil)]
|
||||
(p/let [result (db-sync/<get-remote-graphs)
|
||||
urls (mapv :url result)]
|
||||
(is (= ["logseq_db_demo" "logseq_db_legacy"] urls))
|
||||
(is (not-any? #(re-find #"^logseq_db_logseq_db_" %) urls))
|
||||
(is (some (fn [[k v]]
|
||||
(and (= :rtc/graphs k)
|
||||
(= urls (mapv :url v))))
|
||||
@set-state-calls))))
|
||||
(p/catch (fn [error]
|
||||
(is false (str error))))
|
||||
(p/finally done)))))
|
||||
|
||||
(deftest rtc-download-graph-emits-feedback-before-snapshot-fetch-test
|
||||
(let [trace (atom [])
|
||||
log-events (atom [])]
|
||||
@@ -242,3 +274,56 @@
|
||||
(set! js/fetch original-fetch)
|
||||
(is false (str error))
|
||||
(done)))))))
|
||||
|
||||
(deftest rtc-download-graph-canonicalizes-prefixed-graph-name-before-import-test
|
||||
(async done
|
||||
(let [import-calls (atom [])
|
||||
rows [[1 "content-1" "addresses-1"]]
|
||||
framed-bytes (encode-framed-rows rows)
|
||||
original-fetch js/fetch
|
||||
stream-url "http://base/sync/graph-2/snapshot/stream"]
|
||||
(-> (p/let [gzip-bytes (<gzip-bytes framed-bytes)]
|
||||
(set! js/fetch
|
||||
(fn [url opts]
|
||||
(let [method (or (aget opts "method") "GET")]
|
||||
(cond
|
||||
(and (= url stream-url) (= method "GET"))
|
||||
(js/Promise.resolve
|
||||
#js {:ok true
|
||||
:status 200
|
||||
:headers #js {:get (fn [header]
|
||||
(when (= header "content-length")
|
||||
(str (.-byteLength gzip-bytes))))}
|
||||
:arrayBuffer (fn [] (js/Promise.resolve (.-buffer gzip-bytes)))})
|
||||
|
||||
:else
|
||||
(js/Promise.resolve #js {:ok true :status 200})))))
|
||||
(-> (p/with-redefs [db-sync/http-base (constantly "http://base")
|
||||
db-sync/fetch-json (fn [url _opts _schema]
|
||||
(cond
|
||||
(string/ends-with? url "/pull")
|
||||
(p/resolved {:t 8})
|
||||
|
||||
:else
|
||||
(p/rejected (ex-info "unexpected fetch-json URL"
|
||||
{:url url}))))
|
||||
user-handler/task--ensure-id&access-token (fn [resolve _reject]
|
||||
(resolve true))
|
||||
state/<invoke-db-worker (fn [& args]
|
||||
(swap! import-calls conj args)
|
||||
(p/resolved :ok))
|
||||
state/set-state! (fn [& _] nil)
|
||||
state/pub-event! (fn [& _] nil)]
|
||||
(db-sync/<rtc-download-graph! "logseq_db_demo" "graph-2" true))
|
||||
(p/finally (fn [] (set! js/fetch original-fetch)))))
|
||||
(p/then (fn [_]
|
||||
(is (= 1 (count @import-calls)))
|
||||
(let [[op graph] (first @import-calls)]
|
||||
(is (= :thread-api/db-sync-import-kvs-rows op))
|
||||
(is (= "logseq_db_demo" graph))
|
||||
(is (not (string/starts-with? graph "logseq_db_logseq_db_"))))
|
||||
(done)))
|
||||
(p/catch (fn [error]
|
||||
(set! js/fetch original-fetch)
|
||||
(is false (str error))
|
||||
(done)))))))
|
||||
|
||||
@@ -34,4 +34,10 @@
|
||||
(map #(text-util/wrapped-by? "prop::value" % "" "::") (take 12 (range)))
|
||||
|
||||
'(false false false false false false true true true true true true)
|
||||
(map #(text-util/wrapped-by? "prop::value" % "::" "") (take 12 (range)))))
|
||||
(map #(text-util/wrapped-by? "prop::value" % "::" "") (take 12 (range)))))
|
||||
|
||||
(deftest get-graph-name-from-path-strips-only-one-leading-db-prefix
|
||||
(are [input expected] (= expected (text-util/get-graph-name-from-path input))
|
||||
"logseq_db_demo" "demo"
|
||||
"logseq_db_logseq_db_demo" "logseq_db_demo"
|
||||
"my_logseq_db_notes" "my_logseq_db_notes"))
|
||||
|
||||
@@ -1080,7 +1080,14 @@
|
||||
"--input" "import.zip"
|
||||
"--repo" "demo"])]
|
||||
(is (false? (:ok? result)))
|
||||
(is (= :invalid-options (get-in result [:error :code]))))))
|
||||
(is (= :invalid-options (get-in result [:error :code])))))
|
||||
|
||||
(testing "server status accepts prefix-like repo option values"
|
||||
(let [result (commands/parse-args ["server" "status"
|
||||
"--repo" "logseq_db_logseq_db_demo"])]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :server-status (:command result)))
|
||||
(is (= "logseq_db_logseq_db_demo" (get-in result [:options :repo]))))))
|
||||
|
||||
(deftest test-verb-subcommand-parse-flags
|
||||
(testing "verb subcommands reject unknown flags"
|
||||
@@ -1156,7 +1163,14 @@
|
||||
(let [parsed {:ok? true :command :server-stop :options {:repo "demo"}}
|
||||
result (commands/build-action parsed {})]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :server-stop (get-in result [:action :type]))))))
|
||||
(is (= :server-stop (get-in result [:action :type])))))
|
||||
|
||||
(testing "server status canonicalizes multi-prefixed repo option"
|
||||
(let [parsed {:ok? true :command :server-status :options {:repo "logseq_db_logseq_db_demo"}}
|
||||
result (commands/build-action parsed {})]
|
||||
(is (true? (:ok? result)))
|
||||
(is (= :server-status (get-in result [:action :type])))
|
||||
(is (= "logseq_db_demo" (get-in result [:action :repo]))))))
|
||||
|
||||
(deftest test-build-action-doctor
|
||||
(testing "doctor builds action"
|
||||
@@ -1565,10 +1579,13 @@
|
||||
(deftest test-execute-graph-list-strips-db-prefix
|
||||
(async done
|
||||
(let [orig-list-graphs cli-server/list-graphs]
|
||||
(set! cli-server/list-graphs (fn [_] ["logseq_db_demo" "logseq_db_other"]))
|
||||
(set! cli-server/list-graphs (fn [_] ["logseq_db_demo"
|
||||
"logseq_db_logseq_db_other"
|
||||
"my_logseq_db_notes"]))
|
||||
(-> (p/let [result (commands/execute {:type :graph-list} {})]
|
||||
(is (= :ok (:status result)))
|
||||
(is (= ["demo" "other"] (get-in result [:data :graphs]))))
|
||||
(is (= ["demo" "logseq_db_other" "my_logseq_db_notes"]
|
||||
(get-in result [:data :graphs]))))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))))
|
||||
(p/finally (fn []
|
||||
|
||||
20
src/test/logseq/cli/common/graph_test.cljs
Normal file
20
src/test/logseq/cli/common/graph_test.cljs
Normal file
@@ -0,0 +1,20 @@
|
||||
(ns logseq.cli.common.graph-test
|
||||
(:require [cljs.test :refer [deftest is]]
|
||||
[clojure.string :as string]
|
||||
[frontend.test.node-helper :as node-helper]
|
||||
[logseq.cli.common.graph :as cli-common-graph]
|
||||
["fs" :as fs]
|
||||
["path" :as node-path]))
|
||||
|
||||
(deftest get-db-based-graphs-canonicalizes-legacy-prefixed-directory-names
|
||||
(let [graphs-dir (node-helper/create-tmp-dir "cli-common-graph")
|
||||
_ (doseq [dir ["demo"
|
||||
"logseq_db_demo"
|
||||
"logseq_db_logseq_db_demo"
|
||||
"logseq_local_file-graph"
|
||||
"Unlinked graphs"]]
|
||||
(fs/mkdirSync (node-path/join graphs-dir dir) #js {:recursive true}))]
|
||||
(with-redefs [cli-common-graph/get-db-graphs-dir (fn [] graphs-dir)]
|
||||
(let [graphs (cli-common-graph/get-db-based-graphs)]
|
||||
(is (= #{"logseq_db_demo"} (set graphs)))
|
||||
(is (not-any? #(string/starts-with? % "logseq_db_logseq_db_") graphs))))))
|
||||
@@ -175,7 +175,34 @@
|
||||
{:output-format nil})]
|
||||
(is (= (str "Server ready: demo-repo\n"
|
||||
"Host: 127.0.0.1 Port: 1234")
|
||||
result)))))
|
||||
result))))
|
||||
|
||||
(testing "server status strips only one leading db prefix and keeps middle substrings"
|
||||
(let [double-prefixed (format/format-result {:status :ok
|
||||
:command :server-status
|
||||
:data {:repo "logseq_db_logseq_db_demo"
|
||||
:status :ready}}
|
||||
{:output-format nil})
|
||||
middle-substring (format/format-result {:status :ok
|
||||
:command :server-status
|
||||
:data {:repo "my_logseq_db_notes"
|
||||
:status :ready}}
|
||||
{:output-format nil})]
|
||||
(is (= "Server ready: logseq_db_demo" double-prefixed))
|
||||
(is (= "Server ready: my_logseq_db_notes" middle-substring)))))
|
||||
|
||||
(deftest test-json-output-normalizes-graph-fields-with-single-leading-strip-only
|
||||
(let [result (format/format-result {:status :ok
|
||||
:data {:repo "logseq_db_logseq_db_demo"
|
||||
:graph "my_logseq_db_notes"
|
||||
:graphs ["logseq_db_logseq_db_demo"
|
||||
"my_logseq_db_notes"]}}
|
||||
{:output-format :edn})
|
||||
parsed (reader/read-string result)]
|
||||
(is (= "logseq_db_demo" (get-in parsed [:data :repo])))
|
||||
(is (= "my_logseq_db_notes" (get-in parsed [:data :graph])))
|
||||
(is (= ["logseq_db_demo" "my_logseq_db_notes"]
|
||||
(get-in parsed [:data :graphs])))))
|
||||
|
||||
(deftest test-human-output-server-list-includes-owner
|
||||
(testing "server list shows owner column and value"
|
||||
|
||||
Reference in New Issue
Block a user