-
Notifications
You must be signed in to change notification settings - Fork 0
/
api_3.cljs
119 lines (101 loc) · 2.51 KB
/
api_3.cljs
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
(ns dgknght.app-lib.api-3
(:refer-clojure :exclude [get])
(:require [cljs.core.async :as a]
[cljs.pprint :refer [pprint]]
[cljs-http.client :as http]
[dgknght.app-lib.api :as og]))
(defrecord Error [message])
(def default-opts
{:headers {"Content-Type" "application/json"
"Accept" "application/json"}})
(def path og/path)
(defn- singular?
[v]
(and v
(not (sequential? v))))
(defn- pluralize
[x]
(if x
(if (singular? x)
[x]
x)
[]))
(def ^:private status-msgs
{404 "Not found"
403 "Forbidden"
401 "Unauthorized"
500 "Server error"})
(defn- extract-msg
[{:keys [body status]}]
(or (:message body)
(:error body)
(status-msgs status)
"Unknown"))
(defn- handle-non-success-status
[{:keys [status] :as res}]
(if (<= 200 status 299)
res
(throw (ex-info "non success response" {::message (extract-msg res)}))))
(defn- non-success-msg
[e]
(-> e ex-data ::message))
(defn- build-xf
[{:keys [pre-xf post-xf]}]
(apply comp
(concat (pluralize pre-xf)
[(map handle-non-success-status)
(map #(or (:body %) %))]
(pluralize post-xf))))
(defn- ex-handler
[{:keys [on-error]}]
(fn [e]
(if-let [msg (non-success-msg e)]
(->Error msg)
(if on-error
(on-error e)
(->Error (.getMessage e))))))
(defn- build-chan
[opts]
(a/chan 1 (build-xf opts) (ex-handler opts)))
(defn- wait-and-callback
[ch {:keys [on-success
on-failure
callback]
:or {on-success identity
on-failure identity
callback identity}}]
(a/go
(let [res (a/<! ch)]
(callback)
(if (instance? Error res)
(on-failure (:message res))
(on-success res)))))
(defn- build-req
[opts]
(-> default-opts
(merge opts)
(update-in [:channel] #(or % (build-chan opts)))))
(defn get
([uri] (get uri {}))
([uri opts]
(wait-and-callback
(http/get uri (build-req opts))
opts)))
(defn post
([uri resource] (post uri resource {}))
([uri resource opts]
(wait-and-callback
(http/post uri (assoc (build-req opts) :json-params resource))
opts)))
(defn patch
([uri resource] (patch uri resource {}))
([uri resource opts]
(wait-and-callback
(http/patch uri (assoc (build-req opts) :json-params resource))
opts)))
(defn delete
([uri] (delete uri {}))
([uri opts]
(wait-and-callback
(http/delete uri (build-req opts))
opts)))