packages feed

latest-npm-version 0.2.1 → 0.3.0

raw patch · 4 files changed

+65/−26 lines, 4 filesdep +http-clientdep +http-types

Dependencies added: http-client, http-types

Files

Main.hs view
@@ -1,30 +1,54 @@-{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}+{-# 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)+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 "latest-npm-version v0.1.0"+       &= CA.summary (unwords [programName, showVersion version])+       &= CA.program programName  main :: IO () main = do     mainArgs <- cmdArgsRun args-    let moduleName = (name mainArgs)-    if length moduleName == 0-        then TIO.putStrLn "Missing module name. Consult --help."-        else do-            version <- fetchLatestVersion moduleName-            case version of-                Nothing -> TIO.putStrLn "Error: fetching/parsing JSON failed"-                Just v -> TIO.putStrLn $ T.unwords [T.pack moduleName, v]+    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."
Npm/Latest.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {-|-Module      : Npm.Latestj+Module      : Npm.Latest Description : Fetch the latest version of an npm module. Copyright   : (c) Pascal Hartig, 2014 License     : MIT@@ -13,18 +13,20 @@ -} module Npm.Latest (     fetchLatestVersion,-    extractVersion+    extractVersion,+    GenericNpmException(..) ) where -import Npm.Latest.Internal (buildRequest, makeVersionRequest, extractVersion)+import Control.Exception (SomeException) import Data.Text.Format (Format)+import Npm.Latest.Internal (buildRequest, makeVersionRequest, extractVersion, GenericNpmException(..)) import qualified Data.Text as T  latestUrl :: Format latestUrl = "https://registry.npmjs.org/{}/latest"  -- |Fetch the latest version for the given module name.-fetchLatestVersion :: String -> IO (Maybe T.Text)+fetchLatestVersion :: String -> IO (Either SomeException T.Text) fetchLatestVersion name = do     req <- buildRequest name latestUrl     resp <- makeVersionRequest req
Tests/Main.hs view
@@ -2,21 +2,28 @@ module Main where  import Test.Hspec-import Npm.Latest (extractVersion)+import Control.Exception (SomeException(..), toException)+import Npm.Latest (extractVersion, GenericNpmException(..))  import qualified Data.Text as T +instance Eq SomeException where+    -- Terrible hack, but this is for tests, so it's fine, right?+    a == b = show a == show b+ main :: IO () main = hspec $ do     describe "extractVersion" $ do-        it "returns Just for a valid JSON object" $ do+        it "is Right for a valid JSON object" $ do             let json = T.unpack "{\"version\": \"1.0\"}"-            extractVersion (Just $ Right $ json) `shouldBe` Just "1.0"+            extractVersion (Right json) `shouldBe` (Right "1.0") -        it "returns Nothing for a malformed JSON object" $ do+        it "is Left for a malformed JSON object" $ do             let json = T.unpack "{\"description\": \"not what we expect\"}"-            extractVersion (Just $ Right $ json) `shouldBe` Nothing+            extractVersion (Right $ json) `shouldBe`+                (Left $ toException GenericNpmException) -        it "returns Nothing for a malformed JSON object" $ do+        it "is Left for a malformed JSON object" $ do             let json = T.unpack "not even $ JSON"-            extractVersion (Just $ Right $ json) `shouldBe` Nothing+            extractVersion (Right $ json) `shouldBe`+                (Left $ toException GenericNpmException)
latest-npm-version.cabal view
@@ -1,5 +1,5 @@ name:                  latest-npm-version-version:               0.2.1+version:               0.3.0 synopsis:              Find the latest version of a package on npm homepage:              https://github.com/passy/latest-npm-version license:               MIT@@ -29,7 +29,9 @@                        aeson >= 0.7 && < 0.8,                        pipes-attoparsec >= 0.5 && < 0.6,                        transformers >= 0.3 && < 0.4,-                       lens >= 4.1 && < 4.2+                       lens >= 4.1 && < 4.2,+                       http-client >= 0.3 && < 0.4,+                       http-types == 0.8.*   default-language:    Haskell2010  executable latest-npm-version@@ -47,7 +49,9 @@                        pipes-attoparsec >= 0.5 && < 0.6,                        transformers >= 0.3 && < 0.4,                        lens >= 4.1 && < 4.2,-                       cmdargs >= 0.10 && < 0.11+                       cmdargs >= 0.10 && < 0.11,+                       http-client >= 0.3 && < 0.4,+                       http-types == 0.8.*   default-language:    Haskell2010  @@ -65,4 +69,6 @@                   aeson >= 0.7 && < 0.8,                   pipes-attoparsec >= 0.5 && < 0.6,                   transformers >= 0.3 && < 0.4,-                  lens >= 4.1 && < 4.2+                  lens >= 4.1 && < 4.2,+                  http-client >= 0.3 && < 0.4,+                  http-types == 0.8.*