@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/README.md CHANGED
@@ -4,9 +4,9 @@ A TypeScript client library for interacting with the Vercel Queue Service API, d
4
4
 
5
5
  ## Features
6
6
 
7
- - **Simple API**: `send` and `receive` are all you need
7
+ - **Simple API**: `send` and `handleCallback` are all you need for push-based workflows
8
8
  - **Automatic Triggering on Vercel**: Vercel invokes your route handlers when messages are ready
9
- - **Works Anywhere**: `send` and `receive` work in any Node.js environment
9
+ - **Works Anywhere**: `send` and `receive` work in any Node.js environment, including self-hosted and non-Vercel platforms
10
10
  - **Type Safety**: Full TypeScript generics support
11
11
  - **Customizable Serialization**: Built-in JSON, Buffer, and Stream transports
12
12
  - **Local Dev Mode**: Messages sent locally trigger your handlers automatically
@@ -19,48 +19,36 @@ npm install @vercel/queue
19
19
 
20
20
  ## Quick Start
21
21
 
22
- Set up your region via environment variables. If your framework supports `.env` files (Next.js, Vite, Nuxt, etc.):
22
+ **1. Link your Vercel project and pull credentials:**
23
23
 
24
- ```bash
25
- # .env.production (on Vercel, inherits the platform's region)
26
- QUEUE_REGION=${VERCEL_REGION}
27
-
28
- # .env.development (fixed region for local dev — iad1 is recommended)
29
- QUEUE_REGION=iad1
30
- ```
31
-
32
- Otherwise, set `QUEUE_REGION` in your environment directly (e.g. via your hosting provider's dashboard or a `dotenv` setup).
33
-
34
- Create a shared queue client:
35
-
36
- ```typescript
37
- // lib/queue.ts
38
- 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:
39
25
 
40
- const queue = new QueueClient({ region: process.env.QUEUE_REGION! });
41
- export const { send, receive, handleCallback, handleNodeCallback } = queue;
26
+ ```bash
27
+ npm i -g vercel
28
+ vc link # if you haven't already
29
+ vc env pull
42
30
  ```
43
31
 
44
- Send a message anywhere in your app:
32
+ **2. Send a message anywhere in your app:**
45
33
 
46
34
  ```typescript
47
- import { send } from "@/lib/queue";
35
+ import { send } from "@vercel/queue";
48
36
 
49
37
  await send("my-topic", { message: "Hello world" });
50
38
  ```
51
39
 
52
- Handle incoming messages with a route handler:
40
+ **3. Handle incoming messages with a route handler:**
53
41
 
54
42
  ```typescript
55
43
  // app/api/queue/my-topic/route.ts
56
- import { handleCallback } from "@/lib/queue";
44
+ import { handleCallback } from "@vercel/queue";
57
45
 
58
46
  export const POST = handleCallback(async (message, metadata) => {
59
47
  console.log("Processing:", message);
60
48
  });
61
49
  ```
62
50
 
63
- Configure your `vercel.json`:
51
+ **4. Configure `vercel.json`:**
64
52
 
65
53
  ```json
66
54
  {
@@ -72,28 +60,26 @@ Configure your `vercel.json`:
72
60
  }
73
61
  ```
74
62
 
75
- ### Project Setup
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`.
76
64
 
77
- For local development, link your Vercel project:
65
+ To target a specific region for sending, pass the `region` option:
78
66
 
79
- ```bash
80
- npm i -g vercel
81
- vc link
82
- vc env pull
67
+ ```typescript
68
+ await send("my-topic", payload, { region: "sfo1" });
83
69
  ```
84
70
 
85
71
  ## Local Development
86
72
 
87
- **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.
73
+ **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 exact same lifecycle (receive, visibility extension, ack) as in production.
74
+
75
+ 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`.
88
76
 
89
- > **Note:** Local dev mode is enabled when `NODE_ENV=development`. Most frameworks (Next.js, etc.) set this automatically during `npm run dev`.
77
+ > **Note:** Local dev mode is enabled when `NODE_ENV=development`. Most frameworks set this automatically during `npm run dev`.
90
78
 
91
79
  ## Publishing Messages
92
80
 
93
81
  ```typescript
94
- import { QueueClient } from "@vercel/queue";
95
-
96
- const { send } = new QueueClient({ region: process.env.QUEUE_REGION! });
82
+ import { send } from "@vercel/queue";
97
83
 
98
84
  // Simple send
99
85
  await send("my-topic", { message: "Hello world" });
@@ -106,6 +92,7 @@ await send(
106
92
  idempotencyKey: "unique-key", // Prevent duplicate messages
107
93
  retentionSeconds: 3600, // 1 hour TTL (default: 24h)
108
94
  delaySeconds: 60, // Delay delivery by 1 minute
95
+ region: "sfo1", // Optional — target a specific region
109
96
  },
110
97
  );
111
98
  ```
@@ -114,7 +101,7 @@ Example usage in an API route:
114
101
 
115
102
  ```typescript
116
103
  // app/api/send-message/route.ts
117
- import { send } from "@/lib/queue";
104
+ import { send } from "@vercel/queue";
118
105
 
119
106
  export async function POST(request: Request) {
120
107
  const body = await request.json();
@@ -139,7 +126,7 @@ Returns `(Request) => Promise<Response>`. For frameworks that export Web API rou
139
126
 
140
127
  ```typescript
141
128
  // app/api/queue/my-topic/route.ts
142
- import { handleCallback } from "@/lib/queue";
129
+ import { handleCallback } from "@vercel/queue";
143
130
 
144
131
  export const POST = handleCallback(async (message, metadata) => {
145
132
  // metadata: { messageId, deliveryCount, createdAt, expiresAt?, topicName, consumerGroup, region }
@@ -148,11 +135,37 @@ export const POST = handleCallback(async (message, metadata) => {
148
135
  });
149
136
  ```
150
137
 
138
+ **Nuxt:**
139
+
140
+ ```typescript
141
+ // server/api/queue.ts
142
+ import { handleCallback } from "@vercel/queue";
143
+
144
+ const handler = handleCallback(async (message, metadata) => {
145
+ await processMessage(message);
146
+ });
147
+
148
+ export default defineEventHandler(async (event) => {
149
+ return handler(toWebRequest(event));
150
+ });
151
+ ```
152
+
153
+ **SvelteKit:**
154
+
155
+ ```typescript
156
+ // src/routes/api/queue/+server.ts
157
+ import { handleCallback } from "@vercel/queue";
158
+
159
+ export const POST = handleCallback(async (message, metadata) => {
160
+ await processMessage(message);
161
+ });
162
+ ```
163
+
151
164
  **Hono:**
152
165
 
153
166
  ```typescript
154
167
  import { Hono } from "hono";
155
- import { handleCallback } from "@/lib/queue";
168
+ import { handleCallback } from "@vercel/queue";
156
169
 
157
170
  const app = new Hono();
158
171
  app.post(
@@ -166,7 +179,26 @@ export default app;
166
179
 
167
180
  #### Connect-style — `handleNodeCallback`
168
181
 
169
- Returns `(req, res) => Promise<void>`. For frameworks that export Connect-style handlers (Express, Next.js Pages Router, etc.).
182
+ Returns `(req, res) => Promise<void>`. For frameworks that export Connect-style handlers (Vercel Node.js functions, Express, Next.js Pages Router, etc.). Requires a `QueueClient` instance:
183
+
184
+ ```typescript
185
+ // lib/queue.ts
186
+ import { QueueClient } from "@vercel/queue";
187
+
188
+ const queue = new QueueClient();
189
+ export const { handleNodeCallback } = queue;
190
+ ```
191
+
192
+ **Vercel Node.js Functions (plain `api/` directory):**
193
+
194
+ ```typescript
195
+ // api/queue.ts
196
+ import { handleNodeCallback } from "./lib/queue";
197
+
198
+ export default handleNodeCallback(async (message, metadata) => {
199
+ await processMessage(message);
200
+ });
201
+ ```
170
202
 
171
203
  **Next.js Pages Router:**
172
204
 
@@ -240,6 +272,8 @@ When a handler throws, the message is not acknowledged and becomes available for
240
272
  For finer control over retry timing, pass a `retry` option:
241
273
 
242
274
  ```typescript
275
+ import { handleCallback } from "@vercel/queue";
276
+
243
277
  export const POST = handleCallback(
244
278
  async (message, metadata) => {
245
279
  await processMessage(message);
@@ -258,6 +292,8 @@ When `retry` returns `{ afterSeconds: N }`, the message is rescheduled for redel
258
292
  **Exponential backoff** uses `metadata.deliveryCount` (starts at 1, increments each delivery):
259
293
 
260
294
  ```typescript
295
+ import { handleCallback } from "@vercel/queue";
296
+
261
297
  export const POST = handleCallback(
262
298
  async (message, metadata) => {
263
299
  await processMessage(message);
@@ -275,6 +311,8 @@ export const POST = handleCallback(
275
311
  **Conditional retry** — only retry transient errors:
276
312
 
277
313
  ```typescript
314
+ import { handleCallback } from "@vercel/queue";
315
+
278
316
  export const POST = handleCallback(
279
317
  async (message, metadata) => {
280
318
  await processMessage(message);
@@ -292,6 +330,8 @@ export const POST = handleCallback(
292
330
  **Acknowledging poison messages** — stop retrying messages that can never succeed:
293
331
 
294
332
  ```typescript
333
+ import { handleCallback } from "@vercel/queue";
334
+
295
335
  export const POST = handleCallback(
296
336
  async (message, metadata) => {
297
337
  await processMessage(message);
@@ -310,40 +350,56 @@ The `retry` option is available on `handleCallback`, `handleNodeCallback`, and `
310
350
 
311
351
  ## Custom Client Configuration
312
352
 
313
- All configuration lives on the `QueueClient`:
353
+ 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.
354
+
355
+ ### QueueClient (push mode)
356
+
357
+ For push-based workflows where Vercel delivers messages to your route handlers:
314
358
 
315
359
  ```typescript
316
360
  import { QueueClient, BufferTransport } from "@vercel/queue";
317
361
 
318
362
  const queue = new QueueClient({
319
- region: process.env.QUEUE_REGION!, // Requiredsee Quick Start for env setup
363
+ region: "iad1", // Optionalauto-detected from VERCEL_REGION, falls back to "iad1"
320
364
  token: "my-token", // Auth token (default: OIDC auto-detection)
321
365
  transport: new BufferTransport(), // Serialization (default: JsonTransport)
322
366
  headers: { "X-Custom": "header" }, // Custom headers on all requests
323
367
  deploymentId: null, // null = unpinned, omit = auto from env, or explicit string
324
368
  });
325
369
 
326
- // Use directly
327
- await queue.send("my-topic", myBuffer);
370
+ export const { send, handleCallback, handleNodeCallback } = queue;
371
+ ```
372
+
373
+ ### PollingQueueClient (poll mode)
328
374
 
329
- // Or destructure
330
- export const { send, receive, handleCallback, handleNodeCallback } = queue;
375
+ For manual polling workflows where you call `receive` to poll for messages. Works anywhere — on Vercel, self-hosted, or any Node.js environment:
376
+
377
+ ```typescript
378
+ import { PollingQueueClient, BufferTransport } from "@vercel/queue";
379
+
380
+ const queue = new PollingQueueClient({
381
+ region: "iad1", // Required — messages must be received from a fixed region
382
+ token: "my-token",
383
+ transport: new BufferTransport(),
384
+ headers: { "X-Custom": "header" },
385
+ deploymentId: null,
386
+ });
387
+
388
+ export const { send, receive } = queue;
331
389
  ```
332
390
 
333
- The client sends requests to `https://${region}.vercel-queue.com`. When `handleCallback` receives a message, it reads the `ce-vqsregion` header and routes follow-up API calls to the correct regional endpoint.
391
+ Both clients send requests to `https://${region}.vercel-queue.com`. When `handleCallback` receives a message, it reads the `ce-vqsregion` header and routes follow-up API calls to the correct regional endpoint.
334
392
 
335
393
  To customize the URL scheme, provide a `resolveBaseUrl` that returns a `URL`:
336
394
 
337
395
  ```typescript
338
396
  // Custom domain
339
397
  const queue = new QueueClient({
340
- region: process.env.QUEUE_REGION!,
341
398
  resolveBaseUrl: (region) => new URL(`https://${region}.my-proxy.example`),
342
399
  });
343
400
 
344
401
  // Custom domain with a base path (e.g. reverse proxy prefix)
345
402
  const queue = new QueueClient({
346
- region: process.env.QUEUE_REGION!,
347
403
  resolveBaseUrl: (region) =>
348
404
  new URL(`https://my-proxy.example/queues/${region}`),
349
405
  // → requests go to https://my-proxy.example/queues/<region>/api/v3/…
@@ -372,7 +428,6 @@ import {
372
428
 
373
429
  // JSON with custom serialization
374
430
  const queue = new QueueClient({
375
- region: process.env.QUEUE_REGION!,
376
431
  transport: new JsonTransport({
377
432
  replacer: (key, value) => (key === "password" ? undefined : value),
378
433
  reviver: (key, value) => (key === "date" ? new Date(value) : value),
@@ -381,14 +436,12 @@ const queue = new QueueClient({
381
436
 
382
437
  // Binary data
383
438
  const binQueue = new QueueClient({
384
- region: process.env.QUEUE_REGION!,
385
439
  transport: new BufferTransport(),
386
440
  });
387
441
  await binQueue.send("binary-topic", myBuffer);
388
442
 
389
443
  // Streaming for large payloads
390
444
  const streamQueue = new QueueClient({
391
- region: process.env.QUEUE_REGION!,
392
445
  transport: new StreamTransport(),
393
446
  });
394
447
  await streamQueue.send("large-file", myReadableStream);
@@ -396,30 +449,25 @@ await streamQueue.send("large-file", myReadableStream);
396
449
 
397
450
  ## Manual Receive
398
451
 
399
- Use `receive` to pull and process messages directly. This is an advanced alternative to `handleCallback` that works in any Node.js environment, both on and off Vercel.
452
+ Use `PollingQueueClient` to poll for and process messages directly. This is an advanced alternative to `handleCallback` that works in any Node.js environment, both on and off Vercel.
400
453
 
401
454
  ### Region considerations
402
455
 
403
- Messages can only be received from the region they were sent to. When using `receive`, use a **fixed region** (e.g. `"iad1"`) for both sending and receiving — do not use `VERCEL_REGION` (or `QUEUE_REGION=${VERCEL_REGION}`), because Vercel may route requests to different regions due to failover or load balancing, distributing your messages across regions unpredictably.
404
-
405
- ```bash
406
- # .env.production — fixed region for manual receive workflows
407
- QUEUE_REGION=iad1
408
-
409
- # .env.development
410
- QUEUE_REGION=iad1
411
- ```
456
+ Messages can only be received from the region they were sent to. When using `receive`, use a **fixed region** (e.g. `"iad1"`) for both sending and receiving — do not use `VERCEL_REGION`, because Vercel may route requests to different regions due to failover or load balancing, distributing your messages across regions unpredictably.
412
457
 
413
458
  A single region is still highly available — Vercel deploys across 3+ availability zones within each region. If you need multi-region availability, you are responsible for designing your own HA strategy (e.g. sending to multiple regions and receiving from each).
414
459
 
415
- For most use cases on Vercel, `handleCallback` is the recommended approach — the platform handles region routing automatically and the SDK routes follow-up calls to the correct region via the `ce-vqsregion` header.
460
+ For most use cases on Vercel, `handleCallback` via `QueueClient` is the recommended approach — the platform handles region routing automatically and the SDK routes follow-up calls to the correct region via the `ce-vqsregion` header.
416
461
 
417
462
  ### Usage
418
463
 
419
464
  ```typescript
420
- import { QueueClient } from "@vercel/queue";
465
+ import { PollingQueueClient } from "@vercel/queue";
421
466
 
422
- const { receive } = new QueueClient({ region: "iad1" });
467
+ const { send, receive } = new PollingQueueClient({ region: "iad1" });
468
+
469
+ // Send a message
470
+ await send("my-topic", { message: "Hello world" });
423
471
 
424
472
  // Process next available message
425
473
  const result = await receive(
@@ -451,8 +499,8 @@ import {
451
499
  ForbiddenError,
452
500
  InternalServerError,
453
501
  UnauthorizedError,
502
+ send,
454
503
  } from "@vercel/queue";
455
- import { send } from "@/lib/queue";
456
504
 
457
505
  try {
458
506
  await send("my-topic", payload);
@@ -492,12 +540,11 @@ All error types:
492
540
 
493
541
  ## Environment Variables
494
542
 
495
- | Variable | Description | Default |
496
- | ---------------------- | ----------------------------------------------- | ------- |
497
- | `QUEUE_REGION` | Region code for the queue client (user-defined) | - |
498
- | `VERCEL_REGION` | Current region (auto-set by Vercel) | - |
499
- | `VERCEL_QUEUE_DEBUG` | Enable debug logging (`1` or `true`) | - |
500
- | `VERCEL_DEPLOYMENT_ID` | Deployment ID (auto-set by Vercel) | - |
543
+ | Variable | Description | Default |
544
+ | ---------------------- | ------------------------------------ | ------- |
545
+ | `VERCEL_REGION` | Current region (auto-set by Vercel) | - |
546
+ | `VERCEL_QUEUE_DEBUG` | Enable debug logging (`1` or `true`) | - |
547
+ | `VERCEL_DEPLOYMENT_ID` | Deployment ID (auto-set by Vercel) | - |
501
548
 
502
549
  ## Service Limits & Constraints
503
550
 
@@ -556,13 +603,55 @@ All error types:
556
603
 
557
604
  ## API Reference
558
605
 
606
+ ### Top-level `send(topicName, payload, options?)`
607
+
608
+ 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.
609
+
610
+ ```typescript
611
+ import { send } from "@vercel/queue";
612
+
613
+ const { messageId } = await send("my-topic", payload, {
614
+ idempotencyKey: "unique-key", // Dedup window: min(retention, 24h)
615
+ retentionSeconds: 3600, // Message TTL (default: 86400)
616
+ delaySeconds: 60, // Delay before visible (default: 0)
617
+ headers: { "X-Custom": "val" }, // Custom headers
618
+ region: "sfo1", // Optional — target a specific region
619
+ });
620
+ ```
621
+
622
+ Returns `{ messageId: string | null }`. `messageId` is `null` when the server accepted the message for deferred processing (e.g. during a server-side outage).
623
+
624
+ ### Top-level `handleCallback(handler, options?)`
625
+
626
+ The simplest way to handle incoming queue messages. Uses the same auto-configured default client as `send`.
627
+
628
+ ```typescript
629
+ import { handleCallback } from "@vercel/queue";
630
+
631
+ export const POST = handleCallback(
632
+ async (message, metadata) => {
633
+ await processMessage(message);
634
+ },
635
+ {
636
+ visibilityTimeoutSeconds: 300, // Lock duration (default: 300)
637
+ retry: (error, metadata) => {
638
+ // Optional: return { afterSeconds: N } to reschedule, { acknowledge: true } to ack, or undefined to propagate
639
+ },
640
+ },
641
+ );
642
+ ```
643
+
644
+ 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.
645
+
559
646
  ### `QueueClient`
560
647
 
648
+ 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.
649
+
561
650
  ```typescript
562
651
  import { QueueClient } from "@vercel/queue";
563
652
 
564
653
  const queue = new QueueClient({
565
- region: process.env.QUEUE_REGION!, // Requiredsee Quick Start for env setup
654
+ region: "iad1", // Optionalauto-detected from VERCEL_REGION, falls back to "iad1"
566
655
  resolveBaseUrl: (r) => new URL(`https://${r}.vercel-queue.com`), // Default resolver
567
656
  token: "my-token", // Auto-fetched via OIDC if omitted
568
657
  headers: { "X-Custom": "value" },
@@ -571,24 +660,29 @@ const queue = new QueueClient({
571
660
  });
572
661
 
573
662
  // Methods (arrow functions — safe to destructure)
574
- const { send, receive, handleCallback, handleNodeCallback } = queue;
663
+ const { send, handleCallback, handleNodeCallback } = queue;
575
664
  ```
576
665
 
577
- ### `send(topicName, payload, options?)`
666
+ ### `PollingQueueClient`
578
667
 
579
- Returns `{ messageId: string | null }`. `messageId` is `null` when the server accepted the message for deferred processing (e.g. during a server-side outage).
668
+ Poll-based client for manually receiving messages. Works in any Node.js environment, including self-hosted and non-Vercel platforms. Region is required to ensure send and receive target the same endpoint.
580
669
 
581
670
  ```typescript
582
- const { messageId } = await send("my-topic", payload, {
583
- idempotencyKey: "unique-key", // Dedup window: min(retention, 24h)
584
- retentionSeconds: 3600, // Message TTL (default: 86400)
585
- delaySeconds: 60, // Delay before visible (default: 0)
586
- headers: { "X-Custom": "val" }, // Custom headers
671
+ import { PollingQueueClient } from "@vercel/queue";
672
+
673
+ const queue = new PollingQueueClient({
674
+ region: "iad1", // Required use a fixed region for polling
675
+ // ... same options as QueueClient (except region is required)
587
676
  });
677
+
678
+ // Methods (arrow functions — safe to destructure)
679
+ const { send, receive } = queue;
588
680
  ```
589
681
 
590
682
  ### `receive(topicName, consumerGroup, handler, options?)`
591
683
 
684
+ Available on `PollingQueueClient` only.
685
+
592
686
  Returns a discriminated result: `{ ok: true }` on success, or `{ ok: false, reason }` when no message was processed. The handler is never called when the queue is empty.
593
687
 
594
688
  For receive-by-id, operational errors are returned instead of thrown:
@@ -611,29 +705,18 @@ const result = await receive("my-topic", "my-group", handler, {
611
705
  });
612
706
  ```
613
707
 
614
- ### `handleCallback(handler, options?)`
708
+ ### `handleNodeCallback(handler, options?)`
615
709
 
616
- Vercel only. Returns `(request: Request) => Promise<Response>` — for frameworks that export Web API route handlers.
710
+ Available on `QueueClient` only. Vercel only.
617
711
 
618
- ```typescript
619
- export const POST = handleCallback(
620
- async (message, metadata) => {
621
- await processMessage(message);
622
- },
623
- {
624
- visibilityTimeoutSeconds: 300, // Lock duration (default: 300)
625
- retry: (error, metadata) => {
626
- // Optional: return { afterSeconds: N } to reschedule, { acknowledge: true } to ack, or undefined to propagate
627
- },
628
- },
629
- );
630
- ```
712
+ Returns `(req, res) => Promise<void>` — for frameworks that export Connect-style handlers.
631
713
 
632
- ### `handleNodeCallback(handler, options?)`
714
+ ```typescript
715
+ import { QueueClient } from "@vercel/queue";
633
716
 
634
- Vercel only. Returns `(req, res) => Promise<void>` — for frameworks that export Connect-style handlers.
717
+ const queue = new QueueClient();
718
+ const { handleNodeCallback } = queue;
635
719
 
636
- ```typescript
637
720
  // pages/api/queue/my-topic.ts
638
721
  export default handleNodeCallback(
639
722
  async (message, metadata) => {