Skip to content

feat(envelopes): expand envelope options for multiple serialization formats#184

Merged
j-d-ha merged 16 commits into
mainfrom
feature/#175-expand-envelope-options-for-multiple-serialization-formats
Nov 27, 2025
Merged

feat(envelopes): expand envelope options for multiple serialization formats#184
j-d-ha merged 16 commits into
mainfrom
feature/#175-expand-envelope-options-for-multiple-serialization-formats

Conversation

@j-d-ha

@j-d-ha j-d-ha commented Nov 27, 2025

Copy link
Copy Markdown
Collaborator

🚀 Pull Request

📋 Summary

This PR expands the EnvelopeOptions class to support multiple serialization formats beyond JSON, enabling custom envelope implementations to use XML and other formats. It also refactors the envelope base classes to use an abstract pattern for better extensibility.

Key Changes:

  • Enhanced EnvelopeOptions: Added XmlReaderSettings, XmlWriterSettings, and an Items dictionary for custom extension data
  • Abstract Base Classes: Refactored API Gateway and SQS envelopes to use abstract base classes (ApiGatewayRequestEnvelopeBase, ApiGatewayResponseEnvelopeBase, SqsEnvelopeBase)
  • Stream Feature Abstraction: Introduced IInvocationDataFeature to encapsulate event and response streams, replacing direct RawInvocationData access
  • Context Accessor: Added ILambdaHostContextAccessor for DI-based context access throughout the application
  • Documentation: Added comprehensive README for envelopes package and updated documentation with XML serialization examples
  • GitHub Templates: Added issue and discussion templates for better community engagement

✅ Checklist

  • My changes build cleanly
  • I've added/updated relevant tests
  • I've added/updated documentation or README
  • I've followed the coding style for this project
  • I've tested the changes locally (if applicable)

🧪 Related Issues or PRs

Closes #175


💬 Notes for Reviewers

Breaking Changes:

  • RawInvocationData has been removed from ILambdaHostContext - replaced with IInvocationDataFeature accessible via the features collection
  • Envelope base classes are now abstract, requiring implementations to override ExtractPayload/PackPayload methods

Architecture Improvements:

The new IInvocationDataFeature provides a cleaner abstraction layer for stream handling and aligns with the feature-based architecture pattern used throughout the host.

Examples:

The documentation includes working examples of custom XML envelopes for both API Gateway and SQS, demonstrating how to leverage the new XmlReaderSettings and XmlWriterSettings.

j-d-ha and others added 15 commits November 25, 2025 12:40
- Introduced `ApiGatewayRequestEnvelopeBase` as an abstract base class for strongly typed deserialization.
- Updated `ApiGatewayRequestEnvelope` to inherit from the new base class.
- Simplified `ApiGatewayRequestEnvelope` by moving shared logic to the base class.
- Added `XmlReaderSettings` to support customized XML deserialization for Lambda event payloads.
- Added `XmlWriterSettings` to support customized XML serialization for Lambda event payloads.
- Introduced `Items` dictionary to allow storing custom extension data for envelope processing.
- Introduced `DecodeFromBase64` to toggle base64 decoding for payloads.
- Introduced `EncodeToBase64` to toggle base64 encoding for payloads.
- Both properties default to `null`, preserving existing behavior unless explicitly configured.
- Added config.yml to disable blank issues and provide helpful contact links.
- Created discussion templates (general, idea, and Q&A) for better community engagement.
- Added issue templates for feature requests and bug reports to standardize issue reporting.
…ation (#178)

* feat(core): add ILambdaHostContextAccessor interface

- Introduces an interface for accessing the ILambdaHostContext during Lambda invocations.
- Facilitates dependency injection by eliminating the need to pass context through method parameters.

* feat(core): implement LambdaHostContextAccessor

- Adds LambdaHostContextAccessor for managing ILambdaHostContext access.
- Utilizes AsyncLocal to store and retrieve context during Lambda executions.

* feat(core): add LambdaHostContextFactory and related interface

- Introduces ILambdaHostContextFactory for creating Lambda host contexts.
- Implements LambdaHostContextFactory to manage ILambdaHostContext instantiation.
- Ensures proper dependency injection of required services like IServiceScopeFactory.

* refactor(core): replace FeatureCollectionFactory with LambdaHostContextFactory

- Removed IFeatureCollectionFactory dependency from LambdaHandlerComposer.
- Introduced ILambdaHostContextFactory to streamline Lambda context creation.
- Updated lambda invocation flow to use LambdaHostContextFactory for context management.
- Ensured proper IDisposable handling for LambdaHostContext instances.

* feat(core): add LambdaHostContextAccessor and extend DI support

- Introduced AddLambdaHostContextAccessor method to register ILambdaHostContextAccessor.
- Registered ILambdaHostContextFactory in the service collection for enhanced DI.

* feat(core): add AddLambdaHostContextAccessor extension method

- Registers ILambdaHostContextAccessor as a singleton in the DI container.
- Enables application-wide access to ILambdaHostContext via dependency injection.

* test(builder): add unit tests for AddLambdaHostContextAccessor method

- Validates null IServiceCollection throws ArgumentNullException.
- Confirms IServiceCollection chaining works as expected.
- Ensures ILambdaHostContextAccessor is registered as a singleton.
- Verifies implementation type is LambdaHostContextAccessor.

* refactor(core): make ILambdaHostContextAccessor optional in LambdaHostContextFactory

- Updated constructor to set ILambdaHostContextAccessor as an optional parameter.
- Improves flexibility by allowing null values for ILambdaHostContextAccessor.

* test(core): add unit tests for LambdaHostContextFactory

- Validates null IServiceScopeFactory throws ArgumentNullException.
- Validates null IFeatureCollectionFactory throws ArgumentNullException.
- Confirms successful construction with valid dependencies.
- Verifies Create calls FeatureCollectionFactory.Create.
- Ensures context accessor gets updated when provided.

* chore(core): update license references for third-party code

- Added license notice and source reference to LambdaHostContextAccessor.
- Updated license URL in LambdaApplicationBuilder for consistency with aspnetcore.

* test(core): add unit tests for LambdaHostContextAccessor

- Validates LambdaHostContext returns null when not set.
- Confirms LambdaHostContext retains and returns assigned values.
- Verifies LambdaHostContext updates to new values and reflects changes.
- Ensures LambdaHostContext becomes null when explicitly set to null.
- Confirms multiple instances share AsyncLocal state and reflect latest value.

* test(core): update unit tests to use LambdaHostContextFactory

- Replaced IFeatureCollectionFactory with ILambdaHostContextFactory in unit tests.
- Removed tests specific to IFeatureCollectionFactory as it was deprecated.
- Added mocks and test cases for LambdaHostContextFactory.
- Ensured proper disposal testing with IAsyncDisposable for LambdaHostContext.
- Updated constructor parameter validation tests to reflect new dependencies.

* chore(build): bump VersionPrefix to 1.0.1-beta.4

- Updated Directory.Build.props to reflect the new pre-release version.
* feat(lambda): add interfaces for invocation data feature

- Introduced `IInvocationDataFeatureFactory` to create features from event streams.
- Added `IInvocationDataFeature` to encapsulate raw Lambda event and response data streams.

* feat(lambda): implement invocation data feature factory

- Added `InvocationDataFeatureFactory` to create `InvocationDataFeature` instances using event streams.
- Introduced `InvocationDataFeature` to manage event and response data streams, with proper disposal logic.

* refactor(lambda): remove RawInvocationData and related references

- Deleted `RawInvocationData` class and its documentation.
- Removed `RawInvocationData` usage from `ILambdaHostContext` and `ILambdaHostContextFactory`.
- Simplified APIs and cleaned up legacy code by eliminating raw data stream handling directly.

* refactor(lambda): update usage to InvocationDataFeature for event and response streams

- Replaced `RawInvocationData.Event` with `InvocationDataFeature.EventStream`.
- Replaced `RawInvocationData.Response` with `InvocationDataFeature.ResponseStream`.

* refactor(lambda): integrate InvocationDataFeature across lambda handling

- Replaced `RawInvocationData` with `InvocationDataFeature` in handler composition and context creation.
- Updated feature access to use `IInvocationDataFeature` for event and response stream management.
- Removed all references, properties, and methods related to `RawInvocationData`.
- Ensured proper dependency injection of `IInvocationDataFeatureFactory` where necessary.

* test(lambda): update DefaultEventFeatureTests to use InvocationDataFeature

- Replaced `RawInvocationData.Event` with `InvocationDataFeature.EventStream` in unit tests.
- Updated test arrangement to set up `IInvocationDataFeature` and its event stream mock.

* test(lambda): remove RawInvocationData references in unit tests

- Eliminated all references to `RawInvocationData` in `DefaultLambdaHostContextTests`.
- Updated unit test parameters to exclude `RawInvocationData`.
- Adjusted affected test setups and assertions to align with the new API structure.

* test(lambda): remove RawInvocationData from LambdaHostContextFactoryTests

- Removed `RawInvocationData` from unit test parameters in `LambdaHostContextFactoryTests`.
- Updated test calls to align with the revised `Create` method signature.
- Adjusted test arrangements and assertions to match the updated API structure.

* feat(lambda): register InvocationDataFeatureFactory in DI

- Added `IInvocationDataFeatureFactory` and its implementation to the service collection.
- Ensured proper dependency injection for `InvocationDataFeatureFactory`.

* test(lambda): add unit tests for InvocationDataFeatureFactory

- Added tests to ensure `Create` method returns `IInvocationDataFeature` instances.
- Verified `EventStream` is set to the provided stream during feature creation.
- Asserted `ResponseStream` is initialized as a `MemoryStream` for each feature.
- Ensured `Create` returns new feature instances with each call.
- Checked that created features implement `IDisposable`.

* test(lambda): update DefaultResponseFeatureTests with frozen response stream

- Replaced hardcoded `response` strings with `testData` parameter in test arrangements.
- Introduced `[Frozen] Stream responseStream` to improve test reliability and mock setup.
- Updated assertions to validate `serializer` writes data to the frozen `responseStream`.
- Removed redundant variable declarations for response streams in test cases.

* test(lambda): add unit tests for InvocationDataFeatureFactory in LambdaHandlerComposerTests

- Added tests to validate proper usage of `InvocationDataFeatureFactory` in `LambdaHandlerComposer`.
- Verified factory is invoked to create `IInvocationDataFeature` instances with response stream.
- Ensured factory is included in constructor null-parameter checks and test setups.
- Updated mock setup to generate `IInvocationDataFeature` with `MemoryStream` response.

* test(lambda): parameterize AddLambdaHostCoreServices test with service count

- Converted `AddLambdaHostCoreServices_RegistersExactlyEightServices` to use `[Theory]` and `InlineData`.
- Parameterized test to accept `servicesCount` instead of hardcoding service registrations.
- Updated assertion to validate dynamic `servicesCount` rather than fixed value.

* test(lambda): update snapshots to use InvocationDataFeature streams

- Replaced `RawInvocationData.Response` with `InvocationDataFeature.ResponseStream` in snapshot tests.
- Replaced `RawInvocationData.Event` with `InvocationDataFeature.EventStream` in snapshot tests.
- Ensured alignment with the updated API using `IInvocationDataFeature` for streams.

* refactor(lambda): seal context and feature classes

- Marked `DefaultLambdaHostContext` and `InvocationDataFeature` as `sealed` for performance improvements.
- Ensured classes are no longer inheritable to communicate final design decisions.
…ns (#183)

* fix(ci): add explicit token to checkout and create-pull-request actions

* chore(release): update changelog for v1.1.0

- Add entries for features, bug fixes, documentation, and maintenance for v1.1.0.
- Update version comparison links to v1.1.0.
- Include `.gitignore` update to ignore `temp.md`.
…velopeOptions

- Removed `DecodeFromBase64` and `EncodeToBase64` as they are no longer needed.
- Simplified the `EnvelopeOptions` class to streamline property management.
- Updated `ApiGatewayRequestEnvelope<T>` to be `sealed` to prevent further inheritance.
- Added remarks to `ExtractPayload` method clarifying JSON deserialization behavior.
…nvelopes

Refactor ApiGatewayV2RequestEnvelope, ApiGatewayResponseEnvelope,
ApiGatewayV2ResponseEnvelope, and SqsEnvelope to follow the same
abstract base class pattern as ApiGatewayRequestEnvelope.

This provides:
- Consistency across all envelope implementations
- Sealed concrete classes for better encapsulation
- Foundation for supporting multiple serialization formats
- Centralized payload handling logic in base classes
- Reformatted `ApiGatewayV2RequestEnvelopeBase` and `ApiGatewayV2ResponseEnvelopeBase` for improved readability.
- Applied consistent line-breaking style for multi-line `base class` and `interface` declarations.
- Clarified existing remarks without modifying logic or functionality.
- Documented the process for implementing custom deserialization and serialization logic.
- Provided code examples for XML-based request and response envelopes.
- Clarified how to support multiple formats while preserving the envelope interface.
- Documented how to extend `SqsEnvelopeBase<T>` for custom deserialization logic.
- Added an XML deserialization example using `SqsXmlEnvelope<T>`.
- Explained support for multiple serialization formats with a consistent envelope interface.
…ation

- Added `src/Envelopes/README.md` to provide an overview of envelopes, their benefits, and usage.
- Updated package-specific READMEs to include links to related packages for better navigation.
- Registered `src/Envelopes/README.md` in the solution file for improved project visibility.
@github-actions github-actions Bot added breaking-change Introduces a breaking change type: feat New feature labels Nov 27, 2025
@j-d-ha j-d-ha removed the breaking-change Introduces a breaking change label Nov 27, 2025
@sonarqubecloud

Copy link
Copy Markdown

@j-d-ha
j-d-ha merged commit 309d11f into main Nov 27, 2025
6 checks passed
@j-d-ha
j-d-ha deleted the feature/#175-expand-envelope-options-for-multiple-serialization-formats branch November 27, 2025 01:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: feat New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(host): expand envelope options for multiple serialization formats

1 participant