feat: add AWS Lambda deployment adapter - #197
Conversation
Add @marko/run-adapter-aws-lambda for deploying Marko Run apps to AWS Lambda behind a Function URL or API Gateway HTTP API. - Builds a self-contained handler (dist/index.mjs, exported as `handler`) for the payload format version 2.0; converts the event to a web Request and the Response back to a base64-encoded Lambda result (with cookies) - Serves the bundled static assets from dist/public when no route matches (immutable caching for /assets, path traversal guard) - `marko-run preview` runs the handler behind a local HTTP server, so it can be tested without deploying - Exposes the raw event and invocation context via AWSLambdaPlatformInfo - Adds a run-package fixture covering both dev and preview
🦋 Changeset detectedLatest commit: ac80bd8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 55 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis PR adds a new ChangesRelated issues: None specified Sequence Diagram(s)sequenceDiagram
participant APIGateway
participant handler
participant Router
participant serveStatic
APIGateway->>handler: APIGatewayProxyEventV2
handler->>handler: eventToRequest(event)
handler->>Router: fetch(request)
Router-->>handler: Response
handler->>serveStatic: pathname (if 404)
serveStatic-->>handler: file or null
handler->>handler: responseToResult(response)
handler-->>APIGateway: APIGatewayProxyResultV2
sequenceDiagram
participant Client
participant PreviewServer
participant nodeRequestToEvent
participant handler
Client->>PreviewServer: HTTP request
PreviewServer->>PreviewServer: readBody(req)
PreviewServer->>nodeRequestToEvent: req, body
nodeRequestToEvent-->>PreviewServer: APIGatewayProxyEventV2
PreviewServer->>handler: handler(event, context)
handler-->>PreviewServer: APIGatewayProxyResultV2
PreviewServer-->>Client: HTTP response
Estimated code review effort: 4/5 (~200 minutes) Poem: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (2)
packages/adapters/aws-lambda/scripts/build.ts (1)
7-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider aligning esbuild
targetwith the supported Lambda runtime.
target: ["node14"]is older than thenodejs20.xruntime recommended in the README. Not a functional bug, but syntax lowering for node14 is unnecessary overhead for a package that will run on node18+.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/adapters/aws-lambda/scripts/build.ts` around lines 7 - 13, The esbuild configuration in build() is still targeting node14, which is older than the Lambda runtime this package supports. Update the BuildOptions target in the aws-lambda build script to match the supported nodejs20.x/node18+ runtime referenced by the adapter, so the bundle is not unnecessarily lowered for older Node syntax.packages/run/src/__tests__/fixtures/aws-lambda-adapter/package.json (1)
1-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing
private: trueand declared dependencies.The fixture imports
@marko/run/viteand@marko/run-adapter-aws-lambdainvite.config.ts, but neither is declared as a dependency here, and there's no"private": true. If this package is resolved solely via workspace hoisting it may still work in the monorepo, but omitting explicit dependencies risks the fixture accidentally being picked up by publish/release tooling and makes the dependency on the adapter implicit rather than declared.♻️ Proposed fix
{ "name": "aws-lambda-adapter", "version": "1.0.0", + "private": true, + "dependencies": { + "`@marko/run`": "workspace:*", + "`@marko/run-adapter-aws-lambda`": "workspace:*", + "marko": "*", + "vite": "*" + }, "scripts": {} }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/run/src/__tests__/fixtures/aws-lambda-adapter/package.json` around lines 1 - 5, The aws-lambda-adapter fixture package.json is missing explicit dependency declarations and should be marked private to keep it out of publish/release workflows. Update the fixture’s package metadata to add private true and declare the imports used by vite.config.ts, specifically `@marko/run/vite` and `@marko/run-adapter-aws-lambda`, so the fixture’s requirements are explicit and self-contained.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/adapters/aws-lambda/package.json`:
- Around line 16-22: The package metadata is pointing consumers at source files
that are not included in the published tarball. Update the aws-lambda package’s
exports and types entries so they reference the built entrypoint produced in
dist rather than src/index.ts, keeping the published entrypoint aligned with
what files actually ships. Use the package.json exports and types fields to
locate the change and ensure adapter imports and type resolution work after
publish.
In `@packages/adapters/aws-lambda/README.md`:
- Around line 55-66: The AWS Lambda README example is using the wrong
route-handler parameter shape: `platform` is being destructured from the second
argument, which is actually `next`, not the request context. Update the example
in the `GET` handler to read Lambda data from `context.platform` instead,
keeping the `AWSLambdaPlatformInfo` cast and `lambdaContext` usage aligned with
the `GET(context, next)` signature.
In `@packages/adapters/aws-lambda/scripts/build.ts`:
- Around line 7-28: The package entrypoint configuration still points at src
instead of the published dist output, so update the build/package setup around
the BuildOptions entryPoints and the package export/type references to resolve
from dist. Make sure the aws-lambda package’s exports["."] and types point to
the built artifact produced by the build script, not src/index.ts, so the packed
package has a usable entrypoint.
In `@packages/adapters/aws-lambda/scripts/importMetaURL.js`:
- Around line 1-2: `__importMetaURL` is currently exported as a URL object from
the importMetaURL shim, but it must match `import.meta.url` and be a string in
the CJS build. Update the `__importMetaURL` export in `importMetaURL.js` to
return the string form from `pathToFileURL(__filename)` (use the standard
esbuild shim pattern), so downstream uses like `path.dirname(import.meta.url)`
in `index.ts` keep working.
In `@packages/adapters/aws-lambda/src/default-entry.ts`:
- Around line 143-145: The static fallback path in default-entry.ts can throw
when decodeURIComponent is called on a malformed pathname, so guard that
conversion before calling serveStatic. Update the request handling around the
URL pathname extraction and static fallback to catch invalid percent-encoding
and return the normal non-static response path instead of failing the
invocation; use the request.url, pathname, and serveStatic flow to locate the
fix.
In `@packages/adapters/aws-lambda/src/index.ts`:
- Around line 155-157: The cookie parsing in the Lambda adapter is too strict
because the logic in the request handling path only splits on "; " and misses
valid cookie separators without a trailing space. Update the cookie extraction
in the `index.ts` request flow so `req.headers.cookie` is parsed in a
whitespace-tolerant way, and ensure the resulting `cookies` value matches what
`platform.event.cookies` exposes for the same header format. Use the existing
cookie handling block around `req.headers.cookie.split(...)` as the place to
adjust this behavior.
- Around line 149-153: Update eventToRequest() in the AWS Lambda adapter so
preview events explicitly forward the request scheme instead of relying on the
default https fallback. Set x-forwarded-proto (or the equivalent forwarded
scheme header) for preview requests to http when building the headers map, while
preserving existing behavior for non-preview events, so absolute redirects and
scheme-sensitive logic use the correct protocol.
---
Nitpick comments:
In `@packages/adapters/aws-lambda/scripts/build.ts`:
- Around line 7-13: The esbuild configuration in build() is still targeting
node14, which is older than the Lambda runtime this package supports. Update the
BuildOptions target in the aws-lambda build script to match the supported
nodejs20.x/node18+ runtime referenced by the adapter, so the bundle is not
unnecessarily lowered for older Node syntax.
In `@packages/run/src/__tests__/fixtures/aws-lambda-adapter/package.json`:
- Around line 1-5: The aws-lambda-adapter fixture package.json is missing
explicit dependency declarations and should be marked private to keep it out of
publish/release workflows. Update the fixture’s package metadata to add private
true and declare the imports used by vite.config.ts, specifically
`@marko/run/vite` and `@marko/run-adapter-aws-lambda`, so the fixture’s requirements
are explicit and self-contained.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 65f817a3-8bb1-4eaa-be26-9c0f1c0ba08e
⛔ Files ignored due to path filters (3)
package-lock.jsonis excluded by!**/package-lock.jsonand included by**packages/run/src/__tests__/fixtures/aws-lambda-adapter/__snapshots__/dev.expected.mdis excluded by!**/__snapshots__/**and included by**packages/run/src/__tests__/fixtures/aws-lambda-adapter/__snapshots__/preview.expected.mdis excluded by!**/__snapshots__/**and included by**
📒 Files selected for processing (18)
.changeset/aws-lambda-adapter.mdcspell.jsonpackages/adapters/aws-lambda/README.mdpackages/adapters/aws-lambda/package.jsonpackages/adapters/aws-lambda/scripts/build.tspackages/adapters/aws-lambda/scripts/importMetaURL.jspackages/adapters/aws-lambda/src/default-entry.tspackages/adapters/aws-lambda/src/index.tspackages/adapters/aws-lambda/src/types.tspackages/adapters/aws-lambda/tsconfig.jsonpackages/run/src/__tests__/fixtures/aws-lambda-adapter/.gitignorepackages/run/src/__tests__/fixtures/aws-lambda-adapter/.marko-run/routes.d.tspackages/run/src/__tests__/fixtures/aws-lambda-adapter/package.jsonpackages/run/src/__tests__/fixtures/aws-lambda-adapter/src/components/counter.markopackages/run/src/__tests__/fixtures/aws-lambda-adapter/src/routes/+page.markopackages/run/src/__tests__/fixtures/aws-lambda-adapter/test.config.tspackages/run/src/__tests__/fixtures/aws-lambda-adapter/tsconfig.jsonpackages/run/src/__tests__/fixtures/aws-lambda-adapter/vite.config.ts
- Add package.toggle.json so publish points exports/types at dist/ - Make the injected import.meta.url shim a string (.href) for the CJS build - Fix the README platform example to read from context.platform - Guard decodeURIComponent so a malformed path returns 400 instead of failing the invocation - Force http scheme for preview events (the preview server is plain HTTP) so scheme-sensitive logic and absolute redirects are correct - Parse the preview Cookie header tolerant of `;` without a trailing space
Clarify that Marko Run automatically uses an installed adapter with no Vite config, and place the build + package + `aws lambda` deploy steps in a Deploying section right after installation.
Description
Adds a new adapter package,
@marko/run-adapter-aws-lambda, for deploying Marko Run apps to AWS Lambda behind a Function URL or an API Gateway HTTP API.dist/index.mjs, exported ashandler) for the payload format version 2.0. It converts the Lambda event into a webRequest, runs the app, and converts theResponseback into a base64-encoded Lambda result (includingset-cookiehandling).dist/publicwhen no route matches — withimmutablecaching for/assets/*, a content-type lookup, and a path-traversal guard.marko-run previewruns the handler behind a local HTTP server, so the Lambda build can be tested without deploying or running SAM.AWSLambdaPlatformInfotype.Package the
distdirectory and deploy it withindex.handleras the handler on a Node.js runtime (SAM, CDK, Serverless Framework, Terraform, or the AWS CLI all work).Also adds a test fixture to the
@marko/runpackage (aws-lambda-adapter) covering both dev and preview.Motivation and Context
AWS Lambda is one of the most common serverless deployment targets, but Marko Run had no adapter for it. This produces a self-contained handler compatible with both Function URLs and API Gateway HTTP APIs, serves static assets from the bundle, and can be previewed locally — alongside the existing Node, static, and Netlify adapters.
Notes for reviewers
The runtime's
fetchreturns a404Response(notundefined) for unmatched paths, so the handler checks the router first and only falls back to static-asset serving on a404— otherwise asset requests (e.g./assets/*.js) would never be served. The preview test exercises this end-to-end (hydration works because the client bundle is served).Screenshots (if appropriate):
Checklist:
Generated by Claude Code