{-# LANGUAGE OverloadedStrings, DeriveDataTypeable, ExistentialQuantification #-}
import Paths_latest_npm_version (version)
import Control.Exception (fromException, Exception, SomeException)
import Network.HTTP.Client (HttpException(StatusCodeException))
import Network.HTTP.Types.Status (statusCode)
import Data.Data (Data)
import Data.Version (showVersion)
import Data.Typeable (Typeable)
import Npm.Latest (fetchLatestVersion, GenericNpmException(..))
import System.Console.CmdArgs.Implicit (cmdArgsRun, (&=))
import System.Console.CmdArgs.Explicit (HelpFormat(..), helpText)
import System.IO (stderr)
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import qualified System.Console.CmdArgs.Implicit as CA
data ErrHandler a = forall e . Exception e => ErrHandler (e -> a)
matchErr :: SomeException -> b -> [ErrHandler b] -> b
matchErr e = foldr (\(ErrHandler f) r -> maybe r f $ fromException e)
data LatestNpmVersion = LatestNpmVersion {name :: String}
deriving (Show, Data, Typeable)
programName :: String
programName = "latest-npm-version"
args :: CA.Mode (CA.CmdArgs LatestNpmVersion)
args = CA.cmdArgsMode $ LatestNpmVersion{name = CA.def &= CA.args}
&= CA.summary (unwords [programName, showVersion version])
&= CA.program programName
main :: IO ()
main = do
mainArgs <- cmdArgsRun args
let moduleName = name mainArgs
if null moduleName
then print $ helpText [] HelpFormatDefault args
else fetchLatestVersion moduleName >>= either handleErr TIO.putStrLn
handleErr :: SomeException -> IO ()
handleErr err = TIO.hPutStrLn stderr $ matchErr err handleOther
[ErrHandler handleA, ErrHandler handleB] where
handleA GenericNpmException = "Invalid JSON data received."
handleB (StatusCodeException status _ _) =
if statusCode status == 404
then "Package not found."
else T.unwords
["Invalid status code ", T.pack $ show $ statusCode status]
handleB s@_ = T.unwords ["HTTP error: ", T.pack $ show s]
handleOther = "Unknown error."