Browse Source

enhance: add api-based search cmd

Also add error handler for required option since
search cmd has one
Gabriel Horner 3 months ago
parent
commit
81b3c65d6a

+ 12 - 1
deps/cli/src/logseq/cli.cljs

@@ -7,6 +7,7 @@
             [logseq.cli.commands.export-edn :as cli-export-edn]
             [logseq.cli.commands.graph :as cli-graph]
             [logseq.cli.commands.query :as cli-query]
+            [logseq.cli.commands.search :as cli-search]
             [logseq.cli.common.graph :as cli-common-graph]
             [nbb.error :as error]))
 
@@ -54,6 +55,9 @@
   [{:cmds ["list"] :fn cli-graph/list-graphs :desc "List graphs"}
    {:cmds ["show"] :fn cli-graph/show-graph :desc "Show DB graph(s) info"
     :args->opts [:graphs] :coerce {:graphs []}}
+   {:cmds ["search"] :fn cli-search/search :desc "Search current DB graph"
+    :args->opts [:search-terms] :coerce {:search-terms []}
+    :spec cli-search/spec}
    {:cmds ["query"] :fn cli-query/query :desc "Query DB graph(s)"
     :args->opts [:graph :queries] :coerce {:queries []} :no-keyword-opts true
     :spec cli-query/spec}
@@ -75,7 +79,14 @@
   (when-not (contains? #{nil "-h" "--help"} (first args))
     (error-if-db-version-not-installed))
   (try
-    (cli/dispatch table args {:coerce {:depth :long}})
+    (cli/dispatch table
+                  args
+                  {:error-fn (fn [{:keys [cause msg option] type' :type :as data}]
+                               (if (and (= :org.babashka/cli type')
+                                        (= :require cause))
+                                 (println "Error: Command missing required option" option)
+                                 (throw (ex-info msg data)))
+                               (js/process.exit 1))})
     (catch ^:sci/error js/Error e
       (error/print-error-report e))))
 

+ 15 - 24
deps/cli/src/logseq/cli/commands/query.cljs

@@ -20,30 +20,21 @@
 
 (defn- api-query
   [query token]
-  (let [datalog-query? (string/starts-with? query "[")]
-    (-> (p/let [resp (js/fetch "http://127.0.0.1:12315/api"
-                              (clj->js {:method "POST"
-                                        :headers {"Authorization" (str "Bearer " token)
-                                                  "Content-Type" "application/json"}
-                                        :body (js/JSON.stringify
-                                               #js {:method (if datalog-query?
-                                                              "logseq.app.datascript_query"
-                                                              "logseq.app.q")
-                                                    :args #js [query]})}))]
-         (if (= 200 (.-status resp))
-           (p/let [body (.json resp)]
-             (let [res (js->clj body :keywordize-keys true)
-                   results (if datalog-query?
-                            ;; Remove nesting for most queries which just have one :find binding
-                             (if (= 1 (count (first res))) (mapv first res) res)
-                             res)]
-               (pprint/pprint results)))
-           (do (js/console.error "Error: API Server responded with status" (.-status resp)
-                                 (when (.-statusText resp) (str "and body " (pr-str (.-statusText resp)))))
-               (js/process.exit 1))))
-       (p/catch (fn [err]
-                  (js/console.error "Error:" err)
-                  (js/process.exit 1))))))
+  (let [datalog-query? (string/starts-with? query "[")
+        method (if datalog-query?  "logseq.app.datascript_query" "logseq.app.q")]
+    (-> (p/let [resp (cli-util/api-fetch token method [query])]
+          (if (= 200 (.-status resp))
+            (p/let [body (.json resp)]
+              (let [res (js->clj body :keywordize-keys true)
+                    results (if datalog-query?
+                              ;; Remove nesting for most queries which just have one :find binding
+                              (if (= 1 (count (first res))) (mapv first res) res)
+                              res)]
+                (pprint/pprint results)))
+            (cli-util/api-handle-error-response resp)))
+        (p/catch (fn [err]
+                   (js/console.error "Error:" err)
+                   (js/process.exit 1))))))
 
 (defn query
   [{{:keys [graph queries graphs api-query-token]} :opts}]

+ 30 - 0
deps/cli/src/logseq/cli/commands/search.cljs

@@ -0,0 +1,30 @@
+(ns logseq.cli.commands.search
+  "Search command"
+  (:require [clojure.pprint :as pprint]
+            [clojure.string :as string]
+            [logseq.cli.util :as cli-util]
+            [promesa.core :as p]))
+
+(def spec {:api-query-token {:alias :a
+                             :require true
+                             :desc "Api server token"}
+           :raw {:alias :r
+                 :desc "Print raw response"}})
+
+(defn search
+  [{{:keys [search-terms api-query-token raw]} :opts}]
+  (-> (p/let [resp (cli-util/api-fetch api-query-token "logseq.app.search" [(string/join " " search-terms)])]
+        (if (= 200 (.-status resp))
+          (p/let [body (.json resp)]
+            (let [{:keys [blocks]} (js->clj body :keywordize-keys true)]
+              (println "Search found" (count blocks) "results:")
+              (if raw
+                (pprint/pprint blocks)
+                (println (string/join "\n"
+                                      (->> blocks
+                                           (map :block/title)
+                                           (map #(string/replace % "\n" "\\\\n"))))))))
+          (cli-util/api-handle-error-response resp)))
+      (p/catch (fn [err]
+                 (js/console.error "Error:" err)
+                 (js/process.exit 1)))))

+ 17 - 1
deps/cli/src/logseq/cli/util.cljs

@@ -11,4 +11,20 @@
 (defn ->open-db-args
   "Creates args for sqlite-cli/open-db! given a graph. Similar to sqlite-cli/->open-db-args"
   [graph]
-  [(cli-common-graph/get-db-graphs-dir) (common-sqlite/sanitize-db-name graph)])
+  [(cli-common-graph/get-db-graphs-dir) (common-sqlite/sanitize-db-name graph)])
+
+(defn api-fetch [token method args]
+  (js/fetch "http://127.0.0.1:12315/api"
+            (clj->js {:method "POST"
+                      :headers {"Authorization" (str "Bearer " token)
+                                "Content-Type" "application/json"}
+                      :body (js/JSON.stringify
+                             (clj->js {:method method
+                                       :args args}))})))
+
+(defn api-handle-error-response
+  "Handles a non 200 response"
+  [resp]
+  (js/console.error "Error: API Server responded with status" (.-status resp)
+                    (when (.-statusText resp) (str "and body " (pr-str (.-statusText resp)))))
+  (js/process.exit 1))