-
Notifications
You must be signed in to change notification settings - Fork 0
/
axios.cljc
101 lines (88 loc) · 3.16 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
(ns deepstate.action.axios
#?(:clj
(:require
[deepstate.action :as-alias action]
[deepstate.action.async :as action.async]))
#?(: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
"parse errored axios API responses"
[{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
"parse successful axios API responses"
[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 both axios API response branches"
[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
"function to perform an axios-action - an async-action with
response parsing. invoked from expansions of the `def-axios-action` macro"
[key
state
action
axios-promise-or-axios-handler-map]
(let [{axios-action ::action/axios
:as axios-action-map} (if (map? axios-promise-or-axios-handler-map)
axios-promise-or-axios-handler-map
{::action/axios axios-promise-or-axios-handler-map})
axios-action-map (-> axios-action-map
(dissoc ::action/axios)
(assoc ::action/async
(handle-axios-response axios-action)))]
(action.async/async-action
key
state
action
axios-action-map))))
#?(:clj
(defmacro def-axios-action
"define an axios based async action - it's like an
[[deepstate.action.async/def-async-action]] with parsing
of the axios responses to make things friendlier
use the `::action/axios` key of the `axios-promise-or-axios-handler-map`
to provide the form returning the axios promise"
[key
[_state-bindings _async-action-state-bindings _action-bindings :as bindings]
axios-promise-or-axios-handler-map]
`(action.async/def-async-action-bindings
~key
~bindings
~axios-promise-or-axios-handler-map
axios-action)))