0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-27 15:11:26 -05:00
penpot/frontend/src/app/main/repo.cljs
2024-06-19 16:15:48 +02:00

173 lines
5.5 KiB
Clojure

;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns app.main.repo
(:require
[app.common.data :as d]
[app.common.transit :as t]
[app.common.uri :as u]
[app.config :as cf]
[app.util.http :as http]
[app.util.sse :as sse]
[beicon.v2.core :as rx]
[cuerdas.core :as str]))
(defn handle-response
[{:keys [status body] :as response}]
(cond
(= 204 status)
;; We need to send "something" so the streams listening downstream can act
(rx/of nil)
(= 502 status)
(rx/throw (ex-info "http error" {:type :bad-gateway}))
(= 503 status)
(rx/throw (ex-info "http error" {:type :service-unavailable}))
(= 0 (:status response))
(rx/throw (ex-info "http error" {:type :offline}))
(= 200 status)
(rx/of body)
(= 413 status)
(rx/throw (ex-info "http error"
{:type :validation
:code :request-body-too-large}))
(and (>= status 400) (map? body))
(rx/throw (ex-info "http error" body))
:else
(rx/throw
(ex-info "http error"
{:type :unexpected-error
:status status
:data body}))))
(def default-options
{:update-file {:query-params [:id]}
:get-raw-file {:rename-to :get-file :raw-transit? true}
:create-file-object-thumbnail
{:query-params [:file-id :object-id :tag]
:form-data? true}
:create-file-thumbnail
{:query-params [:file-id :revn]
:form-data? true}
::sse/clone-template
{:response-type ::sse/stream}
::sse/import-binfile
{:response-type ::sse/stream
:form-data? true}
:export-binfile {:response-type :blob}
:retrieve-list-of-builtin-templates {:query-params :all}})
(defn- send!
"A simple helper for a common case of sending and receiving transit
data to the penpot mutation api."
[id params options]
(let [{:keys [response-type
form-data?
raw-transit?
query-params
rename-to]}
(-> (get default-options id)
(merge options))
decode-fn (if raw-transit?
http/conditional-error-decode-transit
http/conditional-decode-transit)
id (or rename-to id)
nid (name id)
method (cond
(= query-params :all) :get
(str/starts-with? nid "get-") :get
:else :post)
request {:method method
:uri (u/join cf/public-uri "api/rpc/command/" nid)
:credentials "include"
:headers {"accept" "application/transit+json,text/event-stream,*/*"
"x-external-session-id" (cf/external-session-id)}
:body (when (= method :post)
(if form-data?
(http/form-data params)
(http/transit-data params)))
:query (if (= method :get)
params
(if query-params
(select-keys params query-params)
nil))
:response-type
(if (= response-type ::sse/stream)
:stream
(or response-type :text))}
result (->> (http/send! request)
(rx/map decode-fn)
(rx/mapcat handle-response))]
(cond->> result
(= ::sse/stream response-type)
(rx/mapcat (fn [body]
(-> (sse/create-stream body)
(sse/read-stream t/decode-str)))))))
(defmulti cmd! (fn [id _] id))
(defmethod cmd! :default
[id params]
(send! id params nil))
(defmethod cmd! :login-with-oidc
[_ {:keys [provider] :as params}]
(let [uri (u/join cf/public-uri "api/auth/oauth/" (d/name provider))
params (dissoc params :provider)]
(->> (http/send! {:method :post
:uri uri
:credentials "include"
:headers {"x-external-session-id" (cf/external-session-id)}
:query params})
(rx/map http/conditional-decode-transit)
(rx/mapcat handle-response))))
(defn- send-export
[{:keys [blob?] :as params}]
(->> (http/send! {:method :post
:uri (u/join cf/public-uri "api/export")
:body (http/transit-data (dissoc params :blob?))
:headers {"x-external-session-id" (cf/external-session-id)}
:credentials "include"
:response-type (if blob? :blob :text)})
(rx/map http/conditional-decode-transit)
(rx/mapcat handle-response)))
(defmethod cmd! :export
[_ params]
(let [default {:wait false :blob? false}]
(send-export (merge default params))))
(derive :upload-file-media-object ::multipart-upload)
(derive :update-profile-photo ::multipart-upload)
(derive :update-team-photo ::multipart-upload)
(defmethod cmd! ::multipart-upload
[id params]
(->> (http/send! {:method :post
:uri (u/join cf/public-uri "api/rpc/command/" (name id))
:credentials "include"
:headers {"x-external-session-id" (cf/external-session-id)}
:body (http/form-data params)})
(rx/map http/conditional-decode-transit)
(rx/mapcat handle-response)))