autodocodec-yaml-0.2.0.0: src/Autodocodec/Yaml/IO.hs
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Autodocodec.Yaml.IO where
import Autodocodec
import Autodocodec.Yaml.Schema
import qualified Data.ByteString as SB
import qualified Data.Text as T
import qualified Data.Yaml as Yaml
import Path
import Path.IO
import System.Exit
-- | Helper function to read a yaml file for a type in 'HasCodec'
--
-- This will output a colourful yaml schema if parsing fails.
readYamlConfigFile :: HasCodec a => Path r File -> IO (Maybe a)
readYamlConfigFile p = readFirstYamlConfigFile [p]
-- | Helper function to read the first in a list of yaml files for a type is 'HasCodec'
--
-- This will output a colourful yaml schema if parsing fails.
readFirstYamlConfigFile :: forall a r. HasCodec a => [Path r File] -> IO (Maybe a)
readFirstYamlConfigFile files = go files
where
go :: [Path r File] -> IO (Maybe a)
go =
\case
[] -> pure Nothing
(p : ps) -> do
mc <- forgivingAbsence $ SB.readFile $ toFilePath p
case mc of
Nothing -> go ps
Just contents ->
case Yaml.decodeEither' contents of
Left err -> do
let failedMsgs =
[ "Failed to parse yaml file",
toFilePath p,
"with error:",
Yaml.prettyPrintParseException err
]
triedFilesMsgs = case files of
[] -> []
[f] -> ["While parsing file: " <> toFilePath f]
fs -> "While parsing files:" : map (("* " <>) . toFilePath) fs
referenceMsgs =
[ "Reference: ",
T.unpack $ renderColouredSchemaViaCodec @a
]
die $
unlines $
concat
[ failedMsgs,
triedFilesMsgs,
referenceMsgs
]
Right (Autodocodec conf) -> pure $ Just conf