@parsrun/queue 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/adapters/memory.ts","../src/adapters/cloudflare.ts","../src/adapters/qstash.ts","../src/index.ts"],"sourcesContent":["/**\n * @parsrun/queue - Type Definitions\n * Queue types and interfaces\n */\n\n// Re-export types from @parsrun/types for convenience\nexport {\n type,\n jobStatus,\n job,\n jobOptions,\n addJobRequest,\n jobProgressUpdate,\n queueStats as parsQueueStats,\n queueListOptions,\n redisQueueConfig,\n workerOptions,\n queueConfig,\n type JobStatus,\n type Job,\n type JobOptions,\n type AddJobRequest,\n type JobProgressUpdate,\n type QueueStats as ParsQueueStats,\n type QueueListOptions,\n type RedisQueueConfig,\n type WorkerOptions,\n type QueueConfig,\n} from \"@parsrun/types\";\n\n/**\n * Queue adapter type\n */\nexport type QueueAdapterType = \"memory\" | \"cloudflare\" | \"qstash\";\n\n/**\n * Message payload\n */\nexport interface QueueMessage<T = unknown> {\n /** Unique message ID */\n id: string;\n /** Message payload */\n body: T;\n /** Message timestamp */\n timestamp: Date;\n /** Number of delivery attempts */\n attempts: number;\n /** Optional delay before processing (seconds) */\n delaySeconds?: number | undefined;\n /** Optional deduplication ID */\n deduplicationId?: string | undefined;\n /** Custom metadata */\n metadata?: Record<string, unknown> | undefined;\n}\n\n/**\n * Send message options\n */\nexport interface SendMessageOptions {\n /** Delay before message is available (seconds) */\n delaySeconds?: number | undefined;\n /** Deduplication ID (prevents duplicate processing) */\n deduplicationId?: string | undefined;\n /** Custom metadata */\n metadata?: Record<string, unknown> | undefined;\n /** Priority (higher = more important) */\n priority?: number | undefined;\n}\n\n/**\n * Batch send result\n */\nexport interface BatchSendResult {\n /** Total messages sent */\n total: number;\n /** Successfully sent */\n successful: number;\n /** Failed to send */\n failed: number;\n /** Individual message IDs */\n messageIds: string[];\n /** Failed messages with errors */\n errors: Array<{ index: number; error: string }>;\n}\n\n/**\n * Message handler function\n */\nexport type MessageHandler<T = unknown> = (\n message: QueueMessage<T>\n) => void | Promise<void>;\n\n/**\n * Consumer options\n */\nexport interface ConsumerOptions {\n /** Maximum messages to process per batch */\n batchSize?: number | undefined;\n /** Visibility timeout (seconds) - how long a message is hidden while processing */\n visibilityTimeout?: number | undefined;\n /** Polling interval (ms) for pull-based queues */\n pollingInterval?: number | undefined;\n /** Maximum retries before dead-letter */\n maxRetries?: number | undefined;\n /** Concurrency - how many messages to process in parallel */\n concurrency?: number | undefined;\n}\n\n/**\n * Queue adapter interface\n */\nexport interface QueueAdapter<T = unknown> {\n /** Adapter type */\n readonly type: QueueAdapterType;\n\n /** Queue name */\n readonly name: string;\n\n /**\n * Send a message to the queue\n */\n send(body: T, options?: SendMessageOptions): Promise<string>;\n\n /**\n * Send multiple messages at once\n */\n sendBatch?(messages: Array<{ body: T; options?: SendMessageOptions }>): Promise<BatchSendResult>;\n\n /**\n * Receive messages from the queue (pull-based)\n * Used for manual message processing\n */\n receive?(maxMessages?: number, visibilityTimeout?: number): Promise<QueueMessage<T>[]>;\n\n /**\n * Acknowledge message processing (mark as complete)\n */\n ack?(messageId: string): Promise<void>;\n\n /**\n * Acknowledge multiple messages\n */\n ackBatch?(messageIds: string[]): Promise<void>;\n\n /**\n * Return message to queue (negative acknowledgement)\n * Optionally with delay\n */\n nack?(messageId: string, delaySeconds?: number): Promise<void>;\n\n /**\n * Start consuming messages (push-based)\n * For adapters that support push-based processing\n */\n consume?(handler: MessageHandler<T>, options?: ConsumerOptions): Promise<void>;\n\n /**\n * Stop consuming messages\n */\n stopConsuming?(): Promise<void>;\n\n /**\n * Get queue statistics\n */\n getStats?(): Promise<QueueStats>;\n\n /**\n * Purge all messages from queue\n */\n purge?(): Promise<void>;\n\n /**\n * Close/cleanup adapter resources\n */\n close?(): Promise<void>;\n}\n\n/**\n * Queue statistics\n */\nexport interface QueueStats {\n /** Approximate number of messages in queue */\n messageCount: number;\n /** Messages currently being processed */\n inFlightCount?: number | undefined;\n /** Messages in dead-letter queue */\n deadLetterCount?: number | undefined;\n}\n\n/**\n * Queue service configuration\n */\nexport interface QueueServiceConfig<T = unknown> {\n /** Queue adapter to use */\n adapter: QueueAdapter<T>;\n /** Enable debug logging */\n debug?: boolean | undefined;\n}\n\n/**\n * Memory queue configuration\n */\nexport interface MemoryQueueConfig {\n /** Queue name */\n name: string;\n /** Maximum queue size (default: unlimited) */\n maxSize?: number | undefined;\n /** Default visibility timeout (seconds) */\n visibilityTimeout?: number | undefined;\n}\n\n/**\n * Cloudflare Queue configuration\n */\nexport interface CloudflareQueueConfig {\n /** Queue binding from environment */\n queue: CloudflareQueue;\n}\n\n/**\n * Cloudflare Queue interface (from Workers runtime)\n */\nexport interface CloudflareQueue<T = unknown> {\n send(message: T, options?: { delaySeconds?: number | undefined; contentType?: string | undefined }): Promise<void>;\n sendBatch(messages: Array<{ body: T; delaySeconds?: number | undefined; contentType?: string | undefined }>): Promise<void>;\n}\n\n/**\n * Cloudflare Queue batch\n */\nexport interface CloudflareMessageBatch<T = unknown> {\n readonly queue: string;\n readonly messages: Array<CloudflareMessage<T>>;\n ackAll(): void;\n retryAll(): void;\n}\n\n/**\n * Cloudflare Queue message\n */\nexport interface CloudflareMessage<T = unknown> {\n readonly id: string;\n readonly timestamp: Date;\n readonly body: T;\n readonly attempts: number;\n ack(): void;\n retry(): void;\n}\n\n/**\n * QStash configuration\n */\nexport interface QStashConfig {\n /** QStash token */\n token: string;\n /** Destination URL for message delivery */\n destinationUrl: string;\n /** Current request URL (for signature verification) */\n currentSigningKey?: string | undefined;\n /** Next signing key (for signature verification) */\n nextSigningKey?: string | undefined;\n}\n\n/**\n * Queue error\n */\nexport class QueueError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = \"QueueError\";\n }\n}\n\n/**\n * Common queue error codes\n */\nexport const QueueErrorCodes = {\n SEND_FAILED: \"SEND_FAILED\",\n RECEIVE_FAILED: \"RECEIVE_FAILED\",\n ACK_FAILED: \"ACK_FAILED\",\n INVALID_CONFIG: \"INVALID_CONFIG\",\n QUEUE_FULL: \"QUEUE_FULL\",\n MESSAGE_NOT_FOUND: \"MESSAGE_NOT_FOUND\",\n NOT_IMPLEMENTED: \"NOT_IMPLEMENTED\",\n} as const;\n","/**\n * @parsrun/queue - Memory Adapter\n * In-memory queue adapter for development and testing\n */\n\nimport type {\n BatchSendResult,\n ConsumerOptions,\n MemoryQueueConfig,\n MessageHandler,\n QueueAdapter,\n QueueMessage,\n QueueStats,\n SendMessageOptions,\n} from \"../types.js\";\nimport { QueueError, QueueErrorCodes } from \"../types.js\";\n\ninterface InternalMessage<T> {\n id: string;\n body: T;\n timestamp: Date;\n attempts: number;\n visibleAt: number;\n deduplicationId?: string | undefined;\n metadata?: Record<string, unknown> | undefined;\n}\n\n/**\n * Memory Queue Adapter\n * Uses in-memory storage for development and testing\n *\n * @example\n * ```typescript\n * const queue = new MemoryQueueAdapter<{ userId: string }>({\n * name: 'user-events',\n * });\n *\n * await queue.send({ userId: '123' });\n *\n * // Pull-based processing\n * const messages = await queue.receive(10);\n * for (const msg of messages) {\n * console.log(msg.body);\n * await queue.ack(msg.id);\n * }\n *\n * // Or push-based processing\n * await queue.consume(async (msg) => {\n * console.log(msg.body);\n * });\n * ```\n */\nexport class MemoryQueueAdapter<T = unknown> implements QueueAdapter<T> {\n readonly type = \"memory\" as const;\n readonly name: string;\n\n private messages: InternalMessage<T>[] = [];\n private inFlight = new Map<string, InternalMessage<T>>();\n private processedIds = new Set<string>();\n private maxSize: number;\n private visibilityTimeout: number;\n private messageCounter = 0;\n private isConsuming = false;\n private consumeInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor(config: MemoryQueueConfig) {\n this.name = config.name;\n this.maxSize = config.maxSize ?? Infinity;\n this.visibilityTimeout = config.visibilityTimeout ?? 30;\n }\n\n private generateId(): string {\n this.messageCounter++;\n return `msg-${Date.now()}-${this.messageCounter}`;\n }\n\n async send(body: T, options?: SendMessageOptions): Promise<string> {\n // Check max size\n if (this.messages.length >= this.maxSize) {\n throw new QueueError(\n `Queue ${this.name} is full`,\n QueueErrorCodes.QUEUE_FULL\n );\n }\n\n // Check deduplication\n if (options?.deduplicationId && this.processedIds.has(options.deduplicationId)) {\n // Return existing message ID for deduplicated messages\n return `dedup-${options.deduplicationId}`;\n }\n\n const id = this.generateId();\n const now = Date.now();\n const visibleAt = options?.delaySeconds\n ? now + options.delaySeconds * 1000\n : now;\n\n const message: InternalMessage<T> = {\n id,\n body,\n timestamp: new Date(),\n attempts: 0,\n visibleAt,\n deduplicationId: options?.deduplicationId,\n metadata: options?.metadata,\n };\n\n // Insert based on priority (higher priority = earlier in queue)\n if (options?.priority !== undefined && options.priority > 0) {\n // Find position for priority message\n const insertIndex = this.messages.findIndex(\n (m) => (m.metadata?.[\"priority\"] as number | undefined) ?? 0 < (options.priority ?? 0)\n );\n if (insertIndex === -1) {\n this.messages.push(message);\n } else {\n this.messages.splice(insertIndex, 0, message);\n }\n } else {\n this.messages.push(message);\n }\n\n if (options?.deduplicationId) {\n this.processedIds.add(options.deduplicationId);\n }\n\n return id;\n }\n\n async sendBatch(\n messages: Array<{ body: T; options?: SendMessageOptions }>\n ): Promise<BatchSendResult> {\n const messageIds: string[] = [];\n const errors: Array<{ index: number; error: string }> = [];\n let successful = 0;\n let failed = 0;\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (!msg) continue;\n\n try {\n const id = await this.send(msg.body, msg.options);\n messageIds.push(id);\n successful++;\n } catch (err) {\n failed++;\n errors.push({\n index: i,\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n }\n }\n\n return {\n total: messages.length,\n successful,\n failed,\n messageIds,\n errors,\n };\n }\n\n async receive(\n maxMessages = 10,\n visibilityTimeoutOverride?: number\n ): Promise<QueueMessage<T>[]> {\n const now = Date.now();\n const timeout = (visibilityTimeoutOverride ?? this.visibilityTimeout) * 1000;\n const result: QueueMessage<T>[] = [];\n\n // Find visible messages\n const visibleMessages: InternalMessage<T>[] = [];\n const remainingMessages: InternalMessage<T>[] = [];\n\n for (const msg of this.messages) {\n if (msg.visibleAt <= now && visibleMessages.length < maxMessages) {\n visibleMessages.push(msg);\n } else {\n remainingMessages.push(msg);\n }\n }\n\n this.messages = remainingMessages;\n\n // Move to in-flight and increment attempts\n for (const msg of visibleMessages) {\n msg.attempts++;\n msg.visibleAt = now + timeout;\n this.inFlight.set(msg.id, msg);\n\n result.push({\n id: msg.id,\n body: msg.body,\n timestamp: msg.timestamp,\n attempts: msg.attempts,\n metadata: msg.metadata,\n });\n }\n\n return result;\n }\n\n async ack(messageId: string): Promise<void> {\n const message = this.inFlight.get(messageId);\n if (!message) {\n throw new QueueError(\n `Message ${messageId} not found in flight`,\n QueueErrorCodes.MESSAGE_NOT_FOUND\n );\n }\n\n this.inFlight.delete(messageId);\n }\n\n async ackBatch(messageIds: string[]): Promise<void> {\n for (const id of messageIds) {\n this.inFlight.delete(id);\n }\n }\n\n async nack(messageId: string, delaySeconds?: number): Promise<void> {\n const message = this.inFlight.get(messageId);\n if (!message) {\n throw new QueueError(\n `Message ${messageId} not found in flight`,\n QueueErrorCodes.MESSAGE_NOT_FOUND\n );\n }\n\n this.inFlight.delete(messageId);\n\n // Return to queue with optional delay\n const now = Date.now();\n message.visibleAt = delaySeconds ? now + delaySeconds * 1000 : now;\n this.messages.push(message);\n }\n\n async consume(\n handler: MessageHandler<T>,\n options?: ConsumerOptions\n ): Promise<void> {\n if (this.isConsuming) {\n return;\n }\n\n this.isConsuming = true;\n const batchSize = options?.batchSize ?? 10;\n const pollingInterval = options?.pollingInterval ?? 1000;\n const visibilityTimeout = options?.visibilityTimeout ?? this.visibilityTimeout;\n const maxRetries = options?.maxRetries ?? 3;\n const concurrency = options?.concurrency ?? 1;\n\n const processMessages = async (): Promise<void> => {\n if (!this.isConsuming) return;\n\n const messages = await this.receive(batchSize, visibilityTimeout);\n\n // Process in batches based on concurrency\n for (let i = 0; i < messages.length; i += concurrency) {\n const batch = messages.slice(i, i + concurrency);\n await Promise.all(\n batch.map(async (msg) => {\n try {\n await handler(msg);\n await this.ack(msg.id);\n } catch (err) {\n // Check retry limit\n if (msg.attempts >= maxRetries) {\n // Dead letter - just remove from queue\n await this.ack(msg.id);\n console.error(\n `[Queue ${this.name}] Message ${msg.id} exceeded max retries, dropped`\n );\n } else {\n // Return to queue for retry\n await this.nack(msg.id, 5); // 5 second retry delay\n }\n }\n })\n );\n }\n };\n\n // Start polling\n this.consumeInterval = setInterval(processMessages, pollingInterval);\n\n // Process immediately\n await processMessages();\n }\n\n async stopConsuming(): Promise<void> {\n this.isConsuming = false;\n if (this.consumeInterval) {\n clearInterval(this.consumeInterval);\n this.consumeInterval = null;\n }\n }\n\n async getStats(): Promise<QueueStats> {\n // Return visibility timeout expired in-flight messages\n const now = Date.now();\n for (const [id, msg] of this.inFlight) {\n if (msg.visibleAt <= now) {\n this.inFlight.delete(id);\n this.messages.push(msg);\n }\n }\n\n return {\n messageCount: this.messages.length,\n inFlightCount: this.inFlight.size,\n };\n }\n\n async purge(): Promise<void> {\n this.messages = [];\n this.inFlight.clear();\n }\n\n async close(): Promise<void> {\n await this.stopConsuming();\n await this.purge();\n this.processedIds.clear();\n }\n}\n\n/**\n * Create a memory queue adapter\n */\nexport function createMemoryQueueAdapter<T = unknown>(\n config: MemoryQueueConfig\n): MemoryQueueAdapter<T> {\n return new MemoryQueueAdapter<T>(config);\n}\n","/**\n * @parsrun/queue - Cloudflare Queues Adapter\n * Adapter for Cloudflare Workers Queues\n */\n\nimport type {\n BatchSendResult,\n CloudflareMessage,\n CloudflareMessageBatch,\n CloudflareQueue,\n CloudflareQueueConfig,\n QueueAdapter,\n QueueMessage,\n SendMessageOptions,\n} from \"../types.js\";\nimport { QueueError, QueueErrorCodes } from \"../types.js\";\n\n/**\n * Cloudflare Queue Adapter\n * Uses Cloudflare Workers Queues for serverless message processing\n *\n * Cloudflare Queues uses a push-based model where messages are delivered\n * to queue consumers via Workers.\n *\n * @example\n * ```typescript\n * // In your Worker\n * export default {\n * async fetch(request, env) {\n * const queue = new CloudflareQueueAdapter({\n * queue: env.MY_QUEUE,\n * });\n *\n * await queue.send({ userId: '123', action: 'welcome-email' });\n * return new Response('Queued');\n * },\n *\n * async queue(batch, env) {\n * // Process messages delivered by Cloudflare\n * const processor = new CloudflareQueueProcessor();\n * await processor.processBatch(batch, async (msg) => {\n * console.log('Processing:', msg.body);\n * });\n * }\n * }\n * ```\n */\nexport class CloudflareQueueAdapter<T = unknown> implements QueueAdapter<T> {\n readonly type = \"cloudflare\" as const;\n readonly name = \"cloudflare-queue\";\n\n private queue: CloudflareQueue<T>;\n\n constructor(config: CloudflareQueueConfig) {\n this.queue = config.queue as CloudflareQueue<T>;\n }\n\n async send(body: T, options?: SendMessageOptions): Promise<string> {\n try {\n await this.queue.send(body, {\n delaySeconds: options?.delaySeconds,\n });\n\n // Cloudflare Queues don't return message IDs on send\n // Generate a client-side ID for tracking\n return `cf-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n } catch (err) {\n throw new QueueError(\n `Cloudflare Queue send failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n QueueErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n\n async sendBatch(\n messages: Array<{ body: T; options?: SendMessageOptions }>\n ): Promise<BatchSendResult> {\n try {\n const batchMessages = messages.map((m) => ({\n body: m.body,\n delaySeconds: m.options?.delaySeconds,\n }));\n\n await this.queue.sendBatch(batchMessages);\n\n // Generate client-side IDs\n const messageIds = messages.map(\n () => `cf-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`\n );\n\n return {\n total: messages.length,\n successful: messages.length,\n failed: 0,\n messageIds,\n errors: [],\n };\n } catch (err) {\n throw new QueueError(\n `Cloudflare Queue batch send failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n QueueErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n\n // Cloudflare Queues are push-based, so receive is not applicable\n // Messages are delivered to queue handlers via Workers\n}\n\n/**\n * Cloudflare Queue Processor\n * Helper for processing queue batches in Workers queue handlers\n *\n * @example\n * ```typescript\n * export default {\n * async queue(batch, env) {\n * const processor = new CloudflareQueueProcessor<MyMessageType>();\n * await processor.processBatch(batch, async (msg) => {\n * // Process each message\n * await handleMessage(msg.body);\n * });\n * }\n * }\n * ```\n */\nexport class CloudflareQueueProcessor<T = unknown> {\n /**\n * Process a batch of messages from Cloudflare Queues\n */\n async processBatch(\n batch: CloudflareMessageBatch<T>,\n handler: (message: QueueMessage<T>) => void | Promise<void>,\n options?: {\n /** Whether to ack all messages at once (default: false - ack individually) */\n ackAll?: boolean;\n /** Whether to retry all on any failure (default: false) */\n retryAllOnFailure?: boolean;\n }\n ): Promise<{ processed: number; failed: number }> {\n let processed = 0;\n let failed = 0;\n\n for (const msg of batch.messages) {\n try {\n const queueMessage: QueueMessage<T> = {\n id: msg.id,\n body: msg.body,\n timestamp: msg.timestamp,\n attempts: msg.attempts,\n };\n\n await handler(queueMessage);\n\n if (!options?.ackAll) {\n msg.ack();\n }\n processed++;\n } catch (err) {\n failed++;\n\n if (options?.retryAllOnFailure) {\n batch.retryAll();\n return { processed, failed: batch.messages.length };\n }\n\n // Retry individual message\n msg.retry();\n }\n }\n\n if (options?.ackAll && failed === 0) {\n batch.ackAll();\n }\n\n return { processed, failed };\n }\n\n /**\n * Convert a Cloudflare message to QueueMessage format\n */\n toQueueMessage(msg: CloudflareMessage<T>): QueueMessage<T> {\n return {\n id: msg.id,\n body: msg.body,\n timestamp: msg.timestamp,\n attempts: msg.attempts,\n };\n }\n}\n\n/**\n * Create a Cloudflare Queue adapter\n */\nexport function createCloudflareQueueAdapter<T = unknown>(\n config: CloudflareQueueConfig\n): CloudflareQueueAdapter<T> {\n return new CloudflareQueueAdapter<T>(config);\n}\n\n/**\n * Create a Cloudflare Queue processor\n */\nexport function createCloudflareQueueProcessor<T = unknown>(): CloudflareQueueProcessor<T> {\n return new CloudflareQueueProcessor<T>();\n}\n","/**\n * @parsrun/queue - QStash Adapter\n * Edge-compatible Upstash QStash adapter using fetch API\n */\n\nimport type {\n BatchSendResult,\n QStashConfig,\n QueueAdapter,\n QueueMessage,\n SendMessageOptions,\n} from \"../types.js\";\nimport { QueueError, QueueErrorCodes } from \"../types.js\";\n\n/**\n * QStash Queue Adapter\n * Edge-compatible using HTTP API\n *\n * QStash is a serverless message queue that delivers messages via HTTP webhooks.\n * Messages are sent to QStash which then delivers them to your endpoint.\n *\n * @example\n * ```typescript\n * const queue = new QStashAdapter({\n * token: process.env.QSTASH_TOKEN,\n * destinationUrl: 'https://myapp.com/api/webhooks/queue',\n * });\n *\n * await queue.send({ userId: '123', action: 'welcome-email' });\n * ```\n */\nexport class QStashAdapter<T = unknown> implements QueueAdapter<T> {\n readonly type = \"qstash\" as const;\n readonly name = \"qstash\";\n\n private token: string;\n private destinationUrl: string;\n private baseUrl = \"https://qstash.upstash.io/v2\";\n\n constructor(config: QStashConfig) {\n this.token = config.token;\n this.destinationUrl = config.destinationUrl;\n }\n\n async send(body: T, options?: SendMessageOptions): Promise<string> {\n try {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n };\n\n // Add delay\n if (options?.delaySeconds) {\n headers[\"Upstash-Delay\"] = `${options.delaySeconds}s`;\n }\n\n // Add deduplication\n if (options?.deduplicationId) {\n headers[\"Upstash-Deduplication-Id\"] = options.deduplicationId;\n }\n\n // Add custom headers from metadata\n if (options?.metadata) {\n for (const [key, value] of Object.entries(options.metadata)) {\n if (typeof value === \"string\") {\n headers[`Upstash-Forward-${key}`] = value;\n }\n }\n }\n\n const response = await fetch(\n `${this.baseUrl}/publish/${encodeURIComponent(this.destinationUrl)}`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n }\n );\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`QStash API error: ${error}`);\n }\n\n const result = await response.json() as { messageId: string };\n return result.messageId;\n } catch (err) {\n throw new QueueError(\n `QStash send failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n QueueErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n\n async sendBatch(\n messages: Array<{ body: T; options?: SendMessageOptions }>\n ): Promise<BatchSendResult> {\n try {\n const batchMessages = messages.map((m) => {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (m.options?.delaySeconds) {\n headers[\"Upstash-Delay\"] = `${m.options.delaySeconds}s`;\n }\n\n if (m.options?.deduplicationId) {\n headers[\"Upstash-Deduplication-Id\"] = m.options.deduplicationId;\n }\n\n return {\n destination: this.destinationUrl,\n headers,\n body: JSON.stringify(m.body),\n };\n });\n\n const response = await fetch(`${this.baseUrl}/batch`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(batchMessages),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`QStash API error: ${error}`);\n }\n\n const results = await response.json() as Array<{\n messageId?: string;\n error?: string;\n }>;\n\n const messageIds: string[] = [];\n const errors: Array<{ index: number; error: string }> = [];\n let successful = 0;\n let failed = 0;\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (result?.messageId) {\n messageIds.push(result.messageId);\n successful++;\n } else {\n failed++;\n errors.push({\n index: i,\n error: result?.error ?? \"Unknown error\",\n });\n }\n }\n\n return {\n total: messages.length,\n successful,\n failed,\n messageIds,\n errors,\n };\n } catch (err) {\n throw new QueueError(\n `QStash batch send failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n QueueErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n\n /**\n * Schedule a message for future delivery\n */\n async schedule(\n body: T,\n cronExpression: string,\n options?: Omit<SendMessageOptions, \"delaySeconds\">\n ): Promise<string> {\n try {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n \"Upstash-Cron\": cronExpression,\n };\n\n if (options?.deduplicationId) {\n headers[\"Upstash-Deduplication-Id\"] = options.deduplicationId;\n }\n\n const response = await fetch(\n `${this.baseUrl}/schedules/${encodeURIComponent(this.destinationUrl)}`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n }\n );\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`QStash API error: ${error}`);\n }\n\n const result = await response.json() as { scheduleId: string };\n return result.scheduleId;\n } catch (err) {\n throw new QueueError(\n `QStash schedule failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n QueueErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n\n /**\n * Delete a scheduled message\n */\n async deleteSchedule(scheduleId: string): Promise<void> {\n try {\n const response = await fetch(`${this.baseUrl}/schedules/${scheduleId}`, {\n method: \"DELETE\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`QStash API error: ${error}`);\n }\n } catch (err) {\n throw new QueueError(\n `QStash delete schedule failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n QueueErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n\n /**\n * List all schedules\n */\n async listSchedules(): Promise<\n Array<{\n scheduleId: string;\n cron: string;\n destination: string;\n body?: string;\n createdAt: number;\n }>\n > {\n try {\n const response = await fetch(`${this.baseUrl}/schedules`, {\n headers: {\n Authorization: `Bearer ${this.token}`,\n },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`QStash API error: ${error}`);\n }\n\n return await response.json() as Array<{\n scheduleId: string;\n cron: string;\n destination: string;\n body?: string;\n createdAt: number;\n }>;\n } catch (err) {\n throw new QueueError(\n `QStash list schedules failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n QueueErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n}\n\n/**\n * QStash Message Receiver\n * Helper for receiving and verifying messages in your webhook endpoint\n *\n * @example\n * ```typescript\n * // In your API route\n * const receiver = new QStashReceiver({\n * currentSigningKey: process.env.QSTASH_CURRENT_SIGNING_KEY,\n * nextSigningKey: process.env.QSTASH_NEXT_SIGNING_KEY,\n * });\n *\n * export async function POST(request: Request) {\n * const message = await receiver.verify(request);\n * if (!message) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * // Process the message\n * console.log(message.body);\n * return new Response('OK');\n * }\n * ```\n */\nexport class QStashReceiver<T = unknown> {\n private currentSigningKey: string;\n private nextSigningKey: string;\n\n constructor(config: { currentSigningKey: string; nextSigningKey: string }) {\n this.currentSigningKey = config.currentSigningKey;\n this.nextSigningKey = config.nextSigningKey;\n }\n\n /**\n * Verify a request from QStash and extract the message\n */\n async verify(request: Request): Promise<QueueMessage<T> | null> {\n const signature = request.headers.get(\"Upstash-Signature\");\n\n if (!signature) {\n return null;\n }\n\n const body = await request.text();\n\n // Try current key first, then next key\n const isValid =\n (await this.verifySignature(body, signature, this.currentSigningKey)) ||\n (await this.verifySignature(body, signature, this.nextSigningKey));\n\n if (!isValid) {\n return null;\n }\n\n const messageId = request.headers.get(\"Upstash-Message-Id\") ?? `qstash-${Date.now()}`;\n const retryCount = parseInt(\n request.headers.get(\"Upstash-Retried\") ?? \"0\",\n 10\n );\n\n let parsedBody: T;\n try {\n parsedBody = JSON.parse(body) as T;\n } catch {\n parsedBody = body as T;\n }\n\n return {\n id: messageId,\n body: parsedBody,\n timestamp: new Date(),\n attempts: retryCount + 1,\n };\n }\n\n private async verifySignature(\n body: string,\n signature: string,\n key: string\n ): Promise<boolean> {\n try {\n // Parse JWT-like signature\n const parts = signature.split(\".\");\n if (parts.length !== 3) {\n return false;\n }\n\n const [headerB64, payloadB64, signatureB64] = parts;\n if (!headerB64 || !payloadB64 || !signatureB64) {\n return false;\n }\n\n // Verify signature using Web Crypto API\n const encoder = new TextEncoder();\n const keyData = encoder.encode(key);\n\n const cryptoKey = await crypto.subtle.importKey(\n \"raw\",\n keyData,\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"verify\"]\n );\n\n const signatureData = this.base64UrlDecode(signatureB64);\n const dataToVerify = encoder.encode(`${headerB64}.${payloadB64}`);\n\n const isValid = await crypto.subtle.verify(\n \"HMAC\",\n cryptoKey,\n signatureData,\n dataToVerify\n );\n\n if (!isValid) {\n return false;\n }\n\n // Verify payload contains correct body hash\n const payload = JSON.parse(atob(payloadB64)) as {\n body?: string;\n iss?: string;\n sub?: string;\n exp?: number;\n nbf?: number;\n iat?: number;\n };\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (payload.exp && payload.exp < now) {\n return false;\n }\n\n // Check not before\n if (payload.nbf && payload.nbf > now) {\n return false;\n }\n\n // Verify body hash\n if (payload.body) {\n const bodyHash = await this.sha256(body);\n const expectedHash = this.base64UrlEncode(\n new Uint8Array(\n atob(payload.body)\n .split(\"\")\n .map((c) => c.charCodeAt(0))\n )\n );\n\n if (bodyHash !== expectedHash && payload.body !== bodyHash) {\n // Also try direct comparison\n const directHash = await this.sha256Base64(body);\n if (directHash !== payload.body) {\n return false;\n }\n }\n }\n\n return true;\n } catch {\n return false;\n }\n }\n\n private base64UrlDecode(str: string): Uint8Array {\n const base64 = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padding = (4 - (base64.length % 4)) % 4;\n const padded = base64 + \"=\".repeat(padding);\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n\n private base64UrlEncode(data: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < data.length; i++) {\n const byte = data[i];\n if (byte !== undefined) {\n binary += String.fromCharCode(byte);\n }\n }\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n }\n\n private async sha256(message: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(message);\n const hash = await crypto.subtle.digest(\"SHA-256\", data);\n return this.base64UrlEncode(new Uint8Array(hash));\n }\n\n private async sha256Base64(message: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(message);\n const hash = await crypto.subtle.digest(\"SHA-256\", data);\n let binary = \"\";\n const bytes = new Uint8Array(hash);\n for (let i = 0; i < bytes.length; i++) {\n const byte = bytes[i];\n if (byte !== undefined) {\n binary += String.fromCharCode(byte);\n }\n }\n return btoa(binary);\n }\n}\n\n/**\n * Create a QStash queue adapter\n */\nexport function createQStashAdapter<T = unknown>(\n config: QStashConfig\n): QStashAdapter<T> {\n return new QStashAdapter<T>(config);\n}\n\n/**\n * Create a QStash receiver for webhook verification\n */\nexport function createQStashReceiver<T = unknown>(config: {\n currentSigningKey: string;\n nextSigningKey: string;\n}): QStashReceiver<T> {\n return new QStashReceiver<T>(config);\n}\n","/**\n * @parsrun/queue\n * Edge-compatible message queues for Pars\n *\n * Supports multiple adapters:\n * - Memory (development)\n * - Cloudflare Queues (Workers)\n * - Upstash QStash (Edge/Serverless)\n *\n * @example\n * ```typescript\n * import { createQueueService, createMemoryQueueAdapter } from '@parsrun/queue';\n *\n * const queue = createQueueService({\n * adapter: createMemoryQueueAdapter({ name: 'tasks' }),\n * });\n *\n * await queue.send({ userId: '123', action: 'send-email' });\n * ```\n */\n\n// Re-export types\nexport * from \"./types.js\";\n\n// Re-export adapters\nexport {\n MemoryQueueAdapter,\n createMemoryQueueAdapter,\n} from \"./adapters/memory.js\";\n\nexport {\n CloudflareQueueAdapter,\n CloudflareQueueProcessor,\n createCloudflareQueueAdapter,\n createCloudflareQueueProcessor,\n} from \"./adapters/cloudflare.js\";\n\nexport {\n QStashAdapter,\n QStashReceiver,\n createQStashAdapter,\n createQStashReceiver,\n} from \"./adapters/qstash.js\";\n\nimport type {\n BatchSendResult,\n ConsumerOptions,\n MessageHandler,\n QueueAdapter,\n QueueMessage,\n QueueServiceConfig,\n QueueStats,\n SendMessageOptions,\n} from \"./types.js\";\n\n/**\n * Queue Service\n * High-level queue service with adapter abstraction\n */\nexport class QueueService<T = unknown> {\n private adapter: QueueAdapter<T>;\n private debug: boolean;\n\n constructor(config: QueueServiceConfig<T>) {\n this.adapter = config.adapter;\n this.debug = config.debug ?? false;\n }\n\n /**\n * Get adapter type\n */\n get adapterType(): string {\n return this.adapter.type;\n }\n\n /**\n * Get queue name\n */\n get name(): string {\n return this.adapter.name;\n }\n\n /**\n * Send a message to the queue\n */\n async send(body: T, options?: SendMessageOptions): Promise<string> {\n if (this.debug) {\n console.log(`[Queue ${this.name}] Sending message:`, body);\n }\n\n const messageId = await this.adapter.send(body, options);\n\n if (this.debug) {\n console.log(`[Queue ${this.name}] Message sent: ${messageId}`);\n }\n\n return messageId;\n }\n\n /**\n * Send multiple messages at once\n */\n async sendBatch(\n messages: Array<{ body: T; options?: SendMessageOptions }>\n ): Promise<BatchSendResult> {\n if (this.debug) {\n console.log(`[Queue ${this.name}] Sending batch of ${messages.length} messages`);\n }\n\n if (this.adapter.sendBatch) {\n return this.adapter.sendBatch(messages);\n }\n\n // Fallback to sequential sends\n const messageIds: string[] = [];\n const errors: Array<{ index: number; error: string }> = [];\n let successful = 0;\n let failed = 0;\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (!msg) continue;\n\n try {\n const id = await this.send(msg.body, msg.options);\n messageIds.push(id);\n successful++;\n } catch (err) {\n failed++;\n errors.push({\n index: i,\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n }\n }\n\n return {\n total: messages.length,\n successful,\n failed,\n messageIds,\n errors,\n };\n }\n\n /**\n * Receive messages from the queue (pull-based)\n */\n async receive(\n maxMessages?: number,\n visibilityTimeout?: number\n ): Promise<QueueMessage<T>[]> {\n if (!this.adapter.receive) {\n throw new Error(`${this.adapter.type} adapter does not support receive()`);\n }\n\n return this.adapter.receive(maxMessages, visibilityTimeout);\n }\n\n /**\n * Acknowledge message processing (mark as complete)\n */\n async ack(messageId: string): Promise<void> {\n if (!this.adapter.ack) {\n throw new Error(`${this.adapter.type} adapter does not support ack()`);\n }\n\n await this.adapter.ack(messageId);\n }\n\n /**\n * Acknowledge multiple messages\n */\n async ackBatch(messageIds: string[]): Promise<void> {\n if (this.adapter.ackBatch) {\n await this.adapter.ackBatch(messageIds);\n return;\n }\n\n if (this.adapter.ack) {\n await Promise.all(messageIds.map((id) => this.adapter.ack!(id)));\n return;\n }\n\n throw new Error(`${this.adapter.type} adapter does not support ack()`);\n }\n\n /**\n * Return message to queue (negative acknowledgement)\n */\n async nack(messageId: string, delaySeconds?: number): Promise<void> {\n if (!this.adapter.nack) {\n throw new Error(`${this.adapter.type} adapter does not support nack()`);\n }\n\n await this.adapter.nack(messageId, delaySeconds);\n }\n\n /**\n * Start consuming messages (push-based)\n */\n async consume(\n handler: MessageHandler<T>,\n options?: ConsumerOptions\n ): Promise<void> {\n if (!this.adapter.consume) {\n throw new Error(`${this.adapter.type} adapter does not support consume()`);\n }\n\n if (this.debug) {\n console.log(`[Queue ${this.name}] Starting consumer`);\n }\n\n await this.adapter.consume(handler, options);\n }\n\n /**\n * Stop consuming messages\n */\n async stopConsuming(): Promise<void> {\n if (this.adapter.stopConsuming) {\n await this.adapter.stopConsuming();\n }\n }\n\n /**\n * Get queue statistics\n */\n async getStats(): Promise<QueueStats> {\n if (this.adapter.getStats) {\n return this.adapter.getStats();\n }\n\n return { messageCount: -1 };\n }\n\n /**\n * Purge all messages from queue\n */\n async purge(): Promise<void> {\n if (this.adapter.purge) {\n await this.adapter.purge();\n }\n }\n\n /**\n * Close/cleanup queue resources\n */\n async close(): Promise<void> {\n if (this.adapter.close) {\n await this.adapter.close();\n }\n }\n}\n\n/**\n * Create a queue service\n *\n * @example\n * ```typescript\n * // With Memory (development)\n * const queue = createQueueService({\n * adapter: createMemoryQueueAdapter({ name: 'tasks' }),\n * });\n *\n * // With Cloudflare Queues (Workers)\n * const queue = createQueueService({\n * adapter: createCloudflareQueueAdapter({ queue: env.MY_QUEUE }),\n * });\n *\n * // With QStash (Edge)\n * const queue = createQueueService({\n * adapter: createQStashAdapter({\n * token: process.env.QSTASH_TOKEN,\n * destinationUrl: 'https://myapp.com/api/queue',\n * }),\n * });\n * ```\n */\nexport function createQueueService<T = unknown>(\n config: QueueServiceConfig<T>\n): QueueService<T> {\n return new QueueService<T>(config);\n}\n\n// Default export\nexport default {\n QueueService,\n createQueueService,\n};\n"],"mappings":";AAMA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAWK;AA8OA,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACE,SACgB,MACA,OAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,kBAAkB;AAAA,EAC7B,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,mBAAmB;AAAA,EACnB,iBAAiB;AACnB;;;AC5OO,IAAM,qBAAN,MAAiE;AAAA,EAC7D,OAAO;AAAA,EACP;AAAA,EAED,WAAiC,CAAC;AAAA,EAClC,WAAW,oBAAI,IAAgC;AAAA,EAC/C,eAAe,oBAAI,IAAY;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,kBAAyD;AAAA,EAEjE,YAAY,QAA2B;AACrC,SAAK,OAAO,OAAO;AACnB,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,oBAAoB,OAAO,qBAAqB;AAAA,EACvD;AAAA,EAEQ,aAAqB;AAC3B,SAAK;AACL,WAAO,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,cAAc;AAAA,EACjD;AAAA,EAEA,MAAM,KAAK,MAAS,SAA+C;AAEjE,QAAI,KAAK,SAAS,UAAU,KAAK,SAAS;AACxC,YAAM,IAAI;AAAA,QACR,SAAS,KAAK,IAAI;AAAA,QAClB,gBAAgB;AAAA,MAClB;AAAA,IACF;AAGA,QAAI,SAAS,mBAAmB,KAAK,aAAa,IAAI,QAAQ,eAAe,GAAG;AAE9E,aAAO,SAAS,QAAQ,eAAe;AAAA,IACzC;AAEA,UAAM,KAAK,KAAK,WAAW;AAC3B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,YAAY,SAAS,eACvB,MAAM,QAAQ,eAAe,MAC7B;AAEJ,UAAM,UAA8B;AAAA,MAClC;AAAA,MACA;AAAA,MACA,WAAW,oBAAI,KAAK;AAAA,MACpB,UAAU;AAAA,MACV;AAAA,MACA,iBAAiB,SAAS;AAAA,MAC1B,UAAU,SAAS;AAAA,IACrB;AAGA,QAAI,SAAS,aAAa,UAAa,QAAQ,WAAW,GAAG;AAE3D,YAAM,cAAc,KAAK,SAAS;AAAA,QAChC,CAAC,MAAO,EAAE,WAAW,UAAU,KAA4B,KAAK,QAAQ,YAAY;AAAA,MACtF;AACA,UAAI,gBAAgB,IAAI;AACtB,aAAK,SAAS,KAAK,OAAO;AAAA,MAC5B,OAAO;AACL,aAAK,SAAS,OAAO,aAAa,GAAG,OAAO;AAAA,MAC9C;AAAA,IACF,OAAO;AACL,WAAK,SAAS,KAAK,OAAO;AAAA,IAC5B;AAEA,QAAI,SAAS,iBAAiB;AAC5B,WAAK,aAAa,IAAI,QAAQ,eAAe;AAAA,IAC/C;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UACJ,UAC0B;AAC1B,UAAM,aAAuB,CAAC;AAC9B,UAAM,SAAkD,CAAC;AACzD,QAAI,aAAa;AACjB,QAAI,SAAS;AAEb,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,MAAM,SAAS,CAAC;AACtB,UAAI,CAAC,IAAK;AAEV,UAAI;AACF,cAAM,KAAK,MAAM,KAAK,KAAK,IAAI,MAAM,IAAI,OAAO;AAChD,mBAAW,KAAK,EAAE;AAClB;AAAA,MACF,SAAS,KAAK;AACZ;AACA,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,OAAO,eAAe,QAAQ,IAAI,UAAU;AAAA,QAC9C,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO,SAAS;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QACJ,cAAc,IACd,2BAC4B;AAC5B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,WAAW,6BAA6B,KAAK,qBAAqB;AACxE,UAAM,SAA4B,CAAC;AAGnC,UAAM,kBAAwC,CAAC;AAC/C,UAAM,oBAA0C,CAAC;AAEjD,eAAW,OAAO,KAAK,UAAU;AAC/B,UAAI,IAAI,aAAa,OAAO,gBAAgB,SAAS,aAAa;AAChE,wBAAgB,KAAK,GAAG;AAAA,MAC1B,OAAO;AACL,0BAAkB,KAAK,GAAG;AAAA,MAC5B;AAAA,IACF;AAEA,SAAK,WAAW;AAGhB,eAAW,OAAO,iBAAiB;AACjC,UAAI;AACJ,UAAI,YAAY,MAAM;AACtB,WAAK,SAAS,IAAI,IAAI,IAAI,GAAG;AAE7B,aAAO,KAAK;AAAA,QACV,IAAI,IAAI;AAAA,QACR,MAAM,IAAI;AAAA,QACV,WAAW,IAAI;AAAA,QACf,UAAU,IAAI;AAAA,QACd,UAAU,IAAI;AAAA,MAChB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,IAAI,WAAkC;AAC1C,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR,WAAW,SAAS;AAAA,QACpB,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,SAAK,SAAS,OAAO,SAAS;AAAA,EAChC;AAAA,EAEA,MAAM,SAAS,YAAqC;AAClD,eAAW,MAAM,YAAY;AAC3B,WAAK,SAAS,OAAO,EAAE;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,WAAmB,cAAsC;AAClE,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR,WAAW,SAAS;AAAA,QACpB,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,SAAK,SAAS,OAAO,SAAS;AAG9B,UAAM,MAAM,KAAK,IAAI;AACrB,YAAQ,YAAY,eAAe,MAAM,eAAe,MAAO;AAC/D,SAAK,SAAS,KAAK,OAAO;AAAA,EAC5B;AAAA,EAEA,MAAM,QACJ,SACA,SACe;AACf,QAAI,KAAK,aAAa;AACpB;AAAA,IACF;AAEA,SAAK,cAAc;AACnB,UAAM,YAAY,SAAS,aAAa;AACxC,UAAM,kBAAkB,SAAS,mBAAmB;AACpD,UAAM,oBAAoB,SAAS,qBAAqB,KAAK;AAC7D,UAAM,aAAa,SAAS,cAAc;AAC1C,UAAM,cAAc,SAAS,eAAe;AAE5C,UAAM,kBAAkB,YAA2B;AACjD,UAAI,CAAC,KAAK,YAAa;AAEvB,YAAM,WAAW,MAAM,KAAK,QAAQ,WAAW,iBAAiB;AAGhE,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,aAAa;AACrD,cAAM,QAAQ,SAAS,MAAM,GAAG,IAAI,WAAW;AAC/C,cAAM,QAAQ;AAAA,UACZ,MAAM,IAAI,OAAO,QAAQ;AACvB,gBAAI;AACF,oBAAM,QAAQ,GAAG;AACjB,oBAAM,KAAK,IAAI,IAAI,EAAE;AAAA,YACvB,SAAS,KAAK;AAEZ,kBAAI,IAAI,YAAY,YAAY;AAE9B,sBAAM,KAAK,IAAI,IAAI,EAAE;AACrB,wBAAQ;AAAA,kBACN,UAAU,KAAK,IAAI,aAAa,IAAI,EAAE;AAAA,gBACxC;AAAA,cACF,OAAO;AAEL,sBAAM,KAAK,KAAK,IAAI,IAAI,CAAC;AAAA,cAC3B;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,SAAK,kBAAkB,YAAY,iBAAiB,eAAe;AAGnE,UAAM,gBAAgB;AAAA,EACxB;AAAA,EAEA,MAAM,gBAA+B;AACnC,SAAK,cAAc;AACnB,QAAI,KAAK,iBAAiB;AACxB,oBAAc,KAAK,eAAe;AAClC,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAM,WAAgC;AAEpC,UAAM,MAAM,KAAK,IAAI;AACrB,eAAW,CAAC,IAAI,GAAG,KAAK,KAAK,UAAU;AACrC,UAAI,IAAI,aAAa,KAAK;AACxB,aAAK,SAAS,OAAO,EAAE;AACvB,aAAK,SAAS,KAAK,GAAG;AAAA,MACxB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,cAAc,KAAK,SAAS;AAAA,MAC5B,eAAe,KAAK,SAAS;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,WAAW,CAAC;AACjB,SAAK,SAAS,MAAM;AAAA,EACtB;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,cAAc;AACzB,UAAM,KAAK,MAAM;AACjB,SAAK,aAAa,MAAM;AAAA,EAC1B;AACF;AAKO,SAAS,yBACd,QACuB;AACvB,SAAO,IAAI,mBAAsB,MAAM;AACzC;;;AC/RO,IAAM,yBAAN,MAAqE;AAAA,EACjE,OAAO;AAAA,EACP,OAAO;AAAA,EAER;AAAA,EAER,YAAY,QAA+B;AACzC,SAAK,QAAQ,OAAO;AAAA,EACtB;AAAA,EAEA,MAAM,KAAK,MAAS,SAA+C;AACjE,QAAI;AACF,YAAM,KAAK,MAAM,KAAK,MAAM;AAAA,QAC1B,cAAc,SAAS;AAAA,MACzB,CAAC;AAID,aAAO,MAAM,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA,IACvE,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,iCAAiC,eAAe,QAAQ,IAAI,UAAU,eAAe;AAAA,QACrF,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UACJ,UAC0B;AAC1B,QAAI;AACF,YAAM,gBAAgB,SAAS,IAAI,CAAC,OAAO;AAAA,QACzC,MAAM,EAAE;AAAA,QACR,cAAc,EAAE,SAAS;AAAA,MAC3B,EAAE;AAEF,YAAM,KAAK,MAAM,UAAU,aAAa;AAGxC,YAAM,aAAa,SAAS;AAAA,QAC1B,MAAM,MAAM,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA,MACtE;AAEA,aAAO;AAAA,QACL,OAAO,SAAS;AAAA,QAChB,YAAY,SAAS;AAAA,QACrB,QAAQ;AAAA,QACR;AAAA,QACA,QAAQ,CAAC;AAAA,MACX;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,uCAAuC,eAAe,QAAQ,IAAI,UAAU,eAAe;AAAA,QAC3F,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAIF;AAmBO,IAAM,2BAAN,MAA4C;AAAA;AAAA;AAAA;AAAA,EAIjD,MAAM,aACJ,OACA,SACA,SAMgD;AAChD,QAAI,YAAY;AAChB,QAAI,SAAS;AAEb,eAAW,OAAO,MAAM,UAAU;AAChC,UAAI;AACF,cAAM,eAAgC;AAAA,UACpC,IAAI,IAAI;AAAA,UACR,MAAM,IAAI;AAAA,UACV,WAAW,IAAI;AAAA,UACf,UAAU,IAAI;AAAA,QAChB;AAEA,cAAM,QAAQ,YAAY;AAE1B,YAAI,CAAC,SAAS,QAAQ;AACpB,cAAI,IAAI;AAAA,QACV;AACA;AAAA,MACF,SAAS,KAAK;AACZ;AAEA,YAAI,SAAS,mBAAmB;AAC9B,gBAAM,SAAS;AACf,iBAAO,EAAE,WAAW,QAAQ,MAAM,SAAS,OAAO;AAAA,QACpD;AAGA,YAAI,MAAM;AAAA,MACZ;AAAA,IACF;AAEA,QAAI,SAAS,UAAU,WAAW,GAAG;AACnC,YAAM,OAAO;AAAA,IACf;AAEA,WAAO,EAAE,WAAW,OAAO;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,KAA4C;AACzD,WAAO;AAAA,MACL,IAAI,IAAI;AAAA,MACR,MAAM,IAAI;AAAA,MACV,WAAW,IAAI;AAAA,MACf,UAAU,IAAI;AAAA,IAChB;AAAA,EACF;AACF;AAKO,SAAS,6BACd,QAC2B;AAC3B,SAAO,IAAI,uBAA0B,MAAM;AAC7C;AAKO,SAAS,iCAA2E;AACzF,SAAO,IAAI,yBAA4B;AACzC;;;AChLO,IAAM,gBAAN,MAA4D;AAAA,EACxD,OAAO;AAAA,EACP,OAAO;AAAA,EAER;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EAElB,YAAY,QAAsB;AAChC,SAAK,QAAQ,OAAO;AACpB,SAAK,iBAAiB,OAAO;AAAA,EAC/B;AAAA,EAEA,MAAM,KAAK,MAAS,SAA+C;AACjE,QAAI;AACF,YAAM,UAAkC;AAAA,QACtC,eAAe,UAAU,KAAK,KAAK;AAAA,QACnC,gBAAgB;AAAA,MAClB;AAGA,UAAI,SAAS,cAAc;AACzB,gBAAQ,eAAe,IAAI,GAAG,QAAQ,YAAY;AAAA,MACpD;AAGA,UAAI,SAAS,iBAAiB;AAC5B,gBAAQ,0BAA0B,IAAI,QAAQ;AAAA,MAChD;AAGA,UAAI,SAAS,UAAU;AACrB,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,QAAQ,GAAG;AAC3D,cAAI,OAAO,UAAU,UAAU;AAC7B,oBAAQ,mBAAmB,GAAG,EAAE,IAAI;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AAEA,YAAM,WAAW,MAAM;AAAA,QACrB,GAAG,KAAK,OAAO,YAAY,mBAAmB,KAAK,cAAc,CAAC;AAAA,QAClE;AAAA,UACE,QAAQ;AAAA,UACR;AAAA,UACA,MAAM,KAAK,UAAU,IAAI;AAAA,QAC3B;AAAA,MACF;AAEA,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,cAAM,IAAI,MAAM,qBAAqB,KAAK,EAAE;AAAA,MAC9C;AAEA,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,aAAO,OAAO;AAAA,IAChB,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,uBAAuB,eAAe,QAAQ,IAAI,UAAU,eAAe;AAAA,QAC3E,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UACJ,UAC0B;AAC1B,QAAI;AACF,YAAM,gBAAgB,SAAS,IAAI,CAAC,MAAM;AACxC,cAAM,UAAkC;AAAA,UACtC,gBAAgB;AAAA,QAClB;AAEA,YAAI,EAAE,SAAS,cAAc;AAC3B,kBAAQ,eAAe,IAAI,GAAG,EAAE,QAAQ,YAAY;AAAA,QACtD;AAEA,YAAI,EAAE,SAAS,iBAAiB;AAC9B,kBAAQ,0BAA0B,IAAI,EAAE,QAAQ;AAAA,QAClD;AAEA,eAAO;AAAA,UACL,aAAa,KAAK;AAAA,UAClB;AAAA,UACA,MAAM,KAAK,UAAU,EAAE,IAAI;AAAA,QAC7B;AAAA,MACF,CAAC;AAED,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,UAAU;AAAA,QACpD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,KAAK;AAAA,UACnC,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,aAAa;AAAA,MACpC,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,cAAM,IAAI,MAAM,qBAAqB,KAAK,EAAE;AAAA,MAC9C;AAEA,YAAM,UAAU,MAAM,SAAS,KAAK;AAKpC,YAAM,aAAuB,CAAC;AAC9B,YAAM,SAAkD,CAAC;AACzD,UAAI,aAAa;AACjB,UAAI,SAAS;AAEb,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,cAAM,SAAS,QAAQ,CAAC;AACxB,YAAI,QAAQ,WAAW;AACrB,qBAAW,KAAK,OAAO,SAAS;AAChC;AAAA,QACF,OAAO;AACL;AACA,iBAAO,KAAK;AAAA,YACV,OAAO;AAAA,YACP,OAAO,QAAQ,SAAS;AAAA,UAC1B,CAAC;AAAA,QACH;AAAA,MACF;AAEA,aAAO;AAAA,QACL,OAAO,SAAS;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,6BAA6B,eAAe,QAAQ,IAAI,UAAU,eAAe;AAAA,QACjF,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SACJ,MACA,gBACA,SACiB;AACjB,QAAI;AACF,YAAM,UAAkC;AAAA,QACtC,eAAe,UAAU,KAAK,KAAK;AAAA,QACnC,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,MAClB;AAEA,UAAI,SAAS,iBAAiB;AAC5B,gBAAQ,0BAA0B,IAAI,QAAQ;AAAA,MAChD;AAEA,YAAM,WAAW,MAAM;AAAA,QACrB,GAAG,KAAK,OAAO,cAAc,mBAAmB,KAAK,cAAc,CAAC;AAAA,QACpE;AAAA,UACE,QAAQ;AAAA,UACR;AAAA,UACA,MAAM,KAAK,UAAU,IAAI;AAAA,QAC3B;AAAA,MACF;AAEA,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,cAAM,IAAI,MAAM,qBAAqB,KAAK,EAAE;AAAA,MAC9C;AAEA,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,aAAO,OAAO;AAAA,IAChB,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,2BAA2B,eAAe,QAAQ,IAAI,UAAU,eAAe;AAAA,QAC/E,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,YAAmC;AACtD,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,cAAc,UAAU,IAAI;AAAA,QACtE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,KAAK;AAAA,QACrC;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,cAAM,IAAI,MAAM,qBAAqB,KAAK,EAAE;AAAA,MAC9C;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,kCAAkC,eAAe,QAAQ,IAAI,UAAU,eAAe;AAAA,QACtF,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAQJ;AACA,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,cAAc;AAAA,QACxD,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,KAAK;AAAA,QACrC;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,cAAM,IAAI,MAAM,qBAAqB,KAAK,EAAE;AAAA,MAC9C;AAEA,aAAO,MAAM,SAAS,KAAK;AAAA,IAO7B,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,iCAAiC,eAAe,QAAQ,IAAI,UAAU,eAAe;AAAA,QACrF,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AA0BO,IAAM,iBAAN,MAAkC;AAAA,EAC/B;AAAA,EACA;AAAA,EAER,YAAY,QAA+D;AACzE,SAAK,oBAAoB,OAAO;AAChC,SAAK,iBAAiB,OAAO;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,SAAmD;AAC9D,UAAM,YAAY,QAAQ,QAAQ,IAAI,mBAAmB;AAEzD,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,MAAM,QAAQ,KAAK;AAGhC,UAAM,UACH,MAAM,KAAK,gBAAgB,MAAM,WAAW,KAAK,iBAAiB,KAClE,MAAM,KAAK,gBAAgB,MAAM,WAAW,KAAK,cAAc;AAElE,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,QAAQ,QAAQ,IAAI,oBAAoB,KAAK,UAAU,KAAK,IAAI,CAAC;AACnF,UAAM,aAAa;AAAA,MACjB,QAAQ,QAAQ,IAAI,iBAAiB,KAAK;AAAA,MAC1C;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,mBAAa,KAAK,MAAM,IAAI;AAAA,IAC9B,QAAQ;AACN,mBAAa;AAAA,IACf;AAEA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,WAAW,oBAAI,KAAK;AAAA,MACpB,UAAU,aAAa;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAc,gBACZ,MACA,WACA,KACkB;AAClB,QAAI;AAEF,YAAM,QAAQ,UAAU,MAAM,GAAG;AACjC,UAAI,MAAM,WAAW,GAAG;AACtB,eAAO;AAAA,MACT;AAEA,YAAM,CAAC,WAAW,YAAY,YAAY,IAAI;AAC9C,UAAI,CAAC,aAAa,CAAC,cAAc,CAAC,cAAc;AAC9C,eAAO;AAAA,MACT;AAGA,YAAM,UAAU,IAAI,YAAY;AAChC,YAAM,UAAU,QAAQ,OAAO,GAAG;AAElC,YAAM,YAAY,MAAM,OAAO,OAAO;AAAA,QACpC;AAAA,QACA;AAAA,QACA,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,QAChC;AAAA,QACA,CAAC,QAAQ;AAAA,MACX;AAEA,YAAM,gBAAgB,KAAK,gBAAgB,YAAY;AACvD,YAAM,eAAe,QAAQ,OAAO,GAAG,SAAS,IAAI,UAAU,EAAE;AAEhE,YAAM,UAAU,MAAM,OAAO,OAAO;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,UAAI,CAAC,SAAS;AACZ,eAAO;AAAA,MACT;AAGA,YAAM,UAAU,KAAK,MAAM,KAAK,UAAU,CAAC;AAU3C,YAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,UAAI,QAAQ,OAAO,QAAQ,MAAM,KAAK;AACpC,eAAO;AAAA,MACT;AAGA,UAAI,QAAQ,OAAO,QAAQ,MAAM,KAAK;AACpC,eAAO;AAAA,MACT;AAGA,UAAI,QAAQ,MAAM;AAChB,cAAM,WAAW,MAAM,KAAK,OAAO,IAAI;AACvC,cAAM,eAAe,KAAK;AAAA,UACxB,IAAI;AAAA,YACF,KAAK,QAAQ,IAAI,EACd,MAAM,EAAE,EACR,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAAA,UAC/B;AAAA,QACF;AAEA,YAAI,aAAa,gBAAgB,QAAQ,SAAS,UAAU;AAE1D,gBAAM,aAAa,MAAM,KAAK,aAAa,IAAI;AAC/C,cAAI,eAAe,QAAQ,MAAM;AAC/B,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,gBAAgB,KAAyB;AAC/C,UAAM,SAAS,IAAI,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACvD,UAAM,WAAW,IAAK,OAAO,SAAS,KAAM;AAC5C,UAAM,SAAS,SAAS,IAAI,OAAO,OAAO;AAC1C,UAAM,SAAS,KAAK,MAAM;AAC1B,UAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,IAChC;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,MAA0B;AAChD,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,OAAO,KAAK,CAAC;AACnB,UAAI,SAAS,QAAW;AACtB,kBAAU,OAAO,aAAa,IAAI;AAAA,MACpC;AAAA,IACF;AACA,WAAO,KAAK,MAAM,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AAAA,EAC/E;AAAA,EAEA,MAAc,OAAO,SAAkC;AACrD,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,OAAO,QAAQ,OAAO,OAAO;AACnC,UAAM,OAAO,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI;AACvD,WAAO,KAAK,gBAAgB,IAAI,WAAW,IAAI,CAAC;AAAA,EAClD;AAAA,EAEA,MAAc,aAAa,SAAkC;AAC3D,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,OAAO,QAAQ,OAAO,OAAO;AACnC,UAAM,OAAO,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI;AACvD,QAAI,SAAS;AACb,UAAM,QAAQ,IAAI,WAAW,IAAI;AACjC,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,SAAS,QAAW;AACtB,kBAAU,OAAO,aAAa,IAAI;AAAA,MACpC;AAAA,IACF;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AAKO,SAAS,oBACd,QACkB;AAClB,SAAO,IAAI,cAAiB,MAAM;AACpC;AAKO,SAAS,qBAAkC,QAG5B;AACpB,SAAO,IAAI,eAAkB,MAAM;AACrC;;;ACpcO,IAAM,eAAN,MAAgC;AAAA,EAC7B;AAAA,EACA;AAAA,EAER,YAAY,QAA+B;AACzC,SAAK,UAAU,OAAO;AACtB,SAAK,QAAQ,OAAO,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,cAAsB;AACxB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAe;AACjB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,MAAS,SAA+C;AACjE,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,UAAU,KAAK,IAAI,sBAAsB,IAAI;AAAA,IAC3D;AAEA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,MAAM,OAAO;AAEvD,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,UAAU,KAAK,IAAI,mBAAmB,SAAS,EAAE;AAAA,IAC/D;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UACJ,UAC0B;AAC1B,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,UAAU,KAAK,IAAI,sBAAsB,SAAS,MAAM,WAAW;AAAA,IACjF;AAEA,QAAI,KAAK,QAAQ,WAAW;AAC1B,aAAO,KAAK,QAAQ,UAAU,QAAQ;AAAA,IACxC;AAGA,UAAM,aAAuB,CAAC;AAC9B,UAAM,SAAkD,CAAC;AACzD,QAAI,aAAa;AACjB,QAAI,SAAS;AAEb,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,MAAM,SAAS,CAAC;AACtB,UAAI,CAAC,IAAK;AAEV,UAAI;AACF,cAAM,KAAK,MAAM,KAAK,KAAK,IAAI,MAAM,IAAI,OAAO;AAChD,mBAAW,KAAK,EAAE;AAClB;AAAA,MACF,SAAS,KAAK;AACZ;AACA,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,OAAO,eAAe,QAAQ,IAAI,UAAU;AAAA,QAC9C,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO,SAAS;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QACJ,aACA,mBAC4B;AAC5B,QAAI,CAAC,KAAK,QAAQ,SAAS;AACzB,YAAM,IAAI,MAAM,GAAG,KAAK,QAAQ,IAAI,qCAAqC;AAAA,IAC3E;AAEA,WAAO,KAAK,QAAQ,QAAQ,aAAa,iBAAiB;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAI,WAAkC;AAC1C,QAAI,CAAC,KAAK,QAAQ,KAAK;AACrB,YAAM,IAAI,MAAM,GAAG,KAAK,QAAQ,IAAI,iCAAiC;AAAA,IACvE;AAEA,UAAM,KAAK,QAAQ,IAAI,SAAS;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,YAAqC;AAClD,QAAI,KAAK,QAAQ,UAAU;AACzB,YAAM,KAAK,QAAQ,SAAS,UAAU;AACtC;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ,KAAK;AACpB,YAAM,QAAQ,IAAI,WAAW,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAK,EAAE,CAAC,CAAC;AAC/D;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,GAAG,KAAK,QAAQ,IAAI,iCAAiC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,WAAmB,cAAsC;AAClE,QAAI,CAAC,KAAK,QAAQ,MAAM;AACtB,YAAM,IAAI,MAAM,GAAG,KAAK,QAAQ,IAAI,kCAAkC;AAAA,IACxE;AAEA,UAAM,KAAK,QAAQ,KAAK,WAAW,YAAY;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QACJ,SACA,SACe;AACf,QAAI,CAAC,KAAK,QAAQ,SAAS;AACzB,YAAM,IAAI,MAAM,GAAG,KAAK,QAAQ,IAAI,qCAAqC;AAAA,IAC3E;AAEA,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,UAAU,KAAK,IAAI,qBAAqB;AAAA,IACtD;AAEA,UAAM,KAAK,QAAQ,QAAQ,SAAS,OAAO;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAA+B;AACnC,QAAI,KAAK,QAAQ,eAAe;AAC9B,YAAM,KAAK,QAAQ,cAAc;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAgC;AACpC,QAAI,KAAK,QAAQ,UAAU;AACzB,aAAO,KAAK,QAAQ,SAAS;AAAA,IAC/B;AAEA,WAAO,EAAE,cAAc,GAAG;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC3B,QAAI,KAAK,QAAQ,OAAO;AACtB,YAAM,KAAK,QAAQ,MAAM;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC3B,QAAI,KAAK,QAAQ,OAAO;AACtB,YAAM,KAAK,QAAQ,MAAM;AAAA,IAC3B;AAAA,EACF;AACF;AA0BO,SAAS,mBACd,QACiB;AACjB,SAAO,IAAI,aAAgB,MAAM;AACnC;AAGA,IAAO,gBAAQ;AAAA,EACb;AAAA,EACA;AACF;","names":[]}
@@ -0,0 +1,246 @@
1
+ export { AddJobRequest, Job, JobOptions, JobProgressUpdate, JobStatus, QueueStats as ParsQueueStats, QueueConfig, QueueListOptions, RedisQueueConfig, WorkerOptions, addJobRequest, job, jobOptions, jobProgressUpdate, jobStatus, queueStats as parsQueueStats, queueConfig, queueListOptions, redisQueueConfig, type, workerOptions } from '@parsrun/types';
2
+
3
+ /**
4
+ * @parsrun/queue - Type Definitions
5
+ * Queue types and interfaces
6
+ */
7
+
8
+ /**
9
+ * Queue adapter type
10
+ */
11
+ type QueueAdapterType = "memory" | "cloudflare" | "qstash";
12
+ /**
13
+ * Message payload
14
+ */
15
+ interface QueueMessage<T = unknown> {
16
+ /** Unique message ID */
17
+ id: string;
18
+ /** Message payload */
19
+ body: T;
20
+ /** Message timestamp */
21
+ timestamp: Date;
22
+ /** Number of delivery attempts */
23
+ attempts: number;
24
+ /** Optional delay before processing (seconds) */
25
+ delaySeconds?: number | undefined;
26
+ /** Optional deduplication ID */
27
+ deduplicationId?: string | undefined;
28
+ /** Custom metadata */
29
+ metadata?: Record<string, unknown> | undefined;
30
+ }
31
+ /**
32
+ * Send message options
33
+ */
34
+ interface SendMessageOptions {
35
+ /** Delay before message is available (seconds) */
36
+ delaySeconds?: number | undefined;
37
+ /** Deduplication ID (prevents duplicate processing) */
38
+ deduplicationId?: string | undefined;
39
+ /** Custom metadata */
40
+ metadata?: Record<string, unknown> | undefined;
41
+ /** Priority (higher = more important) */
42
+ priority?: number | undefined;
43
+ }
44
+ /**
45
+ * Batch send result
46
+ */
47
+ interface BatchSendResult {
48
+ /** Total messages sent */
49
+ total: number;
50
+ /** Successfully sent */
51
+ successful: number;
52
+ /** Failed to send */
53
+ failed: number;
54
+ /** Individual message IDs */
55
+ messageIds: string[];
56
+ /** Failed messages with errors */
57
+ errors: Array<{
58
+ index: number;
59
+ error: string;
60
+ }>;
61
+ }
62
+ /**
63
+ * Message handler function
64
+ */
65
+ type MessageHandler<T = unknown> = (message: QueueMessage<T>) => void | Promise<void>;
66
+ /**
67
+ * Consumer options
68
+ */
69
+ interface ConsumerOptions {
70
+ /** Maximum messages to process per batch */
71
+ batchSize?: number | undefined;
72
+ /** Visibility timeout (seconds) - how long a message is hidden while processing */
73
+ visibilityTimeout?: number | undefined;
74
+ /** Polling interval (ms) for pull-based queues */
75
+ pollingInterval?: number | undefined;
76
+ /** Maximum retries before dead-letter */
77
+ maxRetries?: number | undefined;
78
+ /** Concurrency - how many messages to process in parallel */
79
+ concurrency?: number | undefined;
80
+ }
81
+ /**
82
+ * Queue adapter interface
83
+ */
84
+ interface QueueAdapter<T = unknown> {
85
+ /** Adapter type */
86
+ readonly type: QueueAdapterType;
87
+ /** Queue name */
88
+ readonly name: string;
89
+ /**
90
+ * Send a message to the queue
91
+ */
92
+ send(body: T, options?: SendMessageOptions): Promise<string>;
93
+ /**
94
+ * Send multiple messages at once
95
+ */
96
+ sendBatch?(messages: Array<{
97
+ body: T;
98
+ options?: SendMessageOptions;
99
+ }>): Promise<BatchSendResult>;
100
+ /**
101
+ * Receive messages from the queue (pull-based)
102
+ * Used for manual message processing
103
+ */
104
+ receive?(maxMessages?: number, visibilityTimeout?: number): Promise<QueueMessage<T>[]>;
105
+ /**
106
+ * Acknowledge message processing (mark as complete)
107
+ */
108
+ ack?(messageId: string): Promise<void>;
109
+ /**
110
+ * Acknowledge multiple messages
111
+ */
112
+ ackBatch?(messageIds: string[]): Promise<void>;
113
+ /**
114
+ * Return message to queue (negative acknowledgement)
115
+ * Optionally with delay
116
+ */
117
+ nack?(messageId: string, delaySeconds?: number): Promise<void>;
118
+ /**
119
+ * Start consuming messages (push-based)
120
+ * For adapters that support push-based processing
121
+ */
122
+ consume?(handler: MessageHandler<T>, options?: ConsumerOptions): Promise<void>;
123
+ /**
124
+ * Stop consuming messages
125
+ */
126
+ stopConsuming?(): Promise<void>;
127
+ /**
128
+ * Get queue statistics
129
+ */
130
+ getStats?(): Promise<QueueStats>;
131
+ /**
132
+ * Purge all messages from queue
133
+ */
134
+ purge?(): Promise<void>;
135
+ /**
136
+ * Close/cleanup adapter resources
137
+ */
138
+ close?(): Promise<void>;
139
+ }
140
+ /**
141
+ * Queue statistics
142
+ */
143
+ interface QueueStats {
144
+ /** Approximate number of messages in queue */
145
+ messageCount: number;
146
+ /** Messages currently being processed */
147
+ inFlightCount?: number | undefined;
148
+ /** Messages in dead-letter queue */
149
+ deadLetterCount?: number | undefined;
150
+ }
151
+ /**
152
+ * Queue service configuration
153
+ */
154
+ interface QueueServiceConfig<T = unknown> {
155
+ /** Queue adapter to use */
156
+ adapter: QueueAdapter<T>;
157
+ /** Enable debug logging */
158
+ debug?: boolean | undefined;
159
+ }
160
+ /**
161
+ * Memory queue configuration
162
+ */
163
+ interface MemoryQueueConfig {
164
+ /** Queue name */
165
+ name: string;
166
+ /** Maximum queue size (default: unlimited) */
167
+ maxSize?: number | undefined;
168
+ /** Default visibility timeout (seconds) */
169
+ visibilityTimeout?: number | undefined;
170
+ }
171
+ /**
172
+ * Cloudflare Queue configuration
173
+ */
174
+ interface CloudflareQueueConfig {
175
+ /** Queue binding from environment */
176
+ queue: CloudflareQueue;
177
+ }
178
+ /**
179
+ * Cloudflare Queue interface (from Workers runtime)
180
+ */
181
+ interface CloudflareQueue<T = unknown> {
182
+ send(message: T, options?: {
183
+ delaySeconds?: number | undefined;
184
+ contentType?: string | undefined;
185
+ }): Promise<void>;
186
+ sendBatch(messages: Array<{
187
+ body: T;
188
+ delaySeconds?: number | undefined;
189
+ contentType?: string | undefined;
190
+ }>): Promise<void>;
191
+ }
192
+ /**
193
+ * Cloudflare Queue batch
194
+ */
195
+ interface CloudflareMessageBatch<T = unknown> {
196
+ readonly queue: string;
197
+ readonly messages: Array<CloudflareMessage<T>>;
198
+ ackAll(): void;
199
+ retryAll(): void;
200
+ }
201
+ /**
202
+ * Cloudflare Queue message
203
+ */
204
+ interface CloudflareMessage<T = unknown> {
205
+ readonly id: string;
206
+ readonly timestamp: Date;
207
+ readonly body: T;
208
+ readonly attempts: number;
209
+ ack(): void;
210
+ retry(): void;
211
+ }
212
+ /**
213
+ * QStash configuration
214
+ */
215
+ interface QStashConfig {
216
+ /** QStash token */
217
+ token: string;
218
+ /** Destination URL for message delivery */
219
+ destinationUrl: string;
220
+ /** Current request URL (for signature verification) */
221
+ currentSigningKey?: string | undefined;
222
+ /** Next signing key (for signature verification) */
223
+ nextSigningKey?: string | undefined;
224
+ }
225
+ /**
226
+ * Queue error
227
+ */
228
+ declare class QueueError extends Error {
229
+ readonly code: string;
230
+ readonly cause?: unknown | undefined;
231
+ constructor(message: string, code: string, cause?: unknown | undefined);
232
+ }
233
+ /**
234
+ * Common queue error codes
235
+ */
236
+ declare const QueueErrorCodes: {
237
+ readonly SEND_FAILED: "SEND_FAILED";
238
+ readonly RECEIVE_FAILED: "RECEIVE_FAILED";
239
+ readonly ACK_FAILED: "ACK_FAILED";
240
+ readonly INVALID_CONFIG: "INVALID_CONFIG";
241
+ readonly QUEUE_FULL: "QUEUE_FULL";
242
+ readonly MESSAGE_NOT_FOUND: "MESSAGE_NOT_FOUND";
243
+ readonly NOT_IMPLEMENTED: "NOT_IMPLEMENTED";
244
+ };
245
+
246
+ export { type BatchSendResult, type CloudflareMessage, type CloudflareMessageBatch, type CloudflareQueue, type CloudflareQueueConfig, type ConsumerOptions, type MemoryQueueConfig, type MessageHandler, type QStashConfig, type QueueAdapter, type QueueAdapterType, QueueError, QueueErrorCodes, type QueueMessage, type QueueServiceConfig, type QueueStats, type SendMessageOptions };
package/dist/types.js ADDED
@@ -0,0 +1,47 @@
1
+ // src/types.ts
2
+ import {
3
+ type,
4
+ jobStatus,
5
+ job,
6
+ jobOptions,
7
+ addJobRequest,
8
+ jobProgressUpdate,
9
+ queueStats,
10
+ queueListOptions,
11
+ redisQueueConfig,
12
+ workerOptions,
13
+ queueConfig
14
+ } from "@parsrun/types";
15
+ var QueueError = class extends Error {
16
+ constructor(message, code, cause) {
17
+ super(message);
18
+ this.code = code;
19
+ this.cause = cause;
20
+ this.name = "QueueError";
21
+ }
22
+ };
23
+ var QueueErrorCodes = {
24
+ SEND_FAILED: "SEND_FAILED",
25
+ RECEIVE_FAILED: "RECEIVE_FAILED",
26
+ ACK_FAILED: "ACK_FAILED",
27
+ INVALID_CONFIG: "INVALID_CONFIG",
28
+ QUEUE_FULL: "QUEUE_FULL",
29
+ MESSAGE_NOT_FOUND: "MESSAGE_NOT_FOUND",
30
+ NOT_IMPLEMENTED: "NOT_IMPLEMENTED"
31
+ };
32
+ export {
33
+ QueueError,
34
+ QueueErrorCodes,
35
+ addJobRequest,
36
+ job,
37
+ jobOptions,
38
+ jobProgressUpdate,
39
+ jobStatus,
40
+ queueStats as parsQueueStats,
41
+ queueConfig,
42
+ queueListOptions,
43
+ redisQueueConfig,
44
+ type,
45
+ workerOptions
46
+ };
47
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * @parsrun/queue - Type Definitions\n * Queue types and interfaces\n */\n\n// Re-export types from @parsrun/types for convenience\nexport {\n type,\n jobStatus,\n job,\n jobOptions,\n addJobRequest,\n jobProgressUpdate,\n queueStats as parsQueueStats,\n queueListOptions,\n redisQueueConfig,\n workerOptions,\n queueConfig,\n type JobStatus,\n type Job,\n type JobOptions,\n type AddJobRequest,\n type JobProgressUpdate,\n type QueueStats as ParsQueueStats,\n type QueueListOptions,\n type RedisQueueConfig,\n type WorkerOptions,\n type QueueConfig,\n} from \"@parsrun/types\";\n\n/**\n * Queue adapter type\n */\nexport type QueueAdapterType = \"memory\" | \"cloudflare\" | \"qstash\";\n\n/**\n * Message payload\n */\nexport interface QueueMessage<T = unknown> {\n /** Unique message ID */\n id: string;\n /** Message payload */\n body: T;\n /** Message timestamp */\n timestamp: Date;\n /** Number of delivery attempts */\n attempts: number;\n /** Optional delay before processing (seconds) */\n delaySeconds?: number | undefined;\n /** Optional deduplication ID */\n deduplicationId?: string | undefined;\n /** Custom metadata */\n metadata?: Record<string, unknown> | undefined;\n}\n\n/**\n * Send message options\n */\nexport interface SendMessageOptions {\n /** Delay before message is available (seconds) */\n delaySeconds?: number | undefined;\n /** Deduplication ID (prevents duplicate processing) */\n deduplicationId?: string | undefined;\n /** Custom metadata */\n metadata?: Record<string, unknown> | undefined;\n /** Priority (higher = more important) */\n priority?: number | undefined;\n}\n\n/**\n * Batch send result\n */\nexport interface BatchSendResult {\n /** Total messages sent */\n total: number;\n /** Successfully sent */\n successful: number;\n /** Failed to send */\n failed: number;\n /** Individual message IDs */\n messageIds: string[];\n /** Failed messages with errors */\n errors: Array<{ index: number; error: string }>;\n}\n\n/**\n * Message handler function\n */\nexport type MessageHandler<T = unknown> = (\n message: QueueMessage<T>\n) => void | Promise<void>;\n\n/**\n * Consumer options\n */\nexport interface ConsumerOptions {\n /** Maximum messages to process per batch */\n batchSize?: number | undefined;\n /** Visibility timeout (seconds) - how long a message is hidden while processing */\n visibilityTimeout?: number | undefined;\n /** Polling interval (ms) for pull-based queues */\n pollingInterval?: number | undefined;\n /** Maximum retries before dead-letter */\n maxRetries?: number | undefined;\n /** Concurrency - how many messages to process in parallel */\n concurrency?: number | undefined;\n}\n\n/**\n * Queue adapter interface\n */\nexport interface QueueAdapter<T = unknown> {\n /** Adapter type */\n readonly type: QueueAdapterType;\n\n /** Queue name */\n readonly name: string;\n\n /**\n * Send a message to the queue\n */\n send(body: T, options?: SendMessageOptions): Promise<string>;\n\n /**\n * Send multiple messages at once\n */\n sendBatch?(messages: Array<{ body: T; options?: SendMessageOptions }>): Promise<BatchSendResult>;\n\n /**\n * Receive messages from the queue (pull-based)\n * Used for manual message processing\n */\n receive?(maxMessages?: number, visibilityTimeout?: number): Promise<QueueMessage<T>[]>;\n\n /**\n * Acknowledge message processing (mark as complete)\n */\n ack?(messageId: string): Promise<void>;\n\n /**\n * Acknowledge multiple messages\n */\n ackBatch?(messageIds: string[]): Promise<void>;\n\n /**\n * Return message to queue (negative acknowledgement)\n * Optionally with delay\n */\n nack?(messageId: string, delaySeconds?: number): Promise<void>;\n\n /**\n * Start consuming messages (push-based)\n * For adapters that support push-based processing\n */\n consume?(handler: MessageHandler<T>, options?: ConsumerOptions): Promise<void>;\n\n /**\n * Stop consuming messages\n */\n stopConsuming?(): Promise<void>;\n\n /**\n * Get queue statistics\n */\n getStats?(): Promise<QueueStats>;\n\n /**\n * Purge all messages from queue\n */\n purge?(): Promise<void>;\n\n /**\n * Close/cleanup adapter resources\n */\n close?(): Promise<void>;\n}\n\n/**\n * Queue statistics\n */\nexport interface QueueStats {\n /** Approximate number of messages in queue */\n messageCount: number;\n /** Messages currently being processed */\n inFlightCount?: number | undefined;\n /** Messages in dead-letter queue */\n deadLetterCount?: number | undefined;\n}\n\n/**\n * Queue service configuration\n */\nexport interface QueueServiceConfig<T = unknown> {\n /** Queue adapter to use */\n adapter: QueueAdapter<T>;\n /** Enable debug logging */\n debug?: boolean | undefined;\n}\n\n/**\n * Memory queue configuration\n */\nexport interface MemoryQueueConfig {\n /** Queue name */\n name: string;\n /** Maximum queue size (default: unlimited) */\n maxSize?: number | undefined;\n /** Default visibility timeout (seconds) */\n visibilityTimeout?: number | undefined;\n}\n\n/**\n * Cloudflare Queue configuration\n */\nexport interface CloudflareQueueConfig {\n /** Queue binding from environment */\n queue: CloudflareQueue;\n}\n\n/**\n * Cloudflare Queue interface (from Workers runtime)\n */\nexport interface CloudflareQueue<T = unknown> {\n send(message: T, options?: { delaySeconds?: number | undefined; contentType?: string | undefined }): Promise<void>;\n sendBatch(messages: Array<{ body: T; delaySeconds?: number | undefined; contentType?: string | undefined }>): Promise<void>;\n}\n\n/**\n * Cloudflare Queue batch\n */\nexport interface CloudflareMessageBatch<T = unknown> {\n readonly queue: string;\n readonly messages: Array<CloudflareMessage<T>>;\n ackAll(): void;\n retryAll(): void;\n}\n\n/**\n * Cloudflare Queue message\n */\nexport interface CloudflareMessage<T = unknown> {\n readonly id: string;\n readonly timestamp: Date;\n readonly body: T;\n readonly attempts: number;\n ack(): void;\n retry(): void;\n}\n\n/**\n * QStash configuration\n */\nexport interface QStashConfig {\n /** QStash token */\n token: string;\n /** Destination URL for message delivery */\n destinationUrl: string;\n /** Current request URL (for signature verification) */\n currentSigningKey?: string | undefined;\n /** Next signing key (for signature verification) */\n nextSigningKey?: string | undefined;\n}\n\n/**\n * Queue error\n */\nexport class QueueError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = \"QueueError\";\n }\n}\n\n/**\n * Common queue error codes\n */\nexport const QueueErrorCodes = {\n SEND_FAILED: \"SEND_FAILED\",\n RECEIVE_FAILED: \"RECEIVE_FAILED\",\n ACK_FAILED: \"ACK_FAILED\",\n INVALID_CONFIG: \"INVALID_CONFIG\",\n QUEUE_FULL: \"QUEUE_FULL\",\n MESSAGE_NOT_FOUND: \"MESSAGE_NOT_FOUND\",\n NOT_IMPLEMENTED: \"NOT_IMPLEMENTED\",\n} as const;\n"],"mappings":";AAMA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAWK;AA8OA,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACE,SACgB,MACA,OAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,kBAAkB;AAAA,EAC7B,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,mBAAmB;AAAA,EACnB,iBAAiB;AACnB;","names":[]}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@parsrun/queue",
3
+ "version": "0.1.0",
4
+ "description": "Edge-compatible message queues for Pars - Memory, Cloudflare Queues, Upstash QStash",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./types": {
15
+ "types": "./dist/types.d.ts",
16
+ "import": "./dist/types.js"
17
+ },
18
+ "./adapters": {
19
+ "types": "./dist/adapters/index.d.ts",
20
+ "import": "./dist/adapters/index.js"
21
+ },
22
+ "./adapters/memory": {
23
+ "types": "./dist/adapters/memory.d.ts",
24
+ "import": "./dist/adapters/memory.js"
25
+ },
26
+ "./adapters/cloudflare": {
27
+ "types": "./dist/adapters/cloudflare.d.ts",
28
+ "import": "./dist/adapters/cloudflare.js"
29
+ },
30
+ "./adapters/qstash": {
31
+ "types": "./dist/adapters/qstash.d.ts",
32
+ "import": "./dist/adapters/qstash.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch",
42
+ "test": "vitest run",
43
+ "typecheck": "tsc --noEmit"
44
+ },
45
+ "keywords": [
46
+ "queue",
47
+ "cloudflare-queues",
48
+ "qstash",
49
+ "upstash",
50
+ "edge",
51
+ "pars"
52
+ ],
53
+ "author": "EMS Tech Solutions",
54
+ "license": "MIT",
55
+ "dependencies": {
56
+ "@parsrun/core": "workspace:*",
57
+ "@parsrun/types": "workspace:*"
58
+ },
59
+ "devDependencies": {
60
+ "tsup": "^8.0.0",
61
+ "typescript": "^5.0.0",
62
+ "vitest": "^2.0.0"
63
+ },
64
+ "peerDependencies": {
65
+ "@upstash/qstash": "^2.0.0"
66
+ },
67
+ "peerDependenciesMeta": {
68
+ "@upstash/qstash": {
69
+ "optional": true
70
+ }
71
+ }
72
+ }