@vercel/queue 0.0.0-alpha.2 → 0.0.0-alpha.3
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 +156 -96
- package/dist/index.d.mts +55 -5
- package/dist/index.d.ts +55 -5
- package/dist/index.js +70 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
# Vercel Queues
|
|
2
2
|
|
|
3
|
-
A TypeScript client library for interacting with the Vercel Queue Service API
|
|
3
|
+
A TypeScript client library for interacting with the Vercel Queue Service API
|
|
4
|
+
with customizable serialization/deserialization (transport) support, including
|
|
5
|
+
**streaming support** for memory-efficient processing of large payloads.
|
|
4
6
|
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
|
-
- **Generic Payload Support**: Send and receive any type of data with type
|
|
8
|
-
|
|
9
|
-
- **
|
|
9
|
+
- **Generic Payload Support**: Send and receive any type of data with type
|
|
10
|
+
safety
|
|
11
|
+
- **Customizable Serialization**: Use built-in transports (JSON, Buffer, Stream)
|
|
12
|
+
or create your own
|
|
13
|
+
- **Streaming Support**: Handle large payloads without loading them entirely
|
|
14
|
+
into memory
|
|
10
15
|
- **Pub/Sub Pattern**: Topic-based messaging with consumer groups
|
|
11
16
|
- **Type Safety**: Full TypeScript support with generic types
|
|
12
17
|
- **Automatic Retries**: Built-in visibility timeout management
|
|
@@ -19,7 +24,8 @@ npm install @vercel/queue
|
|
|
19
24
|
|
|
20
25
|
## Quick Start
|
|
21
26
|
|
|
22
|
-
For local development, you'll need to pull your Vercel environment variables
|
|
27
|
+
For local development, you'll need to pull your Vercel environment variables
|
|
28
|
+
(including the OIDC token):
|
|
23
29
|
|
|
24
30
|
```bash
|
|
25
31
|
# Install Vercel CLI if you haven't already
|
|
@@ -33,10 +39,10 @@ Publishing and consuming messages on a queue
|
|
|
33
39
|
|
|
34
40
|
```typescript
|
|
35
41
|
// index.ts
|
|
36
|
-
import {
|
|
42
|
+
import { createTopic, JsonTransport, QueueClient } from "@vercel/queue";
|
|
37
43
|
|
|
38
44
|
// Create a client - automatically authenticated using the OIDC token
|
|
39
|
-
const client = QueueClient.fromVercelFunction();
|
|
45
|
+
const client = await QueueClient.fromVercelFunction();
|
|
40
46
|
|
|
41
47
|
// Create a topic with JSON serialization (default)
|
|
42
48
|
const topic = createTopic<{ message: string; timestamp: number }>(
|
|
@@ -79,13 +85,18 @@ dotenv -e .env.local node index.ts
|
|
|
79
85
|
|
|
80
86
|
## Usage with Vercel
|
|
81
87
|
|
|
82
|
-
When deploying on Vercel, rather than having a persistent server subscribed to a
|
|
88
|
+
When deploying on Vercel, rather than having a persistent server subscribed to a
|
|
89
|
+
queue, Vercel can trigger a callback route when a message is ready for
|
|
90
|
+
consumption.
|
|
83
91
|
|
|
84
|
-
To demonstrate using queues on Vercel, let's use a Next.js app. You can use an
|
|
92
|
+
To demonstrate using queues on Vercel, let's use a Next.js app. You can use an
|
|
93
|
+
existing app or create one using
|
|
94
|
+
[create-next-app](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
|
85
95
|
|
|
86
96
|
### TypeScript Configuration
|
|
87
97
|
|
|
88
|
-
Update your `tsconfig.json` to use `"bundler"` module resolution for proper
|
|
98
|
+
Update your `tsconfig.json` to use `"bundler"` module resolution for proper
|
|
99
|
+
package export resolution:
|
|
89
100
|
|
|
90
101
|
```json
|
|
91
102
|
{
|
|
@@ -104,7 +115,7 @@ Create a new server function to publish messages
|
|
|
104
115
|
// app/action.ts
|
|
105
116
|
"use server";
|
|
106
117
|
|
|
107
|
-
import {
|
|
118
|
+
import { createTopic, QueueClient } from "@vercel/queue";
|
|
108
119
|
|
|
109
120
|
export async function publishTestMessage(message: string) {
|
|
110
121
|
// Initialize a queue client
|
|
@@ -121,12 +132,10 @@ export async function publishTestMessage(message: string) {
|
|
|
121
132
|
{ message, timestamp: Date.now() },
|
|
122
133
|
{
|
|
123
134
|
// Provide a callback URL to invoke a consumer when the message is ready to be processed
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
: "http://localhost:3000/api/queue/handle",
|
|
129
|
-
},
|
|
135
|
+
callback: {
|
|
136
|
+
url: process.env.VERCEL_PROJECT_PRODUCTION_URL
|
|
137
|
+
? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}/api/queue/handle`
|
|
138
|
+
: "http://localhost:3000/api/queue/handle",
|
|
130
139
|
},
|
|
131
140
|
},
|
|
132
141
|
);
|
|
@@ -154,65 +163,45 @@ export default function Button() {
|
|
|
154
163
|
|
|
155
164
|
### Consuming the queue
|
|
156
165
|
|
|
157
|
-
Instead of running a persistent server that subscribes to the queue, we use the
|
|
166
|
+
Instead of running a persistent server that subscribes to the queue, we use the
|
|
167
|
+
callback functionality of Vercel queues to consume messages on the fly, when a
|
|
168
|
+
message is ready to be processed.
|
|
169
|
+
|
|
170
|
+
The `handleCallback` helper function simplifies queue callback handling in NextJS:
|
|
158
171
|
|
|
159
172
|
```typescript
|
|
160
173
|
// app/api/queue/handle/route.ts
|
|
161
|
-
import {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
// Handle
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// Create client
|
|
172
|
-
const client = await QueueClient.fromVercelFunction();
|
|
173
|
-
|
|
174
|
-
// Create topic and consumer group from the callback info
|
|
175
|
-
const topic = new Topic(client, queueName);
|
|
176
|
-
const cg = topic.consumerGroup(consumerGroup);
|
|
177
|
-
|
|
178
|
-
// Process the message
|
|
179
|
-
await cg.receiveMessage(messageId, async (message) => {
|
|
180
|
-
const payload = message.payload as { message: string; timestamp: number };
|
|
181
|
-
console.log(
|
|
182
|
-
`Received message "${payload.message}" (Sent at: ${payload.timestamp})`,
|
|
183
|
-
);
|
|
184
|
-
});
|
|
174
|
+
import { handleCallback } from "@vercel/queue";
|
|
175
|
+
|
|
176
|
+
export const POST = handleCallback({
|
|
177
|
+
// Handle messages sent on the "new-users" topic (the consumer
|
|
178
|
+
// group "default" will be used)
|
|
179
|
+
"my-topic": (message, metadata) => {
|
|
180
|
+
console.log(`Received message:`, message, metadata);
|
|
181
|
+
// metadata: { messageId, deliveryCount, timestamp }
|
|
182
|
+
},
|
|
183
|
+
});
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
185
|
+
// Or, specify separate handlers for separate consumer groups
|
|
186
|
+
export const POST = handleCallback({
|
|
187
|
+
// topic: "my-topic"
|
|
188
|
+
"my-topic": {
|
|
189
|
+
// consumer group: "compress"
|
|
190
|
+
compress: (message, metadata) => {
|
|
191
|
+
console.log("Compressing image:", message);
|
|
192
|
+
},
|
|
193
|
+
// consumer group: "resize"
|
|
194
|
+
resize: (message, metadata) => {
|
|
195
|
+
console.log("Resizing image:", message);
|
|
196
|
+
},
|
|
197
|
+
// consumer group: "watermark"
|
|
198
|
+
watermark: (message, metadata) => {
|
|
199
|
+
console.log("Adding watermark:", message);
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
});
|
|
195
203
|
```
|
|
196
204
|
|
|
197
|
-
> ![NOTE]
|
|
198
|
-
> A single webhook handle can be used to process messages across various queues and consumer groups. Use the values of `queueName` and `consumerGroup` from `parseCallbackRequest()` to dynamically handle different code paths:
|
|
199
|
-
>
|
|
200
|
-
> ```typescript
|
|
201
|
-
> if (queueName === "upload-queue") {
|
|
202
|
-
> processImageQueue(consumerGroup, message);
|
|
203
|
-
> }
|
|
204
|
-
> // ...
|
|
205
|
-
> function processImageQueue(consumerGroup, message) {
|
|
206
|
-
> if (consumerGroup === "compress") {
|
|
207
|
-
> // handle image compression
|
|
208
|
-
> }
|
|
209
|
-
> // ...
|
|
210
|
-
> }
|
|
211
|
-
> // ...
|
|
212
|
-
> ```
|
|
213
|
-
>
|
|
214
|
-
> We are building an SDK to make queues and workflow easier to use. Reach out if you're interested.
|
|
215
|
-
|
|
216
205
|
## Key Features
|
|
217
206
|
|
|
218
207
|
### Streaming Support
|
|
@@ -261,12 +250,14 @@ const webhooks = topic.consumerGroup("webhooks");
|
|
|
261
250
|
## Architecture
|
|
262
251
|
|
|
263
252
|
- **Topics**: Named message channels with configurable serialization
|
|
264
|
-
- **Consumer Groups**: Named groups of consumers that process messages in
|
|
253
|
+
- **Consumer Groups**: Named groups of consumers that process messages in
|
|
254
|
+
parallel
|
|
265
255
|
- `subscribe()`: Continuously process messages with automatic polling
|
|
266
256
|
- `receiveMessage()`: Process a specific message by ID
|
|
267
257
|
- `receiveNextMessage()`: Process the next available message (one-shot)
|
|
268
258
|
- `handleMessage()`: Process message metadata only (without payload)
|
|
269
|
-
- **Transports**: Pluggable serialization/deserialization for different data
|
|
259
|
+
- **Transports**: Pluggable serialization/deserialization for different data
|
|
260
|
+
types
|
|
270
261
|
- **Streaming**: Memory-efficient processing of large payloads
|
|
271
262
|
- **Visibility Timeouts**: Automatic message lifecycle management
|
|
272
263
|
|
|
@@ -277,20 +268,25 @@ The multipart parser is optimized for high-throughput scenarios:
|
|
|
277
268
|
- **Streaming**: Messages are yielded immediately as headers are parsed
|
|
278
269
|
- **Memory Efficient**: No buffering of complete payloads
|
|
279
270
|
- **Fast Parsing**: Native Buffer operations for ~50% performance improvement
|
|
280
|
-
- **Scalable**: Can handle arbitrarily large responses without memory
|
|
271
|
+
- **Scalable**: Can handle arbitrarily large responses without memory
|
|
272
|
+
constraints
|
|
281
273
|
|
|
282
274
|
## Serialization (Transport) System
|
|
283
275
|
|
|
284
|
-
The queue client supports customizable serialization through the `Transport`
|
|
276
|
+
The queue client supports customizable serialization through the `Transport`
|
|
277
|
+
interface with **streaming support** for memory-efficient processing. Transport
|
|
278
|
+
can be configured at the **topic level** when creating a topic, or at the
|
|
279
|
+
**consumer group level** when creating a consumer group.
|
|
285
280
|
|
|
286
281
|
### Built-in Transports
|
|
287
282
|
|
|
288
283
|
#### JsonTransport (Default)
|
|
289
284
|
|
|
290
|
-
Buffers data for JSON parsing - suitable for structured data that fits in
|
|
285
|
+
Buffers data for JSON parsing - suitable for structured data that fits in
|
|
286
|
+
memory.
|
|
291
287
|
|
|
292
288
|
```typescript
|
|
293
|
-
import {
|
|
289
|
+
import { createTopic, JsonTransport } from "@vercel/queue";
|
|
294
290
|
|
|
295
291
|
const topic = createTopic<{ data: any }>(
|
|
296
292
|
client,
|
|
@@ -303,7 +299,8 @@ const topic = createTopic<{ data: any }>(client, "json-topic");
|
|
|
303
299
|
|
|
304
300
|
#### BufferTransport
|
|
305
301
|
|
|
306
|
-
Buffers the entire payload into memory as a Buffer - suitable for binary data
|
|
302
|
+
Buffers the entire payload into memory as a Buffer - suitable for binary data
|
|
303
|
+
that fits in memory.
|
|
307
304
|
|
|
308
305
|
```typescript
|
|
309
306
|
import { BufferTransport, createTopic } from "@vercel/queue";
|
|
@@ -319,10 +316,11 @@ await topic.publish(binaryData);
|
|
|
319
316
|
|
|
320
317
|
#### StreamTransport
|
|
321
318
|
|
|
322
|
-
**True streaming support** - passes ReadableStream directly without buffering.
|
|
319
|
+
**True streaming support** - passes ReadableStream directly without buffering.
|
|
320
|
+
Ideal for large files and memory-efficient processing.
|
|
323
321
|
|
|
324
322
|
```typescript
|
|
325
|
-
import {
|
|
323
|
+
import { createTopic, StreamTransport } from "@vercel/queue";
|
|
326
324
|
|
|
327
325
|
const topic = createTopic<ReadableStream<Uint8Array>>(
|
|
328
326
|
client,
|
|
@@ -346,7 +344,8 @@ await topic.publish(fileStream);
|
|
|
346
344
|
|
|
347
345
|
### Custom Transport
|
|
348
346
|
|
|
349
|
-
You can create your own serialization format by implementing the `Transport`
|
|
347
|
+
You can create your own serialization format by implementing the `Transport`
|
|
348
|
+
interface:
|
|
350
349
|
|
|
351
350
|
```typescript
|
|
352
351
|
import { Transport } from "@vercel/queue";
|
|
@@ -387,6 +386,21 @@ const topic = createTopic<T>(client, topicName, transport?);
|
|
|
387
386
|
// Publish a message (uses topic's transport)
|
|
388
387
|
await topic.publish(payload, options?);
|
|
389
388
|
|
|
389
|
+
// Trigger a callback URL when the message is
|
|
390
|
+
// ready for consumption
|
|
391
|
+
await topic.publish(payload, {
|
|
392
|
+
callback: { url: "https://example.com/webhook" }
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// Or provide multiple callbacks (each URL is called
|
|
396
|
+
// with a separate consumer group)
|
|
397
|
+
await topic.publish(payload, {
|
|
398
|
+
callback: {
|
|
399
|
+
group1: { url: "https://example.com/webhook1" },
|
|
400
|
+
group2: { url: "https://example.com/webhook2", delay: 30 }
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
|
|
390
404
|
// Create a consumer group (can override transport)
|
|
391
405
|
const consumer = topic.consumerGroup<U>(groupName, options?);
|
|
392
406
|
```
|
|
@@ -445,6 +459,42 @@ interface CallbackMessageOptions {
|
|
|
445
459
|
consumerGroup: string;
|
|
446
460
|
messageId: string;
|
|
447
461
|
}
|
|
462
|
+
// Create a callback handler for NextJS route handlers
|
|
463
|
+
function handleCallback(handlers: CallbackHandlers): (request: Request) => Promise<Response>;
|
|
464
|
+
|
|
465
|
+
// Handler function signature for callbacks
|
|
466
|
+
type Handler<T = unknown> = (
|
|
467
|
+
payload: T,
|
|
468
|
+
metadata: MessageMetadata
|
|
469
|
+
) => Promise<MessageHandlerResult> | MessageHandlerResult;
|
|
470
|
+
|
|
471
|
+
// Message metadata provided to handlers
|
|
472
|
+
interface MessageMetadata {
|
|
473
|
+
messageId: string;
|
|
474
|
+
deliveryCount: number;
|
|
475
|
+
timestamp: string;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Configuration object with handlers for different topics
|
|
479
|
+
type CallbackHandlers = {
|
|
480
|
+
[topicName: string]:
|
|
481
|
+
| Handler // Single handler (uses 'default' consumer group)
|
|
482
|
+
| { [consumerGroup: string]: Handler }; // Multiple consumer group handlers
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// Example usage:
|
|
486
|
+
export const POST = handleCallback({
|
|
487
|
+
// Topic handler (uses 'default' consumer group)
|
|
488
|
+
"new-users": (message, metadata) => {
|
|
489
|
+
console.log(`New user event:`, message, metadata);
|
|
490
|
+
},
|
|
491
|
+
|
|
492
|
+
// Consumer group specific handlers
|
|
493
|
+
"image-processing": {
|
|
494
|
+
"compress": (message, metadata) => console.log("Compressing image", message),
|
|
495
|
+
"resize": (message, metadata) => console.log("Resizing image", message),
|
|
496
|
+
}
|
|
497
|
+
});
|
|
448
498
|
|
|
449
499
|
// Error thrown for invalid callback requests
|
|
450
500
|
class InvalidCallbackError extends Error;
|
|
@@ -625,10 +675,11 @@ try {
|
|
|
625
675
|
|
|
626
676
|
### Complete Example: Video Processing Pipeline
|
|
627
677
|
|
|
628
|
-
Here's a comprehensive example showing a video processing pipeline that
|
|
678
|
+
Here's a comprehensive example showing a video processing pipeline that
|
|
679
|
+
processes videos with FFmpeg and stores the results in Vercel Blob:
|
|
629
680
|
|
|
630
681
|
```typescript
|
|
631
|
-
import {
|
|
682
|
+
import { createTopic, QueueClient, StreamTransport } from "@vercel/queue";
|
|
632
683
|
import { spawn } from "child_process";
|
|
633
684
|
import ffmpeg from "ffmpeg-static";
|
|
634
685
|
import { put } from "@vercel/blob";
|
|
@@ -759,30 +810,39 @@ The queue client provides specific error types for different failure scenarios:
|
|
|
759
810
|
|
|
760
811
|
### Error Types
|
|
761
812
|
|
|
762
|
-
- **`QueueEmptyError`**: Thrown when attempting to receive messages from an
|
|
813
|
+
- **`QueueEmptyError`**: Thrown when attempting to receive messages from an
|
|
814
|
+
empty queue (204 status)
|
|
763
815
|
|
|
764
816
|
- Only thrown when directly using `client.receiveMessages()`
|
|
765
|
-
- `ConsumerGroup.subscribe()` handles this error internally and continues
|
|
817
|
+
- `ConsumerGroup.subscribe()` handles this error internally and continues
|
|
818
|
+
polling
|
|
766
819
|
|
|
767
|
-
- **`MessageLockedError`**: Thrown when a message is temporarily locked (423
|
|
820
|
+
- **`MessageLockedError`**: Thrown when a message is temporarily locked (423
|
|
821
|
+
status)
|
|
768
822
|
|
|
769
823
|
- Contains optional `retryAfter` property with seconds to wait before retry
|
|
770
|
-
- For `receiveMessages()` on FIFO queues: the next message in sequence is
|
|
824
|
+
- For `receiveMessages()` on FIFO queues: the next message in sequence is
|
|
825
|
+
locked
|
|
771
826
|
- For `receiveMessageById()`: the requested message is locked
|
|
772
827
|
- `ConsumerGroup.subscribe()` handles this error internally when polling
|
|
773
828
|
|
|
774
829
|
- **`MessageNotFoundError`**: Message doesn't exist (404 status)
|
|
775
830
|
|
|
776
|
-
- **`MessageNotAvailableError`**: Message exists but isn't available for
|
|
831
|
+
- **`MessageNotAvailableError`**: Message exists but isn't available for
|
|
832
|
+
processing (409 status)
|
|
777
833
|
|
|
778
|
-
- **`FifoOrderingViolationError`**: FIFO queue ordering violation (409 status
|
|
834
|
+
- **`FifoOrderingViolationError`**: FIFO queue ordering violation (409 status
|
|
835
|
+
with nextMessageId)
|
|
779
836
|
|
|
780
837
|
- Contains `nextMessageId` property indicating which message to process first
|
|
781
838
|
|
|
782
|
-
- **`FailedDependencyError`**: FIFO ordering violation when receiving by ID (424
|
|
839
|
+
- **`FailedDependencyError`**: FIFO ordering violation when receiving by ID (424
|
|
840
|
+
status)
|
|
783
841
|
|
|
784
|
-
- Contains `nextMessageId` property indicating which message must be processed
|
|
785
|
-
|
|
842
|
+
- Contains `nextMessageId` property indicating which message must be processed
|
|
843
|
+
first
|
|
844
|
+
- Similar to `FifoOrderingViolationError` but specifically for receive-by-ID
|
|
845
|
+
operations
|
|
786
846
|
|
|
787
847
|
- **`MessageCorruptedError`**: Message data is corrupted or can't be parsed
|
|
788
848
|
|
|
@@ -805,14 +865,14 @@ The queue client provides specific error types for different failure scenarios:
|
|
|
805
865
|
|
|
806
866
|
```typescript
|
|
807
867
|
import {
|
|
808
|
-
QueueEmptyError,
|
|
809
|
-
MessageLockedError,
|
|
810
|
-
FifoOrderingViolationError,
|
|
811
|
-
FailedDependencyError,
|
|
812
868
|
BadRequestError,
|
|
813
|
-
|
|
869
|
+
FailedDependencyError,
|
|
870
|
+
FifoOrderingViolationError,
|
|
814
871
|
ForbiddenError,
|
|
815
872
|
InternalServerError,
|
|
873
|
+
MessageLockedError,
|
|
874
|
+
QueueEmptyError,
|
|
875
|
+
UnauthorizedError,
|
|
816
876
|
} from "@vercel/queue";
|
|
817
877
|
|
|
818
878
|
// Handle empty queue or locked messages
|
package/dist/index.d.mts
CHANGED
|
@@ -122,10 +122,12 @@ interface SendMessageOptions<T = unknown> {
|
|
|
122
122
|
*/
|
|
123
123
|
retentionSeconds?: number;
|
|
124
124
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
125
|
+
* Callback configuration
|
|
126
|
+
* - If a single CallbackConfig is provided, it will use the "default" consumer group
|
|
127
|
+
* - If an object is provided, keys are consumer group names with their respective callback configs
|
|
128
|
+
* Format: { consumerGroup: { url, delay?, frequency? } } or { url, delay?, frequency? }
|
|
127
129
|
*/
|
|
128
|
-
|
|
130
|
+
callback?: Record<string, CallbackConfig> | CallbackConfig;
|
|
129
131
|
}
|
|
130
132
|
interface SendMessageResponse {
|
|
131
133
|
/**
|
|
@@ -652,7 +654,7 @@ declare class Topic<T = unknown> {
|
|
|
652
654
|
publish(payload: T, options?: {
|
|
653
655
|
idempotencyKey?: string;
|
|
654
656
|
retentionSeconds?: number;
|
|
655
|
-
|
|
657
|
+
callback?: Record<string, CallbackConfig> | CallbackConfig;
|
|
656
658
|
}): Promise<{
|
|
657
659
|
messageId: string;
|
|
658
660
|
}>;
|
|
@@ -719,7 +721,55 @@ declare function createTopic<T = unknown>(client: QueueClient, topicName: string
|
|
|
719
721
|
* ```
|
|
720
722
|
*/
|
|
721
723
|
declare function parseCallbackRequest(request: Request): CallbackMessageOptions;
|
|
724
|
+
/**
|
|
725
|
+
* Message metadata provided to handlers
|
|
726
|
+
*/
|
|
727
|
+
interface MessageMetadata {
|
|
728
|
+
messageId: string;
|
|
729
|
+
deliveryCount: number;
|
|
730
|
+
timestamp: string;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Handler function signature
|
|
734
|
+
*/
|
|
735
|
+
type Handler<T = unknown> = (payload: T, metadata: MessageMetadata) => Promise<MessageHandlerResult> | MessageHandlerResult;
|
|
736
|
+
/**
|
|
737
|
+
* Configuration object with handlers for different topics
|
|
738
|
+
* Each topic can have either:
|
|
739
|
+
* - A single handler function (uses 'default' consumer group)
|
|
740
|
+
* - An object with handlers for specific consumer groups
|
|
741
|
+
*/
|
|
742
|
+
type CallbackHandlers = {
|
|
743
|
+
[topicName: string]: Handler | {
|
|
744
|
+
[consumerGroup: string]: Handler;
|
|
745
|
+
};
|
|
746
|
+
};
|
|
747
|
+
/**
|
|
748
|
+
* Simplified queue callback handler for NextJS route handlers
|
|
749
|
+
*
|
|
750
|
+
* @param handlers Object with topic-specific handlers
|
|
751
|
+
* @returns A NextJS route handler function
|
|
752
|
+
*
|
|
753
|
+
* @example
|
|
754
|
+
* ```typescript
|
|
755
|
+
* // Topic handler (uses 'default' consumer group)
|
|
756
|
+
* export const POST = handleCallback({
|
|
757
|
+
* "new-users": (message, metadata) => {
|
|
758
|
+
* console.log(`New user event:`, message, metadata);
|
|
759
|
+
* }
|
|
760
|
+
* });
|
|
761
|
+
*
|
|
762
|
+
* // Consumer group specific handlers
|
|
763
|
+
* export const POST = handleCallback({
|
|
764
|
+
* "image-processing": {
|
|
765
|
+
* "compress": (message, metadata) => console.log("Compressing image", message),
|
|
766
|
+
* "resize": (message, metadata) => console.log("Resizing image", message),
|
|
767
|
+
* }
|
|
768
|
+
* });
|
|
769
|
+
* ```
|
|
770
|
+
*/
|
|
771
|
+
declare function handleCallback(handlers: CallbackHandlers): (request: Request) => Promise<Response>;
|
|
722
772
|
|
|
723
773
|
declare function getVercelOidcToken(): Promise<string>;
|
|
724
774
|
|
|
725
|
-
export { BadRequestError, BufferTransport, type CallbackConfig, type CallbackMessageOptions, type ChangeVisibilityOptions, type ChangeVisibilityResponse, ConsumerGroup, type ConsumerGroupOptions, type DeleteMessageOptions, type DeleteMessageResponse, FailedDependencyError, type FifoOrderingError, FifoOrderingViolationError, ForbiddenError, InternalServerError, InvalidCallbackError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler, type MessageHandlerResult, MessageLockedError, MessageNotAvailableError, MessageNotFoundError, type MessageTimeoutResult, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveMessageByIdOptions, type ReceiveMessageByIdResponse, type ReceiveMessagesOptions, type SendMessageOptions, type SendMessageResponse, StreamTransport, Topic, type Transport, UnauthorizedError, createTopic, getVercelOidcToken, parseCallbackRequest };
|
|
775
|
+
export { BadRequestError, BufferTransport, type CallbackConfig, type CallbackMessageOptions, type ChangeVisibilityOptions, type ChangeVisibilityResponse, ConsumerGroup, type ConsumerGroupOptions, type DeleteMessageOptions, type DeleteMessageResponse, FailedDependencyError, type FifoOrderingError, FifoOrderingViolationError, ForbiddenError, InternalServerError, InvalidCallbackError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler, type MessageHandlerResult, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type MessageTimeoutResult, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveMessageByIdOptions, type ReceiveMessageByIdResponse, type ReceiveMessagesOptions, type SendMessageOptions, type SendMessageResponse, StreamTransport, Topic, type Transport, UnauthorizedError, createTopic, getVercelOidcToken, handleCallback, parseCallbackRequest };
|
package/dist/index.d.ts
CHANGED
|
@@ -122,10 +122,12 @@ interface SendMessageOptions<T = unknown> {
|
|
|
122
122
|
*/
|
|
123
123
|
retentionSeconds?: number;
|
|
124
124
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
125
|
+
* Callback configuration
|
|
126
|
+
* - If a single CallbackConfig is provided, it will use the "default" consumer group
|
|
127
|
+
* - If an object is provided, keys are consumer group names with their respective callback configs
|
|
128
|
+
* Format: { consumerGroup: { url, delay?, frequency? } } or { url, delay?, frequency? }
|
|
127
129
|
*/
|
|
128
|
-
|
|
130
|
+
callback?: Record<string, CallbackConfig> | CallbackConfig;
|
|
129
131
|
}
|
|
130
132
|
interface SendMessageResponse {
|
|
131
133
|
/**
|
|
@@ -652,7 +654,7 @@ declare class Topic<T = unknown> {
|
|
|
652
654
|
publish(payload: T, options?: {
|
|
653
655
|
idempotencyKey?: string;
|
|
654
656
|
retentionSeconds?: number;
|
|
655
|
-
|
|
657
|
+
callback?: Record<string, CallbackConfig> | CallbackConfig;
|
|
656
658
|
}): Promise<{
|
|
657
659
|
messageId: string;
|
|
658
660
|
}>;
|
|
@@ -719,7 +721,55 @@ declare function createTopic<T = unknown>(client: QueueClient, topicName: string
|
|
|
719
721
|
* ```
|
|
720
722
|
*/
|
|
721
723
|
declare function parseCallbackRequest(request: Request): CallbackMessageOptions;
|
|
724
|
+
/**
|
|
725
|
+
* Message metadata provided to handlers
|
|
726
|
+
*/
|
|
727
|
+
interface MessageMetadata {
|
|
728
|
+
messageId: string;
|
|
729
|
+
deliveryCount: number;
|
|
730
|
+
timestamp: string;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Handler function signature
|
|
734
|
+
*/
|
|
735
|
+
type Handler<T = unknown> = (payload: T, metadata: MessageMetadata) => Promise<MessageHandlerResult> | MessageHandlerResult;
|
|
736
|
+
/**
|
|
737
|
+
* Configuration object with handlers for different topics
|
|
738
|
+
* Each topic can have either:
|
|
739
|
+
* - A single handler function (uses 'default' consumer group)
|
|
740
|
+
* - An object with handlers for specific consumer groups
|
|
741
|
+
*/
|
|
742
|
+
type CallbackHandlers = {
|
|
743
|
+
[topicName: string]: Handler | {
|
|
744
|
+
[consumerGroup: string]: Handler;
|
|
745
|
+
};
|
|
746
|
+
};
|
|
747
|
+
/**
|
|
748
|
+
* Simplified queue callback handler for NextJS route handlers
|
|
749
|
+
*
|
|
750
|
+
* @param handlers Object with topic-specific handlers
|
|
751
|
+
* @returns A NextJS route handler function
|
|
752
|
+
*
|
|
753
|
+
* @example
|
|
754
|
+
* ```typescript
|
|
755
|
+
* // Topic handler (uses 'default' consumer group)
|
|
756
|
+
* export const POST = handleCallback({
|
|
757
|
+
* "new-users": (message, metadata) => {
|
|
758
|
+
* console.log(`New user event:`, message, metadata);
|
|
759
|
+
* }
|
|
760
|
+
* });
|
|
761
|
+
*
|
|
762
|
+
* // Consumer group specific handlers
|
|
763
|
+
* export const POST = handleCallback({
|
|
764
|
+
* "image-processing": {
|
|
765
|
+
* "compress": (message, metadata) => console.log("Compressing image", message),
|
|
766
|
+
* "resize": (message, metadata) => console.log("Resizing image", message),
|
|
767
|
+
* }
|
|
768
|
+
* });
|
|
769
|
+
* ```
|
|
770
|
+
*/
|
|
771
|
+
declare function handleCallback(handlers: CallbackHandlers): (request: Request) => Promise<Response>;
|
|
722
772
|
|
|
723
773
|
declare function getVercelOidcToken(): Promise<string>;
|
|
724
774
|
|
|
725
|
-
export { BadRequestError, BufferTransport, type CallbackConfig, type CallbackMessageOptions, type ChangeVisibilityOptions, type ChangeVisibilityResponse, ConsumerGroup, type ConsumerGroupOptions, type DeleteMessageOptions, type DeleteMessageResponse, FailedDependencyError, type FifoOrderingError, FifoOrderingViolationError, ForbiddenError, InternalServerError, InvalidCallbackError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler, type MessageHandlerResult, MessageLockedError, MessageNotAvailableError, MessageNotFoundError, type MessageTimeoutResult, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveMessageByIdOptions, type ReceiveMessageByIdResponse, type ReceiveMessagesOptions, type SendMessageOptions, type SendMessageResponse, StreamTransport, Topic, type Transport, UnauthorizedError, createTopic, getVercelOidcToken, parseCallbackRequest };
|
|
775
|
+
export { BadRequestError, BufferTransport, type CallbackConfig, type CallbackMessageOptions, type ChangeVisibilityOptions, type ChangeVisibilityResponse, ConsumerGroup, type ConsumerGroupOptions, type DeleteMessageOptions, type DeleteMessageResponse, FailedDependencyError, type FifoOrderingError, FifoOrderingViolationError, ForbiddenError, InternalServerError, InvalidCallbackError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler, type MessageHandlerResult, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type MessageTimeoutResult, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveMessageByIdOptions, type ReceiveMessageByIdResponse, type ReceiveMessagesOptions, type SendMessageOptions, type SendMessageResponse, StreamTransport, Topic, type Transport, UnauthorizedError, createTopic, getVercelOidcToken, handleCallback, parseCallbackRequest };
|