mirror of
https://github.com/penpot/penpot.git
synced 2025-05-30 01:56:10 +02:00
🎉 Add binfile-v3 export/import file format
This commit is contained in:
parent
4fb5d3fb20
commit
8618cb950f
35 changed files with 2031 additions and 599 deletions
|
@ -8,6 +8,7 @@
|
|||
(:refer-clojure :exclude [assert])
|
||||
(:require
|
||||
[app.binfile.v1 :as bf.v1]
|
||||
[app.binfile.v3 :as bf.v3]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.db :as db]
|
||||
|
@ -35,51 +36,103 @@
|
|||
[:map {:title "export-binfile"}
|
||||
[:name [:string {:max 250}]]
|
||||
[:file-id ::sm/uuid]
|
||||
[:include-libraries :boolean]
|
||||
[:embed-assets :boolean]])
|
||||
[:version {:optional true} ::sm/int]
|
||||
[:include-libraries ::sm/boolean]
|
||||
[:embed-assets ::sm/boolean]])
|
||||
|
||||
(defn stream-export-v1
|
||||
[cfg {:keys [file-id include-libraries embed-assets] :as params}]
|
||||
(reify rres/StreamableResponseBody
|
||||
(-write-body-to-stream [_ _ output-stream]
|
||||
(try
|
||||
(-> cfg
|
||||
(assoc ::bf.v1/ids #{file-id})
|
||||
(assoc ::bf.v1/embed-assets embed-assets)
|
||||
(assoc ::bf.v1/include-libraries include-libraries)
|
||||
(bf.v1/export-files! output-stream))
|
||||
(catch Throwable cause
|
||||
(l/err :hint "exception on exporting file"
|
||||
:file-id (str file-id)
|
||||
:cause cause))))))
|
||||
|
||||
(defn stream-export-v3
|
||||
[cfg {:keys [file-id include-libraries embed-assets] :as params}]
|
||||
(reify rres/StreamableResponseBody
|
||||
(-write-body-to-stream [_ _ output-stream]
|
||||
(try
|
||||
(-> cfg
|
||||
(assoc ::bf.v3/ids #{file-id})
|
||||
(assoc ::bf.v3/embed-assets embed-assets)
|
||||
(assoc ::bf.v3/include-libraries include-libraries)
|
||||
(bf.v3/export-files! output-stream))
|
||||
(catch Throwable cause
|
||||
(l/err :hint "exception on exporting file"
|
||||
:file-id (str file-id)
|
||||
:cause cause))))))
|
||||
|
||||
(sv/defmethod ::export-binfile
|
||||
"Export a penpot file in a binary format."
|
||||
{::doc/added "1.15"
|
||||
::webhooks/event? true
|
||||
::sm/result schema:export-binfile}
|
||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id include-libraries embed-assets] :as params}]
|
||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id version file-id] :as params}]
|
||||
(files/check-read-permissions! pool profile-id file-id)
|
||||
(fn [_]
|
||||
{::rres/status 200
|
||||
::rres/headers {"content-type" "application/octet-stream"}
|
||||
::rres/body (reify rres/StreamableResponseBody
|
||||
(-write-body-to-stream [_ _ output-stream]
|
||||
(try
|
||||
(-> cfg
|
||||
(assoc ::bf.v1/ids #{file-id})
|
||||
(assoc ::bf.v1/embed-assets embed-assets)
|
||||
(assoc ::bf.v1/include-libraries include-libraries)
|
||||
(bf.v1/export-files! output-stream))
|
||||
(catch Throwable cause
|
||||
(l/err :hint "exception on exporting file"
|
||||
:file-id (str file-id)
|
||||
:cause cause)))))}))
|
||||
(let [version (or version 1)
|
||||
body (case (int version)
|
||||
1 (stream-export-v1 cfg params)
|
||||
2 (throw (ex-info "not-implemented" {}))
|
||||
3 (stream-export-v3 cfg params))]
|
||||
|
||||
{::rres/status 200
|
||||
::rres/headers {"content-type" "application/octet-stream"}
|
||||
::rres/body body})))
|
||||
|
||||
;; --- Command: import-binfile
|
||||
|
||||
(defn- import-binfile-v1
|
||||
[{:keys [::wrk/executor] :as cfg} {:keys [project-id profile-id name file]}]
|
||||
(let [cfg (-> cfg
|
||||
(assoc ::bf.v1/project-id project-id)
|
||||
(assoc ::bf.v1/profile-id profile-id)
|
||||
(assoc ::bf.v1/name name)
|
||||
(assoc ::bf.v1/input (:path file)))]
|
||||
|
||||
;; NOTE: the importation process performs some operations that are
|
||||
;; not very friendly with virtual threads, and for avoid
|
||||
;; unexpected blocking of other concurrent operations we dispatch
|
||||
;; that operation to a dedicated executor.
|
||||
(px/invoke! executor (partial bf.v1/import-files! cfg))))
|
||||
|
||||
(defn- import-binfile-v3
|
||||
[{:keys [::wrk/executor] :as cfg} {:keys [project-id profile-id name file]}]
|
||||
(let [cfg (-> cfg
|
||||
(assoc ::bf.v3/project-id project-id)
|
||||
(assoc ::bf.v3/profile-id profile-id)
|
||||
(assoc ::bf.v3/name name)
|
||||
(assoc ::bf.v3/input (:path file)))]
|
||||
;; NOTE: the importation process performs some operations that are
|
||||
;; not very friendly with virtual threads, and for avoid
|
||||
;; unexpected blocking of other concurrent operations we dispatch
|
||||
;; that operation to a dedicated executor.
|
||||
(px/invoke! executor (partial bf.v3/import-files! cfg))))
|
||||
|
||||
(defn- import-binfile
|
||||
[{:keys [::wrk/executor ::bf.v1/project-id ::db/pool] :as cfg} input]
|
||||
;; NOTE: the importation process performs some operations that
|
||||
;; are not very friendly with virtual threads, and for avoid
|
||||
;; unexpected blocking of other concurrent operations we
|
||||
;; dispatch that operation to a dedicated executor.
|
||||
(let [result (px/invoke! executor (partial bf.v1/import-files! cfg input))]
|
||||
[{:keys [::db/pool] :as cfg} {:keys [project-id version] :as params}]
|
||||
(let [result (case (int version)
|
||||
1 (import-binfile-v1 cfg params)
|
||||
3 (import-binfile-v3 cfg params))]
|
||||
(db/update! pool :project
|
||||
{:modified-at (dt/now)}
|
||||
{:id project-id})
|
||||
result))
|
||||
|
||||
(def ^:private
|
||||
schema:import-binfile
|
||||
(def ^:private schema:import-binfile
|
||||
[:map {:title "import-binfile"}
|
||||
[:name [:string {:max 250}]]
|
||||
[:name [:or [:string {:max 250}]
|
||||
[:map-of ::sm/uuid [:string {:max 250}]]]]
|
||||
[:project-id ::sm/uuid]
|
||||
[:version {:optional true} ::sm/int]
|
||||
[:file ::media/upload]])
|
||||
|
||||
(sv/defmethod ::import-binfile
|
||||
|
@ -88,12 +141,11 @@
|
|||
::webhooks/event? true
|
||||
::sse/stream? true
|
||||
::sm/params schema:import-binfile}
|
||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id name project-id file] :as params}]
|
||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id project-id version] :as params}]
|
||||
(projects/check-edition-permissions! pool profile-id project-id)
|
||||
(let [cfg (-> cfg
|
||||
(assoc ::bf.v1/project-id project-id)
|
||||
(assoc ::bf.v1/profile-id profile-id)
|
||||
(assoc ::bf.v1/name name))]
|
||||
(let [params (-> params
|
||||
(assoc :profile-id profile-id)
|
||||
(assoc :version (or version 1)))]
|
||||
(with-meta
|
||||
(sse/response #(import-binfile cfg (:path file)))
|
||||
(sse/response (partial import-binfile cfg params))
|
||||
{::audit/props {:file nil}})))
|
||||
|
|
|
@ -176,7 +176,7 @@
|
|||
|
||||
(binding [bfc/*state* (volatile! {:index {team-id (uuid/next)}})]
|
||||
(let [projs (bfc/get-team-projects cfg team-id)
|
||||
files (bfc/get-team-files cfg team-id)
|
||||
files (bfc/get-team-files-ids cfg team-id)
|
||||
frels (bfc/get-files-rels cfg files)
|
||||
|
||||
team (-> (db/get-by-id conn :team team-id)
|
||||
|
@ -396,14 +396,15 @@
|
|||
(defn clone-template
|
||||
[cfg {:keys [project-id profile-id] :as params} template]
|
||||
(db/tx-run! cfg (fn [{:keys [::db/conn ::wrk/executor] :as cfg}]
|
||||
;; NOTE: the importation process performs some operations that
|
||||
;; are not very friendly with virtual threads, and for avoid
|
||||
;; unexpected blocking of other concurrent operations we
|
||||
;; dispatch that operation to a dedicated executor.
|
||||
;; NOTE: the importation process performs some operations
|
||||
;; that are not very friendly with virtual threads, and for
|
||||
;; avoid unexpected blocking of other concurrent operations
|
||||
;; we dispatch that operation to a dedicated executor.
|
||||
(let [cfg (-> cfg
|
||||
(assoc ::bf.v1/project-id project-id)
|
||||
(assoc ::bf.v1/profile-id profile-id))
|
||||
result (px/invoke! executor (partial bf.v1/import-files! cfg template))]
|
||||
(assoc ::bf.v1/profile-id profile-id)
|
||||
(assoc ::bf.v1/input template))
|
||||
result (px/invoke! executor (partial bf.v1/import-files! cfg))]
|
||||
|
||||
(db/update! conn :project
|
||||
{:modified-at (dt/now)}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue