mirror of
https://github.com/logseq/logseq.git
synced 2026-05-28 06:34:34 +00:00
feat: db export && backup on Electron
This commit is contained in:
@@ -37,14 +37,16 @@
|
||||
"backup CONTENT under DIR :backup-dir or :version-file-dir
|
||||
:backup-dir = `backup-dir`
|
||||
:version-file-dir = `version-file-dir`"
|
||||
[repo dir relative-path ext content]
|
||||
[repo dir relative-path ext content & {:keys [add-desktop?]
|
||||
:or {add-desktop? true}}]
|
||||
{:pre [(contains? #{:backup-dir :version-file-dir} dir)]}
|
||||
(let [dir* (case dir
|
||||
:backup-dir (get-backup-dir repo relative-path)
|
||||
:version-file-dir (get-version-file-dir repo relative-path))
|
||||
new-path (node-path/join dir*
|
||||
(str (string/replace (.toISOString (js/Date.)) ":" "_")
|
||||
".Desktop" ext))]
|
||||
(when add-desktop? ".Desktop")
|
||||
ext))]
|
||||
(fs-extra/ensureDirSync dir*)
|
||||
(fs/writeFileSync new-path content)
|
||||
(fs/statSync new-path)
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
(:require ["path" :as node-path]
|
||||
["fs-extra" :as fs]
|
||||
["electron" :refer [app]]
|
||||
[electron.logger :as logger]
|
||||
[logseq.db.sqlite.db :as sqlite-db]))
|
||||
;; [electron.logger :as logger]
|
||||
[logseq.db.sqlite.db :as sqlite-db]
|
||||
[electron.backup-file :as backup-file]))
|
||||
|
||||
(def close! sqlite-db/close!)
|
||||
|
||||
@@ -17,21 +18,23 @@
|
||||
[]
|
||||
(fs/ensureDirSync (get-graphs-dir)))
|
||||
|
||||
(defn open-db!
|
||||
[db-name]
|
||||
(let [graphs-dir (get-graphs-dir)]
|
||||
(try (sqlite-db/open-db! graphs-dir db-name)
|
||||
(catch :default e
|
||||
(js/console.error e)
|
||||
(logger/error (str e ": " db-name))
|
||||
;; (fs/unlinkSync db-full-path)
|
||||
))))
|
||||
|
||||
(defn new-db!
|
||||
(defn ensure-graph-dir!
|
||||
[db-name]
|
||||
(ensure-graphs-dir!)
|
||||
(let [graph-dir (node-path/join (get-graphs-dir) (sqlite-db/sanitize-db-name db-name))]
|
||||
(fs/ensureDirSync graph-dir)
|
||||
(open-db! db-name)))
|
||||
graph-dir))
|
||||
|
||||
(defn save-db!
|
||||
[db-name data]
|
||||
(let [graph-dir (ensure-graph-dir! db-name)
|
||||
[_db-name db-path] (sqlite-db/get-db-full-path (get-graphs-dir) db-name)]
|
||||
(fs/writeFileSync db-path data)
|
||||
(backup-file/backup-file graph-dir :backup-dir
|
||||
""
|
||||
".sqlite"
|
||||
data
|
||||
{:add-desktop? false})))
|
||||
|
||||
(def unlinked-graphs-dir "Unlinked graphs")
|
||||
|
||||
@@ -48,3 +51,19 @@
|
||||
(when (fs/existsSync path)
|
||||
(fs/ensureDirSync unlinked)
|
||||
(fs/moveSync path new-path'))))
|
||||
|
||||
(comment
|
||||
(defn open-db!
|
||||
[db-name]
|
||||
(let [graphs-dir (get-graphs-dir)]
|
||||
(try (sqlite-db/open-db! graphs-dir db-name)
|
||||
(catch :default e
|
||||
(js/console.error e)
|
||||
(logger/error (str e ": " db-name))
|
||||
;; (fs/unlinkSync db-full-path)
|
||||
))))
|
||||
|
||||
(defn new-db!
|
||||
[db-name]
|
||||
(ensure-graph-dir! db-name)
|
||||
(open-db! db-name)))
|
||||
|
||||
@@ -364,22 +364,9 @@
|
||||
|
||||
;; DB related IPCs start
|
||||
|
||||
;; Needs to be called first for a new graph
|
||||
(defmethod handle :db-new [_window [_ repo]]
|
||||
(db/new-db! repo))
|
||||
|
||||
(defmethod handle :db-transact-data [_window [_ repo data-str]]
|
||||
(let [{:keys [tx-data tx-meta]} (reader/read-string data-str)]
|
||||
(sqlite-db/transact! repo tx-data tx-meta)
|
||||
nil))
|
||||
|
||||
;; Needs to be called first for an existing graph
|
||||
(defmethod handle :get-initial-data [_window [_ repo _opts]]
|
||||
(db/open-db! repo)
|
||||
(dt/write-transit-str (sqlite-db/get-initial-data repo)))
|
||||
|
||||
(defmethod handle :get-other-data [_window [_ _repo _journal-block-uuids _opts]]
|
||||
nil)
|
||||
(defmethod handle :db-export [_window [_ repo data]]
|
||||
(db/ensure-graph-dir! repo)
|
||||
(db/save-db! repo data))
|
||||
|
||||
;; DB related IPCs End
|
||||
|
||||
@@ -737,6 +724,21 @@
|
||||
(defmethod handle :system/info [^js _win _]
|
||||
{:home-dir (.homedir os)})
|
||||
|
||||
(comment
|
||||
;; Needs to be called first for a new graph
|
||||
(defmethod handle :db-new [_window [_ repo]]
|
||||
(db/new-db! repo))
|
||||
|
||||
;; Needs to be called first for an existing graph
|
||||
(defmethod handle :get-initial-data [_window [_ repo _opts]]
|
||||
(db/open-db! repo)
|
||||
(dt/write-transit-str (sqlite-db/get-initial-data repo)))
|
||||
|
||||
(defmethod handle :db-transact-data [_window [_ repo data-str]]
|
||||
(let [{:keys [tx-data tx-meta]} (reader/read-string data-str)]
|
||||
(sqlite-db/transact! repo tx-data tx-meta)
|
||||
nil)))
|
||||
|
||||
(defn set-ipc-handler! [window]
|
||||
(let [main-channel "main"]
|
||||
(.handle ipcMain main-channel
|
||||
|
||||
@@ -48,14 +48,18 @@
|
||||
[repo]
|
||||
(str "/" repo ".sqlite"))
|
||||
|
||||
(comment
|
||||
(defn- export-db-file
|
||||
[repo]
|
||||
;; TODO: get file name by repo
|
||||
(p/let [^js pool (<get-opfs-pool repo)
|
||||
path (get-repo-path repo)]
|
||||
(when pool
|
||||
(.exportFile ^js pool path)))))
|
||||
(defn- <export-db-file
|
||||
[repo]
|
||||
(p/let [^js pool (<get-opfs-pool repo)
|
||||
path (get-repo-path repo)]
|
||||
(when pool
|
||||
(.exportFile ^js pool path))))
|
||||
|
||||
(defn- <import-db
|
||||
[repo data]
|
||||
(p/let [^js pool (<get-opfs-pool repo)]
|
||||
(when pool
|
||||
(.importDB ^js pool (get-repo-path repo) data))))
|
||||
|
||||
(defn upsert-addr-content!
|
||||
"Upsert addr+data-seq"
|
||||
@@ -244,7 +248,19 @@
|
||||
[_this repo]
|
||||
(p/let [_ (close-db! repo)]
|
||||
(remove-vfs! repo)
|
||||
nil)))
|
||||
nil))
|
||||
|
||||
(exportDB
|
||||
[_this repo]
|
||||
(<export-db-file repo))
|
||||
|
||||
(importDB
|
||||
[this repo data]
|
||||
;; FIXME: repo not exists yet
|
||||
(when-not (string/blank? repo)
|
||||
(p/let [_ (.createOrOpenDB this repo)
|
||||
data (<import-db repo data)]
|
||||
nil))))
|
||||
|
||||
(defn init
|
||||
"web worker entry"
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"Backend of DB based graph"
|
||||
(:require [frontend.persist-db.browser :as browser]
|
||||
[frontend.persist-db.protocol :as protocol]
|
||||
[promesa.core :as p]))
|
||||
[promesa.core :as p]
|
||||
[frontend.state :as state]))
|
||||
|
||||
(defonce opfs-db (browser/->InBrowser))
|
||||
|
||||
@@ -17,12 +18,6 @@
|
||||
(defn <unsafe-delete [repo]
|
||||
(protocol/<unsafe-delete (get-impl) repo))
|
||||
|
||||
;; FIXME: limit repo name's length
|
||||
;; @shuyu Do we still need this?
|
||||
(defn <new [repo]
|
||||
{:pre [(<= (count repo) 56)]}
|
||||
(protocol/<new (get-impl) repo))
|
||||
|
||||
(defn <transact-data [repo tx-data tx-meta]
|
||||
(protocol/<transact-data (get-impl) repo tx-data tx-meta))
|
||||
|
||||
@@ -33,3 +28,22 @@
|
||||
(p/let [ret (protocol/<fetch-initial-data (get-impl) repo opts)]
|
||||
(js/console.log "fetch-initial-data" ret)
|
||||
ret)))
|
||||
|
||||
(defn <export-db
|
||||
[repo]
|
||||
(protocol/<export-db (get-impl) repo))
|
||||
|
||||
(defn <import-db
|
||||
[repo data]
|
||||
(protocol/<import-db (get-impl) repo data))
|
||||
|
||||
;; FIXME: limit repo name's length
|
||||
;; @shuyu Do we still need this?
|
||||
(defn <new [repo]
|
||||
{:pre [(<= (count repo) 56)]}
|
||||
(p/do!
|
||||
(let [current-repo (state/get-current-repo)]
|
||||
(when-not (= repo current-repo)
|
||||
;; switch graph
|
||||
(<export-db current-repo))
|
||||
(protocol/<new (get-impl) repo))))
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
[frontend.util :as util]
|
||||
[frontend.handler.notification :as notification]
|
||||
[cljs-bean.core :as bean]
|
||||
[frontend.state :as state]))
|
||||
[frontend.state :as state]
|
||||
[electron.ipc :as ipc]))
|
||||
|
||||
(defonce *sqlite (atom nil))
|
||||
|
||||
@@ -37,6 +38,15 @@
|
||||
(ask-persist-permission!))
|
||||
(notification/show! "It seems that OPFS is not supported on this browser, please upgrade it to the latest version or use another browser." :error))))))
|
||||
|
||||
(defn <export-db!
|
||||
[repo data]
|
||||
(cond
|
||||
(util/electron?)
|
||||
(ipc/ipc :db-export repo data)
|
||||
|
||||
:else
|
||||
nil))
|
||||
|
||||
(defrecord InBrowser []
|
||||
protocol/PersistentDB
|
||||
(<new [_this repo]
|
||||
@@ -76,6 +86,23 @@
|
||||
(-> (p/let [_ (.createOrOpenDB sqlite repo)]
|
||||
(.getInitialData sqlite repo))
|
||||
(p/catch (fn [error]
|
||||
(prn :debug :fetch-initial-data-error)
|
||||
(prn :debug :fetch-initial-data-error repo)
|
||||
(js/console.error error)
|
||||
(notification/show! [:div (str "SQLiteDB fetch error: " error)] :error) {}))))))
|
||||
(notification/show! [:div (str "SQLiteDB fetch error: " error)] :error) {})))))
|
||||
|
||||
(<export-db [_this repo]
|
||||
(when-let [^js sqlite @*sqlite]
|
||||
(-> (p/let [data (.exportDB sqlite repo)]
|
||||
(<export-db! repo data))
|
||||
(p/catch (fn [error]
|
||||
(prn :debug :save-db-error repo)
|
||||
(js/console.error error)
|
||||
(notification/show! [:div (str "SQLiteDB save error: " error)] :error) {})))))
|
||||
|
||||
(<import-db [_this repo data]
|
||||
(when-let [^js sqlite @*sqlite]
|
||||
(-> (.importDB sqlite repo data)
|
||||
(p/catch (fn [error]
|
||||
(prn :debug :import-db-error repo)
|
||||
(js/console.error error)
|
||||
(notification/show! [:div (str "SQLiteDB import error: " error)] :error) {}))))))
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
(ns frontend.persist-db.protocol
|
||||
"Provides protocol for persisting db"
|
||||
(:require))
|
||||
"Provides protocol for persisting db")
|
||||
|
||||
;; TODO: exporting, importing support
|
||||
(defprotocol PersistentDB
|
||||
(<list-db [this])
|
||||
(<new [this repo])
|
||||
(<unsafe-delete [this repo])
|
||||
(<list-db [this] "List all databases")
|
||||
(<new [this repo] "Create or open a graph")
|
||||
(<unsafe-delete [this repo] "Delete graph and its vfs")
|
||||
(<transact-data [this repo tx-data tx-meta] "Transact data to db")
|
||||
(<fetch-initial-data [this repo opts]))
|
||||
(<fetch-initial-data [this repo opts] "Fetch Initial data")
|
||||
(<export-db [this repo] "Save SQLite db")
|
||||
(<import-db [this repo data] "Import SQLite db"))
|
||||
|
||||
Reference in New Issue
Block a user