packages feed

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 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