diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bbcc42b276..37d173f3399 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - server: update `create_scheduled_event` API to return `event_id` in response - server: fix bug which allowed inconsistent metadata to exist after the `replace_metadata` API even though `allow_inconsistent_object` is set to `false`. - server: fix explicit `null` values not allowed in nested object relationship inserts (#7484) +- server: `introspect_remote_schema` API now returns original remote schema instead of customized schema - server: prevent empty subscription roots in the schema (#6898) - console: support tracking of functions with return a single row diff --git a/server/src-lib/Hasura/GraphQL/RemoteServer.hs b/server/src-lib/Hasura/GraphQL/RemoteServer.hs index df44b798dd4..f510e3eac94 100644 --- a/server/src-lib/Hasura/GraphQL/RemoteServer.hs +++ b/server/src-lib/Hasura/GraphQL/RemoteServer.hs @@ -3,10 +3,7 @@ module Hasura.GraphQL.RemoteServer , IntrospectionResult , execRemoteGQ , identityCustomizer - , customizeIntrospectionResult -- The following exports are needed for unit tests - , introspectionResultToJSON - , parseIntrospectionResult , getCustomizer , validateSchemaCustomizationsDistinct ) where @@ -32,10 +29,10 @@ import Control.Arrow.Extended (left) import Control.Exception (try) import Control.Lens ((^.)) import Control.Monad.Unique -import Data.Aeson ((.:), (.:?), (.=)) +import Data.Aeson ((.:), (.:?)) import Data.FileEmbed (makeRelativeToProject) import Data.List.Extended (duplicates) -import Data.Text.Extended (dquoteList, toTxt, (<<>)) +import Data.Text.Extended (dquoteList, (<<>)) import Data.Tuple (swap) import Network.URI (URI) @@ -155,21 +152,18 @@ fetchRemoteSchema -> ValidatedRemoteSchemaDef -> m RemoteSchemaCtx fetchRemoteSchema env manager _rscName rsDef@ValidatedRemoteSchemaDef{..} = do - (_, _, rscRawIntrospectionResultDirty) <- + (_, _, _rscRawIntrospectionResult) <- execRemoteGQ env manager adminUserInfo [] rsDef introspectionQuery -- Parse the JSON into flat GraphQL type AST FromIntrospection _rscIntroOriginal <- - J.eitherDecode rscRawIntrospectionResultDirty `onLeft` (throwRemoteSchema . T.pack) + J.eitherDecode _rscRawIntrospectionResult `onLeft` (throwRemoteSchema . T.pack) -- possibly transform type names from the remote schema, per the user's 'RemoteSchemaDef' let rsCustomizer = getCustomizer (addDefaultRoots _rscIntroOriginal) _vrsdCustomization validateSchemaCustomizations rsCustomizer (irDoc _rscIntroOriginal) - let customizedIntro = customizeIntrospectionResult rsCustomizer _rscIntroOriginal - _rscRawIntrospectionResult = J.encode $ FromIntrospection customizedIntro - let _rscInfo = RemoteSchemaInfo{..} -- Check that the parsed GraphQL type info is valid by running the schema generation (piQuery, piMutation, piSubscription) <- @@ -207,26 +201,15 @@ newtype FromIntrospection a = FromIntrospection { fromIntrospection :: a } deriving (Show, Eq, Generic, Functor) --- | Include a map from type name to kind. This allows us to pass --- extra type information required to convert our schema --- back into JSON. -data WithKinds a - = WithKinds !(HashMap G.Name Text) !a - deriving (Show, Eq, Generic, Functor) - pErr :: (MonadFail m) => Text -> m a pErr = fail . T.unpack kindErr :: (MonadFail m) => Text -> Text -> m a kindErr gKind eKind = pErr $ "Invalid `kind: " <> gKind <> "` in " <> eKind - instance J.FromJSON (FromIntrospection G.Description) where parseJSON = fmap (FromIntrospection . G.Description) . J.parseJSON -instance J.ToJSON (FromIntrospection G.Description) where - toJSON = J.toJSON . G.unDescription . fromIntrospection - instance J.FromJSON (FromIntrospection G.ScalarTypeDefinition) where parseJSON = J.withObject "ScalarTypeDefinition" $ \o -> do kind <- o .: "kind" @@ -237,13 +220,6 @@ instance J.FromJSON (FromIntrospection G.ScalarTypeDefinition) where r = G.ScalarTypeDefinition desc' name [] return $ FromIntrospection r -instance J.ToJSON (FromIntrospection G.ScalarTypeDefinition) where - toJSON (FromIntrospection G.ScalarTypeDefinition {..}) = objectWithoutNullValues - [ "kind" .= J.String "SCALAR" - , "name" .= _stdName - , "description" .= fmap FromIntrospection _stdDescription - ] - instance J.FromJSON (FromIntrospection (G.ObjectTypeDefinition G.InputValueDefinition)) where parseJSON = J.withObject "ObjectTypeDefinition" $ \o -> do kind <- o .: "kind" @@ -258,18 +234,6 @@ instance J.FromJSON (FromIntrospection (G.ObjectTypeDefinition G.InputValueDefin r = G.ObjectTypeDefinition desc' name implIfaces [] flds return $ FromIntrospection r -instance J.ToJSON (WithKinds (G.ObjectTypeDefinition G.InputValueDefinition)) where - toJSON (WithKinds kinds G.ObjectTypeDefinition {..}) = objectWithoutNullValues - [ "kind" .= J.String "OBJECT" - , "name" .= _otdName - , "description" .= fmap FromIntrospection _otdDescription - , "fields" .= fmap (WithKinds kinds) _otdFieldsDefinition - , "interfaces" .= fmap (WithKinds kinds . toInterfaceTypeDefinition) _otdImplementsInterfaces - ] - where - toInterfaceTypeDefinition :: G.Name -> G.InterfaceTypeDefinition [G.Name] G.InputValueDefinition - toInterfaceTypeDefinition name = G.InterfaceTypeDefinition Nothing name [] [] [] - instance (J.FromJSON (FromIntrospection a)) => J.FromJSON (FromIntrospection (G.FieldDefinition a)) where parseJSON = J.withObject "FieldDefinition" $ \o -> do name <- o .: "name" @@ -281,14 +245,6 @@ instance (J.FromJSON (FromIntrospection a)) => J.FromJSON (FromIntrospection (G. (fromIntrospection _type) [] return $ FromIntrospection r -instance J.ToJSON (WithKinds a) => J.ToJSON (WithKinds (G.FieldDefinition a)) where - toJSON (WithKinds kinds G.FieldDefinition {..}) = objectWithoutNullValues - [ "name" .= _fldName - , "description" .= fmap FromIntrospection _fldDescription - , "args" .= fmap (WithKinds kinds) _fldArgumentsDefinition - , "type" .= WithKinds kinds _fldType - ] - instance J.FromJSON (FromIntrospection G.GType) where parseJSON = J.withObject "GType" $ \o -> do kind <- o .: "kind" @@ -309,25 +265,6 @@ instance J.FromJSON (FromIntrospection G.GType) where G.TypeList _ ty -> G.TypeList (G.Nullability False) ty G.TypeNamed _ n -> G.TypeNamed (G.Nullability False) n -instance J.ToJSON (WithKinds G.GType) where - toJSON (WithKinds kinds gtype) = objectWithoutNullValues $ case gtype of - G.TypeNamed (G.Nullability True) name -> - [ "kind" .= Map.lookup name kinds - , "name" .= name - ] - G.TypeNamed (G.Nullability False) name -> - [ "kind" .= J.String "NON_NULL" - , "ofType" .= WithKinds kinds (G.TypeNamed (G.Nullability True) name) - ] - G.TypeList (G.Nullability True) ty -> - [ "kind" .= J.String "LIST" - , "ofType" .= WithKinds kinds ty - ] - G.TypeList (G.Nullability False) ty -> - [ "kind" .= J.String "NON_NULL" - , "ofType" .= WithKinds kinds (G.TypeList (G.Nullability True) ty) - ] - instance J.FromJSON (FromIntrospection G.InputValueDefinition) where parseJSON = J.withObject "InputValueDefinition" $ \o -> do name <- o .: "name" @@ -339,22 +276,11 @@ instance J.FromJSON (FromIntrospection G.InputValueDefinition) where r = G.InputValueDefinition desc' name (fromIntrospection _type) defVal' [] return $ FromIntrospection r -instance J.ToJSON (WithKinds G.InputValueDefinition) where - toJSON (WithKinds kinds G.InputValueDefinition {..}) = objectWithoutNullValues - [ "name" .= _ivdName - , "description" .= fmap FromIntrospection _ivdDescription - , "type" .= WithKinds kinds _ivdType - , "defaultValue" .= fmap FromIntrospection _ivdDefaultValue - ] - instance J.FromJSON (FromIntrospection (G.Value Void)) where parseJSON = J.withText "Value Void" $ \t -> let parseValueConst = G.runParser G.value in FromIntrospection <$> onLeft (parseValueConst t) (fail . T.unpack) -instance J.ToJSON (FromIntrospection (G.Value Void)) where - toJSON = J.String . toTxt . fromIntrospection - instance J.FromJSON (FromIntrospection (G.InterfaceTypeDefinition [G.Name] G.InputValueDefinition)) where parseJSON = J.withObject "InterfaceTypeDefinition" $ \o -> do kind <- o .: "kind" @@ -371,15 +297,6 @@ instance J.FromJSON (FromIntrospection (G.InterfaceTypeDefinition [G.Name] G.Inp let r = G.InterfaceTypeDefinition desc' name [] flds possTps return $ FromIntrospection r -instance J.ToJSON (WithKinds (G.InterfaceTypeDefinition [G.Name] G.InputValueDefinition)) where - toJSON (WithKinds kinds G.InterfaceTypeDefinition {..}) = objectWithoutNullValues - [ "kind" .= J.String "INTERFACE" - , "name" .= _itdName - , "description" .= fmap FromIntrospection _itdDescription - , "fields" .= fmap (WithKinds kinds) _itdFieldsDefinition - , "possibleTypes" .= fmap (WithKinds kinds . toObjectTypeDefinition) _itdPossibleTypes - ] - instance J.FromJSON (FromIntrospection G.UnionTypeDefinition) where parseJSON = J.withObject "UnionTypeDefinition" $ \o -> do kind <- o .: "kind" @@ -392,14 +309,6 @@ instance J.FromJSON (FromIntrospection G.UnionTypeDefinition) where let r = G.UnionTypeDefinition desc' name [] possibleTypes' return $ FromIntrospection r -instance J.ToJSON (WithKinds G.UnionTypeDefinition) where - toJSON (WithKinds kinds G.UnionTypeDefinition {..}) = objectWithoutNullValues - [ "kind" .= J.String "UNION" - , "name" .= _utdName - , "description" .= fmap FromIntrospection _utdDescription - , "possibleTypes" .= fmap (WithKinds kinds . toObjectTypeDefinition) _utdMemberTypes - ] - instance J.FromJSON (FromIntrospection G.EnumTypeDefinition) where parseJSON = J.withObject "EnumTypeDefinition" $ \o -> do kind <- o .: "kind" @@ -411,14 +320,6 @@ instance J.FromJSON (FromIntrospection G.EnumTypeDefinition) where let r = G.EnumTypeDefinition desc' name [] (fmap fromIntrospection vals) return $ FromIntrospection r -instance J.ToJSON (FromIntrospection G.EnumTypeDefinition) where - toJSON (FromIntrospection G.EnumTypeDefinition {..}) = objectWithoutNullValues - [ "kind" .= J.String "ENUM" - , "name" .= _etdName - , "description" .= fmap FromIntrospection _etdDescription - , "enumValues" .= fmap FromIntrospection _etdValueDefinitions - ] - instance J.FromJSON (FromIntrospection G.EnumValueDefinition) where parseJSON = J.withObject "EnumValueDefinition" $ \o -> do name <- o .: "name" @@ -427,12 +328,6 @@ instance J.FromJSON (FromIntrospection G.EnumValueDefinition) where let r = G.EnumValueDefinition desc' name [] return $ FromIntrospection r -instance J.ToJSON (FromIntrospection G.EnumValueDefinition) where - toJSON (FromIntrospection G.EnumValueDefinition {..}) = objectWithoutNullValues - [ "name" .= _evdName - , "description" .= fmap FromIntrospection _evdDescription - ] - instance J.FromJSON (FromIntrospection (G.InputObjectTypeDefinition G.InputValueDefinition)) where parseJSON = J.withObject "InputObjectTypeDefinition" $ \o -> do kind <- o .: "kind" @@ -445,14 +340,6 @@ instance J.FromJSON (FromIntrospection (G.InputObjectTypeDefinition G.InputValue let r = G.InputObjectTypeDefinition desc' name [] inputFields return $ FromIntrospection r -instance J.ToJSON (WithKinds (G.InputObjectTypeDefinition G.InputValueDefinition)) where - toJSON (WithKinds kinds G.InputObjectTypeDefinition {..}) = objectWithoutNullValues - [ "kind" .= J.String "INPUT_OBJECT" - , "name" .= _iotdName - , "description" .= fmap FromIntrospection _iotdDescription - , "inputFields" .= fmap (WithKinds kinds) _iotdValueDefinitions - ] - instance J.FromJSON (FromIntrospection (G.TypeDefinition [G.Name] G.InputValueDefinition)) where parseJSON = J.withObject "TypeDefinition" $ \o -> do kind :: Text <- o .: "kind" @@ -472,15 +359,6 @@ instance J.FromJSON (FromIntrospection (G.TypeDefinition [G.Name] G.InputValueDe _ -> pErr $ "unknown kind: " <> kind return $ FromIntrospection r -instance J.ToJSON (WithKinds (G.TypeDefinition [G.Name] G.InputValueDefinition)) where - toJSON (WithKinds kinds typeDefinition) = case typeDefinition of - G.TypeDefinitionScalar scalarTypeDefinition -> J.toJSON $ FromIntrospection scalarTypeDefinition - G.TypeDefinitionObject objectTypeDefinition -> J.toJSON $ WithKinds kinds objectTypeDefinition - G.TypeDefinitionInterface interfaceTypeDefinition -> J.toJSON $ WithKinds kinds interfaceTypeDefinition - G.TypeDefinitionUnion unionTypeDefinition -> J.toJSON $ WithKinds kinds unionTypeDefinition - G.TypeDefinitionEnum enumTypeDefinition -> J.toJSON $ FromIntrospection enumTypeDefinition - G.TypeDefinitionInputObject inputObjectTypeDefinition -> J.toJSON $ WithKinds kinds inputObjectTypeDefinition - instance J.FromJSON (FromIntrospection IntrospectionResult) where parseJSON = J.withObject "SchemaDocument" $ \o -> do _data <- o .: "data" @@ -519,36 +397,6 @@ instance J.FromJSON (FromIntrospection IntrospectionResult) where queryRoot mutationRoot subsRoot return $ FromIntrospection r -instance J.ToJSON (FromIntrospection IntrospectionResult) where - toJSON (FromIntrospection IntrospectionResult{..}) = objectWithoutNullValues ["data" .= _data] - where - _data = objectWithoutNullValues ["__schema" .= schema] - schema = objectWithoutNullValues - [ "types" .= fmap (WithKinds kinds . fmap _rsitdDefinition) types - , "queryType" .= queryType - , "mutationType" .= mutationType - , "subscriptionType" .= subscriptionType - ] - RemoteSchemaIntrospection types = irDoc - kinds = Map.fromList $ types <&> \case - G.TypeDefinitionScalar G.ScalarTypeDefinition{..} -> (_stdName, "SCALAR") - G.TypeDefinitionObject G.ObjectTypeDefinition{..} -> (_otdName, "OBJECT") - G.TypeDefinitionInterface G.InterfaceTypeDefinition{..} -> (_itdName, "INTERFACE") - G.TypeDefinitionUnion G.UnionTypeDefinition{..} -> (_utdName, "UNION") - G.TypeDefinitionEnum G.EnumTypeDefinition{..} -> (_etdName, "ENUM") - G.TypeDefinitionInputObject G.InputObjectTypeDefinition{..} -> (_iotdName, "INPUT_OBJECT") - named :: G.Name -> J.Object - named = ("name" .=) - queryType = named irQueryRoot - mutationType = named <$> irMutationRoot - subscriptionType = named <$> irSubscriptionRoot - -parseIntrospectionResult :: J.Value -> J.Parser IntrospectionResult -parseIntrospectionResult value = fromIntrospection <$> J.parseJSON value - -introspectionResultToJSON :: IntrospectionResult -> J.Value -introspectionResultToJSON = J.toJSON . FromIntrospection - objectWithoutNullValues :: [J.Pair] -> J.Value objectWithoutNullValues = J.object . filter notNull where @@ -672,129 +520,6 @@ getCustomizer IntrospectionResult{..} (Just RemoteSchemaCustomization{..}) = Rem _rscDecustomizeTypeName = invertMap typeRenameMap _rscDecustomizeFieldName = mapMap (mapLookup typeRenameMap *** invertMap) fieldRenameMap -customizeIntrospectionResult :: RemoteSchemaCustomizer -> IntrospectionResult -> IntrospectionResult -customizeIntrospectionResult remoteSchemaCustomizer IntrospectionResult{..} = IntrospectionResult - { irDoc = customizeRemoteSchemaIntrospection irDoc - , irQueryRoot = customizedQueryRoot - , irMutationRoot = customizedMutationRoot - , irSubscriptionRoot = customizedSubscriptionRoot - } - where - - namespaceField = _rscNamespaceFieldName remoteSchemaCustomizer - customizeTypeName = remoteSchemaCustomizeTypeName remoteSchemaCustomizer - customizeFieldName = remoteSchemaCustomizeFieldName remoteSchemaCustomizer - - -- Create customized root type names by appending "Query", "Mutation" or "Subscription" to the custom namespace field name - customizeRootTypeName suffix = maybe id (const . (<> suffix)) namespaceField - customizedQueryRoot = customizeRootTypeName $$(G.litName "Query") irQueryRoot - customizedMutationRoot = customizeRootTypeName $$(G.litName "Mutation") <$> irMutationRoot - customizedSubscriptionRoot = customizeRootTypeName $$(G.litName "Subscription") <$> irSubscriptionRoot - - -- Create object type definitions for each of the custom namespace root types. - -- Each object type has a single field where the field name is - -- the custom namespace and the type is the original root type. - namespaceRootTypeDefinitions = case namespaceField of - Nothing -> [] - Just namespaceFieldName -> - let mkNamespaceTypeDef originalRootTypeName customizedRootTypeName = - G.TypeDefinitionObject $ G.ObjectTypeDefinition (Just "custom namespace root type") customizedRootTypeName [] [] - [G.FieldDefinition (Just "custom namespace field") namespaceFieldName [] - (G.TypeNamed (G.Nullability True) $ customizeTypeName originalRootTypeName) []] - in catMaybes - [ pure $ mkNamespaceTypeDef irQueryRoot customizedQueryRoot - , mkNamespaceTypeDef <$> irMutationRoot <*> customizedMutationRoot - , mkNamespaceTypeDef <$> irSubscriptionRoot <*> customizedSubscriptionRoot - ] - - customizeRemoteSchemaIntrospection :: RemoteSchemaIntrospection -> RemoteSchemaIntrospection - customizeRemoteSchemaIntrospection (RemoteSchemaIntrospection typeDefinitions) = - RemoteSchemaIntrospection $ namespaceRootTypeDefinitions ++ customizeTypeDefinitions typeDefinitions - where - customizeTypeDefinitions = - if hasTypeOrFieldCustomizations remoteSchemaCustomizer - then fmap customizeTypeDefinition - else id -- no need to traverse the schema if there are no type or field name customizations - - customizeTypeDefinition :: G.TypeDefinition [G.Name] RemoteSchemaInputValueDefinition -> G.TypeDefinition [G.Name] RemoteSchemaInputValueDefinition - customizeTypeDefinition = \case - G.TypeDefinitionScalar scalarTypeDefinition -> G.TypeDefinitionScalar $ customizeScalarTypeDefinition scalarTypeDefinition - G.TypeDefinitionObject objectTypeDefinition -> G.TypeDefinitionObject $ customizeObjectTypeDefinition objectTypeDefinition - G.TypeDefinitionInterface interfaceTypeDefinition -> G.TypeDefinitionInterface $ customizeInterfaceTypeDefinition interfaceTypeDefinition - G.TypeDefinitionUnion unionTypeDefinition -> G.TypeDefinitionUnion $ customizeUnionTypeDefinition unionTypeDefinition - G.TypeDefinitionEnum enumTypeDefinition -> G.TypeDefinitionEnum $ customizeEnumTypeDefinition enumTypeDefinition - G.TypeDefinitionInputObject inputObjectTypeDefinition -> G.TypeDefinitionInputObject $ customizeInputObjectTypeDefinition inputObjectTypeDefinition - - customizeScalarTypeDefinition :: G.ScalarTypeDefinition -> G.ScalarTypeDefinition - customizeScalarTypeDefinition G.ScalarTypeDefinition{..} = - G.ScalarTypeDefinition { _stdName = customizeTypeName _stdName, ..} - - customizeObjectTypeDefinition :: G.ObjectTypeDefinition RemoteSchemaInputValueDefinition -> G.ObjectTypeDefinition RemoteSchemaInputValueDefinition - customizeObjectTypeDefinition G.ObjectTypeDefinition{..} = - G.ObjectTypeDefinition - { _otdName = customizeTypeName _otdName - , _otdImplementsInterfaces = customizeTypeName <$> _otdImplementsInterfaces - , _otdFieldsDefinition = customizeFieldDefinition (customizeFieldName _otdName) <$> _otdFieldsDefinition - , .. - } - - customizeType :: G.GType -> G.GType - customizeType = \case - G.TypeNamed nullability name -> G.TypeNamed nullability $ customizeTypeName name - G.TypeList nullability gtype -> G.TypeList nullability $ customizeType gtype - - customizeFieldDefinition :: (G.Name -> G.Name) -> G.FieldDefinition RemoteSchemaInputValueDefinition -> G.FieldDefinition RemoteSchemaInputValueDefinition - customizeFieldDefinition customizeFieldName' G.FieldDefinition{..} = - G.FieldDefinition - { _fldName = customizeFieldName' _fldName - , _fldType = customizeType _fldType - , _fldArgumentsDefinition = customizeRemoteSchemaInputValueDefinition <$> _fldArgumentsDefinition - , .. - } - - customizeRemoteSchemaInputValueDefinition :: RemoteSchemaInputValueDefinition -> RemoteSchemaInputValueDefinition - customizeRemoteSchemaInputValueDefinition RemoteSchemaInputValueDefinition{..} = - RemoteSchemaInputValueDefinition - { _rsitdDefinition = customizeInputValueDefinition _rsitdDefinition - , .. - } - - customizeInputValueDefinition :: G.InputValueDefinition -> G.InputValueDefinition - customizeInputValueDefinition G.InputValueDefinition{..} = - G.InputValueDefinition - { _ivdType = customizeType _ivdType - , .. - } - - customizeInterfaceTypeDefinition :: G.InterfaceTypeDefinition [G.Name] RemoteSchemaInputValueDefinition -> G.InterfaceTypeDefinition [G.Name] RemoteSchemaInputValueDefinition - customizeInterfaceTypeDefinition G.InterfaceTypeDefinition{..} = - G.InterfaceTypeDefinition - { _itdName = customizeTypeName _itdName - , _itdFieldsDefinition = customizeFieldDefinition (customizeFieldName _itdName) <$> _itdFieldsDefinition - , _itdPossibleTypes = customizeTypeName <$> _itdPossibleTypes - , .. - } - - customizeUnionTypeDefinition :: G.UnionTypeDefinition -> G.UnionTypeDefinition - customizeUnionTypeDefinition G.UnionTypeDefinition{..} = - G.UnionTypeDefinition - { _utdName = customizeTypeName _utdName - , _utdMemberTypes = customizeTypeName <$> _utdMemberTypes - , .. - } - - customizeEnumTypeDefinition :: G.EnumTypeDefinition -> G.EnumTypeDefinition - customizeEnumTypeDefinition G.EnumTypeDefinition{..} = - G.EnumTypeDefinition { _etdName = customizeTypeName _etdName, ..} - - customizeInputObjectTypeDefinition :: G.InputObjectTypeDefinition RemoteSchemaInputValueDefinition -> G.InputObjectTypeDefinition RemoteSchemaInputValueDefinition - customizeInputObjectTypeDefinition G.InputObjectTypeDefinition{..} = - G.InputObjectTypeDefinition - { _iotdName = customizeTypeName _iotdName - , _iotdValueDefinitions = customizeRemoteSchemaInputValueDefinition <$> _iotdValueDefinitions - , .. - } - throwRemoteSchema :: QErrM m => Text -> m a diff --git a/server/src-lib/Hasura/RQL/Types/SchemaCache.hs b/server/src-lib/Hasura/RQL/Types/SchemaCache.hs index 543c79d7cd4..19bde229a99 100644 --- a/server/src-lib/Hasura/RQL/Types/SchemaCache.hs +++ b/server/src-lib/Hasura/RQL/Types/SchemaCache.hs @@ -248,8 +248,7 @@ data RemoteSchemaCtx , _rscIntroOriginal :: !IntrospectionResult -- ^ Original remote schema without customizations , _rscInfo :: !RemoteSchemaInfo , _rscRawIntrospectionResult :: !BL.ByteString - -- ^ The raw response from the introspection query against the remote server, - -- or the serialized customized introspection result if there are schema customizations. + -- ^ The raw response from the introspection query against the remote server. -- We store this so we can efficiently service 'introspect_remote_schema'. , _rscParsed :: ParsedIntrospection -- ^ FieldParsers with schema customizations applied , _rscPermissions :: !(M.HashMap RoleName IntrospectionResult) diff --git a/server/src-test/Hasura/GraphQL/RemoteServerSpec.hs b/server/src-test/Hasura/GraphQL/RemoteServerSpec.hs index 8950b1a9424..3561c9af36f 100644 --- a/server/src-test/Hasura/GraphQL/RemoteServerSpec.hs +++ b/server/src-test/Hasura/GraphQL/RemoteServerSpec.hs @@ -3,15 +3,11 @@ module Hasura.GraphQL.RemoteServerSpec (spec) where import Hasura.Prelude -import qualified Data.Aeson as J -import qualified Data.Aeson.Types as J import qualified Data.HashMap.Strict as Map import qualified Language.GraphQL.Draft.Syntax as G -import Data.ByteString.Lazy (ByteString) import Data.Containers.ListUtils (nubOrd) import Data.Either (isRight) -import Data.Text.RawString (raw) import Test.Hspec import Test.Hspec.QuickCheck import Test.QuickCheck @@ -25,23 +21,6 @@ import Hasura.RQL.Types.SchemaCache spec :: Spec spec = do describe "IntrospectionResult" $ do - prop "JSON roundtrip" $ forAll (scale (`div` 10) arbitrary) $ -- Use scale to ensure tests run in a reasonable time - \introspectionResult -> do - let json = introspectionResultToJSON introspectionResult - J.parse parseIntrospectionResult json `shouldBe` J.Success introspectionResult - customizeIntrospectionResult identityCustomizer introspectionResult `shouldBe` introspectionResult - - it "Example roundtrip" $ - case J.decode rawIntrospectionResult of - Nothing -> error "Failed to decode rawIntrospectionResult" - Just json -> - case J.parse parseIntrospectionResult json of - J.Success introspectionResult -> do - let customizedIntrospectionResult = customizeIntrospectionResult identityCustomizer introspectionResult - customizedIntrospectionResult `shouldBe` introspectionResult - introspectionResultToJSON customizedIntrospectionResult `shouldBe` json - _ -> error "Failed to parse rawIntrospectionResult" - describe "getCustomizer" $ do prop "inverse" $ forAllShrinkShow gen shrink_ show_ $ \(introspectionResult, typesAndFields, customization) -> @@ -133,1914 +112,3 @@ shrink_ (introspectionResult, typesAndFields, customization@RemoteSchemaCustomiz show_ :: (IntrospectionResult, HashMap G.Name [G.Name], RemoteSchemaCustomization) -> String show_ (_a, b, c) = show (b, c) - -rawIntrospectionResult :: ByteString -rawIntrospectionResult = [raw| -{ - "data": { - "__schema": { - "queryType": { - "name": "query_root" - }, - "subscriptionType": { - "name": "subscription_root" - }, - "types": [ - { - "kind": "SCALAR", - "name": "Boolean" - }, - { - "kind": "SCALAR", - "name": "Float" - }, - { - "kind": "SCALAR", - "name": "ID" - }, - { - "kind": "SCALAR", - "name": "Int" - }, - { - "kind": "SCALAR", - "name": "String" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "__Directive", - "fields": [ - { - "args": [], - "name": "args", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__InputValue" - } - } - } - } - }, - { - "args": [], - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [], - "name": "locations", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "__DirectiveLocation" - } - } - } - } - }, - { - "args": [], - "name": "name", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "String" - } - } - } - ] - }, - { - "kind": "ENUM", - "name": "__DirectiveLocation", - "enumValues": [ - { - "name": "ARGUMENT_DEFINITION" - }, - { - "name": "ENUM" - }, - { - "name": "ENUM_VALUE" - }, - { - "name": "FIELD" - }, - { - "name": "FIELD_DEFINITION" - }, - { - "name": "FRAGMENT_DEFINITION" - }, - { - "name": "FRAGMENT_SPREAD" - }, - { - "name": "INLINE_FRAGMENT" - }, - { - "name": "INPUT_FIELD_DEFINITION" - }, - { - "name": "INPUT_OBJECT" - }, - { - "name": "INTERFACE" - }, - { - "name": "MUTATION" - }, - { - "name": "OBJECT" - }, - { - "name": "QUERY" - }, - { - "name": "SCALAR" - }, - { - "name": "SCHEMA" - }, - { - "name": "SUBSCRIPTION" - }, - { - "name": "UNION" - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "__EnumValue", - "fields": [ - { - "args": [], - "name": "deprecationReason", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [], - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [], - "name": "isDeprecated", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "Boolean" - } - } - }, - { - "args": [], - "name": "name", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "String" - } - } - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "__Field", - "fields": [ - { - "args": [], - "name": "args", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__InputValue" - } - } - } - } - }, - { - "args": [], - "name": "deprecationReason", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [], - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [], - "name": "isDeprecated", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "Boolean" - } - } - }, - { - "args": [], - "name": "name", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "String" - } - } - }, - { - "args": [], - "name": "type", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__Type" - } - } - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "__InputValue", - "fields": [ - { - "args": [], - "name": "defaultValue", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [], - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [], - "name": "name", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "String" - } - } - }, - { - "args": [], - "name": "type", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__Type" - } - } - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "__Schema", - "fields": [ - { - "args": [], - "name": "directives", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__Directive" - } - } - } - } - }, - { - "args": [], - "name": "mutationType", - "type": { - "kind": "OBJECT", - "name": "__Type" - } - }, - { - "args": [], - "name": "queryType", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__Type" - } - } - }, - { - "args": [], - "name": "subscriptionType", - "type": { - "kind": "OBJECT", - "name": "__Type" - } - }, - { - "args": [], - "name": "types", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__Type" - } - } - } - } - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "__Type", - "fields": [ - { - "args": [], - "name": "description", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [ - { - "name": "includeDeprecated", - "defaultValue": "false", - "type": { - "kind": "SCALAR", - "name": "Boolean" - } - } - ], - "name": "enumValues", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue" - } - } - } - }, - { - "args": [ - { - "name": "includeDeprecated", - "defaultValue": "false", - "type": { - "kind": "SCALAR", - "name": "Boolean" - } - } - ], - "name": "fields", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__Field" - } - } - } - }, - { - "args": [], - "name": "inputFields", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__InputValue" - } - } - } - }, - { - "args": [], - "name": "interfaces", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__Type" - } - } - } - }, - { - "args": [], - "name": "kind", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "__TypeKind" - } - } - }, - { - "args": [], - "name": "name", - "type": { - "kind": "SCALAR", - "name": "String" - } - }, - { - "args": [], - "name": "ofType", - "type": { - "kind": "OBJECT", - "name": "__Type" - } - }, - { - "args": [], - "name": "possibleTypes", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "__Type" - } - } - } - } - ] - }, - { - "kind": "ENUM", - "name": "__TypeKind", - "enumValues": [ - { - "name": "ENUM" - }, - { - "name": "INPUT_OBJECT" - }, - { - "name": "INTERFACE" - }, - { - "name": "LIST" - }, - { - "name": "NON_NULL" - }, - { - "name": "OBJECT" - }, - { - "name": "SCALAR" - }, - { - "name": "UNION" - } - ] - }, - { - "kind": "ENUM", - "name": "conflict_action", - "enumValues": [ - { - "name": "ignore", - "description": "ignore the insert on this row" - }, - { - "name": "update", - "description": "update the row with the given values" - } - ], - "description": "conflict action" - }, - { - "inputFields": [ - { - "name": "_eq", - "type": { - "kind": "SCALAR", - "name": "Int" - } - }, - { - "name": "_gt", - "type": { - "kind": "SCALAR", - "name": "Int" - } - }, - { - "name": "_gte", - "type": { - "kind": "SCALAR", - "name": "Int" - } - }, - { - "name": "_in", - "type": { - "kind": "LIST", - "ofType": { - "kind": "SCALAR", - "name": "Int" - } - } - }, - { - "name": "_is_null", - "type": { - "kind": "SCALAR", - "name": "Boolean" - } - }, - { - "name": "_lt", - "type": { - "kind": "SCALAR", - "name": "Int" - } - }, - { - "name": "_lte", - "type": { - "kind": "SCALAR", - "name": "Int" - } - }, - { - "name": "_neq", - "type": { - "kind": "SCALAR", - "name": "Int" - } - }, - { - "name": "_nin", - "type": { - "kind": "LIST", - "ofType": { - "kind": "SCALAR", - "name": "Int" - } - } - } - ], - "kind": "INPUT_OBJECT", - "name": "integer_comparison_exp", - "description": "expression to compare columns of type integer. All fields are combined with logical 'AND'." - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "mutation_root", - "description": "mutation root", - "fields": [ - { - "args": [ - { - "name": "where", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - } - }, - "description": "filter the rows which have to be deleted" - } - ], - "name": "delete_test", - "type": { - "kind": "OBJECT", - "name": "test_mutation_response" - }, - "description": "delete data from the table: \"test\"" - }, - { - "args": [ - { - "name": "objects", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_insert_input" - } - } - } - }, - "description": "the rows to be inserted" - }, - { - "name": "on_conflict", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_on_conflict" - }, - "description": "on conflict condition" - } - ], - "name": "insert_test", - "type": { - "kind": "OBJECT", - "name": "test_mutation_response" - }, - "description": "insert data into the table: \"test\"" - }, - { - "args": [ - { - "name": "_inc", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_inc_input" - }, - "description": "increments the integer columns with given value of the filtered values" - }, - { - "name": "_set", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_set_input" - }, - "description": "sets the columns of the filtered rows to the given values" - }, - { - "name": "where", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - } - }, - "description": "filter the rows which have to be updated" - } - ], - "name": "update_test", - "type": { - "kind": "OBJECT", - "name": "test_mutation_response" - }, - "description": "update data of the table: \"test\"" - } - ] - }, - { - "kind": "ENUM", - "name": "order_by", - "enumValues": [ - { - "name": "asc", - "description": "in the ascending order, nulls last" - }, - { - "name": "asc_nulls_first", - "description": "in the ascending order, nulls first" - }, - { - "name": "asc_nulls_last", - "description": "in the ascending order, nulls last" - }, - { - "name": "desc", - "description": "in the descending order, nulls first" - }, - { - "name": "desc_nulls_first", - "description": "in the descending order, nulls first" - }, - { - "name": "desc_nulls_last", - "description": "in the descending order, nulls last" - } - ], - "description": "column ordering options" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "query_root", - "description": "query root", - "fields": [ - { - "args": [ - { - "name": "distinct_on", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "test_select_column" - } - } - }, - "description": "distinct select on columns" - }, - { - "name": "limit", - "type": { - "kind": "SCALAR", - "name": "Int" - }, - "description": "limit the nuber of rows returned" - }, - { - "name": "offset", - "type": { - "kind": "SCALAR", - "name": "Int" - }, - "description": "skip the first n rows. Use only with order_by" - }, - { - "name": "order_by", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_order_by" - } - } - }, - "description": "sort the rows by one or more columns" - }, - { - "name": "where", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - }, - "description": "filter the rows returned" - } - ], - "name": "test", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "test" - } - } - } - }, - "description": "fetch data from the table: \"test\"" - }, - { - "args": [ - { - "name": "distinct_on", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "test_select_column" - } - } - }, - "description": "distinct select on columns" - }, - { - "name": "limit", - "type": { - "kind": "SCALAR", - "name": "Int" - }, - "description": "limit the nuber of rows returned" - }, - { - "name": "offset", - "type": { - "kind": "SCALAR", - "name": "Int" - }, - "description": "skip the first n rows. Use only with order_by" - }, - { - "name": "order_by", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_order_by" - } - } - }, - "description": "sort the rows by one or more columns" - }, - { - "name": "where", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - }, - "description": "filter the rows returned" - } - ], - "name": "test_aggregate", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "test_aggregate" - } - }, - "description": "fetch aggregated fields from the table: \"test\"" - }, - { - "args": [ - { - "name": "id", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "Int" - } - } - } - ], - "name": "test_by_pk", - "type": { - "kind": "OBJECT", - "name": "test" - }, - "description": "fetch data from the table: \"test\" using primary key columns" - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "subscription_root", - "description": "subscription root", - "fields": [ - { - "args": [ - { - "name": "distinct_on", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "test_select_column" - } - } - }, - "description": "distinct select on columns" - }, - { - "name": "limit", - "type": { - "kind": "SCALAR", - "name": "Int" - }, - "description": "limit the nuber of rows returned" - }, - { - "name": "offset", - "type": { - "kind": "SCALAR", - "name": "Int" - }, - "description": "skip the first n rows. Use only with order_by" - }, - { - "name": "order_by", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_order_by" - } - } - }, - "description": "sort the rows by one or more columns" - }, - { - "name": "where", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - }, - "description": "filter the rows returned" - } - ], - "name": "test", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "test" - } - } - } - }, - "description": "fetch data from the table: \"test\"" - }, - { - "args": [ - { - "name": "distinct_on", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "test_select_column" - } - } - }, - "description": "distinct select on columns" - }, - { - "name": "limit", - "type": { - "kind": "SCALAR", - "name": "Int" - }, - "description": "limit the nuber of rows returned" - }, - { - "name": "offset", - "type": { - "kind": "SCALAR", - "name": "Int" - }, - "description": "skip the first n rows. Use only with order_by" - }, - { - "name": "order_by", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_order_by" - } - } - }, - "description": "sort the rows by one or more columns" - }, - { - "name": "where", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - }, - "description": "filter the rows returned" - } - ], - "name": "test_aggregate", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "test_aggregate" - } - }, - "description": "fetch aggregated fields from the table: \"test\"" - }, - { - "args": [ - { - "name": "id", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "Int" - } - } - } - ], - "name": "test_by_pk", - "type": { - "kind": "OBJECT", - "name": "test" - }, - "description": "fetch data from the table: \"test\" using primary key columns" - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test", - "description": "columns and relationships of \"test\"", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "Int" - } - } - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_aggregate", - "description": "aggregated selection of \"test\"", - "fields": [ - { - "args": [], - "name": "aggregate", - "type": { - "kind": "OBJECT", - "name": "test_aggregate_fields" - } - }, - { - "args": [], - "name": "nodes", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "test" - } - } - } - } - } - ] - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_aggregate_fields", - "description": "aggregate fields of \"test\"", - "fields": [ - { - "args": [], - "name": "avg", - "type": { - "kind": "OBJECT", - "name": "test_avg_fields" - } - }, - { - "args": [ - { - "name": "columns", - "type": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "test_select_column" - } - } - } - }, - { - "name": "distinct", - "type": { - "kind": "SCALAR", - "name": "Boolean" - } - } - ], - "name": "count", - "type": { - "kind": "SCALAR", - "name": "Int" - } - }, - { - "args": [], - "name": "max", - "type": { - "kind": "OBJECT", - "name": "test_max_fields" - } - }, - { - "args": [], - "name": "min", - "type": { - "kind": "OBJECT", - "name": "test_min_fields" - } - }, - { - "args": [], - "name": "stddev", - "type": { - "kind": "OBJECT", - "name": "test_stddev_fields" - } - }, - { - "args": [], - "name": "stddev_pop", - "type": { - "kind": "OBJECT", - "name": "test_stddev_pop_fields" - } - }, - { - "args": [], - "name": "stddev_samp", - "type": { - "kind": "OBJECT", - "name": "test_stddev_samp_fields" - } - }, - { - "args": [], - "name": "sum", - "type": { - "kind": "OBJECT", - "name": "test_sum_fields" - } - }, - { - "args": [], - "name": "var_pop", - "type": { - "kind": "OBJECT", - "name": "test_var_pop_fields" - } - }, - { - "args": [], - "name": "var_samp", - "type": { - "kind": "OBJECT", - "name": "test_var_samp_fields" - } - }, - { - "args": [], - "name": "variance", - "type": { - "kind": "OBJECT", - "name": "test_variance_fields" - } - } - ] - }, - { - "inputFields": [ - { - "name": "avg", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_avg_order_by" - } - }, - { - "name": "count", - "type": { - "kind": "ENUM", - "name": "order_by" - } - }, - { - "name": "max", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_max_order_by" - } - }, - { - "name": "min", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_min_order_by" - } - }, - { - "name": "stddev", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_stddev_order_by" - } - }, - { - "name": "stddev_pop", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_stddev_pop_order_by" - } - }, - { - "name": "stddev_samp", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_stddev_samp_order_by" - } - }, - { - "name": "sum", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_sum_order_by" - } - }, - { - "name": "var_pop", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_var_pop_order_by" - } - }, - { - "name": "var_samp", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_var_samp_order_by" - } - }, - { - "name": "variance", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_variance_order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_aggregate_order_by", - "description": "order by aggregate values of table \"test\"" - }, - { - "inputFields": [ - { - "name": "data", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_insert_input" - } - } - } - } - }, - { - "name": "on_conflict", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_on_conflict" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_arr_rel_insert_input", - "description": "input type for inserting array relation for remote table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_avg_fields", - "description": "aggregate avg on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Float" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_avg_order_by", - "description": "order by avg() on columns of table \"test\"" - }, - { - "inputFields": [ - { - "name": "_and", - "type": { - "kind": "LIST", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - } - } - }, - { - "name": "_not", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - } - }, - { - "name": "_or", - "type": { - "kind": "LIST", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_bool_exp" - } - } - }, - { - "name": "id", - "type": { - "kind": "INPUT_OBJECT", - "name": "integer_comparison_exp" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_bool_exp", - "description": "Boolean expression to filter rows from the table \"test\". All fields are combined with a logical 'AND'." - }, - { - "kind": "ENUM", - "name": "test_constraint", - "enumValues": [ - { - "name": "test_pkey", - "description": "unique or primary key constraint" - } - ], - "description": "unique or primary key constraints on table \"test\"" - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Int" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_inc_input", - "description": "input type for incrementing integer columne in table \"test\"" - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Int" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_insert_input", - "description": "input type for inserting data into table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_max_fields", - "description": "aggregate max on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Int" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_max_order_by", - "description": "order by max() on columns of table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_min_fields", - "description": "aggregate min on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Int" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_min_order_by", - "description": "order by min() on columns of table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_mutation_response", - "description": "response of any mutation on the table \"test\"", - "fields": [ - { - "args": [], - "name": "affected_rows", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "SCALAR", - "name": "Int" - } - }, - "description": "number of affected rows by the mutation" - }, - { - "args": [], - "name": "returning", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "OBJECT", - "name": "test" - } - } - } - }, - "description": "data of the affected rows by the mutation" - } - ] - }, - { - "inputFields": [ - { - "name": "data", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "INPUT_OBJECT", - "name": "test_insert_input" - } - } - }, - { - "name": "on_conflict", - "type": { - "kind": "INPUT_OBJECT", - "name": "test_on_conflict" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_obj_rel_insert_input", - "description": "input type for inserting object relation for remote table \"test\"" - }, - { - "inputFields": [ - { - "name": "constraint", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "test_constraint" - } - } - }, - { - "name": "update_columns", - "type": { - "kind": "NON_NULL", - "ofType": { - "kind": "LIST", - "ofType": { - "kind": "NON_NULL", - "ofType": { - "kind": "ENUM", - "name": "test_update_column" - } - } - } - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_on_conflict", - "description": "on conflict condition type for table \"test\"" - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_order_by", - "description": "ordering options when selecting data from \"test\"" - }, - { - "kind": "ENUM", - "name": "test_select_column", - "enumValues": [ - { - "name": "id", - "description": "column name" - } - ], - "description": "select columns of table \"test\"" - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Int" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_set_input", - "description": "input type for updating data in table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_stddev_fields", - "description": "aggregate stddev on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Float" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_stddev_order_by", - "description": "order by stddev() on columns of table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_stddev_pop_fields", - "description": "aggregate stddev_pop on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Float" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_stddev_pop_order_by", - "description": "order by stddev_pop() on columns of table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_stddev_samp_fields", - "description": "aggregate stddev_samp on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Float" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_stddev_samp_order_by", - "description": "order by stddev_samp() on columns of table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_sum_fields", - "description": "aggregate sum on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Int" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_sum_order_by", - "description": "order by sum() on columns of table \"test\"" - }, - { - "kind": "ENUM", - "name": "test_update_column", - "enumValues": [ - { - "name": "id", - "description": "column name" - } - ], - "description": "update columns of table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_var_pop_fields", - "description": "aggregate var_pop on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Float" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_var_pop_order_by", - "description": "order by var_pop() on columns of table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_var_samp_fields", - "description": "aggregate var_samp on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Float" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_var_samp_order_by", - "description": "order by var_samp() on columns of table \"test\"" - }, - { - "kind": "OBJECT", - "interfaces": [], - "name": "test_variance_fields", - "description": "aggregate variance on columns", - "fields": [ - { - "args": [], - "name": "id", - "type": { - "kind": "SCALAR", - "name": "Float" - } - } - ] - }, - { - "inputFields": [ - { - "name": "id", - "type": { - "kind": "ENUM", - "name": "order_by" - } - } - ], - "kind": "INPUT_OBJECT", - "name": "test_variance_order_by", - "description": "order by variance() on columns of table \"test\"" - } - ], - "mutationType": { - "name": "mutation_root" - } - } - } -} -|]