h$      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                                                                      Function transformers that can be used to adapt the base runtime into other useful interfaces.(c) Nike, Inc., 2018BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;"ehal!Upgrades a handler that uses the  monad with an % inside into a base runtime handler.%In the example below, we reconstruct ! without actually using it. The # expects a handler in the form of (event -> ReaderT LambdaContext IO result0 (ignoring constraints). By composing it with e? we get a new runtime which expects a function in the form of #LambdaContext -> event -> IO result which matches that of  myHandler.  {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (readerTRuntime) import AWS.Lambda.Combinators (withIOInterface) import Data.Aeson (FromJSON) import Data.Text (unpack) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Named -> IO (Either String String) myHandler (LambdaContext { functionName }) (Named { name }) = do greeting <- getEnv "GREETING" return $ if name == "World" then Right $ "Hello, World from " ++ unpack functionName ++ "!" else Left "Can only greet the world." main :: IO () main = (readerTRuntime . withIOInterface) myHandler fhal Upgrades a handler that accepts + and an event to return a value inside an $ inside into a base runtime handler.%In the example below, we reconstruct " without actually using it. The # expects a handler in the form of (event -> ReaderT LambdaContext IO result/ (ignoring constraints). By composing it with f? we get a new runtime which expects a function in the form of .LambdaContext -> event -> Either String result which matches that of  myHandler.  {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (readerTRuntime) import AWS.Lambda.Combinators (withFallibleInterface) import Data.Aeson (FromJSON) import Data.Text (unpack) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Named -> Either String String myHandler (LambdaContext { functionName }) (Named { name }) = if name == "World" then Right $ "Hello, World from " ++ unpack functionName ++ "!" else Left "Can only greet the world." main :: IO () main = (readerTRuntime . withFallibleInterface) myHandler ghalThis combinator takes a handler that accepts both an event and  and converts it into a handler that is compatible with the base monadic runtime.%In the example below, we reconstruct " without actually using it. The # expects a handler in the form of (event -> ReaderT LambdaContext IO result/ (ignoring constraints). By composing it with g? we get a new runtime which expects a function in the form of  LambdaContext -> event -> result which matches that of  myHandler.  {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (readerTRuntime) import AWS.Lambda.Combinators (withPureInterface) import Data.Aeson (FromJSON) import Data.Text (unpack) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Named -> String myHandler (LambdaContext { functionName }) (Named { name }) = "Hello, " ++ name ++ " from " ++ unpack functionName ++ "!" main :: IO () main = (readerTRuntime . withPureInterface) myHandler hhal An alias of 0, this upgrades a handler that does not accept 0 as its first curried argument to one that does.This allows us to use other combinators to construct a lambda runtime that accepts a handler that ignores .%In the example below, we reconstruct ! without actually using it. The # expects a handler in the form of (event -> ReaderT LambdaContext IO result/ (ignoring constraints). By composing it with g? we get a new runtime which expects a function in the form of  LambdaContext -> event -> result$, And then finally we also compose h so it accepts the signature event -> result which matches that of  myHandler.  {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Runtime (readerTRuntime) import AWS.Lambda.Combinators (withPureInterface, withoutContext) import Data.Aeson (FromJSON) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Named -> String myHandler (Named { name }) = "Hello, " ++ name main :: IO () main = (readerTRuntime . withPureInterface . withoutContext) myHandler ihalThis modifies a function to accept a JSON AST (Value), instead of its JSON parsable input. It also assumes that the JSON AST passed in will ALWAYS be convertable into the original input type.This allows us to write handlers of the types we're interested in, but then map back to the "native" handler that is only guaranteed JSON (but not necessarily in a useful or restricted structure)./This is essentially the glue that converts the AWS.Lambda.Runtime.Value to (the more standard) AWS.Lambda.Runtime. While both export a , the difference is that the Value Runtime makes no attempt to convert the JSON AST, the standard Runtime does.Rarely would this function be used directly, and you wouldn't want to use it at all, (directly or indirectly via Runtime runtimes), if you wanted to act on a failure to convert the JSON AST sent to the Lambda.efghiefghi/AWS Lambda Context classes and related methods.(c) Nike, Inc., 2018BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #%056789;#2halHelper for using arbitrary monads with only the LambdaContext in its Reader!jklmnvopqrstuwxyz{|}~!}~yz{|lmnvopqrstuwxjk2Data types that represent typical lambda responses(c) Nike, Inc., 2019BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;+UhalFor ensuring that there were no API Gateway custom authorizer values (this is not likely to be useful, you probably want )hal1For ignoring API Gateway custom authorizer valueshalThis type is for representing events that come from API Gateway via the Lambda Proxy integration (forwarding HTTP data directly, rather than a custom integration). It will automatically decode the event that comes in.The  notably has one parameter for the type of information returned by the API Gateway's custom authorizer (if applicable). This type must also implement FromJSON so that it can be decoded. If you do not expect this data to be populated we recommended using the = type exported from this module (which is just an alias for ). If there _must not_ be authorizer populated (this is unlikely) then use the  type.  {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE DuplicateRecordFields #-} module Main where import AWS.Lambda.Runtime (pureRuntime) import AWS.Lambda.Events.ApiGateway.ProxyRequest (ProxyRequest(..), NoAuthorizer) import AWS.Lambda.Events.ApiGateway.ProxyResponse (ProxyResponse(..), textPlain, forbidden403, ok200) myHandler :: ProxyRequest NoAuthorizer -> ProxyResponse myHandler ProxyRequest { httpMethod = "GET", path = "/say_hello" } = ProxyResponse { status = ok200 , body = textPlain "Hello" , headers = mempty , multiValueHeaders = mempty } myHandler _ = ProxyResponse { status = forbidden403 , body = textPlain "Forbidden" , headers = mempty , multiValueHeaders = mempty } main :: IO () main = pureRuntime myHandler halhal--12Data types that represent typical lambda responses(c) Nike, Inc., 2019BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;7 halA response returned to an API Gateway when using the HTTP Lambda Proxy integration. ContentType will be set based on the ProxyBody (recommended) if a value is not present in the headers field.This type can be constructed explicity or via the smart constructor 0. Headers can then be added incrementally with  or . The smart constructor pattern is recommended because it avoids some of the awkwardness of dealing with the multiValueHeaders field's type. {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE OverloadedStrings #-} module Main where import AWS.Lambda.Runtime (pureRuntime) import AWS.Lambda.Events.ApiGateway.ProxyRequest (ProxyRequest(..), NoAuthorizer) import AWS.Lambda.Events.ApiGateway.ProxyResponse (ProxyResponse(..), textPlain, forbidden403, ok200, response) myHandler :: ProxyRequest NoAuthorizer -> ProxyResponse myHandler ProxyRequest { httpMethod = "GET", path = "/say_hello" } = -- Smart Constructor and added header (recommended) addHeader "My-Custom-Header" Value $ response ok200 $ textPlain "Hello" myHandler _ = -- Explicit Construction (not recommended) ProxyResponse { status = forbidden403 , body = textPlain "Forbidden" , multiValueHeaders = fromList [(mk "My-Custom-Header", ["Other Value])] } main :: IO () main = pureRuntime myHandler halType that represents the body returned to an API Gateway when using HTTP Lambda Proxy integration. It is highly recommended that you do not use this type directly, and instead use the smart constructors exposed such as , , and . These make sure that the base64 encodings work transparently.halSmart constructor for creating a ProxyResponse from a status and a bodyhalAdd a header to the ProxyResponse. If there was already a value for this header, this one is added, meaning the response will include multiple copies of this header (valid by the HTTP spec). This does NOT replace any previous headers or their values.halSet a header to the ProxyResponse. If there were any previous values for this header they are  all replaced by this new value.halSmart constructor for creating a ProxyBody with an arbitrary ByteString of the chosen content type. Use this smart constructor to avoid invalid JSON representations of binary data.=From here it is easy to make more specific body constructors: imageGif :: ByteString -> ProxyBody imageGif = genericBinary "image/gif" imageJpeg :: ByteString -> ProxyBody imageJpeg = genericBinary "image/jpeg" hal5Smart constructor for creating a simple body of text.hal5Smart constructor for creating a simple body of JSON.hal  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`dcba  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`dcba1,Data types for consuming EventBridge events.BSD3stableNone #%0156789;C hal,Represents an event from Amazon EventBridge.See the  https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events.htmlAWS documentation5 for information about events, and a sample payload.hal2By default, this is set to 0 (zero) in all events.halA Version 4 UUID that's generated for every event. You can use id to trace events as they move through rules to targets.halIdentifies, in combination with the source field, the fields and values that appear in the detail field.Events that are delivered by CloudTrail have AWS API Call via CloudTrail as the value for detail-type.NOTE: This is called  detail-type in the AWS payload.halIdentifies the service that generated the event. All events that come from AWS services begin with "aws." Customer-generated events can have any value here, as long as it doesn't begin with "aws." We recommend the use of Java package-name style reverse domain-name strings.To find the correct value for source for an AWS service, see The condition keys table, select a service from the list, and look for the service prefix. For example, the source value for Amazon CloudFront is aws.cloudfront.hal/The 12-digit number identifying an AWS account.halThe event timestamp, which can be specified by the service originating the event. If the event spans a time interval, the service can report the start time, so this value might be before the time the event is received.hal5Identifies the AWS Region where the event originated.halA JSON array that contains ARNs that identify resources that are involved in the event. The service generating the event determines whether to include these ARNs. For example, Amazon EC2 instance state-changes include Amazon EC2 instance ARNs, Auto Scaling events include ARNs for both instances and Auto Scaling groups, but API calls with AWS CloudTrail do not include resource ARNs.halA JSON object that contains information about the event. The service generating the event determines the content of this field. The detail content can be as simple as two fields. AWS API call events have detail objects with approximately 50 fields nested several levels deep.halConvenience alias for events of unknown type. Most of the time you will want to define or use a data type Foo representing the detail payload, and write an instance FromJSON Foo to get instance FromJSON ( Foo) . See the &AWS.Lambda.Events.EventBridge.Detail.*+ modules for data types which you can use.  Data types for AWS Systems Manager Parameter Store Change events.BSD3stableNone #%0156789;GhalAWS provides no schema for the "type" field, but these are the only three types of parameters you can create in Parameter Store.halAWS provides no schema for the  "operation" field, so we provide a newtype wrapper and pattern synonyms which we think are complete, based on AWS documentation.halA Parameter Store Change event from Amazon EventBridge. This structure corresponds to the contents of the "detail" field of an EventBridge event, so a full payload from EventBridge can be parsed into a  ParameterStoreChange.+Sample event payloads are provided in the  https://docs.aws.amazon.com/systems-manager/latest/userguide/monitoring-systems-manager-event-examples.html#SSM-Parameter-Store-event-typesAWS Systems Manager User Guide.&Data types for consuming Kafka events.BSD3stableNone #%056789;>N halKafka timestamp types, derived from the Java client's enum at: https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/common/record/TimestampType.javahalAWS serialises record headers to JSON as an array of objects. From their docs: "headers":[{"headerKey":[104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]}] Note: Record -> Maybe (Record' a) hal4NOTE: there can be multiple headers for a given key.halConvenience alias: most of the time you will parse the records straight into some app-specific structure.hal  "aws:kafka"hal SelfManagedKafkahalRepresents an event from either Amazon MSK or a self-managed Apache Kafka cluster, as the payloads are very similar.The  and  instances on $ perform base64 conversion for you.See the  Only present when using the "Amazon MSK" event source mapping.halThe map's keys look like !"${topicName}-${partitionNumber}"hal$Encodes keys and values into base64.hal6Decodes base64-encoded keys and values, where present.&Data types for working with S3 events.(c) Nike, Inc., 2019BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;Ohal7S3 object representations based on event type received.4Currently only Put/Delete events can trigger Lambdashal/Event data sent by S3 when triggering a Lambda.** 'Data types for working with SQS events.(c) Nike, Inc., 2019BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;QJ Internal hal helper methods.(c) Nike, Inc., 2018BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comunstableNone #056789;RI Internal HTTP related machinery for talking to the AWS Lambda Custom Runtime interface.(c) Nike, Inc., 2018BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;Sw HTTP related machinery for talking to the AWS Lambda Custom Runtime interface.(c) Nike, Inc., 2018BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;T\ Runtime methods useful when constructing Haskell handlers for the AWS Lambda Custom Runtime.(c) Nike, Inc., 2018BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;? halFor any monad that supports  and catch. Useful if you need caching behaviours or are comfortable manipulating monad transformers, and want full control over your monadic interface.7In a future version, this function will be renamed to mRuntimeWithContext, (after the deprecated function is removed).%A contrived example, that parses the  argument directly instead of using the higher-level features in AWS.Lambda.Runtime.Value: {-# LANGUAGE DeriveAnyClass, DeriveGeneric, NamedFieldPuns #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (mRuntimeWithContext') import Control.Monad.Catch (Exception, throwM) import Control.Monad.State.Lazy (StateT, evalStateT, get, put) import Control.Monad.Trans (liftIO) import Data.Aeson (FromJSON, Result(..), Value, fromJSON) import Data.Text (unpack) import System.Environment (getEnv) import GHC.Generics (Generic) data AesonParseException = AesonParseException String deriving (Show, Exception) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Value -> StateT Int IO String myHandler LambdaContext { functionName } value = do greeting <- liftIO $ getEnv "GREETING" Named { name } <- case fromJSON value of Error err -> throwM $ AesonParseException err Success named -> pure named greetingCount <- get put $ greetingCount + 1 return $ greeting ++ name ++ " (" ++ show greetingCount ++ ") from " ++ unpack functionName ++ "!" main :: IO () main = evalStateT (mRuntimeWithContext' myHandler) 0 halFor any monad that supports  and catch. Useful if you need caching behaviours or are comfortable manipulating monad transformers, want full control over your monadic interface, but don't need to inspect the l.%A contrived example, that parses the  argument directly instead of using the higher-level features in AWS.Lambda.Runtime.Value: {-# LANGUAGE DeriveAnyClass, DeriveGeneric, NamedFieldPuns #-} module Main where import AWS.Lambda.Runtime (mRuntime) import Control.Monad.Catch (Exception, throwM) import Control.Monad.State.Lazy (StateT, evalStateT, get, put) import Control.Monad.Trans (liftIO) import Data.Aeson (FromJSON, Result(..), Value, fromJSON) import System.Environment (getEnv) import GHC.Generics (Generic) data AesonParseException = AesonParseException String deriving (Show, Exception) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Value -> StateT Int IO String myHandler value = do greeting <- liftIO $ getEnv "GREETING" Named { name } <- case fromJSON value of Error err -> throwM $ AesonParseException err Success named -> pure named greetingCount <- get put $ greetingCount + 1 return $ greeting ++ name ++ " (" ++ show greetingCount ++ ")!" main :: IO () main = evalStateT (mRuntime myHandler) 0 hal:For any monad that supports IO/catch/Reader LambdaContext. StateT Int (ReaderT LambdaContext IO) String myHandler jsonAst = case parseMaybe parseJSON jsonAst of Nothing -> return $ "My name is HAL, what's yours?" Just Named { name } -> do LambdaContext { functionName } <- ask greeting <- liftIO $ getEnv "GREETING" greetingCount <- get put $ greetingCount + 1 return $ greeting ++ name ++ " (" ++ show greetingCount ++ ") from " ++ unpack functionName ++ "!" main :: IO () main = runReaderTLambdaContext (evalStateT (mRuntimeWithContext myHandler) 0) halFor functions that can read the lambda context and use IO within the same monad.Use this for handlers that need any form of side-effect such as reading environment variables or making network requests, and prefer to access the AWS Lambda Context in the same monad. However, do not use this runtime if you need stateful (caching) behaviors. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (readerTRuntime) import Control.Monad.Reader (ReaderT, ask) import Control.Monad.Trans (liftIO) import Data.Aeson (Value, FromJSON, parseJSON) import Data.Aeson.Types (parseMaybe) import Data.Text (unpack) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Value -> ReaderT LambdaContext IO String myHandler jsonAst = case parseMaybe parseJSON jsonAst of Nothing -> return $ "My name is HAL, what's yours?" Just Named { name } -> do LambdaContext { functionName } <- ask greeting <- liftIO $ getEnv "GREETING" return $ greeting ++ name ++ " from " ++ unpack functionName ++ "!" main :: IO () main = readerTRuntime myHandler halFor functions with IO that can fail in a pure way (or via throw).Use this for handlers that need any form of side-effect such as reading environment variables or making network requests, and also need the AWS Lambda Context as input. However, do not use this runtime if you need stateful (caching) behaviors. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (ioRuntimeWithContext) import Control.Monad.Trans (liftIO) import Data.Aeson (Value, FromJSON, parseJSON) import Data.Aeson.Types (parseMaybe) import Data.Text (unpack) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Value -> IO (Either String String) myHandler (LambdaContext { functionName }) jsonAst = case parseMaybe parseJSON jsonAst of Nothing -> return $ pure "My name is HAL, what's yours?" Just Named { name } -> do greeting <- liftIO $ getEnv "GREETING" return $ pure $ greeting ++ name ++ " from " ++ unpack functionName ++ "!" main :: IO () main = ioRuntimeWithContext myHandler halFor functions with IO that can fail in a pure way (or via throw).Use this for handlers that need any form of side-effect such as reading environment variables or making network requests. However, do not use this runtime if you need stateful (caching) behaviors. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Runtime (ioRuntime) import Control.Monad.Trans (liftIO) import Data.Aeson (Value, FromJSON, parseJSON) import Data.Aeson.Types (parseMaybe) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Value -> IO (Either String String) myHandler jsonAst = case parseMaybe parseJSON jsonAst of Nothing -> return $ pure "My name is HAL, what's yours?" Just Named { name } -> do greeting <- liftIO $ getEnv "GREETING" return $ pure $ greeting ++ name main :: IO () main = ioRuntime myHandler hal'For pure functions that can still fail.Use this for simple handlers that just translate input to output without side-effects, but can fail and need the AWS Lambda Context as input. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (fallibleRuntimeWithContext) import Data.Aeson (Value, FromJSON, parseJSON) import Data.Aeson.Types (parseMaybe) import Data.Text (unpack) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Value -> Either String String myHandler (LambdaContext { functionName }) jsonAst = case parseMaybe parseJSON jsonAst of Nothing -> Right "My name is HAL, what's yours?" Just Named { name } -> if name == "World" then Right $ "Hello, World from " ++ unpack functionName ++ "!" else Left "Can only greet the world." main :: IO () main = fallibleRuntimeWithContext myHandler hal'For pure functions that can still fail.Use this for simple handlers that just translate input to output without side-effects, but can fail. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Runtime (fallibleRuntime) import Data.Aeson (Value, FromJSON, parseJSON) import Data.Aeson.Types (parseMaybe) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Value -> Either String String myHandler jsonAst = case parseMaybe parseJSON jsonAst of Nothing -> Right "My name is HAL, what's yours?" Just Named { name } -> if name == "World" then Right "Hello, World!" else Left "Can only greet the world." main :: IO () main = fallibleRuntime myHandler halFor pure functions that can never fail that also need access to the context.Use this for simple handlers that just translate input to output without side-effects, but that need the AWS Lambda Context as input. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (pureRuntimeWithContext) import Data.Aeson (Value, FromJSON, parseJSON) import Data.Aeson.Types (parseMaybe) import Data.Text (unpack) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Value -> Either String String myHandler (LambdaContext { functionName }) jsonAst = case parseMaybe parseJSON jsonAst of Nothing -> Right "My name is HAL, what's yours?" Just Named { name } -> Right $ "Hello, " ++ name ++ " from " ++ unpack functionName ++ "!" main :: IO () main = pureRuntimeWithContext myHandler hal'For pure functions that can never fail.Use this for simple handlers that just translate input to output without side-effects. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Runtime (pureRuntime) import Data.Aeson (Value, FromJSON, parseJSON) import Data.Aeson.Types (parseMaybe) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Value -> String myHandler jsonAst = case parseMaybe parseJSON jsonAst of Nothing -> "My name is HAL, what's yours?" Just Named { name } -> "Hello, " ++ name ++ "!" main :: IO () main = pureRuntime myHandler  Runtime methods useful when constructing Haskell handlers for the AWS Lambda Custom Runtime.(c) Nike, Inc., 2018BSD33nathan.fairhurst@nike.com, fernando.freire@nike.comstableNone #056789;?[ halFor any monad that supports  and catch. Useful if you need caching behaviours or are comfortable manipulating monad transformers, and want full control over your monadic interface.7In a future version, this function will be renamed to mRuntimeWithContext, (after the deprecated function is removed). {-# LANGUAGE DeriveGeneric, NamedFieldPuns #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (mRuntimeWithContext') import Control.Monad.State.Lazy (StateT, evalStateT, get, put) import Control.Monad.Trans (liftIO) import Data.Aeson (FromJSON) import Data.Text (unpack) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Named -> StateT Int IO String myHandler LambdaContext { functionName } Named { name } = do greeting <- liftIO $ getEnv "GREETING" greetingCount <- get put $ greetingCount + 1 return $ greeting ++ name ++ " (" ++ show greetingCount ++ ") from " ++ unpack functionName ++ "!" main :: IO () main = evalStateT (mRuntimeWithContext' myHandler) 0 halFor any monad that supports  and catch. Useful if you need caching behaviours or are comfortable manipulating monad transformers, want full control over your monadic interface, but don't need to inspect the l. {-# LANGUAGE DeriveGeneric, NamedFieldPuns #-} module Main where import AWS.Lambda.Runtime (mRuntime) import Control.Monad.State.Lazy (StateT, evalStateT, get, put) import Control.Monad.Trans (liftIO) import Data.Aeson (FromJSON) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Named -> StateT Int IO String myHandler Named { name } = do greeting <- liftIO $ getEnv "GREETING" greetingCount <- get put $ greetingCount + 1 return $ greeting ++ name ++ " (" ++ show greetingCount ++ ")!" main :: IO () main = evalStateT (mRuntime myHandler) 0 hal:For any monad that supports IO/catch/Reader LambdaContext. StateT Int (ReaderT LambdaContext IO) String myHandler Named { name } = do LambdaContext { functionName } <- ask greeting <- liftIO $ getEnv "GREETING" greetingCount <- get put $ greetingCount + 1 return $ greeting ++ name ++ " (" ++ show greetingCount ++ ") from " ++ unpack functionName ++ "!" main :: IO () main = runReaderTLambdaContext (evalStateT (mRuntimeWithContext myHandler) 0) halFor functions that can read the lambda context and use IO within the same monad.Use this for handlers that need any form of side-effect such as reading environment variables or making network requests, and prefer to access the AWS Lambda Context in the same monad. However, do not use this runtime if you need stateful (caching) behaviors. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (readerTRuntime) import Control.Monad.Reader (ReaderT, ask) import Control.Monad.Trans (liftIO) import Data.Aeson (FromJSON) import Data.Text (unpack) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Named -> ReaderT LambdaContext IO String myHandler Named { name } = do LambdaContext { functionName } <- ask greeting <- liftIO $ getEnv "GREETING" return $ greeting ++ name ++ " from " ++ unpack functionName ++ "!" main :: IO () main = readerTRuntime myHandler halFor functions with IO that can fail in a pure way (or via throw).Use this for handlers that need any form of side-effect such as reading environment variables or making network requests, and also need the AWS Lambda Context as input. However, do not use this runtime if you need stateful (caching) behaviors. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (ioRuntimeWithContext) import Data.Aeson (FromJSON) import Data.Text (unpack) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Named -> IO (Either String String) myHandler (LambdaContext { functionName }) (Named { name }) = do greeting <- getEnv "GREETING" return $ pure $ greeting ++ name ++ " from " ++ unpack functionName ++ "!" main :: IO () main = ioRuntimeWithContext myHandler halFor functions with IO that can fail in a pure way (or via throw).Use this for handlers that need any form of side-effect such as reading environment variables or making network requests. However, do not use this runtime if you need stateful (caching) behaviors. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Runtime (ioRuntime) import Data.Aeson (FromJSON) import System.Environment (getEnv) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Named -> IO (Either String String) myHandler (Named { name }) = do greeting <- getEnv "GREETING" return $ pure $ greeting ++ name main :: IO () main = ioRuntime myHandler hal'For pure functions that can still fail.Use this for simple handlers that just translate input to output without side-effects, but can fail and need the AWS Lambda Context as input. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (fallibleRuntimeWithContext) import Data.Aeson (FromJSON) import Data.Text (unpack) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Named -> Either String String myHandler (LambdaContext { functionName }) (Named { name }) = if name == "World" then Right $ "Hello, World from " ++ unpack functionName ++ "!" else Left "Can only greet the world." main :: IO () main = fallibleRuntimeWithContext myHandler hal'For pure functions that can still fail.Use this for simple handlers that just translate input to output without side-effects, but can fail. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Runtime (fallibleRuntime) import Data.Aeson (FromJSON) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Named -> Either String String myHandler (Named { name }) = if name == "World" then Right "Hello, World!" else Left "Can only greet the world." main :: IO () main = fallibleRuntime myHandler halFor pure functions that can never fail that also need access to the context.Use this for simple handlers that just translate input to output without side-effects, but that need the AWS Lambda Context as input. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Context (LambdaContext(..)) import AWS.Lambda.Runtime (pureRuntimeWithContext) import Data.Aeson (FromJSON) import Data.Text (unpack) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: LambdaContext -> Named -> String myHandler (LambdaContext { functionName }) (Named { name }) = "Hello, " ++ name ++ " from " ++ unpack functionName ++ "!" main :: IO () main = pureRuntimeWithContext myHandler hal'For pure functions that can never fail.Use this for simple handlers that just translate input to output without side-effects. {-# LANGUAGE NamedFieldPuns, DeriveGeneric #-} module Main where import AWS.Lambda.Runtime (pureRuntime) import Data.Aeson (FromJSON) import GHC.Generics (Generic) data Named = Named { name :: String } deriving Generic instance FromJSON Named myHandler :: Named -> String myHandler Named { name } = "Hello, " ++ name ++ "!" main :: IO () main = pureRuntime myHandler  None #056789; !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                                                                      !hal-0.4.10-LWrkeryoXTOAPQgDhWLet9AWS.Lambda.Context*AWS.Lambda.Events.ApiGateway.ProxyResponseAWS.Lambda.Combinators)AWS.Lambda.Events.ApiGateway.ProxyRequestAWS.Lambda.Events.EventBridge=AWS.Lambda.Events.EventBridge.Detail.SSM.ParameterStoreChangeAWS.Lambda.Events.KafkaAWS.Lambda.Events.S3AWS.Lambda.Events.SQSAWS.Lambda.Internal!AWS.Lambda.RuntimeClient.InternalAWS.Lambda.RuntimeClientAWS.Lambda.Runtime.ValueAWS.Lambda.RuntimeioRuntimeWithContextreaderTRuntime LambdaContextfallibleRuntimeWithContextpureRuntimeWithContext pureRuntimemRuntimeWithContextAWS.Lambda.Events EventBridge' Paths_hal#envy-2.1.0.0-4gIMqpHhUlJAKm0q6wSo4B System.Envy defConfig'http-types-0.12.3-XEQjpts9GnAkrn83W7LXBNetwork.HTTP.Types.Status networkAuthenticationRequired511 status511httpVersionNotSupported505 status505gatewayTimeout504 status504serviceUnavailable503 status503 badGateway502 status502notImplemented501 status501internalServerError500 status500requestHeaderFieldsTooLarge431 status431tooManyRequests429 status429preconditionRequired428 status428upgradeRequired426 status426unprocessableEntity422 status422 imATeapot418 status418expectationFailed417 status417requestedRangeNotSatisfiable416 status416unsupportedMediaType415 status415requestURITooLong414 status414requestEntityTooLarge413 status413preconditionFailed412 status412lengthRequired411 status411gone410 status410 conflict409 status409requestTimeout408 status408proxyAuthenticationRequired407 status407notAcceptable406 status406methodNotAllowed405 status405 notFound404 status404 forbidden403 status403paymentRequired402 status402unauthorized401 status401 badRequest400 status400permanentRedirect308 status308temporaryRedirect307 status307 useProxy305 status305notModified304 status304 seeOther303 status303found302 status302movedPermanently301 status301multipleChoices300 status300partialContent206 status206resetContent205 status205 noContent204 status204nonAuthoritative203 status203 accepted202 status202 created201 status201ok200 status200switchingProtocols101 status101 continue100 status100 statusMessage statusCodeStatuswithIOInterfacewithFallibleInterfacewithPureInterfacewithoutContextwithInfallibleParseHasLambdaContext withContext$sel:functionName:LambdaContext"$sel:functionVersion:LambdaContext%$sel:functionMemorySize:LambdaContext$sel:logGroupName:LambdaContext $sel:logStreamName:LambdaContext$sel:awsRequestId:LambdaContext%$sel:invokedFunctionArn:LambdaContext$sel:xRayTraceId:LambdaContext$sel:deadline:LambdaContext $sel:clientContext:LambdaContext$sel:identity:LambdaContextCognitoIdentity$sel:identityId:CognitoIdentity#$sel:identityPoolId:CognitoIdentity ClientContext$sel:client:ClientContext$sel:custom:ClientContext$sel:environment:ClientContextClientApplication$sel:appTitle:ClientApplication%$sel:appVersionName:ClientApplication%$sel:appVersionCode:ClientApplication%$sel:appPackageName:ClientApplicationgetRemainingTimerunReaderTLambdaContext$fFromJSONClientApplication$fToJSONClientApplication$fFromJSONClientContext$fToJSONClientContext$fFromJSONCognitoIdentity$fToJSONCognitoIdentity$fDefConfigLambdaContext$fHasLambdaContextLambdaContext$fShowLambdaContext$fGenericLambdaContext$fEqLambdaContext$fShowCognitoIdentity$fGenericCognitoIdentity$fEqCognitoIdentity$fShowClientContext$fGenericClientContext$fEqClientContext$fShowClientApplication$fGenericClientApplication$fEqClientApplicationStrictlyNoAuthorizer NoAuthorizer ProxyRequest$sel:path:ProxyRequest$sel:headers:ProxyRequest#$sel:multiValueHeaders:ProxyRequest $sel:pathParameters:ProxyRequest $sel:stageVariables:ProxyRequest $sel:requestContext:ProxyRequest$sel:resource:ProxyRequest$sel:httpMethod:ProxyRequest'$sel:queryStringParameters:ProxyRequest1$sel:multiValueQueryStringParameters:ProxyRequest$sel:body:ProxyRequestRequestContext$sel:path:RequestContext$sel:accountId:RequestContext$sel:authorizer:RequestContext$sel:resourceId:RequestContext$sel:stage:RequestContext $sel:domainPrefix:RequestContext$sel:requestId:RequestContext$sel:identity:RequestContext$sel:domainName:RequestContext $sel:resourcePath:RequestContext$sel:httpMethod:RequestContext%$sel:extendedRequestId:RequestContext$sel:apiId:RequestContextIdentity#$sel:cognitoIdentityPoolId:Identity$sel:accountId:Identity$sel:cognitoIdentityId:Identity$sel:caller:Identity$sel:apiKey:Identity$sel:sourceIp:Identity$sel:accessKey:Identity'$sel:cognitoAuthenticationType:Identity+$sel:cognitoAuthenticationProvider:Identity$sel:userArn:Identity$sel:apiKeyId:Identity$sel:userAgent:Identity$sel:user:Identity$fToJSONIdentity$fFromJSONIdentity$fToJSONRequestContext$fFromJSONRequestContext$fToJSONProxyRequest$fFromJSONProxyRequest$fEqProxyRequest$fGenericProxyRequest$fShowProxyRequest$fEqRequestContext$fGenericRequestContext$fShowRequestContext $fEqIdentity$fGenericIdentity$fShowIdentity ProxyResponse$sel:status:ProxyResponse$$sel:multiValueHeaders:ProxyResponse$sel:body:ProxyResponse ProxyBody$sel:contentType:ProxyBody$sel:serialized:ProxyBody$sel:isBase64Encoded:ProxyBodyresponse addHeader setHeader genericBinary textPlainapplicationJson$fFromJSONProxyResponse$fToJSONProxyResponse$fEqProxyResponse$fGenericProxyResponse$fShowProxyResponse $fEqProxyBody$fGenericProxyBody$fShowProxyBodyEventBridgeEvent'EventBridgeEvent$sel:version:EventBridgeEvent$sel:id:EventBridgeEvent $sel:detailType:EventBridgeEvent$sel:source:EventBridgeEvent$sel:account:EventBridgeEvent$sel:time:EventBridgeEvent$sel:region:EventBridgeEvent$sel:resources:EventBridgeEvent$sel:detail:EventBridgeEvent$fToJSONEventBridgeEvent'$fFromJSONEventBridgeEvent'$fEqEventBridgeEvent'$fShowEventBridgeEvent'$fGenericEventBridgeEvent'$fFunctorEventBridgeEvent'$fFoldableEventBridgeEvent'$fTraversableEventBridgeEvent'TypeString StringList SecureString OperationParameterStoreChange#$sel:operation:ParameterStoreChange$sel:name:ParameterStoreChange$sel:type_:ParameterStoreChange%$sel:description:ParameterStoreChangeLabelParameterVersionDeleteUpdateCreate$fToJSONOperation$fFromJSONOperation $fToJSONType$fFromJSONType$fToJSONParameterStoreChange$fFromJSONParameterStoreChange$fEqParameterStoreChange$fShowParameterStoreChange$fGenericParameterStoreChange$fEqType $fOrdType $fShowType $fEnumType $fBoundedType $fGenericType $fEqOperation$fShowOperation$fGenericOperation TimestampNoTimestampType CreateTime LogAppendTimeHeaderRecord'Record$sel:topic:Record$sel:partition:Record$sel:offset:Record$sel:timestamp:Record$sel:headers:Record$sel:key:Record$sel:value:Record EventSourceAwsKafkaSelfManagedKafka KafkaEvent$sel:eventSource:KafkaEvent$sel:eventSourceArn:KafkaEvent $sel:bootstrapServers:KafkaEvent$sel:records:KafkaEventparseTimestampunparseTimestampint64ToUTCTimeutcTimeToInt64$fToJSONEventSource$fFromJSONEventSource$fToJSONHeader$fFromJSONHeader$fToJSONRecord'$fFromJSONRecord'$fToJSONKafkaEvent$fFromJSONKafkaEvent$fEqKafkaEvent$fShowKafkaEvent$fGenericKafkaEvent $fEqRecord' $fShowRecord'$fGenericRecord'$fFunctorRecord'$fFoldableRecord'$fTraversableRecord' $fEqTimestamp$fShowTimestamp$fGenericTimestamp $fEqHeader $fShowHeader$fGenericHeader$fEqEventSource$fShowEventSource$fBoundedEventSource$fEnumEventSource$fOrdEventSource$fGenericEventSourceS3Object PutObject DeleteObject$sel:eTag:PutObject$sel:sequencer:PutObject$sel:key:PutObject$sel:size:PutObjectS3Event$sel:awsRegion:S3Event$sel:eventName:S3Event$sel:eventSource:S3Event$sel:eventTime:S3Event$sel:eventVersion:S3Event$sel:requestParameters:S3Event$sel:responseElements:S3Event$sel:s3:S3Event$sel:userIdentity:S3EventRequestParameters&$sel:sourceIPAddress:RequestParametersResponseElements$sel:amazonId:ResponseElements%$sel:amazonRequestId:ResponseElementsS3Config$sel:bucket:S3Config$sel:configurationId:S3Config$sel:object:S3Config$sel:s3SchemaVersion:S3ConfigS3Bucket$sel:arn:S3Bucket$sel:name:S3Bucket$sel:ownerIdentity:S3BucketPrincipalIdentity"$sel:principalId:PrincipalIdentityRecords$sel:records:Records$fFromJSONPrincipalIdentity$fFromJSONS3Bucket$fFromJSONResponseElements$fFromJSONRequestParameters$fFromJSONS3Object$fFromJSONS3Config$fFromJSONS3Event$fFromJSONRecords $fShowRecords $fEqRecords $fShowS3Event $fEqS3Event$fGenericS3Event$fShowS3Config $fEqS3Config$fGenericS3Config$fShowS3Object $fEqS3Object$fGenericS3Object$fShowRequestParameters$fEqRequestParameters$fGenericRequestParameters$fShowResponseElements$fEqResponseElements$fShowS3Bucket $fEqS3Bucket$fGenericS3Bucket$fShowPrincipalIdentity$fEqPrincipalIdentity$fGenericPrincipalIdentitySQSEvent$sel:messageId:SQSEvent$sel:receiptHandle:SQSEvent$sel:body:SQSEvent$sel:attributes:SQSEvent$sel:messageAttributes:SQSEvent$sel:md5OfBody:SQSEvent$sel:eventSource:SQSEvent$sel:eventSourceARN:SQSEvent$sel:awsRegion:SQSEvent Attributes'$sel:approximateReceiveCount:Attributes$sel:sentTimestamp:Attributes$sel:senderId:Attributes0$sel:approximateFirstReceiveTimestamp:Attributes$fFromJSONAttributes$fFromJSONSQSEvent$fShowSQSEvent $fEqSQSEvent$fGenericSQSEvent$fShowAttributes$fEqAttributesDynamicContext $sel:awsRequestId:DynamicContext&$sel:invokedFunctionArn:DynamicContext$sel:xRayTraceId:DynamicContext$sel:deadline:DynamicContext!$sel:clientContext:DynamicContext$sel:identity:DynamicContext StaticContext$sel:functionName:StaticContext"$sel:functionVersion:StaticContext%$sel:functionMemorySize:StaticContext$sel:logGroupName:StaticContext $sel:logStreamName:StaticContextgetStaticContext mkContext$fShowDynamicContext$fShowStaticContext$fGenericStaticContexteventResponseToNextDataRuntimeClientConfiggetRuntimeClientConfig getNextData getNextEventsendEventSuccesssendEventError$fToJSONLambdaError$fShowLambdaError$fGenericLambdaErrormRuntimeWithContext'mRuntime ioRuntimefallibleRuntimeghc-prim GHC.TypesIObase Data.EitherEitherGHC.Baseconst$aeson-2.0.3.0-HoBWSDM3qT941k5ljFeQlIData.Aeson.Types.InternalValue<&>Data.Traversable Traversabletraverse Data.Aeson decodeStrictData.Aeson.Types.FromJSONFromJSONData.Aeson.Types.ToJSONToJSONversion getBinDir getLibDir getDynLibDir getDataDir getLibexecDir getSysconfDirgetDataFileName