feat(event-handler): add type-safe Store API for request and shared state #5081
Merged
feat(event-handler): add type-safe Store API for request and shared state #5081
Conversation
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.
svozza
commented
Mar 10, 2026
svozza
commented
Mar 10, 2026
…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.
Closed
2 tasks
… 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.
sdangol
requested changes
Mar 17, 2026
Contributor
sdangol
left a comment
There was a problem hiding this comment.
Added a few comments but overall functionality looks good
Closed
1 task
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`.
|
sdangol
approved these changes
Mar 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

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:
Changes
Storeclass backed by aMapwith generic key/value typing via anEnvtype parameterRoutergeneric overTEnv extends Envso thatreqCtx.get(),reqCtx.set(), andreqCtx.shared.get()are fully typedincludeRouteroverload that returnsRouter<MergeEnv<[TEnv, TOther]>>, enabling a fluent chaining style that accumulates store types across sub-routersMergeEnvutility type for users who prefer declaring the full environment upfrontstoresubpath export (@aws-lambda-powertools/event-handler/store)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.