memory_fs.cljs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. (ns frontend.fs.memory-fs
  2. "Memory FS backed by lightning-fs
  3. Paths are denoted by `memory://`. No open-dir/get-files support."
  4. (:require [cljs-bean.core :as bean]
  5. [frontend.db :as db]
  6. [frontend.fs.protocol :as protocol]
  7. [logseq.common.path :as path]
  8. [promesa.core :as p]))
  9. (defn- <readdir
  10. "Read dir recursively, return all paths
  11. accept dir as path, without memory:// prefix for simplicity"
  12. [dir]
  13. (p/let [result (p/loop [result []
  14. dirs [dir]]
  15. (if (empty? dirs)
  16. result
  17. (p/let [dir (first dirs)
  18. stat (js/window.pfs.stat dir)
  19. is-file? (= (.-type stat) "file")
  20. result (if is-file?
  21. (conj result dir)
  22. result)
  23. dir-content (when-not is-file?
  24. (-> (js/window.pfs.readdir dir)
  25. (p/then bean/->clj)
  26. (p/then (fn [rpaths]
  27. (mapv #(path/path-join dir %) rpaths)))))]
  28. (p/recur result (concat (rest dirs) dir-content)))))]
  29. result))
  30. (defn- <ensure-dir!
  31. "dir is path, without memory:// prefix for simplicity"
  32. [dir]
  33. (-> (p/let [stat (js/window.pfs.stat dir)]
  34. (cond
  35. (= (.-type stat) "file")
  36. (p/rejected "Path is a file")
  37. :else
  38. (p/resolved nil)))
  39. (p/catch (fn [_error]
  40. (js/window.pfs.mkdir dir)))))
  41. (defn- <exists?
  42. "dir is path, without memory:// prefix for simplicity"
  43. [dir]
  44. (-> (js/window.pfs.stat dir)
  45. (p/then (fn [stat]
  46. (not (nil? stat))))
  47. (p/catch (fn [_]
  48. nil))))
  49. (defn- <mkdir-recur!
  50. "mkdir, recursively create parent directories if not exist
  51. lightning-fs does not support's :recursive in mkdir options"
  52. [dir]
  53. (p/let [fpath (path/url-to-path dir)
  54. sub-dirs (p/loop [top-parent fpath
  55. remains []]
  56. (p/let [exists? (<exists? top-parent)]
  57. (if exists?
  58. (reverse remains) ;; top-parent is the first non-exist dir
  59. (p/recur (path/parent top-parent)
  60. (conj remains top-parent)))))]
  61. (p/loop [remains sub-dirs]
  62. (if (empty? remains)
  63. (p/resolved nil)
  64. (p/do! (js/window.pfs.mkdir (first remains))
  65. (p/recur (rest remains)))))))
  66. (defrecord MemoryFs []
  67. protocol/Fs
  68. (mkdir! [_this dir]
  69. (when js/window.pfs
  70. (let [fpath (path/url-to-path dir)]
  71. (-> (js/window.pfs.mkdir fpath)
  72. (p/catch (fn [error] (println "(memory-fs)Mkdir error: " error)))))))
  73. (mkdir-recur! [_this dir]
  74. (when js/window.pfs
  75. (let [fpath (path/url-to-path dir)]
  76. (-> (<mkdir-recur! fpath)
  77. (p/catch (fn [error] (println "(memory-fs)Mkdir-recur error: " error)))))))
  78. (readdir [_this dir]
  79. (when js/window.pfs
  80. (let [fpath (path/url-to-path dir)]
  81. (-> (<readdir fpath)
  82. (p/then (fn [rpaths]
  83. (mapv #(path/path-join "memory://" %) rpaths)))
  84. (p/catch (fn [error]
  85. (println "(memory-fs)Readdir error: " error)
  86. (p/rejected error)))))))
  87. (unlink! [_this _repo path opts]
  88. (when js/window.pfs
  89. (p/let [fpath (path/url-to-path path)
  90. stat (js/window.pfs.stat fpath)]
  91. (if (= (.-type stat) "file")
  92. (js/window.pfs.unlink fpath opts)
  93. (p/rejected "Unlinking a directory is not allowed, use rmdir! instead")))))
  94. (rmdir! [_this dir]
  95. (let [fpath (path/url-to-path dir)]
  96. (js/window.workerThread.rimraf fpath)))
  97. (read-file [_this dir path options]
  98. (let [fpath (path/url-to-path (path/path-join dir path))]
  99. (js/window.pfs.readFile fpath (clj->js options))))
  100. (write-file! [_this repo dir rpath content _opts]
  101. (p/let [fpath (path/url-to-path (path/path-join dir rpath))
  102. containing-dir (path/parent fpath)
  103. _ (<ensure-dir! containing-dir)
  104. _ (js/window.pfs.writeFile fpath content)]
  105. (db/set-file-content! repo rpath content)
  106. (db/set-file-last-modified-at! repo rpath (js/Date.))))
  107. (rename! [_this _repo old-path new-path]
  108. (let [old-path (path/url-to-path old-path)
  109. new-path (path/url-to-path new-path)]
  110. (js/window.pfs.rename old-path new-path)))
  111. (stat [_this fpath]
  112. (let [fpath (path/url-to-path fpath)]
  113. (js/window.pfs.stat fpath)))
  114. (open-dir [_this _dir]
  115. nil)
  116. (get-files [_this _path-or-handle]
  117. nil)
  118. (watch-dir! [_this _dir _options]
  119. nil)
  120. (unwatch-dir! [_this _dir]
  121. nil))