Skip to content

feat(vercel): support queues in local dev#4264

Open
RihanArfan wants to merge 1 commit into
mainfrom
feat/vercel-queues-local-dev
Open

feat(vercel): support queues in local dev#4264
RihanArfan wants to merge 1 commit into
mainfrom
feat/vercel-queues-local-dev

Conversation

@RihanArfan
Copy link
Copy Markdown
Member

@RihanArfan RihanArfan commented May 13, 2026

🔗 Linked issue

#4127

Blocked by unjs/env-runner#16

❓ Type of change

  • 📖 Documentation (updates to the documentation, readme, or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Support Vercel Queues during local development. Calling send() from @vercel/queue will call the consumers registered within nitro.config.ts.

Also introduces usage of Vercel env-runner preset during dev when Vercel preset is set.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@RihanArfan RihanArfan requested a review from pi0 as a code owner May 13, 2026 19:22
@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nitro.build Ready Ready Preview, Comment May 13, 2026 7:22pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds local development support for Vercel Queues in Nitro by introducing a new vercelDev preset, dev module that validates configuration and injects a queue consumer plugin, runtime plugin that dispatches queue messages to the vercel:queue hook, and user documentation explaining the feature and setup requirements.

Changes

Vercel Queues Local Development

Layer / File(s) Summary
Preset type definitions and vercelDev preset
src/presets/_types.gen.ts, src/presets/vercel/preset.ts
Type unions PresetName and PresetNameInput updated to include vercel-dev preset in kebab, camel, and snake case; vercelDev preset defined extending nitro-dev with devServer.runner: "vercel", vercelDevModule wiring, dev: true, and added to module default export.
Dev module setup and validation
src/presets/vercel/dev.ts
vercelDevModule validates that dev mode is active and runner is configured as vercel, propagates queue trigger configuration to runtime config, and injects the queue consumer plugin at the front of the plugins array.
Queue consumer plugin implementation
src/presets/vercel/runtime/queue.dev.ts
queueDevPlugin registers Vercel Queue consumers for each configured trigger, dispatches received messages to the vercel:queue hook with metadata, logs and rethrows handler errors to enable queue retries, and unregisters consumers on Nitro shutdown.
Local development documentation
docs/2.deploy/20.providers/vercel.md
New "Local development" section documents that queue messages work in nitro dev, describes delivery to the vercel:queue hook, instructs on Vercel environment setup using vercel link and vercel env pull, and explains retry behavior.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • nitrojs/nitro#4127: Extends the existing Vercel Queues integration by adding a new local-dev preset/module and queue consumer plugin that forwards messages to the same vercel:queue Nitro hook.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(vercel): support queues in local dev' follows conventional commits format with appropriate type and scope.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose of adding Vercel Queues support during local development.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/vercel-queues-local-dev

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/presets/vercel/runtime/queue.dev.ts (1)

50-53: ⚡ Quick win

Avoid silent teardown failures in close hook

The empty catch hides unregister failures, making local queue teardown issues hard to diagnose. Log/capture the error instead of swallowing it.

Suggested diff
   nitroApp.hooks.hook("close", () => {
     for (const unregister of unregisters) {
       try {
         unregister();
-      } catch {}
+      } catch (error) {
+        nitroApp.captureError?.(error as Error, {
+          tags: ["vercel:queue", "close"],
+        });
+      }
     }
   });
🤖 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 `@src/presets/vercel/runtime/queue.dev.ts` around lines 50 - 53, The close hook
currently swallows errors from unregister() with an empty catch; update the
catch to capture the exception and log it (e.g., catch (err) {
console.error('Failed to unregister local queue in close hook:', err) } or use
an existing logger like processLogger.error) so failures in unregister() are
visible; keep the call to unregister() and ensure the log includes context and
the error object for debugging.
🤖 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 `@src/presets/vercel/runtime/queue.dev.ts`:
- Line 36: Replace the direct console.error call in queue.dev.ts with the
preset/dev logger: use nitroApp.logger.error(...) if a nitroApp instance is in
scope, otherwise import and use consola.error(...); specifically change the
console.error("[vercel:queue]", error) invocation to call the appropriate
logger, and add the required import or ensure nitroApp is available in the
surrounding function where the error is handled.
- Line 5: The import path and symbol are wrong: replace the import of
registerVercelQueueConsumer from "env-runner/runners/vercel/queue-dev" with the
correct export from "env-runner/runners/vercel" (verify the exact exported
function name in that package and update the import to match), update any
references to registerVercelQueueConsumer if the exported name differs, change
the console.error call at the place currently using console.error to
consola.error, and inside the teardown catch block (the empty catch around
teardown logic) add explicit error handling/logging (e.g., log the error via
consola.error with context) so errors are not silently swallowed.

---

Nitpick comments:
In `@src/presets/vercel/runtime/queue.dev.ts`:
- Around line 50-53: The close hook currently swallows errors from unregister()
with an empty catch; update the catch to capture the exception and log it (e.g.,
catch (err) { console.error('Failed to unregister local queue in close hook:',
err) } or use an existing logger like processLogger.error) so failures in
unregister() are visible; keep the call to unregister() and ensure the log
includes context and the error object for debugging.
🪄 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: 9ccb08c1-7a29-4496-bf7c-d75f658bd36e

📥 Commits

Reviewing files that changed from the base of the PR and between 0498ce7 and 3a82754.

📒 Files selected for processing (5)
  • docs/2.deploy/20.providers/vercel.md
  • src/presets/_types.gen.ts
  • src/presets/vercel/dev.ts
  • src/presets/vercel/preset.ts
  • src/presets/vercel/runtime/queue.dev.ts

import type { MessageMetadata } from "@vercel/queue";
import type { NitroAppPlugin } from "nitro/types";
import { useRuntimeConfig } from "nitro/runtime-config";
import { registerVercelQueueConsumer } from "env-runner/runners/vercel/queue-dev";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Locate any queue-dev implementation in repo:"
fd -i 'queue-dev.ts|queue-dev.mjs|queue-dev.js'

echo
echo "2) Find all usages of registerVercelQueueConsumer:"
rg -n --type=ts -C3 '\bregisterVercelQueueConsumer\b'

echo
echo "3) Find all imports from env-runner in TS files:"
rg -n --type=ts -C2 'from "env-runner[^"]*"'

echo
echo "4) Check alias/path mapping for env-runner:"
fd -i 'tsconfig*.json' --exec sh -c 'echo "--- $1"; jq ".compilerOptions.paths // {}" "$1"' sh {}

Repository: nitrojs/nitro

Length of output: 30841


🏁 Script executed:

# Check if env-runner is listed as a dependency
fd -i 'package.json' -type f | head -5 | xargs -I {} sh -c 'echo "=== {} ==="; cat "{}" | grep -A 50 -B 5 "env-runner" || true'

Repository: nitrojs/nitro

Length of output: 228


🌐 Web query:

env-runner npm package runners/vercel/queue-dev

💡 Result:

The string “env-runner npm package runners/vercel/queue-dev” doesn’t resolve cleanly to a specific, documented npm package path or file name in the sources I found. What I could confirm: 1) The npm package “env-runner” (unjs/env-runner) exists and provides “runners” including a Vercel runner at the import path env-runner/runners/vercel (not “queue-dev”). It also documents that it can run across multiple environments/runtimes and exposes a Vercel runner that simulates a Vercel deployment environment with Vercel-like header injection. [1][2] 2) Vercel-specific behavior for env-runner is implemented via “VercelEnvRunner”. Its changes include injection of Vercel-related request headers such as x-vercel-deployment-url and x-vercel-id, and it sets process.env values like VERCEL, VERCEL_ENV, VERCEL_REGION, and NOW_REGION in the worker context. [3][4] 3) Vercel Queues are a separate Vercel product (queues durable event streaming). Vercel’s own docs describe authentication and API behavior for Queues, but those docs don’t mention an env-runner “queue-dev” runner. [5][6] If you meant something else by “queue-dev” (for example, a specific file/directory name inside env-runner like runners/vercel/queue-dev, or a tag/example used for local queue development), tell me one of the following and I can re-search precisely: - the full npm package name (including scope/version) you intend, or - the exact GitHub file path you saw (repo + path), or - a snippet of the import/require statement you’re using. Citations: - env-runner README shows available runners and explicitly includes VercelEnvRunner at env-runner/runners/vercel and describes Vercel context/header injection. [1] - env-runner repository overview similarly lists Vercel runner and its purpose. [2] - env-runner commit implementing Vercel env var + header injection (VercelEnvRunner). [3] - env-runner commit adding VERCEL_DEPLOYMENT_ID and testing it in VercelEnvRunner. [4] - Vercel Queues docs (product/API) don’t reference env-runner “queue-dev”. [5][6]

Citations:


🌐 Web query:

registerVercelQueueConsumer env-runner function

💡 Result:

There is no documented function named registerVercelQueueConsumer in either the Vercel Queues SDK/docs or the unjs/env-runner project docs. What you likely want (Vercel Queues “push-mode” consumer registration): 1) Configure your consumer endpoint trigger in vercel.json using a queue/v2beta experimentalTriggers entry for your route. Vercel invokes that route automatically in push mode. [1][2][3] Example: { "functions": { "app/api/queues/process-order/route.ts": { "experimentalTriggers": [{ "type": "queue/v2beta", "topic": "orders" }] } } } 2) Export your handler using @vercel/queue’s handleCallback (or handleNodeCallback for certain routers). Messages are acknowledged when your handler completes and retried if the handler throws. [4][3][5] Example: import { handleCallback } from '@vercel/queue'; export const POST = handleCallback(async (message, metadata) => { await processOrder(message); }); How unjs/env-runner fits in: - env-runner is a generic runtime “environment runner” (it can simulate Vercel via VercelEnvRunner), but its docs don’t mention any Vercel Queue consumer registration helper like registerVercelQueueConsumer. [6][7] - So, in practice, you would still register a Vercel Queues consumer the Vercel way (vercel.json trigger + handleCallback handler), while env-runner may help simulate the Vercel runtime environment during local testing. [6][7][5] If you can share where you saw “registerVercelQueueConsumer” (repo/package/link or the relevant file), I can pinpoint whether it’s from a different library or an internal wrapper and map it to the equivalent Vercel Queues APIs.

Citations:


🏁 Script executed:

# Also check the file to understand what this function is supposed to do
cat -n src/presets/vercel/runtime/queue.dev.ts | head -60

Repository: nitrojs/nitro

Length of output: 2055


Critical: unresolved env-runner/runners/vercel/queue-dev import path

This import does not exist in the env-runner package. The package provides env-runner/runners/vercel but not a queue-dev subpath, and registerVercelQueueConsumer is not an exported function. Verify the correct import path and function name.

Additionally:

  • Line 36: replace console.error with consola.error (required for src/presets/**)
  • Lines 50–52: empty catch block silently swallows teardown errors; add explicit error handling or logging
🧰 Tools
🪛 GitHub Check: tests-checks (ubuntu-latest)

[failure] 5-5:
Cannot find module 'env-runner/runners/vercel/queue-dev' or its corresponding type declarations.

🤖 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 `@src/presets/vercel/runtime/queue.dev.ts` at line 5, The import path and
symbol are wrong: replace the import of registerVercelQueueConsumer from
"env-runner/runners/vercel/queue-dev" with the correct export from
"env-runner/runners/vercel" (verify the exact exported function name in that
package and update the import to match), update any references to
registerVercelQueueConsumer if the exported name differs, change the
console.error call at the place currently using console.error to consola.error,
and inside the teardown catch block (the empty catch around teardown logic) add
explicit error handling/logging (e.g., log the error via consola.error with
context) so errors are not silently swallowed.

send,
});
} catch (error) {
console.error("[vercel:queue]", error);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use Nitro/consola logger instead of console.error

Switch this to nitroApp.logger (or consola) to keep logging consistent with preset/dev conventions.

Suggested diff
-          console.error("[vercel:queue]", error);
+          nitroApp.logger.error("[vercel:queue]", error);

As per coding guidelines src/{build,dev,cli,presets}/**/*.{ts,js,mjs}: Use consola for logging in build/dev code, or nitro.logger when available.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.error("[vercel:queue]", error);
nitroApp.logger.error("[vercel:queue]", error);
🤖 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 `@src/presets/vercel/runtime/queue.dev.ts` at line 36, Replace the direct
console.error call in queue.dev.ts with the preset/dev logger: use
nitroApp.logger.error(...) if a nitroApp instance is in scope, otherwise import
and use consola.error(...); specifically change the
console.error("[vercel:queue]", error) invocation to call the appropriate
logger, and add the required import or ensure nitroApp is available in the
surrounding function where the error is handled.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant