{-# LANGUAGE OverloadedStrings #-} module GH ( get , getEach , getEach_ , getAll , post , put , delete -- * lower level , module GH.Request ) where import Control.Monad (void) import Data.Aeson (FromJSON(..), ToJSON) import Data.List (isInfixOf) import Data.Monoid ((<>)) import GH.Request get :: FromJSON a => Path -> IO a get path = requestJSON path id -- | Get a paginated resource, giving each item to the given action -- -- Notes: -- -- - This will yield each item out of each page, not each page of items. -- - If you're trying to apply a pure function, instead use: -- -- > map f <$> getAll path -- getEach :: FromJSON a => Path -> (a -> IO b) -> IO [b] getEach path f = go 1 where go n = do page <- get $ appendPage n if null page then return [] else (<>) <$> mapM f page <*> go (n + 1) -- Type this expression to avoid defaulted constraint warning appendPage :: Int -> String appendPage n | "?" `isInfixOf` path = path <> "&page=" <> show n | otherwise = path <> "?page=" <> show n -- | @getEach@, but discarding the results of the provided action getEach_ :: FromJSON a => Path -> (a -> IO b) -> IO () getEach_ path = void . getEach path -- | @getEach@, but collecting all values into a list that is returned getAll :: FromJSON a => Path -> IO [a] getAll path = getEach path (return . id) post :: (ToJSON a, FromJSON b) => Path -> a -> IO b post path body = requestJSON path $ setMethod "POST" . setBody body put :: (ToJSON a, FromJSON b) => Path -> a -> IO b put path body = requestJSON path $ setMethod "POST" . setBody body delete :: Path -> IO () delete path = requestJSON path $ setMethod "DELETE"