-
-
Save geraldodev/2925de9cf242101733af311baf552855 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns app.components.routes | |
(:require | |
[clojure.core.async :as a] | |
[clojure.java.io :as io] | |
[com.stuartsierra.component :as component] | |
[com.walmartlabs.lacinia.pedestal2 :as p2] | |
[io.pedestal.interceptor :as ped-interceptor] | |
[muuntaja.core :as m] | |
[reitit.coercion.spec] | |
[reitit.core :as reitit] | |
[reitit.dev.pretty :as pretty] | |
[reitit.http :as http] | |
[reitit.http.coercion :as coercion] | |
[reitit.http.interceptors.exception :as exception] | |
[reitit.http.interceptors.multipart :as multipart] | |
[reitit.http.interceptors.muuntaja :as muuntaja] | |
[reitit.http.interceptors.parameters :as parameters] | |
[reitit.interceptor :as re-interceptor] | |
[reitit.pedestal :as re-pedestal] | |
[reitit.ring :as ring] | |
[reitit.swagger :as swagger] | |
[reitit.swagger-ui :as swagger-ui] | |
) | |
[:import [com.walmartlabs.lacinia.schema CompiledSchema]] | |
) | |
(defn ^:private interceptor [number] | |
{:enter (fn [ctx] (a/go (update-in ctx [:request :number] (fnil + 0) number)))}) | |
(defn ->reitit-interceptor [i] | |
(if (ped-interceptor/interceptor? i) | |
(let [{:keys [name enter leave error]} i] | |
(cond-> {} | |
name (assoc :name name) | |
enter (assoc :enter enter) | |
leave (assoc :leave leave) | |
error (assoc :error | |
(fn [ctx] | |
(error (dissoc ctx :error) | |
(:error ctx)))))) | |
i)) | |
(defn named-route [m name] | |
(if name | |
(assoc m :name name) | |
m)) | |
(defn ->reitit-route | |
[v] | |
(if (vector? v) | |
(let [slug (first v) | |
{:keys [get head route-name post]} (into {} (->> (rest v) | |
(partition 2) | |
(mapv #(into [] %))))] | |
[slug | |
(cond-> {} | |
get (assoc :get (named-route {:handler get} route-name)) | |
head (assoc :head (named-route {:handler head} route-name)) | |
post (assoc :post (named-route {:handler post} route-name)) | |
(pos? (.indexOf slug "*")) (assoc :conflicting true) | |
)]) | |
v)) | |
(defn ->reitit-routes | |
[hash-routes] | |
(if (and (set? hash-routes) | |
(vector? (first hash-routes))) | |
(mapv ->reitit-route hash-routes) | |
hash-routes)) | |
(defn pedestal-interceptors-to-reitit | |
[coll] | |
(mapv ->reitit-interceptor coll)) | |
(def graphql-api-path "/graphql") | |
(def graphql-opts | |
{:api-path graphql-api-path | |
:asset-path "/assets/graphiql"}) | |
(defn ^:private mk-routes | |
[lac-schema] | |
(let [compiled-schema (:schema lac-schema) | |
_ (assert (instance? CompiledSchema compiled-schema)) | |
app-context {:foo :bar} | |
gql-interceptors (pedestal-interceptors-to-reitit (p2/default-interceptors compiled-schema app-context))] | |
; (do | |
; (require '[clojure.pprint]) | |
; (prn "classe " (type gql-interceptors)) | |
; (clojure.pprint/pprint gql-interceptors) | |
; ) | |
(re-pedestal/routing-interceptor | |
(http/router | |
(into | |
(into | |
(->reitit-routes (p2/graphiql-asset-routes (:asset-path graphql-opts))) | |
[["/ide" | |
{:get {:handler (p2/graphiql-ide-handler graphql-opts)}}] | |
[graphql-api-path | |
{:post {:interceptors gql-interceptors | |
; :parameters {:body any?} | |
}}]]) | |
[{:interceptors [;; swagger feature | |
swagger/swagger-feature | |
;; query-params & form-params | |
(parameters/parameters-interceptor) | |
;; content-negotiation | |
(muuntaja/format-negotiate-interceptor) | |
;; encoding response body | |
(muuntaja/format-response-interceptor) | |
;; exception handling | |
(exception/exception-interceptor) | |
;; decoding request body | |
(muuntaja/format-request-interceptor) | |
;; coercing response bodys | |
(coercion/coerce-response-interceptor) | |
;; coercing request parameters | |
(coercion/coerce-request-interceptor) | |
;; multipart | |
(multipart/multipart-interceptor)] } | |
["/custom-gql" | |
{:post {:handler | |
(fn [ctx] | |
{:status 200 :body | |
{"foo" "bar"}}) | |
:parameters {:body any?}}}] | |
["/swagger.json" | |
{:get {:no-doc true | |
:swagger {:info {:title "my-api" | |
:description "with pedestal & reitit-http"}} | |
:handler (swagger/create-swagger-handler)}}] | |
["/interceptors" | |
{:swagger {:tags ["interceptors"]} | |
:interceptors [(interceptor 1)]} | |
["/number" | |
{:interceptors [(interceptor 10)] | |
:get {:interceptors [(interceptor 100)] | |
:handler (fn [req] | |
{:status 200 | |
:body (select-keys req [:number])})}}]] | |
["/files" | |
{:swagger {:tags ["files"]}} | |
["/upload" | |
{:post {:summary "upload a file" | |
:parameters {:multipart {:file multipart/temp-file-part}} | |
:responses {200 {:body {:name string?, :size int?}}} | |
:handler (fn [{{{:keys [file]} :multipart} :parameters}] | |
{:status 200 | |
:body {:name (:filename file) | |
:size (:size file)}})}}] | |
["/download" | |
{:get {:summary "downloads a file" | |
:swagger {:produces ["image/png"]} | |
:handler (fn [_] | |
{:status 200 | |
:headers {"Content-Type" "image/png"} | |
:body (io/input-stream | |
(io/resource "reitit.png"))})}}]] | |
["/math" | |
{:swagger {:tags ["math"]}} | |
["/plus" | |
{:get {:summary "plus with spec query parameters" | |
:parameters {:query {:x int?, :y int?}} | |
:responses {200 {:body {:total int?}}} | |
:handler (fn [{{{:keys [x y]} :query} :parameters}] | |
{:status 200 | |
:body {:total (+ x y)}})} | |
:post {:summary "plus with spec body parameters" | |
:parameters {:body {:x int?, :y int?}} | |
:responses {200 {:body {:total int?}}} | |
:handler (fn [{{{:keys [x y]} :body} :parameters}] | |
{:status 200 | |
:body {:total (+ x y)}})}}]]]) | |
{;:reitit.interceptor/transform dev/print-context-diffs ;; pretty context diffs | |
;;:validate spec/validate ;; enable spec validation for route data | |
;;:reitit.spec/wrap spell/closed ;; strict top-level validation | |
:exception pretty/exception | |
; :data {:coercion reitit.coercion.spec/coercion | |
; :muuntaja m/instance | |
; } | |
}) | |
;; optional default ring handler (if no routes have matched) | |
(ring/routes | |
(swagger-ui/create-swagger-ui-handler | |
{:path "/" | |
:config {:validatorUrl nil | |
:operationsSorter "alpha"}}) | |
(ring/create-resource-handler) | |
(ring/create-default-handler))))) | |
;; it was #'app.servico/routes | |
(defrecord Routes [routes lac-schema] | |
component/Lifecycle | |
(start [this] | |
(if-not routes | |
(assoc this | |
:routes (mk-routes lac-schema)) | |
this)) | |
(stop [this] | |
(assoc this | |
:routes nil))) | |
(defn new-routes [] (map->Routes {})) | |
(comment | |
(ped-interceptor/interceptor {:enter (constantly {}) | |
:error (fn [ctx ex])} ) | |
(type #{}) | |
(set? #{}) | |
(->reitit-routes (p2/graphiql-asset-routes (:asset-path graphql-opts))) | |
(into {} (partition 2 (list :foo :bar :maria :silva))) | |
(into {} [[:foo :bar] (list :um :dois)]) | |
(any?) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment