{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.Client.CodeGen.Utils
  ( getSource,
    handleResult,
    getFile,
    readSchemaSource,
  )
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.Fetch.Types
  ( 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

readSchemaSource :: FilePath -> IO SchemaSource
readSchemaSource :: [Char] -> IO SchemaSource
readSchemaSource [Char]
p
  | [Char]
".json" forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` [Char]
p = ByteString -> SchemaSource
JSON forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO ByteString
L.readFile [Char]
p
  | [Char]
".gql" forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` [Char]
p Bool -> Bool -> Bool
|| [Char]
".graphql" forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` [Char]
p = ByteString -> SchemaSource
GQL forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO ByteString
L.readFile [Char]
p
  | Bool
otherwise = forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"Unsupported file format! The input should have one of the following extensions: json, gql, graphql"

getSource :: FilePath -> Q SchemaSource
getSource :: [Char] -> Q SchemaSource
getSource = forall a. ([Char] -> IO a) -> [Char] -> Q a
readWith [Char] -> IO SchemaSource
readSchemaSource

getFile :: FilePath -> Q Text
getFile :: [Char] -> Q Text
getFile = forall a. ([Char] -> IO a) -> [Char] -> Q a
readWith [Char] -> IO Text
TIO.readFile

readWith :: (FilePath -> IO a) -> FilePath -> Q a
readWith :: forall a. ([Char] -> IO a) -> [Char] -> Q a
readWith [Char] -> IO a
f [Char]
path = do
  [Char]
p <- [Char] -> Q [Char]
makeRelativeToProject [Char]
path
  forall (m :: * -> *). Quasi m => [Char] -> m ()
qAddDependentFile [Char]
p
  Either [Char] a
file <- forall a. IO a -> Q a
runIO (forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
catchError ((forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. b -> Either a b
Right forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> IO a
f) [Char]
p) (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. (Show a, IsString b) => a -> b
show))
  case Either [Char] a
file of
    Left [Char]
x -> forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
x
    Right a
x -> forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x

handleResult :: GQLResult t -> (t -> Q a) -> Q a
handleResult :: forall t a. GQLResult t -> (t -> Q a) -> Q a
handleResult GQLResult t
x t -> Q a
f = case GQLResult t
x of
  Failure NonEmpty GQLError
errors -> forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail (NonEmpty GQLError -> [Char]
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 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> t -> Q a
f t
result