export_client_ops_ops.cljs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. (ns export-client-ops-ops
  2. "Export client-ops tx entities to an EDN file sorted by :db-sync/created-at asc.
  3. Examples:
  4. $ yarn -s nbb-logseq script/export_client_ops_ops.cljs /path/to/client-ops.sqlite
  5. $ yarn -s nbb-logseq script/export_client_ops_ops.cljs /path/to/client-ops.sqlite --out client-ops-ops.edn"
  6. (:require ["fs" :as fs]
  7. ["path" :as node-path]
  8. [babashka.cli :as cli]
  9. [clojure.pprint :as pprint]
  10. [datascript.core :as d]
  11. [logseq.db.common.sqlite-cli :as sqlite-cli]
  12. [nbb.core :as nbb]))
  13. (def spec
  14. {:help {:alias :h
  15. :desc "Show help"}
  16. :out {:alias :o
  17. :desc "Output EDN file path"
  18. :coerce :string}})
  19. (def op-keys
  20. [:db-sync/tx-id
  21. :db-sync/created-at
  22. :db-sync/pending?
  23. :db-sync/failed?
  24. :db-sync/outliner-op
  25. :db-sync/forward-outliner-ops
  26. :db-sync/inverse-outliner-ops
  27. :db-sync/inferred-outliner-ops?
  28. :db-sync/normalized-tx-data
  29. :db-sync/reversed-tx-data])
  30. (defn usage []
  31. (str "Usage: yarn -s nbb-logseq script/export_client_ops_ops.cljs <client-ops-db> [--out <file.edn>]\n"
  32. "Options:\n"
  33. (cli/format-opts {:spec spec})))
  34. (defn resolve-path
  35. [path*]
  36. (if (node-path/isAbsolute path*)
  37. path*
  38. (node-path/join (or js/process.env.ORIGINAL_PWD ".") path*)))
  39. (defn default-output-path
  40. [input-path]
  41. (let [resolved (resolve-path input-path)
  42. dir (node-path/dirname resolved)
  43. base (node-path/basename resolved)
  44. name (node-path/parse base)
  45. stem (or (.-name name) base)]
  46. (node-path/join dir (str stem "-ops.edn"))))
  47. (defn entity->op
  48. [db eid]
  49. (let [ent (d/entity db eid)]
  50. (merge
  51. {:db/id (:db/id ent)}
  52. (select-keys (into {} ent) op-keys))))
  53. (defn read-ops
  54. [conn]
  55. (let [db @conn]
  56. (->> (d/datoms db :avet :db-sync/created-at)
  57. (map (fn [datom] (entity->op db (:e datom))))
  58. (sort-by (juxt :db-sync/created-at :db/id))
  59. vec)))
  60. (defn -main
  61. [argv]
  62. (let [{:keys [opts args]} (cli/parse-args argv {:spec spec})
  63. [input-path] args]
  64. (when (or (:help opts) (nil? input-path))
  65. (println (usage))
  66. (js/process.exit (if (:help opts) 0 1)))
  67. (let [db-path (resolve-path input-path)
  68. _ (when-not (fs/existsSync db-path)
  69. (println "Client ops db file does not exist:" db-path)
  70. (js/process.exit 1))
  71. out-path (resolve-path (or (:out opts) (default-output-path db-path)))
  72. open-args (sqlite-cli/->open-db-args db-path)
  73. {:keys [conn sqlite]} (apply sqlite-cli/open-sqlite-datascript! open-args)]
  74. (try
  75. (let [ops (read-ops conn)]
  76. (println "Read" (count ops) "ops from" db-path)
  77. (println "Writing ops EDN to" out-path)
  78. (fs/writeFileSync out-path (with-out-str (pprint/pprint ops))))
  79. (finally
  80. (when sqlite
  81. (.close sqlite)))))))
  82. (when (= nbb/*file* (nbb/invoked-file))
  83. (-main *command-line-args*))