/
api.clj
130 lines (111 loc) · 3.71 KB
/
api.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
(ns shadow.cljs.devtools.server.web.api
(:require
[clojure.edn :as edn]
[clojure.java.shell :as sh]
[clojure.tools.logging :as log]
[shadow.cljs.devtools.server.web.common :as common]
[shadow.build.closure :as closure]
[shadow.http.router :as http]
[shadow.repl :as repl]
[shadow.cljs.devtools.server.util :as server-util]
[shadow.cljs.devtools.api :as api]
[shadow.cljs.util :as util]
[hiccup.page :refer (html5)]
[clojure.java.io :as io]
[shadow.core-ext :as core-ext]))
(defn index-page [req]
{:status 200
:body "foo"})
(defn transform-level
[{::repl/keys [root-id level-id lang] :as level}]
(-> level
(select-keys [::repl/root-id ::repl/level-id ::repl/lang])
(assoc ::repl/ops (->> level
(keys)
(into #{})))))
(defn transform-root
[{::repl/keys [type levels] :as root}]
(-> root
(select-keys [::repl/root-id ::repl/type])
(assoc ::repl/levels
(->> levels
(map transform-level)
(into [])))))
(defn repl-roots [req]
(common/edn req
(->> (repl/roots)
(vals)
(map transform-root)
(into []))))
(defn repl-root [req root-id]
(common/edn req
(-> (repl/root root-id)
(transform-root))))
(defn repl-level [req root-id level-id]
(common/edn req
(-> (repl/level root-id level-id)
(transform-level))))
(defn open-file [{:keys [config ring-request] :as req}]
(let [data
(-> req
(get-in [:ring-request :body])
(slurp)
(edn/read-string))
{:keys [open-file-command]}
config
result
(try
(if-not open-file-command
{:exit 1
:err "no :open-file-command"}
(let [launch-args
(server-util/make-open-args data open-file-command)
result
(server-util/launch launch-args {})]
(log/debug ::open-file launch-args result)
result))
(catch Exception e
{:type :error
:ex-msg (.getMessage e)
:ex-data (ex-data e)}))]
{:status 200
:headers {"content-type" "application/edn; charset=utf-8"}
:body (core-ext/safe-pr-str result)}))
(defn get-bundle-info [{:keys [config] :as req} build-id]
(try
(let [file (io/file (:cache-root config) "builds" (name build-id) "release" "bundle-info.edn")]
(if (.exists file)
{:status 200
:header {"content-type" "application/edn"}
:body (slurp file)}
;; could generate this on-depend but that might take a long time
{:status 404
:body "Report not found. Run shadow-cljs release."}))
(catch Exception e
{:status 503
:body "Build failed."})))
(defn root* [req]
(http/route req
(:GET "" index-page)
(:GET "/repl" repl-roots)
(:GET "/repl/{root-id:long}" repl-root root-id)
(:GET "/repl/{root-id:long}/{level-id:long}" repl-level root-id level-id)
(:GET "/bundle-info/{build-id:keyword}" get-bundle-info build-id)
(:POST "/open-file" open-file)
common/not-found))
(defn root [{:keys [ring-request] :as req}]
;; not the cleanest CORS implementation but I want to call API methods from the client
(let [headers
{"Access-Control-Allow-Origin" "*"
"Access-Control-Allow-Headers"
(or (get-in ring-request [:headers "access-control-request-headers"])
"content-type")
"content-type" "application/edn; charset=utf-8"}]
(if-not (= :options (:request-method ring-request))
(-> req
(root*)
(update :headers merge headers))
{:status 200
:headers headers
:body ""}
)))