@vercel/queue 0.0.0-alpha.8 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transports.ts","../src/client.ts","../src/types.ts","../src/consumer-group.ts","../src/topic.ts","../src/factory.ts","../src/callback.ts"],"sourcesContent":["/**\n * Serializer/Deserializer interface for message payloads\n */\nexport interface Transport<T = unknown> {\n /**\n * Serialize a value to a buffer or stream for transmission\n */\n serialize(value: T): Buffer | ReadableStream<Uint8Array>;\n\n /**\n * Deserialize a readable stream back to the original value\n */\n deserialize(stream: ReadableStream<Uint8Array>): Promise<T>;\n\n /**\n * Optional cleanup method for deserialized payloads that may contain resources\n * Should be called when the payload is no longer needed, especially in error cases\n * @param payload The deserialized payload to clean up\n */\n finalize?(payload: T): Promise<void>;\n\n /**\n * MIME type for this serialization format\n */\n contentType: string;\n}\n\n/**\n * Built-in JSON serializer/deserializer\n * This implementation reads the entire stream into memory for JSON parsing\n */\nexport class JsonTransport<T = unknown> implements Transport<T> {\n readonly contentType = \"application/json\";\n\n serialize(value: T): Buffer {\n return Buffer.from(JSON.stringify(value), \"utf8\");\n }\n\n async deserialize(stream: ReadableStream<Uint8Array>): Promise<T> {\n // JSON requires reading the entire payload to parse\n const reader = stream.getReader();\n let totalLength = 0;\n const chunks: Uint8Array[] = [];\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n totalLength += value.length;\n }\n } finally {\n reader.releaseLock();\n }\n\n // Combine chunks into a single buffer\n const buffer = Buffer.concat(chunks, totalLength);\n return JSON.parse(buffer.toString(\"utf8\"));\n }\n}\n\n/**\n * Built-in Buffer serializer/deserializer (reads entire stream into a Buffer)\n */\nexport class BufferTransport implements Transport<Buffer> {\n readonly contentType = \"application/octet-stream\";\n\n serialize(value: Buffer): Buffer {\n return value;\n }\n\n async deserialize(stream: ReadableStream<Uint8Array>): Promise<Buffer> {\n // Buffer transport reads the entire stream into memory\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n\n // Combine chunks into a single buffer\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const buffer = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n buffer.set(chunk, offset);\n offset += chunk.length;\n }\n\n return Buffer.from(buffer);\n }\n}\n\n/**\n * Stream serializer/deserializer (pass-through for streaming binary data)\n * This is ideal for large payloads that don't need to be buffered in memory\n *\n * IMPORTANT: When using StreamTransport, you must call finalize(payload) when done\n * processing the message to prevent resource leaks, especially in error cases.\n * ConsumerGroup handles this automatically, but direct QueueClient usage requires manual cleanup.\n *\n * Example usage:\n * ```typescript\n * const transport = new StreamTransport();\n * try {\n * for await (const message of client.receiveMessages(options, transport)) {\n * // Process the stream...\n * const reader = message.payload.getReader();\n * // ... handle stream data\n * }\n * } catch (error) {\n * // Cleanup is handled automatically by ConsumerGroup\n * // or manually: await transport.finalize(message.payload);\n * }\n */\nexport class StreamTransport implements Transport<ReadableStream<Uint8Array>> {\n readonly contentType = \"application/octet-stream\";\n\n serialize(value: ReadableStream<Uint8Array>): ReadableStream<Uint8Array> {\n // Pass through the stream directly without buffering\n return value;\n }\n\n async deserialize(\n stream: ReadableStream<Uint8Array>,\n ): Promise<ReadableStream<Uint8Array>> {\n // Pass through the stream directly without buffering\n return stream;\n }\n\n async finalize(payload: ReadableStream<Uint8Array>): Promise<void> {\n // Consume any remaining stream data to prevent resource leaks\n const reader = payload.getReader();\n try {\n while (true) {\n const { done } = await reader.read();\n if (done) break;\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n","import { parseMultipartStream } from \"mixpart\";\nimport type {\n ChangeVisibilityOptions,\n ChangeVisibilityResponse,\n DeleteMessageOptions,\n DeleteMessageResponse,\n Message,\n QueueClientOptions,\n ReceiveMessageByIdOptions,\n ReceiveMessageByIdResponse,\n ReceiveMessagesOptions,\n SendMessageOptions,\n SendMessageResponse,\n Transport,\n} from \"./types\";\nimport {\n BadRequestError,\n ForbiddenError,\n InternalServerError,\n InvalidLimitError,\n MessageCorruptedError,\n MessageLockedError,\n MessageNotAvailableError,\n MessageNotFoundError,\n QueueEmptyError,\n UnauthorizedError,\n} from \"./types\";\n\n/**\n * Helper function to consume a ReadableStream to completion\n * This is necessary when we need to drain a stream to let the multipart parser proceed\n */\nasync function consumeStream(\n stream: ReadableStream<Uint8Array>,\n): Promise<void> {\n const reader = stream.getReader();\n try {\n while (true) {\n const { done } = await reader.read();\n if (done) break;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Helper function to parse queue headers into a partial message object\n * Handles both multipart message headers and HTTP response headers\n */\nfunction parseQueueHeaders(\n headers: Headers,\n): Omit<Message<unknown>, \"payload\"> | null {\n const messageId = headers.get(\"Vqs-Message-Id\");\n const deliveryCountStr = headers.get(\"Vqs-Delivery-Count\") || \"0\";\n const timestamp = headers.get(\"Vqs-Timestamp\");\n const contentType = headers.get(\"Content-Type\") || \"application/octet-stream\";\n const ticket = headers.get(\"Vqs-Ticket\");\n\n if (!messageId || !timestamp || !ticket) {\n return null;\n }\n\n const deliveryCount = parseInt(deliveryCountStr, 10);\n if (isNaN(deliveryCount)) {\n return null;\n }\n\n return {\n messageId,\n deliveryCount,\n timestamp,\n contentType,\n ticket,\n };\n}\n\n/**\n * Client for interacting with the Vercel Queue Service API\n */\nexport class QueueClient {\n private baseUrl: string;\n private token: string;\n\n /**\n * Internal default instance for use by convenience functions\n * @internal\n */\n private static _defaultInstance: QueueClient | null = null;\n\n /**\n * Create a new Vercel Queue Service client\n * @param options Client configuration options (optional - will auto-detect Vercel Function environment)\n */\n constructor(options: QueueClientOptions = {}) {\n this.baseUrl = options.baseUrl || \"https://vqs.vercel.sh\";\n\n if (options.token) {\n this.token = options.token;\n } else {\n // Try to get OIDC token from Vercel Function environment\n const token = this.getVercelOidcTokenSync();\n if (!token) {\n throw new Error(\n \"Failed to get OIDC token from Vercel Functions. \" +\n \"Make sure you are running in a Vercel Function environment, or provide a token explicitly.\\n\\n\" +\n \"To set up your environment:\\n\" +\n \"1. Link your project: 'vercel link'\\n\" +\n \"2. Pull environment variables: 'vercel env pull'\\n\" +\n \"3. Run with environment: 'dotenv -e .env.local -- your-command'\",\n );\n }\n this.token = token;\n }\n }\n\n /**\n * Get the default client instance for internal use by convenience functions\n * @internal\n */\n static _getDefaultInstance(): QueueClient {\n if (!this._defaultInstance) {\n this._defaultInstance = new QueueClient();\n }\n return this._defaultInstance;\n }\n\n /**\n * Synchronously get OIDC token from environment\n * Used internally by constructor - mirrors the logic from getVercelOidcToken but synchronously\n */\n private getVercelOidcTokenSync(): string | null {\n try {\n // Check for OIDC token in request context (same logic as async version)\n const SYMBOL_FOR_REQ_CONTEXT = Symbol.for(\"@vercel/request-context\");\n const fromSymbol = globalThis as any;\n const context = fromSymbol[SYMBOL_FOR_REQ_CONTEXT]?.get?.() ?? {};\n\n const token =\n context.headers?.[\"x-vercel-oidc-token\"] ??\n process.env.VERCEL_OIDC_TOKEN;\n\n return token || null;\n } catch {\n return null;\n }\n }\n\n /**\n * Send a message to a queue\n * @param options Send message options\n * @param transport Serializer/deserializer for the payload\n * @returns Promise with the message ID\n * @throws {BadRequestError} When request parameters are invalid\n * @throws {UnauthorizedError} When authentication fails\n * @throws {ForbiddenError} When access is denied (environment mismatch)\n * @throws {InternalServerError} When server encounters an error\n */\n async sendMessage<T = unknown>(\n options: SendMessageOptions<T>,\n transport: Transport<T>,\n ): Promise<SendMessageResponse> {\n const { queueName, payload, idempotencyKey, retentionSeconds } = options;\n\n const headers = new Headers({\n Authorization: `Bearer ${this.token}`,\n \"Vqs-Queue-Name\": queueName,\n \"Content-Type\": transport.contentType,\n });\n\n if (process.env.VERCEL_DEPLOYMENT_ID) {\n headers.set(\"Vqs-Deployment-Id\", process.env.VERCEL_DEPLOYMENT_ID);\n }\n\n if (idempotencyKey) {\n headers.set(\"Vqs-Idempotency-Key\", idempotencyKey);\n }\n\n if (retentionSeconds !== undefined) {\n headers.set(\"Vqs-Retention-Seconds\", retentionSeconds.toString());\n }\n\n // Serialize the payload using the provided transport\n const body = transport.serialize(payload);\n\n const response = await fetch(`${this.baseUrl}/api/v2/messages`, {\n method: \"POST\",\n headers,\n body,\n });\n\n if (!response.ok) {\n if (response.status === 400) {\n const errorText = await response.text();\n throw new BadRequestError(errorText || \"Invalid parameters\");\n }\n if (response.status === 401) {\n throw new UnauthorizedError();\n }\n if (response.status === 403) {\n throw new ForbiddenError();\n }\n if (response.status === 409) {\n throw new Error(\"Duplicate idempotency key detected\");\n }\n if (response.status >= 500) {\n throw new InternalServerError(\n `Server error: ${response.status} ${response.statusText}`,\n );\n }\n throw new Error(\n `Failed to send message: ${response.status} ${response.statusText}`,\n );\n }\n\n const responseData = (await response.json()) as SendMessageResponse;\n\n return responseData;\n }\n\n /**\n * Receive messages from a queue\n * @param options Receive messages options\n * @param transport Serializer/deserializer for the payload\n * @returns AsyncGenerator that yields messages as they arrive\n * @throws {InvalidLimitError} When limit parameter is not between 1 and 10\n * @throws {QueueEmptyError} When no messages are available (204)\n * @throws {MessageLockedError} When messages are temporarily locked (423)\n * @throws {BadRequestError} When request parameters are invalid\n * @throws {UnauthorizedError} When authentication fails\n * @throws {ForbiddenError} When access is denied (environment mismatch)\n * @throws {InternalServerError} When server encounters an error\n */\n async *receiveMessages<T = unknown>(\n options: ReceiveMessagesOptions<T>,\n transport: Transport<T>,\n ): AsyncGenerator<Message<T>, void, unknown> {\n const { queueName, consumerGroup, visibilityTimeoutSeconds, limit } =\n options;\n\n // Validate limit parameter\n if (limit !== undefined && (limit < 1 || limit > 10)) {\n throw new InvalidLimitError(limit);\n }\n\n const headers = new Headers({\n Authorization: `Bearer ${this.token}`,\n \"Vqs-Queue-Name\": queueName,\n \"Vqs-Consumer-Group\": consumerGroup,\n Accept: \"multipart/mixed\",\n });\n\n if (visibilityTimeoutSeconds !== undefined) {\n headers.set(\n \"Vqs-Visibility-Timeout\",\n visibilityTimeoutSeconds.toString(),\n );\n }\n\n if (limit !== undefined) {\n headers.set(\"Vqs-Limit\", limit.toString());\n }\n\n const response = await fetch(`${this.baseUrl}/api/v2/messages`, {\n method: \"GET\",\n headers,\n });\n\n // Check for 204 No Content - queue is empty\n if (response.status === 204) {\n throw new QueueEmptyError(queueName, consumerGroup);\n }\n\n if (!response.ok) {\n if (response.status === 400) {\n const errorText = await response.text();\n throw new BadRequestError(errorText || \"Invalid parameters\");\n }\n if (response.status === 401) {\n throw new UnauthorizedError();\n }\n if (response.status === 403) {\n throw new ForbiddenError();\n }\n if (response.status === 423) {\n // Message locked - temporarily unavailable\n const retryAfterHeader = response.headers.get(\"Retry-After\");\n let retryAfter: number | undefined;\n if (retryAfterHeader) {\n const parsed = parseInt(retryAfterHeader, 10);\n retryAfter = isNaN(parsed) ? undefined : parsed;\n }\n throw new MessageLockedError(\"next message\", retryAfter);\n }\n if (response.status >= 500) {\n throw new InternalServerError(\n `Server error: ${response.status} ${response.statusText}`,\n );\n }\n throw new Error(\n `Failed to receive messages: ${response.status} ${response.statusText}`,\n );\n }\n\n // Stream messages as they arrive from the multipart parser\n // Each message's payload stream must be consumed immediately for the parser to proceed\n for await (const multipartMessage of parseMultipartStream(response)) {\n try {\n // Parse VQS headers using the helper function\n const parsedHeaders = parseQueueHeaders(multipartMessage.headers);\n\n if (!parsedHeaders) {\n console.warn(\"Missing required queue headers in multipart part\");\n // Still need to consume the payload stream to let the parser proceed\n await consumeStream(multipartMessage.payload);\n continue;\n }\n\n // Deserialize using the provided transport (must consume the stream)\n const deserializedPayload = await transport.deserialize(\n multipartMessage.payload,\n );\n\n const message: Message<T> = {\n ...parsedHeaders,\n payload: deserializedPayload,\n };\n\n yield message;\n } catch (error) {\n console.warn(\"Failed to process multipart message:\", error);\n // If deserialization failed, we still need to consume the payload stream\n // to let the multipart parser proceed to the next message\n await consumeStream(multipartMessage.payload);\n }\n }\n }\n\n /**\n * Receive a specific message by its ID from a queue\n * @param options Receive message by ID options\n * @param transport Serializer/deserializer for the payload\n * @returns Promise with the message or null if not found/available\n * @throws {MessageNotFoundError} When the message doesn't exist (404)\n * @throws {MessageLockedError} When the message is temporarily locked (423)\n * @throws {MessageNotAvailableError} When message exists but isn't available (409)\n * @throws {MessageCorruptedError} When message data is corrupted\n * @throws {BadRequestError} When request parameters are invalid\n * @throws {UnauthorizedError} When authentication fails\n * @throws {ForbiddenError} When access is denied (environment mismatch)\n * @throws {InternalServerError} When server encounters an error\n */\n async receiveMessageById<T = unknown>(\n options: ReceiveMessageByIdOptions<T> & { skipPayload: true },\n transport?: Transport<T>,\n ): Promise<ReceiveMessageByIdResponse<T, true>>;\n async receiveMessageById<T = unknown>(\n options: ReceiveMessageByIdOptions<T> & { skipPayload?: false | undefined },\n transport: Transport<T>,\n ): Promise<ReceiveMessageByIdResponse<T, false>>;\n async receiveMessageById<T = unknown>(\n options: ReceiveMessageByIdOptions<T>,\n transport?: Transport<T>,\n ): Promise<ReceiveMessageByIdResponse<T, boolean>> {\n const {\n queueName,\n consumerGroup,\n messageId,\n visibilityTimeoutSeconds,\n skipPayload,\n } = options;\n\n const headers = new Headers({\n Authorization: `Bearer ${this.token}`,\n \"Vqs-Queue-Name\": queueName,\n \"Vqs-Consumer-Group\": consumerGroup,\n Accept: \"multipart/mixed\",\n });\n\n if (visibilityTimeoutSeconds !== undefined) {\n headers.set(\n \"Vqs-Visibility-Timeout\",\n visibilityTimeoutSeconds.toString(),\n );\n }\n\n if (skipPayload) {\n headers.set(\"Vqs-Skip-Payload\", \"1\");\n }\n\n const response = await fetch(\n `${this.baseUrl}/api/v2/messages/${encodeURIComponent(messageId)}`,\n {\n method: \"GET\",\n headers,\n },\n );\n\n if (!response.ok) {\n if (response.status === 400) {\n const errorText = await response.text();\n throw new BadRequestError(errorText || \"Invalid parameters\");\n }\n if (response.status === 401) {\n throw new UnauthorizedError();\n }\n if (response.status === 403) {\n throw new ForbiddenError();\n }\n if (response.status === 404) {\n // Message not found\n throw new MessageNotFoundError(messageId);\n }\n if (response.status === 423) {\n // Message is temporarily locked\n const retryAfterHeader = response.headers.get(\"Retry-After\");\n let retryAfter: number | undefined;\n if (retryAfterHeader) {\n const parsed = parseInt(retryAfterHeader, 10);\n retryAfter = isNaN(parsed) ? undefined : parsed;\n }\n throw new MessageLockedError(messageId, retryAfter);\n }\n\n if (response.status === 409) {\n // Message not available (wrong state or claimed by another consumer)\n throw new MessageNotAvailableError(messageId);\n }\n if (response.status >= 500) {\n throw new InternalServerError(\n `Server error: ${response.status} ${response.statusText}`,\n );\n }\n throw new Error(\n `Failed to receive message by ID: ${response.status} ${response.statusText}`,\n );\n }\n\n // Handle skipPayload case with 204 response\n if (skipPayload && response.status === 204) {\n const parsedHeaders = parseQueueHeaders(response.headers);\n\n if (!parsedHeaders) {\n throw new MessageCorruptedError(\n messageId,\n \"Missing required queue headers in 204 response\",\n );\n }\n\n const message: Message<void> = {\n ...parsedHeaders,\n payload: undefined as void,\n };\n\n return { message } as ReceiveMessageByIdResponse<T, boolean>;\n }\n\n // Handle regular multipart response\n if (!transport) {\n throw new Error(\"Transport is required when skipPayload is not true\");\n }\n\n // Parse multipart/mixed response using streaming parser\n try {\n for await (const multipartMessage of parseMultipartStream(response)) {\n try {\n // Parse queue headers using the helper function\n const parsedHeaders = parseQueueHeaders(multipartMessage.headers);\n\n if (!parsedHeaders) {\n console.warn(\"Missing required queue headers in multipart part\");\n // Still need to consume the payload stream to let the parser proceed\n await consumeStream(multipartMessage.payload);\n continue;\n }\n\n // Deserialize using the provided transport (must consume the stream)\n const deserializedPayload = await transport.deserialize(\n multipartMessage.payload,\n );\n\n const message: Message<T> = {\n ...parsedHeaders,\n payload: deserializedPayload,\n };\n\n return { message };\n } catch (error) {\n console.warn(\"Failed to deserialize message by ID:\", error);\n // If deserialization failed, we still need to consume the payload stream\n // to let the multipart parser proceed to the next message\n await consumeStream(multipartMessage.payload);\n throw new MessageCorruptedError(\n messageId,\n `Failed to deserialize payload: ${error}`,\n );\n }\n }\n } catch (error) {\n if (error instanceof MessageCorruptedError) {\n throw error; // Re-throw our own errors\n }\n throw new MessageCorruptedError(\n messageId,\n `Failed to parse multipart response: ${error}`,\n );\n }\n\n // If we get here, no message was found in the multipart response\n throw new MessageNotFoundError(messageId);\n }\n\n /**\n * Delete a message (acknowledge processing)\n * @param options Delete message options\n * @returns Promise with delete status\n * @throws {MessageNotFoundError} When the message doesn't exist (404)\n * @throws {MessageNotAvailableError} When message can't be deleted (409)\n * @throws {BadRequestError} When ticket is missing or invalid (400)\n * @throws {UnauthorizedError} When authentication fails\n * @throws {ForbiddenError} When access is denied (environment mismatch)\n * @throws {InternalServerError} When server encounters an error\n */\n async deleteMessage(\n options: DeleteMessageOptions,\n ): Promise<DeleteMessageResponse> {\n const { queueName, consumerGroup, messageId, ticket } = options;\n\n const response = await fetch(\n `${this.baseUrl}/api/v2/messages/${encodeURIComponent(messageId)}`,\n {\n method: \"DELETE\",\n headers: new Headers({\n Authorization: `Bearer ${this.token}`,\n \"Vqs-Queue-Name\": queueName,\n \"Vqs-Consumer-Group\": consumerGroup,\n \"Vqs-Ticket\": ticket,\n }),\n },\n );\n\n if (!response.ok) {\n if (response.status === 400) {\n throw new BadRequestError(\"Missing or invalid ticket\");\n }\n if (response.status === 401) {\n throw new UnauthorizedError();\n }\n if (response.status === 403) {\n throw new ForbiddenError();\n }\n if (response.status === 404) {\n throw new MessageNotFoundError(messageId);\n }\n if (response.status === 409) {\n throw new MessageNotAvailableError(\n messageId,\n \"Invalid ticket, message not in correct state, or already processed\",\n );\n }\n if (response.status >= 500) {\n throw new InternalServerError(\n `Server error: ${response.status} ${response.statusText}`,\n );\n }\n throw new Error(\n `Failed to delete message: ${response.status} ${response.statusText}`,\n );\n }\n\n return { deleted: true };\n }\n\n /**\n * Change the visibility timeout of a message\n * @param options Change visibility options\n * @returns Promise with update status\n * @throws {MessageNotFoundError} When the message doesn't exist (404)\n * @throws {MessageNotAvailableError} When message can't be updated (409)\n * @throws {BadRequestError} When ticket is missing or visibility timeout invalid (400)\n * @throws {UnauthorizedError} When authentication fails\n * @throws {ForbiddenError} When access is denied (environment mismatch)\n * @throws {InternalServerError} When server encounters an error\n */\n async changeVisibility(\n options: ChangeVisibilityOptions,\n ): Promise<ChangeVisibilityResponse> {\n const {\n queueName,\n consumerGroup,\n messageId,\n ticket,\n visibilityTimeoutSeconds,\n } = options;\n\n const response = await fetch(\n `${this.baseUrl}/api/v2/messages/${encodeURIComponent(messageId)}`,\n {\n method: \"PATCH\",\n headers: new Headers({\n Authorization: `Bearer ${this.token}`,\n \"Vqs-Queue-Name\": queueName,\n \"Vqs-Consumer-Group\": consumerGroup,\n \"Vqs-Ticket\": ticket,\n \"Vqs-Visibility-Timeout\": visibilityTimeoutSeconds.toString(),\n }),\n },\n );\n\n if (!response.ok) {\n if (response.status === 400) {\n throw new BadRequestError(\n \"Missing ticket or invalid visibility timeout\",\n );\n }\n if (response.status === 401) {\n throw new UnauthorizedError();\n }\n if (response.status === 403) {\n throw new ForbiddenError();\n }\n if (response.status === 404) {\n throw new MessageNotFoundError(messageId);\n }\n if (response.status === 409) {\n throw new MessageNotAvailableError(\n messageId,\n \"Invalid ticket, message not in correct state, or already processed\",\n );\n }\n if (response.status >= 500) {\n throw new InternalServerError(\n `Server error: ${response.status} ${response.statusText}`,\n );\n }\n throw new Error(\n `Failed to change visibility: ${response.status} ${response.statusText}`,\n );\n }\n\n return { updated: true };\n }\n}\n","/**\n * Vercel Queue Service client types\n */\nimport type { Transport } from \"./transports\";\n\n// Re-export transport interface for convenience\nexport type { Transport };\n\nexport interface QueueClientOptions {\n /**\n * Base URL for the Vercel Queue Service API\n * @default \"https://vqs.vercel.sh\"\n */\n baseUrl?: string;\n /**\n * Vercel function OIDC token\n * Can be obtained from x-vercel-oidc-token header in Vercel Serverless Functions\n * If not provided, will automatically attempt to retrieve from Vercel Function environment\n */\n token?: string;\n}\n\n/**\n * Shared options for publishing messages\n */\nexport interface PublishOptions {\n /**\n * Unique key to prevent duplicate message submissions\n * @default random UUID\n */\n idempotencyKey?: string;\n /**\n * Message retention time in seconds\n * @default 86400 (24 hours)\n * @min 60\n * @max 86400\n */\n retentionSeconds?: number;\n}\n\nexport interface SendMessageOptions<T = unknown> extends PublishOptions {\n /**\n * The queue name to send the message to\n */\n queueName: string;\n /**\n * The message payload\n */\n payload: T;\n}\n\nexport interface SendMessageResponse {\n /**\n * The generated message ID\n */\n messageId: string;\n}\n\nexport interface Message<T = unknown> {\n /**\n * The message ID\n */\n messageId: string;\n /**\n * The deserialized message payload\n * Note: If using streaming transports, ensure proper cleanup by calling transport.finalize(payload)\n * when done processing, especially in error cases\n */\n payload: T;\n /**\n * Number of times this message has been delivered\n */\n deliveryCount: number;\n /**\n * Timestamp when the message was created\n */\n timestamp: string;\n /**\n * MIME type of the message content\n */\n contentType: string;\n /**\n * Unique ticket for this message delivery (required for delete/patch operations)\n */\n ticket: string;\n}\n\nexport interface ReceiveMessagesOptions<T = unknown> {\n /**\n * The queue name to receive messages from\n */\n queueName: string;\n /**\n * Consumer group name\n */\n consumerGroup: string;\n /**\n * Time in seconds that messages will be invisible to other consumers\n * @default 900 (15 minutes)\n */\n visibilityTimeoutSeconds?: number;\n /**\n * Maximum number of messages to retrieve\n * @default 10\n * @max 10\n */\n limit?: number;\n}\n\nexport interface DeleteMessageOptions {\n /**\n * The queue name the message belongs to\n */\n queueName: string;\n /**\n * Consumer group name\n */\n consumerGroup: string;\n /**\n * The message ID to delete\n */\n messageId: string;\n /**\n * Ticket received from the message\n */\n ticket: string;\n}\n\nexport interface DeleteMessageResponse {\n /**\n * Whether the message was successfully deleted\n */\n deleted: boolean;\n}\n\nexport interface ChangeVisibilityOptions {\n /**\n * The queue name the message belongs to\n */\n queueName: string;\n /**\n * Consumer group name\n */\n consumerGroup: string;\n /**\n * The message ID to update\n */\n messageId: string;\n /**\n * Ticket received from the message\n */\n ticket: string;\n /**\n * New visibility timeout in seconds\n */\n visibilityTimeoutSeconds: number;\n}\n\nexport interface ChangeVisibilityResponse {\n /**\n * Whether the visibility was successfully updated\n */\n updated: boolean;\n}\n\n/**\n * Result indicating the message should be timed out for retry later\n */\nexport interface MessageTimeoutResult {\n /**\n * Time in seconds before the message becomes visible again\n */\n timeoutSeconds: number;\n}\n\n/**\n * Result returned by message handlers\n */\nexport type MessageHandlerResult = void | MessageTimeoutResult;\n\n/**\n * Message metadata provided to handlers\n */\nexport interface MessageMetadata {\n messageId: string;\n deliveryCount: number;\n timestamp: string;\n}\n\n/**\n * Message handler function type\n */\nexport type MessageHandler<T = unknown> = (\n message: T,\n metadata: MessageMetadata,\n) => Promise<MessageHandlerResult> | MessageHandlerResult;\n\n/**\n * Options for creating a ConsumerGroup instance\n */\nexport interface ConsumerGroupOptions<T = unknown> {\n /**\n * Serializer/deserializer for the payload\n * @default JsonTransport instance\n */\n transport?: Transport<T>;\n /**\n * Time in seconds that messages will be invisible to other consumers\n * @default 30\n */\n visibilityTimeoutSeconds?: number;\n /**\n * How often to refresh the visibility timeout during processing (in seconds)\n * @default 10\n */\n refreshInterval?: number;\n}\n\nexport interface ReceiveMessageByIdOptions<T = unknown> {\n /**\n * The queue name to receive the message from\n */\n queueName: string;\n /**\n * Consumer group name\n */\n consumerGroup: string;\n /**\n * The message ID to retrieve\n */\n messageId: string;\n /**\n * Time in seconds that the message will be invisible to other consumers\n * @default 900 (15 minutes)\n */\n visibilityTimeoutSeconds?: number;\n /**\n * Skip payload content and only return message metadata\n * When true, the server returns a 204 status with headers containing message metadata\n * @default false\n */\n skipPayload?: boolean;\n}\n\n// Response type that always contains a message (errors are thrown for failures)\nexport interface ReceiveMessageByIdResponse<\n T = unknown,\n TSkipPayload extends boolean = false,\n> {\n message: TSkipPayload extends true ? Message<void> : Message<T>;\n}\n\n/**\n * Error thrown when a message is not found (404)\n */\nexport class MessageNotFoundError extends Error {\n constructor(messageId: string) {\n super(`Message ${messageId} not found`);\n this.name = \"MessageNotFoundError\";\n }\n}\n\n/**\n * Error thrown when a message is not available for processing (409)\n * This can happen when the message is in the wrong state, already claimed, etc.\n */\nexport class MessageNotAvailableError extends Error {\n constructor(messageId: string, reason?: string) {\n super(\n `Message ${messageId} not available for processing${reason ? `: ${reason}` : \"\"}`,\n );\n this.name = \"MessageNotAvailableError\";\n }\n}\n\n/**\n * Error thrown when message data is corrupted or can't be parsed\n */\nexport class MessageCorruptedError extends Error {\n constructor(messageId: string, reason: string) {\n super(`Message ${messageId} is corrupted: ${reason}`);\n this.name = \"MessageCorruptedError\";\n }\n}\n\n/**\n * Error thrown when there are no messages available in the queue (204)\n */\nexport class QueueEmptyError extends Error {\n constructor(queueName: string, consumerGroup: string) {\n super(\n `No messages available in queue \"${queueName}\" for consumer group \"${consumerGroup}\"`,\n );\n this.name = \"QueueEmptyError\";\n }\n}\n\n/**\n * Error thrown when a message is temporarily locked (423)\n */\nexport class MessageLockedError extends Error {\n public readonly retryAfter?: number;\n\n constructor(messageId: string, retryAfter?: number) {\n const retryMessage = retryAfter\n ? ` Retry after ${retryAfter} seconds.`\n : \" Try again later.\";\n super(`Message ${messageId} is temporarily locked.${retryMessage}`);\n this.name = \"MessageLockedError\";\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Error thrown when authentication fails (401)\n */\nexport class UnauthorizedError extends Error {\n constructor(message: string = \"Missing or invalid authentication token\") {\n super(message);\n this.name = \"UnauthorizedError\";\n }\n}\n\n/**\n * Error thrown when access is forbidden (403)\n */\nexport class ForbiddenError extends Error {\n constructor(\n message: string = \"Queue environment doesn't match token environment\",\n ) {\n super(message);\n this.name = \"ForbiddenError\";\n }\n}\n\n/**\n * Error thrown for bad requests (400)\n */\nexport class BadRequestError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BadRequestError\";\n }\n}\n\n/**\n * Error thrown for internal server errors (500)\n */\nexport class InternalServerError extends Error {\n constructor(message: string = \"Unexpected server error\") {\n super(message);\n this.name = \"InternalServerError\";\n }\n}\n\n/**\n * Error thrown when batch limit parameter is invalid\n */\nexport class InvalidLimitError extends Error {\n constructor(limit: number, min: number = 1, max: number = 10) {\n super(`Invalid limit: ${limit}. Limit must be between ${min} and ${max}.`);\n this.name = \"InvalidLimitError\";\n }\n}\n","import { QueueClient } from \"./client\";\nimport { JsonTransport } from \"./transports\";\nimport type {\n ConsumerGroupOptions,\n Message,\n MessageHandler,\n Transport,\n} from \"./types\";\n\n/**\n * Options for the consume method\n */\nexport interface ConsumeOptions {\n /** The specific message ID to consume (if not provided, consumes next available message) */\n messageId?: string;\n /** Whether to skip downloading the payload (only allowed when messageId is provided) */\n skipPayload?: boolean;\n}\n\n/**\n * A ConsumerGroup represents a named group of consumers that process messages from a topic\n */\nexport class ConsumerGroup<T = unknown> {\n private client: QueueClient;\n private topicName: string;\n private consumerGroupName: string;\n private visibilityTimeout: number;\n private refreshInterval: number;\n private transport: Transport<T>;\n\n /**\n * Create a new ConsumerGroup instance\n * @param client QueueClient instance to use for API calls\n * @param topicName Name of the topic to consume from\n * @param consumerGroupName Name of the consumer group\n * @param options Optional configuration\n */\n constructor(\n client: QueueClient,\n topicName: string,\n consumerGroupName: string,\n options: ConsumerGroupOptions<T> = {},\n ) {\n this.client = client;\n this.topicName = topicName;\n this.consumerGroupName = consumerGroupName;\n this.visibilityTimeout = options.visibilityTimeoutSeconds || 30; // 30 seconds default\n this.refreshInterval = options.refreshInterval || 10; // 10 seconds default\n this.transport = options.transport || new JsonTransport<T>();\n }\n\n /**\n * Starts a background loop that periodically extends the visibility timeout for a message.\n * This prevents the message from becoming visible to other consumers while it's being processed.\n *\n * The extension loop runs every `refreshInterval` seconds and updates the message's\n * visibility timeout to `visibilityTimeout` seconds from the current time.\n *\n * @param messageId - The unique identifier of the message to extend visibility for\n * @param ticket - The receipt ticket that proves ownership of the message\n * @returns A function that when called will stop the extension loop\n *\n * @remarks\n * - The first extension attempt occurs after `refreshInterval` seconds, not immediately\n * - If an extension fails, the loop terminates with an error logged to console\n * - The returned stop function is idempotent - calling it multiple times is safe\n * - By default, the stop function returns immediately without waiting for in-flight\n * - Pass `true` to the stop function to wait for any in-flight extension to complete\n */\n private startVisibilityExtension(\n messageId: string,\n ticket: string,\n ): (waitForCompletion?: boolean) => Promise<void> {\n let isRunning = true;\n let resolveLifecycle: () => void;\n let timeoutId: NodeJS.Timeout | null = null;\n\n // Promise that tracks the actual termination of the extension loop\n const lifecyclePromise = new Promise<void>((resolve) => {\n resolveLifecycle = resolve;\n });\n\n const extend = async (): Promise<void> => {\n // Check if we should stop before attempting extension\n if (!isRunning) {\n resolveLifecycle();\n return;\n }\n\n try {\n // Extend the visibility timeout for another period\n await this.client.changeVisibility({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n messageId,\n ticket,\n visibilityTimeoutSeconds: this.visibilityTimeout,\n });\n\n // Schedule next extension if still running\n if (isRunning) {\n timeoutId = setTimeout(() => extend(), this.refreshInterval * 1000);\n } else {\n // Signal that the loop has terminated after successful extension\n resolveLifecycle();\n }\n } catch (error) {\n // Log error and terminate the loop on failure\n console.error(\n `Failed to extend visibility for message ${messageId}:`,\n error,\n );\n resolveLifecycle();\n }\n };\n\n // Schedule the first extension attempt\n timeoutId = setTimeout(() => extend(), this.refreshInterval * 1000);\n\n // Return a function to stop the extension loop\n return async (waitForCompletion: boolean = false) => {\n // Signal the loop to stop\n isRunning = false;\n\n // Cancel any pending timeout to avoid unnecessary waiting\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n // Only wait for in-flight operations if explicitly requested\n if (waitForCompletion) {\n // Wait for the loop to actually terminate\n // This ensures any in-progress extension completes or fails\n await lifecyclePromise;\n } else {\n // Resolve the lifecycle immediately for any waiting operations\n // This allows immediate return without waiting for in-flight extensions\n resolveLifecycle();\n }\n };\n }\n\n /**\n * Process a single message with the given handler\n * @param message The message to process\n * @param handler Function to process the message\n */\n private async processMessage<TPayload>(\n message: Message<TPayload>,\n handler: MessageHandler<TPayload>,\n ): Promise<void> {\n const stopExtension = this.startVisibilityExtension(\n message.messageId,\n message.ticket,\n );\n\n try {\n const result = await handler(message.payload, {\n messageId: message.messageId,\n deliveryCount: message.deliveryCount,\n timestamp: message.timestamp,\n });\n // Stop extensions immediately - we don't need to wait for in-flight extensions\n // since we're about to delete or update the message visibility anyway\n await stopExtension();\n\n if (result && \"timeoutSeconds\" in result) {\n // Handle timeout request - set new visibility timeout instead of deleting\n await this.client.changeVisibility({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n messageId: message.messageId,\n ticket: message.ticket,\n visibilityTimeoutSeconds: result.timeoutSeconds,\n });\n } else {\n // Normal completion - delete the message\n await this.client.deleteMessage({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n messageId: message.messageId,\n ticket: message.ticket,\n });\n }\n } catch (error) {\n // Stop extensions immediately on error - fail fast without waiting\n // for any in-flight extension attempts\n await stopExtension();\n\n // Clean up the message payload if the transport supports it and payload exists\n // Only call finalize for non-void payloads since transport is typed for T, not void\n if (\n this.transport.finalize &&\n message.payload !== undefined &&\n message.payload !== null\n ) {\n try {\n // Safe cast: when processMessage<T> is called, TPayload is T\n // when processMessage<void> is called, payload is undefined so this won't execute\n await this.transport.finalize(message.payload as T);\n } catch (finalizeError) {\n console.warn(\"Failed to finalize message payload:\", finalizeError);\n }\n }\n\n throw error;\n }\n }\n\n /**\n * Consume the next available message from the queue\n * @param handler Function to process the message\n * @returns Promise that resolves when the message is processed\n * @throws All the same errors as the underlying client methods\n */\n async consume(handler: MessageHandler<T>): Promise<void>;\n\n /**\n * Consume a specific message by its ID with full payload\n * @param handler Function to process the message\n * @param options Consume options with messageId specified\n * @returns Promise that resolves when the message is processed\n * @throws All the same errors as the underlying client methods\n */\n async consume(\n handler: MessageHandler<T>,\n options: { messageId: string; skipPayload?: false | undefined },\n ): Promise<void>;\n\n /**\n * Consume a specific message by its ID without downloading the payload (metadata only)\n * @param handler Function to process the message metadata (payload will be void)\n * @param options Consume options with messageId and skipPayload specified\n * @returns Promise that resolves when the message is processed\n * @throws All the same errors as the underlying client methods\n */\n async consume(\n handler: MessageHandler<void>,\n options: { messageId: string; skipPayload: true },\n ): Promise<void>;\n\n async consume(\n handler: MessageHandler<T> | MessageHandler<void>,\n options?: ConsumeOptions,\n ): Promise<void> {\n if (options?.messageId) {\n // Specific message mode\n if (options.skipPayload) {\n // Skip payload - like old handleMessage\n const response = await this.client.receiveMessageById(\n {\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n messageId: options.messageId,\n visibilityTimeoutSeconds: this.visibilityTimeout,\n skipPayload: true,\n },\n this.transport,\n );\n await this.processMessage<void>(\n response.message,\n handler as MessageHandler<void>,\n );\n } else {\n // With payload - like old receiveMessage\n const response = await this.client.receiveMessageById(\n {\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n messageId: options.messageId,\n visibilityTimeoutSeconds: this.visibilityTimeout,\n },\n this.transport,\n );\n await this.processMessage<T>(\n response.message,\n handler as MessageHandler<T>,\n );\n }\n } else {\n // Next message mode - like old receiveNextMessage\n let messageFound = false;\n\n for await (const message of this.client.receiveMessages<T>(\n {\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n visibilityTimeoutSeconds: this.visibilityTimeout,\n limit: 1,\n },\n this.transport,\n )) {\n messageFound = true;\n await this.processMessage<T>(message, handler as MessageHandler<T>);\n break; // Process only one message\n }\n\n // If we get here without finding a message, the async generator\n // should have already thrown QueueEmptyError, but just in case\n if (!messageFound) {\n throw new Error(\"No messages available\");\n }\n }\n }\n\n /**\n * Get the consumer group name\n */\n get name(): string {\n return this.consumerGroupName;\n }\n\n /**\n * Get the topic name this consumer group is subscribed to\n */\n get topic(): string {\n return this.topicName;\n }\n}\n","import { QueueClient } from \"./client\";\nimport { ConsumerGroup } from \"./consumer-group\";\nimport { JsonTransport } from \"./transports\";\nimport type { ConsumerGroupOptions, PublishOptions, Transport } from \"./types\";\n\n/**\n * A Topic represents a named channel for publishing messages in a pub/sub pattern\n */\nexport class Topic<T = unknown> {\n private client: QueueClient;\n private topicName: string;\n private transport: Transport<T>;\n\n /**\n * Create a new Topic instance\n * @param client QueueClient instance to use for API calls\n * @param topicName Name of the topic to work with\n * @param transport Optional serializer/deserializer for the payload (defaults to JSON)\n */\n constructor(\n client: QueueClient,\n topicName: string,\n transport?: Transport<T>,\n ) {\n this.client = client;\n this.topicName = topicName;\n this.transport = transport || new JsonTransport<T>();\n }\n\n /**\n * Publish a message to the topic\n * @param payload The data to publish\n * @param options Optional publish options\n * @returns An object containing the message ID\n * @throws {BadRequestError} When request parameters are invalid\n * @throws {UnauthorizedError} When authentication fails\n * @throws {ForbiddenError} When access is denied (environment mismatch)\n * @throws {InternalServerError} When server encounters an error\n */\n async publish(\n payload: T,\n options?: PublishOptions,\n ): Promise<{ messageId: string }> {\n const result = await this.client.sendMessage<T>(\n {\n queueName: this.topicName,\n payload,\n idempotencyKey: options?.idempotencyKey,\n retentionSeconds: options?.retentionSeconds,\n },\n this.transport,\n );\n return { messageId: result.messageId };\n }\n\n /**\n * Create a consumer group for this topic\n * @param consumerGroupName Name of the consumer group\n * @param options Optional configuration for the consumer group\n * @returns A ConsumerGroup instance\n */\n consumerGroup<U = T>(\n consumerGroupName: string,\n options?: ConsumerGroupOptions<U>,\n ): ConsumerGroup<U> {\n // If no transport is provided in options, use the topic's transport if types match\n const consumerOptions: ConsumerGroupOptions<U> = {\n ...options,\n transport:\n options?.transport || (this.transport as unknown as Transport<U>),\n };\n\n return new ConsumerGroup<U>(\n this.client,\n this.topicName,\n consumerGroupName,\n consumerOptions,\n );\n }\n\n /**\n * Get the topic name\n */\n get name(): string {\n return this.topicName;\n }\n\n /**\n * Get the transport used by this topic\n */\n get serializer(): Transport<T> {\n return this.transport;\n }\n}\n","import { QueueClient } from \"./client\";\nimport type { ConsumeOptions } from \"./consumer-group\";\nimport { Topic } from \"./topic\";\nimport { JsonTransport } from \"./transports\";\nimport type {\n ConsumerGroupOptions,\n MessageHandler,\n PublishOptions,\n Transport,\n} from \"./types\";\n\n/**\n * Options for the send function\n */\nexport interface SendOptions<T = unknown> extends PublishOptions {\n /**\n * Serializer/deserializer for the payload\n * @default JsonTransport instance\n */\n transport?: Transport<T>;\n}\n\n/**\n * Send a message to a topic (shorthand for topic creation and publishing)\n * Uses the default QueueClient with automatic OIDC token detection\n * @param topicName Name of the topic to send to\n * @param payload The data to send\n * @param options Optional send options including transport and publish settings\n * @returns Promise with the message ID\n * @throws {BadRequestError} When request parameters are invalid\n * @throws {UnauthorizedError} When authentication fails\n * @throws {ForbiddenError} When access is denied (environment mismatch)\n * @throws {InternalServerError} When server encounters an error\n */\nexport async function send<T = unknown>(\n topicName: string,\n payload: T,\n options?: SendOptions<T>,\n): Promise<{ messageId: string }> {\n const transport = options?.transport || new JsonTransport<T>();\n const client = QueueClient._getDefaultInstance();\n\n const result = await client.sendMessage<T>(\n {\n queueName: topicName,\n payload,\n idempotencyKey: options?.idempotencyKey,\n retentionSeconds: options?.retentionSeconds,\n },\n transport,\n );\n\n return { messageId: result.messageId };\n}\n\n/**\n * Options for the receive function\n */\nexport interface ReceiveOptions<T = unknown>\n extends ConsumerGroupOptions<T>,\n ConsumeOptions {}\n\n/**\n * Receive a message from a topic (shorthand for topic and consumer group creation)\n * Uses the default QueueClient with automatic OIDC token detection\n * @param topicName Name of the topic to receive from\n * @param consumerGroup Name of the consumer group\n * @param handler Function to process the message\n * @returns Promise that resolves when the message is processed\n * @throws All the same errors as the underlying client methods\n */\nexport async function receive<T = unknown>(\n topicName: string,\n consumerGroup: string,\n handler: MessageHandler<T>,\n options?: ReceiveOptions<T>,\n): Promise<void>;\n\n/**\n * Receive a specific message by its ID with full payload\n * @param topicName Name of the topic to receive from\n * @param consumerGroup Name of the consumer group\n * @param handler Function to process the message\n * @param options Receive options with messageId specified\n * @returns Promise that resolves when the message is processed\n * @throws All the same errors as the underlying client methods\n */\nexport async function receive<T = unknown>(\n topicName: string,\n consumerGroup: string,\n handler: MessageHandler<T>,\n options: ReceiveOptions<T> & {\n messageId: string;\n skipPayload?: false | undefined;\n },\n): Promise<void>;\n\n/**\n * Receive a specific message by its ID without downloading the payload (metadata only)\n * @param topicName Name of the topic to receive from\n * @param consumerGroup Name of the consumer group\n * @param handler Function to process the message metadata (payload will be void)\n * @param options Receive options with messageId and skipPayload specified\n * @returns Promise that resolves when the message is processed\n * @throws All the same errors as the underlying client methods\n */\nexport async function receive<T = unknown>(\n topicName: string,\n consumerGroup: string,\n handler: MessageHandler<void>,\n options: ReceiveOptions<T> & { messageId: string; skipPayload: true },\n): Promise<void>;\n\nexport async function receive<T = unknown>(\n topicName: string,\n consumerGroup: string,\n handler: MessageHandler<T> | MessageHandler<void>,\n options?: ReceiveOptions<T>,\n): Promise<void> {\n const transport = options?.transport || new JsonTransport<T>();\n\n // Create topic with transport directly\n const client = QueueClient._getDefaultInstance();\n const topic = new Topic<T>(client, topicName, transport);\n\n // Create consumer group with options (excluding consume-specific options)\n const { messageId, skipPayload, ...consumerGroupOptions } = options || {};\n const consumer = topic.consumerGroup(consumerGroup, consumerGroupOptions);\n\n // Call consume with the appropriate overload based on options\n if (messageId) {\n if (skipPayload) {\n // skipPayload: true case\n return consumer.consume(handler as MessageHandler<void>, {\n messageId,\n skipPayload: true,\n });\n } else {\n // messageId with payload case\n return consumer.consume(handler as MessageHandler<T>, { messageId });\n }\n } else {\n // No options case - next available message\n return consumer.consume(handler as MessageHandler<T>);\n }\n}\n","/**\n * Queue Callback utilities for handling incoming webhook payloads from Vercel triggers\n */\nimport { QueueClient } from \"./client\";\nimport { Topic } from \"./topic\";\nimport type { MessageHandler } from \"./types\";\n\n/**\n * CloudEvent specification for queue callbacks\n */\nexport interface CloudEvent<T = unknown> {\n type: string;\n source: string;\n id: string;\n datacontenttype: string;\n data: T;\n time?: string;\n specversion?: string;\n}\n\n/**\n * Configuration object with handlers for different topics and consumer groups\n */\ntype CallbackHandlers = {\n [topicName: string]: { [consumerGroup: string]: MessageHandler };\n};\n\n/**\n * Parsed callback request information\n */\nexport type ParsedCallbackRequest = {\n queueName: string;\n consumerGroup: string;\n messageId: string;\n};\n\n/**\n * Parse and validate callback request using CloudEvent specification\n *\n * Extracts queue information from CloudEvent format and validates\n * that all required fields are present.\n *\n * @param request The incoming webhook request\n * @returns Parsed queue information\n * @throws Error if required fields are missing\n *\n * @example\n * ```typescript\n * // In Next.js API route\n * export async function POST(request: Request) {\n * try {\n * const { queueName, consumerGroup, messageId } = parseCallbackRequest(request);\n *\n * // Use the parsed information...\n * await myWorkflow.handleWebhook(queueName, consumerGroup, messageId);\n *\n * return Response.json({ status: \"success\" });\n * } catch (error) {\n * return Response.json({ error: error.message }, { status: 400 });\n * }\n * }\n * ```\n */\nexport async function parseCallbackRequest(\n request: Request,\n): Promise<ParsedCallbackRequest> {\n // Validate content type header\n const contentType = request.headers.get(\"content-type\");\n if (!contentType || !contentType.includes(\"application/cloudevents+json\")) {\n throw new Error(\n \"Invalid content type: expected 'application/cloudevents+json'\",\n );\n }\n\n let cloudEvent: CloudEvent;\n\n try {\n cloudEvent = (await request.json()) as CloudEvent;\n } catch (error) {\n throw new Error(\"Failed to parse CloudEvent from request body\");\n }\n\n // Validate CloudEvent structure\n if (\n !cloudEvent.type ||\n !cloudEvent.source ||\n !cloudEvent.id ||\n typeof cloudEvent.data !== \"object\" ||\n cloudEvent.data == null\n ) {\n throw new Error(\"Invalid CloudEvent: missing required fields\");\n }\n\n // Validate CloudEvent type\n if (cloudEvent.type !== \"com.vercel.queue.v1beta\") {\n throw new Error(\n `Invalid CloudEvent type: expected 'com.vercel.queue.v1beta', got '${cloudEvent.type}'`,\n );\n }\n\n // Check for required data fields before destructuring\n const missingFields: string[] = [];\n if (!(\"queueName\" in cloudEvent.data)) missingFields.push(\"queueName\");\n if (!(\"consumerGroup\" in cloudEvent.data))\n missingFields.push(\"consumerGroup\");\n if (!(\"messageId\" in cloudEvent.data)) missingFields.push(\"messageId\");\n if (missingFields.length > 0) {\n throw new Error(\n `Missing required CloudEvent data fields: ${missingFields.join(\", \")}`,\n );\n }\n\n const { messageId, queueName, consumerGroup } = cloudEvent.data as {\n messageId: string;\n queueName: string;\n consumerGroup: string;\n };\n\n return {\n queueName,\n consumerGroup,\n messageId,\n };\n}\n\n/**\n * Simplified queue callback handler for Next.js route handlers\n *\n * Automatically extracts queue information from CloudEvent format\n * and routes to the appropriate handler based on topic and consumer group.\n *\n * @param handlers Object with topic-specific handlers organized by consumer groups\n * @returns A Next.js route handler function\n *\n * @example\n * ```typescript\n * // Single topic with multiple consumer groups\n * export const POST = handleCallback({\n * \"image-processing\": {\n * \"compress\": (message, metadata) => console.log(\"Compressing image\", message),\n * \"resize\": (message, metadata) => console.log(\"Resizing image\", message),\n * }\n * });\n *\n * // Multiple topics with consumer groups\n * export const POST = handleCallback({\n * \"user-events\": {\n * \"welcome\": (user, metadata) => console.log(\"Welcoming user\", user),\n * \"analytics\": (user, metadata) => console.log(\"Tracking user\", user),\n * },\n * \"order-events\": {\n * \"fulfillment\": (order, metadata) => console.log(\"Fulfilling order\", order),\n * \"notifications\": (order, metadata) => console.log(\"Notifying order\", order),\n * }\n * });\n * ```\n */\nexport function handleCallback(\n handlers: CallbackHandlers,\n): (request: Request) => Promise<Response> {\n return async (request: Request): Promise<Response> => {\n try {\n // Parse the callback request\n const { queueName, consumerGroup, messageId } =\n await parseCallbackRequest(request);\n\n // Find the topic handler\n const topicHandler = handlers[queueName];\n\n if (!topicHandler) {\n const availableTopics = Object.keys(handlers).join(\", \");\n return Response.json(\n {\n error: `No handler found for topic: ${queueName}`,\n availableTopics,\n },\n { status: 404 },\n );\n }\n\n // Find the consumer group handler\n const consumerGroupHandler = topicHandler[consumerGroup];\n\n if (!consumerGroupHandler) {\n const availableGroups = Object.keys(topicHandler).join(\", \");\n return Response.json(\n {\n error: `No handler found for consumer group \"${consumerGroup}\" in topic \"${queueName}\".`,\n availableGroups,\n },\n { status: 404 },\n );\n }\n\n // Create client and process the message\n const client = new QueueClient();\n const topic = new Topic(client, queueName);\n const cg = topic.consumerGroup(consumerGroup);\n\n await cg.consume(consumerGroupHandler, { messageId });\n\n return Response.json({ status: \"success\" });\n } catch (error) {\n console.error(\"Queue callback error:\", error);\n\n // Handle parsing errors with appropriate status codes\n if (\n error instanceof Error &&\n (error.message.includes(\"Missing required CloudEvent data fields\") ||\n error.message.includes(\"Invalid CloudEvent\") ||\n error.message.includes(\"Invalid CloudEvent type\") ||\n error.message.includes(\"Invalid content type\") ||\n error.message.includes(\"Failed to parse CloudEvent\"))\n ) {\n return Response.json({ error: error.message }, { status: 400 });\n }\n\n return Response.json(\n { error: \"Failed to process queue message\" },\n { status: 500 },\n );\n }\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/transports.ts","../src/api-client.ts","../src/dev.ts","../src/types.ts","../src/consumer-group.ts","../src/topic.ts","../src/callback.ts","../src/oidc.ts","../src/client.ts"],"sourcesContent":["/**\n * Serializer/Deserializer interface for message payloads.\n *\n * Built-in implementations:\n * - `JsonTransport` - JSON serialization (default, buffers entire payload)\n * - `BufferTransport` - Binary data (buffers entire payload)\n * - `StreamTransport` - Pass-through streaming (no buffering, ideal for large payloads)\n */\nexport interface Transport<T = unknown> {\n /**\n * Serialize a value to a buffer or stream for transmission.\n * The result is sent as the request body with the `contentType` header.\n */\n serialize(value: T): Buffer | ReadableStream<Uint8Array>;\n\n /**\n * Deserialize a readable stream back to the original value.\n * Called when receiving messages from the queue.\n */\n deserialize(stream: ReadableStream<Uint8Array>): Promise<T>;\n\n /**\n * Optional cleanup method for deserialized payloads that may contain resources.\n * Called automatically by ConsumerGroup on error; manual cleanup required for direct client usage.\n * @param payload The deserialized payload to clean up\n */\n finalize?(payload: T): Promise<void>;\n\n /**\n * MIME type for this serialization format.\n * Sent as the Content-Type header when publishing messages.\n */\n contentType: string;\n}\n\nasync function streamToBuffer(\n stream: ReadableStream<Uint8Array>,\n): Promise<Buffer> {\n let totalLength = 0;\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n totalLength += value.length;\n }\n } finally {\n reader.releaseLock();\n }\n\n // Combine chunks into a single buffer\n return Buffer.concat(chunks, totalLength);\n}\n\n/**\n * JSON serializer/deserializer (default transport).\n *\n * Ideal for structured data. Buffers the entire payload in memory for parsing.\n *\n * @example\n * ```typescript\n * // Default (JsonTransport is used automatically)\n * const queue = new QueueClient({ region: process.env.QUEUE_REGION! });\n * await queue.send(\"topic\", { data: \"example\" });\n *\n * // With custom serialization\n * const queue = new QueueClient({\n * region: process.env.QUEUE_REGION!,\n * transport: new JsonTransport({\n * replacer: (key, value) => key === \"password\" ? undefined : value,\n * reviver: (key, value) => key === \"date\" ? new Date(value) : value,\n * }),\n * });\n * await queue.send(\"topic\", { data: \"example\" });\n * ```\n */\nexport class JsonTransport<T = unknown> implements Transport<T> {\n readonly contentType = \"application/json\";\n readonly replacer?: Parameters<typeof JSON.stringify>[1];\n readonly reviver?: Parameters<typeof JSON.parse>[1];\n\n /**\n * Create a new JsonTransport.\n * @param options - Optional JSON serialization options\n * @param options.replacer - Custom replacer for JSON.stringify\n * @param options.reviver - Custom reviver for JSON.parse\n */\n constructor(\n options: {\n replacer?: Parameters<typeof JSON.stringify>[1];\n reviver?: Parameters<typeof JSON.parse>[1];\n } = {},\n ) {\n this.replacer = options.replacer;\n this.reviver = options.reviver;\n }\n\n serialize(value: T): Buffer {\n return Buffer.from(JSON.stringify(value, this.replacer), \"utf8\");\n }\n\n async deserialize(stream: ReadableStream<Uint8Array>): Promise<T> {\n const buffer = await streamToBuffer(stream);\n return JSON.parse(buffer.toString(\"utf8\"), this.reviver);\n }\n}\n\n/**\n * Binary data serializer/deserializer.\n *\n * Ideal for binary data that fits in memory. Buffers the entire payload.\n *\n * @example\n * ```typescript\n * const queue = new QueueClient({ region: \"iad1\", transport: new BufferTransport() });\n * await queue.send(\"binary-topic\", myBuffer);\n * ```\n */\nexport class BufferTransport implements Transport<Buffer> {\n readonly contentType = \"application/octet-stream\";\n\n serialize(value: Buffer): Buffer {\n return value;\n }\n\n async deserialize(stream: ReadableStream<Uint8Array>): Promise<Buffer> {\n return await streamToBuffer(stream);\n }\n}\n\n/**\n * Pass-through stream serializer/deserializer.\n *\n * Ideal for large files and real-time streams. Does not buffer data in memory.\n *\n * **Important:** When using StreamTransport, you must call `finalize(payload)` when done\n * processing to prevent resource leaks. ConsumerGroup handles this automatically;\n * direct client usage requires manual cleanup.\n *\n * @example\n * ```typescript\n * const queue = new QueueClient({ region: \"iad1\", transport: new StreamTransport() });\n *\n * // Sending a stream\n * await queue.send(\"large-file\", myReadableStream);\n *\n * // Receiving - cleanup handled automatically\n * await queue.receive(\"large-file\", \"processor\", async (stream, meta) => {\n * const reader = stream.getReader();\n * // Process chunks...\n * });\n * ```\n */\nexport class StreamTransport implements Transport<ReadableStream<Uint8Array>> {\n readonly contentType = \"application/octet-stream\";\n\n serialize(value: ReadableStream<Uint8Array>): ReadableStream<Uint8Array> {\n return value;\n }\n\n async deserialize(\n stream: ReadableStream<Uint8Array>,\n ): Promise<ReadableStream<Uint8Array>> {\n return stream;\n }\n\n /**\n * Consume any remaining stream data to prevent resource leaks.\n * Called automatically by ConsumerGroup; manual call required for direct client usage.\n */\n async finalize(payload: ReadableStream<Uint8Array>): Promise<void> {\n const reader = payload.getReader();\n try {\n while (true) {\n const { done } = await reader.read();\n if (done) break;\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n","declare const __PACKAGE_VERSION__: string;\n\nimport { parseMultipartStream } from \"mixpart\";\nimport { isDevMode } from \"./dev\";\nimport { getVercelOidcToken } from \"./oidc\";\nimport { JsonTransport } from \"./transports\";\nimport type { Transport } from \"./transports\";\nimport type {\n BaseUrlResolver,\n ChangeVisibilityOptions,\n ChangeVisibilityResponse,\n AcknowledgeMessageOptions,\n AcknowledgeMessageResponse,\n Message,\n QueueClientOptions,\n ReceiveMessageByIdOptions,\n ReceiveMessageByIdResponse,\n ReceiveMessagesOptions,\n SendMessageOptions,\n SendMessageResponse,\n} from \"./types\";\nimport {\n BadRequestError,\n ConsumerDiscoveryError,\n ConsumerRegistryNotConfiguredError,\n DuplicateMessageError,\n ForbiddenError,\n InternalServerError,\n InvalidLimitError,\n MessageAlreadyProcessedError,\n MessageCorruptedError,\n MessageNotAvailableError,\n MessageNotFoundError,\n UnauthorizedError,\n} from \"./types\";\n\nfunction isDebugEnabled(): boolean {\n return (\n process.env.VERCEL_QUEUE_DEBUG === \"1\" ||\n process.env.VERCEL_QUEUE_DEBUG === \"true\"\n );\n}\n\nasync function consumeStream(\n stream: ReadableStream<Uint8Array>,\n): Promise<void> {\n const reader = stream.getReader();\n try {\n while (true) {\n const { done } = await reader.read();\n if (done) break;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction throwCommonHttpError(\n status: number,\n statusText: string,\n errorText: string,\n operation: string,\n badRequestDefault: string = \"Invalid parameters\",\n): never {\n if (status === 400) {\n throw new BadRequestError(errorText || badRequestDefault);\n }\n if (status === 401) {\n throw new UnauthorizedError(errorText || undefined);\n }\n if (status === 403) {\n throw new ForbiddenError(errorText || undefined);\n }\n if (status >= 500) {\n throw new InternalServerError(\n errorText || `Server error: ${status} ${statusText}`,\n );\n }\n throw new Error(`Failed to ${operation}: ${status} ${statusText}`);\n}\n\nfunction parseQueueHeaders(\n headers: Headers,\n): Omit<Message<unknown>, \"payload\"> | null {\n const messageId = headers.get(\"Vqs-Message-Id\");\n const deliveryCountStr = headers.get(\"Vqs-Delivery-Count\") || \"0\";\n const timestamp = headers.get(\"Vqs-Timestamp\");\n const contentType = headers.get(\"Content-Type\") || \"application/octet-stream\";\n const receiptHandle = headers.get(\"Vqs-Receipt-Handle\");\n\n if (!messageId || !timestamp || !receiptHandle) {\n return null;\n }\n\n const deliveryCount = parseInt(deliveryCountStr, 10);\n if (Number.isNaN(deliveryCount)) {\n return null;\n }\n\n return {\n messageId,\n deliveryCount,\n createdAt: new Date(timestamp),\n contentType,\n receiptHandle,\n };\n}\n\nconst DEFAULT_BASE_URL_RESOLVER: BaseUrlResolver = (region) =>\n `https://${region}.vercel-queue.com`;\n\nfunction resolveBaseUrl(\n region: string,\n resolver: BaseUrlResolver | undefined,\n): string {\n return (resolver ?? DEFAULT_BASE_URL_RESOLVER)(region);\n}\n\nconst BASE_PATH = \"/api/v3/topic\";\n\nexport class ApiClient {\n private baseUrl: string;\n private customHeaders: Record<string, string>;\n private providedToken?: string;\n private resolvedDeploymentId?: string;\n private pinSends: boolean;\n private explicitlyUnpinned: boolean;\n private transport: Transport;\n private region: string;\n private baseUrlResolver: BaseUrlResolver | undefined;\n\n constructor(options: QueueClientOptions) {\n this.region = options.region;\n this.baseUrlResolver = options.resolveBaseUrl;\n this.baseUrl = resolveBaseUrl(this.region, this.baseUrlResolver);\n this.customHeaders = options.headers || {};\n this.providedToken = options.token;\n this.transport = options.transport || new JsonTransport();\n\n if (options.deploymentId === null) {\n this.pinSends = false;\n this.explicitlyUnpinned = true;\n } else {\n this.resolvedDeploymentId =\n options.deploymentId || process.env.VERCEL_DEPLOYMENT_ID;\n this.pinSends = true;\n this.explicitlyUnpinned = false;\n }\n }\n\n /**\n * Return a new ApiClient targeting the given region, sharing all other\n * configuration (token, transport, headers, deployment ID, resolver).\n * Used internally by handleCallback to route follow-up API calls to the\n * region indicated by the incoming `ce-vqsregion` header.\n */\n withRegion(region: string): ApiClient {\n return new ApiClient({\n region,\n resolveBaseUrl: this.baseUrlResolver,\n token: this.providedToken,\n headers: { ...this.customHeaders },\n deploymentId: this.explicitlyUnpinned ? null : this.resolvedDeploymentId,\n transport: this.transport,\n });\n }\n\n getRegion(): string {\n return this.region;\n }\n\n getTransport(): Transport {\n return this.transport;\n }\n\n private requireDeploymentId(): void {\n if (isDevMode() || this.explicitlyUnpinned || this.resolvedDeploymentId) {\n return;\n }\n throw new Error(\n \"No deployment ID available. VERCEL_DEPLOYMENT_ID is not set.\\n\\n\" +\n \"This usually means the code is running outside a Vercel deployment \" +\n \"(e.g. during build or in a non-Vercel environment).\\n\\n\" +\n \"To fix this, create a new QueueClient with an explicit deploymentId:\\n\" +\n ' new QueueClient({ region: \"iad1\", deploymentId: \"dpl_xxx\" })\\n' +\n \"Or explicitly opt out of deployment pinning:\\n\" +\n ' new QueueClient({ region: \"iad1\", deploymentId: null })',\n );\n }\n\n private getSendDeploymentId(): string | undefined {\n if (isDevMode()) {\n return undefined;\n }\n this.requireDeploymentId();\n return this.pinSends ? this.resolvedDeploymentId : undefined;\n }\n\n private getConsumeDeploymentId(): string | undefined {\n if (isDevMode()) {\n return undefined;\n }\n this.requireDeploymentId();\n return this.resolvedDeploymentId;\n }\n\n private async getToken(): Promise<string> {\n if (this.providedToken) {\n return this.providedToken;\n }\n\n const token = await getVercelOidcToken();\n if (!token) {\n throw new Error(\n \"Failed to get OIDC token from Vercel Functions. \" +\n \"Make sure you are running in a Vercel Function environment, or provide a token explicitly.\\n\\n\" +\n \"To set up your environment:\\n\" +\n \"1. Link your project: 'vercel link'\\n\" +\n \"2. Pull environment variables: 'vercel env pull'\\n\" +\n \"3. Run with environment: 'dotenv -e .env.local -- your-command'\",\n );\n }\n return token;\n }\n\n private buildUrl(queueName: string, ...pathSegments: string[]): string {\n const encodedQueue = encodeURIComponent(queueName);\n const segments = pathSegments.map((s) => encodeURIComponent(s));\n const path = segments.length > 0 ? \"/\" + segments.join(\"/\") : \"\";\n return `${this.baseUrl}${BASE_PATH}/${encodedQueue}${path}`;\n }\n\n private async fetch(\n url: string,\n init: RequestInit & { headers: Headers },\n ): Promise<Response> {\n const method = init.method || \"GET\";\n\n if (isDebugEnabled()) {\n const logData: Record<string, unknown> = {\n method,\n url,\n headers: init.headers,\n };\n\n const body = init.body;\n if (body !== undefined && body !== null) {\n if (body instanceof ArrayBuffer) {\n logData.bodySize = body.byteLength;\n } else if (body instanceof Uint8Array) {\n logData.bodySize = body.byteLength;\n } else if (typeof body === \"string\") {\n logData.bodySize = body.length;\n } else {\n logData.bodyType = typeof body;\n }\n }\n\n console.debug(\"[VQS Debug] Request:\", JSON.stringify(logData, null, 2));\n }\n\n init.headers.set(\"User-Agent\", `@vercel/queue/${__PACKAGE_VERSION__}`);\n init.headers.set(\"Vqs-Client-Ts\", new Date().toISOString());\n\n const response = await fetch(url, init);\n\n if (isDebugEnabled()) {\n const logData: Record<string, unknown> = {\n method,\n url,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n };\n\n console.debug(\"[VQS Debug] Response:\", JSON.stringify(logData, null, 2));\n }\n\n return response;\n }\n\n async sendMessage<T = unknown>(\n options: SendMessageOptions<T>,\n ): Promise<SendMessageResponse | { messageId: null }> {\n const transport = this.transport as Transport<T>;\n const {\n queueName,\n payload,\n idempotencyKey,\n retentionSeconds,\n delaySeconds,\n headers: optionHeaders,\n } = options;\n\n const headers = new Headers();\n\n if (this.customHeaders) {\n for (const [name, value] of Object.entries(this.customHeaders)) {\n headers.append(name, value);\n }\n }\n\n if (optionHeaders) {\n const protectedHeaderNames = new Set([\"authorization\", \"content-type\"]);\n const isProtectedHeader = (name: string): boolean => {\n const lower = name.toLowerCase();\n if (protectedHeaderNames.has(lower)) return true;\n return lower.startsWith(\"vqs-\");\n };\n\n for (const [name, value] of Object.entries(optionHeaders)) {\n if (!isProtectedHeader(name) && value !== undefined) {\n headers.append(name, value);\n }\n }\n }\n\n headers.set(\"Authorization\", `Bearer ${await this.getToken()}`);\n headers.set(\"Content-Type\", transport.contentType);\n\n const deploymentId = this.getSendDeploymentId();\n if (deploymentId) {\n headers.set(\"Vqs-Deployment-Id\", deploymentId);\n }\n\n if (idempotencyKey) {\n headers.set(\"Vqs-Idempotency-Key\", idempotencyKey);\n }\n\n if (retentionSeconds !== undefined) {\n headers.set(\"Vqs-Retention-Seconds\", retentionSeconds.toString());\n }\n\n if (delaySeconds !== undefined) {\n headers.set(\"Vqs-Delay-Seconds\", delaySeconds.toString());\n }\n\n const serialized = transport.serialize(payload);\n const body = Buffer.isBuffer(serialized)\n ? new Uint8Array(serialized)\n : serialized;\n\n const response = await this.fetch(this.buildUrl(queueName), {\n method: \"POST\",\n body,\n headers,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n if (response.status === 409) {\n throw new DuplicateMessageError(\n errorText || \"Duplicate idempotency key detected\",\n idempotencyKey,\n );\n }\n if (response.status === 502) {\n throw new ConsumerDiscoveryError(\n errorText || \"Consumer discovery failed\",\n deploymentId,\n );\n }\n if (response.status === 503) {\n throw new ConsumerRegistryNotConfiguredError(\n errorText || \"Consumer registry not configured\",\n );\n }\n throwCommonHttpError(\n response.status,\n response.statusText,\n errorText,\n \"send message\",\n );\n }\n\n if (response.status === 202) {\n return { messageId: null };\n }\n\n const responseData = (await response.json()) as SendMessageResponse;\n\n return responseData;\n }\n\n async *receiveMessages<T = unknown>(\n options: ReceiveMessagesOptions<T>,\n ): AsyncGenerator<Message<T>, void, unknown> {\n const transport = this.transport as Transport<T>;\n const { queueName, consumerGroup, visibilityTimeoutSeconds, limit } =\n options;\n\n if (limit !== undefined && (limit < 1 || limit > 10)) {\n throw new InvalidLimitError(limit);\n }\n\n const headers = new Headers({\n Authorization: `Bearer ${await this.getToken()}`,\n Accept: \"multipart/mixed\",\n ...this.customHeaders,\n });\n\n if (visibilityTimeoutSeconds !== undefined) {\n headers.set(\n \"Vqs-Visibility-Timeout-Seconds\",\n visibilityTimeoutSeconds.toString(),\n );\n }\n\n if (limit !== undefined) {\n headers.set(\"Vqs-Max-Messages\", limit.toString());\n }\n\n const effectiveDeploymentId = this.getConsumeDeploymentId();\n if (effectiveDeploymentId) {\n headers.set(\"Vqs-Deployment-Id\", effectiveDeploymentId);\n }\n\n const response = await this.fetch(\n this.buildUrl(queueName, \"consumer\", consumerGroup),\n {\n method: \"POST\",\n headers,\n },\n );\n\n if (response.status === 204) {\n return;\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n throwCommonHttpError(\n response.status,\n response.statusText,\n errorText,\n \"receive messages\",\n );\n }\n\n for await (const multipartMessage of parseMultipartStream(response)) {\n try {\n const parsedHeaders = parseQueueHeaders(multipartMessage.headers);\n\n if (!parsedHeaders) {\n console.warn(\"Missing required queue headers in multipart part\");\n await consumeStream(multipartMessage.payload);\n continue;\n }\n\n const deserializedPayload = await transport.deserialize(\n multipartMessage.payload,\n );\n\n const message: Message<T> = {\n ...parsedHeaders,\n payload: deserializedPayload,\n };\n\n yield message;\n } catch (error) {\n console.warn(\"Failed to process multipart message:\", error);\n await consumeStream(multipartMessage.payload);\n }\n }\n }\n\n async receiveMessageById<T = unknown>(\n options: ReceiveMessageByIdOptions<T>,\n ): Promise<ReceiveMessageByIdResponse<T>> {\n const transport = this.transport as Transport<T>;\n const { queueName, consumerGroup, messageId, visibilityTimeoutSeconds } =\n options;\n\n const headers = new Headers({\n Authorization: `Bearer ${await this.getToken()}`,\n Accept: \"multipart/mixed\",\n ...this.customHeaders,\n });\n\n if (visibilityTimeoutSeconds !== undefined) {\n headers.set(\n \"Vqs-Visibility-Timeout-Seconds\",\n visibilityTimeoutSeconds.toString(),\n );\n }\n\n const effectiveDeploymentId = this.getConsumeDeploymentId();\n if (effectiveDeploymentId) {\n headers.set(\"Vqs-Deployment-Id\", effectiveDeploymentId);\n }\n\n const response = await this.fetch(\n this.buildUrl(queueName, \"consumer\", consumerGroup, \"id\", messageId),\n {\n method: \"POST\",\n headers,\n },\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n if (response.status === 404) {\n throw new MessageNotFoundError(messageId);\n }\n if (response.status === 409) {\n let errorData: { error?: string; originalMessageId?: string } = {};\n try {\n errorData = JSON.parse(errorText);\n } catch {\n // ignore parse errors\n }\n\n if (errorData.originalMessageId) {\n throw new MessageNotAvailableError(\n messageId,\n `This message was a duplicate - use originalMessageId: ${errorData.originalMessageId}`,\n );\n }\n throw new MessageNotAvailableError(messageId);\n }\n if (response.status === 410) {\n throw new MessageAlreadyProcessedError(messageId);\n }\n throwCommonHttpError(\n response.status,\n response.statusText,\n errorText,\n \"receive message by ID\",\n );\n }\n\n for await (const multipartMessage of parseMultipartStream(response)) {\n const parsedHeaders = parseQueueHeaders(multipartMessage.headers);\n\n if (!parsedHeaders) {\n await consumeStream(multipartMessage.payload);\n throw new MessageCorruptedError(\n messageId,\n \"Missing required queue headers in response\",\n );\n }\n\n const deserializedPayload = await transport.deserialize(\n multipartMessage.payload,\n );\n\n const message: Message<T> = {\n ...parsedHeaders,\n payload: deserializedPayload,\n };\n\n return { message };\n }\n\n throw new MessageNotFoundError(messageId);\n }\n\n async acknowledgeMessage(\n options: AcknowledgeMessageOptions,\n ): Promise<AcknowledgeMessageResponse> {\n const { queueName, consumerGroup, receiptHandle } = options;\n\n const headers = new Headers({\n Authorization: `Bearer ${await this.getToken()}`,\n ...this.customHeaders,\n });\n\n const effectiveDeploymentId = this.getConsumeDeploymentId();\n if (effectiveDeploymentId) {\n headers.set(\"Vqs-Deployment-Id\", effectiveDeploymentId);\n }\n\n const response = await this.fetch(\n this.buildUrl(\n queueName,\n \"consumer\",\n consumerGroup,\n \"lease\",\n receiptHandle,\n ),\n {\n method: \"DELETE\",\n headers,\n },\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n if (response.status === 404) {\n throw new MessageNotFoundError(receiptHandle);\n }\n if (response.status === 409) {\n throw new MessageNotAvailableError(\n receiptHandle,\n errorText ||\n \"Invalid receipt handle, message not in correct state, or already processed\",\n );\n }\n throwCommonHttpError(\n response.status,\n response.statusText,\n errorText,\n \"acknowledge message\",\n \"Missing or invalid receipt handle\",\n );\n }\n\n return { acknowledged: true };\n }\n\n async changeVisibility(\n options: ChangeVisibilityOptions,\n ): Promise<ChangeVisibilityResponse> {\n const {\n queueName,\n consumerGroup,\n receiptHandle,\n visibilityTimeoutSeconds,\n } = options;\n\n const headers = new Headers({\n Authorization: `Bearer ${await this.getToken()}`,\n \"Content-Type\": \"application/json\",\n ...this.customHeaders,\n });\n\n const effectiveDeploymentId = this.getConsumeDeploymentId();\n if (effectiveDeploymentId) {\n headers.set(\"Vqs-Deployment-Id\", effectiveDeploymentId);\n }\n\n const response = await this.fetch(\n this.buildUrl(\n queueName,\n \"consumer\",\n consumerGroup,\n \"lease\",\n receiptHandle,\n ),\n {\n method: \"PATCH\",\n headers,\n body: JSON.stringify({ visibilityTimeoutSeconds }),\n },\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n if (response.status === 404) {\n throw new MessageNotFoundError(receiptHandle);\n }\n if (response.status === 409) {\n throw new MessageNotAvailableError(\n receiptHandle,\n errorText ||\n \"Invalid receipt handle, message not in correct state, or already processed\",\n );\n }\n throwCommonHttpError(\n response.status,\n response.statusText,\n errorText,\n \"change visibility\",\n \"Missing receipt handle or invalid visibility timeout\",\n );\n }\n\n return { success: true };\n }\n}\n","/**\n * Development mode utilities for local queue compatibility\n * This file contains helpers that enable local callback triggering in development mode\n *\n * Key behaviors:\n * - Discovers queue routes from vercel.json experimentalTriggers config\n * - Makes HTTP requests to trigger callbacks instead of calling registered handlers\n * - Supports wildcard topic patterns\n * - V3 compatibility: Polls for message visibility before triggering callbacks\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CLOUD_EVENT_TYPE_V2BETA, matchesWildcardPattern } from \"./callback\";\nimport { ApiClient } from \"./api-client\";\nimport { MessageNotFoundError, MessageAlreadyProcessedError } from \"./types\";\n\n/**\n * Global key for cached route mappings from vercel.json\n */\nconst ROUTE_MAPPINGS_KEY = Symbol.for(\"@vercel/queue.devRouteMappings\");\n\n/**\n * Route mapping from vercel.json experimentalTriggers\n */\ninterface DevRouteMapping {\n urlPath: string;\n topic: string;\n consumer: string;\n}\n\n/**\n * Convert a file path from vercel.json to a URL path\n * e.g., \"app/api/vm/queue/route.ts\" → \"/api/vm/queue\"\n */\nfunction filePathToUrlPath(filePath: string): string {\n let urlPath = filePath\n .replace(/^app\\//, \"/\")\n .replace(/^pages\\//, \"/\")\n .replace(/\\/route\\.(ts|mts|js|mjs|tsx|jsx)$/, \"\")\n .replace(/\\.(ts|mts|js|mjs|tsx|jsx)$/, \"\");\n\n if (!urlPath.startsWith(\"/\")) {\n urlPath = \"/\" + urlPath;\n }\n\n return urlPath;\n}\n\n/**\n * Convert a file path to a consumer group name using mnemonic escapes\n * Escapes: _ → __, / → _S, . → _D\n * e.g., \"app/api/simple-queue/route.ts\" → \"app_Sapi_Ssimple-queue_Sroute_Dts\"\n */\nfunction filePathToConsumerGroup(filePath: string): string {\n return filePath.replace(/_/g, \"__\").replace(/\\//g, \"_S\").replace(/\\./g, \"_D\");\n}\n\n/**\n * Read and cache route mappings from vercel.json\n * Returns null if vercel.json doesn't exist or has no queue triggers\n */\nfunction getDevRouteMappings(): DevRouteMapping[] | null {\n const g = globalThis as typeof globalThis & {\n [ROUTE_MAPPINGS_KEY]?: DevRouteMapping[] | null;\n };\n\n if (ROUTE_MAPPINGS_KEY in g) {\n return g[ROUTE_MAPPINGS_KEY] ?? null;\n }\n\n try {\n const vercelJsonPath = path.join(process.cwd(), \"vercel.json\");\n if (!fs.existsSync(vercelJsonPath)) {\n g[ROUTE_MAPPINGS_KEY] = null;\n return null;\n }\n\n const vercelJson = JSON.parse(fs.readFileSync(vercelJsonPath, \"utf-8\")) as {\n functions?: {\n [filePath: string]: {\n experimentalTriggers?: Array<{\n type: string;\n topic?: string;\n }>;\n };\n };\n };\n\n if (!vercelJson.functions) {\n g[ROUTE_MAPPINGS_KEY] = null;\n return null;\n }\n\n const mappings: DevRouteMapping[] = [];\n\n for (const [filePath, config] of Object.entries(vercelJson.functions)) {\n if (!config.experimentalTriggers) continue;\n\n for (const trigger of config.experimentalTriggers) {\n if (trigger.type?.startsWith(\"queue/\") && trigger.topic) {\n mappings.push({\n urlPath: filePathToUrlPath(filePath),\n topic: trigger.topic,\n consumer: filePathToConsumerGroup(filePath),\n });\n }\n }\n }\n\n g[ROUTE_MAPPINGS_KEY] = mappings.length > 0 ? mappings : null;\n return g[ROUTE_MAPPINGS_KEY];\n } catch (error) {\n console.warn(\"[Dev Mode] Failed to read vercel.json:\", error);\n g[ROUTE_MAPPINGS_KEY] = null;\n return null;\n }\n}\n\n/**\n * Find routes that match a topic name (supports wildcards)\n */\nfunction findMatchingRoutes(topicName: string): DevRouteMapping[] {\n const mappings = getDevRouteMappings();\n if (!mappings) {\n return [];\n }\n\n return mappings.filter((mapping) => {\n if (mapping.topic.includes(\"*\")) {\n return matchesWildcardPattern(topicName, mapping.topic);\n }\n return mapping.topic === topicName;\n });\n}\n\n/**\n * Check if running in development mode\n */\nexport function isDevMode(): boolean {\n return process.env.NODE_ENV === \"development\";\n}\n\n/**\n * Configuration for visibility polling in V3\n */\nconst DEV_VISIBILITY_POLL_INTERVAL = 50;\nconst DEV_VISIBILITY_MAX_WAIT = 5000;\nconst DEV_VISIBILITY_BACKOFF_MULTIPLIER = 2;\n\n/**\n * Wait for a message to become visible in the queue (V3 eventual consistency)\n * Polls receiveMessageById with visibilityTimeoutSeconds=0 until the message is available\n * @returns true if message became visible, false if timed out\n * @internal\n */\nasync function waitForMessageVisibility(\n topicName: string,\n consumerGroup: string,\n messageId: string,\n region: string,\n): Promise<boolean> {\n const client = new ApiClient({ region });\n\n let elapsed = 0;\n let interval = DEV_VISIBILITY_POLL_INTERVAL;\n\n while (elapsed < DEV_VISIBILITY_MAX_WAIT) {\n try {\n await client.receiveMessageById({\n queueName: topicName,\n consumerGroup,\n messageId,\n visibilityTimeoutSeconds: 0,\n });\n return true;\n } catch (error) {\n if (error instanceof MessageNotFoundError) {\n await new Promise((resolve) => setTimeout(resolve, interval));\n elapsed += interval;\n interval = Math.min(\n interval * DEV_VISIBILITY_BACKOFF_MULTIPLIER,\n DEV_VISIBILITY_MAX_WAIT - elapsed,\n );\n continue;\n }\n if (error instanceof MessageAlreadyProcessedError) {\n console.log(\n `[Dev Mode] Message already processed: topic=\"${topicName}\" messageId=\"${messageId}\"`,\n );\n return false;\n }\n console.error(\n `[Dev Mode] Error polling for message visibility: topic=\"${topicName}\" messageId=\"${messageId}\"`,\n error,\n );\n return false;\n }\n }\n\n console.warn(\n `[Dev Mode] Message visibility timeout after ${DEV_VISIBILITY_MAX_WAIT}ms: topic=\"${topicName}\" messageId=\"${messageId}\"`,\n );\n return false;\n}\n\n/**\n * Trigger development mode callbacks for a topic\n * Discovers routes from vercel.json and makes HTTP requests to trigger callbacks\n * Waits for message visibility in V3 before making requests\n * @internal\n */\nexport function triggerDevCallbacks(\n topicName: string,\n messageId: string,\n region: string,\n delaySeconds?: number,\n): void {\n if (delaySeconds && delaySeconds > 0) {\n console.log(\n `[Dev Mode] Message sent with delay: topic=\"${topicName}\" messageId=\"${messageId}\" delay=${delaySeconds}s`,\n );\n setTimeout(() => {\n triggerDevCallbacks(topicName, messageId, region);\n }, delaySeconds * 1000);\n return;\n }\n\n console.log(\n `[Dev Mode] Message sent: topic=\"${topicName}\" messageId=\"${messageId}\"`,\n );\n\n const matchingRoutes = findMatchingRoutes(topicName);\n\n if (matchingRoutes.length === 0) {\n console.log(\n `[Dev Mode] No matching routes in vercel.json for topic \"${topicName}\"`,\n );\n return;\n }\n\n const consumerGroups = matchingRoutes.map((r) => r.consumer);\n\n console.log(\n `[Dev Mode] Scheduling callbacks for topic=\"${topicName}\" messageId=\"${messageId}\" → consumers: [${consumerGroups.join(\", \")}]`,\n );\n\n (async () => {\n const firstRoute = matchingRoutes[0];\n const isVisible = await waitForMessageVisibility(\n topicName,\n firstRoute.consumer,\n messageId,\n region,\n );\n\n if (!isVisible) {\n console.warn(\n `[Dev Mode] Skipping callbacks - message not visible: topic=\"${topicName}\" messageId=\"${messageId}\"`,\n );\n return;\n }\n\n const port = process.env.PORT || 3000;\n const baseUrl = `http://localhost:${port}`;\n\n for (const route of matchingRoutes) {\n const url = `${baseUrl}${route.urlPath}`;\n\n console.log(\n `[Dev Mode] Invoking handler: topic=\"${topicName}\" consumer=\"${route.consumer}\" messageId=\"${messageId}\" url=\"${url}\"`,\n );\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"ce-type\": CLOUD_EVENT_TYPE_V2BETA,\n \"ce-vqsqueuename\": topicName,\n \"ce-vqsconsumergroup\": route.consumer,\n \"ce-vqsmessageid\": messageId,\n \"ce-vqsregion\": region,\n },\n });\n\n if (response.ok) {\n try {\n const responseData = (await response.json()) as {\n status?: string;\n };\n if (responseData.status === \"success\") {\n console.log(\n `[Dev Mode] ✓ Message processed successfully: topic=\"${topicName}\" consumer=\"${route.consumer}\" messageId=\"${messageId}\"`,\n );\n }\n } catch {\n console.warn(\n `[Dev Mode] Handler returned OK but response was not JSON: topic=\"${topicName}\" consumer=\"${route.consumer}\"`,\n );\n }\n } else {\n try {\n const errorData = (await response.json()) as { error?: string };\n console.error(\n `[Dev Mode] ✗ Handler failed: topic=\"${topicName}\" consumer=\"${route.consumer}\" messageId=\"${messageId}\" error=\"${errorData.error || response.statusText}\"`,\n );\n } catch {\n console.error(\n `[Dev Mode] ✗ Handler failed: topic=\"${topicName}\" consumer=\"${route.consumer}\" messageId=\"${messageId}\" status=${response.status}`,\n );\n }\n }\n } catch (error) {\n console.error(\n `[Dev Mode] ✗ HTTP request failed: topic=\"${topicName}\" consumer=\"${route.consumer}\" messageId=\"${messageId}\" url=\"${url}\"`,\n error,\n );\n }\n }\n })();\n}\n\n/**\n * Clear cached route mappings - for testing only\n * @internal\n */\nfunction clearDevRouteMappings(): void {\n const g = globalThis as typeof globalThis & {\n [ROUTE_MAPPINGS_KEY]?: DevRouteMapping[] | null;\n };\n delete g[ROUTE_MAPPINGS_KEY];\n}\n\n// Export for testing\nif (process.env.NODE_ENV === \"test\" || process.env.VITEST) {\n (globalThis as any).__clearDevRouteMappings = clearDevRouteMappings;\n}\n","/**\n * Vercel Queue Service client types\n */\nimport type { Transport } from \"./transports\";\n\n// Re-export transport interface for convenience\nexport type { Transport };\n\n/**\n * Vercel region code. The 20 known codes match\n * {@link https://dcs.vercel-infra.com/ | dcs.vercel-infra.com}.\n * Arbitrary strings are also accepted for forward compatibility\n * with regions added after this SDK version.\n */\nexport type VercelRegion =\n | \"arn1\"\n | \"bom1\"\n | \"cdg1\"\n | \"cle1\"\n | \"cpt1\"\n | \"dub1\"\n | \"dxb1\"\n | \"fra1\"\n | \"gru1\"\n | \"hkg1\"\n | \"hnd1\"\n | \"iad1\"\n | \"icn1\"\n | \"kix1\"\n | \"lhr1\"\n | \"pdx1\"\n | \"sfo1\"\n | \"sin1\"\n | \"syd1\"\n | \"yul1\"\n | (string & {});\n\n/**\n * Resolves a region code to a base URL for the Vercel Queue Service API.\n *\n * Default: `` (region) => `https://${region}.vercel-queue.com` ``\n */\nexport type BaseUrlResolver = (region: string) => string;\n\nexport interface QueueClientOptions {\n /**\n * Vercel region code for API routing.\n *\n * Requests are sent to the regional endpoint resolved by\n * {@link BaseUrlResolver} (default: `https://${region}.vercel-queue.com`).\n *\n * Use a `QUEUE_REGION` env var set to `${VERCEL_REGION}` in production\n * and a fixed region (e.g. `\"iad1\"`) in development.\n *\n * @example\n * ```ts\n * new QueueClient({ region: process.env.QUEUE_REGION! })\n * ```\n */\n region: VercelRegion;\n\n /**\n * Custom resolver that maps a region code to a base URL.\n * @default (region) => `https://${region}.vercel-queue.com`\n */\n resolveBaseUrl?: BaseUrlResolver;\n\n /**\n * Authentication token for the Vercel Queue Service API.\n * If not provided, the client will attempt to get a token via OIDC\n * when running in a Vercel Function environment.\n */\n token?: string;\n\n /**\n * Custom headers to include in all requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Deployment ID for message routing and lease validation.\n *\n * - `undefined` (default): auto-detect from `VERCEL_DEPLOYMENT_ID` env var;\n * sent messages are pinned to this deployment.\n * - `null`: explicitly unpinned — no deployment ID is sent on any request.\n * - `\"dpl_xxx\"`: explicit value used for both send pinning and consume identification.\n *\n * Ignored in development mode (deployment ID is never sent locally).\n */\n deploymentId?: string | null;\n\n /**\n * Serializer/deserializer for message payloads.\n * Used for all send and receive operations.\n * @default JsonTransport\n */\n transport?: Transport;\n}\n\n/**\n * Options for sending messages.\n */\nexport interface SendOptions {\n /**\n * Unique key to prevent duplicate message submissions.\n * Deduplication window: `min(message retention, 24 hours)`.\n */\n idempotencyKey?: string;\n\n /**\n * Message retention time in seconds. After this period, the message expires.\n * @default 86400 (24 hours)\n * @minimum 60 (1 minute)\n * @maximum 86400 (24 hours)\n */\n retentionSeconds?: number;\n\n /**\n * Delay delivery of the message by this many seconds.\n * The message will not be visible to consumers until the delay has passed.\n * @default 0\n * @minimum 0\n * @maximum Value of retentionSeconds (delay cannot exceed retention)\n */\n delaySeconds?: number;\n\n /**\n * Custom headers to include with this message.\n * These headers are passed through to the VQS server.\n */\n headers?: Record<string, string>;\n}\n\nexport interface SendMessageOptions<T = unknown> extends SendOptions {\n /**\n * The topic/queue name to send the message to.\n * Must match pattern: `[A-Za-z0-9_-]+`\n */\n queueName: string;\n\n /**\n * The message payload. Will be serialized using the provided transport.\n */\n payload: T;\n}\n\nexport interface SendMessageResponse {\n /**\n * The generated message ID\n */\n messageId: string;\n}\n\n/**\n * Result returned by `send()`.\n *\n * `messageId` is `null` when the server accepted the message for deferred\n * processing (e.g. during a server-side outage) and no ID is available yet.\n */\nexport interface SendResult {\n messageId: string | null;\n}\n\nexport interface Message<T = unknown> {\n /**\n * Unique message identifier. Used for receive-by-ID operations.\n */\n messageId: string;\n\n /**\n * The deserialized message payload.\n * Note: If using StreamTransport, ensure proper cleanup by calling\n * `transport.finalize(payload)` when done processing, especially in error cases.\n */\n payload: T;\n\n /**\n * Number of times this message has been delivered.\n * Starts at 1 for the first delivery, increments on each retry.\n */\n deliveryCount: number;\n\n /**\n * Timestamp when the message was created/published.\n */\n createdAt: Date;\n\n /**\n * Timestamp when the message expires.\n * Only present for messages delivered via the v2beta binary callback path.\n */\n expiresAt?: Date;\n\n /**\n * MIME type of the message content.\n * Set by the transport's `contentType` property during publish.\n */\n contentType: string;\n\n /**\n * Receipt handle (lease token) for this message delivery.\n * Required for acknowledge and visibility extension operations.\n * Valid only until the visibility timeout expires.\n */\n receiptHandle: string;\n}\n\nexport interface ReceiveMessagesOptions<T = unknown> {\n /**\n * The topic/queue name to receive messages from.\n * Must match pattern: `[A-Za-z0-9_-]+`\n */\n queueName: string;\n\n /**\n * Consumer group name. Each consumer group maintains independent message state.\n * Must match pattern: `[A-Za-z0-9_-]+`\n */\n consumerGroup: string;\n\n /**\n * Time in seconds that messages will be invisible to other consumers after receipt.\n * Set to 0 for immediate re-visibility (useful for peeking).\n * @default 30\n * @minimum 0\n * @maximum 3600 (1 hour)\n */\n visibilityTimeoutSeconds?: number;\n\n /**\n * Maximum number of messages to retrieve in a single request.\n * @default 1\n * @minimum 1\n * @maximum 10\n */\n limit?: number;\n}\n\nexport interface AcknowledgeMessageOptions {\n /**\n * The topic/queue name the message belongs to.\n */\n queueName: string;\n\n /**\n * Consumer group name.\n */\n consumerGroup: string;\n\n /**\n * Receipt handle received when the message was consumed.\n */\n receiptHandle: string;\n}\n\nexport interface AcknowledgeMessageResponse {\n /**\n * Whether the message was successfully acknowledged\n */\n acknowledged: boolean;\n}\n\nexport interface ChangeVisibilityOptions {\n /**\n * The topic/queue name the message belongs to.\n */\n queueName: string;\n\n /**\n * Consumer group name.\n */\n consumerGroup: string;\n\n /**\n * Receipt handle received when the message was consumed.\n */\n receiptHandle: string;\n\n /**\n * New visibility timeout in seconds.\n * Cannot extend beyond the message's original expiration time.\n * @minimum 0\n * @maximum 3600 (1 hour)\n */\n visibilityTimeoutSeconds: number;\n}\n\nexport interface ChangeVisibilityResponse {\n /**\n * Whether the visibility was successfully updated\n */\n success: boolean;\n}\n\n/**\n * Message metadata provided to handlers\n */\nexport interface MessageMetadata {\n messageId: string;\n deliveryCount: number;\n createdAt: Date;\n expiresAt?: Date;\n topicName: string;\n consumerGroup: string;\n /** Vercel region the client is targeting. */\n region: string;\n}\n\n/**\n * Instruction returned by a {@link RetryHandler} to control what happens\n * to a message when the handler throws.\n *\n * - `{ afterSeconds: N }` — reschedule the message for redelivery after N seconds\n * - `{ acknowledge: true }` — acknowledge the message so it is never retried\n */\nexport type RetryDirective = { afterSeconds: number } | { acknowledge: true };\n\n/**\n * Called when the message handler throws an error.\n * Return a {@link RetryDirective} to reschedule or acknowledge the message,\n * or return `undefined` to let the error propagate normally.\n */\nexport type RetryHandler = (\n error: unknown,\n metadata: MessageMetadata,\n) => RetryDirective | void | undefined;\n\n/**\n * Message handler function type.\n *\n * Called once per message with the deserialized payload and metadata.\n * Not called when the queue is empty — check the return value of `receive()` instead.\n */\nexport type MessageHandler<T = unknown> = (\n message: T,\n metadata: MessageMetadata,\n) => Promise<void> | void;\n\n/**\n * Result returned by `receive()`. Use `ok` to check if messages were processed.\n *\n * @example\n * ```typescript\n * const result = await receive(\"topic\", \"group\", handler);\n * if (result.ok) {\n * // Messages were processed successfully\n * } else if (result.reason === \"empty\") {\n * // Queue had no messages available\n * }\n * ```\n */\nexport type ReceiveResult =\n | { ok: true }\n | { ok: false; reason: \"empty\" }\n | { ok: false; reason: \"not_found\"; messageId: string }\n | { ok: false; reason: \"not_available\"; messageId: string }\n | { ok: false; reason: \"already_processed\"; messageId: string };\n\n/**\n * Options for receiving a specific message by ID.\n */\nexport interface ReceiveByIdOptions {\n /** The specific message ID to consume */\n messageId: string;\n\n /**\n * Message lock duration in seconds.\n * @default 300 (5 minutes)\n * @minimum 30\n * @maximum 3600 (1 hour)\n */\n visibilityTimeoutSeconds?: number;\n\n /**\n * Called when the handler throws. Return `{ afterSeconds: N }` to reschedule\n * the message for redelivery after N seconds, or return `undefined`\n * to let the error propagate normally.\n */\n retry?: RetryHandler;\n}\n\n/**\n * Options for receiving messages from the queue with an optional batch limit.\n */\nexport interface ReceiveBatchOptions {\n /**\n * Maximum number of messages to retrieve in a single request.\n * @default 1\n * @minimum 1\n * @maximum 10\n */\n limit?: number;\n\n /**\n * Message lock duration in seconds.\n * @default 300 (5 minutes)\n * @minimum 30\n * @maximum 3600 (1 hour)\n */\n visibilityTimeoutSeconds?: number;\n\n /**\n * Called when the handler throws. Return `{ afterSeconds: N }` to reschedule\n * the message for redelivery after N seconds, or return `undefined`\n * to let the error propagate normally.\n */\n retry?: RetryHandler;\n}\n\n/**\n * Options for the receive method. Either receive by message ID or receive\n * from the queue with an optional limit. These options are mutually exclusive.\n */\nexport type ReceiveOptions = ReceiveByIdOptions | ReceiveBatchOptions;\n\n/**\n * Options for creating a ConsumerGroup instance.\n */\nexport interface ConsumerGroupOptions<T = unknown> {\n /**\n * Time in seconds that messages will be invisible to other consumers after receipt.\n * The ConsumerGroup will automatically extend this timeout during processing.\n * @default 300 (5 minutes)\n * @minimum 30\n * @maximum 3600 (1 hour)\n */\n visibilityTimeoutSeconds?: number;\n}\n\nexport interface ReceiveMessageByIdOptions<T = unknown> {\n /**\n * The topic/queue name to receive the message from.\n * Must match pattern: `[A-Za-z0-9_-]+`\n */\n queueName: string;\n\n /**\n * Consumer group name.\n * Must match pattern: `[A-Za-z0-9_-]+`\n */\n consumerGroup: string;\n\n /**\n * The specific message ID to retrieve.\n */\n messageId: string;\n\n /**\n * Time in seconds that the message will be invisible to other consumers after receipt.\n * @default 30\n * @minimum 0\n * @maximum 3600 (1 hour)\n */\n visibilityTimeoutSeconds?: number;\n}\n\nexport interface ReceiveMessageByIdResponse<T = unknown> {\n message: Message<T>;\n}\n\n/**\n * Error thrown when a message does not exist or has expired.\n */\nexport class MessageNotFoundError extends Error {\n constructor(messageId: string) {\n super(`Message ${messageId} not found`);\n this.name = \"MessageNotFoundError\";\n }\n}\n\n/**\n * Error thrown when a message exists but cannot be processed.\n * This can happen when the message is in the wrong state or already claimed by another consumer.\n */\nexport class MessageNotAvailableError extends Error {\n constructor(messageId: string, reason?: string) {\n super(\n `Message ${messageId} not available for processing${reason ? `: ${reason}` : \"\"}`,\n );\n this.name = \"MessageNotAvailableError\";\n }\n}\n\n/**\n * Error thrown when message data is corrupted or can't be parsed\n */\nexport class MessageCorruptedError extends Error {\n constructor(messageId: string, reason: string) {\n super(`Message ${messageId} is corrupted: ${reason}`);\n this.name = \"MessageCorruptedError\";\n }\n}\n\n/**\n * Error thrown when there are no messages available in the queue.\n */\nexport class QueueEmptyError extends Error {\n constructor(queueName: string, consumerGroup: string) {\n super(\n `No messages available in queue \"${queueName}\" for consumer group \"${consumerGroup}\"`,\n );\n this.name = \"QueueEmptyError\";\n }\n}\n\n/**\n * Error thrown when a message is temporarily locked by another consumer.\n * The message is currently being processed and cannot be claimed.\n */\nexport class MessageLockedError extends Error {\n /** Suggested retry delay in seconds, if provided by the server. */\n public readonly retryAfter?: number;\n\n constructor(messageId: string, retryAfter?: number) {\n const retryMessage = retryAfter\n ? ` Retry after ${retryAfter} seconds.`\n : \" Try again later.\";\n super(`Message ${messageId} is temporarily locked.${retryMessage}`);\n this.name = \"MessageLockedError\";\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Error thrown when authentication fails.\n * This typically means the token is missing, invalid, or expired.\n */\nexport class UnauthorizedError extends Error {\n constructor(message: string = \"Missing or invalid authentication token\") {\n super(message);\n this.name = \"UnauthorizedError\";\n }\n}\n\n/**\n * Error thrown when access is forbidden.\n * This typically means the queue belongs to a different environment or project.\n */\nexport class ForbiddenError extends Error {\n constructor(\n message: string = \"Queue environment doesn't match token environment\",\n ) {\n super(message);\n this.name = \"ForbiddenError\";\n }\n}\n\n/**\n * Error thrown when request parameters are invalid.\n */\nexport class BadRequestError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BadRequestError\";\n }\n}\n\n/**\n * Error thrown when the server encounters an unexpected error.\n */\nexport class InternalServerError extends Error {\n constructor(message: string = \"Unexpected server error\") {\n super(message);\n this.name = \"InternalServerError\";\n }\n}\n\n/**\n * Error thrown when the batch limit parameter is outside the valid range.\n * The limit must be between 1 and 10 (inclusive).\n */\nexport class InvalidLimitError extends Error {\n constructor(limit: number, min: number = 1, max: number = 10) {\n super(`Invalid limit: ${limit}. Limit must be between ${min} and ${max}.`);\n this.name = \"InvalidLimitError\";\n }\n}\n\n/**\n * Error thrown when attempting to process a message that has already been successfully processed.\n */\nexport class MessageAlreadyProcessedError extends Error {\n constructor(messageId: string) {\n super(`Message ${messageId} has already been processed`);\n this.name = \"MessageAlreadyProcessedError\";\n }\n}\n\n/**\n * Error thrown when a duplicate idempotency key is detected.\n * The message was already sent within the deduplication window.\n */\nexport class DuplicateMessageError extends Error {\n public readonly idempotencyKey?: string;\n\n constructor(message: string, idempotencyKey?: string) {\n super(message);\n this.name = \"DuplicateMessageError\";\n this.idempotencyKey = idempotencyKey;\n }\n}\n\n/**\n * Error thrown when consumer discovery fails.\n * This typically means the deployment could not be reached or is not configured correctly.\n */\nexport class ConsumerDiscoveryError extends Error {\n public readonly deploymentId?: string;\n\n constructor(message: string, deploymentId?: string) {\n super(message);\n this.name = \"ConsumerDiscoveryError\";\n this.deploymentId = deploymentId;\n }\n}\n\n/**\n * Error thrown when the consumer registry is not configured for the project.\n */\nexport class ConsumerRegistryNotConfiguredError extends Error {\n constructor(message: string = \"Consumer registry not configured\") {\n super(message);\n this.name = \"ConsumerRegistryNotConfiguredError\";\n }\n}\n","import { ApiClient } from \"./api-client\";\nimport type {\n ConsumerGroupOptions,\n Message,\n MessageHandler,\n MessageMetadata,\n RetryDirective,\n RetryHandler,\n} from \"./types\";\nimport {\n BadRequestError,\n ForbiddenError,\n MessageNotAvailableError,\n MessageNotFoundError,\n UnauthorizedError,\n} from \"./types\";\n\n/**\n * Default visibility timeout in seconds (5 minutes).\n * This is the initial lock duration requested when receiving messages.\n */\nconst DEFAULT_VISIBILITY_TIMEOUT_SECONDS = 300;\n\n/**\n * Minimum visibility timeout in seconds.\n * Ensures auto-extension has enough time to renew before the lease expires.\n */\nconst MIN_VISIBILITY_TIMEOUT_SECONDS = 30;\n\n/**\n * Maximum renewal interval in seconds.\n * Even for very long visibility timeouts, we renew at least this often.\n */\nconst MAX_RENEWAL_INTERVAL_SECONDS = 60;\n\n/**\n * Minimum renewal interval in seconds.\n * Even for very short visibility timeouts, we don't renew more frequently than this.\n */\nconst MIN_RENEWAL_INTERVAL_SECONDS = 10;\n\n/**\n * Interval in milliseconds between retry attempts when extension fails.\n * On transient failures, retry every 3 seconds.\n */\nconst RETRY_INTERVAL_MS = 3000;\n\n/**\n * Calculate the renewal interval based on visibility timeout.\n * Formula: min(60, max(10, visibilityTimeout / 5))\n *\n * Examples:\n * - 300s visibility → 60s interval (300/5 = 60, capped at 60)\n * - 200s visibility → 40s interval (200/5 = 40)\n * - 100s visibility → 20s interval (100/5 = 20)\n * - 30s visibility → 10s interval (30/5 = 6, floored at 10)\n */\nfunction calculateRenewalInterval(visibilityTimeoutSeconds: number): number {\n return Math.min(\n MAX_RENEWAL_INTERVAL_SECONDS,\n Math.max(MIN_RENEWAL_INTERVAL_SECONDS, visibilityTimeoutSeconds / 5),\n );\n}\n\n/**\n * Options for consuming a specific message by ID.\n */\nexport interface ConsumeByIdOptions {\n /** The specific message ID to consume */\n messageId: string;\n\n /**\n * Called when the handler throws. Return `{ afterSeconds: N }` to reschedule\n * the message for redelivery after N seconds, or return `undefined`\n * to let the error propagate normally.\n */\n retry?: RetryHandler;\n}\n\n/**\n * Options for consuming messages from the queue.\n */\nexport interface ConsumeBatchOptions {\n /**\n * Maximum number of messages to retrieve in a single request.\n * @default 1\n * @minimum 1\n * @maximum 10\n */\n limit?: number;\n\n /**\n * Called when the handler throws. Return `{ afterSeconds: N }` to reschedule\n * the message for redelivery after N seconds, or return `undefined`\n * to let the error propagate normally.\n */\n retry?: RetryHandler;\n}\n\n/**\n * Options for the consume method. Either consume by message ID or consume\n * from the queue with an optional limit. These options are mutually exclusive.\n */\nexport type ConsumeOptions = ConsumeByIdOptions | ConsumeBatchOptions;\n\n/**\n * A ConsumerGroup processes messages from a topic with automatic lifecycle management.\n *\n * Features:\n * - Independent message state per group (each group receives a copy of every message)\n * - Automatic visibility timeout extension during processing\n * - Automatic message deletion on successful handler completion\n */\nexport class ConsumerGroup<T = unknown> {\n private client: ApiClient;\n private topicName: string;\n private consumerGroupName: string;\n private visibilityTimeout: number;\n\n /**\n * Create a new ConsumerGroup instance.\n *\n * @param client - ApiClient instance to use for API calls (transport is configured on the client)\n * @param topicName - Name of the topic to consume from (pattern: `[A-Za-z0-9_-]+`)\n * @param consumerGroupName - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)\n * @param options - Optional configuration\n * @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)\n */\n constructor(\n client: ApiClient,\n topicName: string,\n consumerGroupName: string,\n options: ConsumerGroupOptions<T> = {},\n ) {\n this.client = client;\n this.topicName = topicName;\n this.consumerGroupName = consumerGroupName;\n this.visibilityTimeout = Math.max(\n MIN_VISIBILITY_TIMEOUT_SECONDS,\n options.visibilityTimeoutSeconds ?? DEFAULT_VISIBILITY_TIMEOUT_SECONDS,\n );\n }\n\n /**\n * Check if an error is a 4xx client error that should stop retries.\n * 4xx errors indicate the request is fundamentally invalid and retrying won't help.\n * - 409: Ticket mismatch (lost ownership to another consumer)\n * - 404: Message/receipt handle not found\n * - 400, 401, 403: Other client errors\n */\n private isClientError(error: unknown): boolean {\n return (\n error instanceof MessageNotAvailableError || // 409 - ticket mismatch, lost ownership\n error instanceof MessageNotFoundError || // 404 - receipt handle not found\n error instanceof BadRequestError || // 400 - invalid parameters\n error instanceof UnauthorizedError || // 401 - auth failed\n error instanceof ForbiddenError // 403 - access denied\n );\n }\n\n /**\n * Starts a background loop that periodically extends the visibility timeout for a message.\n *\n * Timing strategy:\n * - Renewal interval: min(60s, max(10s, visibilityTimeout/5))\n * - Extensions request the same duration as the initial visibility timeout\n * - When `visibilityDeadline` is provided (binary mode small body), the first\n * extension delay is calculated from the time remaining until the deadline\n * using the same renewal formula, ensuring the first extension fires before\n * the server-assigned lease expires. Subsequent renewals use the standard interval.\n *\n * Retry strategy:\n * - On transient failures (5xx, network errors): retry every 3 seconds\n * - On 4xx client errors: stop retrying (the lease is lost or invalid)\n *\n * @param receiptHandle - The receipt handle to extend visibility for\n * @param options - Optional configuration\n * @param options.visibilityDeadline - Absolute deadline (from server's `ce-vqsvisibilitydeadline`)\n * when the current visibility timeout expires. Used to calculate the first extension delay.\n */\n private startVisibilityExtension(\n receiptHandle: string,\n options?: { visibilityDeadline?: Date },\n ): (waitForCompletion?: boolean) => Promise<void> {\n let isRunning = true;\n let isResolved = false;\n let resolveLifecycle: () => void;\n let timeoutId: NodeJS.Timeout | null = null;\n\n const renewalIntervalMs =\n calculateRenewalInterval(this.visibilityTimeout) * 1000;\n\n let firstDelayMs = renewalIntervalMs;\n if (options?.visibilityDeadline) {\n const timeRemainingMs = options.visibilityDeadline.getTime() - Date.now();\n if (timeRemainingMs > 0) {\n const timeRemainingSeconds = timeRemainingMs / 1000;\n firstDelayMs = calculateRenewalInterval(timeRemainingSeconds) * 1000;\n } else {\n firstDelayMs = 0;\n }\n }\n\n // Promise that tracks the actual termination of the extension loop\n const lifecyclePromise = new Promise<void>((resolve) => {\n resolveLifecycle = resolve;\n });\n\n const safeResolve = () => {\n if (!isResolved) {\n isResolved = true;\n resolveLifecycle();\n }\n };\n\n const extend = async (): Promise<void> => {\n // Check if we should stop before attempting extension\n if (!isRunning) {\n safeResolve();\n return;\n }\n\n try {\n await this.client.changeVisibility({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n receiptHandle,\n visibilityTimeoutSeconds: this.visibilityTimeout,\n });\n\n // Successfully extended - schedule next extension\n if (isRunning) {\n timeoutId = setTimeout(() => extend(), renewalIntervalMs);\n } else {\n safeResolve();\n }\n } catch (error) {\n // Check if this is a 4xx client error - stop retrying\n if (this.isClientError(error)) {\n console.error(\n `Visibility extension failed with client error for receipt handle ${receiptHandle} (stopping retries):`,\n error,\n );\n safeResolve();\n return;\n }\n\n // Transient error - log and schedule retry\n console.error(\n `Failed to extend visibility for receipt handle ${receiptHandle} (will retry in ${RETRY_INTERVAL_MS / 1000}s):`,\n error,\n );\n\n // Retry after RETRY_INTERVAL_MS if still running\n if (isRunning) {\n timeoutId = setTimeout(() => extend(), RETRY_INTERVAL_MS);\n } else {\n safeResolve();\n }\n }\n };\n\n timeoutId = setTimeout(() => extend(), firstDelayMs);\n\n // Return a function to stop the extension loop\n return async (waitForCompletion: boolean = false) => {\n // Signal the loop to stop\n isRunning = false;\n\n // Cancel any pending timeout to avoid unnecessary waiting\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n // Only wait for in-flight operations if explicitly requested\n if (waitForCompletion) {\n // Wait for the loop to actually terminate\n // This ensures any in-progress extension completes or fails\n await lifecyclePromise;\n } else {\n safeResolve();\n }\n };\n }\n\n /**\n * Clean up the message payload if the transport supports it and payload exists.\n */\n private async finalizePayload<TPayload>(payload: TPayload): Promise<void> {\n const transport = this.client.getTransport();\n if (transport.finalize && payload !== undefined && payload !== null) {\n try {\n await transport.finalize(payload);\n } catch (finalizeError) {\n console.warn(\"Failed to finalize message payload:\", finalizeError);\n }\n }\n }\n\n private async processMessage<TPayload>(\n message: Message<TPayload>,\n handler: MessageHandler<TPayload>,\n options?: { visibilityDeadline?: Date; retry?: RetryHandler },\n ): Promise<void> {\n const stopExtension = this.startVisibilityExtension(\n message.receiptHandle,\n options,\n );\n\n const metadata: MessageMetadata = {\n messageId: message.messageId,\n deliveryCount: message.deliveryCount,\n createdAt: message.createdAt,\n expiresAt: message.expiresAt,\n topicName: this.topicName,\n consumerGroup: this.consumerGroupName,\n region: this.client.getRegion(),\n };\n\n try {\n await handler(message.payload, metadata);\n // Stop extensions immediately - we don't need to wait for in-flight extensions\n // since we're about to acknowledge the message anyway\n await stopExtension();\n\n await this.client.acknowledgeMessage({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n receiptHandle: message.receiptHandle,\n });\n } catch (error) {\n // Stop extensions immediately on error - fail fast without waiting\n // for any in-flight extension attempts\n await stopExtension();\n\n // If a retry handler is configured, give it a chance to reschedule or acknowledge\n if (options?.retry) {\n let directive: RetryDirective | void | undefined;\n try {\n directive = options.retry(error, metadata);\n } catch (retryError) {\n console.warn(\"retry handler threw:\", retryError);\n }\n\n if (directive) {\n if (\"acknowledge\" in directive && directive.acknowledge) {\n // Acknowledge the message so it is never retried\n try {\n await this.client.acknowledgeMessage({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n receiptHandle: message.receiptHandle,\n });\n } catch (ackError) {\n console.warn(\"Failed to acknowledge message:\", ackError);\n }\n\n await this.finalizePayload(message.payload);\n return;\n }\n\n if (\n \"afterSeconds\" in directive &&\n typeof directive.afterSeconds === \"number\"\n ) {\n try {\n await this.client.changeVisibility({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n receiptHandle: message.receiptHandle,\n visibilityTimeoutSeconds: directive.afterSeconds,\n });\n } catch (changeError) {\n console.warn(\n \"Failed to reschedule message for retry:\",\n changeError,\n );\n }\n\n await this.finalizePayload(message.payload);\n return;\n }\n }\n }\n\n await this.finalizePayload(message.payload);\n throw error;\n }\n }\n\n /**\n * Process a pre-fetched message directly, without calling `receiveMessageById`.\n *\n * Used by the binary mode (v2beta) small body fast path, where the server\n * pushes the full message payload in the callback request. The message is\n * processed with the same lifecycle guarantees as `consume()`:\n * - Visibility timeout is extended periodically during processing\n * - Message is acknowledged on successful handler completion\n * - Payload is finalized on error if the transport supports it\n *\n * @param handler - Function to process the message payload and metadata\n * @param message - The complete message including payload and receipt handle\n * @param options - Optional configuration\n * @param options.visibilityDeadline - Absolute deadline when the server-assigned\n * visibility timeout expires (from `ce-vqsvisibilitydeadline`). Used to\n * schedule the first visibility extension before the lease expires.\n */\n async consumeMessage(\n handler: MessageHandler<T>,\n message: Message<T>,\n options?: { visibilityDeadline?: Date; retry?: RetryHandler },\n ): Promise<void> {\n await this.processMessage(message, handler, options);\n }\n\n /**\n * Consume the next available message from the queue.\n *\n * The message is automatically:\n * - Locked with the configured visibility timeout\n * - Kept alive via periodic visibility extensions during processing\n * - Acknowledged upon successful handler completion\n * - Released for retry if the handler throws an error\n *\n * @param handler - Function to process the message payload and metadata.\n * Not called when the queue is empty.\n * @returns Number of messages processed (0 if queue was empty)\n * @throws Handler errors are re-thrown after cleanup\n */\n async consume(handler: MessageHandler<T>): Promise<number>;\n\n /**\n * Consume a specific message by its ID.\n *\n * Used for targeted message processing, typically from webhook callbacks.\n *\n * @param handler - Function to process the message payload and metadata\n * @param options - Options containing the messageId to consume\n * @param options.messageId - Specific message ID to consume\n * @returns Number of messages processed (always 1 on success)\n * @throws {MessageNotFoundError} When message doesn't exist\n * @throws {MessageNotAvailableError} When message in wrong state\n * @throws {MessageAlreadyProcessedError} When already processed\n * @throws Handler errors are re-thrown after cleanup\n */\n async consume(\n handler: MessageHandler<T>,\n options: ConsumeByIdOptions,\n ): Promise<number>;\n\n /**\n * Consume messages from the queue with an optional batch limit.\n *\n * Fetches up to `limit` messages in a single request and processes them\n * sequentially with the provided handler.\n *\n * @param handler - Function to process each message payload and metadata.\n * Not called when the queue is empty.\n * @param options - Options containing the limit\n * @param options.limit - Maximum messages to retrieve (default: 1, min: 1, max: 10)\n * @returns Number of messages processed (0 if queue was empty)\n * @throws Handler errors are re-thrown after cleanup\n */\n async consume(\n handler: MessageHandler<T>,\n options: ConsumeBatchOptions,\n ): Promise<number>;\n\n async consume(\n handler: MessageHandler<T>,\n options?: ConsumeOptions,\n ): Promise<number> {\n const retry = options?.retry;\n\n if (options && \"messageId\" in options) {\n const response = await this.client.receiveMessageById<T>({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n messageId: options.messageId,\n visibilityTimeoutSeconds: this.visibilityTimeout,\n });\n await this.processMessage<T>(response.message, handler, { retry });\n return 1;\n } else {\n const limit = options && \"limit\" in options ? options.limit : 1;\n let messagesProcessed = 0;\n\n for await (const message of this.client.receiveMessages<T>({\n queueName: this.topicName,\n consumerGroup: this.consumerGroupName,\n visibilityTimeoutSeconds: this.visibilityTimeout,\n limit,\n })) {\n messagesProcessed++;\n await this.processMessage<T>(message, handler, { retry });\n }\n\n return messagesProcessed;\n }\n }\n\n /**\n * Get the consumer group name\n */\n get name(): string {\n return this.consumerGroupName;\n }\n\n /**\n * Get the topic name this consumer group is subscribed to\n */\n get topic(): string {\n return this.topicName;\n }\n}\n","import { ApiClient } from \"./api-client\";\nimport { ConsumerGroup } from \"./consumer-group\";\nimport type { ConsumerGroupOptions, SendOptions, SendResult } from \"./types\";\nimport { isDevMode, triggerDevCallbacks } from \"./dev\";\n\n/**\n * A Topic represents a named channel for publishing messages in a pub/sub pattern\n */\nexport class Topic<T = unknown> {\n private client: ApiClient;\n private topicName: string;\n\n /**\n * @param client ApiClient instance to use for API calls\n * @param topicName Name of the topic to work with\n */\n constructor(client: ApiClient, topicName: string) {\n this.client = client;\n this.topicName = topicName;\n }\n\n /**\n * Publish a message to the topic\n * @param payload The data to publish\n * @param options Optional publish options\n * @returns `{ messageId }` — `messageId` is `null` when deferred\n * @throws {BadRequestError} When request parameters are invalid\n * @throws {UnauthorizedError} When authentication fails\n * @throws {ForbiddenError} When access is denied (environment mismatch)\n * @throws {InternalServerError} When server encounters an error\n */\n async publish(payload: T, options?: SendOptions): Promise<SendResult> {\n const result = await this.client.sendMessage<T>({\n queueName: this.topicName,\n payload,\n idempotencyKey: options?.idempotencyKey,\n retentionSeconds: options?.retentionSeconds,\n delaySeconds: options?.delaySeconds,\n headers: options?.headers,\n });\n\n // In development mode, automatically trigger registered callbacks after 1s\n if (result.messageId && isDevMode()) {\n triggerDevCallbacks(\n this.topicName,\n result.messageId,\n this.client.getRegion(),\n );\n }\n\n return { messageId: result.messageId };\n }\n\n /**\n * Create a consumer group for this topic\n * @param consumerGroupName Name of the consumer group\n * @param options Optional configuration for the consumer group\n * @returns A ConsumerGroup instance\n */\n consumerGroup<U = T>(\n consumerGroupName: string,\n options?: ConsumerGroupOptions<U>,\n ): ConsumerGroup<U> {\n return new ConsumerGroup<U>(\n this.client,\n this.topicName,\n consumerGroupName,\n options,\n );\n }\n\n /**\n * Get the topic name\n */\n get name(): string {\n return this.topicName;\n }\n}\n","/**\n * Core queue callback utilities for handling incoming webhook payloads\n * from Vercel triggers using the CloudEvent specification.\n *\n * This module provides the framework-agnostic core. For framework-specific\n * wrappers, see `@vercel/queue/web` and `@vercel/queue/nextjs/pages`.\n */\nimport { getApiClient, type QueueClient } from \"./client\";\nimport { Topic } from \"./topic\";\nimport type { Message, MessageHandler, RetryHandler } from \"./types\";\nimport type { Transport } from \"./transports\";\n\n/**\n * CloudEvent specification for queue callbacks.\n *\n * Incoming webhook payloads from Vercel follow the CloudEvents v1.0 spec\n * with queue-specific data fields.\n *\n * @see https://cloudevents.io/\n */\nexport interface CloudEvent<T = unknown> {\n /** Event type identifier, e.g. `\"com.vercel.queue.v1beta\"` (structured) or `\"com.vercel.queue.v2beta\"` (binary) */\n type: string;\n /** Event source URI, e.g. `\"/topic/my-topic/consumer/my-group\"` */\n source: string;\n /** Unique event identifier */\n id: string;\n /** MIME type of the `data` field */\n datacontenttype: string;\n /** Event payload containing queue message metadata */\n data: T;\n /** ISO 8601 timestamp of when the event was produced */\n time?: string;\n /** CloudEvents specification version */\n specversion?: string;\n}\n\n/**\n * Options for configuring `handleCallback` behavior.\n */\nexport interface HandleCallbackOptions {\n /**\n * QueueClient instance to use for processing messages.\n * If not provided, a default client is created with OIDC authentication\n * and JsonTransport.\n */\n client?: QueueClient;\n\n /**\n * Time in seconds that messages will be invisible to other consumers\n * during processing. The handler will automatically extend this timeout\n * while processing.\n *\n * @default 300 (5 minutes)\n * @minimum 30\n * @maximum 3600 (1 hour)\n */\n visibilityTimeoutSeconds?: number;\n\n /**\n * Called when the handler throws. Return `{ afterSeconds: N }` to reschedule\n * the message for redelivery after N seconds, or return `undefined`\n * to let the error propagate normally.\n */\n retry?: RetryHandler;\n}\n\nexport const CLOUD_EVENT_TYPE_V1BETA = \"com.vercel.queue.v1beta\";\nexport const CLOUD_EVENT_TYPE_V2BETA = \"com.vercel.queue.v2beta\";\n\n/**\n * Routing-only callback: the SDK must fetch the message by ID.\n * Produced by v1beta structured mode and v2beta large-body mode.\n */\nexport type ParsedCallbackV1 = {\n queueName: string;\n consumerGroup: string;\n messageId: string;\n region?: string;\n};\n\n/**\n * Full-message callback: payload and receipt handle are inlined,\n * so the SDK can process directly without an extra fetch.\n * Produced by v2beta small-body mode.\n */\nexport type ParsedCallbackV2 = {\n queueName: string;\n consumerGroup: string;\n messageId: string;\n region?: string;\n receiptHandle: string;\n deliveryCount?: number;\n createdAt?: string;\n expiresAt?: string;\n contentType?: string;\n visibilityDeadline?: string;\n rawBody?: ReadableStream<Uint8Array>;\n parsedPayload?: unknown;\n};\n\nexport type ParsedCallbackRequest = ParsedCallbackV1 | ParsedCallbackV2;\n\n/**\n * Check if a topic name matches a wildcard pattern.\n * Used by dev mode for route discovery from vercel.json.\n *\n * @param topicName - The topic name to test\n * @param pattern - A wildcard pattern ending with `*`\n * @returns `true` if topicName starts with the pattern prefix\n */\nexport function matchesWildcardPattern(\n topicName: string,\n pattern: string,\n): boolean {\n // Remove the trailing *\n const prefix = pattern.slice(0, -1);\n return topicName.startsWith(prefix);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * Parse and validate a v1beta structured CloudEvent body.\n *\n * @internal\n */\nfunction parseV1StructuredBody(\n body: unknown,\n contentType: string | null,\n): ParsedCallbackRequest {\n if (!contentType || !contentType.includes(\"application/cloudevents+json\")) {\n throw new Error(\n \"Invalid content type: expected 'application/cloudevents+json'\",\n );\n }\n\n if (\n !isRecord(body) ||\n !body.type ||\n !body.source ||\n !body.id ||\n !isRecord(body.data)\n ) {\n throw new Error(\"Invalid CloudEvent: missing required fields\");\n }\n\n if (body.type !== CLOUD_EVENT_TYPE_V1BETA) {\n throw new Error(\n `Invalid CloudEvent type: expected '${CLOUD_EVENT_TYPE_V1BETA}', got '${String(body.type)}'`,\n );\n }\n\n const { data } = body;\n const missingFields: string[] = [];\n if (!(\"queueName\" in data)) missingFields.push(\"queueName\");\n if (!(\"consumerGroup\" in data)) missingFields.push(\"consumerGroup\");\n if (!(\"messageId\" in data)) missingFields.push(\"messageId\");\n if (missingFields.length > 0) {\n throw new Error(\n `Missing required CloudEvent data fields: ${missingFields.join(\", \")}`,\n );\n }\n\n return {\n queueName: String(data.queueName),\n consumerGroup: String(data.consumerGroup),\n messageId: String(data.messageId),\n };\n}\n\ntype HeaderSource = Headers | Record<string, string | string[] | undefined>;\n\nfunction getHeader(headers: HeaderSource, name: string): string | null {\n if (headers instanceof Headers) {\n return headers.get(name);\n }\n const value = headers[name];\n if (Array.isArray(value)) return value[0] ?? null;\n return (value as string) ?? null;\n}\n\nfunction parseBinaryHeaders(headers: HeaderSource): ParsedCallbackRequest {\n const ceType = getHeader(headers, \"ce-type\");\n if (ceType !== CLOUD_EVENT_TYPE_V2BETA) {\n throw new Error(\n `Invalid CloudEvent type: expected '${CLOUD_EVENT_TYPE_V2BETA}', got '${ceType}'`,\n );\n }\n\n const queueName = getHeader(headers, \"ce-vqsqueuename\");\n const consumerGroup = getHeader(headers, \"ce-vqsconsumergroup\");\n const messageId = getHeader(headers, \"ce-vqsmessageid\");\n\n const missingFields: string[] = [];\n if (!queueName) missingFields.push(\"ce-vqsqueuename\");\n if (!consumerGroup) missingFields.push(\"ce-vqsconsumergroup\");\n if (!messageId) missingFields.push(\"ce-vqsmessageid\");\n if (missingFields.length > 0) {\n throw new Error(\n `Missing required CloudEvent headers: ${missingFields.join(\", \")}`,\n );\n }\n\n const region = getHeader(headers, \"ce-vqsregion\") ?? undefined;\n\n const base = {\n queueName: queueName!,\n consumerGroup: consumerGroup!,\n messageId: messageId!,\n region,\n };\n\n const receiptHandle = getHeader(headers, \"ce-vqsreceipthandle\");\n if (!receiptHandle) {\n return base;\n }\n\n const result: ParsedCallbackV2 = { ...base, receiptHandle };\n\n const deliveryCount = getHeader(headers, \"ce-vqsdeliverycount\");\n if (deliveryCount) {\n result.deliveryCount = parseInt(deliveryCount, 10);\n }\n\n const createdAt = getHeader(headers, \"ce-vqscreatedat\");\n if (createdAt) {\n result.createdAt = createdAt;\n }\n\n const expiresAt = getHeader(headers, \"ce-vqsexpiresat\");\n if (expiresAt) {\n result.expiresAt = expiresAt;\n }\n\n const contentType = getHeader(headers, \"content-type\");\n if (contentType) {\n result.contentType = contentType;\n }\n\n const visibilityDeadline = getHeader(headers, \"ce-vqsvisibilitydeadline\");\n if (visibilityDeadline) {\n result.visibilityDeadline = visibilityDeadline;\n }\n\n return result;\n}\n\n/**\n * Parse a callback from a pre-parsed body and headers.\n *\n * For frameworks like Next.js Pages Router where the body has already been\n * parsed, use this instead of {@link parseCallback}.\n *\n * Detects the CloudEvent version from the `ce-type` header:\n * - `com.vercel.queue.v2beta`: binary content mode (metadata in headers,\n * payload in body). For small messages, the body is attached as `parsedPayload`.\n * - Otherwise: structured content mode (v1beta, entire CloudEvent in JSON body)\n *\n * @param body - The framework-parsed request body. Type depends on Content-Type\n * and framework configuration:\n * - v1beta: parsed CloudEvent JSON object\n * - v2beta: the message payload as parsed by the framework (object, Buffer, or string)\n * @param headers - HTTP headers\n * @returns Parsed callback request with routing metadata and optional payload\n */\nexport function parseRawCallback(\n body: unknown,\n headers: Record<string, string | string[] | undefined>,\n): ParsedCallbackRequest {\n const ceType = getHeader(headers, \"ce-type\");\n\n if (ceType === CLOUD_EVENT_TYPE_V2BETA) {\n const result = parseBinaryHeaders(headers);\n if (\"receiptHandle\" in result) {\n result.parsedPayload = body;\n }\n return result;\n }\n\n return parseV1StructuredBody(body, getHeader(headers, \"content-type\"));\n}\n\n/**\n * Parse and validate a CloudEvent callback from a Web API `Request` object.\n *\n * Detects the CloudEvent version from the `ce-type` header:\n * - `com.vercel.queue.v2beta`: binary content mode (metadata in headers,\n * payload in body). For v2beta, the body is attached as `rawBody` (a\n * ReadableStream) rather than being parsed.\n * - Otherwise: structured content mode (v1beta, entire CloudEvent in JSON body)\n *\n * For frameworks that pre-parse the body (e.g. Next.js Pages Router),\n * use {@link parseRawCallback} instead.\n */\nexport async function parseCallback(\n request: Request,\n): Promise<ParsedCallbackRequest> {\n const ceType = request.headers.get(\"ce-type\");\n\n if (ceType === CLOUD_EVENT_TYPE_V2BETA) {\n const result = parseBinaryHeaders(request.headers);\n if (\"receiptHandle\" in result && request.body) {\n result.rawBody = request.body;\n }\n return result;\n }\n\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n throw new Error(\"Failed to parse CloudEvent from request body\");\n }\n\n const headers: Record<string, string> = {};\n request.headers.forEach((value, key) => {\n headers[key] = value;\n });\n\n return parseRawCallback(body, headers);\n}\n\n/**\n * Core queue callback handler. Processes the message using the provided handler.\n *\n * This is the framework-agnostic core — it takes already-parsed request data\n * and throws on errors. Framework-specific wrappers (in `@vercel/queue/web`\n * and `@vercel/queue/nextjs/pages`) compose around this function to handle\n * request parsing and response formatting.\n *\n * @param handler - Function to process the message payload and metadata\n * @param request - A {@link ParsedCallbackV1} (routing metadata only, message\n * fetched by ID) or {@link ParsedCallbackV2} (full message inlined, no fetch).\n * @param options - Optional configuration (client, visibilityTimeoutSeconds)\n * @throws {Error} If binary mode request has a receipt handle but no payload\n * @throws {Error} If message processing fails\n *\n * @example\n * ```typescript\n * import { handleCallback, parseRawCallback } from \"@vercel/queue\";\n *\n * const parsed = parseRawCallback(body, headers);\n * await handleCallback(async (message, metadata) => {\n * console.log(\"Processing:\", message);\n * }, parsed);\n * ```\n */\nexport async function handleCallback<T = unknown>(\n handler: MessageHandler<T>,\n request: ParsedCallbackRequest,\n options?: HandleCallbackOptions,\n): Promise<void> {\n const { queueName, consumerGroup, messageId } = request;\n\n if (!options?.client) {\n throw new Error(\"HandleCallbackOptions.client is required\");\n }\n let api = getApiClient(options.client);\n if (request.region) {\n api = api.withRegion(request.region);\n }\n const topic = new Topic<T>(api, queueName);\n const cg = topic.consumerGroup(\n consumerGroup,\n options?.visibilityTimeoutSeconds !== undefined\n ? { visibilityTimeoutSeconds: options.visibilityTimeoutSeconds }\n : undefined,\n );\n\n if (\"receiptHandle\" in request) {\n const transport = api.getTransport() as Transport<T>;\n\n let payload: T;\n if (request.rawBody) {\n payload = await transport.deserialize(request.rawBody);\n } else if (request.parsedPayload !== undefined) {\n payload = request.parsedPayload as T;\n } else {\n throw new Error(\n \"Binary mode callback with receipt handle is missing payload\",\n );\n }\n\n const message: Message<T> = {\n messageId,\n payload,\n deliveryCount: request.deliveryCount ?? 1,\n createdAt: request.createdAt ? new Date(request.createdAt) : new Date(),\n expiresAt: request.expiresAt ? new Date(request.expiresAt) : undefined,\n contentType: request.contentType ?? transport.contentType,\n receiptHandle: request.receiptHandle,\n };\n\n const visibilityDeadline = request.visibilityDeadline\n ? new Date(request.visibilityDeadline)\n : undefined;\n\n await cg.consumeMessage(handler, message, {\n visibilityDeadline,\n retry: options?.retry,\n });\n } else {\n await cg.consume(handler, { messageId, retry: options?.retry });\n }\n}\n","export { getVercelOidcToken } from \"@vercel/oidc\";\n","import { ApiClient } from \"./api-client\";\nimport {\n handleCallback as coreHandleCallback,\n parseCallback,\n parseRawCallback,\n} from \"./callback\";\nimport { isDevMode, triggerDevCallbacks } from \"./dev\";\nimport { Topic } from \"./topic\";\nimport type {\n MessageHandler,\n QueueClientOptions,\n ReceiveBatchOptions,\n ReceiveOptions,\n ReceiveResult,\n RetryHandler,\n SendOptions,\n SendResult,\n} from \"./types\";\nimport {\n MessageAlreadyProcessedError,\n MessageNotAvailableError,\n MessageNotFoundError,\n} from \"./types\";\n\nconst apiClients = new WeakMap<QueueClient, ApiClient>();\n\n/**\n * Resolve the internal ApiClient for a QueueClient instance.\n * Used by internal modules (callback.ts) that need API access from a user-provided QueueClient.\n * Not exported from the package entrypoint.\n */\nexport function getApiClient(client: QueueClient): ApiClient {\n const api = apiClients.get(client);\n if (!api) {\n throw new Error(\"QueueClient not initialized\");\n }\n return api;\n}\n\nexport class QueueClient {\n constructor(options: QueueClientOptions) {\n apiClients.set(this, new ApiClient(options));\n }\n\n /**\n * Send a message to a topic.\n *\n * This is an arrow function property so it can be destructured:\n * ```typescript\n * const { send } = new QueueClient({ region: process.env.QUEUE_REGION! });\n * await send(\"my-topic\", payload);\n * ```\n *\n * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)\n * @param payload - The data to send (serialized via the configured transport)\n * @param options - Optional send options (idempotencyKey, retentionSeconds, delaySeconds, headers)\n * @returns `{ messageId }` — `messageId` is `null` when the server accepted\n * the message for deferred processing (no ID available yet)\n */\n send = async <T = unknown>(\n topicName: string,\n payload: T,\n options?: SendOptions,\n ): Promise<SendResult> => {\n const api = getApiClient(this);\n const result = await api.sendMessage<T>({\n queueName: topicName,\n payload,\n idempotencyKey: options?.idempotencyKey,\n retentionSeconds: options?.retentionSeconds,\n delaySeconds: options?.delaySeconds,\n headers: options?.headers,\n });\n\n if (result.messageId && isDevMode()) {\n triggerDevCallbacks(\n topicName,\n result.messageId,\n api.getRegion(),\n options?.delaySeconds,\n );\n }\n\n return { messageId: result.messageId };\n };\n\n /**\n * Receive and process messages from a topic.\n *\n * Each message is automatically locked, kept alive via periodic visibility\n * extensions during processing, and acknowledged upon successful handler completion.\n * The handler is not called when the queue is empty — check `result.ok` instead.\n *\n * This is an arrow function property so it can be destructured:\n * ```typescript\n * const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });\n * const result = await receive(\"my-topic\", \"my-group\", handler);\n * if (!result.ok) console.log(result.reason);\n * ```\n *\n * @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)\n * @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)\n * @param handler - Function to process each message payload and metadata.\n * Not called when the queue is empty.\n * @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)\n * @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise\n */\n receive = async <T = unknown>(\n topicName: string,\n consumerGroup: string,\n handler: MessageHandler<T>,\n options?: ReceiveOptions,\n ): Promise<ReceiveResult> => {\n const api = getApiClient(this);\n const topic = new Topic<T>(api, topicName);\n const visibilityTimeoutSeconds =\n options && \"visibilityTimeoutSeconds\" in options\n ? options.visibilityTimeoutSeconds\n : undefined;\n const consumer = topic.consumerGroup(\n consumerGroup,\n visibilityTimeoutSeconds !== undefined\n ? { visibilityTimeoutSeconds }\n : {},\n );\n\n try {\n let count: number;\n const retry = options?.retry;\n if (options && \"messageId\" in options) {\n count = await consumer.consume(handler, {\n messageId: options.messageId,\n retry,\n });\n } else {\n const limit =\n options && \"limit\" in options\n ? (options as ReceiveBatchOptions).limit\n : undefined;\n count = await consumer.consume(handler, {\n ...(limit !== undefined ? { limit } : {}),\n retry,\n });\n }\n\n if (count === 0) {\n return { ok: false, reason: \"empty\" };\n }\n return { ok: true };\n } catch (error) {\n if (\n options &&\n \"messageId\" in options &&\n error instanceof MessageNotFoundError\n ) {\n return { ok: false, reason: \"not_found\", messageId: options.messageId };\n }\n if (\n options &&\n \"messageId\" in options &&\n error instanceof MessageNotAvailableError\n ) {\n return {\n ok: false,\n reason: \"not_available\",\n messageId: options.messageId,\n };\n }\n if (\n options &&\n \"messageId\" in options &&\n error instanceof MessageAlreadyProcessedError\n ) {\n return {\n ok: false,\n reason: \"already_processed\",\n messageId: options.messageId,\n };\n }\n throw error;\n }\n };\n\n /**\n * Create a Web API route handler for processing queue callback messages.\n *\n * Parses incoming `Request` as a CloudEvent and invokes the handler.\n * For use on Vercel — Vercel invokes this route when messages are available.\n *\n * This is an arrow function property so it can be destructured:\n * ```typescript\n * const { handleCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });\n * export const POST = handleCallback(handler);\n * ```\n *\n * @param handler - Function to process the message payload and metadata\n * @param options - Optional configuration\n * @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)\n * @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to\n * reschedule the message for redelivery after N seconds.\n * @returns A `(request: Request) => Promise<Response>` route handler\n */\n handleCallback = <T = unknown>(\n handler: MessageHandler<T>,\n options?: { visibilityTimeoutSeconds?: number; retry?: RetryHandler },\n ): ((request: Request) => Promise<Response>) => {\n return async (request: Request): Promise<Response> => {\n try {\n const parsed = await parseCallback(request);\n await coreHandleCallback(handler, parsed, {\n client: this,\n visibilityTimeoutSeconds: options?.visibilityTimeoutSeconds,\n retry: options?.retry,\n });\n return Response.json({ status: \"success\" });\n } catch (error) {\n console.error(\"Queue callback error:\", error);\n\n if (\n error instanceof Error &&\n (error.message.includes(\"Invalid content type\") ||\n error.message.includes(\"Invalid CloudEvent\") ||\n error.message.includes(\"Missing required CloudEvent\") ||\n error.message.includes(\"Failed to parse CloudEvent\") ||\n error.message.includes(\"Binary mode callback\"))\n ) {\n return Response.json({ error: error.message }, { status: 400 });\n }\n\n return Response.json(\n { error: \"Failed to process queue message\" },\n { status: 500 },\n );\n }\n };\n };\n\n /**\n * Create a Connect-style route handler for processing queue callback messages.\n * For use on Vercel — Vercel invokes this route when messages are available.\n *\n * For frameworks using the `(req, res)` middleware pattern where `req.body`\n * is pre-parsed (Next.js Pages Router, etc.).\n *\n * This is an arrow function property so it can be destructured:\n * ```typescript\n * const { handleNodeCallback } = new QueueClient({ region: process.env.QUEUE_REGION! });\n * app.post(\"/api/queue\", handleNodeCallback(handler));\n * ```\n *\n * @param handler - Function to process the message payload and metadata\n * @param options - Optional configuration\n * @param options.visibilityTimeoutSeconds - Message lock duration (default: 300, max: 3600)\n * @param options.retry - Called when the handler throws. Return `{ afterSeconds: N }` to\n * reschedule the message for redelivery after N seconds.\n * @returns A `(req, res) => Promise<void>` route handler\n */\n handleNodeCallback = <T = unknown>(\n handler: MessageHandler<T>,\n options?: { visibilityTimeoutSeconds?: number; retry?: RetryHandler },\n ): ((\n req: {\n method?: string;\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n },\n res: {\n status(code: number): { json(data: unknown): void; end(): void };\n end(): void;\n },\n ) => Promise<void>) => {\n return async (req, res) => {\n if (req.method !== \"POST\") {\n res.status(200).end();\n return;\n }\n\n try {\n const parsed = parseRawCallback(req.body, req.headers);\n await coreHandleCallback(handler, parsed, {\n client: this,\n visibilityTimeoutSeconds: options?.visibilityTimeoutSeconds,\n retry: options?.retry,\n });\n res.status(200).json({ status: \"success\" });\n } catch (error) {\n console.error(\"Queue callback error:\", error);\n\n if (\n error instanceof Error &&\n (error.message.includes(\"Invalid content type\") ||\n error.message.includes(\"Invalid CloudEvent\") ||\n error.message.includes(\"Missing required CloudEvent\") ||\n error.message.includes(\"Failed to parse CloudEvent\") ||\n error.message.includes(\"Binary mode callback\"))\n ) {\n res.status(400).json({ error: error.message });\n return;\n }\n\n res.status(500).json({ error: \"Failed to process queue message\" });\n }\n };\n };\n}\n"],"mappings":"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","names":["path"]}
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "@vercel/queue",
3
- "version": "0.0.0-alpha.8",
4
- "access": "restricted",
3
+ "version": "0.0.1",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
5
7
  "description": "A Node.js library for interacting with the Vercel Queue Service API",
6
8
  "main": "dist/index.js",
7
9
  "module": "dist/index.mjs",
@@ -9,7 +11,7 @@
9
11
  "exports": {
10
12
  ".": {
11
13
  "import": {
12
- "types": "./dist/index.d.ts",
14
+ "types": "./dist/index.d.mts",
13
15
  "default": "./dist/index.mjs"
14
16
  },
15
17
  "require": {
@@ -22,7 +24,7 @@
22
24
  "dist"
23
25
  ],
24
26
  "engines": {
25
- "node": ">=22.0.0"
27
+ "node": ">=20.0.0"
26
28
  },
27
29
  "keywords": [
28
30
  "vercel",
@@ -34,7 +36,8 @@
34
36
  "author": "Timer <timer@vercel.com>",
35
37
  "license": "MIT",
36
38
  "dependencies": {
37
- "mixpart": "0.0.4"
39
+ "@vercel/oidc": "^3.0.5",
40
+ "mixpart": "0.0.5"
38
41
  },
39
42
  "devDependencies": {
40
43
  "@microsoft/api-extractor": "^7.52.8",