├── .analysis_option.yaml ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ ├── main.yml │ └── page.yml ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── dart_test.yaml ├── data ├── apigateway_event.json ├── cloudwatch_event.json ├── cloudwatch_log_event.json ├── cognito_event.json ├── dynamodb_event.json ├── kinesis_data_firehose_event.json ├── kinesis_data_stream_event.json ├── s3_event.json └── sqs_event.json ├── example ├── build.sh ├── build.yaml ├── lib │ └── main.dart ├── pubspec.yaml └── template.yml ├── lib ├── aws_lambda_dart_runtime.dart ├── client │ └── client.dart ├── events │ ├── alb_event.dart │ ├── alb_event.g.dart │ ├── alexa_event.dart │ ├── alexa_event.g.dart │ ├── apigateway_event.dart │ ├── apigateway_event.g.dart │ ├── appsync_event.dart │ ├── appsync_event.g.dart │ ├── cloudwatch_event.dart │ ├── cloudwatch_event.g.dart │ ├── cloudwatch_log_event.dart │ ├── cloudwatch_log_event.g.dart │ ├── cognito_event.dart │ ├── cognito_event.g.dart │ ├── dynamodb_event.dart │ ├── dynamodb_event.g.dart │ ├── kinesis_data_firehose_event.dart │ ├── kinesis_data_firehose_event.g.dart │ ├── kinesis_data_stream_event.dart │ ├── kinesis_data_stream_event.g.dart │ ├── s3_event.dart │ ├── s3_event.g.dart │ ├── sqs_event.dart │ └── sqs_event.g.dart └── runtime │ ├── context.dart │ ├── event.dart │ ├── exception.dart │ └── runtime.dart ├── pubspec.yaml └── test ├── alb_event_test.dart ├── apigateway_event_test.dart ├── client_test.dart ├── cloudwatch_event_test.dart ├── cloudwatch_log_event_test.dart ├── cognito_event_test.dart ├── common.dart ├── context_test.dart ├── dynamodb_event_test.dart ├── event_test.dart ├── exception_test.dart ├── kinesis_data_firehose_event.dart ├── kinesis_data_stream_event_test.dart ├── runtime_test.dart ├── s3_event.dart ├── sqs_event_test.dart └── testing.dart /.analysis_option.yaml: -------------------------------------------------------------------------------- 1 | include: package:pedantic/analysis_options.yaml 2 | 3 | analyzer: 4 | exclude: 5 | - lib/runtime/*.g.dart 6 | - test/_data/** 7 | strong-mode: 8 | implicit-casts: false 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: bug 6 | assignees: "" 7 | ---**Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 13 | 1. Start with '...' parameters 14 | 2. Send message from '....' 15 | 3. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Logs & Screenshots ** 21 | Add log output from the Lambda execution. If applicable, add screenshots to help explain your problem. 22 | 23 | **Additional context** 24 | Add any other context about the problem here. 25 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - release/* 8 | pull_request: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | container: 17 | image: google/dart:latest 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Install dependencies 22 | run: pub get 23 | - name: Run tests 24 | run: pub run test 25 | -------------------------------------------------------------------------------- /.github/workflows/page.yml: -------------------------------------------------------------------------------- 1 | name: Page 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | container: 13 | image: google/dart:latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Generate docs 18 | run: dartdoc --output doc 19 | - name: Publish GitHub Pages 20 | uses: peaceiris/actions-gh-pages@v3 21 | with: 22 | github_token: ${{ secrets.DEPLOY_TOKEN }} 23 | publish_dir: ./doc 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | build/ 7 | # If you're building an application, you may want to check-in your pubspec.lock 8 | pubspec.lock 9 | 10 | # Directory created by dartdoc 11 | # If you don't generate documentation locally you can remove this line. 12 | doc/api/ 13 | 14 | # Avoid committing generated Javascript files: 15 | *.dart.js 16 | *.info.json # Produced by the --dump-info flag. 17 | *.js # When generated by dart2js. Don't specify *.js if your 18 | # project includes source files written in JavaScript. 19 | *.js_ 20 | *.js.deps 21 | *.js.map 22 | 23 | # Further artifacts 24 | *.exe 25 | *.zip 26 | bootstrap -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "search.exclude": { 4 | "**/docs": true 5 | } 6 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.3+2 2 | 3 | - #14 Adding type signatured to API Gateway response 4 | 5 | ## 1.0.3+1 6 | 7 | - #13 Expose raw headers on AwsApiGatewayEvent 8 | 9 | ## 1.0.3 10 | 11 | - #10 Throw exception on missing handler 12 | - #9 Better error messages 13 | 14 | ## 1.0.2 15 | 16 | - #6 Adding body to API Gateway request 17 | 18 | ## 1.0.1 19 | 20 | - #5 Adding headers to API Gateway response 21 | 22 | ## 1.0.0-beta.2 23 | 24 | - Change docs publication 25 | 26 | ## 1.0.0-beta.1 27 | 28 | - Next beta release to [pub.dev](https://pub.dev) 29 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/awslabs/aws-lambda-dart-runtime/issues), or [recently closed](https://github.com/awslabs/aws-lambda-dart-runtime/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | 25 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 26 | 27 | 1. You are working against the latest source on the *master* branch. 28 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 29 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 30 | 31 | To send us a pull request, please: 32 | 33 | 1. Fork the repository. 34 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 35 | 3. Ensure local tests pass. 36 | 4. Commit to your fork using clear commit messages and ensure that every source file is formatted. 37 | 5. Send us a pull request, answering any default questions in the pull request interface. 38 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 39 | 40 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 41 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 42 | 43 | 44 | ## Finding contributions to work on 45 | 46 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/awslabs/aws-lambda-dart-runtime/labels/help%20wanted) issues is a great place to start. 47 | 48 | 49 | ## Code of Conduct 50 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 51 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 52 | opensource-codeofconduct@amazon.com with any additional questions or comments. 53 | 54 | 55 | ## Security issue notifications 56 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 57 | 58 | 59 | ## Licensing 60 | 61 | See the [LICENSE](https://github.com/awslabs/aws-lambda-dart-runtime/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 62 | 63 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | AWS Lambda Dart Runtime 2 | Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dart Runtime for AWS Lambda 2 | 3 | ![Main](https://github.com/awslabs/aws-lambda-dart-runtime/workflows/Main/badge.svg?branch=master) 4 | [![License Apache 2](https://img.shields.io/badge/License-Apache2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) 5 | 6 |

7 | A 🎯 Dart Runtime for ƛ AWS Lambda 8 |

9 | 10 | --- 11 | 12 | > Read [Introducing a Dart runtime for AWS Lambda](https://aws.amazon.com/de/blogs/opensource/introducing-a-dart-runtime-for-aws-lambda/) 13 | 14 | > 🚀 [Experimental support](#-serverless-framework-experimental) for ⚡️ serverless framework 15 | 16 | > If you need to access AWS APIs in your Lambda function, [please search on pub.dev](https://pub.dev/packages?q=dependency%3Ashared_aws_api&sort=popularity) for packages provided by [Agilord](https://www.agilord.com/) 17 | 18 | ## Features 19 | 20 | - Great performance `< 10ms` on event processing and `< 50MB` memory consumption 21 | - No need to ship the Dart runtime 22 | - Multiple event handlers 23 | - Typed events 24 | - Custom events 25 | 26 | > this package requires Dart `>= 2.6` 27 | > currently `dart2native` only supports building for the platform it is run on, so you must either build on a `Linux` machine or use `docker` 28 | 29 | ## 🚀 Introduction 30 | 31 | [Dart](https://dart.dev/) is an unsupported [AWS Lambda](https://aws.amazon.com/lambda/) runtime language. However, with a [custom runtime](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html) you can support virtually every programming language. 32 | 33 | There are two ways in which you could use [Dart](https://dart.dev/). You could bundle the Dart Runtime in a [Lambda layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) and use JIT compilation within the lambda execution to run a Dart program. The other is to compile a shippable binary of the Dart program. 34 | 35 | Dart `>= 2.6` introduced `dart2native`. The [tool](https://dart.dev/tools/dart2native) uses AOT (ahead-of-time) to compile a Dart program to [native x64 machine code](https://dart.dev/platforms). This standalone executable is native machine code that's compiled from the specific Dart file and its dependencies, plus a small Dart runtime that handles type checking and garbage collection. 36 | 37 | We decided to use the latter approach rather then the just-in-time compilation of Dart files. The main reason for this decision is that we wanted to avoid having to ship and maintain a standalone Dart runtime version. We would eventually have to deprecate versions, or always update the version when moving forward. Furthermore, shipping a binary has the advantage of having an always runnable version of your function in addition to performance benefits. 38 | 39 | We want to highlight [Firecracker open-source innovation](https://www.youtube.com/watch?v=yDplzXEdBTI) from re:Invent 2019 which gives you a brief overview of [Firecracker](https://firecracker-microvm.github.io/) which is the underlying technology of AWS Lambda. 40 | 41 | ## 📦 Use 42 | 43 | Add the following snippet to your [pubspec file](https://dart.dev/tools/pub/pubspec) in `pubspec.yaml`. 44 | 45 | ```yaml 46 | dependencies: 47 | aws_lambda_dart_runtime: ^1.0.3+2 48 | ``` 49 | 50 | [Docs](https://awslabs.github.io/aws-lambda-dart-runtime/) are available. They are also accessible in the [`docs`](https://github.com/awslabs/aws-lambda-dart-runtime/blob/docs) folder. 51 | 52 | ```bash 53 | # access the docs local 54 | pub global activate dhttpd 55 | dhttpd --path docs 56 | ``` 57 | 58 | > you can generate the docs with `dartdoc --output docs` 59 | 60 | Build and deploy the Dart functions by the [serverless](https://serverless.com) framework or by custom deployment. 61 | 62 | ### 🧪 Serverless Framework (experimental) 63 | 64 | Checkout [serverless-dart](https://github.com/katallaxie/serverless-dart) to create your functions with [serverless](https://serverless.com). 65 | 66 | You can start your next project using the [serverless-aws-dart](https://github.com/katallaxie/serverless-aws-dart) template. 67 | 68 | ```bash 69 | $ npx serverless install \ 70 | --url https://github.com/katallaxie/serverless-aws-dart \ 71 | --name hello 72 | ``` 73 | 74 | Every [serverless workflow command](https://www.serverless.com/framework/docs/providers/aws/guide/workflow/) should work out of the box. The template also includes an example [GitHub actions](https://github.com/features/actions) [configuration file](.github/workflows/main.yml) which can unlock a virtuous cycle of continuous integration and deployment 75 | ( i.e all tests are run on prs and every push to master results in a deployment). 76 | 77 | ### Custom deployment 78 | 79 | The deployment is a manual task right now. We have a [`example/build.sh`](https://github.com/awslabs/aws-lambda-dart-runtime/blob/master/example/build.sh) script which makes the process a bit easier. There are three steps to get your code ready to be shipped. 80 | 81 | 1. Compile your Dart program with `dart2native main.dart -o bootstrap` 82 | 2. Create a `.zip` file with `zip lambda.zip bootstrap` 83 | 3. Upload the `lambda.zip` to a S3 bucket or use the [AWS CLI](https://aws.amazon.com/cli) to upload it 84 | 85 | > again, you have to build this on Linux, because `dart2native` does not support cross-compiling 86 | 87 | When you created your function and upload it via the the console. Please, replace `arn:aws:iam::xxx:xxx` with the role you created for your lambda. 88 | 89 | ```bash 90 | aws lambda create-function --function-name dartTest \ 91 | --handler hello.apigateway \ 92 | --zip-file fileb://./lambda.zip \ 93 | --runtime provided \ 94 | --role arn:aws:iam::xxx:xxx \ 95 | --environment Variables={DART_BACKTRACE=1} \ 96 | --tracing-config Mode=Active 97 | ``` 98 | 99 | Updating a function is a fairly easy task. Rebuild your `lambda.zip` package and execute the following command. 100 | 101 | ```bash 102 | aws lambda update-function-code --function-name dartTest --zip-file fileb://./lambda.zip 103 | 104 | ``` 105 | 106 | ## Events 107 | 108 | There are a number of events that come with the Dart Runtime. 109 | 110 | - Application Load Balancer 111 | - Alexa 112 | - API Gateway 113 | - AppSync 114 | - Cloudwatch 115 | - Cognito 116 | - DynamoDB 117 | - Kinesis 118 | - S3 119 | - SQS 120 | 121 | You can also register custom events. 122 | 123 | ```dart 124 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 125 | 126 | class MyCustomEvent { 127 | factory MyCustomEvent.fromJson(Map json) => 128 | MyCustomEvent(json); 129 | 130 | const MyCustomEvent(); 131 | } 132 | 133 | void main() async { 134 | final Handler successHandler = 135 | (context, event) async { 136 | return InvocationResult(context.requestId, "SUCCESS"); 137 | }; 138 | 139 | Runtime() 140 | ..registerEvent((Map json) => MyCustomEvent.from(json)) 141 | ..registerHandler("doesnt.matter", successHandler) 142 | ..invoke(); 143 | } 144 | ``` 145 | 146 | ## Example 147 | 148 | The example in [`main.dart`](https://github.com/awslabs/aws-lambda-dart-runtime/blob/master/example/lib/main.dart) show how the package is intended to be used. Because `dart2native` does not support cross-platform compilation, you can use the [`google/dart`](https://hub.docker.com/r/google/dart/) (:warning: if you are on `Linux` you can ignore this) container to build the project. The `build.sh` script automates the build process in the container. 149 | 150 | ``` 151 | # will build the binary in the container 152 | cd example; docker run -v $PWD:/app --entrypoint app/build.sh google/dart && zip lambda.zip bootstrap && rm bootstrap 153 | ``` 154 | 155 | You will see the `lambda.zip` which you can upload manually, or use the client of your choice. 156 | 157 | What you see in the example is an example of the interface to the Dart Runtime that we created. 158 | 159 | You will have to make `aws_lambda_dart_runtime` a dependency of your project. 160 | 161 | ``` 162 | ... 163 | dependencies: 164 | aws_lambda_dart_runtime: 165 | ... 166 | ``` 167 | 168 | We support using multiple handlers in one executable. The following example shows to register one handler. 169 | 170 | ```dart 171 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 172 | 173 | void main() async { 174 | /// This demo's handling an API Gateway request. 175 | final Handler helloApiGateway = (context, event) async { 176 | final response = {"message": "hello ${context.requestId}"}; 177 | 178 | /// it returns an encoded response to the gateway 179 | return InvocationResult( 180 | context.requestId, AwsApiGatewayResponse.fromJson(response)); 181 | }; 182 | 183 | /// The Runtime is a singleton. You can define the handlers as you wish. 184 | Runtime() 185 | ..registerHandler("hello.apigateway", helloApiGateway) 186 | ..invoke(); 187 | } 188 | ``` 189 | 190 | This example registers the `hello.apigateway` handler with the function to execute for this handler. The handler function is typed to receive a [Amazon API Gateway Event](https://aws.amazon.com/api-gateway) and it returns a response to the invoking gateway. We support many other [events](#events). Handler functions get a `Context` injected with the needed information about the invocation. You can also register your own custom events via `Runtime.registerEvent(Handler)` (see [events](#events)). 191 | 192 | ## Limitations 193 | 194 | - No Just-in-time (JIT) support 195 | - Requires Dart `>= 2.6` 196 | - No cross-platform compile support (see [#28617](https://github.com/dart-lang/sdk/issues/28617)). 197 | 198 | ## Development 199 | 200 | If you want to use the [Repository](https://github.com/awslabs/aws-lambda-dart-runtime.git) directly you can clone it and overwrite the dependency in your `pubspec.yaml` as follows. 201 | 202 | ```yaml 203 | dependency_overrides: 204 | aws_lambda_dart_runtime: 205 | path: 206 | ``` 207 | 208 | The [`data`](https://github.com/aws-lambda-dart-runtime/data) folder contains examples of the used events. We use this to run our tests, but you can also use them to implement new features. If you want to request the processing of a new event, you may provide a payload here. 209 | 210 | ```bash 211 | # run the tests 212 | pub run test 213 | ``` 214 | 215 | ## License 216 | 217 | [Apache 2.0](/LICENSE) 218 | 219 | We :blue_heart: Dart. 220 | -------------------------------------------------------------------------------- /dart_test.yaml: -------------------------------------------------------------------------------- 1 | tags: 2 | presubmit-only: 3 | skip: "Should only be run during presubmit" 4 | -------------------------------------------------------------------------------- /data/apigateway_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "/test/hello", 3 | "headers": { 4 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 5 | "Accept-Encoding": "gzip, deflate, lzma, sdch, br", 6 | "Accept-Language": "en-US,en;q=0.8", 7 | "CloudFront-Forwarded-Proto": "https", 8 | "CloudFront-Is-Desktop-Viewer": "true", 9 | "CloudFront-Is-Mobile-Viewer": "false", 10 | "CloudFront-Is-SmartTV-Viewer": "false", 11 | "CloudFront-Is-Tablet-Viewer": "false", 12 | "CloudFront-Viewer-Country": "US", 13 | "Host": "wt6mne2s9k.execute-api.us-west-2.amazonaws.com", 14 | "Upgrade-Insecure-Requests": "1", 15 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48", 16 | "Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)", 17 | "X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==", 18 | "X-Forwarded-For": "192.168.100.1, 192.168.1.1", 19 | "X-Forwarded-Port": "443", 20 | "X-Forwarded-Proto": "https" 21 | }, 22 | "pathParameters": { 23 | "proxy": "hello" 24 | }, 25 | "requestContext": { 26 | "accountId": "123456789012", 27 | "resourceId": "us4z18", 28 | "stage": "test", 29 | "requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9", 30 | "identity": { 31 | "cognitoIdentityPoolId": "", 32 | "accountId": "", 33 | "cognitoIdentityId": "", 34 | "caller": "", 35 | "apiKey": "", 36 | "sourceIp": "192.168.100.1", 37 | "cognitoAuthenticationType": "", 38 | "cognitoAuthenticationProvider": "", 39 | "userArn": "", 40 | "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48", 41 | "user": "" 42 | }, 43 | "resourcePath": "/{proxy+}", 44 | "httpMethod": "POST", 45 | "apiId": "wt6mne2s9k" 46 | }, 47 | "body": "{\"foo\":\"bar\"}", 48 | "resource": "/{proxy+}", 49 | "httpMethod": "GET", 50 | "queryStringParameters": { 51 | "name": "me" 52 | }, 53 | "stageVariables": { 54 | "stageVarName": "stageVarValue" 55 | } 56 | } -------------------------------------------------------------------------------- /data/cloudwatch_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c", 3 | "detail-type": "Scheduled Event", 4 | "source": "aws.events", 5 | "account": "1234567890", 6 | "time": "1970-01-01T00:00:00Z", 7 | "region": "eu-west-1", 8 | "resources": [ 9 | "arn:aws:events:eu-west-1:123456789012:rule/ExampleRule" 10 | ], 11 | "detail": {} 12 | } -------------------------------------------------------------------------------- /data/cloudwatch_log_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "awslogs": { 3 | "data": "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA==" 4 | } 5 | } -------------------------------------------------------------------------------- /data/cognito_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "triggerSource": "CustomMessage_SignUp/CustomMessage_ResendCode/CustomMessage_ForgotPassword/CustomMessage_VerifyUserAttribute", 4 | "region": "eu-west-1", 5 | "userPoolId": "1234567", 6 | "userName": "foo", 7 | "callerContext": { 8 | "awsSdk": "1.0", 9 | "clientId": "bar" 10 | }, 11 | "request": { 12 | "userAttributes": { 13 | "phone_number_verified": false, 14 | "email_verified": true 15 | }, 16 | "codeParameter": "12345678" 17 | }, 18 | "response": { 19 | "smsMessage": "foo", 20 | "emailMessage": "bar", 21 | "emailSubject": "foo" 22 | } 23 | } -------------------------------------------------------------------------------- /data/dynamodb_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "eventID": "c4ca4238a0b923820dcc509a6f75849b", 5 | "eventName": "INSERT", 6 | "eventVersion": "1.1", 7 | "eventSource": "aws:dynamodb", 8 | "awsRegion": "eu-west-1", 9 | "dynamodb": { 10 | "Keys": { 11 | "Id": { 12 | "N": "101" 13 | } 14 | }, 15 | "NewImage": { 16 | "Message": { 17 | "S": "New item!" 18 | }, 19 | "Id": { 20 | "N": "101" 21 | } 22 | }, 23 | "ApproximateCreationDateTime": 1428537600, 24 | "SequenceNumber": "4421584500000000017450439091", 25 | "SizeBytes": 26, 26 | "StreamViewType": "NEW_AND_OLD_IMAGES" 27 | }, 28 | "eventSourceARN": "arn:aws:dynamodb:eu-west-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /data/kinesis_data_firehose_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "invocationId": "invocationIdExample", 3 | "deliveryStreamArn": "arn:aws:kinesis:EXAMPLE", 4 | "region": "eu-west-1", 5 | "records": [ 6 | { 7 | "recordId": "49546986683135544286507457936321625675700192471156785154", 8 | "approximateArrivalTimestamp": 1495072949453, 9 | "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /data/kinesis_data_stream_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "kinesis": { 5 | "partitionKey": "partitionKey-03", 6 | "kinesisSchemaVersion": "1.0", 7 | "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=", 8 | "sequenceNumber": "49545115243490985018280067714973144582180062593244200961", 9 | "approximateArrivalTimestamp": 1428537600 10 | }, 11 | "eventSource": "aws:kinesis", 12 | "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961", 13 | "invokeIdentityArn": "arn:aws:iam::EXAMPLE", 14 | "eventVersion": "1.0", 15 | "eventName": "aws:kinesis:record", 16 | "eventSourceARN": "arn:aws:kinesis:EXAMPLE", 17 | "awsRegion": "eu-west-1" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /data/s3_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "eventVersion": "2.0", 5 | "eventSource": "aws:s3", 6 | "awsRegion": "eu-west-1", 7 | "eventTime": "1970-01-01T00:00:00.000Z", 8 | "eventName": "ObjectCreated:Put", 9 | "userIdentity": { 10 | "principalId": "EXAMPLE" 11 | }, 12 | "requestParameters": { 13 | "sourceIPAddress": "127.0.0.1" 14 | }, 15 | "responseElements": { 16 | "x-amz-request-id": "EXAMPLE123456789", 17 | "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH" 18 | }, 19 | "s3": { 20 | "s3SchemaVersion": "1.0", 21 | "configurationId": "testConfigRule", 22 | "bucket": { 23 | "name": "example-bucket", 24 | "ownerIdentity": { 25 | "principalId": "EXAMPLE" 26 | }, 27 | "arn": "arn:aws:s3:::example-bucket" 28 | }, 29 | "object": { 30 | "key": "test/key", 31 | "size": 1024, 32 | "eTag": "0123456789abcdef0123456789abcdef", 33 | "sequencer": "0A1B2C3D4E5F678901" 34 | } 35 | } 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /data/sqs_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78", 5 | "receiptHandle": "MessageReceiptHandle", 6 | "body": "Hello from SQS!", 7 | "attributes": { 8 | "ApproximateReceiveCount": "1", 9 | "SentTimestamp": "1523232000000", 10 | "SenderId": "123456789012", 11 | "ApproximateFirstReceiveTimestamp": "1523232000001" 12 | }, 13 | "messageAttributes": {}, 14 | "md5OfBody": "7b270e59b47ff90a553787216d55d91d", 15 | "eventSource": "aws:sqs", 16 | "eventSourceARN": "arn:aws:sqs:eu-west-1:123456789012:MyQueue", 17 | "awsRegion": "eu-west-1" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /example/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # setting cacke folder 4 | export PUB_CACHE=/tmp 5 | 6 | # creating a temporary directory for the build 7 | cd $(mktemp -d) 8 | 9 | # pub the app 10 | cp -Rp /app/* . 11 | ls -l 12 | # setup deps 13 | /usr/lib/dart/bin/pub get 14 | # build the binary 15 | /usr/lib/dart/bin/dart2native lib/main.dart -o bootstrap 16 | # move this back to app 17 | mv bootstrap /app/bootstrap -------------------------------------------------------------------------------- /example/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 2 | 3 | void main() async { 4 | /// This demo's handling an API Gateway request. 5 | final Handler helloApiGateway = (context, event) async { 6 | final response = {"message": "hello ${context.requestId}"}; 7 | 8 | /// it returns an encoded response to the gateway 9 | return InvocationResult( 10 | context.requestId, AwsApiGatewayResponse.fromJson(response)); 11 | }; 12 | 13 | /// The Runtime is a singleton. You can define the handlers as you wish. 14 | Runtime() 15 | ..registerHandler("hello.apigateway", helloApiGateway) 16 | ..invoke(); 17 | } 18 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | 3 | environment: 4 | sdk: ">=2.6.0 <3.0.0" 5 | 6 | dependencies: 7 | aws_lambda_dart_runtime: 8 | git: https://github.com/awslabs/aws-lambda-dart-runtime.git 9 | 10 | dev_dependencies: 11 | build_runner: 12 | -------------------------------------------------------------------------------- /example/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: "2010-09-09" 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: A sample SAM template for deploying Lambda functions. 4 | 5 | Resources: 6 | # Details about the myDateTimeFunction Lambda function 7 | myExampleFunction: 8 | Type: AWS::Serverless::Function 9 | Properties: 10 | Handler: hello.apigateway 11 | Runtime: Provided 12 | # Instructs your myDateTimeFunction is published to an alias named "live". 13 | AutoPublishAlias: live 14 | # Grants this function permission to call lambda:InvokeFunction 15 | Policies: 16 | - Version: "2012-10-17" 17 | Statement: 18 | - Effect: "Allow" 19 | Action: 20 | - "lambda:InvokeFunction" 21 | Resource: "*" 22 | DeploymentPreference: 23 | # Specifies the deployment configuration 24 | Type: Linear10PercentEvery1Minute 25 | # Specifies Lambda functions for deployment lifecycle hooks 26 | Hooks: 27 | PreTraffic: !Ref beforeAllowTraffic 28 | PostTraffic: !Ref afterAllowTraffic 29 | -------------------------------------------------------------------------------- /lib/aws_lambda_dart_runtime.dart: -------------------------------------------------------------------------------- 1 | export 'client/client.dart'; 2 | export 'events/alb_event.dart'; 3 | export 'events/alexa_event.dart'; 4 | export 'events/apigateway_event.dart'; 5 | export 'events/appsync_event.dart'; 6 | export 'events/cloudwatch_event.dart'; 7 | export 'events/cloudwatch_log_event.dart'; 8 | export 'events/cognito_event.dart'; 9 | export 'events/dynamodb_event.dart'; 10 | export 'events/kinesis_data_firehose_event.dart'; 11 | export 'events/kinesis_data_stream_event.dart'; 12 | export 'events/s3_event.dart'; 13 | export 'events/sqs_event.dart'; 14 | export 'runtime/event.dart'; 15 | export 'runtime/exception.dart'; 16 | export 'runtime/runtime.dart'; 17 | -------------------------------------------------------------------------------- /lib/client/client.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:async'; 3 | import 'dart:convert'; 4 | 5 | /// Next invocation data wraps the data from the 6 | /// invocation endpoint of the Lambda Runtime Interface. 7 | class NextInvocation { 8 | static const runtimeRequestId = 'lambda-runtime-aws-request-id'; 9 | static const runtimeDeadlineMs = 'lambda-runtime-aws-deadline-ms'; 10 | static const runtimeInvokedFunctionArn = 11 | 'lambda-runtime-invoked-functions-arn'; 12 | static const runtimeTraceId = 'lambda-runtime-trace-id'; 13 | static const runtimeClientContext = 'lambda-runtime-client-context'; 14 | static const runtimeCognitoIdentity = 'lambda-runtime-cognito-identity'; 15 | 16 | /// Raw response of invocation data that we received. 17 | final Map response; 18 | 19 | /// Request Id is the identifier of the request. 20 | final String requestId; 21 | 22 | /// Deadline milliseconds is the setting for ultimate cancelation of the invocation. 23 | final String deadlineMs; 24 | 25 | /// Invoked function ARN is the identifier of the function. 26 | final String invokedFunctionArn; 27 | 28 | /// Tracing id is the identifier for tracing like X-Ray. 29 | final String traceId; 30 | 31 | /// Client context is the context that is provided to the function. 32 | final String clientContext; 33 | 34 | /// Cognito identity is the identity that maybe is used for authorizing the request. 35 | final String cognitoIdentity; 36 | 37 | /// Digesting a [HttpClientResponse] into a [NextInvocation]. 38 | static Future fromResponse( 39 | HttpClientResponse response) async { 40 | return NextInvocation( 41 | response: json 42 | .decode((await response.transform(Utf8Decoder()).toList()).first), 43 | requestId: response.headers.value(runtimeRequestId), 44 | deadlineMs: response.headers.value(runtimeDeadlineMs), 45 | invokedFunctionArn: response.headers.value(runtimeInvokedFunctionArn), 46 | traceId: response.headers.value(runtimeTraceId), 47 | clientContext: response.headers.value(runtimeClientContext), 48 | cognitoIdentity: response.headers.value(runtimeCognitoIdentity)); 49 | } 50 | 51 | const NextInvocation( 52 | {this.requestId, 53 | this.deadlineMs, 54 | this.traceId, 55 | this.clientContext, 56 | this.cognitoIdentity, 57 | this.invokedFunctionArn, 58 | this.response}) 59 | : assert(requestId != null); 60 | } 61 | 62 | /// Invocation result is the result that the invoked handler 63 | /// returns and is posted to the Lambda Runtime Interface. 64 | class InvocationResult { 65 | /// The Id of the request in the Lambda Runtime Interface. 66 | /// This is used to associate the result of the handler with 67 | /// the triggered execution in the Runtime. 68 | final String requestId; 69 | 70 | /// The result of the handler execution. This can contain 71 | /// any json-encodable data type. 72 | final dynamic body; 73 | 74 | const InvocationResult(this.requestId, this.body) 75 | : assert(requestId != null), 76 | assert(body != null); 77 | } 78 | 79 | /// Invocation error occurs when there has been an 80 | /// error in the invocation of a handlers. It dynamically 81 | /// wraps the inner [error] and attaches the [requestId] to 82 | /// track it along the event. 83 | class InvocationError { 84 | /// The error that catched during the invocation and 85 | /// which is posted to the Lambda Runtime Interface. 86 | final dynamic error; 87 | 88 | /// StackTrace ... 89 | final StackTrace stackTrace; 90 | 91 | /// Extracts the [InvocationError] data into a JSON 92 | /// representation for the Runtime Interface. 93 | Map toJson() => { 94 | 'errorMessage': error.toString(), 95 | 'errorType': "InvocationError", 96 | 'stackTrace': this.stackTrace.toString() 97 | }; 98 | 99 | const InvocationError(this.error, this.stackTrace); 100 | } 101 | 102 | /// Client is the Lambda Runtime Interface client. 103 | /// It is implemented as a singleton whereby [Client.instance] 104 | /// always returns the already instantiated client. 105 | class Client { 106 | HttpClient _client; 107 | 108 | static final Client _singleton = Client._internal(); 109 | 110 | factory Client() { 111 | return _singleton; 112 | } 113 | 114 | Client._internal() { 115 | _client = HttpClient(); 116 | } 117 | 118 | static const runtimeApiVersion = '2018-06-01'; 119 | static final runtimeApi = Platform.environment["AWS_LAMBDA_RUNTIME_API"]; 120 | 121 | /// Get the next inovation from the AWS Lambda Runtime Interface (see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html). 122 | Future getNextInvocation() async { 123 | final request = await _client.getUrl(Uri.parse( 124 | 'http://${runtimeApi}/${runtimeApiVersion}/runtime/invocation/next')); 125 | final response = await request.close(); 126 | return NextInvocation.fromResponse(response); 127 | } 128 | 129 | /// Post the invocation response to the AWS Lambda Runtime Interface. 130 | Future postInvocationResponse( 131 | InvocationResult result) async { 132 | final request = await _client.postUrl( 133 | Uri.parse( 134 | 'http://${runtimeApi}/${runtimeApiVersion}/runtime/invocation/${result.requestId}/response', 135 | ), 136 | ); 137 | request.add( 138 | utf8.encode( 139 | json.encode(result.body), 140 | ), 141 | ); 142 | 143 | return await request.close(); 144 | } 145 | 146 | /// Post an invocation error to the AWS Lambda Runtime Interface. 147 | /// It takes in an [InvocationError] and the [requestId]. The [requestId] 148 | /// is used to map the error to the execution. 149 | Future postInvocationError( 150 | String requestId, InvocationError err) async { 151 | final request = await _client.postUrl( 152 | Uri.parse( 153 | 'http://${runtimeApi}/${runtimeApiVersion}/runtime/invocation/$requestId/error', 154 | ), 155 | ); 156 | request.add( 157 | utf8.encode( 158 | json.encode(err) 159 | ) 160 | ); 161 | 162 | return await request.close(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /lib/events/alb_event.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | part 'alb_event.g.dart'; 6 | 7 | /// Event send by an Application Load Balancer to the 8 | /// invocation to the Lambda. 9 | @JsonSerializable() 10 | class AwsALBEvent { 11 | /// Request context in which this request is executed. 12 | /// For the ELB this is the ARN of the target group. 13 | @JsonKey() 14 | final AwsALBEventContext context; 15 | 16 | /// HTTP method that is used to trigger the invocation of the Lambda. 17 | @JsonKey() 18 | final String httpMethod; 19 | 20 | /// The URI that is accessed to trigger the invocation of the Lambda. 21 | @JsonKey() 22 | final String path; 23 | 24 | /// HTTP headers that are send with the request to the load balancer. 25 | @JsonKey() 26 | final Map headers; 27 | 28 | /// The query parameters for the request to the load balancer. 29 | @JsonKey() 30 | final Map queryStringParameters; 31 | 32 | /// Body of the request. This can be data that is send with the POST 33 | /// to the request. 34 | @JsonKey() 35 | final String body; 36 | 37 | /// Singals that the request is Base64 encoded. 38 | @JsonKey() 39 | final bool isBase64Encoded; 40 | 41 | factory AwsALBEvent.fromJson(Map json) => 42 | _$AwsALBEventFromJson(json); 43 | 44 | Map toJson() => _$AwsALBEventToJson(this); 45 | 46 | const AwsALBEvent( 47 | {this.context, 48 | this.httpMethod, 49 | this.path, 50 | this.headers, 51 | this.queryStringParameters, 52 | this.body, 53 | this.isBase64Encoded}); 54 | } 55 | 56 | /// Response for a request from an Application Load Balancer. 57 | /// It has to have a [statusCode], [headers] and a [body]. 58 | /// They should reflect the informationen needed here. 59 | class AwsALBResponse { 60 | /// The body of the HTTP Response send from the API Gateway to the client. 61 | String body; 62 | 63 | /// Indicates if the [body] is Base64 encoded or not. By default is `false`. 64 | bool isBase64Encoded; 65 | 66 | /// HTTP status code of the response of the API Gateway to the client. 67 | /// The default status code is `200 OK`. 68 | int statusCode; 69 | 70 | /// Description of the send HTTP status code. 71 | String statusDescription; 72 | 73 | /// The HTTP headers that should be send with the response to the client. 74 | Map headers; 75 | 76 | /// Returns the JSON representation of the response. This is called by 77 | /// the JSON encoder to produce the response. 78 | Map toJson() => { 79 | 'body': body, 80 | 'isBase64Encoded': isBase64Encoded, 81 | 'statusCode': statusCode, 82 | 'statusDescription': statusDescription, 83 | 'headers': headers 84 | }; 85 | 86 | factory AwsALBResponse.fromString( 87 | String body, { 88 | bool isBase64Encoded, 89 | int statusCode, 90 | String statusDescription, 91 | Map headers, 92 | }) { 93 | return AwsALBResponse( 94 | body: body, 95 | headers: headers, 96 | isBase64Encoded: isBase64Encoded, 97 | statusCode: statusCode, 98 | statusDescription: statusDescription); 99 | } 100 | 101 | /// The Response that should be returned to the Application Load Balancer. 102 | /// It is constructed with some default values for the optional parameters. 103 | AwsALBResponse( 104 | {body, headers, isBase64Encoded, statusCode, statusDescription}) { 105 | this.body = body ?? ''; 106 | this.isBase64Encoded = isBase64Encoded ?? false; 107 | this.headers = headers ?? {"Content-Type": "text/html; charset=utf-8"}; 108 | this.statusCode = statusCode ?? HttpStatus.ok; 109 | this.statusDescription = statusDescription ?? "200 OK"; 110 | } 111 | } 112 | 113 | /// AWS ALB Event Request Context ... 114 | @JsonSerializable() 115 | class AwsALBEventContext { 116 | factory AwsALBEventContext.fromJson(Map json) => 117 | _$AwsALBEventContextFromJson(json); 118 | 119 | Map toJson() => _$AwsALBEventContextToJson(this); 120 | 121 | const AwsALBEventContext(); 122 | } 123 | -------------------------------------------------------------------------------- /lib/events/alb_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'alb_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsALBEvent _$AwsALBEventFromJson(Map json) { 10 | return AwsALBEvent( 11 | context: json['context'] == null 12 | ? null 13 | : AwsALBEventContext.fromJson(json['context'] as Map), 14 | httpMethod: json['httpMethod'] as String, 15 | path: json['path'] as String, 16 | headers: json['headers'] as Map, 17 | queryStringParameters: 18 | json['queryStringParameters'] as Map, 19 | body: json['body'] as String, 20 | isBase64Encoded: json['isBase64Encoded'] as bool, 21 | ); 22 | } 23 | 24 | Map _$AwsALBEventToJson(AwsALBEvent instance) => 25 | { 26 | 'context': instance.context, 27 | 'httpMethod': instance.httpMethod, 28 | 'path': instance.path, 29 | 'headers': instance.headers, 30 | 'queryStringParameters': instance.queryStringParameters, 31 | 'body': instance.body, 32 | 'isBase64Encoded': instance.isBase64Encoded, 33 | }; 34 | 35 | AwsALBEventContext _$AwsALBEventContextFromJson(Map json) { 36 | return AwsALBEventContext(); 37 | } 38 | 39 | Map _$AwsALBEventContextToJson(AwsALBEventContext instance) => 40 | {}; 41 | -------------------------------------------------------------------------------- /lib/events/alexa_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'alexa_event.g.dart'; 4 | 5 | /// Header are meta information about the event. 6 | @JsonSerializable() 7 | class AwsAlexaEventHeader { 8 | /// Version of the send payload. 9 | @JsonKey() 10 | final String payloadVersion; 11 | 12 | /// Namespace of the event. 13 | @JsonKey() 14 | final String namespace; 15 | 16 | /// Name of the event 17 | @JsonKey() 18 | final String name; 19 | 20 | factory AwsAlexaEventHeader.fromJson(Map json) => 21 | _$AwsAlexaEventHeaderFromJson(json); 22 | 23 | Map toJson() => _$AwsAlexaEventHeaderToJson(this); 24 | 25 | const AwsAlexaEventHeader({this.namespace, this.payloadVersion, this.name}); 26 | } 27 | 28 | /// Event send by an Application Load Balancer to the 29 | /// invocation to the Lambda. 30 | @JsonSerializable() 31 | class AwsAlexaEvent { 32 | /// Meta information about the event. 33 | @JsonKey() 34 | final AwsAlexaEventHeader header; 35 | 36 | /// Payload of the event send by Alexa. 37 | @JsonKey() 38 | final Map payload; 39 | 40 | factory AwsAlexaEvent.fromJson(Map json) => 41 | _$AwsAlexaEventFromJson(json); 42 | 43 | Map toJson() => _$AwsAlexaEventToJson(this); 44 | 45 | const AwsAlexaEvent({this.header, this.payload}); 46 | } 47 | -------------------------------------------------------------------------------- /lib/events/alexa_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'alexa_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsAlexaEventHeader _$AwsAlexaEventHeaderFromJson(Map json) { 10 | return AwsAlexaEventHeader( 11 | namespace: json['namespace'] as String, 12 | payloadVersion: json['payloadVersion'] as String, 13 | name: json['name'] as String, 14 | ); 15 | } 16 | 17 | Map _$AwsAlexaEventHeaderToJson( 18 | AwsAlexaEventHeader instance) => 19 | { 20 | 'payloadVersion': instance.payloadVersion, 21 | 'namespace': instance.namespace, 22 | 'name': instance.name, 23 | }; 24 | 25 | AwsAlexaEvent _$AwsAlexaEventFromJson(Map json) { 26 | return AwsAlexaEvent( 27 | header: json['header'] == null 28 | ? null 29 | : AwsAlexaEventHeader.fromJson(json['header'] as Map), 30 | payload: json['payload'] as Map, 31 | ); 32 | } 33 | 34 | Map _$AwsAlexaEventToJson(AwsAlexaEvent instance) => 35 | { 36 | 'header': instance.header, 37 | 'payload': instance.payload, 38 | }; 39 | -------------------------------------------------------------------------------- /lib/events/apigateway_event.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:convert'; 3 | 4 | import 'package:json_annotation/json_annotation.dart'; 5 | 6 | part 'apigateway_event.g.dart'; 7 | 8 | /// API Gateway Response contains the data for a response 9 | /// to the API Gateway. It contains the [body] of the HTTP response. 10 | /// It also contains a HTTP Status Code which by default is `200`. 11 | /// Furthermore it indicates if the [body] is Base64 encoded or not. 12 | class AwsApiGatewayResponse { 13 | /// The body of the HTTP Response send from the API Gateway to the client. 14 | String body; 15 | 16 | /// Indicates if the [body] is Base64 encoded or not. By default is `false`. 17 | bool isBase64Encoded; 18 | 19 | // HTTP Status Code of the response of the API Gateway to the client. 20 | int statusCode; 21 | 22 | /// The HTTP headers that should be send with the response to the client. 23 | Map headers; 24 | 25 | /// Returns the JSON representation of the response. This is called by 26 | /// the JSON encoder to produce the response. 27 | Map toJson() => { 28 | 'body': body, 29 | 'isBase64Encoded': isBase64Encoded, 30 | 'statusCode': statusCode, 31 | 'headers': headers 32 | }; 33 | 34 | /// The factory creates a new [AwsApiGatewayResponse] from JSON. 35 | /// It optionally accepts the Base64 encoded flag and a HTTP Status Code 36 | /// for the response. 37 | factory AwsApiGatewayResponse.fromJson(Map body, 38 | {bool isBase64Encoded, int statusCode, Map headers}) { 39 | return AwsApiGatewayResponse( 40 | body: json.encode(body), 41 | isBase64Encoded: isBase64Encoded, 42 | headers: headers, 43 | statusCode: statusCode); 44 | } 45 | 46 | /// The Response that should be returned by the API Gateway for the 47 | /// Lambda invocation. It has a [body] which reflects the body of the HTTP Response. 48 | /// But also it signals if the [body] is Base64 encoded and what the HTTP Status Code 49 | /// of the response is. 50 | AwsApiGatewayResponse({ 51 | String body, 52 | bool isBase64Encoded, 53 | Map headers, 54 | int statusCode, 55 | }) { 56 | this.body = body ?? ''; 57 | this.isBase64Encoded = isBase64Encoded ?? false; 58 | this.headers = headers ?? {"Content-Type": "application/json"}; 59 | this.statusCode = statusCode ?? HttpStatus.ok; 60 | } 61 | } 62 | 63 | /// API Gateway Event ... 64 | @JsonSerializable() 65 | class AwsApiGatewayEvent { 66 | /// URL Path ... 67 | @JsonKey() 68 | final String path; 69 | 70 | /// Resource ... 71 | @JsonKey() 72 | final String resource; 73 | 74 | /// HTTP Method ... 75 | @JsonKey() 76 | final String httpMethod; 77 | 78 | /// Body ... 79 | @JsonKey() 80 | final String body; 81 | 82 | /// Headers ... 83 | @JsonKey() 84 | final AwsApiGatewayEventHeaders headers; 85 | 86 | /// Path Parameters ... 87 | @JsonKey() 88 | final Map pathParameters; 89 | 90 | /// Query String Parameters ... 91 | @JsonKey() 92 | final Map queryStringParameters; 93 | 94 | /// Stage Variables ... 95 | @JsonKey() 96 | final Map stageVariables; 97 | 98 | /// Request Context ... 99 | final AwsApiGatewayEventRequestContext requestContext; 100 | 101 | factory AwsApiGatewayEvent.fromJson(Map json) => 102 | _$AwsApiGatewayEventFromJson(json); 103 | 104 | Map toJson() => _$AwsApiGatewayEventToJson(this); 105 | 106 | const AwsApiGatewayEvent( 107 | {this.resource, 108 | this.path, 109 | this.httpMethod, 110 | this.body, 111 | this.headers, 112 | this.queryStringParameters, 113 | this.stageVariables, 114 | this.requestContext, 115 | this.pathParameters}); 116 | } 117 | 118 | /// API Gateway Event Headers ... 119 | @JsonSerializable() 120 | class AwsApiGatewayEventHeaders { 121 | @JsonKey(name: "Accept") 122 | final String accept; 123 | 124 | @JsonKey(name: "Accept-Encoding") 125 | final String acceptEncoding; 126 | 127 | @JsonKey(name: "CloudFront-Forwarded-Proto") 128 | final String cloudfrontForwardProto; 129 | 130 | @JsonKey(name: "CloudFront-Is-Desktop-Viewer") 131 | final String cloudfrontIsDesktopViewer; 132 | 133 | @JsonKey(name: "CloudFront-Is-Mobile-Viewer") 134 | final String cloudfrontIsMobileViewer; 135 | 136 | @JsonKey(name: "CloudFront-Is-SmartTV-Viewer") 137 | final String cloudfrontIsSmartTvViewer; 138 | 139 | @JsonKey(name: "CloudFront-Is-Tablet-Viewer") 140 | final String cloudfrontIsTabletViewer; 141 | 142 | @JsonKey(name: "CloudFront-Viewer-Country") 143 | final String cloudfrontViewerCountry; 144 | 145 | @JsonKey(name: "Host") 146 | final String host; 147 | 148 | @JsonKey(name: "Upgrade-Insecure-Requests") 149 | final String upgradeInsecureRequests; 150 | 151 | @JsonKey(name: "User-Agent") 152 | final String userAgent; 153 | 154 | @JsonKey(name: "Via") 155 | final String via; 156 | 157 | @JsonKey(name: "X-Amz-Cf-Id") 158 | final String xAmzCfId; 159 | 160 | @JsonKey(name: "X-Forwarded-For") 161 | final String xForwardedFor; 162 | 163 | @JsonKey(name: "X-Forwarded-Port") 164 | final String xForwardedPort; 165 | 166 | @JsonKey(name: "X-Forwarded-Proto") 167 | final String xForwardedProto; 168 | 169 | @JsonKey(name: "Cache-Control") 170 | final String cacheControl; 171 | 172 | @JsonKey(name: "X-Amzn-Trace-Id") 173 | final String xAmznTraceId; 174 | 175 | @JsonKey(ignore: true) 176 | Map raw; 177 | 178 | factory AwsApiGatewayEventHeaders.fromJson(Map json) { 179 | final event = _$AwsApiGatewayEventHeadersFromJson(json); 180 | event.raw = json; 181 | 182 | return event; 183 | } 184 | 185 | Map toJson() => _$AwsApiGatewayEventHeadersToJson(this); 186 | 187 | AwsApiGatewayEventHeaders( 188 | {this.accept, 189 | this.acceptEncoding, 190 | this.cloudfrontIsDesktopViewer, 191 | this.cloudfrontIsMobileViewer, 192 | this.cloudfrontIsSmartTvViewer, 193 | this.cloudfrontForwardProto, 194 | this.cloudfrontIsTabletViewer, 195 | this.cloudfrontViewerCountry, 196 | this.upgradeInsecureRequests, 197 | this.cacheControl, 198 | this.host, 199 | this.via, 200 | this.userAgent, 201 | this.xAmzCfId, 202 | this.xAmznTraceId, 203 | this.xForwardedFor, 204 | this.xForwardedPort, 205 | this.xForwardedProto}); 206 | } 207 | 208 | /// API Gateway Event Request Context ... 209 | @JsonSerializable() 210 | class AwsApiGatewayEventRequestContext { 211 | @JsonKey() 212 | final String accountId; 213 | 214 | @JsonKey() 215 | final String resourceId; 216 | 217 | @JsonKey() 218 | final String stage; 219 | 220 | @JsonKey() 221 | final String requestId; 222 | 223 | @JsonKey() 224 | final String resourcePath; 225 | 226 | @JsonKey() 227 | final String httpMethod; 228 | 229 | @JsonKey() 230 | final String apiId; 231 | 232 | factory AwsApiGatewayEventRequestContext.fromJson( 233 | Map json) => 234 | _$AwsApiGatewayEventRequestContextFromJson(json); 235 | 236 | Map toJson() => 237 | _$AwsApiGatewayEventRequestContextToJson(this); 238 | 239 | const AwsApiGatewayEventRequestContext( 240 | {this.accountId, 241 | this.resourceId, 242 | this.stage, 243 | this.requestId, 244 | this.resourcePath, 245 | this.httpMethod, 246 | this.apiId}); 247 | } 248 | 249 | /// API Gateway Event Identity 250 | @JsonSerializable() 251 | class AwsApiGatewayEventRequestContextIdentity { 252 | @JsonKey() 253 | final String cognitoIdentityPoolId; 254 | 255 | @JsonKey() 256 | final String accountId; 257 | 258 | @JsonKey() 259 | final String cognitoIdentityId; 260 | 261 | @JsonKey() 262 | final String caller; 263 | 264 | @JsonKey() 265 | final String apiKey; 266 | 267 | @JsonKey() 268 | final String sourceIp; 269 | 270 | @JsonKey() 271 | final String cognitoAuthenticationType; 272 | 273 | @JsonKey() 274 | final String cognitoAuthenticationProvider; 275 | 276 | @JsonKey() 277 | final String userArn; 278 | 279 | @JsonKey() 280 | final String userAgent; 281 | 282 | @JsonKey() 283 | final String user; 284 | 285 | factory AwsApiGatewayEventRequestContextIdentity.fromJson( 286 | Map json) => 287 | _$AwsApiGatewayEventRequestContextIdentityFromJson(json); 288 | 289 | Map toJson() => 290 | _$AwsApiGatewayEventRequestContextIdentityToJson(this); 291 | 292 | const AwsApiGatewayEventRequestContextIdentity( 293 | {this.cognitoIdentityPoolId, 294 | this.cognitoAuthenticationProvider, 295 | this.cognitoAuthenticationType, 296 | this.caller, 297 | this.accountId, 298 | this.cognitoIdentityId, 299 | this.apiKey, 300 | this.sourceIp, 301 | this.user, 302 | this.userAgent, 303 | this.userArn}); 304 | } 305 | -------------------------------------------------------------------------------- /lib/events/apigateway_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'apigateway_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsApiGatewayEvent _$AwsApiGatewayEventFromJson(Map json) { 10 | return AwsApiGatewayEvent( 11 | resource: json['resource'] as String, 12 | path: json['path'] as String, 13 | httpMethod: json['httpMethod'] as String, 14 | body: json['body'] as String, 15 | headers: json['headers'] == null 16 | ? null 17 | : AwsApiGatewayEventHeaders.fromJson( 18 | json['headers'] as Map), 19 | queryStringParameters: 20 | json['queryStringParameters'] as Map, 21 | stageVariables: json['stageVariables'] as Map, 22 | requestContext: json['requestContext'] == null 23 | ? null 24 | : AwsApiGatewayEventRequestContext.fromJson( 25 | json['requestContext'] as Map), 26 | pathParameters: json['pathParameters'] as Map, 27 | ); 28 | } 29 | 30 | Map _$AwsApiGatewayEventToJson(AwsApiGatewayEvent instance) => 31 | { 32 | 'path': instance.path, 33 | 'resource': instance.resource, 34 | 'httpMethod': instance.httpMethod, 35 | 'body': instance.body, 36 | 'headers': instance.headers, 37 | 'pathParameters': instance.pathParameters, 38 | 'queryStringParameters': instance.queryStringParameters, 39 | 'stageVariables': instance.stageVariables, 40 | 'requestContext': instance.requestContext, 41 | }; 42 | 43 | AwsApiGatewayEventHeaders _$AwsApiGatewayEventHeadersFromJson( 44 | Map json) { 45 | return AwsApiGatewayEventHeaders( 46 | accept: json['Accept'] as String, 47 | acceptEncoding: json['Accept-Encoding'] as String, 48 | cloudfrontIsDesktopViewer: json['CloudFront-Is-Desktop-Viewer'] as String, 49 | cloudfrontIsMobileViewer: json['CloudFront-Is-Mobile-Viewer'] as String, 50 | cloudfrontIsSmartTvViewer: json['CloudFront-Is-SmartTV-Viewer'] as String, 51 | cloudfrontForwardProto: json['CloudFront-Forwarded-Proto'] as String, 52 | cloudfrontIsTabletViewer: json['CloudFront-Is-Tablet-Viewer'] as String, 53 | cloudfrontViewerCountry: json['CloudFront-Viewer-Country'] as String, 54 | upgradeInsecureRequests: json['Upgrade-Insecure-Requests'] as String, 55 | cacheControl: json['Cache-Control'] as String, 56 | host: json['Host'] as String, 57 | via: json['Via'] as String, 58 | userAgent: json['User-Agent'] as String, 59 | xAmzCfId: json['X-Amz-Cf-Id'] as String, 60 | xAmznTraceId: json['X-Amzn-Trace-Id'] as String, 61 | xForwardedFor: json['X-Forwarded-For'] as String, 62 | xForwardedPort: json['X-Forwarded-Port'] as String, 63 | xForwardedProto: json['X-Forwarded-Proto'] as String, 64 | ); 65 | } 66 | 67 | Map _$AwsApiGatewayEventHeadersToJson( 68 | AwsApiGatewayEventHeaders instance) => 69 | { 70 | 'Accept': instance.accept, 71 | 'Accept-Encoding': instance.acceptEncoding, 72 | 'CloudFront-Forwarded-Proto': instance.cloudfrontForwardProto, 73 | 'CloudFront-Is-Desktop-Viewer': instance.cloudfrontIsDesktopViewer, 74 | 'CloudFront-Is-Mobile-Viewer': instance.cloudfrontIsMobileViewer, 75 | 'CloudFront-Is-SmartTV-Viewer': instance.cloudfrontIsSmartTvViewer, 76 | 'CloudFront-Is-Tablet-Viewer': instance.cloudfrontIsTabletViewer, 77 | 'CloudFront-Viewer-Country': instance.cloudfrontViewerCountry, 78 | 'Host': instance.host, 79 | 'Upgrade-Insecure-Requests': instance.upgradeInsecureRequests, 80 | 'User-Agent': instance.userAgent, 81 | 'Via': instance.via, 82 | 'X-Amz-Cf-Id': instance.xAmzCfId, 83 | 'X-Forwarded-For': instance.xForwardedFor, 84 | 'X-Forwarded-Port': instance.xForwardedPort, 85 | 'X-Forwarded-Proto': instance.xForwardedProto, 86 | 'Cache-Control': instance.cacheControl, 87 | 'X-Amzn-Trace-Id': instance.xAmznTraceId, 88 | }; 89 | 90 | AwsApiGatewayEventRequestContext _$AwsApiGatewayEventRequestContextFromJson( 91 | Map json) { 92 | return AwsApiGatewayEventRequestContext( 93 | accountId: json['accountId'] as String, 94 | resourceId: json['resourceId'] as String, 95 | stage: json['stage'] as String, 96 | requestId: json['requestId'] as String, 97 | resourcePath: json['resourcePath'] as String, 98 | httpMethod: json['httpMethod'] as String, 99 | apiId: json['apiId'] as String, 100 | ); 101 | } 102 | 103 | Map _$AwsApiGatewayEventRequestContextToJson( 104 | AwsApiGatewayEventRequestContext instance) => 105 | { 106 | 'accountId': instance.accountId, 107 | 'resourceId': instance.resourceId, 108 | 'stage': instance.stage, 109 | 'requestId': instance.requestId, 110 | 'resourcePath': instance.resourcePath, 111 | 'httpMethod': instance.httpMethod, 112 | 'apiId': instance.apiId, 113 | }; 114 | 115 | AwsApiGatewayEventRequestContextIdentity 116 | _$AwsApiGatewayEventRequestContextIdentityFromJson( 117 | Map json) { 118 | return AwsApiGatewayEventRequestContextIdentity( 119 | cognitoIdentityPoolId: json['cognitoIdentityPoolId'] as String, 120 | cognitoAuthenticationProvider: 121 | json['cognitoAuthenticationProvider'] as String, 122 | cognitoAuthenticationType: json['cognitoAuthenticationType'] as String, 123 | caller: json['caller'] as String, 124 | accountId: json['accountId'] as String, 125 | cognitoIdentityId: json['cognitoIdentityId'] as String, 126 | apiKey: json['apiKey'] as String, 127 | sourceIp: json['sourceIp'] as String, 128 | user: json['user'] as String, 129 | userAgent: json['userAgent'] as String, 130 | userArn: json['userArn'] as String, 131 | ); 132 | } 133 | 134 | Map _$AwsApiGatewayEventRequestContextIdentityToJson( 135 | AwsApiGatewayEventRequestContextIdentity instance) => 136 | { 137 | 'cognitoIdentityPoolId': instance.cognitoIdentityPoolId, 138 | 'accountId': instance.accountId, 139 | 'cognitoIdentityId': instance.cognitoIdentityId, 140 | 'caller': instance.caller, 141 | 'apiKey': instance.apiKey, 142 | 'sourceIp': instance.sourceIp, 143 | 'cognitoAuthenticationType': instance.cognitoAuthenticationType, 144 | 'cognitoAuthenticationProvider': instance.cognitoAuthenticationProvider, 145 | 'userArn': instance.userArn, 146 | 'userAgent': instance.userAgent, 147 | 'user': instance.user, 148 | }; 149 | -------------------------------------------------------------------------------- /lib/events/appsync_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'appsync_event.g.dart'; 4 | 5 | /// App Sync Event ... 6 | @JsonSerializable() 7 | class AwsAppSyncEvent { 8 | @JsonKey(name: "version") 9 | final String version; 10 | 11 | @JsonKey(name: "operation") 12 | final String operation; 13 | 14 | @JsonKey(name: "payload") 15 | final String payload; 16 | 17 | factory AwsAppSyncEvent.fromJson(Map json) => 18 | _$AwsAppSyncEventFromJson(json); 19 | 20 | Map toJson() => _$AwsAppSyncEventToJson(this); 21 | 22 | const AwsAppSyncEvent({this.version, this.operation, this.payload}); 23 | } 24 | -------------------------------------------------------------------------------- /lib/events/appsync_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'appsync_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsAppSyncEvent _$AwsAppSyncEventFromJson(Map json) { 10 | return AwsAppSyncEvent( 11 | version: json['version'] as String, 12 | operation: json['operation'] as String, 13 | payload: json['payload'] as String, 14 | ); 15 | } 16 | 17 | Map _$AwsAppSyncEventToJson(AwsAppSyncEvent instance) => 18 | { 19 | 'version': instance.version, 20 | 'operation': instance.operation, 21 | 'payload': instance.payload, 22 | }; 23 | -------------------------------------------------------------------------------- /lib/events/cloudwatch_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'cloudwatch_event.g.dart'; 4 | 5 | /// Event that is send via SQS to trigger for an innovation 6 | /// of a Lambda. 7 | /// 8 | /// Example 9 | /// 10 | /// ``` 11 | /// { 12 | /// "id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c", 13 | /// "detail-type": "Scheduled Event", 14 | /// "source": "aws.events", 15 | /// "account": "{{{account-id}}}", 16 | /// "time": "1970-01-01T00:00:00Z", 17 | /// "region": "eu-west-1", 18 | /// "resources": [ 19 | /// "arn:aws:events:eu-west-1:123456789012:rule/ExampleRule" 20 | /// ], 21 | /// "detail": {} 22 | /// } 23 | /// ``` 24 | @JsonSerializable() 25 | class AwsCloudwatchEvent { 26 | /// Resources ... 27 | @JsonKey() 28 | final List resources; 29 | 30 | /// Region ... 31 | @JsonKey() 32 | final String region; 33 | 34 | /// Id ... 35 | @JsonKey() 36 | final String id; 37 | 38 | /// Source ... 39 | @JsonKey() 40 | final String source; 41 | 42 | /// Account ... 43 | @JsonKey() 44 | final String account; 45 | 46 | /// Data Type ... 47 | @JsonKey(name: "detail-type") 48 | final String detailType; 49 | 50 | /// Detail ... 51 | @JsonKey() 52 | final Map detail; 53 | 54 | /// Time ... 55 | @JsonKey() 56 | final DateTime time; 57 | 58 | factory AwsCloudwatchEvent.fromJson(Map json) => 59 | _$AwsCloudwatchEventFromJson(json); 60 | 61 | Map toJson() => _$AwsCloudwatchEventToJson(this); 62 | 63 | const AwsCloudwatchEvent( 64 | {this.resources, 65 | this.region, 66 | this.id, 67 | this.source, 68 | this.account, 69 | this.detailType, 70 | this.detail, 71 | this.time}); 72 | } 73 | -------------------------------------------------------------------------------- /lib/events/cloudwatch_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'cloudwatch_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsCloudwatchEvent _$AwsCloudwatchEventFromJson(Map json) { 10 | return AwsCloudwatchEvent( 11 | resources: (json['resources'] as List)?.map((e) => e as String)?.toList(), 12 | region: json['region'] as String, 13 | id: json['id'] as String, 14 | source: json['source'] as String, 15 | account: json['account'] as String, 16 | detailType: json['detail-type'] as String, 17 | detail: json['detail'] as Map, 18 | time: json['time'] == null ? null : DateTime.parse(json['time'] as String), 19 | ); 20 | } 21 | 22 | Map _$AwsCloudwatchEventToJson(AwsCloudwatchEvent instance) => 23 | { 24 | 'resources': instance.resources, 25 | 'region': instance.region, 26 | 'id': instance.id, 27 | 'source': instance.source, 28 | 'account': instance.account, 29 | 'detail-type': instance.detailType, 30 | 'detail': instance.detail, 31 | 'time': instance.time?.toIso8601String(), 32 | }; 33 | -------------------------------------------------------------------------------- /lib/events/cloudwatch_log_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'cloudwatch_log_event.g.dart'; 4 | 5 | // { 6 | // "awslogs": { 7 | // "data": "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA==" 8 | // } 9 | // } 10 | 11 | /// Cloudwatch Log Event ... 12 | @JsonSerializable() 13 | class AwsCloudwatchLogEvent { 14 | /// awslogs ... 15 | @JsonKey() 16 | final Map awslogs; 17 | 18 | factory AwsCloudwatchLogEvent.fromJson(Map json) => 19 | _$AwsCloudwatchLogEventFromJson(json); 20 | 21 | Map toJson() => _$AwsCloudwatchLogEventToJson(this); 22 | 23 | const AwsCloudwatchLogEvent({this.awslogs}); 24 | } 25 | -------------------------------------------------------------------------------- /lib/events/cloudwatch_log_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'cloudwatch_log_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsCloudwatchLogEvent _$AwsCloudwatchLogEventFromJson( 10 | Map json) { 11 | return AwsCloudwatchLogEvent( 12 | awslogs: json['awslogs'] as Map, 13 | ); 14 | } 15 | 16 | Map _$AwsCloudwatchLogEventToJson( 17 | AwsCloudwatchLogEvent instance) => 18 | { 19 | 'awslogs': instance.awslogs, 20 | }; 21 | -------------------------------------------------------------------------------- /lib/events/cognito_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'cognito_event.g.dart'; 4 | 5 | @JsonSerializable() 6 | class AwsCognitoEvent { 7 | @JsonKey() 8 | final int version; 9 | 10 | @JsonKey() 11 | final String triggerSource; 12 | 13 | @JsonKey() 14 | final String region; 15 | 16 | @JsonKey() 17 | final String userPoolId; 18 | 19 | @JsonKey() 20 | final String userName; 21 | 22 | @JsonKey() 23 | final Map callerContext; 24 | 25 | @JsonKey() 26 | final AwsCognitoRequest request; 27 | 28 | @JsonKey() 29 | final AwsCognitoResponse response; 30 | 31 | const AwsCognitoEvent( 32 | {this.version, 33 | this.triggerSource, 34 | this.region, 35 | this.userPoolId, 36 | this.userName, 37 | this.callerContext, 38 | this.request, 39 | this.response}); 40 | 41 | factory AwsCognitoEvent.fromJson(Map json) => 42 | _$AwsCognitoEventFromJson(json); 43 | 44 | Map toJson() => _$AwsCognitoEventToJson(this); 45 | } 46 | 47 | @JsonSerializable() 48 | class AwsCognitoRequest { 49 | @JsonKey() 50 | final Map userAttributes; 51 | 52 | @JsonKey() 53 | final Map validationData; 54 | 55 | @JsonKey() 56 | final Map clientMetadata; 57 | 58 | @JsonKey() 59 | final bool newDeviceUsed; 60 | 61 | @JsonKey() 62 | final AwsGroupConfiguration groupConfiguration; 63 | 64 | @JsonKey() 65 | final String password; 66 | 67 | @JsonKey() 68 | final String codeParameter; 69 | 70 | const AwsCognitoRequest( 71 | {this.userAttributes, 72 | this.validationData, 73 | this.clientMetadata, 74 | this.newDeviceUsed, 75 | this.codeParameter, 76 | this.password, 77 | this.groupConfiguration}); 78 | 79 | factory AwsCognitoRequest.fromJson(Map json) => 80 | _$AwsCognitoRequestFromJson(json); 81 | 82 | Map toJson() => _$AwsCognitoRequestToJson(this); 83 | } 84 | 85 | @JsonSerializable() 86 | class AwsCognitoResponse { 87 | @JsonKey() 88 | final bool autoConfirmUser; 89 | 90 | @JsonKey() 91 | final bool autoVerifyPhone; 92 | 93 | @JsonKey() 94 | final bool autoVerifyEmail; 95 | 96 | @JsonKey() 97 | final AwsClaimOverrideDetails claimsOverrideDetails; 98 | 99 | @JsonKey() 100 | final Map userAttributes; 101 | 102 | @JsonKey() 103 | final String finalUserStatus; 104 | 105 | @JsonKey() 106 | final String messageAction; 107 | 108 | @JsonKey() 109 | final List desiredDeliveryMediums; 110 | 111 | @JsonKey() 112 | final bool forceAliasCreation; 113 | 114 | @JsonKey() 115 | final String smsMessage; 116 | 117 | @JsonKey() 118 | final String emailMessage; 119 | 120 | @JsonKey() 121 | final String emailSubject; 122 | 123 | const AwsCognitoResponse( 124 | {this.autoConfirmUser, 125 | this.autoVerifyEmail, 126 | this.autoVerifyPhone, 127 | this.claimsOverrideDetails, 128 | this.userAttributes, 129 | this.finalUserStatus, 130 | this.desiredDeliveryMediums, 131 | this.forceAliasCreation, 132 | this.messageAction, 133 | this.smsMessage, 134 | this.emailMessage, 135 | this.emailSubject}); 136 | 137 | factory AwsCognitoResponse.fromJson(Map json) => 138 | _$AwsCognitoResponseFromJson(json); 139 | 140 | Map toJson() => _$AwsCognitoResponseToJson(this); 141 | } 142 | 143 | @JsonSerializable() 144 | class AwsGroupConfiguration { 145 | @JsonKey() 146 | final List groupsToOverride; 147 | 148 | @JsonKey() 149 | final List iamRolesToOverride; 150 | 151 | @JsonKey() 152 | final String preferredRole; 153 | 154 | @JsonKey() 155 | final Map clientMetadata; 156 | 157 | const AwsGroupConfiguration( 158 | {this.groupsToOverride, 159 | this.iamRolesToOverride, 160 | this.preferredRole, 161 | this.clientMetadata}); 162 | 163 | factory AwsGroupConfiguration.fromJson(Map json) => 164 | _$AwsGroupConfigurationFromJson(json); 165 | 166 | Map toJson() => _$AwsGroupConfigurationToJson(this); 167 | } 168 | 169 | @JsonSerializable() 170 | class AwsClaimOverrideDetails { 171 | @JsonKey() 172 | final Map claimsToAddOrOverride; 173 | 174 | @JsonKey() 175 | final List claimsToSuppress; 176 | 177 | @JsonKey() 178 | final AwsGroupConfiguration groupOverrideDetails; 179 | 180 | const AwsClaimOverrideDetails( 181 | {this.claimsToAddOrOverride, 182 | this.claimsToSuppress, 183 | this.groupOverrideDetails}); 184 | 185 | factory AwsClaimOverrideDetails.fromJson(Map json) => 186 | _$AwsClaimOverrideDetailsFromJson(json); 187 | 188 | Map toJson() => _$AwsClaimOverrideDetailsToJson(this); 189 | } 190 | -------------------------------------------------------------------------------- /lib/events/cognito_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'cognito_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsCognitoEvent _$AwsCognitoEventFromJson(Map json) { 10 | return AwsCognitoEvent( 11 | version: json['version'] as int, 12 | triggerSource: json['triggerSource'] as String, 13 | region: json['region'] as String, 14 | userPoolId: json['userPoolId'] as String, 15 | userName: json['userName'] as String, 16 | callerContext: (json['callerContext'] as Map)?.map( 17 | (k, e) => MapEntry(k, e as String), 18 | ), 19 | request: json['request'] == null 20 | ? null 21 | : AwsCognitoRequest.fromJson(json['request'] as Map), 22 | response: json['response'] == null 23 | ? null 24 | : AwsCognitoResponse.fromJson(json['response'] as Map), 25 | ); 26 | } 27 | 28 | Map _$AwsCognitoEventToJson(AwsCognitoEvent instance) => 29 | { 30 | 'version': instance.version, 31 | 'triggerSource': instance.triggerSource, 32 | 'region': instance.region, 33 | 'userPoolId': instance.userPoolId, 34 | 'userName': instance.userName, 35 | 'callerContext': instance.callerContext, 36 | 'request': instance.request, 37 | 'response': instance.response, 38 | }; 39 | 40 | AwsCognitoRequest _$AwsCognitoRequestFromJson(Map json) { 41 | return AwsCognitoRequest( 42 | userAttributes: json['userAttributes'] as Map, 43 | validationData: (json['validationData'] as Map)?.map( 44 | (k, e) => MapEntry(k, e as String), 45 | ), 46 | clientMetadata: (json['clientMetadata'] as Map)?.map( 47 | (k, e) => MapEntry(k, e as String), 48 | ), 49 | newDeviceUsed: json['newDeviceUsed'] as bool, 50 | codeParameter: json['codeParameter'] as String, 51 | password: json['password'] as String, 52 | groupConfiguration: json['groupConfiguration'] == null 53 | ? null 54 | : AwsGroupConfiguration.fromJson( 55 | json['groupConfiguration'] as Map), 56 | ); 57 | } 58 | 59 | Map _$AwsCognitoRequestToJson(AwsCognitoRequest instance) => 60 | { 61 | 'userAttributes': instance.userAttributes, 62 | 'validationData': instance.validationData, 63 | 'clientMetadata': instance.clientMetadata, 64 | 'newDeviceUsed': instance.newDeviceUsed, 65 | 'groupConfiguration': instance.groupConfiguration, 66 | 'password': instance.password, 67 | 'codeParameter': instance.codeParameter, 68 | }; 69 | 70 | AwsCognitoResponse _$AwsCognitoResponseFromJson(Map json) { 71 | return AwsCognitoResponse( 72 | autoConfirmUser: json['autoConfirmUser'] as bool, 73 | autoVerifyEmail: json['autoVerifyEmail'] as bool, 74 | autoVerifyPhone: json['autoVerifyPhone'] as bool, 75 | claimsOverrideDetails: json['claimsOverrideDetails'] == null 76 | ? null 77 | : AwsClaimOverrideDetails.fromJson( 78 | json['claimsOverrideDetails'] as Map), 79 | userAttributes: (json['userAttributes'] as Map)?.map( 80 | (k, e) => MapEntry(k, e as String), 81 | ), 82 | finalUserStatus: json['finalUserStatus'] as String, 83 | desiredDeliveryMediums: (json['desiredDeliveryMediums'] as List) 84 | ?.map((e) => e as String) 85 | ?.toList(), 86 | forceAliasCreation: json['forceAliasCreation'] as bool, 87 | messageAction: json['messageAction'] as String, 88 | smsMessage: json['smsMessage'] as String, 89 | emailMessage: json['emailMessage'] as String, 90 | emailSubject: json['emailSubject'] as String, 91 | ); 92 | } 93 | 94 | Map _$AwsCognitoResponseToJson(AwsCognitoResponse instance) => 95 | { 96 | 'autoConfirmUser': instance.autoConfirmUser, 97 | 'autoVerifyPhone': instance.autoVerifyPhone, 98 | 'autoVerifyEmail': instance.autoVerifyEmail, 99 | 'claimsOverrideDetails': instance.claimsOverrideDetails, 100 | 'userAttributes': instance.userAttributes, 101 | 'finalUserStatus': instance.finalUserStatus, 102 | 'messageAction': instance.messageAction, 103 | 'desiredDeliveryMediums': instance.desiredDeliveryMediums, 104 | 'forceAliasCreation': instance.forceAliasCreation, 105 | 'smsMessage': instance.smsMessage, 106 | 'emailMessage': instance.emailMessage, 107 | 'emailSubject': instance.emailSubject, 108 | }; 109 | 110 | AwsGroupConfiguration _$AwsGroupConfigurationFromJson( 111 | Map json) { 112 | return AwsGroupConfiguration( 113 | groupsToOverride: 114 | (json['groupsToOverride'] as List)?.map((e) => e as String)?.toList(), 115 | iamRolesToOverride: 116 | (json['iamRolesToOverride'] as List)?.map((e) => e as String)?.toList(), 117 | preferredRole: json['preferredRole'] as String, 118 | clientMetadata: (json['clientMetadata'] as Map)?.map( 119 | (k, e) => MapEntry(k, e as String), 120 | ), 121 | ); 122 | } 123 | 124 | Map _$AwsGroupConfigurationToJson( 125 | AwsGroupConfiguration instance) => 126 | { 127 | 'groupsToOverride': instance.groupsToOverride, 128 | 'iamRolesToOverride': instance.iamRolesToOverride, 129 | 'preferredRole': instance.preferredRole, 130 | 'clientMetadata': instance.clientMetadata, 131 | }; 132 | 133 | AwsClaimOverrideDetails _$AwsClaimOverrideDetailsFromJson( 134 | Map json) { 135 | return AwsClaimOverrideDetails( 136 | claimsToAddOrOverride: 137 | (json['claimsToAddOrOverride'] as Map)?.map( 138 | (k, e) => MapEntry(k, e as String), 139 | ), 140 | claimsToSuppress: 141 | (json['claimsToSuppress'] as List)?.map((e) => e as String)?.toList(), 142 | groupOverrideDetails: json['groupOverrideDetails'] == null 143 | ? null 144 | : AwsGroupConfiguration.fromJson( 145 | json['groupOverrideDetails'] as Map), 146 | ); 147 | } 148 | 149 | Map _$AwsClaimOverrideDetailsToJson( 150 | AwsClaimOverrideDetails instance) => 151 | { 152 | 'claimsToAddOrOverride': instance.claimsToAddOrOverride, 153 | 'claimsToSuppress': instance.claimsToSuppress, 154 | 'groupOverrideDetails': instance.groupOverrideDetails, 155 | }; 156 | -------------------------------------------------------------------------------- /lib/events/dynamodb_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'dynamodb_event.g.dart'; 4 | 5 | /// Event send by a DynamoDB stream that contains 6 | /// the updated records in the DynamoDB table. 7 | @JsonSerializable() 8 | class AwsDynamoDBUpdateRecord { 9 | /// Keys ... 10 | @JsonKey(name: "Keys") 11 | final Map keys; 12 | 13 | /// New Image ... 14 | @JsonKey(name: "NewImage") 15 | final Map oldImage; 16 | 17 | /// Old Image .... 18 | @JsonKey(name: "OldImage") 19 | final Map newImage; 20 | 21 | factory AwsDynamoDBUpdateRecord.fromJson(Map json) => 22 | _$AwsDynamoDBUpdateRecordFromJson(json); 23 | 24 | Map toJson() => _$AwsDynamoDBUpdateRecordToJson(this); 25 | 26 | const AwsDynamoDBUpdateRecord({this.keys, this.oldImage, this.newImage}); 27 | } 28 | 29 | /// DynamoDB Update Event Record ... 30 | @JsonSerializable() 31 | class AwsDynamoDBUpdateEventRecord { 32 | /// Event Id ... 33 | @JsonKey() 34 | final String eventId; 35 | 36 | /// Event Name ... 37 | @JsonKey() 38 | final String eventName; 39 | 40 | /// Event Source ... 41 | @JsonKey() 42 | final String eventSource; 43 | 44 | /// Event Version ... 45 | @JsonKey() 46 | final String eventVersion; 47 | 48 | /// AWS Region ... 49 | @JsonKey() 50 | final String awsRegion; 51 | 52 | /// Event Source ARN ... 53 | @JsonKey() 54 | final String eventSourceARN; 55 | 56 | factory AwsDynamoDBUpdateEventRecord.fromJson(Map json) => 57 | _$AwsDynamoDBUpdateEventRecordFromJson(json); 58 | 59 | Map toJson() => _$AwsDynamoDBUpdateEventRecordToJson(this); 60 | 61 | const AwsDynamoDBUpdateEventRecord( 62 | {this.eventId, 63 | this.eventName, 64 | this.eventSource, 65 | this.eventVersion, 66 | this.awsRegion, 67 | this.eventSourceARN}); 68 | } 69 | 70 | /// DynamoDB Update Event ... 71 | @JsonSerializable() 72 | class AwsDynamoDBUpdateEvent { 73 | /// awslogs ... 74 | @JsonKey(name: "Records") 75 | final List records; 76 | 77 | factory AwsDynamoDBUpdateEvent.fromJson(Map json) => 78 | _$AwsDynamoDBUpdateEventFromJson(json); 79 | 80 | Map toJson() => _$AwsDynamoDBUpdateEventToJson(this); 81 | 82 | const AwsDynamoDBUpdateEvent({this.records}); 83 | } 84 | -------------------------------------------------------------------------------- /lib/events/dynamodb_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'dynamodb_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsDynamoDBUpdateRecord _$AwsDynamoDBUpdateRecordFromJson( 10 | Map json) { 11 | return AwsDynamoDBUpdateRecord( 12 | keys: json['Keys'] as Map, 13 | oldImage: json['NewImage'] as Map, 14 | newImage: json['OldImage'] as Map, 15 | ); 16 | } 17 | 18 | Map _$AwsDynamoDBUpdateRecordToJson( 19 | AwsDynamoDBUpdateRecord instance) => 20 | { 21 | 'Keys': instance.keys, 22 | 'NewImage': instance.oldImage, 23 | 'OldImage': instance.newImage, 24 | }; 25 | 26 | AwsDynamoDBUpdateEventRecord _$AwsDynamoDBUpdateEventRecordFromJson( 27 | Map json) { 28 | return AwsDynamoDBUpdateEventRecord( 29 | eventId: json['eventId'] as String, 30 | eventName: json['eventName'] as String, 31 | eventSource: json['eventSource'] as String, 32 | eventVersion: json['eventVersion'] as String, 33 | awsRegion: json['awsRegion'] as String, 34 | eventSourceARN: json['eventSourceARN'] as String, 35 | ); 36 | } 37 | 38 | Map _$AwsDynamoDBUpdateEventRecordToJson( 39 | AwsDynamoDBUpdateEventRecord instance) => 40 | { 41 | 'eventId': instance.eventId, 42 | 'eventName': instance.eventName, 43 | 'eventSource': instance.eventSource, 44 | 'eventVersion': instance.eventVersion, 45 | 'awsRegion': instance.awsRegion, 46 | 'eventSourceARN': instance.eventSourceARN, 47 | }; 48 | 49 | AwsDynamoDBUpdateEvent _$AwsDynamoDBUpdateEventFromJson( 50 | Map json) { 51 | return AwsDynamoDBUpdateEvent( 52 | records: (json['Records'] as List) 53 | ?.map((e) => e == null 54 | ? null 55 | : AwsDynamoDBUpdateEventRecord.fromJson(e as Map)) 56 | ?.toList(), 57 | ); 58 | } 59 | 60 | Map _$AwsDynamoDBUpdateEventToJson( 61 | AwsDynamoDBUpdateEvent instance) => 62 | { 63 | 'Records': instance.records, 64 | }; 65 | -------------------------------------------------------------------------------- /lib/events/kinesis_data_firehose_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'kinesis_data_firehose_event.g.dart'; 4 | 5 | /// Kinesis ..... 6 | @JsonSerializable() 7 | class AwsKinesisFirehoseData { 8 | /// Record ID ... 9 | @JsonKey() 10 | final String recordId; 11 | 12 | /// Approximated Arrival Timestamp ... 13 | @JsonKey() 14 | final int approximateArrivalTimestamp; 15 | 16 | /// Data ... 17 | @JsonKey() 18 | final String data; 19 | 20 | factory AwsKinesisFirehoseData.fromJson(Map json) { 21 | return _$AwsKinesisFirehoseDataFromJson(json); 22 | } 23 | 24 | Map toJson() => _$AwsKinesisFirehoseDataToJson(this); 25 | 26 | const AwsKinesisFirehoseData( 27 | {this.recordId, this.data, this.approximateArrivalTimestamp}); 28 | } 29 | 30 | /// Kinesis Event ... 31 | @JsonSerializable() 32 | class AwsKinesisFirehoseDataEvent { 33 | /// Invocation ID ... 34 | @JsonKey() 35 | final String invocationId; 36 | 37 | /// Delivery Stream ARN ... 38 | @JsonKey() 39 | final String deliveryStreamArn; 40 | 41 | /// Region ... 42 | @JsonKey() 43 | final String region; 44 | 45 | /// Records ... 46 | @JsonKey() 47 | final List records; 48 | 49 | factory AwsKinesisFirehoseDataEvent.fromJson(Map json) { 50 | return _$AwsKinesisFirehoseDataEventFromJson(json); 51 | } 52 | 53 | Map toJson() => _$AwsKinesisFirehoseDataEventToJson(this); 54 | 55 | const AwsKinesisFirehoseDataEvent( 56 | {this.records, this.invocationId, this.deliveryStreamArn, this.region}); 57 | } 58 | -------------------------------------------------------------------------------- /lib/events/kinesis_data_firehose_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'kinesis_data_firehose_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsKinesisFirehoseData _$AwsKinesisFirehoseDataFromJson( 10 | Map json) { 11 | return AwsKinesisFirehoseData( 12 | recordId: json['recordId'] as String, 13 | data: json['data'] as String, 14 | approximateArrivalTimestamp: json['approximateArrivalTimestamp'] as int, 15 | ); 16 | } 17 | 18 | Map _$AwsKinesisFirehoseDataToJson( 19 | AwsKinesisFirehoseData instance) => 20 | { 21 | 'recordId': instance.recordId, 22 | 'approximateArrivalTimestamp': instance.approximateArrivalTimestamp, 23 | 'data': instance.data, 24 | }; 25 | 26 | AwsKinesisFirehoseDataEvent _$AwsKinesisFirehoseDataEventFromJson( 27 | Map json) { 28 | return AwsKinesisFirehoseDataEvent( 29 | records: (json['records'] as List) 30 | ?.map((e) => e == null 31 | ? null 32 | : AwsKinesisFirehoseData.fromJson(e as Map)) 33 | ?.toList(), 34 | invocationId: json['invocationId'] as String, 35 | deliveryStreamArn: json['deliveryStreamArn'] as String, 36 | region: json['region'] as String, 37 | ); 38 | } 39 | 40 | Map _$AwsKinesisFirehoseDataEventToJson( 41 | AwsKinesisFirehoseDataEvent instance) => 42 | { 43 | 'invocationId': instance.invocationId, 44 | 'deliveryStreamArn': instance.deliveryStreamArn, 45 | 'region': instance.region, 46 | 'records': instance.records, 47 | }; 48 | -------------------------------------------------------------------------------- /lib/events/kinesis_data_stream_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'kinesis_data_stream_event.g.dart'; 4 | 5 | /// Kinesis ..... 6 | @JsonSerializable() 7 | class AwsKinesisDataStream { 8 | /// Partition Key ... 9 | @JsonKey() 10 | final String partitionKey; 11 | 12 | /// Kinesis Schema Version ... 13 | @JsonKey() 14 | final String kinesisSchemaVersion; 15 | 16 | /// Data ... 17 | @JsonKey() 18 | final String data; 19 | 20 | /// Sequenzer Number ... 21 | @JsonKey() 22 | final String sequenceNumber; 23 | 24 | /// Approximate Arrival Timestamp ... 25 | @JsonKey() 26 | final int approximateArrivalTimestamp; 27 | 28 | factory AwsKinesisDataStream.fromJson(Map json) { 29 | return _$AwsKinesisDataStreamFromJson(json); 30 | } 31 | 32 | Map toJson() => _$AwsKinesisDataStreamToJson(this); 33 | 34 | const AwsKinesisDataStream( 35 | {this.partitionKey, 36 | this.kinesisSchemaVersion, 37 | this.data, 38 | this.sequenceNumber, 39 | this.approximateArrivalTimestamp}); 40 | } 41 | 42 | /// Kinesis record that is send via [AwsKinesisEvent]. 43 | @JsonSerializable() 44 | class AwsKinesisDataStreamRecord { 45 | /// Data ... 46 | @JsonKey() 47 | final AwsKinesisDataStream kinesis; 48 | 49 | /// Source of the Event. 50 | @JsonKey() 51 | final String eventSource; 52 | 53 | /// Event Id ... 54 | @JsonKey() 55 | final String eventID; 56 | 57 | /// Event Version ... 58 | @JsonKey() 59 | final String eventVersion; 60 | 61 | /// Event Name ... 62 | @JsonKey() 63 | final String eventName; 64 | 65 | /// Event Source ARN ... 66 | @JsonKey() 67 | final String eventSourceARN; 68 | 69 | /// Invokey Identity ARN ... 70 | @JsonKey() 71 | final String invokeIdentityArn; 72 | 73 | /// Aws Region this event was emitted from 74 | @JsonKey() 75 | final String awsRegion; 76 | 77 | factory AwsKinesisDataStreamRecord.fromJson(Map json) { 78 | return _$AwsKinesisDataStreamRecordFromJson(json); 79 | } 80 | 81 | Map toJson() => _$AwsKinesisDataStreamRecordToJson(this); 82 | 83 | const AwsKinesisDataStreamRecord( 84 | {this.kinesis, 85 | this.invokeIdentityArn, 86 | this.eventName, 87 | this.eventID, 88 | this.eventSource, 89 | this.eventVersion, 90 | this.eventSourceARN, 91 | this.awsRegion}); 92 | } 93 | 94 | /// Kinesis Event ... 95 | @JsonSerializable() 96 | class AwsKinesisDataStreamEvent { 97 | /// The SQS message records that have been send with the event. 98 | @JsonKey(name: "Records") 99 | final List records; 100 | 101 | factory AwsKinesisDataStreamEvent.fromJson(Map json) { 102 | return _$AwsKinesisDataStreamEventFromJson(json); 103 | } 104 | 105 | Map toJson() => _$AwsKinesisDataStreamEventToJson(this); 106 | 107 | const AwsKinesisDataStreamEvent({this.records}); 108 | } 109 | -------------------------------------------------------------------------------- /lib/events/kinesis_data_stream_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'kinesis_data_stream_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsKinesisDataStream _$AwsKinesisDataStreamFromJson(Map json) { 10 | return AwsKinesisDataStream( 11 | partitionKey: json['partitionKey'] as String, 12 | kinesisSchemaVersion: json['kinesisSchemaVersion'] as String, 13 | data: json['data'] as String, 14 | sequenceNumber: json['sequenceNumber'] as String, 15 | approximateArrivalTimestamp: json['approximateArrivalTimestamp'] as int, 16 | ); 17 | } 18 | 19 | Map _$AwsKinesisDataStreamToJson( 20 | AwsKinesisDataStream instance) => 21 | { 22 | 'partitionKey': instance.partitionKey, 23 | 'kinesisSchemaVersion': instance.kinesisSchemaVersion, 24 | 'data': instance.data, 25 | 'sequenceNumber': instance.sequenceNumber, 26 | 'approximateArrivalTimestamp': instance.approximateArrivalTimestamp, 27 | }; 28 | 29 | AwsKinesisDataStreamRecord _$AwsKinesisDataStreamRecordFromJson( 30 | Map json) { 31 | return AwsKinesisDataStreamRecord( 32 | kinesis: json['kinesis'] == null 33 | ? null 34 | : AwsKinesisDataStream.fromJson( 35 | json['kinesis'] as Map), 36 | invokeIdentityArn: json['invokeIdentityArn'] as String, 37 | eventName: json['eventName'] as String, 38 | eventID: json['eventID'] as String, 39 | eventSource: json['eventSource'] as String, 40 | eventVersion: json['eventVersion'] as String, 41 | eventSourceARN: json['eventSourceARN'] as String, 42 | awsRegion: json['awsRegion'] as String, 43 | ); 44 | } 45 | 46 | Map _$AwsKinesisDataStreamRecordToJson( 47 | AwsKinesisDataStreamRecord instance) => 48 | { 49 | 'kinesis': instance.kinesis, 50 | 'eventSource': instance.eventSource, 51 | 'eventID': instance.eventID, 52 | 'eventVersion': instance.eventVersion, 53 | 'eventName': instance.eventName, 54 | 'eventSourceARN': instance.eventSourceARN, 55 | 'invokeIdentityArn': instance.invokeIdentityArn, 56 | 'awsRegion': instance.awsRegion, 57 | }; 58 | 59 | AwsKinesisDataStreamEvent _$AwsKinesisDataStreamEventFromJson( 60 | Map json) { 61 | return AwsKinesisDataStreamEvent( 62 | records: (json['Records'] as List) 63 | ?.map((e) => e == null 64 | ? null 65 | : AwsKinesisDataStreamRecord.fromJson(e as Map)) 66 | ?.toList(), 67 | ); 68 | } 69 | 70 | Map _$AwsKinesisDataStreamEventToJson( 71 | AwsKinesisDataStreamEvent instance) => 72 | { 73 | 'Records': instance.records, 74 | }; 75 | -------------------------------------------------------------------------------- /lib/events/s3_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 's3_event.g.dart'; 4 | 5 | /// Representing a recorded S3 Event send to the Lambda. 6 | /// This can be send in batches of operations. 7 | @JsonSerializable() 8 | class AwsS3Event { 9 | @JsonKey(name: "Records") 10 | final List records; 11 | 12 | const AwsS3Event({this.records}); 13 | 14 | factory AwsS3Event.fromJson(Map json) => 15 | _$AwsS3EventFromJson(json); 16 | 17 | Map toJson() => _$AwsS3EventToJson(this); 18 | } 19 | 20 | /// Notifcation Event for Lambda in S3. 21 | @JsonSerializable() 22 | class AwsS3EventRecord { 23 | final String eventVersion; 24 | final String eventSource; 25 | final String awsRegion; 26 | final DateTime eventTime; 27 | final String eventName; 28 | final AwsS3UserIdentity userIdentity; 29 | final Map requestParameters; 30 | final Map responseElements; 31 | final AwsS3Data s3; 32 | 33 | const AwsS3EventRecord( 34 | {this.eventName, 35 | this.eventSource, 36 | this.awsRegion, 37 | this.eventTime, 38 | this.eventVersion, 39 | this.userIdentity, 40 | this.requestParameters, 41 | this.responseElements, 42 | this.s3}); 43 | 44 | factory AwsS3EventRecord.fromJson(Map json) => 45 | _$AwsS3EventRecordFromJson(json); 46 | 47 | Map toJson() => _$AwsS3EventRecordToJson(this); 48 | } 49 | 50 | @JsonSerializable() 51 | class AwsS3Data { 52 | String s3SchemaVersion; 53 | String configurationId; 54 | AwsS3Bucket bucket; 55 | AWSS3EventObject object; 56 | 57 | AwsS3Data( 58 | {this.s3SchemaVersion, this.configurationId, this.bucket, this.object}); 59 | 60 | factory AwsS3Data.fromJson(Map json) => 61 | _$AwsS3DataFromJson(json); 62 | 63 | Map toJson() => _$AwsS3DataToJson(this); 64 | } 65 | 66 | @JsonSerializable() 67 | class AwsS3Bucket { 68 | String name; 69 | AwsS3UserIdentity ownerIdentity; 70 | String arn; 71 | 72 | AwsS3Bucket({this.name, this.ownerIdentity, this.arn}); 73 | 74 | factory AwsS3Bucket.fromJson(Map json) => 75 | _$AwsS3BucketFromJson(json); 76 | 77 | Map toJson() => _$AwsS3BucketToJson(this); 78 | } 79 | 80 | @JsonSerializable() 81 | class AWSS3EventObject { 82 | String key; 83 | int size; 84 | String eTag; 85 | String sequencer; 86 | 87 | AWSS3EventObject({this.key, this.size, this.eTag, this.sequencer}); 88 | 89 | factory AWSS3EventObject.fromJson(Map json) => 90 | _$AWSS3EventObjectFromJson(json); 91 | 92 | Map toJson() => _$AWSS3EventObjectToJson(this); 93 | } 94 | 95 | @JsonSerializable() 96 | class AwsS3UserIdentity { 97 | String principalId; 98 | 99 | AwsS3UserIdentity({this.principalId}); 100 | 101 | factory AwsS3UserIdentity.fromJson(Map json) => 102 | _$AwsS3UserIdentityFromJson(json); 103 | 104 | Map toJson() => _$AwsS3UserIdentityToJson(this); 105 | } 106 | -------------------------------------------------------------------------------- /lib/events/s3_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 's3_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsS3Event _$AwsS3EventFromJson(Map json) { 10 | return AwsS3Event( 11 | records: (json['Records'] as List) 12 | ?.map((e) => e == null 13 | ? null 14 | : AwsS3EventRecord.fromJson(e as Map)) 15 | ?.toList(), 16 | ); 17 | } 18 | 19 | Map _$AwsS3EventToJson(AwsS3Event instance) => 20 | { 21 | 'Records': instance.records, 22 | }; 23 | 24 | AwsS3EventRecord _$AwsS3EventRecordFromJson(Map json) { 25 | return AwsS3EventRecord( 26 | eventName: json['eventName'] as String, 27 | eventSource: json['eventSource'] as String, 28 | awsRegion: json['awsRegion'] as String, 29 | eventTime: json['eventTime'] == null 30 | ? null 31 | : DateTime.parse(json['eventTime'] as String), 32 | eventVersion: json['eventVersion'] as String, 33 | userIdentity: json['userIdentity'] == null 34 | ? null 35 | : AwsS3UserIdentity.fromJson( 36 | json['userIdentity'] as Map), 37 | requestParameters: (json['requestParameters'] as Map)?.map( 38 | (k, e) => MapEntry(k, e as String), 39 | ), 40 | responseElements: (json['responseElements'] as Map)?.map( 41 | (k, e) => MapEntry(k, e as String), 42 | ), 43 | s3: json['s3'] == null 44 | ? null 45 | : AwsS3Data.fromJson(json['s3'] as Map), 46 | ); 47 | } 48 | 49 | Map _$AwsS3EventRecordToJson(AwsS3EventRecord instance) => 50 | { 51 | 'eventVersion': instance.eventVersion, 52 | 'eventSource': instance.eventSource, 53 | 'awsRegion': instance.awsRegion, 54 | 'eventTime': instance.eventTime?.toIso8601String(), 55 | 'eventName': instance.eventName, 56 | 'userIdentity': instance.userIdentity, 57 | 'requestParameters': instance.requestParameters, 58 | 'responseElements': instance.responseElements, 59 | 's3': instance.s3, 60 | }; 61 | 62 | AwsS3Data _$AwsS3DataFromJson(Map json) { 63 | return AwsS3Data( 64 | s3SchemaVersion: json['s3SchemaVersion'] as String, 65 | configurationId: json['configurationId'] as String, 66 | bucket: json['bucket'] == null 67 | ? null 68 | : AwsS3Bucket.fromJson(json['bucket'] as Map), 69 | object: json['object'] == null 70 | ? null 71 | : AWSS3EventObject.fromJson(json['object'] as Map), 72 | ); 73 | } 74 | 75 | Map _$AwsS3DataToJson(AwsS3Data instance) => { 76 | 's3SchemaVersion': instance.s3SchemaVersion, 77 | 'configurationId': instance.configurationId, 78 | 'bucket': instance.bucket, 79 | 'object': instance.object, 80 | }; 81 | 82 | AwsS3Bucket _$AwsS3BucketFromJson(Map json) { 83 | return AwsS3Bucket( 84 | name: json['name'] as String, 85 | ownerIdentity: json['ownerIdentity'] == null 86 | ? null 87 | : AwsS3UserIdentity.fromJson( 88 | json['ownerIdentity'] as Map), 89 | arn: json['arn'] as String, 90 | ); 91 | } 92 | 93 | Map _$AwsS3BucketToJson(AwsS3Bucket instance) => 94 | { 95 | 'name': instance.name, 96 | 'ownerIdentity': instance.ownerIdentity, 97 | 'arn': instance.arn, 98 | }; 99 | 100 | AWSS3EventObject _$AWSS3EventObjectFromJson(Map json) { 101 | return AWSS3EventObject( 102 | key: json['key'] as String, 103 | size: json['size'] as int, 104 | eTag: json['eTag'] as String, 105 | sequencer: json['sequencer'] as String, 106 | ); 107 | } 108 | 109 | Map _$AWSS3EventObjectToJson(AWSS3EventObject instance) => 110 | { 111 | 'key': instance.key, 112 | 'size': instance.size, 113 | 'eTag': instance.eTag, 114 | 'sequencer': instance.sequencer, 115 | }; 116 | 117 | AwsS3UserIdentity _$AwsS3UserIdentityFromJson(Map json) { 118 | return AwsS3UserIdentity( 119 | principalId: json['principalId'] as String, 120 | ); 121 | } 122 | 123 | Map _$AwsS3UserIdentityToJson(AwsS3UserIdentity instance) => 124 | { 125 | 'principalId': instance.principalId, 126 | }; 127 | -------------------------------------------------------------------------------- /lib/events/sqs_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'sqs_event.g.dart'; 4 | 5 | /// SQS Event Record that is send via [AwsSQSEvent]. 6 | @JsonSerializable() 7 | class AwsSQSEventRecord { 8 | /// Id of the SQS message. 9 | @JsonKey() 10 | final String messageId; 11 | 12 | /// Name of the receipt handle. 13 | @JsonKey() 14 | final String receiptHandle; 15 | 16 | /// Body of the message 17 | @JsonKey() 18 | final String body; 19 | 20 | /// Attributes that are send with the event. 21 | @JsonKey() 22 | final Map attributes; 23 | 24 | /// Message attributes that are send with the event. 25 | @JsonKey() 26 | final Map messageAttributes; 27 | 28 | /// The md5 hash of the message body. 29 | @JsonKey() 30 | final String md5OfBody; 31 | 32 | /// Source of the Event. 33 | @JsonKey() 34 | final String eventSource; 35 | 36 | /// Source of the Event ARN. 37 | @JsonKey() 38 | final String eventSourceARN; 39 | 40 | /// Aws Region this event was emitted from 41 | @JsonKey() 42 | final String awsRegion; 43 | 44 | factory AwsSQSEventRecord.fromJson(Map json) { 45 | return _$AwsSQSEventRecordFromJson(json); 46 | } 47 | 48 | Map toJson() => _$AwsSQSEventRecordToJson(this); 49 | 50 | const AwsSQSEventRecord( 51 | {this.messageId, 52 | this.body, 53 | this.receiptHandle, 54 | this.attributes, 55 | this.messageAttributes, 56 | this.md5OfBody, 57 | this.eventSource, 58 | this.eventSourceARN, 59 | this.awsRegion}); 60 | } 61 | 62 | /// Event that is send via SQS to trigger for an innovation 63 | /// of a Lambda. 64 | @JsonSerializable() 65 | class AwsSQSEvent { 66 | /// The SQS message records that have been send with the event. 67 | @JsonKey(name: "Records") 68 | final List records; 69 | 70 | factory AwsSQSEvent.fromJson(Map json) { 71 | return _$AwsSQSEventFromJson(json); 72 | } 73 | 74 | Map toJson() => _$AwsSQSEventToJson(this); 75 | 76 | const AwsSQSEvent({this.records}); 77 | } 78 | -------------------------------------------------------------------------------- /lib/events/sqs_event.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'sqs_event.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AwsSQSEventRecord _$AwsSQSEventRecordFromJson(Map json) { 10 | return AwsSQSEventRecord( 11 | messageId: json['messageId'] as String, 12 | body: json['body'] as String, 13 | receiptHandle: json['receiptHandle'] as String, 14 | attributes: json['attributes'] as Map, 15 | messageAttributes: json['messageAttributes'] as Map, 16 | md5OfBody: json['md5OfBody'] as String, 17 | eventSource: json['eventSource'] as String, 18 | eventSourceARN: json['eventSourceARN'] as String, 19 | awsRegion: json['awsRegion'] as String, 20 | ); 21 | } 22 | 23 | Map _$AwsSQSEventRecordToJson(AwsSQSEventRecord instance) => 24 | { 25 | 'messageId': instance.messageId, 26 | 'receiptHandle': instance.receiptHandle, 27 | 'body': instance.body, 28 | 'attributes': instance.attributes, 29 | 'messageAttributes': instance.messageAttributes, 30 | 'md5OfBody': instance.md5OfBody, 31 | 'eventSource': instance.eventSource, 32 | 'eventSourceARN': instance.eventSourceARN, 33 | 'awsRegion': instance.awsRegion, 34 | }; 35 | 36 | AwsSQSEvent _$AwsSQSEventFromJson(Map json) { 37 | return AwsSQSEvent( 38 | records: (json['Records'] as List) 39 | ?.map((e) => e == null 40 | ? null 41 | : AwsSQSEventRecord.fromJson(e as Map)) 42 | ?.toList(), 43 | ); 44 | } 45 | 46 | Map _$AwsSQSEventToJson(AwsSQSEvent instance) => 47 | { 48 | 'Records': instance.records, 49 | }; 50 | -------------------------------------------------------------------------------- /lib/runtime/context.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io' show Platform; 2 | import '../client/client.dart'; 3 | 4 | /// Context contains the Lambda execution context information. 5 | /// They are either provided via [Platform.environment] or [NextInvocation] 6 | /// which is the result from the Lambda API. 7 | /// 8 | /// Note: this should not be used directly. 9 | class Context { 10 | /// These are the constants used to map [Platform.environment] 11 | /// which are specific to the Lambda execution environment. 12 | static const _kAWSLambdaHandler = '_HANDLER'; 13 | static const _kAWSLambdaFunctionName = 'AWS_LAMBDA_FUNCTION_NAME'; 14 | static const _kAWSLambdaFunctionVersion = 'AWS_LAMBDA_FUNCTION_VERSION'; 15 | static const _kAWSLambdaLogGroupName = 'AWS_LAMBDA_LOG_GROUP_NAME'; 16 | static const _kAWSLambdaLogStreamName = 'AWS_LAMBDA_LOG_STREAM_NAME'; 17 | static const _kAWSLambdaFunctionMemorySize = 18 | 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE'; 19 | static const _kAWSLambdaRegion = 'AWS_REGION'; 20 | static const _kAWSLambdaExecutionEnv = 'AWS_EXECUTION_ENV'; 21 | static const _kAWSLambdaAccessKey = 'AWS_ACCESS_KEY_ID'; 22 | static const _kAWSLambdaSecretAccesKey = 'AWS_SECRET_ACCESS_KEY'; 23 | static const _kAWSLambdaSessionToken = 'AWS_SESSION_TOKEN'; 24 | 25 | /// Creates a new [Context] from [NextInvocation] which is the data 26 | /// from the Lambda Runtime Interface for the next [Handler] invocation. 27 | static fromNextInvocation(NextInvocation nextInvocation) { 28 | return Context( 29 | requestId: nextInvocation.requestId, 30 | invokedFunction: nextInvocation.invokedFunctionArn); 31 | } 32 | 33 | /// Handler that is used for the invocation of the function 34 | String handler; 35 | 36 | /// Name of the function that is invoked. 37 | String functionName; 38 | 39 | /// Version of the function that is invoked. 40 | String functionVersion; 41 | 42 | /// Memory sized that is allocated to execution of the function. 43 | String functionMemorySize; 44 | 45 | /// Cloudwatch LogGroup that is associated with the Lambda. 46 | String logGroupName; 47 | 48 | /// Cloudwach LogStream that is associated with the Lambda. 49 | String logStreamName; 50 | 51 | /// Region that this function exists in. 52 | String region; 53 | 54 | /// The execution environment of the function. 55 | String executionEnv; 56 | 57 | /// Access key that is acquired via STS. 58 | String accessKey; 59 | 60 | /// Secret access key that is acquired via STS. 61 | String secretAccessKey; 62 | 63 | /// The session token from STS. 64 | String sessionToken; 65 | 66 | /// Id of the request. 67 | /// You can use this to track the request for the invocation. 68 | String requestId; 69 | 70 | /// The ARN to identify the function. 71 | String invokedFunctionArn; 72 | 73 | Context( 74 | {String handler, 75 | String functionName, 76 | String functionMemorySize, 77 | String logGroupName, 78 | String logStreamName, 79 | String requestId, 80 | String invokedFunction, 81 | String region, 82 | String executionEnv, 83 | String accessKey, 84 | String secretAccessKey, 85 | String sessionToken}) { 86 | assert(requestId != null); 87 | assert(handler != null); 88 | 89 | this.handler = handler ?? Platform.environment[_kAWSLambdaHandler]; 90 | this.functionName = 91 | functionName ?? Platform.environment[_kAWSLambdaFunctionName]; 92 | this.functionVersion = 93 | functionVersion ?? Platform.environment[_kAWSLambdaFunctionVersion]; 94 | this.functionMemorySize = functionMemorySize ?? 95 | Platform.environment[_kAWSLambdaFunctionMemorySize]; 96 | this.logGroupName = 97 | logGroupName ?? Platform.environment[_kAWSLambdaLogGroupName]; 98 | this.logStreamName = 99 | logStreamName ?? Platform.environment[_kAWSLambdaLogStreamName]; 100 | this.requestId = requestId; 101 | this.invokedFunctionArn = invokedFunctionArn; 102 | this.region = region ?? Platform.environment[_kAWSLambdaRegion]; 103 | this.executionEnv = 104 | executionEnv ?? Platform.environment[_kAWSLambdaExecutionEnv]; 105 | this.accessKey = accessKey ?? Platform.environment[_kAWSLambdaAccessKey]; 106 | this.secretAccessKey = 107 | secretAccessKey ?? Platform.environment[_kAWSLambdaSecretAccesKey]; 108 | this.sessionToken = 109 | sessionToken ?? Platform.environment[_kAWSLambdaSessionToken]; 110 | } 111 | 112 | /// Allows to copy a created [Context] over with some new settings. 113 | Context copyWith( 114 | {String handler, 115 | String functionName, 116 | String functionMemorySize, 117 | String logGroupName, 118 | String logStreamName, 119 | String requestId, 120 | String invokedFunction, 121 | String region, 122 | String executionEnv, 123 | String accessKey, 124 | String secretAccessKey, 125 | String sessionToken}) { 126 | return Context( 127 | handler: handler ?? this.handler, 128 | functionName: functionName ?? this.functionName, 129 | functionMemorySize: functionMemorySize ?? this.functionMemorySize, 130 | logGroupName: logGroupName ?? this.logGroupName, 131 | logStreamName: logStreamName ?? this.logStreamName, 132 | requestId: requestId ?? this.requestId, 133 | invokedFunction: invokedFunction ?? this.invokedFunctionArn, 134 | region: region ?? this.region, 135 | executionEnv: executionEnv ?? this.executionEnv, 136 | accessKey: accessKey ?? this.accessKey, 137 | secretAccessKey: secretAccessKey ?? this.secretAccessKey, 138 | sessionToken: sessionToken ?? this.sessionToken); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /lib/runtime/event.dart: -------------------------------------------------------------------------------- 1 | import '../events/alb_event.dart'; 2 | import '../events/alexa_event.dart'; 3 | import '../events/apigateway_event.dart'; 4 | import '../events/appsync_event.dart'; 5 | import '../events/cloudwatch_event.dart'; 6 | import '../events/cloudwatch_log_event.dart'; 7 | import '../events/cognito_event.dart'; 8 | import '../events/dynamodb_event.dart'; 9 | import '../events/s3_event.dart'; 10 | import '../events/sqs_event.dart'; 11 | import '../events/kinesis_data_stream_event.dart'; 12 | 13 | /// Event is the abstraction for every event that 14 | /// can be ingested by a handler. 15 | /// 16 | /// Note is currently not supported to register your 17 | /// own events here. 18 | abstract class Event { 19 | static final _registry = { 20 | AwsCognitoEvent: (Map json) => 21 | AwsCognitoEvent.fromJson(json), 22 | AwsS3Event: (Map json) => AwsS3Event.fromJson(json), 23 | AwsApiGatewayEvent: (Map json) => 24 | AwsApiGatewayEvent.fromJson(json), 25 | AwsAppSyncEvent: (Map json) => 26 | AwsAppSyncEvent.fromJson(json), 27 | AwsALBEvent: (Map json) => AwsALBEvent.fromJson(json), 28 | AwsAlexaEvent: (Map json) => AwsAlexaEvent.fromJson(json), 29 | AwsSQSEvent: (Map json) => AwsSQSEvent.fromJson(json), 30 | AwsCloudwatchEvent: (Map json) => 31 | AwsCloudwatchEvent.fromJson(json), 32 | AwsCloudwatchLogEvent: (Map json) => 33 | AwsCloudwatchLogEvent.fromJson(json), 34 | AwsDynamoDBUpdateEvent: (Map json) => 35 | AwsDynamoDBUpdateEvent.fromJson(json), 36 | AwsKinesisDataStreamEvent: (Map json) => 37 | AwsKinesisDataStreamEvent.fromJson(json) 38 | }; 39 | 40 | /// Checks if a type of event is already registered. 41 | static exists() { 42 | return Event._registry.containsKey(T); 43 | } 44 | 45 | /// Returs the value of a registered event. It is [null] 46 | /// if no such event has been registered. 47 | static value() { 48 | return Event._registry[T]; 49 | } 50 | 51 | /// Registers an event. 52 | static registerEvent(func) { 53 | Event._registry[T] = func; 54 | } 55 | 56 | /// Deregisters an event. 57 | static deregisterEvent() { 58 | Event._registry.remove(T); 59 | } 60 | 61 | /// Creates a new event from a handler type with the [NextInvocation.response]. 62 | static fromHandler(Type type, Map json) { 63 | return _registry[type](json); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/runtime/exception.dart: -------------------------------------------------------------------------------- 1 | /// An exception thrown when there is an error in the runtime. 2 | class RuntimeException implements Exception { 3 | const RuntimeException(this.cause); 4 | 5 | /// Explains the reason why there is an exception thrown 6 | /// in the runtime. 7 | final String cause; 8 | 9 | @override 10 | String toString() => "RuntimeException: $cause"; 11 | } 12 | -------------------------------------------------------------------------------- /lib/runtime/runtime.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import '../client/client.dart'; 4 | import 'event.dart'; 5 | import 'context.dart'; 6 | import 'exception.dart'; 7 | 8 | /// A function which ingests and Event and a [Context] 9 | /// and returns a [InvocationResult]. The result is ecoded 10 | /// by the [Runtime] and posted to the Lambda API. 11 | typedef Handler = Future Function( 12 | Context context, T event); 13 | 14 | class _RuntimeHandler { 15 | final Type type; 16 | final dynamic handler; 17 | 18 | const _RuntimeHandler(this.type, this.handler) 19 | : assert(type != null), 20 | assert(handler != null); 21 | } 22 | 23 | /// A Runtime manages the interface to the Lambda API. 24 | /// 25 | /// The Runtime is designed as singleton and [Runtime.instance] 26 | /// returns the same instance of the [Runtime] everytime. 27 | /// 28 | /// ```dart 29 | /// final Handler helloWorldHandler = 30 | /// (context, event) async { 31 | /// return new InvocationResult(context.requestId, "HELLO WORLD"); 32 | /// }; 33 | /// 34 | /// await Runtime.instance 35 | /// ..registerHandler("hello.world", helloWorld) 36 | /// ..invoke(); 37 | /// ``` 38 | /// 39 | /// Note: You can register an 40 | class Runtime { 41 | Client _client; 42 | 43 | static final Runtime _singleton = Runtime._internal(); 44 | final Map _handlers = {}; 45 | 46 | factory Runtime() { 47 | return _singleton; 48 | } 49 | 50 | Runtime._internal() { 51 | _client = Client(); 52 | } 53 | 54 | /// Lists the registered handlers by name. 55 | /// The name is a simple [String] which reflects 56 | /// the name of the trigger in the Lambda Execution API. 57 | List get handlers => _handlers.keys; 58 | 59 | /// Checks if a specific handlers has been registered 60 | /// with the runtime. 61 | bool handlerExists(String name) => _handlers.containsKey(name); 62 | 63 | /// Register a handler function [Handler] with [name] 64 | /// which digests an event [T]. 65 | Handler registerHandler(String name, Handler handler) { 66 | _handlers[name] = _RuntimeHandler(T, handler); 67 | 68 | return _handlers[name].handler; 69 | } 70 | 71 | /// Unregister a handler function [Handler] with [name]. 72 | Handler deregisterHandler(String name) => 73 | _handlers.remove(name).handler; 74 | 75 | /// Register an new event to be ingested by a handler. 76 | /// The type should reflect your type in your handler definition [Handler]. 77 | void registerEvent(func) { 78 | Event.registerEvent(func); 79 | } 80 | 81 | /// Deregister an new event to be ingested by a handler. 82 | /// The type should reflect your type in your handler definition [Handler]. 83 | void deregisterEvent() { 84 | Event.deregisterEvent(); 85 | } 86 | 87 | /// Run the [Runtime] in loop and digest events that are 88 | /// fetched from the AWS Lambda API Interface. The events are processed 89 | /// sequentially and are fetched from the AWS Lambda API Interface. 90 | /// 91 | /// If the invocation of an event was successful the function 92 | /// sends the [InvocationResult] via [_client.postInvocationResponse(result)] to the API. 93 | /// If there is an error during the execution. The execption gets catched 94 | /// and the error is posted via [_client.postInvocationError(err)] to the API. 95 | void invoke() async { 96 | do { 97 | NextInvocation nextInvocation; 98 | 99 | try { 100 | // get the next invocation 101 | nextInvocation = await _client.getNextInvocation(); 102 | 103 | // creating the new context 104 | final context = Context.fromNextInvocation(nextInvocation); 105 | 106 | final func = _handlers[context.handler]; 107 | if(func == null) { 108 | throw RuntimeException('No handler with name "${context.handler}" registered in runtime!'); 109 | } 110 | final event = 111 | Event.fromHandler(func.type, await nextInvocation.response); 112 | final result = await func.handler(context, event); 113 | 114 | await _client.postInvocationResponse(result); 115 | } on Exception catch (error, stacktrace) { 116 | await _client.postInvocationError( 117 | nextInvocation.requestId, InvocationError(error, stacktrace)); 118 | } 119 | 120 | nextInvocation = null; 121 | } while (true); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: aws_lambda_dart_runtime 2 | version: 1.0.3+2 3 | description: |- 4 | A powerful runtime to build Lambda functions in Dart with native AWS events. 5 | homepage: https://github.com/awslabs/aws-lambda-dart-runtime 6 | documentation: https://awslabs.github.io/aws-lambda-dart-runtime/ 7 | 8 | environment: 9 | sdk: ">=2.6.0 <3.0.0" 10 | 11 | dependencies: 12 | json_annotation: ^3.0.0 13 | 14 | dev_dependencies: 15 | json_serializable: ^3.2.3 16 | build_runner: ^1.7.2 17 | test: ^1.9.4 18 | mockito: ^4.1.1 19 | pedantic: ^1.0.0 20 | -------------------------------------------------------------------------------- /test/alb_event_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 4 | import "package:test/test.dart"; 5 | 6 | void main() { 7 | group("albevent_default", () { 8 | test("factory creates response with default values", () { 9 | final response = AwsALBResponse.fromString("SUCCESS"); 10 | 11 | expect(response.body, equals("SUCCESS")); 12 | expect(response.statusCode, equals(200)); 13 | expect(response.isBase64Encoded, equals(false)); 14 | }); 15 | 16 | test("factory creates a response with HTTP Status 400", () { 17 | final response = AwsALBResponse.fromString("SUCCESS", 18 | statusCode: HttpStatus.badRequest); 19 | 20 | expect(response.body, equals("SUCCESS")); 21 | expect(response.statusCode, equals(HttpStatus.badRequest)); 22 | expect(response.isBase64Encoded, equals(false)); 23 | }); 24 | 25 | test("factory creates an event with html/text Header", () { 26 | final response = AwsALBResponse.fromString(""); 27 | 28 | expect(response.headers, 29 | equals({"Content-Type": "text/html; charset=utf-8"})); 30 | }); 31 | 32 | test("factory creates an event with JSON Header", () { 33 | final response = AwsALBResponse.fromString("", 34 | headers: {"Content-Type": "application/json"}); 35 | 36 | expect(response.headers, equals({"Content-Type": "application/json"})); 37 | }); 38 | 39 | test("factory creates response which is base64 encoded", () { 40 | final response = 41 | AwsALBResponse.fromString("SUCCESS", isBase64Encoded: true); 42 | 43 | expect(response.body, equals("SUCCESS")); 44 | expect(response.statusCode, equals(HttpStatus.ok)); 45 | expect(response.isBase64Encoded, equals(true)); 46 | }); 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /test/apigateway_event_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:io' show File; 3 | import 'dart:convert'; 4 | 5 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 6 | import "package:test/test.dart"; 7 | 8 | final file = 'data/apigateway_event.json'; 9 | 10 | final String contents = new File(file).readAsStringSync(); 11 | final Map json = jsonDecode(contents); 12 | 13 | void main() { 14 | group("apigateway_default", () { 15 | test("json got parsed and creates an event", () async { 16 | final event = AwsApiGatewayEvent.fromJson(json); 17 | 18 | expect(event.body, equals(jsonEncode({"foo": "bar"}))); 19 | expect(event.path, equals("/test/hello")); 20 | expect(event.headers.acceptEncoding, 21 | equals("gzip, deflate, lzma, sdch, br")); 22 | expect(event.requestContext.httpMethod, equals("POST")); 23 | expect(event.requestContext.accountId, equals("123456789012")); 24 | expect(event.requestContext.requestId, 25 | equals("41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9")); 26 | expect(event.queryStringParameters, equals({"name": "me"})); 27 | expect(event.requestContext.resourcePath, equals("/{proxy+}")); 28 | expect(event.headers.raw['Accept-Encoding'], 29 | equals("gzip, deflate, lzma, sdch, br")); 30 | }); 31 | test("factory creates event with default values", () { 32 | final response = AwsApiGatewayResponse.fromJson({}); 33 | 34 | expect(response.body, equals({}.toString())); 35 | expect(response.statusCode, equals(200)); 36 | expect(response.isBase64Encoded, equals(false)); 37 | }); 38 | 39 | test("factory creates an event with HTTP Status 400", () { 40 | final response = 41 | AwsApiGatewayResponse.fromJson({}, statusCode: HttpStatus.badRequest); 42 | 43 | expect(response.body, equals({}.toString())); 44 | expect(response.statusCode, equals(HttpStatus.badRequest)); 45 | expect(response.isBase64Encoded, equals(false)); 46 | }); 47 | 48 | test("factory creates an event with JSON Header", () { 49 | final response = AwsApiGatewayResponse.fromJson({}); 50 | 51 | expect(response.headers, equals({"Content-Type": "application/json"})); 52 | }); 53 | 54 | test("factory creates an event with text/html Header", () { 55 | final response = AwsApiGatewayResponse.fromJson({}, 56 | headers: {"Content-Type": "text/html; charset=utf-8"}); 57 | 58 | expect(response.headers, 59 | equals({"Content-Type": "text/html; charset=utf-8"})); 60 | }); 61 | 62 | test("factory creates an event with is based 64 encoded", () { 63 | final response = 64 | AwsApiGatewayResponse.fromJson({}, isBase64Encoded: true); 65 | 66 | expect(response.body, equals({}.toString())); 67 | expect(response.statusCode, equals(HttpStatus.ok)); 68 | expect(response.isBase64Encoded, equals(true)); 69 | }); 70 | }); 71 | } 72 | -------------------------------------------------------------------------------- /test/client_test.dart: -------------------------------------------------------------------------------- 1 | import "package:test/test.dart"; 2 | 3 | import 'package:aws_lambda_dart_runtime/client/client.dart'; 4 | 5 | void main() { 6 | group('invocation', () { 7 | test("invocation result gets populated", () { 8 | final result = InvocationResult("1234567890", "SUCCESS"); 9 | 10 | expect(result.requestId, "1234567890"); 11 | expect(result.body, "SUCCESS"); 12 | }); 13 | 14 | test("invocation error gets populated", () { 15 | final stateError = new StateError("foo"); 16 | final invocationError = 17 | InvocationError(stateError, new StackTrace.fromString("")); 18 | 19 | expect(invocationError.error, stateError); 20 | }); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /test/cloudwatch_event_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io' show File; 3 | 4 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | final file = 'data/cloudwatch_event.json'; 8 | 9 | final String contents = new File(file).readAsStringSync(); 10 | final Map json = jsonDecode(contents); 11 | 12 | void main() { 13 | group("cloudwatch_default", () { 14 | test("json got parsed and creates an event", () async { 15 | final event = AwsCloudwatchEvent.fromJson(json); 16 | 17 | expect(event.account, equals("1234567890")); 18 | expect(event.region, equals("eu-west-1")); 19 | expect(event.detailType, equals("Scheduled Event")); 20 | expect(event.id, equals("cdc73f9d-aea9-11e3-9d5a-835b769c0d9c")); 21 | expect(event.detail, equals({})); 22 | expect(event.time, equals(DateTime.parse("1970-01-01T00:00:00Z"))); 23 | }); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /test/cloudwatch_log_event_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io' show File; 3 | 4 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | final file = 'data/cloudwatch_log_event.json'; 8 | 9 | final String contents = new File(file).readAsStringSync(); 10 | final Map json = jsonDecode(contents); 11 | 12 | void main() { 13 | group("cloudwatch_log_default", () { 14 | test("json got parsed and creates an event", () async { 15 | final event = AwsCloudwatchLogEvent.fromJson(json); 16 | 17 | expect( 18 | event.awslogs, 19 | equals({ 20 | "data": 21 | "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA==" 22 | })); 23 | }); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /test/cognito_event_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io' show File; 3 | 4 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | final file = 'data/cognito_event.json'; 8 | 9 | final String contents = new File(file).readAsStringSync(); 10 | final Map json = jsonDecode(contents); 11 | 12 | void main() { 13 | group("cognito_default", () { 14 | test("json got parsed and creates an event", () async { 15 | final event = AwsCognitoEvent.fromJson(json); 16 | 17 | expect(event.version, equals(1)); 18 | expect(event.userPoolId, equals("1234567")); 19 | expect(event.userName, equals("foo")); 20 | expect(event.response.smsMessage, equals("foo")); 21 | expect(event.response.emailSubject, equals("foo")); 22 | expect(event.response.emailMessage, equals("bar")); 23 | }); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /test/common.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:mockito/mockito.dart'; 4 | 5 | class MockHttpClientResponse extends Mock implements HttpClientResponse { 6 | MockHttpClientResponse(this.statusCode, 7 | {this.result, this.headers, this.body}); 8 | 9 | @override 10 | final int statusCode; 11 | 12 | final String result; 13 | 14 | @override 15 | final HttpHeaders headers; 16 | 17 | // encode the response body as bytes. 18 | final List body; 19 | } 20 | 21 | /// A mocked [HttpHeaders] that ignores all writes. 22 | class MockHttpHeaders extends HttpHeaders { 23 | @override 24 | List operator [](String name) => []; 25 | 26 | @override 27 | void add(String name, Object value, {bool preserveHeaderCase = false}) {} 28 | 29 | @override 30 | void clear() {} 31 | 32 | @override 33 | void forEach(void Function(String name, List values) f) {} 34 | 35 | @override 36 | void noFolding(String name) {} 37 | 38 | @override 39 | void remove(String name, Object value) {} 40 | 41 | @override 42 | void removeAll(String name) {} 43 | 44 | @override 45 | void set(String name, Object value, {bool preserveHeaderCase = false}) {} 46 | 47 | @override 48 | String value(String name) => null; 49 | } 50 | -------------------------------------------------------------------------------- /test/context_test.dart: -------------------------------------------------------------------------------- 1 | import "dart:convert"; 2 | 3 | import "package:test/test.dart"; 4 | 5 | import 'package:aws_lambda_dart_runtime/runtime/context.dart'; 6 | import 'package:aws_lambda_dart_runtime/client/client.dart'; 7 | import 'common.dart'; 8 | 9 | void main() { 10 | group('context', () { 11 | test("Context gets initialized with a Platform.environment", () async { 12 | final Map environment = { 13 | "_HANDLER": "foo", 14 | "AWS_LAMBDA_FUNCTION_NAME": "bar", 15 | "AWS_LAMBDA_FUNCTION_VERSION": "1", 16 | "AWS_LAMBDA_LOG_GROUP_NAME": "foo", 17 | "AWS_LAMBDA_LOG_STREAM_NAME": "foo", 18 | "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "128", 19 | "AWS_REGION": "eu-west-1", 20 | "AWS_EXECUTION_ENV": "foo", 21 | "AWS_ACCESS_KEY_ID": "secret", 22 | "AWS_SECRET_ACCESS_KEY": "key", 23 | "AWS_SESSION_TOKEN": "1234567890" 24 | }; 25 | 26 | final headers = MockHttpHeaders(); 27 | 28 | final response = MockHttpClientResponse(200, 29 | result: "", headers: headers, body: utf8.encode("{}")); 30 | final nextInvocation = await NextInvocation.fromResponse(response); 31 | 32 | final ctx = Context.fromNextInvocation(nextInvocation); 33 | 34 | expect(ctx.handler, environment["_HANDLER"]); 35 | expect(ctx.functionName, environment["AWS_LAMBDA_FUNCTION_NAME"]); 36 | expect(ctx.functionVersion, environment["AWS_LAMBDA_FUNCTION_VERSION"]); 37 | expect(ctx.logGroupName, environment["AWS_LAMBDA_LOG_GROUP_NAME"]); 38 | expect(ctx.logStreamName, environment["AWS_LAMBDA_LOG_STREAM_NAME"]); 39 | expect(ctx.functionMemorySize, 40 | environment["AWS_LAMBDA_FUNCTION_MEMORY_SIZE"]); 41 | expect(ctx.region, environment["AWS_REGION"]); 42 | expect(ctx.executionEnv, environment["AWS_EXECUTION_ENV"]); 43 | expect(ctx.accessKey, environment["AWS_ACCESS_KEY_ID"]); 44 | expect(ctx.secretAccessKey, environment["AWS_SECRET_ACCESS_KEY"]); 45 | expect(ctx.sessionToken, environment["AWS_SESSION_TOKEN"]); 46 | }); 47 | }, skip: "the tests are not quite ready"); 48 | } 49 | -------------------------------------------------------------------------------- /test/dynamodb_event_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io' show File; 3 | 4 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | final file = 'data/dynamodb_event.json'; 8 | 9 | final String contents = new File(file).readAsStringSync(); 10 | final Map json = jsonDecode(contents); 11 | 12 | void main() { 13 | group("dynamodb_default", () { 14 | test("json got parsed and creates an event", () async { 15 | final event = AwsDynamoDBUpdateEvent.fromJson(json); 16 | 17 | expect(event.records.length, equals(1)); 18 | }); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/event_test.dart: -------------------------------------------------------------------------------- 1 | import "package:test/test.dart"; 2 | 3 | import 'package:aws_lambda_dart_runtime/runtime/event.dart'; 4 | 5 | class CustomTestEvent { 6 | factory CustomTestEvent.fromJson(Map json) { 7 | return CustomTestEvent(); 8 | } 9 | 10 | const CustomTestEvent(); 11 | } 12 | 13 | void main() { 14 | group('runtime', () { 15 | test("Custom event is add to the events", () { 16 | Event.registerEvent( 17 | (Map json) => CustomTestEvent.fromJson({})); 18 | 19 | expect(Event.exists(), true); 20 | }); 21 | 22 | test("Custom event is deregistered", () { 23 | Event.registerEvent( 24 | (Map json) => CustomTestEvent.fromJson({})); 25 | 26 | Event.deregisterEvent(); 27 | 28 | expect(Event.exists(), false); 29 | }); 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /test/exception_test.dart: -------------------------------------------------------------------------------- 1 | import "package:test/test.dart"; 2 | 3 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 4 | 5 | void main() { 6 | group("runtime exception", () { 7 | test("return the cause a string", () { 8 | final exception = RuntimeException("missing handler"); 9 | expect(exception.toString(), equals("RuntimeException: missing handler")); 10 | }); 11 | 12 | test("catch exception with cause", () { 13 | try { 14 | throw RuntimeException("missing handler"); 15 | } on RuntimeException catch (e) { 16 | expect(e.cause, 'missing handler'); 17 | return; 18 | } 19 | }); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/kinesis_data_firehose_event.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io' show File; 3 | 4 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | final file = 'data/kinesis_data_firehose_event.json'; 8 | 9 | final String contents = new File(file).readAsStringSync(); 10 | final Map json = jsonDecode(contents); 11 | 12 | void main() { 13 | group("kinesis_firehose_default", () { 14 | test("json got parsed and creates an event", () async { 15 | final event = AwsKinesisFirehoseDataEvent.fromJson(json); 16 | 17 | expect(event.records.length, equals(1)); 18 | expect(event.invocationId, equals("invocationIdExample")); 19 | expect(event.deliveryStreamArn, equals("arn:aws:kinesis:EXAMPLE")); 20 | expect(event.region, equals("eu-west-1")); 21 | expect(event.records[0].recordId, 22 | equals("49546986683135544286507457936321625675700192471156785154")); 23 | expect( 24 | event.records[0].approximateArrivalTimestamp, equals(1495072949453)); 25 | expect(event.records[0].data, 26 | equals("SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=")); 27 | }); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /test/kinesis_data_stream_event_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io' show File; 3 | 4 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | final file = 'data/kinesis_data_stream_event.json'; 8 | 9 | final String contents = new File(file).readAsStringSync(); 10 | final Map json = jsonDecode(contents); 11 | 12 | void main() { 13 | group("kinesis_default", () { 14 | test("json got parsed and creates an event", () async { 15 | final event = AwsKinesisDataStreamEvent.fromJson(json); 16 | 17 | expect(event.records.length, equals(1)); 18 | expect(event.records[0].eventSource, equals("aws:kinesis")); 19 | expect( 20 | event.records[0].eventID, 21 | equals( 22 | "shardId-000000000000:49545115243490985018280067714973144582180062593244200961")); 23 | expect( 24 | event.records[0].eventSourceARN, equals("arn:aws:kinesis:EXAMPLE")); 25 | expect(event.records[0].awsRegion, equals("eu-west-1")); 26 | expect(event.records[0].eventVersion, equals("1.0")); 27 | expect( 28 | event.records[0].invokeIdentityArn, equals("arn:aws:iam::EXAMPLE")); 29 | expect(event.records[0].kinesis.partitionKey, equals("partitionKey-03")); 30 | expect(event.records[0].kinesis.data, 31 | equals("SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=")); 32 | expect(event.records[0].kinesis.sequenceNumber, 33 | equals("49545115243490985018280067714973144582180062593244200961")); 34 | }); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /test/runtime_test.dart: -------------------------------------------------------------------------------- 1 | import "package:test/test.dart"; 2 | 3 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 4 | 5 | void main() { 6 | group('runtime', () { 7 | test("instance is created without error", () { 8 | expect(() => Runtime(), returnsNormally); 9 | }); 10 | 11 | test("instance is same accross invocation", () async { 12 | final runtime = await Runtime(); 13 | 14 | expect(runtime, await Runtime()); 15 | }); 16 | 17 | test("successfully add a handler to runtime", () async { 18 | final runtime = await Runtime(); 19 | 20 | final Handler testHandler = (context, event) async { 21 | return new InvocationResult(context.requestId, "HELLO WORLD"); 22 | }; 23 | 24 | final addHandler = runtime.registerHandler("test.handler", testHandler); 25 | 26 | expect(runtime.handlerExists("test.handler"), equals(true)); 27 | expect(addHandler, equals(testHandler)); 28 | }); 29 | 30 | test("successfully deregister a handler to runtime", () async { 31 | final runtime = await Runtime(); 32 | 33 | final Handler testHandler = (context, event) async { 34 | return new InvocationResult(context.requestId, "HELLO WORLD"); 35 | }; 36 | 37 | runtime.registerHandler("test.handler", testHandler); 38 | final removedHandler = 39 | runtime.deregisterHandler("test.handler"); 40 | 41 | expect(runtime.handlerExists("test.handler"), equals(false)); 42 | expect(removedHandler, equals(testHandler)); 43 | }); 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /test/s3_event.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io' show File; 3 | 4 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | final file = 'data/s3_event.json'; 8 | 9 | final String contents = new File(file).readAsStringSync(); 10 | final Map json = jsonDecode(contents); 11 | 12 | void main() { 13 | group("s3_default", () { 14 | test("json got parsed and creates an event", () async { 15 | final event = AwsS3Event.fromJson(json); 16 | 17 | expect(event.records[0].eventVersion, equals("2.0")); 18 | expect(event.records[0].eventSource, equals("aws:s3")); 19 | expect(event.records[0].awsRegion, equals("eu-west-1")); 20 | expect(event.records[0].eventTime, 21 | equals(DateTime.parse("1970-01-01T00:00:00.000Z"))); 22 | expect(event.records[0].eventName, equals("ObjectCreated:Put")); 23 | expect(event.records[0].userIdentity.principalId, equals("EXAMPLE")); 24 | expect(event.records[0].requestParameters["sourceIPAddress"], 25 | equals("127.0.0.1")); 26 | expect(event.records[0].s3.s3SchemaVersion, equals("1.0")); 27 | expect(event.records[0].s3.configurationId, equals("testConfigRule")); 28 | }); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /test/sqs_event_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io' show File; 3 | 4 | import 'package:aws_lambda_dart_runtime/aws_lambda_dart_runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | final file = 'data/sqs_event.json'; 8 | 9 | final String contents = new File(file).readAsStringSync(); 10 | final Map json = jsonDecode(contents); 11 | 12 | void main() { 13 | group("sqs_default", () { 14 | test("json got parsed and creates an event", () async { 15 | final event = AwsSQSEvent.fromJson(json); 16 | 17 | expect(event.records.length, equals(1)); 18 | expect(event.records[0].md5OfBody, 19 | equals("7b270e59b47ff90a553787216d55d91d")); 20 | expect(event.records[0].eventSource, equals("aws:sqs")); 21 | expect(event.records[0].eventSourceARN, 22 | equals("arn:aws:sqs:eu-west-1:123456789012:MyQueue")); 23 | expect(event.records[0].awsRegion, equals("eu-west-1")); 24 | expect(event.records[0].body, equals("Hello from SQS!")); 25 | expect(event.records[0].messageId, 26 | equals("19dd0b57-b21e-4ac1-bd88-01bbb068cb78")); 27 | expect(event.records[0].receiptHandle, equals("MessageReceiptHandle")); 28 | }); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /test/testing.dart: -------------------------------------------------------------------------------- 1 | library testing; 2 | 3 | export 'common.dart'; 4 | --------------------------------------------------------------------------------