@vercel/queue 0.0.0-alpha.9 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +478 -603
- package/dist/index.d.mts +497 -188
- package/dist/index.d.ts +497 -188
- package/dist/index.js +1419 -765
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1395 -757
- 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
|
-
* This is ideal for large payloads that don't need to be buffered in memory
|
|
88
|
+
* Pass-through stream serializer/deserializer.
|
|
44
89
|
*
|
|
45
|
-
*
|
|
46
|
-
* processing the message to prevent resource leaks, especially in error cases.
|
|
47
|
-
* ConsumerGroup handles this automatically, but direct QueueClient usage requires manual cleanup.
|
|
90
|
+
* Ideal for large files and real-time streams. Does not buffer data in memory.
|
|
48
91
|
*
|
|
49
|
-
*
|
|
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.
|
|
95
|
+
*
|
|
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
|
|
|
@@ -72,120 +123,292 @@ declare class StreamTransport implements Transport<ReadableStream<Uint8Array>> {
|
|
|
72
123
|
*/
|
|
73
124
|
|
|
74
125
|
/**
|
|
75
|
-
*
|
|
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 {@link URL} for the Vercel Queue Service API.
|
|
134
|
+
*
|
|
135
|
+
* The SDK appends its own API path (`/api/v3/…`) to the returned URL.
|
|
136
|
+
* To add a prefix (e.g. when routing through a reverse proxy), include it
|
|
137
|
+
* in the pathname of the returned URL:
|
|
138
|
+
*
|
|
139
|
+
* ```ts
|
|
140
|
+
* // Default — domain only, no prefix:
|
|
141
|
+
* (region) => new URL(`https://${region}.vercel-queue.com`)
|
|
142
|
+
*
|
|
143
|
+
* // Custom domain with a base path:
|
|
144
|
+
* (region) => new URL(`https://my-proxy.example/custom-prefix`)
|
|
145
|
+
* // → requests go to https://my-proxy.example/custom-prefix/api/v3/…
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* Default: `` (region) => new URL(`https://${region}.vercel-queue.com`) ``
|
|
76
149
|
*/
|
|
77
|
-
|
|
150
|
+
type BaseUrlResolver = (region: string) => URL;
|
|
151
|
+
interface QueueClientOptions {
|
|
152
|
+
/**
|
|
153
|
+
* Vercel region code for API routing.
|
|
154
|
+
*
|
|
155
|
+
* Requests are sent to the regional endpoint resolved by
|
|
156
|
+
* {@link BaseUrlResolver} (default: `https://${region}.vercel-queue.com`).
|
|
157
|
+
*
|
|
158
|
+
* Use a `QUEUE_REGION` env var set to `${VERCEL_REGION}` in production
|
|
159
|
+
* and a fixed region (e.g. `"iad1"`) in development.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* new QueueClient({ region: process.env.QUEUE_REGION! })
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
region: VercelRegion;
|
|
78
167
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
168
|
+
* Custom resolver that maps a region code to a base {@link URL}.
|
|
169
|
+
*
|
|
170
|
+
* The SDK always appends its own API path (`/api/v3/…`) to the returned URL.
|
|
171
|
+
* Include a pathname to add a prefix (e.g. for reverse-proxy routing):
|
|
172
|
+
*
|
|
173
|
+
* ```ts
|
|
174
|
+
* resolveBaseUrl: (region) => new URL(`https://my-proxy.example/prefix`)
|
|
175
|
+
* ```
|
|
176
|
+
*
|
|
177
|
+
* @default (region) => new URL(`https://${region}.vercel-queue.com`)
|
|
178
|
+
*/
|
|
179
|
+
resolveBaseUrl?: BaseUrlResolver;
|
|
180
|
+
/**
|
|
181
|
+
* Authentication token for the Vercel Queue Service API.
|
|
182
|
+
* If not provided, the client will attempt to get a token via OIDC
|
|
183
|
+
* when running in a Vercel Function environment.
|
|
184
|
+
*/
|
|
185
|
+
token?: string;
|
|
186
|
+
/**
|
|
187
|
+
* Custom headers to include in all requests.
|
|
188
|
+
*/
|
|
189
|
+
headers?: Record<string, string>;
|
|
190
|
+
/**
|
|
191
|
+
* Deployment ID for message routing and lease validation.
|
|
192
|
+
*
|
|
193
|
+
* - `undefined` (default): auto-detect from `VERCEL_DEPLOYMENT_ID` env var;
|
|
194
|
+
* sent messages are pinned to this deployment.
|
|
195
|
+
* - `null`: explicitly unpinned — no deployment ID is sent on any request.
|
|
196
|
+
* - `"dpl_xxx"`: explicit value used for both send pinning and consume identification.
|
|
197
|
+
*
|
|
198
|
+
* Ignored in development mode (deployment ID is never sent locally).
|
|
199
|
+
*/
|
|
200
|
+
deploymentId?: string | null;
|
|
201
|
+
/**
|
|
202
|
+
* Serializer/deserializer for message payloads.
|
|
203
|
+
* Used for all send and receive operations.
|
|
204
|
+
* @default JsonTransport
|
|
205
|
+
*/
|
|
206
|
+
transport?: Transport;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Options for sending messages.
|
|
210
|
+
*/
|
|
211
|
+
interface SendOptions {
|
|
212
|
+
/**
|
|
213
|
+
* Unique key to prevent duplicate message submissions.
|
|
214
|
+
* Deduplication window: `min(message retention, 24 hours)`.
|
|
81
215
|
*/
|
|
82
216
|
idempotencyKey?: string;
|
|
83
217
|
/**
|
|
84
|
-
* Message retention time in seconds
|
|
218
|
+
* Message retention time in seconds. After this period, the message expires.
|
|
85
219
|
* @default 86400 (24 hours)
|
|
86
|
-
* @
|
|
87
|
-
* @
|
|
220
|
+
* @minimum 60 (1 minute)
|
|
221
|
+
* @maximum 86400 (24 hours)
|
|
88
222
|
*/
|
|
89
223
|
retentionSeconds?: number;
|
|
90
|
-
}
|
|
91
|
-
interface SendMessageOptions<T = unknown> extends PublishOptions {
|
|
92
224
|
/**
|
|
93
|
-
*
|
|
225
|
+
* Delay delivery of the message by this many seconds.
|
|
226
|
+
* The message will not be visible to consumers until the delay has passed.
|
|
227
|
+
* @default 0
|
|
228
|
+
* @minimum 0
|
|
229
|
+
* @maximum Value of retentionSeconds (delay cannot exceed retention)
|
|
94
230
|
*/
|
|
95
|
-
|
|
231
|
+
delaySeconds?: number;
|
|
96
232
|
/**
|
|
97
|
-
*
|
|
233
|
+
* Custom headers to include with this message.
|
|
234
|
+
* These headers are passed through to the VQS server.
|
|
98
235
|
*/
|
|
99
|
-
|
|
236
|
+
headers?: Record<string, string>;
|
|
100
237
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
238
|
+
/**
|
|
239
|
+
* Result returned by `send()`.
|
|
240
|
+
*
|
|
241
|
+
* `messageId` is `null` when the server accepted the message for deferred
|
|
242
|
+
* processing (e.g. during a server-side outage) and no ID is available yet.
|
|
243
|
+
*/
|
|
244
|
+
interface SendResult {
|
|
245
|
+
messageId: string | null;
|
|
106
246
|
}
|
|
107
247
|
interface Message<T = unknown> {
|
|
108
248
|
/**
|
|
109
|
-
*
|
|
249
|
+
* Unique message identifier. Used for receive-by-ID operations.
|
|
110
250
|
*/
|
|
111
251
|
messageId: string;
|
|
112
252
|
/**
|
|
113
|
-
* The deserialized message payload
|
|
114
|
-
* Note: If using
|
|
115
|
-
* when done processing, especially in error cases
|
|
253
|
+
* The deserialized message payload.
|
|
254
|
+
* Note: If using StreamTransport, ensure proper cleanup by calling
|
|
255
|
+
* `transport.finalize(payload)` when done processing, especially in error cases.
|
|
116
256
|
*/
|
|
117
257
|
payload: T;
|
|
118
258
|
/**
|
|
119
|
-
* Number of times this message has been delivered
|
|
259
|
+
* Number of times this message has been delivered.
|
|
260
|
+
* Starts at 1 for the first delivery, increments on each retry.
|
|
120
261
|
*/
|
|
121
262
|
deliveryCount: number;
|
|
122
263
|
/**
|
|
123
|
-
* Timestamp when the message was created
|
|
264
|
+
* Timestamp when the message was created/published.
|
|
124
265
|
*/
|
|
125
|
-
|
|
266
|
+
createdAt: Date;
|
|
126
267
|
/**
|
|
127
|
-
*
|
|
268
|
+
* Timestamp when the message expires.
|
|
269
|
+
* Only present for messages delivered via the v2beta binary callback path.
|
|
128
270
|
*/
|
|
129
|
-
|
|
271
|
+
expiresAt?: Date;
|
|
130
272
|
/**
|
|
131
|
-
*
|
|
273
|
+
* MIME type of the message content.
|
|
274
|
+
* Set by the transport's `contentType` property during publish.
|
|
132
275
|
*/
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Result indicating the message should be timed out for retry later
|
|
137
|
-
*/
|
|
138
|
-
interface MessageTimeoutResult {
|
|
276
|
+
contentType: string;
|
|
139
277
|
/**
|
|
140
|
-
*
|
|
278
|
+
* Receipt handle (lease token) for this message delivery.
|
|
279
|
+
* Required for acknowledge and visibility extension operations.
|
|
280
|
+
* Valid only until the visibility timeout expires.
|
|
141
281
|
*/
|
|
142
|
-
|
|
282
|
+
receiptHandle: string;
|
|
143
283
|
}
|
|
144
|
-
/**
|
|
145
|
-
* Result returned by message handlers
|
|
146
|
-
*/
|
|
147
|
-
type MessageHandlerResult = void | MessageTimeoutResult;
|
|
148
284
|
/**
|
|
149
285
|
* Message metadata provided to handlers
|
|
150
286
|
*/
|
|
151
287
|
interface MessageMetadata {
|
|
152
288
|
messageId: string;
|
|
153
289
|
deliveryCount: number;
|
|
154
|
-
|
|
290
|
+
createdAt: Date;
|
|
291
|
+
expiresAt?: Date;
|
|
292
|
+
topicName: string;
|
|
293
|
+
consumerGroup: string;
|
|
294
|
+
/** Vercel region the client is targeting. */
|
|
295
|
+
region: string;
|
|
155
296
|
}
|
|
156
297
|
/**
|
|
157
|
-
*
|
|
298
|
+
* Instruction returned by a {@link RetryHandler} to control what happens
|
|
299
|
+
* to a message when the handler throws.
|
|
300
|
+
*
|
|
301
|
+
* - `{ afterSeconds: N }` — reschedule the message for redelivery after N seconds
|
|
302
|
+
* - `{ acknowledge: true }` — acknowledge the message so it is never retried
|
|
303
|
+
*/
|
|
304
|
+
type RetryDirective = {
|
|
305
|
+
afterSeconds: number;
|
|
306
|
+
} | {
|
|
307
|
+
acknowledge: true;
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Called when the message handler throws an error.
|
|
311
|
+
* Return a {@link RetryDirective} to reschedule or acknowledge the message,
|
|
312
|
+
* or return `undefined` to let the error propagate normally.
|
|
158
313
|
*/
|
|
159
|
-
type
|
|
314
|
+
type RetryHandler = (error: unknown, metadata: MessageMetadata) => RetryDirective | void | undefined;
|
|
160
315
|
/**
|
|
161
|
-
*
|
|
316
|
+
* Message handler function type.
|
|
317
|
+
*
|
|
318
|
+
* Called once per message with the deserialized payload and metadata.
|
|
319
|
+
* Not called when the queue is empty — check the return value of `receive()` instead.
|
|
320
|
+
*/
|
|
321
|
+
type MessageHandler<T = unknown> = (message: T, metadata: MessageMetadata) => Promise<void> | void;
|
|
322
|
+
/**
|
|
323
|
+
* Result returned by `receive()`. Use `ok` to check if messages were processed.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```typescript
|
|
327
|
+
* const result = await receive("topic", "group", handler);
|
|
328
|
+
* if (result.ok) {
|
|
329
|
+
* // Messages were processed successfully
|
|
330
|
+
* } else if (result.reason === "empty") {
|
|
331
|
+
* // Queue had no messages available
|
|
332
|
+
* }
|
|
333
|
+
* ```
|
|
162
334
|
*/
|
|
163
|
-
|
|
335
|
+
type ReceiveResult = {
|
|
336
|
+
ok: true;
|
|
337
|
+
} | {
|
|
338
|
+
ok: false;
|
|
339
|
+
reason: "empty";
|
|
340
|
+
} | {
|
|
341
|
+
ok: false;
|
|
342
|
+
reason: "not_found";
|
|
343
|
+
messageId: string;
|
|
344
|
+
} | {
|
|
345
|
+
ok: false;
|
|
346
|
+
reason: "not_available";
|
|
347
|
+
messageId: string;
|
|
348
|
+
} | {
|
|
349
|
+
ok: false;
|
|
350
|
+
reason: "already_processed";
|
|
351
|
+
messageId: string;
|
|
352
|
+
};
|
|
353
|
+
/**
|
|
354
|
+
* Options for receiving a specific message by ID.
|
|
355
|
+
*/
|
|
356
|
+
interface ReceiveByIdOptions {
|
|
357
|
+
/** The specific message ID to consume */
|
|
358
|
+
messageId: string;
|
|
164
359
|
/**
|
|
165
|
-
*
|
|
166
|
-
* @default
|
|
360
|
+
* Message lock duration in seconds.
|
|
361
|
+
* @default 300 (5 minutes)
|
|
362
|
+
* @minimum 30
|
|
363
|
+
* @maximum 3600 (1 hour)
|
|
167
364
|
*/
|
|
168
|
-
|
|
365
|
+
visibilityTimeoutSeconds?: number;
|
|
169
366
|
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
367
|
+
* Called when the handler throws. Return `{ afterSeconds: N }` to reschedule
|
|
368
|
+
* the message for redelivery after N seconds, or return `undefined`
|
|
369
|
+
* to let the error propagate normally.
|
|
370
|
+
*/
|
|
371
|
+
retry?: RetryHandler;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Options for receiving messages from the queue with an optional batch limit.
|
|
375
|
+
*/
|
|
376
|
+
interface ReceiveBatchOptions {
|
|
377
|
+
/**
|
|
378
|
+
* Maximum number of messages to retrieve in a single request.
|
|
379
|
+
* @default 1
|
|
380
|
+
* @minimum 1
|
|
381
|
+
* @maximum 10
|
|
382
|
+
*/
|
|
383
|
+
limit?: number;
|
|
384
|
+
/**
|
|
385
|
+
* Message lock duration in seconds.
|
|
386
|
+
* @default 300 (5 minutes)
|
|
387
|
+
* @minimum 30
|
|
388
|
+
* @maximum 3600 (1 hour)
|
|
172
389
|
*/
|
|
173
390
|
visibilityTimeoutSeconds?: number;
|
|
174
391
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
392
|
+
* Called when the handler throws. Return `{ afterSeconds: N }` to reschedule
|
|
393
|
+
* the message for redelivery after N seconds, or return `undefined`
|
|
394
|
+
* to let the error propagate normally.
|
|
177
395
|
*/
|
|
178
|
-
|
|
396
|
+
retry?: RetryHandler;
|
|
179
397
|
}
|
|
180
398
|
/**
|
|
181
|
-
*
|
|
399
|
+
* Options for the receive method. Either receive by message ID or receive
|
|
400
|
+
* from the queue with an optional limit. These options are mutually exclusive.
|
|
401
|
+
*/
|
|
402
|
+
type ReceiveOptions = ReceiveByIdOptions | ReceiveBatchOptions;
|
|
403
|
+
/**
|
|
404
|
+
* Error thrown when a message does not exist or has expired.
|
|
182
405
|
*/
|
|
183
406
|
declare class MessageNotFoundError extends Error {
|
|
184
407
|
constructor(messageId: string);
|
|
185
408
|
}
|
|
186
409
|
/**
|
|
187
|
-
* Error thrown when a message
|
|
188
|
-
* This can happen when the message is in the wrong state
|
|
410
|
+
* Error thrown when a message exists but cannot be processed.
|
|
411
|
+
* This can happen when the message is in the wrong state or already claimed by another consumer.
|
|
189
412
|
*/
|
|
190
413
|
declare class MessageNotAvailableError extends Error {
|
|
191
414
|
constructor(messageId: string, reason?: string);
|
|
@@ -197,166 +420,252 @@ declare class MessageCorruptedError extends Error {
|
|
|
197
420
|
constructor(messageId: string, reason: string);
|
|
198
421
|
}
|
|
199
422
|
/**
|
|
200
|
-
* Error thrown when there are no messages available in the queue
|
|
423
|
+
* Error thrown when there are no messages available in the queue.
|
|
201
424
|
*/
|
|
202
425
|
declare class QueueEmptyError extends Error {
|
|
203
426
|
constructor(queueName: string, consumerGroup: string);
|
|
204
427
|
}
|
|
205
428
|
/**
|
|
206
|
-
* Error thrown when a message is temporarily locked
|
|
429
|
+
* Error thrown when a message is temporarily locked by another consumer.
|
|
430
|
+
* The message is currently being processed and cannot be claimed.
|
|
207
431
|
*/
|
|
208
432
|
declare class MessageLockedError extends Error {
|
|
433
|
+
/** Suggested retry delay in seconds, if provided by the server. */
|
|
209
434
|
readonly retryAfter?: number;
|
|
210
435
|
constructor(messageId: string, retryAfter?: number);
|
|
211
436
|
}
|
|
212
437
|
/**
|
|
213
|
-
* Error thrown when authentication fails
|
|
438
|
+
* Error thrown when authentication fails.
|
|
439
|
+
* This typically means the token is missing, invalid, or expired.
|
|
214
440
|
*/
|
|
215
441
|
declare class UnauthorizedError extends Error {
|
|
216
442
|
constructor(message?: string);
|
|
217
443
|
}
|
|
218
444
|
/**
|
|
219
|
-
* Error thrown when access is forbidden
|
|
445
|
+
* Error thrown when access is forbidden.
|
|
446
|
+
* This typically means the queue belongs to a different environment or project.
|
|
220
447
|
*/
|
|
221
448
|
declare class ForbiddenError extends Error {
|
|
222
449
|
constructor(message?: string);
|
|
223
450
|
}
|
|
224
451
|
/**
|
|
225
|
-
* Error thrown
|
|
452
|
+
* Error thrown when request parameters are invalid.
|
|
226
453
|
*/
|
|
227
454
|
declare class BadRequestError extends Error {
|
|
228
455
|
constructor(message: string);
|
|
229
456
|
}
|
|
230
457
|
/**
|
|
231
|
-
* Error thrown
|
|
458
|
+
* Error thrown when the server encounters an unexpected error.
|
|
232
459
|
*/
|
|
233
460
|
declare class InternalServerError extends Error {
|
|
234
461
|
constructor(message?: string);
|
|
235
462
|
}
|
|
236
463
|
/**
|
|
237
|
-
* Error thrown when batch limit parameter is
|
|
464
|
+
* Error thrown when the batch limit parameter is outside the valid range.
|
|
465
|
+
* The limit must be between 1 and 10 (inclusive).
|
|
238
466
|
*/
|
|
239
467
|
declare class InvalidLimitError extends Error {
|
|
240
468
|
constructor(limit: number, min?: number, max?: number);
|
|
241
469
|
}
|
|
242
|
-
|
|
243
470
|
/**
|
|
244
|
-
*
|
|
471
|
+
* Error thrown when attempting to process a message that has already been successfully processed.
|
|
245
472
|
*/
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
messageId?: string;
|
|
249
|
-
/** Whether to skip downloading the payload (only allowed when messageId is provided) */
|
|
250
|
-
skipPayload?: boolean;
|
|
473
|
+
declare class MessageAlreadyProcessedError extends Error {
|
|
474
|
+
constructor(messageId: string);
|
|
251
475
|
}
|
|
252
|
-
|
|
253
476
|
/**
|
|
254
|
-
*
|
|
477
|
+
* Error thrown when a duplicate idempotency key is detected.
|
|
478
|
+
* The message was already sent within the deduplication window.
|
|
255
479
|
*/
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
* @default JsonTransport instance
|
|
260
|
-
*/
|
|
261
|
-
transport?: Transport<T>;
|
|
480
|
+
declare class DuplicateMessageError extends Error {
|
|
481
|
+
readonly idempotencyKey?: string;
|
|
482
|
+
constructor(message: string, idempotencyKey?: string);
|
|
262
483
|
}
|
|
263
484
|
/**
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
* @throws {UnauthorizedError} When authentication fails
|
|
272
|
-
* @throws {ForbiddenError} When access is denied (environment mismatch)
|
|
273
|
-
* @throws {InternalServerError} When server encounters an error
|
|
274
|
-
*/
|
|
275
|
-
declare function send<T = unknown>(topicName: string, payload: T, options?: SendOptions<T>): Promise<{
|
|
276
|
-
messageId: string;
|
|
277
|
-
}>;
|
|
485
|
+
* Error thrown when consumer discovery fails.
|
|
486
|
+
* This typically means the deployment could not be reached or is not configured correctly.
|
|
487
|
+
*/
|
|
488
|
+
declare class ConsumerDiscoveryError extends Error {
|
|
489
|
+
readonly deploymentId?: string;
|
|
490
|
+
constructor(message: string, deploymentId?: string);
|
|
491
|
+
}
|
|
278
492
|
/**
|
|
279
|
-
*
|
|
493
|
+
* Error thrown when the consumer registry is not configured for the project.
|
|
280
494
|
*/
|
|
281
|
-
|
|
495
|
+
declare class ConsumerRegistryNotConfiguredError extends Error {
|
|
496
|
+
constructor(message?: string);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
declare class QueueClient {
|
|
500
|
+
constructor(options: QueueClientOptions);
|
|
501
|
+
/**
|
|
502
|
+
* Send a message to a topic.
|
|
503
|
+
*
|
|
504
|
+
* This is an arrow function property so it can be destructured:
|
|
505
|
+
* ```typescript
|
|
506
|
+
* const { send } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
507
|
+
* await send("my-topic", payload);
|
|
508
|
+
* ```
|
|
509
|
+
*
|
|
510
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
511
|
+
* @param payload - The data to send (serialized via the configured transport)
|
|
512
|
+
* @param options - Optional send options (idempotencyKey, retentionSeconds, delaySeconds, headers)
|
|
513
|
+
* @returns `{ messageId }` — `messageId` is `null` when the server accepted
|
|
514
|
+
* the message for deferred processing (no ID available yet)
|
|
515
|
+
*/
|
|
516
|
+
send: <T = unknown>(topicName: string, payload: T, options?: SendOptions) => Promise<SendResult>;
|
|
517
|
+
/**
|
|
518
|
+
* Receive and process messages from a topic.
|
|
519
|
+
*
|
|
520
|
+
* Each message is automatically locked, kept alive via periodic visibility
|
|
521
|
+
* extensions during processing, and acknowledged upon successful handler completion.
|
|
522
|
+
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
523
|
+
*
|
|
524
|
+
* This is an arrow function property so it can be destructured:
|
|
525
|
+
* ```typescript
|
|
526
|
+
* const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
527
|
+
* const result = await receive("my-topic", "my-group", handler);
|
|
528
|
+
* if (!result.ok) console.log(result.reason);
|
|
529
|
+
* ```
|
|
530
|
+
*
|
|
531
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
532
|
+
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
533
|
+
* @param handler - Function to process each message payload and metadata.
|
|
534
|
+
* Not called when the queue is empty.
|
|
535
|
+
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
536
|
+
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
537
|
+
*/
|
|
538
|
+
receive: <T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions) => Promise<ReceiveResult>;
|
|
539
|
+
/**
|
|
540
|
+
* Create a Web API route handler for processing queue callback messages.
|
|
541
|
+
*
|
|
542
|
+
* Parses incoming `Request` as a CloudEvent and invokes the handler.
|
|
543
|
+
* For use on Vercel — Vercel invokes this route when messages are available.
|
|
544
|
+
*
|
|
545
|
+
* This is an arrow function property so it can be destructured:
|
|
546
|
+
* ```typescript
|
|
547
|
+
* const { handleCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
548
|
+
* export const POST = handleCallback(handler);
|
|
549
|
+
* ```
|
|
550
|
+
*
|
|
551
|
+
* @param handler - Function to process the message payload and metadata
|
|
552
|
+
* @param options - Optional configuration
|
|
553
|
+
* @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)
|
|
554
|
+
* @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to
|
|
555
|
+
* reschedule the message for redelivery after N seconds.
|
|
556
|
+
* @returns A `(request: Request) => Promise<Response>` route handler
|
|
557
|
+
*/
|
|
558
|
+
handleCallback: <T = unknown>(handler: MessageHandler<T>, options?: {
|
|
559
|
+
visibilityTimeoutSeconds?: number;
|
|
560
|
+
retry?: RetryHandler;
|
|
561
|
+
}) => ((request: Request) => Promise<Response>);
|
|
562
|
+
/**
|
|
563
|
+
* Create a Connect-style route handler for processing queue callback messages.
|
|
564
|
+
* For use on Vercel — Vercel invokes this route when messages are available.
|
|
565
|
+
*
|
|
566
|
+
* For frameworks using the `(req, res)` middleware pattern where `req.body`
|
|
567
|
+
* is pre-parsed (Next.js Pages Router, etc.).
|
|
568
|
+
*
|
|
569
|
+
* This is an arrow function property so it can be destructured:
|
|
570
|
+
* ```typescript
|
|
571
|
+
* const { handleNodeCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
572
|
+
* app.post("/api/queue", handleNodeCallback(handler));
|
|
573
|
+
* ```
|
|
574
|
+
*
|
|
575
|
+
* @param handler - Function to process the message payload and metadata
|
|
576
|
+
* @param options - Optional configuration
|
|
577
|
+
* @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)
|
|
578
|
+
* @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to
|
|
579
|
+
* reschedule the message for redelivery after N seconds.
|
|
580
|
+
* @returns A `(req, res) => Promise<void>` route handler
|
|
581
|
+
*/
|
|
582
|
+
handleNodeCallback: <T = unknown>(handler: MessageHandler<T>, options?: {
|
|
583
|
+
visibilityTimeoutSeconds?: number;
|
|
584
|
+
retry?: RetryHandler;
|
|
585
|
+
}) => ((req: {
|
|
586
|
+
method?: string;
|
|
587
|
+
headers: Record<string, string | string[] | undefined>;
|
|
588
|
+
body?: unknown;
|
|
589
|
+
}, res: {
|
|
590
|
+
status(code: number): {
|
|
591
|
+
json(data: unknown): void;
|
|
592
|
+
end(): void;
|
|
593
|
+
};
|
|
594
|
+
end(): void;
|
|
595
|
+
}) => Promise<void>);
|
|
282
596
|
}
|
|
597
|
+
|
|
283
598
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
|
|
290
|
-
* @throws All the same errors as the underlying client methods
|
|
291
|
-
*/
|
|
292
|
-
declare function receive<T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions<T>): Promise<void>;
|
|
293
|
-
/**
|
|
294
|
-
* Receive a specific message by its ID with full payload
|
|
295
|
-
* @param topicName Name of the topic to receive from
|
|
296
|
-
* @param consumerGroup Name of the consumer group
|
|
297
|
-
* @param handler Function to process the message
|
|
298
|
-
* @param options Receive options with messageId specified
|
|
299
|
-
* @returns Promise that resolves when the message is processed
|
|
300
|
-
* @throws All the same errors as the underlying client methods
|
|
301
|
-
*/
|
|
302
|
-
declare function receive<T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options: ReceiveOptions<T> & {
|
|
303
|
-
messageId: string;
|
|
304
|
-
skipPayload?: false | undefined;
|
|
305
|
-
}): Promise<void>;
|
|
306
|
-
/**
|
|
307
|
-
* Receive a specific message by its ID without downloading the payload (metadata only)
|
|
308
|
-
* @param topicName Name of the topic to receive from
|
|
309
|
-
* @param consumerGroup Name of the consumer group
|
|
310
|
-
* @param handler Function to process the message metadata (payload will be void)
|
|
311
|
-
* @param options Receive options with messageId and skipPayload specified
|
|
312
|
-
* @returns Promise that resolves when the message is processed
|
|
313
|
-
* @throws All the same errors as the underlying client methods
|
|
314
|
-
*/
|
|
315
|
-
declare function receive<T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<void>, options: ReceiveOptions<T> & {
|
|
316
|
-
messageId: string;
|
|
317
|
-
skipPayload: true;
|
|
318
|
-
}): Promise<void>;
|
|
599
|
+
* Core queue callback utilities for handling incoming webhook payloads
|
|
600
|
+
* from Vercel triggers using the CloudEvent specification.
|
|
601
|
+
*
|
|
602
|
+
* This module provides the framework-agnostic core. For framework-specific
|
|
603
|
+
* wrappers, see `@vercel/queue/web` and `@vercel/queue/nextjs/pages`.
|
|
604
|
+
*/
|
|
319
605
|
|
|
606
|
+
declare const CLOUD_EVENT_TYPE_V1BETA = "com.vercel.queue.v1beta";
|
|
607
|
+
declare const CLOUD_EVENT_TYPE_V2BETA = "com.vercel.queue.v2beta";
|
|
608
|
+
/**
|
|
609
|
+
* Routing-only callback: the SDK must fetch the message by ID.
|
|
610
|
+
* Produced by v1beta structured mode and v2beta large-body mode.
|
|
611
|
+
*/
|
|
612
|
+
type ParsedCallbackV1 = {
|
|
613
|
+
queueName: string;
|
|
614
|
+
consumerGroup: string;
|
|
615
|
+
messageId: string;
|
|
616
|
+
region?: string;
|
|
617
|
+
};
|
|
320
618
|
/**
|
|
321
|
-
*
|
|
619
|
+
* Full-message callback: payload and receipt handle are inlined,
|
|
620
|
+
* so the SDK can process directly without an extra fetch.
|
|
621
|
+
* Produced by v2beta small-body mode.
|
|
322
622
|
*/
|
|
323
|
-
type
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
623
|
+
type ParsedCallbackV2 = {
|
|
624
|
+
queueName: string;
|
|
625
|
+
consumerGroup: string;
|
|
626
|
+
messageId: string;
|
|
627
|
+
region?: string;
|
|
628
|
+
receiptHandle: string;
|
|
629
|
+
deliveryCount?: number;
|
|
630
|
+
createdAt?: string;
|
|
631
|
+
expiresAt?: string;
|
|
632
|
+
contentType?: string;
|
|
633
|
+
visibilityDeadline?: string;
|
|
634
|
+
rawBody?: ReadableStream<Uint8Array>;
|
|
635
|
+
parsedPayload?: unknown;
|
|
327
636
|
};
|
|
637
|
+
type ParsedCallbackRequest = ParsedCallbackV1 | ParsedCallbackV2;
|
|
328
638
|
/**
|
|
329
|
-
*
|
|
639
|
+
* Parse a callback from a pre-parsed body and headers.
|
|
330
640
|
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
641
|
+
* For frameworks like Next.js Pages Router where the body has already been
|
|
642
|
+
* parsed, use this instead of {@link parseCallback}.
|
|
333
643
|
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
644
|
+
* Detects the CloudEvent version from the `ce-type` header:
|
|
645
|
+
* - `com.vercel.queue.v2beta`: binary content mode (metadata in headers,
|
|
646
|
+
* payload in body). For small messages, the body is attached as `parsedPayload`.
|
|
647
|
+
* - Otherwise: structured content mode (v1beta, entire CloudEvent in JSON body)
|
|
336
648
|
*
|
|
337
|
-
* @
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
649
|
+
* @param body - The framework-parsed request body. Type depends on Content-Type
|
|
650
|
+
* and framework configuration:
|
|
651
|
+
* - v1beta: parsed CloudEvent JSON object
|
|
652
|
+
* - v2beta: the message payload as parsed by the framework (object, Buffer, or string)
|
|
653
|
+
* @param headers - HTTP headers
|
|
654
|
+
* @returns Parsed callback request with routing metadata and optional payload
|
|
655
|
+
*/
|
|
656
|
+
declare function parseRawCallback(body: unknown, headers: Record<string, string | string[] | undefined>): ParsedCallbackRequest;
|
|
657
|
+
/**
|
|
658
|
+
* Parse and validate a CloudEvent callback from a Web API `Request` object.
|
|
346
659
|
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
* "notifications": (order, metadata) => console.log("Notifying order", order),
|
|
356
|
-
* }
|
|
357
|
-
* });
|
|
358
|
-
* ```
|
|
660
|
+
* Detects the CloudEvent version from the `ce-type` header:
|
|
661
|
+
* - `com.vercel.queue.v2beta`: binary content mode (metadata in headers,
|
|
662
|
+
* payload in body). For v2beta, the body is attached as `rawBody` (a
|
|
663
|
+
* ReadableStream) rather than being parsed.
|
|
664
|
+
* - Otherwise: structured content mode (v1beta, entire CloudEvent in JSON body)
|
|
665
|
+
*
|
|
666
|
+
* For frameworks that pre-parse the body (e.g. Next.js Pages Router),
|
|
667
|
+
* use {@link parseRawCallback} instead.
|
|
359
668
|
*/
|
|
360
|
-
declare function
|
|
669
|
+
declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
|
|
361
670
|
|
|
362
|
-
export { BadRequestError, BufferTransport, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler,
|
|
671
|
+
export { BadRequestError, type BaseUrlResolver, BufferTransport, CLOUD_EVENT_TYPE_V1BETA, CLOUD_EVENT_TYPE_V2BETA, ConsumerDiscoveryError, ConsumerRegistryNotConfiguredError, DuplicateMessageError, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageAlreadyProcessedError, MessageCorruptedError, type MessageHandler, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type ParsedCallbackRequest, type ParsedCallbackV1, type ParsedCallbackV2, QueueClient, type QueueClientOptions, QueueEmptyError, type ReceiveBatchOptions, type ReceiveByIdOptions, type ReceiveOptions, type ReceiveResult, type RetryDirective, type RetryHandler, type SendOptions, type SendResult, StreamTransport, type Transport, UnauthorizedError, type VercelRegion, parseCallback, parseRawCallback };
|