       (let [tag (:tag type)
             name (:name type)]
         (cond
+          (= :list-type tag) :LIST ; has to be before :NON_NULL
           (:required type) :NON_NULL
           (and (= :basic-type tag)
                (contains? #{'Int 'Float 'String 'Boolean 'ID} name)) :SCALAR
           (= :basic-type tag) :OBJECT
-          (= :list-type tag) :LIST
           (= :type-definition tag) :OBJECT ; root query kind
           (= :union-definition tag) :UNION
           (= :interface-definition tag) :INTERFACE

                      (get-in field [:type :name]))
        type (:type field)
        kind (field-kind field)
        inner-type (get-in field [:type :inner-type])]
    (assert kind (format "field kind is nil for field: %s" field))
    (if (#{:LIST} kind)
      (assert inner-type (format "field inner-type is nil for field: %s" field)))
    (assert (or type-name inner-type) (format "field type-name and inner-type are both nil for field: %s" field))
    (if (= :NON_NULL kind)
      {:kind kind
       :inner-type (dissoc type :required)}
      {:name (:name field)
       :description (:description field)
       :args (:arguments field) ; defer resolving of arguments
       
       ;; :type nil ; defer resolving of type
       :type-name type-name
       :kind kind
       :inner-type inner-type
       :required (:required field)
       
       :isDeprecated false ; TODO
       :deprecationReason nil ; TODO
       })))

(defn type-resolver [type]
  (let [kind (type-kind type)

          :else (assert nil (format "Unhandled type kind for type: %s" type)))))))

(defn field-kind [field]
  (let [tag (:tag field)
        name (:name field)
        type (:type field)]
    (assert tag (format "field tag is nil for type: %s" field))
    (assert name (format "field name is nil for type: %s" field))
    (cond
      (= :type-field tag) (type-kind type)
      :else (throw (ex-info (format "unknown field kind for field: %s" field) {:field field})))))
