-
Notifications
You must be signed in to change notification settings - Fork 0
/
axios.cljc
107 lines (91 loc) · 3.11 KB
/
axios.cljc
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
(ns deepstate.action.axios
#?(:clj
(:require
[deepstate.action :as-alias action]))
#?(:cljs
(:require
[promesa.core :as p]
[deepstate.action :as action]
[deepstate.action.async :as action.async]))
#?(:cljs
(:require-macros
[deepstate.action.axios])))
;; you might think that :deepstate.action.api could be required with
;; an :as-alias to shorten the keywords below, but that would require
;; both :clj and :cljs :as-alias statements which compiles just fine,
;; but chokes cljdoc
#?(:cljs
(defn parse-axios-success-response
[{data :data
status :status
content-type :content-type
:as _r}]
{::action/schema :api
:deepstate.action.api/data data
:deepstate.action.api/status status
:deepstate.action.api/content-type content-type}))
#?(:cljs
(defn parse-axios-error-response
[r]
(let [{err-message :message
err-stack :stack
err-code :code
:as err-data} (-> r (.toJSON) (js->clj :keywordize-keys true))]
(p/rejected
{::action/schema :api
:deepstate.action.api/err-message err-message
:deepstate.action.api/err-stack err-stack
:deepstate.action.api/err-code err-code
:deepstate.action.api/org-err err-data}))))
#?(:cljs
(defn handle-axios-response
"parse API response branches into data"
[api-promise]
(p/handle
api-promise
(fn [succ err]
(if (some? err)
(parse-axios-error-response err)
(parse-axios-success-response succ))))))
#?(:cljs
(defn axios-action
"perform an axios-action - an async-action with
response parsing"
[key
action
axios-promise-or-axios-action-map
state]
(let [{axios-action ::action/axios
:as axios-action-map} (if (map? axios-promise-or-axios-action-map)
axios-promise-or-axios-action-map
{::action/axios axios-promise-or-axios-action-map})
axios-action-map (-> axios-action-map
(dissoc ::action/axios)
(assoc ::action/async
(handle-axios-response axios-action)))]
(action.async/async-action
key
action
axios-action-map
state))))
#?(:clj
(defmacro def-axios-action
"define an axios based async action - it's just an
async-action with a little parsing of the axios
responses to make things friendlier
cf `deepstate.action.async/def-async-action`
use the `::action/axios` key of the `action-map` to
provide the form returning the axios promise"
[key
[state-bindings action-bindings]
axios-promise-or-axios-action-map]
`(defmethod action/handle ~key
[action#]
(let [~action-bindings (action/remove-action-keys action#)]
(fn [state#]
(let [~state-bindings state#]
(axios-action
~key
action#
~axios-promise-or-axios-action-map
state#)))))))