diff --git a/CHANGELOG.md b/CHANGELOG.md index 434a8d6..05217eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog][chg] and this project adheres to [Haskell's Package Versioning Policy][pvp] -## 1.0.1 - 2023-12-15 +## unreleased - 2023-11-23 + + - `fallibleRuntime` and `fallibleRuntimeWithContext` report errors to AWS + instead of returning `{"Left": "some error"}`. + - `fallibleRuntime` and `fallibleRuntimeWithContext` no longer wrap their + successful responses in `{"Right": ...}`. + - `pureRuntime`, `pureRuntimeWithContext`, `fallibleRuntime` and `fallibleRuntimeWithContext` + no longer crash the Lambda runtime if input can't be parsed from JSON. + +## `1.0.1` - 2023-12-15 - Add support for aeson 2.2. Users can opt in by setting the `use-aeson-2-2` flag to `true`, which for many users will be set automatically. In a future breaking change release, this flag will default to `true`. diff --git a/src/AWS/Lambda/Combinators.hs b/src/AWS/Lambda/Combinators.hs index c8e69ce..735e268 100644 --- a/src/AWS/Lambda/Combinators.hs +++ b/src/AWS/Lambda/Combinators.hs @@ -13,7 +13,8 @@ They map functions (instead of values) to turn basic handlers into handlers comp module AWS.Lambda.Combinators ( withoutContext, - withInfallibleParse + withInfallibleParse, + withFallibleParse ) where import Data.Aeson (FromJSON, parseJSON, Value) @@ -70,3 +71,7 @@ withoutContext = const -- on a failure to convert the JSON AST sent to the Lambda. withInfallibleParse :: FromJSON a => (a -> b) -> Value -> b withInfallibleParse fn = either error fn . parseEither parseJSON + +-- | Like 'withInfallibleParse', but return the result in an 'Either' instead of using 'error'. +withFallibleParse :: FromJSON a => (a -> b) -> Value -> Either String b +withFallibleParse fn = fmap fn . parseEither parseJSON diff --git a/src/AWS/Lambda/Context.hs b/src/AWS/Lambda/Context.hs index abcc97f..c5f8f63 100644 --- a/src/AWS/Lambda/Context.hs +++ b/src/AWS/Lambda/Context.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE NamedFieldPuns, OverloadedStrings #-} +{-# LANGUAGE NamedFieldPuns #-} {-| Module : AWS.Lambda.Context diff --git a/src/AWS/Lambda/Runtime.hs b/src/AWS/Lambda/Runtime.hs index 32e38b7..8eed552 100644 --- a/src/AWS/Lambda/Runtime.hs +++ b/src/AWS/Lambda/Runtime.hs @@ -29,9 +29,12 @@ module AWS.Lambda.Runtime ( mRuntimeWithContext ) where -import AWS.Lambda.Combinators (withInfallibleParse) +import AWS.Lambda.Combinators (withInfallibleParse, + withFallibleParse, + withoutContext) import AWS.Lambda.Context (LambdaContext(..)) import qualified AWS.Lambda.Runtime.Value as ValueRuntime +import Control.Monad (join) import Control.Monad.Catch (MonadCatch) import Control.Monad.IO.Class (MonadIO) import Control.Monad.Reader (ReaderT) @@ -253,7 +256,7 @@ ioRuntime = ValueRuntime.ioRuntime . withInfallibleParse -- @ fallibleRuntimeWithContext :: (FromJSON event, ToJSON result) => (LambdaContext -> event -> Either String result) -> IO () -fallibleRuntimeWithContext = ValueRuntime.fallibleRuntimeWithContext . fmap withInfallibleParse +fallibleRuntimeWithContext fn = ValueRuntime.fallibleRuntimeWithContext $ \lc -> join . withFallibleParse (fn lc) -- | For pure functions that can still fail. -- @@ -286,7 +289,7 @@ fallibleRuntimeWithContext = ValueRuntime.fallibleRuntimeWithContext . fmap with -- @ fallibleRuntime :: (FromJSON event, ToJSON result) => (event -> Either String result) -> IO () -fallibleRuntime = ValueRuntime.fallibleRuntime . withInfallibleParse +fallibleRuntime = fallibleRuntimeWithContext . withoutContext -- | For pure functions that can never fail that also need access to the context. -- @@ -318,7 +321,7 @@ fallibleRuntime = ValueRuntime.fallibleRuntime . withInfallibleParse -- @ pureRuntimeWithContext :: (FromJSON event, ToJSON result) => (LambdaContext -> event -> result) -> IO () -pureRuntimeWithContext = ValueRuntime.pureRuntimeWithContext . fmap withInfallibleParse +pureRuntimeWithContext = fallibleRuntimeWithContext . fmap (fmap pure) -- | For pure functions that can never fail. -- @@ -345,4 +348,4 @@ pureRuntimeWithContext = ValueRuntime.pureRuntimeWithContext . fmap withInfallib -- main = pureRuntime myHandler -- @ pureRuntime :: (FromJSON event, ToJSON result) => (event -> result) -> IO () -pureRuntime = ValueRuntime.pureRuntime . withInfallibleParse +pureRuntime = pureRuntimeWithContext . withoutContext diff --git a/src/AWS/Lambda/Runtime/Value.hs b/src/AWS/Lambda/Runtime/Value.hs index 16778ef..db6343c 100644 --- a/src/AWS/Lambda/Runtime/Value.hs +++ b/src/AWS/Lambda/Runtime/Value.hs @@ -39,10 +39,11 @@ module AWS.Lambda.Runtime.Value ( mRuntimeWithContext, ) where -import AWS.Lambda.RuntimeClient (RuntimeClientConfig, getRuntimeClientConfig, - getNextData, sendEventError, sendEventSuccess) import AWS.Lambda.Combinators (withoutContext) import AWS.Lambda.Context (LambdaContext(..)) +import AWS.Lambda.RuntimeClient (RuntimeClientConfig, getNextData, + getRuntimeClientConfig, + sendEventError, sendEventSuccess) import Control.Exception (SomeException, displayException) import Control.Monad ((<=<), forever) import Control.Monad.Catch (MonadCatch, try) @@ -331,7 +332,7 @@ ioRuntime = ioRuntimeWithContext . withoutContext -- @ fallibleRuntimeWithContext :: ToJSON result => (LambdaContext -> Value -> Either String result) -> IO () -fallibleRuntimeWithContext = mRuntimeWithContext . fmap (fmap pure) +fallibleRuntimeWithContext fn = mRuntimeWithContext (\lc -> either error pure . fn lc) -- | For pure functions that can still fail. --