diff --git a/source/AirGQL/GraphQL.hs b/source/AirGQL/GraphQL.hs
index f13696d..d678437 100644
--- a/source/AirGQL/GraphQL.hs
+++ b/source/AirGQL/GraphQL.hs
@@ -106,7 +106,7 @@ import AirGQL.Lib (
   AccessMode (ReadAndWrite, ReadOnly, WriteOnly),
   ColumnEntry (column_name, datatype, datatype_gql),
   GqlTypeName (root),
-  TableEntryRaw (name),
+  TableEntry (name),
   column_name_gql,
   getColumns,
  )
@@ -433,7 +433,7 @@ queryType
   :: Connection
   -> AccessMode
   -> Text
-  -> [TableEntryRaw]
+  -> [TableEntry]
   -> IO (Out.ObjectType IO)
 queryType connection accessMode dbId tables = do
   let
@@ -700,7 +700,7 @@ queryType connection accessMode dbId tables = do
     getResolvers :: IO (HashMap.HashMap Text (Resolver IO))
     getResolvers = do
       let
-        getTableTuple :: TableEntryRaw -> IO (Text, Resolver IO)
+        getTableTuple :: TableEntry -> IO (Text, Resolver IO)
         getTableTuple table = do
           outField <- getOutField table.name
           pure
@@ -741,7 +741,7 @@ queryType connection accessMode dbId tables = do
   --   getTableTuples <&> HashMap.fromList
 
   resolvers <- getResolvers
-  schemaResolver <- getSchemaResolver dbId connection accessMode tables
+  schemaResolver <- getSchemaResolver accessMode tables
 
   -- resolversPrimaryKey <- getResolversPrimaryKey
   let
@@ -1092,7 +1092,7 @@ mutationType
   -> Integer
   -> AccessMode
   -> Text
-  -> [TableEntryRaw]
+  -> [TableEntry]
   -> IO (Maybe (Out.ObjectType IO))
 mutationType connection maxRowsPerTable accessMode dbId tables = do
   let
@@ -1229,7 +1229,6 @@ mutationType connection maxRowsPerTable accessMode dbId tables = do
       columnEntries <- liftIO $ getColumns dbId connection tableName
 
       context <- ask
-
       let
         columnNames :: [Text]
         columnNames =
@@ -1602,7 +1601,7 @@ mutationType connection maxRowsPerTable accessMode dbId tables = do
     getMutationResolvers :: IO (HashMap.HashMap Text (Resolver IO))
     getMutationResolvers = do
       let
-        getInsertTableTuple :: TableEntryRaw -> IO (Text, Resolver IO)
+        getInsertTableTuple :: TableEntry -> IO (Text, Resolver IO)
         getInsertTableTuple table = do
           outFieldInsertion <- getOutField table.name
           pure
@@ -1612,7 +1611,7 @@ mutationType connection maxRowsPerTable accessMode dbId tables = do
                 (executeDbInserts table.name)
             )
 
-        getUpdateTableTuple :: TableEntryRaw -> IO (Text, Resolver IO)
+        getUpdateTableTuple :: TableEntry -> IO (Text, Resolver IO)
         getUpdateTableTuple table = do
           outFieldUpdate <- getOutFieldUpdate table.name
           pure
@@ -1622,7 +1621,7 @@ mutationType connection maxRowsPerTable accessMode dbId tables = do
                 (executeDbUpdates table.name)
             )
 
-        getDeleteTableTuple :: TableEntryRaw -> IO (Text, Resolver IO)
+        getDeleteTableTuple :: TableEntry -> IO (Text, Resolver IO)
         getDeleteTableTuple table = do
           outFieldDeletion <- getOutFieldDeletion table.name
           pure
@@ -1654,7 +1653,7 @@ getDerivedSchema
   :: SchemaConf
   -> Connection
   -> Text
-  -> [TableEntryRaw]
+  -> [TableEntry]
   -> IO (Schema IO)
 getDerivedSchema schemaConf connection dbId tables = do
   let sqlitePragmas = getSQLitePragmas schemaConf.pragmaConf
diff --git a/source/AirGQL/Introspection.hs b/source/AirGQL/Introspection.hs
index 54eb20c..280a275 100644
--- a/source/AirGQL/Introspection.hs
+++ b/source/AirGQL/Introspection.hs
@@ -1,2559 +1,360 @@
 module AirGQL.Introspection (
-  getSchemaResolver,
   typeNameResolver,
-  createType,
+  getSchemaResolver,
 )
 where
 
 import Protolude (
   Applicative (pure),
-  Bool (False, True),
-  Eq ((/=)),
-  Foldable (null),
+  Either (Left, Right),
   IO,
-  Int,
-  IsString,
   Maybe (Just, Nothing),
-  MonadReader (ask),
   Monoid (mempty),
-  Num ((+)),
-  Ord ((<)),
   Semigroup ((<>)),
   Text,
-  concat,
-  filter,
-  forM,
   fromMaybe,
-  not,
   ($),
   (&),
   (<&>),
-  (>>=),
  )
+import Protolude qualified as P
 
-import Data.HashMap.Strict as HashMap (
-  HashMap,
-  empty,
-  fromList,
-  lookup,
-  singleton,
- )
-import Database.SQLite.Simple (Connection)
-import Language.GraphQL.Type (
-  Value (Boolean, List, Null, Object, String),
-  boolean,
-  string,
- )
-import Language.GraphQL.Type.In as In (Type (NamedScalarType))
+import Data.HashMap.Strict as HashMap (HashMap, singleton)
 import Language.GraphQL.Type.Out as Out (
-  Context (values),
   Field (Field),
   Resolver (ValueResolver),
-  Type (
-    ListType,
-    NamedObjectType,
-    NamedScalarType,
-    NonNullListType,
-    NonNullObjectType,
-    NonNullScalarType
-  ),
+  Type (NonNullScalarType),
  )
 
-import AirGQL.GQLWrapper (
-  InArgument (InArgument, argDescMb, argType, valueMb),
-  OutField (OutField, arguments, descriptionMb, fieldType),
-  inArgumentToArgument,
-  outFieldToField,
- )
+import AirGQL.Introspection.Resolver (makeType)
+import AirGQL.Introspection.Types (IntrospectionType)
+import AirGQL.Introspection.Types qualified as Type
 import AirGQL.Lib (
-  AccessMode (ReadAndWrite, ReadOnly, WriteOnly),
+  AccessMode,
   ColumnEntry,
   GqlTypeName (full),
-  TableEntryRaw (name),
+  TableEntry (columns, name),
+  canRead,
+  canWrite,
   column_name_gql,
   datatype_gql,
-  getColumns,
   isOmittable,
   notnull,
-  select_options,
- )
-import AirGQL.Types.OutObjectType (
-  OutObjectType (OutObjectType, descriptionMb, fields, interfaceTypes, name),
-  outObjectTypeToObjectType,
  )
+import Control.Monad (MonadFail (fail))
+import Data.Text qualified as T
 import DoubleXEncoding (doubleXEncodeGql)
-
-
-emptyType :: Value
-emptyType =
-  Object $ HashMap.singleton "kind" "OBJECT"
-
-
-intType :: Value
-intType =
-  Object $
-    HashMap.fromList
-      [ ("__typename", "__Type")
-      , ("kind", "SCALAR")
-      , ("name", "Int")
-      ,
-        ( "description"
-        , "The `Int` scalar type represents \
-          \non-fractional signed whole numeric values. \
-          \Int can represent values between -(2^31) and 2^31 - 1."
-        )
-      ]
-
-
-floatType :: Value
-floatType =
-  Object $
-    HashMap.fromList
-      [ ("__typename", "__Type")
-      , ("kind", "SCALAR")
-      , ("name", "Float")
-      ,
-        ( "description"
-        , "Signed double-precision floating-point value."
-        )
-      ]
-
-
-stringType :: Value
-stringType =
-  Object $
-    HashMap.fromList
-      [ ("__typename", "__Type")
-      , ("kind", "SCALAR")
-      , ("name", "String")
-      ,
-        ( "description"
-        , "The `String` scalar type represents textual data, \
-          \represented as UTF-8 character sequences. \
-          \The String type is most often used by GraphQL \
-          \to represent free-form human-readable text."
-        )
-      ]
-
-
-booleanType :: Value
-booleanType =
-  Object $
-    HashMap.fromList
-      [ ("__typename", "__Type")
-      , ("kind", "SCALAR")
-      , ("name", "Boolean")
-      ,
-        ( "description"
-        , "The `Boolean` scalar type represents `true` or `false`."
-        )
-      ]
-
-
-nonNullString :: Out.Field IO
-nonNullString =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "nonNullString description"
-      , fieldType = Out.NonNullScalarType string
-      , arguments = HashMap.empty
-      }
-
-
-nullableString :: Out.Field IO
-nullableString =
-  Out.Field
-    (Just "nullableString")
-    (Out.NamedScalarType string)
-    HashMap.empty
-
-
-nonNullBoolean :: Out.Field IO
-nonNullBoolean =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "nonNullBoolean description"
-      , fieldType = Out.NonNullScalarType boolean
-      , arguments = HashMap.empty
-      }
-
-
-getTypeTuple :: (IsString a) => Value -> Value -> (a, Value)
-getTypeTuple theKind theType =
-  ( "type"
-  , Object $
-      HashMap.fromList
-        [ ("kind", theKind)
-        , ("name", theType)
-        ]
-  )
-
-
-nonNullType :: Value -> Value
-nonNullType inner =
-  Object $
-    HashMap.fromList
-      [ ("kind", "NON_NULL")
-      , ("ofType", inner)
-      ]
-
-
-listType :: Value -> Value
-listType inner =
-  Object $
-    HashMap.fromList
-      [ ("kind", "LIST")
-      , ("ofType", inner)
-      ]
-
-
-createType :: Text -> Text -> [Value] -> [Text] -> Text -> Value
-createType rootName description args nestedTypes name =
-  let
-    createChildType :: [Text] -> Text -> Value
-    createChildType nestedChildTypes childName =
-      case nestedChildTypes of
-        [] -> Null
-        (childHeadKind : childRestKinds) ->
-          if not $ null childRestKinds
-            then
-              Object $
-                HashMap.fromList
-                  [ ("kind", String childHeadKind)
-                  , ("ofType", createChildType childRestKinds childName)
-                  ]
-            else
-              Object $
-                HashMap.fromList
-                  [ ("kind", String childHeadKind)
-                  , ("name", String name)
-                  ]
-  in
-    case nestedTypes of
-      [] -> Null
-      kinds ->
-        Object $
-          HashMap.fromList
-            ( [ ("name", String rootName)
-              , ("description", String description)
-              , ("type", createChildType kinds name)
-              ]
-                <> if null args then [] else [("args", List args)]
-            )
-
-
-createField :: Text -> Maybe Text -> Value -> Value
-createField name descriptionMb type_ =
-  Object $
-    HashMap.fromList
-      [ ("name", String name)
-      , ("type", type_)
-      ]
-      <> case descriptionMb of
-        Nothing -> mempty
-        Just description ->
-          HashMap.singleton
-            "description"
-            (String description)
-
-
-nameField :: Value
-nameField =
-  Object $
-    HashMap.fromList
-      [ ("name", "name")
-      ,
-        ( "type"
-        , nonNullType $
-            Object $
-              HashMap.fromList
-                [ ("kind", "SCALAR")
-                , ("name", "String")
-                ]
-        )
-      ]
-
-
-descriptionField :: Value
-descriptionField =
-  Object $
-    HashMap.fromList
-      [ ("name", "description")
-      , getTypeTuple "SCALAR" "String"
-      ]
-
-
-argsFieldValue :: Value
-argsFieldValue =
-  Object $
-    HashMap.fromList
-      [ ("name", "args")
-      ,
-        ( "type"
-        , nonNullType $
-            listType $
-              nonNullType $
-                Object $
-                  HashMap.fromList
-                    [ ("kind", "OBJECT")
-                    , ("name", "__InputValue")
-                    ]
-        )
-      ]
-
-
-locationsFieldValue :: Value
-locationsFieldValue =
-  Object $
-    HashMap.fromList
-      [ ("name", "locations")
-      ,
-        ( "type"
-        , nonNullType $
-            listType $
-              nonNullType $
-                Object $
-                  HashMap.fromList
-                    [ ("kind", "ENUM")
-                    , ("name", "__DirectiveLocation")
-                    ]
-        )
-      ]
-
-
-typeFieldValue :: Value
-typeFieldValue =
-  Object $
-    HashMap.fromList
-      [ ("name", "type")
-      ,
-        ( "type"
-        , nonNullType $
-            Object $
-              HashMap.fromList
-                [ ("kind", "OBJECT")
-                , ("name", "__Type")
-                ]
-        )
-      ]
-
-
-isDeprecatedFieldValue :: Value
-isDeprecatedFieldValue =
-  Object $
-    HashMap.fromList
-      [ ("name", "isDeprecated")
-      ,
-        ( "type"
-        , nonNullType $
-            Object $
-              HashMap.fromList
-                [ ("kind", "SCALAR")
-                , ("name", "Boolean")
-                ]
-        )
-      ]
-
-
-typeType :: Int -> Out.Type IO
-typeType level =
-  Out.NamedObjectType $
-    outObjectTypeToObjectType $
-      OutObjectType
-        { name = "__Type"
-        , descriptionMb = Just "__Type description"
-        , interfaceTypes = []
-        , fields =
-            HashMap.fromList $
-              [
-                ( "__typename"
-                , ValueResolver nonNullString $ pure "__Type"
-                )
-              ,
-                ( "kind"
-                , ValueResolver nonNullString $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe "ERROR: kind" $
-                            HashMap.lookup "kind" obj
-                      _ -> pure "ERROR: kind"
-                )
-              ,
-                ( "name"
-                , ValueResolver nullableString $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe Null $
-                            HashMap.lookup "name" obj
-                      _ -> pure Null
-                )
-              ,
-                ( "description"
-                , ValueResolver nullableString $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe Null $
-                            HashMap.lookup "description" obj
-                      _ -> pure Null
-                )
-              ,
-                ( "fields"
-                , ValueResolver fieldsField $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe Null $
-                            HashMap.lookup "fields" obj
-                      _ -> pure Null
-                )
-              ,
-                ( "possibleTypes"
-                , ValueResolver typesField $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe Null $
-                            HashMap.lookup "possibleTypes" obj
-                      _ -> pure Null
-                )
-              ,
-                ( "interfaces"
-                , ValueResolver typesField $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe (List []) $
-                            HashMap.lookup "interfaces" obj
-                      _ -> pure $ List []
-                )
-              ,
-                ( "inputFields"
-                , ValueResolver inputsFieldsField $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe Null $
-                            HashMap.lookup "inputFields" obj
-                      _ -> pure Null
-                )
-              ,
-                ( "enumValues"
-                , ValueResolver enumValuesField $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe Null $
-                            HashMap.lookup "enumValues" obj
-                      _ -> pure Null
-                )
-              ]
-                <> ( if level < 7
-                      then
-                        [
-                          ( "ofType"
-                          , ValueResolver (typeField $ level + 1) $ do
-                              context <- ask
-                              case context & Out.values of
-                                Object obj ->
-                                  pure $
-                                    fromMaybe Null $
-                                      HashMap.lookup "ofType" obj
-                                _ -> pure Null
-                          )
-                        ]
-                      else []
-                   )
-        }
-
-
-typeField :: Int -> Field IO
-typeField level =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "typeField description"
-      , fieldType = typeType level
-      , arguments = HashMap.empty
-      }
-
-
-typesField :: Field IO
-typesField =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "typesField description"
-      , fieldType = Out.ListType $ typeType 0
-      , arguments = HashMap.empty
-      }
-
-
-inputValueType :: Out.Type IO
-inputValueType =
-  Out.NonNullObjectType $
-    outObjectTypeToObjectType $
-      OutObjectType
-        { name = "__InputValue"
-        , descriptionMb = Just "__InputValue description"
-        , interfaceTypes = []
-        , fields =
-            HashMap.fromList
-              [
-                ( "__typename"
-                , ValueResolver nonNullString $ pure "__InputValue"
-                )
-              ,
-                ( "name"
-                , ValueResolver nonNullString $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe "ERROR: name" $
-                            HashMap.lookup "name" obj
-                      _ -> pure "ERROR: name"
-                )
-              ,
-                ( "description"
-                , ValueResolver nullableString $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe Null $
-                            HashMap.lookup "description" obj
-                      _ -> pure Null
-                )
-              ,
-                ( "defaultValue"
-                , ValueResolver nullableString $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe Null $
-                            HashMap.lookup "defaultValue" obj
-                      _ -> pure Null
-                )
-              ,
-                ( "type"
-                , ValueResolver (typeField 0) $ do
-                    context <- ask
-                    case context & Out.values of
-                      Object obj ->
-                        pure $
-                          fromMaybe emptyType $
-                            HashMap.lookup "type" obj
-                      _ -> pure emptyType
-                )
-              ]
-        }
-
-
-argsField :: Field IO
-argsField =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "argsField description"
-      , fieldType = Out.NonNullListType inputValueType
-      , arguments = HashMap.empty
-      }
-
-
-inputsFieldsField :: Field IO
-inputsFieldsField =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "inputsFieldsField description"
-      , fieldType = Out.ListType inputValueType
-      , arguments = HashMap.empty
-      }
-
-
-enumValuesType :: Out.Type IO
-enumValuesType =
-  Out.ListType $
-    Out.NonNullObjectType $
-      outObjectTypeToObjectType $
-        OutObjectType
-          { name = "__EnumValue"
-          , descriptionMb = Just "__EnumValue description"
-          , interfaceTypes = []
-          , fields =
-              HashMap.fromList
-                [
-                  ( "__typename"
-                  , ValueResolver nonNullString $ pure "__EnumValue"
-                  )
-                ,
-                  ( "name"
-                  , ValueResolver nonNullString $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe "ERROR: name" $
-                              HashMap.lookup "name" obj
-                        _ -> pure "ERROR: name"
-                  )
-                ,
-                  ( "description"
-                  , ValueResolver nullableString $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe Null $
-                              HashMap.lookup "description" obj
-                        _ -> pure Null
-                  )
-                ,
-                  ( "isDeprecated"
-                  , ValueResolver nonNullBoolean $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe (Boolean False) $
-                              HashMap.lookup "isDeprecated" obj
-                        _ -> pure $ Boolean False
-                  )
-                ,
-                  ( "deprecationReason"
-                  , ValueResolver nullableString $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe Null $
-                              HashMap.lookup "deprecationReason" obj
-                        _ -> pure Null
-                  )
-                ]
-          }
-
-
-enumValuesField :: Field IO
-enumValuesField =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "enumValuesField description"
-      , fieldType = enumValuesType
-      , arguments =
-          HashMap.fromList
-            [
-              ( "includeDeprecated"
-              , inArgumentToArgument $
-                  InArgument
-                    { argDescMb = Just "includeDeprecated description"
-                    , argType = In.NamedScalarType boolean
-                    , valueMb = Just $ Boolean True
-                    }
-              )
-            ]
-      }
-
-
-queryTypeType :: Field IO
-queryTypeType =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "Provides the queryType"
-      , fieldType = typeType 0
-      , arguments = HashMap.empty
-      }
-
-
-mutationTypeType :: Field IO
-mutationTypeType =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "Provides the mutationType"
-      , fieldType = typeType 0
-      , arguments = HashMap.empty
-      }
-
-
-subscriptionTypeType :: Field IO
-subscriptionTypeType =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "Provides the subscriptionType"
-      , fieldType = typeType 0
-      , arguments = HashMap.empty
-      }
-
-
-fieldsTypeOutput :: Out.Type IO
-fieldsTypeOutput =
-  Out.ListType $
-    Out.NonNullObjectType $
-      outObjectTypeToObjectType $
-        OutObjectType
-          { name = "__Field"
-          , descriptionMb = Just "__Field description"
-          , interfaceTypes = []
-          , fields =
-              HashMap.fromList
-                [
-                  ( "__typename"
-                  , ValueResolver nonNullString $ pure "__Field"
-                  )
-                ,
-                  ( "name"
-                  , ValueResolver nonNullString $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe "ERROR: name" $
-                              HashMap.lookup "name" obj
-                        _ -> pure "ERROR: name"
-                  )
-                ,
-                  ( "description"
-                  , ValueResolver nullableString $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe Null $
-                              HashMap.lookup "description" obj
-                        _ -> pure Null
-                  )
-                ,
-                  ( "args"
-                  , ValueResolver argsField $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe (List []) $
-                              HashMap.lookup "args" obj
-                        _ -> pure $ List []
-                  )
-                ,
-                  ( "type"
-                  , ValueResolver (typeField 0) $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe emptyType $
-                              HashMap.lookup "type" obj
-                        _ -> pure emptyType
-                  )
-                ,
-                  ( "isDeprecated"
-                  , ValueResolver nonNullBoolean $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe (Boolean False) $
-                              HashMap.lookup "isDeprecated" obj
-                        _ -> pure $ Boolean False
-                  )
-                ,
-                  ( "deprecationReason"
-                  , ValueResolver nullableString $ do
-                      context <- ask
-                      case context & Out.values of
-                        Object obj ->
-                          pure $
-                            fromMaybe Null $
-                              HashMap.lookup "deprecationReason" obj
-                        _ -> pure Null
-                  )
-                ]
-          }
-
-
-fieldsField :: Field IO
-fieldsField =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "The fields type"
-      , fieldType = fieldsTypeOutput
-      , arguments =
-          HashMap.fromList
-            [
-              ( "includeDeprecated"
-              , inArgumentToArgument $
-                  InArgument
-                    { argDescMb = Just "includeDeprecated description"
-                    , argType = In.NamedScalarType boolean
-                    , valueMb = Just $ Boolean True
-                    }
-              )
-            ]
-      }
-
-
-directivesType :: Field IO
-directivesType =
-  let
-    directivesTypeOutput :: Out.Type IO
-    directivesTypeOutput =
-      Out.ListType $
-        Out.NonNullObjectType $
-          outObjectTypeToObjectType $
-            OutObjectType
-              { name = "__Directive"
-              , descriptionMb = Just "__Directive description"
-              , interfaceTypes = []
-              , fields =
-                  HashMap.fromList
-                    [
-                      ( "__typename"
-                      , ValueResolver nullableString $ pure "__Directive"
-                      )
-                    ,
-                      ( "name"
-                      , ValueResolver nonNullString $ do
-                          context <- ask
-                          case context & Out.values of
-                            Object obj ->
-                              pure $
-                                fromMaybe "ERROR: name" $
-                                  HashMap.lookup "name" obj
-                            _ -> pure "ERROR: name"
-                      )
-                    ,
-                      ( "description"
-                      , ValueResolver nullableString $ do
-                          context <- ask
-                          case context & Out.values of
-                            Object obj ->
-                              pure $
-                                fromMaybe Null $
-                                  HashMap.lookup "description" obj
-                            _ -> pure Null
-                      )
-                    ,
-                      ( "locations"
-                      , let
-                          locationsTypeName :: Field m
-                          locationsTypeName =
-                            Out.Field
-                              (Just "locationsTypeName name")
-                              (Out.ListType $ Out.NonNullScalarType string)
-                              HashMap.empty
-                        in
-                          ValueResolver locationsTypeName $ do
-                            context <- ask
-                            case context & Out.values of
-                              Object obj ->
-                                pure $
-                                  fromMaybe (List []) $
-                                    HashMap.lookup "locations" obj
-                              _ -> pure $ List []
-                      )
-                    ,
-                      ( "args"
-                      , ValueResolver argsField $ do
-                          context <- ask
-                          case context & Out.values of
-                            Object obj ->
-                              pure $
-                                fromMaybe (List []) $
-                                  HashMap.lookup "args" obj
-                            _ -> pure $ List []
-                      )
-                    ]
-              }
-  in
-    outFieldToField $
-      OutField
-        { descriptionMb = Just "Provides the directivesType"
-        , fieldType = directivesTypeOutput
-        , arguments = HashMap.empty
-        }
-
-
-filterType :: Bool -> Text -> Value
-filterType isRequired tableName =
-  let
-    filterObj =
-      Object $
-        HashMap.fromList
-          [ ("kind", "INPUT_OBJECT")
-          , ("name", String $ doubleXEncodeGql tableName <> "_filter")
-          ,
-            ( "description"
-            , "Select rows matching the provided filter object"
-            )
-          ]
-  in
-    if isRequired
-      then nonNullType filterObj
-      else filterObj
-
-
-getFieldsForQuery :: Text -> Value
-getFieldsForQuery tableName =
-  createType
-    (doubleXEncodeGql tableName)
-    ("Rows from the table \"" <> tableName <> "\"")
-    [ Object $
-        HashMap.fromList
-          [ ("name", "filter")
-          , ("description", "Filter to select specific rows")
-          , ("type", filterType False tableName)
-          ]
-    , Object $
-        HashMap.fromList
-          [ ("name", "order_by")
-          , ("description", "Columns used to sort the data")
-          ,
-            ( "type"
-            , listType $
-                Object $
-                  HashMap.fromList
-                    [ ("kind", "INPUT_OBJECT")
-                    ,
-                      ( "name"
-                      , String $
-                          doubleXEncodeGql tableName
-                            <> "_order_by"
-                      )
-                    ]
-            )
-          ]
-    , Object $
-        HashMap.fromList
-          [ ("name", "limit")
-          , ("description", "Limit the number of returned rows")
-          , ("type", intType)
-          ]
-    , Object $
-        HashMap.fromList
-          [ ("name", "offset")
-          , ("description", "The index to start returning rows from")
-          , ("type", intType)
-          ]
-    ]
-    ["NON_NULL", "LIST", "NON_NULL", "OBJECT"]
-    (doubleXEncodeGql tableName <> "_row")
-
-
-getFieldsForMutation :: Text -> [Value]
-getFieldsForMutation tableName =
-  [ Object $
-      HashMap.fromList
-        [ ("name", String $ "insert_" <> doubleXEncodeGql tableName)
-        ,
-          ( "description"
-          , String $
-              "Insert new rows in table \"" <> tableName <> "\""
-          )
-        ,
-          ( "args"
-          , List
-              [ createField
-                  "objects"
-                  (Just "Rows to be inserted")
-                  $ nonNullType
-                  $ listType
-                  $ nonNullType
-                  $ Object
-                  $ HashMap.fromList
-                    [ ("kind", "INPUT_OBJECT")
-                    ,
-                      ( "name"
-                      , String $
-                          doubleXEncodeGql
-                            tableName
-                            <> "_insert_input"
-                      )
-                    ]
-              , createField
-                  "on_conflict"
-                  (Just "Specifies how to handle broken UNIQUE constraints")
-                  $ listType
-                  $ nonNullType
-                  $ Object
-                  $ HashMap.fromList
-                    [ ("kind", "INPUT_OBJECT")
-                    ,
-                      ( "name"
-                      , String $
-                          doubleXEncodeGql
-                            tableName
-                            <> "_upsert_on_conflict"
-                      )
-                    ]
-              ]
-          )
-        ,
-          ( "type"
-          , nonNullType $
-              Object $
-                HashMap.fromList
-                  [ ("kind", "OBJECT")
-                  ,
-                    ( "name"
-                    , String $
-                        doubleXEncodeGql tableName
-                          <> "_mutation_response"
-                    )
-                  ]
-          )
-        ]
-  , Object $
-      HashMap.fromList
-        [ ("name", String $ "update_" <> doubleXEncodeGql tableName)
-        ,
-          ( "description"
-          , String $
-              "Update rows in table \"" <> tableName <> "\""
-          )
-        ,
-          ( "args"
-          , List
-              [ Object $
-                  HashMap.fromList
-                    [ ("name", "filter")
-                    , ("description", "Filter to select rows to be updated")
-                    , ("type", filterType True tableName)
-                    ]
-              , Object $
-                  HashMap.fromList
-                    [ ("name", "set")
-                    , ("description", "Fields to be updated")
-                    ,
-                      ( "type"
-                      , nonNullType $
-                          Object $
-                            HashMap.fromList
-                              [ ("kind", "INPUT_OBJECT")
-                              ,
-                                ( "name"
-                                , String $
-                                    doubleXEncodeGql tableName
-                                      <> "_set_input"
-                                )
-                              ]
-                      )
-                    ]
-              ]
-          )
-        ,
-          ( "type"
-          , nonNullType $
-              Object $
-                HashMap.fromList
-                  [ ("kind", "OBJECT")
-                  ,
-                    ( "name"
-                    , String $
-                        doubleXEncodeGql tableName
-                          <> "_mutation_response"
-                    )
-                  ]
-          )
-        ]
-  , Object $
-      HashMap.fromList
-        [ ("name", String $ "delete_" <> doubleXEncodeGql tableName)
-        ,
-          ( "description"
-          , String $ "Delete rows in table \"" <> tableName <> "\""
-          )
-        ,
-          ( "args"
-          , List
-              [ Object $
-                  HashMap.fromList
-                    [ ("name", "filter")
-                    , ("description", "Filter to select rows to be deleted")
-                    , ("type", filterType True tableName)
-                    ]
-              ]
-          )
-        ,
-          ( "type"
-          , nonNullType $
-              Object $
-                HashMap.fromList
-                  [ ("kind", "OBJECT")
-                  ,
-                    ( "name"
-                    , String $
-                        doubleXEncodeGql tableName
-                          <> "_mutation_response"
-                    )
-                  ]
-          )
-        ]
-  ]
-
-
-makeComparisonType :: Text -> Text -> Value -> Value
-makeComparisonType typeName description type_ =
-  let field fieldName = createField fieldName Nothing type_
-  in  Object $
-        HashMap.fromList
-          [ ("__typename", "__Type")
-          , ("kind", "INPUT_OBJECT")
-          , ("name", String typeName)
-          ,
-            ( "description"
-            , String description
-            )
-          ,
-            ( "inputFields"
-            , List
-                [ field "eq"
-                , field "neq"
-                , field "gt"
-                , field "gte"
-                , field "lt"
-                , field "lte"
-                , field "like"
-                , field "ilike"
-                , createField
-                    "in"
-                    Nothing
-                    (listType type_)
-                , createField
-                    "nin"
-                    Nothing
-                    (listType type_)
-                ]
-            )
-          ]
-
-
-comparisonTypes :: AccessMode -> [Value]
-comparisonTypes accessMode =
-  case accessMode of
-    ReadOnly -> []
-    _ ->
-      [ makeComparisonType "IntComparison" "Compare to an Int" intType
-      , makeComparisonType "FloatComparison" "Compare to a Float" floatType
-      , makeComparisonType "StringComparison" "Compare to a String" stringType
-      , makeComparisonType "BooleanComparison" "Compare to a Boolean" booleanType
-      ]
-
-
-orderingTermType :: Value
-orderingTermType =
-  Object $
-    HashMap.fromList
-      [ ("__typename", "__Type")
-      , ("kind", "ENUM")
-      , ("name", String "OrderingTerm")
-      ,
-        ( "description"
-        , String "Ordering options when ordering by a column"
-        )
-      ,
-        ( "enumValues"
-        , List
-            [ Object $
-                HashMap.fromList
-                  [ ("name", "ASC")
-                  , ("description", "In ascending order")
-                  ]
-            , Object $
-                HashMap.fromList
-                  [ ("name", "asc")
-                  , ("description", "In ascending order")
-                  , ("isDeprecated", Boolean True)
-                  ,
-                    ( "deprecationReason"
-                    , String "GraphQL spec recommends all caps for enums"
-                    )
-                  ]
-            , Object $
-                HashMap.fromList
-                  [ ("name", "DESC")
-                  , ("description", "In descending order")
-                  ]
-            , Object $
-                HashMap.fromList
-                  [ ("name", "desc")
-                  , ("description", "In descending order")
-                  , ("isDeprecated", Boolean True)
-                  ,
-                    ( "deprecationReason"
-                    , String "GraphQL spec recommends all caps for enums"
-                    )
-                  ]
-            ]
-        )
-      ]
-
-
-getFullDatatype :: ColumnEntry -> Text
-getFullDatatype entry = case entry.datatype_gql of
-  -- TODO: Should be "Any", but that's not a valid GraphQL type
-  Nothing -> "String"
-  Just type_ -> type_.full
-
-
-getSchemaFieldOutput
-  :: Text
-  -> Connection
-  -> AccessMode
-  -> [TableEntryRaw]
-  -> IO (Out.Type IO)
-getSchemaFieldOutput dbId conn accessMode tables = do
-  typesForTables <- forM tables $ \table -> do
-    columns <- getColumns dbId conn table.name
-    fieldsIn <- forM columns $ \columnEntry -> do
-      let colName = columnEntry.column_name_gql
-      pure $
-        createType
-          colName
-          "" -- TODO: Reactivate description when user can specify it
-          [] -- No arguments
-          ( if columnEntry.isOmittable
-              then ["SCALAR"]
-              else ["NON_NULL", "SCALAR"]
-          )
-          (getFullDatatype columnEntry)
-
-    fieldsOut <- forM columns $ \columnEntry -> do
-      let colName = columnEntry.column_name_gql
-      pure $
-        createType
-          colName
-          "" -- TODO: Reactivate description when user can specify it
-          [] -- No arguments
-          ( if columnEntry.notnull
-              then ["NON_NULL", "SCALAR"]
-              else ["SCALAR"]
-          )
-          (getFullDatatype columnEntry)
-
-    fieldsNullable <- forM columns $ \columnEntry -> do
-      let colName = columnEntry.column_name_gql
-      pure $
-        createType
-          colName
-          "" -- TODO: Reactivate description when user can specify it
-          [] -- No arguments
-          ["SCALAR"]
-          (getFullDatatype columnEntry)
-
-    fieldsWithComparisonExp <- forM columns $ \columnEntry -> do
-      let colName = columnEntry.column_name_gql
-      pure $
-        createType
-          colName
-          "" -- TODO: Reactivate description when user can specify it
-          [] -- No arguments
-          ["INPUT_OBJECT"]
-          (getFullDatatype columnEntry <> "Comparison")
-
-    fieldsWithOrderingTerm <- forM columns $ \columnEntry -> do
-      let colName = columnEntry.column_name_gql
-      pure $
-        createType
-          colName
-          "" -- TODO: Reactivate description when user can specify it
-          [] -- No arguments
-          ["INPUT_OBJECT"]
-          "OrderingTerm"
-
-    let
-      customRowTypes =
-        columns
-          >>= \columnEntry ->
-            case (columnEntry.select_options, columnEntry.datatype_gql) of
-              (Just _, Just name) ->
-                let
-                  colName = columnEntry.column_name_gql
-                  typeName = name.full
-                  description = "Data type for column " <> colName
-                  rowType =
-                    Object $
-                      HashMap.fromList
-                        [ ("__typename", "__Type")
-                        , ("kind", "SCALAR")
-                        , ("name", String typeName)
-                        , ("description", String description)
-                        ]
-
-                  comparisonType =
-                    makeComparisonType
-                      (typeName <> "Comparison")
-                      ("Compare with values for column" <> colName)
-                      ( Object $
-                          HashMap.fromList
-                            [ ("kind", "SCALAR")
-                            , ("name", String typeName)
-                            , ("description", String description)
-                            ]
-                      )
-                in
-                  [rowType, comparisonType]
-              _ -> []
-
-      fieldEnumVariants =
-        columns
-          <&> \columnEntry ->
-            Object $
-              HashMap.singleton "name" $
-                String $
-                  column_name_gql columnEntry
-
-      fieldEnumDescription =
-        "This enum contains a variant for each column in the table" :: Value
-
-      fieldEnumType =
-        Object $
-          HashMap.fromList
-            [ ("__typename", "__Type")
-            , ("kind", "ENUM")
-            , ("name", String $ doubleXEncodeGql table.name <> "_column")
-            ,
-              ( "description"
-              , fieldEnumDescription
-              )
-            , ("enumValues", List fieldEnumVariants)
-            ]
-
-      fieldEnumTypeReference =
-        Object $
-          HashMap.fromList
-            [ ("kind", "INPUT_OBJECT")
-            , ("name", String $ doubleXEncodeGql table.name <> "_column")
-            ,
-              ( "description"
-              , fieldEnumDescription
-              )
-            ]
-
-      requiresWrite obj = case accessMode of
-        ReadOnly -> Null
-        WriteOnly -> obj
-        ReadAndWrite -> obj
-      requiresRead obj = case accessMode of
-        ReadOnly -> Null
-        WriteOnly -> obj
-        ReadAndWrite -> obj
-
-    pure $
-      customRowTypes
-        <> [ Object $
-              HashMap.fromList
-                [ ("__typename", "__Type")
-                , ("kind", "OBJECT")
-                , ("name", String $ doubleXEncodeGql table.name <> "_row")
-                ,
-                  ( "description"
-                  , String $
-                      "Available columns for table \""
-                        <> table.name
-                        <> "\""
-                  )
-                , ("fields", List fieldsOut)
-                ]
-           , requiresWrite $
-              Object $
-                HashMap.fromList
-                  [ ("__typename", "__Type")
-                  , ("kind", "OBJECT")
-                  ,
-                    ( "name"
-                    , String $
-                        doubleXEncodeGql table.name <> "_mutation_response"
-                    )
-                  ,
-                    ( "description"
-                    , String $ "Mutation response for " <> table.name
-                    )
-                  ,
-                    ( "fields"
-                    , List
-                        [ Object $
-                            HashMap.fromList
-                              [ ("name", "affected_rows")
-                              ,
-                                ( "type"
-                                , Object $
-                                    HashMap.fromList
-                                      [ ("kind", "NON_NULL")
-                                      ,
-                                        ( "ofType"
-                                        , Object $
-                                            HashMap.fromList
-                                              [ ("kind", "SCALAR")
-                                              , ("name", "Int")
-                                              ]
-                                        )
-                                      ]
-                                )
-                              ]
-                        , requiresRead $
-                            Object $
-                              HashMap.fromList
-                                [ ("name", "returning")
-                                ,
-                                  ( "type"
-                                  , Object $
-                                      HashMap.fromList
-                                        [ ("kind", "NON_NULL")
-                                        ,
-                                          ( "ofType"
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("kind", "LIST")
-                                                ,
-                                                  ( "ofType"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "NON_NULL")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "OBJECT")
-                                                                ,
-                                                                  ( "name"
-                                                                  , String $ doubleXEncodeGql table.name <> "_row"
-                                                                  )
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ]
-                                          )
-                                        ]
-                                  )
-                                ]
-                        ]
-                    )
-                  ]
-           , requiresWrite $
-              Object $
-                HashMap.fromList
-                  [ ("__typename", "__Type")
-                  , ("kind", "INPUT_OBJECT")
-                  ,
-                    ( "name"
-                    , String $ doubleXEncodeGql table.name <> "_insert_input"
-                    )
-                  ,
-                    ( "description"
-                    , String $ "Input object for " <> table.name
-                    )
-                  , ("inputFields", List fieldsIn)
-                  ]
-           , fieldEnumType
-           , requiresWrite $
-              Object $
-                HashMap.fromList
-                  [ ("__typename", "__Type")
-                  , ("kind", "INPUT_OBJECT")
-                  ,
-                    ( "name"
-                    , String $ doubleXEncodeGql table.name <> "_upsert_on_conflict"
-                    )
-                  ,
-                    ( "description"
-                    , String $ "Specifies how broken UNIQUE constraints for " <> table.name <> " should be handled"
-                    )
-                  ,
-                    ( "inputFields"
-                    , List
-                        [ createField
-                            "constraint"
-                            (Just "columns to handle conflicts of")
-                            $ nonNullType
-                            $ listType
-                            $ nonNullType fieldEnumTypeReference
-                        , createField
-                            "update_columns"
-                            (Just "columns to override on conflict")
-                            $ nonNullType
-                            $ listType
-                            $ nonNullType fieldEnumTypeReference
-                        , createField
-                            "where"
-                            (Just "filter specifying which conflicting columns to update")
-                            (filterType False table.name)
-                        ]
-                    )
-                  ]
-           , requiresWrite $
-              Object $
-                HashMap.fromList
-                  [ ("__typename", "__Type")
-                  , ("kind", "INPUT_OBJECT")
-                  ,
-                    ( "name"
-                    , String $ doubleXEncodeGql table.name <> "_set_input"
-                    )
-                  ,
-                    ( "description"
-                    , String $ "Fields to set for " <> table.name
-                    )
-                  , ("inputFields", List fieldsNullable)
-                  ]
-           , requiresWrite $
-              Object $
-                HashMap.fromList
-                  [ ("__typename", "__Type")
-                  , ("kind", "INPUT_OBJECT")
-                  ,
-                    ( "name"
-                    , String $ doubleXEncodeGql table.name <> "_filter"
-                    )
-                  ,
-                    ( "description"
-                    , String "Filter object to select rows"
-                    )
-                  , ("inputFields", List fieldsWithComparisonExp)
-                  ]
-           , requiresWrite $
-              Object $
-                HashMap.fromList
-                  [ ("__typename", "__Type")
-                  , ("kind", "INPUT_OBJECT")
-                  ,
-                    ( "name"
-                    , String $ doubleXEncodeGql table.name <> "_order_by"
-                    )
-                  ,
-                    ( "description"
-                    , String $
-                        "Ordering options when selecting data from \""
-                          <> table.name
-                          <> "\"."
-                    )
-                  , ("inputFields", List fieldsWithOrderingTerm)
-                  ]
-           ]
-
-  let
-    queryTypeObj =
-      Object $
-        HashMap.fromList
-          [ ("__typename", "__Type")
-          , ("kind", "OBJECT")
-          , ("name", "Query")
-          ,
-            ( "fields"
-            , List $
-                tables
-                  <&> AirGQL.Lib.name
-                  <&> getFieldsForQuery
-            )
-          ]
-    mutationTypeObj =
-      Object $
-        HashMap.fromList
-          [ ("__typename", "__Type")
-          , ("kind", "OBJECT")
-          , ("name", "Mutation")
-          ,
-            ( "fields"
-            , List $
-                tables
-                  <&> AirGQL.Lib.name
-                  <&> getFieldsForMutation
-                  & concat
-            )
-          ]
-
-  pure $
-    Out.NonNullObjectType $
-      outObjectTypeToObjectType $
-        OutObjectType
-          { name = "__Schema"
-          , descriptionMb = Just "__Schema description"
-          , interfaceTypes = []
-          , fields =
-              HashMap.fromList
-                [
-                  ( "__typename"
-                  , ValueResolver nonNullString $ pure "__Schema"
-                  )
-                ,
-                  ( "queryType"
-                  , ValueResolver queryTypeType $ pure queryTypeObj
-                  )
-                ,
-                  ( "mutationType"
-                  , case accessMode of
-                      ReadOnly -> ValueResolver mutationTypeType $ pure Null
-                      WriteOnly ->
-                        ValueResolver mutationTypeType $ pure mutationTypeObj
-                      ReadAndWrite ->
-                        ValueResolver mutationTypeType $ pure mutationTypeObj
-                  )
-                ,
-                  ( "subscriptionType"
-                  , -- AirGQL doesn't support Subscriptions yet
-                    ValueResolver subscriptionTypeType $ pure Null
-                  )
-                ,
-                  ( "types"
-                  , ValueResolver typesField $
-                      pure $
-                        List $
-                          concat typesForTables
-                            <> comparisonTypes accessMode
-                            <> [orderingTermType]
-                            <> [ queryTypeObj
-                               , case accessMode of
-                                  ReadOnly -> Null
-                                  WriteOnly -> mutationTypeObj
-                                  ReadAndWrite -> mutationTypeObj
-                               , booleanType
-                               , intType
-                               , floatType
-                               , stringType
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "SCALAR")
-                                    , ("name", "ID")
-                                    ,
-                                      ( "description"
-                                      , "The `ID` scalar type represents a unique identifier, \
-                                        \often used to refetch an object or as key for a cache. \
-                                        \The ID type appears in a JSON response as a String; \
-                                        \however, it is not intended to be human-readable. \
-                                        \When expected as an input type, any string \
-                                        \(such as `\"4\"`) or integer (such as `4`) input value \
-                                        \will be accepted as an ID."
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "SCALAR")
-                                    , ("name", "Upload")
-                                    ,
-                                      ( "description"
-                                      , "The `Upload` scalar type represents a file upload."
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "OBJECT")
-                                    , ("name", "__Schema")
-                                    ,
-                                      ( "description"
-                                      , "A GraphQL Schema defines the capabilities of a GraphQL server. \
-                                        \It exposes all available types and directives on the server, \
-                                        \as well as the entry points for \
-                                        \query, mutation, and subscription operations."
-                                      )
-                                    ,
-                                      ( "fields"
-                                      , List
-                                          [ Object $
-                                              HashMap.fromList
-                                                [ ("name", "types")
-                                                ,
-                                                  ( "description"
-                                                  , "A list of all types supported by this server."
-                                                  )
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "NON_NULL")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "LIST")
-                                                                ,
-                                                                  ( "ofType"
-                                                                  , Object $
-                                                                      HashMap.fromList
-                                                                        [ ("kind", "NON_NULL")
-                                                                        ,
-                                                                          ( "ofType"
-                                                                          , Object $
-                                                                              HashMap.fromList
-                                                                                [ ("kind", "OBJECT")
-                                                                                , ("name", "__Type")
-                                                                                ]
-                                                                          )
-                                                                        ]
-                                                                  )
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "queryType")
-                                                ,
-                                                  ( "description"
-                                                  , "The type that query operations will be rooted at."
-                                                  )
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "NON_NULL")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "OBJECT")
-                                                                , ("name", "__Type")
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "mutationType")
-                                                ,
-                                                  ( "description"
-                                                  , "If this server supports mutation, the type \
-                                                    \that mutation operations will be rooted at."
-                                                  )
-                                                , getTypeTuple "OBJECT" "__Type"
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "subscriptionType")
-                                                ,
-                                                  ( "description"
-                                                  , "If this server support subscription, the type \
-                                                    \that subscription operations will be rooted at."
-                                                  )
-                                                , getTypeTuple "OBJECT" "__Type"
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "directives")
-                                                ,
-                                                  ( "description"
-                                                  , "A list of all directives supported by this server."
-                                                  )
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "NON_NULL")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "LIST")
-                                                                ,
-                                                                  ( "ofType"
-                                                                  , Object $
-                                                                      HashMap.fromList
-                                                                        [ ("kind", "NON_NULL")
-                                                                        ,
-                                                                          ( "ofType"
-                                                                          , Object $
-                                                                              HashMap.fromList
-                                                                                [ ("kind", "OBJECT")
-                                                                                , ("name", "__Directive")
-                                                                                ]
-                                                                          )
-                                                                        ]
-                                                                  )
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ]
-                                          ]
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "OBJECT")
-                                    , ("name", "__Type")
-                                    ,
-                                      ( "description"
-                                      , "The fundamental unit of any GraphQL Schema is the type. \
-                                        \There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\n\
-                                        \Depending on the kind of a type, certain fields describe information about that type. \
-                                        \Scalar types provide no information beyond a name and description, while Enum types provide their values. \
-                                        \Object and Interface types provide the fields they describe. \
-                                        \Abstract types, Union and Interface, provide the Object types possible at runtime. \
-                                        \List and NonNull types compose other types."
-                                      )
-                                    ,
-                                      ( "fields"
-                                      , List
-                                          [ Object $
-                                              HashMap.fromList
-                                                [ ("name", "kind")
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "NON_NULL")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "ENUM")
-                                                                , ("name", "__TypeKind")
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "name")
-                                                , -- Don't know why not "NON_NULL"
-                                                  getTypeTuple "SCALAR" "String"
-                                                ]
-                                          , descriptionField
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "fields")
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "LIST")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "NON_NULL")
-                                                                ,
-                                                                  ( "ofType"
-                                                                  , Object $
-                                                                      HashMap.fromList
-                                                                        [ ("kind", "OBJECT")
-                                                                        , ("name", "__Field")
-                                                                        ]
-                                                                  )
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ,
-                                                  ( "args"
-                                                  , List
-                                                      [ Object $
-                                                          HashMap.fromList
-                                                            [ ("name", "includeDeprecated")
-                                                            , getTypeTuple "SCALAR" "Boolean"
-                                                            , -- Don't know why this has to be a string
-                                                              ("defaultValue", "false")
-                                                            ]
-                                                      ]
-                                                  )
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "interfaces")
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "LIST")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "NON_NULL")
-                                                                ,
-                                                                  ( "ofType"
-                                                                  , Object $
-                                                                      HashMap.fromList
-                                                                        [ ("kind", "OBJECT")
-                                                                        , ("name", "__Type")
-                                                                        ]
-                                                                  )
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "possibleTypes")
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "LIST")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "NON_NULL")
-                                                                ,
-                                                                  ( "ofType"
-                                                                  , Object $
-                                                                      HashMap.fromList
-                                                                        [ ("kind", "OBJECT")
-                                                                        , ("name", "__Type")
-                                                                        ]
-                                                                  )
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "enumValues")
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "LIST")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "NON_NULL")
-                                                                ,
-                                                                  ( "ofType"
-                                                                  , Object $
-                                                                      HashMap.fromList
-                                                                        [ ("kind", "OBJECT")
-                                                                        , ("name", "__EnumValue")
-                                                                        ]
-                                                                  )
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ,
-                                                  ( "args"
-                                                  , List
-                                                      [ Object $
-                                                          HashMap.fromList
-                                                            [ ("name", "includeDeprecated")
-                                                            , getTypeTuple "SCALAR" "Boolean"
-                                                            , -- Don't know why this has to be a string
-                                                              ("defaultValue", "false")
-                                                            ]
-                                                      ]
-                                                  )
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "inputFields")
-                                                ,
-                                                  ( "type"
-                                                  , Object $
-                                                      HashMap.fromList
-                                                        [ ("kind", "LIST")
-                                                        ,
-                                                          ( "ofType"
-                                                          , Object $
-                                                              HashMap.fromList
-                                                                [ ("kind", "NON_NULL")
-                                                                ,
-                                                                  ( "ofType"
-                                                                  , Object $
-                                                                      HashMap.fromList
-                                                                        [ ("kind", "OBJECT")
-                                                                        , ("name", "__InputValue")
-                                                                        ]
-                                                                  )
-                                                                ]
-                                                          )
-                                                        ]
-                                                  )
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "ofType")
-                                                , getTypeTuple "OBJECT" "__Type"
-                                                ]
-                                          ]
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "ENUM")
-                                    , ("name", "__TypeKind")
-                                    ,
-                                      ( "description"
-                                      , "An enum describing what kind of type a given `__Type` is."
-                                      )
-                                    ,
-                                      ( "enumValues"
-                                      , List
-                                          [ Object $
-                                              HashMap.fromList
-                                                [ ("name", "SCALAR")
-                                                ,
-                                                  ( "description"
-                                                  , "Indicates this type is a scalar."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "OBJECT")
-                                                ,
-                                                  ( "description"
-                                                  , "Indicates this type is an object. `fields` and `interfaces` are valid fields."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "INTERFACE")
-                                                ,
-                                                  ( "description"
-                                                  , "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "UNION")
-                                                ,
-                                                  ( "description"
-                                                  , "Indicates this type is a union. `possibleTypes` is a valid field."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "ENUM")
-                                                ,
-                                                  ( "description"
-                                                  , "Indicates this type is an enum. `enumValues` is a valid field."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "INPUT_OBJECT")
-                                                ,
-                                                  ( "description"
-                                                  , "Indicates this type is an input object. `inputFields` is a valid field."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "LIST")
-                                                ,
-                                                  ( "description"
-                                                  , "Indicates this type is a list. `ofType` is a valid field."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "NON_NULL")
-                                                ,
-                                                  ( "description"
-                                                  , "Indicates this type is a non-null. `ofType` is a valid field."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          ]
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "OBJECT")
-                                    , ("name", "__Field")
-                                    ,
-                                      ( "description"
-                                      , "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type."
-                                      )
-                                    ,
-                                      ( "fields"
-                                      , List
-                                          [ nameField
-                                          , descriptionField
-                                          , argsFieldValue
-                                          , typeFieldValue
-                                          , isDeprecatedFieldValue
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "deprecationReason")
-                                                , getTypeTuple "SCALAR" "String"
-                                                ]
-                                          ]
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "OBJECT")
-                                    , ("name", "__InputValue")
-                                    ,
-                                      ( "description"
-                                      , "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value."
-                                      )
-                                    ,
-                                      ( "fields"
-                                      , List
-                                          [ nameField
-                                          , descriptionField
-                                          , typeFieldValue
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "defaultValue")
-                                                ,
-                                                  ( "description"
-                                                  , "A GraphQL-formatted string representing \
-                                                    \the default value for this input value."
-                                                  )
-                                                , getTypeTuple "SCALAR" "String"
-                                                ]
-                                          ]
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "OBJECT")
-                                    , ("name", "__EnumValue")
-                                    ,
-                                      ( "description"
-                                      , "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string."
-                                      )
-                                    ,
-                                      ( "fields"
-                                      , List
-                                          [ nameField
-                                          , descriptionField
-                                          , isDeprecatedFieldValue
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "deprecationReason")
-                                                , getTypeTuple "SCALAR" "String"
-                                                ]
-                                          ]
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "OBJECT")
-                                    , ("name", "__Directive")
-                                    ,
-                                      ( "description"
-                                      , "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor."
-                                      )
-                                    ,
-                                      ( "fields"
-                                      , List
-                                          [ nameField
-                                          , descriptionField
-                                          , locationsFieldValue
-                                          , argsFieldValue
-                                          ]
-                                      )
-                                    ]
-                               , Object $
-                                  HashMap.fromList
-                                    [ ("__typename", "__Type")
-                                    , ("kind", "ENUM")
-                                    , ("name", "__DirectiveLocation")
-                                    ,
-                                      ( "description"
-                                      , "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies."
-                                      )
-                                    ,
-                                      ( "enumValues"
-                                      , List
-                                          [ Object $
-                                              HashMap.fromList
-                                                [ ("name", "QUERY")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a query operation."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "MUTATION")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a mutation operation."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "SUBSCRIPTION")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a subscription operation."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "FIELD")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a field."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "FRAGMENT_DEFINITION")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a fragment definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "FRAGMENT_SPREAD")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a fragment spread."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "INLINE_FRAGMENT")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to an inline fragment."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "VARIABLE_DEFINITION")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a variable definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "SCHEMA")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a schema definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "SCALAR")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a scalar definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "OBJECT")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to an object type definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "FIELD_DEFINITION")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a field definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "ARGUMENT_DEFINITION")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to an argument definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "INTERFACE")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to an interface definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "UNION")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to a union definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "ENUM")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to an enum definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "ENUM_VALUE")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to an enum value definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "INPUT_OBJECT")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to an input object \
-                                                    \type definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          , Object $
-                                              HashMap.fromList
-                                                [ ("name", "INPUT_FIELD_DEFINITION")
-                                                ,
-                                                  ( "description"
-                                                  , "Location adjacent to an input object \
-                                                    \field definition."
-                                                  )
-                                                , ("isDeprecated", Boolean False)
-                                                , ("deprecationReason", Null)
-                                                ]
-                                          ]
-                                      )
-                                    ]
-                               ]
-                              & filter (/= Null)
-                  )
-                ,
-                  ( "directives"
-                  , ValueResolver directivesType $
-                      pure $
-                        List
-                          [ Object $
-                              HashMap.fromList
-                                [ ("__typename", "__Directive")
-                                , ("name", "skip")
-                                ,
-                                  ( "description"
-                                  , "Directs the executor to skip this field or fragment \
-                                    \when the `if` argument is true."
-                                  )
-                                ,
-                                  ( "locations"
-                                  , List ["INLINE_FRAGMENT", "FRAGMENT_SPREAD", "FIELD"]
-                                  )
-                                ,
-                                  ( "args"
-                                  , List
-                                      [ Object $
-                                          HashMap.fromList
-                                            [ ("name", "if")
-                                            , ("description", "Skipped when true.")
-                                            , ("defaultValue", Null)
-                                            ,
-                                              ( "type"
-                                              , Object $
-                                                  HashMap.fromList
-                                                    [ ("kind", "NON_NULL")
-                                                    ,
-                                                      ( "ofType"
-                                                      , Object $
-                                                          HashMap.fromList
-                                                            [ ("kind", "SCALAR")
-                                                            , ("name", "Boolean")
-                                                            ]
-                                                      )
-                                                    ]
-                                              )
-                                            ]
-                                      ]
-                                  )
-                                ]
-                          , Object $
-                              HashMap.fromList
-                                [ ("__typename", "__Directive")
-                                , ("name", "include")
-                                ,
-                                  ( "description"
-                                  , "Directs the executor to include this field or fragment \
-                                    \only when the `if` argument is true."
-                                  )
-                                ,
-                                  ( "locations"
-                                  , List ["INLINE_FRAGMENT", "FRAGMENT_SPREAD", "FIELD"]
-                                  )
-                                ,
-                                  ( "args"
-                                  , List
-                                      [ Object $
-                                          HashMap.fromList
-                                            [ ("name", "if")
-                                            , ("description", "Included when true.")
-                                            , ("defaultValue", Null)
-                                            ,
-                                              ( "type"
-                                              , Object $
-                                                  HashMap.fromList
-                                                    [ ("kind", "NON_NULL")
-                                                    ,
-                                                      ( "ofType"
-                                                      , Object $
-                                                          HashMap.fromList
-                                                            [ ("kind", "SCALAR")
-                                                            , ("name", "Boolean")
-                                                            ]
-                                                      )
-                                                    ]
-                                              )
-                                            ]
-                                      ]
-                                  )
-                                ]
-                          , Object $
-                              HashMap.fromList
-                                [ ("__typename", "__Directive")
-                                , ("name", "deprecated")
-                                ,
-                                  ( "description"
-                                  , "Marks an element of a GraphQL schema \
-                                    \as no longer supported."
-                                  )
-                                ,
-                                  ( "locations"
-                                  , List ["ENUM_VALUE", "FIELD_DEFINITION"]
-                                  )
-                                ,
-                                  ( "args"
-                                  , List
-                                      [ Object $
-                                          HashMap.fromList
-                                            [ ("name", "reason")
-                                            ,
-                                              ( "description"
-                                              , "Explains why this element was deprecated, \
-                                                \usually also including a suggestion \
-                                                \for how to access supported similar data. \
-                                                \Formatted using the Markdown syntax \
-                                                \(as specified by \
-                                                \[CommonMark](https://commonmark.org/)."
-                                              )
-                                            , ("defaultValue", "\"No longer supported\"")
-                                            , getTypeTuple "SCALAR" "String"
-                                            ]
-                                      ]
-                                  )
-                                ]
-                          ]
-                  )
-                ]
-          }
-
-
-getSchemaField
-  :: Text
-  -> Connection
-  -> AccessMode
-  -> [TableEntryRaw]
-  -> IO (Field IO)
-getSchemaField dbId conn accessMode tables = do
-  schemaFieldOutput <- getSchemaFieldOutput dbId conn accessMode tables
-
-  pure $
-    outFieldToField $
-      OutField
-        { descriptionMb = Just "The schema"
-        , fieldType = schemaFieldOutput
-        , arguments = HashMap.empty
-        }
-
-
-getSchemaResolver
-  :: Text
-  -> Connection
-  -> AccessMode
-  -> [TableEntryRaw]
-  -> IO (HashMap Text (Resolver IO))
-getSchemaResolver dbId conn accessMode tables = do
-  schemaField <- getSchemaField dbId conn accessMode tables
-
-  pure $
-    HashMap.singleton
-      "__schema"
-      (ValueResolver schemaField (pure Null))
-
-
-typeNameOutField :: Field m
-typeNameOutField =
-  outFieldToField $
-    OutField
-      { descriptionMb = Just "The type name"
-      , fieldType = Out.NonNullScalarType string
-      , arguments = HashMap.empty
-      }
+import Language.GraphQL.Class (ToGraphQL (toGraphQL))
+import Language.GraphQL.Type (string)
 
 
 typeNameResolver :: HashMap Text (Resolver IO)
 typeNameResolver =
   HashMap.singleton
     "__typename"
-    (ValueResolver typeNameOutField $ pure "Query")
+    $ ValueResolver
+      (Out.Field Nothing (Out.NonNullScalarType string) mempty)
+    $ pure "Query"
+
+
+columnTypeName :: ColumnEntry -> Text
+columnTypeName entry = fromMaybe "String" (columnType entry).name
+
+
+columnType :: ColumnEntry -> IntrospectionType
+columnType entry = case entry.datatype_gql of
+  Nothing -> Type.typeString
+  Just type_ ->
+    Type.scalar type_.full
+      & Type.withDescription
+        ("Data type for column" <> entry.column_name_gql)
+
+
+orderingTermType :: Type.IntrospectionType
+orderingTermType =
+  Type.enum
+    "OrderingTerm"
+    [ Type.enumValue "ASC" & Type.enumValueWithDescription "In ascending order"
+    , Type.enumValue "asc"
+        & Type.enumValueWithDescription "In ascending order"
+        & Type.deprecatedEnumValue "GraphQL spec recommends all caps for enums"
+    , Type.enumValue "DESC" & Type.enumValueWithDescription "In descending order"
+    , Type.enumValue "desc"
+        & Type.enumValueWithDescription "In descending order"
+        & Type.deprecatedEnumValue "GraphQL spec recommends all caps for enums"
+    ]
+
+
+filterType :: TableEntry -> IntrospectionType
+filterType table = do
+  let
+    fieldsWithComparisonExp =
+      table.columns <&> \columnEntry -> do
+        let colName = columnEntry.column_name_gql
+        let typeName = columnTypeName columnEntry
+        let type_ = columnType columnEntry
+        Type.inputValue colName $
+          Type.inputObject
+            (typeName <> "Comparison")
+            [ Type.inputValue "eq" type_
+            , Type.inputValue "neq" type_
+            , Type.inputValue "gt" type_
+            , Type.inputValue "gte" type_
+            , Type.inputValue "lt" type_
+            , Type.inputValue "lte" type_
+            , Type.inputValue "like" type_
+            , Type.inputValue "ilike" type_
+            , Type.inputValue "in" $ Type.list type_
+            , Type.inputValue "nin" $ Type.list type_
+            ]
+
+  Type.inputObject
+    (doubleXEncodeGql table.name <> "_filter")
+    fieldsWithComparisonExp
+    & Type.withDescription "Select rows matching the provided filter object"
+
+
+tableRowType :: TableEntry -> Type.IntrospectionType
+tableRowType table = do
+  let fields =
+        table.columns <&> \columnEntry -> do
+          let colName = columnEntry.column_name_gql
+          let base = columnType columnEntry
+          let type_ =
+                if columnEntry.notnull
+                  then Type.nonNull base
+                  else base
+          Type.field colName type_
+  Type.object (doubleXEncodeGql table.name <> "_row") fields
+
+
+tableQueryField :: TableEntry -> Type.Field
+tableQueryField table = do
+  let tableName = table.name
+
+  let fieldsWithOrderingTerm =
+        table.columns <&> \columnEntry -> do
+          let colName = columnEntry.column_name_gql
+          Type.inputValue colName orderingTermType
+
+  let orderType =
+        Type.inputObject
+          (doubleXEncodeGql tableName <> "_order_by")
+          fieldsWithOrderingTerm
+          & Type.withDescription
+            ( "Ordering options when selecting data from \""
+                <> table.name
+                <> "\"."
+            )
+
+  Type.field
+    (doubleXEncodeGql tableName)
+    (Type.nonNull $ Type.list $ Type.nonNull $ tableRowType table)
+    & Type.fieldWithDescription ("Rows from the table \"" <> tableName <> "\"")
+    & Type.withArguments
+      [ Type.inputValue "filter" (filterType table)
+          & Type.inputValueWithDescription "Filter to select specific rows"
+      , Type.inputValue "order_by" (Type.list orderType)
+          & Type.inputValueWithDescription "Columns used to sort the data"
+      , Type.inputValue "limit" Type.typeInt
+          & Type.inputValueWithDescription "Limit the number of returned rows"
+      , Type.inputValue "offset" Type.typeInt
+          & Type.inputValueWithDescription "The index to start returning rows from"
+      ]
+
+
+mutationResponseType :: AccessMode -> TableEntry -> Type.IntrospectionType
+mutationResponseType accessMode table = do
+  let tableName = doubleXEncodeGql table.name
+  let readFields =
+        if canRead accessMode
+          then
+            pure
+              $ Type.field
+                "returning"
+              $ Type.nonNull
+              $ Type.list
+              $ Type.nonNull
+              $ tableRowType table
+          else []
+
+  Type.object
+    (tableName <> "_mutation_response")
+    ( [ Type.field "affected_rows" (Type.nonNull Type.typeInt)
+      ]
+        <> readFields
+    )
+    & Type.withDescription ("Mutation response for " <> table.name)
+
+
+tableInsertField :: AccessMode -> TableEntry -> Type.Field
+tableInsertField accessMode table = do
+  let
+    tableName = doubleXEncodeGql table.name
+    fields =
+      table.columns <&> \columnEntry -> do
+        let colName = columnEntry.column_name_gql
+        let base = columnType columnEntry
+        let type_ =
+              if columnEntry.isOmittable
+                then Type.nonNull base
+                else base
+        Type.inputValue colName type_
+
+    insertRows =
+      Type.inputObject
+        (tableName <> "_insert_input")
+        fields
+        & Type.withDescription
+          ("Input object for " <> table.name)
+
+    fieldEnumVariants =
+      table.columns <&> \columnEntry ->
+        Type.enumValue $ column_name_gql columnEntry
+
+    fieldEnumType =
+      Type.enum (tableName <> "_column") fieldEnumVariants
+        & Type.withDescription
+          "This enum contains a variant for each column in the table"
+
+    onConflict =
+      Type.inputObject
+        (tableName <> "_upsert_on_conflict")
+        [ Type.inputValue
+            "constraint"
+            (Type.nonNull $ Type.list $ Type.nonNull fieldEnumType)
+            & Type.inputValueWithDescription
+              "columns to handle conflicts of"
+        , Type.inputValue
+            "update_columns"
+            (Type.nonNull $ Type.list $ Type.nonNull fieldEnumType)
+            & Type.inputValueWithDescription
+              "columns to override on conflict"
+        , Type.inputValue "where" (filterType table)
+            & Type.inputValueWithDescription
+              "filter specifying which conflicting columns to update"
+        ]
+        & Type.withDescription
+          ( "Specifies how broken UNIQUE constraints for "
+              <> table.name
+              <> " should be handled"
+          )
+
+  Type.field
+    ("insert_" <> tableName)
+    (mutationResponseType accessMode table)
+    & Type.fieldWithDescription
+      ("Insert new rows in table \"" <> table.name <> "\"")
+    & Type.withArguments
+      [ Type.inputValue
+          "objects"
+          (Type.nonNull $ Type.list $ Type.nonNull insertRows)
+          & Type.inputValueWithDescription "Rows to be inserted"
+      , Type.inputValue
+          "on_conflict"
+          (Type.list $ Type.nonNull onConflict)
+          & Type.inputValueWithDescription
+            "Specifies how to handle broken UNIQUE constraints"
+      ]
+
+
+tableUpdateField :: AccessMode -> TableEntry -> Type.Field
+tableUpdateField accessMode table = do
+  let
+    tableName = doubleXEncodeGql table.name
+
+    fields =
+      table.columns <&> \columnEntry -> do
+        let colName = columnEntry.column_name_gql
+        let base = columnType columnEntry
+        Type.inputValue colName $ Type.nonNull base
+
+    updateRow =
+      Type.inputObject
+        (tableName <> "_set_input")
+        fields
+        & Type.withDescription
+          ("Fields to set for " <> table.name)
+
+  Type.field
+    ("update_" <> tableName)
+    (mutationResponseType accessMode table)
+    & Type.fieldWithDescription
+      ("Update rows in table \"" <> table.name <> "\"")
+    & Type.withArguments
+      [ Type.inputValue
+          "set"
+          (Type.nonNull $ Type.nonNull updateRow)
+          & Type.inputValueWithDescription "Fields to be updated"
+      , Type.inputValue
+          "filter"
+          (Type.nonNull $ filterType table)
+          & Type.inputValueWithDescription "Filter to select rows to be updated"
+      ]
+
+
+tableDeleteField :: AccessMode -> TableEntry -> Type.Field
+tableDeleteField accessMode table = do
+  Type.field
+    ("delete_" <> doubleXEncodeGql table.name)
+    (mutationResponseType accessMode table)
+    & Type.fieldWithDescription
+      ("Delete rows in table \"" <> table.name <> "\"")
+    & Type.withArguments
+      [ Type.inputValue
+          "filter"
+          (Type.nonNull $ filterType table)
+          & Type.inputValueWithDescription "Filter to select rows to be deleted"
+      ]
+
+
+getSchema
+  :: AccessMode
+  -> [TableEntry]
+  -> Type.Schema
+getSchema accessMode tables = do
+  let
+    queryType =
+      if canRead accessMode
+        then tables <&> tableQueryField
+        else []
+
+    mutationType =
+      if canWrite accessMode
+        then
+          P.fold
+            [ tables <&> tableInsertField accessMode
+            , tables <&> tableUpdateField accessMode
+            , tables <&> tableDeleteField accessMode
+            ]
+        else []
+
+  Type.collectSchemaTypes $
+    Type.Schema
+      Nothing
+      []
+      (Type.object "Query" queryType)
+      (Just $ Type.object "Mutation" mutationType)
+
+
+-- We make this toplevel, because putting it inside `getSchemaResolver`
+-- means haskell will evaluate it each time, which leads to each execution
+-- taking 2-3s
+makeSchemaResolver :: Either Text (Type.Schema -> Resolver IO)
+makeSchemaResolver = do
+  let schemaField = Type.field "__schema" Type.typeSchema
+  ty <- makeType schemaField.type_
+  let gqlField = Out.Field schemaField.description ty mempty
+  pure $ \schema -> Out.ValueResolver gqlField $ pure $ toGraphQL schema
+
+
+getSchemaResolver
+  :: AccessMode
+  -> [TableEntry]
+  -> IO (HashMap Text (Resolver IO))
+getSchemaResolver accessMode tables = do
+  case makeSchemaResolver of
+    Right make -> do
+      let schema = getSchema accessMode tables
+      pure $ HashMap.singleton "__schema" $ make schema
+    Left err -> fail $ T.unpack err
diff --git a/source/AirGQL/Introspection/Resolver.hs b/source/AirGQL/Introspection/Resolver.hs
new file mode 100644
index 0000000..f030c65
--- /dev/null
+++ b/source/AirGQL/Introspection/Resolver.hs
@@ -0,0 +1,182 @@
+module AirGQL.Introspection.Resolver (makeType, makeConstField, makeChildField) where
+
+import Protolude (
+  Either (Left),
+  IO,
+  Int,
+  MonadReader (ask),
+  Text,
+  fromMaybe,
+  mempty,
+  note,
+  pure,
+  ($),
+  (+),
+  (<$>),
+  (<&>),
+  (<>),
+  (>=),
+ )
+import Protolude qualified as P
+
+import AirGQL.Introspection.Types qualified as IType
+import Data.HashMap.Strict qualified as HashMap
+import Language.GraphQL.Type qualified as Type
+import Language.GraphQL.Type.In qualified as In
+import Language.GraphQL.Type.Out qualified as Out
+
+
+type Result = Either Text
+
+
+maxDepth :: Int
+maxDepth = 9
+
+
+makeType :: IType.IntrospectionType -> Result (Out.Type IO)
+makeType = makeTypeWithDepth 0
+
+
+makeTypeWithDepth :: Int -> IType.IntrospectionType -> Result (Out.Type IO)
+makeTypeWithDepth depth ty = do
+  case ty.kind of
+    IType.Scalar -> do
+      name <- note "No `name` found for scalar" ty.name
+      pure $ Out.NamedScalarType $ Type.ScalarType name ty.description
+    IType.List -> do
+      ofType <- note "No `ofType` found for list" ty.ofType
+      Out.ListType <$> makeTypeWithDepth depth ofType
+    IType.Enum -> do
+      name <- note "No `name` found for enum" ty.name
+      enumValues <- note "No `enumValues` found for enum" ty.enumValues
+      let variants = enumValues <&> \variant -> (variant.name, Type.EnumValue variant.description)
+      pure $
+        Out.NamedEnumType $
+          Type.EnumType name ty.description $
+            HashMap.fromList variants
+    IType.NonNull -> do
+      ofType <- note "No `ofType` found for nonnull" ty.ofType
+      inner <- makeTypeWithDepth depth ofType
+      pure $ case inner of
+        Out.EnumBaseType enumType -> Out.NonNullEnumType enumType
+        Out.UnionBaseType unionType -> Out.NonNullUnionType unionType
+        Out.ScalarBaseType scalarType -> Out.NonNullScalarType scalarType
+        Out.ObjectBaseType objectType -> Out.NonNullObjectType objectType
+        Out.ListBaseType listType -> Out.NonNullListType listType
+        Out.InterfaceBaseType interfaceType -> Out.NonNullInterfaceType interfaceType
+    IType.InputObject -> do
+      Left "input object in out position"
+    IType.Object -> do
+      name <- note "No `name` found for object" ty.name
+      fields <- note "No `fields` found for object" ty.fields
+      resolvers <-
+        if depth >= maxDepth
+          then pure []
+          else P.for fields $ \field -> do
+            resolver <- makeChildFieldWithDepth (depth + 1) field
+            pure (field.name, resolver)
+
+      typenameResolver <-
+        makeConstFieldWithDepth
+          depth
+          (IType.field "__typename" $ IType.nonNull IType.typeString)
+          (Type.String name)
+
+      pure
+        $ Out.NamedObjectType
+        $ Type.ObjectType
+          name
+          ty.description
+          []
+        $ HashMap.fromList
+        $ ("__typename", typenameResolver) : resolvers
+
+
+makeConstField :: IType.Field -> Type.Value -> Result (Out.Resolver IO)
+makeConstField = makeConstFieldWithDepth 0
+
+
+makeConstFieldWithDepth :: Int -> IType.Field -> Type.Value -> Result (Out.Resolver IO)
+makeConstFieldWithDepth depth field value = do
+  ty <- makeTypeWithDepth depth field.type_
+  let gqlField = Out.Field field.description ty mempty
+  pure $ Out.ValueResolver gqlField $ pure value
+
+
+makeChildField :: IType.Field -> Result (Out.Resolver IO)
+makeChildField = makeChildFieldWithDepth 0
+
+
+makeChildFieldWithDepth :: Int -> IType.Field -> Result (Out.Resolver IO)
+makeChildFieldWithDepth depth field = do
+  args <- P.for field.args $ \arg -> do
+    ty <- makeInTypeWithDepth depth arg.type_
+    pure (arg.name, In.Argument arg.description ty arg.defaultValue)
+  ty <- makeTypeWithDepth depth field.type_
+  let gqlField = Out.Field field.description ty $ HashMap.fromList args
+  pure $ Out.ValueResolver gqlField $ do
+    context <- ask
+    let defaultValue =
+          if Out.isNonNullType ty
+            then
+              Type.String $
+                "Error: field '"
+                  <> field.name
+                  <> "' not found "
+            else Type.Null
+    case context.values of
+      Type.Object obj ->
+        pure $
+          fromMaybe defaultValue $
+            HashMap.lookup field.name obj
+      _ -> pure defaultValue
+
+
+makeInTypeWithDepth :: Int -> IType.IntrospectionType -> Result In.Type
+makeInTypeWithDepth depth ty = do
+  case ty.kind of
+    IType.Scalar -> do
+      name <- note "No `name` found for scalar" ty.name
+      pure $ In.NamedScalarType $ Type.ScalarType name ty.description
+    IType.List -> do
+      ofType <- note "No `ofType` found for list" ty.ofType
+      In.ListType <$> makeInTypeWithDepth depth ofType
+    IType.Enum -> do
+      name <- note "No `name` found for enum" ty.name
+      enumValues <- note "No `enumValues` found for enum" ty.enumValues
+      let variants = enumValues <&> \variant -> (variant.name, Type.EnumValue variant.description)
+      pure $
+        In.NamedEnumType $
+          Type.EnumType name ty.description $
+            HashMap.fromList variants
+    IType.NonNull -> do
+      ofType <- note "No `ofType` found for nonnull" ty.ofType
+      inner <- makeInTypeWithDepth depth ofType
+      pure $ case inner of
+        In.EnumBaseType enumType -> In.NonNullEnumType enumType
+        In.ScalarBaseType scalarType -> In.NonNullScalarType scalarType
+        In.InputObjectBaseType objectType -> In.NonNullInputObjectType objectType
+        In.ListBaseType listType -> In.NonNullListType listType
+    IType.Object -> do
+      Left "out object in input position"
+    IType.InputObject -> do
+      name <- note "No `name` found for object" ty.name
+      fields <- note "No `inputFields` found for object" ty.inputFields
+      gqlFields <-
+        if depth >= maxDepth
+          then pure []
+          else P.for fields $ \field -> do
+            inner <- makeInTypeWithDepth (depth + 1) field.type_
+            let inputField =
+                  In.InputField
+                    field.description
+                    inner
+                    field.defaultValue
+            pure (field.name, inputField)
+
+      pure
+        $ In.NamedInputObjectType
+        $ Type.InputObjectType
+          name
+          ty.description
+        $ HashMap.fromList gqlFields
diff --git a/source/AirGQL/Introspection/Types.hs b/source/AirGQL/Introspection/Types.hs
new file mode 100644
index 0000000..ed8ecc4
--- /dev/null
+++ b/source/AirGQL/Introspection/Types.hs
@@ -0,0 +1,481 @@
+module AirGQL.Introspection.Types (
+  Schema (..),
+  IntrospectionType (..),
+  TypeKind (..),
+  Field (..),
+  InputValue (..),
+  EnumValue (..),
+  list,
+  nonNull,
+  field,
+  withArguments,
+  inputValue,
+  inputValueWithDescription,
+  withName,
+  withDescription,
+  fieldWithDescription,
+  scalar,
+  object,
+  inputObject,
+  typeSchema,
+  typeIntrospectionType,
+  typeField,
+  typeString,
+  typeInt,
+  typeBool,
+  collectSchemaTypes,
+  enum,
+  enumValue,
+  enumValueWithDescription,
+  deprecatedEnumValue,
+) where
+
+import Data.HashMap.Strict (HashMap)
+import Data.HashMap.Strict qualified as HashMap
+import Language.GraphQL.Class (ToGraphQL (toGraphQL))
+import Language.GraphQL.Type qualified as Value
+import Protolude (
+  Bool (False, True),
+  Generic,
+  Maybe (Just, Nothing),
+  MonadState (get, put),
+  Monoid (mempty),
+  Show,
+  State,
+  Text,
+  execState,
+  for_,
+  not,
+  show,
+  when,
+  ($),
+  (&),
+ )
+
+
+data Schema = Schema
+  { description :: Maybe Text
+  , types :: [IntrospectionType]
+  , queryType :: IntrospectionType
+  , mutationType :: Maybe IntrospectionType
+  }
+  deriving (Show, Generic)
+
+
+instance ToGraphQL Schema where
+  toGraphQL schema =
+    Value.Object $
+      HashMap.fromList
+        [ ("description", toGraphQL schema.description)
+        , ("types", toGraphQL schema.types)
+        , ("queryType", toGraphQL schema.queryType)
+        , ("mutationType", toGraphQL schema.mutationType)
+        , ("subscriptionType", Value.Null)
+        , ("directives", Value.List [])
+        ]
+
+
+typeSchema :: IntrospectionType
+typeSchema =
+  object
+    "__Schema"
+    [ field "description" typeString
+    , field "types" $ nonNull $ list $ nonNull typeIntrospectionType
+    , field "queryType" $ nonNull typeIntrospectionType
+    , field "mutationType" typeIntrospectionType
+    , field "subscriptionType" typeIntrospectionType
+    , field "directives" $ nonNull $ list $ nonNull typeDirective
+    ]
+
+
+typeDirective :: IntrospectionType
+typeDirective =
+  object
+    "__Directive"
+    [ field "name" typeString
+    , field "description" typeString
+    , field "args" $ nonNull $ list $ nonNull typeInputValue
+    , field "isRepeatable" $ nonNull typeBool
+    , field "locations" $ nonNull $ list $ nonNull typeDirectiveLocation
+    ]
+
+
+typeDirectiveLocation :: IntrospectionType
+typeDirectiveLocation =
+  enum
+    "__DirectiveLocation"
+    [ enumValue "QUERY"
+    , enumValue "MUTATION"
+    , enumValue "SUBSCRIPTION"
+    , enumValue "FIELD"
+    , enumValue "FRAGMENT_DEFINITION"
+    , enumValue "FRAGMENT_SPREAD"
+    , enumValue "INLINE_FRAGMENT"
+    , enumValue "VARIABLE_DEFINITION"
+    , enumValue "SCHEMA"
+    , enumValue "SCALAR"
+    , enumValue "OBJECT"
+    , enumValue "FIELD_DEFINITION"
+    , enumValue "ARGUMENT_DEFINITION"
+    , enumValue "INTERFACE"
+    , enumValue "UNION"
+    , enumValue "ENUM"
+    , enumValue "ENUM_VALUE"
+    , enumValue "INPUT_OBJECT"
+    , enumValue "INPUT_FIELD_DEFINITION"
+    ]
+
+
+data TypeKind = Scalar | Object | Enum | InputObject | List | NonNull
+  deriving (Show, Generic)
+
+
+-- $(deriveToGraphQL ''TypeKind)
+instance ToGraphQL TypeKind where
+  toGraphQL Scalar = Value.Enum "SCALAR"
+  toGraphQL Object = Value.Enum "OBJECT"
+  toGraphQL Enum = Value.Enum "ENUM"
+  toGraphQL InputObject = Value.Enum "INPUT_OBJECT"
+  toGraphQL List = Value.Enum "LIST"
+  toGraphQL NonNull = Value.Enum "NON_NULL"
+
+
+data IntrospectionType = IType
+  { kind :: TypeKind
+  , name :: Maybe Text
+  , description :: Maybe Text
+  , interfaces :: Maybe [IntrospectionType]
+  , possibleTypes :: Maybe [IntrospectionType]
+  , fields :: Maybe [Field]
+  , inputFields :: Maybe [InputValue]
+  , enumValues :: Maybe [EnumValue]
+  , ofType :: Maybe IntrospectionType
+  }
+  deriving (Show, Generic)
+
+
+instance ToGraphQL IntrospectionType where
+  toGraphQL ty =
+    Value.Object $
+      HashMap.fromList
+        [ ("kind", toGraphQL ty.kind)
+        , ("name", toGraphQL ty.name)
+        , ("description", toGraphQL ty.description)
+        , ("interfaces", toGraphQL ty.interfaces)
+        , ("possibleTypes", toGraphQL ty.possibleTypes)
+        , ("fields", toGraphQL ty.fields)
+        , ("enumValues", toGraphQL ty.enumValues)
+        , ("inputFields", toGraphQL ty.inputFields)
+        , ("ofType", toGraphQL ty.ofType)
+        ]
+
+
+typeIntrospectionType :: IntrospectionType
+typeIntrospectionType =
+  object
+    "__Type"
+    [ field
+        "kind"
+        $ enum
+          "__TypeKind"
+          [ enumValue "SCALAR"
+          , enumValue "OBJECT"
+          , enumValue "ENUM"
+          , enumValue "INPUT_OBJECT"
+          , enumValue "LIST"
+          , enumValue "NON_NULL"
+          , enumValue "INTERFACE"
+          ]
+    , field "name" typeString
+    , field "description" typeString
+    , field "interfaces" $ list $ nonNull typeIntrospectionType
+    , field "possibleTypes" $ list $ nonNull typeIntrospectionType
+    , field "fields" (list $ nonNull typeField)
+        & withArguments [inputValue "includeDeprecated" typeBool]
+    , field "enumValues" (list $ nonNull typeEnumValue)
+        & withArguments [inputValue "includeDeprecated" typeBool]
+    , field "inputFields" $ list $ nonNull typeInputValue
+    , field "ofType" typeIntrospectionType
+    ]
+
+
+emptyType :: TypeKind -> IntrospectionType
+emptyType kind =
+  IType
+    { kind
+    , name = Nothing
+    , description = Nothing
+    , interfaces = Nothing
+    , possibleTypes = Nothing
+    , fields = Nothing
+    , enumValues = Nothing
+    , inputFields = Nothing
+    , ofType = Nothing
+    }
+
+
+nonNull :: IntrospectionType -> IntrospectionType
+nonNull ty =
+  (emptyType NonNull)
+    { ofType = Just ty
+    }
+
+
+list :: IntrospectionType -> IntrospectionType
+list ty =
+  (emptyType List)
+    { ofType = Just ty
+    }
+
+
+object :: Text -> [Field] -> IntrospectionType
+object name fields =
+  (emptyType Object)
+    { fields = Just fields
+    , name = Just name
+    , interfaces = Just []
+    }
+
+
+inputObject :: Text -> [InputValue] -> IntrospectionType
+inputObject name fields =
+  (emptyType InputObject)
+    { inputFields = Just fields
+    , name = Just name
+    , interfaces = Just []
+    }
+
+
+enum :: Text -> [EnumValue] -> IntrospectionType
+enum name variants =
+  (emptyType Enum)
+    { enumValues = Just variants
+    , name = Just name
+    }
+
+
+withName :: Text -> IntrospectionType -> IntrospectionType
+withName newName (IType{..}) =
+  IType
+    { name = Just newName
+    , ..
+    }
+
+
+withDescription :: Text -> IntrospectionType -> IntrospectionType
+withDescription newDesc (IType{..}) =
+  IType
+    { description = Just newDesc
+    , ..
+    }
+
+
+scalar :: Text -> IntrospectionType
+scalar tyName =
+  emptyType Scalar
+    & withName tyName
+
+
+data Field = Field
+  { name :: Text
+  , description :: Maybe Text
+  , args :: [InputValue]
+  , type_ :: IntrospectionType
+  , isDeprecated :: Bool
+  , deprecationReason :: Maybe Text
+  }
+  deriving (Show, Generic)
+
+
+instance ToGraphQL Field where
+  toGraphQL thisField =
+    Value.Object $
+      HashMap.fromList
+        [ ("name", toGraphQL thisField.name)
+        , ("description", toGraphQL thisField.description)
+        , ("args", toGraphQL thisField.args)
+        , ("type", toGraphQL thisField.type_)
+        , ("isDeprecated", toGraphQL thisField.isDeprecated)
+        , ("deprecationReason", toGraphQL thisField.deprecationReason)
+        ]
+
+
+typeField :: IntrospectionType
+typeField =
+  object
+    "__Field"
+    [ field "name" $ nonNull typeString
+    , field "description" typeString
+    , field "args" $ nonNull $ list $ nonNull typeInputValue
+    , field "type" $ nonNull typeIntrospectionType
+    , field "isDeprecated" $ nonNull typeBool
+    , field "deprecationReason" typeString
+    ]
+
+
+fieldWithDescription :: Text -> Field -> Field
+fieldWithDescription newDesc (Field{..}) =
+  Field
+    { description = Just newDesc
+    , ..
+    }
+
+
+field :: Text -> IntrospectionType -> Field
+field fieldName fieldType =
+  Field
+    { name = fieldName
+    , description = Nothing
+    , args = []
+    , type_ = fieldType
+    , isDeprecated = False
+    , deprecationReason = Nothing
+    }
+
+
+withArguments :: [InputValue] -> Field -> Field
+withArguments argList (Field{..}) = Field{args = argList, ..}
+
+
+data InputValue = InputValue
+  { name :: Text
+  , description :: Maybe Text
+  , type_ :: IntrospectionType
+  , defaultValue :: Maybe Value.Value
+  }
+  deriving (Show, Generic)
+
+
+instance ToGraphQL InputValue where
+  toGraphQL value =
+    Value.Object $
+      HashMap.fromList
+        [ ("name", toGraphQL value.name)
+        , ("description", toGraphQL value.description)
+        , ("type", toGraphQL value.type_)
+        , -- TODO: I don't think show is the correct function here
+          ("defaultValue", Value.String $ show value.defaultValue)
+        ]
+
+
+typeInputValue :: IntrospectionType
+typeInputValue =
+  object
+    "__InputValue"
+    [ field "name" $ nonNull typeString
+    , field "description" typeString
+    , field "type" $ nonNull typeIntrospectionType
+    , field "defaultValue" typeString
+    ]
+
+
+inputValue :: Text -> IntrospectionType -> InputValue
+inputValue fieldName fieldType =
+  InputValue
+    { name = fieldName
+    , description = Nothing
+    , type_ = fieldType
+    , defaultValue = Nothing
+    }
+
+
+inputValueWithDescription :: Text -> InputValue -> InputValue
+inputValueWithDescription newDesc (InputValue{..}) =
+  InputValue
+    { description = Just newDesc
+    , ..
+    }
+
+
+data EnumValue = EnumValue
+  { name :: Text
+  , description :: Maybe Text
+  , isDeprecated :: Bool
+  , deprecationReason :: Maybe Text
+  }
+  deriving (Show, Generic)
+
+
+instance ToGraphQL EnumValue where
+  toGraphQL value =
+    Value.Object $
+      HashMap.fromList
+        [ ("name", toGraphQL value.name)
+        , ("description", toGraphQL value.description)
+        , ("isDeprecated", toGraphQL value.isDeprecated)
+        , ("deprecationReason", toGraphQL value.deprecationReason)
+        ]
+
+
+typeEnumValue :: IntrospectionType
+typeEnumValue =
+  object
+    "__EnumValue"
+    [ field "name" $ nonNull typeString
+    , field "description" typeString
+    , field "isDeprecated" $ nonNull typeBool
+    , field "deprecationReason" typeString
+    ]
+
+
+enumValue :: Text -> EnumValue
+enumValue name = EnumValue{name = name, description = Nothing, isDeprecated = False, deprecationReason = Nothing}
+
+
+enumValueWithDescription :: Text -> EnumValue -> EnumValue
+enumValueWithDescription newDesc (EnumValue{..}) =
+  EnumValue{description = Just newDesc, ..}
+
+
+deprecatedEnumValue :: Text -> EnumValue -> EnumValue
+deprecatedEnumValue reason (EnumValue{..}) =
+  EnumValue
+    { isDeprecated = True
+    , deprecationReason = Just reason
+    , ..
+    }
+
+
+typeString :: IntrospectionType
+typeString = scalar "String"
+
+
+typeInt :: IntrospectionType
+typeInt = scalar "Int"
+
+
+typeBool :: IntrospectionType
+typeBool = scalar "Boolean"
+
+
+collectSchemaTypes :: Schema -> Schema
+collectSchemaTypes schema = do
+  let basic = [typeInt, typeString, typeBool, typeSchema]
+  let all = do
+        collectTypes schema.queryType
+        for_ schema.mutationType collectTypes
+        for_ basic collectTypes
+  schema
+    { types = HashMap.elems $ execState all mempty
+    }
+
+
+-- | Collect a map of all the named types occurring inside a type
+collectTypes :: IntrospectionType -> State (HashMap Text IntrospectionType) ()
+collectTypes ty = do
+  for_ ty.ofType collectTypes
+  for_ ty.name $ \name -> do
+    current <- get
+    when (not $ HashMap.member name current) $ do
+      put $ HashMap.insert name ty current
+      for_ ty.interfaces $ \interfaces -> do
+        for_ interfaces collectTypes
+      for_ ty.possibleTypes $ \possibleTypes -> do
+        for_ possibleTypes collectTypes
+      for_ ty.inputFields $ \inputFields -> do
+        for_ inputFields $ \thisField -> collectTypes thisField.type_
+      for_ ty.fields $ \fields -> do
+        for_ fields $ \thisField -> do
+          collectTypes thisField.type_
+          for_ thisField.args $ \arg ->
+            collectTypes arg.type_
diff --git a/source/AirGQL/Lib.hs b/source/AirGQL/Lib.hs
index 5aa4902..c3c72ff 100644
--- a/source/AirGQL/Lib.hs
+++ b/source/AirGQL/Lib.hs
@@ -7,6 +7,8 @@
 
 module AirGQL.Lib (
   AccessMode (..),
+  canRead,
+  canWrite,
   ColumnEntry (..),
   GqlTypeName (..),
   getEnrichedTable,
@@ -117,6 +119,16 @@ data AccessMode = ReadOnly | WriteOnly | ReadAndWrite
   deriving (Eq, Show)
 
 
+canRead :: AccessMode -> Bool
+canRead WriteOnly = False
+canRead _ = True
+
+
+canWrite :: AccessMode -> Bool
+canWrite ReadOnly = False
+canWrite _ = True
+
+
 data ObjectType = Table | Index | View | Trigger
   deriving (Show, Eq, Generic)
 
diff --git a/source/AirGQL/ServerUtils.hs b/source/AirGQL/ServerUtils.hs
index 4cfbb4e..f046436 100644
--- a/source/AirGQL/ServerUtils.hs
+++ b/source/AirGQL/ServerUtils.hs
@@ -26,7 +26,7 @@ import Language.GraphQL.JSON (graphql)
 import System.FilePath (pathSeparator, (</>))
 
 import AirGQL.GraphQL (getDerivedSchema)
-import AirGQL.Lib (getTables)
+import AirGQL.Lib (getEnrichedTables)
 import AirGQL.Types.SchemaConf (SchemaConf)
 import AirGQL.Types.Types (
   GQLResponse (GQLResponse, data_, errors),
@@ -49,23 +49,32 @@ executeQuery schemaConf dbIdOrPath reqDir query vars opNameMb = do
           else reqDir </> "main.sqlite"
 
   theConn <- SS.open dbFilePath
-  tables <- getTables theConn
-  schema <- getDerivedSchema schemaConf theConn dbIdOrPath tables
-  result <- graphql schema opNameMb vars query
-  SS.close theConn
-
-  case result of
-    Left errMsg -> do
-      errors <- sourceToList errMsg
+  tablesEither <- getEnrichedTables theConn
+  case tablesEither of
+    Left err ->
       pure $
         gqlResponseToObject $
           GQLResponse
             { data_ = Nothing
-            , errors =
-                Just $
-                  errors
-                    <&> ((\(Response _ errs) -> errs) >>> toList)
-                    & P.concat
-                    <&> (\(Error msg _ _) -> String msg)
+            , errors = Just [String err]
             }
-    Right response -> pure response
+    Right tables -> do
+      schema <- getDerivedSchema schemaConf theConn dbIdOrPath tables
+      result <- graphql schema opNameMb vars query
+      SS.close theConn
+
+      case result of
+        Left errMsg -> do
+          errors <- sourceToList errMsg
+          pure $
+            gqlResponseToObject $
+              GQLResponse
+                { data_ = Nothing
+                , errors =
+                    Just $
+                      errors
+                        <&> ((\(Response _ errs) -> errs) >>> toList)
+                        & P.concat
+                        <&> (\(Error msg _ _) -> String msg)
+                }
+        Right response -> pure response