Skip to content

feat(event-handler): add type-safe Store API for request and shared state #5081

Merged
svozza merged 22 commits intomainfrom
feat/store-api
Mar 18, 2026
Merged

feat(event-handler): add type-safe Store API for request and shared state #5081
svozza merged 22 commits intomainfrom
feat/store-api

Conversation

@svozza
Copy link
Copy Markdown
Contributor

@svozza svozza commented Mar 10, 2026

Summary

Add a Store API to the HTTP event handler that provides type-safe, scoped state management for route handlers. This gives users two storage scopes:

  • Request store — per-invocation state (set in middleware, read in handlers). Cleared automatically between requests.
  • Shared store — router-scoped state (set at cold start, read everywhere). Persists across invocations.

Changes

  • Add Store class backed by a Map with generic key/value typing via an Env type parameter
  • Make Router generic over TEnv extends Env so that reqCtx.get(), reqCtx.set(), and reqCtx.shared.get() are fully typed
  • Add includeRouter overload that returns Router<MergeEnv<[TEnv, TOther]>>, enabling a fluent chaining style that accumulates store types across sub-routers
  • Export MergeEnv utility type for users who prefer declaring the full environment upfront
  • Add store subpath export (@aws-lambda-powertools/event-handler/store)
  • Unit tests, type-level tests, and e2e tests for both store scopes
  • Documentation with examples for untyped usage, typed usage, and split-router patterns

Issue number: closes #5072


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

svozza added 15 commits March 10, 2026 14:45
Add a generic Store<T> class backed by a Map with set, get, has, and
delete methods. This is the foundation for the Store API that will
enable type-safe state sharing across the request lifecycle.

Refs: #5072
Add Env type and helper types (RequestStoreOf, SharedStoreOf) for
extracting store types. Thread TEnv generic parameter through
RequestContext, TypedRequestContext, Middleware, RouteHandler,
TypedRouteHandler, MiddlewareOrHandler, and HandlerOrOptions.

All generics default to Env so existing code is unaffected.

Refs: #5072
Replace all hardcoded Env references with TEnv type parameter across
Router class, middleware, route handlers, and HTTP method overloads.
Add IStore interface to avoid invariance issues from private class
fields. Add request-scoped store methods (set/get/has/delete) and
shared store to RequestContext. Wire up store creation in Router#resolve.
Add runtime tests for request-scoped store (set/get/has/delete,
isolation between requests, middleware-handler sharing, post-next
access) and shared store (persistence across requests, cross-route
sharing, middleware access). Add type tests for RequestContext store
properties and IStore typing.
Add ./store package entry point exporting Store class and IStore
interface. Export Env type from ./types for users to define typed
router environments.
includeRouter now returns Router<MergeEnv<[TEnv, TOther]>> so chaining
accumulates store types automatically without upfront declaration.

Also threads RouteHandler<TEnv> through all HTTP method overloads so
handler callbacks receive the router's actual store types, and widens
internal middleware storage to Middleware[] to avoid casts when merging
sub-router middleware.
…ctAll

Extract duplicated request store closure methods (set/get/has/delete)
into a single #createStoreAccessors private method, removing the
copy-paste between the error path and normal path in #resolve.

Change IntersectAll base case from Record<string, unknown> to unknown
(the intersection identity type) to eliminate noisy trailing
& Record<string, unknown> in resolved types.
Add documentation for the request and shared store, typed stores with
Env generics, and typed stores with split routers (chained includeRouter
and upfront MergeEnv patterns). Export MergeEnv from the public types
entry point and add a type test for the upfront pattern.
…types script

Use typed Router<AppEnv> in store tests so store get/set calls are
type-safe. Use ?? fallbacks instead of non-null assertions. Wire up
the test:unit:types npm script to run vitest --typecheck on tests/types.
Add storeRouter with request-scoped and shared store routes. Update
FunctionCode to use chained includeRouter syntax with StoreEnv typing.
Add e2e tests verifying request store isolation and shared store
persistence. Fix nestedRouter type error by using req.url instead of
event.path.
Co-locate Store module with its entry point so src/store/index.ts
re-exports from a sibling rather than reaching up to the parent.
Comment thread packages/event-handler/src/http/Router.ts
Comment thread packages/event-handler/tests/e2e/routers/nestedRouter.ts
svozza added 2 commits March 10, 2026 22:22
…ate type tests

Remove ?? '' fallbacks in test handlers where values are expected to
exist so assertions catch undefined instead of silently passing.

Move Store type tests from unit/Store.test.ts to types/store.test-d.ts
so they run under test:unit:types.
…outer

The chained includeRouter calls infer the merged type automatically.
… MergeEnv

When an untyped Router was merged with a typed one via includeRouter,
the fallback Record<string, unknown> from the untyped side would poison
the intersection, making the store accept any string key. Introduce
ForMerge extractors that fall back to {} (intersection identity) and
DefaultIfEmpty to widen back to Record<string, unknown> only when all
envs are untyped. Also constrain MergeEnv to require at least 2 envs.
Copy link
Copy Markdown
Contributor

@sdangol sdangol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few comments but overall functionality looks good

Comment thread docs/features/event-handler/http.md Outdated
Comment thread packages/event-handler/src/http/Router.ts
Comment thread packages/event-handler/tests/types/http.test-d.ts
Comment thread packages/event-handler/tests/types/http.test-d.ts
Comment thread packages/event-handler/tests/types/http.test-d.ts
Comment thread packages/event-handler/tests/types/store.test-d.ts
Comment thread packages/event-handler/tests/unit/Store.test.ts
svozza and others added 3 commits March 18, 2026 10:52
Co-authored-by: Swopnil Dangol <swopnildangol@gmail.com>
…erty

Add Prepare/Act/Assess comments to type test files and add type
assertions for Router's implicit Env type parameter. Deprecate
the `context` property in favor of `requestContext.shared`.
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Mar 18, 2026

Quality Gate Passed Quality Gate passed

Issues
0 New issues
4 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
2.0% Duplication on New Code

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XXL PRs with 1K+ LOC, largely documentation related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: Type-safe Store API for sharing state across the request lifecycle

2 participants