Skip to content

Commit 44e58bb

Browse files
author
Nick Tchayka
authored
Merge pull request theam#97 from dnikolovv/no-th-4.0.0
Version 4.0.0 - API redesign - no TH + native ALB support
2 parents 5163a60 + 41564a6 commit 44e58bb

37 files changed

+1316
-1103
lines changed

.github/workflows/ci.yml

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,39 @@
11
name: CI
22

3-
# Trigger the workflow on push or pull request, but only for the master branch
43
on:
54
pull_request:
65
push:
76
branches: [master]
87

98
jobs:
109
build:
11-
name: ghc ${{ matrix.ghc }}
12-
runs-on: ubuntu-16.04
13-
strategy:
14-
matrix:
15-
cabal: ["2.4"]
16-
ghc:
17-
- "8.6.5"
18-
10+
runs-on: ubuntu-latest
1911
steps:
20-
- uses: actions/checkout@v2
21-
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'
22-
23-
- uses: actions/setup-haskell@v1
24-
name: Setup Haskell
12+
13+
# Needed for the add-path command
14+
- name: ACTIONS_ALLOW_UNSECURE_COMMANDS
15+
id: ACTIONS_ALLOW_UNSECURE_COMMANDS
16+
run: echo 'ACTIONS_ALLOW_UNSECURE_COMMANDS=true' >> $GITHUB_ENV
17+
18+
- uses: actions/checkout@v1
19+
20+
- uses: mstksg/setup-stack@v1
21+
22+
- uses: actions/cache@v1
23+
name: Cache ~/.stack
2524
with:
26-
ghc-version: ${{ matrix.ghc }}
27-
cabal-version: ${{ matrix.cabal }}
25+
path: ~/.stack
26+
key: ${{ runner.os }}-stack-${{ hashFiles('stack.yaml') }}
27+
restore-keys: |
28+
${{ runner.os }}-stack-
2829
2930
- uses: actions/cache@v1
30-
name: Cache ~/.cabal/store
31+
name: Cache .stack-work
3132
with:
32-
path: ~/.cabal/store
33-
key: ${{ runner.os }}-${{ matrix.ghc }}-cabal
34-
35-
- name: Build
36-
run: |
37-
cabal v2-update
38-
cabal v2-build --enable-tests --enable-benchmarks
39-
- name: Test
40-
run: |
41-
cabal v2-test --enable-tests
33+
path: .stack-work
34+
key: ${{ runner.os }}-stack-work-${{ hashFiles('stack.yaml') }}-${{ hashFiles('**/*.hs') }}
35+
restore-keys: |
36+
${{ runner.os }}-stack-work-
37+
38+
- name: Compile with Stack
39+
run: stack test --fast

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ cabal.project.local~
2828
.HTF/
2929
.ghc.environment.*
3030

31+
# VSCode
32+
.vscode/settings.json
33+
3134
# IntelliJ
3235
.idea
3336
*.iml

aws-lambda-haskell-runtime.cabal

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
cabal-version: 1.12
2-
3-
-- This file has been generated from package.yaml by hpack version 0.34.2.
4-
--
5-
-- see: https://github.com/sol/hpack
1+
cabal-version: 3.0
62

73
name: aws-lambda-haskell-runtime
8-
version: 3.0.5
4+
version: 4.0.0
95
synopsis: Haskell runtime for AWS Lambda
106
description: Please see the README on GitHub at <https://github.com/theam/aws-lambda-haskell-runtime#readme>
117
category: AWS
128
homepage: https://github.com/theam/aws-lambda-haskell-runtime#readme
139
bug-reports: https://github.com/theam/aws-lambda-haskell-runtime/issues
1410
author: Nikita Tchayka
1511
maintainer: [email protected]
16-
copyright: 2018 The Agile Monkeys SL
12+
copyright: 2021 The Agile Monkeys SL
1713
license: Apache-2.0
1814
license-file: LICENSE
1915
build-type: Simple
@@ -27,36 +23,37 @@ source-repository head
2723
library
2824
exposed-modules:
2925
Aws.Lambda
30-
Aws.Lambda.Runtime
31-
Aws.Lambda.Runtime.Common
3226
other-modules:
33-
Aws.Lambda.Configuration
34-
Aws.Lambda.Meta.Common
35-
Aws.Lambda.Meta.Discover
36-
Aws.Lambda.Meta.Dispatch
37-
Aws.Lambda.Meta.Main
38-
Aws.Lambda.Meta.Run
27+
Aws.Lambda.Runtime
28+
Aws.Lambda.Runtime.ALB.Types
3929
Aws.Lambda.Runtime.API.Endpoints
4030
Aws.Lambda.Runtime.API.Version
41-
Aws.Lambda.Runtime.ApiGatewayInfo
31+
Aws.Lambda.Runtime.APIGateway.Types
4232
Aws.Lambda.Runtime.ApiInfo
33+
Aws.Lambda.Runtime.Common
34+
Aws.Lambda.Runtime.Configuration
4335
Aws.Lambda.Runtime.Context
4436
Aws.Lambda.Runtime.Environment
4537
Aws.Lambda.Runtime.Error
4638
Aws.Lambda.Runtime.Publish
39+
Aws.Lambda.Runtime.StandaloneLambda.Types
40+
Aws.Lambda.Setup
4741
Aws.Lambda.Utilities
4842
Paths_aws_lambda_haskell_runtime
4943
hs-source-dirs:
5044
src
5145
default-extensions: TemplateHaskell OverloadedStrings RecordWildCards ScopedTypeVariables DeriveGeneric TypeApplications FlexibleContexts DeriveAnyClass QuasiQuotes
52-
ghc-options: -Wall -fno-warn-orphans -optP-Wno-nonportable-include-path -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat -Widentities -Wredundant-constraints -Wmissing-export-lists -Wpartial-fields -fhide-source-paths -freverse-errors
46+
ghc-options: -Wall -Werror -optP-Wno-nonportable-include-path -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat -Widentities -Wredundant-constraints -Wmissing-export-lists -Wpartial-fields -fhide-source-paths -freverse-errors
5347
build-depends:
5448
aeson
5549
, base >=4.7 && <5
5650
, bytestring
5751
, case-insensitive
52+
, exceptions
53+
, hashable
5854
, http-client
5955
, http-types
56+
, mtl
6057
, path >0.7
6158
, path-io
6259
, safe-exceptions-checked
@@ -73,7 +70,7 @@ test-suite aws-lambda-haskell-runtime-test
7370
hs-source-dirs:
7471
test
7572
default-extensions: TemplateHaskell OverloadedStrings RecordWildCards ScopedTypeVariables DeriveGeneric TypeApplications FlexibleContexts DeriveAnyClass QuasiQuotes
76-
ghc-options: -Wall -fno-warn-orphans -optP-Wno-nonportable-include-path -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat -Widentities -Wredundant-constraints -Wmissing-export-lists -Wpartial-fields -fhide-source-paths -freverse-errors -threaded -rtsopts -with-rtsopts=-N
73+
ghc-options: -Wall -Werror -optP-Wno-nonportable-include-path -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat -Widentities -Wredundant-constraints -Wmissing-export-lists -Wpartial-fields -fhide-source-paths -freverse-errors -threaded -rtsopts -with-rtsopts=-N
7774
build-depends:
7875
base >=4.7 && <5
7976
, hspec

doc/01-getting-started.md

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,25 @@ If not, you can do so by issuing the following command on your terminal:
1111
curl -sSL https://get.haskellstack.org/ | sh
1212
```
1313

14-
Haskell compiles to **native code**, which is super efficient. But it has one main drawback: linking changes from machine to machine.
14+
Haskell compiles to **native code**, which is super efficient. But it has one main drawback: linking changes from machine to machine. It's very hard to make sure that the executable you build will work when deployed to AWS Lambda.
1515

16-
To make sure that our projects always work and are reproducible, we use the Stack [feature](https://docs.haskellstack.org/en/stable/docker_integration/)
17-
for [Docker](https://www.docker.com/) support to build our projects. Be sure to install Docker before getting started with the runtime 😄
16+
To make sure our projects work consistently, we use AWS Lambda's [docker image](https://aws.amazon.com/blogs/aws/new-for-aws-lambda-container-image-support/) feature. Be sure to install Docker before getting started with the runtime 😄
1817

1918
## Using the template
2019

2120
If you are testing the package, or you are starting a new project, we have provided a Stack template that will scaffold the project for you.
2221
To use it, enter the following command:
2322

2423
```bash
25-
stack new my-haskell-lambda https://github.com/theam/aws-lambda-haskell-runtime/raw/master/stack-template.hsfiles --resolver=lts-15.16 --omit-packages
24+
stack new my-haskell-lambda https://github.com/theam/aws-lambda-haskell-runtime/raw/master/stack-template.hsfiles
2625
```
2726

2827
This will create a `my-haskell-lambda` directory with the following structure:
2928

3029
```text
3130
.
3231
├── LICENSE
32+
├── Dockerfile
3333
├── Makefile
3434
├── README.md
3535
├── Setup.hs
@@ -42,43 +42,27 @@ This will create a `my-haskell-lambda` directory with the following structure:
4242
└── stack.yaml
4343
```
4444

45-
Now, add the following to your `stack.yaml` file:
46-
47-
```yaml
48-
packages:
49-
- .
50-
51-
extra-deps:
52-
- aws-lambda-haskell-runtime-3.0.0
53-
```
45+
The project contains a sample handler that you can use as a starting point.
5446

5547
## Adding the dependency to an existing project
5648

57-
If you currently have a project, you can add this package by adding,
58-
59-
to the `stack.yaml` file:
49+
If you want to add the runtime to an existing project, you can do so by adding the following `extra-dep` entry to the `stack.yaml` file:
6050

6151
```yaml
6252
extra-deps:
63-
- aws-lambda-haskell-runtime-3.0.0
53+
- aws-lambda-haskell-runtime-4.0.0
6454
```
6555
6656
and, to the `package.yaml` file:
6757

6858
```yaml
6959
dependencies:
7060
- ... # other dependencies of your project
71-
- aws-lambda-haskell-runtime >= 3.0.0
61+
- aws-lambda-haskell-runtime >= 4.0.0
7262
```
7363

74-
## Keep reading!
75-
76-
If you have completed these steps, and type into your terminal:
77-
78-
```bash
79-
stack build
80-
```
64+
If you have completed these steps, you should be able to execute `stack build` and see the project build correctly.
8165

82-
you should get a proper build of your project.
66+
## Keep reading!
8367

8468
Let's see how we can add our first handler!

doc/02-adding-a-handler.md

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,64 +8,59 @@ In this example, we'll create a person age validator.
88

99
If you have used the Stack template, you will have a handler that is pre-defined in the `src/Lib.hs` file.
1010

11-
If you are starting from scratch, let's write it bit by bit:
12-
13-
First, we will enable some language extensions in order to work with JSON easier, also, we'll import the required
14-
modules:
15-
16-
```haskell top hide
17-
{-# LANGUAGE DeriveGeneric #-}
18-
{-# LANGUAGE DeriveAnyClass #-}
19-
```
11+
First, we need to enable some language extensions in order to make working with JSON easier. We'll also import a few required modules:
2012

2113
```haskell
2214
{-# LANGUAGE DeriveGeneric #-}
2315
{-# LANGUAGE DeriveAnyClass #-}
2416

2517
module Lib where
26-
```
2718

28-
```haskell top
2919
import Aws.Lambda
3020
import GHC.Generics
3121
import Data.Aeson
3222
```
3323

34-
The runtime will decode the JSON input that reaches the AWS Lambda handler, so let's create a type
35-
for persons. We also tell the compiler to derive (auto-implement) the `Generic`, `FromJSON` and `ToJSON` classes
36-
for us.
24+
We'll create a basic handler that validates a person's age is positive. Let's create a `Person` type to use.
3725

3826
```haskell top
3927
data Person = Person
4028
{ name :: String
4129
, age :: Int
42-
} deriving (Generic, FromJSON, ToJSON)
30+
} -- We kindly ask the compiler to autogenerate JSON instances for us
31+
deriving (Generic, FromJSON, ToJSON)
4332
```
4433

45-
Now, let's write the handler. It **must** be a function that is called `handler` and has a type signature.
34+
Now, let's implement the actual handler.
4635

47-
The arguments to this function will always go like this:
36+
A handler is a function with the following type signature:
4837

49-
* The first argument to this handler will always be the input type we expect (note that it has to implement `FromJSON`).
50-
* The second argument is the `Aws.Lambda` `Context` type, which has some information regarding our Lambda execution. The `Context` type also takes a `context` parameter, which we can use if we want to have some state that is shared between Lambda calls. For this example, we don't want to have such state, so we'll just use `()`.
38+
```haskell
39+
-- Note that request, error and response must all implement ToJSON and FromJSON
40+
handler :: request -> Context context -> IO (Either error response)
41+
```
5142

52-
The output will always be an `IO (Either errorType resultType)` where
43+
For our person validator usecase this means the following:
5344

54-
* `errorType` is whatever custom error type you want to use.
55-
* `resultType` is what your function will return if everything goes well.
45+
```haskell
46+
handler :: Person -> Context () -> IO (Either String Person)
47+
```
5648

57-
Note that both types must implement `ToJSON`, as the runtime will use it to serialize the values.
49+
This means we expect to be given a `Person` object and we'll return either some `String` as an error or some other `Person` object (that passed validation).
5850

59-
For example, here we will check if the age of a `Person` is positive, and will return if it is correct. If not, we
60-
will return a `String` error:
51+
You can ignore the `Context ()` parameter at this point. This is the Lambda context object which is present in every runtime. By specifying `()` as an inner value, we say we don't want to have anything there.
6152

62-
```haskell top
53+
The implementation of our handler will look like this:
54+
55+
```haskell
6356
handler :: Person -> Context () -> IO (Either String Person)
64-
handler person context =
57+
handler person _context =
6558
if age person > 0 then
6659
pure (Right person)
6760
else
6861
pure (Left "A person's age must be positive")
6962
```
7063

71-
Note how we are using `Right` to return the value in case everything went **right**, and `Left` if something went wrong.
64+
Note how we are using `Right` to return the value in case everything went **right**, and `Left` if something went wrong.
65+
66+
Now let's see how to register this handler into our runtime.

0 commit comments

Comments
 (0)