module Follow
( Recipe(..)
, Subject(..)
, Entry(..)
, Fetched
, Directory(..)
, Step
, Middleware
, Digester
, directoryFromRecipe
, directoryFromFetched
, applyMiddlewares
, applySteps
, emptyDirectory
, mergeEntries
) where
import Control.Monad.Catch (MonadThrow)
import Data.Foldable (foldlM)
import Data.List (nub)
import Follow.Types (Digester, Directory (..), Entry (..),
Fetched, Middleware, Recipe (..), Step,
Subject (..))
directoryFromRecipe :: MonadThrow m => Recipe m -> m Directory
directoryFromRecipe recipe =
let Recipe {rSubject = subject, rSteps = steps, rMiddlewares = middlewares} =
recipe
in applyMiddlewares middlewares <$> applySteps (emptyDirectory subject) steps
directoryFromFetched :: MonadThrow m => m [Entry] -> Subject -> m Directory
directoryFromFetched fetched header = Directory header <$> fetched
applyMiddlewares :: [Middleware] -> Directory -> Directory
applyMiddlewares = flip $ foldl (flip ($))
applySteps :: MonadThrow m => Directory -> [Step m] -> m Directory
applySteps = foldlM applyStep
where
applyStep directory (fetched, middlewares) =
applyMiddlewares middlewares . mergeEntries directory <$> fetched
emptyDirectory :: Subject -> Directory
emptyDirectory s = Directory {dSubject = s, dEntries = mempty}
mergeEntries :: Directory -> [Entry] -> Directory
mergeEntries d e = d {dEntries = nub $ dEntries d ++ e}