Last active
May 23, 2017 19:02
-
-
Save danielneal/ae3a1b6ddfc52393dd18c859464a6ec3 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.graphql | |
(:require [om.next :as om] | |
[clojure.string :as str] | |
[clojure.set :as set])) | |
(defn graphql-type [v] | |
(cond | |
(string? v) "String" | |
(int? v) "Int" | |
(float? v) "Float" | |
(boolean? v) "Boolean" | |
:else "String")) | |
(def graphql-symbols | |
{::arg-brace-left "(" | |
::arg-brace-right ")" | |
::arg-list-separator "," | |
::arg-separator ":" | |
::arg-signifier "$" | |
::field-brace-left "{" | |
::field-brace-right "}" | |
::separator " " | |
::query-signifier "query " | |
::union-signifier "... on"}) | |
(defn params->graphql [params] | |
(let [variables (set (for [[k v] params] | |
{:name (name k) | |
:unique-name (gensym (name k)) | |
:type (graphql-type v) | |
:value v}))] | |
{:query [::arg-brace-left | |
(->> (for [{:keys [name unique-name]} variables] | |
[name ::arg-separator ::arg-signifier unique-name]) | |
(interpose ::arg-list-separator)) | |
::arg-brace-right] | |
:variables variables})) | |
(defmulti node->graphql :type) | |
(defmethod node->graphql :prop | |
[node] | |
(let [{:keys [dispatch-key params]} node | |
graphql-params (some-> params params->graphql)] | |
{:query [(name dispatch-key) (:query graphql-params)] | |
:variables (:variables graphql-params)})) | |
(defmethod node->graphql :join | |
[node] | |
(let [{:keys [dispatch-key children params query]} node | |
graphql (map node->graphql children) | |
graphql-params (some-> params params->graphql)] | |
{:query [(name dispatch-key) | |
(:query graphql-params) | |
::separator | |
::field-brace-left | |
(->> (map :query graphql) | |
(interpose ::separator)) | |
::field-brace-right] | |
:variables (apply set/union (:variables graphql-params) (map :variables graphql))})) | |
(defmethod node->graphql :union-entry | |
[node] | |
(let [{:keys [children union-key]} node | |
graphql (map node->graphql children)] | |
{:query [::union-signifier ::separator (name union-key) ::separator | |
::field-brace-left | |
(->> (map :query graphql) | |
(interpose ::separator)) | |
::field-brace-right] | |
:variables (apply set/union (map :variables graphql))})) | |
(defmethod node->graphql :union | |
[node] | |
(let [{:keys [children]} node | |
graphql (map node->graphql children)] | |
{:query (->> (map :query graphql) | |
(interpose ::separator)) | |
:variables (apply set/union (map :variables graphql))})) | |
(defmethod node->graphql :root | |
[node] | |
(let [{:keys [children]} node | |
graphql (map node->graphql children)] | |
{:query [::field-brace-left | |
(->> (map :query graphql) | |
(interpose ::separator)) | |
::field-brace-right] | |
:variables (apply set/union (map :variables graphql))})) | |
(defn wrap-top-level-query [{:keys [query variables]}] | |
[::query-signifier | |
::separator | |
(when (seq variables) | |
[::arg-brace-left (->> (for [{:keys [unique-name type]} variables] | |
[::arg-signifier unique-name ::arg-separator type]) | |
(interpose ::arg-list-separator)) | |
::arg-brace-right]) | |
query]) | |
(defn query->graphql [query] | |
(let [ast (om/query->ast query) | |
{:keys [variables] :as graphql} (node->graphql ast)] | |
{:query (str/join (map #(get graphql-symbols % %) (flatten (wrap-top-level-query graphql)))) | |
:variables (->> (for [{:keys [unique-name value] :as v} variables] | |
[unique-name value]) | |
(into {}))})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment