{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NoImplicitPrelude #-} module Data.Morpheus.Client.Internal.Utils ( removeDuplicates, isEnum, getSource, handleResult, getFile, ) where import Control.Monad.Except (MonadError (catchError)) import qualified Data.ByteString.Lazy.Char8 as L import Data.FileEmbed (makeRelativeToProject) import Data.List (isSuffixOf) import Data.Morpheus.Client.Internal.Types ( ClientConstructorDefinition (cFields), SchemaSource (..), ) import Data.Morpheus.Error (gqlWarnings, renderGQLErrors) import Data.Morpheus.Internal.Ext (GQLResult, Result (..)) import qualified Data.Text.IO as TIO import Language.Haskell.TH (Q, runIO) import Language.Haskell.TH.Syntax (qAddDependentFile) import Relude removeDuplicates :: Eq a => [a] -> [a] removeDuplicates :: [a] -> [a] removeDuplicates = ([a], [a]) -> [a] forall a b. (a, b) -> a fst (([a], [a]) -> [a]) -> ([a] -> ([a], [a])) -> [a] -> [a] forall b c a. (b -> c) -> (a -> b) -> a -> c . [a] -> ([a], [a]) forall a. Eq a => [a] -> ([a], [a]) splitDuplicates splitDuplicates :: Eq a => [a] -> ([a], [a]) splitDuplicates :: [a] -> ([a], [a]) splitDuplicates = ([a], [a]) -> [a] -> ([a], [a]) forall a. Eq a => ([a], [a]) -> [a] -> ([a], [a]) collectElems ([], []) where collectElems :: Eq a => ([a], [a]) -> [a] -> ([a], [a]) collectElems :: ([a], [a]) -> [a] -> ([a], [a]) collectElems ([a], [a]) collected [] = ([a], [a]) collected collectElems ([a] collected, [a] errors) (a x : [a] xs) | a x a -> [a] -> Bool forall (f :: * -> *) a. (Foldable f, DisallowElem f, Eq a) => a -> f a -> Bool `elem` [a] collected = ([a], [a]) -> [a] -> ([a], [a]) forall a. Eq a => ([a], [a]) -> [a] -> ([a], [a]) collectElems ([a] collected, [a] errors [a] -> [a] -> [a] forall a. Semigroup a => a -> a -> a <> [a x]) [a] xs | Bool otherwise = ([a], [a]) -> [a] -> ([a], [a]) forall a. Eq a => ([a], [a]) -> [a] -> ([a], [a]) collectElems ([a] collected [a] -> [a] -> [a] forall a. Semigroup a => a -> a -> a <> [a x], [a] errors) [a] xs isEnum :: [ClientConstructorDefinition] -> Bool isEnum :: [ClientConstructorDefinition] -> Bool isEnum = (ClientConstructorDefinition -> Bool) -> [ClientConstructorDefinition] -> Bool forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool all ([FieldDefinition ANY VALID] -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null ([FieldDefinition ANY VALID] -> Bool) -> (ClientConstructorDefinition -> [FieldDefinition ANY VALID]) -> ClientConstructorDefinition -> Bool forall b c a. (b -> c) -> (a -> b) -> a -> c . ClientConstructorDefinition -> [FieldDefinition ANY VALID] cFields) getSource :: FilePath -> Q SchemaSource getSource :: FilePath -> Q SchemaSource getSource FilePath p | FilePath ".json" FilePath -> FilePath -> Bool forall a. Eq a => [a] -> [a] -> Bool `isSuffixOf` FilePath p = ByteString -> SchemaSource JSON (ByteString -> SchemaSource) -> Q ByteString -> Q SchemaSource forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> (FilePath -> IO ByteString) -> FilePath -> Q ByteString forall a. (FilePath -> IO a) -> FilePath -> Q a readWith FilePath -> IO ByteString L.readFile FilePath p | FilePath ".gql" FilePath -> FilePath -> Bool forall a. Eq a => [a] -> [a] -> Bool `isSuffixOf` FilePath p Bool -> Bool -> Bool || FilePath ".graphql" FilePath -> FilePath -> Bool forall a. Eq a => [a] -> [a] -> Bool `isSuffixOf` FilePath p = ByteString -> SchemaSource GQL (ByteString -> SchemaSource) -> Q ByteString -> Q SchemaSource forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> (FilePath -> IO ByteString) -> FilePath -> Q ByteString forall a. (FilePath -> IO a) -> FilePath -> Q a readWith FilePath -> IO ByteString L.readFile FilePath p | Bool otherwise = FilePath -> Q SchemaSource forall (m :: * -> *) a. MonadFail m => FilePath -> m a fail FilePath "Unsupported file format! The input should have one of the following extensions: json, gql, graphql" getFile :: FilePath -> Q Text getFile :: FilePath -> Q Text getFile = (FilePath -> IO Text) -> FilePath -> Q Text forall a. (FilePath -> IO a) -> FilePath -> Q a readWith FilePath -> IO Text TIO.readFile readWith :: (FilePath -> IO a) -> FilePath -> Q a readWith :: (FilePath -> IO a) -> FilePath -> Q a readWith FilePath -> IO a f FilePath path = do FilePath p <- FilePath -> Q FilePath makeRelativeToProject FilePath path FilePath -> Q () forall (m :: * -> *). Quasi m => FilePath -> m () qAddDependentFile FilePath p Either FilePath a file <- IO (Either FilePath a) -> Q (Either FilePath a) forall a. IO a -> Q a runIO (IO (Either FilePath a) -> (IOException -> IO (Either FilePath a)) -> IO (Either FilePath a) forall e (m :: * -> *) a. MonadError e m => m a -> (e -> m a) -> m a catchError (((a -> Either FilePath a) -> IO a -> IO (Either FilePath a) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap a -> Either FilePath a forall a b. b -> Either a b Right (IO a -> IO (Either FilePath a)) -> (FilePath -> IO a) -> FilePath -> IO (Either FilePath a) forall b c a. (b -> c) -> (a -> b) -> a -> c . FilePath -> IO a f) FilePath p) (Either FilePath a -> IO (Either FilePath a) forall (f :: * -> *) a. Applicative f => a -> f a pure (Either FilePath a -> IO (Either FilePath a)) -> (IOException -> Either FilePath a) -> IOException -> IO (Either FilePath a) forall b c a. (b -> c) -> (a -> b) -> a -> c . FilePath -> Either FilePath a forall a b. a -> Either a b Left (FilePath -> Either FilePath a) -> (IOException -> FilePath) -> IOException -> Either FilePath a forall b c a. (b -> c) -> (a -> b) -> a -> c . IOException -> FilePath forall b a. (Show a, IsString b) => a -> b show)) case Either FilePath a file of Left FilePath x -> FilePath -> Q a forall (m :: * -> *) a. MonadFail m => FilePath -> m a fail FilePath x Right a x -> a -> Q a forall (f :: * -> *) a. Applicative f => a -> f a pure a x handleResult :: GQLResult t -> (t -> Q a) -> Q a handleResult :: GQLResult t -> (t -> Q a) -> Q a handleResult GQLResult t x t -> Q a f = case GQLResult t x of Failure NonEmpty GQLError errors -> FilePath -> Q a forall (m :: * -> *) a. MonadFail m => FilePath -> m a fail (NonEmpty GQLError -> FilePath renderGQLErrors NonEmpty GQLError errors) Success { t result :: forall err a. Result err a -> a result :: t result, [GQLError] warnings :: forall err a. Result err a -> [err] warnings :: [GQLError] warnings } -> [GQLError] -> Q () gqlWarnings [GQLError] warnings Q () -> Q a -> Q a forall (m :: * -> *) a b. Monad m => m a -> m b -> m b >> t -> Q a f t result