Przeglądaj źródła

impl 005-logseq-cli-output-and-db-worker-node-log.md (3)

rcmerci 1 dzień temu
rodzic
commit
2ee23aacc0

+ 1 - 1
docs/agent-guide/005-logseq-cli-output-and-db-worker-node-log.md

@@ -29,7 +29,7 @@ Target: plain text, no ANSI colors. Each command has a stable layout and orderin
 | remove block | `Removed block: <block-id> (repo: <repo>)` | n/a | Prefer UUID if available |
 | remove page | `Removed page: <page> (repo: <repo>)` | n/a | |
 | search | Table with header `TYPE TITLE/CONTENT UUID UPDATED-AT CREATED-AT`, rows in stable order, followed by `Count: N` | Header + `Count: 0` | For block rows use content snippet; for tag/property rows omit timestamps |
-| show (text) | Raw tree text (no table), trimmed | n/a | For `--format json|edn`, keep existing structured output |
+| show (text) | Raw tree text with `:db/id` as first column, trimmed | n/a | Tree lines should be prefixed by `:db/id` followed by the tree glyphs. Example:<br/><br/>`id1 block1`<br/>`id2 ├── b2`<br/>`id3 │   └── b3`<br/>`id4 ├── b4`<br/>`id5 │   ├── b5`<br/>`id6 │   │   └── b6`<br/>`id7 │   └── b7`<br/>`id8 └── b8`<br/><br/>If a block title spans multiple lines, show the first line on the tree line and indent the remaining lines under the glyph column. Example:<br/><br/>`168 Jan 18th, 2026`<br/>`169 ├── b1`<br/>`173 ├── aaaxx`<br/>`174 ├── block-line1`<br/>`    │   block-line2`<br/>`175 └── cccc`<br/><br/>For `--format json|edn`, keep existing structured output |
 | errors | `Error (<code>): <message>` + optional `Hint: <hint>` line | n/a | Ensure error codes are stable and consistent |
 
 ## Problem statement

+ 12 - 0
docs/cli/logseq-cli.md

@@ -93,6 +93,18 @@ Options grouping:
 Output formats:
 - Global `--output <human|json|edn>` (also accepted per subcommand)
 - Human output is plain text. List/search commands render tables with a final `Count: N` line. For list subcommands, the ID column uses `:db/id` (not UUID). If `:db/ident` exists, an `IDENT` column is included. Times such as list `UPDATED-AT`/`CREATED-AT` and `graph info` `Created at` are shown in human-friendly relative form. Errors include error codes and may include a `Hint:` line. Use `--output json|edn` for structured output.
+- `show` human output prints the `:db/id` as the first column followed by a tree:
+
+```
+id1 block1
+id2 ├── b2
+id3 │   └── b3
+id4 ├── b4
+id5 │   ├── b5
+id6 │   │   └── b6
+id7 │   └── b7
+id8 └── b8
+```
 
 Examples:
 

+ 31 - 9
src/main/logseq/cli/commands.cljs

@@ -693,15 +693,37 @@
 
 (defn- tree->text
   [{:keys [root]}]
-  (let [title (or (:block/title root) (:block/name root) (str (:block/uuid root)))
-        lines (atom [title])
-        walk (fn walk [node depth]
-               (doseq [child (:block/children node)]
-                 (let [prefix (apply str (repeat depth "  "))
-                       label (or (:block/title child) (:block/name child) (str (:block/uuid child)))]
-                   (swap! lines conj (str prefix "- " label)))
-                 (walk child (inc depth))))]
-    (walk root 1)
+  (let [label (fn [node]
+                (or (:block/title node) (:block/name node) (str (:block/uuid node))))
+        node-id (fn [node]
+                  (or (:db/id node) "-"))
+        id-padding (fn [node]
+                     (apply str (repeat (inc (count (str (node-id node)))) " ")))
+        split-lines (fn [value]
+                      (string/split (or value "") #"\n"))
+        lines (atom [])
+        walk (fn walk [node prefix]
+               (let [children (:block/children node)
+                     total (count children)]
+                 (doseq [[idx child] (map-indexed vector children)]
+                   (let [last-child? (= idx (dec total))
+                         branch (if last-child? "└── " "├── ")
+                         next-prefix (str prefix (if last-child? "    " "│   "))
+                         rows (split-lines (label child))
+                         first-row (first rows)
+                         rest-rows (rest rows)
+                         line (str (node-id child) " " prefix branch first-row)]
+                     (swap! lines conj line)
+                     (doseq [row rest-rows]
+                       (swap! lines conj (str (id-padding child) next-prefix row)))
+                     (walk child next-prefix)))))]
+    (let [rows (split-lines (label root))
+          first-row (first rows)
+          rest-rows (rest rows)]
+      (swap! lines conj (str (node-id root) " " first-row))
+      (doseq [row rest-rows]
+        (swap! lines conj (str (id-padding root) row))))
+    (walk root "")
     (string/join "\n" @lines)))
 
 (defn- resolve-repo

+ 28 - 0
src/test/frontend/worker/db_worker_node_test.cljs

@@ -140,6 +140,34 @@
                          (-> (stop!) (p/finally (fn [] (done))))
                          (done))))))))
 
+(deftest db-worker-node-log-retention
+  (let [enforce-log-retention! #'db-worker-node/enforce-log-retention!
+        data-dir (node-helper/create-tmp-dir "db-worker-log-retention")
+        repo (str "logseq_db_log_retention_" (subs (str (random-uuid)) 0 8))
+        pool-name (worker-util/get-pool-name repo)
+        repo-dir (node-path/join data-dir (str "." pool-name))
+        days ["20240101" "20240102" "20240103" "20240104" "20240105"
+              "20240106" "20240107" "20240108" "20240109"]
+        make-log (fn [day]
+                   (node-path/join repo-dir (str "db-worker-node-" day ".log")))]
+    (fs/mkdirSync repo-dir #js {:recursive true})
+    (doseq [day days]
+      (fs/writeFileSync (make-log day) "log\n"))
+    (enforce-log-retention! repo-dir)
+    (let [remaining (->> (fs/readdirSync repo-dir)
+                         (filter (fn [^js name]
+                                   (re-matches #"db-worker-node-\d{8}\.log" name)))
+                         (sort))]
+      (is (= 7 (count remaining)))
+      (is (= ["db-worker-node-20240103.log"
+              "db-worker-node-20240104.log"
+              "db-worker-node-20240105.log"
+              "db-worker-node-20240106.log"
+              "db-worker-node-20240107.log"
+              "db-worker-node-20240108.log"
+              "db-worker-node-20240109.log"]
+             remaining)))))
+
 (deftest db-worker-node-parse-args-ignores-host-and-port
   (let [parse-args #'db-worker-node/parse-args
         result (parse-args #js ["node" "db-worker-node.js"

+ 38 - 0
src/test/logseq/cli/commands_test.cljs

@@ -130,6 +130,44 @@
       (is (true? (:ok? result)))
       (is (= "json" (get-in result [:options :output]))))))
 
+(deftest test-tree->text-format
+  (testing "show tree text uses db/id with tree glyphs"
+    (let [tree->text #'commands/tree->text
+          tree-data {:root {:db/id 1
+                            :block/title "Root"
+                            :block/children [{:db/id 2
+                                              :block/title "Child A"
+                                              :block/children [{:db/id 3
+                                                                :block/title "Grandchild A1"}]}
+                                             {:db/id 4
+                                              :block/title "Child B"}]}}]
+      (is (= (str "1 Root\n"
+                  "2 ├── Child A\n"
+                  "3 │   └── Grandchild A1\n"
+                  "4 └── Child B")
+             (tree->text tree-data))))))
+
+(deftest test-tree->text-multiline
+  (testing "show tree text renders multiline blocks under glyph column"
+    (let [tree->text #'commands/tree->text
+          tree-data {:root {:db/id 168
+                            :block/title "Jan 18th, 2026"
+                            :block/children [{:db/id 169
+                                              :block/title "b1"}
+                                             {:db/id 173
+                                              :block/title "aaaxx"}
+                                             {:db/id 174
+                                              :block/title "block-line1\nblock-line2"}
+                                             {:db/id 175
+                                              :block/title "cccc"}]}}]
+      (is (= (str "168 Jan 18th, 2026\n"
+                  "169 ├── b1\n"
+                  "173 ├── aaaxx\n"
+                  "174 ├── block-line1\n"
+                  "    │   block-line2\n"
+                  "175 └── cccc")
+             (tree->text tree-data))))))
+
 (deftest test-list-subcommand-parse
   (testing "list page parses"
     (let [result (commands/parse-args ["list" "page"

+ 13 - 5
src/test/logseq/cli/format_test.cljs

@@ -145,12 +145,20 @@
                                                          :content "Note"
                                                          :uuid "u2"
                                                          :updated-at 4
-                                                         :created-at 2}]}}
+                                                         :created-at 2}
+                                                        {:type "tag"
+                                                         :title "Taggy"
+                                                         :uuid "u3"}
+                                                        {:type "property"
+                                                         :title "Prop"
+                                                         :uuid "u4"}]}}
                                        {:output-format nil})]
-      (is (= (str "TYPE   TITLE/CONTENT  UUID  UPDATED-AT  CREATED-AT\n"
-                  "page   Alpha          u1    3           1\n"
-                  "block  Note           u2    4           2\n"
-                  "Count: 2")
+      (is (= (str "TYPE      TITLE/CONTENT  UUID  UPDATED-AT  CREATED-AT\n"
+                  "page      Alpha          u1    3           1\n"
+                  "block     Note           u2    4           2\n"
+                  "tag       Taggy          u3    -           -\n"
+                  "property  Prop           u4    -           -\n"
+                  "Count: 4")
              result))))
 
   (testing "show renders text payloads directly"