aur 6.1.0.1 → 6.2.0
raw patch · 6 files changed
+169/−176 lines, 6 filesdep −errorsdep ~servantdep ~servant-clientPVP ok
version bump matches the API change (PVP)
Dependencies removed: errors
Dependency ranges changed: servant, servant-client
API changes (from Hackage documentation)
- Linux.Arch.Aur.Rpc: info :: Manager -> [Text] -> IO (Maybe [AurInfo])
- Linux.Arch.Aur.Rpc: search :: Manager -> Text -> IO (Maybe [AurInfo])
- Linux.Arch.Aur.Types: AurInfo :: Int -> Text -> Int -> Text -> Text -> Maybe Text -> Maybe Text -> Int -> Float -> Maybe Int -> Maybe Text -> Int -> Int -> Maybe Text -> [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> AurInfo
- Linux.Arch.Aur.Types: RPCResp :: Int -> Text -> Int -> [AurInfo] -> RPCResp
- Linux.Arch.Aur.Types: [_resultCount] :: RPCResp -> Int
- Linux.Arch.Aur.Types: [_results] :: RPCResp -> [AurInfo]
- Linux.Arch.Aur.Types: [_type] :: RPCResp -> Text
- Linux.Arch.Aur.Types: [_version] :: RPCResp -> Int
- Linux.Arch.Aur.Types: [aurDescriptionOf] :: AurInfo -> Maybe Text
- Linux.Arch.Aur.Types: [aurIdOf] :: AurInfo -> Int
- Linux.Arch.Aur.Types: [aurMaintainerOf] :: AurInfo -> Maybe Text
- Linux.Arch.Aur.Types: [aurNameOf] :: AurInfo -> Text
- Linux.Arch.Aur.Types: [aurVersionOf] :: AurInfo -> Text
- Linux.Arch.Aur.Types: [aurVotesOf] :: AurInfo -> Int
- Linux.Arch.Aur.Types: [conflictsOf] :: AurInfo -> [Text]
- Linux.Arch.Aur.Types: [dateObsoleteOf] :: AurInfo -> Maybe Int
- Linux.Arch.Aur.Types: [dependsOf] :: AurInfo -> [Text]
- Linux.Arch.Aur.Types: [keywordsOf] :: AurInfo -> [Text]
- Linux.Arch.Aur.Types: [licenseOf] :: AurInfo -> [Text]
- Linux.Arch.Aur.Types: [makeDepsOf] :: AurInfo -> [Text]
- Linux.Arch.Aur.Types: [modifiedDateOf] :: AurInfo -> Int
- Linux.Arch.Aur.Types: [optDepsOf] :: AurInfo -> [Text]
- Linux.Arch.Aur.Types: [pkgBaseIdOf] :: AurInfo -> Int
- Linux.Arch.Aur.Types: [pkgBaseOf] :: AurInfo -> Text
- Linux.Arch.Aur.Types: [popularityOf] :: AurInfo -> Float
- Linux.Arch.Aur.Types: [providesOf] :: AurInfo -> [Text]
- Linux.Arch.Aur.Types: [submissionDateOf] :: AurInfo -> Int
- Linux.Arch.Aur.Types: [urlOf] :: AurInfo -> Maybe Text
- Linux.Arch.Aur.Types: [urlPathOf] :: AurInfo -> Maybe Text
- Linux.Arch.Aur.Types: data AurInfo
- Linux.Arch.Aur.Types: data RPCResp
- Linux.Arch.Aur.Types: instance Data.Aeson.Types.FromJSON.FromJSON Linux.Arch.Aur.Types.AurInfo
- Linux.Arch.Aur.Types: instance Data.Aeson.Types.FromJSON.FromJSON Linux.Arch.Aur.Types.RPCResp
- Linux.Arch.Aur.Types: instance Data.Aeson.Types.ToJSON.ToJSON Linux.Arch.Aur.Types.AurInfo
- Linux.Arch.Aur.Types: instance GHC.Classes.Eq Linux.Arch.Aur.Types.AurInfo
- Linux.Arch.Aur.Types: instance GHC.Show.Show Linux.Arch.Aur.Types.AurInfo
- Linux.Arch.Aur.Types: instance GHC.Show.Show Linux.Arch.Aur.Types.RPCResp
+ Linux.Arch.Aur: AurInfo :: Int -> Text -> Int -> Text -> Text -> Maybe Text -> Maybe Text -> Int -> Float -> Maybe Int -> Maybe Text -> Int -> Int -> Maybe Text -> [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> AurInfo
+ Linux.Arch.Aur: ConnectionError :: SomeException -> ClientError
+ Linux.Arch.Aur: DecodeFailure :: Text -> Response -> ClientError
+ Linux.Arch.Aur: FailureResponse :: RequestF () (BaseUrl, ByteString) -> Response -> ClientError
+ Linux.Arch.Aur: InvalidContentTypeHeader :: Response -> ClientError
+ Linux.Arch.Aur: UnsupportedContentType :: MediaType -> Response -> ClientError
+ Linux.Arch.Aur: [aurDescriptionOf] :: AurInfo -> Maybe Text
+ Linux.Arch.Aur: [aurIdOf] :: AurInfo -> Int
+ Linux.Arch.Aur: [aurMaintainerOf] :: AurInfo -> Maybe Text
+ Linux.Arch.Aur: [aurNameOf] :: AurInfo -> Text
+ Linux.Arch.Aur: [aurVersionOf] :: AurInfo -> Text
+ Linux.Arch.Aur: [aurVotesOf] :: AurInfo -> Int
+ Linux.Arch.Aur: [conflictsOf] :: AurInfo -> [Text]
+ Linux.Arch.Aur: [dateObsoleteOf] :: AurInfo -> Maybe Int
+ Linux.Arch.Aur: [dependsOf] :: AurInfo -> [Text]
+ Linux.Arch.Aur: [keywordsOf] :: AurInfo -> [Text]
+ Linux.Arch.Aur: [licenseOf] :: AurInfo -> [Text]
+ Linux.Arch.Aur: [makeDepsOf] :: AurInfo -> [Text]
+ Linux.Arch.Aur: [modifiedDateOf] :: AurInfo -> Int
+ Linux.Arch.Aur: [optDepsOf] :: AurInfo -> [Text]
+ Linux.Arch.Aur: [pkgBaseIdOf] :: AurInfo -> Int
+ Linux.Arch.Aur: [pkgBaseOf] :: AurInfo -> Text
+ Linux.Arch.Aur: [popularityOf] :: AurInfo -> Float
+ Linux.Arch.Aur: [providesOf] :: AurInfo -> [Text]
+ Linux.Arch.Aur: [submissionDateOf] :: AurInfo -> Int
+ Linux.Arch.Aur: [urlOf] :: AurInfo -> Maybe Text
+ Linux.Arch.Aur: [urlPathOf] :: AurInfo -> Maybe Text
+ Linux.Arch.Aur: data AurInfo
+ Linux.Arch.Aur: data ClientError
+ Linux.Arch.Aur: info :: Manager -> [Text] -> IO (Either ClientError [AurInfo])
+ Linux.Arch.Aur: instance Data.Aeson.Types.FromJSON.FromJSON Linux.Arch.Aur.AurInfo
+ Linux.Arch.Aur: instance Data.Aeson.Types.FromJSON.FromJSON Linux.Arch.Aur.RPCResp
+ Linux.Arch.Aur: instance Data.Aeson.Types.ToJSON.ToJSON Linux.Arch.Aur.AurInfo
+ Linux.Arch.Aur: instance GHC.Classes.Eq Linux.Arch.Aur.AurInfo
+ Linux.Arch.Aur: instance GHC.Show.Show Linux.Arch.Aur.AurInfo
+ Linux.Arch.Aur: instance GHC.Show.Show Linux.Arch.Aur.RPCResp
+ Linux.Arch.Aur: search :: Manager -> Text -> IO (Either ClientError [AurInfo])
Files
- CHANGELOG.md +6/−0
- aur.cabal +3/−6
- lib/Linux/Arch/Aur.hs +158/−4
- lib/Linux/Arch/Aur/Rpc.hs +0/−59
- lib/Linux/Arch/Aur/Types.hs +0/−105
- tests/Test.hs +2/−2
CHANGELOG.md view
@@ -1,5 +1,11 @@ # Changelog +## 6.2.0++- `info` and `search` now return in `Either`.+- Everything has been combined into a single module.+- Hard requirement on `servant ^>= 0.16`.+ ## 6.1.0.1 - Massaged various bounds for future-proofing.
aur.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2 name: aur-version: 6.1.0.1+version: 6.2.0 synopsis: Access metadata from the Arch Linux User Repository. description:@@ -41,13 +41,10 @@ hs-source-dirs: lib exposed-modules: Linux.Arch.Aur- Linux.Arch.Aur.Rpc- Linux.Arch.Aur.Types build-depends: aeson >= 0.9 && < 1.5- , errors ^>= 2.3- , servant >= 0.9 && < 0.17- , servant-client >= 0.13 && < 0.17+ , servant ^>= 0.16+ , servant-client ^>= 0.16 , text test-suite aur-test
lib/Linux/Arch/Aur.hs view
@@ -1,6 +1,160 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeOperators #-}++-- |+-- Module : Linux.Arch.Aur+-- Copyright : (c) Colin Woodbury, 2014 - 2019+-- License : GPL3+-- Maintainer: Colin Woodbury <colin@fosskers.ca>+--+-- Access package metadata from the Arch Linux User Repository.+ module Linux.Arch.Aur- ( module Linux.Arch.Aur.Rpc- , module Linux.Arch.Aur.Types ) where+ ( -- * Types+ AurInfo(..)+ -- * Queries+ , info, search+ -- * Re-exports+ -- | These are __Servant__ types which you could want to manipulate without+ -- directly depending on (and importing) servant.+ , ClientError(..)+ ) where -import Linux.Arch.Aur.Rpc-import Linux.Arch.Aur.Types+import Control.Applicative ((<|>))+import Control.Monad (mzero)+import Data.Aeson+import Data.Proxy+import Data.Text (Text)+import Network.HTTP.Client (Manager)+import Servant.API+import Servant.Client++---++data RPCResp = RPCResp+ { _version :: Int+ , _type :: Text+ , _resultCount :: Int+ , _results :: [AurInfo] } deriving (Show)++instance FromJSON RPCResp where+ parseJSON (Object v) = RPCResp+ <$> v .: "version"+ <*> v .: "type"+ <*> v .: "resultcount"+ <*> v .: "results"++ parseJSON _ = mzero++-- | All relevant information about an AUR package.+data AurInfo = AurInfo+ { aurIdOf :: Int+ , aurNameOf :: Text+ , pkgBaseIdOf :: Int+ , pkgBaseOf :: Text+ , aurVersionOf :: Text+ , aurDescriptionOf :: Maybe Text+ , urlOf :: Maybe Text+ , aurVotesOf :: Int+ , popularityOf :: Float+ , dateObsoleteOf :: Maybe Int+ , aurMaintainerOf :: Maybe Text+ , submissionDateOf :: Int+ , modifiedDateOf :: Int+ , urlPathOf :: Maybe Text+ , dependsOf :: [Text]+ , makeDepsOf :: [Text]+ , optDepsOf :: [Text]+ , conflictsOf :: [Text]+ , providesOf :: [Text]+ , licenseOf :: [Text]+ , keywordsOf :: [Text] } deriving (Eq,Show)++instance FromJSON AurInfo where+ parseJSON (Object v) = AurInfo+ <$> v .: "ID"+ <*> v .: "Name"+ <*> v .: "PackageBaseID"+ <*> v .: "PackageBase"+ <*> v .: "Version"+ <*> v .:? "Description"+ <*> v .:? "URL"+ <*> v .: "NumVotes"+ <*> v .: "Popularity"+ <*> (v .: "OutOfDate" <|> pure Nothing)+ <*> (v .: "Maintainer" <|> pure Nothing)+ <*> v .: "FirstSubmitted"+ <*> v .: "LastModified"+ <*> v .:? "URLPath"+ <*> v .:? "Depends" .!= []+ <*> v .:? "MakeDepends" .!= []+ <*> v .:? "OptDepends" .!= []+ <*> v .:? "Conflicts" .!= []+ <*> v .:? "Provides" .!= []+ <*> v .:? "License" .!= []+ <*> v .:? "Keywords" .!= []++ parseJSON _ = mzero++instance ToJSON AurInfo where+ toJSON ai = object+ [ "ID" .= aurIdOf ai+ , "Name" .= aurNameOf ai+ , "PackageBaseID" .= pkgBaseIdOf ai+ , "PackageBase" .= pkgBaseOf ai+ , "Version" .= aurVersionOf ai+ , "Description" .= aurDescriptionOf ai+ , "URL" .= urlOf ai+ , "NumVotes" .= aurVotesOf ai+ , "Popularity" .= popularityOf ai+ , "OutOfDate" .= dateObsoleteOf ai+ , "Maintainer" .= aurMaintainerOf ai+ , "FirstSubmitted" .= submissionDateOf ai+ , "LastModified" .= modifiedDateOf ai+ , "URLPath" .= urlPathOf ai+ , "Depends" .= dependsOf ai+ , "MakeDepends" .= makeDepsOf ai+ , "OptDepends" .= optDepsOf ai+ , "Conflicts" .= conflictsOf ai+ , "Provides" .= providesOf ai+ , "License" .= licenseOf ai+ , "Keywords" .= keywordsOf ai ]++---++type Info = "rpc" :> QueryParam "v" Text+ :> QueryParam "type" Text+ :> QueryParams "arg[]" Text+ :> Get '[JSON] RPCResp++type Search = "rpc" :> QueryParam "v" Text+ :> QueryParam "type" Text+ :> QueryParam "arg" Text+ :> Get '[JSON] RPCResp++type API = Info :<|> Search++api :: Proxy API+api = Proxy++url :: BaseUrl+url = BaseUrl Https "aur.archlinux.org" 443 ""++-- | Make a call to the AUR RPC. Assumes version 5 of the API.+rpcI :: Maybe Text -> Maybe Text -> [Text] -> ClientM RPCResp+rpcS :: Maybe Text -> Maybe Text -> Maybe Text -> ClientM RPCResp+rpcI :<|> rpcS = client api++-- | Perform an @info@ call on one or more package names.+-- Will fail with a `Nothing` if there was a connection/decoding error.+info :: Manager -> [Text] -> IO (Either ClientError [AurInfo])+info m ps = unwrap m $ rpcI (Just "5") (Just "info") ps++-- | Perform a @search@ call on a package name or description text.+-- Will fail with a `Nothing` if there was a connection/decoding error.+search :: Manager -> Text -> IO (Either ClientError [AurInfo])+search m p = unwrap m $ rpcS (Just "5") (Just "search") (Just p)++unwrap :: Manager -> ClientM RPCResp -> IO (Either ClientError [AurInfo])+unwrap m r = fmap _results <$> runClientM r (ClientEnv m url Nothing)
− lib/Linux/Arch/Aur/Rpc.hs
@@ -1,59 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators #-}---- |--- Module : Linux.Arch.Aur.Rpc--- Copyright : (c) Colin Woodbury, 2014 - 2019--- License : GPL3--- Maintainer: Colin Woodbury <colin@fosskers.ca>------ See https://aur.archlinux.org/rpc for details.--module Linux.Arch.Aur.Rpc ( info, search ) where--import Control.Error.Util (hush)-import Data.Proxy-import Data.Text (Text)-import Linux.Arch.Aur.Types-import Network.HTTP.Client (Manager)-import Servant.API-import Servant.Client-------type Info = "rpc" :> QueryParam "v" Text- :> QueryParam "type" Text- :> QueryParams "arg[]" Text- :> Get '[JSON] RPCResp--type Search = "rpc" :> QueryParam "v" Text- :> QueryParam "type" Text- :> QueryParam "arg" Text- :> Get '[JSON] RPCResp--type API = Info :<|> Search--api :: Proxy API-api = Proxy--url :: BaseUrl-url = BaseUrl Https "aur.archlinux.org" 443 ""---- | Make a call to the AUR RPC. Assumes version 5 of the API.-rpcI :: Maybe Text -> Maybe Text -> [Text] -> ClientM RPCResp-rpcS :: Maybe Text -> Maybe Text -> Maybe Text -> ClientM RPCResp-rpcI :<|> rpcS = client api---- | Perform an @info@ call on one or more package names.--- Will fail with a `Nothing` if there was a connection/decoding error.-info :: Manager -> [Text] -> IO (Maybe [AurInfo])-info m ps = unwrap m $ rpcI (Just "5") (Just "info") ps---- | Perform a @search@ call on a package name or description text.--- Will fail with a `Nothing` if there was a connection/decoding error.-search :: Manager -> Text -> IO (Maybe [AurInfo])-search m p = unwrap m $ rpcS (Just "5") (Just "search") (Just p)--unwrap :: Manager -> ClientM RPCResp -> IO (Maybe [AurInfo])-unwrap m r = fmap _results . hush <$> runClientM r (ClientEnv m url Nothing)
− lib/Linux/Arch/Aur/Types.hs
@@ -1,105 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- |--- Module : Linux.Arch.Aur.Types--- Copyright : (c) Colin Woodbury, 2014 - 2019--- License : GPL3--- Maintainer: Colin Woodbury <colin@fosskers.ca>--module Linux.Arch.Aur.Types- ( RPCResp(..)- , AurInfo(..)- ) where--import Control.Applicative ((<|>))-import Control.Monad (mzero)-import Data.Aeson-import Data.Text-------data RPCResp = RPCResp { _version :: Int- , _type :: Text- , _resultCount :: Int- , _results :: [AurInfo] } deriving (Show)--instance FromJSON RPCResp where- parseJSON (Object v) = RPCResp <$>- v .: "version" <*>- v .: "type" <*>- v .: "resultcount" <*>- v .: "results"-- parseJSON _ = mzero--data AurInfo = AurInfo { aurIdOf :: Int- , aurNameOf :: Text- , pkgBaseIdOf :: Int- , pkgBaseOf :: Text- , aurVersionOf :: Text- , aurDescriptionOf :: Maybe Text- , urlOf :: Maybe Text- , aurVotesOf :: Int- , popularityOf :: Float- , dateObsoleteOf :: Maybe Int- , aurMaintainerOf :: Maybe Text- , submissionDateOf :: Int- , modifiedDateOf :: Int- , urlPathOf :: Maybe Text- , dependsOf :: [Text]- , makeDepsOf :: [Text]- , optDepsOf :: [Text]- , conflictsOf :: [Text]- , providesOf :: [Text]- , licenseOf :: [Text]- , keywordsOf :: [Text] } deriving (Eq,Show)--instance FromJSON AurInfo where- parseJSON (Object v) = AurInfo <$>- v .: "ID" <*>- v .: "Name" <*>- v .: "PackageBaseID" <*>- v .: "PackageBase" <*>- v .: "Version" <*>- v .:? "Description" <*>- v .:? "URL" <*>- v .: "NumVotes" <*>- v .: "Popularity" <*>- (v .: "OutOfDate" <|> pure Nothing) <*>- (v .: "Maintainer" <|> pure Nothing) <*>- v .: "FirstSubmitted" <*>- v .: "LastModified" <*>- v .:? "URLPath" <*>- v .:? "Depends" .!= [] <*>- v .:? "MakeDepends" .!= [] <*>- v .:? "OptDepends" .!= [] <*>- v .:? "Conflicts" .!= [] <*>- v .:? "Provides" .!= [] <*>- v .:? "License" .!= [] <*>- v .:? "Keywords" .!= []-- parseJSON _ = mzero--instance ToJSON AurInfo where- toJSON ai = object- [ "ID" .= aurIdOf ai- , "Name" .= aurNameOf ai- , "PackageBaseID" .= pkgBaseIdOf ai- , "PackageBase" .= pkgBaseOf ai- , "Version" .= aurVersionOf ai- , "Description" .= aurDescriptionOf ai- , "URL" .= urlOf ai- , "NumVotes" .= aurVotesOf ai- , "Popularity" .= popularityOf ai- , "OutOfDate" .= dateObsoleteOf ai- , "Maintainer" .= aurMaintainerOf ai- , "FirstSubmitted" .= submissionDateOf ai- , "LastModified" .= modifiedDateOf ai- , "URLPath" .= urlPathOf ai- , "Depends" .= dependsOf ai- , "MakeDepends" .= makeDepsOf ai- , "OptDepends" .= optDepsOf ai- , "Conflicts" .= conflictsOf ai- , "Provides" .= providesOf ai- , "License" .= licenseOf ai- , "Keywords" .= keywordsOf ai ]
tests/Test.hs view
@@ -18,10 +18,10 @@ ] infoTest :: Manager -> Assertion-infoTest m = info m ["aura"] >>= \x -> (not . null <$> x) @?= Just True+infoTest m = info m ["aura"] >>= \x -> (not . null <$> x) @?= Right True infoTest' :: Manager -> Assertion-infoTest' m = info m ["aura1234567"] >>= \x -> (null <$> x) @?= Just True+infoTest' m = info m ["aura1234567"] >>= \x -> (null <$> x) @?= Right True searchTest :: Manager -> Assertion searchTest m = search m "aura" >>= assertBool "Good search" . not . null