Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a685af8
feat(api-gateway): enhance response handling in `Program.cs`
j-d-ha Dec 2, 2025
bd5a6b0
refactor(api-gateway): rename `ApiGatewayResponseEnvelope` to `ApiGat…
j-d-ha Dec 2, 2025
a7db5fc
feat(local-dev): enhance AWS Lambda test tool configuration
j-d-ha Dec 2, 2025
b3208b2
feat(api-gateway): add Microsoft.AspNetCore.Http package reference
j-d-ha Dec 2, 2025
eb49a41
refactor(api-gateway): update class naming from `ApiGatewayResponseEn…
j-d-ha Dec 2, 2025
3c7a91e
refactor(api-gateway): simplify handler logic and remove unused exten…
j-d-ha Dec 2, 2025
5744764
feat(api-gateway): extend `ApiGatewayResult` with additional status c…
j-d-ha Dec 2, 2025
958bbf9
feat(api-gateway): add factory methods for `201 Created` status in `A…
j-d-ha Dec 2, 2025
b9f80a8
feat(dependencies): add Microsoft.AspNetCore.Http package to Director…
j-d-ha Dec 14, 2025
5fa44c4
refactor(api-gateway): update namespace and dependency references in …
j-d-ha Dec 14, 2025
9f7fd71
feat(api-gateway): refactor and generalize `ApiGatewayResult` respons…
j-d-ha Dec 15, 2025
5caaac6
feat(local-dev): add `--config-storage-path` option to AWS Lambda tes…
j-d-ha Dec 15, 2025
2793bb8
feat(api-gateway): introduce `ApiGatewayV2Result` and remove redundan…
j-d-ha Dec 15, 2025
0426f7f
feat(envelopes): add `MinimalLambda.Envelopes` project to solution
j-d-ha Dec 15, 2025
9b73c77
feat(api-gateway): split extensions and enhance `ApiGatewayV2Result` …
j-d-ha Dec 15, 2025
ec45136
refactor(dependencies): remove `Microsoft.AspNetCore.Http` from `Dire…
j-d-ha Dec 15, 2025
826b01f
feat(envelopes): introduce `AlbResult` and enhance HTTP response cust…
j-d-ha Dec 15, 2025
b97b555
refactor(envelopes): rename `Configure` method to `Customize` across …
j-d-ha Dec 15, 2025
deba0e8
refactor(envelopes): remove `UpdateHttpResultExtensions` for cleanup
j-d-ha Dec 15, 2025
749ed49
feat(envelopes): add detailed XML comments for HTTP result extensions
j-d-ha Dec 15, 2025
96c5ec0
feat(envelopes): add missing XML documentation for `Customize` and `C…
j-d-ha Dec 15, 2025
6faef78
feat(envelopes): enhance XML documentation for AWS Lambda result classes
j-d-ha Dec 15, 2025
16b549a
refactor(envelopes): remove `Customize` method from result classes
j-d-ha Dec 15, 2025
833856d
feat(events): add `MinimalLambda.Envelopes` to `MinimalLambda.Example…
j-d-ha Dec 15, 2025
f06580c
refactor(envelopes): simplify `Create` method by removing unused para…
j-d-ha Dec 15, 2025
5518f03
refactor(envelopes): remove redundant `IHttpResult2` interface and un…
j-d-ha Dec 15, 2025
bca9e72
feat(envelopes): update package description and add README file
j-d-ha Dec 15, 2025
afbaeab
feat(docs): add `MinimalLambda.Envelopes` package references to READM…
j-d-ha Dec 15, 2025
229e581
feat(docs): add `AlbResult`, `ApiGatewayResult`, and `ApiGatewayV2Res…
j-d-ha Dec 15, 2025
4dabb1c
feat(docs): add detailed documentation for `MinimalLambda.Envelopes` …
j-d-ha Dec 15, 2025
ebba9be
feat(docs): update installation guide and add `MinimalLambda.Envelope…
j-d-ha Dec 15, 2025
1535b39
chore(build): bump version to 2.0.0-beta.7
j-d-ha Dec 15, 2025
fb1a9c8
feat(tests): add unit tests for `BaseHttpResultExtensions` methods
j-d-ha Dec 15, 2025
453cf46
feat(tests): add unit tests for `HttpResultExtensions` methods
j-d-ha Dec 15, 2025
37f3324
feat(envelopes): added more tests
j-d-ha Dec 15, 2025
c305d82
feat(tests): add unit tests for new `HttpResultExtensions` methods
j-d-ha Dec 15, 2025
8d3fae7
feat(envelopes): add `Create` methods for result creation from envelopes
j-d-ha Dec 15, 2025
bfc0aa6
feat(envelopes): update XML docs for `IHttpResult.Create` method
j-d-ha Dec 15, 2025
7cafce3
Merge branch 'main' into feature/#212-support-multiple-response-types…
j-d-ha Dec 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>2.0.0-beta.6</Version>
<Version>2.0.0-beta.7</Version>
<!-- SPDX license identifier for MIT -->
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<!-- Other useful metadata -->
Expand Down
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<PackageVersion Include="AutoFixture.Xunit3" Version="4.19.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
<PackageVersion Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Routing" Version="2.3.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.1" />
Expand Down
15 changes: 15 additions & 0 deletions MinimalLambda.sln
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalLambda.Testing.UnitT
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lambdas", "Lambdas", "{D9109C8A-AFA8-49C8-A19C-381500902B4D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalLambda.Envelopes", "src\Envelopes\MinimalLambda.Envelopes\MinimalLambda.Envelopes.csproj", "{190CC9C7-007F-48C5-867D-03B911D53397}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -435,6 +437,18 @@ Global
{381F49C0-297F-4B61-8A82-E9E502E523AD}.Release|x64.Build.0 = Release|Any CPU
{381F49C0-297F-4B61-8A82-E9E502E523AD}.Release|x86.ActiveCfg = Release|Any CPU
{381F49C0-297F-4B61-8A82-E9E502E523AD}.Release|x86.Build.0 = Release|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Debug|Any CPU.Build.0 = Debug|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Debug|x64.ActiveCfg = Debug|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Debug|x64.Build.0 = Debug|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Debug|x86.ActiveCfg = Debug|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Debug|x86.Build.0 = Debug|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Release|Any CPU.ActiveCfg = Release|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Release|Any CPU.Build.0 = Release|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Release|x64.ActiveCfg = Release|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Release|x64.Build.0 = Release|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Release|x86.ActiveCfg = Release|Any CPU
{190CC9C7-007F-48C5-867D-03B911D53397}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -471,5 +485,6 @@ Global
{7350482B-DFDE-4DCD-A0C5-899D5EA00F74} = {D9109C8A-AFA8-49C8-A19C-381500902B4D}
{381F49C0-297F-4B61-8A82-E9E502E523AD} = {D9109C8A-AFA8-49C8-A19C-381500902B4D}
{7E7B3004-C6C4-4A8C-8610-2A1CB61F834A} = {D9109C8A-AFA8-49C8-A19C-381500902B4D}
{190CC9C7-007F-48C5-867D-03B911D53397} = {1C3C52D9-2936-4A0C-A9C8-F330F22B8359}
EndGlobalSection
EndGlobal
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ including SQS, SNS, API Gateway, Kinesis, and more.

| Package | NuGet | Downloads |
|------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [**MinimalLambda.Envelopes**](./src/Envelopes/MinimalLambda.Envelopes/README.md) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes) | [![Downloads](https://img.shields.io/nuget/dt/MinimalLambda.Envelopes.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes/) |
| [**MinimalLambda.Envelopes.Sqs**](./MinimalLambda.Envelopes.Sqs/README.md) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.Sqs.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sqs) | [![Downloads](https://img.shields.io/nuget/dt/MinimalLambda.Envelopes.Sqs.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sqs/) |
| [**MinimalLambda.Envelopes.ApiGateway**](./MinimalLambda.Envelopes.ApiGateway/README.md) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.ApiGateway.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.ApiGateway) | [![Downloads](https://img.shields.io/nuget/dt/MinimalLambda.Envelopes.ApiGateway.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.ApiGateway/) |
| [**MinimalLambda.Envelopes.Sns**](./MinimalLambda.Envelopes.Sns/README.md) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.Sns.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sns) | [![Downloads](https://img.shields.io/nuget/dt/MinimalLambda.Envelopes.Sns.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sns/) |
Expand Down
125 changes: 125 additions & 0 deletions docs/features/envelopes.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Install only the envelopes you need; each one lives in its own NuGet package.

| Event Source | Package | NuGet |
|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Infrastructure / Base | [MinimalLambda.Envelopes](https://github.com/j-d-ha/minimal-lambda/tree/main/src/Envelopes/MinimalLambda.Envelopes) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes) |
| SQS | [MinimalLambda.Envelopes.Sqs](https://github.com/j-d-ha/minimal-lambda/tree/main/src/Envelopes/MinimalLambda.Envelopes.Sqs) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.Sqs.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sqs) |
| SNS | [MinimalLambda.Envelopes.Sns](https://github.com/j-d-ha/minimal-lambda/tree/main/src/Envelopes/MinimalLambda.Envelopes.Sns) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.Sns.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sns) |
| API Gateway / HTTP API | [MinimalLambda.Envelopes.ApiGateway](https://github.com/j-d-ha/minimal-lambda/tree/main/src/Envelopes/MinimalLambda.Envelopes.ApiGateway) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.ApiGateway.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.ApiGateway) |
Expand All @@ -35,6 +36,11 @@ Install only the envelopes you need; each one lives in its own NuGet package.
| CloudWatch Logs | [MinimalLambda.Envelopes.CloudWatchLogs](https://github.com/j-d-ha/minimal-lambda/tree/main/src/Envelopes/MinimalLambda.Envelopes.CloudWatchLogs) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.CloudWatchLogs.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.CloudWatchLogs) |
| Application Load Balancer (ALB) | [MinimalLambda.Envelopes.Alb](https://github.com/j-d-ha/minimal-lambda/tree/main/src/Envelopes/MinimalLambda.Envelopes.Alb) | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.Alb.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Alb) |

!!! note "Infrastructure Package"
`MinimalLambda.Envelopes` is automatically referenced by ALB and API Gateway packages. It provides
`IHttpResult<TSelf>` and extension methods for the response builder API. You don't need to install
it directly.

Each package ships with README examples in the repository if you need event-specific guidance.

## Quick Start
Expand Down Expand Up @@ -75,6 +81,125 @@ await lambda.RunAsync();
internal sealed record OrderMessage(string OrderId, decimal Amount);
```

## Response Builder API

For HTTP-based event sources (API Gateway, ALB), result classes provide a fluent API for building
responses. **Key benefit**: Return multiple strongly typed models from the same handlerβ€”for example,
different success and error response types.

```csharp title="API Gateway Example" linenums="1"
using MinimalLambda.Envelopes.ApiGateway;

lambda.MapHandler(([Event] ApiGatewayRequestEnvelope<LoginRequest> request) =>
{
// Each return statement uses a different strongly typed model
if (string.IsNullOrEmpty(request.BodyContent?.Username))
return ApiGatewayResult.BadRequest(new ValidationError("Username required"));

if (!authService.Authenticate(request.BodyContent))
return ApiGatewayResult.Unauthorized(new AuthError("Invalid credentials"));

return ApiGatewayResult.Ok(new LoginSuccess(token, expiresAt));
});

internal record LoginRequest(string Username, string Password);
internal record ValidationError(string Message);
internal record AuthError(string Message);
internal record LoginSuccess(string Token, DateTime ExpiresAt);
```

### Available Result Classes

| Class | Package | Use Case |
|------------------------|--------------------------------------|---------------------------------------------|
| `AlbResult` | MinimalLambda.Envelopes.Alb | Application Load Balancer responses |
| `ApiGatewayResult` | MinimalLambda.Envelopes.ApiGateway | REST API / HTTP API v1 / WebSocket |
| `ApiGatewayV2Result` | MinimalLambda.Envelopes.ApiGateway | HTTP API v2 responses |

Common methods: `Ok()`, `Created()`, `NoContent()`, `BadRequest()`, `Unauthorized()`, `NotFound()`,
`Conflict()`, `UnprocessableEntity()`, `InternalServerError()`, `StatusCode(int)`, `Text(int,
string)`, `Json<T>(int, T)`. All methods have overloads with and without body content.

### When to Use Results vs. Envelopes

**Use result classes** when you need to return multiple strongly typed models from the same handler.
Provides convenient methods for common HTTP status codes.

**Use envelope classes directly** when you need custom serialization (e.g., XML) or want to extend
envelope base classes for custom behavior.

!!! tip "Complete API Reference"
For detailed method documentation, AOT configuration, and advanced usage, see the package README
files:

- [ALB Package README](https://github.com/j-d-ha/minimal-lambda/tree/main/src/Envelopes/MinimalLambda.Envelopes.Alb)
- [API Gateway Package README](https://github.com/j-d-ha/minimal-lambda/tree/main/src/Envelopes/MinimalLambda.Envelopes.ApiGateway)

!!! note
Result classes use their respective envelope classes internally (`AlbResponseEnvelope<T>`,
`ApiGatewayResponseEnvelope<T>`, etc.). They're a convenience layer over the envelope
infrastructure.

## AOT Support

When using .NET Native AOT, register all envelope and payload types in your `JsonSerializerContext`.

!!! tip "Register Both Envelope and Payload Types"
You must register **both** the envelope type (e.g., `ApiGatewayRequestEnvelope<LoginRequest>`)
**and** the inner payload type (e.g., `LoginRequest`). The envelope wraps the AWS event
structure, while the payload is your business type inside the envelope.

### Basic Envelope Setup

```csharp title="Program.cs" linenums="1"
using System.Text.Json.Serialization;

[JsonSerializable(typeof(ApiGatewayRequestEnvelope<LoginRequest>))] // Envelope wrapper
[JsonSerializable(typeof(ApiGatewayResponseEnvelope<LoginSuccess>))] // Envelope wrapper
[JsonSerializable(typeof(LoginRequest))] // Inner payload type
[JsonSerializable(typeof(LoginSuccess))] // Inner payload type
internal partial class SerializerContext : JsonSerializerContext;
```

### Result Classes with Multiple Return Types

When using result classes (`AlbResult`, `ApiGatewayResult`, `ApiGatewayV2Result`), register each
response type separately:

```csharp title="Program.cs" linenums="1"
using System.Text.Json.Serialization;

[JsonSerializable(typeof(ApiGatewayRequestEnvelope<LoginRequest>))]
[JsonSerializable(typeof(ApiGatewayResult))]
[JsonSerializable(typeof(LoginRequest))]
[JsonSerializable(typeof(ValidationError))]
[JsonSerializable(typeof(AuthError))]
[JsonSerializable(typeof(LoginSuccess))]
internal partial class SerializerContext : JsonSerializerContext;
```

### Registering the Serializer Context

Register the serializer and configure envelope options to use the context:

```csharp title="Program.cs" linenums="1"
var builder = LambdaApplication.CreateBuilder();

builder.Services.AddLambdaSerializerWithContext<SerializerContext>();

builder.Services.ConfigureEnvelopeOptions(options =>
{
options.JsonOptions.TypeInfoResolver = SerializerContext.Default;
});
```

!!! important "Why Register in Two Places?"
The context must be registered as the type resolver for **both** the envelope options and the
Lambda serializer because deserialization happens at different steps:

1. **Lambda serializer** deserializes the raw AWS event (e.g., API Gateway event structure)
2. **Envelope options** deserialize the envelope content into your payload types

## Custom Serialization & EnvelopeOptions

All envelope packages respect the global `EnvelopeOptions` configuration. Call
Expand Down
1 change: 1 addition & 0 deletions docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ Envelope packages provide type-safe, strongly-typed event handling for specific

| Package | Event Source | When to Use |
|----------------------------------------------|---------------------------|-------------------------------|
| **MinimalLambda.Envelopes** | Infrastructure | HTTP response builders (auto-referenced) |
| **MinimalLambda.Envelopes.Sqs** | Amazon SQS | Processing SQS queue messages |
| **MinimalLambda.Envelopes.Sns** | Amazon SNS | Handling SNS notifications |
| **MinimalLambda.Envelopes.ApiGateway** | API Gateway | Building REST/HTTP APIs |
Expand Down
8 changes: 2 additions & 6 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,7 @@ already know, while still embracing Lambda’s execution model.
var greeting = await service.GreetAsync(request.BodyContent.Name, cancellationToken);

// βœ… Type-safe response - automatic JSON serialization
return new ApiGatewayResponseEnvelope<GreetingResponse>
{
BodyContent = new GreetingResponse(greeting, DateTime.UtcNow),
StatusCode = 200,
Headers = new Dictionary<string, string> { ["Content-Type"] = "application/json" },
};
return ApiGatewayResult.Ok(new GreetingResponse(greeting, DateTime.UtcNow));
}
);

Expand Down Expand Up @@ -211,6 +206,7 @@ deserialization.

| Package | Description | NuGet | Downloads |
|----------------------------------------------------------------------------------------|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **MinimalLambda.Envelopes** | Infrastructure package for HTTP response builders | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes) | [![Downloads](https://img.shields.io/nuget/dt/MinimalLambda.Envelopes.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes/) |
| **MinimalLambda.Envelopes.Sqs** | Simple Queue Service events with typed message bodies | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.Sqs.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sqs) | [![Downloads](https://img.shields.io/nuget/dt/MinimalLambda.Envelopes.Sqs.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sqs/) |
| **MinimalLambda.Envelopes.Sns** | Simple Notification Service messages | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.Sns.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sns) | [![Downloads](https://img.shields.io/nuget/dt/MinimalLambda.Envelopes.Sns.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.Sns/) |
| **MinimalLambda.Envelopes.ApiGateway** | REST, HTTP, and WebSocket APIs | [![NuGet](https://img.shields.io/nuget/v/MinimalLambda.Envelopes.ApiGateway.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.ApiGateway) | [![Downloads](https://img.shields.io/nuget/dt/MinimalLambda.Envelopes.ApiGateway.svg)](https://www.nuget.org/packages/MinimalLambda.Envelopes.ApiGateway/) |
Expand Down
Loading
Loading