|
@@ -3,36 +3,64 @@
|
|
|
(:require ["fs" :as fs]
|
|
|
[clojure.edn :as edn]
|
|
|
[clojure.pprint :as pprint]
|
|
|
+ [clojure.string :as string]
|
|
|
[datascript.core :as d]
|
|
|
[logseq.cli.util :as cli-util]
|
|
|
[logseq.db.common.sqlite-cli :as sqlite-cli]
|
|
|
- [logseq.db.frontend.rules :as rules]))
|
|
|
+ [logseq.db.frontend.rules :as rules]
|
|
|
+ [promesa.core :as p]))
|
|
|
|
|
|
(def spec
|
|
|
"Query spec"
|
|
|
- {:additional-graphs {:alias :a
|
|
|
- :coerce []
|
|
|
- :desc "Additional graphs to query"}})
|
|
|
+ {:graphs {:alias :g
|
|
|
+ :coerce []
|
|
|
+ :desc "Additional graphs to query"}
|
|
|
+ :api-query-token {:alias :a
|
|
|
+ :desc "Query current graph with api server token"}})
|
|
|
+
|
|
|
+(defn- api-query
|
|
|
+ [query token]
|
|
|
+ (-> (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 (string/starts-with? query "[")
|
|
|
+ "logseq.app.datascript_query"
|
|
|
+ "logseq.app.q")
|
|
|
+ :args #js [query]})}))]
|
|
|
+ (if (= 200 (.-status resp))
|
|
|
+ (p/let [body (.json resp)]
|
|
|
+ (js/console.log body))
|
|
|
+ (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)))))
|
|
|
|
|
|
(defn query
|
|
|
- [{{:keys [graph queries additional-graphs]} :opts}]
|
|
|
- (let [graphs (into [graph] additional-graphs)]
|
|
|
- (doseq [graph' graphs]
|
|
|
- (if (fs/existsSync (cli-util/get-graph-dir graph'))
|
|
|
- (let [conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph))
|
|
|
- query* (when (string? (first queries)) (edn/read-string (first queries)))
|
|
|
- ;; If datalog query detected run it or else default to entity lookups
|
|
|
- results (if (and (vector? query*) (= :find (first query*)))
|
|
|
- ;; assumes no :in are in queries
|
|
|
- (let [query' (into query* [:in '$ '%])
|
|
|
- res (d/q query' @conn (rules/extract-rules rules/db-query-dsl-rules))]
|
|
|
- ;; Remove nesting for most queries which just have one :find binding
|
|
|
- (if (= 1 (count (first res))) (mapv first res) res))
|
|
|
- (map #(when-let [ent (d/entity @conn
|
|
|
- (if (string? %) (edn/read-string %) %))]
|
|
|
- (into {:db/id (:db/id ent)} ent))
|
|
|
- queries))]
|
|
|
- (when (> (count graphs) 1)
|
|
|
- (println "Results for graph" (pr-str graph')))
|
|
|
- (pprint/pprint results))
|
|
|
- (println "Graph" (pr-str graph') "does not exist")))))
|
|
|
+ [{{:keys [graph queries graphs api-query-token]} :opts}]
|
|
|
+ (if api-query-token
|
|
|
+ ;; graph can be query since it's not used for api-query
|
|
|
+ (api-query (or graph (first queries)) api-query-token)
|
|
|
+ (let [graphs' (into [graph] graphs)]
|
|
|
+ (doseq [graph' graphs']
|
|
|
+ (if (fs/existsSync (cli-util/get-graph-dir graph'))
|
|
|
+ (let [conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph))
|
|
|
+ query* (when (string? (first queries)) (edn/read-string (first queries)))
|
|
|
+ ;; If datalog query detected run it or else default to entity lookups
|
|
|
+ results (if (and (vector? query*) (= :find (first query*)))
|
|
|
+ ;; assumes no :in are in queries
|
|
|
+ (let [query' (into query* [:in '$ '%])
|
|
|
+ res (d/q query' @conn (rules/extract-rules rules/db-query-dsl-rules))]
|
|
|
+ ;; Remove nesting for most queries which just have one :find binding
|
|
|
+ (if (= 1 (count (first res))) (mapv first res) res))
|
|
|
+ (map #(when-let [ent (d/entity @conn
|
|
|
+ (if (string? %) (edn/read-string %) %))]
|
|
|
+ (into {:db/id (:db/id ent)} ent))
|
|
|
+ queries))]
|
|
|
+ (when (> (count graphs') 1)
|
|
|
+ (println "Results for graph" (pr-str graph')))
|
|
|
+ (pprint/pprint results))
|
|
|
+ (println "Graph" (pr-str graph') "does not exist"))))))
|