Repository: wilkerlucio/pathom
Pull request #68 (2018-12-08 02:42:01)

Feature/clj http+GitHub starts


Patch:
diff --git a/deps.edn b/deps.edn
index 0c2a4935..a32dcefe 100644
--- a/deps.edn
+++ b/deps.edn
@@ -25,7 +25,8 @@
                  com.wsscode/pathom-viz     {:mvn/version "1.0.3"}}}
 
   :http-drivers
-  {:extra-deps {clj-http {:mvn/version "3.8.0"}}}
+  {:extra-deps {clj-http          {:mvn/version "3.8.0"}
+                cheshire/cheshire {:mvn/version "5.8.1"}}}
 
   :profile
   {:extra-deps {criterium {:mvn/version "0.4.4"}}}
diff --git a/project.clj b/project.clj
index f8772a32..662cbef5 100644
--- a/project.clj
+++ b/project.clj
@@ -16,6 +16,7 @@
 
                  ; provided
 
+                 [cheshire/cheshire "5.8.1" :scope "provided"]
                  [fulcrologic/fulcro "2.6.0" :scope "provided"]
                  [org.clojure/clojure "1.9.0" :scope "provided"]
                  [org.clojure/clojurescript "1.9.946" :scope "provided"]
diff --git a/src-docs/com/wsscode/pathom/book/graphql/github_stars_clj.clj b/src-docs/com/wsscode/pathom/book/graphql/github_stars_clj.clj
new file mode 100644
index 00000000..69728470
--- /dev/null
+++ b/src-docs/com/wsscode/pathom/book/graphql/github_stars_clj.clj
@@ -0,0 +1,52 @@
+(ns com.wsscode.pathom.book.graphql.github-stars-clj
+  (:require
+    [com.wsscode.common.async-clj :refer [go-promise <?]]
+    [com.wsscode.pathom.connect :as pc]
+    [com.wsscode.pathom.connect.graphql :as pcg]
+    [com.wsscode.pathom.core :as p]
+    [com.wsscode.pathom.diplomat.http :as p.http]
+    [com.wsscode.pathom.diplomat.http.clj-http :as http.clj-http]))
+
+(defonce indexes (atom {}))
+
+(pc/defresolver repositories [_ _]
+  {::pc/output [{:demo-repos [:github.user/login :github.repository/name]}]}
+  {:demo-repos
+   [{:github.user/login "wilkerlucio" :github.repository/name "pathom"}
+    {:github.user/login "fulcrologic" :github.repository/name "fulcro"}
+    {:github.user/login "fulcrologic" :github.repository/name "fulcro-inspect"}
+    {:github.user/login "fulcrologic" :github.repository/name "fulcro-css"}
+    {:github.user/login "fulcrologic" :github.repository/name "fulcro-spec"}
+    {:github.user/login "thheller" :github.repository/name "shadow-cljs"}]})
+
+(def github-gql
+  {::pcg/url       (str "https://api.github.com/graphql?access_token=" (System/getenv "GITHUB_TOKEN"))
+   ::pcg/prefix    "github"
+   ::pcg/ident-map {"user"       {"login" ["User" "login"]}
+                    "repository" {"owner" ["User" "login"]
+                                  "name"  ["Repository" "name"]}}
+   ::p.http/driver http.clj-http/request-async})
+
+(def parser
+  (p/parallel-parser
+    {::p/env     {::p/reader               [p/map-reader
+                                            pc/parallel-reader
+                                            pc/open-ident-reader
+                                            p/env-placeholder-reader]
+                  ::p/placeholder-prefixes #{">"}
+                  ::p.http/driver          http.clj-http/request-async}
+     ::p/mutate  pc/mutate-async
+     ::p/plugins [(pc/connect-plugin {::pc/register repositories
+                                      ::pc/indexes  indexes})
+                  p/error-handler-plugin
+                  p/request-cache-plugin
+                  p/trace-plugin]}))
+
+(defonce github-index-status
+  (go-promise
+    (<? (pcg/load-index github-gql indexes))))
+
+(comment
+  (require '[clojure.core.async :as async])
+  (async/<!! (parser {} [{[:github.user/login "wilkerlucio"]
+                          [:github.user/created-at]}])))
diff --git a/src/com/wsscode/pathom/connect/graphql.cljc b/src/com/wsscode/pathom/connect/graphql.cljc
index 6ce5e18f..b2ee7cc3 100644
--- a/src/com/wsscode/pathom/connect/graphql.cljc
+++ b/src/com/wsscode/pathom/connect/graphql.cljc
@@ -337,6 +337,7 @@
 
 (defn request [{::keys [url] :as env} query]
   (let-chan [response (p.http/request (assoc env ::p.http/url url
+                                                 ::p.http/content-type ::p.http/json
                                                  ::p.http/method ::p.http/post
                                                  ::p.http/as ::p.http/json
                                                  ::p.http/form-params {:query (if (string? query) query (query->graphql query))}))]
diff --git a/src/com/wsscode/pathom/diplomat/http.cljc b/src/com/wsscode/pathom/diplomat/http.cljc
index 984ce7ce..b1341a82 100644
--- a/src/com/wsscode/pathom/diplomat/http.cljc
+++ b/src/com/wsscode/pathom/diplomat/http.cljc
@@ -23,8 +23,9 @@
                                ::debug?
                                ::body]))
 
-(s/def ::response (s/keys :req [::headers]
-                          :opt [::body]))
+(s/def ::response (s/keys :req [::status]
+                          :opt [::headers
+                                ::body]))
 
 (s/def ::driver fn?)
 
diff --git a/src/com/wsscode/pathom/diplomat/http/clj_http.clj b/src/com/wsscode/pathom/diplomat/http/clj_http.clj
index 910214a8..d943f46d 100644
--- a/src/com/wsscode/pathom/diplomat/http/clj_http.clj
+++ b/src/com/wsscode/pathom/diplomat/http/clj_http.clj
@@ -1,25 +1,54 @@
 (ns com.wsscode.pathom.diplomat.http.clj-http
   (:require [clj-http.client :as client]
             [com.wsscode.pathom.diplomat.http :as http]
-            [clojure.spec.alpha :as s]))
+            [clojure.spec.alpha :as s]
+            [com.wsscode.common.async-clj :refer [go-catch go-promise]]
+            [clojure.core.async :as async]))
 
-;; TODO: ::http/form-params, ::http/debug?
+;; TODO: ::http/debug?
 (defn build-request-map
-  [{::http/keys [url content-type accept as body headers] :as req}]
+  [{::http/keys [url content-type accept as body headers form-params] :as req}]
   (let [q? (partial contains? req)]
     (cond-> {:url    url
              :method (keyword (http/request-method req))}
             (q? ::http/headers) (assoc :headers headers)
-            (q? ::http/content-type) (assoc :content-type (http/encode-type->header content-type))
+            (q? ::http/content-type) (assoc :content-type (keyword (name content-type)))
             (q? ::http/accept) (assoc :accept (http/encode-type->header accept))
-            (q? ::http/as) (assoc :as (http/encode-type->header as))
+            (q? ::http/as) (assoc :as (keyword (name as)))
+            (q? ::http/form-params) (assoc :form-params form-params)
             (q? ::http/body) (assoc :body body))))
 
+(defn build-response-map
+  [{:keys [status body headers]
+    :as   response}]
+  (with-meta {::http/status  status
+              ::http/body    body
+              ::http/headers headers}
+             response))
+
 (defn request [req]
   (s/assert ::http/request req)
   (-> req
       build-request-map
-      client/request))
+      client/request
+      build-response-map))
+
+(defn request-async
+  [req]
+  (s/assert ::http/request req)
+  (let [chan (async/promise-chan)
+        raise (fn request-async-raise [ex]
+                (async/put! chan ex))
+        respond (fn request-async-respond [response]
+                  (try
+                    (async/put! chan (build-response-map response))
+                    (catch Throwable e
+                      (raise e))))]
+    (-> req
+        build-request-map
+        (assoc :async? true)
+        (client/request respond raise))
+    chan))
 
 (s/fdef request
   :args (s/cat :request ::http/request)


Test patch:
diff --git a/test/com/wsscode/pathom/diplomat/http/clj_http_test.clj b/test/com/wsscode/pathom/diplomat/http/clj_http_test.clj
index 36d7929f..73050042 100644
--- a/test/com/wsscode/pathom/diplomat/http/clj_http_test.clj
+++ b/test/com/wsscode/pathom/diplomat/http/clj_http_test.clj
@@ -18,4 +18,4 @@
                   ::p.http/content-type ::p.http/json}
                  {:url          "/foo"
                   :method       :get
-                  :content-type "application/json"}))
+                  :content-type :json}))