{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NoImplicitPrelude #-} module Data.Morpheus.Client.CodeGen.Declare ( declareGlobalTypes, declareGlobalTypesByName, declareLocalTypes, declareLocalTypesInline, internalLegacyLocalDeclareTypes, clientTypeDeclarations, raw, parseClientTypeDeclarations, ) where import Data.Morpheus.Client.CodeGen.AST ( ClientDeclaration (..), ) import Data.Morpheus.Client.CodeGen.Interpreting.Global ( toGlobalDefinitions, ) import Data.Morpheus.Client.CodeGen.Interpreting.Local ( toLocalDefinitions, ) import Data.Morpheus.Client.CodeGen.QuasiQuoter (raw) import Data.Morpheus.Client.CodeGen.TH ( declareIfNotDeclared, deriveIfNotDefined, ) import Data.Morpheus.Client.CodeGen.Utils (getFile, getSource, handleResult) import Data.Morpheus.Client.Fetch.Types ( ExecutableSource, SchemaSource, ) import Data.Morpheus.Client.Schema.Parse (parseSchema) import Data.Morpheus.CodeGen.TH ( PrintDec (printDec), ) import Data.Morpheus.CodeGen.Utils import Data.Morpheus.Core (parseRequest) import Data.Morpheus.Internal.Ext (GQLResult) import Data.Morpheus.Types.IO (GQLRequest (..)) import Data.Morpheus.Types.Internal.AST (TypeName) import qualified Data.Set as S import Language.Haskell.TH (Dec, Q, runIO) import Relude printDeclarations :: [ClientDeclaration] -> Q [Dec] printDeclarations clientType = concat <$> traverse typeDeclarations clientType typeDeclarations :: ClientDeclaration -> Q [Dec] typeDeclarations (InstanceDeclaration _ dec) = deriveIfNotDefined printDec dec typeDeclarations (ClientTypeDeclaration c) = declareIfNotDeclared printDec c internalLegacyLocalDeclareTypes :: IO SchemaSource -> ExecutableSource -> Q [Dec] internalLegacyLocalDeclareTypes schemaSrc query = do schemaText <- runIO schemaSrc clientTypeDeclarations schemaText (Just query) globalTypeDeclarations :: SchemaSource -> (TypeName -> Bool) -> Q [Dec] globalTypeDeclarations src f = handleResult (parseSchema src >>= fmap fst . toGlobalDefinitions f) printDeclarations parseClientTypeDeclarations :: SchemaSource -> Maybe Text -> GQLResult ([ClientDeclaration], Flags) parseClientTypeDeclarations schemaText (Just query) = do schemaDoc <- parseSchema schemaText executableDoc <- parseRequest GQLRequest { query, operationName = Nothing, variables = Nothing } toLocalDefinitions (query, executableDoc) schemaDoc parseClientTypeDeclarations src Nothing = parseSchema src >>= toGlobalDefinitions (const True) -- | declares global or local types, depending -- on whether the second argument is specified or not clientTypeDeclarations :: SchemaSource -> Maybe ExecutableSource -> Q [Dec] clientTypeDeclarations src x = handleResult (fmap fst (parseClientTypeDeclarations src x)) printDeclarations {- ORMOLU_DISABLE -} -- | declares input, enum and scalar types for specified schema -- -- Example where the schema is defined in SDL format -- -- @ -- 'declareGlobalTypes' "schema.gql" -- @ -- -- Example with schema as introspection in JSON format. -- -- @ -- 'declareGlobalTypes' "schema.json" -- @ declareGlobalTypes :: FilePath -- ^ the schema path relative to the project location, -- both introspection (.json) and -- schema definition (.gql, .graphql) are accepted. -> Q [Dec] declareGlobalTypes = flip declareClientTypes Nothing {- ORMOLU_ENABLE -} -- | declares global types like 'declareGlobalTypes', -- while enabling to select only the types that are needed. declareGlobalTypesByName :: FilePath -> [TypeName] -> Q [Dec] declareGlobalTypesByName path names = do schema <- getSource path globalTypeDeclarations schema (`S.member` S.fromList names) {- ORMOLU_DISABLE -} -- | declares object, interface and union types for -- specified schema and query. -- -- Example where the schema is defined in SDL format -- -- @ -- 'declareLocalTypes' "schema.gql" "query.gql" -- @ -- -- Example with schema as introspection in JSON format. -- -- @ -- 'declareLocalTypes' "schema.json" "query.gql" -- @ declareLocalTypes :: FilePath -- ^ the schema path relative to the project location. -- both introspection (`.json`) and -- schema definition (`.gql`, `.graphql`) are accepted. -> FilePath -- ^ query path relative to the project location -> Q [Dec] declareLocalTypes schema query = declareClientTypes schema (Just query) {- ORMOLU_ENABLE -} {- ORMOLU_DISABLE -} -- | inline version of `declareLocalTypes`, however -- instead of specifying the file path, you can simply -- pass the query as text using QuasiQuoter `raw` -- -- @ -- `declareLocalTypesInline` "schema.gql" -- [`raw`| -- query GetUsers { -- users { -- name -- } -- } -- ] -- @ declareLocalTypesInline :: FilePath -- ^ the schema path relative to the project location. -- both introspection (`.json`) and -- schema definition (`.gql`, `.graphql`) are accepted. -> ExecutableSource -- ^ inline graphql query in Text format -> Q [Dec] declareLocalTypesInline schemaPath query = do schema <- getSource schemaPath clientTypeDeclarations schema (Just query) {- ORMOLU_ENABLE -} declareClientTypes :: FilePath -> Maybe FilePath -> Q [Dec] declareClientTypes schemaPath queryPath = do schema <- getSource schemaPath query <- traverse getFile queryPath clientTypeDeclarations schema query