serverless-haskell 0.11.3 → 0.12.0
raw patch · 8 files changed
+160/−146 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- AWSLambda.Events: APIGateway :: !APIGatewayEvent -> LambdaEvent message
- AWSLambda.Events: Alexa :: !AlexaEvent -> LambdaEvent message
- AWSLambda.Events: CloudFormation :: !CloudFormationEvent -> LambdaEvent message
- AWSLambda.Events: CloudFront :: !CloudFrontEvent -> LambdaEvent message
- AWSLambda.Events: CloudWatchEvents :: !CloudWatchEventsEvent -> LambdaEvent message
- AWSLambda.Events: CloudWatchLogs :: !CloudWatchLogsEvent -> LambdaEvent message
- AWSLambda.Events: CodeCommit :: !CodeCommitEvent -> LambdaEvent message
- AWSLambda.Events: Cognito :: !CognitoEvent -> LambdaEvent message
- AWSLambda.Events: Config :: !ConfigEvent -> LambdaEvent message
- AWSLambda.Events: Custom :: !Value -> LambdaEvent message
- AWSLambda.Events: DynamoDB :: !DynamoDBEvent -> LambdaEvent message
- AWSLambda.Events: Firehose :: !FirehoseEvent -> LambdaEvent message
- AWSLambda.Events: Invoke :: !InvokeEvent -> LambdaEvent message
- AWSLambda.Events: IoTButton :: !IoTButtonEvent -> LambdaEvent message
- AWSLambda.Events: KinesisStream :: !KinesisEvent -> LambdaEvent message
- AWSLambda.Events: Lex :: !LexEvent -> LambdaEvent message
- AWSLambda.Events: S3 :: !S3Event -> LambdaEvent message
- AWSLambda.Events: SES :: !SESEvent -> LambdaEvent message
- AWSLambda.Events: SNS :: !SNSEvent message -> LambdaEvent message
- AWSLambda.Events: SQS :: !SQSEvent message -> LambdaEvent message
- AWSLambda.Events: _APIGateway :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) APIGatewayEvent
- AWSLambda.Events: _Alexa :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) AlexaEvent
- AWSLambda.Events: _CloudFormation :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) CloudFormationEvent
- AWSLambda.Events: _CloudFront :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) CloudFrontEvent
- AWSLambda.Events: _CloudWatchEvents :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) CloudWatchEventsEvent
- AWSLambda.Events: _CloudWatchLogs :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) CloudWatchLogsEvent
- AWSLambda.Events: _CodeCommit :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) CodeCommitEvent
- AWSLambda.Events: _Cognito :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) CognitoEvent
- AWSLambda.Events: _Config :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) ConfigEvent
- AWSLambda.Events: _Custom :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) Value
- AWSLambda.Events: _DynamoDB :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) DynamoDBEvent
- AWSLambda.Events: _Firehose :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) FirehoseEvent
- AWSLambda.Events: _Invoke :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) InvokeEvent
- AWSLambda.Events: _IoTButton :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) IoTButtonEvent
- AWSLambda.Events: _KinesisStream :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) KinesisEvent
- AWSLambda.Events: _Lex :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) LexEvent
- AWSLambda.Events: _S3 :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) S3Event
- AWSLambda.Events: _SES :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) SESEvent
- AWSLambda.Events: _SNS :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) (SNSEvent message_aRdt)
- AWSLambda.Events: _SQS :: forall message_aRdt. Prism' (LambdaEvent message_aRdt) (SQSEvent message_aRdt)
- AWSLambda.Events: data APIGatewayEvent
- AWSLambda.Events: data AlexaEvent
- AWSLambda.Events: data CloudFormationEvent
- AWSLambda.Events: data CloudFrontEvent
- AWSLambda.Events: data CloudWatchEventsEvent
- AWSLambda.Events: data CloudWatchLogsEvent
- AWSLambda.Events: data CodeCommitEvent
- AWSLambda.Events: data CognitoEvent
- AWSLambda.Events: data ConfigEvent
- AWSLambda.Events: data DynamoDBEvent
- AWSLambda.Events: data FirehoseEvent
- AWSLambda.Events: data InvokeEvent
- AWSLambda.Events: data IoTButtonEvent
- AWSLambda.Events: data LambdaEvent message
- AWSLambda.Events: data LexEvent
- AWSLambda.Events: data SESEvent
- AWSLambda.Events: instance Network.AWS.Data.Text.FromText message => Data.Aeson.Types.FromJSON.FromJSON (AWSLambda.Events.LambdaEvent message)
+ AWSLambda.Events: s3InSnsInSqsMain :: (MonadCatch m, MonadIO m) => (S3EventNotification -> m ()) -> m ()
+ AWSLambda.Events: snsInSqsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()
+ AWSLambda.Events.Records: instance Data.Foldable.Foldable AWSLambda.Events.Records.RecordsEvent
+ AWSLambda.Events.Records: instance GHC.Base.Functor AWSLambda.Events.Records.RecordsEvent
+ AWSLambda.Events.Records: recordsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()
+ AWSLambda.Events.Records: traverseRecords :: Applicative m => (a -> m ()) -> RecordsEvent a -> m ()
+ AWSLambda.Events.S3Event: isCreateEvent :: S3EventNotification -> Bool
+ AWSLambda.Events.S3Event: isRemoveEvent :: S3EventNotification -> Bool
+ AWSLambda.Events.SNSEvent: snsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()
+ AWSLambda.Events.SNSEvent: traverseSns :: (FromJSON a, Applicative m) => (a -> m ()) -> SNSEvent (Embedded a) -> m ()
+ AWSLambda.Events.SQSEvent: sqsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()
+ AWSLambda.Events.SQSEvent: traverseSqs :: (FromJSON a, Applicative m) => (a -> m ()) -> SQSEvent (Embedded a) -> m ()
+ AWSLambda.Handler: lambdaMainRaw :: (MonadCatch m, MonadIO m) => (ByteString -> m ByteString) -> m ()
- AWSLambda: lambdaMain :: (FromJSON event, ToJSON res) => (event -> IO res) -> IO ()
+ AWSLambda: lambdaMain :: (FromJSON event, ToJSON res, MonadCatch m, MonadIO m) => (event -> m res) -> m ()
- AWSLambda.Events.APIGateway: agprqBody :: forall body_aUsO body_aUNm. Lens (APIGatewayProxyRequest body_aUsO) (APIGatewayProxyRequest body_aUNm) (Maybe (TextValue body_aUsO)) (Maybe (TextValue body_aUNm))
+ AWSLambda.Events.APIGateway: agprqBody :: forall body_aRBb body_aRUO. Lens (APIGatewayProxyRequest body_aRBb) (APIGatewayProxyRequest body_aRUO) (Maybe (TextValue body_aRBb)) (Maybe (TextValue body_aRUO))
- AWSLambda.Events.APIGateway: agprqHeaders :: forall body_aUsO. Lens' (APIGatewayProxyRequest body_aUsO) RequestHeaders
+ AWSLambda.Events.APIGateway: agprqHeaders :: forall body_aRBb. Lens' (APIGatewayProxyRequest body_aRBb) RequestHeaders
- AWSLambda.Events.APIGateway: agprqHttpMethod :: forall body_aUsO. Lens' (APIGatewayProxyRequest body_aUsO) Method
+ AWSLambda.Events.APIGateway: agprqHttpMethod :: forall body_aRBb. Lens' (APIGatewayProxyRequest body_aRBb) Method
- AWSLambda.Events.APIGateway: agprqPath :: forall body_aUsO. Lens' (APIGatewayProxyRequest body_aUsO) ByteString
+ AWSLambda.Events.APIGateway: agprqPath :: forall body_aRBb. Lens' (APIGatewayProxyRequest body_aRBb) ByteString
- AWSLambda.Events.APIGateway: agprqPathParameters :: forall body_aUsO. Lens' (APIGatewayProxyRequest body_aUsO) (HashMap PathParamName PathParamValue)
+ AWSLambda.Events.APIGateway: agprqPathParameters :: forall body_aRBb. Lens' (APIGatewayProxyRequest body_aRBb) (HashMap PathParamName PathParamValue)
- AWSLambda.Events.APIGateway: agprqQueryStringParameters :: forall body_aUsO. Lens' (APIGatewayProxyRequest body_aUsO) Query
+ AWSLambda.Events.APIGateway: agprqQueryStringParameters :: forall body_aRBb. Lens' (APIGatewayProxyRequest body_aRBb) Query
- AWSLambda.Events.APIGateway: agprqRequestContext :: forall body_aUsO. Lens' (APIGatewayProxyRequest body_aUsO) ProxyRequestContext
+ AWSLambda.Events.APIGateway: agprqRequestContext :: forall body_aRBb. Lens' (APIGatewayProxyRequest body_aRBb) ProxyRequestContext
- AWSLambda.Events.APIGateway: agprqResource :: forall body_aUsO. Lens' (APIGatewayProxyRequest body_aUsO) Text
+ AWSLambda.Events.APIGateway: agprqResource :: forall body_aRBb. Lens' (APIGatewayProxyRequest body_aRBb) Text
- AWSLambda.Events.APIGateway: agprqStageVariables :: forall body_aUsO. Lens' (APIGatewayProxyRequest body_aUsO) (HashMap StageVarName StageVarValue)
+ AWSLambda.Events.APIGateway: agprqStageVariables :: forall body_aRBb. Lens' (APIGatewayProxyRequest body_aRBb) (HashMap StageVarName StageVarValue)
- AWSLambda.Events.APIGateway: agprsBody :: forall body_aUPf body_aV6i. Lens (APIGatewayProxyResponse body_aUPf) (APIGatewayProxyResponse body_aV6i) (Maybe (TextValue body_aUPf)) (Maybe (TextValue body_aV6i))
+ AWSLambda.Events.APIGateway: agprsBody :: forall body_aRWH body_aSe3. Lens (APIGatewayProxyResponse body_aRWH) (APIGatewayProxyResponse body_aSe3) (Maybe (TextValue body_aRWH)) (Maybe (TextValue body_aSe3))
- AWSLambda.Events.APIGateway: agprsHeaders :: forall body_aUPf. Lens' (APIGatewayProxyResponse body_aUPf) ResponseHeaders
+ AWSLambda.Events.APIGateway: agprsHeaders :: forall body_aRWH. Lens' (APIGatewayProxyResponse body_aRWH) ResponseHeaders
- AWSLambda.Events.APIGateway: agprsStatusCode :: forall body_aUPf. Lens' (APIGatewayProxyResponse body_aUPf) Int
+ AWSLambda.Events.APIGateway: agprsStatusCode :: forall body_aRWH. Lens' (APIGatewayProxyResponse body_aRWH) Int
- AWSLambda.Events.Records: reRecords :: forall a_akKS a_apUu. Iso (RecordsEvent a_akKS) (RecordsEvent a_apUu) [a_akKS] [a_apUu]
+ AWSLambda.Events.Records: reRecords :: forall a_atWh a_auV8. Iso (RecordsEvent a_atWh) (RecordsEvent a_auV8) [a_atWh] [a_auV8]
- AWSLambda.Events.SNSEvent: smMessage :: forall message_aK9J message_aKoh. Lens (SNSMessage message_aK9J) (SNSMessage message_aKoh) (TextValue message_aK9J) (TextValue message_aKoh)
+ AWSLambda.Events.SNSEvent: smMessage :: forall message_aM7M message_aMmd. Lens (SNSMessage message_aM7M) (SNSMessage message_aMmd) (TextValue message_aM7M) (TextValue message_aMmd)
- AWSLambda.Events.SNSEvent: smMessageAttributes :: forall message_aK9J. Lens' (SNSMessage message_aK9J) (HashMap Text MessageAttribute)
+ AWSLambda.Events.SNSEvent: smMessageAttributes :: forall message_aM7M. Lens' (SNSMessage message_aM7M) (HashMap Text MessageAttribute)
- AWSLambda.Events.SNSEvent: smMessageId :: forall message_aK9J. Lens' (SNSMessage message_aK9J) Text
+ AWSLambda.Events.SNSEvent: smMessageId :: forall message_aM7M. Lens' (SNSMessage message_aM7M) Text
- AWSLambda.Events.SNSEvent: smSignature :: forall message_aK9J. Lens' (SNSMessage message_aK9J) Text
+ AWSLambda.Events.SNSEvent: smSignature :: forall message_aM7M. Lens' (SNSMessage message_aM7M) Text
- AWSLambda.Events.SNSEvent: smSignatureVersion :: forall message_aK9J. Lens' (SNSMessage message_aK9J) Text
+ AWSLambda.Events.SNSEvent: smSignatureVersion :: forall message_aM7M. Lens' (SNSMessage message_aM7M) Text
- AWSLambda.Events.SNSEvent: smSigningCertUrl :: forall message_aK9J. Lens' (SNSMessage message_aK9J) Text
+ AWSLambda.Events.SNSEvent: smSigningCertUrl :: forall message_aM7M. Lens' (SNSMessage message_aM7M) Text
- AWSLambda.Events.SNSEvent: smSubject :: forall message_aK9J. Lens' (SNSMessage message_aK9J) Text
+ AWSLambda.Events.SNSEvent: smSubject :: forall message_aM7M. Lens' (SNSMessage message_aM7M) Text
- AWSLambda.Events.SNSEvent: smTimestamp :: forall message_aK9J. Lens' (SNSMessage message_aK9J) UTCTime
+ AWSLambda.Events.SNSEvent: smTimestamp :: forall message_aM7M. Lens' (SNSMessage message_aM7M) UTCTime
- AWSLambda.Events.SNSEvent: smTopicArn :: forall message_aK9J. Lens' (SNSMessage message_aK9J) Text
+ AWSLambda.Events.SNSEvent: smTopicArn :: forall message_aM7M. Lens' (SNSMessage message_aM7M) Text
- AWSLambda.Events.SNSEvent: smType :: forall message_aK9J. Lens' (SNSMessage message_aK9J) Text
+ AWSLambda.Events.SNSEvent: smType :: forall message_aM7M. Lens' (SNSMessage message_aM7M) Text
- AWSLambda.Events.SNSEvent: smUnsubscribeUrl :: forall message_aK9J. Lens' (SNSMessage message_aK9J) Text
+ AWSLambda.Events.SNSEvent: smUnsubscribeUrl :: forall message_aM7M. Lens' (SNSMessage message_aM7M) Text
- AWSLambda.Events.SNSEvent: srEventSource :: forall message_aKqS. Lens' (SNSRecord message_aKqS) Text
+ AWSLambda.Events.SNSEvent: srEventSource :: forall message_aMoO. Lens' (SNSRecord message_aMoO) Text
- AWSLambda.Events.SNSEvent: srEventSubscriptionArn :: forall message_aKqS. Lens' (SNSRecord message_aKqS) Text
+ AWSLambda.Events.SNSEvent: srEventSubscriptionArn :: forall message_aMoO. Lens' (SNSRecord message_aMoO) Text
- AWSLambda.Events.SNSEvent: srEventVersion :: forall message_aKqS. Lens' (SNSRecord message_aKqS) Text
+ AWSLambda.Events.SNSEvent: srEventVersion :: forall message_aMoO. Lens' (SNSRecord message_aMoO) Text
- AWSLambda.Events.SNSEvent: srSns :: forall message_aKqS message_aKCm. Lens (SNSRecord message_aKqS) (SNSRecord message_aKCm) (SNSMessage message_aKqS) (SNSMessage message_aKCm)
+ AWSLambda.Events.SNSEvent: srSns :: forall message_aMoO message_aMAi. Lens (SNSRecord message_aMoO) (SNSRecord message_aMAi) (SNSMessage message_aMoO) (SNSMessage message_aMAi)
- AWSLambda.Events.SQSEvent: sqsmAttributes :: forall body_aG27. Lens' (SQSMessage body_aG27) (HashMap Text Text)
+ AWSLambda.Events.SQSEvent: sqsmAttributes :: forall body_aHSX. Lens' (SQSMessage body_aHSX) (HashMap Text Text)
- AWSLambda.Events.SQSEvent: sqsmAwsRegion :: forall body_aG27. Lens' (SQSMessage body_aG27) Region
+ AWSLambda.Events.SQSEvent: sqsmAwsRegion :: forall body_aHSX. Lens' (SQSMessage body_aHSX) Region
- AWSLambda.Events.SQSEvent: sqsmBody :: forall body_aG27 body_aHfg. Lens (SQSMessage body_aG27) (SQSMessage body_aHfg) (TextValue body_aG27) (TextValue body_aHfg)
+ AWSLambda.Events.SQSEvent: sqsmBody :: forall body_aHSX body_aJ68. Lens (SQSMessage body_aHSX) (SQSMessage body_aJ68) (TextValue body_aHSX) (TextValue body_aJ68)
- AWSLambda.Events.SQSEvent: sqsmEventSource :: forall body_aG27. Lens' (SQSMessage body_aG27) Text
+ AWSLambda.Events.SQSEvent: sqsmEventSource :: forall body_aHSX. Lens' (SQSMessage body_aHSX) Text
- AWSLambda.Events.SQSEvent: sqsmEventSourceARN :: forall body_aG27. Lens' (SQSMessage body_aG27) Text
+ AWSLambda.Events.SQSEvent: sqsmEventSourceARN :: forall body_aHSX. Lens' (SQSMessage body_aHSX) Text
- AWSLambda.Events.SQSEvent: sqsmMd5OfBody :: forall body_aG27. Lens' (SQSMessage body_aG27) Text
+ AWSLambda.Events.SQSEvent: sqsmMd5OfBody :: forall body_aHSX. Lens' (SQSMessage body_aHSX) Text
- AWSLambda.Events.SQSEvent: sqsmMessageAttributes :: forall body_aG27. Lens' (SQSMessage body_aG27) (HashMap Text MessageAttribute)
+ AWSLambda.Events.SQSEvent: sqsmMessageAttributes :: forall body_aHSX. Lens' (SQSMessage body_aHSX) (HashMap Text MessageAttribute)
- AWSLambda.Events.SQSEvent: sqsmMessageId :: forall body_aG27. Lens' (SQSMessage body_aG27) Text
+ AWSLambda.Events.SQSEvent: sqsmMessageId :: forall body_aHSX. Lens' (SQSMessage body_aHSX) Text
- AWSLambda.Events.SQSEvent: sqsmReceiptHandle :: forall body_aG27. Lens' (SQSMessage body_aG27) Text
+ AWSLambda.Events.SQSEvent: sqsmReceiptHandle :: forall body_aHSX. Lens' (SQSMessage body_aHSX) Text
- AWSLambda.Handler: lambdaMain :: (FromJSON event, ToJSON res) => (event -> IO res) -> IO ()
+ AWSLambda.Handler: lambdaMain :: (FromJSON event, ToJSON res, MonadCatch m, MonadIO m) => (event -> m res) -> m ()
- Data.Aeson.Embedded: unEmbed :: forall a_aEP5 a_aEWu. Iso (Embedded a_aEP5) (Embedded a_aEWu) a_aEP5 a_aEWu
+ Data.Aeson.Embedded: unEmbed :: forall a_aGFV a_aGNl. Iso (Embedded a_aGFV) (Embedded a_aGNl) a_aGFV a_aGNl
- Data.Aeson.TextValue: unTextValue :: forall a_aFu7 a_aFzJ. Iso (TextValue a_aFu7) (TextValue a_aFzJ) a_aFu7 a_aFzJ
+ Data.Aeson.TextValue: unTextValue :: forall a_aHkX a_aHqz. Iso (TextValue a_aHkX) (TextValue a_aHqz) a_aHkX a_aHqz
Files
- README.md +1/−1
- serverless-haskell.cabal +2/−2
- src/AWSLambda/Events.hs +27/−86
- src/AWSLambda/Events/Records.hs +19/−3
- src/AWSLambda/Events/S3Event.hs +33/−6
- src/AWSLambda/Events/SNSEvent.hs +26/−13
- src/AWSLambda/Events/SQSEvent.hs +24/−11
- src/AWSLambda/Handler.hs +28/−24
README.md view
@@ -1,6 +1,6 @@ # Serverless Haskell -[](https://travis-ci.org/seek-oss/serverless-haskell)+ [](https://hackage.haskell.org/package/serverless-haskell) [](https://www.stackage.org/lts/package/serverless-haskell) [](https://packdeps.haskellers.com/feed?needle=serverless-haskell)
serverless-haskell.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: b59f07c12f9fd7b00b5fe4ab4e1842ce35b15ae050d1c4166bc645916b13f94e+-- hash: f3d35ad6736c054bc1bebffa93ddf0f4d556eca6a0743b1a17f9dc2e7d898c4d name: serverless-haskell-version: 0.11.3+version: 0.12.0 synopsis: Deploying Haskell code onto AWS Lambda using Serverless description: Utilities to help process the events from AWS Lambda when deployed with the serverless-haskell plugin. category: AWS, Cloud, Network
src/AWSLambda/Events.hs view
@@ -1,96 +1,37 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE TemplateHaskell #-} -module AWSLambda.Events where+module AWSLambda.Events+ ( module AWSLambda.Events.APIGateway+ , module AWSLambda.Events.KinesisEvent+ , module AWSLambda.Events.MessageAttribute+ , module AWSLambda.Events.Records+ , module AWSLambda.Events.S3Event+ , module AWSLambda.Events.SNSEvent+ , module AWSLambda.Events.SQSEvent+ , snsInSqsMain+ , s3InSnsInSqsMain+ ) where -import Control.Applicative ((<|>))-import Control.Lens.TH-import Data.Aeson (FromJSON (..), Value)-import Network.AWS.Data.Text (FromText)+import Control.Exception.Safe (MonadCatch)+import Control.Monad.IO.Class+import Data.Aeson (FromJSON(..)) +import AWSLambda.Events.APIGateway import AWSLambda.Events.KinesisEvent+import AWSLambda.Events.MessageAttribute+import AWSLambda.Events.Records import AWSLambda.Events.S3Event import AWSLambda.Events.SNSEvent import AWSLambda.Events.SQSEvent --- | Not yet implemented-data DynamoDBEvent---- | Not yet implemented-data SESEvent---- | Not yet implemented-data CognitoEvent---- | Not yet implemented-data CloudFormationEvent---- | Not yet implemented-data CloudWatchLogsEvent---- | Not yet implemented-data CloudWatchEventsEvent---- | Not yet implemented-data CodeCommitEvent---- | Not yet implemented-data ConfigEvent---- | Not yet implemented-data AlexaEvent---- | Not yet implemented-data LexEvent---- | Not yet implemented-data APIGatewayEvent---- | Not yet implemented-data IoTButtonEvent---- | Not yet implemented-data CloudFrontEvent---- | Not yet implemented-data FirehoseEvent---- | Not yet implemented-data InvokeEvent---- | Sum type for all possible Lambda events.--- Parameterised on the type of SNS Events to be handled.--- See @SNSEvent@ for details.-data LambdaEvent message- = S3 !S3Event- | DynamoDB !DynamoDBEvent- | KinesisStream !KinesisEvent- | SNS !(SNSEvent message)- | SQS !(SQSEvent message)- | SES !SESEvent- | Cognito !CognitoEvent- | CloudFormation !CloudFormationEvent- | CloudWatchLogs !CloudWatchLogsEvent- | CloudWatchEvents !CloudWatchEventsEvent- | CodeCommit !CodeCommitEvent- | Config !ConfigEvent- | Alexa !AlexaEvent- | Lex !LexEvent- | APIGateway !APIGatewayEvent- | IoTButton !IoTButtonEvent- | CloudFront !CloudFrontEvent- | Firehose !FirehoseEvent- | Invoke !InvokeEvent- | Custom !Value---- | Attempt to parse the various event types.--- Any valid JSON that can't be parsed as a specific--- event type will result in a 'Custom' value.-instance FromText message =>- FromJSON (LambdaEvent message) where- parseJSON v =- try S3 v <|> try KinesisStream v <|> try SNS v <|> try SQS v <|> pure (Custom v)- where- try f = fmap f . parseJSON+-- | A specialised version of the 'lambdaMain' entry-point+-- for handling individual SNS messages embedded in SQS messages+snsInSqsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()+snsInSqsMain = sqsMain . traverseSns -$(makePrisms ''LambdaEvent)+-- | A specialised version of the 'lambdaMain' entry-point+-- for handling individual S3 event notifications embedded in+-- SNS messages embedded in SQS messages+s3InSnsInSqsMain :: (MonadCatch m, MonadIO m) => (S3EventNotification -> m ()) -> m ()+s3InSnsInSqsMain = snsInSqsMain . traverseRecords
src/AWSLambda/Events/Records.hs view
@@ -1,14 +1,30 @@+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskell #-} module AWSLambda.Events.Records where +import Control.Exception.Safe (MonadCatch) import Control.Lens.TH (makeLenses)-import Data.Aeson (FromJSON (..), withObject, (.:))+import Control.Monad.IO.Class+import Data.Aeson (FromJSON(..), withObject, (.:))+import Data.Foldable (traverse_) -newtype RecordsEvent a = RecordsEvent { _reRecords :: [a] } deriving (Eq, Show)+import AWSLambda.Handler (lambdaMain) +newtype RecordsEvent a = RecordsEvent { _reRecords :: [a] } deriving (Eq, Show, Functor, Foldable)+ instance FromJSON a => FromJSON (RecordsEvent a) where parseJSON = withObject "RecordsEvent" $ \o -> RecordsEvent <$> o .: "Records" $(makeLenses ''RecordsEvent)++-- | Traverse all the records in a Lambda event+traverseRecords :: Applicative m => (a -> m ()) -> RecordsEvent a -> m ()+traverseRecords = traverse_++-- | A specialised version of the 'lambdaMain' entry-point+-- for handling individual records in a Lambda event+recordsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()+recordsMain = lambdaMain . traverseRecords
src/AWSLambda/Events/S3Event.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE LambdaCase #-} {-| Module: AWSLambda.Events.S3Event@@ -17,7 +18,7 @@ import Data.Aeson.TH (deriveFromJSON) import Data.Text (Text) import Data.Time.Clock (UTCTime)-import qualified Network.AWS.S3 as S3+import Network.AWS.S3 (BucketName, ETag, Event(..), ObjectKey, ObjectVersionId) import qualified Network.AWS.Types as AWS import AWSLambda.Events.Records@@ -32,7 +33,7 @@ data S3BucketEntity = S3BucketEntity { _sbeArn :: !Text- , _sbeName :: !S3.BucketName+ , _sbeName :: !BucketName , _sbeOwnerIdentity :: !UserIdentityEntity } deriving (Eq, Show) @@ -40,11 +41,11 @@ $(makeLenses ''S3BucketEntity) data S3ObjectEntity = S3ObjectEntity- { _soeETag :: !(Maybe S3.ETag)- , _soeKey :: !S3.ObjectKey+ { _soeETag :: !(Maybe ETag)+ , _soeKey :: !ObjectKey , _soeSize :: !(Maybe Integer) , _soeSequencer :: !Text- , _soeVersionId :: !(Maybe S3.ObjectVersionId)+ , _soeVersionId :: !(Maybe ObjectVersionId) } deriving (Eq, Show) $(deriveFromJSON (aesonDrop 4 camelCase) ''S3ObjectEntity)@@ -81,7 +82,7 @@ data S3EventNotification = S3EventNotification { _senAwsRegion :: !AWS.Region- , _senEventName :: !S3.Event+ , _senEventName :: !Event , _senEventSource :: !Text , _senEventTime :: !UTCTime , _senEventVersion :: !Text@@ -107,3 +108,29 @@ $(makeLenses ''S3EventNotification) type S3Event = RecordsEvent S3EventNotification++-- | Is the event an object creation event+isCreateEvent :: S3EventNotification -> Bool+isCreateEvent e = case _senEventName e of+ S3ObjectCreated -> True+ S3ObjectCreatedCompleteMultipartUpload -> True+ S3ObjectCreatedCopy -> True+ S3ObjectCreatedPost -> True+ S3ObjectCreatedPut -> True+ S3ObjectRemoved -> False+ S3ObjectRemovedDelete -> False+ S3ObjectRemovedDeleteMarkerCreated -> False+ S3ReducedRedundancyLostObject -> False++-- | Is the event an object removal event+isRemoveEvent :: S3EventNotification -> Bool+isRemoveEvent e = case _senEventName e of+ S3ObjectCreated -> False+ S3ObjectCreatedCompleteMultipartUpload -> False+ S3ObjectCreatedCopy -> False+ S3ObjectCreatedPost -> False+ S3ObjectCreatedPut -> False+ S3ObjectRemoved -> True+ S3ObjectRemovedDelete -> True+ S3ObjectRemovedDeleteMarkerCreated -> True+ S3ReducedRedundancyLostObject -> False
src/AWSLambda/Events/SNSEvent.hs view
@@ -1,7 +1,7 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-} {-| Module: AWSLambda.Events.SNSEvent@@ -11,23 +11,26 @@ -} module AWSLambda.Events.SNSEvent where -import Control.Applicative ((<|>))+import Control.Applicative ((<|>))+import Control.Exception.Safe (MonadCatch) import Control.Lens-import Data.Aeson (FromJSON (..), genericParseJSON,- withObject, (.:), (.:?), (.!=))-import Data.Aeson.Casing (aesonDrop, pascalCase)+import Control.Monad.IO.Class+import Data.Aeson+ (FromJSON(..), genericParseJSON, withObject, (.!=), (.:), (.:?))+import Data.Aeson.Casing (aesonDrop, pascalCase) import Data.Aeson.Embedded import Data.Aeson.TextValue-import Data.ByteString (ByteString)-import Data.HashMap.Strict (HashMap)-import Data.Text (Text)-import Data.Time.Clock (UTCTime)-import GHC.Generics (Generic)+import Data.ByteString (ByteString)+import Data.HashMap.Strict (HashMap)+import Data.Text (Text)+import Data.Time.Clock (UTCTime)+import GHC.Generics (Generic) import Network.AWS.Data.Base64-import Network.AWS.Data.Text (FromText)+import Network.AWS.Data.Text (FromText) import AWSLambda.Events.MessageAttribute import AWSLambda.Events.Records+import AWSLambda.Handler (lambdaMain) data SNSMessage message = SNSMessage { _smMessage :: !(TextValue message )@@ -100,3 +103,13 @@ binary :: Traversal' (SNSEvent Base64) ByteString binary = messages . _Base64++-- | Traverse all the messages in an SNS event+traverseSns :: (FromJSON a, Applicative m) => (a -> m ()) -> SNSEvent (Embedded a) -> m ()+traverseSns act = traverseRecords $ \record ->+ act $ record ^. srSns . smMessage . unTextValue . unEmbed++-- | A specialed version of the 'lambdaMain' entry-point+-- for handling individual SNS messages+snsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()+snsMain = lambdaMain . traverseSns
src/AWSLambda/Events/SQSEvent.hs view
@@ -1,7 +1,7 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-} {-| Module: AWSLambda.Events.SQSEvent@@ -9,21 +9,24 @@ -} module AWSLambda.Events.SQSEvent where +import Control.Exception.Safe (MonadCatch) import Control.Lens-import Data.Aeson (FromJSON (..), genericParseJSON)-import Data.Aeson.Casing (aesonPrefix, camelCase)+import Control.Monad.IO.Class+import Data.Aeson (FromJSON(..), genericParseJSON)+import Data.Aeson.Casing (aesonPrefix, camelCase) import Data.Aeson.Embedded import Data.Aeson.TextValue-import Data.ByteString (ByteString)-import Data.HashMap.Strict (HashMap)-import Data.Text (Text)-import GHC.Generics (Generic)+import Data.ByteString (ByteString)+import Data.HashMap.Strict (HashMap)+import Data.Text (Text)+import GHC.Generics (Generic) import Network.AWS.Data.Base64-import Network.AWS.Data.Text (FromText)-import qualified Network.AWS.Types as AWS+import Network.AWS.Data.Text (FromText)+import qualified Network.AWS.Types as AWS import AWSLambda.Events.MessageAttribute import AWSLambda.Events.Records+import AWSLambda.Handler (lambdaMain) data SQSMessage body = SQSMessage { _sqsmMessageId :: !Text@@ -54,3 +57,13 @@ sqsBinary :: Traversal' (SQSEvent Base64) ByteString sqsBinary = sqsMessages . _Base64++-- | Traverse all the messages in an SQS event+traverseSqs :: (FromJSON a, Applicative m) => (a -> m ()) -> SQSEvent (Embedded a) -> m ()+traverseSqs act = traverseRecords $ \record ->+ act $ record ^. sqsmBody . unTextValue . unEmbed++-- | A specialised version of the 'lambdaMain' entry-point+-- for handling individual SQS messages+sqsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()+sqsMain = lambdaMain . traverseSqs
src/AWSLambda/Handler.hs view
@@ -9,15 +9,17 @@ -} module AWSLambda.Handler ( lambdaMain+ , lambdaMainRaw ) where -import Control.Exception.Safe (SomeException(..), displayException, tryAny)-import Control.Monad (forever, void)+import Control.Exception.Safe (MonadCatch, SomeException(..), displayException, tryAny)+import Control.Monad (forever, void)+import Control.Monad.IO.Class -import Data.Aeson ((.=))+import Data.Aeson ((.=)) import qualified Data.Aeson as Aeson -import Data.Typeable (typeOf)+import Data.Typeable (typeOf) import qualified Data.ByteString as ByteString import qualified Data.ByteString.Char8 as Char8@@ -26,13 +28,13 @@ import qualified Data.Text.Encoding as Text import qualified Data.Text.IO as Text -import GHC.IO.Handle (BufferMode(..), hSetBuffering)+import GHC.IO.Handle (BufferMode(..), hSetBuffering) -import Network.HTTP.Client-import Network.HTTP.Types (HeaderName)+import Network.HTTP.Client+import Network.HTTP.Types (HeaderName) -import System.Environment (lookupEnv)-import System.IO (stdout)+import System.Environment (lookupEnv)+import System.IO (stdout) -- | Process incoming events from @serverless-haskell@ using a provided -- function.@@ -84,38 +86,40 @@ -- the command line, and the result of the execution is printed, also as JSON, -- to the standard output. lambdaMain ::- (Aeson.FromJSON event, Aeson.ToJSON res)- => (event -> IO res) -- ^ Function to process the event- -> IO ()+ (Aeson.FromJSON event, Aeson.ToJSON res, MonadCatch m, MonadIO m)+ => (event -> m res) -- ^ Function to process the event+ -> m () lambdaMain act =- runMain $ \input -> do+ lambdaMainRaw $ \input -> do case Aeson.eitherDecode input of Left err -> error err Right event -> do result <- act event pure $ Aeson.encode result --- Process the incoming requests (using the AWS Lambda runtime interface or from the standard input).+-- | Process the incoming requests (using the AWS Lambda runtime interface or from the standard input). -- Also set line buffering on standard output for AWS Lambda so the logs are output in a timely manner.-runMain :: (LBS.ByteString -> IO LBS.ByteString) -> IO ()-runMain act = do- lambdaApiAddress <- lookupEnv lambdaApiAddressEnv+-- This function provides a lower level interface than 'lambdaMain' for users who don't want to use+-- Aeson for encoding and decoding JSON.+lambdaMainRaw :: (MonadCatch m, MonadIO m) => (LBS.ByteString -> m LBS.ByteString) -> m ()+lambdaMainRaw act = do+ lambdaApiAddress <- liftIO $ lookupEnv lambdaApiAddressEnv case lambdaApiAddress of Just address -> do- hSetBuffering stdout LineBuffering- manager <- newManager defaultManagerSettings+ liftIO $ hSetBuffering stdout LineBuffering+ manager <- liftIO $ newManager defaultManagerSettings forever $ do- invocation <- httpLbs (invocationRequest address) manager+ invocation <- liftIO $ httpLbs (invocationRequest address) manager let input = responseBody invocation let requestId = responseRequestId invocation resultOrError <- tryAny $ act input case resultOrError of- Right result -> void $ httpNoBody (resultRequest address requestId result) manager- Left exception -> void $ httpNoBody (errorRequest address requestId exception) manager+ Right result -> liftIO $ void $ httpNoBody (resultRequest address requestId result) manager+ Left exception -> liftIO $ void $ httpNoBody (errorRequest address requestId exception) manager Nothing -> do- input <- LBS.fromStrict <$> ByteString.getLine+ input <- liftIO $ LBS.fromStrict <$> ByteString.getLine result <- act input- Text.putStrLn $ Text.decodeUtf8 $ LBS.toStrict result+ liftIO $ Text.putStrLn $ Text.decodeUtf8 $ LBS.toStrict result lambdaApiAddressEnv :: String lambdaApiAddressEnv = "AWS_LAMBDA_RUNTIME_API"