aws-easy (empty) → 0.1.0.0
raw patch · 12 files changed
+488/−0 lines, 12 filesdep +amazonkadep +amazonka-coredep +aws-easysetup-changed
Dependencies added: amazonka, amazonka-core, aws-easy, base, bytestring, lens, resourcet, template-haskell, text
Files
- LICENSE +20/−0
- README.md +41/−0
- Setup.hs +16/−0
- app/Main.hs +4/−0
- aws-easy.cabal +46/−0
- lib/Network/AWS/Easy.hs +25/−0
- lib/Network/AWS/Easy/Classes.hs +30/−0
- lib/Network/AWS/Easy/Prelude.hs +45/−0
- lib/Network/AWS/Easy/Service.hs +113/−0
- lib/Network/AWS/Easy/TH.hs +87/−0
- lib/Network/AWS/Easy/Types.hs +30/−0
- lib/Network/AWS/Easy/Util.hs +31/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2018 Richard Cook++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,41 @@+# AWS Easy++A simplified, high-level [AWS][aws] API built on top of [amazonka][amazonka]++This is a collection of helper functions and some Template Haskell that I use regularly and has streamlined by use of the [amazonka][amazonka] framework. It was extracted from the code I wrote as part of my [AWS via Haskell][aws-via-haskell] series of blog posts.+++## Setup++### Clone repository++```+git clone https://github.com/rcook/aws-easy.git+```++### Install compiler++```+stack setup+```++### Build++```+stack build --fast+```++### Test++```+stack test+```++## Licence++Released under [MIT License][licence]++[amazonka]: https://hackage.haskell.org/package/amazonka+[aws]: https://aws.amazon.com/+[aws-via-haskell]: http://blog.rcook.org/blog/2017/aws-via-haskell/+[licence]: LICENSE
+ Setup.hs view
@@ -0,0 +1,16 @@+{-|+Module : Main+Description : Setup entrypoint for @aws-easy@+Copyright : (C) Richard Cook, 2018+Licence : MIT+Maintainer : rcook@rcook.org+Stability : stable+Portability : portable+-}++module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,4 @@+module Main (main) where++main :: IO ()+main = putStrLn "Hello world"
+ aws-easy.cabal view
@@ -0,0 +1,46 @@+name: aws-easy+version: 0.1.0.0+synopsis: AWS Easy: Helper functions for working with amazonka+description: This package provides assorted functions and some Template Haskell to simplify working the amazonka family of packages for interacting with Amazon Web Services.+homepage: https://github.com/rcook/aws-easy#readme+license: MIT+license-file: LICENSE+author: Richard Cook+maintainer: rcook@rcook.org+copyright: 2018 Richard Cook+category: Network+build-type: Simple+cabal-version: >= 1.10+extra-source-files: README.md++source-repository head+ type: git+ location: https://github.com/rcook/aws-easy.git++library+ default-language: Haskell2010+ hs-source-dirs: lib+ ghc-options: -W -Wall -fwarn-incomplete-patterns -fwarn-unused-imports+ build-depends: amazonka+ , amazonka-core+ , base >= 4.7 && < 5+ , bytestring+ , lens+ , resourcet+ , template-haskell+ , text+ exposed-modules: Network.AWS.Easy+ , Network.AWS.Easy.Classes+ , Network.AWS.Easy.Prelude+ , Network.AWS.Easy.Service+ , Network.AWS.Easy.TH+ , Network.AWS.Easy.Types+ , Network.AWS.Easy.Util++executable aws-easy-app+ default-language: Haskell2010+ hs-source-dirs: app+ main-is: Main.hs+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -W -Wall -fwarn-incomplete-patterns -fwarn-unused-imports+ build-depends: aws-easy+ , base >= 4.7 && < 5
+ lib/Network/AWS/Easy.hs view
@@ -0,0 +1,25 @@+{-|+Module : Network.AWS.Easy+Description : Umbrella module+Copyright : (C) Richard Cook, 2018+License : MIT+Maintainer : rcook@rcook.org+Stability : experimental+Portability : portable+-}++module Network.AWS.Easy+ ( module Network.AWS.Easy.Classes+ , module Network.AWS.Easy.Prelude+ , module Network.AWS.Easy.Service+ , module Network.AWS.Easy.TH+ , module Network.AWS.Easy.Types+ , module Network.AWS.Easy.Util+ ) where++import Network.AWS.Easy.Classes+import Network.AWS.Easy.Prelude+import Network.AWS.Easy.Service+import Network.AWS.Easy.TH+import Network.AWS.Easy.Types+import Network.AWS.Easy.Util
+ lib/Network/AWS/Easy/Classes.hs view
@@ -0,0 +1,30 @@+{-|+Module : Network.AWS.Easy.Classes+Description : Service and session type classes+Copyright : (C) Richard Cook, 2018+License : MIT+Maintainer : rcook@rcook.org+Stability : experimental+Portability : portable++This modules provides service and session type classes for the "AWS via Haskell" project.+-}++{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE TypeFamilies #-}++module Network.AWS.Easy.Classes+ ( ServiceClass(..)+ , SessionClass(..)+ ) where++import Network.AWS (Service)+import Network.AWS.Easy.Types++class ServiceClass a where+ type TypedSession a :: *+ rawService :: a -> Service+ wrappedSession :: Session -> TypedSession a++class SessionClass a where+ rawSession :: a -> Session
+ lib/Network/AWS/Easy/Prelude.hs view
@@ -0,0 +1,45 @@+{-|+Module : Network.AWS.Easy.Prelude+Description : Re-exports of most commonly used Amazonka functions+Copyright : (C) Richard Cook, 2018+License : MIT+Maintainer : rcook@rcook.org+Stability : experimental+Portability : portable++This module provides re-exports of most commonly used Amazonka functions as well as lens and error-handling functions.+-}++module Network.AWS.Easy.Prelude+ ( (^.)+ , (&)+ , (.~)+ , _ServiceError+ , AsError+ , Credentials(..)+ , Region(..)+ , ServiceError+ , await+ , hasCode+ , hasStatus+ , send+ , sinkBody+ , toText+ ) where++import Control.Lens ((^.), (&), (.~))+import Network.AWS+ ( _ServiceError+ , AsError+ , Credentials(..)+ , Region(..)+ , ServiceError+ , await+ , send+ , sinkBody+ )+import Network.AWS.Data (toText)+import Network.AWS.Error+ ( hasCode+ , hasStatus+ )
+ lib/Network/AWS/Easy/Service.hs view
@@ -0,0 +1,113 @@+{-|+Module : Network.AWS.Easy.Service+Description : Configuring and making client connections to AWS services+Copyright : (C) Richard Cook, 2018+License : MIT+Maintainer : rcook@rcook.org+Stability : experimental+Portability : portable++This modules provides support for configuring and making client connections to AWS services for the "AWS via Haskell" project.+-}++{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++module Network.AWS.Easy.Service+ ( AWSConfig+ , Endpoint(..)+ , HostName+ , Logging(..)+ , Port+ , awscCredentials+ , awscEndpoint+ , awscLogging+ , awsConfig+ , connect+ , withAWS+ ) where++import Control.Lens ((<&>), makeLenses, set)+import Control.Monad.Trans.AWS+ ( AWST'+ , reconfigure+ , runAWST+ , within+ )+import Control.Monad.Trans.Resource+ ( MonadBaseControl+ , ResourceT+ )+import Data.ByteString (ByteString)+import Network.AWS+ ( Credentials(..)+ , Env+ , LogLevel(..)+ , Region(..)+ , Service+ , envLogger+ , newEnv+ , newLogger+ , runResourceT+ , setEndpoint+ )+import Network.AWS.Easy.Classes+import Network.AWS.Easy.Types+import System.IO (stdout)++type HostName = ByteString++type Port = Int++data Logging = LoggingEnabled | LoggingDisabled++data Endpoint = AWSRegion Region | Local HostName Port++data AWSConfig = AWSConfig+ { _awscEndpoint :: Endpoint+ , _awscLogging :: Logging+ , _awscCredentials :: Credentials+ }+makeLenses ''AWSConfig++awsConfig :: Endpoint -> AWSConfig+awsConfig endpoint = AWSConfig endpoint LoggingDisabled Discover++connect :: forall a . ServiceClass a => AWSConfig -> a -> IO (TypedSession a)+connect (AWSConfig endpoint logging credentials) service = do+ let serviceRaw = rawService service+ e <- mkEnv logging credentials+ let (r, s) = regionService endpoint serviceRaw+ session' <- return $ Session e r s+ let session = wrappedSession @a session'+ return session++mkEnv :: Logging -> Credentials -> IO Env+-- Standard discovery mechanism for credentials, log to standard output+mkEnv LoggingEnabled c = do+ logger <- newLogger Debug stdout+ newEnv c <&> set envLogger logger+-- Standard discovery mechanism for credentials, no logging+mkEnv LoggingDisabled c = newEnv c++regionService :: Endpoint -> Service -> (Region, Service)+-- Run against a DynamoDB instance running on AWS in specified region+regionService (AWSRegion region) s = (region, s)+-- Run against a local DynamoDB instance on a given host and port+regionService (Local hostName port) s = (NorthVirginia, setEndpoint False hostName port s)++withAWS :: (MonadBaseControl IO m, SessionClass b) =>+ AWST' Env (ResourceT m) a+ -> b+ -> m a+withAWS action session =+ let Session{..} = rawSession session+ in+ runResourceT . runAWST _sEnv . within _sRegion $ do+ reconfigure _sService action
+ lib/Network/AWS/Easy/TH.hs view
@@ -0,0 +1,87 @@+{-|+Module : Network.AWS.Easy.TH+Description : Template Haskell helpers for 'Network.AWS.Easy'+Copyright : (C) Richard Cook, 2018+License : MIT+Maintainer : rcook@rcook.org+Stability : experimental+Portability : portable++This modules provides Template Haskell helper functions for eliminating boilerplate+-}++{-# LANGUAGE TemplateHaskell #-}++module Network.AWS.Easy.TH+ ( wrapAWSService+ ) where++import Language.Haskell.TH+import Network.AWS (Service)+import Network.AWS.Easy.Classes+import Network.AWS.Easy.Types++-- |Generates type-safe AWS service and session wrappers types for use with+-- 'AWSViaHaskell.AWSService.connect' and 'AWSViaHaskell.AWSService.withAWS' functions+--+-- Example top-level invocation:+--+-- @+-- wrapAWSService \'dynamoDB \"DDBService\" \"DDBSession\"+-- @+--+-- This will generate boilerplate like the following:+--+-- @+-- data DDBService = DDBService Service+--+-- data DDBSession = DDBSession Session+--+-- instance ServiceClass DDBService where+-- type TypedSession DDBService = DDBSession+-- rawService (DDBService x) = x+-- wrappedSession = DDBSession+--+-- instance SessionClass DDBSession where+-- rawSession (DDBSession x) = x+--+-- dynamoDBService :: DDBService+-- dynamoDBService = DDBService dynamoDB+-- @+wrapAWSService ::+ Name -- ^ Name of the amazonka 'Network.AWS.Types.Service' value to wrap+ -> String -- ^ Name of the service type to generate+ -> String -- ^ Name of the session type to generate+ -> Q [Dec] -- ^ Declarations for splicing into source file+wrapAWSService varN serviceTypeName sessionTypeName = do+ serviceVarN <- newName "x"+ sessionVarN <- newName "x"+ let serviceN = mkName serviceTypeName+ sessionN = mkName sessionTypeName+ wrappedVarN = mkName $ nameBase varN ++ "Service"+ serviceD = DataD [] serviceN [] Nothing [NormalC serviceN [(Bang NoSourceUnpackedness NoSourceStrictness, ConT ''Service)]] []+ sessionD = DataD [] sessionN [] Nothing [NormalC sessionN [(Bang NoSourceUnpackedness NoSourceStrictness, ConT ''Session)]] []+ serviceInst = InstanceD+ Nothing+ []+ (AppT (ConT ''ServiceClass) (ConT serviceN))+ [ TySynInstD ''TypedSession (TySynEqn [ConT serviceN] (ConT sessionN))+ , FunD 'rawService [Clause [ConP serviceN [VarP serviceVarN]] (NormalB (VarE serviceVarN)) []]+ , ValD (VarP 'wrappedSession) (NormalB (ConE $ mkName sessionTypeName)) []+ ]+ sessionInst = InstanceD+ Nothing+ []+ (AppT (ConT ''SessionClass) (ConT sessionN))+ [ FunD 'rawSession [Clause [ConP sessionN [VarP sessionVarN]] (NormalB (VarE sessionVarN)) []]+ ]+ sig = SigD wrappedVarN (ConT serviceN)+ var = ValD (VarP wrappedVarN) (NormalB (AppE (ConE serviceN) (VarE $ varN))) []+ pure+ [ serviceD+ , sessionD+ , serviceInst+ , sessionInst+ , sig+ , var+ ]
+ lib/Network/AWS/Easy/Types.hs view
@@ -0,0 +1,30 @@+{-|+Module : Network.AWS.Easy.Types+Description : Support types+Copyright : (C) Richard Cook, 2018+License : MIT+Maintainer : rcook@rcook.org+Stability : experimental+Portability : portable++This modules provides support types for the "AWS via Haskell" project.+-}++{-# LANGUAGE TemplateHaskell #-}++module Network.AWS.Easy.Types+ ( Session(..)+ , sEnv+ , sRegion+ , sService+ ) where++import Control.Lens (makeLenses)+import Network.AWS (Env, Region, Service)++data Session = Session+ { _sEnv :: Env+ , _sRegion :: Region+ , _sService :: Service+ }+makeLenses ''Session
+ lib/Network/AWS/Easy/Util.hs view
@@ -0,0 +1,31 @@+{-|+Module : Network.AWS.Easy.Util+Description : General-purpose helper functions+Copyright : (C) Richard Cook, 2018+License : MIT+Maintainer : rcook@rcook.org+Stability : experimental+Portability : portable++This modules provides general-purpose helper functions for the "AWS via Haskell" project.+-}++{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RecordWildCards #-}++module Network.AWS.Easy.Util+ ( intToText+ , parseInt+ ) where++import Data.Text (Text)+import qualified Data.Text as Text (null, pack)+import qualified Data.Text.Read as Text (decimal)++intToText :: Int -> Text+intToText = Text.pack . show++parseInt :: Text -> Maybe Int+parseInt s = case Text.decimal s of+ Left _ -> Nothing+ Right (result, s') -> if Text.null s' then Just result else Nothing