@vercel/queue 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,20 +19,20 @@ npm install @vercel/queue
19
19
 
20
20
  ## Quick Start
21
21
 
22
- **1. Create a shared queue client:**
22
+ **1. Link your Vercel project and pull credentials:**
23
23
 
24
- ```typescript
25
- // lib/queue.ts
26
- import { QueueClient } from "@vercel/queue";
24
+ The SDK authenticates via OIDC. Link your project if you haven't already, then pull to get fresh tokens:
27
25
 
28
- const queue = new QueueClient();
29
- export const { send, handleCallback } = queue;
26
+ ```bash
27
+ npm i -g vercel
28
+ vc link # if you haven't already
29
+ vc env pull
30
30
  ```
31
31
 
32
32
  **2. Send a message anywhere in your app:**
33
33
 
34
34
  ```typescript
35
- import { send } from "@/lib/queue";
35
+ import { send } from "@vercel/queue";
36
36
 
37
37
  await send("my-topic", { message: "Hello world" });
38
38
  ```
@@ -41,7 +41,7 @@ await send("my-topic", { message: "Hello world" });
41
41
 
42
42
  ```typescript
43
43
  // app/api/queue/my-topic/route.ts
44
- import { handleCallback } from "@/lib/queue";
44
+ import { handleCallback } from "@vercel/queue";
45
45
 
46
46
  export const POST = handleCallback(async (message, metadata) => {
47
47
  console.log("Processing:", message);
@@ -60,28 +60,28 @@ export const POST = handleCallback(async (message, metadata) => {
60
60
  }
61
61
  ```
62
62
 
63
- **5. Link your project for local development:**
63
+ That's it. The top-level `send` and `handleCallback` use an auto-configured default client. The region is auto-detected from `VERCEL_REGION` (set automatically on Vercel). If the region can't be detected (e.g. local dev), it falls back to `iad1`.
64
64
 
65
- ```bash
66
- npm i -g vercel
67
- vc link
68
- vc env pull
65
+ To target a specific region for sending with the top-level `send`, pass the `region` option:
66
+
67
+ ```typescript
68
+ await send("my-topic", payload, { region: "sfo1" });
69
69
  ```
70
70
 
71
- That's it. `new QueueClient()` auto-detects the region from `VERCEL_REGION` (set automatically on Vercel). If the region can't be detected (e.g. local dev), it falls back to `iad1`.
71
+ > **Note:** The `region` option is only available on the top-level `send()` convenience export. When using a `QueueClient` instance, the region is set once in the constructor via `new QueueClient({ region: "sfo1" })` and applies to all operations on that client.
72
72
 
73
73
  ## Local Development
74
74
 
75
- **Queues just work locally.** When you `send()` messages in development mode, the library sends them to the real Vercel Queue Service, reads your `vercel.json` configuration, discovers your queue handlers, and triggers them automatically via local HTTP requests. This means your local dev environment behaves identically to production no surprising behavior differences.
75
+ **Queues just work locally.** When you `send()` messages in development mode, the library sends them to the real Vercel Queue Service, then invokes your registered `handleCallback` handlers directly in-process using the same code path as production. Your handlers are called with the same lifecycle (receive, visibility extension, ack) as in production. If a handler throws, the message is re-delivered after the configured retry delay (from `retryAfterSeconds` in `vercel.json` or the `retry` callback's `afterSeconds`), with an incrementing `deliveryCount`, matching production retry semantics.
76
76
 
77
- > **Note:** Local dev mode is enabled when `NODE_ENV=development`. Most frameworks (Next.js, etc.) set this automatically during `npm run dev`.
77
+ Works with Next.js (Turbopack and webpack), Nuxt, SvelteKit, and any framework that runs server-side JavaScript. The SDK automatically discovers handlers from your `vercel.json` configuration and loads route modules on demand — no manual setup required beyond `vercel.json`.
78
+
79
+ > **Note:** Local dev mode is enabled when `NODE_ENV=development`. Most frameworks set this automatically during `npm run dev`.
78
80
 
79
81
  ## Publishing Messages
80
82
 
81
83
  ```typescript
82
- import { QueueClient } from "@vercel/queue";
83
-
84
- const { send } = new QueueClient();
84
+ import { send } from "@vercel/queue";
85
85
 
86
86
  // Simple send
87
87
  await send("my-topic", { message: "Hello world" });
@@ -94,6 +94,7 @@ await send(
94
94
  idempotencyKey: "unique-key", // Prevent duplicate messages
95
95
  retentionSeconds: 3600, // 1 hour TTL (default: 24h)
96
96
  delaySeconds: 60, // Delay delivery by 1 minute
97
+ region: "sfo1", // Top-level send() only — not available on QueueClient.send()
97
98
  },
98
99
  );
99
100
  ```
@@ -102,7 +103,7 @@ Example usage in an API route:
102
103
 
103
104
  ```typescript
104
105
  // app/api/send-message/route.ts
105
- import { send } from "@/lib/queue";
106
+ import { send } from "@vercel/queue";
106
107
 
107
108
  export async function POST(request: Request) {
108
109
  const body = await request.json();
@@ -127,12 +128,43 @@ Returns `(Request) => Promise<Response>`. For frameworks that export Web API rou
127
128
 
128
129
  ```typescript
129
130
  // app/api/queue/my-topic/route.ts
130
- import { handleCallback } from "@/lib/queue";
131
+ import { handleCallback } from "@vercel/queue";
132
+
133
+ export const POST = handleCallback(
134
+ async (message, metadata) => {
135
+ // metadata: { messageId, deliveryCount, createdAt, expiresAt, topicName, consumerGroup, region }
136
+ await processMessage(message);
137
+ // Throwing an error will automatically retry the message
138
+ },
139
+ {
140
+ visibilityTimeoutSeconds: 600, // Lock duration while processing (default: 300)
141
+ },
142
+ );
143
+ ```
144
+
145
+ **Nuxt:**
146
+
147
+ ```typescript
148
+ // server/api/queue.ts
149
+ import { handleCallback } from "@vercel/queue";
150
+
151
+ const handler = handleCallback(async (message, metadata) => {
152
+ await processMessage(message);
153
+ });
154
+
155
+ export default defineEventHandler(async (event) => {
156
+ return handler(toWebRequest(event));
157
+ });
158
+ ```
159
+
160
+ **SvelteKit:**
161
+
162
+ ```typescript
163
+ // src/routes/api/queue/+server.ts
164
+ import { handleCallback } from "@vercel/queue";
131
165
 
132
166
  export const POST = handleCallback(async (message, metadata) => {
133
- // metadata: { messageId, deliveryCount, createdAt, expiresAt?, topicName, consumerGroup, region }
134
167
  await processMessage(message);
135
- // Throwing an error will automatically retry the message
136
168
  });
137
169
  ```
138
170
 
@@ -140,7 +172,7 @@ export const POST = handleCallback(async (message, metadata) => {
140
172
 
141
173
  ```typescript
142
174
  import { Hono } from "hono";
143
- import { handleCallback } from "@/lib/queue";
175
+ import { handleCallback } from "@vercel/queue";
144
176
 
145
177
  const app = new Hono();
146
178
  app.post(
@@ -154,7 +186,26 @@ export default app;
154
186
 
155
187
  #### Connect-style — `handleNodeCallback`
156
188
 
157
- Returns `(req, res) => Promise<void>`. For frameworks that export Connect-style handlers (Express, Next.js Pages Router, etc.).
189
+ Returns `(req, res) => Promise<void>`. For frameworks that export Connect-style handlers (Vercel Node.js functions, Express, Next.js Pages Router, etc.). **`handleNodeCallback` is not a top-level export** — it is only available via a `QueueClient` instance:
190
+
191
+ ```typescript
192
+ // lib/queue.ts
193
+ import { QueueClient } from "@vercel/queue";
194
+
195
+ const queue = new QueueClient();
196
+ export const { handleNodeCallback } = queue;
197
+ ```
198
+
199
+ **Vercel Node.js Functions (plain `api/` directory):**
200
+
201
+ ```typescript
202
+ // api/queue.ts
203
+ import { handleNodeCallback } from "./lib/queue";
204
+
205
+ export default handleNodeCallback(async (message, metadata) => {
206
+ await processMessage(message);
207
+ });
208
+ ```
158
209
 
159
210
  **Next.js Pages Router:**
160
211
 
@@ -225,14 +276,17 @@ Multiple route files for the same topic create separate consumer groups — each
225
276
 
226
277
  When a handler throws, the message is not acknowledged and becomes available for redelivery after the `retryAfterSeconds` interval configured in `vercel.json`. Retries continue until the handler succeeds or the message expires (default: 24 hours).
227
278
 
228
- For finer control over retry timing, pass a `retry` option:
279
+ For finer control over retry timing, pass a `retry` option. You can also set `visibilityTimeoutSeconds` to control how long the message is locked during processing (default: 300):
229
280
 
230
281
  ```typescript
282
+ import { handleCallback } from "@vercel/queue";
283
+
231
284
  export const POST = handleCallback(
232
285
  async (message, metadata) => {
233
286
  await processMessage(message);
234
287
  },
235
288
  {
289
+ visibilityTimeoutSeconds: 600, // Lock duration while processing (default: 300)
236
290
  retry: (error, metadata) => {
237
291
  if (error instanceof RateLimitError) return { afterSeconds: 60 };
238
292
  // Return undefined to let the error propagate normally
@@ -246,6 +300,8 @@ When `retry` returns `{ afterSeconds: N }`, the message is rescheduled for redel
246
300
  **Exponential backoff** uses `metadata.deliveryCount` (starts at 1, increments each delivery):
247
301
 
248
302
  ```typescript
303
+ import { handleCallback } from "@vercel/queue";
304
+
249
305
  export const POST = handleCallback(
250
306
  async (message, metadata) => {
251
307
  await processMessage(message);
@@ -263,6 +319,8 @@ export const POST = handleCallback(
263
319
  **Conditional retry** — only retry transient errors:
264
320
 
265
321
  ```typescript
322
+ import { handleCallback } from "@vercel/queue";
323
+
266
324
  export const POST = handleCallback(
267
325
  async (message, metadata) => {
268
326
  await processMessage(message);
@@ -280,6 +338,8 @@ export const POST = handleCallback(
280
338
  **Acknowledging poison messages** — stop retrying messages that can never succeed:
281
339
 
282
340
  ```typescript
341
+ import { handleCallback } from "@vercel/queue";
342
+
283
343
  export const POST = handleCallback(
284
344
  async (message, metadata) => {
285
345
  await processMessage(message);
@@ -298,6 +358,8 @@ The `retry` option is available on `handleCallback`, `handleNodeCallback`, and `
298
358
 
299
359
  ## Custom Client Configuration
300
360
 
361
+ For most use cases, the top-level `send` and `handleCallback` functions are all you need. For advanced configuration (custom transports, explicit tokens, deployment pinning), create a `QueueClient` instance directly.
362
+
301
363
  ### QueueClient (push mode)
302
364
 
303
365
  For push-based workflows where Vercel delivers messages to your route handlers:
@@ -445,8 +507,8 @@ import {
445
507
  ForbiddenError,
446
508
  InternalServerError,
447
509
  UnauthorizedError,
510
+ send,
448
511
  } from "@vercel/queue";
449
- import { send } from "@/lib/queue";
450
512
 
451
513
  try {
452
514
  await send("my-topic", payload);
@@ -499,7 +561,7 @@ All error types:
499
561
  | Limit | Value | Notes |
500
562
  | --------------------------- | --------------------- | ----------------------------------- |
501
563
  | Message throughput | 10,000+ msg/sec/topic | Scales horizontally |
502
- | Payload size | 1 GB | Smaller messages have lower latency |
564
+ | Payload size | 100 MB | Smaller messages have lower latency |
503
565
  | Number of topics | Unlimited | No hard limit |
504
566
  | Consumer groups per message | ~4,000 | Per-message limit |
505
567
  | Messages per queue | Unlimited | No hard limit |
@@ -549,9 +611,51 @@ All error types:
549
611
 
550
612
  ## API Reference
551
613
 
614
+ ### Top-level `send(topicName, payload, options?)`
615
+
616
+ The simplest way to send a message. Uses an auto-configured default client that detects the region from `VERCEL_REGION`, falling back to `"iad1"` with a console warning on first use.
617
+
618
+ ```typescript
619
+ import { send } from "@vercel/queue";
620
+
621
+ const { messageId } = await send("my-topic", payload, {
622
+ idempotencyKey: "unique-key", // Dedup window: min(retention, 24h)
623
+ retentionSeconds: 3600, // Message TTL (default: 86400)
624
+ delaySeconds: 60, // Delay before visible (default: 0)
625
+ headers: { "X-Custom": "val" }, // Custom headers
626
+ region: "sfo1", // Override the auto-detected region for this send
627
+ });
628
+ ```
629
+
630
+ The `region` option is exclusive to the top-level `send()`. It creates a one-off client targeting the given region. When using `QueueClient`, the region is set once in the constructor and applies to all operations.
631
+
632
+ Returns `{ messageId: string | null }`. `messageId` is `null` when the server accepted the message for deferred processing (e.g. during a server-side outage).
633
+
634
+ ### Top-level `handleCallback(handler, options?)`
635
+
636
+ The simplest way to handle incoming queue messages. Uses the same auto-configured default client as `send`.
637
+
638
+ ```typescript
639
+ import { handleCallback } from "@vercel/queue";
640
+
641
+ export const POST = handleCallback(
642
+ async (message, metadata) => {
643
+ await processMessage(message);
644
+ },
645
+ {
646
+ visibilityTimeoutSeconds: 300, // Lock duration (default: 300)
647
+ retry: (error, metadata) => {
648
+ // Optional: return { afterSeconds: N } to reschedule, { acknowledge: true } to ack, or undefined to propagate
649
+ },
650
+ },
651
+ );
652
+ ```
653
+
654
+ Returns `(request: Request) => Promise<Response>` — for frameworks that export Web API route handlers. Vercel only. The region for follow-up API calls is determined automatically from the `ce-vqsregion` header in the incoming event.
655
+
552
656
  ### `QueueClient`
553
657
 
554
- Push-based client for workflows where Vercel delivers messages to your route handlers. Region is auto-detected from `VERCEL_REGION` (set automatically on Vercel), falling back to `"iad1"` with a console warning.
658
+ Push-based client for workflows where Vercel delivers messages to your route handlers. Use this when you need custom configuration (transport, token, headers, deployment pinning). Region is auto-detected from `VERCEL_REGION` (set automatically on Vercel), falling back to `"iad1"` with a console warning.
555
659
 
556
660
  ```typescript
557
661
  import { QueueClient } from "@vercel/queue";
@@ -585,21 +689,6 @@ const queue = new PollingQueueClient({
585
689
  const { send, receive } = queue;
586
690
  ```
587
691
 
588
- ### `send(topicName, payload, options?)`
589
-
590
- Available on both `QueueClient` and `PollingQueueClient`.
591
-
592
- Returns `{ messageId: string | null }`. `messageId` is `null` when the server accepted the message for deferred processing (e.g. during a server-side outage).
593
-
594
- ```typescript
595
- const { messageId } = await send("my-topic", payload, {
596
- idempotencyKey: "unique-key", // Dedup window: min(retention, 24h)
597
- retentionSeconds: 3600, // Message TTL (default: 86400)
598
- delaySeconds: 60, // Delay before visible (default: 0)
599
- headers: { "X-Custom": "val" }, // Custom headers
600
- });
601
- ```
602
-
603
692
  ### `receive(topicName, consumerGroup, handler, options?)`
604
693
 
605
694
  Available on `PollingQueueClient` only.
@@ -626,33 +715,18 @@ const result = await receive("my-topic", "my-group", handler, {
626
715
  });
627
716
  ```
628
717
 
629
- ### `handleCallback(handler, options?)`
630
-
631
- Available on `QueueClient` only. Vercel only.
632
-
633
- Returns `(request: Request) => Promise<Response>` — for frameworks that export Web API route handlers.
634
-
635
- ```typescript
636
- export const POST = handleCallback(
637
- async (message, metadata) => {
638
- await processMessage(message);
639
- },
640
- {
641
- visibilityTimeoutSeconds: 300, // Lock duration (default: 300)
642
- retry: (error, metadata) => {
643
- // Optional: return { afterSeconds: N } to reschedule, { acknowledge: true } to ack, or undefined to propagate
644
- },
645
- },
646
- );
647
- ```
648
-
649
718
  ### `handleNodeCallback(handler, options?)`
650
719
 
651
- Available on `QueueClient` only. Vercel only.
720
+ Available on `QueueClient` instances only (not a top-level export). Vercel only.
652
721
 
653
722
  Returns `(req, res) => Promise<void>` — for frameworks that export Connect-style handlers.
654
723
 
655
724
  ```typescript
725
+ import { QueueClient } from "@vercel/queue";
726
+
727
+ const queue = new QueueClient();
728
+ const { handleNodeCallback } = queue;
729
+
656
730
  // pages/api/queue/my-topic.ts
657
731
  export default handleNodeCallback(
658
732
  async (message, metadata) => {
@@ -676,7 +750,7 @@ interface MessageMetadata {
676
750
  messageId: string;
677
751
  deliveryCount: number;
678
752
  createdAt: Date;
679
- expiresAt?: Date;
753
+ expiresAt: Date;
680
754
  topicName: string;
681
755
  consumerGroup: string;
682
756
  region: string;
package/dist/index.d.mts CHANGED
@@ -289,7 +289,8 @@ interface Message<T = unknown> {
289
289
  createdAt: Date;
290
290
  /**
291
291
  * Timestamp when the message expires.
292
- * Only present for messages delivered via the v2beta binary callback path.
292
+ * Present in v2beta binary callback (`ce-vqsexpiresat` header) and
293
+ * V3 multipart/NDJSON responses (`Vqs-Expires-At` header / `expiresAt` field).
293
294
  */
294
295
  expiresAt?: Date;
295
296
  /**
@@ -311,7 +312,7 @@ interface MessageMetadata {
311
312
  messageId: string;
312
313
  deliveryCount: number;
313
314
  createdAt: Date;
314
- expiresAt?: Date;
315
+ expiresAt: Date;
315
316
  topicName: string;
316
317
  consumerGroup: string;
317
318
  /** Vercel region the client is targeting. */
@@ -519,6 +520,9 @@ declare class ConsumerRegistryNotConfiguredError extends Error {
519
520
  constructor(message?: string);
520
521
  }
521
522
 
523
+ type CallbackRequestInput$1 = Request | {
524
+ request: Request;
525
+ };
522
526
  /**
523
527
  * Queue client for push-based (callback) workflows.
524
528
  *
@@ -577,12 +581,12 @@ declare class QueueClient {
577
581
  * @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)
578
582
  * @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to
579
583
  * reschedule the message for redelivery after N seconds.
580
- * @returns A `(request: Request) => Promise<Response>` route handler
584
+ * @returns A route handler that accepts either `Request` or `{ request: Request }`
581
585
  */
582
586
  handleCallback: <T = unknown>(handler: MessageHandler<T>, options?: {
583
587
  visibilityTimeoutSeconds?: number;
584
588
  retry?: RetryHandler;
585
- }) => ((request: Request) => Promise<Response>);
589
+ }) => ((requestOrEvent: CallbackRequestInput$1) => Promise<Response>);
586
590
  /**
587
591
  * Create a Connect-style route handler for processing queue callback messages.
588
592
  * For use on Vercel — Vercel invokes this route when messages are available.
@@ -680,6 +684,58 @@ declare class PollingQueueClient {
680
684
  receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
681
685
  }
682
686
 
687
+ type CallbackRequestInput = Request | {
688
+ request: Request;
689
+ };
690
+ /**
691
+ * Send a message to a topic using the default auto-configured client.
692
+ *
693
+ * The default client auto-detects the region from `VERCEL_REGION`,
694
+ * falling back to `"iad1"` with a console warning on first use.
695
+ *
696
+ * This is an arrow function–free alternative to destructuring from a
697
+ * {@link QueueClient} instance — import and use directly:
698
+ * ```typescript
699
+ * import { send } from "@vercel/queue";
700
+ * await send("my-topic", { hello: "world" });
701
+ * ```
702
+ *
703
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
704
+ * @param payload - The data to send (serialized via JsonTransport)
705
+ * @param options - Optional send options. Pass `region` to route to a specific region.
706
+ * @returns `{ messageId }` — `messageId` is `null` when the server accepted
707
+ * the message for deferred processing
708
+ */
709
+ declare function send<T = unknown>(topicName: string, payload: T, options?: SendOptions & {
710
+ region?: VercelRegion;
711
+ }): Promise<SendResult>;
712
+ /**
713
+ * Create a Web API route handler for processing queue callback messages
714
+ * using the default auto-configured client.
715
+ *
716
+ * The default client auto-detects the region from `VERCEL_REGION`,
717
+ * falling back to `"iad1"` with a console warning on first use.
718
+ * The callback region is determined automatically from the incoming
719
+ * `ce-vqsregion` header in the v2beta event — no manual configuration needed.
720
+ *
721
+ * This is an arrow function–free alternative to destructuring from a
722
+ * {@link QueueClient} instance — import and use directly:
723
+ * ```typescript
724
+ * import { handleCallback } from "@vercel/queue";
725
+ * export const POST = handleCallback(async (message, metadata) => {
726
+ * console.log("Processing:", message);
727
+ * });
728
+ * ```
729
+ *
730
+ * @param handler - Function to process the message payload and metadata
731
+ * @param options - Optional configuration (visibilityTimeoutSeconds, retry)
732
+ * @returns A route handler that accepts either `Request` or `{ request: Request }`
733
+ */
734
+ declare function handleCallback<T = unknown>(handler: MessageHandler<T>, options?: {
735
+ visibilityTimeoutSeconds?: number;
736
+ retry?: RetryHandler;
737
+ }): (requestOrEvent: CallbackRequestInput) => Promise<Response>;
738
+
683
739
  /**
684
740
  * Core queue callback utilities for handling incoming webhook payloads
685
741
  * from Vercel triggers using the CloudEvent specification.
@@ -753,4 +809,4 @@ declare function parseRawCallback(body: unknown, headers: Record<string, string
753
809
  */
754
810
  declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
755
811
 
756
- export { BadRequestError, type BaseUrlResolver, BufferTransport, CLOUD_EVENT_TYPE_V1BETA, CLOUD_EVENT_TYPE_V2BETA, ConsumerDiscoveryError, ConsumerRegistryNotConfiguredError, DuplicateMessageError, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageAlreadyProcessedError, MessageCorruptedError, type MessageHandler, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type ParsedCallbackRequest, type ParsedCallbackV1, type ParsedCallbackV2, PollingQueueClient, type PollingQueueClientOptions, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveBatchOptions, type ReceiveByIdOptions, type ReceiveOptions, type ReceiveResult, type RetryDirective, type RetryHandler, type SendOptions, type SendResult, StreamTransport, type Transport, UnauthorizedError, type VercelRegion, parseCallback, parseRawCallback };
812
+ export { BadRequestError, type BaseUrlResolver, BufferTransport, CLOUD_EVENT_TYPE_V1BETA, CLOUD_EVENT_TYPE_V2BETA, ConsumerDiscoveryError, ConsumerRegistryNotConfiguredError, DuplicateMessageError, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageAlreadyProcessedError, MessageCorruptedError, type MessageHandler, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type ParsedCallbackRequest, type ParsedCallbackV1, type ParsedCallbackV2, PollingQueueClient, type PollingQueueClientOptions, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveBatchOptions, type ReceiveByIdOptions, type ReceiveOptions, type ReceiveResult, type RetryDirective, type RetryHandler, type SendOptions, type SendResult, StreamTransport, type Transport, UnauthorizedError, type VercelRegion, handleCallback, parseCallback, parseRawCallback, send };
package/dist/index.d.ts CHANGED
@@ -289,7 +289,8 @@ interface Message<T = unknown> {
289
289
  createdAt: Date;
290
290
  /**
291
291
  * Timestamp when the message expires.
292
- * Only present for messages delivered via the v2beta binary callback path.
292
+ * Present in v2beta binary callback (`ce-vqsexpiresat` header) and
293
+ * V3 multipart/NDJSON responses (`Vqs-Expires-At` header / `expiresAt` field).
293
294
  */
294
295
  expiresAt?: Date;
295
296
  /**
@@ -311,7 +312,7 @@ interface MessageMetadata {
311
312
  messageId: string;
312
313
  deliveryCount: number;
313
314
  createdAt: Date;
314
- expiresAt?: Date;
315
+ expiresAt: Date;
315
316
  topicName: string;
316
317
  consumerGroup: string;
317
318
  /** Vercel region the client is targeting. */
@@ -519,6 +520,9 @@ declare class ConsumerRegistryNotConfiguredError extends Error {
519
520
  constructor(message?: string);
520
521
  }
521
522
 
523
+ type CallbackRequestInput$1 = Request | {
524
+ request: Request;
525
+ };
522
526
  /**
523
527
  * Queue client for push-based (callback) workflows.
524
528
  *
@@ -577,12 +581,12 @@ declare class QueueClient {
577
581
  * @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)
578
582
  * @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to
579
583
  * reschedule the message for redelivery after N seconds.
580
- * @returns A `(request: Request) => Promise<Response>` route handler
584
+ * @returns A route handler that accepts either `Request` or `{ request: Request }`
581
585
  */
582
586
  handleCallback: <T = unknown>(handler: MessageHandler<T>, options?: {
583
587
  visibilityTimeoutSeconds?: number;
584
588
  retry?: RetryHandler;
585
- }) => ((request: Request) => Promise<Response>);
589
+ }) => ((requestOrEvent: CallbackRequestInput$1) => Promise<Response>);
586
590
  /**
587
591
  * Create a Connect-style route handler for processing queue callback messages.
588
592
  * For use on Vercel — Vercel invokes this route when messages are available.
@@ -680,6 +684,58 @@ declare class PollingQueueClient {
680
684
  receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
681
685
  }
682
686
 
687
+ type CallbackRequestInput = Request | {
688
+ request: Request;
689
+ };
690
+ /**
691
+ * Send a message to a topic using the default auto-configured client.
692
+ *
693
+ * The default client auto-detects the region from `VERCEL_REGION`,
694
+ * falling back to `"iad1"` with a console warning on first use.
695
+ *
696
+ * This is an arrow function–free alternative to destructuring from a
697
+ * {@link QueueClient} instance — import and use directly:
698
+ * ```typescript
699
+ * import { send } from "@vercel/queue";
700
+ * await send("my-topic", { hello: "world" });
701
+ * ```
702
+ *
703
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
704
+ * @param payload - The data to send (serialized via JsonTransport)
705
+ * @param options - Optional send options. Pass `region` to route to a specific region.
706
+ * @returns `{ messageId }` — `messageId` is `null` when the server accepted
707
+ * the message for deferred processing
708
+ */
709
+ declare function send<T = unknown>(topicName: string, payload: T, options?: SendOptions & {
710
+ region?: VercelRegion;
711
+ }): Promise<SendResult>;
712
+ /**
713
+ * Create a Web API route handler for processing queue callback messages
714
+ * using the default auto-configured client.
715
+ *
716
+ * The default client auto-detects the region from `VERCEL_REGION`,
717
+ * falling back to `"iad1"` with a console warning on first use.
718
+ * The callback region is determined automatically from the incoming
719
+ * `ce-vqsregion` header in the v2beta event — no manual configuration needed.
720
+ *
721
+ * This is an arrow function–free alternative to destructuring from a
722
+ * {@link QueueClient} instance — import and use directly:
723
+ * ```typescript
724
+ * import { handleCallback } from "@vercel/queue";
725
+ * export const POST = handleCallback(async (message, metadata) => {
726
+ * console.log("Processing:", message);
727
+ * });
728
+ * ```
729
+ *
730
+ * @param handler - Function to process the message payload and metadata
731
+ * @param options - Optional configuration (visibilityTimeoutSeconds, retry)
732
+ * @returns A route handler that accepts either `Request` or `{ request: Request }`
733
+ */
734
+ declare function handleCallback<T = unknown>(handler: MessageHandler<T>, options?: {
735
+ visibilityTimeoutSeconds?: number;
736
+ retry?: RetryHandler;
737
+ }): (requestOrEvent: CallbackRequestInput) => Promise<Response>;
738
+
683
739
  /**
684
740
  * Core queue callback utilities for handling incoming webhook payloads
685
741
  * from Vercel triggers using the CloudEvent specification.
@@ -753,4 +809,4 @@ declare function parseRawCallback(body: unknown, headers: Record<string, string
753
809
  */
754
810
  declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
755
811
 
756
- export { BadRequestError, type BaseUrlResolver, BufferTransport, CLOUD_EVENT_TYPE_V1BETA, CLOUD_EVENT_TYPE_V2BETA, ConsumerDiscoveryError, ConsumerRegistryNotConfiguredError, DuplicateMessageError, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageAlreadyProcessedError, MessageCorruptedError, type MessageHandler, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type ParsedCallbackRequest, type ParsedCallbackV1, type ParsedCallbackV2, PollingQueueClient, type PollingQueueClientOptions, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveBatchOptions, type ReceiveByIdOptions, type ReceiveOptions, type ReceiveResult, type RetryDirective, type RetryHandler, type SendOptions, type SendResult, StreamTransport, type Transport, UnauthorizedError, type VercelRegion, parseCallback, parseRawCallback };
812
+ export { BadRequestError, type BaseUrlResolver, BufferTransport, CLOUD_EVENT_TYPE_V1BETA, CLOUD_EVENT_TYPE_V2BETA, ConsumerDiscoveryError, ConsumerRegistryNotConfiguredError, DuplicateMessageError, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageAlreadyProcessedError, MessageCorruptedError, type MessageHandler, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type ParsedCallbackRequest, type ParsedCallbackV1, type ParsedCallbackV2, PollingQueueClient, type PollingQueueClientOptions, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveBatchOptions, type ReceiveByIdOptions, type ReceiveOptions, type ReceiveResult, type RetryDirective, type RetryHandler, type SendOptions, type SendResult, StreamTransport, type Transport, UnauthorizedError, type VercelRegion, handleCallback, parseCallback, parseRawCallback, send };