Releases: aws-powertools/powertools-lambda-python
v1.18.1
Summary
Fix a pesky regression introduced when fixing API Gateway/ALB Event Handler routing regex in 1.18.0. This bug made numeric and safe URI chars to return 404 -- Big thanks to @moretension for raising it
Changes
🐛 Bug and hot fixes
- fix(api-gateway): route regression for non-word and unsafe URI chars (#556) by @heitorlessa
This release was made possible by the following contributors:
v1.18.0
Summary
This release mainly focused on bug fixes and a few minor features, so we can spend time documenting a new utility (Feature Toggles) that will be fully available in 1.19.0.
Bug fixes were largely on MyPy errors (~600 to 38) across the entire code base. We also fixed a a) faulty greedy regex in the API Gateway event handler when dealing with long and dynamic routes (more in Changes section), b) Parser authorization and version fields for API Gateway that should've been optional, and c) Event Source Data Classes to conform with AppSync Scalar by including milliseconds in the time resolution.
We also had two new first-time contributors: 👏 @walmsles and @whardier, we appreciate your help with this release!
Changes
New get_correlation_id method in Logger
You can now retrieve the latest correlation ID previously set in the Logger instance at any part of the code base. This is useful when propagating correlation ID for external calls whether these are AWS service integrations or 3rd party endpoints.
from aws_lambda_powertools import Logger
logger = Logger(service="payment")
@logger.inject_lambda_context(correlation_id_path="headers.my_request_id_header")
def handler(event, context):
logger.debug(f"NEW Correlation ID => {logger.get_correlation_id()}")
Debug mode and HTTP service errors in Event Handlers
You can now easily enable debug mode for API Gateway or ALB event handlers. Additionally, we've made it easier to raise quick HTTP service errors in response to malformed requests, resources not found, etc.
from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver
from aws_lambda_powertools.event_handler.exceptions import (
BadRequestError,
InternalServerError,
NotFoundError,
ServiceError,
UnauthorizedError,
)
app = ApiGatewayResolver(debug=True)
@app.get(rule="/bad-request-error")
def bad_request_error():
# HTTP 400
raise BadRequestError("Missing required parameter")
@app.get(rule="/unauthorized-error")
def unauthorized_error():
# HTTP 401
raise UnauthorizedError("Unauthorized")
@app.get(rule="/not-found-error")
def not_found_error():
# HTTP 404
raise NotFoundError
@app.get(rule="/internal-server-error")
def internal_server_error():
# HTTP 500
raise InternalServerError("Internal server error")
@app.get(rule="/service-error", cors=True)
def service_error():
raise ServiceError(502, "Something went wrong!")
# alternatively
# from http import HTTPStatus
# raise ServiceError(HTTPStatus.BAD_GATEWAY.value, "Something went wrong)
def handler(event, context):
return app.resolve(event, context)
Data model sub-classing in AppSync event handler
When building data-driven APIs using GraphQL and AppSync, you might have a set of reusable methods you want closer to the data model. Event Handler for AppSync supports a new parameter data_model
to facilitate that.
You can now subclass AppSyncResolverEvent
from Event Source Data Classes while handling incoming requests with Event Handler for AppSync.
from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.event_handler import AppSyncResolver
tracer = Tracer(service="sample_resolver")
logger = Logger(service="sample_resolver")
app = AppSyncResolver()
class MyCustomModel(AppSyncResolverEvent):
@property
def country_viewer(self) -> str:
return self.request_headers.get("cloudfront-viewer-country")
@app.resolver(field_name="listLocations")
@app.resolver(field_name="locations")
def get_locations(name: str, description: str = ""):
if app.current_event.country_viewer == "US":
...
return name + description
@logger.inject_lambda_context(correlation_id_path=correlation_paths.APPSYNC_RESOLVER)
@tracer.capture_lambda_handler
def lambda_handler(event, context):
return app.resolve(event, context, data_model=MyCustomModel)
Bugfix API Gateway routing params
This fixes a regex bug that used a greedy pattern ending with incorrect path resolution, as any path after a pattern would be included in the argument.
Excerpt:
@app.get("/accounts/<account_id>")
def get_account(account_id: str):
print(f"Account ID ({account_id}) would be 123")
# Greedy regex would inject the incorrect function parameter
@app.get("/accounts/<account_id>/source_networks")
def get_account_networks(account_id: str):
print(f"Account ID ({account_id}) would be 123/source_networks")
In this example, say we have a GET request as /accounts/123
and another as /accounts/123/source_networks
, we'd have the following effect prior to this fix:
Function | Regex | Effective account_id value |
---|---|---|
get_account | r'^/accounts/(?P<account_id>.+)$' |
123 |
get_account_networks | r'^/accounts/(?P<account_id>.+)/source_networks$' |
123/source_networks |
With this fix, account_id
parameter would be 123 in both occasions due to word boundary not being non-greedy. This also allows an arbitrary number of dynamic route paths and static route paths.
Function | Regex | Effective account_id value |
---|---|---|
get_account | r'^/accounts/(?P<account_id>\\w+\\b)$' |
123 |
get_account_networks | r'^/accounts/(?P<account_id>\\w+\\b)/source_networks$' |
123 |
🌟New features and non-breaking changes
- feat(appsync): Support AppSyncResolverEvent subclassing (#526) by @whardier
- feat(logger): add get_correlation_id method (#516) by @michaelbrewer
- feat(feat-toggle): new simple feature toggles rule engine (WIP) (#494) by @risenberg-cyberark
- feat(api-gateway): add debug mode (#507) by @michaelbrewer
- feat(api-gateway): add common HTTP service errors (#506) by @michaelbrewer
📜 Documentation updates
- docs(api-gateway): new HTTP service error exceptions (#546) by @heitorlessa
- docs(logger): new get_correlation_id method (#545) by @heitorlessa
- feat(appsync): Support AppSyncResolverEvent subclassing (#526) by @whardier
🐛 Bug and hot fixes
- fix(api-gateway): non-greedy route pattern regex (#533) by @heitorlessa
- fix(tracer): mypy generic to preserve decorated method signature (#529) by @heitorlessa
- fix(data-classes): include milliseconds in scalar types (#504) by @michaelbrewer
- fix(parser): Make ApiGateway version, authorizer fields optional (#532) by @walmsles
- fix(mypy): addresses lack of optional types (#521) by @michaelbrewer
🔧 Maintenance
- chore: bump 1.18.0 (#547) by @heitorlessa
- chore(deps-dev): bump mkdocs-material from 7.1.10 to 7.1.11 (#542) by @dependabot
- chore(deps): bump codecov/codecov-action from 1 to 2.0.1 (#539) by @dependabot
- refactor(feature-toggles): code coverage and housekeeping (#530) by @michaelbrewer
- chore(deps): bump boto3 from 1.18.0 to 1.18.1 (#528) by @dependabot
- chore(deps): bump boto3 from 1.17.110 to 1.18.0 (#527) by @dependabot
- chore(deps-dev): bump mkdocs-material from 7.1.9 to 7.1.10 (#522) by @dependabot
- chore(deps): bump boto3 from 1.17.102 to 1.17.110 (#523) by @dependabot
- chore(deps-dev): bump isort from 5.9.1 to 5.9.2 (#514) by @dependabot
- chore(mypy): add mypy support to makefile (#508) by @michaelbrewer
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa, @michaelbrewer, @risenberg-cyberark, @walmsles and @whardier
v1.17.1
Summary
This patch release fixes JSON Schema Validation utility when a built-in format date-time
is used but previously unrecognized.
Additionally, this includes Dark Mode (🕶️) to the Documentation, Serverless Framework and CDK examples for installing Lambda Layers from SAR, and clarifications on logger and auto-capture tracer's feature.
Changes
📜 Documentation updates
- docs(logger): add FAQ for cross-account searches (#501) by @heitorlessa
- docs: add Layers example for Serverless framework & CDK (#500) by @heitorlessa
- docs(tracer): additional scenario when to disable auto-capture (#499) by @heitorlessa
- docs: enable dark mode switch (#471) by @michaelbrewer
🐛 Bug and hot fixes
- fix(validator): handle built-in custom formats correctly (#498) by @heitorlessa
🔧 Maintenance
- chore: bump 1.17.1 (#502) by @heitorlessa
- chore(deps): bump boto3 from 1.17.101 to 1.17.102 (#493) by @dependabot
- chore(deps-dev): bump flake8-eradicate from 1.0.0 to 1.1.0 (#492) by @dependabot
- chore(deps-dev): bump isort from 5.8.0 to 5.9.1 (#487) by @dependabot
- chore(deps): bump boto3 from 1.17.91 to 1.17.101 (#490) by @dependabot
- chore(deps): bump email-validator from 1.1.2 to 1.1.3 (#478) by @dependabot
- chore(deps-dev): bump mkdocs-material from 7.1.7 to 7.1.9 (#491) by @dependabot
- chore(deps): bump boto3 from 1.17.89 to 1.17.91 (#473) by @dependabot
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa and @michaelbrewer
v1.17.0
Summary
This release brings a 1/ new handy decorator event_source
for data classes, 2/ API Gateway HTTP API support for Parser, 3/ a new parameter to reset logging state upon every Lambda invocation in Logger, and 4/ high level methods to fetch attribute values and their types when using DynamoDBStreamEvent
data class.
Event source decorator
Similarly to Parser's parse
decorator, you can now use event_source
decorator to instantiate a data class as part of the invocation more easily.
from typing import Dict, Any
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEventV2, event_source
from aws_lambda_powertools.utilities.typing import LambdaContext
@event_source(data_class=APIGatewayProxyEventV2)
def lambda_handler(event: APIGatewayProxyEventV2, context: LambdaContext) -> Dict[str, Any]:
assert event.get_header_value("x-foo") == "Foo"
This also gives you the ability to combine other utilities like Idempotency which expects a dictionary to serialize/deserialize without losing the benefits of self-documented schema and high level data methods.
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEventV2, event_source
from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools.utilities.idempotency import (
DynamoDBPersistenceLayer, idempotent
)
persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
@event_source(data_class=APIGatewayProxyEventV2)
@idempotent(persistence_store=persistence_layer)
def lambda_handler(event: APIGatewayProxyEventV2, context):
assert isinstance(event, APIGatewayProxyEventV2)
API Gateway HTTP API Parser support
Parser now supports API Gateway HTTP API as a native model in addition to REST API.
from typing import Dict, Any
from aws_lambda_powertools.utilities.parser import envelopes, event_parser
from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventV2Model
@event_parser(model=APIGatewayProxyEventV2Model)
def lambda_handler(event: APIGatewayProxyEventV2Model, context: LambdaContext) -> Dict[str, Any]:
...
Like REST API, Parser also supports an envelope for HTTP API to help you extract your model from the payload, providing deep data validation, type enforcement at runtime, and more.
from typing import Dict, Any
from aws_lambda_powertools.utilities.parser import envelopes, event_parser
from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventV2Model
from aws_lambda_powertools.utilities.parser.pydantic import EmailStr, UUID4, Json
class UserModel(BaseModel):
id: UUID4
username: str
preferences: Json
email: EmailStr
@event_parser(model=APIGatewayProxyEventV2Model, envelope=envelopes.ApiGatewayV2Envelope)
def lambda_handler(event: UserModel, context: LambdaContext) -> Dict[str, Any]:
assert event.username == "ran_isenberg"
Resetting Logger state on every invocation
As Logger is initialized in the global scope, logging state can persist across invocations. It is a good practice to always append new keys and use default values (None
if unavailable), so Logger can update and remove keys on a per invocation basis.
However, there are times where you might add keys conditionally depending on the incoming event. For these type of use cases, you can now use clear_state
parameter when using inject_lambda_context
decorator.
from aws_lambda_powertools import Logger
logger = Logger(service="payment")
@logger.inject_lambda_context(clear_state=True)
def handler(event, context):
if event.get("special_key"):
# Should only be available in the first request log
# as the second request doesn't contain `special_key`
logger.append_keys(debugging_key="value")
logger.info("Collecting payment")
DynamoDB Stream Event AttributeValueType and AttributeValue
You can now introspect what DynamoDB Record type and value is more easily with AttributeValueType
and AttributeValue
. This is useful when you might want to deserialize or deal with certain records and their attributes differently based on their type, e.g. a map vs string.
Each DynamoDB key available in the stream record now has high level methods such as get_value
and get_type
.
from aws_lambda_powertools.utilities.data_classes import event_source, DynamoDBStreamEvent
from aws_lambda_powertools.utilities.data_classes.dynamo_db_stream_event import AttributeValueType, AttributeValue
from aws_lambda_powertools.utilities.typing import LambdaContext
@event_source(data_class=DynamoDBStreamEvent)
def lambda_handler(event: DynamoDBStreamEvent, context: LambdaContext):
for record in event.records:
key: AttributeValue = record.dynamodb.keys["id"]
if key == AttributeValueType.Number:
# {"N": "123.45"} => "123.45"
assert key.get_value == key.n_value
print(key.get_value)
elif key == AttributeValueType.Map:
assert key.get_value == key.map_value
print(key.get_value)
You can find their respective implementations and all contributors below.
Changes
🌟New features and non-breaking changes
- feat(logger): add option to clear state per invocation (#467) by @heitorlessa
- feat(data-classes): add AttributeValueType to DynamoDBStreamEvent (#462) by @michaelbrewer
- feat(data-classes): decorator to instantiate data_classes and docs updates (#442) by @michaelbrewer
- feat(parser): add support for API Gateway HTTP API #434 (#441) by @risenberg-cyberark
📜 Documentation updates
- feat(logger): add option to clear state per invocation (#467) by @heitorlessa
- feat(data-classes): decorator to instantiate data_classes and docs updates (#442) by @michaelbrewer
- docs: include new public roadmap (#452) by @heitorlessa
- feat(parser): add support for API Gateway HTTP API #434 (#441) by @risenberg-cyberark
🔧 Maintenance
- chore(deps): bump boto3 from 1.17.88 to 1.17.89 (#466) by @dependabot
- chore(deps): bump boto3 from 1.17.87 to 1.17.88 (#463) by @dependabot
- chore(deps-dev): bump mkdocs-material from 7.1.6 to 7.1.7 (#464) by @dependabot
- chore(deps): bump boto3 from 1.17.86 to 1.17.87 (#459) by @dependabot
- chore(deps): bump boto3 from 1.17.85 to 1.17.86 (#458) by @dependabot
- chore(deps): bump boto3 from 1.17.84 to 1.17.85 (#455) by @dependabot
- chore(deps-dev): bump pytest-cov from 2.12.0 to 2.12.1 (#454) by @dependabot
- chore: update mergify to require approval on dependabot (#456) by @heitorlessa
- chore: bump actions/setup-python from 1 to 2.2.2 (#445) by @dependabot
- chore: bump xenon from 0.7.1 to 0.7.3 (#446) by @dependabot
- chore: bump boto3 from 1.17.78 to 1.17.84 (#449) by @dependabot
- chore: bump mkdocs-material from 7.1.5 to 7.1.6 (#451) by @dependabot
- build(deps-dev): bump pytest-asyncio from 0.14.0 to 0.15.1 (#448) by @dependabot
- chore: enable mergify (#450) by @heitorlessa
- chore: enable dependabot for dep upgrades (#444) by @heitorlessa
- chore: assited changelog pre-generation, auto-label PR (#443) by @heitorlessa
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa, @michaelbrewer and @risenberg-cyberark
v1.16.1
Summary
Emergency release to patch Pydantic against CVE-2021-29510used by Parser utility - This causes resource starvation when parsing infinity/-inf
values.
Thanks to @risenberg-cyberark for the quick turnaround.
Changes
This release was made possible by the following contributors:
@risenberg-cyberark
v1.16.0
Summary
This release adds support for CodePipeline Job event, and a new property to save you some keystrokes when decoding base64 encoded data in API Gateway and ALB when using Data Classes utility.
CodePipeline Job support
If you're new to the CodePipeline Job event, customers typically use it for out of band integrations, such as orchestrate heavy deployments with a State Machine or validate an external system/KPI before continuing.
This release adds support for CodePipeline Job including methods to easily retrieve user parameters, download artifacts from S3 using temporary credentials sent as part of event, etc.
Base64 decode support
Based on this thread on Twitter with Luc from SentiaCloud, decoding base64 data in the first try without looking at a snippet is not for everyone :D
When using Data classes for API Gateway or ALB, you can now easily decode data with the new decoded_body
property:
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent
def lambda_handler(event: dict, context):
event = APIGatewayProxyEvent(event)
# Dynamically base64 decode body as a str
body: str = event.decoded_body
return body
Changes
🌟 New features and non-breaking changes
- feat(data-classes): support for code pipeline job event (#416) by @michaelbrewer
🌟 Minor Changes
- feat(data-classes): decode base64 encoded body (#425) by @michaelbrewer
This release was made possible by the following contributors:
v1.15.1
Summary
Quick release to fix a regression in Logger for the %s
operator.
Changes
🌟 Minor Changes
📜 Documentation updates
- fix(docs): Use updated names for ProxyEventType (#424) by @michaelbrewer
This release was made possible by the following contributors:
v1.15.0
Summary
This release has three major goodies: 1/ Idempotency utility is now GA, 2/ New API Gateway and ALB event handler, and 3/ MANY enhancements to Logger.
Idempotency
Idempotency utility was introduced in 1.11.0 as beta. If you haven't used it yet, it converts Lambda functions into idempotent operations that are safe to retry - This is mostly needed when your code is not idempotent.
Since launch, we've made improvements to error handling and documentation updates. This gives us confidence that the UX won't radically change and therefore can be used safely moving forward.
API Gateway and ALB event handler
huge thanks to @michaelbrewer
This new utility provides a lightweight routing to reduce boilerplate for API Gateway REST/HTTP API and ALB. It also natively integrates with Data classes utility giving you handy methods and self-documented properties of API Gateway and ALB events.
It's important to note that this is not a replacement for fully fledged web frameworks like Flask and Djano, or microframeworks like Chalice. Instead, this gives you a nearly zero overhead (~1-2ms) lightweight solution to build applications on top of either API Gateway or ALB.
As a trade-off for being so lightweight, you have to setup infrastructure to use Lambda Proxy Integration using your preferred framework be that CloudFormation, SAM, CDK, Terraform, etc. Rest assured we provide a sample template to demonstrate how you can configure it if you haven't done this yet.
Did I say CORS is simplified too? :)
Logger
This release makes Logger more flexible by allowing you to bring your own Logging Formatter and Handler. It also includes a ton of improvements such as:
- Easily remap keys or bring own defaults by inheriting the now exposed
LambdaPowertoolsFormatter
- UTC support with as simple as
utc=True
flag - Easier methods to add or remove logging keys at runtime with
append_keys()
andremove_keys()
. The previous method,structure_logs(append=True, ...)
, will continue to work for backwards compatibility and will be effectively when we decide to cut a major version (2.0) - warnings will be place in time too - All keys can be reordered including the ones you're going to introduce yet at runtime
sampling_rate
key only gets added when feature is added- Bring your own JSON serializer or deserializer function like the ultra fast Orjson, for when you need to crunch every possible ms
timestamp
key now includes timezone at the end: from2021-05-03 11:47:12,494
to2021-05-03 11:47:12,494+0200
API Gateway support for Parser
huge thanks to @risenberg-cyberark
You can now easily parse and run deep data validation with APIGatewayProxyEvent
in Parser, including an envelope ApiGatewayEnvelope
.
Metrics
Last but not least, you can now set default metric dimensions to ensure these will always be added across all metrics: metrics.set_default_dimensions(environment="prod", another="one")
Changes
🌟New features and non-breaking changes
- refactor(event-handler): Add ResponseBuilder and more docs (#412) by @michaelbrewer
- feat(event-handler): add http ProxyEvent handler (#369) by @michaelbrewer
- feat(metrics): add support to persist default dimensions (#410) by @heitorlessa
- refactor(logger): BYOFormatter and Handler, UTC support, and more (#404) by @heitorlessa
- feat(parser): Support for API GW v1 proxy schema & envelope (#403) by @risenberg-cyberark
🌟 Minor Changes
- feat(event-handler): allow for
cors=None
setting (#421) by @michaelbrewer - refactor(event-handler): api gateway handler review changes (#420) by @michaelbrewer
- refactor: simplify custom formatter for minor changes (#417) by @heitorlessa
📜 Documentation updates
- docs(api_gateway): new event handler for API Gateway and ALB (#418) by @heitorlessa
- docs(logger): improvements extensibility & new features (#415) by @heitorlessa
- fix(docs): workflow to include api ref in latest alias (#408) by @heitorlessa
- docs(tracer): Fix line highlighting (#395) by @michaelbrewer
🐛 Bug and hot fixes
- fix(parser): Improve types for parser.py (#419) by @carlos-alberto
- fix(validator): event type annotation as any in validate fn (#405) by @heitorlessa
Internal
- chore: bump to 1.15.0 (#422) by @heitorlessa
- fix(deps): Bump aws-xray-sdk from 2.6.0 to 2.8.0 (#413) by @michaelbrewer
This release was made possible by the following contributors:
@carlos-alberto, @heitorlessa, @michaelbrewer and @risenberg-cyberark
v1.14.0
Summary
This release a new Event Handlers core utility, and enables versioning for documentation so you can access staging docs early or a specific release doc.
Additionally, there are a number of enhancements in the documentation, Parser's support for S3 Object Lambda event, a better support for MyPy (more to come), etc.
Event Handlers
This is a new core utility to help you reduce boilerplate when working with Event Sources. For example, you can now have clearly defined single purpose methods to be called depending on what's inside the event instead of nested flow controls (if/else/elif).
AWS AppSync is our first event handler (thanks to @michaelbrewer), and we would love to hear from you what other event handlers would be useful to boost your experience even further.
Notice how you can combine AppSync scalar utilities, Logger correlation ID, Tracer, and have tiny functions to compute a given GraphQL field or type now.
Versioned docs
Some of you might have already noticed a new version switch at the top of the documentation, including additional stats from GitHub directly on the top right corner.
This means you can now access early versions of the documentation before we release as well as the last two releases. This opens the door for a possible nightly build release :)
Changes
🌟New features and non-breaking changes
- docs: enable versioning feature (#374) by @heitorlessa
- feat(event-handler): Add AppSync handler decorator (#363) by @michaelbrewer
- feat(parser): Add S3 Object Lambda Event (#362) by @risenberg-cyberark
🌟 Minor Changes
- feat(parameter): add dynamodb_endpoint_url for local_testing (#376) by @rtrive
- fix(data-classes): Add missing operationName (#373) by @michaelbrewer
- fix(tracer): Correct type hint for MyPy (#365) by @michaelbrewer
📜 Documentation updates
- docs(logger): add example on how to set UTC timestamp (#392) by @heitorlessa
- docs(idempotency): add default table configuration for those not using IaC (#391) by @heitorlessa
- docs: Correct link targets and line highlights (#390) by @michaelbrewer
- docs(validator): include more complete examples & intro to JSON Schema (#389) by @heitorlessa
- docs: introduce event handlers utility section (#388) by @heitorlessa
- docs: Fix doc links and line highlights (#380) by @michaelbrewer
- docs: enable versioning feature (#374) by @heitorlessa
🐛 Bug and hot fixes
- fix: lock X-Ray SDK to 2.6.0 due to regression (#384) by @heitorlessa
- fix(idempotent): Correctly raise IdempotencyKeyError (#378) by @michaelbrewer
- fix(parser): S3Model support empty keys (#375) by @heitorlessa
- fix(metrics): AttributeError raised by MetricManager and Typing and docs (#357) by @michaelbrewer
🔧 Internal
- fix: downgrade poetry to 1.1.4 (#385) by @heitorlessa
- build(pre-commit): Add pre-commit to
make pr
(#368) by @michaelbrewer
This release was made possible by the following contributors:
@heitorlessa, @michaelbrewer, @risenberg-cyberark and @rtrive
Discussion: #394
v1.13.0
Summary
Quick release to add support for the new S3 Object Lambda event within Event Source Data Classes utility - Thanks to @michaelbrewer
Event Source Data Classes utility provides self-documented schema for multiple Lambda Event Sources, and helper methods to easily parse, decode, and fetch common attributes, headers, and data in various forms.
Changes
🌟New features and non-breaking changes
- feat(data-classes): Add S3 Object Lambda Event (#353) by @michaelbrewer
📜 Documentation updates
- docs: Fix layers example template config (#350) by @BrockReece
🔧 Internal
- fix(deps): Bump dependencies and fix some of the dev tooling (#354) by @michaelbrewer
- fix(lint): Move
tests/THIRD-PARTY-LICENSES
to root (#352) by @michaelbrewer