workmatic 1.0.5 → 1.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.
- package/README.md +114 -13
- package/dashboard/app.js +1 -3
- package/dashboard/index.html +0 -14
- package/dist/cli.cjs +905 -108
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +905 -108
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +360 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -6
- package/dist/index.d.ts +118 -6
- package/dist/index.js +357 -66
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../node_modules/tsup/assets/cjs_shims.js","../src/database.ts","../src/client.ts","../src/utils.ts","../src/worker.ts","../src/dashboard.ts"],"sourcesContent":["/**\n * Workmatic - A persistent job queue for Node.js\n * \n * @packageDocumentation\n */\n\n// Main exports\nexport { createDatabase } from './database.js';\nexport { createClient } from './client.js';\nexport { createWorker } from './worker.js';\nexport { createDashboard, createDashboardMiddleware } from './dashboard.js';\n\n// Utility exports\nexport { defaultBackoff, validatePayload } from './utils.js';\n\n// Type exports\nexport type {\n // Core types\n Job,\n JobStatus,\n JobStats,\n ClaimedJob,\n WorkerState,\n \n // Options\n AddJobOptions,\n AddJobResult,\n DatabaseOptions,\n ClientOptions,\n WorkerOptions,\n DashboardOptions,\n DashboardMiddlewareOptions,\n BackoffFunction,\n JobProcessor,\n \n // Interfaces\n WorkmaticClient,\n WorkmaticWorker,\n WorkmaticDashboard,\n DashboardMiddleware,\n WorkmaticDb,\n WorkmaticDatabase,\n WorkmaticJobsTable,\n} from './types.js';\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import Database from 'better-sqlite3';\nimport { Kysely, SqliteDialect } from 'kysely';\nimport type { WorkmaticDatabase, WorkmaticDb, DatabaseOptions } from './types.js';\n\n/**\n * Create and initialize the workmatic database\n * \n * @param options - Database options\n * @returns Kysely database instance\n * \n * @example\n * ```ts\n * // Using a file path\n * const db = createDatabase({ filename: './jobs.db' });\n * \n * // Using an existing better-sqlite3 instance\n * import Database from 'better-sqlite3';\n * const sqlite = new Database('./jobs.db');\n * const db = createDatabase({ db: sqlite });\n * \n * // In-memory database (for testing)\n * const db = createDatabase({ filename: ':memory:' });\n * ```\n */\nexport function createDatabase(options: DatabaseOptions = {}): WorkmaticDb {\n let sqliteDb: Database.Database;\n\n if (options.db) {\n sqliteDb = options.db;\n } else {\n const filename = options.filename ?? ':memory:';\n sqliteDb = new Database(filename);\n }\n\n // Set pragmas for performance and safety\n sqliteDb.pragma('journal_mode = WAL');\n sqliteDb.pragma('synchronous = NORMAL');\n sqliteDb.pragma('busy_timeout = 5000');\n\n // Create Kysely instance\n const db = new Kysely<WorkmaticDatabase>({\n dialect: new SqliteDialect({\n database: sqliteDb,\n }),\n });\n\n // Create schema synchronously using better-sqlite3 directly\n createSchema(sqliteDb);\n\n return db;\n}\n\n/**\n * Create the database schema if it doesn't exist\n */\nfunction createSchema(db: Database.Database): void {\n // Create the jobs table\n db.exec(`\n CREATE TABLE IF NOT EXISTS workmatic_jobs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n public_id TEXT UNIQUE NOT NULL,\n queue TEXT NOT NULL,\n payload TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'ready',\n priority INTEGER NOT NULL DEFAULT 0,\n run_at INTEGER NOT NULL,\n attempts INTEGER NOT NULL DEFAULT 0,\n max_attempts INTEGER NOT NULL DEFAULT 3,\n lease_until INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n last_error TEXT\n )\n `);\n\n // Create composite index for efficient job claiming\n // (queue, status, run_at, priority, id)\n db.exec(`\n CREATE INDEX IF NOT EXISTS idx_workmatic_jobs_claim \n ON workmatic_jobs (queue, status, run_at, priority, id)\n `);\n\n // Create index for lease expiration checking\n // (status, lease_until)\n db.exec(`\n CREATE INDEX IF NOT EXISTS idx_workmatic_jobs_lease \n ON workmatic_jobs (status, lease_until)\n `);\n\n // Create settings table for queue-level settings (pause state, etc.)\n db.exec(`\n CREATE TABLE IF NOT EXISTS workmatic_settings (\n queue TEXT PRIMARY KEY,\n paused INTEGER NOT NULL DEFAULT 0,\n updated_at INTEGER NOT NULL\n )\n `);\n}\n\n/**\n * Get the underlying better-sqlite3 database instance from a Kysely instance\n * This is useful for advanced operations or testing\n */\nexport function getUnderlyingDb(db: WorkmaticDb): Database.Database {\n // Access the internal database through the dialect\n // This is a bit hacky but necessary for some operations\n const dialect = (db as any).getExecutor().adapter.db;\n return dialect;\n}\n","import { nanoid } from 'nanoid';\nimport { sql } from 'kysely';\nimport type {\n WorkmaticDb,\n ClientOptions,\n WorkmaticClient,\n AddJobOptions,\n AddJobResult,\n JobStats,\n JobStatus,\n} from './types.js';\nimport { validatePayload, now } from './utils.js';\n\n/**\n * Create a job queue client for adding jobs\n * \n * @param options - Client options\n * @returns Client instance\n * \n * @example\n * ```ts\n * const client = createClient({ db });\n * \n * // Add a simple job\n * const result = await client.add({ email: 'user@example.com' });\n * console.log(result.id); // Job public ID\n * \n * // Add a job with options\n * await client.add(\n * { userId: 123 },\n * { priority: 1, delayMs: 5000, maxAttempts: 5 }\n * );\n * \n * // Get queue statistics\n * const stats = await client.stats();\n * console.log(stats); // { ready: 5, running: 2, done: 100, ... }\n * ```\n */\nexport function createClient(options: ClientOptions): WorkmaticClient {\n const { db, queue = 'default' } = options;\n\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n return {\n /**\n * Add a job to the queue\n */\n async add<TPayload = unknown>(\n payload: TPayload,\n opts: AddJobOptions = {}\n ): Promise<AddJobResult> {\n const {\n priority = 0,\n delayMs = 0,\n maxAttempts = 3,\n } = opts;\n\n // Validate and serialize payload\n const payloadJson = validatePayload(payload);\n \n // Generate unique public ID\n const publicId = nanoid();\n \n const timestamp = now();\n const runAt = timestamp + delayMs;\n\n // Insert job\n await db\n .insertInto('workmatic_jobs')\n .values({\n public_id: publicId,\n queue,\n payload: payloadJson,\n status: 'ready',\n priority,\n run_at: runAt,\n attempts: 0,\n max_attempts: maxAttempts,\n lease_until: 0,\n created_at: timestamp,\n updated_at: timestamp,\n last_error: null,\n })\n .execute();\n\n return { ok: true, id: publicId };\n },\n\n /**\n * Get job statistics for the queue\n */\n async stats(): Promise<JobStats> {\n const result = await db\n .selectFrom('workmatic_jobs')\n .select([\n 'status',\n sql<number>`count(*)`.as('count'),\n ])\n .where('queue', '=', queue)\n .groupBy('status')\n .execute();\n\n const stats: JobStats = {\n ready: 0,\n running: 0,\n done: 0,\n failed: 0,\n dead: 0,\n total: 0,\n };\n\n for (const row of result) {\n const status = row.status as JobStatus;\n const count = Number(row.count);\n if (status in stats) {\n stats[status] = count;\n }\n stats.total += count;\n }\n\n return stats;\n },\n\n /**\n * Clear all jobs from the queue\n */\n async clear(options: { status?: JobStatus } = {}): Promise<number> {\n let query = db\n .deleteFrom('workmatic_jobs')\n .where('queue', '=', queue);\n\n if (options.status) {\n query = query.where('status', '=', options.status);\n }\n\n const result = await query.execute();\n return Number(result[0]?.numDeletedRows ?? 0);\n },\n };\n}\n","import type { BackoffFunction } from './types.js';\n\n/**\n * Default exponential backoff function\n * Returns delay in milliseconds: 1000 * 2^attempts\n * \n * @param attempts - Number of failed attempts\n * @returns Delay in milliseconds\n * \n * @example\n * ```ts\n * defaultBackoff(0) // 1000ms (1 second)\n * defaultBackoff(1) // 2000ms (2 seconds)\n * defaultBackoff(2) // 4000ms (4 seconds)\n * defaultBackoff(3) // 8000ms (8 seconds)\n * ```\n */\nexport const defaultBackoff: BackoffFunction = (attempts: number): number => {\n return 1000 * Math.pow(2, attempts);\n};\n\n/**\n * Validate that a payload is JSON-serializable\n * \n * @param payload - The payload to validate\n * @throws Error if payload cannot be serialized to JSON\n * @returns The JSON string representation\n */\nexport function validatePayload(payload: unknown): string {\n try {\n return JSON.stringify(payload);\n } catch (error) {\n throw new Error(\n `Payload is not JSON-serializable: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n}\n\n/**\n * Parse a JSON payload safely\n * \n * @param json - JSON string to parse\n * @returns Parsed payload\n * @throws Error if JSON is invalid\n */\nexport function parsePayload<T = unknown>(json: string): T {\n try {\n return JSON.parse(json) as T;\n } catch (error) {\n throw new Error(\n `Invalid JSON payload: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n}\n\n/**\n * Sleep for a specified duration\n * \n * @param ms - Duration in milliseconds\n * @returns Promise that resolves after the duration\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Get current timestamp in milliseconds\n */\nexport function now(): number {\n return Date.now();\n}\n","import fastq from 'fastq';\nimport type { queueAsPromised } from 'fastq';\nimport { sql } from 'kysely';\nimport type {\n WorkmaticDb,\n WorkerOptions,\n WorkmaticWorker,\n JobProcessor,\n JobStats,\n JobStatus,\n Job,\n ClaimedJob,\n WorkerState,\n} from './types.js';\nimport { defaultBackoff, parsePayload, sleep, now } from './utils.js';\n\n/**\n * Create a job queue worker for processing jobs\n * \n * @param options - Worker options\n * @returns Worker instance\n * \n * @example\n * ```ts\n * const worker = createWorker({ db, concurrency: 4 });\n * \n * // Set the processor function\n * worker.process(async (job) => {\n * console.log('Processing job:', job.id);\n * await sendEmail(job.payload.email);\n * });\n * \n * // Start processing\n * worker.start();\n * \n * // Later, gracefully stop\n * await worker.stop();\n * ```\n */\nexport function createWorker(options: WorkerOptions): WorkmaticWorker {\n const {\n db,\n queue = 'default',\n concurrency = 1,\n leaseMs = 30000,\n pollMs = 1000,\n timeoutMs,\n backoff = defaultBackoff,\n persistState = false,\n autoRestore = true,\n } = options;\n\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n // State\n let running = false;\n let paused = false;\n let processor: JobProcessor<any> | null = null;\n let pumpTimeout: NodeJS.Timeout | null = null;\n let fastqQueue: queueAsPromised<ClaimedJob, void> | null = null;\n\n /**\n * Get the settings key for this worker's state\n */\n function getStateKey(): string {\n return `worker_state_${queue}`;\n }\n\n /**\n * Save worker state to database\n */\n async function saveState(state: WorkerState): Promise<void> {\n if (!persistState) return;\n\n const timestamp = now();\n const key = getStateKey();\n\n // Ensure settings table exists\n await db.schema\n .createTable('workmatic_settings')\n .ifNotExists()\n .addColumn('queue', 'text', (col) => col.primaryKey())\n .addColumn('paused', 'integer', (col) => col.notNull().defaultTo(0))\n .addColumn('updated_at', 'integer', (col) => col.notNull())\n .execute()\n .catch(() => {}); // Ignore if exists\n\n // Use raw SQL for upsert since different SQLite versions have different syntax\n await sql`\n INSERT INTO workmatic_settings (queue, paused, updated_at)\n VALUES (${key}, ${state === 'paused' ? 1 : state === 'running' ? 2 : 0}, ${timestamp})\n ON CONFLICT(queue) DO UPDATE SET \n paused = ${state === 'paused' ? 1 : state === 'running' ? 2 : 0},\n updated_at = ${timestamp}\n `.execute(db);\n }\n\n /**\n * Load worker state from database\n */\n async function loadState(): Promise<WorkerState | null> {\n if (!persistState) return null;\n\n try {\n const key = getStateKey();\n const result = await db\n .selectFrom('workmatic_settings')\n .select('paused')\n .where('queue', '=', key)\n .executeTakeFirst();\n\n if (!result) return null;\n \n // paused: 0 = stopped, 1 = paused, 2 = running\n if (result.paused === 2) return 'running';\n if (result.paused === 1) return 'paused';\n return 'stopped';\n } catch {\n return null;\n }\n }\n\n /**\n * Requeue jobs with expired leases\n */\n async function requeueExpiredLeases(): Promise<number> {\n const timestamp = now();\n\n const result = await db\n .updateTable('workmatic_jobs')\n .set({\n status: 'ready',\n lease_until: 0,\n updated_at: timestamp,\n })\n .where('status', '=', 'running')\n .where('lease_until', '<', timestamp)\n .where('lease_until', '>', 0)\n .execute();\n\n return Number(result[0]?.numUpdatedRows ?? 0);\n }\n\n /**\n * Claim a batch of jobs for processing\n */\n async function claimBatch(limit: number): Promise<ClaimedJob[]> {\n const timestamp = now();\n const leaseUntil = timestamp + leaseMs;\n\n // Use a transaction to ensure atomic claim\n return await db.transaction().execute(async (trx) => {\n // Select eligible jobs\n const jobs = await trx\n .selectFrom('workmatic_jobs')\n .select(['id', 'public_id', 'queue', 'payload', 'attempts', 'max_attempts'])\n .where('queue', '=', queue)\n .where('status', '=', 'ready')\n .where('run_at', '<=', timestamp)\n .orderBy('priority', 'asc')\n .orderBy('id', 'asc')\n .limit(limit)\n .execute();\n\n if (jobs.length === 0) {\n return [];\n }\n\n // Get the IDs of claimed jobs\n const jobIds = jobs.map(j => j.id);\n\n // Update them to running status\n await trx\n .updateTable('workmatic_jobs')\n .set({\n status: 'running',\n lease_until: leaseUntil,\n updated_at: timestamp,\n })\n .where('id', 'in', jobIds)\n .execute();\n\n return jobs;\n });\n }\n\n /**\n * Mark a job as completed\n */\n async function markDone(jobId: number): Promise<void> {\n await db\n .updateTable('workmatic_jobs')\n .set({\n status: 'done',\n lease_until: 0,\n updated_at: now(),\n })\n .where('id', '=', jobId)\n .execute();\n }\n\n /**\n * Handle job failure\n */\n async function markFailed(\n jobId: number,\n attempts: number,\n maxAttempts: number,\n error: Error\n ): Promise<void> {\n const timestamp = now();\n const newAttempts = attempts + 1;\n const errorMessage = error.message || String(error);\n\n if (newAttempts < maxAttempts) {\n // Retry: set back to ready with backoff delay\n const runAt = timestamp + backoff(newAttempts);\n \n await db\n .updateTable('workmatic_jobs')\n .set({\n status: 'ready',\n attempts: newAttempts,\n run_at: runAt,\n lease_until: 0,\n last_error: errorMessage,\n updated_at: timestamp,\n })\n .where('id', '=', jobId)\n .execute();\n } else {\n // Max attempts reached: mark as dead\n await db\n .updateTable('workmatic_jobs')\n .set({\n status: 'dead',\n attempts: newAttempts,\n lease_until: 0,\n last_error: errorMessage,\n updated_at: timestamp,\n })\n .where('id', '=', jobId)\n .execute();\n }\n }\n\n /**\n * Run a promise with timeout\n */\n async function withTimeout<T>(\n promise: Promise<T>,\n ms: number,\n jobId: string\n ): Promise<T> {\n let timeoutId: NodeJS.Timeout;\n \n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(`Job ${jobId} timed out after ${ms}ms`));\n }, ms);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n clearTimeout(timeoutId!);\n }\n }\n\n /**\n * Process a single job\n */\n async function processJob(claimedJob: ClaimedJob): Promise<void> {\n if (!processor) {\n throw new Error('No processor set');\n }\n\n // Parse payload and create job object\n const payload = parsePayload(claimedJob.payload);\n const job: Job = {\n id: claimedJob.public_id,\n queue: claimedJob.queue,\n payload,\n status: 'running',\n priority: 0, // Not needed for processing\n attempts: claimedJob.attempts,\n maxAttempts: claimedJob.max_attempts,\n createdAt: 0, // Not needed for processing\n lastError: null,\n };\n\n try {\n // Run processor with optional timeout\n if (timeoutMs) {\n await withTimeout(processor(job), timeoutMs, job.id);\n } else {\n await processor(job);\n }\n await markDone(claimedJob.id);\n } catch (error) {\n await markFailed(\n claimedJob.id,\n claimedJob.attempts,\n claimedJob.max_attempts,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n /**\n * Check if queue is paused in database (for CLI control)\n */\n async function isQueuePausedInDb(): Promise<boolean> {\n const setting = await db\n .selectFrom('workmatic_settings')\n .select('paused')\n .where('queue', '=', queue)\n .executeTakeFirst();\n \n return setting?.paused === 1;\n }\n\n /**\n * Main pump loop\n */\n async function pump(): Promise<void> {\n if (!running) {\n return;\n }\n\n // Check both in-memory pause and database pause (for CLI control)\n if (paused) {\n pumpTimeout = setTimeout(pump, pollMs);\n return;\n }\n\n try {\n // Check database pause state (allows CLI to pause running workers)\n const dbPaused = await isQueuePausedInDb();\n if (dbPaused) {\n pumpTimeout = setTimeout(pump, pollMs);\n return;\n }\n\n // Requeue expired leases\n await requeueExpiredLeases();\n\n // Claim a batch of jobs\n const batchSize = concurrency * 2;\n const jobs = await claimBatch(batchSize);\n\n if (jobs.length > 0) {\n // Push jobs into fastq\n for (const job of jobs) {\n fastqQueue!.push(job);\n }\n // Immediately pump again\n pumpTimeout = setTimeout(pump, 0);\n } else {\n // No jobs, wait before polling again\n pumpTimeout = setTimeout(pump, pollMs);\n }\n } catch (error) {\n // Log error and continue\n console.error('[workmatic] Pump error:', error);\n pumpTimeout = setTimeout(pump, pollMs);\n }\n }\n\n // Create the worker object\n const worker: WorkmaticWorker = {\n process<TPayload = unknown>(fn: JobProcessor<TPayload>): void {\n processor = fn as JobProcessor<any>;\n },\n\n start(): void {\n if (running) {\n return;\n }\n\n if (!processor) {\n throw new Error('No processor set. Call process() before start()');\n }\n\n running = true;\n paused = false;\n\n // Create fastq queue\n fastqQueue = fastq.promise(processJob, concurrency);\n\n // Save state to database\n saveState('running').catch(() => {});\n\n // Start pump loop\n pump();\n },\n\n async stop(): Promise<void> {\n if (!running) {\n return;\n }\n\n running = false;\n\n // Clear pump timeout\n if (pumpTimeout) {\n clearTimeout(pumpTimeout);\n pumpTimeout = null;\n }\n\n // Wait for fastq to drain\n if (fastqQueue) {\n await fastqQueue.drained();\n fastqQueue = null;\n }\n\n // Save state to database\n await saveState('stopped');\n },\n\n pause(): void {\n paused = true;\n saveState('paused').catch(() => {});\n },\n\n resume(): void {\n paused = false;\n saveState('running').catch(() => {});\n },\n\n async stats(): Promise<JobStats> {\n const result = await db\n .selectFrom('workmatic_jobs')\n .select([\n 'status',\n sql<number>`count(*)`.as('count'),\n ])\n .where('queue', '=', queue)\n .groupBy('status')\n .execute();\n\n const stats: JobStats = {\n ready: 0,\n running: 0,\n done: 0,\n failed: 0,\n dead: 0,\n total: 0,\n };\n\n for (const row of result) {\n const status = row.status as JobStatus;\n const count = Number(row.count);\n if (status in stats) {\n stats[status] = count;\n }\n stats.total += count;\n }\n\n return stats;\n },\n\n get isRunning(): boolean {\n return running;\n },\n\n get isPaused(): boolean {\n return paused;\n },\n\n get queue(): string {\n return queue;\n },\n\n async restoreState(): Promise<WorkerState | null> {\n const state = await loadState();\n if (state === 'running' && processor) {\n this.start();\n } else if (state === 'paused' && processor) {\n this.start();\n this.pause();\n }\n return state;\n },\n\n async clear(options: { status?: JobStatus } = {}): Promise<number> {\n let query = db\n .deleteFrom('workmatic_jobs')\n .where('queue', '=', queue);\n\n if (options.status) {\n query = query.where('status', '=', options.status);\n }\n\n const result = await query.execute();\n return Number(result[0]?.numDeletedRows ?? 0);\n },\n };\n\n // Auto-restore state if enabled\n if (persistState && autoRestore) {\n // Use setImmediate to allow processor to be set first\n setImmediate(async () => {\n if (processor) {\n await worker.restoreState();\n }\n });\n }\n\n return worker;\n}\n","import { createServer, IncomingMessage, ServerResponse } from 'http';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { readFile } from 'fs/promises';\nimport { sql } from 'kysely';\nimport type {\n WorkmaticDb,\n DashboardOptions,\n DashboardMiddlewareOptions,\n WorkmaticDashboard,\n WorkmaticWorker,\n DashboardMiddleware,\n JobStats,\n JobStatus,\n} from './types.js';\n\n// Get the directory of this module for static file serving\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Content types for static files\nconst CONTENT_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n};\n\n/**\n * Create the core request handler (shared between standalone and middleware)\n */\nfunction createRequestHandler(\n db: WorkmaticDb,\n workerMap: Map<string, WorkmaticWorker>,\n basePath: string = ''\n) {\n /**\n * Send JSON response\n */\n function sendJson(res: ServerResponse, data: unknown, status = 200): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n }\n\n /**\n * Send error response\n */\n function sendError(res: ServerResponse, message: string, status = 500): void {\n sendJson(res, { error: message }, status);\n }\n\n /**\n * Parse URL query parameters\n */\n function parseQuery(url: string): URLSearchParams {\n const queryIndex = url.indexOf('?');\n if (queryIndex === -1) return new URLSearchParams();\n return new URLSearchParams(url.slice(queryIndex + 1));\n }\n\n /**\n * Get path from URL (removing basePath prefix)\n */\n function getPath(url: string): string {\n const queryIndex = url.indexOf('?');\n let path = queryIndex === -1 ? url : url.slice(0, queryIndex);\n \n // Remove basePath prefix if present\n if (basePath && path.startsWith(basePath)) {\n path = path.slice(basePath.length) || '/';\n }\n \n return path;\n }\n\n /**\n * API: Get jobs list\n */\n async function handleGetJobs(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const query = parseQuery(req.url || '');\n const queueFilter = query.get('queue');\n const statusFilter = query.get('status') as JobStatus | null;\n const limit = Math.min(parseInt(query.get('limit') || '50', 10), 100);\n const offset = parseInt(query.get('offset') || '0', 10);\n\n let queryBuilder = db\n .selectFrom('workmatic_jobs')\n .select([\n 'public_id',\n 'queue',\n 'payload',\n 'status',\n 'priority',\n 'attempts',\n 'max_attempts',\n 'run_at',\n 'created_at',\n 'updated_at',\n 'last_error',\n ])\n .orderBy('created_at', 'desc')\n .limit(limit)\n .offset(offset);\n\n if (queueFilter) {\n queryBuilder = queryBuilder.where('queue', '=', queueFilter);\n }\n if (statusFilter) {\n queryBuilder = queryBuilder.where('status', '=', statusFilter);\n }\n\n const jobs = await queryBuilder.execute();\n\n // Transform to API format\n const apiJobs = jobs.map(job => ({\n id: job.public_id,\n queue: job.queue,\n payload: JSON.parse(job.payload),\n status: job.status,\n priority: job.priority,\n attempts: job.attempts,\n maxAttempts: job.max_attempts,\n runAt: job.run_at,\n createdAt: job.created_at,\n updatedAt: job.updated_at,\n lastError: job.last_error,\n }));\n\n sendJson(res, { jobs: apiJobs, limit, offset });\n }\n\n /**\n * API: Get statistics\n */\n async function handleGetStats(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const query = parseQuery(req.url || '');\n const queueFilter = query.get('queue');\n\n // Get counts by status\n let statsQuery = db\n .selectFrom('workmatic_jobs')\n .select([\n 'status',\n sql<number>`count(*)`.as('count'),\n ])\n .groupBy('status');\n\n if (queueFilter) {\n statsQuery = statsQuery.where('queue', '=', queueFilter);\n }\n\n const statusCounts = await statsQuery.execute();\n\n const stats: JobStats = {\n ready: 0,\n running: 0,\n done: 0,\n failed: 0,\n dead: 0,\n total: 0,\n };\n\n for (const row of statusCounts) {\n const status = row.status as JobStatus;\n const count = Number(row.count);\n if (status in stats) {\n stats[status] = count;\n }\n stats.total += count;\n }\n\n // Get queue list\n const queuesResult = await db\n .selectFrom('workmatic_jobs')\n .select('queue')\n .groupBy('queue')\n .execute();\n\n const queues = queuesResult.map(q => q.queue);\n\n // Get worker status\n const workersStatus = Array.from(workerMap.entries()).map(([queue, worker]) => ({\n queue,\n running: worker.isRunning,\n paused: worker.isPaused,\n }));\n\n sendJson(res, { stats, queues, workers: workersStatus });\n }\n\n /**\n * API: Get single job by ID\n */\n async function handleGetJob(req: IncomingMessage, res: ServerResponse, publicId: string): Promise<void> {\n const job = await db\n .selectFrom('workmatic_jobs')\n .select([\n 'public_id',\n 'queue',\n 'payload',\n 'status',\n 'priority',\n 'attempts',\n 'max_attempts',\n 'run_at',\n 'lease_until',\n 'created_at',\n 'updated_at',\n 'last_error',\n ])\n .where('public_id', '=', publicId)\n .executeTakeFirst();\n\n if (!job) {\n return sendError(res, 'Job not found', 404);\n }\n\n sendJson(res, {\n id: job.public_id,\n queue: job.queue,\n payload: JSON.parse(job.payload),\n status: job.status,\n priority: job.priority,\n attempts: job.attempts,\n maxAttempts: job.max_attempts,\n runAt: job.run_at,\n leaseUntil: job.lease_until,\n createdAt: job.created_at,\n updatedAt: job.updated_at,\n lastError: job.last_error,\n });\n }\n\n /**\n * API: Pause worker\n */\n async function handlePauseWorker(res: ServerResponse, queue: string): Promise<void> {\n const worker = workerMap.get(queue);\n if (!worker) {\n return sendError(res, `Worker for queue '${queue}' not found`, 404);\n }\n worker.pause();\n sendJson(res, { ok: true, queue, paused: true });\n }\n\n /**\n * API: Resume worker\n */\n async function handleResumeWorker(res: ServerResponse, queue: string): Promise<void> {\n const worker = workerMap.get(queue);\n if (!worker) {\n return sendError(res, `Worker for queue '${queue}' not found`, 404);\n }\n worker.resume();\n sendJson(res, { ok: true, queue, paused: false });\n }\n\n /**\n * Serve static files from the dashboard directory\n */\n async function serveStatic(res: ServerResponse, filePath: string): Promise<void> {\n // Navigate from dist/dashboard.js to dashboard/ directory\n const dashboardDir = join(__dirname, '..', 'dashboard');\n const fullPath = join(dashboardDir, filePath);\n \n // Determine content type\n const ext = filePath.substring(filePath.lastIndexOf('.')) || '.html';\n const contentType = CONTENT_TYPES[ext] || 'application/octet-stream';\n\n try {\n const content = await readFile(fullPath, 'utf-8');\n res.writeHead(200, { 'Content-Type': contentType });\n res.end(content);\n } catch (error) {\n sendError(res, 'Not found', 404);\n }\n }\n\n /**\n * Main request handler\n */\n return async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n next?: () => void\n ): Promise<boolean> {\n const path = getPath(req.url || '/');\n\n // Check if this request is for the dashboard\n const fullUrl = req.url || '/';\n if (basePath && !fullUrl.startsWith(basePath)) {\n // Not our route, call next middleware if available\n if (next) next();\n return false;\n }\n\n // CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return true;\n }\n\n try {\n // API routes\n if (path === '/api/jobs' && req.method === 'GET') {\n await handleGetJobs(req, res);\n return true;\n }\n\n if (path === '/api/stats' && req.method === 'GET') {\n await handleGetStats(req, res);\n return true;\n }\n\n // Single job: /api/jobs/:id\n const jobMatch = path.match(/^\\/api\\/jobs\\/([^/]+)$/);\n if (jobMatch && req.method === 'GET') {\n await handleGetJob(req, res, jobMatch[1]);\n return true;\n }\n\n // Pause worker: /api/workers/:queue/pause\n const pauseMatch = path.match(/^\\/api\\/workers\\/([^/]+)\\/pause$/);\n if (pauseMatch && req.method === 'POST') {\n await handlePauseWorker(res, pauseMatch[1]);\n return true;\n }\n\n // Resume worker: /api/workers/:queue/resume\n const resumeMatch = path.match(/^\\/api\\/workers\\/([^/]+)\\/resume$/);\n if (resumeMatch && req.method === 'POST') {\n await handleResumeWorker(res, resumeMatch[1]);\n return true;\n }\n\n // Static files\n if (path === '/' || path === '/index.html') {\n await serveStatic(res, 'index.html');\n return true;\n }\n if (path === '/style.css') {\n await serveStatic(res, 'style.css');\n return true;\n }\n if (path === '/app.js') {\n await serveStatic(res, 'app.js');\n return true;\n }\n\n // 404 for unknown routes under our basePath\n sendError(res, 'Not found', 404);\n return true;\n } catch (error) {\n console.error('[workmatic] Dashboard error:', error);\n sendError(res, 'Internal server error', 500);\n return true;\n }\n };\n}\n\n/**\n * Create a dashboard HTTP server for monitoring and controlling the job queue\n * \n * @param options - Dashboard options\n * @returns Dashboard instance\n * \n * @example\n * ```ts\n * const dashboard = createDashboard({ \n * db, \n * port: 3000,\n * workers: [worker1, worker2] \n * });\n * \n * console.log(`Dashboard running at http://localhost:${dashboard.port}`);\n * \n * // Later, close the server\n * await dashboard.close();\n * ```\n */\nexport function createDashboard(options: DashboardOptions): WorkmaticDashboard {\n const {\n db,\n port = 3000,\n workers = [],\n } = options;\n\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n // Worker registry by queue name\n const workerMap = new Map<string, WorkmaticWorker>();\n for (const worker of workers) {\n workerMap.set(worker.queue, worker);\n }\n\n const handleRequest = createRequestHandler(db, workerMap);\n\n // Create and start HTTP server\n const server = createServer((req, res) => {\n handleRequest(req, res).catch(error => {\n console.error('[workmatic] Unhandled error:', error);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Internal server error' }));\n });\n });\n\n server.listen(port);\n\n return {\n async close(): Promise<void> {\n return new Promise((resolve, reject) => {\n server.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n },\n\n get port(): number {\n return port;\n },\n };\n}\n\n/**\n * Create an Express-compatible middleware for the dashboard\n * \n * @param options - Middleware options\n * @returns Express middleware function\n * \n * @example\n * ```ts\n * import express from 'express';\n * import { createDashboardMiddleware } from 'workmatic';\n * \n * const app = express();\n * \n * // Mount dashboard at /workmatic\n * app.use(createDashboardMiddleware({ \n * db,\n * basePath: '/workmatic',\n * workers: [worker] \n * }));\n * \n * app.listen(3000);\n * // Dashboard available at http://localhost:3000/workmatic\n * ```\n */\nexport function createDashboardMiddleware(options: DashboardMiddlewareOptions): DashboardMiddleware {\n const {\n db,\n workers = [],\n basePath = '',\n } = options;\n\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n // Worker registry by queue name\n const workerMap = new Map<string, WorkmaticWorker>();\n for (const worker of workers) {\n workerMap.set(worker.queue, worker);\n }\n\n const handleRequest = createRequestHandler(db, workerMap, basePath);\n\n return (req, res, next) => {\n handleRequest(req, res, next).catch(error => {\n console.error('[workmatic] Unhandled error:', error);\n if (next) {\n next();\n } else {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Internal server error' }));\n }\n });\n };\n}\n"],"mappings":"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","names":["Database","import_kysely","options","import_kysely","fastq","options","import_kysely","__filename"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../node_modules/tsup/assets/cjs_shims.js","../src/database.ts","../src/client.ts","../src/utils.ts","../src/worker.ts","../src/orchestrator.ts","../src/dashboard.ts"],"sourcesContent":["/**\n * Workmatic - A persistent job queue for Node.js\n * \n * @packageDocumentation\n */\n\n// Main exports\nexport { createDatabase, getUnderlyingDb } from './database.js';\nexport { createClient } from './client.js';\nexport { createWorker, DEFAULT_WORKER_TIMEOUT_MS } from './worker.js';\nexport { createOrchestrator } from './orchestrator.js';\nexport { createDashboard, createDashboardMiddleware } from './dashboard.js';\n\n// Utility exports\nexport { defaultBackoff, validatePayload } from './utils.js';\n\n// Type exports\nexport type {\n // Core types\n Job,\n JobStatus,\n JobStats,\n ClaimedJob,\n WorkerState,\n \n // Options\n AddJobOptions,\n AddJobResult,\n AddManyResult,\n DatabaseOptions,\n ClientOptions,\n WorkerOptions,\n OrchestratorOptions,\n RegisterQueueOptions,\n TransferOptions,\n TransferResult,\n MoveJobOptions,\n DashboardOptions,\n DashboardMiddlewareOptions,\n BackoffFunction,\n JobProcessor,\n \n // Interfaces\n WorkmaticClient,\n WorkmaticWorker,\n WorkmaticOrchestrator,\n WorkmaticDashboard,\n DashboardMiddleware,\n WorkmaticDb,\n WorkmaticDatabase,\n WorkmaticJobsTable,\n} from './types.js';\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import Database from 'better-sqlite3';\nimport { Kysely, SqliteDialect } from 'kysely';\nimport type { WorkmaticDatabase, WorkmaticDb, DatabaseOptions } from './types.js';\n\n/** Maps Kysely instances created via {@link createDatabase} to the underlying driver DB. */\nconst kyselyToSqlite = new WeakMap<WorkmaticDb, Database.Database>();\n\n/**\n * Create and initialize the workmatic database\n * \n * @param options - Database options\n * @returns Kysely database instance\n * \n * @example\n * ```ts\n * // Using a file path\n * const db = createDatabase({ filename: './jobs.db' });\n * \n * // Using an existing better-sqlite3 instance\n * import Database from 'better-sqlite3';\n * const sqlite = new Database('./jobs.db');\n * const db = createDatabase({ db: sqlite });\n * \n * // In-memory database (for testing)\n * const db = createDatabase({ filename: ':memory:' });\n * ```\n */\nexport function createDatabase(options: DatabaseOptions = {}): WorkmaticDb {\n let sqliteDb: Database.Database;\n\n if (options.db) {\n sqliteDb = options.db;\n } else {\n const filename = options.filename ?? ':memory:';\n sqliteDb = new Database(filename);\n }\n\n // Set pragmas for performance and safety\n sqliteDb.pragma('journal_mode = WAL');\n sqliteDb.pragma('synchronous = NORMAL');\n sqliteDb.pragma('busy_timeout = 5000');\n\n // Create Kysely instance\n const db = new Kysely<WorkmaticDatabase>({\n dialect: new SqliteDialect({\n database: sqliteDb,\n }),\n });\n\n // Create schema synchronously using better-sqlite3 directly\n createSchema(sqliteDb);\n\n kyselyToSqlite.set(db, sqliteDb);\n\n return db;\n}\n\n/**\n * Create the database schema if it doesn't exist\n */\nfunction createSchema(db: Database.Database): void {\n // Create the jobs table\n db.exec(`\n CREATE TABLE IF NOT EXISTS workmatic_jobs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n public_id TEXT UNIQUE NOT NULL,\n queue TEXT NOT NULL,\n payload TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'ready',\n priority INTEGER NOT NULL DEFAULT 0,\n run_at INTEGER NOT NULL,\n attempts INTEGER NOT NULL DEFAULT 0,\n max_attempts INTEGER NOT NULL DEFAULT 3,\n lease_until INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n last_error TEXT\n )\n `);\n\n // Create composite index for efficient job claiming\n // (queue, status, run_at, priority, id)\n db.exec(`\n CREATE INDEX IF NOT EXISTS idx_workmatic_jobs_claim \n ON workmatic_jobs (queue, status, run_at, priority, id)\n `);\n\n // Create index for lease expiration checking\n // (status, lease_until)\n db.exec(`\n CREATE INDEX IF NOT EXISTS idx_workmatic_jobs_lease \n ON workmatic_jobs (status, lease_until)\n `);\n\n // Create settings table for queue-level settings (pause state, etc.)\n db.exec(`\n CREATE TABLE IF NOT EXISTS workmatic_settings (\n queue TEXT PRIMARY KEY,\n paused INTEGER NOT NULL DEFAULT 0,\n updated_at INTEGER NOT NULL\n )\n `);\n\n // Legacy status no longer used in the state machine (retries use `ready`, terminal errors use `dead`)\n db.exec(`\n UPDATE workmatic_jobs SET status = 'dead' WHERE status = 'failed'\n `);\n}\n\n/**\n * Get the underlying better-sqlite3 database instance from a Kysely instance\n * created with {@link createDatabase}. For manually constructed `Kysely` instances,\n * falls back to reading the dialect adapter (may break across Kysely versions).\n */\nexport function getUnderlyingDb(db: WorkmaticDb): Database.Database {\n const mapped = kyselyToSqlite.get(db);\n if (mapped) {\n return mapped;\n }\n try {\n const ex = (db as unknown as { getExecutor?: () => { adapter: { db: Database.Database } } })\n .getExecutor?.();\n const dialect = ex?.adapter?.db;\n if (dialect) {\n return dialect;\n }\n } catch {\n /* ignore */\n }\n throw new Error(\n 'getUnderlyingDb: could not resolve better-sqlite3 instance (use createDatabase() or pass db from it)'\n );\n}\n","import { nanoid } from 'nanoid';\nimport { sql } from 'kysely';\nimport type {\n WorkmaticDb,\n ClientOptions,\n WorkmaticClient,\n AddJobOptions,\n AddJobResult,\n AddManyResult,\n JobStats,\n JobStatus,\n} from './types.js';\nimport { validatePayload, now } from './utils.js';\n\n/**\n * Create a job queue client for adding jobs\n * \n * @param options - Client options\n * @returns Client instance\n * \n * @example\n * ```ts\n * const client = createClient({ db });\n * \n * // Add a simple job\n * const result = await client.add({ email: 'user@example.com' });\n * console.log(result.id); // Job public ID\n * \n * // Add a job with options\n * await client.add(\n * { userId: 123 },\n * { priority: 1, delayMs: 5000, maxAttempts: 5 }\n * );\n * \n * // Get queue statistics\n * const stats = await client.stats();\n * console.log(stats); // { ready: 5, running: 2, done: 100, ... }\n * ```\n */\nexport function createClient(options: ClientOptions): WorkmaticClient {\n const { db, queue = 'default' } = options;\n\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n return {\n /**\n * Add a job to the queue\n */\n async add<TPayload = unknown>(\n payload: TPayload,\n opts: AddJobOptions = {}\n ): Promise<AddJobResult> {\n const {\n priority = 0,\n delayMs = 0,\n maxAttempts = 3,\n } = opts;\n\n // Validate and serialize payload\n const payloadJson = validatePayload(payload);\n \n // Generate unique public ID\n const publicId = nanoid();\n \n const timestamp = now();\n const runAt = timestamp + delayMs;\n\n // Insert job\n await db\n .insertInto('workmatic_jobs')\n .values({\n public_id: publicId,\n queue,\n payload: payloadJson,\n status: 'ready',\n priority,\n run_at: runAt,\n attempts: 0,\n max_attempts: maxAttempts,\n lease_until: 0,\n created_at: timestamp,\n updated_at: timestamp,\n last_error: null,\n })\n .execute();\n\n return { ok: true, id: publicId };\n },\n\n async addMany<TPayload = unknown>(\n payloads: TPayload[],\n opts: AddJobOptions = {}\n ): Promise<AddManyResult> {\n const {\n priority = 0,\n delayMs = 0,\n maxAttempts = 3,\n } = opts;\n\n if (payloads.length === 0) {\n return { ok: true, ids: [] };\n }\n\n const timestamp = now();\n const runAt = timestamp + delayMs;\n\n return await db.transaction().execute(async (trx) => {\n const ids: string[] = [];\n const rows = payloads.map((payload) => {\n const payloadJson = validatePayload(payload);\n const publicId = nanoid();\n ids.push(publicId);\n return {\n public_id: publicId,\n queue,\n payload: payloadJson,\n status: 'ready' as const,\n priority,\n run_at: runAt,\n attempts: 0,\n max_attempts: maxAttempts,\n lease_until: 0,\n created_at: timestamp,\n updated_at: timestamp,\n last_error: null,\n };\n });\n\n await trx.insertInto('workmatic_jobs').values(rows).execute();\n return { ok: true, ids };\n });\n },\n\n /**\n * Get job statistics for the queue\n */\n async stats(): Promise<JobStats> {\n const result = await db\n .selectFrom('workmatic_jobs')\n .select([\n 'status',\n sql<number>`count(*)`.as('count'),\n ])\n .where('queue', '=', queue)\n .groupBy('status')\n .execute();\n\n const stats: JobStats = {\n ready: 0,\n running: 0,\n done: 0,\n dead: 0,\n total: 0,\n };\n\n for (const row of result) {\n const status = row.status as JobStatus;\n const count = Number(row.count);\n if (status in stats) {\n stats[status] = count;\n }\n stats.total += count;\n }\n\n return stats;\n },\n\n /**\n * Clear all jobs from the queue\n */\n async clear(options: { status?: JobStatus } = {}): Promise<number> {\n let query = db\n .deleteFrom('workmatic_jobs')\n .where('queue', '=', queue);\n\n if (options.status) {\n query = query.where('status', '=', options.status);\n }\n\n const result = await query.execute();\n return Number(result[0]?.numDeletedRows ?? 0);\n },\n };\n}\n","import type { BackoffFunction } from './types.js';\n\n/**\n * Default exponential backoff function\n * Returns delay in milliseconds: 1000 * 2^attempts\n * \n * @param attempts - Number of failed attempts\n * @returns Delay in milliseconds\n * \n * @example\n * ```ts\n * defaultBackoff(0) // 1000ms (1 second)\n * defaultBackoff(1) // 2000ms (2 seconds)\n * defaultBackoff(2) // 4000ms (4 seconds)\n * defaultBackoff(3) // 8000ms (8 seconds)\n * ```\n */\nexport const defaultBackoff: BackoffFunction = (attempts: number): number => {\n return 1000 * Math.pow(2, attempts);\n};\n\n/**\n * Validate that a payload is JSON-serializable\n * \n * @param payload - The payload to validate\n * @throws Error if payload cannot be serialized to JSON\n * @returns The JSON string representation\n */\nexport function validatePayload(payload: unknown): string {\n try {\n return JSON.stringify(payload);\n } catch (error) {\n throw new Error(\n `Payload is not JSON-serializable: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n}\n\n/**\n * Parse a JSON payload safely\n * \n * @param json - JSON string to parse\n * @returns Parsed payload\n * @throws Error if JSON is invalid\n */\nexport function parsePayload<T = unknown>(json: string): T {\n try {\n return JSON.parse(json) as T;\n } catch (error) {\n throw new Error(\n `Invalid JSON payload: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n}\n\n/**\n * Sleep for a specified duration\n * \n * @param ms - Duration in milliseconds\n * @returns Promise that resolves after the duration\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Get current timestamp in milliseconds\n */\nexport function now(): number {\n return Date.now();\n}\n","import fastq from 'fastq';\nimport type { queueAsPromised } from 'fastq';\nimport { sql } from 'kysely';\nimport type {\n WorkmaticDb,\n WorkerOptions,\n WorkmaticWorker,\n JobProcessor,\n JobStats,\n JobStatus,\n Job,\n ClaimedJob,\n WorkerState,\n} from './types.js';\nimport { defaultBackoff, parsePayload, now } from './utils.js';\n\n/** Default job execution timeout when `timeoutMs` is omitted (1 minute). Use `timeoutMs: 0` for no limit. */\nexport const DEFAULT_WORKER_TIMEOUT_MS = 60_000;\n\n/** @internal Exported for tests — maps SQLite RETURNING result to claimed jobs */\nexport function parseClaimedRows(result: unknown): ClaimedJob[] {\n const rows = (result as { rows?: ClaimedJob[] }).rows;\n if (!rows || !Array.isArray(rows)) {\n return [];\n }\n return rows.map((row) => ({\n id: row.id,\n public_id: row.public_id,\n queue: row.queue,\n payload: row.payload,\n attempts: row.attempts,\n max_attempts: row.max_attempts,\n priority: row.priority,\n created_at: row.created_at,\n last_error: row.last_error,\n }));\n}\n\n/** @internal Exported for tests */\nexport function requireProcessor<T>(processor: JobProcessor<T> | null): JobProcessor<T> {\n if (!processor) {\n throw new Error('No processor set');\n }\n return processor;\n}\n\n/**\n * Create a job queue worker for processing jobs\n * \n * @param options - Worker options\n * @returns Worker instance\n * \n * @example\n * ```ts\n * const worker = createWorker({ db, concurrency: 4 });\n * \n * // Set the processor function\n * worker.process(async (job) => {\n * console.log('Processing job:', job.id);\n * await sendEmail(job.payload.email);\n * });\n * \n * // Start processing\n * worker.start();\n * \n * // Later, gracefully stop\n * await worker.stop();\n * ```\n */\nexport function createWorker(options: WorkerOptions): WorkmaticWorker {\n const {\n db,\n queue = 'default',\n concurrency = 1,\n leaseMs = 30000,\n pollMs = 1000,\n timeoutMs = DEFAULT_WORKER_TIMEOUT_MS,\n backoff = defaultBackoff,\n persistState = false,\n autoRestore = true,\n pauseCheckIntervalMs = 300,\n requeueExpiredIntervalMs = 0,\n onPumpError,\n } = options;\n\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n // State\n let running = false;\n let paused = false;\n let processor: JobProcessor<any> | null = null;\n let pumpTimeout: NodeJS.Timeout | null = null;\n let fastqQueue: queueAsPromised<ClaimedJob, void> | null = null;\n let lastPauseCheckAt = 0;\n let cachedDbPaused = false;\n let lastRequeueAt = 0;\n\n function notifyPumpError(error: unknown): void {\n console.error('[workmatic] Pump error:', error);\n onPumpError?.(error);\n }\n\n /**\n * Get the settings key for this worker's state\n */\n function getStateKey(): string {\n return `worker_state_${queue}`;\n }\n\n /**\n * Save worker state to database\n */\n async function saveState(state: WorkerState): Promise<void> {\n if (!persistState) return;\n\n const timestamp = now();\n const key = getStateKey();\n\n // Use raw SQL for upsert since different SQLite versions have different syntax\n await sql`\n INSERT INTO workmatic_settings (queue, paused, updated_at)\n VALUES (${key}, ${state === 'paused' ? 1 : state === 'running' ? 2 : 0}, ${timestamp})\n ON CONFLICT(queue) DO UPDATE SET \n paused = ${state === 'paused' ? 1 : state === 'running' ? 2 : 0},\n updated_at = ${timestamp}\n `.execute(db);\n }\n\n /**\n * Load worker state from database\n */\n async function loadState(): Promise<WorkerState | null> {\n if (!persistState) return null;\n\n try {\n const key = getStateKey();\n const result = await db\n .selectFrom('workmatic_settings')\n .select('paused')\n .where('queue', '=', key)\n .executeTakeFirst();\n\n if (!result) return null;\n \n // paused: 0 = stopped, 1 = paused, 2 = running\n if (result.paused === 2) return 'running';\n if (result.paused === 1) return 'paused';\n return 'stopped';\n } catch {\n return null;\n }\n }\n\n /**\n * Requeue jobs with expired leases\n */\n async function requeueExpiredLeases(): Promise<number> {\n const timestamp = now();\n\n const result = await db\n .updateTable('workmatic_jobs')\n .set({\n status: 'ready',\n lease_until: 0,\n updated_at: timestamp,\n })\n .where('status', '=', 'running')\n .where('lease_until', '<', timestamp)\n .where('lease_until', '>', 0)\n .execute();\n\n return Number(result[0]?.numUpdatedRows ?? 0);\n }\n\n /**\n * Claim a batch of jobs for processing (single UPDATE … RETURNING per SQLite 3.35+)\n */\n async function claimBatch(limit: number): Promise<ClaimedJob[]> {\n const timestamp = now();\n const leaseUntil = timestamp + leaseMs;\n\n return await db.transaction().execute(async (trx) => {\n const result = await sql<{\n id: number;\n public_id: string;\n queue: string;\n payload: string;\n attempts: number;\n max_attempts: number;\n priority: number;\n created_at: number;\n last_error: string | null;\n }>`\n UPDATE workmatic_jobs\n SET status = 'running', lease_until = ${leaseUntil}, updated_at = ${timestamp}\n WHERE rowid IN (\n SELECT rowid FROM workmatic_jobs\n WHERE queue = ${queue}\n AND status = 'ready'\n AND run_at <= ${timestamp}\n ORDER BY priority ASC, id ASC\n LIMIT ${limit}\n )\n RETURNING id, public_id, queue, payload, attempts, max_attempts, priority, created_at, last_error\n `.execute(trx);\n\n return parseClaimedRows(result);\n });\n }\n\n /**\n * Mark a job as completed\n */\n async function markDone(jobId: number): Promise<void> {\n await db\n .updateTable('workmatic_jobs')\n .set({\n status: 'done',\n lease_until: 0,\n updated_at: now(),\n })\n .where('id', '=', jobId)\n .execute();\n }\n\n /**\n * Handle job failure\n */\n async function markFailed(\n jobId: number,\n attempts: number,\n maxAttempts: number,\n error: Error\n ): Promise<void> {\n const timestamp = now();\n const newAttempts = attempts + 1;\n const errorMessage = error.message || String(error);\n\n if (newAttempts < maxAttempts) {\n // Retry: set back to ready with backoff delay\n const runAt = timestamp + backoff(newAttempts);\n \n await db\n .updateTable('workmatic_jobs')\n .set({\n status: 'ready',\n attempts: newAttempts,\n run_at: runAt,\n lease_until: 0,\n last_error: errorMessage,\n updated_at: timestamp,\n })\n .where('id', '=', jobId)\n .execute();\n } else {\n // Max attempts reached: mark as dead\n await db\n .updateTable('workmatic_jobs')\n .set({\n status: 'dead',\n attempts: newAttempts,\n lease_until: 0,\n last_error: errorMessage,\n updated_at: timestamp,\n })\n .where('id', '=', jobId)\n .execute();\n }\n }\n\n /**\n * Run a promise with timeout\n */\n async function withTimeout<T>(\n promise: Promise<T>,\n ms: number,\n jobId: string\n ): Promise<T> {\n let timeoutId: NodeJS.Timeout;\n \n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(`Job ${jobId} timed out after ${ms}ms`));\n }, ms);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n clearTimeout(timeoutId!);\n }\n }\n\n /**\n * Process a single job\n */\n async function processJob(claimedJob: ClaimedJob): Promise<void> {\n const fn = requireProcessor(processor);\n\n // Parse payload and create job object\n const payload = parsePayload(claimedJob.payload);\n const job: Job = {\n id: claimedJob.public_id,\n queue: claimedJob.queue,\n payload,\n status: 'running',\n priority: claimedJob.priority,\n attempts: claimedJob.attempts,\n maxAttempts: claimedJob.max_attempts,\n createdAt: claimedJob.created_at,\n lastError: claimedJob.last_error,\n };\n\n try {\n // Run processor with optional timeout\n if (timeoutMs) {\n await withTimeout(fn(job), timeoutMs, job.id);\n } else {\n await fn(job);\n }\n await markDone(claimedJob.id);\n } catch (error) {\n await markFailed(\n claimedJob.id,\n claimedJob.attempts,\n claimedJob.max_attempts,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n /**\n * Check if queue is paused in database (for CLI control)\n */\n async function isQueuePausedInDb(): Promise<boolean> {\n const setting = await db\n .selectFrom('workmatic_settings')\n .select('paused')\n .where('queue', '=', queue)\n .executeTakeFirst();\n \n return setting?.paused === 1;\n }\n\n /**\n * Main pump loop\n */\n async function pump(): Promise<void> {\n if (!running) {\n return;\n }\n\n // Check both in-memory pause and database pause (for CLI control)\n if (paused) {\n pumpTimeout = setTimeout(pump, pollMs);\n return;\n }\n\n try {\n const t = now();\n if (t - lastPauseCheckAt >= pauseCheckIntervalMs) {\n lastPauseCheckAt = t;\n cachedDbPaused = await isQueuePausedInDb();\n }\n if (cachedDbPaused) {\n pumpTimeout = setTimeout(pump, pollMs);\n return;\n }\n\n if (\n requeueExpiredIntervalMs <= 0 ||\n t - lastRequeueAt >= requeueExpiredIntervalMs\n ) {\n if (requeueExpiredIntervalMs > 0) {\n lastRequeueAt = t;\n }\n await requeueExpiredLeases();\n }\n\n // Claim a batch of jobs\n const batchSize = concurrency * 2;\n const jobs = await claimBatch(batchSize);\n\n if (jobs.length > 0) {\n // Push jobs into fastq\n for (const job of jobs) {\n fastqQueue!.push(job);\n }\n // Immediately pump again\n pumpTimeout = setTimeout(pump, 0);\n } else {\n // No jobs, wait before polling again\n pumpTimeout = setTimeout(pump, pollMs);\n }\n } catch (error) {\n notifyPumpError(error);\n pumpTimeout = setTimeout(pump, pollMs);\n }\n }\n\n // Create the worker object\n const worker: WorkmaticWorker = {\n process<TPayload = unknown>(fn: JobProcessor<TPayload>): void {\n processor = fn as JobProcessor<any>;\n },\n\n start(): void {\n if (running) {\n return;\n }\n\n if (!processor) {\n throw new Error('No processor set. Call process() before start()');\n }\n\n running = true;\n paused = false;\n\n // Create fastq queue\n fastqQueue = fastq.promise(processJob, concurrency);\n\n // Save state to database\n saveState('running').catch(() => {});\n\n // Start pump loop\n pump();\n },\n\n async stop(): Promise<void> {\n if (!running) {\n return;\n }\n\n running = false;\n\n // Clear pump timeout\n if (pumpTimeout) {\n clearTimeout(pumpTimeout);\n pumpTimeout = null;\n }\n\n // Wait for fastq to drain\n if (fastqQueue) {\n await fastqQueue.drained();\n fastqQueue = null;\n }\n\n // Save state to database\n await saveState('stopped');\n },\n\n pause(): void {\n paused = true;\n saveState('paused').catch(() => {});\n },\n\n resume(): void {\n paused = false;\n saveState('running').catch(() => {});\n },\n\n async stats(): Promise<JobStats> {\n const result = await db\n .selectFrom('workmatic_jobs')\n .select([\n 'status',\n sql<number>`count(*)`.as('count'),\n ])\n .where('queue', '=', queue)\n .groupBy('status')\n .execute();\n\n const stats: JobStats = {\n ready: 0,\n running: 0,\n done: 0,\n dead: 0,\n total: 0,\n };\n\n for (const row of result) {\n const status = row.status as JobStatus;\n const count = Number(row.count);\n if (status in stats) {\n stats[status] = count;\n }\n stats.total += count;\n }\n\n return stats;\n },\n\n get isRunning(): boolean {\n return running;\n },\n\n get isPaused(): boolean {\n return paused;\n },\n\n get queue(): string {\n return queue;\n },\n\n async restoreState(): Promise<WorkerState | null> {\n const state = await loadState();\n if (state === 'running' && processor) {\n this.start();\n } else if (state === 'paused' && processor) {\n this.start();\n this.pause();\n }\n return state;\n },\n\n async clear(options: { status?: JobStatus } = {}): Promise<number> {\n let query = db\n .deleteFrom('workmatic_jobs')\n .where('queue', '=', queue);\n\n if (options.status) {\n query = query.where('status', '=', options.status);\n }\n\n const result = await query.execute();\n return Number(result[0]?.numDeletedRows ?? 0);\n },\n };\n\n // Auto-restore state if enabled\n if (persistState && autoRestore) {\n // Use setImmediate to allow processor to be set first\n setImmediate(async () => {\n if (processor) {\n await worker.restoreState();\n }\n });\n }\n\n return worker;\n}\n","import { sql } from 'kysely';\nimport { createClient } from './client.js';\nimport { createWorker } from './worker.js';\nimport type {\n WorkmaticDb,\n OrchestratorOptions,\n RegisterQueueOptions,\n WorkmaticOrchestrator,\n WorkmaticClient,\n WorkmaticWorker,\n TransferOptions,\n TransferResult,\n MoveJobOptions,\n JobStats,\n JobStatus,\n JobProcessor,\n} from './types.js';\nimport { now } from './utils.js';\n\nconst DEFAULT_TRANSFER_STATUSES: JobStatus[] = ['ready', 'dead'];\nconst DEFAULT_TRANSFER_LIMIT = 10_000;\n\n/** @internal Exported for tests */\nexport function rowsUpdated(result: unknown): number {\n const row = (result as { numUpdatedRows?: number | bigint }[])[0];\n return Number(row?.numUpdatedRows ?? 0);\n}\n\nfunction normalizeStatuses(status?: JobStatus | JobStatus[]): JobStatus[] {\n if (!status) return [...DEFAULT_TRANSFER_STATUSES];\n return Array.isArray(status) ? status : [status];\n}\n\ninterface QueueEntry {\n client: WorkmaticClient;\n worker?: WorkmaticWorker;\n}\n\n/**\n * Create a multi-queue orchestrator for registration, lifecycle, and transfers.\n */\nexport function createOrchestrator(options: OrchestratorOptions): WorkmaticOrchestrator {\n const { db } = options;\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n const registry = new Map<string, QueueEntry>();\n\n function ensureEntry(queue: string): QueueEntry {\n let entry = registry.get(queue);\n if (!entry) {\n entry = { client: createClient({ db, queue }) };\n registry.set(queue, entry);\n }\n return entry;\n }\n\n async function setQueuePaused(queue: string, paused: boolean): Promise<void> {\n const timestamp = now();\n const value = paused ? 1 : 0;\n await sql`\n INSERT INTO workmatic_settings (queue, paused, updated_at)\n VALUES (${queue}, ${value}, ${timestamp})\n ON CONFLICT(queue) DO UPDATE SET\n paused = ${value},\n updated_at = ${timestamp}\n `.execute(db);\n }\n\n async function selectJobIds(\n from: string,\n status: JobStatus,\n limit: number\n ): Promise<number[]> {\n const rows = await db\n .selectFrom('workmatic_jobs')\n .select('id')\n .where('queue', '=', from)\n .where('status', '=', status)\n .orderBy('priority', 'asc')\n .orderBy('id', 'asc')\n .limit(limit)\n .execute();\n return rows.map((r) => r.id);\n }\n\n async function transferReady(from: string, to: string, limit: number): Promise<number> {\n const ids = await selectJobIds(from, 'ready', limit);\n if (ids.length === 0) return 0;\n const timestamp = now();\n const result = await db\n .updateTable('workmatic_jobs')\n .set({ queue: to, updated_at: timestamp })\n .where('id', 'in', ids)\n .execute();\n return rowsUpdated(result);\n }\n\n async function transferDead(\n from: string,\n to: string,\n limit: number,\n resetForRetry: boolean\n ): Promise<number> {\n const ids = await selectJobIds(from, 'dead', limit);\n if (ids.length === 0) return 0;\n const timestamp = now();\n if (resetForRetry) {\n const result = await db\n .updateTable('workmatic_jobs')\n .set({\n queue: to,\n status: 'ready',\n attempts: 0,\n lease_until: 0,\n last_error: null,\n updated_at: timestamp,\n run_at: timestamp,\n })\n .where('id', 'in', ids)\n .execute();\n return rowsUpdated(result);\n }\n\n const result = await db\n .updateTable('workmatic_jobs')\n .set({ queue: to, updated_at: timestamp })\n .where('id', 'in', ids)\n .execute();\n return rowsUpdated(result);\n }\n\n async function transferOtherStatus(\n from: string,\n to: string,\n status: JobStatus,\n limit: number\n ): Promise<number> {\n const ids = await selectJobIds(from, status, limit);\n if (ids.length === 0) return 0;\n const timestamp = now();\n const result = await db\n .updateTable('workmatic_jobs')\n .set({ queue: to, updated_at: timestamp })\n .where('id', 'in', ids)\n .execute();\n return rowsUpdated(result);\n }\n\n const orchestrator: WorkmaticOrchestrator = {\n register(queue: string, opts: RegisterQueueOptions = {}): WorkmaticClient {\n const client = createClient({ db, queue });\n let worker: WorkmaticWorker | undefined;\n if (opts.worker) {\n worker = createWorker({ db, queue, ...opts.worker });\n }\n registry.set(queue, { client, worker });\n return client;\n },\n\n client(queue: string): WorkmaticClient {\n return ensureEntry(queue).client;\n },\n\n worker(queue: string): WorkmaticWorker {\n const entry = registry.get(queue);\n if (!entry?.worker) {\n throw new Error(`No worker registered for queue \"${queue}\"`);\n }\n return entry.worker;\n },\n\n workers(): WorkmaticWorker[] {\n return [...registry.values()]\n .map((e) => e.worker)\n .filter((w): w is WorkmaticWorker => w !== undefined);\n },\n\n async queues(): Promise<string[]> {\n const rows = await db\n .selectFrom('workmatic_jobs')\n .select('queue')\n .distinct()\n .execute();\n const names = new Set<string>(rows.map((r) => r.queue));\n for (const name of registry.keys()) {\n names.add(name);\n }\n return [...names].sort();\n },\n\n process<TPayload = unknown>(queue: string, fn: JobProcessor<TPayload>): void {\n this.worker(queue).process(fn);\n },\n\n startAll(): void {\n for (const entry of registry.values()) {\n entry.worker?.start();\n }\n },\n\n async stopAll(): Promise<void> {\n const stops = [...registry.values()]\n .map((e) => e.worker?.stop())\n .filter((p): p is Promise<void> => p !== undefined);\n await Promise.all(stops);\n },\n\n async pause(queue: string): Promise<void> {\n const entry = registry.get(queue);\n entry?.worker?.pause();\n await setQueuePaused(queue, true);\n },\n\n async resume(queue: string): Promise<void> {\n const entry = registry.get(queue);\n entry?.worker?.resume();\n await setQueuePaused(queue, false);\n },\n\n async isPaused(queue: string): Promise<boolean> {\n const setting = await db\n .selectFrom('workmatic_settings')\n .select('paused')\n .where('queue', '=', queue)\n .executeTakeFirst();\n return setting?.paused === 1;\n },\n\n async stats(queueName?: string): Promise<Record<string, JobStats>> {\n const names = queueName ? [queueName] : await this.queues();\n const result: Record<string, JobStats> = {};\n for (const name of names) {\n result[name] = await ensureEntry(name).client.stats();\n }\n return result;\n },\n\n async transfer(opts: TransferOptions): Promise<TransferResult> {\n const { from, to, resetForRetry = false } = opts;\n if (from === to) {\n return { moved: 0 };\n }\n\n const statuses = normalizeStatuses(opts.status);\n let remaining = opts.limit ?? DEFAULT_TRANSFER_LIMIT;\n let moved = 0;\n\n if (statuses.includes('ready') && remaining > 0) {\n const n = await transferReady(from, to, remaining);\n moved += n;\n remaining -= n;\n }\n if (statuses.includes('dead') && remaining > 0) {\n const n = await transferDead(from, to, remaining, resetForRetry);\n moved += n;\n remaining -= n;\n }\n for (const status of statuses) {\n if (status === 'ready' || status === 'dead' || remaining <= 0) continue;\n const n = await transferOtherStatus(from, to, status, remaining);\n moved += n;\n remaining -= n;\n }\n\n return { moved };\n },\n\n async moveJob(\n publicId: string,\n toQueue: string,\n opts: MoveJobOptions = {}\n ): Promise<void> {\n const allowed = normalizeStatuses(opts.status);\n const row = await db\n .selectFrom('workmatic_jobs')\n .select(['id', 'queue', 'status'])\n .where('public_id', '=', publicId)\n .executeTakeFirst();\n\n if (!row) {\n throw new Error(`Job not found: ${publicId}`);\n }\n if (row.queue === toQueue) {\n return;\n }\n if (!allowed.includes(row.status)) {\n throw new Error(\n `Job ${publicId} has status \"${row.status}\" and cannot be moved (allowed: ${allowed.join(', ')})`\n );\n }\n\n const timestamp = now();\n const resetForRetry = opts.resetForRetry ?? false;\n\n if (row.status === 'dead' && resetForRetry) {\n await db\n .updateTable('workmatic_jobs')\n .set({\n queue: toQueue,\n status: 'ready',\n attempts: 0,\n lease_until: 0,\n last_error: null,\n updated_at: timestamp,\n run_at: timestamp,\n })\n .where('public_id', '=', publicId)\n .execute();\n return;\n }\n\n await db\n .updateTable('workmatic_jobs')\n .set({ queue: toQueue, updated_at: timestamp })\n .where('public_id', '=', publicId)\n .execute();\n },\n };\n\n return orchestrator;\n}\n","import { createServer, IncomingMessage, ServerResponse } from 'http';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { readFile } from 'fs/promises';\nimport { sql } from 'kysely';\nimport type {\n WorkmaticDb,\n DashboardOptions,\n DashboardMiddlewareOptions,\n WorkmaticDashboard,\n WorkmaticWorker,\n DashboardMiddleware,\n JobStats,\n JobStatus,\n} from './types.js';\n\n// Get the directory of this module for static file serving\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Content types for static files\nconst CONTENT_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n};\n\n/** @internal Exported for tests */\nexport function requestUrl(url: string | undefined): string {\n return url || '';\n}\n\n/** @internal Exported for tests — maps dashboard asset path to Content-Type */\nexport function staticContentTypeFor(filePath: string): string {\n const ext = filePath.substring(filePath.lastIndexOf('.')) || '.html';\n return CONTENT_TYPES[ext] || 'application/octet-stream';\n}\n\n/**\n * Create the core request handler (shared between standalone and middleware)\n */\nexport function createRequestHandler(\n db: WorkmaticDb,\n workerMap: Map<string, WorkmaticWorker>,\n basePath: string = ''\n) {\n /**\n * Send JSON response\n */\n function sendJson(res: ServerResponse, data: unknown, status = 200): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n }\n\n /**\n * Send error response\n */\n function sendError(res: ServerResponse, message: string, status = 500): void {\n sendJson(res, { error: message }, status);\n }\n\n /**\n * Parse URL query parameters\n */\n function parseQuery(url: string): URLSearchParams {\n const queryIndex = url.indexOf('?');\n if (queryIndex === -1) return new URLSearchParams();\n return new URLSearchParams(url.slice(queryIndex + 1));\n }\n\n /**\n * Get path from URL (removing basePath prefix)\n */\n function getPath(url: string): string {\n const queryIndex = url.indexOf('?');\n let path = queryIndex === -1 ? url : url.slice(0, queryIndex);\n \n // Remove basePath prefix if present\n if (basePath && path.startsWith(basePath)) {\n path = path.slice(basePath.length) || '/';\n }\n \n return path;\n }\n\n /**\n * API: Get jobs list\n */\n async function handleGetJobs(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const query = parseQuery(requestUrl(req.url));\n const queueFilter = query.get('queue');\n const statusFilter = query.get('status') as JobStatus | null;\n const limit = Math.min(parseInt(query.get('limit') || '50', 10), 100);\n const offset = parseInt(query.get('offset') || '0', 10);\n\n let queryBuilder = db\n .selectFrom('workmatic_jobs')\n .select([\n 'public_id',\n 'queue',\n 'payload',\n 'status',\n 'priority',\n 'attempts',\n 'max_attempts',\n 'run_at',\n 'created_at',\n 'updated_at',\n 'last_error',\n ])\n .orderBy('created_at', 'desc')\n .limit(limit)\n .offset(offset);\n\n if (queueFilter) {\n queryBuilder = queryBuilder.where('queue', '=', queueFilter);\n }\n if (statusFilter) {\n queryBuilder = queryBuilder.where('status', '=', statusFilter);\n }\n\n const jobs = await queryBuilder.execute();\n\n // Transform to API format\n const apiJobs = jobs.map(job => ({\n id: job.public_id,\n queue: job.queue,\n payload: JSON.parse(job.payload),\n status: job.status,\n priority: job.priority,\n attempts: job.attempts,\n maxAttempts: job.max_attempts,\n runAt: job.run_at,\n createdAt: job.created_at,\n updatedAt: job.updated_at,\n lastError: job.last_error,\n }));\n\n sendJson(res, { jobs: apiJobs, limit, offset });\n }\n\n /**\n * API: Get statistics\n */\n async function handleGetStats(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const query = parseQuery(requestUrl(req.url));\n const queueFilter = query.get('queue');\n\n // Get counts by status\n let statsQuery = db\n .selectFrom('workmatic_jobs')\n .select([\n 'status',\n sql<number>`count(*)`.as('count'),\n ])\n .groupBy('status');\n\n if (queueFilter) {\n statsQuery = statsQuery.where('queue', '=', queueFilter);\n }\n\n const statusCounts = await statsQuery.execute();\n\n const stats: JobStats = {\n ready: 0,\n running: 0,\n done: 0,\n dead: 0,\n total: 0,\n };\n\n for (const row of statusCounts) {\n const status = row.status as JobStatus;\n const count = Number(row.count);\n if (status in stats) {\n stats[status] = count;\n }\n stats.total += count;\n }\n\n // Get queue list\n const queuesResult = await db\n .selectFrom('workmatic_jobs')\n .select('queue')\n .groupBy('queue')\n .execute();\n\n const queues = queuesResult.map(q => q.queue);\n\n // Get worker status\n const workersStatus = Array.from(workerMap.entries()).map(([queue, worker]) => ({\n queue,\n running: worker.isRunning,\n paused: worker.isPaused,\n }));\n\n sendJson(res, { stats, queues, workers: workersStatus });\n }\n\n /**\n * API: Get single job by ID\n */\n async function handleGetJob(req: IncomingMessage, res: ServerResponse, publicId: string): Promise<void> {\n const job = await db\n .selectFrom('workmatic_jobs')\n .select([\n 'public_id',\n 'queue',\n 'payload',\n 'status',\n 'priority',\n 'attempts',\n 'max_attempts',\n 'run_at',\n 'lease_until',\n 'created_at',\n 'updated_at',\n 'last_error',\n ])\n .where('public_id', '=', publicId)\n .executeTakeFirst();\n\n if (!job) {\n return sendError(res, 'Job not found', 404);\n }\n\n sendJson(res, {\n id: job.public_id,\n queue: job.queue,\n payload: JSON.parse(job.payload),\n status: job.status,\n priority: job.priority,\n attempts: job.attempts,\n maxAttempts: job.max_attempts,\n runAt: job.run_at,\n leaseUntil: job.lease_until,\n createdAt: job.created_at,\n updatedAt: job.updated_at,\n lastError: job.last_error,\n });\n }\n\n /**\n * API: Pause worker\n */\n async function handlePauseWorker(res: ServerResponse, queue: string): Promise<void> {\n const worker = workerMap.get(queue);\n if (!worker) {\n return sendError(res, `Worker for queue '${queue}' not found`, 404);\n }\n worker.pause();\n sendJson(res, { ok: true, queue, paused: true });\n }\n\n /**\n * API: Resume worker\n */\n async function handleResumeWorker(res: ServerResponse, queue: string): Promise<void> {\n const worker = workerMap.get(queue);\n if (!worker) {\n return sendError(res, `Worker for queue '${queue}' not found`, 404);\n }\n worker.resume();\n sendJson(res, { ok: true, queue, paused: false });\n }\n\n /**\n * Serve static files from the dashboard directory\n */\n async function serveStatic(res: ServerResponse, filePath: string): Promise<void> {\n // Navigate from dist/dashboard.js to dashboard/ directory\n const dashboardDir = join(__dirname, '..', 'dashboard');\n const fullPath = join(dashboardDir, filePath);\n \n // Determine content type\n const contentType = staticContentTypeFor(filePath);\n\n try {\n const content = await readFile(fullPath, 'utf-8');\n res.writeHead(200, { 'Content-Type': contentType });\n res.end(content);\n } catch (error) {\n sendError(res, 'Not found', 404);\n }\n }\n\n /**\n * Main request handler\n */\n return async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n next?: () => void\n ): Promise<boolean> {\n try {\n const path = getPath(req.url || '/');\n\n // Check if this request is for the dashboard\n const fullUrl = req.url || '/';\n if (basePath && !fullUrl.startsWith(basePath)) {\n if (next) next();\n return false;\n }\n\n // CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return true;\n }\n // API routes\n if (path === '/api/jobs' && req.method === 'GET') {\n await handleGetJobs(req, res);\n return true;\n }\n\n if (path === '/api/stats' && req.method === 'GET') {\n await handleGetStats(req, res);\n return true;\n }\n\n // Single job: /api/jobs/:id\n const jobMatch = path.match(/^\\/api\\/jobs\\/([^/]+)$/);\n if (jobMatch && req.method === 'GET') {\n await handleGetJob(req, res, jobMatch[1]);\n return true;\n }\n\n // Pause worker: /api/workers/:queue/pause\n const pauseMatch = path.match(/^\\/api\\/workers\\/([^/]+)\\/pause$/);\n if (pauseMatch && req.method === 'POST') {\n await handlePauseWorker(res, pauseMatch[1]);\n return true;\n }\n\n // Resume worker: /api/workers/:queue/resume\n const resumeMatch = path.match(/^\\/api\\/workers\\/([^/]+)\\/resume$/);\n if (resumeMatch && req.method === 'POST') {\n await handleResumeWorker(res, resumeMatch[1]);\n return true;\n }\n\n // Static files\n if (path === '/' || path === '/index.html') {\n await serveStatic(res, 'index.html');\n return true;\n }\n if (path === '/style.css') {\n await serveStatic(res, 'style.css');\n return true;\n }\n if (path === '/app.js') {\n await serveStatic(res, 'app.js');\n return true;\n }\n\n // 404 for unknown routes under our basePath\n sendError(res, 'Not found', 404);\n return true;\n } catch (error) {\n console.error('[workmatic] Dashboard error:', error);\n sendError(res, 'Internal server error', 500);\n return true;\n }\n };\n}\n\n/**\n * Create a dashboard HTTP server for monitoring and controlling the job queue\n * \n * @param options - Dashboard options\n * @returns Dashboard instance\n * \n * @example\n * ```ts\n * const dashboard = createDashboard({ \n * db, \n * port: 3000,\n * workers: [worker1, worker2] \n * });\n * \n * console.log(`Dashboard running at http://localhost:${dashboard.port}`);\n * \n * // Later, close the server\n * await dashboard.close();\n * ```\n */\nexport function createDashboard(options: DashboardOptions): WorkmaticDashboard {\n const {\n db,\n port = 3000,\n workers = [],\n } = options;\n\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n // Worker registry by queue name\n const workerMap = new Map<string, WorkmaticWorker>();\n for (const worker of workers) {\n workerMap.set(worker.queue, worker);\n }\n\n const handleRequest = createRequestHandler(db, workerMap);\n\n // Create and start HTTP server\n const server = createServer((req, res) => {\n void handleRequest(req, res);\n });\n\n server.listen(port);\n\n return {\n async close(): Promise<void> {\n return new Promise((resolve, reject) => {\n server.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n },\n\n get port(): number {\n return port;\n },\n };\n}\n\n/**\n * Create an Express-compatible middleware for the dashboard\n * \n * @param options - Middleware options\n * @returns Express middleware function\n * \n * @example\n * ```ts\n * import express from 'express';\n * import { createDashboardMiddleware } from 'workmatic';\n * \n * const app = express();\n * \n * // Mount dashboard at /workmatic\n * app.use(createDashboardMiddleware({ \n * db,\n * basePath: '/workmatic',\n * workers: [worker] \n * }));\n * \n * app.listen(3000);\n * // Dashboard available at http://localhost:3000/workmatic\n * ```\n */\nexport function createDashboardMiddleware(options: DashboardMiddlewareOptions): DashboardMiddleware {\n const {\n db,\n workers = [],\n basePath = '',\n } = options;\n\n if (!db) {\n throw new Error('Database instance is required');\n }\n\n // Worker registry by queue name\n const workerMap = new Map<string, WorkmaticWorker>();\n for (const worker of workers) {\n workerMap.set(worker.queue, worker);\n }\n\n const handleRequest = createRequestHandler(db, workerMap, basePath);\n\n return (req, res, next) => {\n void handleRequest(req, res, next);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,IAAM,mBAAmB,MACvB,OAAO,aAAa,cAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,OAC7B,SAAS,iBAAiB,SAAS,cAAc,QAAQ,YAAY,MAAM,WAC1E,SAAS,cAAc,MACvB,IAAI,IAAI,WAAW,SAAS,OAAO,EAAE;AAEtC,IAAM,gBAAgC,iCAAiB;;;ACZ9D,4BAAqB;AACrB,oBAAsC;AAItC,IAAM,iBAAiB,oBAAI,QAAwC;AAsB5D,SAAS,eAAe,UAA2B,CAAC,GAAgB;AACzE,MAAI;AAEJ,MAAI,QAAQ,IAAI;AACd,eAAW,QAAQ;AAAA,EACrB,OAAO;AACL,UAAM,WAAW,QAAQ,YAAY;AACrC,eAAW,IAAI,sBAAAA,QAAS,QAAQ;AAAA,EAClC;AAGA,WAAS,OAAO,oBAAoB;AACpC,WAAS,OAAO,sBAAsB;AACtC,WAAS,OAAO,qBAAqB;AAGrC,QAAM,KAAK,IAAI,qBAA0B;AAAA,IACvC,SAAS,IAAI,4BAAc;AAAA,MACzB,UAAU;AAAA,IACZ,CAAC;AAAA,EACH,CAAC;AAGD,eAAa,QAAQ;AAErB,iBAAe,IAAI,IAAI,QAAQ;AAE/B,SAAO;AACT;AAKA,SAAS,aAAa,IAA6B;AAEjD,KAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAgBP;AAID,KAAG,KAAK;AAAA;AAAA;AAAA,GAGP;AAID,KAAG,KAAK;AAAA;AAAA;AAAA,GAGP;AAGD,KAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAMP;AAGD,KAAG,KAAK;AAAA;AAAA,GAEP;AACH;AAOO,SAAS,gBAAgB,IAAoC;AAClE,QAAM,SAAS,eAAe,IAAI,EAAE;AACpC,MAAI,QAAQ;AACV,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,KAAM,GACT,cAAc;AACjB,UAAM,UAAU,IAAI,SAAS;AAC7B,QAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;;;ACpIA,oBAAuB;AACvB,IAAAC,iBAAoB;;;ACgBb,IAAM,iBAAkC,CAAC,aAA6B;AAC3E,SAAO,MAAO,KAAK,IAAI,GAAG,QAAQ;AACpC;AASO,SAAS,gBAAgB,SAA0B;AACxD,MAAI;AACF,WAAO,KAAK,UAAU,OAAO;AAAA,EAC/B,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,qCAAqC,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,IAC/F;AAAA,EACF;AACF;AASO,SAAS,aAA0B,MAAiB;AACzD,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,yBAAyB,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,IACnF;AAAA,EACF;AACF;AAeO,SAAS,MAAc;AAC5B,SAAO,KAAK,IAAI;AAClB;;;AD/BO,SAAS,aAAa,SAAyC;AACpE,QAAM,EAAE,IAAI,QAAQ,UAAU,IAAI;AAElC,MAAI,CAAC,IAAI;AACP,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL,MAAM,IACJ,SACA,OAAsB,CAAC,GACA;AACvB,YAAM;AAAA,QACJ,WAAW;AAAA,QACX,UAAU;AAAA,QACV,cAAc;AAAA,MAChB,IAAI;AAGJ,YAAM,cAAc,gBAAgB,OAAO;AAG3C,YAAM,eAAW,sBAAO;AAExB,YAAM,YAAY,IAAI;AACtB,YAAM,QAAQ,YAAY;AAG1B,YAAM,GACH,WAAW,gBAAgB,EAC3B,OAAO;AAAA,QACN,WAAW;AAAA,QACX;AAAA,QACA,SAAS;AAAA,QACT,QAAQ;AAAA,QACR;AAAA,QACA,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,cAAc;AAAA,QACd,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,YAAY;AAAA,MACd,CAAC,EACA,QAAQ;AAEX,aAAO,EAAE,IAAI,MAAM,IAAI,SAAS;AAAA,IAClC;AAAA,IAEA,MAAM,QACJ,UACA,OAAsB,CAAC,GACC;AACxB,YAAM;AAAA,QACJ,WAAW;AAAA,QACX,UAAU;AAAA,QACV,cAAc;AAAA,MAChB,IAAI;AAEJ,UAAI,SAAS,WAAW,GAAG;AACzB,eAAO,EAAE,IAAI,MAAM,KAAK,CAAC,EAAE;AAAA,MAC7B;AAEA,YAAM,YAAY,IAAI;AACtB,YAAM,QAAQ,YAAY;AAE1B,aAAO,MAAM,GAAG,YAAY,EAAE,QAAQ,OAAO,QAAQ;AACnD,cAAM,MAAgB,CAAC;AACvB,cAAM,OAAO,SAAS,IAAI,CAAC,YAAY;AACrC,gBAAM,cAAc,gBAAgB,OAAO;AAC3C,gBAAM,eAAW,sBAAO;AACxB,cAAI,KAAK,QAAQ;AACjB,iBAAO;AAAA,YACL,WAAW;AAAA,YACX;AAAA,YACA,SAAS;AAAA,YACT,QAAQ;AAAA,YACR;AAAA,YACA,QAAQ;AAAA,YACR,UAAU;AAAA,YACV,cAAc;AAAA,YACd,aAAa;AAAA,YACb,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,YAAY;AAAA,UACd;AAAA,QACF,CAAC;AAED,cAAM,IAAI,WAAW,gBAAgB,EAAE,OAAO,IAAI,EAAE,QAAQ;AAC5D,eAAO,EAAE,IAAI,MAAM,IAAI;AAAA,MACzB,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA,IAKA,MAAM,QAA2B;AAC/B,YAAM,SAAS,MAAM,GAClB,WAAW,gBAAgB,EAC3B,OAAO;AAAA,QACN;AAAA,QACA,6BAAsB,GAAG,OAAO;AAAA,MAClC,CAAC,EACA,MAAM,SAAS,KAAK,KAAK,EACzB,QAAQ,QAAQ,EAChB,QAAQ;AAEX,YAAM,QAAkB;AAAA,QACtB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAEA,iBAAW,OAAO,QAAQ;AACxB,cAAM,SAAS,IAAI;AACnB,cAAM,QAAQ,OAAO,IAAI,KAAK;AAC9B,YAAI,UAAU,OAAO;AACnB,gBAAM,MAAM,IAAI;AAAA,QAClB;AACA,cAAM,SAAS;AAAA,MACjB;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,MAAM,MAAMC,WAAkC,CAAC,GAAoB;AACjE,UAAI,QAAQ,GACT,WAAW,gBAAgB,EAC3B,MAAM,SAAS,KAAK,KAAK;AAE5B,UAAIA,SAAQ,QAAQ;AAClB,gBAAQ,MAAM,MAAM,UAAU,KAAKA,SAAQ,MAAM;AAAA,MACnD;AAEA,YAAM,SAAS,MAAM,MAAM,QAAQ;AACnC,aAAO,OAAO,OAAO,CAAC,GAAG,kBAAkB,CAAC;AAAA,IAC9C;AAAA,EACF;AACF;;;AEzLA,mBAAkB;AAElB,IAAAC,iBAAoB;AAeb,IAAM,4BAA4B;AAGlC,SAAS,iBAAiB,QAA+B;AAC9D,QAAM,OAAQ,OAAmC;AACjD,MAAI,CAAC,QAAQ,CAAC,MAAM,QAAQ,IAAI,GAAG;AACjC,WAAO,CAAC;AAAA,EACV;AACA,SAAO,KAAK,IAAI,CAAC,SAAS;AAAA,IACxB,IAAI,IAAI;AAAA,IACR,WAAW,IAAI;AAAA,IACf,OAAO,IAAI;AAAA,IACX,SAAS,IAAI;AAAA,IACb,UAAU,IAAI;AAAA,IACd,cAAc,IAAI;AAAA,IAClB,UAAU,IAAI;AAAA,IACd,YAAY,IAAI;AAAA,IAChB,YAAY,IAAI;AAAA,EAClB,EAAE;AACJ;AAGO,SAAS,iBAAoB,WAAoD;AACtF,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACpC;AACA,SAAO;AACT;AAyBO,SAAS,aAAa,SAAyC;AACpE,QAAM;AAAA,IACJ;AAAA,IACA,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,UAAU;AAAA,IACV,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,eAAe;AAAA,IACf,cAAc;AAAA,IACd,uBAAuB;AAAA,IACvB,2BAA2B;AAAA,IAC3B;AAAA,EACF,IAAI;AAEJ,MAAI,CAAC,IAAI;AACP,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAGA,MAAI,UAAU;AACd,MAAI,SAAS;AACb,MAAI,YAAsC;AAC1C,MAAI,cAAqC;AACzC,MAAI,aAAuD;AAC3D,MAAI,mBAAmB;AACvB,MAAI,iBAAiB;AACrB,MAAI,gBAAgB;AAEpB,WAAS,gBAAgB,OAAsB;AAC7C,YAAQ,MAAM,2BAA2B,KAAK;AAC9C,kBAAc,KAAK;AAAA,EACrB;AAKA,WAAS,cAAsB;AAC7B,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AAKA,iBAAe,UAAU,OAAmC;AAC1D,QAAI,CAAC,aAAc;AAEnB,UAAM,YAAY,IAAI;AACtB,UAAM,MAAM,YAAY;AAGxB,UAAM;AAAA;AAAA,gBAEM,GAAG,KAAK,UAAU,WAAW,IAAI,UAAU,YAAY,IAAI,CAAC,KAAK,SAAS;AAAA;AAAA,mBAEvE,UAAU,WAAW,IAAI,UAAU,YAAY,IAAI,CAAC;AAAA,uBAChD,SAAS;AAAA,MAC1B,QAAQ,EAAE;AAAA,EACd;AAKA,iBAAe,YAAyC;AACtD,QAAI,CAAC,aAAc,QAAO;AAE1B,QAAI;AACF,YAAM,MAAM,YAAY;AACxB,YAAM,SAAS,MAAM,GAClB,WAAW,oBAAoB,EAC/B,OAAO,QAAQ,EACf,MAAM,SAAS,KAAK,GAAG,EACvB,iBAAiB;AAEpB,UAAI,CAAC,OAAQ,QAAO;AAGpB,UAAI,OAAO,WAAW,EAAG,QAAO;AAChC,UAAI,OAAO,WAAW,EAAG,QAAO;AAChC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAKA,iBAAe,uBAAwC;AACrD,UAAM,YAAY,IAAI;AAEtB,UAAM,SAAS,MAAM,GAClB,YAAY,gBAAgB,EAC5B,IAAI;AAAA,MACH,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,YAAY;AAAA,IACd,CAAC,EACA,MAAM,UAAU,KAAK,SAAS,EAC9B,MAAM,eAAe,KAAK,SAAS,EACnC,MAAM,eAAe,KAAK,CAAC,EAC3B,QAAQ;AAEX,WAAO,OAAO,OAAO,CAAC,GAAG,kBAAkB,CAAC;AAAA,EAC9C;AAKA,iBAAe,WAAW,OAAsC;AAC9D,UAAM,YAAY,IAAI;AACtB,UAAM,aAAa,YAAY;AAE/B,WAAO,MAAM,GAAG,YAAY,EAAE,QAAQ,OAAO,QAAQ;AACnD,YAAM,SAAS,MAAM;AAAA;AAAA,gDAYqB,UAAU,kBAAkB,SAAS;AAAA;AAAA;AAAA,0BAG3D,KAAK;AAAA;AAAA,4BAEH,SAAS;AAAA;AAAA,kBAEnB,KAAK;AAAA;AAAA;AAAA,QAGf,QAAQ,GAAG;AAEb,aAAO,iBAAiB,MAAM;AAAA,IAChC,CAAC;AAAA,EACH;AAKA,iBAAe,SAAS,OAA8B;AACpD,UAAM,GACH,YAAY,gBAAgB,EAC5B,IAAI;AAAA,MACH,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,YAAY,IAAI;AAAA,IAClB,CAAC,EACA,MAAM,MAAM,KAAK,KAAK,EACtB,QAAQ;AAAA,EACb;AAKA,iBAAe,WACb,OACA,UACA,aACA,OACe;AACf,UAAM,YAAY,IAAI;AACtB,UAAM,cAAc,WAAW;AAC/B,UAAM,eAAe,MAAM,WAAW,OAAO,KAAK;AAElD,QAAI,cAAc,aAAa;AAE7B,YAAM,QAAQ,YAAY,QAAQ,WAAW;AAE7C,YAAM,GACH,YAAY,gBAAgB,EAC5B,IAAI;AAAA,QACH,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,MACd,CAAC,EACA,MAAM,MAAM,KAAK,KAAK,EACtB,QAAQ;AAAA,IACb,OAAO;AAEL,YAAM,GACH,YAAY,gBAAgB,EAC5B,IAAI;AAAA,QACH,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,MACd,CAAC,EACA,MAAM,MAAM,KAAK,KAAK,EACtB,QAAQ;AAAA,IACb;AAAA,EACF;AAKA,iBAAe,YACb,SACA,IACA,OACY;AACZ,QAAI;AAEJ,UAAM,iBAAiB,IAAI,QAAe,CAAC,GAAG,WAAW;AACvD,kBAAY,WAAW,MAAM;AAC3B,eAAO,IAAI,MAAM,OAAO,KAAK,oBAAoB,EAAE,IAAI,CAAC;AAAA,MAC1D,GAAG,EAAE;AAAA,IACP,CAAC;AAED,QAAI;AACF,aAAO,MAAM,QAAQ,KAAK,CAAC,SAAS,cAAc,CAAC;AAAA,IACrD,UAAE;AACA,mBAAa,SAAU;AAAA,IACzB;AAAA,EACF;AAKA,iBAAe,WAAW,YAAuC;AAC/D,UAAM,KAAK,iBAAiB,SAAS;AAGrC,UAAM,UAAU,aAAa,WAAW,OAAO;AAC/C,UAAM,MAAW;AAAA,MACf,IAAI,WAAW;AAAA,MACf,OAAO,WAAW;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,MACR,UAAU,WAAW;AAAA,MACrB,UAAU,WAAW;AAAA,MACrB,aAAa,WAAW;AAAA,MACxB,WAAW,WAAW;AAAA,MACtB,WAAW,WAAW;AAAA,IACxB;AAEA,QAAI;AAEF,UAAI,WAAW;AACb,cAAM,YAAY,GAAG,GAAG,GAAG,WAAW,IAAI,EAAE;AAAA,MAC9C,OAAO;AACL,cAAM,GAAG,GAAG;AAAA,MACd;AACA,YAAM,SAAS,WAAW,EAAE;AAAA,IAC9B,SAAS,OAAO;AACd,YAAM;AAAA,QACJ,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW;AAAA,QACX,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAKA,iBAAe,oBAAsC;AACnD,UAAM,UAAU,MAAM,GACnB,WAAW,oBAAoB,EAC/B,OAAO,QAAQ,EACf,MAAM,SAAS,KAAK,KAAK,EACzB,iBAAiB;AAEpB,WAAO,SAAS,WAAW;AAAA,EAC7B;AAKA,iBAAe,OAAsB;AACnC,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAGA,QAAI,QAAQ;AACV,oBAAc,WAAW,MAAM,MAAM;AACrC;AAAA,IACF;AAEA,QAAI;AACF,YAAM,IAAI,IAAI;AACd,UAAI,IAAI,oBAAoB,sBAAsB;AAChD,2BAAmB;AACnB,yBAAiB,MAAM,kBAAkB;AAAA,MAC3C;AACA,UAAI,gBAAgB;AAClB,sBAAc,WAAW,MAAM,MAAM;AACrC;AAAA,MACF;AAEA,UACE,4BAA4B,KAC5B,IAAI,iBAAiB,0BACrB;AACA,YAAI,2BAA2B,GAAG;AAChC,0BAAgB;AAAA,QAClB;AACA,cAAM,qBAAqB;AAAA,MAC7B;AAGA,YAAM,YAAY,cAAc;AAChC,YAAM,OAAO,MAAM,WAAW,SAAS;AAEvC,UAAI,KAAK,SAAS,GAAG;AAEnB,mBAAW,OAAO,MAAM;AACtB,qBAAY,KAAK,GAAG;AAAA,QACtB;AAEA,sBAAc,WAAW,MAAM,CAAC;AAAA,MAClC,OAAO;AAEL,sBAAc,WAAW,MAAM,MAAM;AAAA,MACvC;AAAA,IACF,SAAS,OAAO;AACd,sBAAgB,KAAK;AACrB,oBAAc,WAAW,MAAM,MAAM;AAAA,IACvC;AAAA,EACF;AAGA,QAAM,SAA0B;AAAA,IAC9B,QAA4B,IAAkC;AAC5D,kBAAY;AAAA,IACd;AAAA,IAEA,QAAc;AACZ,UAAI,SAAS;AACX;AAAA,MACF;AAEA,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AAEA,gBAAU;AACV,eAAS;AAGT,mBAAa,aAAAC,QAAM,QAAQ,YAAY,WAAW;AAGlD,gBAAU,SAAS,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAGnC,WAAK;AAAA,IACP;AAAA,IAEA,MAAM,OAAsB;AAC1B,UAAI,CAAC,SAAS;AACZ;AAAA,MACF;AAEA,gBAAU;AAGV,UAAI,aAAa;AACf,qBAAa,WAAW;AACxB,sBAAc;AAAA,MAChB;AAGA,UAAI,YAAY;AACd,cAAM,WAAW,QAAQ;AACzB,qBAAa;AAAA,MACf;AAGA,YAAM,UAAU,SAAS;AAAA,IAC3B;AAAA,IAEA,QAAc;AACZ,eAAS;AACT,gBAAU,QAAQ,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACpC;AAAA,IAEA,SAAe;AACb,eAAS;AACT,gBAAU,SAAS,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACrC;AAAA,IAEA,MAAM,QAA2B;AAC/B,YAAM,SAAS,MAAM,GAClB,WAAW,gBAAgB,EAC3B,OAAO;AAAA,QACN;AAAA,QACA,6BAAsB,GAAG,OAAO;AAAA,MAClC,CAAC,EACA,MAAM,SAAS,KAAK,KAAK,EACzB,QAAQ,QAAQ,EAChB,QAAQ;AAEX,YAAM,QAAkB;AAAA,QACtB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAEA,iBAAW,OAAO,QAAQ;AACxB,cAAM,SAAS,IAAI;AACnB,cAAM,QAAQ,OAAO,IAAI,KAAK;AAC9B,YAAI,UAAU,OAAO;AACnB,gBAAM,MAAM,IAAI;AAAA,QAClB;AACA,cAAM,SAAS;AAAA,MACjB;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,IAAI,YAAqB;AACvB,aAAO;AAAA,IACT;AAAA,IAEA,IAAI,WAAoB;AACtB,aAAO;AAAA,IACT;AAAA,IAEA,IAAI,QAAgB;AAClB,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,eAA4C;AAChD,YAAM,QAAQ,MAAM,UAAU;AAC9B,UAAI,UAAU,aAAa,WAAW;AACpC,aAAK,MAAM;AAAA,MACb,WAAW,UAAU,YAAY,WAAW;AAC1C,aAAK,MAAM;AACX,aAAK,MAAM;AAAA,MACb;AACA,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,MAAMC,WAAkC,CAAC,GAAoB;AACjE,UAAI,QAAQ,GACT,WAAW,gBAAgB,EAC3B,MAAM,SAAS,KAAK,KAAK;AAE5B,UAAIA,SAAQ,QAAQ;AAClB,gBAAQ,MAAM,MAAM,UAAU,KAAKA,SAAQ,MAAM;AAAA,MACnD;AAEA,YAAM,SAAS,MAAM,MAAM,QAAQ;AACnC,aAAO,OAAO,OAAO,CAAC,GAAG,kBAAkB,CAAC;AAAA,IAC9C;AAAA,EACF;AAGA,MAAI,gBAAgB,aAAa;AAE/B,iBAAa,YAAY;AACvB,UAAI,WAAW;AACb,cAAM,OAAO,aAAa;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AC9hBA,IAAAC,iBAAoB;AAmBpB,IAAM,4BAAyC,CAAC,SAAS,MAAM;AAC/D,IAAM,yBAAyB;AAGxB,SAAS,YAAY,QAAyB;AACnD,QAAM,MAAO,OAAkD,CAAC;AAChE,SAAO,OAAO,KAAK,kBAAkB,CAAC;AACxC;AAEA,SAAS,kBAAkB,QAA+C;AACxE,MAAI,CAAC,OAAQ,QAAO,CAAC,GAAG,yBAAyB;AACjD,SAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AACjD;AAUO,SAAS,mBAAmB,SAAqD;AACtF,QAAM,EAAE,GAAG,IAAI;AACf,MAAI,CAAC,IAAI;AACP,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,QAAM,WAAW,oBAAI,IAAwB;AAE7C,WAAS,YAAY,OAA2B;AAC9C,QAAI,QAAQ,SAAS,IAAI,KAAK;AAC9B,QAAI,CAAC,OAAO;AACV,cAAQ,EAAE,QAAQ,aAAa,EAAE,IAAI,MAAM,CAAC,EAAE;AAC9C,eAAS,IAAI,OAAO,KAAK;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAEA,iBAAe,eAAe,OAAe,QAAgC;AAC3E,UAAM,YAAY,IAAI;AACtB,UAAM,QAAQ,SAAS,IAAI;AAC3B,UAAM;AAAA;AAAA,gBAEM,KAAK,KAAK,KAAK,KAAK,SAAS;AAAA;AAAA,mBAE1B,KAAK;AAAA,uBACD,SAAS;AAAA,MAC1B,QAAQ,EAAE;AAAA,EACd;AAEA,iBAAe,aACb,MACA,QACA,OACmB;AACnB,UAAM,OAAO,MAAM,GAChB,WAAW,gBAAgB,EAC3B,OAAO,IAAI,EACX,MAAM,SAAS,KAAK,IAAI,EACxB,MAAM,UAAU,KAAK,MAAM,EAC3B,QAAQ,YAAY,KAAK,EACzB,QAAQ,MAAM,KAAK,EACnB,MAAM,KAAK,EACX,QAAQ;AACX,WAAO,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,EAC7B;AAEA,iBAAe,cAAc,MAAc,IAAY,OAAgC;AACrF,UAAM,MAAM,MAAM,aAAa,MAAM,SAAS,KAAK;AACnD,QAAI,IAAI,WAAW,EAAG,QAAO;AAC7B,UAAM,YAAY,IAAI;AACtB,UAAM,SAAS,MAAM,GAClB,YAAY,gBAAgB,EAC5B,IAAI,EAAE,OAAO,IAAI,YAAY,UAAU,CAAC,EACxC,MAAM,MAAM,MAAM,GAAG,EACrB,QAAQ;AACX,WAAO,YAAY,MAAM;AAAA,EAC3B;AAEA,iBAAe,aACb,MACA,IACA,OACA,eACiB;AACjB,UAAM,MAAM,MAAM,aAAa,MAAM,QAAQ,KAAK;AAClD,QAAI,IAAI,WAAW,EAAG,QAAO;AAC7B,UAAM,YAAY,IAAI;AACtB,QAAI,eAAe;AACjB,YAAMC,UAAS,MAAM,GAClB,YAAY,gBAAgB,EAC5B,IAAI;AAAA,QACH,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV,CAAC,EACA,MAAM,MAAM,MAAM,GAAG,EACrB,QAAQ;AACX,aAAO,YAAYA,OAAM;AAAA,IAC3B;AAEA,UAAM,SAAS,MAAM,GAClB,YAAY,gBAAgB,EAC5B,IAAI,EAAE,OAAO,IAAI,YAAY,UAAU,CAAC,EACxC,MAAM,MAAM,MAAM,GAAG,EACrB,QAAQ;AACX,WAAO,YAAY,MAAM;AAAA,EAC3B;AAEA,iBAAe,oBACb,MACA,IACA,QACA,OACiB;AACjB,UAAM,MAAM,MAAM,aAAa,MAAM,QAAQ,KAAK;AAClD,QAAI,IAAI,WAAW,EAAG,QAAO;AAC7B,UAAM,YAAY,IAAI;AACtB,UAAM,SAAS,MAAM,GAClB,YAAY,gBAAgB,EAC5B,IAAI,EAAE,OAAO,IAAI,YAAY,UAAU,CAAC,EACxC,MAAM,MAAM,MAAM,GAAG,EACrB,QAAQ;AACX,WAAO,YAAY,MAAM;AAAA,EAC3B;AAEA,QAAM,eAAsC;AAAA,IAC1C,SAAS,OAAe,OAA6B,CAAC,GAAoB;AACxE,YAAM,SAAS,aAAa,EAAE,IAAI,MAAM,CAAC;AACzC,UAAI;AACJ,UAAI,KAAK,QAAQ;AACf,iBAAS,aAAa,EAAE,IAAI,OAAO,GAAG,KAAK,OAAO,CAAC;AAAA,MACrD;AACA,eAAS,IAAI,OAAO,EAAE,QAAQ,OAAO,CAAC;AACtC,aAAO;AAAA,IACT;AAAA,IAEA,OAAO,OAAgC;AACrC,aAAO,YAAY,KAAK,EAAE;AAAA,IAC5B;AAAA,IAEA,OAAO,OAAgC;AACrC,YAAM,QAAQ,SAAS,IAAI,KAAK;AAChC,UAAI,CAAC,OAAO,QAAQ;AAClB,cAAM,IAAI,MAAM,mCAAmC,KAAK,GAAG;AAAA,MAC7D;AACA,aAAO,MAAM;AAAA,IACf;AAAA,IAEA,UAA6B;AAC3B,aAAO,CAAC,GAAG,SAAS,OAAO,CAAC,EACzB,IAAI,CAAC,MAAM,EAAE,MAAM,EACnB,OAAO,CAAC,MAA4B,MAAM,MAAS;AAAA,IACxD;AAAA,IAEA,MAAM,SAA4B;AAChC,YAAM,OAAO,MAAM,GAChB,WAAW,gBAAgB,EAC3B,OAAO,OAAO,EACd,SAAS,EACT,QAAQ;AACX,YAAM,QAAQ,IAAI,IAAY,KAAK,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACtD,iBAAW,QAAQ,SAAS,KAAK,GAAG;AAClC,cAAM,IAAI,IAAI;AAAA,MAChB;AACA,aAAO,CAAC,GAAG,KAAK,EAAE,KAAK;AAAA,IACzB;AAAA,IAEA,QAA4B,OAAe,IAAkC;AAC3E,WAAK,OAAO,KAAK,EAAE,QAAQ,EAAE;AAAA,IAC/B;AAAA,IAEA,WAAiB;AACf,iBAAW,SAAS,SAAS,OAAO,GAAG;AACrC,cAAM,QAAQ,MAAM;AAAA,MACtB;AAAA,IACF;AAAA,IAEA,MAAM,UAAyB;AAC7B,YAAM,QAAQ,CAAC,GAAG,SAAS,OAAO,CAAC,EAChC,IAAI,CAAC,MAAM,EAAE,QAAQ,KAAK,CAAC,EAC3B,OAAO,CAAC,MAA0B,MAAM,MAAS;AACpD,YAAM,QAAQ,IAAI,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,MAAM,OAA8B;AACxC,YAAM,QAAQ,SAAS,IAAI,KAAK;AAChC,aAAO,QAAQ,MAAM;AACrB,YAAM,eAAe,OAAO,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,OAAO,OAA8B;AACzC,YAAM,QAAQ,SAAS,IAAI,KAAK;AAChC,aAAO,QAAQ,OAAO;AACtB,YAAM,eAAe,OAAO,KAAK;AAAA,IACnC;AAAA,IAEA,MAAM,SAAS,OAAiC;AAC9C,YAAM,UAAU,MAAM,GACnB,WAAW,oBAAoB,EAC/B,OAAO,QAAQ,EACf,MAAM,SAAS,KAAK,KAAK,EACzB,iBAAiB;AACpB,aAAO,SAAS,WAAW;AAAA,IAC7B;AAAA,IAEA,MAAM,MAAM,WAAuD;AACjE,YAAM,QAAQ,YAAY,CAAC,SAAS,IAAI,MAAM,KAAK,OAAO;AAC1D,YAAM,SAAmC,CAAC;AAC1C,iBAAW,QAAQ,OAAO;AACxB,eAAO,IAAI,IAAI,MAAM,YAAY,IAAI,EAAE,OAAO,MAAM;AAAA,MACtD;AACA,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,SAAS,MAAgD;AAC7D,YAAM,EAAE,MAAM,IAAI,gBAAgB,MAAM,IAAI;AAC5C,UAAI,SAAS,IAAI;AACf,eAAO,EAAE,OAAO,EAAE;AAAA,MACpB;AAEA,YAAM,WAAW,kBAAkB,KAAK,MAAM;AAC9C,UAAI,YAAY,KAAK,SAAS;AAC9B,UAAI,QAAQ;AAEZ,UAAI,SAAS,SAAS,OAAO,KAAK,YAAY,GAAG;AAC/C,cAAM,IAAI,MAAM,cAAc,MAAM,IAAI,SAAS;AACjD,iBAAS;AACT,qBAAa;AAAA,MACf;AACA,UAAI,SAAS,SAAS,MAAM,KAAK,YAAY,GAAG;AAC9C,cAAM,IAAI,MAAM,aAAa,MAAM,IAAI,WAAW,aAAa;AAC/D,iBAAS;AACT,qBAAa;AAAA,MACf;AACA,iBAAW,UAAU,UAAU;AAC7B,YAAI,WAAW,WAAW,WAAW,UAAU,aAAa,EAAG;AAC/D,cAAM,IAAI,MAAM,oBAAoB,MAAM,IAAI,QAAQ,SAAS;AAC/D,iBAAS;AACT,qBAAa;AAAA,MACf;AAEA,aAAO,EAAE,MAAM;AAAA,IACjB;AAAA,IAEA,MAAM,QACJ,UACA,SACA,OAAuB,CAAC,GACT;AACf,YAAM,UAAU,kBAAkB,KAAK,MAAM;AAC7C,YAAM,MAAM,MAAM,GACf,WAAW,gBAAgB,EAC3B,OAAO,CAAC,MAAM,SAAS,QAAQ,CAAC,EAChC,MAAM,aAAa,KAAK,QAAQ,EAChC,iBAAiB;AAEpB,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,kBAAkB,QAAQ,EAAE;AAAA,MAC9C;AACA,UAAI,IAAI,UAAU,SAAS;AACzB;AAAA,MACF;AACA,UAAI,CAAC,QAAQ,SAAS,IAAI,MAAM,GAAG;AACjC,cAAM,IAAI;AAAA,UACR,OAAO,QAAQ,gBAAgB,IAAI,MAAM,mCAAmC,QAAQ,KAAK,IAAI,CAAC;AAAA,QAChG;AAAA,MACF;AAEA,YAAM,YAAY,IAAI;AACtB,YAAM,gBAAgB,KAAK,iBAAiB;AAE5C,UAAI,IAAI,WAAW,UAAU,eAAe;AAC1C,cAAM,GACH,YAAY,gBAAgB,EAC5B,IAAI;AAAA,UACH,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ,QAAQ;AAAA,QACV,CAAC,EACA,MAAM,aAAa,KAAK,QAAQ,EAChC,QAAQ;AACX;AAAA,MACF;AAEA,YAAM,GACH,YAAY,gBAAgB,EAC5B,IAAI,EAAE,OAAO,SAAS,YAAY,UAAU,CAAC,EAC7C,MAAM,aAAa,KAAK,QAAQ,EAChC,QAAQ;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AACT;;;AClUA,kBAA8D;AAC9D,iBAA8B;AAC9B,kBAA8B;AAC9B,sBAAyB;AACzB,IAAAC,iBAAoB;AAapB,IAAMC,kBAAa,0BAAc,aAAe;AAChD,IAAM,gBAAY,qBAAQA,WAAU;AAGpC,IAAM,gBAAwC;AAAA,EAC5C,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AACX;AAGO,SAAS,WAAW,KAAiC;AAC1D,SAAO,OAAO;AAChB;AAGO,SAAS,qBAAqB,UAA0B;AAC7D,QAAM,MAAM,SAAS,UAAU,SAAS,YAAY,GAAG,CAAC,KAAK;AAC7D,SAAO,cAAc,GAAG,KAAK;AAC/B;AAKO,SAAS,qBACd,IACA,WACA,WAAmB,IACnB;AAIA,WAAS,SAAS,KAAqB,MAAe,SAAS,KAAW;AACxE,QAAI,UAAU,QAAQ,EAAE,gBAAgB,mBAAmB,CAAC;AAC5D,QAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,EAC9B;AAKA,WAAS,UAAU,KAAqB,SAAiB,SAAS,KAAW;AAC3E,aAAS,KAAK,EAAE,OAAO,QAAQ,GAAG,MAAM;AAAA,EAC1C;AAKA,WAAS,WAAW,KAA8B;AAChD,UAAM,aAAa,IAAI,QAAQ,GAAG;AAClC,QAAI,eAAe,GAAI,QAAO,IAAI,gBAAgB;AAClD,WAAO,IAAI,gBAAgB,IAAI,MAAM,aAAa,CAAC,CAAC;AAAA,EACtD;AAKA,WAAS,QAAQ,KAAqB;AACpC,UAAM,aAAa,IAAI,QAAQ,GAAG;AAClC,QAAI,OAAO,eAAe,KAAK,MAAM,IAAI,MAAM,GAAG,UAAU;AAG5D,QAAI,YAAY,KAAK,WAAW,QAAQ,GAAG;AACzC,aAAO,KAAK,MAAM,SAAS,MAAM,KAAK;AAAA,IACxC;AAEA,WAAO;AAAA,EACT;AAKA,iBAAe,cAAc,KAAsB,KAAoC;AACrF,UAAM,QAAQ,WAAW,WAAW,IAAI,GAAG,CAAC;AAC5C,UAAM,cAAc,MAAM,IAAI,OAAO;AACrC,UAAM,eAAe,MAAM,IAAI,QAAQ;AACvC,UAAM,QAAQ,KAAK,IAAI,SAAS,MAAM,IAAI,OAAO,KAAK,MAAM,EAAE,GAAG,GAAG;AACpE,UAAM,SAAS,SAAS,MAAM,IAAI,QAAQ,KAAK,KAAK,EAAE;AAEtD,QAAI,eAAe,GAChB,WAAW,gBAAgB,EAC3B,OAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,EACA,QAAQ,cAAc,MAAM,EAC5B,MAAM,KAAK,EACX,OAAO,MAAM;AAEhB,QAAI,aAAa;AACf,qBAAe,aAAa,MAAM,SAAS,KAAK,WAAW;AAAA,IAC7D;AACA,QAAI,cAAc;AAChB,qBAAe,aAAa,MAAM,UAAU,KAAK,YAAY;AAAA,IAC/D;AAEA,UAAM,OAAO,MAAM,aAAa,QAAQ;AAGxC,UAAM,UAAU,KAAK,IAAI,UAAQ;AAAA,MAC/B,IAAI,IAAI;AAAA,MACR,OAAO,IAAI;AAAA,MACX,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,MAC/B,QAAQ,IAAI;AAAA,MACZ,UAAU,IAAI;AAAA,MACd,UAAU,IAAI;AAAA,MACd,aAAa,IAAI;AAAA,MACjB,OAAO,IAAI;AAAA,MACX,WAAW,IAAI;AAAA,MACf,WAAW,IAAI;AAAA,MACf,WAAW,IAAI;AAAA,IACjB,EAAE;AAEF,aAAS,KAAK,EAAE,MAAM,SAAS,OAAO,OAAO,CAAC;AAAA,EAChD;AAKA,iBAAe,eAAe,KAAsB,KAAoC;AACtF,UAAM,QAAQ,WAAW,WAAW,IAAI,GAAG,CAAC;AAC5C,UAAM,cAAc,MAAM,IAAI,OAAO;AAGrC,QAAI,aAAa,GACd,WAAW,gBAAgB,EAC3B,OAAO;AAAA,MACN;AAAA,MACA,6BAAsB,GAAG,OAAO;AAAA,IAClC,CAAC,EACA,QAAQ,QAAQ;AAEnB,QAAI,aAAa;AACf,mBAAa,WAAW,MAAM,SAAS,KAAK,WAAW;AAAA,IACzD;AAEA,UAAM,eAAe,MAAM,WAAW,QAAQ;AAE9C,UAAM,QAAkB;AAAA,MACtB,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAEA,eAAW,OAAO,cAAc;AAC9B,YAAM,SAAS,IAAI;AACnB,YAAM,QAAQ,OAAO,IAAI,KAAK;AAC9B,UAAI,UAAU,OAAO;AACnB,cAAM,MAAM,IAAI;AAAA,MAClB;AACA,YAAM,SAAS;AAAA,IACjB;AAGA,UAAM,eAAe,MAAM,GACxB,WAAW,gBAAgB,EAC3B,OAAO,OAAO,EACd,QAAQ,OAAO,EACf,QAAQ;AAEX,UAAM,SAAS,aAAa,IAAI,OAAK,EAAE,KAAK;AAG5C,UAAM,gBAAgB,MAAM,KAAK,UAAU,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,MAAM,OAAO;AAAA,MAC9E;AAAA,MACA,SAAS,OAAO;AAAA,MAChB,QAAQ,OAAO;AAAA,IACjB,EAAE;AAEF,aAAS,KAAK,EAAE,OAAO,QAAQ,SAAS,cAAc,CAAC;AAAA,EACzD;AAKA,iBAAe,aAAa,KAAsB,KAAqB,UAAiC;AACtG,UAAM,MAAM,MAAM,GACf,WAAW,gBAAgB,EAC3B,OAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,EACA,MAAM,aAAa,KAAK,QAAQ,EAChC,iBAAiB;AAEpB,QAAI,CAAC,KAAK;AACR,aAAO,UAAU,KAAK,iBAAiB,GAAG;AAAA,IAC5C;AAEA,aAAS,KAAK;AAAA,MACZ,IAAI,IAAI;AAAA,MACR,OAAO,IAAI;AAAA,MACX,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,MAC/B,QAAQ,IAAI;AAAA,MACZ,UAAU,IAAI;AAAA,MACd,UAAU,IAAI;AAAA,MACd,aAAa,IAAI;AAAA,MACjB,OAAO,IAAI;AAAA,MACX,YAAY,IAAI;AAAA,MAChB,WAAW,IAAI;AAAA,MACf,WAAW,IAAI;AAAA,MACf,WAAW,IAAI;AAAA,IACjB,CAAC;AAAA,EACH;AAKA,iBAAe,kBAAkB,KAAqB,OAA8B;AAClF,UAAM,SAAS,UAAU,IAAI,KAAK;AAClC,QAAI,CAAC,QAAQ;AACX,aAAO,UAAU,KAAK,qBAAqB,KAAK,eAAe,GAAG;AAAA,IACpE;AACA,WAAO,MAAM;AACb,aAAS,KAAK,EAAE,IAAI,MAAM,OAAO,QAAQ,KAAK,CAAC;AAAA,EACjD;AAKA,iBAAe,mBAAmB,KAAqB,OAA8B;AACnF,UAAM,SAAS,UAAU,IAAI,KAAK;AAClC,QAAI,CAAC,QAAQ;AACX,aAAO,UAAU,KAAK,qBAAqB,KAAK,eAAe,GAAG;AAAA,IACpE;AACA,WAAO,OAAO;AACd,aAAS,KAAK,EAAE,IAAI,MAAM,OAAO,QAAQ,MAAM,CAAC;AAAA,EAClD;AAKA,iBAAe,YAAY,KAAqB,UAAiC;AAE/E,UAAM,mBAAe,kBAAK,WAAW,MAAM,WAAW;AACtD,UAAM,eAAW,kBAAK,cAAc,QAAQ;AAG5C,UAAM,cAAc,qBAAqB,QAAQ;AAEjD,QAAI;AACF,YAAM,UAAU,UAAM,0BAAS,UAAU,OAAO;AAChD,UAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,UAAI,IAAI,OAAO;AAAA,IACjB,SAAS,OAAO;AACd,gBAAU,KAAK,aAAa,GAAG;AAAA,IACjC;AAAA,EACF;AAKA,SAAO,eAAe,cACpB,KACA,KACA,MACkB;AAClB,QAAI;AACF,YAAM,OAAO,QAAQ,IAAI,OAAO,GAAG;AAGnC,YAAM,UAAU,IAAI,OAAO;AAC3B,UAAI,YAAY,CAAC,QAAQ,WAAW,QAAQ,GAAG;AAC7C,YAAI,KAAM,MAAK;AACf,eAAO;AAAA,MACT;AAGA,UAAI,UAAU,+BAA+B,GAAG;AAChD,UAAI,UAAU,gCAAgC,oBAAoB;AAClE,UAAI,UAAU,gCAAgC,cAAc;AAE5D,UAAI,IAAI,WAAW,WAAW;AAC5B,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI;AACR,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,eAAe,IAAI,WAAW,OAAO;AAChD,cAAM,cAAc,KAAK,GAAG;AAC5B,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,gBAAgB,IAAI,WAAW,OAAO;AACjD,cAAM,eAAe,KAAK,GAAG;AAC7B,eAAO;AAAA,MACT;AAGA,YAAM,WAAW,KAAK,MAAM,wBAAwB;AACpD,UAAI,YAAY,IAAI,WAAW,OAAO;AACpC,cAAM,aAAa,KAAK,KAAK,SAAS,CAAC,CAAC;AACxC,eAAO;AAAA,MACT;AAGA,YAAM,aAAa,KAAK,MAAM,kCAAkC;AAChE,UAAI,cAAc,IAAI,WAAW,QAAQ;AACvC,cAAM,kBAAkB,KAAK,WAAW,CAAC,CAAC;AAC1C,eAAO;AAAA,MACT;AAGA,YAAM,cAAc,KAAK,MAAM,mCAAmC;AAClE,UAAI,eAAe,IAAI,WAAW,QAAQ;AACxC,cAAM,mBAAmB,KAAK,YAAY,CAAC,CAAC;AAC5C,eAAO;AAAA,MACT;AAGA,UAAI,SAAS,OAAO,SAAS,eAAe;AAC1C,cAAM,YAAY,KAAK,YAAY;AACnC,eAAO;AAAA,MACT;AACA,UAAI,SAAS,cAAc;AACzB,cAAM,YAAY,KAAK,WAAW;AAClC,eAAO;AAAA,MACT;AACA,UAAI,SAAS,WAAW;AACtB,cAAM,YAAY,KAAK,QAAQ;AAC/B,eAAO;AAAA,MACT;AAGA,gBAAU,KAAK,aAAa,GAAG;AAC/B,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,gCAAgC,KAAK;AACnD,gBAAU,KAAK,yBAAyB,GAAG;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAsBO,SAAS,gBAAgB,SAA+C;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,IACP,UAAU,CAAC;AAAA,EACb,IAAI;AAEJ,MAAI,CAAC,IAAI;AACP,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAGA,QAAM,YAAY,oBAAI,IAA6B;AACnD,aAAW,UAAU,SAAS;AAC5B,cAAU,IAAI,OAAO,OAAO,MAAM;AAAA,EACpC;AAEA,QAAM,gBAAgB,qBAAqB,IAAI,SAAS;AAGxD,QAAM,aAAS,0BAAa,CAAC,KAAK,QAAQ;AACxC,SAAK,cAAc,KAAK,GAAG;AAAA,EAC7B,CAAC;AAED,SAAO,OAAO,IAAI;AAElB,SAAO;AAAA,IACL,MAAM,QAAuB;AAC3B,aAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,eAAO,MAAM,CAAC,QAAQ;AACpB,cAAI,IAAK,QAAO,GAAG;AAAA,cACd,SAAQ;AAAA,QACf,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,IAEA,IAAI,OAAe;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AACF;AA0BO,SAAS,0BAA0B,SAA0D;AAClG,QAAM;AAAA,IACJ;AAAA,IACA,UAAU,CAAC;AAAA,IACX,WAAW;AAAA,EACb,IAAI;AAEJ,MAAI,CAAC,IAAI;AACP,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAGA,QAAM,YAAY,oBAAI,IAA6B;AACnD,aAAW,UAAU,SAAS;AAC5B,cAAU,IAAI,OAAO,OAAO,MAAM;AAAA,EACpC;AAEA,QAAM,gBAAgB,qBAAqB,IAAI,WAAW,QAAQ;AAElE,SAAO,CAAC,KAAK,KAAK,SAAS;AACzB,SAAK,cAAc,KAAK,KAAK,IAAI;AAAA,EACnC;AACF;","names":["Database","import_kysely","options","import_kysely","fastq","options","import_kysely","result","import_kysely","__filename"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import * as http from 'http';
|
|
2
1
|
import * as better_sqlite3 from 'better-sqlite3';
|
|
2
|
+
import better_sqlite3__default from 'better-sqlite3';
|
|
3
|
+
import * as http from 'http';
|
|
3
4
|
import { Kysely, Generated } from 'kysely';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Job status types
|
|
7
8
|
*/
|
|
8
|
-
type JobStatus = 'ready' | 'running' | 'done' | '
|
|
9
|
+
type JobStatus = 'ready' | 'running' | 'done' | 'dead';
|
|
9
10
|
/**
|
|
10
11
|
* Database table schema for workmatic_jobs
|
|
11
12
|
*/
|
|
@@ -63,7 +64,7 @@ interface Job<TPayload = unknown> {
|
|
|
63
64
|
maxAttempts: number;
|
|
64
65
|
/** When the job was created (unix ms) */
|
|
65
66
|
createdAt: number;
|
|
66
|
-
/** Last error
|
|
67
|
+
/** Last error from a previous attempt (e.g. before retry) */
|
|
67
68
|
lastError: string | null;
|
|
68
69
|
}
|
|
69
70
|
/**
|
|
@@ -84,6 +85,13 @@ interface AddJobResult {
|
|
|
84
85
|
ok: true;
|
|
85
86
|
id: string;
|
|
86
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Result of adding multiple jobs in one transaction
|
|
90
|
+
*/
|
|
91
|
+
interface AddManyResult {
|
|
92
|
+
ok: true;
|
|
93
|
+
ids: string[];
|
|
94
|
+
}
|
|
87
95
|
/**
|
|
88
96
|
* Options for creating a database
|
|
89
97
|
*/
|
|
@@ -124,7 +132,7 @@ interface WorkerOptions {
|
|
|
124
132
|
leaseMs?: number;
|
|
125
133
|
/** Poll interval in ms when no jobs available. Default: 1000 */
|
|
126
134
|
pollMs?: number;
|
|
127
|
-
/** Job execution timeout in ms. Default:
|
|
135
|
+
/** Job execution timeout in ms. Default: 60000 (1 min). Set to 0 to disable. */
|
|
128
136
|
timeoutMs?: number;
|
|
129
137
|
/** Backoff function for retries. Default: exponential */
|
|
130
138
|
backoff?: BackoffFunction;
|
|
@@ -132,6 +140,18 @@ interface WorkerOptions {
|
|
|
132
140
|
persistState?: boolean;
|
|
133
141
|
/** Auto-restore worker state on creation. Default: true (only applies if persistState is true) */
|
|
134
142
|
autoRestore?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Minimum interval between database pause checks (CLI `pause`). Reduces round-trips while pumping.
|
|
145
|
+
* Default: 300 ms
|
|
146
|
+
*/
|
|
147
|
+
pauseCheckIntervalMs?: number;
|
|
148
|
+
/**
|
|
149
|
+
* Minimum interval between lease requeue scans. Default: every pump (0).
|
|
150
|
+
* Set to e.g. 1000 to run expired-lease recovery at most once per second.
|
|
151
|
+
*/
|
|
152
|
+
requeueExpiredIntervalMs?: number;
|
|
153
|
+
/** Called when the pump loop catches an error (after optional default logging) */
|
|
154
|
+
onPumpError?: (error: unknown) => void;
|
|
135
155
|
}
|
|
136
156
|
/**
|
|
137
157
|
* Job processor function type
|
|
@@ -144,7 +164,6 @@ interface JobStats {
|
|
|
144
164
|
ready: number;
|
|
145
165
|
running: number;
|
|
146
166
|
done: number;
|
|
147
|
-
failed: number;
|
|
148
167
|
dead: number;
|
|
149
168
|
total: number;
|
|
150
169
|
}
|
|
@@ -154,6 +173,11 @@ interface JobStats {
|
|
|
154
173
|
interface WorkmaticClient {
|
|
155
174
|
/** Add a job to the queue */
|
|
156
175
|
add<TPayload = unknown>(payload: TPayload, options?: AddJobOptions): Promise<AddJobResult>;
|
|
176
|
+
/**
|
|
177
|
+
* Add many jobs in a single transaction (shared priority, delay, maxAttempts).
|
|
178
|
+
* Faster than repeated `add()` when inserting large batches.
|
|
179
|
+
*/
|
|
180
|
+
addMany<TPayload = unknown>(payloads: TPayload[], options?: AddJobOptions): Promise<AddManyResult>;
|
|
157
181
|
/** Get job statistics */
|
|
158
182
|
stats(): Promise<JobStats>;
|
|
159
183
|
/** Clear all jobs from the queue */
|
|
@@ -225,6 +249,78 @@ interface WorkmaticDashboard {
|
|
|
225
249
|
/** Server port */
|
|
226
250
|
readonly port: number;
|
|
227
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Options for creating an orchestrator
|
|
254
|
+
*/
|
|
255
|
+
interface OrchestratorOptions {
|
|
256
|
+
/** Kysely database instance */
|
|
257
|
+
db: WorkmaticDb;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Options when registering a queue with the orchestrator
|
|
261
|
+
*/
|
|
262
|
+
interface RegisterQueueOptions {
|
|
263
|
+
/** Create a worker for this queue (omit for client-only) */
|
|
264
|
+
worker?: Omit<WorkerOptions, 'db' | 'queue'>;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Options for bulk transfer between queues
|
|
268
|
+
*/
|
|
269
|
+
interface TransferOptions {
|
|
270
|
+
/** Source queue name */
|
|
271
|
+
from: string;
|
|
272
|
+
/** Target queue name */
|
|
273
|
+
to: string;
|
|
274
|
+
/**
|
|
275
|
+
* Job statuses to transfer. Default: `['ready', 'dead']`.
|
|
276
|
+
* `running` and `done` are excluded by default for safety.
|
|
277
|
+
*/
|
|
278
|
+
status?: JobStatus | JobStatus[];
|
|
279
|
+
/** Max jobs to move (default: 10000) */
|
|
280
|
+
limit?: number;
|
|
281
|
+
/** When moving `dead` jobs, reset to `ready` with attempts cleared (retry queue) */
|
|
282
|
+
resetForRetry?: boolean;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Result of a bulk transfer
|
|
286
|
+
*/
|
|
287
|
+
interface TransferResult {
|
|
288
|
+
moved: number;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Options for moving a single job by public id
|
|
292
|
+
*/
|
|
293
|
+
interface MoveJobOptions {
|
|
294
|
+
/** Allowed source statuses (default: ready, dead) */
|
|
295
|
+
status?: JobStatus | JobStatus[];
|
|
296
|
+
/** Reset dead job for retry in target queue */
|
|
297
|
+
resetForRetry?: boolean;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Multi-queue orchestrator interface
|
|
301
|
+
*/
|
|
302
|
+
interface WorkmaticOrchestrator {
|
|
303
|
+
/** Register a queue (client + optional worker) */
|
|
304
|
+
register(queue: string, options?: RegisterQueueOptions): WorkmaticClient;
|
|
305
|
+
/** Get client for a queue (lazy-creates if not registered) */
|
|
306
|
+
client(queue: string): WorkmaticClient;
|
|
307
|
+
/** Get worker for a queue (must be registered with worker option) */
|
|
308
|
+
worker(queue: string): WorkmaticWorker;
|
|
309
|
+
/** All registered workers (for dashboard) */
|
|
310
|
+
workers(): WorkmaticWorker[];
|
|
311
|
+
/** Queue names from DB and registry */
|
|
312
|
+
queues(): Promise<string[]>;
|
|
313
|
+
/** Set processor on a registered worker */
|
|
314
|
+
process<TPayload = unknown>(queue: string, fn: JobProcessor<TPayload>): void;
|
|
315
|
+
startAll(): void;
|
|
316
|
+
stopAll(): Promise<void>;
|
|
317
|
+
pause(queue: string): Promise<void>;
|
|
318
|
+
resume(queue: string): Promise<void>;
|
|
319
|
+
isPaused(queue: string): Promise<boolean>;
|
|
320
|
+
stats(queue?: string): Promise<Record<string, JobStats>>;
|
|
321
|
+
transfer(options: TransferOptions): Promise<TransferResult>;
|
|
322
|
+
moveJob(publicId: string, toQueue: string, options?: MoveJobOptions): Promise<void>;
|
|
323
|
+
}
|
|
228
324
|
/**
|
|
229
325
|
* Internal job representation from database
|
|
230
326
|
*/
|
|
@@ -235,6 +331,9 @@ interface ClaimedJob {
|
|
|
235
331
|
payload: string;
|
|
236
332
|
attempts: number;
|
|
237
333
|
max_attempts: number;
|
|
334
|
+
priority: number;
|
|
335
|
+
created_at: number;
|
|
336
|
+
last_error: string | null;
|
|
238
337
|
}
|
|
239
338
|
|
|
240
339
|
/**
|
|
@@ -258,6 +357,12 @@ interface ClaimedJob {
|
|
|
258
357
|
* ```
|
|
259
358
|
*/
|
|
260
359
|
declare function createDatabase(options?: DatabaseOptions): WorkmaticDb;
|
|
360
|
+
/**
|
|
361
|
+
* Get the underlying better-sqlite3 database instance from a Kysely instance
|
|
362
|
+
* created with {@link createDatabase}. For manually constructed `Kysely` instances,
|
|
363
|
+
* falls back to reading the dialect adapter (may break across Kysely versions).
|
|
364
|
+
*/
|
|
365
|
+
declare function getUnderlyingDb(db: WorkmaticDb): better_sqlite3__default.Database;
|
|
261
366
|
|
|
262
367
|
/**
|
|
263
368
|
* Create a job queue client for adding jobs
|
|
@@ -286,6 +391,8 @@ declare function createDatabase(options?: DatabaseOptions): WorkmaticDb;
|
|
|
286
391
|
*/
|
|
287
392
|
declare function createClient(options: ClientOptions): WorkmaticClient;
|
|
288
393
|
|
|
394
|
+
/** Default job execution timeout when `timeoutMs` is omitted (1 minute). Use `timeoutMs: 0` for no limit. */
|
|
395
|
+
declare const DEFAULT_WORKER_TIMEOUT_MS = 60000;
|
|
289
396
|
/**
|
|
290
397
|
* Create a job queue worker for processing jobs
|
|
291
398
|
*
|
|
@@ -311,6 +418,11 @@ declare function createClient(options: ClientOptions): WorkmaticClient;
|
|
|
311
418
|
*/
|
|
312
419
|
declare function createWorker(options: WorkerOptions): WorkmaticWorker;
|
|
313
420
|
|
|
421
|
+
/**
|
|
422
|
+
* Create a multi-queue orchestrator for registration, lifecycle, and transfers.
|
|
423
|
+
*/
|
|
424
|
+
declare function createOrchestrator(options: OrchestratorOptions): WorkmaticOrchestrator;
|
|
425
|
+
|
|
314
426
|
/**
|
|
315
427
|
* Create a dashboard HTTP server for monitoring and controlling the job queue
|
|
316
428
|
*
|
|
@@ -383,4 +495,4 @@ declare const defaultBackoff: BackoffFunction;
|
|
|
383
495
|
*/
|
|
384
496
|
declare function validatePayload(payload: unknown): string;
|
|
385
497
|
|
|
386
|
-
export { type AddJobOptions, type AddJobResult, type BackoffFunction, type ClaimedJob, type ClientOptions, type DashboardMiddleware, type DashboardMiddlewareOptions, type DashboardOptions, type DatabaseOptions, type Job, type JobProcessor, type JobStats, type JobStatus, type WorkerOptions, type WorkerState, type WorkmaticClient, type WorkmaticDashboard, type WorkmaticDatabase, type WorkmaticDb, type WorkmaticJobsTable, type WorkmaticWorker, createClient, createDashboard, createDashboardMiddleware, createDatabase, createWorker, defaultBackoff, validatePayload };
|
|
498
|
+
export { type AddJobOptions, type AddJobResult, type AddManyResult, type BackoffFunction, type ClaimedJob, type ClientOptions, DEFAULT_WORKER_TIMEOUT_MS, type DashboardMiddleware, type DashboardMiddlewareOptions, type DashboardOptions, type DatabaseOptions, type Job, type JobProcessor, type JobStats, type JobStatus, type MoveJobOptions, type OrchestratorOptions, type RegisterQueueOptions, type TransferOptions, type TransferResult, type WorkerOptions, type WorkerState, type WorkmaticClient, type WorkmaticDashboard, type WorkmaticDatabase, type WorkmaticDb, type WorkmaticJobsTable, type WorkmaticOrchestrator, type WorkmaticWorker, createClient, createDashboard, createDashboardMiddleware, createDatabase, createOrchestrator, createWorker, defaultBackoff, getUnderlyingDb, validatePayload };
|