{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}

{-|
Module: AWSLambda.Events.SNSEvent
Description: Types for SNS Lambda events

Based on https://github.com/aws/aws-lambda-dotnet/tree/master/Libraries/src/Amazon.Lambda.SNSEvents
-}
module AWSLambda.Events.SNSEvent where

import           Control.Applicative ((<|>))
import           Control.Exception.Safe (MonadCatch)
import           Control.Lens
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           Network.AWS.Data.Base64
import           Network.AWS.Data.Text (FromText)

import           AWSLambda.Events.MessageAttribute
import           AWSLambda.Events.Records
import           AWSLambda.Handler (lambdaMain)

data SNSMessage message = SNSMessage
  { SNSMessage message -> TextValue message
_smMessage           :: !(TextValue message )
  , SNSMessage message -> HashMap Text MessageAttribute
_smMessageAttributes :: !(HashMap Text MessageAttribute)
  , SNSMessage message -> Text
_smMessageId         :: !Text
  , SNSMessage message -> Text
_smSignature         :: !Text
  , SNSMessage message -> Text
_smSignatureVersion  :: !Text
  , SNSMessage message -> Text
_smSigningCertUrl    :: !Text
  , SNSMessage message -> Text
_smSubject           :: !Text
  , SNSMessage message -> UTCTime
_smTimestamp         :: !UTCTime
  , SNSMessage message -> Text
_smTopicArn          :: !Text
  , SNSMessage message -> Text
_smType              :: !Text
  , SNSMessage message -> Text
_smUnsubscribeUrl    :: !Text
  } deriving (SNSMessage message -> SNSMessage message -> Bool
(SNSMessage message -> SNSMessage message -> Bool)
-> (SNSMessage message -> SNSMessage message -> Bool)
-> Eq (SNSMessage message)
forall message.
Eq message =>
SNSMessage message -> SNSMessage message -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SNSMessage message -> SNSMessage message -> Bool
$c/= :: forall message.
Eq message =>
SNSMessage message -> SNSMessage message -> Bool
== :: SNSMessage message -> SNSMessage message -> Bool
$c== :: forall message.
Eq message =>
SNSMessage message -> SNSMessage message -> Bool
Eq, Int -> SNSMessage message -> ShowS
[SNSMessage message] -> ShowS
SNSMessage message -> String
(Int -> SNSMessage message -> ShowS)
-> (SNSMessage message -> String)
-> ([SNSMessage message] -> ShowS)
-> Show (SNSMessage message)
forall message. Show message => Int -> SNSMessage message -> ShowS
forall message. Show message => [SNSMessage message] -> ShowS
forall message. Show message => SNSMessage message -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SNSMessage message] -> ShowS
$cshowList :: forall message. Show message => [SNSMessage message] -> ShowS
show :: SNSMessage message -> String
$cshow :: forall message. Show message => SNSMessage message -> String
showsPrec :: Int -> SNSMessage message -> ShowS
$cshowsPrec :: forall message. Show message => Int -> SNSMessage message -> ShowS
Show, (forall x. SNSMessage message -> Rep (SNSMessage message) x)
-> (forall x. Rep (SNSMessage message) x -> SNSMessage message)
-> Generic (SNSMessage message)
forall x. Rep (SNSMessage message) x -> SNSMessage message
forall x. SNSMessage message -> Rep (SNSMessage message) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall message x. Rep (SNSMessage message) x -> SNSMessage message
forall message x. SNSMessage message -> Rep (SNSMessage message) x
$cto :: forall message x. Rep (SNSMessage message) x -> SNSMessage message
$cfrom :: forall message x. SNSMessage message -> Rep (SNSMessage message) x
Generic)

-- When a lambda is triggered directly off of an SNS topic,
-- the SNS message contains message attributes and the URI
-- fields are cased as `SigningCertUrl` and `UnsubscribeUrl`.
-- When an SNS message is embedded in an SQS event,
-- the SNS message changes in two ways; `MessageAttributes`
-- is not present and the casing for the URI fields becomes
-- `SigningCertURL` and `UnsubscribeURL`.
-- For these reasons we must hand-roll the `FromJSON` instance.
instance FromText message => FromJSON (SNSMessage message) where
  parseJSON :: Value -> Parser (SNSMessage message)
parseJSON = String
-> (Object -> Parser (SNSMessage message))
-> Value
-> Parser (SNSMessage message)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SNSMessage'" ((Object -> Parser (SNSMessage message))
 -> Value -> Parser (SNSMessage message))
-> (Object -> Parser (SNSMessage message))
-> Value
-> Parser (SNSMessage message)
forall a b. (a -> b) -> a -> b
$ \Object
o ->
    TextValue message
-> HashMap Text MessageAttribute
-> Text
-> Text
-> Text
-> Text
-> Text
-> UTCTime
-> Text
-> Text
-> Text
-> SNSMessage message
forall message.
TextValue message
-> HashMap Text MessageAttribute
-> Text
-> Text
-> Text
-> Text
-> Text
-> UTCTime
-> Text
-> Text
-> Text
-> SNSMessage message
SNSMessage
      (TextValue message
 -> HashMap Text MessageAttribute
 -> Text
 -> Text
 -> Text
 -> Text
 -> Text
 -> UTCTime
 -> Text
 -> Text
 -> Text
 -> SNSMessage message)
-> Parser (TextValue message)
-> Parser
     (HashMap Text MessageAttribute
      -> Text
      -> Text
      -> Text
      -> Text
      -> Text
      -> UTCTime
      -> Text
      -> Text
      -> Text
      -> SNSMessage message)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser (TextValue message)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Message"
      Parser
  (HashMap Text MessageAttribute
   -> Text
   -> Text
   -> Text
   -> Text
   -> Text
   -> UTCTime
   -> Text
   -> Text
   -> Text
   -> SNSMessage message)
-> Parser (HashMap Text MessageAttribute)
-> Parser
     (Text
      -> Text
      -> Text
      -> Text
      -> Text
      -> UTCTime
      -> Text
      -> Text
      -> Text
      -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe (HashMap Text MessageAttribute))
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"MessageAttributes" Parser (Maybe (HashMap Text MessageAttribute))
-> HashMap Text MessageAttribute
-> Parser (HashMap Text MessageAttribute)
forall a. Parser (Maybe a) -> a -> Parser a
.!= HashMap Text MessageAttribute
forall a. Monoid a => a
mempty
      Parser
  (Text
   -> Text
   -> Text
   -> Text
   -> Text
   -> UTCTime
   -> Text
   -> Text
   -> Text
   -> SNSMessage message)
-> Parser Text
-> Parser
     (Text
      -> Text
      -> Text
      -> Text
      -> UTCTime
      -> Text
      -> Text
      -> Text
      -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"MessageId"
      Parser
  (Text
   -> Text
   -> Text
   -> Text
   -> UTCTime
   -> Text
   -> Text
   -> Text
   -> SNSMessage message)
-> Parser Text
-> Parser
     (Text
      -> Text
      -> Text
      -> UTCTime
      -> Text
      -> Text
      -> Text
      -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Signature"
      Parser
  (Text
   -> Text
   -> Text
   -> UTCTime
   -> Text
   -> Text
   -> Text
   -> SNSMessage message)
-> Parser Text
-> Parser
     (Text
      -> Text -> UTCTime -> Text -> Text -> Text -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"SignatureVersion"
      Parser
  (Text
   -> Text -> UTCTime -> Text -> Text -> Text -> SNSMessage message)
-> Parser Text
-> Parser
     (Text -> UTCTime -> Text -> Text -> Text -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> do Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"SigningCertUrl" Parser Text -> Parser Text -> Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"SigningCertURL"
      Parser
  (Text -> UTCTime -> Text -> Text -> Text -> SNSMessage message)
-> Parser Text
-> Parser (UTCTime -> Text -> Text -> Text -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Subject"
      Parser (UTCTime -> Text -> Text -> Text -> SNSMessage message)
-> Parser UTCTime
-> Parser (Text -> Text -> Text -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser UTCTime
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Timestamp"
      Parser (Text -> Text -> Text -> SNSMessage message)
-> Parser Text -> Parser (Text -> Text -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"TopicArn"
      Parser (Text -> Text -> SNSMessage message)
-> Parser Text -> Parser (Text -> SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Type"
      Parser (Text -> SNSMessage message)
-> Parser Text -> Parser (SNSMessage message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> do Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"UnsubscribeUrl" Parser Text -> Parser Text -> Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object
o Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"UnsubscribeURL"

$(makeLenses ''SNSMessage)

data SNSRecord message = SNSRecord
  { SNSRecord message -> Text
_srEventVersion         :: !Text
  , SNSRecord message -> Text
_srEventSubscriptionArn :: !Text
  , SNSRecord message -> Text
_srEventSource          :: !Text
  , SNSRecord message -> SNSMessage message
_srSns                  :: !(SNSMessage message)
  } deriving (SNSRecord message -> SNSRecord message -> Bool
(SNSRecord message -> SNSRecord message -> Bool)
-> (SNSRecord message -> SNSRecord message -> Bool)
-> Eq (SNSRecord message)
forall message.
Eq message =>
SNSRecord message -> SNSRecord message -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SNSRecord message -> SNSRecord message -> Bool
$c/= :: forall message.
Eq message =>
SNSRecord message -> SNSRecord message -> Bool
== :: SNSRecord message -> SNSRecord message -> Bool
$c== :: forall message.
Eq message =>
SNSRecord message -> SNSRecord message -> Bool
Eq, Int -> SNSRecord message -> ShowS
[SNSRecord message] -> ShowS
SNSRecord message -> String
(Int -> SNSRecord message -> ShowS)
-> (SNSRecord message -> String)
-> ([SNSRecord message] -> ShowS)
-> Show (SNSRecord message)
forall message. Show message => Int -> SNSRecord message -> ShowS
forall message. Show message => [SNSRecord message] -> ShowS
forall message. Show message => SNSRecord message -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SNSRecord message] -> ShowS
$cshowList :: forall message. Show message => [SNSRecord message] -> ShowS
show :: SNSRecord message -> String
$cshow :: forall message. Show message => SNSRecord message -> String
showsPrec :: Int -> SNSRecord message -> ShowS
$cshowsPrec :: forall message. Show message => Int -> SNSRecord message -> ShowS
Show, (forall x. SNSRecord message -> Rep (SNSRecord message) x)
-> (forall x. Rep (SNSRecord message) x -> SNSRecord message)
-> Generic (SNSRecord message)
forall x. Rep (SNSRecord message) x -> SNSRecord message
forall x. SNSRecord message -> Rep (SNSRecord message) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall message x. Rep (SNSRecord message) x -> SNSRecord message
forall message x. SNSRecord message -> Rep (SNSRecord message) x
$cto :: forall message x. Rep (SNSRecord message) x -> SNSRecord message
$cfrom :: forall message x. SNSRecord message -> Rep (SNSRecord message) x
Generic)

instance FromText message => FromJSON (SNSRecord message) where
  parseJSON :: Value -> Parser (SNSRecord message)
parseJSON = Options -> Value -> Parser (SNSRecord message)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (Options -> Value -> Parser (SNSRecord message))
-> Options -> Value -> Parser (SNSRecord message)
forall a b. (a -> b) -> a -> b
$ Int -> ShowS -> Options
aesonDrop Int
3 ShowS
pascalCase

$(makeLenses ''SNSRecord)

-- | SNSEvent.
-- The 'message' type is parameterised. To treat it as a text value
-- use @SNSEvent Text@.
-- To extract an embedded event object use the 'Embedded' type.
-- E.g. @SNSEvent (Embedded S3Event)@ will treat the message
-- as an embedded S3Event.
-- To extract embedded Base64 encoded binary use
-- @SNSEvent Base64@
type SNSEvent message = RecordsEvent (SNSRecord message)

-- | A Traversal to get messages from an SNSEvent
messages :: Traversal (SNSEvent message) (SNSEvent message') message message'
messages :: (message -> f message')
-> SNSEvent message -> f (SNSEvent message')
messages = ([SNSRecord message] -> f [SNSRecord message'])
-> SNSEvent message -> f (SNSEvent message')
forall a1 a2. Iso (RecordsEvent a1) (RecordsEvent a2) [a1] [a2]
reRecords (([SNSRecord message] -> f [SNSRecord message'])
 -> SNSEvent message -> f (SNSEvent message'))
-> ((message -> f message')
    -> [SNSRecord message] -> f [SNSRecord message'])
-> (message -> f message')
-> SNSEvent message
-> f (SNSEvent message')
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SNSRecord message -> f (SNSRecord message'))
-> [SNSRecord message] -> f [SNSRecord message']
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((SNSRecord message -> f (SNSRecord message'))
 -> [SNSRecord message] -> f [SNSRecord message'])
-> ((message -> f message')
    -> SNSRecord message -> f (SNSRecord message'))
-> (message -> f message')
-> [SNSRecord message]
-> f [SNSRecord message']
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SNSMessage message -> f (SNSMessage message'))
-> SNSRecord message -> f (SNSRecord message')
forall message message.
Lens
  (SNSRecord message)
  (SNSRecord message)
  (SNSMessage message)
  (SNSMessage message)
srSns ((SNSMessage message -> f (SNSMessage message'))
 -> SNSRecord message -> f (SNSRecord message'))
-> ((message -> f message')
    -> SNSMessage message -> f (SNSMessage message'))
-> (message -> f message')
-> SNSRecord message
-> f (SNSRecord message')
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TextValue message -> f (TextValue message'))
-> SNSMessage message -> f (SNSMessage message')
forall message message.
Lens
  (SNSMessage message)
  (SNSMessage message)
  (TextValue message)
  (TextValue message)
smMessage ((TextValue message -> f (TextValue message'))
 -> SNSMessage message -> f (SNSMessage message'))
-> ((message -> f message')
    -> TextValue message -> f (TextValue message'))
-> (message -> f message')
-> SNSMessage message
-> f (SNSMessage message')
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (message -> f message')
-> TextValue message -> f (TextValue message')
forall a1 a2. Iso (TextValue a1) (TextValue a2) a1 a2
unTextValue

-- | A Traversal to get embedded JSON values from an SNSEvent
embedded :: Traversal (SNSEvent (Embedded v)) (SNSEvent (Embedded v')) v v'
embedded :: (v -> f v') -> SNSEvent (Embedded v) -> f (SNSEvent (Embedded v'))
embedded = (Embedded v -> f (Embedded v'))
-> SNSEvent (Embedded v) -> f (SNSEvent (Embedded v'))
forall message message'.
Traversal (SNSEvent message) (SNSEvent message') message message'
messages ((Embedded v -> f (Embedded v'))
 -> SNSEvent (Embedded v) -> f (SNSEvent (Embedded v')))
-> ((v -> f v') -> Embedded v -> f (Embedded v'))
-> (v -> f v')
-> SNSEvent (Embedded v)
-> f (SNSEvent (Embedded v'))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (v -> f v') -> Embedded v -> f (Embedded v')
forall a1 a2. Iso (Embedded a1) (Embedded a2) a1 a2
unEmbed

binary :: Traversal' (SNSEvent Base64) ByteString
binary :: (ByteString -> f ByteString)
-> SNSEvent Base64 -> f (SNSEvent Base64)
binary = (Base64 -> f Base64) -> SNSEvent Base64 -> f (SNSEvent Base64)
forall message message'.
Traversal (SNSEvent message) (SNSEvent message') message message'
messages ((Base64 -> f Base64) -> SNSEvent Base64 -> f (SNSEvent Base64))
-> ((ByteString -> f ByteString) -> Base64 -> f Base64)
-> (ByteString -> f ByteString)
-> SNSEvent Base64
-> f (SNSEvent Base64)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> f ByteString) -> Base64 -> f Base64
Iso' Base64 ByteString
_Base64

-- | Traverse an SNS message
traverseSnsMessage :: (FromJSON a, Applicative m) => (a -> m ()) -> SNSMessage (Embedded a) -> m ()
traverseSnsMessage :: (a -> m ()) -> SNSMessage (Embedded a) -> m ()
traverseSnsMessage a -> m ()
act SNSMessage (Embedded a)
message =
    a -> m ()
act (a -> m ()) -> a -> m ()
forall a b. (a -> b) -> a -> b
$ SNSMessage (Embedded a)
message SNSMessage (Embedded a)
-> Getting a (SNSMessage (Embedded a)) a -> a
forall s a. s -> Getting a s a -> a
^. (TextValue (Embedded a) -> Const a (TextValue (Embedded a)))
-> SNSMessage (Embedded a) -> Const a (SNSMessage (Embedded a))
forall message message.
Lens
  (SNSMessage message)
  (SNSMessage message)
  (TextValue message)
  (TextValue message)
smMessage ((TextValue (Embedded a) -> Const a (TextValue (Embedded a)))
 -> SNSMessage (Embedded a) -> Const a (SNSMessage (Embedded a)))
-> ((a -> Const a a)
    -> TextValue (Embedded a) -> Const a (TextValue (Embedded a)))
-> Getting a (SNSMessage (Embedded a)) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Embedded a -> Const a (Embedded a))
-> TextValue (Embedded a) -> Const a (TextValue (Embedded a))
forall a1 a2. Iso (TextValue a1) (TextValue a2) a1 a2
unTextValue ((Embedded a -> Const a (Embedded a))
 -> TextValue (Embedded a) -> Const a (TextValue (Embedded a)))
-> ((a -> Const a a) -> Embedded a -> Const a (Embedded a))
-> (a -> Const a a)
-> TextValue (Embedded a)
-> Const a (TextValue (Embedded a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Const a a) -> Embedded a -> Const a (Embedded a)
forall a1 a2. Iso (Embedded a1) (Embedded a2) a1 a2
unEmbed

-- | Traverse all the messages in an SNS event
traverseSns :: (FromJSON a, Applicative m) => (a -> m ()) -> SNSEvent (Embedded a) -> m ()
traverseSns :: (a -> m ()) -> SNSEvent (Embedded a) -> m ()
traverseSns a -> m ()
act = (SNSRecord (Embedded a) -> m ()) -> SNSEvent (Embedded a) -> m ()
forall (m :: * -> *) a.
Applicative m =>
(a -> m ()) -> RecordsEvent a -> m ()
traverseRecords ((SNSRecord (Embedded a) -> m ()) -> SNSEvent (Embedded a) -> m ())
-> (SNSRecord (Embedded a) -> m ())
-> SNSEvent (Embedded a)
-> m ()
forall a b. (a -> b) -> a -> b
$ \SNSRecord (Embedded a)
record ->
    a -> m ()
act (a -> m ()) -> a -> m ()
forall a b. (a -> b) -> a -> b
$ SNSRecord (Embedded a)
record SNSRecord (Embedded a) -> Getting a (SNSRecord (Embedded a)) a -> a
forall s a. s -> Getting a s a -> a
^. (SNSMessage (Embedded a) -> Const a (SNSMessage (Embedded a)))
-> SNSRecord (Embedded a) -> Const a (SNSRecord (Embedded a))
forall message message.
Lens
  (SNSRecord message)
  (SNSRecord message)
  (SNSMessage message)
  (SNSMessage message)
srSns ((SNSMessage (Embedded a) -> Const a (SNSMessage (Embedded a)))
 -> SNSRecord (Embedded a) -> Const a (SNSRecord (Embedded a)))
-> ((a -> Const a a)
    -> SNSMessage (Embedded a) -> Const a (SNSMessage (Embedded a)))
-> Getting a (SNSRecord (Embedded a)) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TextValue (Embedded a) -> Const a (TextValue (Embedded a)))
-> SNSMessage (Embedded a) -> Const a (SNSMessage (Embedded a))
forall message message.
Lens
  (SNSMessage message)
  (SNSMessage message)
  (TextValue message)
  (TextValue message)
smMessage ((TextValue (Embedded a) -> Const a (TextValue (Embedded a)))
 -> SNSMessage (Embedded a) -> Const a (SNSMessage (Embedded a)))
-> ((a -> Const a a)
    -> TextValue (Embedded a) -> Const a (TextValue (Embedded a)))
-> (a -> Const a a)
-> SNSMessage (Embedded a)
-> Const a (SNSMessage (Embedded a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Embedded a -> Const a (Embedded a))
-> TextValue (Embedded a) -> Const a (TextValue (Embedded a))
forall a1 a2. Iso (TextValue a1) (TextValue a2) a1 a2
unTextValue ((Embedded a -> Const a (Embedded a))
 -> TextValue (Embedded a) -> Const a (TextValue (Embedded a)))
-> ((a -> Const a a) -> Embedded a -> Const a (Embedded a))
-> (a -> Const a a)
-> TextValue (Embedded a)
-> Const a (TextValue (Embedded a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Const a a) -> Embedded a -> Const a (Embedded a)
forall a1 a2. Iso (Embedded a1) (Embedded a2) a1 a2
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 :: (a -> m ()) -> m ()
snsMain = (SNSEvent (Embedded a) -> m ()) -> m ()
forall event res (m :: * -> *).
(FromJSON event, ToJSON res, MonadCatch m, MonadIO m) =>
(event -> m res) -> m ()
lambdaMain ((SNSEvent (Embedded a) -> m ()) -> m ())
-> ((a -> m ()) -> SNSEvent (Embedded a) -> m ())
-> (a -> m ())
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> m ()) -> SNSEvent (Embedded a) -> m ()
forall a (m :: * -> *).
(FromJSON a, Applicative m) =>
(a -> m ()) -> SNSEvent (Embedded a) -> m ()
traverseSns