@vercel/queue 0.0.2 → 0.1.1

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/dist/index.d.mts CHANGED
@@ -37,12 +37,11 @@ interface Transport<T = unknown> {
37
37
  * @example
38
38
  * ```typescript
39
39
  * // Default (JsonTransport is used automatically)
40
- * const queue = new QueueClient({ region: process.env.QUEUE_REGION! });
40
+ * const queue = new QueueClient();
41
41
  * await queue.send("topic", { data: "example" });
42
42
  *
43
43
  * // With custom serialization
44
44
  * const queue = new QueueClient({
45
- * region: process.env.QUEUE_REGION!,
46
45
  * transport: new JsonTransport({
47
46
  * replacer: (key, value) => key === "password" ? undefined : value,
48
47
  * reviver: (key, value) => key === "date" ? new Date(value) : value,
@@ -75,7 +74,7 @@ declare class JsonTransport<T = unknown> implements Transport<T> {
75
74
  *
76
75
  * @example
77
76
  * ```typescript
78
- * const queue = new QueueClient({ region: "iad1", transport: new BufferTransport() });
77
+ * const queue = new QueueClient({ transport: new BufferTransport() });
79
78
  * await queue.send("binary-topic", myBuffer);
80
79
  * ```
81
80
  */
@@ -95,13 +94,13 @@ declare class BufferTransport implements Transport<Buffer> {
95
94
  *
96
95
  * @example
97
96
  * ```typescript
98
- * const queue = new QueueClient({ region: "iad1", transport: new StreamTransport() });
99
- *
100
97
  * // Sending a stream
98
+ * const queue = new QueueClient({ transport: new StreamTransport() });
101
99
  * await queue.send("large-file", myReadableStream);
102
100
  *
103
101
  * // Receiving - cleanup handled automatically
104
- * await queue.receive("large-file", "processor", async (stream, meta) => {
102
+ * const poller = new PollingQueueClient({ region: "iad1", transport: new StreamTransport() });
103
+ * await poller.receive("large-file", "processor", async (stream, meta) => {
105
104
  * const reader = stream.getReader();
106
105
  * // Process chunks...
107
106
  * });
@@ -155,15 +154,17 @@ interface QueueClientOptions {
155
154
  * Requests are sent to the regional endpoint resolved by
156
155
  * {@link BaseUrlResolver} (default: `https://${region}.vercel-queue.com`).
157
156
  *
158
- * Use a `QUEUE_REGION` env var set to `${VERCEL_REGION}` in production
159
- * and a fixed region (e.g. `"iad1"`) in development.
157
+ * When omitted, the region is auto-detected from the `VERCEL_REGION`
158
+ * environment variable (set automatically on Vercel). If not available,
159
+ * defaults to `"iad1"` with a console warning.
160
160
  *
161
161
  * @example
162
162
  * ```ts
163
- * new QueueClient({ region: process.env.QUEUE_REGION! })
163
+ * new QueueClient() // auto-detect, falls back to "iad1"
164
+ * new QueueClient({ region: "iad1" }) // explicit
164
165
  * ```
165
166
  */
166
- region: VercelRegion;
167
+ region?: VercelRegion;
167
168
  /**
168
169
  * Custom resolver that maps a region code to a base {@link URL}.
169
170
  *
@@ -205,6 +206,28 @@ interface QueueClientOptions {
205
206
  */
206
207
  transport?: Transport;
207
208
  }
209
+ /**
210
+ * Options for creating a {@link PollingQueueClient}.
211
+ *
212
+ * Identical to {@link QueueClientOptions} except `region` is **required**
213
+ * because messages can only be received from the region they were sent to.
214
+ * Using a fixed region (e.g. `"iad1"`) ensures that `send` and `receive`
215
+ * target the same endpoint.
216
+ */
217
+ interface PollingQueueClientOptions extends QueueClientOptions {
218
+ /**
219
+ * Vercel region code for API routing — **required** for polling.
220
+ *
221
+ * Messages can only be received from the region they were sent to.
222
+ * Use a fixed region (e.g. `"iad1"`) for both sending and receiving.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * new PollingQueueClient({ region: "iad1" })
227
+ * ```
228
+ */
229
+ region: VercelRegion;
230
+ }
208
231
  /**
209
232
  * Options for sending messages.
210
233
  */
@@ -496,14 +519,40 @@ declare class ConsumerRegistryNotConfiguredError extends Error {
496
519
  constructor(message?: string);
497
520
  }
498
521
 
522
+ type CallbackRequestInput$1 = Request | {
523
+ request: Request;
524
+ };
525
+ /**
526
+ * Queue client for push-based (callback) workflows.
527
+ *
528
+ * Use this client when Vercel delivers messages to your route handlers.
529
+ * Provides {@link send}, {@link handleCallback}, and {@link handleNodeCallback}.
530
+ *
531
+ * Region is resolved automatically:
532
+ * 1. Explicit `region` option (highest priority)
533
+ * 2. `VERCEL_REGION` environment variable (set automatically on Vercel)
534
+ * 3. Falls back to `"iad1"` with a console warning
535
+ *
536
+ * The constructor never throws — `new QueueClient()` always works.
537
+ *
538
+ * For manual polling workflows, use {@link PollingQueueClient} instead.
539
+ *
540
+ * @example
541
+ * ```typescript
542
+ * import { QueueClient } from "@vercel/queue";
543
+ *
544
+ * const queue = new QueueClient();
545
+ * export const { send, handleCallback, handleNodeCallback } = queue;
546
+ * ```
547
+ */
499
548
  declare class QueueClient {
500
- constructor(options: QueueClientOptions);
549
+ constructor(options?: QueueClientOptions);
501
550
  /**
502
551
  * Send a message to a topic.
503
552
  *
504
553
  * This is an arrow function property so it can be destructured:
505
554
  * ```typescript
506
- * const { send } = new QueueClient({ region: process.env.QUEUE_REGION! });
555
+ * const { send } = new QueueClient();
507
556
  * await send("my-topic", payload);
508
557
  * ```
509
558
  *
@@ -514,28 +563,6 @@ declare class QueueClient {
514
563
  * the message for deferred processing (no ID available yet)
515
564
  */
516
565
  send: <T = unknown>(topicName: string, payload: T, options?: SendOptions) => Promise<SendResult>;
517
- /**
518
- * Receive and process messages from a topic.
519
- *
520
- * Each message is automatically locked, kept alive via periodic visibility
521
- * extensions during processing, and acknowledged upon successful handler completion.
522
- * The handler is not called when the queue is empty — check `result.ok` instead.
523
- *
524
- * This is an arrow function property so it can be destructured:
525
- * ```typescript
526
- * const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });
527
- * const result = await receive("my-topic", "my-group", handler);
528
- * if (!result.ok) console.log(result.reason);
529
- * ```
530
- *
531
- * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
532
- * @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
533
- * @param handler - Function to process each message payload and metadata.
534
- * Not called when the queue is empty.
535
- * @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
536
- * @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
537
- */
538
- receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
539
566
  /**
540
567
  * Create a Web API route handler for processing queue callback messages.
541
568
  *
@@ -544,7 +571,7 @@ declare class QueueClient {
544
571
  *
545
572
  * This is an arrow function property so it can be destructured:
546
573
  * ```typescript
547
- * const { handleCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });
574
+ * const { handleCallback } = new QueueClient();
548
575
  * export const POST = handleCallback(handler);
549
576
  * ```
550
577
  *
@@ -553,12 +580,12 @@ declare class QueueClient {
553
580
  * @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)
554
581
  * @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to
555
582
  * reschedule the message for redelivery after N seconds.
556
- * @returns A `(request: Request) => Promise<Response>` route handler
583
+ * @returns A route handler that accepts either `Request` or `{ request: Request }`
557
584
  */
558
585
  handleCallback: <T = unknown>(handler: MessageHandler<T>, options?: {
559
586
  visibilityTimeoutSeconds?: number;
560
587
  retry?: RetryHandler;
561
- }) => ((request: Request) => Promise<Response>);
588
+ }) => ((requestOrEvent: CallbackRequestInput$1) => Promise<Response>);
562
589
  /**
563
590
  * Create a Connect-style route handler for processing queue callback messages.
564
591
  * For use on Vercel — Vercel invokes this route when messages are available.
@@ -568,7 +595,7 @@ declare class QueueClient {
568
595
  *
569
596
  * This is an arrow function property so it can be destructured:
570
597
  * ```typescript
571
- * const { handleNodeCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });
598
+ * const { handleNodeCallback } = new QueueClient();
572
599
  * app.post("/api/queue", handleNodeCallback(handler));
573
600
  * ```
574
601
  *
@@ -594,6 +621,119 @@ declare class QueueClient {
594
621
  end(): void;
595
622
  }) => Promise<void>);
596
623
  }
624
+ /**
625
+ * Queue client for poll-based (manual receive) workflows.
626
+ *
627
+ * Use this client when you manually poll for messages with {@link receive}.
628
+ * Also provides {@link send} for publishing messages.
629
+ *
630
+ * Region is **required** because messages can only be received from the
631
+ * region they were sent to. Use a fixed region (e.g. `"iad1"`) for both
632
+ * sending and receiving.
633
+ *
634
+ * For push-based (callback) workflows on Vercel, use {@link QueueClient} instead.
635
+ *
636
+ * @example
637
+ * ```typescript
638
+ * import { PollingQueueClient } from "@vercel/queue";
639
+ *
640
+ * const queue = new PollingQueueClient({ region: "iad1" });
641
+ * export const { send, receive } = queue;
642
+ * ```
643
+ */
644
+ declare class PollingQueueClient {
645
+ constructor(options: PollingQueueClientOptions);
646
+ /**
647
+ * Send a message to a topic.
648
+ *
649
+ * This is an arrow function property so it can be destructured:
650
+ * ```typescript
651
+ * const { send } = new PollingQueueClient({ region: "iad1" });
652
+ * await send("my-topic", payload);
653
+ * ```
654
+ *
655
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
656
+ * @param payload - The data to send (serialized via the configured transport)
657
+ * @param options - Optional send options (idempotencyKey, retentionSeconds, delaySeconds, headers)
658
+ * @returns `{ messageId }` — `messageId` is `null` when the server accepted
659
+ * the message for deferred processing (no ID available yet)
660
+ */
661
+ send: <T = unknown>(topicName: string, payload: T, options?: SendOptions) => Promise<SendResult>;
662
+ /**
663
+ * Receive and process messages from a topic.
664
+ *
665
+ * Each message is automatically locked, kept alive via periodic visibility
666
+ * extensions during processing, and acknowledged upon successful handler completion.
667
+ * The handler is not called when the queue is empty — check `result.ok` instead.
668
+ *
669
+ * This is an arrow function property so it can be destructured:
670
+ * ```typescript
671
+ * const { receive } = new PollingQueueClient({ region: "iad1" });
672
+ * const result = await receive("my-topic", "my-group", handler);
673
+ * if (!result.ok) console.log(result.reason);
674
+ * ```
675
+ *
676
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
677
+ * @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
678
+ * @param handler - Function to process each message payload and metadata.
679
+ * Not called when the queue is empty.
680
+ * @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
681
+ * @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
682
+ */
683
+ receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
684
+ }
685
+
686
+ type CallbackRequestInput = Request | {
687
+ request: Request;
688
+ };
689
+ /**
690
+ * Send a message to a topic using the default auto-configured client.
691
+ *
692
+ * The default client auto-detects the region from `VERCEL_REGION`,
693
+ * falling back to `"iad1"` with a console warning on first use.
694
+ *
695
+ * This is an arrow function–free alternative to destructuring from a
696
+ * {@link QueueClient} instance — import and use directly:
697
+ * ```typescript
698
+ * import { send } from "@vercel/queue";
699
+ * await send("my-topic", { hello: "world" });
700
+ * ```
701
+ *
702
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
703
+ * @param payload - The data to send (serialized via JsonTransport)
704
+ * @param options - Optional send options. Pass `region` to route to a specific region.
705
+ * @returns `{ messageId }` — `messageId` is `null` when the server accepted
706
+ * the message for deferred processing
707
+ */
708
+ declare function send<T = unknown>(topicName: string, payload: T, options?: SendOptions & {
709
+ region?: VercelRegion;
710
+ }): Promise<SendResult>;
711
+ /**
712
+ * Create a Web API route handler for processing queue callback messages
713
+ * using the default auto-configured client.
714
+ *
715
+ * The default client auto-detects the region from `VERCEL_REGION`,
716
+ * falling back to `"iad1"` with a console warning on first use.
717
+ * The callback region is determined automatically from the incoming
718
+ * `ce-vqsregion` header in the v2beta event — no manual configuration needed.
719
+ *
720
+ * This is an arrow function–free alternative to destructuring from a
721
+ * {@link QueueClient} instance — import and use directly:
722
+ * ```typescript
723
+ * import { handleCallback } from "@vercel/queue";
724
+ * export const POST = handleCallback(async (message, metadata) => {
725
+ * console.log("Processing:", message);
726
+ * });
727
+ * ```
728
+ *
729
+ * @param handler - Function to process the message payload and metadata
730
+ * @param options - Optional configuration (visibilityTimeoutSeconds, retry)
731
+ * @returns A route handler that accepts either `Request` or `{ request: Request }`
732
+ */
733
+ declare function handleCallback<T = unknown>(handler: MessageHandler<T>, options?: {
734
+ visibilityTimeoutSeconds?: number;
735
+ retry?: RetryHandler;
736
+ }): (requestOrEvent: CallbackRequestInput) => Promise<Response>;
597
737
 
598
738
  /**
599
739
  * Core queue callback utilities for handling incoming webhook payloads
@@ -668,4 +808,4 @@ declare function parseRawCallback(body: unknown, headers: Record<string, string
668
808
  */
669
809
  declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
670
810
 
671
- 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, 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 };
811
+ 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
@@ -37,12 +37,11 @@ interface Transport<T = unknown> {
37
37
  * @example
38
38
  * ```typescript
39
39
  * // Default (JsonTransport is used automatically)
40
- * const queue = new QueueClient({ region: process.env.QUEUE_REGION! });
40
+ * const queue = new QueueClient();
41
41
  * await queue.send("topic", { data: "example" });
42
42
  *
43
43
  * // With custom serialization
44
44
  * const queue = new QueueClient({
45
- * region: process.env.QUEUE_REGION!,
46
45
  * transport: new JsonTransport({
47
46
  * replacer: (key, value) => key === "password" ? undefined : value,
48
47
  * reviver: (key, value) => key === "date" ? new Date(value) : value,
@@ -75,7 +74,7 @@ declare class JsonTransport<T = unknown> implements Transport<T> {
75
74
  *
76
75
  * @example
77
76
  * ```typescript
78
- * const queue = new QueueClient({ region: "iad1", transport: new BufferTransport() });
77
+ * const queue = new QueueClient({ transport: new BufferTransport() });
79
78
  * await queue.send("binary-topic", myBuffer);
80
79
  * ```
81
80
  */
@@ -95,13 +94,13 @@ declare class BufferTransport implements Transport<Buffer> {
95
94
  *
96
95
  * @example
97
96
  * ```typescript
98
- * const queue = new QueueClient({ region: "iad1", transport: new StreamTransport() });
99
- *
100
97
  * // Sending a stream
98
+ * const queue = new QueueClient({ transport: new StreamTransport() });
101
99
  * await queue.send("large-file", myReadableStream);
102
100
  *
103
101
  * // Receiving - cleanup handled automatically
104
- * await queue.receive("large-file", "processor", async (stream, meta) => {
102
+ * const poller = new PollingQueueClient({ region: "iad1", transport: new StreamTransport() });
103
+ * await poller.receive("large-file", "processor", async (stream, meta) => {
105
104
  * const reader = stream.getReader();
106
105
  * // Process chunks...
107
106
  * });
@@ -155,15 +154,17 @@ interface QueueClientOptions {
155
154
  * Requests are sent to the regional endpoint resolved by
156
155
  * {@link BaseUrlResolver} (default: `https://${region}.vercel-queue.com`).
157
156
  *
158
- * Use a `QUEUE_REGION` env var set to `${VERCEL_REGION}` in production
159
- * and a fixed region (e.g. `"iad1"`) in development.
157
+ * When omitted, the region is auto-detected from the `VERCEL_REGION`
158
+ * environment variable (set automatically on Vercel). If not available,
159
+ * defaults to `"iad1"` with a console warning.
160
160
  *
161
161
  * @example
162
162
  * ```ts
163
- * new QueueClient({ region: process.env.QUEUE_REGION! })
163
+ * new QueueClient() // auto-detect, falls back to "iad1"
164
+ * new QueueClient({ region: "iad1" }) // explicit
164
165
  * ```
165
166
  */
166
- region: VercelRegion;
167
+ region?: VercelRegion;
167
168
  /**
168
169
  * Custom resolver that maps a region code to a base {@link URL}.
169
170
  *
@@ -205,6 +206,28 @@ interface QueueClientOptions {
205
206
  */
206
207
  transport?: Transport;
207
208
  }
209
+ /**
210
+ * Options for creating a {@link PollingQueueClient}.
211
+ *
212
+ * Identical to {@link QueueClientOptions} except `region` is **required**
213
+ * because messages can only be received from the region they were sent to.
214
+ * Using a fixed region (e.g. `"iad1"`) ensures that `send` and `receive`
215
+ * target the same endpoint.
216
+ */
217
+ interface PollingQueueClientOptions extends QueueClientOptions {
218
+ /**
219
+ * Vercel region code for API routing — **required** for polling.
220
+ *
221
+ * Messages can only be received from the region they were sent to.
222
+ * Use a fixed region (e.g. `"iad1"`) for both sending and receiving.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * new PollingQueueClient({ region: "iad1" })
227
+ * ```
228
+ */
229
+ region: VercelRegion;
230
+ }
208
231
  /**
209
232
  * Options for sending messages.
210
233
  */
@@ -496,14 +519,40 @@ declare class ConsumerRegistryNotConfiguredError extends Error {
496
519
  constructor(message?: string);
497
520
  }
498
521
 
522
+ type CallbackRequestInput$1 = Request | {
523
+ request: Request;
524
+ };
525
+ /**
526
+ * Queue client for push-based (callback) workflows.
527
+ *
528
+ * Use this client when Vercel delivers messages to your route handlers.
529
+ * Provides {@link send}, {@link handleCallback}, and {@link handleNodeCallback}.
530
+ *
531
+ * Region is resolved automatically:
532
+ * 1. Explicit `region` option (highest priority)
533
+ * 2. `VERCEL_REGION` environment variable (set automatically on Vercel)
534
+ * 3. Falls back to `"iad1"` with a console warning
535
+ *
536
+ * The constructor never throws — `new QueueClient()` always works.
537
+ *
538
+ * For manual polling workflows, use {@link PollingQueueClient} instead.
539
+ *
540
+ * @example
541
+ * ```typescript
542
+ * import { QueueClient } from "@vercel/queue";
543
+ *
544
+ * const queue = new QueueClient();
545
+ * export const { send, handleCallback, handleNodeCallback } = queue;
546
+ * ```
547
+ */
499
548
  declare class QueueClient {
500
- constructor(options: QueueClientOptions);
549
+ constructor(options?: QueueClientOptions);
501
550
  /**
502
551
  * Send a message to a topic.
503
552
  *
504
553
  * This is an arrow function property so it can be destructured:
505
554
  * ```typescript
506
- * const { send } = new QueueClient({ region: process.env.QUEUE_REGION! });
555
+ * const { send } = new QueueClient();
507
556
  * await send("my-topic", payload);
508
557
  * ```
509
558
  *
@@ -514,28 +563,6 @@ declare class QueueClient {
514
563
  * the message for deferred processing (no ID available yet)
515
564
  */
516
565
  send: <T = unknown>(topicName: string, payload: T, options?: SendOptions) => Promise<SendResult>;
517
- /**
518
- * Receive and process messages from a topic.
519
- *
520
- * Each message is automatically locked, kept alive via periodic visibility
521
- * extensions during processing, and acknowledged upon successful handler completion.
522
- * The handler is not called when the queue is empty — check `result.ok` instead.
523
- *
524
- * This is an arrow function property so it can be destructured:
525
- * ```typescript
526
- * const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });
527
- * const result = await receive("my-topic", "my-group", handler);
528
- * if (!result.ok) console.log(result.reason);
529
- * ```
530
- *
531
- * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
532
- * @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
533
- * @param handler - Function to process each message payload and metadata.
534
- * Not called when the queue is empty.
535
- * @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
536
- * @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
537
- */
538
- receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
539
566
  /**
540
567
  * Create a Web API route handler for processing queue callback messages.
541
568
  *
@@ -544,7 +571,7 @@ declare class QueueClient {
544
571
  *
545
572
  * This is an arrow function property so it can be destructured:
546
573
  * ```typescript
547
- * const { handleCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });
574
+ * const { handleCallback } = new QueueClient();
548
575
  * export const POST = handleCallback(handler);
549
576
  * ```
550
577
  *
@@ -553,12 +580,12 @@ declare class QueueClient {
553
580
  * @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)
554
581
  * @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to
555
582
  * reschedule the message for redelivery after N seconds.
556
- * @returns A `(request: Request) => Promise<Response>` route handler
583
+ * @returns A route handler that accepts either `Request` or `{ request: Request }`
557
584
  */
558
585
  handleCallback: <T = unknown>(handler: MessageHandler<T>, options?: {
559
586
  visibilityTimeoutSeconds?: number;
560
587
  retry?: RetryHandler;
561
- }) => ((request: Request) => Promise<Response>);
588
+ }) => ((requestOrEvent: CallbackRequestInput$1) => Promise<Response>);
562
589
  /**
563
590
  * Create a Connect-style route handler for processing queue callback messages.
564
591
  * For use on Vercel — Vercel invokes this route when messages are available.
@@ -568,7 +595,7 @@ declare class QueueClient {
568
595
  *
569
596
  * This is an arrow function property so it can be destructured:
570
597
  * ```typescript
571
- * const { handleNodeCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });
598
+ * const { handleNodeCallback } = new QueueClient();
572
599
  * app.post("/api/queue", handleNodeCallback(handler));
573
600
  * ```
574
601
  *
@@ -594,6 +621,119 @@ declare class QueueClient {
594
621
  end(): void;
595
622
  }) => Promise<void>);
596
623
  }
624
+ /**
625
+ * Queue client for poll-based (manual receive) workflows.
626
+ *
627
+ * Use this client when you manually poll for messages with {@link receive}.
628
+ * Also provides {@link send} for publishing messages.
629
+ *
630
+ * Region is **required** because messages can only be received from the
631
+ * region they were sent to. Use a fixed region (e.g. `"iad1"`) for both
632
+ * sending and receiving.
633
+ *
634
+ * For push-based (callback) workflows on Vercel, use {@link QueueClient} instead.
635
+ *
636
+ * @example
637
+ * ```typescript
638
+ * import { PollingQueueClient } from "@vercel/queue";
639
+ *
640
+ * const queue = new PollingQueueClient({ region: "iad1" });
641
+ * export const { send, receive } = queue;
642
+ * ```
643
+ */
644
+ declare class PollingQueueClient {
645
+ constructor(options: PollingQueueClientOptions);
646
+ /**
647
+ * Send a message to a topic.
648
+ *
649
+ * This is an arrow function property so it can be destructured:
650
+ * ```typescript
651
+ * const { send } = new PollingQueueClient({ region: "iad1" });
652
+ * await send("my-topic", payload);
653
+ * ```
654
+ *
655
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
656
+ * @param payload - The data to send (serialized via the configured transport)
657
+ * @param options - Optional send options (idempotencyKey, retentionSeconds, delaySeconds, headers)
658
+ * @returns `{ messageId }` — `messageId` is `null` when the server accepted
659
+ * the message for deferred processing (no ID available yet)
660
+ */
661
+ send: <T = unknown>(topicName: string, payload: T, options?: SendOptions) => Promise<SendResult>;
662
+ /**
663
+ * Receive and process messages from a topic.
664
+ *
665
+ * Each message is automatically locked, kept alive via periodic visibility
666
+ * extensions during processing, and acknowledged upon successful handler completion.
667
+ * The handler is not called when the queue is empty — check `result.ok` instead.
668
+ *
669
+ * This is an arrow function property so it can be destructured:
670
+ * ```typescript
671
+ * const { receive } = new PollingQueueClient({ region: "iad1" });
672
+ * const result = await receive("my-topic", "my-group", handler);
673
+ * if (!result.ok) console.log(result.reason);
674
+ * ```
675
+ *
676
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
677
+ * @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
678
+ * @param handler - Function to process each message payload and metadata.
679
+ * Not called when the queue is empty.
680
+ * @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
681
+ * @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
682
+ */
683
+ receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
684
+ }
685
+
686
+ type CallbackRequestInput = Request | {
687
+ request: Request;
688
+ };
689
+ /**
690
+ * Send a message to a topic using the default auto-configured client.
691
+ *
692
+ * The default client auto-detects the region from `VERCEL_REGION`,
693
+ * falling back to `"iad1"` with a console warning on first use.
694
+ *
695
+ * This is an arrow function–free alternative to destructuring from a
696
+ * {@link QueueClient} instance — import and use directly:
697
+ * ```typescript
698
+ * import { send } from "@vercel/queue";
699
+ * await send("my-topic", { hello: "world" });
700
+ * ```
701
+ *
702
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
703
+ * @param payload - The data to send (serialized via JsonTransport)
704
+ * @param options - Optional send options. Pass `region` to route to a specific region.
705
+ * @returns `{ messageId }` — `messageId` is `null` when the server accepted
706
+ * the message for deferred processing
707
+ */
708
+ declare function send<T = unknown>(topicName: string, payload: T, options?: SendOptions & {
709
+ region?: VercelRegion;
710
+ }): Promise<SendResult>;
711
+ /**
712
+ * Create a Web API route handler for processing queue callback messages
713
+ * using the default auto-configured client.
714
+ *
715
+ * The default client auto-detects the region from `VERCEL_REGION`,
716
+ * falling back to `"iad1"` with a console warning on first use.
717
+ * The callback region is determined automatically from the incoming
718
+ * `ce-vqsregion` header in the v2beta event — no manual configuration needed.
719
+ *
720
+ * This is an arrow function–free alternative to destructuring from a
721
+ * {@link QueueClient} instance — import and use directly:
722
+ * ```typescript
723
+ * import { handleCallback } from "@vercel/queue";
724
+ * export const POST = handleCallback(async (message, metadata) => {
725
+ * console.log("Processing:", message);
726
+ * });
727
+ * ```
728
+ *
729
+ * @param handler - Function to process the message payload and metadata
730
+ * @param options - Optional configuration (visibilityTimeoutSeconds, retry)
731
+ * @returns A route handler that accepts either `Request` or `{ request: Request }`
732
+ */
733
+ declare function handleCallback<T = unknown>(handler: MessageHandler<T>, options?: {
734
+ visibilityTimeoutSeconds?: number;
735
+ retry?: RetryHandler;
736
+ }): (requestOrEvent: CallbackRequestInput) => Promise<Response>;
597
737
 
598
738
  /**
599
739
  * Core queue callback utilities for handling incoming webhook payloads
@@ -668,4 +808,4 @@ declare function parseRawCallback(body: unknown, headers: Record<string, string
668
808
  */
669
809
  declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
670
810
 
671
- 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, 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 };
811
+ 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 };