@vercel/queue 0.0.0-alpha.4 → 0.0.0-alpha.40
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 +467 -827
- package/dist/index.d.mts +436 -584
- package/dist/index.d.ts +436 -584
- package/dist/index.js +1452 -986
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1434 -976
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,37 +1,83 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Serializer/Deserializer interface for message payloads
|
|
2
|
+
* Serializer/Deserializer interface for message payloads.
|
|
3
|
+
*
|
|
4
|
+
* Built-in implementations:
|
|
5
|
+
* - `JsonTransport` - JSON serialization (default, buffers entire payload)
|
|
6
|
+
* - `BufferTransport` - Binary data (buffers entire payload)
|
|
7
|
+
* - `StreamTransport` - Pass-through streaming (no buffering, ideal for large payloads)
|
|
3
8
|
*/
|
|
4
9
|
interface Transport<T = unknown> {
|
|
5
10
|
/**
|
|
6
|
-
* Serialize a value to a buffer or stream for transmission
|
|
11
|
+
* Serialize a value to a buffer or stream for transmission.
|
|
12
|
+
* The result is sent as the request body with the `contentType` header.
|
|
7
13
|
*/
|
|
8
14
|
serialize(value: T): Buffer | ReadableStream<Uint8Array>;
|
|
9
15
|
/**
|
|
10
|
-
* Deserialize a readable stream back to the original value
|
|
16
|
+
* Deserialize a readable stream back to the original value.
|
|
17
|
+
* Called when receiving messages from the queue.
|
|
11
18
|
*/
|
|
12
19
|
deserialize(stream: ReadableStream<Uint8Array>): Promise<T>;
|
|
13
20
|
/**
|
|
14
|
-
* Optional cleanup method for deserialized payloads that may contain resources
|
|
15
|
-
*
|
|
21
|
+
* Optional cleanup method for deserialized payloads that may contain resources.
|
|
22
|
+
* Called automatically by ConsumerGroup on error; manual cleanup required for direct client usage.
|
|
16
23
|
* @param payload The deserialized payload to clean up
|
|
17
24
|
*/
|
|
18
25
|
finalize?(payload: T): Promise<void>;
|
|
19
26
|
/**
|
|
20
|
-
* MIME type for this serialization format
|
|
27
|
+
* MIME type for this serialization format.
|
|
28
|
+
* Sent as the Content-Type header when publishing messages.
|
|
21
29
|
*/
|
|
22
30
|
contentType: string;
|
|
23
31
|
}
|
|
24
32
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
33
|
+
* JSON serializer/deserializer (default transport).
|
|
34
|
+
*
|
|
35
|
+
* Ideal for structured data. Buffers the entire payload in memory for parsing.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // Default (JsonTransport is used automatically)
|
|
40
|
+
* const queue = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
41
|
+
* await queue.send("topic", { data: "example" });
|
|
42
|
+
*
|
|
43
|
+
* // With custom serialization
|
|
44
|
+
* const queue = new QueueClient({
|
|
45
|
+
* region: process.env.QUEUE_REGION!,
|
|
46
|
+
* transport: new JsonTransport({
|
|
47
|
+
* replacer: (key, value) => key === "password" ? undefined : value,
|
|
48
|
+
* reviver: (key, value) => key === "date" ? new Date(value) : value,
|
|
49
|
+
* }),
|
|
50
|
+
* });
|
|
51
|
+
* await queue.send("topic", { data: "example" });
|
|
52
|
+
* ```
|
|
27
53
|
*/
|
|
28
54
|
declare class JsonTransport<T = unknown> implements Transport<T> {
|
|
29
55
|
readonly contentType = "application/json";
|
|
56
|
+
readonly replacer?: Parameters<typeof JSON.stringify>[1];
|
|
57
|
+
readonly reviver?: Parameters<typeof JSON.parse>[1];
|
|
58
|
+
/**
|
|
59
|
+
* Create a new JsonTransport.
|
|
60
|
+
* @param options - Optional JSON serialization options
|
|
61
|
+
* @param options.replacer - Custom replacer for JSON.stringify
|
|
62
|
+
* @param options.reviver - Custom reviver for JSON.parse
|
|
63
|
+
*/
|
|
64
|
+
constructor(options?: {
|
|
65
|
+
replacer?: Parameters<typeof JSON.stringify>[1];
|
|
66
|
+
reviver?: Parameters<typeof JSON.parse>[1];
|
|
67
|
+
});
|
|
30
68
|
serialize(value: T): Buffer;
|
|
31
69
|
deserialize(stream: ReadableStream<Uint8Array>): Promise<T>;
|
|
32
70
|
}
|
|
33
71
|
/**
|
|
34
|
-
*
|
|
72
|
+
* Binary data serializer/deserializer.
|
|
73
|
+
*
|
|
74
|
+
* Ideal for binary data that fits in memory. Buffers the entire payload.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const queue = new QueueClient({ region: "iad1", transport: new BufferTransport() });
|
|
79
|
+
* await queue.send("binary-topic", myBuffer);
|
|
80
|
+
* ```
|
|
35
81
|
*/
|
|
36
82
|
declare class BufferTransport implements Transport<Buffer> {
|
|
37
83
|
readonly contentType = "application/octet-stream";
|
|
@@ -39,31 +85,36 @@ declare class BufferTransport implements Transport<Buffer> {
|
|
|
39
85
|
deserialize(stream: ReadableStream<Uint8Array>): Promise<Buffer>;
|
|
40
86
|
}
|
|
41
87
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
88
|
+
* Pass-through stream serializer/deserializer.
|
|
89
|
+
*
|
|
90
|
+
* Ideal for large files and real-time streams. Does not buffer data in memory.
|
|
44
91
|
*
|
|
45
|
-
*
|
|
46
|
-
* processing
|
|
47
|
-
*
|
|
92
|
+
* **Important:** When using StreamTransport, you must call `finalize(payload)` when done
|
|
93
|
+
* processing to prevent resource leaks. ConsumerGroup handles this automatically;
|
|
94
|
+
* direct client usage requires manual cleanup.
|
|
48
95
|
*
|
|
49
|
-
*
|
|
96
|
+
* @example
|
|
50
97
|
* ```typescript
|
|
51
|
-
* const
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* //
|
|
60
|
-
*
|
|
61
|
-
*
|
|
98
|
+
* const queue = new QueueClient({ region: "iad1", transport: new StreamTransport() });
|
|
99
|
+
*
|
|
100
|
+
* // Sending a stream
|
|
101
|
+
* await queue.send("large-file", myReadableStream);
|
|
102
|
+
*
|
|
103
|
+
* // Receiving - cleanup handled automatically
|
|
104
|
+
* await queue.receive("large-file", "processor", async (stream, meta) => {
|
|
105
|
+
* const reader = stream.getReader();
|
|
106
|
+
* // Process chunks...
|
|
107
|
+
* });
|
|
108
|
+
* ```
|
|
62
109
|
*/
|
|
63
110
|
declare class StreamTransport implements Transport<ReadableStream<Uint8Array>> {
|
|
64
111
|
readonly contentType = "application/octet-stream";
|
|
65
112
|
serialize(value: ReadableStream<Uint8Array>): ReadableStream<Uint8Array>;
|
|
66
113
|
deserialize(stream: ReadableStream<Uint8Array>): Promise<ReadableStream<Uint8Array>>;
|
|
114
|
+
/**
|
|
115
|
+
* Consume any remaining stream data to prevent resource leaks.
|
|
116
|
+
* Called automatically by ConsumerGroup; manual call required for direct client usage.
|
|
117
|
+
*/
|
|
67
118
|
finalize(payload: ReadableStream<Uint8Array>): Promise<void>;
|
|
68
119
|
}
|
|
69
120
|
|
|
@@ -71,269 +122,276 @@ declare class StreamTransport implements Transport<ReadableStream<Uint8Array>> {
|
|
|
71
122
|
* Vercel Queue Service client types
|
|
72
123
|
*/
|
|
73
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Vercel region code. The 20 known codes match
|
|
127
|
+
* {@link https://dcs.vercel-infra.com/ | dcs.vercel-infra.com}.
|
|
128
|
+
* Arbitrary strings are also accepted for forward compatibility
|
|
129
|
+
* with regions added after this SDK version.
|
|
130
|
+
*/
|
|
131
|
+
type VercelRegion = "arn1" | "bom1" | "cdg1" | "cle1" | "cpt1" | "dub1" | "dxb1" | "fra1" | "gru1" | "hkg1" | "hnd1" | "iad1" | "icn1" | "kix1" | "lhr1" | "pdx1" | "sfo1" | "sin1" | "syd1" | "yul1" | (string & {});
|
|
132
|
+
/**
|
|
133
|
+
* Resolves a region code to a base URL for the Vercel Queue Service API.
|
|
134
|
+
*
|
|
135
|
+
* Default: `` (region) => `https://${region}.vercel-queue.com` ``
|
|
136
|
+
*/
|
|
137
|
+
type BaseUrlResolver = (region: string) => string;
|
|
74
138
|
interface QueueClientOptions {
|
|
75
139
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
140
|
+
* Vercel region code for API routing.
|
|
141
|
+
*
|
|
142
|
+
* Requests are sent to the regional endpoint resolved by
|
|
143
|
+
* {@link BaseUrlResolver} (default: `https://${region}.vercel-queue.com`).
|
|
144
|
+
*
|
|
145
|
+
* Use a `QUEUE_REGION` env var set to `${VERCEL_REGION}` in production
|
|
146
|
+
* and a fixed region (e.g. `"iad1"`) in development.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* new QueueClient({ region: process.env.QUEUE_REGION! })
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
region: VercelRegion;
|
|
154
|
+
/**
|
|
155
|
+
* Custom resolver that maps a region code to a base URL.
|
|
156
|
+
* @default (region) => `https://${region}.vercel-queue.com`
|
|
78
157
|
*/
|
|
79
|
-
|
|
158
|
+
resolveBaseUrl?: BaseUrlResolver;
|
|
80
159
|
/**
|
|
81
|
-
* Vercel
|
|
82
|
-
*
|
|
83
|
-
*
|
|
160
|
+
* Authentication token for the Vercel Queue Service API.
|
|
161
|
+
* If not provided, the client will attempt to get a token via OIDC
|
|
162
|
+
* when running in a Vercel Function environment.
|
|
84
163
|
*/
|
|
85
164
|
token?: string;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Callback configuration for a consumer group
|
|
89
|
-
*/
|
|
90
|
-
interface CallbackConfig {
|
|
91
165
|
/**
|
|
92
|
-
*
|
|
166
|
+
* Custom headers to include in all requests.
|
|
93
167
|
*/
|
|
94
|
-
|
|
168
|
+
headers?: Record<string, string>;
|
|
95
169
|
/**
|
|
96
|
-
*
|
|
170
|
+
* Deployment ID for message routing and lease validation.
|
|
171
|
+
*
|
|
172
|
+
* - `undefined` (default): auto-detect from `VERCEL_DEPLOYMENT_ID` env var;
|
|
173
|
+
* sent messages are pinned to this deployment.
|
|
174
|
+
* - `null`: explicitly unpinned — no deployment ID is sent on any request.
|
|
175
|
+
* - `"dpl_xxx"`: explicit value used for both send pinning and consume identification.
|
|
176
|
+
*
|
|
177
|
+
* Ignored in development mode (deployment ID is never sent locally).
|
|
97
178
|
*/
|
|
98
|
-
|
|
179
|
+
deploymentId?: string | null;
|
|
99
180
|
/**
|
|
100
|
-
*
|
|
181
|
+
* Serializer/deserializer for message payloads.
|
|
182
|
+
* Used for all send and receive operations.
|
|
183
|
+
* @default JsonTransport
|
|
101
184
|
*/
|
|
102
|
-
|
|
185
|
+
transport?: Transport;
|
|
103
186
|
}
|
|
104
187
|
/**
|
|
105
|
-
*
|
|
188
|
+
* Options for sending messages.
|
|
106
189
|
*/
|
|
107
|
-
interface
|
|
190
|
+
interface SendOptions {
|
|
108
191
|
/**
|
|
109
|
-
* Unique key to prevent duplicate message submissions
|
|
110
|
-
*
|
|
192
|
+
* Unique key to prevent duplicate message submissions.
|
|
193
|
+
* Deduplication window: `min(message retention, 24 hours)`.
|
|
111
194
|
*/
|
|
112
195
|
idempotencyKey?: string;
|
|
113
196
|
/**
|
|
114
|
-
* Message retention time in seconds
|
|
197
|
+
* Message retention time in seconds. After this period, the message expires.
|
|
115
198
|
* @default 86400 (24 hours)
|
|
116
|
-
* @
|
|
117
|
-
* @
|
|
199
|
+
* @minimum 60 (1 minute)
|
|
200
|
+
* @maximum 86400 (24 hours)
|
|
118
201
|
*/
|
|
119
202
|
retentionSeconds?: number;
|
|
120
203
|
/**
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
204
|
+
* Delay delivery of the message by this many seconds.
|
|
205
|
+
* The message will not be visible to consumers until the delay has passed.
|
|
206
|
+
* @default 0
|
|
207
|
+
* @minimum 0
|
|
208
|
+
* @maximum Value of retentionSeconds (delay cannot exceed retention)
|
|
124
209
|
*/
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
interface SendMessageOptions<T = unknown> extends PublishOptions {
|
|
210
|
+
delaySeconds?: number;
|
|
128
211
|
/**
|
|
129
|
-
*
|
|
212
|
+
* Custom headers to include with this message.
|
|
213
|
+
* These headers are passed through to the VQS server.
|
|
130
214
|
*/
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* The message payload
|
|
134
|
-
*/
|
|
135
|
-
payload: T;
|
|
215
|
+
headers?: Record<string, string>;
|
|
136
216
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
217
|
+
/**
|
|
218
|
+
* Result returned by `send()`.
|
|
219
|
+
*
|
|
220
|
+
* `messageId` is `null` when the server accepted the message for deferred
|
|
221
|
+
* processing (e.g. during a server-side outage) and no ID is available yet.
|
|
222
|
+
*/
|
|
223
|
+
interface SendResult {
|
|
224
|
+
messageId: string | null;
|
|
142
225
|
}
|
|
143
226
|
interface Message<T = unknown> {
|
|
144
227
|
/**
|
|
145
|
-
*
|
|
228
|
+
* Unique message identifier. Used for receive-by-ID operations.
|
|
146
229
|
*/
|
|
147
230
|
messageId: string;
|
|
148
231
|
/**
|
|
149
|
-
* The deserialized message payload
|
|
150
|
-
* Note: If using
|
|
151
|
-
* when done processing, especially in error cases
|
|
232
|
+
* The deserialized message payload.
|
|
233
|
+
* Note: If using StreamTransport, ensure proper cleanup by calling
|
|
234
|
+
* `transport.finalize(payload)` when done processing, especially in error cases.
|
|
152
235
|
*/
|
|
153
236
|
payload: T;
|
|
154
237
|
/**
|
|
155
|
-
* Number of times this message has been delivered
|
|
238
|
+
* Number of times this message has been delivered.
|
|
239
|
+
* Starts at 1 for the first delivery, increments on each retry.
|
|
156
240
|
*/
|
|
157
241
|
deliveryCount: number;
|
|
158
242
|
/**
|
|
159
|
-
* Timestamp when the message was created
|
|
160
|
-
*/
|
|
161
|
-
timestamp: string;
|
|
162
|
-
/**
|
|
163
|
-
* MIME type of the message content
|
|
164
|
-
*/
|
|
165
|
-
contentType: string;
|
|
166
|
-
/**
|
|
167
|
-
* Unique ticket for this message delivery (required for delete/patch operations)
|
|
168
|
-
*/
|
|
169
|
-
ticket: string;
|
|
170
|
-
}
|
|
171
|
-
interface ReceiveMessagesOptions<T = unknown> {
|
|
172
|
-
/**
|
|
173
|
-
* The queue name to receive messages from
|
|
243
|
+
* Timestamp when the message was created/published.
|
|
174
244
|
*/
|
|
175
|
-
|
|
245
|
+
createdAt: Date;
|
|
176
246
|
/**
|
|
177
|
-
*
|
|
247
|
+
* Timestamp when the message expires.
|
|
248
|
+
* Only present for messages delivered via the v2beta binary callback path.
|
|
178
249
|
*/
|
|
179
|
-
|
|
250
|
+
expiresAt?: Date;
|
|
180
251
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
252
|
+
* MIME type of the message content.
|
|
253
|
+
* Set by the transport's `contentType` property during publish.
|
|
183
254
|
*/
|
|
184
|
-
|
|
255
|
+
contentType: string;
|
|
185
256
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* @note FIFO queues must use limit=1
|
|
257
|
+
* Receipt handle (lease token) for this message delivery.
|
|
258
|
+
* Required for acknowledge and visibility extension operations.
|
|
259
|
+
* Valid only until the visibility timeout expires.
|
|
190
260
|
*/
|
|
191
|
-
|
|
261
|
+
receiptHandle: string;
|
|
192
262
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
queueName: string;
|
|
198
|
-
/**
|
|
199
|
-
* Consumer group name
|
|
200
|
-
*/
|
|
201
|
-
consumerGroup: string;
|
|
202
|
-
/**
|
|
203
|
-
* The message ID to delete
|
|
204
|
-
*/
|
|
263
|
+
/**
|
|
264
|
+
* Message metadata provided to handlers
|
|
265
|
+
*/
|
|
266
|
+
interface MessageMetadata {
|
|
205
267
|
messageId: string;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
interface DeleteMessageResponse {
|
|
212
|
-
/**
|
|
213
|
-
* Whether the message was successfully deleted
|
|
214
|
-
*/
|
|
215
|
-
deleted: boolean;
|
|
216
|
-
}
|
|
217
|
-
interface ChangeVisibilityOptions {
|
|
218
|
-
/**
|
|
219
|
-
* The queue name the message belongs to
|
|
220
|
-
*/
|
|
221
|
-
queueName: string;
|
|
222
|
-
/**
|
|
223
|
-
* Consumer group name
|
|
224
|
-
*/
|
|
268
|
+
deliveryCount: number;
|
|
269
|
+
createdAt: Date;
|
|
270
|
+
expiresAt?: Date;
|
|
271
|
+
topicName: string;
|
|
225
272
|
consumerGroup: string;
|
|
226
|
-
/**
|
|
227
|
-
|
|
228
|
-
*/
|
|
229
|
-
messageId: string;
|
|
230
|
-
/**
|
|
231
|
-
* Ticket received from the message
|
|
232
|
-
*/
|
|
233
|
-
ticket: string;
|
|
234
|
-
/**
|
|
235
|
-
* New visibility timeout in seconds
|
|
236
|
-
*/
|
|
237
|
-
visibilityTimeoutSeconds: number;
|
|
238
|
-
}
|
|
239
|
-
interface ChangeVisibilityResponse {
|
|
240
|
-
/**
|
|
241
|
-
* Whether the visibility was successfully updated
|
|
242
|
-
*/
|
|
243
|
-
updated: boolean;
|
|
273
|
+
/** Vercel region the client is targeting. */
|
|
274
|
+
region: string;
|
|
244
275
|
}
|
|
245
276
|
/**
|
|
246
|
-
*
|
|
277
|
+
* Instruction returned by a {@link RetryHandler} to control what happens
|
|
278
|
+
* to a message when the handler throws.
|
|
279
|
+
*
|
|
280
|
+
* - `{ afterSeconds: N }` — reschedule the message for redelivery after N seconds
|
|
281
|
+
* - `{ acknowledge: true }` — acknowledge the message so it is never retried
|
|
247
282
|
*/
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
283
|
+
type RetryDirective = {
|
|
284
|
+
afterSeconds: number;
|
|
285
|
+
} | {
|
|
286
|
+
acknowledge: true;
|
|
287
|
+
};
|
|
254
288
|
/**
|
|
255
|
-
*
|
|
289
|
+
* Called when the message handler throws an error.
|
|
290
|
+
* Return a {@link RetryDirective} to reschedule or acknowledge the message,
|
|
291
|
+
* or return `undefined` to let the error propagate normally.
|
|
256
292
|
*/
|
|
257
|
-
type
|
|
293
|
+
type RetryHandler = (error: unknown, metadata: MessageMetadata) => RetryDirective | void | undefined;
|
|
258
294
|
/**
|
|
259
|
-
* Message
|
|
295
|
+
* Message handler function type.
|
|
296
|
+
*
|
|
297
|
+
* Called once per message with the deserialized payload and metadata.
|
|
298
|
+
* Not called when the queue is empty — check the return value of `receive()` instead.
|
|
260
299
|
*/
|
|
261
|
-
|
|
262
|
-
messageId: string;
|
|
263
|
-
deliveryCount: number;
|
|
264
|
-
timestamp: string;
|
|
265
|
-
}
|
|
300
|
+
type MessageHandler<T = unknown> = (message: T, metadata: MessageMetadata) => Promise<void> | void;
|
|
266
301
|
/**
|
|
267
|
-
*
|
|
302
|
+
* Result returned by `receive()`. Use `ok` to check if messages were processed.
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```typescript
|
|
306
|
+
* const result = await receive("topic", "group", handler);
|
|
307
|
+
* if (result.ok) {
|
|
308
|
+
* // Messages were processed successfully
|
|
309
|
+
* } else if (result.reason === "empty") {
|
|
310
|
+
* // Queue had no messages available
|
|
311
|
+
* }
|
|
312
|
+
* ```
|
|
268
313
|
*/
|
|
269
|
-
type
|
|
314
|
+
type ReceiveResult = {
|
|
315
|
+
ok: true;
|
|
316
|
+
} | {
|
|
317
|
+
ok: false;
|
|
318
|
+
reason: "empty";
|
|
319
|
+
} | {
|
|
320
|
+
ok: false;
|
|
321
|
+
reason: "not_found";
|
|
322
|
+
messageId: string;
|
|
323
|
+
} | {
|
|
324
|
+
ok: false;
|
|
325
|
+
reason: "not_available";
|
|
326
|
+
messageId: string;
|
|
327
|
+
} | {
|
|
328
|
+
ok: false;
|
|
329
|
+
reason: "already_processed";
|
|
330
|
+
messageId: string;
|
|
331
|
+
};
|
|
270
332
|
/**
|
|
271
|
-
* Options for
|
|
333
|
+
* Options for receiving a specific message by ID.
|
|
272
334
|
*/
|
|
273
|
-
interface
|
|
274
|
-
/**
|
|
275
|
-
|
|
276
|
-
* @default JsonTransport instance
|
|
277
|
-
*/
|
|
278
|
-
transport?: Transport<T>;
|
|
335
|
+
interface ReceiveByIdOptions {
|
|
336
|
+
/** The specific message ID to consume */
|
|
337
|
+
messageId: string;
|
|
279
338
|
/**
|
|
280
|
-
*
|
|
281
|
-
* @default
|
|
339
|
+
* Message lock duration in seconds.
|
|
340
|
+
* @default 300 (5 minutes)
|
|
341
|
+
* @minimum 30
|
|
342
|
+
* @maximum 3600 (1 hour)
|
|
282
343
|
*/
|
|
283
344
|
visibilityTimeoutSeconds?: number;
|
|
284
345
|
/**
|
|
285
|
-
*
|
|
286
|
-
*
|
|
346
|
+
* Called when the handler throws. Return `{ afterSeconds: N }` to reschedule
|
|
347
|
+
* the message for redelivery after N seconds, or return `undefined`
|
|
348
|
+
* to let the error propagate normally.
|
|
287
349
|
*/
|
|
288
|
-
|
|
350
|
+
retry?: RetryHandler;
|
|
289
351
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
queueName: string;
|
|
295
|
-
/**
|
|
296
|
-
* Consumer group name
|
|
297
|
-
*/
|
|
298
|
-
consumerGroup: string;
|
|
352
|
+
/**
|
|
353
|
+
* Options for receiving messages from the queue with an optional batch limit.
|
|
354
|
+
*/
|
|
355
|
+
interface ReceiveBatchOptions {
|
|
299
356
|
/**
|
|
300
|
-
*
|
|
357
|
+
* Maximum number of messages to retrieve in a single request.
|
|
358
|
+
* @default 1
|
|
359
|
+
* @minimum 1
|
|
360
|
+
* @maximum 10
|
|
301
361
|
*/
|
|
302
|
-
|
|
362
|
+
limit?: number;
|
|
303
363
|
/**
|
|
304
|
-
*
|
|
305
|
-
* @default
|
|
364
|
+
* Message lock duration in seconds.
|
|
365
|
+
* @default 300 (5 minutes)
|
|
366
|
+
* @minimum 30
|
|
367
|
+
* @maximum 3600 (1 hour)
|
|
306
368
|
*/
|
|
307
369
|
visibilityTimeoutSeconds?: number;
|
|
308
370
|
/**
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
371
|
+
* Called when the handler throws. Return `{ afterSeconds: N }` to reschedule
|
|
372
|
+
* the message for redelivery after N seconds, or return `undefined`
|
|
373
|
+
* to let the error propagate normally.
|
|
312
374
|
*/
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
interface ReceiveMessageByIdResponse<T = unknown, TSkipPayload extends boolean = false> {
|
|
316
|
-
message: TSkipPayload extends true ? Message<void> : Message<T>;
|
|
375
|
+
retry?: RetryHandler;
|
|
317
376
|
}
|
|
318
377
|
/**
|
|
319
|
-
*
|
|
378
|
+
* Options for the receive method. Either receive by message ID or receive
|
|
379
|
+
* from the queue with an optional limit. These options are mutually exclusive.
|
|
380
|
+
*/
|
|
381
|
+
type ReceiveOptions = ReceiveByIdOptions | ReceiveBatchOptions;
|
|
382
|
+
/**
|
|
383
|
+
* Error thrown when a message does not exist or has expired.
|
|
320
384
|
*/
|
|
321
385
|
declare class MessageNotFoundError extends Error {
|
|
322
386
|
constructor(messageId: string);
|
|
323
387
|
}
|
|
324
388
|
/**
|
|
325
|
-
* Error thrown when a message
|
|
326
|
-
* This can happen when the message is in the wrong state
|
|
389
|
+
* Error thrown when a message exists but cannot be processed.
|
|
390
|
+
* This can happen when the message is in the wrong state or already claimed by another consumer.
|
|
327
391
|
*/
|
|
328
392
|
declare class MessageNotAvailableError extends Error {
|
|
329
393
|
constructor(messageId: string, reason?: string);
|
|
330
394
|
}
|
|
331
|
-
/**
|
|
332
|
-
* Error thrown when there's a FIFO ordering violation (409)
|
|
333
|
-
*/
|
|
334
|
-
declare class FifoOrderingViolationError extends Error {
|
|
335
|
-
constructor(messageId: string, reason: string);
|
|
336
|
-
}
|
|
337
395
|
/**
|
|
338
396
|
* Error thrown when message data is corrupted or can't be parsed
|
|
339
397
|
*/
|
|
@@ -341,458 +399,252 @@ declare class MessageCorruptedError extends Error {
|
|
|
341
399
|
constructor(messageId: string, reason: string);
|
|
342
400
|
}
|
|
343
401
|
/**
|
|
344
|
-
* Error thrown when there are no messages available in the queue
|
|
402
|
+
* Error thrown when there are no messages available in the queue.
|
|
345
403
|
*/
|
|
346
404
|
declare class QueueEmptyError extends Error {
|
|
347
405
|
constructor(queueName: string, consumerGroup: string);
|
|
348
406
|
}
|
|
349
407
|
/**
|
|
350
|
-
* Error thrown when a message is temporarily locked
|
|
408
|
+
* Error thrown when a message is temporarily locked by another consumer.
|
|
409
|
+
* The message is currently being processed and cannot be claimed.
|
|
351
410
|
*/
|
|
352
411
|
declare class MessageLockedError extends Error {
|
|
412
|
+
/** Suggested retry delay in seconds, if provided by the server. */
|
|
353
413
|
readonly retryAfter?: number;
|
|
354
414
|
constructor(messageId: string, retryAfter?: number);
|
|
355
415
|
}
|
|
356
416
|
/**
|
|
357
|
-
* Error thrown when authentication fails
|
|
417
|
+
* Error thrown when authentication fails.
|
|
418
|
+
* This typically means the token is missing, invalid, or expired.
|
|
358
419
|
*/
|
|
359
420
|
declare class UnauthorizedError extends Error {
|
|
360
421
|
constructor(message?: string);
|
|
361
422
|
}
|
|
362
423
|
/**
|
|
363
|
-
* Error thrown when access is forbidden
|
|
424
|
+
* Error thrown when access is forbidden.
|
|
425
|
+
* This typically means the queue belongs to a different environment or project.
|
|
364
426
|
*/
|
|
365
427
|
declare class ForbiddenError extends Error {
|
|
366
428
|
constructor(message?: string);
|
|
367
429
|
}
|
|
368
430
|
/**
|
|
369
|
-
* Error thrown
|
|
431
|
+
* Error thrown when request parameters are invalid.
|
|
370
432
|
*/
|
|
371
433
|
declare class BadRequestError extends Error {
|
|
372
434
|
constructor(message: string);
|
|
373
435
|
}
|
|
374
436
|
/**
|
|
375
|
-
* Error thrown when
|
|
376
|
-
*/
|
|
377
|
-
declare class FailedDependencyError extends Error {
|
|
378
|
-
constructor(messageId: string);
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Error thrown for internal server errors (500)
|
|
437
|
+
* Error thrown when the server encounters an unexpected error.
|
|
382
438
|
*/
|
|
383
439
|
declare class InternalServerError extends Error {
|
|
384
440
|
constructor(message?: string);
|
|
385
441
|
}
|
|
386
442
|
/**
|
|
387
|
-
* Error thrown when batch limit parameter is
|
|
443
|
+
* Error thrown when the batch limit parameter is outside the valid range.
|
|
444
|
+
* The limit must be between 1 and 10 (inclusive).
|
|
388
445
|
*/
|
|
389
446
|
declare class InvalidLimitError extends Error {
|
|
390
447
|
constructor(limit: number, min?: number, max?: number);
|
|
391
448
|
}
|
|
392
449
|
/**
|
|
393
|
-
*
|
|
450
|
+
* Error thrown when attempting to process a message that has already been successfully processed.
|
|
394
451
|
*/
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
* The queue name extracted from Vqs-Queue-Name header
|
|
398
|
-
*/
|
|
399
|
-
queueName: string;
|
|
400
|
-
/**
|
|
401
|
-
* The consumer group extracted from Vqs-Consumer-Group header
|
|
402
|
-
*/
|
|
403
|
-
consumerGroup: string;
|
|
404
|
-
/**
|
|
405
|
-
* The message ID extracted from Vqs-Message-Id header
|
|
406
|
-
*/
|
|
407
|
-
messageId: string;
|
|
452
|
+
declare class MessageAlreadyProcessedError extends Error {
|
|
453
|
+
constructor(messageId: string);
|
|
408
454
|
}
|
|
409
455
|
/**
|
|
410
|
-
* Error thrown when
|
|
456
|
+
* Error thrown when a duplicate idempotency key is detected.
|
|
457
|
+
* The message was already sent within the deduplication window.
|
|
411
458
|
*/
|
|
412
|
-
declare class
|
|
413
|
-
|
|
459
|
+
declare class DuplicateMessageError extends Error {
|
|
460
|
+
readonly idempotencyKey?: string;
|
|
461
|
+
constructor(message: string, idempotencyKey?: string);
|
|
414
462
|
}
|
|
415
|
-
|
|
416
463
|
/**
|
|
417
|
-
*
|
|
464
|
+
* Error thrown when consumer discovery fails.
|
|
465
|
+
* This typically means the deployment could not be reached or is not configured correctly.
|
|
418
466
|
*/
|
|
419
|
-
declare class
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Internal default instance for use by createTopic and other convenience functions
|
|
424
|
-
* @internal
|
|
425
|
-
*/
|
|
426
|
-
private static _defaultInstance;
|
|
427
|
-
/**
|
|
428
|
-
* Create a new Vercel Queue Service client
|
|
429
|
-
* @param options Client configuration options (optional - will auto-detect Vercel Function environment)
|
|
430
|
-
*/
|
|
431
|
-
constructor(options?: QueueClientOptions);
|
|
432
|
-
/**
|
|
433
|
-
* Get the default client instance for internal use by convenience functions
|
|
434
|
-
* @internal
|
|
435
|
-
*/
|
|
436
|
-
static _getDefaultInstance(): QueueClient;
|
|
437
|
-
/**
|
|
438
|
-
* Synchronously get OIDC token from environment
|
|
439
|
-
* Used internally by constructor - mirrors the logic from getVercelOidcToken but synchronously
|
|
440
|
-
*/
|
|
441
|
-
private getVercelOidcTokenSync;
|
|
442
|
-
/**
|
|
443
|
-
* Send a message to a queue
|
|
444
|
-
* @param options Send message options
|
|
445
|
-
* @param transport Serializer/deserializer for the payload
|
|
446
|
-
* @returns Promise with the message ID
|
|
447
|
-
* @throws {BadRequestError} When request parameters are invalid
|
|
448
|
-
* @throws {UnauthorizedError} When authentication fails
|
|
449
|
-
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
450
|
-
* @throws {InternalServerError} When server encounters an error
|
|
451
|
-
*/
|
|
452
|
-
sendMessage<T = unknown>(options: SendMessageOptions<T>, transport: Transport<T>): Promise<SendMessageResponse>;
|
|
453
|
-
/**
|
|
454
|
-
* Receive messages from a queue
|
|
455
|
-
* @param options Receive messages options
|
|
456
|
-
* @param transport Serializer/deserializer for the payload
|
|
457
|
-
* @returns AsyncGenerator that yields messages as they arrive
|
|
458
|
-
* @throws {InvalidLimitError} When limit parameter is not between 1 and 10
|
|
459
|
-
* @throws {QueueEmptyError} When no messages are available (204)
|
|
460
|
-
* @throws {MessageLockedError} When FIFO queue has locked messages (423)
|
|
461
|
-
* @throws {BadRequestError} When request parameters are invalid
|
|
462
|
-
* @throws {UnauthorizedError} When authentication fails
|
|
463
|
-
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
464
|
-
* @throws {InternalServerError} When server encounters an error
|
|
465
|
-
*/
|
|
466
|
-
receiveMessages<T = unknown>(options: ReceiveMessagesOptions<T>, transport: Transport<T>): AsyncGenerator<Message<T>, void, unknown>;
|
|
467
|
-
/**
|
|
468
|
-
* Receive a specific message by its ID from a queue
|
|
469
|
-
* @param options Receive message by ID options
|
|
470
|
-
* @param transport Serializer/deserializer for the payload
|
|
471
|
-
* @returns Promise with the message or null if not found/available
|
|
472
|
-
* @throws {MessageNotFoundError} When the message doesn't exist (404)
|
|
473
|
-
* @throws {MessageLockedError} When the message is temporarily locked (423)
|
|
474
|
-
* @throws {FailedDependencyError} When FIFO ordering is violated (424)
|
|
475
|
-
* @throws {MessageNotAvailableError} When message exists but isn't available (409)
|
|
476
|
-
* @throws {MessageCorruptedError} When message data is corrupted
|
|
477
|
-
* @throws {BadRequestError} When request parameters are invalid
|
|
478
|
-
* @throws {UnauthorizedError} When authentication fails
|
|
479
|
-
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
480
|
-
* @throws {InternalServerError} When server encounters an error
|
|
481
|
-
*/
|
|
482
|
-
receiveMessageById<T = unknown>(options: ReceiveMessageByIdOptions<T> & {
|
|
483
|
-
skipPayload: true;
|
|
484
|
-
}, transport?: Transport<T>): Promise<ReceiveMessageByIdResponse<T, true>>;
|
|
485
|
-
receiveMessageById<T = unknown>(options: ReceiveMessageByIdOptions<T> & {
|
|
486
|
-
skipPayload?: false | undefined;
|
|
487
|
-
}, transport: Transport<T>): Promise<ReceiveMessageByIdResponse<T, false>>;
|
|
488
|
-
/**
|
|
489
|
-
* Delete a message (acknowledge processing)
|
|
490
|
-
* @param options Delete message options
|
|
491
|
-
* @returns Promise with delete status
|
|
492
|
-
* @throws {MessageNotFoundError} When the message doesn't exist (404)
|
|
493
|
-
* @throws {MessageNotAvailableError} When message can't be deleted (409)
|
|
494
|
-
* @throws {BadRequestError} When ticket is missing or invalid (400)
|
|
495
|
-
* @throws {UnauthorizedError} When authentication fails
|
|
496
|
-
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
497
|
-
* @throws {InternalServerError} When server encounters an error
|
|
498
|
-
*/
|
|
499
|
-
deleteMessage(options: DeleteMessageOptions): Promise<DeleteMessageResponse>;
|
|
500
|
-
/**
|
|
501
|
-
* Change the visibility timeout of a message
|
|
502
|
-
* @param options Change visibility options
|
|
503
|
-
* @returns Promise with update status
|
|
504
|
-
* @throws {MessageNotFoundError} When the message doesn't exist (404)
|
|
505
|
-
* @throws {MessageNotAvailableError} When message can't be updated (409)
|
|
506
|
-
* @throws {BadRequestError} When ticket is missing or visibility timeout invalid (400)
|
|
507
|
-
* @throws {UnauthorizedError} When authentication fails
|
|
508
|
-
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
509
|
-
* @throws {InternalServerError} When server encounters an error
|
|
510
|
-
*/
|
|
511
|
-
changeVisibility(options: ChangeVisibilityOptions): Promise<ChangeVisibilityResponse>;
|
|
467
|
+
declare class ConsumerDiscoveryError extends Error {
|
|
468
|
+
readonly deploymentId?: string;
|
|
469
|
+
constructor(message: string, deploymentId?: string);
|
|
512
470
|
}
|
|
513
|
-
|
|
514
471
|
/**
|
|
515
|
-
*
|
|
472
|
+
* Error thrown when the consumer registry is not configured for the project.
|
|
516
473
|
*/
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
messageId?: string;
|
|
520
|
-
/** Whether to skip downloading the payload (only allowed when messageId is provided) */
|
|
521
|
-
skipPayload?: boolean;
|
|
474
|
+
declare class ConsumerRegistryNotConfiguredError extends Error {
|
|
475
|
+
constructor(message?: string);
|
|
522
476
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
declare class ConsumerGroup<T = unknown> {
|
|
527
|
-
private client;
|
|
528
|
-
private topicName;
|
|
529
|
-
private consumerGroupName;
|
|
530
|
-
private visibilityTimeout;
|
|
531
|
-
private refreshInterval;
|
|
532
|
-
private transport;
|
|
477
|
+
|
|
478
|
+
declare class QueueClient {
|
|
479
|
+
constructor(options: QueueClientOptions);
|
|
533
480
|
/**
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
481
|
+
* Send a message to a topic.
|
|
482
|
+
*
|
|
483
|
+
* This is an arrow function property so it can be destructured:
|
|
484
|
+
* ```typescript
|
|
485
|
+
* const { send } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
486
|
+
* await send("my-topic", payload);
|
|
487
|
+
* ```
|
|
488
|
+
*
|
|
489
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
490
|
+
* @param payload - The data to send (serialized via the configured transport)
|
|
491
|
+
* @param options - Optional send options (idempotencyKey, retentionSeconds, delaySeconds, headers)
|
|
492
|
+
* @returns `{ messageId }` — `messageId` is `null` when the server accepted
|
|
493
|
+
* the message for deferred processing (no ID available yet)
|
|
539
494
|
*/
|
|
540
|
-
|
|
495
|
+
send: <T = unknown>(topicName: string, payload: T, options?: SendOptions) => Promise<SendResult>;
|
|
541
496
|
/**
|
|
542
|
-
*
|
|
543
|
-
* This prevents the message from becoming visible to other consumers while it's being processed.
|
|
497
|
+
* Receive and process messages from a topic.
|
|
544
498
|
*
|
|
545
|
-
*
|
|
546
|
-
*
|
|
499
|
+
* Each message is automatically locked, kept alive via periodic visibility
|
|
500
|
+
* extensions during processing, and acknowledged upon successful handler completion.
|
|
501
|
+
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
547
502
|
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
503
|
+
* This is an arrow function property so it can be destructured:
|
|
504
|
+
* ```typescript
|
|
505
|
+
* const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
506
|
+
* const result = await receive("my-topic", "my-group", handler);
|
|
507
|
+
* if (!result.ok) console.log(result.reason);
|
|
508
|
+
* ```
|
|
551
509
|
*
|
|
552
|
-
* @
|
|
553
|
-
* -
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*/
|
|
559
|
-
private startVisibilityExtension;
|
|
560
|
-
/**
|
|
561
|
-
* Process a single message with the given handler
|
|
562
|
-
* @param message The message to process
|
|
563
|
-
* @param handler Function to process the message
|
|
564
|
-
*/
|
|
565
|
-
private processMessage;
|
|
566
|
-
/**
|
|
567
|
-
* Consume the next available message from the queue
|
|
568
|
-
* @param handler Function to process the message
|
|
569
|
-
* @returns Promise that resolves when the message is processed
|
|
570
|
-
* @throws All the same errors as the underlying client methods
|
|
571
|
-
*/
|
|
572
|
-
consume(handler: MessageHandler<T>): Promise<void>;
|
|
573
|
-
/**
|
|
574
|
-
* Consume a specific message by its ID with full payload
|
|
575
|
-
* @param handler Function to process the message
|
|
576
|
-
* @param options Consume options with messageId specified
|
|
577
|
-
* @returns Promise that resolves when the message is processed
|
|
578
|
-
* @throws All the same errors as the underlying client methods
|
|
579
|
-
*/
|
|
580
|
-
consume(handler: MessageHandler<T>, options: {
|
|
581
|
-
messageId: string;
|
|
582
|
-
skipPayload?: false | undefined;
|
|
583
|
-
}): Promise<void>;
|
|
584
|
-
/**
|
|
585
|
-
* Consume a specific message by its ID without downloading the payload (metadata only)
|
|
586
|
-
* @param handler Function to process the message metadata (payload will be void)
|
|
587
|
-
* @param options Consume options with messageId and skipPayload specified
|
|
588
|
-
* @returns Promise that resolves when the message is processed
|
|
589
|
-
* @throws All the same errors as the underlying client methods
|
|
510
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
511
|
+
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
512
|
+
* @param handler - Function to process each message payload and metadata.
|
|
513
|
+
* Not called when the queue is empty.
|
|
514
|
+
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
515
|
+
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
590
516
|
*/
|
|
591
|
-
|
|
592
|
-
messageId: string;
|
|
593
|
-
skipPayload: true;
|
|
594
|
-
}): Promise<void>;
|
|
517
|
+
receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
|
|
595
518
|
/**
|
|
596
|
-
*
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
*
|
|
601
|
-
|
|
602
|
-
|
|
519
|
+
* Create a Web API route handler for processing queue callback messages.
|
|
520
|
+
*
|
|
521
|
+
* Parses incoming `Request` as a CloudEvent and invokes the handler.
|
|
522
|
+
* For use on Vercel — Vercel invokes this route when messages are available.
|
|
523
|
+
*
|
|
524
|
+
* This is an arrow function property so it can be destructured:
|
|
525
|
+
* ```typescript
|
|
526
|
+
* const { handleCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
527
|
+
* export const POST = handleCallback(handler);
|
|
528
|
+
* ```
|
|
529
|
+
*
|
|
530
|
+
* @param handler - Function to process the message payload and metadata
|
|
531
|
+
* @param options - Optional configuration
|
|
532
|
+
* @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)
|
|
533
|
+
* @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to
|
|
534
|
+
* reschedule the message for redelivery after N seconds.
|
|
535
|
+
* @returns A `(request: Request) => Promise<Response>` route handler
|
|
536
|
+
*/
|
|
537
|
+
handleCallback: <T = unknown>(handler: MessageHandler<T>, options?: {
|
|
538
|
+
visibilityTimeoutSeconds?: number;
|
|
539
|
+
retry?: RetryHandler;
|
|
540
|
+
}) => ((request: Request) => Promise<Response>);
|
|
541
|
+
/**
|
|
542
|
+
* Create a Connect-style route handler for processing queue callback messages.
|
|
543
|
+
* For use on Vercel — Vercel invokes this route when messages are available.
|
|
544
|
+
*
|
|
545
|
+
* For frameworks using the `(req, res)` middleware pattern where `req.body`
|
|
546
|
+
* is pre-parsed (Next.js Pages Router, etc.).
|
|
547
|
+
*
|
|
548
|
+
* This is an arrow function property so it can be destructured:
|
|
549
|
+
* ```typescript
|
|
550
|
+
* const { handleNodeCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
551
|
+
* app.post("/api/queue", handleNodeCallback(handler));
|
|
552
|
+
* ```
|
|
553
|
+
*
|
|
554
|
+
* @param handler - Function to process the message payload and metadata
|
|
555
|
+
* @param options - Optional configuration
|
|
556
|
+
* @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)
|
|
557
|
+
* @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to
|
|
558
|
+
* reschedule the message for redelivery after N seconds.
|
|
559
|
+
* @returns A `(req, res) => Promise<void>` route handler
|
|
560
|
+
*/
|
|
561
|
+
handleNodeCallback: <T = unknown>(handler: MessageHandler<T>, options?: {
|
|
562
|
+
visibilityTimeoutSeconds?: number;
|
|
563
|
+
retry?: RetryHandler;
|
|
564
|
+
}) => ((req: {
|
|
565
|
+
method?: string;
|
|
566
|
+
headers: Record<string, string | string[] | undefined>;
|
|
567
|
+
body?: unknown;
|
|
568
|
+
}, res: {
|
|
569
|
+
status(code: number): {
|
|
570
|
+
json(data: unknown): void;
|
|
571
|
+
end(): void;
|
|
572
|
+
};
|
|
573
|
+
end(): void;
|
|
574
|
+
}) => Promise<void>);
|
|
603
575
|
}
|
|
604
576
|
|
|
605
577
|
/**
|
|
606
|
-
*
|
|
578
|
+
* Core queue callback utilities for handling incoming webhook payloads
|
|
579
|
+
* from Vercel triggers using the CloudEvent specification.
|
|
580
|
+
*
|
|
581
|
+
* This module provides the framework-agnostic core. For framework-specific
|
|
582
|
+
* wrappers, see `@vercel/queue/web` and `@vercel/queue/nextjs/pages`.
|
|
607
583
|
*/
|
|
608
|
-
declare class Topic<T = unknown> {
|
|
609
|
-
private client;
|
|
610
|
-
private topicName;
|
|
611
|
-
private transport;
|
|
612
|
-
/**
|
|
613
|
-
* Create a new Topic instance
|
|
614
|
-
* @param client QueueClient instance to use for API calls
|
|
615
|
-
* @param topicName Name of the topic to work with
|
|
616
|
-
* @param transport Optional serializer/deserializer for the payload (defaults to JSON)
|
|
617
|
-
*/
|
|
618
|
-
constructor(client: QueueClient, topicName: string, transport?: Transport<T>);
|
|
619
|
-
/**
|
|
620
|
-
* Publish a message to the topic
|
|
621
|
-
* @param payload The data to publish
|
|
622
|
-
* @param options Optional publish options
|
|
623
|
-
* @returns An object containing the message ID
|
|
624
|
-
* @throws {BadRequestError} When request parameters are invalid
|
|
625
|
-
* @throws {UnauthorizedError} When authentication fails
|
|
626
|
-
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
627
|
-
* @throws {InternalServerError} When server encounters an error
|
|
628
|
-
*/
|
|
629
|
-
publish(payload: T, options?: PublishOptions): Promise<{
|
|
630
|
-
messageId: string;
|
|
631
|
-
}>;
|
|
632
|
-
/**
|
|
633
|
-
* Create a consumer group for this topic
|
|
634
|
-
* @param consumerGroupName Name of the consumer group
|
|
635
|
-
* @param options Optional configuration for the consumer group
|
|
636
|
-
* @returns A ConsumerGroup instance
|
|
637
|
-
*/
|
|
638
|
-
consumerGroup<U = T>(consumerGroupName: string, options?: ConsumerGroupOptions<U>): ConsumerGroup<U>;
|
|
639
|
-
/**
|
|
640
|
-
* Get the topic name
|
|
641
|
-
*/
|
|
642
|
-
get name(): string;
|
|
643
|
-
/**
|
|
644
|
-
* Get the transport used by this topic
|
|
645
|
-
*/
|
|
646
|
-
get serializer(): Transport<T>;
|
|
647
|
-
}
|
|
648
584
|
|
|
585
|
+
declare const CLOUD_EVENT_TYPE_V1BETA = "com.vercel.queue.v1beta";
|
|
586
|
+
declare const CLOUD_EVENT_TYPE_V2BETA = "com.vercel.queue.v2beta";
|
|
649
587
|
/**
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
* @param topicName Name of the topic
|
|
653
|
-
* @param transport Optional serializer/deserializer for the payload (defaults to JSON)
|
|
654
|
-
* @returns A Topic instance
|
|
588
|
+
* Routing-only callback: the SDK must fetch the message by ID.
|
|
589
|
+
* Produced by v1beta structured mode and v2beta large-body mode.
|
|
655
590
|
*/
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
*/
|
|
660
|
-
interface SendOptions<T = unknown> extends PublishOptions {
|
|
661
|
-
/**
|
|
662
|
-
* Serializer/deserializer for the payload
|
|
663
|
-
* @default JsonTransport instance
|
|
664
|
-
*/
|
|
665
|
-
transport?: Transport<T>;
|
|
666
|
-
}
|
|
667
|
-
/**
|
|
668
|
-
* Send a message to a topic (shorthand for topic creation and publishing)
|
|
669
|
-
* Uses the default QueueClient with automatic OIDC token detection
|
|
670
|
-
* @param topicName Name of the topic to send to
|
|
671
|
-
* @param payload The data to send
|
|
672
|
-
* @param options Optional send options including transport and publish settings
|
|
673
|
-
* @returns Promise with the message ID
|
|
674
|
-
* @throws {BadRequestError} When request parameters are invalid
|
|
675
|
-
* @throws {UnauthorizedError} When authentication fails
|
|
676
|
-
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
677
|
-
* @throws {InternalServerError} When server encounters an error
|
|
678
|
-
*/
|
|
679
|
-
declare function send<T = unknown>(topicName: string, payload: T, options?: SendOptions<T>): Promise<{
|
|
591
|
+
type ParsedCallbackV1 = {
|
|
592
|
+
queueName: string;
|
|
593
|
+
consumerGroup: string;
|
|
680
594
|
messageId: string;
|
|
681
|
-
|
|
595
|
+
region?: string;
|
|
596
|
+
};
|
|
682
597
|
/**
|
|
683
|
-
*
|
|
598
|
+
* Full-message callback: payload and receipt handle are inlined,
|
|
599
|
+
* so the SDK can process directly without an extra fetch.
|
|
600
|
+
* Produced by v2beta small-body mode.
|
|
684
601
|
*/
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
* Receive a message from a topic (shorthand for topic and consumer group creation)
|
|
689
|
-
* Uses the default QueueClient with automatic OIDC token detection
|
|
690
|
-
* @param topicName Name of the topic to receive from
|
|
691
|
-
* @param consumerGroup Name of the consumer group
|
|
692
|
-
* @param handler Function to process the message
|
|
693
|
-
* @returns Promise that resolves when the message is processed
|
|
694
|
-
* @throws All the same errors as the underlying client methods
|
|
695
|
-
*/
|
|
696
|
-
declare function receive<T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions<T>): Promise<void>;
|
|
697
|
-
/**
|
|
698
|
-
* Receive a specific message by its ID with full payload
|
|
699
|
-
* @param topicName Name of the topic to receive from
|
|
700
|
-
* @param consumerGroup Name of the consumer group
|
|
701
|
-
* @param handler Function to process the message
|
|
702
|
-
* @param options Receive options with messageId specified
|
|
703
|
-
* @returns Promise that resolves when the message is processed
|
|
704
|
-
* @throws All the same errors as the underlying client methods
|
|
705
|
-
*/
|
|
706
|
-
declare function receive<T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options: ReceiveOptions<T> & {
|
|
707
|
-
messageId: string;
|
|
708
|
-
skipPayload?: false | undefined;
|
|
709
|
-
}): Promise<void>;
|
|
710
|
-
/**
|
|
711
|
-
* Receive a specific message by its ID without downloading the payload (metadata only)
|
|
712
|
-
* @param topicName Name of the topic to receive from
|
|
713
|
-
* @param consumerGroup Name of the consumer group
|
|
714
|
-
* @param handler Function to process the message metadata (payload will be void)
|
|
715
|
-
* @param options Receive options with messageId and skipPayload specified
|
|
716
|
-
* @returns Promise that resolves when the message is processed
|
|
717
|
-
* @throws All the same errors as the underlying client methods
|
|
718
|
-
*/
|
|
719
|
-
declare function receive<T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<void>, options: ReceiveOptions<T> & {
|
|
602
|
+
type ParsedCallbackV2 = {
|
|
603
|
+
queueName: string;
|
|
604
|
+
consumerGroup: string;
|
|
720
605
|
messageId: string;
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
606
|
+
region?: string;
|
|
607
|
+
receiptHandle: string;
|
|
608
|
+
deliveryCount?: number;
|
|
609
|
+
createdAt?: string;
|
|
610
|
+
expiresAt?: string;
|
|
611
|
+
contentType?: string;
|
|
612
|
+
visibilityDeadline?: string;
|
|
613
|
+
rawBody?: ReadableStream<Uint8Array>;
|
|
614
|
+
parsedPayload?: unknown;
|
|
615
|
+
};
|
|
616
|
+
type ParsedCallbackRequest = ParsedCallbackV1 | ParsedCallbackV2;
|
|
728
617
|
/**
|
|
729
|
-
* Parse a
|
|
618
|
+
* Parse a callback from a pre-parsed body and headers.
|
|
730
619
|
*
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
* @throws {InvalidCallbackError} When required queue headers are missing or invalid
|
|
620
|
+
* For frameworks like Next.js Pages Router where the body has already been
|
|
621
|
+
* parsed, use this instead of {@link parseCallback}.
|
|
734
622
|
*
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
*
|
|
623
|
+
* Detects the CloudEvent version from the `ce-type` header:
|
|
624
|
+
* - `com.vercel.queue.v2beta`: binary content mode (metadata in headers,
|
|
625
|
+
* payload in body). For small messages, the body is attached as `parsedPayload`.
|
|
626
|
+
* - Otherwise: structured content mode (v1beta, entire CloudEvent in JSON body)
|
|
738
627
|
*
|
|
739
|
-
*
|
|
740
|
-
*
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
745
|
-
* const message = await client.receiveMessageById({
|
|
746
|
-
* ...callbackOptions,
|
|
747
|
-
* visibilityTimeoutSeconds: 30
|
|
748
|
-
* }, transport);
|
|
749
|
-
*
|
|
750
|
-
* // Process the message...
|
|
751
|
-
* } catch (error) {
|
|
752
|
-
* if (error instanceof InvalidCallbackError) {
|
|
753
|
-
* return new Response('Invalid callback', { status: 400 });
|
|
754
|
-
* }
|
|
755
|
-
* throw error;
|
|
756
|
-
* }
|
|
757
|
-
* }
|
|
758
|
-
* ```
|
|
628
|
+
* @param body - The framework-parsed request body. Type depends on Content-Type
|
|
629
|
+
* and framework configuration:
|
|
630
|
+
* - v1beta: parsed CloudEvent JSON object
|
|
631
|
+
* - v2beta: the message payload as parsed by the framework (object, Buffer, or string)
|
|
632
|
+
* @param headers - HTTP headers
|
|
633
|
+
* @returns Parsed callback request with routing metadata and optional payload
|
|
759
634
|
*/
|
|
760
|
-
declare function
|
|
761
|
-
/**
|
|
762
|
-
* Configuration object with handlers for different topics
|
|
763
|
-
* Each topic can have either:
|
|
764
|
-
* - A single handler function (uses 'default' consumer group)
|
|
765
|
-
* - An object with handlers for specific consumer groups
|
|
766
|
-
*/
|
|
767
|
-
type CallbackHandlers = {
|
|
768
|
-
[topicName: string]: MessageHandler | {
|
|
769
|
-
[consumerGroup: string]: MessageHandler;
|
|
770
|
-
};
|
|
771
|
-
};
|
|
635
|
+
declare function parseRawCallback(body: unknown, headers: Record<string, string | string[] | undefined>): ParsedCallbackRequest;
|
|
772
636
|
/**
|
|
773
|
-
*
|
|
637
|
+
* Parse and validate a CloudEvent callback from a Web API `Request` object.
|
|
774
638
|
*
|
|
775
|
-
*
|
|
776
|
-
*
|
|
639
|
+
* Detects the CloudEvent version from the `ce-type` header:
|
|
640
|
+
* - `com.vercel.queue.v2beta`: binary content mode (metadata in headers,
|
|
641
|
+
* payload in body). For v2beta, the body is attached as `rawBody` (a
|
|
642
|
+
* ReadableStream) rather than being parsed.
|
|
643
|
+
* - Otherwise: structured content mode (v1beta, entire CloudEvent in JSON body)
|
|
777
644
|
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
780
|
-
* // Topic handler (uses 'default' consumer group)
|
|
781
|
-
* export const POST = handleCallback({
|
|
782
|
-
* "new-users": (message, metadata) => {
|
|
783
|
-
* console.log(`New user event:`, message, metadata);
|
|
784
|
-
* }
|
|
785
|
-
* });
|
|
786
|
-
*
|
|
787
|
-
* // Consumer group specific handlers
|
|
788
|
-
* export const POST = handleCallback({
|
|
789
|
-
* "image-processing": {
|
|
790
|
-
* "compress": (message, metadata) => console.log("Compressing image", message),
|
|
791
|
-
* "resize": (message, metadata) => console.log("Resizing image", message),
|
|
792
|
-
* }
|
|
793
|
-
* });
|
|
794
|
-
* ```
|
|
645
|
+
* For frameworks that pre-parse the body (e.g. Next.js Pages Router),
|
|
646
|
+
* use {@link parseRawCallback} instead.
|
|
795
647
|
*/
|
|
796
|
-
declare function
|
|
648
|
+
declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
|
|
797
649
|
|
|
798
|
-
export { BadRequestError,
|
|
650
|
+
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 };
|