re-graph icon indicating copy to clipboard operation
re-graph copied to clipboard

AppSync Support

Open lowecg opened this issue 1 year ago • 0 comments

Hi Oli,

I have re-graph working with AppSync and Cognito (Amplify), but I needed to make some changes to support subscription. I'll raise a PR very shortly to cast your eye over.

I needed to carefully configure re-graph using the JWT token from my Cognito authorised session. Might be worth getting this into the README?

(ns app.core
  (:require
    ...
    ["/aws-exports.js" :default aws-exports])) ;; generated by Amplify

(defn clj->json-str [obj]
  (.stringify js/JSON (clj->js obj)))

(defn str->base64 [s]
  (.btoa js/window s))

(defn extract-host [url]
  (-> url
      (string/replace #"^https?://" "")
      (string/split #"/")
      (first)))

(defn re-graph-appsync-init [{:keys [token] :as data}]
    (let [graphql-endpoint-url (.-aws_appsync_graphqlEndpoint aws-exports)
          ;; https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html
          graphql-endpoint-ws-url (-> graphql-endpoint-url
                                      (string/replace #"^https:" "wss:")
                                      (string/replace #"\.appsync-api\." ".appsync-realtime-api."))

          appsync-host (extract-host graphql-endpoint-url)
          header-b64 (str->base64 (clj->json-str {"Host" appsync-host, "Authorization" token}))
          payload-b64 (str->base64 (clj->json-str {})) ;; documentation states that an empty payload is required here
          graphql-endpoint-ws-url-with-auth (str graphql-endpoint-ws-url "?header=" header-b64 "&payload=" payload-b64)]
      (rf/dispatch
        [:re-graph.core/init
         {:ws   {:url                  graphql-endpoint-ws-url-with-auth
                 :supported-operations #{:subscribe}
                 :impl                 {:subscription-query-as-data? true ;; this also will cause extensions to be included in the subscription query payload
                                        :extensions                  {"authorization" {"Authorization" token
                                                                                       "host"          appsync-host}}}}

          :http {:url                  graphql-endpoint-url
                 :supported-operations #{:query :mutation}
                 :impl                 {:with-credentials? false
                                        :headers           {"Authorization" token}}}}])))

lowecg avatar Nov 11 '24 14:11 lowecg