@vercel/queue 0.0.0-alpha.34 → 0.0.0-alpha.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Q as QueueClientOptions, S as SendMessageOptions, T as Transport, a as SendMessageResponse, R as ReceiveMessagesOptions, M as Message, b as ReceiveMessageByIdOptions, c as ReceiveMessageByIdResponse, D as DeleteMessageOptions, d as DeleteMessageResponse, C as ChangeVisibilityOptions, e as ChangeVisibilityResponse, f as MessageHandler, P as PublishOptions, g as ConsumerGroupOptions } from './types-BHtRP_i_.js';
2
- export { i as BadRequestError, B as BufferTransport, j as ConcurrencyLimitError, k as ConsumerDiscoveryError, l as ConsumerRegistryNotConfiguredError, m as DuplicateMessageError, F as ForbiddenError, I as InternalServerError, n as InvalidLimitError, J as JsonTransport, o as MessageAlreadyProcessedError, p as MessageCorruptedError, q as MessageLockedError, u as MessageMetadata, r as MessageNotAvailableError, s as MessageNotFoundError, t as QueueEmptyError, h as StreamTransport, U as UnauthorizedError } from './types-BHtRP_i_.js';
1
+ import { Q as QueueClientOptions, S as SendMessageOptions, T as Transport, a as SendMessageResponse, R as ReceiveMessagesOptions, M as Message, b as ReceiveMessageByIdOptions, c as ReceiveMessageByIdResponse, D as DeleteMessageOptions, d as DeleteMessageResponse, C as ChangeVisibilityOptions, e as ChangeVisibilityResponse, f as MessageHandler, P as PublishOptions, g as ConsumerGroupOptions } from './types-BLG4ASI_.js';
2
+ export { i as BadRequestError, B as BufferTransport, j as ConcurrencyLimitError, k as ConsumerDiscoveryError, l as ConsumerRegistryNotConfiguredError, m as DuplicateMessageError, F as ForbiddenError, I as InternalServerError, n as InvalidLimitError, J as JsonTransport, o as MessageAlreadyProcessedError, p as MessageCorruptedError, q as MessageLockedError, u as MessageMetadata, r as MessageNotAvailableError, s as MessageNotFoundError, t as QueueEmptyError, h as StreamTransport, U as UnauthorizedError } from './types-BLG4ASI_.js';
3
3
 
4
4
  declare class QueueClient {
5
5
  private baseUrl;
@@ -14,10 +14,100 @@ declare class QueueClient {
14
14
  private getToken;
15
15
  private buildUrl;
16
16
  private fetch;
17
+ /**
18
+ * Send a message to a topic.
19
+ *
20
+ * @param options - Message options including queue name, payload, and optional settings
21
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
22
+ * @param options.payload - Message payload
23
+ * @param options.idempotencyKey - Optional deduplication key (dedup window: min(retention, 24h))
24
+ * @param options.retentionSeconds - Message TTL (default: 86400, min: 60, max: 86400)
25
+ * @param options.delaySeconds - Delivery delay (default: 0, max: retentionSeconds)
26
+ * @param transport - Serializer for the payload
27
+ * @returns Promise with the generated messageId
28
+ * @throws {DuplicateMessageError} When idempotency key was already used
29
+ * @throws {ConsumerDiscoveryError} When consumer discovery fails
30
+ * @throws {ConsumerRegistryNotConfiguredError} When registry not configured
31
+ * @throws {BadRequestError} When parameters are invalid
32
+ * @throws {UnauthorizedError} When authentication fails
33
+ * @throws {ForbiddenError} When access is denied
34
+ * @throws {InternalServerError} When server encounters an error
35
+ */
17
36
  sendMessage<T = unknown>(options: SendMessageOptions<T>, transport: Transport<T>): Promise<SendMessageResponse>;
37
+ /**
38
+ * Receive messages from a topic as an async generator.
39
+ *
40
+ * @param options - Receive options
41
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
42
+ * @param options.consumerGroup - Consumer group name (pattern: `[A-Za-z0-9_-]+`)
43
+ * @param options.visibilityTimeoutSeconds - Lock duration (default: 30, min: 0, max: 3600)
44
+ * @param options.limit - Max messages to retrieve (default: 1, min: 1, max: 10)
45
+ * @param options.maxConcurrency - Max in-flight messages (default: unlimited, min: 1)
46
+ * @param transport - Deserializer for message payloads
47
+ * @yields Message objects with payload, messageId, receiptHandle, etc.
48
+ * @throws {QueueEmptyError} When no messages available
49
+ * @throws {InvalidLimitError} When limit is outside 1-10 range
50
+ * @throws {ConcurrencyLimitError} When maxConcurrency exceeded
51
+ * @throws {BadRequestError} When parameters are invalid
52
+ * @throws {UnauthorizedError} When authentication fails
53
+ * @throws {ForbiddenError} When access is denied
54
+ * @throws {InternalServerError} When server encounters an error
55
+ */
18
56
  receiveMessages<T = unknown>(options: ReceiveMessagesOptions<T>, transport: Transport<T>): AsyncGenerator<Message<T>, void, unknown>;
57
+ /**
58
+ * Receive a specific message by its ID.
59
+ *
60
+ * @param options - Receive options
61
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
62
+ * @param options.consumerGroup - Consumer group name (pattern: `[A-Za-z0-9_-]+`)
63
+ * @param options.messageId - Message ID to retrieve
64
+ * @param options.visibilityTimeoutSeconds - Lock duration (default: 30, min: 0, max: 3600)
65
+ * @param options.maxConcurrency - Max in-flight messages (default: unlimited, min: 1)
66
+ * @param transport - Deserializer for the message payload
67
+ * @returns Promise with the message
68
+ * @throws {MessageNotFoundError} When message doesn't exist
69
+ * @throws {MessageNotAvailableError} When message is in wrong state or was a duplicate
70
+ * @throws {MessageAlreadyProcessedError} When message was already processed
71
+ * @throws {ConcurrencyLimitError} When maxConcurrency exceeded
72
+ * @throws {BadRequestError} When parameters are invalid
73
+ * @throws {UnauthorizedError} When authentication fails
74
+ * @throws {ForbiddenError} When access is denied
75
+ * @throws {InternalServerError} When server encounters an error
76
+ */
19
77
  receiveMessageById<T = unknown>(options: ReceiveMessageByIdOptions<T>, transport: Transport<T>): Promise<ReceiveMessageByIdResponse<T>>;
78
+ /**
79
+ * Delete (acknowledge) a message after successful processing.
80
+ *
81
+ * @param options - Delete options
82
+ * @param options.queueName - Topic name
83
+ * @param options.consumerGroup - Consumer group name
84
+ * @param options.receiptHandle - Receipt handle from the received message (must use same deployment ID as receive)
85
+ * @returns Promise indicating deletion success
86
+ * @throws {MessageNotFoundError} When receipt handle not found
87
+ * @throws {MessageNotAvailableError} When receipt handle invalid or message already processed
88
+ * @throws {BadRequestError} When parameters are invalid
89
+ * @throws {UnauthorizedError} When authentication fails
90
+ * @throws {ForbiddenError} When access is denied
91
+ * @throws {InternalServerError} When server encounters an error
92
+ */
20
93
  deleteMessage(options: DeleteMessageOptions): Promise<DeleteMessageResponse>;
94
+ /**
95
+ * Extend or change the visibility timeout of a message.
96
+ * Used to prevent message redelivery while still processing.
97
+ *
98
+ * @param options - Visibility options
99
+ * @param options.queueName - Topic name
100
+ * @param options.consumerGroup - Consumer group name
101
+ * @param options.receiptHandle - Receipt handle from the received message (must use same deployment ID as receive)
102
+ * @param options.visibilityTimeoutSeconds - New timeout (min: 0, max: 3600, cannot exceed message expiration)
103
+ * @returns Promise indicating success
104
+ * @throws {MessageNotFoundError} When receipt handle not found
105
+ * @throws {MessageNotAvailableError} When receipt handle invalid or message already processed
106
+ * @throws {BadRequestError} When parameters are invalid
107
+ * @throws {UnauthorizedError} When authentication fails
108
+ * @throws {ForbiddenError} When access is denied
109
+ * @throws {InternalServerError} When server encounters an error
110
+ */
21
111
  changeVisibility(options: ChangeVisibilityOptions): Promise<ChangeVisibilityResponse>;
22
112
  /**
23
113
  * Alternative endpoint for changing message visibility timeout.
@@ -42,6 +132,24 @@ type CallbackHandlers = {
42
132
  [consumerGroup: string]: MessageHandler;
43
133
  };
44
134
  };
135
+ /**
136
+ * Options for handleCallback.
137
+ */
138
+ interface HandleCallbackOptions {
139
+ /**
140
+ * QueueClient instance to use for processing messages.
141
+ * If not provided, a default client is created with OIDC authentication.
142
+ */
143
+ client?: QueueClient;
144
+ /**
145
+ * Time in seconds that messages will be invisible to other consumers during processing.
146
+ * The handler will automatically extend this timeout while processing.
147
+ * @default 30
148
+ * @minimum 0
149
+ * @maximum 3600 (1 hour)
150
+ */
151
+ visibilityTimeoutSeconds?: number;
152
+ }
45
153
  /**
46
154
  * Parsed callback request information
47
155
  */
@@ -79,39 +187,41 @@ type ParsedCallbackRequest = {
79
187
  */
80
188
  declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
81
189
  /**
82
- * Simplified queue callback handler for Next.js route handlers
190
+ * Simplified queue callback handler for Next.js route handlers.
83
191
  *
84
192
  * Automatically extracts queue information from CloudEvent format
85
193
  * and routes to the appropriate handler based on topic and consumer group.
86
194
  *
87
- * @param handlers Object with topic-specific handlers organized by consumer groups
88
- * @param client Optional QueueClient instance to use. If not provided, a default client is created.
195
+ * @param handlers - Object with topic-specific handlers organized by consumer groups
196
+ * @param options - Optional configuration
197
+ * @param options.client - QueueClient instance (default: new client with OIDC auth)
198
+ * @param options.visibilityTimeoutSeconds - Message lock duration (default: 30, max: 3600)
89
199
  * @returns A Next.js route handler function
90
200
  *
91
201
  * @example
92
202
  * ```typescript
93
- * // Single topic with multiple consumer groups
203
+ * // Basic usage
94
204
  * export const POST = handleCallback({
95
205
  * "image-processing": {
96
- * "compress": (message, metadata) => console.log("Compressing image", message),
97
- * "resize": (message, metadata) => console.log("Resizing image", message),
206
+ * "compress": (message, metadata) => console.log("Compressing", message),
207
+ * "resize": (message, metadata) => console.log("Resizing", message),
98
208
  * }
99
209
  * });
100
210
  *
101
- * // Multiple topics with consumer groups
211
+ * // With custom visibility timeout for long-running handlers
102
212
  * export const POST = handleCallback({
103
- * "user-events": {
104
- * "welcome": (user, metadata) => console.log("Welcoming user", user),
105
- * "analytics": (user, metadata) => console.log("Tracking user", user),
106
- * },
107
- * "order-events": {
108
- * "fulfillment": (order, metadata) => console.log("Fulfilling order", order),
109
- * "notifications": (order, metadata) => console.log("Notifying order", order),
213
+ * "video-processing": {
214
+ * "transcode": async (video, metadata) => {
215
+ * // Long-running transcoding operation
216
+ * await transcodeVideo(video);
217
+ * },
110
218
  * }
219
+ * }, {
220
+ * visibilityTimeoutSeconds: 300, // 5 minutes
111
221
  * });
112
222
  * ```
113
223
  */
114
- declare function handleCallback(handlers: CallbackHandlers, client?: QueueClient): (request: Request) => Promise<Response>;
224
+ declare function handleCallback(handlers: CallbackHandlers, options?: HandleCallbackOptions): (request: Request) => Promise<Response>;
115
225
 
116
226
  /**
117
227
  * Client - User-facing wrapper for the Vercel Queue Service
@@ -166,22 +276,35 @@ declare class Client {
166
276
  messageId: string;
167
277
  }>;
168
278
  /**
169
- * Create a callback handler for processing queue messages
170
- * Returns a Next.js route handler function that routes messages to appropriate handlers
171
- * @param handlers Object with topic-specific handlers organized by consumer groups
279
+ * Create a callback handler for processing queue messages.
280
+ * Returns a Next.js route handler function that routes messages to appropriate handlers.
281
+ *
282
+ * @param handlers - Object with topic-specific handlers organized by consumer groups
283
+ * @param options - Optional configuration
284
+ * @param options.visibilityTimeoutSeconds - Message lock duration (default: 30, max: 3600)
172
285
  * @returns A Next.js route handler function
173
286
  *
174
287
  * @example
175
288
  * ```typescript
289
+ * // Basic usage
176
290
  * export const POST = client.handleCallback({
177
291
  * "user-events": {
178
292
  * "welcome": (user, metadata) => console.log("Welcoming user", user),
179
293
  * "analytics": (user, metadata) => console.log("Tracking user", user),
180
294
  * },
181
295
  * });
296
+ *
297
+ * // With custom visibility timeout
298
+ * export const POST = client.handleCallback({
299
+ * "video-processing": {
300
+ * "transcode": async (video) => await transcodeVideo(video),
301
+ * },
302
+ * }, {
303
+ * visibilityTimeoutSeconds: 300, // 5 minutes for long operations
304
+ * });
182
305
  * ```
183
306
  */
184
- handleCallback(handlers: CallbackHandlers): (request: Request) => Promise<Response>;
307
+ handleCallback(handlers: CallbackHandlers, options?: Omit<HandleCallbackOptions, "client">): (request: Request) => Promise<Response>;
185
308
  }
186
309
 
187
310
  /**
@@ -193,76 +316,107 @@ interface ConsumeOptions {
193
316
  }
194
317
 
195
318
  /**
196
- * Options for the send function
319
+ * Options for the send function.
197
320
  */
198
321
  interface SendOptions<T = unknown> extends PublishOptions {
199
322
  /**
200
- * Serializer/deserializer for the payload
201
- * @default JsonTransport instance
323
+ * Serializer for the payload.
324
+ * @default JsonTransport
202
325
  */
203
326
  transport?: Transport<T>;
204
327
  /**
205
- * QueueClient instance to use for sending the message
206
- * If not provided, a default client is created
328
+ * QueueClient instance to use for sending the message.
329
+ * If not provided, a default client is created with OIDC authentication.
207
330
  */
208
331
  client?: QueueClient;
209
332
  }
210
333
  /**
211
- * Send a message to a topic (shorthand for topic creation and publishing)
212
- * Uses the default QueueClient with automatic OIDC token detection, or a provided client
213
- * @param topicName Name of the topic to send to
214
- * @param payload The data to send
215
- * @param options Optional send options including transport, publish settings, and client
216
- * @returns Promise with the message ID
217
- * @throws {BadRequestError} When request parameters are invalid
334
+ * Send a message to a topic.
335
+ *
336
+ * Uses the default QueueClient with automatic OIDC token detection, or a provided client.
337
+ *
338
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
339
+ * @param payload - The data to send
340
+ * @param options - Optional send options
341
+ * @param options.idempotencyKey - Deduplication key (dedup window: min(retention, 24h))
342
+ * @param options.retentionSeconds - Message TTL (default: 86400, min: 60, max: 86400)
343
+ * @param options.delaySeconds - Delivery delay (default: 0, max: retentionSeconds)
344
+ * @param options.transport - Payload serializer (default: JsonTransport)
345
+ * @param options.client - Custom QueueClient instance
346
+ * @returns Promise with the generated messageId
347
+ * @throws {DuplicateMessageError} When idempotency key was already used
348
+ * @throws {BadRequestError} When parameters are invalid
218
349
  * @throws {UnauthorizedError} When authentication fails
219
- * @throws {ForbiddenError} When access is denied (environment mismatch)
350
+ * @throws {ForbiddenError} When access is denied
220
351
  * @throws {InternalServerError} When server encounters an error
221
352
  *
222
353
  * @example
223
354
  * ```typescript
224
- * // Using default client (OIDC token)
355
+ * // Basic usage (OIDC auth)
225
356
  * await send("my-topic", { hello: "world" });
226
357
  *
358
+ * // With options
359
+ * await send("my-topic", payload, {
360
+ * idempotencyKey: "unique-key",
361
+ * retentionSeconds: 3600, // 1 hour TTL
362
+ * delaySeconds: 60, // Delay 1 minute
363
+ * });
364
+ *
227
365
  * // Using custom client
228
366
  * const client = new QueueClient({ token: "my-token" });
229
- * await send("my-topic", { hello: "world" }, { client });
367
+ * await send("my-topic", payload, { client });
230
368
  * ```
231
369
  */
232
370
  declare function send<T = unknown>(topicName: string, payload: T, options?: SendOptions<T>): Promise<{
233
371
  messageId: string;
234
372
  }>;
235
373
  /**
236
- * Options for the receive function
374
+ * Options for the receive function.
237
375
  */
238
376
  interface ReceiveOptions<T = unknown> extends ConsumerGroupOptions<T>, ConsumeOptions {
239
377
  /**
240
- * QueueClient instance to use for receiving the message
241
- * If not provided, a default client is created
378
+ * QueueClient instance to use for receiving the message.
379
+ * If not provided, a default client is created with OIDC authentication.
242
380
  */
243
381
  client?: QueueClient;
244
382
  }
245
383
  /**
246
- * Receive a message from a topic (shorthand for topic and consumer group creation)
247
- * Uses the default QueueClient with automatic OIDC token detection
248
- * @param topicName Name of the topic to receive from
249
- * @param consumerGroup Name of the consumer group
250
- * @param handler Function to process the message
251
- * @returns Promise that resolves when the message is processed
252
- * @throws All the same errors as the underlying client methods
384
+ * Receive a message from a topic.
385
+ *
386
+ * Shorthand for creating a topic and consumer group. The message is automatically:
387
+ * - Locked with the configured visibility timeout
388
+ * - Kept alive via periodic visibility extensions during processing
389
+ * - Deleted upon successful handler completion
390
+ *
391
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
392
+ * @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
393
+ * @param handler - Function to process the message payload and metadata
394
+ * @param options - Optional receive options
395
+ * @param options.visibilityTimeoutSeconds - Message lock duration (default: 30, max: 3600)
396
+ * @param options.visibilityRefreshInterval - Lock refresh interval (default: visibilityTimeout / 3)
397
+ * @param options.transport - Payload deserializer (default: JsonTransport)
398
+ * @returns Promise that resolves when the message is processed and deleted
399
+ * @throws {QueueEmptyError} When no messages available
400
+ * @throws {ConcurrencyLimitError} When maxConcurrency exceeded
253
401
  */
254
402
  declare function receive<T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options?: ReceiveOptions<T>): Promise<void>;
255
403
  /**
256
- * Receive a specific message by its ID
257
- * @param topicName Name of the topic to receive from
258
- * @param consumerGroup Name of the consumer group
259
- * @param handler Function to process the message
260
- * @param options Receive options with messageId specified
261
- * @returns Promise that resolves when the message is processed
262
- * @throws All the same errors as the underlying client methods
404
+ * Receive a specific message by its ID.
405
+ *
406
+ * Used for targeted message processing, typically from webhook callbacks.
407
+ *
408
+ * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
409
+ * @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
410
+ * @param handler - Function to process the message payload and metadata
411
+ * @param options - Receive options with messageId
412
+ * @param options.messageId - Specific message ID to consume
413
+ * @returns Promise that resolves when the message is processed and deleted
414
+ * @throws {MessageNotFoundError} When message doesn't exist
415
+ * @throws {MessageNotAvailableError} When message in wrong state
416
+ * @throws {MessageAlreadyProcessedError} When already processed
263
417
  */
264
418
  declare function receive<T = unknown>(topicName: string, consumerGroup: string, handler: MessageHandler<T>, options: ReceiveOptions<T> & {
265
419
  messageId: string;
266
420
  }): Promise<void>;
267
421
 
268
- export { type CallbackHandlers, Client, Message, MessageHandler, type ParsedCallbackRequest, PublishOptions, QueueClientOptions, type ReceiveOptions, SendMessageOptions, SendMessageResponse, type SendOptions, Transport, handleCallback, parseCallback, receive, send };
422
+ export { type CallbackHandlers, Client, type HandleCallbackOptions, Message, MessageHandler, type ParsedCallbackRequest, PublishOptions, QueueClientOptions, type ReceiveOptions, SendMessageOptions, SendMessageResponse, type SendOptions, Transport, handleCallback, parseCallback, receive, send };
package/dist/index.js CHANGED
@@ -77,6 +77,12 @@ var JsonTransport = class {
77
77
  contentType = "application/json";
78
78
  replacer;
79
79
  reviver;
80
+ /**
81
+ * Create a new JsonTransport.
82
+ * @param options - Optional JSON serialization options
83
+ * @param options.replacer - Custom replacer for JSON.stringify
84
+ * @param options.reviver - Custom reviver for JSON.parse
85
+ */
80
86
  constructor(options = {}) {
81
87
  this.replacer = options.replacer;
82
88
  this.reviver = options.reviver;
@@ -106,6 +112,10 @@ var StreamTransport = class {
106
112
  async deserialize(stream) {
107
113
  return stream;
108
114
  }
115
+ /**
116
+ * Consume any remaining stream data to prevent resource leaks.
117
+ * Called automatically by ConsumerGroup; manual call required for direct client usage.
118
+ */
109
119
  async finalize(payload) {
110
120
  const reader = payload.getReader();
111
121
  try {
@@ -156,6 +166,7 @@ var QueueEmptyError = class extends Error {
156
166
  }
157
167
  };
158
168
  var MessageLockedError = class extends Error {
169
+ /** Suggested retry delay in seconds, if provided by the server. */
159
170
  retryAfter;
160
171
  constructor(messageId, retryAfter) {
161
172
  const retryMessage = retryAfter ? ` Retry after ${retryAfter} seconds.` : " Try again later.";
@@ -201,7 +212,9 @@ var MessageAlreadyProcessedError = class extends Error {
201
212
  }
202
213
  };
203
214
  var ConcurrencyLimitError = class extends Error {
215
+ /** Current number of in-flight messages for this consumer group. */
204
216
  currentInflight;
217
+ /** Maximum allowed concurrent messages (as configured). */
205
218
  maxConcurrency;
206
219
  constructor(message = "Concurrency limit exceeded", currentInflight, maxConcurrency) {
207
220
  super(message);
@@ -588,6 +601,25 @@ var QueueClient = class {
588
601
  }
589
602
  return response;
590
603
  }
604
+ /**
605
+ * Send a message to a topic.
606
+ *
607
+ * @param options - Message options including queue name, payload, and optional settings
608
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
609
+ * @param options.payload - Message payload
610
+ * @param options.idempotencyKey - Optional deduplication key (dedup window: min(retention, 24h))
611
+ * @param options.retentionSeconds - Message TTL (default: 86400, min: 60, max: 86400)
612
+ * @param options.delaySeconds - Delivery delay (default: 0, max: retentionSeconds)
613
+ * @param transport - Serializer for the payload
614
+ * @returns Promise with the generated messageId
615
+ * @throws {DuplicateMessageError} When idempotency key was already used
616
+ * @throws {ConsumerDiscoveryError} When consumer discovery fails
617
+ * @throws {ConsumerRegistryNotConfiguredError} When registry not configured
618
+ * @throws {BadRequestError} When parameters are invalid
619
+ * @throws {UnauthorizedError} When authentication fails
620
+ * @throws {ForbiddenError} When access is denied
621
+ * @throws {InternalServerError} When server encounters an error
622
+ */
591
623
  async sendMessage(options, transport) {
592
624
  const {
593
625
  queueName,
@@ -650,6 +682,25 @@ var QueueClient = class {
650
682
  const responseData = await response.json();
651
683
  return responseData;
652
684
  }
685
+ /**
686
+ * Receive messages from a topic as an async generator.
687
+ *
688
+ * @param options - Receive options
689
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
690
+ * @param options.consumerGroup - Consumer group name (pattern: `[A-Za-z0-9_-]+`)
691
+ * @param options.visibilityTimeoutSeconds - Lock duration (default: 30, min: 0, max: 3600)
692
+ * @param options.limit - Max messages to retrieve (default: 1, min: 1, max: 10)
693
+ * @param options.maxConcurrency - Max in-flight messages (default: unlimited, min: 1)
694
+ * @param transport - Deserializer for message payloads
695
+ * @yields Message objects with payload, messageId, receiptHandle, etc.
696
+ * @throws {QueueEmptyError} When no messages available
697
+ * @throws {InvalidLimitError} When limit is outside 1-10 range
698
+ * @throws {ConcurrencyLimitError} When maxConcurrency exceeded
699
+ * @throws {BadRequestError} When parameters are invalid
700
+ * @throws {UnauthorizedError} When authentication fails
701
+ * @throws {ForbiddenError} When access is denied
702
+ * @throws {InternalServerError} When server encounters an error
703
+ */
653
704
  async *receiveMessages(options, transport) {
654
705
  const {
655
706
  queueName,
@@ -735,6 +786,26 @@ var QueueClient = class {
735
786
  }
736
787
  }
737
788
  }
789
+ /**
790
+ * Receive a specific message by its ID.
791
+ *
792
+ * @param options - Receive options
793
+ * @param options.queueName - Topic name (pattern: `[A-Za-z0-9_-]+`)
794
+ * @param options.consumerGroup - Consumer group name (pattern: `[A-Za-z0-9_-]+`)
795
+ * @param options.messageId - Message ID to retrieve
796
+ * @param options.visibilityTimeoutSeconds - Lock duration (default: 30, min: 0, max: 3600)
797
+ * @param options.maxConcurrency - Max in-flight messages (default: unlimited, min: 1)
798
+ * @param transport - Deserializer for the message payload
799
+ * @returns Promise with the message
800
+ * @throws {MessageNotFoundError} When message doesn't exist
801
+ * @throws {MessageNotAvailableError} When message is in wrong state or was a duplicate
802
+ * @throws {MessageAlreadyProcessedError} When message was already processed
803
+ * @throws {ConcurrencyLimitError} When maxConcurrency exceeded
804
+ * @throws {BadRequestError} When parameters are invalid
805
+ * @throws {UnauthorizedError} When authentication fails
806
+ * @throws {ForbiddenError} When access is denied
807
+ * @throws {InternalServerError} When server encounters an error
808
+ */
738
809
  async receiveMessageById(options, transport) {
739
810
  const {
740
811
  queueName,
@@ -829,6 +900,21 @@ var QueueClient = class {
829
900
  }
830
901
  throw new MessageNotFoundError(messageId);
831
902
  }
903
+ /**
904
+ * Delete (acknowledge) a message after successful processing.
905
+ *
906
+ * @param options - Delete options
907
+ * @param options.queueName - Topic name
908
+ * @param options.consumerGroup - Consumer group name
909
+ * @param options.receiptHandle - Receipt handle from the received message (must use same deployment ID as receive)
910
+ * @returns Promise indicating deletion success
911
+ * @throws {MessageNotFoundError} When receipt handle not found
912
+ * @throws {MessageNotAvailableError} When receipt handle invalid or message already processed
913
+ * @throws {BadRequestError} When parameters are invalid
914
+ * @throws {UnauthorizedError} When authentication fails
915
+ * @throws {ForbiddenError} When access is denied
916
+ * @throws {InternalServerError} When server encounters an error
917
+ */
832
918
  async deleteMessage(options) {
833
919
  const { queueName, consumerGroup, receiptHandle } = options;
834
920
  const headers = new Headers({
@@ -873,6 +959,23 @@ var QueueClient = class {
873
959
  }
874
960
  return { deleted: true };
875
961
  }
962
+ /**
963
+ * Extend or change the visibility timeout of a message.
964
+ * Used to prevent message redelivery while still processing.
965
+ *
966
+ * @param options - Visibility options
967
+ * @param options.queueName - Topic name
968
+ * @param options.consumerGroup - Consumer group name
969
+ * @param options.receiptHandle - Receipt handle from the received message (must use same deployment ID as receive)
970
+ * @param options.visibilityTimeoutSeconds - New timeout (min: 0, max: 3600, cannot exceed message expiration)
971
+ * @returns Promise indicating success
972
+ * @throws {MessageNotFoundError} When receipt handle not found
973
+ * @throws {MessageNotAvailableError} When receipt handle invalid or message already processed
974
+ * @throws {BadRequestError} When parameters are invalid
975
+ * @throws {UnauthorizedError} When authentication fails
976
+ * @throws {ForbiddenError} When access is denied
977
+ * @throws {InternalServerError} When server encounters an error
978
+ */
876
979
  async changeVisibility(options) {
877
980
  const {
878
981
  queueName,
@@ -995,36 +1098,26 @@ var ConsumerGroup = class {
995
1098
  refreshInterval;
996
1099
  transport;
997
1100
  /**
998
- * Create a new ConsumerGroup instance
999
- * @param client QueueClient instance to use for API calls
1000
- * @param topicName Name of the topic to consume from
1001
- * @param consumerGroupName Name of the consumer group
1002
- * @param options Optional configuration
1101
+ * Create a new ConsumerGroup instance.
1102
+ *
1103
+ * @param client - QueueClient instance to use for API calls
1104
+ * @param topicName - Name of the topic to consume from (pattern: `[A-Za-z0-9_-]+`)
1105
+ * @param consumerGroupName - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
1106
+ * @param options - Optional configuration
1107
+ * @param options.transport - Payload serializer (default: JsonTransport)
1108
+ * @param options.visibilityTimeoutSeconds - Message lock duration (default: 30, max: 3600)
1109
+ * @param options.visibilityRefreshInterval - Lock refresh interval in seconds (default: visibilityTimeout / 3)
1003
1110
  */
1004
1111
  constructor(client, topicName, consumerGroupName, options = {}) {
1005
1112
  this.client = client;
1006
1113
  this.topicName = topicName;
1007
1114
  this.consumerGroupName = consumerGroupName;
1008
- this.visibilityTimeout = options.visibilityTimeoutSeconds || 30;
1009
- this.refreshInterval = options.refreshInterval || 10;
1115
+ this.visibilityTimeout = options.visibilityTimeoutSeconds ?? 30;
1116
+ this.refreshInterval = options.visibilityRefreshInterval ?? Math.floor(this.visibilityTimeout / 3);
1010
1117
  this.transport = options.transport || new JsonTransport();
1011
1118
  }
1012
1119
  /**
1013
1120
  * Starts a background loop that periodically extends the visibility timeout for a message.
1014
- * This prevents the message from becoming visible to other consumers while it's being processed.
1015
- *
1016
- * The extension loop runs every `refreshInterval` seconds and updates the message's
1017
- * visibility timeout to `visibilityTimeout` seconds from the current time.
1018
- *
1019
- * @param receiptHandle - The receipt handle that proves ownership of the message
1020
- * @returns A function that when called will stop the extension loop
1021
- *
1022
- * @remarks
1023
- * - The first extension attempt occurs after `refreshInterval` seconds, not immediately
1024
- * - If an extension fails, the loop terminates with an error logged to console
1025
- * - The returned stop function is idempotent - calling it multiple times is safe
1026
- * - By default, the stop function returns immediately without waiting for in-flight
1027
- * - Pass `true` to the stop function to wait for any in-flight extension to complete
1028
1121
  */
1029
1122
  startVisibilityExtension(receiptHandle) {
1030
1123
  let isRunning = true;
@@ -1296,7 +1389,7 @@ async function parseCallback(request) {
1296
1389
  messageId
1297
1390
  };
1298
1391
  }
1299
- function createCallbackHandler(handlers, client) {
1392
+ function createCallbackHandler(handlers, client, visibilityTimeoutSeconds) {
1300
1393
  for (const topicPattern in handlers) {
1301
1394
  if (topicPattern.includes("*")) {
1302
1395
  if (!validateWildcardPattern(topicPattern)) {
@@ -1332,7 +1425,10 @@ function createCallbackHandler(handlers, client) {
1332
1425
  );
1333
1426
  }
1334
1427
  const topic = new Topic(client, queueName);
1335
- const cg = topic.consumerGroup(consumerGroup);
1428
+ const cg = topic.consumerGroup(
1429
+ consumerGroup,
1430
+ visibilityTimeoutSeconds !== void 0 ? { visibilityTimeoutSeconds } : void 0
1431
+ );
1336
1432
  await cg.consume(consumerGroupHandler, { messageId });
1337
1433
  return Response.json({ status: "success" });
1338
1434
  } catch (error) {
@@ -1348,8 +1444,12 @@ function createCallbackHandler(handlers, client) {
1348
1444
  };
1349
1445
  return routeHandler;
1350
1446
  }
1351
- function handleCallback(handlers, client) {
1352
- return createCallbackHandler(handlers, client || new QueueClient());
1447
+ function handleCallback(handlers, options) {
1448
+ return createCallbackHandler(
1449
+ handlers,
1450
+ options?.client || new QueueClient(),
1451
+ options?.visibilityTimeoutSeconds
1452
+ );
1353
1453
  }
1354
1454
 
1355
1455
  // src/factory.ts
@@ -1412,23 +1512,39 @@ var Client = class {
1412
1512
  });
1413
1513
  }
1414
1514
  /**
1415
- * Create a callback handler for processing queue messages
1416
- * Returns a Next.js route handler function that routes messages to appropriate handlers
1417
- * @param handlers Object with topic-specific handlers organized by consumer groups
1515
+ * Create a callback handler for processing queue messages.
1516
+ * Returns a Next.js route handler function that routes messages to appropriate handlers.
1517
+ *
1518
+ * @param handlers - Object with topic-specific handlers organized by consumer groups
1519
+ * @param options - Optional configuration
1520
+ * @param options.visibilityTimeoutSeconds - Message lock duration (default: 30, max: 3600)
1418
1521
  * @returns A Next.js route handler function
1419
1522
  *
1420
1523
  * @example
1421
1524
  * ```typescript
1525
+ * // Basic usage
1422
1526
  * export const POST = client.handleCallback({
1423
1527
  * "user-events": {
1424
1528
  * "welcome": (user, metadata) => console.log("Welcoming user", user),
1425
1529
  * "analytics": (user, metadata) => console.log("Tracking user", user),
1426
1530
  * },
1427
1531
  * });
1532
+ *
1533
+ * // With custom visibility timeout
1534
+ * export const POST = client.handleCallback({
1535
+ * "video-processing": {
1536
+ * "transcode": async (video) => await transcodeVideo(video),
1537
+ * },
1538
+ * }, {
1539
+ * visibilityTimeoutSeconds: 300, // 5 minutes for long operations
1540
+ * });
1428
1541
  * ```
1429
1542
  */
1430
- handleCallback(handlers) {
1431
- return handleCallback(handlers, this.client);
1543
+ handleCallback(handlers, options) {
1544
+ return handleCallback(handlers, {
1545
+ ...options,
1546
+ client: this.client
1547
+ });
1432
1548
  }
1433
1549
  };
1434
1550
  // Annotate the CommonJS export names for ESM import in node: